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