Skip to content

forme 0.10.0

Choose a tag to compare

@mgilbir mgilbir released this 09 Oct 20:45
· 57 commits to main since this release
7c539d4

Untrusted fonts are read within their size wherever offsets alias, AAT
machines are charged as HarfBuzz charges them, CSS gains revert, the math
functions and a first transform, and the coverage check stops shaping.
From PRs #925 to #938.

Untrusted fonts (font, shape, #925 to #928, #934, #938):

  • A name table, a variation store, an ltag table and a collection's
    directory are read within their file's size however their records point
    at the same bytes. Before, a 76 KB font made Load allocate 250 MB, a
    56 KB variation store 99 MB, and a 33 KB collection a 10 MB program.
  • font.SFNTTables refuses a directory whose tables add up to more than
    twice the file. Load and LoadInstance say why such a font is refused,
    rather than "not an sfnt".
  • CollectionFaces is linear in the collection, however its faces share a
    directory or a name table.
  • kerx attachment by points, morx and kerx subtables tried, trak tables
    and the morx rewind are charged to the run. A one-character run that
    took 3.4 s now takes 0.2 ms, and a trak that does not fit its table is
    not applied, as HarfBuzz's sanitizer refuses it.
  • A run whose morx, mort or kerx spends HarfBuzz's allowance is refused
    where HarfBuzz gives up on it: bounded calls and ComposeContext return
    ErrRunLimit. An unbounded ShapeGlyphs returns what HarfBuzz leaves in
    the buffer, and Compose reports it.
  • A bitmap strike is chosen from an index built once per face.

Performance (shape, layout, paragraph, #930, #933, #934):

  • The coverage check counts missing glyphs without shaping
    (Face.MissingGlyphs). Layout is up to eight times faster: a page of
    Devanagari in Noto Sans from 1.1 s to 0.14 s, Arabic from 128 ms to
    43 ms, Latin from 69 ms to 42 ms.
  • A face's Used() holds only glyphs a backend drew, not glyphs a coverage
    probe touched, so a face that was asked and not chosen embeds nothing.
  • Colour glyphs are classified without drawing and counted once per
    glyph; a face reads its MATH table and table directory once; a morx
    run's glyph set and output are kept on the face (18% faster on real
    morx fonts, 61% fewer bytes).

CSS (style, layout, #929, #931, #932, #935 to #937):

  • revert and revert-layer roll the cascade back as CSS Cascade 5 says,
    rather than reading as unset. A layered author rule now beats a
    presentational hint.
  • min(), max(), clamp(), round(), mod(), rem() and the other math
    functions are evaluated wherever calc() is, including against a
    percentage's basis (style.LengthMath, Length.HasPercent).
  • display: contents computes to none on replaced elements, form controls
    and MathML, and to block on the root, as CSS Display 3 says.
  • transform and transform-origin: a transform that keeps rectangles
    rectangles is drawn with the existing ops. Options.TransformGroups,
    off by default, draws every 2D transform through layout.TransformGroup,
    which a backend must implement before turning it on. 3D transforms,
    the root and table parts are still reported.
  • A length too large to hold is the largest length, written literally or
    in a math function, rather than a declaration lost silently.
  • @page margin and size take the CSS-wide keywords.

Verified on 7c539d4: gofmt, go vet and go test ./... with every corpus,
and without; the race detector on CI; 6253 reftests, 5996 passed cleanly,
66 with something unsupported, 191 failed, unchanged since 0.9.0. apidiff
against 0.9.0 reports additions only.