Interprets Type 2 charstrings, which is how a CFF font describes a glyph.
A charstring is a little stack program: operands are pushed, an operator consumes them and draws something. Every coordinate is relative to the last one, and curves are cubic, unlike TrueType's quadratics.
Two details account for most of the difficulty. Subroutines - which 92 of the
94 CFF fonts surveyed on a development machine use - are called by an index
biased by the size of the subroutine table, so the same call means different
things in different fonts. And the first stack-clearing operator may carry one
extra leading operand, the glyph's width; it's recognised by the argument count
being odd where the operator expects an even number. Widths are ignored here,
since hmtx carries them too and is easier to trust.
Example
A charstring which moves and draws a triangle: 100 100 rmoveto, then
200 0 0 200 rlineto, then endchar.
iex> <<239, 239, 21, 247, 92, 139, 139, 247, 92, 5, 14>>
...> |> Vivid.CFF.Charstring.contours({}, {})
[[Vivid.Point.init(100, 100), Vivid.Point.init(300, 100), Vivid.Point.init(300, 300)]]
Summary
Functions
Interpret charstring, returning its contours as lists of points.
Functions
@spec contours(binary(), tuple(), tuple()) :: [[Vivid.Point.t()]]
Interpret charstring, returning its contours as lists of points.
subrsthe font's local subroutines.gsubrsthe font's global subroutines.