pub struct TtfFontStore { /* private fields */ }Expand description
Owns the raw bytes of every distinct font file that was loaded, plus a
FontKey(0/1/2) -> file lookup that lets bold/oblique fall back to the
regular face without duplicating its bytes in memory (and, in the PDF
writer, without embedding the same font file twice).
Face ownership: rather than caching a ttf_parser::Face<'a> alongside the
Vec<u8> it borrows from (which needs either unsafe self-referential
storage or a crate like owned-ttf-parser), each accessor reparses a
Face on demand from the stored bytes. Face::parse only walks the sfnt
table directory and a few small required tables (head, hhea, maxp,
OS/2, …); it does not touch glyph outlines, so its cost does not scale
with document size and is cheap at the milestone’s scale (a handful of
pages, one parse per glyph lookup). This keeps TtfFontStore a plain,
safe struct.
Implementations§
Source§impl TtfFontStore
impl TtfFontStore
Sourcepub fn load(
regular: &Path,
bold: Option<&Path>,
oblique: Option<&Path>,
) -> Result<Self, FontError>
pub fn load( regular: &Path, bold: Option<&Path>, oblique: Option<&Path>, ) -> Result<Self, FontError>
Load up to three faces. bold/oblique fall back to regular when
not given.
Sourcepub fn from_bytes(
regular: Vec<u8>,
bold: Option<Vec<u8>>,
oblique: Option<Vec<u8>>,
label: &str,
) -> Result<Self, FontError>
pub fn from_bytes( regular: Vec<u8>, bold: Option<Vec<u8>>, oblique: Option<Vec<u8>>, label: &str, ) -> Result<Self, FontError>
Self::load for bytes that never came from a path.
The WebAssembly build is why this exists: a browser has no filesystem,
so a font supplied by the user arrives as bytes from a file picker.
label names the source in a FontError::Parse — a file name, a URL,
whatever the caller can show the user — since there is no path to
report.
bold/oblique fall back to regular when absent, exactly as
Self::load does, and the bytes are shared rather than duplicated.
Sourcepub fn file_index(&self, font: FontKey) -> usize
pub fn file_index(&self, font: FontKey) -> usize
The physical-file index backing font (after bold/oblique fallback).
Used by the CID embedder to dedup: two FontKeys that resolve to the
same file are embedded (and their Type0 font object shared) once.
pub rather than pub(crate) because rustyfi-html needs it too, to
key its @font-face set by physical file the same way — a one-way
dependency, since rustyfi-pdf does not depend back on it.
pub fn num_files(&self) -> usize
Sourcepub fn file_bytes(&self, file_index: usize) -> &[u8] ⓘ
pub fn file_bytes(&self, file_index: usize) -> &[u8] ⓘ
Raw bytes of a physical file, for FontFile2 embedding.
Sourcepub fn file_family_name(&self, file_index: usize) -> Option<String>
pub fn file_family_name(&self, file_index: usize) -> Option<String>
The typographic family name a physical file declares in its name
table (English where the font offers it, since that is what a CSS
font-family has to match), or None for a file with no usable
family record.
pub for rustyfi-html’s reflow backend, which NAMES fonts rather
than embedding them: a reflowed document is explicitly not
metric-faithful, so paying several megabytes of base64 to pin the
exact face would buy nothing it wants and cost the reader everything
(fonts::reflow_font_stack). The faithful backend still embeds.
Sourcepub fn abbrev_key(&self, abbrev: &str) -> Option<FontKey>
pub fn abbrev_key(&self, abbrev: &str) -> Option<FontKey>
Resolve a registry abbrev (“ipaexm”, “Junicode-b”, …) to its
allocated FontKey, or None if the store has no such abbrev
(either it wasn’t configured, or the store came from a bare load).
Trait Implementations§
Source§impl FontMetrics for TtfFontStore
impl FontMetrics for TtfFontStore
Source§fn math_script_variant(
&self,
font: FontKey,
c: char,
size: Length,
) -> Option<MathVariantGlyph>
fn math_script_variant( &self, font: FontKey, c: char, size: Length, ) -> Option<MathVariantGlyph>
ssty (Math Script Style): the GSUB feature a math font uses to swap in
purpose-drawn exponent/index forms — upstream’s
FontFormat.get_math_script_variant (fontFormat.ml:2216-2241).
Two divergences from upstream’s fold, neither reachable in the math fonts this port ships or tests against:
- upstream reaches
sstythrough a SCRIPT and its default langsys (fontFormat.ml:2185-2194); this scans the feature LIST by tag, so a font whosesstydiffers per script would diverge; - an
Alternatesubstitution takes the FIRST alternate — upstream’sgidorgto :: _verbatim, where OpenType would index it by script LEVEL. Matching upstream is the point.
Upstream substitutes ssty BEFORE looking for a MathVariants vertical
variant (fontInfo.ml:379-401); this port applies it in
push_char_glyph only, so a big operator inside a script keeps its
unsubstituted vertical variant. The two coverages are disjoint in the
fonts here, so the orders agree.
Source§fn math_vertical_variant(
&self,
font: FontKey,
c: char,
size: Length,
policy: VertVariantPolicy,
) -> Option<MathVariantGlyph>
fn math_vertical_variant( &self, font: FontKey, c: char, size: Length, policy: VertVariantPolicy, ) -> Option<MathVariantGlyph>
Pick a vertically-grown MATH variant (MathVariants) of c per
policy and report its real per-glyph ink metrics at size.
Assembly-only constructions (variants.len() == 0, big enough
stretchy delimiters in some fonts) return None here — they are
math_vertical_assembly’s job.
Source§fn math_vertical_assembly(
&self,
font: FontKey,
c: char,
size: Length,
target: Length,
) -> Option<Vec<(u16, Length, Length)>>
fn math_vertical_assembly( &self, font: FontKey, c: char, size: Length, target: Length, ) -> Option<Vec<(u16, Length, Length)>>
Stretch c (via OpenType MATH GlyphAssembly) beyond the largest discrete
MathVariants record by stacking the assembly’s GlyphParts
vertically, repeating extender parts to reach target. Faithful to
the OpenType “assembling glyphs” recipe (and math.ml’s
MathVariants/GlyphConstruction reader): parts are listed
bottom-to-top; every non-extender part is placed exactly once, and all
extender parts are repeated the same number of times r (the smallest
r whose stacked extent, at the minimum min_connector_overlap
overlap, covers target). Each connection overlaps by exactly
min_connector_overlap design units (the smallest legal overlap, which
yields the LONGEST assembly for a given part count — so the result
always covers target). Returns (gid, dy, advance) per placed part
with dy the y-up box-local baseline offset (bottom part at dy = 0,
each next part raised by the previous part’s advance minus the
overlap) and advance the part’s full_advance scaled to size.
Source§fn font_abbrev(&self, key: FontKey) -> Option<String>
fn font_abbrev(&self, key: FontKey) -> Option<String>
Reverse scan of abbrevs. Linear, but that map holds one row per
configured font (tens at most) and get-font is called a handful of
times per document, so a second index would cost more than it saves.
Source§fn advance(&self, font: FontKey, c: char, size: Length) -> Option<Length>
fn advance(&self, font: FontKey, c: char, size: Length) -> Option<Length>
c at size, or None if the font has no
glyph for it.Source§fn descender(&self, font: FontKey, size: Length) -> Length
fn descender(&self, font: FontKey, size: Length) -> Length
size (a positive value).Source§fn glyph_vextent(
&self,
font: FontKey,
c: char,
size: Length,
) -> Option<(Length, Length)>
fn glyph_vextent( &self, font: FontKey, c: char, size: Length, ) -> Option<(Length, Length)>
(height above baseline = ymax, depth below baseline = -ymin), both in
size units. None when the provider has no per-glyph bbox (base-14 /
test stubs), in which case run_vextent falls back to
ascender/descender. This is how SATySFi measures glyphs
(fontFormat.ml’s get_glyph_metrics: hgt = ymax, dpt = ymin).Source§fn math_constants(&self, font: FontKey) -> Option<MathConstants>
fn math_constants(&self, font: FontKey) -> Option<MathConstants>
MathConstants table, or None when the
font has no MATH table (every base-14/non-math provider). Lang-side
math layout (MathC resolver) falls back to the pre-MATH-table
fixed constants whenever this is None, so a provider that never
overrides it (like Base14Metrics) keeps today’s fixtures
byte-identical.Source§fn italic_correction(
&self,
font: FontKey,
c: char,
size: Length,
) -> Option<Length>
fn italic_correction( &self, font: FontKey, c: char, size: Length, ) -> Option<Length>
c at size (OpenType MATH
MathItalicsCorrectionInfo), or None when the font has no MATH
table or no entry for this glyph.Source§fn math_kern(
&self,
font: FontKey,
c: char,
size: Length,
corner: MathCorner,
corr: Length,
) -> Option<Length>
fn math_kern( &self, font: FontKey, c: char, size: Length, corner: MathCorner, corr: Length, ) -> Option<Length>
c at size, sampled at
correction height corr (MathKernInfo/MathKern), or None when
the font has no MATH table or no kern data for this glyph/corner.Source§fn resolve_font_abbrev(&self, abbrev: &str) -> Option<FontKey>
fn resolve_font_abbrev(&self, abbrev: &str) -> Option<FontKey>
"ipaexm", "Junicode-b", …) to its
FontKey. None means either “no such abbrev in this
provider’s registry” or “this provider has no registry at all” (every
provider that predates the registry, Base14Metrics) — the caller
then falls back to the milestone-1 3-face name heuristic
(resolve_font_abbrev free fn, rustyfi-lang), keeping every existing
set-font call byte-identical.Source§fn default_script_font(&self, script: Script) -> Option<(FontKey, f64, f64)>
fn default_script_font(&self, script: Script) -> Option<(FontKey, f64, f64)>
(font, ratio, rising) for script, from
default-font.satysfi-hash’s scripts block. None means “no
scheme configured for this script” — the caller then falls back to
(ctx.font, 1.0, 0.0), i.e. today’s single-font behavior.Source§fn default_math_font(&self) -> Option<FontKey>
fn default_math_font(&self) -> Option<FontKey>
default-font.satysfi-hash’s
optional "math" abbrev. None means “no math default
configured” — the caller (get-initial-context) then leaves
Context::math_font at its Context::initial seed (FontKey(0), the
regular text face), i.e. today’s behavior. Every provider that
predates this math-default support (Base14Metrics, a bare
TtfFontStore::load, a registry with no "math" entry) returns
None here, so this is purely additive.Source§fn run_vextent(
&self,
font: FontKey,
text: &str,
size: Length,
) -> (Length, Length)
fn run_vextent( &self, font: FontKey, text: &str, size: Length, ) -> (Length, Length)
(height, depth) the way SATySFi’s get_metrics_of_word
(fontInfo.ml:192) computes it: the MAX glyph ymax and MAX -ymin
over the run’s actual glyph bounding boxes — NOT the font-level
ascender/descender. Starting the folds at zero clamps a run with no
descenders (Japanese, digits, TOC leader dots) to depth 0, matching
SATySFi’s much tighter inter-line advance for such content. Falls back
to ascender/descender when no glyph exposes a bbox.