pub struct Rasterizer { /* private fields */ }Expand description
CPU glyph rasterization, on swash. One per renderer — swash’s context caches scaling state, and the stroker its segment buffers.
Implementations§
Source§impl Rasterizer
impl Rasterizer
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
16fn main() {
17 let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/fonts");
18 // A CJK face is 20k+ glyphs and too big to vendor: point VALO_CJK_FONT
19 // at one to get the CJK column, otherwise the bench runs latin only.
20 let cjk_file = std::env::var("VALO_CJK_FONT").unwrap_or_default();
21 let mut fonts = FaceSet::default();
22 let latin = fonts
23 .register(
24 "Latin",
25 std::fs::read(format!("{dir}/fira_sans.ttf")).unwrap(),
26 )
27 .unwrap();
28 let cjk = std::fs::read(cjk_file)
29 .ok()
30 .and_then(|bytes| fonts.register("CJK", bytes));
31
32 let mut sets = vec![("latin", latin, glyphs(&fonts, latin, LATIN))];
33 if let Some(id) = cjk {
34 sets.push(("cjk", id, glyphs(&fonts, id, CJK)));
35 }
36
37 println!(
38 "{:>6} {:>6} {:>12} {:>12} (µs/glyph, n={})",
39 "set",
40 "px",
41 "alpha",
42 "sdf",
43 LATIN.len()
44 );
45 let mut raster = Rasterizer::new();
46 for (label, font, ids) in &sets {
47 for px in SIZES {
48 let alpha = time_per_glyph(ids, |g| {
49 raster.alpha(fonts.get(*font), g, px, 0.0);
50 });
51 let mut raster2 = Rasterizer::new();
52 let sdf = time_per_glyph(ids, |g| {
53 raster2.sdf(fonts.get(*font), g, px);
54 });
55 println!("{label:>6} {px:>6.0} {alpha:>10.1}µs {sdf:>10.1}µs");
56 }
57 }
58}Sourcepub fn alpha(
&mut self,
font: &Font,
glyph: u32,
px: f32,
dx: f32,
) -> Option<GlyphImage>
pub fn alpha( &mut self, font: &Font, glyph: u32, px: f32, dx: f32, ) -> Option<GlyphImage>
Plain alpha coverage at px — the mask tier. dx is the subpixel
x-phase (0/¼/½/¾ px) baked into the raster, Skia/Impeller’s
quarter-pixel positioning.
Examples found in repository?
16fn main() {
17 let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/fonts");
18 // A CJK face is 20k+ glyphs and too big to vendor: point VALO_CJK_FONT
19 // at one to get the CJK column, otherwise the bench runs latin only.
20 let cjk_file = std::env::var("VALO_CJK_FONT").unwrap_or_default();
21 let mut fonts = FaceSet::default();
22 let latin = fonts
23 .register(
24 "Latin",
25 std::fs::read(format!("{dir}/fira_sans.ttf")).unwrap(),
26 )
27 .unwrap();
28 let cjk = std::fs::read(cjk_file)
29 .ok()
30 .and_then(|bytes| fonts.register("CJK", bytes));
31
32 let mut sets = vec![("latin", latin, glyphs(&fonts, latin, LATIN))];
33 if let Some(id) = cjk {
34 sets.push(("cjk", id, glyphs(&fonts, id, CJK)));
35 }
36
37 println!(
38 "{:>6} {:>6} {:>12} {:>12} (µs/glyph, n={})",
39 "set",
40 "px",
41 "alpha",
42 "sdf",
43 LATIN.len()
44 );
45 let mut raster = Rasterizer::new();
46 for (label, font, ids) in &sets {
47 for px in SIZES {
48 let alpha = time_per_glyph(ids, |g| {
49 raster.alpha(fonts.get(*font), g, px, 0.0);
50 });
51 let mut raster2 = Rasterizer::new();
52 let sdf = time_per_glyph(ids, |g| {
53 raster2.sdf(fonts.get(*font), g, px);
54 });
55 println!("{label:>6} {px:>6.0} {alpha:>10.1}µs {sdf:>10.1}µs");
56 }
57 }
58}Sourcepub fn stroked(
&mut self,
font: &Font,
glyph: u32,
px: f32,
dx: f32,
stroke: &GlyphStroke,
) -> Option<GlyphImage>
pub fn stroked( &mut self, font: &Font, glyph: u32, px: f32, dx: f32, stroke: &GlyphStroke, ) -> Option<GlyphImage>
Alpha coverage of the glyph’s STROKED outline — the stroked mask tier. Stroking happens before rasterizing, which is what lets the result be an ordinary cached atlas entry (Skia’s scaler strokes inside the strike for the same reason).
This does NOT go through swash. swash rasterizes with zeno, and
zeno’s miter join short-circuits to a bevel whenever the two segment
normals point apart (stroke.rs’s dot < 0.0), which caps its miter
ratio at √2 and silently flattens every join sharper than a right
angle — the apex of A, M, W, and most of what a stroked
headline is made of. tiny-skia, already here for COLRv1, ports
Skia’s stroker and honours miter_limit, and it hands back a real
path whose tight bounds size the atlas cell. That measurement is the
point: Impeller sizes its slot the same way, by handing the stroking
paint to SkFont::getBounds.
Sourcepub fn sdf(&mut self, font: &Font, glyph: u32, px: f32) -> Option<GlyphImage>
pub fn sdf(&mut self, font: &Font, glyph: u32, px: f32) -> Option<GlyphImage>
Signed distance field at px: the 1× AA coverage seeds the exact
EDT directly (mapbox TinySDF’s shape — partial alpha carries the
sub-pixel edge, so no supersample; ~7× the old
2×-8SSEDT pipeline). 128 = edge, ±SDF_PAD px span the range.
Examples found in repository?
16fn main() {
17 let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/fonts");
18 // A CJK face is 20k+ glyphs and too big to vendor: point VALO_CJK_FONT
19 // at one to get the CJK column, otherwise the bench runs latin only.
20 let cjk_file = std::env::var("VALO_CJK_FONT").unwrap_or_default();
21 let mut fonts = FaceSet::default();
22 let latin = fonts
23 .register(
24 "Latin",
25 std::fs::read(format!("{dir}/fira_sans.ttf")).unwrap(),
26 )
27 .unwrap();
28 let cjk = std::fs::read(cjk_file)
29 .ok()
30 .and_then(|bytes| fonts.register("CJK", bytes));
31
32 let mut sets = vec![("latin", latin, glyphs(&fonts, latin, LATIN))];
33 if let Some(id) = cjk {
34 sets.push(("cjk", id, glyphs(&fonts, id, CJK)));
35 }
36
37 println!(
38 "{:>6} {:>6} {:>12} {:>12} (µs/glyph, n={})",
39 "set",
40 "px",
41 "alpha",
42 "sdf",
43 LATIN.len()
44 );
45 let mut raster = Rasterizer::new();
46 for (label, font, ids) in &sets {
47 for px in SIZES {
48 let alpha = time_per_glyph(ids, |g| {
49 raster.alpha(fonts.get(*font), g, px, 0.0);
50 });
51 let mut raster2 = Rasterizer::new();
52 let sdf = time_per_glyph(ids, |g| {
53 raster2.sdf(fonts.get(*font), g, px);
54 });
55 println!("{label:>6} {px:>6.0} {alpha:>10.1}µs {sdf:>10.1}µs");
56 }
57 }
58}Sourcepub fn color(&mut self, font: &Font, glyph: u32, px: f32) -> Option<GlyphImage>
pub fn color(&mut self, font: &Font, glyph: u32, px: f32) -> Option<GlyphImage>
Color glyph (COLR outlines / CBDT-sbix bitmaps) at px: premultiplied
RGBA, or None when the glyph has no color form — the caller falls
back to the mask tiers. Mini rendered emoji through Canvas2D; swash
is the native replacement.