pub struct Font {
pub units_per_em: u16,
pub num_glyphs: u16,
pub ascent: i16,
pub descent: i16,
pub line_gap: i16,
/* private fields */
}Expand description
A parsed font, owning its backing bytes.
Fields§
§units_per_em: u16Font design units per em (the coordinate scale; advances are in these).
num_glyphs: u16Number of glyphs in the font.
ascent: i16Typographic ascender (design units).
descent: i16Typographic descender (design units, usually negative).
line_gap: i16Recommended extra line gap (design units).
Implementations§
Source§impl Font
impl Font
Sourcepub fn cff_outline(&self, gid: u16) -> Result<CffOutline, SubsetError>
pub fn cff_outline(&self, gid: u16) -> Result<CffOutline, SubsetError>
Decode a CFF1 glyph, preserving exact cubic control points. No host APIs.
Examples found in repository?
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 let args: Vec<_> = std::env::args().collect();
5 let font = Font::parse(std::fs::read(&args[1])?)?;
6 for gid in 0..font.num_glyphs {
7 let outline = font.cff_outline(gid)?;
8 println!("G {gid} {} {}", outline.advance, outline.lsb);
9 for c in outline.commands {
10 match c {
11 Command::Move(p) => println!("M {} {}", p.x, p.y),
12 Command::Line(p) => println!("L {} {}", p.x, p.y),
13 Command::Curve(a, b, c) => {
14 println!("C {} {} {} {} {} {}", a.x, a.y, b.x, b.y, c.x, c.y)
15 }
16 Command::Close => println!("Z"),
17 }
18 }
19 }
20 if let Some(path) = args.get(2) {
21 let subset = font.try_subset_glyphs(&[1, 5, 73, 100, 500, 1000, 2000, 3000], &[])?;
22 std::fs::write(path, subset.bytes)?;
23 }
24 Ok(())
25}Source§impl Font
impl Font
Sourcepub fn glyph_outline(&self, gid: u16) -> Result<GlyphOutline, OutlineError>
pub fn glyph_outline(&self, gid: u16) -> Result<GlyphOutline, OutlineError>
Decode glyph gid to quadratic contours with phantom-point-correct
metrics. Blank glyphs (space) succeed with empty contours.
§Errors
OutlineError::NoGlyfOutlines for CFF-only fonts,
OutlineError::BadGlyphId for out-of-range ids, and
OutlineError::Malformed / OutlineError::BudgetExceeded for
structurally invalid or hostile glyph data.
Source§impl Font
impl Font
Sourcepub fn shape(
&self,
text: &str,
opts: &ShapeOptions<'_>,
) -> Result<ShapedRun, ShapeError>
pub fn shape( &self, text: &str, opts: &ShapeOptions<'_>, ) -> Result<ShapedRun, ShapeError>
Shape a single explicitly segmented run. See module docs for exact coverage.
Examples found in repository?
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let args: Vec<_> = std::env::args().collect();
8 let f = Font::parse(std::fs::read(&args[1])?)?;
9 let arabic = args[2] == "arab";
10 let options = ShapeOptions {
11 script: if arabic { *b"arab" } else { *b"latn" },
12 direction: if arabic {
13 Direction::RightToLeft
14 } else {
15 Direction::LeftToRight
16 },
17 ..ShapeOptions::default()
18 };
19 let run = f.shape(&args[3], &options)?;
20 for g in run.glyphs {
21 println!(
22 "{} {} {} {} {} {} {}",
23 g.glyph_id,
24 g.cluster.start,
25 g.cluster.end,
26 g.x_advance,
27 g.y_advance,
28 g.x_offset,
29 g.y_offset
30 );
31 }
32 Ok(())
33}Source§impl Font
impl Font
Sourcepub fn try_subset(&self, keep: &[char]) -> Result<Subset, SubsetError>
pub fn try_subset(&self, keep: &[char]) -> Result<Subset, SubsetError>
Strict subset for browser embedding. Unlike the legacy Option API, invalid glyphs and malformed composites are refused, never repaired.
Sourcepub fn try_subset_glyphs(
&self,
glyphs: &[u16],
cmap_chars: &[char],
) -> Result<Subset, SubsetError>
pub fn try_subset_glyphs( &self, glyphs: &[u16], cmap_chars: &[char], ) -> Result<Subset, SubsetError>
Strict subset of a pre-shaped glyph set, with explicit embedding format.
Examples found in repository?
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 let args: Vec<_> = std::env::args().collect();
5 let font = Font::parse(std::fs::read(&args[1])?)?;
6 for gid in 0..font.num_glyphs {
7 let outline = font.cff_outline(gid)?;
8 println!("G {gid} {} {}", outline.advance, outline.lsb);
9 for c in outline.commands {
10 match c {
11 Command::Move(p) => println!("M {} {}", p.x, p.y),
12 Command::Line(p) => println!("L {} {}", p.x, p.y),
13 Command::Curve(a, b, c) => {
14 println!("C {} {} {} {} {} {}", a.x, a.y, b.x, b.y, c.x, c.y)
15 }
16 Command::Close => println!("Z"),
17 }
18 }
19 }
20 if let Some(path) = args.get(2) {
21 let subset = font.try_subset_glyphs(&[1, 5, 73, 100, 500, 1000, 2000, 3000], &[])?;
22 std::fs::write(path, subset.bytes)?;
23 }
24 Ok(())
25}Sourcepub fn try_subset_glyphs_with_lookup(
&self,
glyphs: &[u16],
cmap_chars: &[char],
) -> Result<Subset, SubsetError>
pub fn try_subset_glyphs_with_lookup( &self, glyphs: &[u16], cmap_chars: &[char], ) -> Result<Subset, SubsetError>
Dense-map spelling for callers migrating from the legacy lookup API.
Source§impl Font
impl Font
Sourcepub fn parse(data: Vec<u8>) -> Result<Self, FontError>
pub fn parse(data: Vec<u8>) -> Result<Self, FontError>
Parse a font from its raw bytes (e.g. an include_bytes! blob).
§Errors
Returns a FontError for a non-sfnt file, a missing required table, a
truncated file, or the absence of a usable Unicode cmap.
Examples found in repository?
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let args: Vec<_> = std::env::args().collect();
8 let f = Font::parse(std::fs::read(&args[1])?)?;
9 let arabic = args[2] == "arab";
10 let options = ShapeOptions {
11 script: if arabic { *b"arab" } else { *b"latn" },
12 direction: if arabic {
13 Direction::RightToLeft
14 } else {
15 Direction::LeftToRight
16 },
17 ..ShapeOptions::default()
18 };
19 let run = f.shape(&args[3], &options)?;
20 for g in run.glyphs {
21 println!(
22 "{} {} {} {} {} {} {}",
23 g.glyph_id,
24 g.cluster.start,
25 g.cluster.end,
26 g.x_advance,
27 g.y_advance,
28 g.x_offset,
29 g.y_offset
30 );
31 }
32 Ok(())
33}More examples
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 let args: Vec<_> = std::env::args().collect();
5 let font = Font::parse(std::fs::read(&args[1])?)?;
6 for gid in 0..font.num_glyphs {
7 let outline = font.cff_outline(gid)?;
8 println!("G {gid} {} {}", outline.advance, outline.lsb);
9 for c in outline.commands {
10 match c {
11 Command::Move(p) => println!("M {} {}", p.x, p.y),
12 Command::Line(p) => println!("L {} {}", p.x, p.y),
13 Command::Curve(a, b, c) => {
14 println!("C {} {} {} {} {} {}", a.x, a.y, b.x, b.y, c.x, c.y)
15 }
16 Command::Close => println!("Z"),
17 }
18 }
19 }
20 if let Some(path) = args.get(2) {
21 let subset = font.try_subset_glyphs(&[1, 5, 73, 100, 500, 1000, 2000, 3000], &[])?;
22 std::fs::write(path, subset.bytes)?;
23 }
24 Ok(())
25}Sourcepub fn has_glyf_outlines(&self) -> bool
pub fn has_glyf_outlines(&self) -> bool
True when the font carries TrueType (glyf) outlines we can read/subset.
Sourcepub fn axes(&self) -> &[VariationAxis]
pub fn axes(&self) -> &[VariationAxis]
Variation axes from fvar, in table order. Empty for static fonts.
Sourcepub fn named_instances(&self) -> &[NamedInstance]
pub fn named_instances(&self) -> &[NamedInstance]
Named instances from fvar. Empty when the table is absent or has none.
Sourcepub fn instance_bounds(&self, tag: [u8; 4]) -> Option<AxisBounds>
pub fn instance_bounds(&self, tag: [u8; 4]) -> Option<AxisBounds>
User-space (min, default, max) for the axis whose tag is tag.
Sourcepub fn normalized_axis(&self, tag: [u8; 4], user: f32) -> Option<f32>
pub fn normalized_axis(&self, tag: [u8; 4], user: f32) -> Option<f32>
Clamp user to the axis bounds, normalize to [-1, 1], then apply
avar (identity when the table is absent or that axis has no maps).
Values below min and above max map to the corresponding endpoints
(-1 / +1 after identity avar).
Sourcepub fn instance(&self, weight: f32) -> Option<Font>
pub fn instance(&self, weight: f32) -> Option<Font>
Instance this face at CSS font-weight weight on the wght axis.
Applies gvar tuple deltas (packed point numbers, packed deltas, IUP)
and returns a static TrueType font: fvar/avar/gvar are
dropped, glyf/loca hold the frozen outlines. None when the font
has no wght axis, no TrueType outlines, or a table is unreadable.
The same weight twice yields identical bytes.
Sourcepub fn as_sfnt(&self) -> &[u8] ⓘ
pub fn as_sfnt(&self) -> &[u8] ⓘ
Current sfnt bytes. After Self::instance, this is the static
instanced face (fvar/avar/gvar dropped).
Sourcepub fn glyph_data(&self, gid: u16) -> Option<&[u8]>
pub fn glyph_data(&self, gid: u16) -> Option<&[u8]>
Raw glyf bytes for glyph gid (for subset embedding), or None.
An empty (zero-length) glyph yields Some(&[]).
Sourcepub fn glyph_bbox(&self, gid: u16) -> Option<[i16; 4]>
pub fn glyph_bbox(&self, gid: u16) -> Option<[i16; 4]>
Glyph bounding box [xMin, yMin, xMax, yMax] (design units), or None
for an empty glyph / no outlines.
Sourcepub fn is_composite(&self, gid: u16) -> bool
pub fn is_composite(&self, gid: u16) -> bool
True when glyph gid is a composite (built from component glyphs).
Sourcepub fn glyph_components(&self, gid: u16) -> Vec<u16>
pub fn glyph_components(&self, gid: u16) -> Vec<u16>
Component glyph ids referenced by a composite glyph (for transitive subsetting). Empty for simple or empty glyphs.
Sourcepub fn advance_width(&self, gid: u16) -> u16
pub fn advance_width(&self, gid: u16) -> u16
The advance width of glyph gid in design units. Glyphs past the
hmtx metric run share the last advance (monospaced trailing run).
Sourcepub fn left_side_bearing(&self, gid: u16) -> i16
pub fn left_side_bearing(&self, gid: u16) -> i16
The left side bearing of glyph gid in design units. Glyphs past the
long-metric run share the last advance but keep their own trailing LSB.
Sourcepub fn glyph_index(&self, ch: char) -> u16
pub fn glyph_index(&self, ch: char) -> u16
The glyph id for a character, or 0 (.notdef) if unmapped.
Sourcepub fn advance_1000(&self, ch: char) -> u32
pub fn advance_1000(&self, ch: char) -> u32
Advance width of ch in 1/1000 em (PDF text-space units). An unmapped
ch resolves to glyph 0 (.notdef) and reserves that glyph’s advance
(so a tofu box still occupies its natural width); only an unparsable face
with units_per_em == 0 yields 0.
Sourcepub fn kerning_between_glyphs(&self, left: u16, right: u16) -> i16
pub fn kerning_between_glyphs(&self, left: u16, right: u16) -> i16
Kerning adjustment between two glyph ids in design units.
Unsupported or absent kerning tables return zero. This currently supports
legacy TrueType/Microsoft kern table version 0, format 0, horizontal
pairs. GPOS pair positioning is tracked separately.
Sourcepub fn kerning(&self, left: char, right: char) -> i16
pub fn kerning(&self, left: char, right: char) -> i16
Kerning adjustment between two characters in design units.
Sourcepub fn kerning_1000(&self, left: char, right: char) -> i32
pub fn kerning_1000(&self, left: char, right: char) -> i32
Kerning adjustment between two characters in 1/1000 em units.
Sourcepub fn subset(&self, keep: &[char]) -> Option<Vec<u8>>
pub fn subset(&self, keep: &[char]) -> Option<Vec<u8>>
Build a new, minimal, valid TrueType (glyf) font containing glyph 0
(.notdef) plus exactly the glyphs needed to render keep (mapped
through the original cmap), transitively closing over composite
components. Returns a fresh sfnt (0x00010000) suitable for a PDF
FontFile2, or None on any failure (missing glyf/loca/required
table, or a malformed read).
Sourcepub fn subset_glyphs(
&self,
glyphs: &[u16],
cmap_chars: &[char],
) -> Option<(Vec<u8>, BTreeMap<u16, u16>)>
pub fn subset_glyphs( &self, glyphs: &[u16], cmap_chars: &[char], ) -> Option<(Vec<u8>, BTreeMap<u16, u16>)>
Subset to an explicit glyph set (the closure still pulls in composite
components), building the cmap from cmap_chars. Returns the font bytes
plus the old->new glyph id remap — for callers that pre-shaped a glyph
sequence (e.g. GSUB ligatures) and must emit the renumbered ids.
The map is the ordered projection of Font::subset_glyphs_with_lookup;
prefer that method when a dense lookup table is more useful than an
ordered map (same font bytes, no per-glyph tree nodes).
§Errors
Returns None for a font without glyf/loca outlines or on a malformed
read (same conditions as Font::subset).
Sourcepub fn subset_glyphs_with_lookup(
&self,
glyphs: &[u16],
cmap_chars: &[char],
) -> Option<(Vec<u8>, Vec<u16>)>
pub fn subset_glyphs_with_lookup( &self, glyphs: &[u16], cmap_chars: &[char], ) -> Option<(Vec<u8>, Vec<u16>)>
Subset to an explicit glyph set (same closure and cmap construction as
Font::subset_glyphs), returning the font bytes plus the subsetter’s
own dense old->new lookup: lookup[old] is the glyph’s renumbered id in
the subset, or MISSING_GLYPH_REMAP when old is not part of it.
The vector has max(num_glyphs, 1) entries indexed by old gid — the
exact table the subsetter builds internally, so callers translating
pre-shaped glyph runs need neither an ordered map nor a rebuild of
this very vector. Font bytes are identical to Font::subset_glyphs.
§Errors
Returns None for a font without glyf/loca outlines or on a malformed
read (same conditions as Font::subset).