Skip to content

Add decoded glyph outline access - #122

Open
jplot wants to merge 2 commits into
prawnpdf:masterfrom
jplot:glyph-contours
Open

Add decoded glyph outline access#122
jplot wants to merge 2 commits into
prawnpdf:masterfrom
jplot:glyph-contours

Conversation

@jplot

@jplot jplot commented Jul 29, 2026

Copy link
Copy Markdown

TTFunk parses everything around glyph outlines — headers, bounding boxes, component ids for subsetting — but stops one byte short of the outlines themselves: Simple keeps flags and coordinates undecoded in raw, and Compound's documented Component struct is never instantiated. (History note: full decomposition existed for one night in December 2008 and was removed in e80ad0e in favor of parsing "just enough to write it back out in a font subset" — the struct declaration stayed behind.)

This PR completes that surface:

  • Glyf::Simple#contours — decoded outline points (coordinates and on-curve flags), lazily and memoized, so the subsetting path pays nothing.
  • Glyf::Compound#components — fully parsed component records into the existing Component struct: signed x/y offsets vs unsigned point numbers per ARGS_ARE_XY_VALUES (a flag the codebase had not defined), and F2Dot14 transforms in all three forms.
  • Glyf#contours_for(glyph_id) — composite-resolved, positioned contours. Component nesting is capped to protect against reference cycles, and point-matching alignment raises TTFunk::Error rather than producing silently wrong geometry.

Additive only — no existing API changes, no new dependencies, and the raw-copy subsetting strategy is untouched (decoding is read-only and on demand).

Motivation: we used this decoding in production to recover text from PDFs whose subsetted fonts had lost their ToUnicode tables, by matching glyph shapes against reference fonts. Outline access also enables subset verification and glyph-level comparison generally.

Tests: 17 new examples against the DejaVuSans fixture (including exact bounding-box span of decoded points and point-by-point verification of composite translation) plus hand-built binary records for the F2Dot14 scale and unsigned point-number paths. Full suite green (207 examples), RuboCop clean.

Copilot AI review requested due to automatic review settings July 29, 2026 12:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants