font

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package font reads font dictionaries and answers the two questions text extraction asks of a font: what does this character code mean, and how far does it advance the text position (ISO 32000-2 §9.5 through §9.7).

Those two questions are why this package exists as a unit. They are usually treated separately — a decoder here, a metrics table there — and separating them is how extractors end up with correct characters in the wrong order, or with the 4,069-character "word" that a single dropped advance produces. Both answers come from the same dictionary and both must agree about which code is being discussed, so both live behind one Font.

A Font is read once per font dictionary and used for every glyph on every page that references it, so the expensive work — parsing a /ToUnicode CMap, walking a /W array, applying /Differences — happens in Load and never again.

This package resolves codes to text and widths. It does not position glyphs: composing the text matrix and inferring inter-word spaces from the gap between advances belongs to extract, because those depend on state this package cannot see. What this package guarantees is that the advance it reports is the one the font actually declares, which is the input that decision needs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsStandard

func IsStandard(fontName string) bool

IsStandard reports whether a font name is one of the standard 14 this package carries metrics for, which is what decides whether a font with no /Widths is still usable.

func StandardWidth

func StandardWidth(fontName, glyph string) (int, bool)

StandardWidth returns the advance of a glyph in one of the standard 14 fonts.

The font name is matched after alias resolution and after any subset prefix is stripped, so "ABCDEF+Arial,Bold" resolves. Reporting false rather than a plausible default is deliberate: the caller falls back to the font descriptor's /MissingWidth, and inventing a width here would silently misplace text.

Types

type Font

type Font struct {
	// Kind decides how Decode splits bytes into codes.
	Kind Kind

	// BaseFont is the /BaseFont name, with any subset prefix intact. Extraction
	// reports it, and the standard-14 metrics match against it.
	BaseFont string

	// Subtype is the font dictionary's /Subtype.
	Subtype string

	// Vertical reports a vertical writing mode, from a CMap name ending in -V.
	// Advances then apply to the y axis, which is the difference between reading
	// a vertical Japanese document and stacking every glyph at one point.
	Vertical bool
	// contains filtered or unexported fields
}

Font is a loaded font dictionary, ready to decode codes and report advances.

Its fields are read-only after Load. Nothing here holds a Store, so a Font outlives the document handle it was read from and is safe to share across goroutines.

func Load

func Load(s objects.Store, d objects.Dict) *Font

Load reads a font dictionary.

It never fails on a defective dictionary. A font with no /Widths, no /ToUnicode, and an unrecognized /Encoding still yields a usable Font: codes decode to nothing and advances fall back to the default, which loses text but keeps the rest of the page. Returning an error instead would abandon a whole document over one bad font, and defective font dictionaries are common in exactly the files that most need extracting.

func (*Font) Bold

func (f *Font) Bold() bool

Bold, Italic, and Monospaced report the font's typographic traits.

func (*Font) CMap

func (f *Font) CMap() *cmap.CMap

CMap returns the font's encoding CMap, or nil for a simple font. Exposed so a caller can ask how a string splits without decoding it.

func (*Font) Decode

func (f *Font) Decode(s []byte) []Glyph

Decode splits a PDF string into glyphs.

Splitting and decoding happen together because they cannot be separated correctly: how many bytes the next code occupies is a question only the font's CMap can answer, and a caller that splits first has already had to guess. This is the specific mistake behind extracted text that has plausible characters in an implausible order.

func (*Font) GlyphName

func (f *Font) GlyphName(code byte) string

GlyphName returns the glyph name a simple font's code maps to, or "" for a composite font or an unmapped code. Diagnostic: it is what `probe` reports and what makes an encoding problem legible.

func (*Font) HasToUnicode

func (f *Font) HasToUnicode() bool

HasToUnicode reports whether the font carries a /ToUnicode CMap. This is the signal that decides whether a page's text is recoverable at all, which is what routes a page to OCR.

