Skip to content

External surfaces: home-screen widgets + Live Activities / Dynamic Island#5365

Open
shai-almog wants to merge 27 commits into
masterfrom
feature/external-surfaces
Open

External surfaces: home-screen widgets + Live Activities / Dynamic Island#5365
shai-almog wants to merge 27 commits into
masterfrom
feature/external-surfaces

Conversation

@shai-almog

@shai-almog shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

A unified declarative API for external surfaces -- live information that resides outside the app. One concept, one API family, covering:

  • Home-screen widgets: iOS WidgetKit (generated CN1Widgets extension with a generic SwiftUI renderer), Android app widgets (generic RemoteViews renderer, no Compose/Glance dependency), desktop floating widgets (JavaSE/Windows/Linux) and the Windows 11 Widgets Board (MSIX + Adaptive Cards, behind windows.msix=true).
  • Live Activities / Dynamic Island: ActivityKit on iOS with full island regions, ongoing notifications on Android, floating pill windows on desktop.

Architecture

Follows the com.codename1.car pattern (sealed node catalog, fluent builders, SPI bridge, bytecode-scan build gating, zero cost when unused) with one crucial difference: surfaces render while the app process is dead. Descriptors serialize in core to one canonical JSON wire format plus content-hash-named PNG blobs (SurfaceSerializer on JSONWriter); layouts embed ${key} placeholders resolved from per-entry state maps, so updates ship data, not layouts. Interactions are string action ids delivered to a registered handler on the EDT with cold-start queueing. SurfaceDynamicText provides OS-native countdown/elapsed text (WidgetKit Text(date, style:) / Android Chronometer) -- timers and ETAs tick with zero app wakeups.

Widget kinds are declared at build time in a surfaces.json project resource (widget galleries are compiled into native apps) and mirrored at runtime via Surfaces.registerWidgetKind. Refresh is app-driven (publish + BackgroundFetch); the wire format is push-ready for a future server-driven update path.

Verification

  • 32 unit tests (serialization round-trips, timeline ordering, image dedup, live-activity lifecycle, cold-start action queue) green on JDK 8.
  • SurfacesSample (delivery tracker) verified end-to-end in the simulator: Widgets preview rendered the timeline with a ticking countdown, entries flipped on schedule, the mock Dynamic Island tracked live-activity updates, and clicking a widget hit-rect routed through Surfaces.dispatchAction to the app's handler.
  • Generated Swift renderer compiled and linked cleanly at arm64-apple-ios16.1-simulator (extension) and x86_64-apple-ios12.0-simulator (app-target glue).
  • Maven plugin, core, javase, android (JDK 17), ios, windows and linux modules all build; PMD/ASCII gates pass on new code.
  • Not machine-verified (documented in commits): on-device iOS/Android behavior, Windows/Linux native window code (no Windows SDK/GTK on this host), the MSIX pipeline, Catalyst archive.

Notes for reviewers

  • Twin PR in BuildDaemon: codenameone/BuildDaemon#150 (daemon builder mirrors; the daemon's CodenameOne dependency clone must be refreshed after this merges).
  • iOS signing: widgets require an App Group on both the app and <bundleId>.CN1Widgets; automatic signing handles it locally, cloud manual signing uses ios.appext.CN1Widgets.provisioningURL. The daemon entitlement gate was widened accordingly.
  • Known v1 limits are documented in com.codename1.surfaces package-info (LCD contract table): Android approximations (weights collapse to equal shares, date/relative dynamic text static, circular progress falls back to linear), small iOS widgets honor only the root action, Wayland floating-window degradation.

🤖 Generated with Claude Code

shai-almog and others added 7 commits July 11, 2026 16:23
External surfaces model home-screen widgets (WidgetKit / Android app
widgets) and live activities (ActivityKit / Dynamic Island / ongoing
notifications) as one declarative concept: a serializable layout node
tree with ${key} state placeholders, published as JSON + content-hash
named PNG blobs that platform renderers draw while the app process is
dead. Includes the SurfaceBridge SPI, timeline/live-activity facades,
the shared serializer and cold-start-safe action dispatch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…p floating widgets

SurfaceRasterizer renders descriptor JSON to a mutable CN1 Image with
Graphics primitives (no theme/component dependence) returning ARGB
pixels + action hit-rects + next-tick hints; shared by all desktop
ports. The JavaSE bridge persists published surfaces, the simulator
gains a Widgets preview window with a mock Dynamic Island, and
desktop-packaged apps get frameless always-on-top widget windows with
Preferences-persisted pinning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…going-notification live activities

The renderer composes pre-baked layout XMLs via RemoteViews.addView
(Chronometer countdowns, weighted cells, binder-budgeted bitmaps,
night-aware colors). CN1WidgetProvider picks timeline entries and
schedules flips with inexact alarms; live activities lower to ongoing
silent notifications; taps route through a Theme.NoDisplay trampoline
into Surfaces.dispatchAction with cold-start support. The builder
scans for surfaces usage, parses surfaces.json, generates per-kind
receivers + appwidget-provider XML and injects manifest entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d, IPhoneBuilder wiring

Ships a generic SwiftUI renderer in a generated CN1Widgets extension
target (deployment 16.1) that reads published timeline JSON + images
from the app group container; ActivityKit live activities render the
same descriptors with full Dynamic Island regions. The app-side Swift
bridge is reached from ObjC via NSClassFromString behind
CN1_USE_WIDGETS, cn1surface:// taps route into Surfaces.dispatchAction,
and IPhoneBuilder gains the surfaces.json manifest, app-group plist and
entitlement wiring and the xcodeproj ruby extension target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Floating widgets are frameless layered Win32 windows (premultiplied
DIB via UpdateLayeredWindow, pump-thread marshaled through
WM_CN1_WIDGET, hit-rect click routing over a string poll queue,
per-monitor DPI). Behind windows.msix=true the builder additionally
packages a signed MSIX with a C++/WinRT IWidgetProvider (gated by
CN1_WIDGETBOARD) that maps descriptors to Adaptive Cards for the
Windows 11 Widgets Board; plain-exe distributions keep the floating
windows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Undecorated keep-above sticky GTK3 windows with RGBA visuals render
rasterized descriptors via cairo; all GTK access marshals through
g_idle_add with a slot table, clicks and moves flow back over a string
poll queue into Surfaces.dispatchAction. Under Wayland positioning and
keep-above degrade to plain floating windows (documented); X11 gets
full applet behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sample exercises the full surface family (widget timeline with
native countdown, live activity with Dynamic Island regions, action
routing incl. cold start, BackgroundFetch republish) and was verified
end-to-end in the simulator Widgets preview. Mac Catalyst builds now
exclude the widget extension from the Mac slice (platform_filter ios,
SUPPORTS_MACCATALYST=NO) since Mac entitlements carry no app group;
the extension builder accepts both small/medium and
systemSmall/systemMedium family spellings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 145 screenshots: 145 matched.

