Skip to main content

Face

Struct Face 

Source
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

Source

pub fn has_color_bitmaps(&self) -> bool

true when this face ships CBDT/CBLC tables. Wraps oxideav_ttf::Font::has_color_bitmaps.

Source

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.

Source

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.

Source

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

Source

pub fn from_ttf_bytes(bytes: Vec<u8>) -> Result<Self, Error>

Parse a TTF from owned bytes.

Source

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.

Source

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].

Source

pub fn kind(&self) -> FaceKind

Underlying parser flavour for this face.

Source

pub fn id(&self) -> u64

Stable per-process id for this face. Used as the first component of the glyph-bitmap cache key.

Source

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.

Source

pub fn family_name(&self) -> Option<&str>

Family name from the font’s name table. May be None for stripped or non-standard fonts.

Source

pub fn units_per_em(&self) -> u16

Units per em (head.unitsPerEm). Practically always 1024 or 2048; never zero in valid fonts.

Source

pub fn ascent_px(&self, size_px: f32) -> f32

Typographic ascent in raster pixels at size_px.

Source

pub fn descent_px(&self, size_px: f32) -> f32

Typographic descent in raster pixels (negative for fonts with strokes below the baseline).

Source

pub fn line_height_px(&self, size_px: f32) -> f32

Recommended line height: ascent - descent + line_gap, in raster pixels.

Source

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.

Source

pub fn weight_class(&self) -> u16

OS/2.usWeightClass (100..=1000). 400 if the font has no OS/2 table.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

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. Use Face::glyph_node for 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_node in 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.

Source

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 glyphNode::Path(PathNode { path, fill: Some(black), .. }). Replace fill if the caller wants colour.
  • Bitmap glyph (CBDT/sbix from round 5) → Node::Image(ImageRef { ... }) carrying the rasterised RGBA bitmap as a VideoFrame. Bounds are sized to the bitmap’s CBDT-declared placement at the strike’s native ppem (caller scales via the outer Transform2D when 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 Group of PathNodes here, one per COLR layer.

Returns None for empty / non-rendering glyphs (e.g. SPACE).

Trait Implementations§

Source§

impl Debug for Face

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Face

§

impl RefUnwindSafe for Face

§

impl Send for Face

§

impl Sync for Face

§

impl Unpin for Face

§

impl UnsafeUnpin for Face

§

impl UnwindSafe for Face

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> 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, 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.