Skip to content

Match HarfBuzz's CFF2 coordinate and metric arithmetic - #2266

Closed
behdad wants to merge 10 commits into
skera-cff-review-nested-blendsfrom
skera-cff-review-precision
Closed

behdad wants to merge 10 commits into
skera-cff-review-nested-blendsfrom
skera-cff-review-precision

Conversation

@behdad

@behdad behdad commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Fractional CFF2 locations need separate normalization paths for outline/store instancing and runtime metrics. Match HarfBuzz's float normalization and half-unit rounding toward positive infinity; keep the metric path's intermediate 16.16 normalization before its 2.14 coordinates.

Use the shared unquantized float-region-scalar helper, double CFF operand products/accumulation, consumer-specific metric arithmetic, and a continuous bounds action on the common Type 2 interpreter. Full output retains per-blend rounding; bounds evaluate without operand rounding. Initialize outline coordinates directly instead of computing and discarding a second normalization result and clone.

Validation: 466 Skera tests with all features, the shared-reader scalar regression, Clippy with warnings denied, and Rust 1.85 all-target/all-feature checks. The current review's 90 full and 38 partial CFF comparisons pass, including decoded outlines, metrics, axis records, Private DICTs, and second-stage samples. Partial re-encoding retains its documented coefficient/F2Dot14 quantization limits.

Stacked on #2264 and preserves its reviewed nested-expression and performance fixes. Shared reader APIs provide the scalar evaluation; write-fonts supplies owned table models and assembly. No secondary generated table tree.

@behdad
behdad force-pushed the skera-cff-review-precision branch from 80eafff to 368ce8a Compare October 14, 2026 23:11
@behdad

behdad commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Review findings before changes:

  • The separate outline/store and runtime-metric normalization paths are justified by HarfBuzz's arithmetic. hb_ot_var_normalize_* uses a 16.16 intermediate before conversion to 2.14; subset-plan normalization uses the outline path. HarfBuzz overrides roundf to round ties toward positive infinity, which is relevant when comparing the implementation with libc names.
  • VariationScalars delegates region ratios to the shared read-fonts float helper and retains float accumulation for metrics. Continuous control bounds use the same Type 2 interpreter, an argument buffer reused across commands, and double coordinates. Full blend emission retains its separate rounding policy. The independent path-operator tests are useful coverage, rather than relying only on reference font bytes.
  • One redundant computation remains: AxisPlan::new calls Skrifa's axes.location(...), clones those coordinates, overwrites every outline coordinate, and later recomputes the runtime metric coordinates explicitly. Remove that discarded normalization and allocate the outline-coordinate vector directly.
  • The PR description predates the shared reader scalar helper and the earlier backports, so it needs to describe the remaining diff and current validation accurately. Partial re-encoding remains quantized; the sampled corpus is not proof of universal equivalence.

I will make the normalization cleanup, run the Skera suite and comparison matrices at this boundary, and update the description.

Each outline coordinate is filled by the explicit normalization path; metric coordinates are computed separately below. Initialize the vector directly.

Assisted-by: OpenAI Codex
@behdad

behdad commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Pushed the reviewed parent and the precision cleanup through the stack. Axis planning now initializes the outline-coordinate buffer directly instead of computing and cloning a normalization result that was immediately overwritten. The reviewed boundary passes 466 Skera tests, the shared reader regression, Clippy and Rust 1.85 checks; the 90 full / 38 partial CFF comparisons retain their results.

@behdad

behdad commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by the rebuilt, consolidated instancing stack in #2416–#2423. MATH and name-table overrides remain separately covered by #2415 and #2411.

@behdad behdad closed this Oct 28, 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.

1 participant