Native Android coverage

  • 📊 Line coverage: 11.01% (11425/103792 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.75% (56065/575016), branch 5.03% (2640/52460), complexity 4.81% (2654/55149), method 7.20% (2049/28458), class 11.22% (453/4039)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 11.01% (11425/103792 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.75% (56065/575016), branch 5.03% (2640/52460), complexity 4.81% (2654/55149), method 7.20% (2049/28458), class 11.22% (453/4039)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 169ms / native 146ms = 1.1x speedup
SIMD float-mul (64K x300) java 97ms / native 111ms = 0.8x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 234.000 ms
Base64 CN1 decode 173.000 ms
Base64 native encode 1327.000 ms
Base64 encode ratio (CN1/native) 0.176x (82.4% faster)
Base64 native decode 1474.000 ms
Base64 decode ratio (CN1/native) 0.117x (88.3% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 168 screenshots: 168 matched.
✅ JavaScript-port screenshot tests passed.

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 142 screenshots: 142 matched.
Native Linux port (x64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub x64 runner. Baseline: scripts/linux/screenshots.

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 142 screenshots: 142 matched.
Native Linux port (arm64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub arm64 runner. Baseline: scripts/linux/screenshots-arm.

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 141 screenshots: 141 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 61ms / native 4ms = 15.2x speedup
SIMD float-mul (64K x300) java 60ms / native 4ms = 15.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 204.000 ms
Base64 CN1 decode 121.000 ms
Base64 SIMD encode 96.000 ms
Base64 encode ratio (SIMD/CN1) 0.471x (52.9% faster)
Base64 SIMD decode 84.000 ms
Base64 decode ratio (SIMD/CN1) 0.694x (30.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 10.000 ms
Image createMask (SIMD on) 6.000 ms
Image createMask ratio (SIMD on/off) 0.600x (40.0% faster)
Image applyMask (SIMD off) 34.000 ms
Image applyMask (SIMD on) 21.000 ms
Image applyMask ratio (SIMD on/off) 0.618x (38.2% faster)
Image modifyAlpha (SIMD off) 23.000 ms
Image modifyAlpha (SIMD on) 19.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.826x (17.4% faster)
Image modifyAlpha removeColor (SIMD off) 25.000 ms
Image modifyAlpha removeColor (SIMD on) 21.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.840x (16.0% faster)

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 141 screenshots: 141 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD float-mul (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 246.000 ms
Base64 CN1 decode 136.000 ms
Base64 SIMD encode 64.000 ms
Base64 encode ratio (SIMD/CN1) 0.260x (74.0% faster)
Base64 SIMD decode 59.000 ms
Base64 decode ratio (SIMD/CN1) 0.434x (56.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 7.000 ms
Image createMask ratio (SIMD on/off) 0.636x (36.4% faster)
Image applyMask (SIMD off) 23.000 ms
Image applyMask (SIMD on) 17.000 ms
Image applyMask ratio (SIMD on/off) 0.739x (26.1% faster)
Image modifyAlpha (SIMD off) 14.000 ms
Image modifyAlpha (SIMD on) 11.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.786x (21.4% faster)
Image modifyAlpha removeColor (SIMD off) 16.000 ms
Image modifyAlpha removeColor (SIMD on) 11.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.688x (31.3% faster)

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 143 screenshots: 143 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 212 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 53ms / native 2ms = 26.5x speedup
SIMD float-mul (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 166.000 ms
Base64 CN1 decode 137.000 ms
Base64 native encode 36968.000 ms
Base64 encode ratio (CN1/native) 0.004x (99.6% faster)
Base64 native decode 2302.000 ms
Base64 decode ratio (CN1/native) 0.060x (94.0% faster)
Base64 SIMD encode 50.000 ms
Base64 encode ratio (SIMD/CN1) 0.301x (69.9% faster)
Base64 SIMD decode 110.000 ms
Base64 decode ratio (SIMD/CN1) 0.803x (19.7% faster)
Base64 encode ratio (SIMD/native) 0.001x (99.9% faster)
Base64 decode ratio (SIMD/native) 0.048x (95.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 33.000 ms
Image createMask (SIMD on) 25.000 ms
Image createMask ratio (SIMD on/off) 0.758x (24.2% faster)
Image applyMask (SIMD off) 270.000 ms
Image applyMask (SIMD on) 267.000 ms
Image applyMask ratio (SIMD on/off) 0.989x (1.1% faster)
Image modifyAlpha (SIMD off) 231.000 ms
Image modifyAlpha (SIMD on) 189.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.818x (18.2% faster)
Image modifyAlpha removeColor (SIMD off) 292.000 ms
Image modifyAlpha removeColor (SIMD on) 156.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.534x (46.6% faster)

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 138 screenshots: 138 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 545 seconds

Build and Run Timing

Metric Duration
Simulator Boot 90000 ms
Simulator Boot (Run) 2000 ms
App Install 15000 ms
App Launch 5000 ms
Test Execution 503000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 54ms / native 3ms = 18.0x speedup
SIMD float-mul (64K x300) java 56ms / native 3ms = 18.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 284.000 ms
Base64 CN1 decode 484.000 ms
Base64 native encode 857.000 ms
Base64 encode ratio (CN1/native) 0.331x (66.9% faster)
Base64 native decode 1770.000 ms
Base64 decode ratio (CN1/native) 0.273x (72.7% faster)
Base64 SIMD encode 55.000 ms
Base64 encode ratio (SIMD/CN1) 0.194x (80.6% faster)
Base64 SIMD decode 110.000 ms
Base64 decode ratio (SIMD/CN1) 0.227x (77.3% faster)
Base64 encode ratio (SIMD/native) 0.064x (93.6% faster)
Base64 decode ratio (SIMD/native) 0.062x (93.8% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 9.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.222x (77.8% faster)
Image applyMask (SIMD off) 313.000 ms
Image applyMask (SIMD on) 276.000 ms
Image applyMask ratio (SIMD on/off) 0.882x (11.8% faster)
Image modifyAlpha (SIMD off) 243.000 ms
Image modifyAlpha (SIMD on) 54.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.222x (77.8% faster)
Image modifyAlpha removeColor (SIMD off) 155.000 ms
Image modifyAlpha removeColor (SIMD on) 130.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.839x (16.1% faster)

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 141 screenshots: 141 matched.
Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 63ms / native 6ms = 10.5x speedup
SIMD float-mul (64K x300) java 65ms / native 5ms = 13.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 194.000 ms
Base64 CN1 decode 137.000 ms
Base64 SIMD encode 101.000 ms
Base64 encode ratio (SIMD/CN1) 0.521x (47.9% faster)
Base64 SIMD decode 93.000 ms
Base64 decode ratio (SIMD/CN1) 0.679x (32.1% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 18.000 ms
Image createMask (SIMD on) 14.000 ms
Image createMask ratio (SIMD on/off) 0.778x (22.2% faster)
Image applyMask (SIMD off) 39.000 ms
Image applyMask (SIMD on) 35.000 ms
Image applyMask ratio (SIMD on/off) 0.897x (10.3% faster)
Image modifyAlpha (SIMD off) 40.000 ms
Image modifyAlpha (SIMD on) 34.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.850x (15.0% faster)
Image modifyAlpha removeColor (SIMD off) 31.000 ms
Image modifyAlpha removeColor (SIMD on) 25.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.806x (19.4% faster)

…cc ICE

Four client-side CI breaks:
- SurfaceSerializer used Long.toHexString, absent from the CLDC
  bootclasspath the Ant core build compiles against; format the
  content-hash by hand (verified with ant compile).
- CN1SurfaceStore's unreachable UnsupportedEncodingException fallback
  called default-encoding String.getBytes(), tripping the forbidden
  SpotBugs DM_DEFAULT_ENCODING gate; throw instead.
- cn1_windows_widgets.cpp used the MSVC STL, which demands Clang 19+
  under xwin while the cross-compile CI's clang-cl is older (STL1000);
  replaced std::deque/string/vector with a C event ring and an owned
  RECT array, matching how cn1_windows_browser.cpp guards its STL.
- The widget bridges' isSystemDark returned a freshly merged boolean
  from inside a translated try block, which ICEs Alpine 3.20 gcc with
  SSA corruption on the generated C (reproduced in Docker against the
  exact compiler: old shape ICEs, new assign-in-try shape compiles
  clean); restructured both the Linux and Windows twins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 12 screenshots: 12 matched.
✅ JavaSE simulator integration screenshots matched stored baselines.

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 144 screenshots: 144 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 285 seconds

Build and Run Timing

Metric Duration
Simulator Boot 67000 ms
Simulator Boot (Run) 0 ms
App Install 14000 ms
App Launch 1000 ms
Test Execution 346000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD float-mul (64K x300) java 56ms / native 3ms = 18.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 179.000 ms
Base64 CN1 decode 123.000 ms
Base64 native encode 667.000 ms
Base64 encode ratio (CN1/native) 0.268x (73.2% faster)
Base64 native decode 250.000 ms
Base64 decode ratio (CN1/native) 0.492x (50.8% faster)
Base64 SIMD encode 52.000 ms
Base64 encode ratio (SIMD/CN1) 0.291x (70.9% faster)
Base64 SIMD decode 45.000 ms
Base64 decode ratio (SIMD/CN1) 0.366x (63.4% faster)
Base64 encode ratio (SIMD/native) 0.078x (92.2% faster)
Base64 decode ratio (SIMD/native) 0.180x (82.0% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 9.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.111x (88.9% faster)
Image applyMask (SIMD off) 40.000 ms
Image applyMask (SIMD on) 57.000 ms
Image applyMask ratio (SIMD on/off) 1.425x (42.5% slower)
Image modifyAlpha (SIMD off) 121.000 ms
Image modifyAlpha (SIMD on) 153.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.264x (26.4% slower)
Image modifyAlpha removeColor (SIMD off) 197.000 ms
Image modifyAlpha removeColor (SIMD on) 154.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.782x (21.8% faster)

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 140 screenshots: 140 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 217 screenshots: 217 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

shai-almog and others added 5 commits July 11, 2026 22:15
… fidelity, image GC

- areWidgetsSupported() on iOS now gates on the CN1Widgets extension's
  actual deployment target (new CN1SurfacesMinOS plist key injected by
  the builder, default 16.1) instead of WidgetKit's iOS 14 floor, so
  iOS 14-15 no longer accepts publications for a gallery entry that
  cannot exist.
- Android live-activity updates replace the persisted state map
  wholesale instead of merging, matching every other platform; omitted
  keys no longer linger.
- The desktop rasterizer honors the alpha byte verbatim (fully
  transparent explicit colors draw nothing), matching the iOS/Android
  renderers; SurfaceColor.rgb docs now spell out the 0xAARRGGBB
  contract.
- Publishing garbage collects content-hash image blobs the replacement
  timeline no longer references, on every port (iOS app group, Android
  files dir, JavaSE/Windows/Linux stores). The serializer's images
  list now names the COMPLETE reference set including registered-name
  reuse, which also fixes registered-name references dropping out of
  the desktop bridges' in-memory image maps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ials)

A small vector-op catalog (rects, ellipses, arcs, lines, polygons,
anchored text) with rotation groups whose angle can come from the
state map, so an analog clock is a static face plus per-minute
timeline entries carrying hand angles. Lowered to SwiftUI Canvas on
iOS, an in-process anti-aliased Bitmap on Android (RemoteViews cannot
draw vectors) and CN1 Graphics shapes with a software affine on
desktop. Wire convention: degrees, 0 = 12 o'clock, clockwise; each
renderer documents its arc-API conversion. The sample gains an
analog-clock widget kind. HTML subset rejected: neither RemoteViews
nor widget extensions can host a web engine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…get pull

Audited the publish path on every port for background safety (Android
publish works from the UI-less BackgroundFetchHandler service context;
iOS is app-group file IO plus thread-safe WidgetCenter reload; desktop
bridges never block on the EDT) and documented the any-thread contract
on Surfaces.publish. New pull direction on Android: when a widget
renders with no timeline or an exhausted atEnd timeline, the provider
starts the app's declared BackgroundFetch (throttled to once per 15
minutes per kind) so the app republishes fresh content without any UI.
spi/package-info and BackgroundFetch document the per-platform story.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five suite tests exercise the framework on the real device VMs:
serializer round-trip (all node types, per-size layouts, image blobs),
SurfaceRasterizer screenshot (deterministic pinned-clock descriptor,
light + dark, bit-identical across runs), timeline logic, action
dispatch cold-start ordering on the EDT, and publish/reload no-op
safety. The suite app now ships a surfaces.json so the iOS/Android
build lowering is exercised by the platform CI legs. Golden
screenshots must be seeded from each leg's first run per the
screenshots README process.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Covers the concept and dead-process rule, surfaces.json and first
publish, the node catalog with the LCD contract, the SurfaceVector
analog clock, live activities and Dynamic Island regions, actions and
cold start, background refresh, per-platform notes and the build-hint
table. Screenshots captured live from the simulator Widgets preview.
Passes all guide gates (asciidoctor, Vale, paragraph cap, snippet
validation, LanguageTool) at zero findings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Second round pushed (ba1a0e25da..12c964f916), addressing the review and the design feedback:

Review findings

  • P1 iOS 14-15 support gate: areWidgetsSupported() now gates on the extension's real deployment target via a new CN1SurfacesMinOS plist key (builder-injected, default 16.1).
  • P2 Android live-activity state: replaced wholesale instead of merged.
  • P2 desktop alpha: honored verbatim; SurfaceColor.rgb documents the 0xAARRGGBB contract.
  • P2 image accumulation: publish now garbage collects unreferenced content-hash blobs on every port. The serializer's images list became the complete reference set (including registered-name reuse), which also fixed registered-name references dropping out of the desktop bridges' in-memory maps.

Design feedback

  • SurfaceVector: retained vector drawing (rects/ellipses/arcs/lines/paths/anchored text + state-keyed rotation groups) so clocks, gauges and dials are expressible - the sample now ships an analog clock widget publishing per-minute hand angles. Lowered to SwiftUI Canvas (iOS), in-process bitmaps (Android), CN1 Graphics shapes (desktop). HTML subset rejected: no web engine is available inside RemoteViews or widget extensions.
  • Background updates: Surfaces.publish is documented and audited as callable from any thread including BackgroundFetch (Android publish verified working from the UI-less service context). New pull direction on Android: a widget with no/exhausted timeline starts the app's declared BackgroundFetch (throttled 15 min/kind) so widgets refresh themselves without the UI ever opening.
  • Real cross-platform tests: five cn1ss suite tests in scripts/hellocodenameone (serializer round-trip on the device VMs, deterministic rasterizer screenshot light+dark, timeline logic, EDT action dispatch, publish safety) run on every platform CI leg. Note: the new SurfacesRasterizer golden screenshots must be seeded per leg from this branch's first CI artifacts (the standard screenshots README process) - those legs will report missing_expected until then.
  • Developer guide: new "External Surfaces: Widgets and Live Activities" chapter with live simulator screenshots (widget preview, Dynamic Island mock, vector clock); passes all guide gates at zero findings.

@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

shai-almog and others added 3 commits July 12, 2026 00:03
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… Swift sources

The schemes ruby re-runs after pods integration; its global
deployment-target pass iterated every target, so on the second pass it
stomped the already-created CN1Widgets extension down to the app's
iOS 14 -- WidgetKit sources then failed to compile (GraphicsContext is
15+). The pass now skips app-extension product types, which own their
deployment targets (this also protected the wallet extension).

Defense in depth: the renderer sources now compile at ANY deployment
target the generated project ends up with -- Canvas/GraphicsContext,
Text(timerInterval:), ProgressView(timerInterval:), Gauge and tint are
all #available-guarded with the documented degradations as fallbacks
(verified with swiftc -typecheck at ios14.0 and ios16.1 targets).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…es tests on JS

Goldens seeded from the branch's first CI artifacts and visually
verified (light + dark widget tiles, countdown, progress, arc, action
outline): Android legs are pixel-identical across JDKs, Linux x64 and
arm64 are identical, Windows x64/cross are identical with the arm64
capture inside the 2-pixel tolerance. iOS and Mac goldens follow once
those legs build with the deployment-target fix.

The JS port fails the serializer round-trip (JSONParser returns
mangled tokens, a runtime string/JSON bug rather than a surfaces bug)
and NPEs in the rasterizer screenshot setup; both tests are parked on
JS per the port.js convention pending a JS runtime fix. All other
platform legs gate them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • Tests: 395 total, 0 failed, 14 skipped

Benchmark Results

  • Execution Time: 18156 ms

  • Hotspots (Top 20 sampled methods):

    • 14.43% java.util.ArrayList.indexOf (227 samples)
    • 7.82% com.codename1.tools.translator.ByteCodeClass.markDependent (123 samples)
    • 4.90% com.codename1.tools.translator.BytecodeMethod.addToConstantPool (77 samples)
    • 3.50% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (55 samples)
    • 3.31% com.codename1.tools.translator.Parser.generateClassAndMethodIndexHeader (52 samples)
    • 3.05% java.lang.StringBuilder.append (48 samples)
    • 2.99% com.codename1.tools.translator.Parser.cn1EnsureSubclassIndex (47 samples)
    • 2.48% com.codename1.tools.translator.BytecodeMethod.equals (39 samples)
    • 2.29% org.objectweb.asm.tree.analysis.Analyzer.findSubroutine (36 samples)
    • 2.23% com.codename1.tools.translator.Parser.classIndex (35 samples)
    • 2.03% org.objectweb.asm.tree.analysis.Analyzer.analyze (32 samples)
    • 1.84% com.codename1.tools.translator.BytecodeMethod.optimize (29 samples)
    • 1.59% java.lang.Object.hashCode (25 samples)
    • 1.46% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (23 samples)
    • 1.40% com.codename1.tools.translator.Parser.addToConstantPool (22 samples)
    • 1.34% org.objectweb.asm.ClassReader.readCode (21 samples)
    • 1.21% java.lang.String.equals (19 samples)
    • 1.14% com.codename1.tools.translator.BytecodeMethod.updateInlinableFieldDependencies (18 samples)
    • 1.14% com.codename1.tools.translator.BytecodeMethod.appendCMethodPrefix (18 samples)
    • 1.08% com.codename1.tools.translator.Parser.resolveDupForms (17 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

shai-almog and others added 11 commits July 12, 2026 02:57
…natives)

The ParparVM iOS runtime has no native implementations for
java.io.File's mutating methods; referencing exists/delete/list/mkdir/
renameTo from IOSSurfaceBridge failed the native link with five
undefined java_io_File_*Impl symbols (and would have failed at runtime
regardless). All bridge file IO now goes through FileSystemStorage,
whose iOS implementation tolerates the App Group container's plain
absolute paths, with a segment-by-segment mkdirs helper and
rename-within-directory for the atomic timeline swap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ActivityKit can be imported on Mac Catalyst but ActivityAttributes and
Activity are marked unavailable there, so canImport alone let the
app-target glue reach the Catalyst compile and fail; every ActivityKit
guard now also excludes targetEnvironment(macCatalyst) (verified with
a macabi typecheck of the previously failing file). Seeds the four
visually verified iOS-family SurfacesRasterizer goldens (GL, Metal,
tvOS, watchOS); the Mac golden follows once its leg builds with this
fix. Also swaps the string concat in IOSSurfaceBridge.mkdirs for a
StringBuilder per the SpotBugs gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captured by the first mac-native run after the Catalyst ActivityKit
guards landed; visually verified (light + dark tiles, countdown,
timer-up, progress bar, arc, action outline).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d JSON numbers

The append(Object) native converted heap objects with the synchronous
toNativeString fallback ('' + value), so boxed numbers rendered as the
literal string [object Object] -- JSONWriter emitted corrupt documents
and every JSONParser round-trip on the JS port mangled (the parked
surfacesJsonRoundTrip / surfacesRasterizerNpe failures, plus the
silently failing timeline-logic test, were all this one defect). The
native now dispatches the real Java toString() through the generator
path; strings/null keep the sync fast path. Both surfaces tests are
un-parked, the JS SurfacesRasterizer golden is seeded from a
CI-calibrated Linux container capture, and a full-suite A/B shows all
135 existing screenshots byte-identical with zero regressions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… test

The exactAlarms build hint (promised in the hint table) now injects
SCHEDULE_EXACT_ALARM plus a manifest meta-data flag the provider reads;
timeline entry flips use setExactAndAllowWhileIdle when the user has
not revoked exact-alarm access, falling back to the inexact window
otherwise. A new Android-only cn1ss test exercises the REAL RemoteViews
lowering on the emulator legs: it publishes through AndroidSurfaceBridge,
renders light + dark via CN1SurfaceRenderer, applies the RemoteViews to
live views shown through a PeerComponent and screenshots the result;
Chronometer lowering is asserted without a screenshot for determinism.
Skips cleanly on every other platform (verified on JavaSE).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A new windows-runner job compiles cn1_windows_widgetboard.cpp with
CN1_WIDGETBOARD=1 against the real Windows App SDK (nuget winmds +
cppwinrt-generated projections) using clang-cl -- the production
toolchain -- plus a second-toolchain compile of the floating-widget TU.
Static verification against the winmd and Microsoft Learn found one
real defect (missing explicit unknwn.h include enabling classic-COM
interop in C++/WinRT) and builder layout bugs: the WinAppSDK nupkg
ships winmds only (no prebuilt projections) and puts Bootstrap.lib/dll
under lib/win10-<arch> and runtimes/win10-<arch>/native, which
resolveWinAppSdkDir/widgetBoardLinkFlags/the MSIX packer now accept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On layer-shell compositors (Sway/Hyprland/Wayfire/KDE) widget windows
now anchor as real desktop applets: LAYER_BOTTOM above the wallpaper
with left/top margins carrying the persisted position (the pill docks
LAYER_TOP centered), keyboard-mode NONE and zero exclusive zone.
begin_move_drag does not work on layer surfaces, so a press outside the
hit-rects starts a manual margin-updating drag off GTK's implicit grab.
The library binds lazily via dlopen (services.c convention); absence or
gtk_layer_is_supported()==false leaves the X11/EWMH path byte-for-byte
unchanged. Compile-verified at -O2 in an Alpine GTK container.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The suite's surfaces.json now enables liveActivities, so the ActivityKit
lowering (CN1LiveActivityWidget.swift, NSSupportsLiveActivities, the
Android ongoing-notification manager) is compiled and linked by every
platform build instead of only shipping untested. SurfacesPublishTest
runs the full start/update/end lifecycle: inert-handle semantics where
the platform refuses, the real surface (notification, desktop pill)
where supported, with no support value asserted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Running the floating widgets in a real (skinless) desktop app exposed
three bugs: widget clicks never focused the app because the port's
window field is only set on simulator paths (now falls back to the
canvas's top-level ancestor), toFront() could not raise the app over
other macOS apps (now also requests foreground activation via
java.awt.Desktop when available), and default placement stacked every
widget on the same top-right anchor (new windows now cascade below
intersecting ones). Verified end to end: rendering, countdown ticks
and timeline flips over 70s, drag, position persistence across
relaunches, and click-through to the action form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…header isolation

The suite settings rewrite in the exactAlarms commit accidentally added
an ios.NSMicrophoneUsageDescription, which defines
INCLUDE_MICROPHONE_USAGE and compiles requestRecordPermission: --
unavailable on tvOS/watchOS, breaking those legs. The file is restored
to its previous content.

The new widgetboard compile check did its job and caught two real
problems: C++/WinRT at C++17 falls back to <experimental/coroutine>,
which the modern MSVC STL rejects under clang (STL1009), and including
cn1_globals.h (C11 stdatomic) alongside the winrt STL headers conflicts
on atomic fences. The widgetboard TU no longer includes cn1_windows.h
(it only needed the logger, now forward-declared with C linkage) and
compiles at C++20: the translator's generated CMakeLists now defaults
CMAKE_CXX_STANDARD only when unset and WindowsNativeBuilder passes 20
for windows.msix=true builds (both branches; CI step matches).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The wizard now handles the App Group nuance that widgets/Live Activities
need. When a project uses external surfaces (surfaces.json present), the
one-click auto-setup: finds-or-creates the App Group (group.<package> or
the surfaces.json override), enables the APP_GROUPS capability on the
main and <package>.CN1Widgets App IDs associated with that group,
creates + downloads a distribution profile for the extension, and writes
codename1.arg.ios.surfaces.appGroup + codename1.ios.appext.CN1Widgets.provision
into the project settings. A manual bundle dialog also gets an App Groups
checkbox. The OpenAPI contract gains /app-groups (create/list) and an
optional appGroupIds on the capability request; SigningState tracks app
groups; MockSigningService + tests cover the full surfaces flow.

CN1BuildMojo carries the generated extension's provisioning profile to
the cloud build: any codename1.ios.appext.<Name>.provision file is
base64-encoded into the ios.appext.<Name>.provisioningData build arg
(local Xcode builds use automatic signing and are untouched).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Native fidelity (Android, Material 3)

54 pairs compared -- median 95.6%, worst 91.3% (FlatButton_pressed_dark), 25th pct 94.9%, mean 95.7%.

Distribution -- >=99%: 2 | 95-99%: 37 | 90-95%: 15 | <90%: 0

Component State Appearance Material Fidelity SSIM mean delta vs base Geometry
FlatButton pressed dark normal 91.3% 0.899 3.10 0.0 ok
Tabs normal light normal 92.3% 0.914 3.05 0.0 ok
Button pressed dark normal 92.6% 0.949 4.32 0.0 ok
FlatButton normal dark normal 93.2% 0.938 2.69 0.0 ok
Button disabled dark normal 93.3% 0.928 2.20 0.0 ok
Button pressed light normal 93.3% 0.952 3.68 0.0 ok
FlatButton normal light normal 93.7% 0.941 2.29 0.0 ok
FlatButton pressed light normal 93.8% 0.942 2.56 0.0 ok
FloatingActionButton pressed light normal 94.4% 0.927 2.82 0.0 OFF (h 0.88)
RadioButton normal dark normal 94.5% 0.963 2.19 0.0 ok
RadioButton normal light normal 94.7% 0.964 1.85 0.0 ok
CheckBox selected dark normal 94.7% 0.950 2.60 0.0 ok
RadioButton selected dark normal 94.8% 0.963 2.42 0.0 ok
CheckBox normal dark normal 94.9% 0.952 2.69 0.0 ok
Button normal dark normal 94.9% 0.949 3.16 0.0 ok
CheckBox normal light normal 95.0% 0.953 2.30 0.0 ok
Toolbar normal dark normal 95.1% 0.906 1.60 0.0 ok
RaisedButton pressed dark normal 95.2% 0.950 2.39 0.0 ok
CheckBox disabled dark normal 95.2% 0.954 1.47 0.0 ok
CheckBox disabled light normal 95.2% 0.956 1.34 0.0 ok
Tabs normal dark normal 95.2% 0.913 3.65 0.0 ok
RadioButton disabled dark normal 95.3% 0.963 1.18 0.0 ok
RadioButton selected light normal 95.3% 0.964 1.84 0.0 ok
CheckBox selected light normal 95.4% 0.952 2.06 0.0 ok
Switch selected light normal 95.4% 0.966 1.59 0.0 ok
Switch selected dark normal 95.5% 0.966 1.86 0.0 ok
RadioButton disabled light normal 95.5% 0.966 1.08 0.0 ok
Switch disabled dark normal 95.6% 0.961 0.85 0.0 ok
Dialog normal light normal 95.7% 0.930 2.30 0.0 ok
RaisedButton pressed light normal 95.8% 0.958 2.16 0.0 ok
Button normal light normal 95.8% 0.953 2.46 0.0 ok
Dialog normal dark normal 95.8% 0.932 2.30 0.0 ok
Switch normal light normal 96.0% 0.961 1.45 0.0 ok
FloatingActionButton normal light normal 96.1% 0.937 1.14 0.0 ok
FloatingActionButton pressed dark normal 96.2% 0.951 2.45 0.0 ok
Switch normal dark normal 96.2% 0.962 1.39 0.0 ok
TextField disabled dark normal 96.2% 0.965 0.76 0.0 ok
RaisedButton normal dark normal 96.4% 0.952 1.78 0.0 ok
Switch disabled light normal 96.4% 0.970 0.61 0.0 ok
Button disabled light normal 96.8% 0.960 1.06 0.0 ok
ProgressBar normal dark normal 96.9% 0.967 2.03 0.0 OFF (h 1.50)
RaisedButton disabled dark normal 97.0% 0.955 0.89 0.0 ok
FloatingActionButton normal dark normal 97.1% 0.952 1.43 0.0 ok
ProgressBar normal light normal 97.3% 0.974 1.53 0.0 OFF (h 1.50)
RaisedButton disabled light normal 97.3% 0.961 0.79 0.0 ok
TextField disabled light normal 97.3% 0.965 0.79 0.0 ok
RaisedButton normal light normal 97.3% 0.961 1.40 0.0 ok
TextField normal dark normal 97.6% 0.958 1.83 0.0 ok
TextField normal light normal 97.6% 0.958 1.63 0.0 ok
Slider normal dark normal 98.4% 0.990 0.87 0.0 ok
Toolbar normal light normal 98.7% 0.974 1.28 0.0 ok
Slider normal light normal 99.0% 0.991 0.47 0.0 ok
Slider disabled dark normal 99.6% 0.993 0.22 0.0 ok
Slider disabled light normal 99.6% 0.993 0.18 0.0 ok
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Component State Appearance bbox dx,dy (px) w ratio h ratio center off (px) radius native->cn1 (px)
FloatingActionButton pressed light +0,+0 0.929 0.881 4.0 -
FloatingActionButton normal light +0,+0 0.946 0.912 2.9 -
Button pressed dark +0,+0 0.947 0.975 2.6 -
Button disabled dark +0,+0 0.947 0.975 2.6 -
Button pressed light +0,+0 0.947 0.975 2.6 -
Button normal dark +0,+0 0.947 0.975 2.6 -
RaisedButton pressed dark +0,+0 0.945 0.975 2.6 -
RaisedButton pressed light +0,+0 0.945 0.975 2.6 -
Button normal light +0,+0 0.947 0.975 2.6 -
RaisedButton normal dark +0,+0 0.945 0.975 2.6 -
Button disabled light +0,+0 0.947 0.975 2.6 -
RaisedButton disabled dark +0,+0 0.945 0.975 2.6 -
RaisedButton disabled light +0,+0 0.945 0.975 2.6 -
RaisedButton normal light +0,+0 0.945 0.975 2.6 -
RadioButton normal dark +1,+1 1.029 1.000 2.2 -
RadioButton normal light +1,+1 1.029 1.000 2.2 -
RadioButton selected dark +1,+1 1.029 1.000 2.2 -
RadioButton disabled dark +1,+1 1.029 1.000 2.2 -
RadioButton selected light +1,+1 1.029 1.000 2.2 -
Switch selected light +0,+0 1.080 1.063 2.2 -
RadioButton disabled light +1,+1 1.029 1.000 2.2 -
CheckBox selected dark +1,+1 1.013 1.000 1.8 -
CheckBox normal dark +1,+1 1.013 1.000 1.8 -
CheckBox normal light +1,+1 1.013 1.000 1.8 -
CheckBox disabled dark +1,+1 1.013 1.000 1.8 -
CheckBox disabled light +1,+1 1.013 1.000 1.8 -
CheckBox selected light +1,+1 1.013 1.000 1.8 -
Switch selected dark +0,+0 1.060 1.031 1.6 -
Switch disabled dark +0,-1 1.060 1.031 1.6 -
Dialog normal light +0,+0 1.007 0.982 1.6 -
Dialog normal dark +0,+0 1.007 0.982 1.6 -
Switch normal light +0,-1 1.060 1.031 1.6 -
Switch normal dark +0,-1 1.060 1.031 1.6 -
Switch disabled light +0,-1 1.060 1.031 1.6 -
FloatingActionButton pressed dark +0,+0 0.963 0.963 1.4 -
FloatingActionButton normal dark +0,+0 0.963 0.963 1.4 -
Toolbar normal light -1,+1 1.000 1.000 1.4 -
FlatButton pressed dark +0,+0 0.977 0.975 1.1 -
FlatButton normal dark +0,+0 0.977 0.975 1.1 -
FlatButton normal light +0,+0 0.977 0.975 1.1 -
FlatButton pressed light +0,+0 0.977 0.975 1.1 -
TextField normal dark +0,+0 1.015 1.036 1.1 -
TextField normal light +0,+0 1.015 1.036 1.1 -
Toolbar normal dark +0,+0 1.000 1.032 1.0 -
ProgressBar normal dark +0,+0 1.000 1.500 1.0 -
ProgressBar normal light +0,+0 1.000 1.500 1.0 -
TextField disabled dark +0,+0 1.015 1.018 0.7 -
TextField disabled light +0,+0 1.015 1.018 0.7 -
Tabs normal light +0,+1 1.000 0.984 0.5 -
Slider normal dark +1,+0 0.996 1.000 0.5 -
Slider normal light +1,+0 0.996 1.000 0.5 -
Tabs normal dark +0,+0 1.000 1.000 0.0 -
Slider disabled dark +0,+0 1.000 1.000 0.0 -
Slider disabled light +0,+0 1.000 1.000 0.0 -

Side-by-side comparisons (worst first)

  • FlatButton_pressed_dark -- 91.25% fidelity (SSIM 0.8985) (no change)

    native FlatButton_pressed_dark cn1 FlatButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • Tabs_normal_light -- 92.28% fidelity (SSIM 0.9140) (no change)

    native Tabs_normal_light cn1 Tabs_normal_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_dark -- 92.61% fidelity (SSIM 0.9485) (no change)

    native Button_pressed_dark cn1 Button_pressed_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_dark -- 93.24% fidelity (SSIM 0.9381) (no change)

    native FlatButton_normal_dark cn1 FlatButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_disabled_dark -- 93.26% fidelity (SSIM 0.9278) (no change)

    native Button_disabled_dark cn1 Button_disabled_dark
    Left: native widget. Right: Codename One render.

  • Button_pressed_light -- 93.34% fidelity (SSIM 0.9521) (no change)

    native Button_pressed_light cn1 Button_pressed_light
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_light -- 93.72% fidelity (SSIM 0.9410) (no change)

    native FlatButton_normal_light cn1 FlatButton_normal_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_light -- 93.77% fidelity (SSIM 0.9424) (no change)

    native FlatButton_pressed_light cn1 FlatButton_pressed_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_pressed_light -- 94.44% fidelity (SSIM 0.9273) (no change)

    native FloatingActionButton_pressed_light cn1 FloatingActionButton_pressed_light
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_dark -- 94.46% fidelity (SSIM 0.9630) (no change)

    native RadioButton_normal_dark cn1 RadioButton_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_light -- 94.69% fidelity (SSIM 0.9643) (no change)

    native RadioButton_normal_light cn1 RadioButton_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_dark -- 94.71% fidelity (SSIM 0.9502) (no change)

    native CheckBox_selected_dark cn1 CheckBox_selected_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_dark -- 94.79% fidelity (SSIM 0.9630) (no change)

    native RadioButton_selected_dark cn1 RadioButton_selected_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_dark -- 94.93% fidelity (SSIM 0.9516) (no change)

    native CheckBox_normal_dark cn1 CheckBox_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_normal_dark -- 94.94% fidelity (SSIM 0.9491) (no change)

    native Button_normal_dark cn1 Button_normal_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_light -- 95.03% fidelity (SSIM 0.9531) (no change)

    native CheckBox_normal_light cn1 CheckBox_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_dark -- 95.07% fidelity (SSIM 0.9059) (no change)

    native Toolbar_normal_dark cn1 Toolbar_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_dark -- 95.19% fidelity (SSIM 0.9501) (no change)

    native RaisedButton_pressed_dark cn1 RaisedButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_dark -- 95.20% fidelity (SSIM 0.9538) (no change)

    native CheckBox_disabled_dark cn1 CheckBox_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_light -- 95.21% fidelity (SSIM 0.9562) (no change)

    native CheckBox_disabled_light cn1 CheckBox_disabled_light
    Left: native widget. Right: Codename One render.

  • Tabs_normal_dark -- 95.23% fidelity (SSIM 0.9125) (no change)

    native Tabs_normal_dark cn1 Tabs_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_dark -- 95.29% fidelity (SSIM 0.9630) (no change)

    native RadioButton_disabled_dark cn1 RadioButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_light -- 95.33% fidelity (SSIM 0.9642) (no change)

    native RadioButton_selected_light cn1 RadioButton_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_light -- 95.37% fidelity (SSIM 0.9524) (no change)

    native CheckBox_selected_light cn1 CheckBox_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_light -- 95.37% fidelity (SSIM 0.9658) (no change)

    native Switch_selected_light cn1 Switch_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_dark -- 95.45% fidelity (SSIM 0.9656) (no change)

    native Switch_selected_dark cn1 Switch_selected_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_light -- 95.46% fidelity (SSIM 0.9657) (no change)

    native RadioButton_disabled_light cn1 RadioButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_dark -- 95.57% fidelity (SSIM 0.9613) (no change)

    native Switch_disabled_dark cn1 Switch_disabled_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_light -- 95.65% fidelity (SSIM 0.9300) (no change)

    native Dialog_normal_light cn1 Dialog_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_light -- 95.78% fidelity (SSIM 0.9578) (no change)

    native RaisedButton_pressed_light cn1 RaisedButton_pressed_light
    Left: native widget. Right: Codename One render.

  • Button_normal_light -- 95.79% fidelity (SSIM 0.9528) (no change)

    native Button_normal_light cn1 Button_normal_light
    Left: native widget. Right: Codename One render.

  • Dialog_normal_dark -- 95.79% fidelity (SSIM 0.9322) (no change)

    native Dialog_normal_dark cn1 Dialog_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_light -- 95.97% fidelity (SSIM 0.9612) (no change)

    native Switch_normal_light cn1 Switch_normal_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_normal_light -- 96.09% fidelity (SSIM 0.9367) (no change)

    native FloatingActionButton_normal_light cn1 FloatingActionButton_normal_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_pressed_dark -- 96.16% fidelity (SSIM 0.9513) (no change)

    native FloatingActionButton_pressed_dark cn1 FloatingActionButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_dark -- 96.17% fidelity (SSIM 0.9616) (no change)

    native Switch_normal_dark cn1 Switch_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_disabled_dark -- 96.21% fidelity (SSIM 0.9648) (no change)

    native TextField_disabled_dark cn1 TextField_disabled_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_dark -- 96.41% fidelity (SSIM 0.9516) (no change)

    native RaisedButton_normal_dark cn1 RaisedButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_disabled_light -- 96.43% fidelity (SSIM 0.9698) (no change)

    native Switch_disabled_light cn1 Switch_disabled_light
    Left: native widget. Right: Codename One render.

  • Button_disabled_light -- 96.80% fidelity (SSIM 0.9596) (no change)

    native Button_disabled_light cn1 Button_disabled_light
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_dark -- 96.91% fidelity (SSIM 0.9669) (no change)

    native ProgressBar_normal_dark cn1 ProgressBar_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_dark -- 97.02% fidelity (SSIM 0.9549) (no change)

    native RaisedButton_disabled_dark cn1 RaisedButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_normal_dark -- 97.07% fidelity (SSIM 0.9521) (no change)

    native FloatingActionButton_normal_dark cn1 FloatingActionButton_normal_dark
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_light -- 97.26% fidelity (SSIM 0.9739) (no change)

    native ProgressBar_normal_light cn1 ProgressBar_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_light -- 97.26% fidelity (SSIM 0.9611) (no change)

    native RaisedButton_disabled_light cn1 RaisedButton_disabled_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_light -- 97.29% fidelity (SSIM 0.9649) (no change)

    native TextField_disabled_light cn1 TextField_disabled_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_light -- 97.32% fidelity (SSIM 0.9613) (no change)

    native RaisedButton_normal_light cn1 RaisedButton_normal_light
    Left: native widget. Right: Codename One render.

  • TextField_normal_dark -- 97.61% fidelity (SSIM 0.9583) (no change)

    native TextField_normal_dark cn1 TextField_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_light -- 97.62% fidelity (SSIM 0.9582) (no change)

    native TextField_normal_light cn1 TextField_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_dark -- 98.39% fidelity (SSIM 0.9900) (no change)

    native Slider_normal_dark cn1 Slider_normal_dark
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_light -- 98.69% fidelity (SSIM 0.9739) (no change)

    native Toolbar_normal_light cn1 Toolbar_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_light -- 98.95% fidelity (SSIM 0.9908) (no change)

    native Slider_normal_light cn1 Slider_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_dark -- 99.56% fidelity (SSIM 0.9927) (no change)

    native Slider_disabled_dark cn1 Slider_disabled_dark
    Left: native widget. Right: Codename One render.

  • Slider_disabled_light -- 99.59% fidelity (SSIM 0.9932) (no change)

    native Slider_disabled_light cn1 Slider_disabled_light
    Left: native widget. Right: Codename One render.

@shai-almog

shai-almog commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Native fidelity (iOS Modern, Metal)

68 pairs compared -- median 94.4%, worst 83.5% (Tabs_normal_dark), 25th pct 91.4%, mean 93.7%.

Distribution -- >=99%: 0 | 95-99%: 32 | 90-95%: 26 | <90%: 10

Component State Appearance Material Fidelity SSIM mean delta vs base Geometry
Tabs normal dark glass 83.5% 0.884 11.66 -1.3 ok
Tabs normal light glass 86.4% 0.896 8.01 0.0 ok
Toolbar normal light glass 87.6% 0.951 4.24 0.0 ok
Toolbar normal dark glass 87.7% 0.950 3.69 0.0 ok
FlatButton pressed dark glass 87.8% 0.966 3.09 +1.1 ok
RaisedButton disabled dark glass 87.8% 0.954 4.42 0.0 OFF (off 12px, w 1.11)
FlatButton normal dark glass 87.9% 0.968 3.12 0.0 ok
FlatButton normal light glass 88.2% 0.970 3.28 0.0 ok
FlatButton pressed light glass 88.4% 0.968 3.09 +1.0 ok
RaisedButton disabled light glass 89.4% 0.952 3.90 +0.6 OFF (off 11px, w 1.10)
TextField normal light normal 90.4% 0.961 2.70 0.0 ok
Button normal light glass 90.5% 0.948 4.19 -1.0 OFF (off 11px)
RaisedButton normal light glass 90.7% 0.955 3.65 -1.8 OFF (off 11px, w 1.10)
Button pressed dark glass 90.9% 0.951 3.83 -0.3 OFF (off 11px)
RaisedButton pressed light glass 91.0% 0.957 3.54 +1.3 OFF (off 11px, w 1.10)
Button normal dark glass 91.1% 0.952 3.76 +0.2 OFF (off 11px)
Button pressed light glass 91.2% 0.948 3.64 +0.3 OFF (off 11px)
TextField disabled light normal 91.4% 0.965 2.20 0.0 ok
Spinner normal dark normal 91.5% 0.893 3.25 0.0 ok
Button disabled dark glass 91.7% 0.955 3.17 +0.3 OFF (off 11px)
Spinner normal light normal 91.8% 0.914 4.28 0.0 ok
Switch selected light normal 92.1% 0.981 1.47 0.0 ok
CheckBox normal light normal 92.2% 0.994 0.68 -0.1 ok
RadioButton normal light normal 92.2% 0.994 0.68 -0.1 ok
Slider disabled dark normal 92.4% 0.945 2.27 0.0 ok
RaisedButton normal dark glass 92.5% 0.962 2.89 0.0 OFF (off 11px, w 1.10)
CheckBox disabled light normal 92.7% 0.995 0.50 -0.8 ok
RadioButton disabled light normal 92.7% 0.995 0.50 -0.8 ok
Slider normal dark normal 92.7% 0.946 2.48 0.0 ok
RaisedButton pressed dark glass 92.8% 0.964 2.82 +4.8 OFF (off 11px, w 1.10)
TabsGeom normal dark normal 93.0% 0.892 8.76 -0.5 ok
TabsGeom normal light normal 93.0% 0.886 7.10 0.0 ok
Button disabled light glass 93.2% 0.954 2.70 -0.3 OFF (off 11px)
Slider disabled light normal 94.0% 0.963 1.74 0.0 OFF (h 4.50)
ProgressBar normal dark normal 94.4% 0.979 1.55 0.0 OFF (h 1.20)
RadioButton selected light normal 94.8% 0.992 0.86 +0.4 ok
Slider normal light normal 95.1% 0.958 1.58 0.0 ok
ProgressBar normal light normal 95.4% 0.984 1.37 0.0 OFF (h 1.20)
Switch normal light normal 95.5% 0.986 0.70 0.0 ok
Switch disabled dark normal 95.5% 0.978 0.90 0.0 ok
TabOne normal light normal 95.6% 0.946 8.63 0.0 OFF (off 40px, w 0.75, h 0.54)
CheckBox disabled dark normal 95.8% 0.993 0.25 +1.2 ok
RadioButton disabled dark normal 95.8% 0.993 0.25 +1.2 ok
CheckBox selected light normal 95.8% 0.994 0.67 -0.5 ok
Switch selected dark normal 95.9% 0.985 1.02 0.0 ok
TabOne normal dark normal 96.0% 0.945 6.14 -0.1 OFF (off 40px, w 0.75, h 0.54)
GlassPanelPhoto normal light glass 96.1% 0.970 8.35 0.0 ok
GlassPanelPhoto normal dark glass 96.2% 0.972 9.12 0.0 ok
Switch disabled light normal 96.3% 0.991 0.52 0.0 OFF (off 7px)
CheckBox normal dark normal 96.5% 0.993 0.35 +1.5 ok
RadioButton normal dark normal 96.5% 0.993 0.35 +1.5 ok
Switch normal dark normal 96.8% 0.986 0.82 0.0 ok
RadioButton selected dark normal 96.8% 0.991 0.57 +1.4 ok
Dialog normal dark normal 97.0% 0.948 2.20 0.0 ok
TextField normal dark normal 97.1% 0.953 3.23 -0.4 ok
Dialog normal light normal 97.1% 0.951 2.24 0.0 ok
TextField disabled dark normal 97.3% 0.956 2.34 -0.2 ok
CheckBox selected dark normal 97.8% 0.993 0.38 +0.3 ok
GlassPanelGrad normal light normal 98.2% 0.982 4.87 0.0 ok
GlassPanelGrey normal light normal 98.4% 0.982 3.78 0.0 ok
GlassPanelGrey normal dark normal 98.4% 0.982 3.62 0.0 ok
GlassPanelGrad normal dark normal 98.4% 0.983 4.11 0.0 ok
GlassPanelRed normal light normal 98.4% 0.982 3.96 0.0 ok
GlassPanelRed normal dark normal 98.6% 0.983 3.48 0.0 ok
GlassIcon normal dark normal 98.6% 0.984 3.55 0.0 ok
GlassText normal dark normal 98.6% 0.984 3.52 0.0 ok
GlassIcon normal light normal 98.7% 0.986 3.54 0.0 ok
GlassText normal light normal 98.7% 0.986 3.58 0.0 ok
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Component State Appearance bbox dx,dy (px) w ratio h ratio center off (px) radius native->cn1 (px)
TabOne normal light +35,+0 0.747 0.543 39.5 79.1 -> 46.7
TabOne normal dark +35,+0 0.747 0.543 39.5 80.3 -> 47.2
RaisedButton disabled dark +0,+0 1.110 0.968 11.6 49.8 -> 44.2
RaisedButton disabled light +0,+0 1.104 0.968 11.1 54.1 -> 45.1
Button normal light +0,+0 1.100 0.968 11.1 44.5 -> 45.6
RaisedButton normal light +0,+0 1.104 0.968 11.1 44.5 -> 44.3
Button pressed dark +0,+0 1.100 0.968 11.1 45.4 -> 44.3
RaisedButton pressed light +0,+0 1.104 0.968 11.1 44.7 -> 44.3
Button normal dark +0,+0 1.100 0.968 11.1 45.8 -> 44.3
Button pressed light +0,+0 1.100 0.968 11.1 48.1 -> 55.6
Button disabled dark +0,+0 1.100 0.968 11.1 45.1 -> 44.3
RaisedButton normal dark +0,+0 1.104 0.968 11.1 44.4 -> 44.3
RaisedButton pressed dark +0,+0 1.104 0.968 11.1 44.5 -> 44.2
Button disabled light +0,+0 1.100 0.968 11.1 44.0 -> 44.7
Switch disabled light +10,+0 0.960 1.000 6.5 -
FlatButton pressed dark +0,+0 1.062 0.968 4.7 95.3 -> 48.2
FlatButton normal dark +0,+0 1.062 0.968 4.7 91.8 -> 44.5
FlatButton normal light +0,+0 1.062 0.968 4.7 91.9 -> 44.5
FlatButton pressed light +0,+0 1.062 0.968 4.7 95.4 -> 48.2
Toolbar normal light +4,+7 0.987 0.926 3.5 62.5 -> 56.1
Toolbar normal dark +4,+7 0.987 0.919 3.2 60.5 -> 55.5
Switch selected light +0,+0 1.028 1.026 2.7 -
Slider disabled light +0,-29 1.000 4.500 2.5 -
CheckBox disabled light +1,-3 1.000 1.023 2.2 -
RadioButton disabled light +1,-3 1.000 1.023 2.2 -
CheckBox disabled dark +1,-3 1.000 1.023 2.2 -
RadioButton disabled dark +1,-3 1.000 1.023 2.2 -
Switch normal light +0,+0 1.023 1.013 2.1 -
Switch disabled dark +0,+0 1.023 1.013 2.1 -
Switch normal dark +0,+0 1.023 1.013 2.1 -
CheckBox normal dark +0,-2 1.000 1.000 2.0 -
RadioButton normal dark +0,-2 1.000 1.000 2.0 -
RadioButton selected dark +0,-2 1.000 1.000 2.0 -
CheckBox selected dark +0,-2 1.000 1.000 2.0 -
Tabs normal dark +9,+0 0.973 1.012 1.8 79.7 -> 80.7
Tabs normal light +9,+0 0.973 1.012 1.8 79.2 -> 80.3
TabsGeom normal dark +9,+0 0.973 1.012 1.8 80.5 -> 80.9
TabsGeom normal light +9,+0 0.973 1.012 1.8 79.3 -> 80.6
Switch selected dark +0,+0 1.017 1.013 1.6 -
CheckBox normal light +0,-2 1.000 1.011 1.5 -
RadioButton normal light +0,-2 1.000 1.011 1.5 -
RadioButton selected light +0,-2 1.000 1.011 1.5 -
CheckBox selected light +0,-2 1.000 1.011 1.5 -
GlassIcon normal dark +0,+1 0.999 1.000 1.1 92.1 -> 91.5
GlassText normal dark +0,+1 0.999 1.000 1.1 92.1 -> 91.5
Spinner normal dark -23,-14 1.044 1.082 1.0 -
ProgressBar normal dark +0,+0 1.000 1.200 1.0 -
ProgressBar normal light +0,+0 1.000 1.200 1.0 -
GlassPanelGrey normal dark +1,+1 0.998 1.000 1.0 26.4 -> 49.4
Spinner normal light -24,-15 1.045 1.085 0.7 -
Slider disabled dark +0,-1 1.000 1.015 0.5 -
Slider normal light +0,+1 1.000 0.964 0.5 -
GlassPanelPhoto normal light +0,+0 1.000 1.005 0.5 25.6 -> 55.3
GlassPanelPhoto normal dark +0,+0 1.000 1.005 0.5 23.0 -> 52.5
GlassPanelGrad normal light +0,+0 1.000 1.005 0.5 22.3 -> 51.9
GlassPanelGrey normal light +0,+0 1.000 1.005 0.5 22.4 -> 51.9
GlassPanelGrad normal dark +1,+1 0.998 0.995 0.5 25.7 -> 48.4
GlassPanelRed normal light +0,+0 1.000 1.005 0.5 22.1 -> 51.9
GlassPanelRed normal dark +1,+1 0.998 0.995 0.5 26.6 -> 48.9
GlassIcon normal light +0,+0 1.000 1.005 0.5 91.6 -> 92.3
GlassText normal light +0,+0 1.000 1.005 0.5 91.6 -> 92.3
TextField normal light +0,+0 1.000 1.000 0.0 -
TextField disabled light +0,+0 1.000 1.000 0.0 -
Slider normal dark +0,+0 1.000 1.000 0.0 -
Dialog normal dark +0,+0 1.000 1.000 0.0 -
TextField normal dark +0,+0 1.000 1.000 0.0 -
Dialog normal light +0,+0 1.000 1.000 0.0 -
TextField disabled dark +0,+0 1.000 1.000 0.0 -

Side-by-side comparisons (worst first)

  • Tabs_normal_dark -- 83.45% fidelity (SSIM 0.8842) (-1.32 vs baseline)

    native Tabs_normal_dark cn1 Tabs_normal_dark
    Left: native widget. Right: Codename One render.

  • Tabs_normal_light -- 86.44% fidelity (SSIM 0.8961) (no change)

    native Tabs_normal_light cn1 Tabs_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_light -- 87.64% fidelity (SSIM 0.9511) (no change)

    native Toolbar_normal_light cn1 Toolbar_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_dark -- 87.70% fidelity (SSIM 0.9495) (no change)

    native Toolbar_normal_dark cn1 Toolbar_normal_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_dark -- 87.79% fidelity (SSIM 0.9664) (+1.14 vs baseline)

    native FlatButton_pressed_dark cn1 FlatButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_dark -- 87.82% fidelity (SSIM 0.9541) (no change)

    native RaisedButton_disabled_dark cn1 RaisedButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_dark -- 87.88% fidelity (SSIM 0.9677) (no change)

    native FlatButton_normal_dark cn1 FlatButton_normal_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_light -- 88.16% fidelity (SSIM 0.9696) (no change)

    native FlatButton_normal_light cn1 FlatButton_normal_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_light -- 88.40% fidelity (SSIM 0.9676) (+1.01 vs baseline)

    native FlatButton_pressed_light cn1 FlatButton_pressed_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_light -- 89.39% fidelity (SSIM 0.9518) (+0.62 vs baseline)

    native RaisedButton_disabled_light cn1 RaisedButton_disabled_light
    Left: native widget. Right: Codename One render.

  • TextField_normal_light -- 90.40% fidelity (SSIM 0.9614) (no change)

    native TextField_normal_light cn1 TextField_normal_light
    Left: native widget. Right: Codename One render.

  • Button_normal_light -- 90.49% fidelity (SSIM 0.9481) (-1.03 vs baseline)

    native Button_normal_light cn1 Button_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_light -- 90.68% fidelity (SSIM 0.9548) (-1.78 vs baseline)

    native RaisedButton_normal_light cn1 RaisedButton_normal_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_dark -- 90.87% fidelity (SSIM 0.9510) (-0.27 vs baseline)

    native Button_pressed_dark cn1 Button_pressed_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_light -- 90.99% fidelity (SSIM 0.9568) (+1.28 vs baseline)

    native RaisedButton_pressed_light cn1 RaisedButton_pressed_light
    Left: native widget. Right: Codename One render.

  • Button_normal_dark -- 91.10% fidelity (SSIM 0.9517) (+0.17 vs baseline)

    native Button_normal_dark cn1 Button_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_pressed_light -- 91.24% fidelity (SSIM 0.9484) (+0.27 vs baseline)

    native Button_pressed_light cn1 Button_pressed_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_light -- 91.35% fidelity (SSIM 0.9651) (no change)

    native TextField_disabled_light cn1 TextField_disabled_light
    Left: native widget. Right: Codename One render.

  • Spinner_normal_dark -- 91.47% fidelity (SSIM 0.8933) (no change)

    native Spinner_normal_dark cn1 Spinner_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_disabled_dark -- 91.66% fidelity (SSIM 0.9553) (+0.29 vs baseline)

    native Button_disabled_dark cn1 Button_disabled_dark
    Left: native widget. Right: Codename One render.

  • Spinner_normal_light -- 91.79% fidelity (SSIM 0.9141) (no change)

    native Spinner_normal_light cn1 Spinner_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_light -- 92.13% fidelity (SSIM 0.9806) (no change)

    native Switch_selected_light cn1 Switch_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_light -- 92.16% fidelity (SSIM 0.9938) (-0.06 vs baseline)

    native CheckBox_normal_light cn1 CheckBox_normal_light
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_light -- 92.16% fidelity (SSIM 0.9938) (-0.06 vs baseline)

    native RadioButton_normal_light cn1 RadioButton_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_dark -- 92.44% fidelity (SSIM 0.9448) (no change)

    native Slider_disabled_dark cn1 Slider_disabled_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_dark -- 92.52% fidelity (SSIM 0.9616) (no change)

    native RaisedButton_normal_dark cn1 RaisedButton_normal_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_light -- 92.71% fidelity (SSIM 0.9953) (-0.77 vs baseline)

    native CheckBox_disabled_light cn1 CheckBox_disabled_light
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_light -- 92.71% fidelity (SSIM 0.9953) (-0.77 vs baseline)

    native RadioButton_disabled_light cn1 RadioButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_dark -- 92.74% fidelity (SSIM 0.9458) (no change)

    native Slider_normal_dark cn1 Slider_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_dark -- 92.75% fidelity (SSIM 0.9637) (+4.79 vs baseline)

    native RaisedButton_pressed_dark cn1 RaisedButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • TabsGeom_normal_dark -- 93.01% fidelity (SSIM 0.8920) (-0.48 vs baseline)

    native TabsGeom_normal_dark cn1 TabsGeom_normal_dark
    Left: native widget. Right: Codename One render.

  • TabsGeom_normal_light -- 93.02% fidelity (SSIM 0.8861) (no change)

    native TabsGeom_normal_light cn1 TabsGeom_normal_light
    Left: native widget. Right: Codename One render.

  • Button_disabled_light -- 93.15% fidelity (SSIM 0.9540) (-0.29 vs baseline)

    native Button_disabled_light cn1 Button_disabled_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_light -- 94.01% fidelity (SSIM 0.9626) (no change)

    native Slider_disabled_light cn1 Slider_disabled_light
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_dark -- 94.44% fidelity (SSIM 0.9788) (no change)

    native ProgressBar_normal_dark cn1 ProgressBar_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_light -- 94.84% fidelity (SSIM 0.9916) (+0.41 vs baseline)

    native RadioButton_selected_light cn1 RadioButton_selected_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_light -- 95.13% fidelity (SSIM 0.9583) (no change)

    native Slider_normal_light cn1 Slider_normal_light
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_light -- 95.41% fidelity (SSIM 0.9836) (no change)

    native ProgressBar_normal_light cn1 ProgressBar_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_normal_light -- 95.51% fidelity (SSIM 0.9863) (no change)

    native Switch_normal_light cn1 Switch_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_dark -- 95.53% fidelity (SSIM 0.9778) (no change)

    native Switch_disabled_dark cn1 Switch_disabled_dark
    Left: native widget. Right: Codename One render.

  • TabOne_normal_light -- 95.62% fidelity (SSIM 0.9463) (no change)

    native TabOne_normal_light cn1 TabOne_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_dark -- 95.76% fidelity (SSIM 0.9928) (+1.17 vs baseline)

    native CheckBox_disabled_dark cn1 CheckBox_disabled_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_dark -- 95.76% fidelity (SSIM 0.9928) (+1.17 vs baseline)

    native RadioButton_disabled_dark cn1 RadioButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_light -- 95.80% fidelity (SSIM 0.9938) (-0.52 vs baseline)

    native CheckBox_selected_light cn1 CheckBox_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_dark -- 95.90% fidelity (SSIM 0.9850) (no change)

    native Switch_selected_dark cn1 Switch_selected_dark
    Left: native widget. Right: Codename One render.

  • TabOne_normal_dark -- 96.04% fidelity (SSIM 0.9449) (-0.10 vs baseline)

    native TabOne_normal_dark cn1 TabOne_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelPhoto_normal_light -- 96.08% fidelity (SSIM 0.9696) (no change)

    native GlassPanelPhoto_normal_light cn1 GlassPanelPhoto_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelPhoto_normal_dark -- 96.17% fidelity (SSIM 0.9724) (no change)

    native GlassPanelPhoto_normal_dark cn1 GlassPanelPhoto_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_disabled_light -- 96.31% fidelity (SSIM 0.9909) (no change)

    native Switch_disabled_light cn1 Switch_disabled_light
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_dark -- 96.52% fidelity (SSIM 0.9927) (+1.45 vs baseline)

    native CheckBox_normal_dark cn1 CheckBox_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_dark -- 96.52% fidelity (SSIM 0.9927) (+1.45 vs baseline)

    native RadioButton_normal_dark cn1 RadioButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_dark -- 96.80% fidelity (SSIM 0.9855) (no change)

    native Switch_normal_dark cn1 Switch_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_dark -- 96.81% fidelity (SSIM 0.9908) (+1.35 vs baseline)

    native RadioButton_selected_dark cn1 RadioButton_selected_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_dark -- 96.97% fidelity (SSIM 0.9479) (no change)

    native Dialog_normal_dark cn1 Dialog_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_dark -- 97.08% fidelity (SSIM 0.9528) (-0.38 vs baseline)

    native TextField_normal_dark cn1 TextField_normal_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_light -- 97.09% fidelity (SSIM 0.9505) (no change)

    native Dialog_normal_light cn1 Dialog_normal_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_dark -- 97.34% fidelity (SSIM 0.9555) (-0.22 vs baseline)

    native TextField_disabled_dark cn1 TextField_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_dark -- 97.79% fidelity (SSIM 0.9932) (+0.34 vs baseline)

    native CheckBox_selected_dark cn1 CheckBox_selected_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelGrad_normal_light -- 98.24% fidelity (SSIM 0.9819) (no change)

    native GlassPanelGrad_normal_light cn1 GlassPanelGrad_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelGrey_normal_light -- 98.38% fidelity (SSIM 0.9819) (no change)

    native GlassPanelGrey_normal_light cn1 GlassPanelGrey_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelGrey_normal_dark -- 98.42% fidelity (SSIM 0.9816) (no change)

    native GlassPanelGrey_normal_dark cn1 GlassPanelGrey_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelGrad_normal_dark -- 98.43% fidelity (SSIM 0.9829) (no change)

    native GlassPanelGrad_normal_dark cn1 GlassPanelGrad_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelRed_normal_light -- 98.43% fidelity (SSIM 0.9823) (no change)

    native GlassPanelRed_normal_light cn1 GlassPanelRed_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelRed_normal_dark -- 98.57% fidelity (SSIM 0.9832) (no change)

    native GlassPanelRed_normal_dark cn1 GlassPanelRed_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassIcon_normal_dark -- 98.59% fidelity (SSIM 0.9841) (no change)

    native GlassIcon_normal_dark cn1 GlassIcon_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassText_normal_dark -- 98.59% fidelity (SSIM 0.9837) (no change)

    native GlassText_normal_dark cn1 GlassText_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassIcon_normal_light -- 98.67% fidelity (SSIM 0.9860) (no change)

    native GlassIcon_normal_light cn1 GlassIcon_normal_light
    Left: native widget. Right: Codename One render.

  • GlassText_normal_light -- 98.69% fidelity (SSIM 0.9862) (no change)

    native GlassText_normal_light cn1 GlassText_normal_light
    Left: native widget. Right: Codename One render.

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