pub struct Face { /* private fields */ }Expand description
An owning, re-parseable wrapper around either an
oxideav_ttf::Font or an oxideav_otf::Font. The discriminant
is recorded in Face::kind so callers can pick the right
outline path.
Implementations§
Source§impl Face
impl Face
Sourcepub fn has_color_bitmaps(&self) -> bool
pub fn has_color_bitmaps(&self) -> bool
true when this face ships CBDT/CBLC tables. Wraps
oxideav_ttf::Font::has_color_bitmaps.
Sourcepub fn color_strike_sizes(&self) -> Vec<(u8, u8)>
pub fn color_strike_sizes(&self) -> Vec<(u8, u8)>
All (ppem_x, ppem_y) strikes the face’s CBDT/CBLC tables ship.
Empty when the face has no colour bitmaps.
Sourcepub fn raster_color_glyph(
&self,
glyph_id: u16,
size_px: f32,
) -> Result<Option<ColorGlyphBitmap>, Error>
pub fn raster_color_glyph( &self, glyph_id: u16, size_px: f32, ) -> Result<Option<ColorGlyphBitmap>, Error>
Rasterise the colour bitmap for glyph_id at the strike whose
ppem_y is closest to size_px.round(), at the strike’s
native pixel dimensions.
The returned bitmap is the un-scaled CBDT strike — typically
109 px or 136 px on a side for Noto Color Emoji even when the
caller asked for size_px = 32. Use
Face::raster_color_glyph_at when you want the bitmap
pre-resampled to size_px.
Returns Ok(None) if the face has no CBDT/CBLC, or no strike
covers the glyph, or the per-glyph CBDT entry is in a format we
don’t decode (anything other than 17/18/19 — the three
PNG-payload formats).
Returns Err(Error::InvalidSize) if size_px is non-positive
or NaN, mirroring the rest of the scribe entry points.
Sourcepub fn raster_color_glyph_at(
&self,
glyph_id: u16,
size_px: f32,
) -> Result<Option<ColorGlyphBitmap>, Error>
pub fn raster_color_glyph_at( &self, glyph_id: u16, size_px: f32, ) -> Result<Option<ColorGlyphBitmap>, Error>
Rasterise the colour bitmap for glyph_id, bilinearly
resampled to the requested size_px.
Walks CBLC → CBDT to find the closest strike, decodes the PNG to
straight-alpha RGBA8 (via Face::raster_color_glyph), then
runs RgbaBitmap::resample_bilinear to scale the bitmap to
the dimensions matching size_px at the strike’s aspect ratio.
The returned ColorGlyphBitmap::bearing_x / bearing_y /
advance are also pre-scaled by size_px / ppem (rounded),
and ppem reports the requested raster size (not the strike’s
native ppem) so the caller can use the metrics directly without
a second-stage scale.
Returns the same Ok(None) / Err(Error::InvalidSize) cases as
Face::raster_color_glyph.
Source§impl Face
impl Face
Sourcepub fn from_ttc_bytes(bytes: Vec<u8>, index: u32) -> Result<Self, Error>
pub fn from_ttc_bytes(bytes: Vec<u8>, index: u32) -> Result<Self, Error>
Parse the index-th subfont out of an owned TrueType Collection
(.ttc / 'ttcf') byte buffer. Convenience wrapper around
oxideav_ttf::Font::from_collection_bytes. Index is recorded on
the face so Face::with_font can re-parse the right subfont.
Sourcepub fn from_otf_bytes(bytes: Vec<u8>) -> Result<Self, Error>
pub fn from_otf_bytes(bytes: Vec<u8>) -> Result<Self, Error>
Parse an OTF (OpenType-CFF) font from owned bytes. Returns
a Face whose Face::kind is FaceKind::Otf and whose
outlines come back as cubic Beziers via the cubic flattener
in [crate::outline].
Sourcepub fn id(&self) -> u64
pub fn id(&self) -> u64
Stable per-process id for this face. Used as the first component of the glyph-bitmap cache key.
Sourcepub fn stable_id(&self) -> u64
pub fn stable_id(&self) -> u64
Stable, content-derived identity for this face that is stable
across loads of the same font bytes (in contrast to Face::id
which is a per-process counter). Used as the producer-side
component of the oxideav_core::Group::cache_key emitted by
crate::Shaper::shape_to_paths so the downstream rasterizer’s
bitmap cache reuses the same memoised glyph across renderer
instances and across program restarts.
Implementation: a DefaultHasher digest of the font’s leading
bytes (up to 256) plus the byte length, plus the TTC subfont
index when applicable. Two faces parsed from the same bytes get
the same stable_id; two distinct fonts almost certainly do
not.
Sourcepub fn family_name(&self) -> Option<&str>
pub fn family_name(&self) -> Option<&str>
Family name from the font’s name table. May be None for
stripped or non-standard fonts.
Sourcepub fn units_per_em(&self) -> u16
pub fn units_per_em(&self) -> u16
Units per em (head.unitsPerEm). Practically always 1024 or
2048; never zero in valid fonts.
Sourcepub fn descent_px(&self, size_px: f32) -> f32
pub fn descent_px(&self, size_px: f32) -> f32
Typographic descent in raster pixels (negative for fonts with strokes below the baseline).
Sourcepub fn line_height_px(&self, size_px: f32) -> f32
pub fn line_height_px(&self, size_px: f32) -> f32
Recommended line height: ascent - descent + line_gap, in
raster pixels.
Sourcepub fn italic_angle(&self) -> f32
pub fn italic_angle(&self) -> f32
post.italicAngle in degrees (negative for forward slanted
faces, 0 for upright). Used by crate::style to decide
whether to synthesise italic for an upright font or honour the
font’s own slant.
Sourcepub fn weight_class(&self) -> u16
pub fn weight_class(&self) -> u16
OS/2.usWeightClass (100..=1000). 400 if the font has no
OS/2 table.
Sourcepub fn with_font<R>(&self, f: impl FnOnce(&Font<'_>) -> R) -> Result<R, Error>
pub fn with_font<R>(&self, f: impl FnOnce(&Font<'_>) -> R) -> Result<R, Error>
Run a closure with a freshly-parsed oxideav_ttf::Font<'_>
view of the owned bytes. We re-parse on each call instead of
storing a self-referential Font<'static> (which would
require unsafe or a third-party crate like ouroboros, both
of which we avoid). Re-parsing is read-only header walking —
well under a millisecond on any modern font.
Returns Error::WrongFaceKind if this face was constructed
from OTF bytes; use Face::with_otf_font in that case.
Sourcepub fn subfont_index(&self) -> Option<u32>
pub fn subfont_index(&self) -> Option<u32>
True if this face is the i-th subfont of a TrueType Collection
(the bytes buffer holds the WHOLE TTC; the subfont is selected
at parse-time). Returns None for plain sfnt-flavour faces.
Sourcepub fn is_variable(&self) -> bool
pub fn is_variable(&self) -> bool
true if the underlying font ships an fvar table — i.e. it
exposes one or more variation axes. false for OTF faces and
for static TTF faces.
Sourcepub fn variation_axes(&self) -> Vec<VariationAxis>
pub fn variation_axes(&self) -> Vec<VariationAxis>
All variation axes the font publishes, cloned out of the
underlying fvar. Empty for static / OTF faces. Each
VariationAxis carries min / default / max plus the
tag (b"wght" / b"wdth" / b"opsz" / …) and the name_id
for the human-readable axis label.
Sourcepub fn named_instances(&self) -> Vec<NamedInstance>
pub fn named_instances(&self) -> Vec<NamedInstance>
All named instances (pre-defined axis vectors like “Light”,
“Regular”, “Bold”) the font publishes, in declaration order.
Empty for static / OTF faces. Each NamedInstance carries
subfamily_name_id (a name-table id for the subfamily label),
coords (one f32 per axis matching Self::variation_axes),
and an optional post_script_name_id.
Callers that want to pick an instance by axis vector (e.g. “the
instance whose wght=900”) iterate this slice and inspect
coords. Resolving the human-readable subfamily label requires
reading the name table directly via Self::with_font —
scribe deliberately doesn’t surface a bespoke
name_id → string accessor.
Sourcepub fn variation_coords(&self) -> &[f32]
pub fn variation_coords(&self) -> &[f32]
Current user-space variation coordinates (one entry per axis,
in fvar declaration order). Empty before any
Self::set_variation_coords call AND for static / OTF faces.
Sourcepub fn set_variation_coords(&mut self, coords: &[f32]) -> Result<(), Error>
pub fn set_variation_coords(&mut self, coords: &[f32]) -> Result<(), Error>
Set the user-space variation coordinates that scribe will
re-apply on every Self::with_font re-parse, so subsequent
glyph outline lookups consume the gvar-blended outline at those
coords. Each entry is in user-space units (e.g. wght is
100..900 on Inter).
The vector is silently length-normalised against the axis count
— shorter vectors leave the trailing axes at their previous
value (or each axis’s default for a fresh face), longer vectors
are truncated. Out-of-range values are clamped to each axis’s
[min, max] via the underlying parser, so the value visible
on a subsequent Self::variation_coords call may differ from
what was passed in. No-op for static / OTF faces.
Pre-condition: this method works for FaceKind::Ttf faces
only. Calling it on an OTF face returns Err(WrongFaceKind)
(variable CFF2 / OTF is out of scope for the initial round).
Sourcepub fn clear_variation_coords(&mut self)
pub fn clear_variation_coords(&mut self)
Reset the variation coordinates to the empty vector — i.e.
subsequent with_font re-parses fall back to each axis’s
default value (the static-font baseline). No-op when no
coords were ever set.
Sourcepub fn with_otf_font<R>(
&self,
f: impl FnOnce(&Font<'_>) -> R,
) -> Result<R, Error>
pub fn with_otf_font<R>( &self, f: impl FnOnce(&Font<'_>) -> R, ) -> Result<R, Error>
Run a closure with a freshly-parsed oxideav_otf::Font<'_>
view of the owned bytes. Mirrors Face::with_font for the
CFF / cubic-Bezier path.
Returns Error::WrongFaceKind if this face was constructed
from TTF bytes.
Sourcepub fn glyph_path(&self, glyph_id: u16) -> Option<Path>
pub fn glyph_path(&self, glyph_id: u16) -> Option<Path>
Returns the raw glyph outline as vector commands in the font’s
native Y-up font-unit coordinate space (no Y-flip, no scaling
applied — the canonical “1 em = units_per_em units” frame).
- TT outlines map to
MoveTo+LineTo+QuadCurveTo+Close. Two consecutive off-curve points expand to an implicit on-curve midpoint (the standard TrueType reconstruction rule). - CFF outlines map to
MoveTo+LineTo+CubicCurveTo+Close, mirroring the Type 2 charstring decode directly. - Bitmap-only glyphs (CBDT/sbix where the face has no outline
table) return
None. UseFace::glyph_nodefor a vector wrapper that handles the bitmap-vs-outline dispatch. - COLRv1 layered glyphs (round-6 work) return the base outline
here; the layered group is exposed via
Face::glyph_nodein round 6.
The Y-axis convention deliberately stays Y-up so the returned
Path is “what the font says”. Callers that want Y-down
(oxideav-core’s render convention) should compose with
Transform2D::scale(scale, -scale) and an appropriate
translation, or use Face::glyph_node which bakes that flip
into a render-ready Node.
Sourcepub fn glyph_node(&self, glyph_id: u16, size_px: f32) -> Option<Node>
pub fn glyph_node(&self, glyph_id: u16, size_px: f32) -> Option<Node>
Returns a self-contained Node for glyph_id ready to be
positioned at the pen origin — its local origin (0, 0) is the
glyph’s pen origin, X grows rightward, Y grows downward (matching
oxideav-core / SVG / PDF raster conventions). The Y-flip + size
scale are baked into the path so callers don’t have to reason
about font units.
Dispatch:
- Outline glyph →
Node::Path(PathNode { path, fill: Some(black), .. }). Replacefillif the caller wants colour. - Bitmap glyph (CBDT/sbix from round 5) →
Node::Image(ImageRef { ... })carrying the rasterised RGBA bitmap as aVideoFrame. Bounds are sized to the bitmap’s CBDT-declared placement at the strike’s native ppem (caller scales via the outerTransform2Dwhen blitting at a non-strike size). - COLRv1 layered glyph (round 6 — not yet implemented) — for
now, falls through to the outline path. Round 6 will return a
GroupofPathNodes here, one per COLR layer.
Returns None for empty / non-rendering glyphs (e.g. SPACE).