pub enum Font {
Simple(Box<SimpleFont>),
Type0(Box<Type0Font>),
Type3(Box<Type3Font>),
}Expand description
A loaded PDF font, ready to decode strings and produce glyphs.
Three variants, because PDF has three genuinely different kinds of font and they share almost nothing below the surface: a simple font maps one byte to one glyph through a name, a Type0 font maps a multi-byte code through a CMap to a CID and then to a glyph, and a Type3 font has no glyphs at all — its “glyphs” are content streams the page layer executes.
Variants§
Simple(Box<SimpleFont>)
Type1, MMType1, TrueType, or a font whose /Subtype was missing or
unrecognised — PDFium’s dispatch sends all of those here.
Type0(Box<Type0Font>)
A composite font: /Type0 with a CID-keyed descendant.
Type3(Box<Type3Font>)
A font whose glyph procedures are content streams.
Implementations§
Source§impl Font
impl Font
Sourcepub fn decode<'a>(&'a self, s: &'a [u8]) -> impl Iterator<Item = CharItem> + 'a
pub fn decode<'a>(&'a self, s: &'a [u8]) -> impl Iterator<Item = CharItem> + 'a
Decode a string into one CharItem per character code.
The one text-decoding entry point rendering and extraction share, so they cannot disagree about where one character ends and the next begins — which for a Type0 font is a question only the CMap’s codespace can answer.
Sourcepub fn glyph_path(&self, gid: Gid) -> Option<BezPath>
pub fn glyph_path(&self, gid: Gid) -> Option<BezPath>
A glyph’s outline in 1000/em text space.
None for a missing or degenerate outline, and always for a Type3
font, whose glyphs are content streams rather than outlines.
This is the uncached path. A renderer drawing many glyphs should go
through crate::GlyphCache instead, which keys on the substitution
parameters that change the outline for a Multiple-Master face.
Sourcepub fn hinted_glyph_path(&self, gid: Gid) -> Option<BezPath>
pub fn hinted_glyph_path(&self, gid: Gid) -> Option<BezPath>
A glyph’s outline in 1000/em text space, grid-fitted at 64 ppem.
The same space Self::glyph_path returns, so a caller can substitute
one for the other without touching its matrices — which is what a
renderer rasterizing a glyph bitmap does, since hinting applies to
that path and not to the outline one.
None for every font that is not hinted: a face with no table
directory (every bare CFF and every Type 1 program, so every base-14
substitution), a Type 3 font, and a face whose own programs the
interpreter refuses. In all of them the caller falls back to
Self::glyph_path rather than drawing nothing.
Uncached, and expensive: it builds a hinting instance and runs the face’s bytecode. A renderer should call it only on a bitmap-cache miss.
Sourcepub fn render_synth(&self, xx: i32, xy: i32) -> Option<SynthGlyph>
pub fn render_synth(&self, xx: i32, xy: i32) -> Option<SynthGlyph>
The synthetic italic and embolden the glyph-bitmap side applies, resolved against the device matrix’s two horizontal components.
The bitmap side is a second call site with its own two levels
(CFX_Face::RenderGlyph, cfx_face.cpp:769-778 and :806-816), not
the path side’s, which is why it cannot simply reuse the outline the
glyph cache already adjusted: the render-path embolden level depends on
the device matrix, which only the renderer knows, and the render-path
skew is the effective one rather than the plain one.
xx and xy are the oracle’s own 16.16 quantities —
matrix.a / 64 * 65536 and matrix.c / 64 * 65536
(cfx_face.cpp:766-767) — because the embolden table’s / 36655 is
calibrated to that scale and nothing else. The SynthGlyph that
comes back is therefore in device pixels, and belongs on an outline
already mapped into that space.
None where the C++ returns a negative level and RenderGlyph bails
out with a null bitmap (cfx_face.cpp:809-811): a substitution weight
of 1400 or more, which is past the table. A caller draws nothing.
Sourcepub fn is_vertical(&self) -> bool
pub fn is_vertical(&self) -> bool
Is this a vertical-writing font? Only a Type0 font with a -V CMap is.
Sourcepub fn is_embedded(&self) -> bool
pub fn is_embedded(&self) -> bool
Does the font carry its own program, rather than being substituted?
Consulted far more widely than it looks: PDFium’s per-glyph fallback, its glyph-spacing heuristic and its all-caps aliasing all branch on it, and a program that failed to parse counts as not embedded.
Sourcepub fn is_unicode_compatible(&self) -> bool
pub fn is_unicode_compatible(&self) -> bool
Whether character codes can be turned into Unicode at all, which text extraction uses to decide a font is worth reading.
Sourcepub fn font_bbox(&self) -> Rect
pub fn font_bbox(&self) -> Rect
The font bounding box in 1000/em text space, after the derivation of the former working note has filled in whatever the PDF failed to declare.
Sourcepub fn type3(&self) -> Option<&Type3Font>
pub fn type3(&self) -> Option<&Type3Font>
The Type3 font, when this is one. Its glyph procedures are raw
/CharProcs streams that pdfrum-page executes.
Sourcepub fn base_font_name(&self) -> &[u8] ⓘ
pub fn base_font_name(&self) -> &[u8] ⓘ
The base font name, with any subset prefix already stripped.
Sourcepub fn subst(&self) -> Option<&SubstFont>
pub fn subst(&self) -> Option<&SubstFont>
The substitution record, when the font was substituted rather than embedded. Carries the synthetic skew and embolden levels a renderer applies.
Sourcepub fn char_width(&self, code: CharCode) -> f32
pub fn char_width(&self, code: CharCode) -> f32
The width of one character code in 1000/em text space.
Sourcepub fn applies_glyph_spacing(&self) -> bool
pub fn applies_glyph_spacing(&self) -> bool
Whether this font’s glyphs take the glyph-spacing correction.
Reads the font’s five relevant facts and asks the glyph-spacing rule, where the reasoning lives.
Sourcepub fn glyph_advance(&self, gid: Gid) -> i32
pub fn glyph_advance(&self, gid: Gid) -> i32
One glyph’s own advance width, in 1000/em units, as the face declares it — not as the PDF does.
Zero when there is no face or the glyph has no advance, which callers treat as “unknown” rather than as a genuine zero-width glyph.
Sourcepub fn char_bbox(&self, code: CharCode) -> Rect
pub fn char_bbox(&self, code: CharCode) -> Rect
The bounding box of one character code’s glyph, in 1000/em text space
and y-up: Rect::new(left, bottom, right, top) with
bottom <= top.
Rect::ZERO when there is no glyph, and always for a Type 3 font,
whose glyph boxes are a property of the content streams the page layer
executes rather than of the font.
Text extraction reads this per code — not per decoded string — when it builds a character’s tight box and when its width ladder has run out of better answers.
Sourcepub fn japan1_transform(&self, code: CharCode) -> Option<CidTransform>
pub fn japan1_transform(&self, code: CharCode) -> Option<CidTransform>
The Adobe-Japan1 per-CID transform a character takes, when one applies.
Only a non-embedded Japan1 CID font has one, and only for the hundred and fifty-four CIDs the table lists. It moves the glyph within its em box without touching the advance, so a renderer applies it to the drawing origin alone — the pen walks on as if it were not there.
Non-Japan1, embedded and non-CID fonts all answer None — those three
tests are the whole gate, and there is no fourth.
Sourcepub fn string_width(&self, bytes: &[u8]) -> f32
pub fn string_width(&self, bytes: &[u8]) -> f32
The width of a string of character codes, decoded through this font’s own encoding and summed.
Not the same as summing char_width over the codes
a caller already has: the string is re-decoded, so a code that does not
round-trip through append_char — a simple font’s
code above 255, say — comes back as a different code and contributes
a different width. That difference is the whole point of the rung this
serves in text extraction’s width ladder.
Sourcepub fn type_ascent(&self) -> i32
pub fn type_ascent(&self) -> i32
The typographic ascent, truncated to an integer as the C++ stores it.
Sourcepub fn type_descent(&self) -> i32
pub fn type_descent(&self) -> i32
The typographic descent, truncated to an integer, normally negative.
Sourcepub fn cid_from_charcode(&self, code: CharCode) -> Option<Cid>
pub fn cid_from_charcode(&self, code: CharCode) -> Option<Cid>
The CID a character code maps to, for a composite font only.
Sourcepub fn vert_origin(&self, code: CharCode) -> Option<(f32, f32)>
pub fn vert_origin(&self, code: CharCode) -> Option<(f32, f32)>
The vertical origin of a character code, in 1000/em units, for a composite font only.
Sourcepub fn vert_width(&self, code: CharCode) -> Option<f32>
pub fn vert_width(&self, code: CharCode) -> Option<f32>
The vertical advance of a character code, in 1000/em units, for a composite font only. Normally negative.
Sourcepub fn unicode_from_charcode(&self, code: CharCode) -> SmallVec<[char; 2]>
pub fn unicode_from_charcode(&self, code: CharCode) -> SmallVec<[char; 2]>
The Unicode a character code stands for, /ToUnicode first.
Sourcepub fn char_code_from_unicode(&self, unicode: char) -> Option<CharCode>
pub fn char_code_from_unicode(&self, unicode: char) -> Option<CharCode>
The character code that produces unicode, or None.
The inverse of unicode_from_charcode,
and the direction appearance generation needs: to write a string with
a font the document already carries, a caller has to turn characters
back into the codes that font understands.
None means the font cannot express that character at all, which is
the caller’s signal to pick a different font rather than to emit a
code that will draw the wrong glyph.
use pdfrum_common::{Diagnostics, Limits};
use pdfrum_font::{CharCode, Font, FontCache, StandardFont};
let font = Font::load_standard(StandardFont::Helvetica, &FontCache::new());
assert_eq!(font.char_code_from_unicode('A'), Some(CharCode(u32::from(b'A'))));
// A character no Latin encoding carries.
assert_eq!(font.char_code_from_unicode('\u{4e00}'), None);Sourcepub fn append_char(&self, out: &mut Vec<u8>, code: CharCode)
pub fn append_char(&self, out: &mut Vec<u8>, code: CharCode)
Append one character code to a string being built, in the font’s own byte encoding.
A simple font writes one byte; a composite font writes as many as its
CMap’s codespace says, which is the whole reason this is a method
rather than a cast at the call site. Pairs with
char_code_from_unicode to turn text
into a string a content stream can show.
use pdfrum_font::{CharCode, Font, FontCache, StandardFont};
let font = Font::load_standard(StandardFont::Helvetica, &FontCache::new());
let mut out = Vec::new();
for ch in "Hi".chars() {
if let Some(code) = font.char_code_from_unicode(ch) {
font.append_char(&mut out, code);
}
}
assert_eq!(out, b"Hi");Sourcepub fn load_standard(which: StandardFont, cache: &FontCache) -> Self
pub fn load_standard(which: StandardFont, cache: &FontCache) -> Self
Build one of the fourteen standard fonts, with no document behind it.
Every reader must supply these faces, so a caller that needs to draw
text of its own — an annotation’s appearance stream, say — can have one
without inventing a font dictionary. The result is exactly what
synthesizing /Type /Font /Subtype /Type1 /BaseFont <name> /Encoding /WinAnsiEncoding would produce, which is how PDFium’s own stock-font
path builds them.
use pdfrum_font::{CharCode, Font, FontCache, StandardFont};
let cache = FontCache::new();
let helvetica = Font::load_standard(StandardFont::Helvetica, &cache);
assert_eq!(helvetica.base_font_name(), b"Helvetica");
// The Couriers are fixed-pitch: every glyph is 600 units wide.
let courier = Font::load_standard(StandardFont::Courier, &cache);
assert_eq!(courier.char_width(CharCode(u32::from(b'i'))), 600.0);
assert_eq!(courier.char_width(CharCode(u32::from(b'W'))), 600.0);Sourcepub fn should_use_own_glyph(&self, gid: Option<Gid>) -> bool
pub fn should_use_own_glyph(&self, gid: Option<Gid>) -> bool
Whether this character’s glyph is drawn from this font (ShouldUseFont).
A Type 3 font has no glyph indices and never takes GetCharPosList, so
it always answers true: there is no Arial stand-in for a content stream.
Sourcepub fn glyph_fallback(&self) -> Option<&GlyphFallback>
pub fn glyph_fallback(&self) -> Option<&GlyphFallback>
The Arial stand-in GetCharPosList draws when
Self::should_use_own_glyph fails. Created on first miss; None if
even Arial failed to load.