func (*Font) Italic

func (f *Font) Italic() bool

func (*Font) Monospaced

func (f *Font) Monospaced() bool

func (*Font) Name

func (f *Font) Name() string

Name returns the /BaseFont name with any subset prefix stripped.

The prefix is stripped because it identifies the subset, not the typeface: the same font subset twice in one document gets two different prefixes, and a consumer grouping runs by font name would treat them as unrelated and break a paragraph at every subset boundary. BaseFont keeps the prefix for callers that want the name exactly as written.

func (*Font) SpaceWidth

func (f *Font) SpaceWidth() float64

SpaceWidth returns the advance of the space glyph, or 0 when the font has none.

Exposed because it is the denominator of the space-inference threshold, which is what turns glyph positions back into words. A consumer comparing gaps in absolute units gets a threshold that is wrong at every font size, so the comparison has to be relative to this.

func (*Font) Text

func (f *Font) Text(code uint32) string

Text returns what a character code means, without measuring it. Decode is the normal entry point; this exists for callers that already know the code.

func (*Font) Width

func (f *Font) Width(code, cid uint32) float64

Width returns a glyph's horizontal advance in glyph space units.

Both the code and the CID are taken because the two font kinds index their metrics differently — a simple font by code offset from /FirstChar, a composite font by CID — and a caller holding a Glyph has both.

type Glyph

type Glyph struct {
	// Code is the character code as written, big-endian.
	Code uint32

	// Bytes is how many bytes Code occupied in the string. Always 1 for a simple
	// font; one to four for a composite one.
	Bytes int

	// CID is the glyph identifier the code maps to, for a composite font. Equal to
	// Code for a simple font, where the two are the same thing.
	CID uint32

	// Text is what the glyph means, which may be several characters for a ligature
	// or empty when the font gives no way to tell. Empty is a real answer and not
	// an error: a symbolic font with no /ToUnicode has genuinely undecodable codes,
	// and substituting U+FFFD would put noise in the output.
	Text string

	// Width is the horizontal advance in 1/1000 em, whatever the font's kind. The
	// caller scales it by font size and any horizontal scaling.
	//
	// 1/1000 is the glyph space of every font kind except Type 3, whose glyph space
	// is whatever its /FontMatrix says (§9.6.4). Those advances are converted into
	// these units when the font loads, so a caller never asks what kind it holds —
	// and must not apply a /FontMatrix again.
	Width float64
}

Glyph is one character code decoded: what it means, how far it advances, and what it was written as.

All four fields travel together because the caller needs them together. A consumer inferring inter-word spaces compares Width against the gap it measures in device space, and one that cannot also see Bytes cannot tell a two-byte code 32 (which /Tw must not affect) from a single-byte space (which it must). Keeping them in one struct is what stops that rule from being lost.

type Kind

type Kind int

Kind distinguishes the two ways a font addresses glyphs, which is the single most consequential fact about it: a simple font takes one byte per glyph, a composite font takes a variable number decided by its CMap. Assuming the wrong one does not produce an error, it produces a plausible-looking stream of wrong glyphs.

const (
	// Simple is a Type1, TrueType, Type3, or MMType1 font: single-byte codes
	// resolved through an encoding.
	Simple Kind = iota

	// Composite is a Type0 font: codes of one to four bytes resolved through a
	// CMap to CIDs.
	Composite
)

Directories

Path Synopsis
Package cmap reads PDF CMaps: the code-to-CID mappings of composite fonts and the code-to-Unicode mappings of /ToUnicode streams (ISO 32000-2 §9.7.5, §9.10.3).
Package cmap reads PDF CMaps: the code-to-CID mappings of composite fonts and the code-to-Unicode mappings of /ToUnicode streams (ISO 32000-2 §9.7.5, §9.10.3).
Package encoding maps simple-font character codes to glyph names and Unicode.
Package encoding maps simple-font character codes to glyph names and Unicode.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL