Introduce PhysicalGlyph for offsetting and scaling

This commit is contained in:
Héctor Ramón Jiménez 2023-06-20 06:07:24 +02:00
parent e8b10fd675
commit eb09cf0259
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
5 changed files with 79 additions and 38 deletions

View file

@ -749,16 +749,27 @@ impl Buffer {
{ {
for run in self.layout_runs() { for run in self.layout_runs() {
for glyph in run.glyphs.iter() { 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 { let glyph_color = match glyph.color_opt {
Some(some) => some, Some(some) => some,
None => color, None => color,
}; };
cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| { cache.with_pixels(
f(x_int + x, run.line_y as i32 + y_int + y, 1, 1, color); 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,
);
},
);
} }
} }
} }

View file

@ -23,7 +23,7 @@ impl CacheKey {
pos: (f32, f32), pos: (f32, f32),
) -> (Self, i32, i32) { ) -> (Self, i32, i32) {
let (x, x_bin) = SubpixelBin::new(pos.0); 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 { Self {
font_id, font_id,

View file

@ -696,7 +696,6 @@ impl Edit for Editor {
) where ) where
F: FnMut(i32, i32, u32, u32, Color), F: FnMut(i32, i32, u32, u32, Color),
{ {
let font_size = self.buffer.metrics().font_size;
let line_height = self.buffer.metrics().line_height; let line_height = self.buffer.metrics().line_height;
for run in self.buffer.layout_runs() { for run in self.buffer.layout_runs() {
@ -852,16 +851,27 @@ impl Edit for Editor {
} }
for glyph in run.glyphs.iter() { 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 { let glyph_color = match glyph.color_opt {
Some(some) => some, Some(some) => some,
None => color, None => color,
}; };
cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| { cache.with_pixels(
f(x_int + x, line_y as i32 + y_int + y, 1, 1, color); 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,
);
},
);
} }
} }
} }

View file

@ -14,19 +14,24 @@ pub struct LayoutGlyph {
pub start: usize, pub start: usize,
/// End index of cluster in original line /// End index of cluster in original line
pub end: usize, 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 /// X offset of hitbox
pub x: f32, pub x: f32,
/// width of hitbox /// Y offset of hitbox
pub y: f32,
/// Width of hitbox
pub w: f32, pub w: f32,
/// Unicode BiDi embedding level, character is left-to-right if `level` is divisible by 2 /// Unicode BiDi embedding level, character is left-to-right if `level` is divisible by 2
pub level: unicode_bidi::Level, pub level: unicode_bidi::Level,
/// Cache key, see [CacheKey]
pub cache_key: CacheKey,
/// X offset in line /// X offset in line
/// ///
/// If you are dealing with physical coordinates, you will want to use [`Self::x_int`] /// If you are dealing with physical coordinates, use [`Self::physical`] to obtain a
/// together with [`CacheKey::x_bin`] instead. This will ensure the best alignment of the /// [`PhysicalGlyph`] for rendering.
/// rasterized glyphs with the pixel grid.
/// ///
/// This offset is useful when you are dealing with logical units and you do not care or /// 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 /// 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, pub x_offset: f32,
/// Y offset in line /// Y offset in line
/// ///
/// If you are dealing with physical coordinates, you will want to use [`Self::y_int`] /// If you are dealing with physical coordinates, use [`Self::physical`] to obtain a
/// together with [`CacheKey::y_bin`] instead. This will ensure the best alignment of the /// [`PhysicalGlyph`] for rendering.
/// rasterized glyphs with the pixel grid.
/// ///
/// This offset is useful when you are dealing with logical units and you do not care or /// 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 /// cannot guarantee pixel grid alignment. For instance, when you want to use the glyphs
/// for vectorial text, apply linear transformations to the layout, etc. /// for vectorial text, apply linear transformations to the layout, etc.
pub y_offset: f32, 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 /// Optional color override
pub color_opt: Option<Color>, pub color_opt: Option<Color>,
/// Metadata from `Attrs` /// Metadata from `Attrs`
pub metadata: usize, 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 /// A line of laid out glyphs
pub struct LayoutLine { pub struct LayoutLine {
/// Width of the line /// Width of the line

View file

@ -9,7 +9,7 @@ use unicode_script::{Script, UnicodeScript};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use crate::fallback::FontFallbackIter; 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. /// The shaping strategy of some text.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -332,26 +332,18 @@ impl ShapeGlyph {
w: f32, w: f32,
level: unicode_bidi::Level, level: unicode_bidi::Level,
) -> LayoutGlyph { ) -> 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 { LayoutGlyph {
start: self.start, start: self.start,
end: self.end, end: self.end,
font_size,
font_id: self.font_id,
glyph_id: self.glyph_id,
x, x,
y,
w, w,
level, level,
cache_key, x_offset: self.x_offset,
x_offset, y_offset: self.y_offset,
y_offset,
x_int,
y_int,
color_opt: self.color_opt, color_opt: self.color_opt,
metadata: self.metadata, metadata: self.metadata,
} }