Skip to content

forme 0.5.0

Choose a tag to compare

@mgilbir mgilbir released this 03 Oct 21:55
· 126 commits to main since this release
d354ae9

Bounded, cancellable shaping for callers that shape untrusted text, and a
shaped run that no longer leaves most of its glyph buffer behind as garbage.

Face.ShapeGlyphsContext shapes one run under a context and RunLimits:

  • The limits are input bytes, live glyphs and charged lookup work. The
    defaults are 4096 bytes, 32768 glyphs and 64 million work units.
  • Cancellation is checked between shaping phases and lookup steps.
    Font parsing and Unicode preprocessing keep their own bounds and are
    not interrupted inside a phase.
  • The run is shaped through a private clone, so the receiver's used-glyph
    record is unchanged and concurrent calls are safe.
  • On any failure the result is zero; there are never partial glyphs.
    Failures are cancellation, ErrRunLimit for spent work, glyph growth or
    lookup recursion, and a limit reading the layout tables the run was
    shaped with ran into. Limits other calls ran into on the same face do
    not count.
  • RunResult.Work is the work charged, for a caller to deduct from a
    document-wide budget.

Face.WithShapingLimits runs a callback, such as paragraph breaking, with
one budget shared across every measurement and shaping call it makes on the
face it is handed. Each run is checked against the input limit. A face kept
past the call shapes without limits.

The unbounded entry points are unchanged in what they return. The checks
cost them about 2.5% on a cold 30-character Latin label.

shapeGlyphsIn and shapeByCode now size a run's glyph buffer once, by
its runes, rather than growing it one doubling at a time. Output is
unchanged. On aster's BenchmarkTextLong, as reported in #877, this took
421 to 243 ms/op and 376.7 to 185.6 MB/op.

fonttest.GPOSExtensionLookups now builds on 32-bit targets. Its sentinel
constant overflowed int there.

The whole suite with every corpus, and go test -race ./..., passed on CI
for each pull request in this release.

Pre-1.0. This adds exported API (ShapeGlyphsContext, WithShapingLimits,
RunInput, RunLimits, RunResult, ErrRunLimit) and removes none.