sfnt

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package sfnt reads the parts of a TrueType or OpenType font that embedding one in a PDF needs, and cuts a subset of it down to the glyphs a document actually uses.

It is deliberately not a font library. It does not rasterize, it does not shape, it does not kern, and it reads no table it has no use for. What it answers is the four questions github.com/timzifer/refract/backend/pdf has to ask before it can write a font into a document: which glyph is this rune, how wide is that glyph, what does the font descriptor say about the face, and what is the smallest file that still draws these glyphs.

It lives in the core module because the core module has no dependencies and keeps none — see AGENTS.md — and because parsing a table-directory format is a few hundred lines of `binary.BigEndian` and nothing else.

What it supports

TrueType outlines — a `glyf` and `loca` pair — are parsed and can be subset. CFF outlines, which is what an `.otf` file usually carries, are recognised and *not* subset: the charstring format is a second interpreter and cutting one up correctly is a different project. Such a font is embedded whole, which is a correct document and a larger one; Font.CanSubset is how a caller finds out which it has.

Bitmap-only fonts, `ttc` collections and variable-font instancing are out of scope and are refused rather than half-read.

Index

Constants

This section is empty.

Variables

View Source
var ErrFormat = errors.New("refract/internal/sfnt: unsupported font file")

ErrFormat reports a file this package cannot read.

Functions

This section is empty.

Types

type Font

type Font struct {
	// contains filtered or unexported fields
}

Font is a parsed font.

It borrows the bytes it was parsed from: the tables are slices into the caller's buffer, so the buffer must outlive the Font. That is the same bargain github.com/timzifer/refract/data.Float64Columns makes about a column, for the same reason — a font file is a megabyte and copying it to read four tables would be the only allocation in the package worth naming.

func Parse

func Parse(b []byte) (*Font, error)

Parse reads a font file.

func (*Font) Advance

func (f *Font) Advance(g uint16) int

Advance is glyph g's advance width in font units.

func (*Font) Ascent

func (f *Font) Ascent() int

Ascent, Descent, CapHeight and the bounding box are the descriptor's numbers, in font units. Descent is negative, as the font stores it.

func (*Font) BBox

func (f *Font) BBox() (xMin, yMin, xMax, yMax int)

func (*Font) CFF

func (f *Font) CFF() bool

CFF reports whether the outlines are CFF charstrings, which decides which PDF font subtype the caller has to write.

func (*Font) CanSubset

func (f *Font) CanSubset() bool

CanSubset reports whether this font's outlines can be cut down. It is true for TrueType outlines and false for CFF ones — see the package comment.

func (*Font) CapHeight

func (f *Font) CapHeight() int

func (*Font) Descent

func (f *Font) Descent() int

func (*Font) GlyphIndex

func (f *Font) GlyphIndex(r rune) uint16

GlyphIndex maps a rune to a glyph, returning 0 — .notdef — for a rune the font has no glyph for.

func (*Font) HasUnicodeMap

func (f *Font) HasUnicodeMap() bool

HasUnicodeMap reports whether the font carries a character map this package can read. A font without one — which includes every subset Font.Subset writes — answers 0 for every rune, because a CID font addresses glyphs by id and never asks.

func (*Font) ItalicAngle

func (f *Font) ItalicAngle() float64

ItalicAngle is degrees anticlockwise from vertical, negative for a face that leans right.

func (*Font) NumGlyphs

func (f *Font) NumGlyphs() int

NumGlyphs is how many glyphs the font has.

func (*Font) PostScriptName

func (f *Font) PostScriptName() string

PostScriptName is the font's own name, or "" when it carries none.

func (*Font) Raw

func (f *Font) Raw() []byte

Raw returns the bytes the font was parsed from, which is what a caller embedding a font it cannot subset writes out.

func (*Font) Subset

func (f *Font) Subset(order []uint16) (data []byte, final []uint16, err error)

Subset builds a font file holding only the glyphs in order, renumbered so that glyph i of the result is order[i] of the original.

The caller decides the order and the result honours it, which is what lets a PDF writer hand out a glyph id the moment it first sees a rune and write the content stream immediately, rather than buffering the whole document until it knows which glyphs it used. First-appearance order is also what makes the output a pure function of the input — the same rule [ADR 0012](../../docs/adr/0012-parallel-panels.md) puts on everything else in this repository that could have reached for a map.

order[0] must be glyph 0, the .notdef glyph: every TrueType font has one and every consumer assumes glyph 0 is it.

A composite glyph refers to other glyphs, so the subset is closed over those references: the components are appended to order and the returned slice is the order the result actually uses, which is order with whatever it pulled in. A caller that assigned ids from its own copy of order therefore keeps them — nothing already in the list moves.

func (*Font) UnitsPerEm

func (f *Font) UnitsPerEm() int

UnitsPerEm is the font's design grid.

func (*Font) WeightClass

func (f *Font) WeightClass() int

WeightClass is the OS/2 usWeightClass, or 0 for a font that carries none.

Jump to

Keyboard shortcuts

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