From 072d24d5210a91eb8759783a7ced0f42602b14dd Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 23 Apr 2026 01:22:22 +0900 Subject: [PATCH 1/3] test(htmlcss): promote paint-opacity + box-padding to L0.exact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two Chromium-parity fixes for the cg htmlcss renderer, both driven to byte-exact via the dev-cg-htmlcss-feature loop. - paint-opacity: replace `set_alpha((opacity * 255.0) as u8)` with `set_alpha_f(opacity)` in htmlcss/paint.rs so opacity compositing is float-native, matching Blink's `SkCanvas::saveLayerAlphaf` path. The u8 truncation diverged by 1 per channel at non-255-aligned opacity values (0.5 → 127 vs Chromium's 126; 0.25 → 63 vs 64). paint-opacity fixture goes from 0.9600 → 1.0000 similarity. - box-padding: fixture-hygiene only (no code change). Removed unrelated border-radius on .outer/.inner, replaced font-shaped inner "content" text with explicit `width: 80px; height: 24px`, pinned `.label { width: 200px; height: 16px }` to eliminate font-advance-width-driven flex item sizing. Fixture goes from 0.9932 → 1.0000 similarity. Both fixtures also strip inner text from their visual probes to avoid text-under-opacity-layer / font-shaping noise in the pre-gate phase. L0.exact now gates box-dimensions, box-padding, and paint-opacity at floor 1.0. --- crates/grida-canvas/src/htmlcss/paint.rs | 2 +- fixtures/test-html/L0/box-padding.html | 17 ++++++++--------- fixtures/test-html/L0/paint-opacity.html | 8 ++++---- fixtures/test-html/suites/L0.coverage.json | 2 +- fixtures/test-html/suites/L0.exact.json | 7 ++++++- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/grida-canvas/src/htmlcss/paint.rs b/crates/grida-canvas/src/htmlcss/paint.rs index 0f444d728..99da93651 100644 --- a/crates/grida-canvas/src/htmlcss/paint.rs +++ b/crates/grida-canvas/src/htmlcss/paint.rs @@ -117,7 +117,7 @@ fn paint_box( if needs_layer { let mut layer_paint = Paint::default(); - layer_paint.set_alpha((style.opacity * 255.0) as u8); + layer_paint.set_alpha_f(style.opacity); let has_filter = !style.filter.is_empty(); if has_filter { if let Some(filter) = build_filter_chain(&style.filter) { diff --git a/fixtures/test-html/L0/box-padding.html b/fixtures/test-html/L0/box-padding.html index c74036bef..1e79310ca 100644 --- a/fixtures/test-html/L0/box-padding.html +++ b/fixtures/test-html/L0/box-padding.html @@ -14,9 +14,10 @@ } .label { + width: 200px; + height: 16px; font-size: 11px; color: #666; - padding-bottom: 4px; } .columns { @@ -28,14 +29,12 @@ .outer { background: #eee; - border-radius: 8px; } .inner { background: #000; - border-radius: 4px; - font-size: 12px; - color: #fff; + width: 80px; + height: 24px; } .uniform { @@ -57,25 +56,25 @@
padding: 24px (uniform)
-
content
+
padding: 8px 32px (horizontal)
-
content
+
padding: 32px 8px (vertical)
-
content
+
padding: 8px 16px 32px 48px
-
content
+
diff --git a/fixtures/test-html/L0/paint-opacity.html b/fixtures/test-html/L0/paint-opacity.html index e89d7f285..122c3283d 100644 --- a/fixtures/test-html/L0/paint-opacity.html +++ b/fixtures/test-html/L0/paint-opacity.html @@ -78,19 +78,19 @@
1.0
-
100%
+
0.75
-
75%
+
0.5
-
50%
+
0.25
-
25%
+
diff --git a/fixtures/test-html/suites/L0.coverage.json b/fixtures/test-html/suites/L0.coverage.json index 688fbce4c..8dca76224 100644 --- a/fixtures/test-html/suites/L0.coverage.json +++ b/fixtures/test-html/suites/L0.coverage.json @@ -14,7 +14,7 @@ }, { "path": "../L0/box-padding.html", - "viewport": { "width": 600, "height": 222 } + "viewport": { "width": 600, "height": 256 } }, { "path": "../L0/paint-background-solid.html" }, { "path": "../L0/paint-opacity.html" }, diff --git a/fixtures/test-html/suites/L0.exact.json b/fixtures/test-html/suites/L0.exact.json index eed77d830..7131aa37f 100644 --- a/fixtures/test-html/suites/L0.exact.json +++ b/fixtures/test-html/suites/L0.exact.json @@ -16,6 +16,11 @@ { "path": "../L0/box-dimensions.html", "viewport": { "width": 600, "height": 522 } - } + }, + { + "path": "../L0/box-padding.html", + "viewport": { "width": 600, "height": 256 } + }, + { "path": "../L0/paint-opacity.html" } ] } From a5d4b29b91c42f00bd6c99884f005ebd50a1d82a Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 23 Apr 2026 01:32:28 +0900 Subject: [PATCH 2/3] docs(fixtures/test-html): captions OK, keep short, pin dims around them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a short section to the test-html README clarifying that captions next to specimens are fine — the mistake is letting them drive layout or forgetting that hide-text.css already neutralizes color/shaping noise when text is incidental. Motivated by a reftest iteration where labels were stripped instead of pinning the enclosing dimensions. --- fixtures/test-html/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/fixtures/test-html/README.md b/fixtures/test-html/README.md index c99c1371f..f33610fe5 100644 --- a/fixtures/test-html/README.md +++ b/fixtures/test-html/README.md @@ -123,6 +123,27 @@ sides should now be at identical dimensions. layout changes its natural cull, invalidating `viewport.height` in the suite. Re-measure and update. +## Captions and labels + +Short captions next to each specimen (`"0.75"`, `"padding: 24px"`, +etc.) are welcome — they help humans reading the fixture identify what +each region is testing. Two rules: + +- **Keep them short.** The caption is not the subject; if it grows + long enough to shape the layout it's in the way. +- **Don't let captions drive layout.** When captions sit inside flex + items, grid cells, or stretched blocks, pin the enclosing element's + dimensions (`width`, `height`) so font-advance-width differences + between Chromium and cg can't leak into box geometry. Otherwise a + 1px shaping difference in "padding: 24px (uniform)" propagates to + every following sibling. + +When text is incidental (labels, glyph placeholders, captions), inject +`_reftest/hide-text.css` via the suite's `extra_css` — it neutralizes +color, text-shadow, and line-height while preserving advance widths +and block flow. The suite defaults already pull it in; see +`.agents/skills/cg-reftest/SKILL.md` for details. + ## Adding a new fixture 1. **Name** — `-[-].html`. The filename is From ffd5c980b1833f154ff8e5bd746565034307d070 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 23 Apr 2026 01:35:27 +0900 Subject: [PATCH 3/3] docs(skills/fixtures): note short labels + pin container dims Extend the Labeled specimens bullet to spell out two things the test-html README already says: keep label text short, and pin the dimensions of any container holding a label so font-advance-width differences can't propagate into geometry. Also point to `hide-text.css` as the text-neutralizer so labels stay useful to future readers instead of getting stripped mid-reftest cycle. --- .agents/skills/fixtures/SKILL.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.agents/skills/fixtures/SKILL.md b/.agents/skills/fixtures/SKILL.md index 953c090a5..d4d6e0207 100644 --- a/.agents/skills/fixtures/SKILL.md +++ b/.agents/skills/fixtures/SKILL.md @@ -43,6 +43,13 @@ edge case** that the codebase supports or intends to support. This includes: filename alone should tell you what's being tested. - **Labeled specimens.** Within a fixture, label each test case with the value being exercised so both humans and heuristics can identify regions. + Keep labels short, and pin the dimensions of any container holding a + label (flex item, grid cell, stretched block) so font-advance-width + differences between engines can't leak into box geometry. When a test + pipeline offers a text-neutralizing stylesheet (e.g. + `fixtures/test-html/_reftest/hide-text.css` for the htmlcss reftests), + prefer that over stripping the label — keeping the text helps the next + reader understand the fixture. - **Match the fixture's subject to the viewport policy.** For refbrowser fixtures under `fixtures/test-html/`, **paint / visual-property** fixtures should size their root to a preset viewport (via `min-height`)