Skip to content

Finish the CSS tail: mask-composite, hyphens:auto, multicol fragmentation (+ 2 inline fixes) - #16

Merged
andrevanzuydam merged 3 commits into
mainfrom
feature/rendering-fidelity-10
Sep 17, 2026
Merged

andrevanzuydam merged 3 commits into
mainfrom
feature/rendering-fidelity-10

Conversation

@andrevanzuydam

Copy link
Copy Markdown
Owner

Finishes the three remaining CSS subsystems — the index is now 137 ✅ · 0 🟡 · 0 📦 · 0 ❌, every standard property implemented with proof.

mask-composite

ApplyMaskLayers composites comma-separated mask layers per mask-composite (add/subtract/intersect/exclude). Each layer renders its coverage onto a scratch buffer (reusing the gradient/image-mask routines); 2nd+ url() layers decode via a shell callback threaded into ApplyFilterChainF and wired on all five shells. All four ops within 0.01 of Chrome. Reftest css-mask-composite.

hyphens:auto

New Tina4Hyphen embeds the public-domain en-US TeX patterns (hyph-en-us, 4938) + the standard exceptions and runs Liang/Knuth; AutoHyphenate inserts U+00AD at the dictionary points, reusing the manual soft-hyphen path. hyphenation→hy-phen-ation; a justified paragraph wraps to the same 13 lines as Chrome. Reftest css-hyphens-auto 0.00%.

multicol line-level fragmentation

FragmentChildren splits a plain paragraph into one anonymous box per line (tiled at the mid-points between lines), so the balancer distributes lines across columns — a tall paragraph flows across the column break like Chrome (within 2px). Reftest css-column-fragment.

Two inline-layout bugs from the comparison

  • A button wrapping to a new line no longer inherits the previous button's margin-right as a leading indent (margin spacers now record their side; only margin-left crosses the wrap). GitHub button flush-left under Get started.
  • An inline-block with text takes its baseline from its text line (CSS), not the box bottom — a padded pill (monospace badge) sits on the text baseline instead of riding high. Content-less colour badges unchanged.

Verification

Compliance 219/219, raster 11/11, DOM + interaction pass, leak-clean 30×, all shells cross-compile. Chrome sweep: 0 unexpected failures.

🤖 Generated with Claude Code

andrevanzuydam and others added 3 commits September 17, 2026 15:28
Multi-layer masks now combine per `mask-composite`. The DOM already kept
the comma-separated mask-image list; the composite ops fold in as a
`##composite=` sentinel. ApplyMaskLayers (compositor) splits the layers,
renders each layer's coverage onto an opaque scratch buffer (reusing the
gradient / image-mask routines), then combines pairwise:

- add       = s + d - s·d   (source-over union)
- subtract  = d · (1 - s)    (destination outside source)
- intersect = s · d
- exclude   = s + d - 2·s·d

The 2nd+ url() layer is decoded through a shell-provided callback
(DecodeMaskImage), threaded into ApplyFilterChainF and wired on every
shell (Cocoa/iOS/Win/Linux/raster-Android). All four operators verified
within 0.01 of headless Chrome (gradient layers); reftest
css-mask-composite (0.31%, step-boundary AA). Single-layer masks keep
their fast path unchanged.

Compliance 217/217, raster 11/11, DOM + interaction pass, leak-clean 30×;
all five shells compile for their targets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hyphens:auto now hyphenates with the actual algorithm browsers use.
Tina4Hyphen embeds the public-domain en-US TeX patterns (hyph-en-us,
4938 patterns) + the standard exception list and runs Liang/Knuth:
each plain ASCII word gets soft hyphens (U+00AD) inserted at the
dictionary points (lefthyphenmin 2, righthyphenmin 3), then the existing
manual soft-hyphen path breaks and renders them.

hyphenation→hy-phen-ation, representation→rep-re-sen-ta-tion,
beautiful→beau-ti-ful — verified against known TeX output; a justified
paragraph wraps to the same 13 lines as headless Chrome (same patterns).
The dictionary builds once (lazily) and frees at finalization.

Reftest css-hyphens-auto 0.00% (auto == manual with &shy; at the
dictionary points). DOM, compliance 218/218, raster 11/11, interaction,
leak-clean 30×; Android cross-compiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… fixes

Multi-column: line-level fragmentation. FragmentChildren splits a plain
multi-line paragraph into one anonymous box per line (tiled at the
mid-points between lines so the runs keep their positions), so the
balancer distributes LINES across columns — a tall paragraph now flows
across the column break like Chrome (verified filling both columns within
2px). Reftest css-column-fragment. This clears the last multicol caveat;
the CSS index is now 137 ✅ · 0 🟡 · 0 📦 · 0 ❌.

Two inline-layout bugs the comparison surfaced:
- A button that wraps to a new line no longer inherits the PREVIOUS
  button's margin-right as a leading indent. A margin spacer now records
  whether it is a margin-LEFT (belongs to the next item, carried on wrap)
  or margin-RIGHT (belongs to the previous item, not carried); only
  lead-margin spacers cross the wrap. The GitHub button is now flush-left
  under Get started, matching Chrome (was indented ~11px).
- An inline-block WITH text (a padded/coloured pill like a monospace
  badge) now takes its baseline from its text line (CSS), not the box
  bottom — so it sits on the surrounding text baseline instead of riding
  high. Content-less coloured badges keep the box-bottom baseline.

Compliance 219/219, raster 11/11, DOM + interaction pass, leak-clean 30×.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@andrevanzuydam
andrevanzuydam merged commit 4736fe0 into main Sep 17, 2026
3 checks passed
@andrevanzuydam
andrevanzuydam deleted the feature/rendering-fidelity-10 branch September 17, 2026 14:09
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