Documentation
¶
Overview ¶
Package typeset loads TrueType fonts, shapes and wraps text, and places one text block on a page. It is pure computation: it knows nothing about PDF.
Fonts ¶
A Font is an immutable, validated static TrueType font (glyf outlines). Variable fonts, CFF (OpenType/CFF), collections, fonts whose OS/2 fsType forbids embedding, and malformed files are rejected with an error; loading never panics. A font's identity is the SHA-256 of its bytes. A Font is safe to share between goroutines.
Text ¶
Text is left-to-right Latin, Greek and Cyrillic (script classes Common and Inherited included) with combining marks positioned by the font's GPOS. Text is never normalized: decomposed and precomposed forms stay as given. Every character must have a glyph in the font; a missing glyph is an error, never a substitute box. Right-to-left and complex scripts, control characters (including TAB), and format characters (joiners, bidi controls, soft hyphen) are rejected early with a TextError.
Whitespace ¶
- CRLF and lone CR are line breaks, equivalent to LF.
- Every LF ends a paragraph; one final LF adds no empty paragraph. Empty text has no lines.
- U+0020 is the only breaking and justification space. Runs of spaces are preserved verbatim: leading and interior spaces occupy width. Spaces at a wrap point are consumed by the break. Trailing spaces of a line never count towards its width and are never justified.
- U+00A0 and every other space character are ordinary glyphs: never a break opportunity, never collapsed, never justified.
- U+2028 and U+2029 are rejected.
Placement ¶
A text block is as wide as the wrap width (or the widest line when there is no wrap width, or the widest overflowing line) and as high as first-line ascent plus last-line descent plus the line advances. The block is anchored to one of nine points of the page and moved by offsets (+x right, +y up, points); the alignment acts inside the block. The block bounds use font advances, ascent and descent, not glyph ink.
Concurrency ¶
A Shaper holds mutable shaping state and must not be shared between goroutines; use one per goroutine. The returned Placed values are plain data.
Index ¶
- Constants
- Variables
- type Align
- type Anchor
- type Cluster
- type Digest
- type EmbeddingError
- type Finding
- type FindingKind
- type Font
- func (f *Font) Ascent() float64
- func (f *Font) BBox() [4]int
- func (f *Font) Bytes() []byte
- func (f *Font) CapHeight() float64
- func (f *Font) Descent() float64
- func (f *Font) GlyphAdvance(glyph uint16) int
- func (f *Font) GlyphText(glyph uint16) string
- func (f *Font) Identity() Digest
- func (f *Font) PostScriptName() string
- func (f *Font) UnitsPerEm() int
- type Glyph
- type InvalidParamError
- type Line
- type OutlineError
- type OverflowError
- type OverflowPolicy
- type Params
- type Placed
- type Problem
- type Rect
- type Shaper
- type TextError
Constants ¶
const ( // MinFontSize is the smallest font size in points that survives three-decimal output. MinFontSize = 0.01 // MaxFontSize equals the largest generated page side. MaxFontSize = 14400.0 // MinPageSide bounds a generated page side from below, in points. MinPageSide = 1.0 // MaxPageSide bounds a generated page side from above, in points. MaxPageSide = 14400.0 // MaxOffset bounds the absolute x and y offsets and the wrap width in points. MaxOffset = 1e6 // MaxLineSpacing bounds the line spacing multiplier. MaxLineSpacing = 100.0 // AnchorTopLeft places the block's top-left corner on the page's. The nine anchors run row by row from // here to AnchorBottomRight; the block's matching point is placed on the page's. AnchorTopLeft Anchor = 0 // AnchorTopCenter anchors the middle of the block's top edge to the middle of the page's. AnchorTopCenter Anchor = 1 // AnchorTopRight anchors the block's top-right corner to the page's. AnchorTopRight Anchor = 2 // AnchorMiddleLeft anchors the middle of the block's left edge to the middle of the page's. AnchorMiddleLeft Anchor = 3 // AnchorCenter anchors the block's center to the page's. AnchorCenter Anchor = 4 // AnchorMiddleRight anchors the middle of the block's right edge to the middle of the page's. AnchorMiddleRight Anchor = 5 // AnchorBottomLeft anchors the block's bottom-left corner to the page's. AnchorBottomLeft Anchor = 6 // AnchorBottomCenter anchors the middle of the block's bottom edge to the middle of the page's. AnchorBottomCenter Anchor = 7 // AnchorBottomRight anchors the block's bottom-right corner to the page's. AnchorBottomRight Anchor = 8 // AlignLeft aligns lines to the block's left edge. The alignments act inside the block. AlignLeft Align = 0 // AlignCenter centers lines in the block. AlignCenter Align = 1 // AlignRight aligns lines to the block's right edge. AlignRight Align = 2 // AlignJustify spreads interior U+0020 spaces so a wrapped line fills the block; the last line of // each paragraph stays left-aligned. AlignJustify Align = 3 // OverflowReject turns findings into an error (the plan value "error"). OverflowReject OverflowPolicy = 0 // OverflowAllow reports findings and succeeds. OverflowAllow OverflowPolicy = 1 // FindingWordTooWide means a line, necessarily a single unbreakable word, is wider than the wrap width. FindingWordTooWide FindingKind = "word-wider-than-box" // FindingOutsidePageHorizontal means the block leaves the page on the left or right. FindingOutsidePageHorizontal FindingKind = "outside-page-horizontal" // FindingOutsidePageVertical means the block leaves the page on the top or bottom (vertical overflow). FindingOutsidePageVertical FindingKind = "outside-page-vertical" )
const DefaultFontName = "Noto Sans"
DefaultFontName is the plan-level name of the embedded default font.
const (
// MaxTextRunes bounds the text of one block, so wrapping and shaping memory stays proportional to it.
MaxTextRunes = 100_000
)
Variables ¶
var ( // ErrMalformedFont is wrapped by every error that reports a font file that is damaged or inconsistent. ErrMalformedFont = errors.New("malformed font") // ErrUnsupportedFont is wrapped by every error that reports a well-formed font of a kind this package does not embed. ErrUnsupportedFont = errors.New("unsupported font") // ErrShapingFailed is wrapped by every error that reports a failure of the shaper itself rather than of the text. ErrShapingFailed = errors.New("shaping failed") )
Functions ¶
This section is empty.
Types ¶
type Anchor ¶
type Anchor int
Anchor is one of nine points of the page to which the text block is attached.
type Cluster ¶
Cluster is the unit that maps glyphs back to source text: the glyphs that one run of source characters shaped to (a base and its marks, a ligature, or a single character).
type EmbeddingError ¶
type EmbeddingError struct {
FsType uint16
}
EmbeddingError reports an OS/2 fsType that forbids embedding.
type Finding ¶
type Finding struct {
Kind FindingKind
Detail string
// Line is the zero-based line of a FindingWordTooWide, otherwise -1.
Line int
}
Finding is one overflow condition.
type Font ¶
type Font struct {
// contains filtered or unexported fields
}
Font is a validated, immutable static TrueType font.
func LoadDefaultFont ¶
LoadDefaultFont parses the embedded default font. Each call returns a new Font with the same identity; callers load it once per job.
func LoadFont ¶
LoadFont validates data as an embeddable static TrueType font. It retains data, which the caller must not modify afterwards. It never panics on malformed input; every defect is an error.
func (*Font) CapHeight ¶
CapHeight returns the capital height in font units, or the ascent when the font declares none.
func (*Font) GlyphAdvance ¶
GlyphAdvance returns the nominal horizontal advance of a glyph in font units, or 0 for an unknown glyph.
func (*Font) GlyphText ¶
GlyphText returns the text a glyph stands for on its own: the smallest code point the cmap maps to it, or "" when no code point maps to it.
func (*Font) PostScriptName ¶
PostScriptName returns the font's name restricted to characters legal in a PDF name.
func (*Font) UnitsPerEm ¶
UnitsPerEm returns the font design units per em.
type Glyph ¶
type Glyph struct {
ID uint16
// Advance is the pen advance after the glyph, with kerning applied.
Advance int
// XOffset and YOffset move the drawn glyph from the pen; GPOS mark attachment lands here.
XOffset, YOffset int
}
Glyph is one positioned glyph. All distances are font units.
type InvalidParamError ¶
InvalidParamError names a Params field outside its domain.
func (*InvalidParamError) Error ¶
func (e *InvalidParamError) Error() string
Error implements error.
type Line ¶
type Line struct {
Clusters []Cluster
X float64
Baseline float64
// Width is the advance width without trailing spaces, justification included.
Width float64
// ExtraSpace is the justification added to each interior U+0020, in points.
ExtraSpace float64
}
Line is one positioned line. X and Baseline are the page coordinates of the first glyph's pen.
type OutlineError ¶
type OutlineError struct {
// Font is the PostScript name of the font.
Font string
// Rune is the first character of the cluster that needs the glyph.
Rune rune
// Glyph is the glyph identifier in the font.
Glyph uint16
}
OutlineError reports a font whose outline for a glyph that the text needs cannot be read, which would render that character blank. The parsing library discards the whole outline table when any glyph of it is damaged, so every glyph of such a font reports this error, not only the damaged one. It matches ErrMalformedFont under errors.Is.
func (*OutlineError) Unwrap ¶
func (*OutlineError) Unwrap() error
Unwrap lets errors.Is match ErrMalformedFont.
type OverflowError ¶
type OverflowError struct {
Findings []Finding
// WrapWidth and PageWidth retain the configured width and authored canvas
// for diagnostics; glyph-expanded block bounds cannot identify this cause.
WrapWidth float64
PageWidth float64
}
OverflowError reports findings under OverflowReject policy.
func (*OverflowError) FixedWidthExceedsPage ¶ added in v0.2.0
func (e *OverflowError) FixedWidthExceedsPage() bool
FixedWidthExceedsPage identifies a configured block that cannot fit even when both horizontal edges receive the existing placement tolerance. It requires an actual horizontal finding and does not classify glyph-expanded widths.
type Params ¶
type Params struct {
Text string
// Language is an optional BCP-47 tag selecting language-specific glyph forms (for example "lv").
Language string
// Size is the font size, MinFontSize through MaxFontSize.
Size float64
// PageWidth and PageHeight are the page sides, MinPageSide through MaxPageSide.
PageWidth, PageHeight float64
// OffsetX and OffsetY move the anchored block; each is within +-MaxOffset.
OffsetX, OffsetY float64
// WrapWidth is the block width; 0 means no wrapping (explicit line breaks only).
WrapWidth float64
// LineSpacing is the baseline-to-baseline distance as a multiple of Size; it is greater than 0.
LineSpacing float64
Anchor Anchor
Align Align
Overflow OverflowPolicy
}
Params describes one text block on one page. Lengths are points; +x is right and +y is up.
type Placed ¶
type Placed struct {
Font *Font
InkBounds *Rect
Lines []Line
Findings []Finding
Bounds Rect
Size float64
}
Placed is a laid-out text block positioned on a page.
type Problem ¶
type Problem struct {
Reason string
// Offset is the rune offset into the text, or -1 for invalid UTF-8.
Offset int
// More counts further consecutive code points rejected for the same reason.
More int
Rune rune
}
Problem is one reason text cannot be rendered with a font.
type Rect ¶
type Rect struct {
X, Y, Width, Height float64
}
Rect is a rectangle in page coordinates: its bottom-left corner and size.
type Shaper ¶
type Shaper struct {
// contains filtered or unexported fields
}
Shaper holds reusable shaping state. It is not safe for concurrent use; use one per goroutine. A Font may be shared between Shapers.
go-text's Face carries a mutable glyph cache, so a Face must not be shared between goroutines even though the parsed font is immutable; each Shaper therefore owns a private Face per Font.
func (*Shaper) Place ¶
Place shapes, wraps and positions params.Text with the font. Empty text yields no lines, zero bounds and no findings. A rejected text returns a *TextError and invalid numbers an *InvalidParamError, both with a nil result. When findings exist under OverflowReject policy, Place returns the complete result together with an *OverflowError, so callers can report computed bounds.