Skip to content

[gpos] Keep GPOS variation-index deltas fractional#403

Merged
behdad merged 1 commit into
mainfrom
gpos-fractional-var-delta
Jul 3, 2026
Merged

[gpos] Keep GPOS variation-index deltas fractional#403
behdad merged 1 commit into
mainfrom
gpos-fractional-var-delta

Conversation

@behdad

@behdad behdad commented Jul 3, 2026

Copy link
Copy Markdown
Member

Fixes #402

Problem

GPOS Device/VariationIndex deltas — both value-record adjustments and anchor
coordinates — were read via ItemVariationStore::compute_delta, which rounds
the delta to whole font units, and then scaled to output units. That double
rounding discards up to half a font unit of the advance / placement /
attachment adjustment.

HarfBuzz instead keeps the delta fractional and rounds only once, after scaling
to output units (Device::get_x_delta is em_scalef_x(get_delta()), i.e.
roundf(delta * scale / upem), used for both value records and
Anchor::get_anchor). For variable fonts this made the harfrust shaper
disagree with ot by sub-font-unit amounts on non-default instances — e.g.
SFNSItalic.ttf shaping "System italic font at weight N" at weights other
than the default (#402).

Fix

Read the deltas with compute_float_delta and scale them with new
Scale::scale_x_f / scale_y_f helpers that mirror HarfBuzz's em_multf
(roundf(v * scale / upem)), keeping f32 arithmetic to match HarfBuzz. The
static value-record path stays on the integer scale, matching HarfBuzz
(static → em_scale, device → em_scalef). resolve_anchor now returns
fractional font units, and its cursive and mark callers round once when
scaling.

Requires read-fonts 0.41.0

This bumps the read-fonts dependency to 0.41.0 for the public
FloatItemDelta::to_f64 accessor (googlefonts/fontations#1954). CI will build
once read-fonts 0.41.0 is published on crates.io.

Testing

  • SFNSItalic.ttf advances now match the ot shaper exactly (0.000000px):
    hb-shape --shaper harfrust vs --shaper ot is byte-identical across
    weights 100–900.
  • cargo test -p harfrust: 6027 passed, 0 failed.
  • HarfBuzz meson test --suite shape: 3/3 OK (8912 subtests), 0 failures.

GPOS Device/VariationIndex deltas -- both value-record adjustments
and anchor coordinates -- were computed with
ItemVariationStore::compute_delta, which rounds the delta to whole
font units, and then scaled to output units.  That double rounding
discards up to half a font unit of the advance, placement, or
attachment adjustment.

HarfBuzz instead keeps the delta fractional and rounds only once,
after scaling: Device::get_x_delta is em_scalef_x(get_delta()),
i.e. roundf(delta * scale / upem), used for both value records and
Anchor::get_anchor.  For variable fonts this made the "harfrust"
shaper disagree with "ot" by sub-font-unit amounts on non-default
instances (#402, e.g. SFNSItalic at weights other
than the default).

Compute the deltas with compute_float_delta and scale them with new
Scale::scale_x_f/scale_y_f helpers that mirror HarfBuzz's em_multf
(roundf(v * scale / upem)), keeping f32 arithmetic to match it.
resolve_anchor now returns fractional font units, and its cursive
and mark callers round once when scaling.  The static value-record
path stays on the integer scale, matching HarfBuzz (static ->
em_scale, device -> em_scalef).

Bump the read-fonts dependency to 0.41.0, which makes the
FloatItemDelta::to_f64 accessor public (googlefonts/fontations#1954);
compute_float_delta's result is read through it.

Advances now match the "ot" shaper exactly (0.000000px) for
SFNSItalic across weights 100-900; the harfrust and HarfBuzz shape
suites pass with no regressions.

Fixes: #402
Assisted-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@behdad
behdad force-pushed the gpos-fractional-var-delta branch from 2fa4583 to e09971c Compare July 3, 2026 18:55
@behdad
behdad merged commit f548a0c into main Jul 3, 2026
3 checks passed
@behdad
behdad deleted the gpos-fractional-var-delta branch July 3, 2026 18:59
This was referenced Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Differences in Mac system fonts (ot + trak) results between HarfBuzz ot and HarfRust

1 participant