iOS 27 glass: dark luminance curve, edge outline, gated fidelity row, motion references - #5888
shai-almog wants to merge 4 commits into
Conversation
… motion refs iOS 27's dark Liquid Glass is not affine: after the best affine fit the residual is a parabola in backdrop luma. GlassRecipe gains a luminance curve term, curve * 255 * (lum/255 - curveMid)^2, carried by the dark chrome27 and pill27 recipes. On device the pill tiles moved with it (Tabs dark 68.75% -> 73.45%, TabsGeom dark 87.73% -> 90.72%). The dark panel stays affine: its curve improved the offline fit slightly but cost three tiles 0.3 on device. iOS 27 also draws a thin dark outline around the sides of its panel and pill glass, in both appearances, which iOS 26 does not. On the boundary pixel each backdrop channel b becomes max(b - 76, 0.22 * b) to within a few levels across grey, red, gradient and photo backdrops. That outline -- not the material -- is what makes the native dark panel visible over a flat grey, so without it GlassPanelGrey/Red dark rendered no silhouette and the fidelity gate rightly refused to baseline them. GlassRecipe.getOutline carries it; the optics draw it on the outermost pixel, weighted by the horizontal component of the edge normal. Both formerly empty tiles now match the native bounding box to 1-2px. Both terms are implemented in every glass backend -- iOS offscreen (Java), the iOS and MacPort live Metal CPU paths (including the patch-cache key), JavaSE and the JavaScript bridge -- and pinned bit-for-bit across the Java and JS implementations in verify-javascript-lens-parity.mjs. Zero curve and zero outline short-circuit, so every iOS 26 recipe renders exactly as before. The ios-27-metal fidelity baseline is recorded and fidelity-ios-metal-27 is now a real gate (continue-on-error removed, drift guard updated). The TabsMorph frame goldens are reseeded for the new pill material, and goldens/ios-27-metal-anim holds the tap-driven native tab and switch motion recordings plus the CN1 morph rendered on the iOS 27 simulator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Compared 12 screenshots: 12 matched. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Native fidelity (Android, Material 3)54 pairs compared -- median 95.6%, worst 91.3% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Compared 172 screenshots: 172 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 172 screenshots: 172 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 157 screenshots: 157 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
Cloudflare Preview
|
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 172 screenshots: 172 matched. |
|
Compared 172 screenshots: 172 matched. |
Native fidelity (ios-27-metal)68 pairs compared -- median 94.6%, worst 73.5% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
|
Compared 172 screenshots: 172 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 193 screenshots: 193 matched. |
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
Native fidelity (iOS Modern, Metal)68 pairs compared -- median 95.0%, worst 83.5% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
…rial The only capture of 155 the build-ios-metal-27 leg reported as changed; the difference is confined to the tab-bar pill (rows 2191-2435), which now carries the dark pill27 luminance curve and the iOS 27 edge outline. Taken from that leg's CI artifact. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Compared 154 screenshots: 154 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 150 screenshots: 150 matched. |
|
Compared 223 screenshots: 223 matched. |
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 166 screenshots: 166 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
…t failure menuBarAddsCommandsAndTracksDefaults failed intermittently on build-test (21), here and on unrelated PRs, with "Second command should have a bound button in button bar mode". It is not intermittent -- it is order-dependent. DialogInWindowTest set touchDevice true for one test and in its finally set it to false, not to the value it found; the test implementation defaults to true. TestCodenameOneImplementation.reset() never restored touchDevice, so every test after it in the JVM ran on a "non-touch device", where CodenameOneImplementation.setCommandBehavior turns COMMAND_BEHAVIOR_BUTTON_BAR into SOFTKEY and MenuBar creates no command buttons. Surefire runs classes in filesystem order, which differs between checkouts, so the failure appeared only when DialogInWindowTest happened to run first. Reproduced by replaying the failing CI run's exact class order in one JVM on JDK 21 (4411 tests, 1 failure: this one), and reduced to the pair DialogInWindowTest -> MenuBarDialogSideMenuTest, which fails while the latter alone passes. With the fix both the pair and the full replay pass. reset() is the choke point, so it now restores all six setter-backed fields it was missing (touchDevice, portrait, tablet, trueTypeSupported, autoProcessConnections, locationButtonReady) to their declared defaults, and DialogInWindowTest restores the value it found. None of the six is set in any @BeforeAll, so no class relies on one surviving a test's teardown; the full suite passes 7338/7338. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aRememberPromptCannotPublishAKeyReplacedByRotationOrImport failed on build-test (21) with "replacement 1 ==> expected: <CONFLICT> but was: <null>". The vault was right; the fake device store was not holding the prompt. FakeDeviceProtection.ensureKey counted down ensureEntered and only THEN read releaseEnsure. Counting down wakes the test thread, whose next step clears releaseEnsure so the replacement's own ensureKey does not block. When that clear landed first, the prompt under test skipped its wait, ran alongside the rotation/import, finished before it changed anything and reported success. The fields were also plain, so the worker was not even guaranteed to see them. The latch is now read before entry is announced, and both fields are volatile. Proven with a probe that sleeps between the two steps to widen the window: the old ordering then fails deterministically with the CI message, the new one passes under the same sleep. The probe is removed; VaultTest passes 153/153 and the full suite 7338/7338. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>




















































































































































































































































































































































































