diff --git a/src/buffer.rs b/src/buffer.rs index fefa7ac..14a8b2f 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -749,16 +749,27 @@ impl Buffer { { for run in self.layout_runs() { for glyph in run.glyphs.iter() { - let (cache_key, x_int, y_int) = (glyph.cache_key, glyph.x_int, glyph.y_int); + let physical_glyph = glyph.physical((0., 0.), 1.0); let glyph_color = match glyph.color_opt { Some(some) => some, None => color, }; - cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| { - f(x_int + x, run.line_y as i32 + y_int + y, 1, 1, color); - }); + cache.with_pixels( + font_system, + physical_glyph.cache_key, + glyph_color, + |x, y, color| { + f( + physical_glyph.x + x, + run.line_y as i32 + physical_glyph.y + y, + 1, + 1, + color, + ); + }, + ); } } } diff --git a/src/cache.rs b/src/cache.rs index ce93b38..4dbebd9 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -23,7 +23,7 @@ impl CacheKey { pos: (f32, f32), ) -> (Self, i32, i32) { let (x, x_bin) = SubpixelBin::new(pos.0); - let (y, y_bin) = SubpixelBin::new(pos.1); + let (y, y_bin) = SubpixelBin::new(pos.1.trunc()); ( Self { font_id, diff --git a/src/edit/editor.rs b/src/edit/editor.rs index 4c6c7b6..027ce27 100644 --- a/src/edit/editor.rs +++ b/src/edit/editor.rs @@ -696,7 +696,6 @@ impl Edit for Editor { ) where F: FnMut(i32, i32, u32, u32, Color), { - let font_size = self.buffer.metrics().font_size; let line_height = self.buffer.metrics().line_height; for run in self.buffer.layout_runs() { @@ -852,16 +851,27 @@ impl Edit for Editor { } for glyph in run.glyphs.iter() { - let (cache_key, x_int, y_int) = (glyph.cache_key, glyph.x_int, glyph.y_int); + let physical_glyph = glyph.physical((0., 0.), 1.0); let glyph_color = match glyph.color_opt { Some(some) => some, None => color, }; - cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| { - f(x_int + x, line_y as i32 + y_int + y, 1, 1, color); - }); + cache.with_pixels( + font_system, + physical_glyph.cache_key, + glyph_color, + |x, y, color| { + f( + physical_glyph.x + x, + line_y as i32 + physical_glyph.y + y, + 1, + 1, + color, + ); + }, + ); } } } diff --git a/src/layout.rs b/src/layout.rs index 483ed93..939a88d 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -14,19 +14,24 @@ pub struct LayoutGlyph { pub start: usize, /// End index of cluster in original line pub end: usize, + /// Font size of the glyph + pub font_size: f32, + /// Font id of the glyph + pub font_id: fontdb::ID, + /// Font id of the glyph + pub glyph_id: u16, /// X offset of hitbox pub x: f32, - /// width of hitbox + /// Y offset of hitbox + pub y: f32, + /// Width of hitbox pub w: f32, /// Unicode BiDi embedding level, character is left-to-right if `level` is divisible by 2 pub level: unicode_bidi::Level, - /// Cache key, see [CacheKey] - pub cache_key: CacheKey, /// X offset in line /// - /// If you are dealing with physical coordinates, you will want to use [`Self::x_int`] - /// together with [`CacheKey::x_bin`] instead. This will ensure the best alignment of the - /// rasterized glyphs with the pixel grid. + /// If you are dealing with physical coordinates, use [`Self::physical`] to obtain a + /// [`PhysicalGlyph`] for rendering. /// /// This offset is useful when you are dealing with logical units and you do not care or /// cannot guarantee pixel grid alignment. For instance, when you want to use the glyphs @@ -34,24 +39,47 @@ pub struct LayoutGlyph { pub x_offset: f32, /// Y offset in line /// - /// If you are dealing with physical coordinates, you will want to use [`Self::y_int`] - /// together with [`CacheKey::y_bin`] instead. This will ensure the best alignment of the - /// rasterized glyphs with the pixel grid. + /// If you are dealing with physical coordinates, use [`Self::physical`] to obtain a + /// [`PhysicalGlyph`] for rendering. /// /// This offset is useful when you are dealing with logical units and you do not care or /// cannot guarantee pixel grid alignment. For instance, when you want to use the glyphs /// for vectorial text, apply linear transformations to the layout, etc. pub y_offset: f32, - /// Integer component of X offset in line - pub x_int: i32, - /// Integer component of Y offset in line - pub y_int: i32, /// Optional color override pub color_opt: Option, /// Metadata from `Attrs` pub metadata: usize, } +pub struct PhysicalGlyph { + /// Cache key, see [CacheKey] + pub cache_key: CacheKey, + /// Integer component of X offset in line + pub x: i32, + /// Integer component of Y offset in line + pub y: i32, +} + +impl LayoutGlyph { + pub fn physical(&self, offset: (f32, f32), scale: f32) -> PhysicalGlyph { + let x_offset = self.font_size * self.x_offset; + let y_offset = self.font_size * self.y_offset; + + let (cache_key, x, y) = CacheKey::new( + self.font_id, + self.glyph_id, + self.font_size * scale, + ( + (self.x + x_offset) * scale + offset.0, + (self.y - y_offset) * scale + offset.1, + ), + ); + + PhysicalGlyph { cache_key, x, y } + } +} + /// A line of laid out glyphs pub struct LayoutLine { /// Width of the line diff --git a/src/shape.rs b/src/shape.rs index 98b0ba3..cf1c413 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -9,7 +9,7 @@ use unicode_script::{Script, UnicodeScript}; use unicode_segmentation::UnicodeSegmentation; use crate::fallback::FontFallbackIter; -use crate::{Align, AttrsList, CacheKey, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Wrap}; +use crate::{Align, AttrsList, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Wrap}; /// The shaping strategy of some text. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -332,26 +332,18 @@ impl ShapeGlyph { w: f32, level: unicode_bidi::Level, ) -> LayoutGlyph { - let x_offset = font_size * self.x_offset; - let y_offset = font_size * self.y_offset; - - let (cache_key, x_int, y_int) = CacheKey::new( - self.font_id, - self.glyph_id, - font_size, - (x + x_offset, y - y_offset), - ); LayoutGlyph { start: self.start, end: self.end, + font_size, + font_id: self.font_id, + glyph_id: self.glyph_id, x, + y, w, level, - cache_key, - x_offset, - y_offset, - x_int, - y_int, + x_offset: self.x_offset, + y_offset: self.y_offset, color_opt: self.color_opt, metadata: self.metadata, }