Repository navigation
T116: same-colour border corners painted solid via Blink's side painter (device-pixels iOS 65→57, Android 94→86) - #68
Merged
Conversation
…our corners are solid as in Chrome (rebuilt on p6a-promote-v2) T116: solid-only borders go through Blink's side painter (paint-dash.ts), so same-colour sides meet with no miter (ComputeMiter) and the corner pixel is solid as in Chrome, not two anti-aliased diagonal halves; boxes with a visible double side and no dashed or dotted one keep the band painter. border-join fixture (solid corners: same colour, mixed colours, uneven and fractional widths, translucent); p6a-dash-oracle.test.ts compares every crisp border pixel of every case with a solid side against Chrome (pixels past the raster and under glyphs skipped) and pins border-join's crisp corners; dash vector inputs gain solid-only style sets p6a-dash-oracle.test.ts: prove the T116 raster-bounds and glyph skips drop no pixel the pre-T116 comparison checked (dashed and dotted boxes only, no skips): for every dashed or dotted case at every DPR the pre-T116 checked pixels are a subset of the current ones Rebuilt from t116-border-join 2e300022 (8e9d0a71, 17dc8b28) on the split p6a stack: the same source changes, outputs regenerated in the next commit.
…committed sources, then pnpm run profile:rows: env DRAGON_WRITE_DASH_INPUTS=1 npx vitest run packages/layout/test/paint-dash.test.ts; grammar:gen, ua:capture, parity:capture, profile:rows, parity:capture, profile:rows, layout:vectors, parity:dpr-capture, layout:dpr-vectors, layout:break-vectors, parity:break-capture, parity:pixel-capture, layout:paint-vectors, native:gen, node --conditions=dragon-internal examples/music-player/tools/check.ts, wpt:run --target web, wpt:update-expectations --target web, tw:sweep, parity:glyph-b3 --write-bottom-pins, media-sweep.ts and --check, parity:lanes --run-host): the border-join captures, DPR and break captures, vectors and Chrome PNGs; the dash paint vectors gain the solid-only style sets; the translated PaintDash; border-join joins the proofs of the rows it uses (no row added or removed and no status changed on ios, android or web), so emitted CSS digests move; corpus-dpr.json; host-only lanes.json. Pass 2 changed only native-lanes.ts (pass 1's profile:rows read the pre-run lanes.json), and the final profile:rows left it unchanged
… into t116-border-join-v2: no source conflict; generated files kept from this side for pnpm regen to rebuild
…der-join-v2: p6a-dash-oracle.test keeps T116's glyph skips and #63's paint-order occluders (the ancestors helper goes with the old occluder rule); paint-dash.ts keeps T116's side painter routing and #63's innerBorderRect; the merged dash inputs equal dashVectorInputs(); generated files kept from this side for pnpm regen to rebuild
…se.sh pnpm regen: fixed point after 3 passes): the translated engine (PaintDash with T116's side painter routing and innerBorderRect) and the dash paint vectors over the merged inputs; lanes.json and native-lanes.ts follow from the device run
… from the device run on T116 (/tmp/device-lease.sh pnpm run parity:devices): device-pixels ios 61 -> 57, android 90 -> 86 (master after #63): position-absolute-out-of-flow and -rtl (the T144 solid-corner joins, 2 + 2 per target) go to 0; the border-join cases pass on both targets; lane states equal master's, lane parity passes
…ease.sh pnpm regen: fixed point after 2 passes) over T116's device record: ios notPassing device-pixels 57, android 86, nothing stale; profiles and lanes.json unchanged (the T075J cycle proof)
…r (paintsOver: a box in a positioned layer, a non-static box or a descendant of one, paints over every in-flow box; within a phase, tree order), not tree order alone. #63's tree-order rule compared position-relative-percent's in-flow c3 border under the earlier relatively positioned b5, which Chrome paints over it (730 mismatches once T116 compares solid borders); the earlier-sibling case #63 fixed stays compared. paintsOver and positionedLayer are pinned on that fixture
…64 SIZE-ar, #65 P6a-promote) (/tmp/heavy-lease.sh pnpm regen: fixed point after 3 passes): the border-join captures and vectors gain SIZE-ar's aspect-ratio; the pixel manifest regains SIZE-ar's sizing-ratio sets (the merge kept this side's manifest); profile proofs list both branches' cases (no row added or removed and no status changed on ios, android or web), so the emitted CSS digests move; the translated engine; corpus-dpr.json; lanes.json and native-lanes.ts follow from the device run
… from the device run on T116 after the merge of origin/master 7c5419f (/tmp/device-lease.sh pnpm run parity:devices): device-pixels ios 65 -> 57, android 94 -> 86; position-absolute-out-of-flow(-rtl) (T144) and sizing-ratio-abspos(-rtl) (SIZE-ar's corner pixels) go from 2 + 2 + 2 + 2 to 0 per target; border-join passes on both targets; lane states equal master's, lane parity passes
…ease.sh pnpm regen: fixed point after 2 passes) over T116's device record: device-pixels the only lane not passing (ios 57, android 86), nothing stale; profiles and lanes.json unchanged (the T075J cycle proof)
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a narrowly scoped border-rendering correction that routes solid-only borders through the existing Blink-compatible side painter while preserving the double-border fallback. Unit, Chrome pixel-parity, multi-DPR, and device-lane coverage account for the changed behavior. You can add or adjust custom eligibility rules. Learn more. |
thejackshelton
added a commit
that referenced
this pull request
Oct 2, 2026
…igin/master 6295700 (/tmp/device-lease.sh pnpm run parity:devices): failure lists unchanged (ios 57, android 86)
thejackshelton
added a commit
that referenced
this pull request
Oct 2, 2026
…66 INL1a part 1) (/tmp/heavy-lease.sh pnpm regen: fixed point after 3 passes): the translated engine; profile proofs list both branches' cases (no row added or removed and no status changed on ios, android or web), so the emitted CSS digests move; the pixel manifest, font captures and corpus-dpr.json; lanes.json and native-lanes.ts follow from the device run
…igin/master 30f03f4 (/tmp/device-lease.sh pnpm run parity:devices): device-pixels ios 65 -> 57, android 94 -> 86 against master (position-absolute-out-of-flow(-rtl) and sizing-ratio-abspos(-rtl) to 0); failure lists unchanged from the previous run; lane states equal master's, lane parity passes
…glyph only when its text paints over the border (textPaintsOver, CSS2 Appendix E): over an in-flow border every text does, over a positioned border only its own text and that of boxes painting over it; a positioned border under in-flow text is compared now. Pinned with paintsOver on the position-relative-percent ids; every case still matches Chrome.
…a-dash-oracle.test keeps master's tree-order occluder rule, so the subset proof (every pixel the pre-T116 comparison checked is still checked) measures the paint-order change as well as the raster-bounds and glyph skips; it holds on every dashed and dotted case at every DPR
…the whole occluder model of p6a-dash-oracle.test re-audited (the file's third round) An occluder now hides only what it paints, where it paints, when it paints: - paint order within a phase is order-modified document order (paintOrder: flex items by order, stably), not program order; - a box hides its border box only when its background is not transparent, else only its visible border bands; - every occluder and glyph is clipped by the overflow-clipping boxes on its containing-block chain (an absolutely positioned box escapes the clips below its containing block, a fixed one all of them), glyphs also by their own box; - a transparent text run hides nothing; a translucent one still changes the pixel, so it still hides it. The pre-T116 comparison keeps master's rule for the subset proof. paintOrder and intersect are pinned; position-absolute-scroll-container proves the containing-block escape (a naive tree clip compared a border pixel the escaping box paints over). Every case still matches Chrome at every DPR.
…ex container's in-flow items by order; an absolutely positioned child is not a flex item and keeps its tree-order slot. Pinned with an out-of-flow child carrying an order and a relatively positioned item that is reordered. The engine has no fixed positioning, so the dead fixed branches go.
thejackshelton
added a commit
that referenced
this pull request
Oct 2, 2026
thejackshelton
added a commit
that referenced
this pull request
Oct 2, 2026
…-a: device-failures-*.json take master's (device-run outputs; train 2's device run rewrites them); generated outputs rebuilt by pnpm regen next
This was referenced Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
T116: the border join. Where two same-colour sides meet, native now paints the shared corner pixel solid, as Chrome does, instead of two anti-aliased diagonal halves (75% coverage). It also closes T144, which was the same bug.
Device-pixels delta (
pnpm run parity:deviceson master 7c5419f plus T116)What changed
borderNeedsSidePainter). Same-colour sides meet with no miter (ComputeMiter). A box with a visible double side and no dashed or dotted side keeps the band painter.What passed
pnpm typecheck.pnpm test: 160 files; 3514 pass and 1 is skipped (the opt-inpnpm regen --check).pnpm regenat a fixed point.No profile row is added or removed, and no status changes. No tolerance, check or test is loosened or removed. The reviewed diff is 25.5 KB in 6 files.
🤖 Generated with Claude Code
Note
Route same-colour solid border corners through the side painter (iOS 65→57, Android 94→86 device-pixel failures)
borderNeedsSidePainterin paint-dash.ts now selects the side painter when at least one border side is visible and all visible sides are solid, in addition to the existing dashed/dotted route. Visible double borders without dashed/dotted sides stay on the band painter.border-joinparity fixture in border-join.html with eight border cases, plus generated expected pixels, DPR snapshots, and expected-breaks at DPR 1, 2, 2.625, and 3. Theborder-joincase is registered in theBORDER_PAINTfixture group.webProfile,iosProfile, andandroidProfilesupport records to associateborder-joinwith border-color features, and lowers the recorded iOS device-pixel failures from 65 to 57 and Android from 94 to 86 in native-lanes.ts.paintDash_borderNeedsSidePainterin PaintDash.swift and PaintDash.kt.Macroscope summarized 16234f6.