Items 2, 3 and 6 of the Xcode 27 migration as one change. Toolchain (
CN1_XCODE_MAJOR), theios.themeGenerationdefault and the 27.1 foldable CI are deliberately not here.The dark glass curve (item 3)
iOS 27's dark Liquid Glass is not affine. After the best affine fit the residual is a parabola in backdrop luma.
GlassRecipegains a curve term,curve * 255 * (lum/255 - curveMid)^2, carried by darkchrome27andpill27.The dark panel stays affine. Its curve took the offline fit from rms 3.59 to only 3.18, and on device it cost three tiles about 0.3 each, so it was measured and dropped.
chrome27is fitted but not device-verified: the suite's Toolbar tile paints no glass, and its score was byte-identical across the change. That's recorded in the javadoc.The edge outline, and why it unblocks the gate (item 2)
The ios-27-metal baseline couldn't be recorded because
GlassPanelGrey/GlassPanelRedin dark had no CN1 silhouette, andFidelityGatecorrectly refuses a one-sided empty. The cause turned out not to be the material. iOS 27 draws a thin dark line around the sides of its panel and pill glass, in both appearances, and iOS 26 does not. On the boundary pixel, each backdrop channelbbecomesmax(b - 76, 0.22 * b)to within a few levels, across grey, red, gradient and photo backdrops.GlassRecipe.getOutline()carries it (panel27 0.95, pill27 0.55, measured). The optics draw it on the outermost pixel, weighted by the horizontal component of the edge normal. Both formerly empty tiles now match the native bounding box to 1–2 px and the corner radius to within 0.5 px.Raising the specular rim instead was tried first and rejected. It overshot the rim on the other backdrops about 2:1 and cost every other dark panel tile 0.1–0.9.
Both terms are in every glass backend:
verify-javascript-lens-parity.mjspins them bit for bit: two material pins and three outline pins, with checksums from the iOS and JavaSE implementations. Zero curve and zero outline short-circuit, so every iOS 26 recipe renders as before.With the baseline committed,
fidelity-ios-metal-27loses itscontinue-on-error, and the drift guard no longer allows it in the copy. A local run in CI mode (CN1SS_FAIL_ON_MISMATCH=1) passes: 68/68 at or above baseline, 4 morph groups validated.Motion references (item 6)
goldens/ios-27-metal-anim:Tabs.setMorphTestStateat each 60 fps timeline value, rather than in JavaSE as the iOS 26 set was.The README explains each.
Expected CI follow-up
build-ios-metal-27renders hellocodenameone with the iOS 27 theme, so its glass captures will move. Those goldens are reseeded from that leg's artifacts, after checking the diffs are glass-only.🤖 Generated with Claude Code