Skip to main content

FaceSet

Struct FaceSet 

Source
pub struct FaceSet { /* private fields */ }
Expand description

The host’s registered fonts: families for styles to name, plus a global fallback chain consulted per character. Immutable once built — register everything, then Arc it for builders and the renderer.

Implementations§

Source§

impl FaceSet

Source

pub fn new() -> Self

Source

pub fn register(&mut self, family: &str, bytes: Vec<u8>) -> Option<FontId>

Register font bytes under a family name (regular weight/style). Returns None when the bytes don’t parse as a font.

Examples found in repository?
examples/raster_bench.rs (lines 23-26)
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}
Source

pub fn register_with( &mut self, family: &str, attrs: FontAttrs, bytes: Vec<u8>, ) -> Option<FontId>

Register one variant of a family — resolve picks the nearest weight with a matching style (CSS §5.2, simplified: style first, then minimal weight distance, ties to the first registered).

Source

pub fn add(&mut self, font: Font) -> FontId

Add an already-parsed Font under ITS OWN name/attrs — the SkTypefaceregisterTypeface shape.

Source

pub fn with_font(&self, font: Font) -> (FaceSet, FontId)

A new collection = this one + font. Faces are shared by Arc, so this is O(faces) pointer clones — no re-parsing, and every existing holder of the old collection is untouched.

Source

pub fn with_fallbacks(&self, fallbacks: Vec<FontId>) -> FaceSet

A new collection with the fallback chain REPLACED (order matters).

Source

pub fn add_fallback(&mut self, id: FontId)

Append to the global fallback chain (consulted after a style’s own families: nearest attrs among the faces covering the character, ties in chain order).

Source

pub fn grown_by( &self, source: &mut dyn FontSource, demand: &FontDemand, ) -> Option<FaceSet>

Grow this collection to answer demand from source: demanded families register under their own names PLUS the demanded name as an alias (a localized or differently-spelled request must match on the next layout, or a loop around this call could demand forever); codepoints still uncovered afterwards extend the fallback chain with a face matching the demanding span’s attrs. Some(grown) only when something new was found — the caller’s signal to re-register the collection and lay out again. Grow a COPY of this face set to answer demand from source — the out-of-band path (a host that already knows what it wants). Live resolution goes through FontCollection, which owns its sources.

Source

pub fn is_empty(&self) -> bool

True until the first add/register — building paragraphs against an empty collection is a contract violation (resolve asserts).

Source

pub fn len(&self) -> usize

Faces registered so far. Ids are append-only, so a holder of an older collection can name the faces added since: old.len()..new.len().

Source

pub fn get_arc(&self, id: FontId) -> Arc<Font>

The shared instance behind id — what glyph runs carry to the renderer (Skia: blobs hold sk_sp<SkTypeface>).

Source

pub fn get(&self, id: FontId) -> &Font

Examples found in repository?
examples/raster_bench.rs (line 49)
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}
59
60fn glyphs(fonts: &FaceSet, id: FontId, text: &str) -> Vec<u32> {
61    let font = fonts.get(id);
62    text.chars().filter_map(|ch| font.glyph_for(ch)).collect()
63}
Source

pub fn family(&self, name: &str) -> Option<FontId>

Source

pub fn faces<'a>(&'a self, name: &'a str) -> impl Iterator<Item = FontId> + 'a

Ids of EVERY face answering to name, in registration order. Subset families (css2/cn-font-split unicode-range chunks) register many faces under one name with disjoint coverage — a fallback chain built from Self::family alone reaches only the first-loaded chunk, so hosts expand fallback names with this.

Source

pub fn family_variant(&self, name: &str, attrs: FontAttrs) -> Option<FontId>

The family variant nearest attrs: matching style wins, then the smallest weight distance (ties to the first registered).

Source

pub fn resolve(&self, families: &[String], attrs: FontAttrs, ch: char) -> FontId

The font that renders ch for a style: per requested family, the nearest variant that COVERS ch — subset families (cn-font-split chunks) carry one unicode range per face, so coverage must look past the best-attrs face. Then the fallback chain, else the first candidate.

Source

pub fn resolve_covered( &self, families: &[String], attrs: FontAttrs, ch: char, ) -> (FontId, bool)

Self::resolve plus whether ANYTHING actually covers ch — false means the returned face will shape .notdef. The demand signal: callers report uncovered chars to the host, which decides where fonts come from — valo only detects.

Trait Implementations§

Source§

impl Clone for FaceSet

Source§

fn clone(&self) -> FaceSet

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Default for FaceSet

Source§

fn default() -> FaceSet

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.