From fc7a21ee2d471da4cc75ee99304b46dcb97cae0c Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 8 May 2026 06:34:09 +0300 Subject: [PATCH 01/11] Native theme accents: bake var() bindings into the .res, retune at runtime CSS rules in the iOS Modern and Android Material 3 native themes reference an accent palette via var(--accent-color, fallback). The Flute compiler still inlines the fallback as the baked-in default AND additionally emits a @cn1-bind:.=accent-color constant alongside, so the .res file remembers which style keys track which palette variable. UIManager.buildTheme() gains an applyThemeBindings() pass that overlays @ overrides supplied via addThemeProps onto every bound theme key. A user app rebrands the accent with a single addThemeProps({"@accent-color": "ff2d95", ...}) call - no per-UIID rule duplication, no theme recompile. Replaces the compile-time-only var() approach reverted in #4877 (PR #4848). The same accent vocabulary works at runtime now and the docs no longer suggest forking the shipped native theme. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/_build-ios-port.yml | 2 +- .github/workflows/ios-packaging.yml | 2 +- .github/workflows/scripts-android.yml | 4 + .github/workflows/scripts-ios-native.yml | 6 +- .github/workflows/scripts-ios.yml | 8 +- .../src/com/codename1/ui/plaf/UIManager.java | 95 ++++++++++++ docs/developer-guide/Native-Themes.asciidoc | 138 ++++++++++++++++-- .../ui/plaf/NativeThemeBindingsTest.java | 90 ++++++++++++ .../ui/plaf/UIManagerThemeBindingsTest.java | 129 ++++++++++++++++ .../com/codename1/designer/css/CSSTheme.java | 116 ++++++++++++++- native-themes/android-material/theme.css | 123 +++++++++------- native-themes/ios-modern/theme.css | 86 ++++++----- .../PaletteOverrideThemeScreenshotTest.java | 80 +++++----- 13 files changed, 735 insertions(+), 144 deletions(-) create mode 100644 maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java create mode 100644 maven/core-unittests/src/test/java/com/codename1/ui/plaf/UIManagerThemeBindingsTest.java diff --git a/.github/workflows/_build-ios-port.yml b/.github/workflows/_build-ios-port.yml index 0558bd8cf5..ac40f4521d 100644 --- a/.github/workflows/_build-ios-port.yml +++ b/.github/workflows/_build-ios-port.yml @@ -68,7 +68,7 @@ jobs: id: src_hash run: | set -euo pipefail - SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes \ + SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes native-themes \ -type f \( -name '*.java' -o -name '*.m' -o -name '*.h' -o -name '*.xml' -o -name '*.properties' -o -name '*.css' \) 2>/dev/null \ | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}') POM_HASH=$(find . -name 'pom.xml' -not -path './scripts/*' 2>/dev/null \ diff --git a/.github/workflows/ios-packaging.yml b/.github/workflows/ios-packaging.yml index 4b35730fc3..1db554a0e3 100644 --- a/.github/workflows/ios-packaging.yml +++ b/.github/workflows/ios-packaging.yml @@ -85,7 +85,7 @@ jobs: id: src_hash run: | set -euo pipefail - SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes \ + SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes native-themes \ -type f \( -name '*.java' -o -name '*.m' -o -name '*.h' -o -name '*.xml' -o -name '*.properties' -o -name '*.css' \) 2>/dev/null \ | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}') POM_HASH=$(find . -name 'pom.xml' -not -path './scripts/*' 2>/dev/null \ diff --git a/.github/workflows/scripts-android.yml b/.github/workflows/scripts-android.yml index abac1b2717..95f198b8ff 100644 --- a/.github/workflows/scripts-android.yml +++ b/.github/workflows/scripts-android.yml @@ -22,6 +22,8 @@ name: Test Android build scripts - '!CodenameOne/src/**/*.md' - 'Ports/Android/**' - '!Ports/Android/**/*.md' + - 'native-themes/android-material/**' + - '!native-themes/android-material/**/*.md' - 'maven/**' - '!maven/core-unittests/**' - 'tests/**' @@ -49,6 +51,8 @@ name: Test Android build scripts - '!CodenameOne/src/**/*.md' - 'Ports/Android/**' - '!Ports/Android/**/*.md' + - 'native-themes/android-material/**' + - '!native-themes/android-material/**/*.md' - 'maven/**' - '!maven/core-unittests/**' - 'tests/**' diff --git a/.github/workflows/scripts-ios-native.yml b/.github/workflows/scripts-ios-native.yml index 5fc0b56aac..0c1ec5ddb5 100644 --- a/.github/workflows/scripts-ios-native.yml +++ b/.github/workflows/scripts-ios-native.yml @@ -20,6 +20,8 @@ on: - '!CodenameOne/src/**/*.md' - 'Ports/iOSPort/**' - '!Ports/iOSPort/**/*.md' + - 'native-themes/ios-modern/**' + - '!native-themes/ios-modern/**/*.md' - 'vm/**' - '!vm/**/*.md' - 'tests/**' @@ -47,6 +49,8 @@ on: - '!CodenameOne/src/**/*.md' - 'Ports/iOSPort/**' - '!Ports/iOSPort/**/*.md' + - 'native-themes/ios-modern/**' + - '!native-themes/ios-modern/**/*.md' - 'vm/**' - '!vm/**/*.md' - 'tests/**' @@ -108,7 +112,7 @@ jobs: id: src_hash run: | set -euo pipefail - SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes \ + SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes native-themes \ -type f \( -name '*.java' -o -name '*.m' -o -name '*.h' -o -name '*.xml' -o -name '*.properties' -o -name '*.css' \) 2>/dev/null \ | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}') POM_HASH=$(find . -name 'pom.xml' -not -path './scripts/*' 2>/dev/null \ diff --git a/.github/workflows/scripts-ios.yml b/.github/workflows/scripts-ios.yml index eaba9af79a..6a3697f9a7 100644 --- a/.github/workflows/scripts-ios.yml +++ b/.github/workflows/scripts-ios.yml @@ -23,6 +23,8 @@ on: - '!CodenameOne/src/**/*.md' - 'Ports/iOSPort/**' - '!Ports/iOSPort/**/*.md' + - 'native-themes/ios-modern/**' + - '!native-themes/ios-modern/**/*.md' - 'vm/**' - '!vm/**/*.md' - 'tests/**' @@ -53,6 +55,8 @@ on: - '!CodenameOne/src/**/*.md' - 'Ports/iOSPort/**' - '!Ports/iOSPort/**/*.md' + - 'native-themes/ios-modern/**' + - '!native-themes/ios-modern/**/*.md' - 'vm/**' - '!vm/**/*.md' - 'tests/**' @@ -120,7 +124,7 @@ jobs: id: src_hash run: | set -euo pipefail - SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes \ + SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes native-themes \ -type f \( -name '*.java' -o -name '*.m' -o -name '*.h' -o -name '*.xml' -o -name '*.properties' -o -name '*.css' \) 2>/dev/null \ | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}') POM_HASH=$(find . -name 'pom.xml' -not -path './scripts/*' 2>/dev/null \ @@ -269,7 +273,7 @@ jobs: id: src_hash run: | set -euo pipefail - SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes \ + SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes native-themes \ -type f \( -name '*.java' -o -name '*.m' -o -name '*.h' -o -name '*.xml' -o -name '*.properties' -o -name '*.css' \) 2>/dev/null \ | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}') POM_HASH=$(find . -name 'pom.xml' -not -path './scripts/*' 2>/dev/null \ diff --git a/CodenameOne/src/com/codename1/ui/plaf/UIManager.java b/CodenameOne/src/com/codename1/ui/plaf/UIManager.java index bf15bd88da..1680a61713 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/UIManager.java +++ b/CodenameOne/src/com/codename1/ui/plaf/UIManager.java @@ -1802,6 +1802,8 @@ private void buildTheme(Hashtable themeProps) { this.themeProps.put(key, themeProps.get(key)); } + applyThemeBindings(); + updateLargerTextScaleSettingFromTheme(); if (!this.themeProps.containsKey("PickerButtonBar.derive")) { @@ -1863,6 +1865,99 @@ private void buildTheme(Hashtable themeProps) { } + /// Theme entries can be bound to a named theme constant via a + /// `@cn1-bind:<themeKey>=<varName>` pseudo-constant emitted by the CSS + /// compiler when it expands a `var(--name, fallback)` reference. The + /// compiler still inlines `fallback` as the baked-in default (so themes + /// load correctly with no override), but additionally records that the + /// resolved style property tracks `--name`. + /// + /// At runtime, callers tune the palette by injecting an `@<varName>` + /// constant via [#addThemeProps]. This method walks the binding entries + /// and overlays the override value onto every bound style key, so a + /// single `addThemeProps({"@accent-color": "ff2d95"})` call retunes + /// every UIID whose CSS rule referenced `var(--accent-color, ...)`. + /// Bindings without a matching override are left at their baked-in + /// default (whatever was already in themeProps from the initial load). + private void applyThemeBindings() { + if (themeConstants == null || themeConstants.isEmpty() || themeProps == null) { + return; + } + final String prefix = "cn1-bind:"; + for (Map.Entry entry : themeConstants.entrySet()) { + String constantKey = entry.getKey(); + if (constantKey == null || !constantKey.startsWith(prefix)) { + continue; + } + Object varNameObj = entry.getValue(); + if (!(varNameObj instanceof String)) { + continue; + } + String varName = ((String) varNameObj).trim(); + if (varName.length() == 0) { + continue; + } + Object override = themeConstants.get(varName); + if (!(override instanceof String)) { + continue; + } + String themeKey = constantKey.substring(prefix.length()); + if (themeKey.length() == 0) { + continue; + } + // Only retune keys that are already present in themeProps so a + // stale binding entry (left over after the bound rule was + // dropped from the source CSS) can't materialize a phantom + // style key from the user's override value. + if (!themeProps.containsKey(themeKey)) { + continue; + } + String overrideValue = (String) override; + if (themeKey.endsWith("Color")) { + overrideValue = normalizeBoundColorValue(overrideValue); + if (overrideValue == null) { + continue; + } + } + themeProps.put(themeKey, overrideValue); + } + } + + /// `loadTheme` stores color theme entries as plain hex strings (no `#`, + /// lowercase). User-supplied overrides may use either form, so trim a + /// leading `#` and lowercase the value before assigning it to a bound + /// color key. Returns null when the value can't be parsed as a 3- or + /// 6-digit hex color so the binding falls through to its default. + private static String normalizeBoundColorValue(String raw) { + if (raw == null) { + return null; + } + String value = raw.trim(); + if (value.length() == 0) { + return null; + } + if (value.charAt(0) == '#') { + value = value.substring(1); + } + if (value.length() == 3) { + char r = value.charAt(0); + char g = value.charAt(1); + char b = value.charAt(2); + value = "" + r + r + g + g + b + b; + } + if (value.length() != 6) { + return null; + } + for (int i = 0; i < 6; i++) { + char c = value.charAt(i); + boolean hex = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); + if (!hex) { + return null; + } + } + return value.toLowerCase(); + } + private Map parseCache() { if (parseCache == null) { parseCache = new HashMap(); diff --git a/docs/developer-guide/Native-Themes.asciidoc b/docs/developer-guide/Native-Themes.asciidoc index 56bd7ffa9d..4144236f00 100644 --- a/docs/developer-guide/Native-Themes.asciidoc +++ b/docs/developer-guide/Native-Themes.asciidoc @@ -149,8 +149,13 @@ inherits from it. |=== To rebrand the app, override the colour at the role level rather -than touching every UIID. For example, to flip the primary -container palette to teal: +than touching every UIID. The example below layers a teal palette +on top from your app's own `theme.css`; if you want the same +rebrand to apply at *runtime* (for in-app accent toggles, branded +flavours, A/B tests) without recompiling the theme, see +`Runtime accent palette override` further down - a single +`addThemeProps({"@accent-color": ...})` call retunes every +accent-bearing UIID at once. [source,css] ---- @@ -242,25 +247,127 @@ accent-driven UIIDs the same way as Android above. The colour names match Apple's `UIColor.systemBlue` etc. so you can mirror the SF Symbols semantics if you want. -=== Runtime palette override +=== Runtime accent palette override + +Both shipped native themes expose their accent palette as named +constants you can retune at runtime through `UIManager.addThemeProps`. +The CSS source uses `var(--accent-color, fallback)` references so +the fallback ships as the baked-in default (the .res file loads +fine with no override) and the compiler additionally emits a +`@cn1-bind:.=accent-color` constant alongside each +affected style key. At app launch you push a tiny Hashtable of +`@`-prefixed accent constants and the runtime UIManager fans the +overrides out to every bound UIID at once - no per-UIID rule +duplication, no theme recompile. + +.iOS modern (`native-themes/ios-modern/theme.css`) +[cols="2,1,1,3", options="header"] +|=== +|Constant |Light default |Dark default |Drives + +|`@accent-color` +|`#007aff` +|(see `@accent-color-dark`) +|`Button.fgColor`, `RaisedButton.bgColor`, +`CheckBox.selected`, `RadioButton.selected`, `OnOffSwitch.fgColor`, +`BackCommand`, `TitleCommand`, `FloatingActionButton.bgColor`. + +|`@accent-color-dark` +|n/a +|`#0a84ff` +|`$Dark` counterparts of the above. + +|`@accent-pressed-color` / `@accent-pressed-color-dark` +|`#0064d1` +|`#64b1ff` +|All `.press#fg/bgColor` accent overrides. -Push a Hashtable of theme props through `UIManager.addThemeProps` -to flip the palette live, without recompiling the theme: +|`@accent-disabled-color` / `@accent-disabled-color-dark` +|`#b3d4ff` +|`#004a99` +|All `.dis#fg/bgColor` accent overrides. + +|`@accent-on-color` +|`#ffffff` +|(same) +|Text colour painted on top of the accent fill. +|=== + +.Android Material 3 (`native-themes/android-material/theme.css`) +[cols="2,1,1,2", options="header"] +|=== +|Constant |Light default |Dark default |Material 3 token + +|`@accent-color` / `@accent-color-dark` +|`#6750a4` +|`#d0bcff` +|`primary` + +|`@accent-on-color` / `@accent-on-color-dark` +|`#ffffff` +|`#381e72` +|`on-primary` + +|`@accent-container-color` / `@accent-container-color-dark` +|`#eaddff` +|`#4f378b` +|`primary-container` + +|`@accent-on-container-color` / `@accent-on-container-color-dark` +|`#21005d` +|`#eaddff` +|`on-primary-container` + +|`@accent-pressed-color` / `@accent-pressed-color-dark` +|`#d0bcff` +|`#4f378b` +|`state-pressed` +|=== [source,java] ---- Hashtable override = new Hashtable(); -override.put("RaisedButton.bgColor", "d81b60"); -override.put("RaisedButton.sel#bgColor", "b71c5c"); -override.put("RaisedButton.press#bgColor", "ad1457"); -override.put("BackCommand.fgColor", "d81b60"); +override.put("@accent-color", "ff2d95"); +override.put("@accent-color-dark", "ff2d95"); +override.put("@accent-pressed-color", "c71a75"); +override.put("@accent-pressed-color-dark", "c71a75"); +override.put("@accent-on-color", "ffffff"); +// Android-only tonal pair; iOS ignores these (no bindings reference +// them) so it's safe to set them unconditionally. +override.put("@accent-container-color", "ff2d95"); +override.put("@accent-container-color-dark", "ff2d95"); +override.put("@accent-on-container-color", "ffffff"); +override.put("@accent-on-container-color-dark", "ffffff"); UIManager.getInstance().addThemeProps(override); Form.getCurrentForm().refreshTheme(); ---- -Common cases are demonstrated by the `PaletteOverrideThemeScreenshotTest` -in the hellocodenameone test suite, which flips the primary accent -to magenta at runtime and re-renders the same form. +Values can be passed with or without the leading `#` and in any +case; the runtime accepts `"ff2d95"`, `"#FF2D95"`, and the 3-digit +shorthand `"#f0a"` interchangeably. Bindings that reference a +constant you did not override stay at their baked-in default, so a +partial override (e.g. just `@accent-color`) is fine. + +`PaletteOverrideThemeScreenshotTest` in the hellocodenameone test +suite is the worked example - it flips the primary accent to +magenta at runtime and re-renders the same form across both light +and dark capture, on both native themes. + +==== When the runtime override path doesn't apply + +The binding mechanism handles every accent UIID the shipped themes +expose. For other widgets - or when you want to override a colour +the native CSS hard-codes (e.g. the iOS `success` green on +`Switch.selected`) - either: + +* Layer a redeclaration in your app's `theme.css` (see + `Customising in your own theme` below). Compile-time, ships with + the .res. Right when you want a permanent rebrand and you control + the build. +* Or pass the specific UIID/state key directly into + `UIManager.addThemeProps` (`Switch.sel#bgColor` etc.). Runtime, + bypasses the binding system. Right when you need a one-off colour + tweak the binding vocabulary doesn't already cover. === Platform-specific UIIDs @@ -384,6 +491,13 @@ RaisedButton.disabled { background-color: #ffd6e2; color: #ffffff; } The user's CSS is layered on top of the native theme at app launch, so refresh / restart picks the override up. +For a wholesale accent rebrand consider the runtime +`@accent-color`-style override in `Runtime accent palette override` +above - it's a one-line `addThemeProps` call versus the per-UIID +redeclaration here. Layering remains the right choice for tweaking +non-accent UIIDs (typography, spacing, surface fills) the runtime +binding vocabulary doesn't cover. + === Inheriting from a native UIID `cn1-derive` lets a custom UIID start from one of the native diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java new file mode 100644 index 0000000000..b686753ede --- /dev/null +++ b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java @@ -0,0 +1,90 @@ +package com.codename1.ui.plaf; + +import com.codename1.junit.UITestBase; +import com.codename1.ui.Button; +import com.codename1.ui.util.Resources; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Hashtable; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * End-to-end check: load the shipped iOS Modern native theme `.res`, + * verify the var() bindings the CSS compiler emitted survived the + * round-trip, and that pushing an `@accent-color` override through + * {@link UIManager#addThemeProps(Hashtable)} retunes a Button's + * fgColor without touching `Button.fgColor` directly. + * + * Loads the `.res` straight from the repo's `Themes/` build output + * (next to where `scripts/build-native-themes.sh` writes it). When + * that file is absent the test is silently skipped rather than failed + * - the runtime-side binding logic is already covered by + * {@link UIManagerThemeBindingsTest}, so this test only fires when a + * fresh native theme is sitting on disk. + */ +public class NativeThemeBindingsTest extends UITestBase { + + @Test + public void iosModernThemeBindingRetunesButton() throws Exception { + File themeFile = locateNativeTheme("iOSModernTheme.res"); + if (themeFile == null) { + return; + } + Resources res; + InputStream stream = new FileInputStream(themeFile); + try { + res = Resources.open(stream); + } finally { + stream.close(); + } + String[] themeNames = res.getThemeResourceNames(); + assertNotNull(themeNames); + Hashtable theme = res.getTheme(themeNames[0]); + assertNotNull(theme); + + // Compiler should have emitted both the baked-in default AND + // the binding entry. Resources.loadTheme stores colors as the + // unpadded hex of their int value (Integer.toHexString), so the + // expected default is "7aff" rather than "007aff". + assertEquals("7aff", theme.get("Button.fgColor")); + assertEquals("accent-color", theme.get("@cn1-bind:Button.fgColor")); + + UIManager.getInstance().setThemeProps(theme); + + Button defaultBtn = new Button("default"); + defaultBtn.setUIID("Button"); + assertEquals(0x007aff, defaultBtn.getUnselectedStyle().getFgColor(), + "Native theme button should pick up the inlined fallback when no override is supplied"); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "ff2d95"); + UIManager.getInstance().addThemeProps(override); + + Button retuned = new Button("magenta"); + retuned.setUIID("Button"); + assertEquals(0xff2d95, retuned.getUnselectedStyle().getFgColor(), + "@accent-color override should retune every UIID bound to --accent-color"); + } + + /// Searches a few well-known relative locations for a freshly-built + /// native theme `.res`. We surfboard up a few directory levels + /// because the surefire `user.dir` lands inside the unittests + /// module while the build output lives at the repo root's + /// `Themes/`. + private static File locateNativeTheme(String fileName) { + File cwd = new File(".").getAbsoluteFile(); + for (int i = 0; i < 6 && cwd != null; i++) { + File candidate = new File(cwd, "Themes/" + fileName); + if (candidate.isFile()) { + return candidate; + } + cwd = cwd.getParentFile(); + } + return null; + } +} diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/UIManagerThemeBindingsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/UIManagerThemeBindingsTest.java new file mode 100644 index 0000000000..0927cc0a1a --- /dev/null +++ b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/UIManagerThemeBindingsTest.java @@ -0,0 +1,129 @@ +package com.codename1.ui.plaf; + +import com.codename1.junit.UITestBase; +import com.codename1.ui.Button; +import org.junit.jupiter.api.Test; + +import java.util.Hashtable; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Verifies the runtime theme-binding pass installed in + * {@link UIManager#buildTheme} resolves `@cn1-bind:<themeKey>=<varname>` + * entries against the live theme constants and overlays the resulting + * value onto the bound theme key. + * + * The CSS compiler emits the binding entries when it expands a + * `var(--name, fallback)` reference - the fallback is inlined as the + * baked-in default and the binding survives in the .res file as a + * `@cn1-bind:Button.fgColor=name` constant. At app launch the user + * passes {@link UIManager#addThemeProps(Hashtable)} a single + * `@accent-color` override and every bound UIID picks it up without + * having to redeclare per-UIID rules. + */ +public class UIManagerThemeBindingsTest extends UITestBase { + + @Test + public void boundThemeKeyKeepsDefaultWithoutOverride() { + Hashtable theme = new Hashtable(); + theme.put("Button.fgColor", "007aff"); + theme.put("@cn1-bind:Button.fgColor", "accent-color"); + + UIManager.getInstance().setThemeProps(theme); + + Button b = new Button("default"); + b.setUIID("Button"); + assertEquals(0x007aff, b.getUnselectedStyle().getFgColor()); + } + + @Test + public void boundThemeKeyPicksUpAccentOverride() { + Hashtable theme = new Hashtable(); + theme.put("Button.fgColor", "007aff"); + theme.put("RaisedButton.bgColor", "007aff"); + theme.put("@cn1-bind:Button.fgColor", "accent-color"); + theme.put("@cn1-bind:RaisedButton.bgColor", "accent-color"); + UIManager.getInstance().setThemeProps(theme); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "ff2d95"); + UIManager.getInstance().addThemeProps(override); + + Button b = new Button("themed"); + b.setUIID("Button"); + assertEquals(0xff2d95, b.getUnselectedStyle().getFgColor()); + + Button raised = new Button("raised"); + raised.setUIID("RaisedButton"); + assertEquals(0xff2d95, raised.getUnselectedStyle().getBgColor()); + } + + @Test + public void overrideAcceptsHashPrefixAndCaseVariants() { + Hashtable theme = new Hashtable(); + theme.put("Button.fgColor", "007aff"); + theme.put("@cn1-bind:Button.fgColor", "accent-color"); + UIManager.getInstance().setThemeProps(theme); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "#FF2D95"); + UIManager.getInstance().addThemeProps(override); + + Button b = new Button(); + b.setUIID("Button"); + assertEquals(0xff2d95, b.getUnselectedStyle().getFgColor()); + } + + @Test + public void shorthand3DigitOverrideExpandsTo6Digits() { + Hashtable theme = new Hashtable(); + theme.put("Button.fgColor", "007aff"); + theme.put("@cn1-bind:Button.fgColor", "accent-color"); + UIManager.getInstance().setThemeProps(theme); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "#f0a"); + UIManager.getInstance().addThemeProps(override); + + Button b = new Button(); + b.setUIID("Button"); + assertEquals(0xff00aa, b.getUnselectedStyle().getFgColor()); + } + + @Test + public void unboundThemeKeyIsNotMaterializedFromOverride() { + Hashtable theme = new Hashtable(); + theme.put("Button.fgColor", "007aff"); + // Stale binding referencing a key the theme does not actually + // emit - the runtime must NOT create RaisedButton.fgColor out of + // thin air when the user supplies an @accent-color override. + theme.put("@cn1-bind:RaisedButton.fgColor", "accent-color"); + UIManager.getInstance().setThemeProps(theme); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "ff2d95"); + UIManager.getInstance().addThemeProps(override); + + // Button stays at the baked-in default (no binding). + Button b = new Button(); + b.setUIID("Button"); + assertEquals(0x007aff, b.getUnselectedStyle().getFgColor()); + } + + @Test + public void invalidColorOverrideLeavesDefaultIntact() { + Hashtable theme = new Hashtable(); + theme.put("Button.fgColor", "007aff"); + theme.put("@cn1-bind:Button.fgColor", "accent-color"); + UIManager.getInstance().setThemeProps(theme); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "not-a-color"); + UIManager.getInstance().addThemeProps(override); + + Button b = new Button(); + b.setUIID("Button"); + assertEquals(0x007aff, b.getUnselectedStyle().getFgColor()); + } +} diff --git a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java index 20c0b5d7b0..e77f3f05ea 100644 --- a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java +++ b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java @@ -883,14 +883,21 @@ private static class ScaledUnit implements LexicalUnit { CN1Gradient gradient; LexicalUnit next, prev, param; - - + + /// Set to the originating CSS variable name (no `--` prefix) when this + /// unit is the result of expanding a `var(--name, fallback)` reference. + /// `evaluate()` carries it down so `apply()` can stash a runtime binding + /// on the owning Element, letting `updateResources()` emit a + /// `@cn1-bind:<themeKey>=<name>` constant alongside the resolved + /// default value. Null on units that did not originate from a var(). + String bindingVarName; + ScaledUnit(LexicalUnit src, double dpi, int screenWidth, int screenHeight) { this.src = src; this.dpi = dpi; this.screenWidth = screenWidth; this.screenHeight = screenHeight; - + } @@ -1690,6 +1697,28 @@ private boolean isOwnedBy(String key, String id) { return key.indexOf('.', id.length() + 1) == -1; } + /// Emits a `@cn1-bind:<themeKey>=<varName>` constant when the source + /// Element has a `var()` binding for the given CSS property. This lets + /// the runtime UIManager retune every UIID that referenced the same + /// `--name` constant via a single `addThemeProps({"@name": value})` + /// call without forcing the theme to be recompiled. + /// + /// `stateEl` is the per-state Element (Unselected / Selected / Pressed + /// / Disabled). Its `resolveBinding` walks up to the parent UIID + /// Element so a base `Button { color: var(--accent) }` rule still + /// emits a binding for the per-state `Button.press#fgColor` even when + /// `Button.pressed` did not redeclare `color`. + private void emitColorBinding(EditableResources res, String themeName, String themeKey, Element stateEl, String cssProperty) { + if (stateEl == null) { + return; + } + String varName = stateEl.resolveBinding(cssProperty); + if (varName == null || varName.length() == 0) { + return; + } + res.setThemeProperty(themeName, "@cn1-bind:" + themeKey, varName); + } + public void updateResources() { if (res != null) { Map themeData = res.getTheme(themeName); @@ -1840,12 +1869,16 @@ public void updateResources() { currToken = "fgColor"; res.setThemeProperty(themeName, unselId+".fgColor", el.getThemeFgColor(unselectedStyles)); + emitColorBinding(res, themeName, unselId+".fgColor", el.getUnselected(), "color"); currToken = "selected fgColor"; res.setThemeProperty(themeName, selId+"#fgColor", el.getThemeFgColor(selectedStyles)); + emitColorBinding(res, themeName, selId+"#fgColor", el.getSelected(), "color"); currToken = "pressed fgColor"; res.setThemeProperty(themeName, pressedId+"#fgColor", el.getThemeFgColor(pressedStyles)); + emitColorBinding(res, themeName, pressedId+"#fgColor", el.getPressed(), "color"); currToken = "disabled fgColor"; res.setThemeProperty(themeName, disabledId+"#fgColor", el.getThemeFgColor(disabledStyles)); + emitColorBinding(res, themeName, disabledId+"#fgColor", el.getDisabled(), "color"); currToken = "fgAlpha"; res.setThemeProperty(themeName, unselId+".fgAlpha", el.getThemeFgAlpha(unselectedStyles)); @@ -1858,12 +1891,16 @@ public void updateResources() { currToken = "bgColor"; res.setThemeProperty(themeName, unselId+".bgColor", el.getThemeBgColor(unselectedStyles)); + emitColorBinding(res, themeName, unselId+".bgColor", el.getUnselected(), "background-color"); currToken = "selected bgColor"; res.setThemeProperty(themeName, selId+"#bgColor", el.getThemeBgColor(selectedStyles)); + emitColorBinding(res, themeName, selId+"#bgColor", el.getSelected(), "background-color"); currToken = "pressed bgColor"; res.setThemeProperty(themeName, pressedId+"#bgColor", el.getThemeBgColor(pressedStyles)); + emitColorBinding(res, themeName, pressedId+"#bgColor", el.getPressed(), "background-color"); currToken = "disabled bgColor"; res.setThemeProperty(themeName, disabledId+"#bgColor", el.getThemeBgColor(disabledStyles)); + emitColorBinding(res, themeName, disabledId+"#bgColor", el.getDisabled(), "background-color"); currToken = "transparency"; res.setThemeProperty(themeName, unselId+".transparency", el.getThemeTransparency(unselectedStyles)); @@ -3224,7 +3261,18 @@ public static String generateSHA256(String message) { public class Element { Element parent = anyNodeStyle; Map properties = new LinkedHashMap(); - + + /// Records `(cssProperty -> varName)` for any property on this + /// Element whose value was set via a `var(--name, fallback)` + /// expansion. Populated by `apply(Element, String, LexicalUnit)` + /// from `ScaledUnit.bindingVarName` and consumed by + /// `updateResources()` to emit `@cn1-bind:<themeKey>=<name>` + /// constants. Each state sub-Element (unselected / selected / + /// pressed / disabled) keeps its own map so per-state var + /// references map cleanly to the corresponding `Button.press#fgColor` + /// shape. + Map bindings = new LinkedHashMap(); + Element unselected; Element selected; Element pressed; @@ -3552,7 +3600,35 @@ Element getDisabled() { } return disabled; } - + + /// Returns the var name a given CSS property is bound to, walking + /// the current Element first and falling back to its `parent` + /// chain. State sub-Elements have their parent set to the + /// owning UIID Element (see `getUnselected/Selected/Pressed/Disabled`) + /// so a `Button { color: var(--accent) }` binding visible on the + /// Button base also reaches `Button.press#fgColor` whenever + /// `Button.pressed` did not redeclare `color`. Likewise a + /// `cn1-derive: Button` chain inherits Button's bindings so + /// derived UIIDs retune in lockstep when the user overrides the + /// referenced theme constant. + String resolveBinding(String cssProperty) { + String b = bindings.get(cssProperty); + if (b != null) { + return b; + } + // anyNodeStyle.parent points back to itself (default field + // initializer); stop the walk there to avoid infinite + // recursion. Any binding declared on anyNodeStyle is still + // returned by the bindings.get() check above. + if (this == anyNodeStyle) { + return null; + } + if (parent != null && parent != this) { + return parent.resolveBinding(cssProperty); + } + return null; + } + void put(String key, Object value) { style.put(key, value); } @@ -5559,7 +5635,19 @@ String renderAsCSSString(String property, Map styles) { public void apply(Element style, String property, LexicalUnit value) { - + // Capture any var() binding tagged onto the head ScaledUnit so the + // owning Element knows this property is bound to a runtime + // overridable theme constant. We record on every property so + // `updateResources()` only has to look in one place; emission to + // the .res is gated on whether the resulting theme key is one of + // the accent-bearing color outputs (fg/bg color today). + if (value instanceof ScaledUnit) { + String varName = ((ScaledUnit) value).bindingVarName; + if (varName != null && varName.length() > 0) { + style.bindings.put(property, varName); + } + } + switch (property) { case "refresh-images": refreshImages = true; @@ -7372,6 +7460,22 @@ private ScaledUnit evaluate(LexicalUnit lu) throws CSSException { } else { su = evaluate(new ScaledUnit(varVal, theme.currentDpi, theme.getPreviewScreenWidth(), theme.getPreviewScreenHeight())); } + // Tag the resolved unit with the originating var name + // (sans the `cn1--` prefix the loader rewrites `--` to) + // so apply() can stash a runtime binding on the owning + // Element. We tag the head only - the chain after the + // var() expansion stays unbound. + if (su != null && varname != null) { + String bare = varname; + if (bare.startsWith("cn1--")) { + bare = bare.substring("cn1--".length()); + } else if (bare.startsWith("--")) { + bare = bare.substring(2); + } + if (bare.length() > 0) { + su.bindingVarName = bare; + } + } // Evaluate the variable value in case it also includes other variables that need to be evaluated. //ScaledUnit su = evaluate(new ScaledUnit(varVal, theme.currentDpi, theme.getPreviewScreenWidth(), theme.getPreviewScreenHeight())); LexicalUnit toAppend = lu.getNextLexicalUnit(); diff --git a/native-themes/android-material/theme.css b/native-themes/android-material/theme.css index cbe99f8aec..aaf75f58f8 100644 --- a/native-themes/android-material/theme.css +++ b/native-themes/android-material/theme.css @@ -5,8 +5,7 @@ * rounded/pill borders, state selectors via .pressed / .selected / * .disabled. Light and dark palettes live at the bottom of this file * in a prefers-color-scheme block the compiler rewrites into $DarkUIID - * entries. Colors are inlined (not CSS variables) because the rewriter - * operates at string level and doesn't re-scope :root declarations. + * entries. * * Material 3 baseline palette reference: * primary #6750a4 dark #d0bcff @@ -24,12 +23,36 @@ * state-disabled #e0dce4 dark #2b2930 * on-disabled #a5a0ab dark #5c5967 * - * Overridable palette: user apps layer their own theme.css or runtime - * UIManager.addThemeProps on top of this theme - see - * PaletteOverrideThemeScreenshotTest for a working example. + * Accent palette: every var(--accent-...) reference below resolves to + * the inlined fallback at compile time AND emits a runtime binding so + * the same color can be retuned at app launch via + * UIManager.addThemeProps({"@accent-color": "ff2d95", ...}). No theme + * recompile needed - the .res ships with the variable bindings baked + * in. See PaletteOverrideThemeScreenshotTest for a worked example. + * Variable names mirror the M3 token names: --accent maps to "primary", + * --accent-on to "on-primary", --accent-container to + * "primary-container", --accent-on-container to "on-primary-container", + * --accent-pressed to "state-pressed". Keep light/dark variants in + * sync (-dark suffix) so an app override affecting only the light + * constant doesn't desynchronise dark mode. */ #Constants { + /* Material 3 primary accent palette overridable at runtime via + addThemeProps. Each var(--name, fallback) embeds the fallback as + the baked-in default and emits a @cn1-bind constant the runtime + UIManager consults when an @ override is supplied. */ + --accent-color: #6750a4; + --accent-color-dark: #d0bcff; + --accent-on-color: #ffffff; + --accent-on-color-dark: #381e72; + --accent-container-color: #eaddff; + --accent-container-color-dark: #4f378b; + --accent-on-container-color: #21005d; + --accent-on-container-color-dark: #eaddff; + --accent-pressed-color: #d0bcff; + --accent-pressed-color-dark: #4f378b; + includeNativeBool: false; darkModeBool: true; commandBehavior: Native; @@ -120,8 +143,8 @@ SpanLabelText { cn1-derive: Label; background-color: transparent; } only honours base-level cn1-derive), so explicit values are the reliable fix. */ Button { - color: #ffffff; - background-color: #6750a4; + color: var(--accent-on-color, #ffffff); + background-color: var(--accent-color, #6750a4); padding: 1.5mm 4mm 1.5mm 4mm; margin: 0.8mm; font-family: "native:MainRegular"; @@ -130,8 +153,8 @@ Button { text-align: center; } Button.pressed { - color: #21005d; - background-color: #d0bcff; + color: var(--accent-on-container-color, #21005d); + background-color: var(--accent-pressed-color, #d0bcff); padding: 1.5mm 4mm 1.5mm 4mm; margin: 0.8mm; font-family: "native:MainRegular"; @@ -155,8 +178,8 @@ Button.disabled { dark mode where Button's own container color otherwise matches. */ RaisedButton { cn1-derive: Button; - color: #21005d; - background-color: #eaddff; + color: var(--accent-on-container-color, #21005d); + background-color: var(--accent-container-color, #eaddff); padding: 1.5mm 4mm 1.5mm 4mm; margin: 0.8mm; font-family: "native:MainRegular"; @@ -165,8 +188,8 @@ RaisedButton { text-align: center; } RaisedButton.pressed { - color: #21005d; - background-color: #d0bcff; + color: var(--accent-on-container-color, #21005d); + background-color: var(--accent-pressed-color, #d0bcff); padding: 1.5mm 4mm 1.5mm 4mm; margin: 0.8mm; font-family: "native:MainRegular"; @@ -188,11 +211,11 @@ RaisedButton.disabled { FlatButton { cn1-derive: Button; background-color: transparent; - color: #6750a4; + color: var(--accent-color, #6750a4); cn1-background-type: cn1-pill-border; text-align: center; } -FlatButton.pressed { background-color: #eaddff; color: #21005d; cn1-background-type: cn1-pill-border; } +FlatButton.pressed { background-color: var(--accent-container-color, #eaddff); color: var(--accent-on-container-color, #21005d); cn1-background-type: cn1-pill-border; } TextField { color: #1d1b20; @@ -233,7 +256,7 @@ CheckBox { font-size: 3.5mm; icon-gap: 2mm; } -CheckBox.selected { color: #6750a4; } +CheckBox.selected { color: var(--accent-color, #6750a4); } CheckBox.disabled { color: #a5a0ab; background-color: #e0dce4; } RadioButton { @@ -245,7 +268,7 @@ RadioButton { font-size: 3.5mm; icon-gap: 2mm; } -RadioButton.selected { color: #6750a4; } +RadioButton.selected { color: var(--accent-color, #6750a4); } RadioButton.disabled { color: #a5a0ab; background-color: #e0dce4; } /* Switch's track left-edge aligns with Label's text left-edge @@ -257,17 +280,17 @@ Switch { margin: 1mm 1.5mm 1mm 1.5mm; text-align: left; } -Switch.selected { color: #ffffff; background-color: #6750a4; } +Switch.selected { color: var(--accent-on-color, #ffffff); background-color: var(--accent-color, #6750a4); } Switch.disabled { color: #a5a0ab; background-color: #e0dce4; } OnOffSwitch { cn1-derive: Label; - color: #ffffff; + color: var(--accent-on-color, #ffffff); background-color: #e7e0ec; padding: 1mm 2mm 1mm 2mm; cn1-background-type: cn1-pill-border; } -OnOffSwitch.selected { background-color: #6750a4; color: #ffffff; } +OnOffSwitch.selected { background-color: var(--accent-color, #6750a4); color: var(--accent-on-color, #ffffff); } Toolbar { background-color: #fef7ff; @@ -294,8 +317,8 @@ Title { } MainTitle { cn1-derive: Title; } -BackCommand { cn1-derive: Button; background-color: transparent; color: #6750a4; padding: 1mm 2mm 1mm 2mm; } -TitleCommand { cn1-derive: Button; background-color: transparent; color: #6750a4; padding: 1mm 2mm 1mm 2mm; } +BackCommand { cn1-derive: Button; background-color: transparent; color: var(--accent-color, #6750a4); padding: 1mm 2mm 1mm 2mm; } +TitleCommand { cn1-derive: Button; background-color: transparent; color: var(--accent-color, #6750a4); padding: 1mm 2mm 1mm 2mm; } /* Material 3 top tabs: flat surface with selected tab underlined by color rather than a pill fill. No border-radius here - @@ -313,10 +336,10 @@ Tab { font-size: 3.5mm; text-align: center; } -Tab.selected { color: #6750a4; background-color: #fef7ff; } -Tab.pressed { color: #21005d; background-color: #eaddff; } +Tab.selected { color: var(--accent-color, #6750a4); background-color: #fef7ff; } +Tab.pressed { color: var(--accent-on-container-color, #21005d); background-color: var(--accent-container-color, #eaddff); } -SelectedTab { cn1-derive: Tab; color: #6750a4; } +SelectedTab { cn1-derive: Tab; color: var(--accent-color, #6750a4); } UnselectedTab { cn1-derive: Tab; color: #49454f; } SideNavigationPanel { background-color: #fef7ff; padding: 0; margin: 0; } @@ -328,7 +351,7 @@ SideCommand { padding: 2mm 3mm 2mm 3mm; margin: 0; } -SideCommand.pressed { background-color: #eaddff; } +SideCommand.pressed { background-color: var(--accent-container-color, #eaddff); } List { background-color: #fef7ff; padding: 0; margin: 0; } @@ -348,7 +371,7 @@ MultiButton { font-family: "native:MainRegular"; font-size: 3.5mm; } -MultiButton.pressed { background-color: #eaddff; } +MultiButton.pressed { background-color: var(--accent-container-color, #eaddff); } MultiButton.disabled { color: #a5a0ab; background-color: #e0dce4; } MultiLine1 { cn1-derive: Label; color: #1d1b20; font-family: "native:MainBold"; } @@ -389,14 +412,14 @@ DialogContentPane { background-color: transparent; padding: 2mm; margin: 0; } DialogCommandArea { background-color: transparent; padding: 1mm; } FloatingActionButton { - color: #21005d; - background-color: #eaddff; + color: var(--accent-on-container-color, #21005d); + background-color: var(--accent-container-color, #eaddff); padding: 3mm; margin: 3mm; font-family: "native:MainBold"; cn1-background-type: cn1-pill-border; } -FloatingActionButton.pressed { background-color: #d0bcff; } +FloatingActionButton.pressed { background-color: var(--accent-pressed-color, #d0bcff); } Separator { background-color: #cac4d0; padding: 0; margin: 0; } PopupContent { @@ -421,16 +444,16 @@ PopupContent { /* Re-declare cn1-background-type on each dark Button override - the compiler doesn't carry the light declaration's pill border forward into the $Dark entries. */ - Button { color: #381e72; background-color: #d0bcff; cn1-background-type: cn1-pill-border; } - Button.pressed { background-color: #4f378b; color: #eaddff; cn1-background-type: cn1-pill-border; } + Button { color: var(--accent-on-color-dark, #381e72); background-color: var(--accent-color-dark, #d0bcff); cn1-background-type: cn1-pill-border; } + Button.pressed { background-color: var(--accent-pressed-color-dark, #4f378b); color: var(--accent-on-container-color-dark, #eaddff); cn1-background-type: cn1-pill-border; } Button.disabled { color: #5c5967; background-color: #2b2930; cn1-background-type: cn1-pill-border; } - RaisedButton { color: #eaddff; background-color: #4f378b; cn1-background-type: cn1-pill-border; } - RaisedButton.pressed { color: #eaddff; background-color: #6750a4; cn1-background-type: cn1-pill-border; } + RaisedButton { color: var(--accent-on-container-color-dark, #eaddff); background-color: var(--accent-container-color-dark, #4f378b); cn1-background-type: cn1-pill-border; } + RaisedButton.pressed { color: var(--accent-on-container-color-dark, #eaddff); background-color: var(--accent-color, #6750a4); cn1-background-type: cn1-pill-border; } RaisedButton.disabled { background-color: #2b2930; color: #5c5967; cn1-background-type: cn1-pill-border; } - FlatButton { color: #d0bcff; background-color: transparent; cn1-background-type: cn1-pill-border; } - FlatButton.pressed { background-color: #4f378b; color: #eaddff; cn1-background-type: cn1-pill-border; } + FlatButton { color: var(--accent-color-dark, #d0bcff); background-color: transparent; cn1-background-type: cn1-pill-border; } + FlatButton.pressed { background-color: var(--accent-container-color-dark, #4f378b); color: var(--accent-on-container-color-dark, #eaddff); cn1-background-type: cn1-pill-border; } TextField { color: #e6e0e9; background-color: #211f26; } TextField.pressed { background-color: #49454f; } @@ -441,42 +464,42 @@ PopupContent { TextHint { color: #938f99; } CheckBox { color: #e6e0e9; background-color: transparent; } - CheckBox.selected { color: #d0bcff; } + CheckBox.selected { color: var(--accent-color-dark, #d0bcff); } CheckBox.disabled { color: #5c5967; background-color: #2b2930; } RadioButton { color: #e6e0e9; background-color: transparent; } - RadioButton.selected { color: #d0bcff; } + RadioButton.selected { color: var(--accent-color-dark, #d0bcff); } RadioButton.disabled { color: #5c5967; background-color: #2b2930; } Switch { color: #938f99; background-color: #49454f; } - Switch.selected { color: #381e72; background-color: #d0bcff; } + Switch.selected { color: var(--accent-on-color-dark, #381e72); background-color: var(--accent-color-dark, #d0bcff); } Switch.disabled { color: #5c5967; background-color: #2b2930; } - OnOffSwitch { color: #381e72; background-color: #49454f; } - OnOffSwitch.selected { background-color: #d0bcff; color: #381e72; } + OnOffSwitch { color: var(--accent-on-color-dark, #381e72); background-color: #49454f; } + OnOffSwitch.selected { background-color: var(--accent-color-dark, #d0bcff); color: var(--accent-on-color-dark, #381e72); } Toolbar { background-color: #141218; color: #e6e0e9; } TitleArea { background-color: #141218; color: #e6e0e9; } Title { color: #e6e0e9; background-color: #141218; } MainTitle { color: #e6e0e9; background-color: #141218; } - BackCommand { color: #d0bcff; background-color: transparent; } - TitleCommand { color: #d0bcff; background-color: transparent; } + BackCommand { color: var(--accent-color-dark, #d0bcff); background-color: transparent; } + TitleCommand { color: var(--accent-color-dark, #d0bcff); background-color: transparent; } Tabs { background-color: #141218; } TabsContainer { background-color: #141218; color: #e6e0e9; } Tab { color: #cac4d0; background-color: #141218; } - Tab.selected { color: #d0bcff; background-color: #141218; } - Tab.pressed { color: #eaddff; background-color: #4f378b; } - SelectedTab { color: #d0bcff; } + Tab.selected { color: var(--accent-color-dark, #d0bcff); background-color: #141218; } + Tab.pressed { color: var(--accent-on-container-color-dark, #eaddff); background-color: var(--accent-pressed-color-dark, #4f378b); } + SelectedTab { color: var(--accent-color-dark, #d0bcff); } UnselectedTab { color: #cac4d0; } SideNavigationPanel { background-color: #141218; } SideCommand { color: #e6e0e9; background-color: transparent; } - SideCommand.pressed { background-color: #4f378b; } + SideCommand.pressed { background-color: var(--accent-pressed-color-dark, #4f378b); } List { background-color: #141218; } ListRenderer { color: #e6e0e9; background-color: transparent; } MultiButton { background-color: #141218; color: #e6e0e9; } - MultiButton.pressed { background-color: #4f378b; } + MultiButton.pressed { background-color: var(--accent-pressed-color-dark, #4f378b); } MultiLine1 { color: #e6e0e9; } MultiLine2 { color: #cac4d0; } MultiLine3 { color: #938f99; } @@ -489,8 +512,8 @@ PopupContent { DialogCommandArea { background-color: #211f26; } PopupContent { background-color: #211f26; color: #e6e0e9; } - FloatingActionButton { color: #eaddff; background-color: #4f378b; } - FloatingActionButton.pressed { background-color: #d0bcff; } + FloatingActionButton { color: var(--accent-on-container-color-dark, #eaddff); background-color: var(--accent-container-color-dark, #4f378b); } + FloatingActionButton.pressed { background-color: var(--accent-color-dark, #d0bcff); } Separator { background-color: #49454f; } } diff --git a/native-themes/ios-modern/theme.css b/native-themes/ios-modern/theme.css index d1e1d3de13..b53a55ea06 100644 --- a/native-themes/ios-modern/theme.css +++ b/native-themes/ios-modern/theme.css @@ -5,8 +5,7 @@ * rounded/pill borders, state selectors via .pressed / .selected / * .disabled. Light and dark palettes live at the bottom of this file * in a prefers-color-scheme block the compiler rewrites into $DarkUIID - * entries. Colors are inlined (not CSS variables) because the rewriter - * operates at string level and doesn't re-scope :root declarations. + * entries. * * Apple system palette reference (light / dark): * accent 007aff / 0a84ff @@ -22,13 +21,32 @@ * separator c6c6c8 / 38383a * success 34c759 / 30d158 * - * Overridable palette: user apps layer their own theme.css or runtime - * UIManager.addThemeProps on top of this theme - see - * PaletteOverrideThemeScreenshotTest for a working example that flips - * the accent to magenta at runtime. + * Accent palette: every var(--accent-...) reference below resolves to + * the inlined fallback at compile time AND emits a runtime binding so + * the same color can be retuned at app launch via + * UIManager.addThemeProps({"@accent-color": "ff2d95", ...}). No theme + * recompile needed - the .res ships with the variable bindings baked + * in. See PaletteOverrideThemeScreenshotTest for a worked example. + * Keep light/dark variants in sync (-dark suffix) so an app override + * affecting only the light constant doesn't desynchronise dark mode. */ #Constants { + /* Accent palette overridable at runtime via addThemeProps. The + light values feed the default rules; the -dark counterparts feed + the corresponding $Dark entries the dark @media block + compiles into. var(--name, fallback) embeds the fallback as the + baked-in default and emits a @cn1-bind:.= + constant the runtime UIManager consults when an @ + override is supplied. */ + --accent-color: #007aff; + --accent-color-dark: #0a84ff; + --accent-pressed-color: #0064d1; + --accent-pressed-color-dark: #64b1ff; + --accent-disabled-color: #b3d4ff; + --accent-disabled-color-dark: #004a99; + --accent-on-color: #ffffff; + includeNativeBool: false; darkModeBool: true; commandBehavior: Native; @@ -134,7 +152,7 @@ SpanLabelText { cn1-derive: Label; background-color: transparent; } degenerate to a circle when width<=height - RoundBorder paints a circle in that case, border-radius always keeps the corner radius. */ Button { - color: #007aff; + color: var(--accent-color, #007aff); padding: 2mm 4mm 2mm 4mm; margin: 1mm; font-family: "native:MainRegular"; @@ -142,18 +160,18 @@ Button { border-radius: 3mm; text-align: center; } -Button.pressed { color: #0064d1; background-color: #e5e5ea; } -Button.disabled { color: #b3d4ff; } +Button.pressed { color: var(--accent-pressed-color, #0064d1); background-color: #e5e5ea; } +Button.disabled { color: var(--accent-disabled-color, #b3d4ff); } RaisedButton { cn1-derive: Button; - color: #ffffff; - background-color: #007aff; + color: var(--accent-on-color, #ffffff); + background-color: var(--accent-color, #007aff); border-radius: 3mm; text-align: center; } -RaisedButton.pressed { color: #ffffff; background-color: #0064d1; } -RaisedButton.disabled { background-color: #b3d4ff; color: #ffffff; } +RaisedButton.pressed { color: var(--accent-on-color, #ffffff); background-color: var(--accent-pressed-color, #0064d1); } +RaisedButton.disabled { background-color: var(--accent-disabled-color, #b3d4ff); color: var(--accent-on-color, #ffffff); } FlatButton { cn1-derive: Button; } @@ -193,7 +211,7 @@ CheckBox { font-family: "native:MainRegular"; icon-gap: 2mm; } -CheckBox.selected { color: #007aff; } +CheckBox.selected { color: var(--accent-color, #007aff); } CheckBox.disabled { color: #c7c7cc; background-color: #e5e5ea; } RadioButton { @@ -204,7 +222,7 @@ RadioButton { font-family: "native:MainRegular"; icon-gap: 2mm; } -RadioButton.selected { color: #007aff; } +RadioButton.selected { color: var(--accent-color, #007aff); } RadioButton.disabled { color: #c7c7cc; background-color: #e5e5ea; } /* Switch's track-left needs to land at the same x as the Label @@ -224,7 +242,7 @@ Switch.disabled { color: #c7c7cc; background-color: #e5e5ea; } OnOffSwitch { cn1-derive: Label; - color: #007aff; + color: var(--accent-color, #007aff); background-color: #e5e5ea; padding: 1mm 2mm 1mm 2mm; cn1-background-type: cn1-pill-border; @@ -254,8 +272,8 @@ Title { } MainTitle { cn1-derive: Title; } -BackCommand { cn1-derive: Button; color: #007aff; padding: 1mm 2mm 1mm 2mm; } -TitleCommand { cn1-derive: Button; color: #007aff; padding: 1mm 2mm 1mm 2mm; } +BackCommand { cn1-derive: Button; color: var(--accent-color, #007aff); padding: 1mm 2mm 1mm 2mm; } +TitleCommand { cn1-derive: Button; color: var(--accent-color, #007aff); padding: 1mm 2mm 1mm 2mm; } /* iOS 26 tab-bar look: the TabsContainer is the visible pill group hugging the bottom edge, with individual tabs rendered as @@ -406,14 +424,14 @@ DialogContentPane { background-color: transparent; padding: 2mm; margin: 0; } DialogCommandArea { background-color: transparent; padding: 1mm; } FloatingActionButton { - color: #ffffff; - background-color: #007aff; + color: var(--accent-on-color, #ffffff); + background-color: var(--accent-color, #007aff); padding: 3mm; margin: 3mm; font-family: "native:MainBold"; cn1-background-type: cn1-pill-border; } -FloatingActionButton.pressed { background-color: #0064d1; } +FloatingActionButton.pressed { background-color: var(--accent-pressed-color, #0064d1); } Separator { background-color: #c6c6c8; padding: 0; margin: 0; } PopupContent { @@ -435,13 +453,13 @@ PopupContent { SpanLabel { color: #ffffff; background-color: transparent; } SpanLabelText { color: #ffffff; background-color: transparent; } - Button { color: #0a84ff; } - Button.pressed { color: #64b1ff; background-color: #3a3a3c; } - Button.disabled { color: #004a99; } + Button { color: var(--accent-color-dark, #0a84ff); } + Button.pressed { color: var(--accent-pressed-color-dark, #64b1ff); background-color: #3a3a3c; } + Button.disabled { color: var(--accent-disabled-color-dark, #004a99); } - RaisedButton { color: #ffffff; background-color: #0a84ff; } - RaisedButton.pressed { background-color: #64b1ff; } - RaisedButton.disabled { background-color: #004a99; } + RaisedButton { color: var(--accent-on-color, #ffffff); background-color: var(--accent-color-dark, #0a84ff); } + RaisedButton.pressed { background-color: var(--accent-pressed-color-dark, #64b1ff); } + RaisedButton.disabled { background-color: var(--accent-disabled-color-dark, #004a99); } TextField { color: #ffffff; background-color: #1c1c1e; } TextField.pressed { background-color: #2c2c2e; } @@ -452,25 +470,25 @@ PopupContent { TextHint { color: #8e8e93; } CheckBox { color: #ffffff; background-color: transparent; } - CheckBox.selected { color: #0a84ff; } + CheckBox.selected { color: var(--accent-color-dark, #0a84ff); } CheckBox.disabled { color: #48484a; background-color: #2c2c2e; } RadioButton { color: #ffffff; background-color: transparent; } - RadioButton.selected { color: #0a84ff; } + RadioButton.selected { color: var(--accent-color-dark, #0a84ff); } RadioButton.disabled { color: #48484a; background-color: #2c2c2e; } Switch { color: #ffffff; background-color: #2c2c2e; } Switch.selected { color: #ffffff; background-color: #30d158; } Switch.disabled { color: #48484a; background-color: #2c2c2e; } - OnOffSwitch { color: #0a84ff; background-color: #2c2c2e; } + OnOffSwitch { color: var(--accent-color-dark, #0a84ff); background-color: #2c2c2e; } OnOffSwitch.selected { background-color: #30d158; color: #ffffff; } Toolbar { background-color: #000000; color: #ffffff; } TitleArea { background-color: #000000; color: #ffffff; } Title { color: #ffffff; background-color: #000000; } MainTitle { color: #ffffff; background-color: #000000; } - BackCommand { color: #0a84ff; } - TitleCommand { color: #0a84ff; } + BackCommand { color: var(--accent-color-dark, #0a84ff); } + TitleCommand { color: var(--accent-color-dark, #0a84ff); } Tabs { background-color: transparent; } TabbedPane { background-color: #1c1c1e; } @@ -517,8 +535,8 @@ PopupContent { DialogCommandArea { background-color: transparent; } PopupContent { background-color: rgba(44,44,46,0.95); color: #ffffff; } - FloatingActionButton { color: #ffffff; background-color: #0a84ff; } - FloatingActionButton.pressed { background-color: #64b1ff; } + FloatingActionButton { color: var(--accent-on-color, #ffffff); background-color: var(--accent-color-dark, #0a84ff); } + FloatingActionButton.pressed { background-color: var(--accent-pressed-color-dark, #64b1ff); } Separator { background-color: #38383a; } } diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java index af0555a085..d707a01b28 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java @@ -13,23 +13,23 @@ * Verifies that a sub-theme can re-skin the native palette without * touching the native theme's CSS source. * - * The native CSS declares a palette (--cn1-accent, --cn1-primary etc.) - * that's inlined into each UIID at compile time. At runtime a user app - * overrides specific colors by layering an additional {@link Hashtable} - * of theme props on top of the installed native theme via - * {@link UIManager#addThemeProps}. This test installs a magenta - * override - vivid enough that a visual diff against the native - * baseline is unmistakable - and verifies both the light and dark - * captures pick it up. + * The native CSS declares an accent palette via `var(--accent-color, + * fallback)` references. The compiler bakes the fallback into each + * UIID at compile time AND emits `@cn1-bind:<UIID>.<key>=accent-color` + * constants alongside, so the .res ships with every accent-bearing + * UIID quietly tracking the underlying palette variable. At app + * launch the user calls + * {@link UIManager#addThemeProps(Hashtable)} with a single + * `@accent-color`-style constant per palette role and the runtime + * binding pass overlays the override onto every bound UIID at once - + * no per-UIID rule duplication, no theme recompile. * - * The override is installed once when the suite reaches this test; the - * light capture exercises it with the light base styles, the dark - * capture exercises it with the base styles picking up the - * {@code $Dark} variants merged under the same override layer. - * Because {@link Style#setBgColor} on an override key blows away the - * {@code $Dark} variant for that specific key, the dark capture also - * ends up showing the override color - proving the override reaches - * every appearance. + * This test installs a magenta override - vivid enough that a visual + * diff against the native baseline is unmistakable - and verifies both + * the light and dark captures pick it up. The light capture exercises + * the light base styles; the dark capture exercises the + * {@code $Dark} variants which are bound to the matching + * `-dark` palette variables. */ public class PaletteOverrideThemeScreenshotTest extends DualAppearanceBaseTest { @@ -77,30 +77,36 @@ protected void populate(Form form, String suffix) { /** * Adds a palette-override layer on top of the installed native - * theme. Uses {@link UIManager#addThemeProps} so the native theme - * stays resident underneath - the override table only has to - * redeclare the handful of keys it wants to change, plus the - * matching {@code $Dark} keys so the override applies in dark - * mode too. + * theme by declaring `@`-prefixed accent constants. The runtime + * binding pass in {@link UIManager} fans each constant out to every + * bound UIID/state/dark variant, so this short Hashtable replaces + * the 12+ explicit per-UIID keys the override used to require. + * + * Both Android and iOS native themes share the same variable + * vocabulary (see native-themes/<family>/theme.css `#Constants`). + * The Android theme additionally exposes M3-flavoured container + * tokens (`accent-container-color`, `accent-on-container-color`) + * which we override too so RaisedButton-style "tonal" surfaces also + * pick up the magenta - leaving them at the default would let + * Android-only RaisedButton.bgColor remain at the M3 baseline tone + * even though Button.fgColor and the matching iOS RaisedButton + * already shifted. */ private void installPaletteOverride() { Hashtable override = new Hashtable(); - override.put("RaisedButton.bgColor", OVERRIDE_ACCENT); - override.put("RaisedButton.fgColor", OVERRIDE_ACCENT_TEXT); - override.put("RaisedButton.press#bgColor", OVERRIDE_ACCENT_PRESSED); - override.put("RaisedButton.press#fgColor", OVERRIDE_ACCENT_TEXT); - override.put("Button.fgColor", OVERRIDE_ACCENT); - override.put("Button.press#fgColor", OVERRIDE_ACCENT_PRESSED); - // Dark override mirrors the light override so the magenta - // applies across both appearances. A real user theme would - // probably choose two variants; this test keeps them identical - // for easy visual confirmation. - override.put("$DarkRaisedButton.bgColor", OVERRIDE_ACCENT); - override.put("$DarkRaisedButton.fgColor", OVERRIDE_ACCENT_TEXT); - override.put("$DarkRaisedButton.press#bgColor", OVERRIDE_ACCENT_PRESSED); - override.put("$DarkRaisedButton.press#fgColor", OVERRIDE_ACCENT_TEXT); - override.put("$DarkButton.fgColor", OVERRIDE_ACCENT); - override.put("$DarkButton.press#fgColor", OVERRIDE_ACCENT_PRESSED); + override.put("@accent-color", OVERRIDE_ACCENT); + override.put("@accent-color-dark", OVERRIDE_ACCENT); + override.put("@accent-pressed-color", OVERRIDE_ACCENT_PRESSED); + override.put("@accent-pressed-color-dark", OVERRIDE_ACCENT_PRESSED); + override.put("@accent-on-color", OVERRIDE_ACCENT_TEXT); + override.put("@accent-on-color-dark", OVERRIDE_ACCENT_TEXT); + // Material 3 RaisedButton uses the "container" tonal pair; iOS + // ignores these vars (no bindings reference them) so it's safe + // to set them unconditionally for both platforms. + override.put("@accent-container-color", OVERRIDE_ACCENT); + override.put("@accent-container-color-dark", OVERRIDE_ACCENT); + override.put("@accent-on-container-color", OVERRIDE_ACCENT_TEXT); + override.put("@accent-on-container-color-dark", OVERRIDE_ACCENT_TEXT); UIManager.getInstance().addThemeProps(override); } } From 21e7eb98a77fa108208489a3228de6f0b35a4a3f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 8 May 2026 07:30:06 +0300 Subject: [PATCH 02/11] PaletteOverride: also retune @accent-disabled-color so iOS visibly diffs The old per-UIID override and the new @accent-color override happen to map to the same set of visible widgets on the iOS Modern capture form (Button.fgColor, RaisedButton.bg/fg) - both produce the same magenta there, so the iOS pipeline shows zero unmatched screenshots which masks whether the new binding mechanism actually fires on iOS. Add a vivid teal override on @accent-disabled-color (iOS-only - the M3 theme hard-codes its disabled colours and has no binding for this slot) so the disabled RaisedButton on the form switches from the default iOS accent-disabled blue to teal. iOS captures now diverge from the pre-binding baseline, confirming the runtime binding pass fires on iOS too. Android's diff is already covered by the magenta @accent-container-color retuning RaisedButton's tonal fill. Add a sanity log at install time that surfaces any leak from a previous test in the suite (a stale @accent-color constant). The test runs near the tail of Cn1ssDeviceRunner and finish() reloads /theme via initFirstTheme which clears themeConstants - so the expected pre-state is "no leak". The log is the cheap signal we need if a future framework regression ever drops that cleanup. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../PaletteOverrideThemeScreenshotTest.java | 74 +++++++++++++++++-- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java index d707a01b28..bad6e6b15e 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java @@ -24,18 +24,48 @@ * binding pass overlays the override onto every bound UIID at once - * no per-UIID rule duplication, no theme recompile. * - * This test installs a magenta override - vivid enough that a visual - * diff against the native baseline is unmistakable - and verifies both - * the light and dark captures pick it up. The light capture exercises - * the light base styles; the dark capture exercises the - * {@code $Dark} variants which are bound to the matching - * `-dark` palette variables. + * This test installs a magenta override on the primary accent and a + * vivid teal on the disabled accent. The teal is the load-bearing + * choice for cross-platform coverage: on iOS Modern the only visible + * widgets that rebind when accent-color changes are RaisedButton + + * Button (which the magenta already exercises), but the disabled + * RaisedButton stays at the default light-blue accent-disabled tone + * unless `@accent-disabled-color` is also retuned. Adding the teal + * therefore produces a visible iOS pixel diff against a baseline that + * predates the binding mechanism, confirming the binding fires on iOS + * and isn't merely a no-op coincidence with the magenta. Android + * Material 3 doesn't bind its disabled state to accent-disabled (its + * disabled colours are hard-coded in CSS), so the teal is iOS-only; + * Android's diff is driven by the magenta `@accent-container-color` + * retuning RaisedButton's tonal fill. + * + * The light capture exercises the light base styles; the dark capture + * exercises the {@code $Dark} variants which are bound to the + * matching `-dark` palette variables. + * + * Suite hygiene: this test installs the `@`-prefixed override + * constants once during the light populate(). DualAppearanceBaseTest's + * `finish()` runs after the dark capture and reloads `/theme` via + * {@link UIManager#initFirstTheme}, which routes through + * `setThemePropsImpl` and clears `themeConstants` before re-populating + * from the freshly-loaded theme - so the `@accent-color` (etc.) + * constants do NOT survive into the next test in the suite. The + * test's slot in `Cn1ssDeviceRunner` (after the theme-fidelity + * sub-suite, before OrientationLock) keeps it on the back end of the + * run regardless, so any future regression that drops + * `initFirstTheme` would still only affect tests that explicitly opt + * in to this run's tail. */ public class PaletteOverrideThemeScreenshotTest extends DualAppearanceBaseTest { private static final String OVERRIDE_ACCENT = "ff2d95"; private static final String OVERRIDE_ACCENT_PRESSED = "c71a75"; private static final String OVERRIDE_ACCENT_TEXT = "ffffff"; + /// Vivid teal for the disabled accent slot. Distinct from the iOS + /// Modern light/dark blue defaults (#b3d4ff / #004a99) and from the + /// magenta accent so the disabled RaisedButton on the form reads + /// as a third independent colour at a glance. + private static final String OVERRIDE_ACCENT_DISABLED = "00b894"; private boolean overrideInstalled; @Override @@ -93,6 +123,23 @@ protected void populate(Form form, String suffix) { * already shifted. */ private void installPaletteOverride() { + // Sanity check: log if a previous test in the suite leaked an + // accent constant into themeConstants. The test class that + // runs immediately before us (DarkLightShowcaseThemeScreenshot + // Test) does not touch the accent vocabulary, and the + // theme-fidelity tests that precede it install the modern + // theme via DualAppearanceBaseTest.installModernThemeIfRequest + // ed which routes through setThemeProps -> setThemePropsImpl + // -> themeConstants.clear(). So the expected pre-state here + // is "no @accent-color set". Any leaked value surfaces as a + // CN1SS:WARN line in the run log, making post-mortem + // investigation of suite-state cross-talk much cheaper. + String stale = UIManager.getInstance().getThemeConstant("accent-color", null); + if (stale != null) { + System.out.println("CN1SS:WARN:test=PaletteOverrideThemeScreenshotTest " + + "stale-accent-color=" + stale + + " (a previous test left an @accent-color constant in UIManager state)"); + } Hashtable override = new Hashtable(); override.put("@accent-color", OVERRIDE_ACCENT); override.put("@accent-color-dark", OVERRIDE_ACCENT); @@ -100,6 +147,21 @@ private void installPaletteOverride() { override.put("@accent-pressed-color-dark", OVERRIDE_ACCENT_PRESSED); override.put("@accent-on-color", OVERRIDE_ACCENT_TEXT); override.put("@accent-on-color-dark", OVERRIDE_ACCENT_TEXT); + // iOS-only: retunes the disabled RaisedButton's bg and the + // disabled Button.fgColor away from the platform accent- + // disabled blue. Without this slot, iOS captures resolve to + // byte-identical pixels as the pre-binding baseline (every + // visible widget on the form happens to bind to accent-color + // / accent-on-color, both of which still produce the same + // magenta the old per-UIID override forced). Including a + // unique colour here makes the iOS diff vs baseline + // unambiguous and proves the runtime binding fires on iOS too. + // Android Material 3 leaves disabled-state colours hard-coded + // in CSS, so this constant has no Android effect (and that's + // fine - Android's accent-container-color override below + // produces its own visible diff there). + override.put("@accent-disabled-color", OVERRIDE_ACCENT_DISABLED); + override.put("@accent-disabled-color-dark", OVERRIDE_ACCENT_DISABLED); // Material 3 RaisedButton uses the "container" tonal pair; iOS // ignores these vars (no bindings reference them) so it's safe // to set them unconditionally for both platforms. From 81e45271d1e3711c3f97ecf92840a7296597fa2f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 8 May 2026 08:54:20 +0300 Subject: [PATCH 03/11] RoundBorder cn1-pill-border: respect Style.bgColor when bound to a var() Android Material 3's RaisedButton (and other UIIDs using cn1-pill-border) wraps its fill in a RoundBorder whose color the CSS compiler bakes in at compile time. By default RoundBorder paints from that baked field via fillShape() with uiid=false, ignoring Style.bgColor at render time. The runtime binding pass updates themeProps[.bgColor] correctly when the user pushes an @accent-color override, but the visible pill stays at the compile-time fallback because the border, not the Style, owns the visible color. When the source background-color came from a var() expansion (i.e. the binding mechanism wants this fill to be runtime-tunable), flip the RoundBorder into uiid mode so it routes through Style.getBgPainter() at paint time. Style.bgColor then drives the fill, and a runtime @accent-* override propagates all the way to the visible pixels. Legacy themes whose backgrounds are inlined hex (no var()) keep the existing baked-color path, so this is a no-op for everything that isn't already opted into the binding mechanism. Update iOS PaletteOverrideTheme_light/dark goldens (both GL and Metal) to the captures produced by the previously-pushed override-color expansion - iOS uses border-radius (RoundRectBorder) which already respects Style.bgColor, so its captures only changed because we added @accent-disabled-color to the override and the disabled RaisedButton on the form is now teal instead of accent-disabled blue. Android goldens will need a fresh CI run with this fix to capture the now-correct magenta RaisedButton; deferring those. NativeThemeBindingsTest: extended to cover the AndroidMaterialTheme .res so the binding round-trip is exercised on both shipped native-theme palettes. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ui/plaf/NativeThemeBindingsTest.java | 40 ++++++++++++++++++ .../com/codename1/designer/css/CSSTheme.java | 15 +++++++ .../PaletteOverrideTheme_dark.png | Bin 118533 -> 118384 bytes .../PaletteOverrideTheme_light.png | Bin 116843 -> 117670 bytes .../screenshots/PaletteOverrideTheme_dark.png | Bin 89477 -> 89438 bytes .../PaletteOverrideTheme_light.png | Bin 89980 -> 90575 bytes 6 files changed, 55 insertions(+) diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java index b686753ede..f7150981bd 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java @@ -71,6 +71,46 @@ public void iosModernThemeBindingRetunesButton() throws Exception { "@accent-color override should retune every UIID bound to --accent-color"); } + @Test + public void androidMaterialThemeBindingRetunesButton() throws Exception { + File themeFile = locateNativeTheme("AndroidMaterialTheme.res"); + if (themeFile == null) { + return; + } + Resources res; + InputStream stream = new FileInputStream(themeFile); + try { + res = Resources.open(stream); + } finally { + stream.close(); + } + String[] themeNames = res.getThemeResourceNames(); + assertNotNull(themeNames); + Hashtable theme = res.getTheme(themeNames[0]); + assertNotNull(theme); + + // M3 baseline primary is #6750a4 → "6750a4" when stored via + // Integer.toHexString. + assertEquals("6750a4", theme.get("Button.bgColor")); + assertEquals("accent-color", theme.get("@cn1-bind:Button.bgColor")); + + UIManager.getInstance().setThemeProps(theme); + + Button defaultBtn = new Button("default"); + defaultBtn.setUIID("Button"); + assertEquals(0x6750a4, defaultBtn.getUnselectedStyle().getBgColor(), + "Android M3 button bg should pick up the inlined fallback when no override is supplied"); + + Hashtable override = new Hashtable(); + override.put("@accent-color", "ff2d95"); + UIManager.getInstance().addThemeProps(override); + + Button retuned = new Button("magenta"); + retuned.setUIID("Button"); + assertEquals(0xff2d95, retuned.getUnselectedStyle().getBgColor(), + "@accent-color override should retune Button.bgColor on the Android Material 3 theme"); + } + /// Searches a few well-known relative locations for a freshly-built /// native theme `.res`. We surfboard up a few directory levels /// because the surefire `user.dir` lands inside the unittests diff --git a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java index e77f3f05ea..88e9e2d626 100644 --- a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java +++ b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java @@ -5004,6 +5004,21 @@ private com.codename1.ui.plaf.Border createRoundBorder(Map s } else { out.opacity(255); } + // When the source background-color came from a var() + // expansion, flip the RoundBorder into "uiid mode" so it + // paints via the Style's bgPainter (i.e. Style.bgColor) + // at render time instead of the static color baked into + // the border at compile time. Without this, a runtime + // `@accent-color` override updates themeProps[bgColor] + // correctly but the visible pill stays at the compile- + // time fallback because RoundBorder.fillShape uses its + // own field. Only flip when the binding is present so + // legacy themes that rely on the baked-color path keep + // their existing rendering. + if (backgroundColor instanceof ScaledUnit + && ((ScaledUnit) backgroundColor).bindingVarName != null) { + out.uiid(true); + } } else { out.opacity(0); } diff --git a/scripts/ios/screenshots-metal/PaletteOverrideTheme_dark.png b/scripts/ios/screenshots-metal/PaletteOverrideTheme_dark.png index da9a335b1b80175e6608ddb370ccc6550104c2f7..d552b1933c88f82ab30d4dc3163031cbe3d47fb6 100644 GIT binary patch delta 33407 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 o6#?Pt$byBq0{5Tv`MK}xz|qjWdlR?oT5 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 D)i@hg diff --git a/scripts/ios/screenshots-metal/PaletteOverrideTheme_light.png b/scripts/ios/screenshots-metal/PaletteOverrideTheme_light.png index f4d8d85df84cb764c33c2bfd5ccde4b2de04bfe4..c8e4b87c04e4b258002324f5d6502b54b1c7ce28 100644 GIT binary patch delta 30212 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 delta 30254 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 MgJ~%>D!`-v7vBQkV*mgE diff --git a/scripts/ios/screenshots/PaletteOverrideTheme_dark.png b/scripts/ios/screenshots/PaletteOverrideTheme_dark.png index 694eb9550da49b615599f54520f872a663e0a0e3..4aa4dfe42756a8ee07c0d0933c937ece5adeda4e 100644 GIT binary patch delta 29299 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 z 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 diff --git a/scripts/ios/screenshots/PaletteOverrideTheme_light.png b/scripts/ios/screenshots/PaletteOverrideTheme_light.png index 336bf90dc58fadaf39c136534986b53c6f0ee2d7..e9b8a4ee39a8b2ba678ae7f15feeb8c510d45491 100644 GIT binary patch delta 36018 zcmeFZXIN9+)-G&A5g$YWL8XZbNJo)gf*L@j2?$6Dpr}+qAoQ|CMMRoNl@^T@0SN+z z5~|Xq8);G_ASCn>Ae0c!3X100@7~{g&bjv4*Z1T72U&BiIp>)79COSu?lH&}bZymi z&zJV@`;>dUODJ!B8V+1>=^%}`R~>bzstc&h1NQFY%+osm@x-IYJB}TOwqDs4@c6T? z<(`wz&g^NtxSub2L=c}u6ikLUj%$x2KV9kFB=sW;3$4?g+|xZgCYA@R5k7W4S=rgR ziNu#W^|C$ZxK$4c@C}xiQNAYG^EY$wOtb{g9H`f{;SFC(c5ZJ3^m&TptVJBZFyr0F zAf>SDPKv#oQ@UO;^^M&FlJ3hb!a4)*HaIHvqKk+=7ZtXvC%gl-x;ipJVhOsAY1%(WZ&)9$ES3GNaMj`lBZ$M5|Z_%A@^%< z<08{gU*}=x!s56ql-GmL3B$gvWb1VzfAb9~W{uG7?_b;EB9gCJ&uX*_3m-5|k{;^J z3M|H5@fVrzs{GDd7tp+@=(0^k_#hCP7B`GvP8=<;k% zSjOx>bV34P+=Yg+lemnnBlcHr7Sw;+$8>zXF4)T1)_7W=HLuy{X#M2y>E;QNPlmRq zph3t3*0{kmL^0&Hw;%&!uvqxmC?xVP;xTdmZ7COE41^h8B)%U66k)7kp% zU1!9HSpQ-9@`+AyuEg{l5x7!KTyJnq{N`o&6}5mJJ9iamsvr}GXU`Tm_)JuYAKL}~ zVg^{ghkC3gM-03Hc9e${B;Hh$Xfn0A4A;$Zk7`(v41c2fwaJuV5MFS;U567gxi~K%|4a@vsv6Q3S z>e&m~P2PSI^*xEYu5kzI4<;$NH=~7TH2|-1t`V7onapje%ma1mnzFNbcD#=6%=^}c z8@|sD0wOcjJ=v1jATs_LofTuHSIgp!GR1ppfn)n3EB$a~jKL^;@#1muc5p4M@^CvAiE(f()tui_@*;F^=e%d`LSyq3GEiKk{5&6bf-4h}=)q0mxQ* z!D53SAad4Iucvr-vT&Gsooaa+jtyunBDIF>uqQ6BNunyUO%yij=7pSbajmL9^oMOd zS5-a2v7@q$;DqC~b}=VI)gOQp))%>^0Y@lcQVh&x=Wq5nH{Rl8oLsxf8T5I~Op@DY zO;Af3TkC@J`2Gz`Mq_ZwE$&Gt`y+?%|_kzP|UmKD=t8t>uZ5s-98cR6Wq zuvnZfKZpni=I4a;6`y8@-gv`}(MNm1#nZQp2^PCCtQNQ0wp!#4Xvh(sm31|`C|(dd zH`vM^UaLP<;n&z0B_Sj4doh_Z8>+{V?0M~@hxRdr>AL+)#Z8IfeK255KuwLl89)j! zR$9n8k~`Zr`G@PUm5anLr?jj+)r>}t?Olz48gVECREc(hB4*~IZfDIr6-cnyjPeWa zBp6+c?0VkvP4bu@zoOsznvV~6W9g6Z`S+4lXED7lBhM;sz*9>-Z#3k;2S=_qpI;!V*bAQPP;lpV)M&u#>mOj=K`siz4QySR+7gzFIxG5 z>-KY@l)oVxgbvOwZ6PIwB+Lk5Q9r*nzYq9m9eAttRzG;&mMM}PR-o9 z>b(mHPYldEv+a{kYct2u^@|bvh7EEy$Wy@n7(R@0qyeaxs_X<#V6VWpAY8l4j~}!0 zG>mwZh;X{oHXCllRBlJEHDxC?YaGTbASf&_#kb#^>Xnz*haUM90t-tcEqJ_I#j?>z z`yU>=a`ihgax6~C zUjby3PGYFQ0|>A_uZn+E+?_TuaAPeoG2!}=1?X|nve)&xHB#=}O$Z6ffPNi2ya_p9 z_vS-q&xrV_-_wxY_KBvOhsA{slmWFnuq`S9emk>6s~;zpSqy=-eb( zZ;_>3V)1^XQT;%NKR7;wyvwI|m1VC6{YCg3Q%%fGNB~YhCsjH>0NCmmHSn52mL-tIYinGXTqI_hkXv-@WOpA7v~D`NvqLO zOcRCd>e?(9J0((^EJ;Mf%V^h{*%#%>Hl0l&l=lR)44ZX?+HWpMg)KOLy_p<Gi=v&>QS(@@hQ}epMvo% z$Xf&PNgvR_k0~Zk4XNv0H}*1fET2-Q;2>!KR563FgwD(ty9F?Wd;K>?Tc^qzJ3P&w zS|6=Z^>fzDom{E#tk09}ELg>V3^L-rKiPQ^*waLou*%8&?BlF?j!hKnwj>it-F8=0 zkWmCsnX6b%(1Aw8aFpyp^HE4fzXY#BZAmzBrq#m2I6UY@J>%(Yo%x&0un%)cuKM9C z`;)C9b$TbYYA;mEN_|+Jyx9L{VI(LbS+-JRC6p*JA~&Af<99@~hR$>T+hVU^!ePMJ zYTS9*77Y(Zd9jvV1&ssa6DP1*8>D#S_s4REHTG}mnn)GJIZ?g#xCkzv*`30n_o3y#*_Ex>PL=O8CrWOAO0EwX^d>Gw83M zem=WLFQRaV@F+9s?6qiQA239HgbIY>Ynq1Cbq~;duvt6c>FrAtO4oB@{Zv8Jpa~1DFpmZdF?~_x zwCBZ^jEqXWu`#ES!CfGu>bXbByMwLh=Y%9rIfWt!ZKqWdyQ&f5J*{UkHh1DXCB$i0 z;%=gfaE4i7EP*pU@m?QdiE45GdTx0%!0_M~H1!e3U6B@z-wz&Cy<@hS+yP4rZoP>y zM(;N<251Jem+kknfS~qJ+6i(8urYl>ClQ9n5(})4z7wP!2*2>5Hh=s19k8Zgu>_(6 zrXl<-RY`1%pqV?sFy%s=^(VFz^*9-Uj+T^r*aRy2w?+$q_L^Wo*NEAV++~(zS8)NU zw?Z`1li=860>S0Wf9Uc@hPVe}dfuy=sM8F2jWr%AE5lb$$Vw$V#3%!#0!Xq=#z z_l0}MIuVB_k^){b0R>x^lV8%xMpQjAP3e(3q=l^+*MN62(7R>h`0c}JM)!74I$pC$ zkyG0P8FEKqcl($&&Fb3mOC(#HwBAQ%v+>lQG%DczAWypz7Xv=Kv;#I`ftX{mYH_h# zbR~`eo8!FU%WdF1sG8uFC@@Ab7)mA)vb3QnSHFRYJT21$f2LA!;l#=2zqsR?m|lcI zks4espB<$gHoB-v`)5}wuXnwdjM}*^?U8Z_6>A<6<=N78I0%@WaV}(a>c7;_ovO)PH{mBrVMT19$}f5s?33JOY1kw_^*C|6x1=zZUTq za&z|lhw%vP-1T=rZf~3a5FP<4a%lniAI2l_-zmud$9M#`70tg=kpCBW)U2$!l$bpC zr8{WN&$9bKdSzei=2>2K?5OB1>}ieDlx02ui$e!-G8JB7CvUSeYx^S}rHh?kU| zg;4O9(1fbz&SG~FJ!cZq!t%pu{TtpZ_bO)qgL|v!%k<0Ht^e zRCi&YRS2MGXb(N>>EB}$0*}@U7AN2_R7tBrRgfGpvu97`U)XAR7r18W66}awD1J5b zx{YgTPGQ+^vC_kT5#r(bgV85v$N0>tXNXofc}*7(UyE}`8JYUm7@!$C5loKG6OZlGVO;G-zGI(#Z*{vs zKcW~DelBIY_Ropv%hZ`r9R-3^hfT5R*f(O~WJ2abu&}hELjxDf!7kB~(F)mwxCzDl zWycV9k<1~H@~P#rdHMhYx?t4aQ9y^f?ne)A8yW$+hY12$QOIH=YlGfUWcTdSTo9A@ zVxU5*pux>re)SGz$2gvIH<$MTzTP>Xo-y$x9rs#{DHSPMs>u3u$wHa`;70B2H`gMq zBgku7W~;Ly?lMv+ zz|uGTB1}V}t>eI6W9MoBT>abU)JA=pHSg_= z1usPb*uyq}HoQr@Seg$NBRBnl>JT@HK9c;@$MS1h9Z7ZbeE&X``4EdBw$Gq(XISZ}=f5Q@7&p;f<(6bHeWXnN|1Mnu%fKZIC9y!% z8AWoJ-*JCpLd3fwkM1RJ%eVszb_Q~&k0I;1@Ei-RXu|RPWm_(Sc5#|5*8+OI#k-GH zt-WM6!ntkwmOHIh&-PSyeOjn4?Z=%%z>rN+(bTO0Sk{47Ahq+6#D@o|o!3!2ujY|` zA6v0TmTW~$q3zI;a&JD~!S{D$yGX&1_RI4^)Y)qm{C)OE5GhgW#p_H-eTzO-qvM^U zK^;6-jQqO9%6}A+9nTnyfKzB2_KB79J*oj`lr^WC`T@W=`*Q+yO%@}{`KTV=jy+)a zk8tvGd>D0${Py8sotKG=nEukKA&;rVyI-x!TB!^DqmX$4C)Q0xG8>ZhumUQ>6W zV89r(XmNs0@R8~e#ZUYmft*itGzND;=WM>D$mu4ymn)tk|G#QK-MC0L6oxUkM=ZA0f@Ue0*%@ z90D|XOvioddltcESdJmDc-h`!oxzPD_q&SvYmR^9Nr^Qwby-KEI=A-2&Ry-Ner~n# zV@?|2Ay9SZz`Jvxwy<$bN$2)jngMrKMxmMps(f;YDGXvx2H|$?01VWigPy0HAC4M~ zSUaIsejFZ8E57d3KrXcps|OIISvTh_mcTm#X5Gg1tW>>lLgL=<8^D{B;9h1&gnJR5 zsT|SazmZ4bWpZ$B&1XTC1G5_3{p8fL$hUJM%fGb`ePXkx}LYE2ZptUnp#V}#$!ChDgY-hYd`%hqqiy=l-rvHrMp*y zj7Pv>oVj>{$!h-HLzJJn%SbsD|0$Wr8=3s3i}#0#m{8`{4_;p4@tV$M6E{2e`qS|G zDb92T-5dVjV$ckrq7AlsvEm+iCE+_ zS1KT0;qfVI)Xt;H%zv>Hrfe@TcybhLG?V|MaNVvmmd91AI}lvxGd~ylJZL;q2Yh^Q z-$|<2hN*`@jD4QX>Vg$M=iAC$9^S$9fRS_Wk4qME?&D>F=$Np{QT`;|65TjSp=@Kj zqRT)g4`IFX&HX0rl+C$5f0*e9sF5Uz8Z4yOe6+p4R6g#~a4d1^DUlI}kh6+!Ug=Lg zE%tbFsUu(+qR%dB;obT0j(|CP_v}C=zP2f%xX}$heM%u@>%=wWJApkyR;t^#^-XYt zQ!SAKvu#5Jwrzj^x?Z*{zz!QCs7LkIn(PSpZ43N-bIvfBUj@IO*IbmA8>{|8I||Je_~|H+n}j zSHN+F5L{8?nT0LVeHlvw4h1d1K64w>>A(5|eCyf(N{DTmJI*hc%y(y7Yk?i5t6T16 z9{9MAXW7(mlRP-PF*s?l`NVIzXEwzr_IwERpk@v#uMUtgN*Oc4Ef;#ERw&`++KzdS z-$P5@-?wmVb0U`_l+&TcaqmTCs^+#{1CQKA`cQ8Gsqu1XTnAV?tj;;`;Kjbs_{p_N zC)>A*E#l~ynqIq%n9jD38ImBSWeGH)WCb<~^To=Kzihp;H1TNsk1&q!d3FVU_^Ut3 z10ZqWR=SX?O{J)|AV}GTX8<^_1DLLtnZft?@(O!xYj37A!~7+r)yiVr#yf$}aItJ7 z9?d_#$}cA*&=yZi#fsg#M%9(`hq_Fi;{1X6kb9M@Ely6wLu$Ex)0>Jz`*kk!iXKs( z3t)1)=RVV)ja!H|+BD%uX(S{Y%?PI2hfjEzHUc6Au0D=>pHk z(5lM<7`s|j$=DiuIic3;?fM9WGLntLIL3FTjCuX+w{b!Po+DxR$B739K|mArMtSLs z32V{Q=1T+Xg8(VurlC&){@%}yvc<9JPj6{llhyRmk%U`}BZE)oPd{RvNLh%6WF=dc zv}>38l1C74{bg`u1(>d5*?eKKw$p$cZtk7+Mm5g{mPctm7?^9ernEF!RMZt!EDbb? zS7uF$po5LfoLksT$u=!g-D{^fW<8CE_(_8_rwhe92BWL9e)Ck)uJJE-MOy^Ca%Cr_-kAdnFXB*@6!mb0 znbhm9D^Qutp>O`{$ypyaA~shdJ{*JcGJ3O~T+Nsn4QvSSt!g@+qBL9hC(saJz`zOK_>@ z^6*=0N3`ezcX9%8tI4?4Z}rj@(}i@&qHzAaVp0G8`n0Z#OZeGM$}F&4fQWGTqN9-P zcB?T-t{&=9 zuv+f2gUf|Q9?Kche06UN^&W-wS~eYjQQqYW+FsjUyF&!^SE*2T^$!b9b54GfeG5_! z+Hel1vMb6?xeM9mOB1MiFULy1p%4r53v<`e_K}bKlS`1X1SA?D*8`3C36Xjc4_vvd z#m6(HDKfEfAvFV=k!Y6xFj!8|X+QAMu_lrkAxdPw)SN#q_d*Hh+ zho$kQd=IXxEPs6Q@ARmHsSjUxQ-rI>o-I%f!B3FwkOSq8mp{ zA=Ms>Sj|R|e`FBvW-oY8mdoX`j8e&ZQHSs+DXWN0uj#a+%8g_+o81)=p;Y6Pl^Oxc zG>!sG+I*RwdXW>jV(*x-Y)3As=Uz|k(H}xk#t{~)jZzBi^K~*6nFWDNel{EDt%Pc> zBw`z6J>%1BPSx(yhCgDg_ra}GWHCo8(T{>UYbJ0{->e>IRJ4nNbA=Cadf%9uCM+n(ayd{*FxWL>9OWQ$&)C;ecV zm&}hN+KTfXi*~HT+@fds3~qd|@iP0wZj_KF@4R+rIsv1IRZV$krwr;@rK$I)td?zr zC}HNR%9>%&Ay5U81KG_J*jNM0k_l=Qz37qKpEH!EZ8HN2YGw-_qcPovox}Ont?j!` znT-NrHQu#eF`0p9YA!VC>nIguu?X1Bl+NxPC*1mgu&a}D@KR_QXS~B`XFSbf(OQTC2Tio`jZwY{cH7in8QZD0{@6 zw)MGc9!hbSKlzxF~k0i-EgwPX`2L%zQl zm5*$zjxag@wJraNb?$zeK$gnpu0TEvqYT+Ig>TqD)YiZU;KPK7VMGvoNTUQk@tPRe zVaqI>Xc5_qqL=h^1>Al-owJ}o+sSFy!_5{`1(f7O&o~}&XY zhMAFLGa{evvsLop!>qJ&m7Hl=dLmPnHzXaAiQdW3<~Kw9s%IDXcJzwKgztQag`*9` zTx%N2JF_oJ2tN(75vL2!q9rx-4;T#TYyyiq?I$08NGNU+E6oVjUHQo5e?3unv%npP zrLYXlRp&KE$BFXjoZ?5?*vt`xU1=)2Yu#&j~GK#kZKbrt?|d`6u+)kJ%ZM?v(>_L|bDwMD^e zH<0V=m4G1wvomDFmyd%PfL&i-$|XgZs;7I|2Nvt!xn1z+p!|8K_lDs{79>nJzUWA% z)Qe59^Wn7*CQWF_$oHFyUr(UfCS!!opT>Arm?hlN3oKqk*#XmNi>SMy995}-?xHnB z!oqXKOei}e%1)M2d{fr&W&XlJCP_PNt5BSjqR*h|FAHxgY7}+kj3Bo2pm|Qon8|9d zv;gL<7kOTwa#Yl*g(oX^m!?on`(ekD(eSdKGxdkd$opL~T`s-m#j2jkLE~1fIU$;1 z>V;R19A_RlZcp~0j>oghtkZw+Qzd1xp#7rHkp=7B+R|9n#NABP>(Ic6Az4UoD z2=#h_AoKR76hau&F}DshS&??X2X(%-#p zZ+yE{0PfSM2Y=W`0XwPY@v0I2>7iWDT48&8g&t^J8#l?VnFn~!MuKSO`Y&Z$w7qGf zo*U+k2b}dO8OlqUnRi{0>pgA$k!_~J^?CIj+N^~*|BUP4%GVNWh$UhbD+}k15P`kC zUk2R!3U1cr0vm~|!%uYJtNF*DoXT2?BA6UQ`^SQCs~Dy-6MvnE{KD7NkbQR9IU~1g z6@iPKE}w_c2Giilae+=@w#;;iBdF5OH4V~jjCaf2ASYFm%J6=+YmzDR&DSdpWtYFP z=%deoE@HgW?CJsbK_mOu;4=Ykk5)~s+M$nLM90fg9LxiwaTYOS&psVgAfIdLG?oRm z^vU-Im7v+BXTTe7KPp-irsvH?2vG-4DNY)1J~x_yU>W5&v7P>)rTwOhdT`8ga{ctC zZMkq3#U&e-eT?8?h|VfttRrSXRG zw59IN%L&|V8c(g9$J4GqE!FRGO#YfgKz{VR=#ii#?oc+r(h#K!Ow);b-lW)p_Klsc zoSW3lTd$9FaX*OZ3yd=T36PtLm7HfGxl#$e;9afV%!?Prta%`dVM74J8*~aYzuE?z zweWV}^}=PjfWyX9hdotE3r^OfwNQ2$emQ*7fo0t0E7`9Lp#5`!vZU1LockH&!3Kaw z_HvJPWmzD2ZX8HH?+k=zKsLrRP5is=OqG5P;)NEkyP9nGuxJCFb%Oc}>aM`^j6IqkPk2|l6p0i7NdTaWthVD~I-Am%L zDtmf!eMhsslC$~&B!`PEQqt6^9Dof5R3B70H+$2-@lMB@8E8EvZ^%&j!ao6{g4iXA zAe@x0iE8=UHo{FRCa-(vaLT+a`|+X#)}3R74B2gS)@V?h^VT!hO;m-qf0B~t+BhDR z*0NVpNP^E)o{mY)5u@fN@w^bD5s+$HajSpev?F`T&=Zc@a=lx?twjiAuJe9w(pp!bnSVvo6QbE;3gRtBM$TIc~dr2Fe}2?-f8y z#3?U+k;_YnEKLEe&>u%CmeDO=6V!MQS{i0Yb$c~vm{SdPLHT2C@|&fV>+2I~Z(}WF zjvC30O`ner0yx8MO5E}BpsKX4$*Tb^FiGi9n=%vl)^Z|ypHCSeHvZ7gEWt>Q4&2Mr zMoj%~DY4bZJLfid<}T^TkAIMj%rBW=wCj(kD12JnciS6n#EV)CIps6n`2v`OW^l9e}gKptb|HU_m4#2VH#of^H&X-9brU`Aarj)WF zWBlP*jItt?6K_(nu^i~!YCU1zeNjaIV6hvl-G-OD?T}agWa!zm3+9|jp>`lgHs0g& zknHydk4oLeb>Ml?yy~JRPjSlBgAOgb`NvX?kFGkyj}cIw4|aCPQSYS+gTOoryzZ1b zd*6m+cYwPya0SC7gPv8)et%Wa`TBIUeyh!mYe~`Axr&3yggZ`$Y41MUhlZh4`;m$IV#g8sO&b!RDA#=pz z6&S-SIK^5kIgd<6$)t`~qRpkmIpDIlV7CT~PoEPzOs*9#WUPX7!R{G@ruJsjGgYPr z^T{&EpL@@F`sO-lchwLrvu`V!ol|Dm_?v&Z#TvNE`kYWBN8@tZc8&ARK)zVh{N4+4 z!Tu>vYMS3ChZ@BCr8ll2w;lf5ie#Jp;WlgQmm9L%F~6IZqsjL>0JnX5|03Bj zlXwV{+ueZQo&Hx1-J{C8ejoi{C`$M50S+)~`^zgGQ@p8y_yeCqHb#GM`MV)HaSE;W zdoB-Df`5nDe#vZ`{ZzBDZ;i&^s8ae*8Um*=ATMR$b}lX5m5RrI3bTJd9)W)ZZMd5?Jzqcv1!9~lkf`d~>IB$6eUl3a=iH907s)Rlk zeX)%y>XPW6zBU>z>m7Zv{VBVe4Avm%JG5A^S5NBC3HG2$h%W1aOyg_EAIz}lR{-bi z{`b`Ei0!XfCeT%!BZVGTbe9ndM#-O)X}NUEnPxK_ijP*|1fJQ*$g5A^RmRp{D7msf zi)NK~1RP_3Y9qrCGg7Ir>T8Z(>Hsf5??|EnivbP@o_sq*4Q>`BAMeq zn#q7H{&0=D-tg#()@{gB;R_P^W$#OEba!jnBSU0m6r(=!1+qp&+6;88l=9Q zZu}~z8ZLTTK7ti7mRBUZ{W^tsVIbcG91JYF|y3@)kpN)22KxNe&N&T2KR%=t<^yKfMQ~P2H7}6=@6vCDWG*09l zGp1pV@40)`^7Hze%W%`Sj?czov~Pi+$Nq_BfT9h!x#x-EybG8EQoYz$M$z($k$30*FieFWF46NFw4f@Yx zS2eb-vDcESs$|rU&B2((C&@N+Rq2$!$G^saxa}-uw!4MSl{;rmiAe7G042I5n?rjLtN?B zM@AB4;XZ?H=3G-E-hG-Zsng?!>%%Lpe69wQ{fHW^gO${&e=}sZ&rUYvJdH6tN@ddr z9Nwa`Z*4q+(JRo4=#JGbS8h)6{-lj49*!>Vx$?}_V2G=Hwt9ZO-myCyeJpA4=Qqy$ z?Hg+w+>$4Er*nXqiN6p4Cg^oGWFS5?y(A5$1Yvx*y}##b54!C&x|#oTo~^gnap($Y zcT6pn70L>LJo}%SqF-{WZnMCA&nr{DO%Jn0dcEx%jTL5C`|R*DG6vrc!Bss4!MEWb zaV&CYJL8tHt9As7d9No)`g7@=yZm~l;s{fh_IqDkTKzq@YQE0dxLoCeNd`*8{>sqF z#e*fTlunJ=a*x{GP2A>Z0bmswHCwTy0ZLOQV`|VXwztMQschXEr8r$&>X=Y8RiP@( zZMHUdsaw>7l}Y0%pYmjfl3h$YqWs0TUOX43y~VYyVm91HXxCRkQvceY zm_TG2AQon~mCS}KaGMqW7z!E_D_MUVDC57}*iHdfR+8l>J+y--nE{s#)rkqq7# zy;54|XJ#jQ9Z;V8Ty5H1`D#*BNuh7t%uv&7v}B+9cFb#FvUM}rs&HK1Ni$S^^PX$_ z9pQX(Qi3AHzH6u7D7B9Hc5&Ae6LD_qL|xBGthBVqp25 z8tKye@bptI;8e-)R4IqO_fiQ^bV@Z;_8tmzequf7VBr7NSt04{yh%lG=y;pw{foCN zO%9+>v*o}_7E{h^bYE;<@Zn-I$VKa$UR}Zmi7UM3bx*&;mG^xOHAG|z@AGec$f1Wu z1xqMYX>w1U;2X~2`c(?P{bP498+@)HpD_UQzZQ0`u%%FR!CDaBO(ZSnf+ zbt2m4GCWSCLb&A!drUbwX*coM$S~&f-OP)MduGM?%^Q}73zl_q)p%#H%=&ra83}$`%E7_%~B(jrk})7_o{O zl~JeqzlK@ssUfQz`?g8))3ANG+Ri(fy*^@c(z(Pplj54xLlPXPOa9;CgsWGeV zkQK_JLiWXNbAiTWYpbqEyG5p7CxfS@+C%ya(Jgh!OHc7w&$(a)+OMxoZ9ibbgvExedRT5E1r;Wx&rjLbzF z+m!ug6;10zm5ABn3+{HoGaeB={7fd!?7&Ntrtvl~KJ}>V$5ef|3}t@5!YKRqfu%1S z&Q@*bjm&R=XHI)$U6x?57>QcG08C2Tu94uk|F0;*@Nki07}P`qkx7gwM9Le zDMtMYM&Ye>nzLcZSb;o3g9mETB}qc`thrWs*u{P({_^M|eGLGP?yKu)710vC9vH|p zh+sRM+F9daac)RrBqLWbN7{&DJzepJ85aHqwDAKjg7k%oih5Rg3-HwAt0hHSeZw?+KNiBlm*j&4Cnr$FF8@pg+KU!o4zx~WqcV)QK zI+ejo0SyJ%t)tRQhSv(s_*+sKK(6ui)%ZXegZ7c0zd!dLZ>PCuVx?!nwf+>r6^pJ*u~(S(fIl9WD;;=&@zWJm)jdpCKsMWt1Un{05IHwFtjgOw&qj}RX?8E zb*r2jAMvQk;yxL7{N0h^iPEf%H*ACP=Fey%OCne|gLBkG#XG;V0T%frz+_3TGWi)) zy*B$hW${E7Sclhm&%P<2^)m8nJHe{di;7%B5#hMJ<(-`Ba|;5W(;68A0dTsn!JJe) zV)YXJNxO8g6w6F%sgo^1r&?qFT}jqPSzuFae+*l1_HziwHRNR4ZF$h%VgT9fYir#4 zU!HE=WYRBFHIq^FXu}T{7AJ+0MyOGawxW;ah_JS@%Mjx#%a4V-ZRNAAV9ZDX=b~!P z+c^KA^s^^;%2)#J_N~1(GY!tnW1C5Ur+LOu>zVnZMG#rX^}T(bSr-O7q-D$#gk(-* z=(AVNuxU?lBy$%B@1<#W9vGSjdlr4DUNW%_8pfioKYHde+%}Y&dw%WrC0@mXYJWi# z9fMYz*wd)Nq0LS0e!k6)t?1CO*KT0beQhvuW|-GuB%+a0NmsL*poe}NRq5UN)n}9V zZsTjV*U&qk*~fWx4i7kst8y$%ugd;-dw5_z9=X(VEgjW(Po(MM0& zDTlM3o5<%s_jN>{8dGayX~TPWW%{I2gH#6tDn?}LXE3c4w0&zUyTCSL-ew=?*-kVE z(F6SAcZ2XzLH5lpL=A&Mp^IhwK37ebyn2MOwT~DET^sT`oj55IOGDl(4=454SLK3A z2fXhj_-`!Kmfr<>dRVyo29gM^rL(O#h8@=*5m$46;xq_A@W!kcJR?{?TRfl@H+tn%V_(0gu{9HIJSfj~Fn)o^QJ*bp zewJePc-jf0*zz+Rlw43hAZTBtZL1B(0+x!eOAC_Y^Y6GX+`g`WuTWU91FI2bsg8DZ z7QY#TEXgLVWC)PY0iQhmo)ehEsTWZOP&55>p%RR! zj&n!Ng{gLuIq6~b$jY~Tu&RWC=Tje5_ws_vxlmI20sN2ok#(XtfegG0>r3ljtNMCf z6f&9bE;dZHR;7J7?={T|>Ph8;jP*`szfoKCBTJr?m2Wd|S@aibr35e@=DwOHAZO%o zEqTSfv(+NG%s%OTLYAspSaTBFVf#3cACVM%+$hCzWWv4vEyZMek!P4OKysC z4=dP*@Ttq~uAF+T*s2;>WDdV>GFqwZRYYbk^^{7v%8nPV8_*hdkE|@7|5|KxRWp== z-&b*b#?5PFBgCm>GjGwe=SAtrl~L#YX8qDcfUJ4|nM}sN^Kr^mtr!FCn{exNyy(x^ z&gg_>xAN?l8!ewJ8~O?eHA_ftJnt5uGO+TBm;3(G#T@;xbdu$ z`j$iZ8JITq(~Y=w!C9F5Viw-KTr)`8m<5dv$t6|mX&yj8Pg*9$Jgk04hw_sV$Efj6 z^T6V-;^9+iM&OYW7{d0>x%C1%I{vO^pzOVKjs?b(4MHpf2t+Y4jb+5%?tQ`gkrr3` z>3W2-F--9_s=!5gl%mc}iI7|l&Ul^yW};=JQp15~G*pn2Bp*%Vk*p%>MTvo0cZ43| z$_DgbQ`pEYumUkBRG+NzH8L;yl3idi;}tWh?xm|GI_A!H(_JFAp#D#8=mCq#P<(x7 z8W`K;Bi?r`4ebOYNZ5s_@IKzwRn37(lc%cnJBv{E$3<&Kj-AwTPd>}9HW>0KN>>Yc zU{593?Tve&2{yY$+XQc0;5-(B0Hc~7KLMQIWJ(ciBQ3ivwEfijY8l8q!(LRxigBxc z@iM#_qc{Av_dweeWZEy`X0I-f(lzk;e+2;bFCz ziO!cLxX+oRjn|71)Q2Sr;L-Pu*Q0e-k@+b8X5H>~g!94-I@TVjqXRshPueJUi&@}4 zqh7OSyfy@j2pvy=P;m-oPUEi+FH)9+-VjZ-qWUOh^n<_@X%5?02fM?pM&o*70LDD6|vT{z-;*z_>QtKFQ5e@TL)U ztiN4oVB&pJGu0n>el%69)&Jl0b6UFvf-gk>w}~}MBqDAB=~X$TC_k&srUX9 zX9Ihy`m$>`j^Hv^AjT&j@HdxX4t=vG($zKEaIX%S4F1Re*X$Aypi{y*aWok!(Nwhb$zs=Ay6quT$KHH5;HDUo1LU0~B(*Gd zQLlu*CbVbAoZTofRnM?`|W z6BFa?umZ)0#}#-9f1s_?@)y6v513f?nXM0xT8>zY{h7s{y9HHq>fOC^YDM`+1kC>? ze-#|)bad%4LAu6kr_&TPc>q%2ayVbvi(=(8yEi{)0$2VFrb>kUci9r-3SAT05;JS8 zzaJ^@)1eKP+$~TE*+($ZhC35mdK4x8F6fqB^HW7X3!Wh5+S2X0AvDB6u)Z7}VB)nG zma^Z}lN&aebWJ9)NPF@R9q56|Bb7;Ku?3^`;MS5j#!Cd+SmNCbl}Ws*VNh4E4jhZR zCZkZKOIz?o#VA1VnXA4_DC+7nvA2`*&-rQOBXNK(eb~22P*Dv4%cy+1*Fjq;1@sSW z6*K|snP9@xf`5Ysgp^Q#V3@0Z3gOmH?aCyBzHDm2uWekN*stl9lo$>b=tvv-TR>x( zUh`5?Vmg#PBsk`!(kW{#TC4#r|FoQmT%wFUjUX(g=^f-rp{M|xXZ+e0$ZSKEw~34# zd2ZBu?N3;P<#zs7&BWE+vA>I&O#E~BRdynOt7kGY^uccH$*-yb&CLI`ph>L5sNtU) zAYiGH|5DGS$j|iDA2?=bt3czADT>AMoaP9I#>xM9J}`l)HKi%uk{wWWhBI1YJX0vt z5ShKkdb3*>DDAX#En@g1WYF#XRAAmTMDNrB9t_qerC;?3AIRa}WO+xoJ((Q=C-)5B z=s%NDtavue8`-pee3W(WQ+Jw&D%tuAO)TV;*tNhSy_065Cy&Gu?8<-Uf^93yyI{_x z$EE|o?N1};e`D(Uc0d13X%CwC@Bc?_kN7o`-or}z(er260g&uh*6 z`|t=*<3VvS_a#yVX@pDybAPx*Qf5B1&v+^9oQ@BvIzzveBeRAzbn+ePtDr17 z)dNvCF^gb9M+C*b`K4>WgjP-+v5;Q5<*H;K(KAEKv>VLlP;Qx2o*QPEUap$7SEC|0 zUTK%)bAq<~_+nfo*I#)@L)x%ySa@cc%i#uIcI0@*#lr;Vg=;Tr$~>7Nv}0a zl$$t}d!(lOuT!YHB9J90jBK}Gjb*$@sJ7UbJwdvno2hUm{{AV1G>An z>U~N0>`^<3EnjV!Ed!b0QK~q*?CGyX&$2+bjg{xdQjwYOeE(u!8z3?PhD5omZ$(wC zjw$RjcO2}P(u8j~;7h(f|Gqn-!&0)ti0UkbYKs) z9+@NI3SN3DVD^RQfE!Mau4FM6+8uGT!UIBBd#Rc{et2cZ1BjL$V**x2szuIk)p7QcCf=V*?6mi+jMGtSidnziZcJn|25mI z$?kNh^5r@$nTiZxp zAr$NwCe;-_duAio6fnCJ{m@JZjHv8bCTbNS+&f;L3;^?!&igho!#4Z8guhoa_3RLB zzTU=%*}1n#Wb2@?oY(^nOjT$dBq7bZD&bqp`O}KaK*{d@wkb2Wm z$0!ynvxS+!U0?w(b7F!_#qg2bE0GSZNh3ybdqLu9QLDVu)q)xW&dmPj1XSrv9W^5b zOhm!sD9fbswN59H9oFU7*Eh(K;W$%9eR5jY*i$Z&(BKtO|cfedg~7cNNUcP8-j@+s|^B(`O3}pX^>F50%qRDqPxvWAoukP z$kR+4@W9~<`)0BXv;j4U{s@=`bz4d)WrUr{|C{Bbu)&qOB6S6xwJ%R_D|MvhzS-yN zGp4cNRT89_m)Q;N=2^K6Fo#^UlV)(Pe0d#mYJRzoeJn=7sY>$OedtK?DVH`S4br!f z?z0SM*(To+>u%&`F>Q2*MuJ}7lH*;%+PV~w%YE2pehvffI7R@>Q@nCC#cw&#HddJh zHZmcunZsykW8W0Kw6l ziqVPWL^Dl9N1v*IgL0Y?QeiY&(kgYBOK_0a>Okn`XVZIV*k%Mr@|5Yv)H?Y!gonbw zF+SyM2W7v%Ujb}9CrxoIvyeQudu8+1%LAlW@hQ0rJ4QbiZlbK%``W;~$HR!@Ak}HNNDZD6jbK;jLv9{1S!qvLo?^N#OOP=9Df| z_8N~z;=V)nv%dI!!>6or(B|wMWHk;yZ+tQ-NoMv5@Zkh_YiT?ZKLjN~HVe!Zm!#-I zwWL@3g#SD(c2~UY9yd9d?TZ>3U+9u=VmJ3R=Kicu%9>X~ywEqFb2hhxG`J65 zn3T@x{tfFjs-p3~+WYdTCa>;Yty)^CqEexXfEEE20Tmg-6h~A>5fPacL=;FO5W*Dl zRxKzp$vlP>5D^fNAqfyj92jLt83PFr1VWg?6d(jha$mH+e!cfwcdfhD{kQ+VD}*qG0Z4om2}&Y3Z;PY&U~fi+Ea7n19HA6r}ns?Jo)N zD@c{rVxlAL;kNwNr~@fk=}S{w3n0FSQG$2}7R6HH-A|zLJ>HS4{hn(UW5jE;si4`x}$C!4JEQiozpzJ*bcHA z(~F9-SYc4-k=PV|!c&P%$wqsR!PyOsXn$G1?jQM)u>rnQtL8Y0oeH9Q@_v3>-+Crc zbm+d0%W?eP@QX$d&s!fc3@dD3axUk4231JeyAJFp5dNU!0Ph)X@+>HQv8!rLlf6MD z5Hhw&=<9zx2jl39BK>1l+Y@w8<#TGJ1MC^Mmpoo%1TWY4yn*>_t8qL^Ee_Q`csV;_ zFF+$1_Ce0_6H*k1j*46CQx6v8$sf6_3tQ<%US}2=O2xSA9 zDJ$ohpg8lP18$%OlI@*wNymx0z3-OV_sw~ZiPB-Y7X7s7i2BWJk(%-Y&f80)Z68e@W#;ew{r#aPkSJ6;f!gTZJ$F;G5KuVv%JysOl!`W3 zdDSf{*mK3$^})!5OUBL{!N-NBlW#muh;(9J9?H9gQv3CF9d--NX?-~#4^{y+zEW;K`XlY{J;YFCea>rsT`(I;Nnt(#e1&Ko zE!a^@kVA*@o7onnO{{cMARp-_L+X|)9)LOTh2$^cm!tvr-dt_$>OEMcB9BKA#ozQT z6s4D$Z?1*8HL7SxAYV}sw4 zoL=-&0a=BxycRuY6(+Jv7Ox{8MYhfnF_7LmnV8>G??kAgx=8 zd#tY6q-W{NGX;9{m7|7AIfBaX9zByqMVY9$?ifYA^&Y%{uM~P}0cIt;j8C3kDQKAV z=(#cS?uLV6%I?H5d)MtX1?I~Ll|r0$O0p*wm|4KVH#TtXB4h{MOnXr7h^jnE9kWo# z7q#`#T}!Sw9VwP*ChcWm2;A@Ij}S{I-Y4j4FX>BR5k85X?-A0PJyTRL9m)VF6&uz- zxO&0vr;QYMtRIHs@ZtHdlY#;d_f_JP0xYIM*JFIJ__ho078)NVy3|uO>wRv91TY1b zWXH>p_S=O?om2{*1C8F^kZ^VsVTep4h|n{gLqr{K1+At6Z19|8&{Bu;FdMnw2M~p*S!|OH{lcuXi>1;O$-mc$KG(!A9NDi|*%kJ)UOwVM zjhX?@CKZ%M`|AE<)9*IMf;vP$=E8X+*M z4>ji-u9C5MgxhEQ@#vtrAMCPLx zcZB3as&#i$xl~}LK_<}3+y05Q+8Z1K`l*XmTad`TEmtc5`Wg)n(87AAe&;?jTq;F7 zVuaiuC5QoY!8D7KhWtc)e<9R2s`8LZ&jE~1c0T=i-CnvAEt&T>e`Y!EK?X{4R=u=!BWY3ejt2xp{LxaI|8 z9L|z+twSETee=qffr@DS1(Bu<`E}!<|6;_cPp8lx;srvGpXNSA zRN7qUT0&F0^t)N;x2|l^emX+dbS|KAy^CS;^BQ!)=c`vr z)z6>~Dp70pG>&o28=_-2dT!AldTPM2xwLi8y!g&f2M2*IqL45^((|(6tno|4ky4Q^ z^TG`XxwuaFVagvDvfH!^oijnS zmxdHUH=x_QOm#v!s@O=zK!pj1JWAxQkqT-?qe<*U-|E#Q9OdV>Ua2(PX_+fXHkFcF z@aN}8m#p~D-{O0xN48b=K3;PFYIGW$-oJbbVdpZV+2sAz*m-VXAK&NWVSiP>C+F^7 zkn45vthJywdSnHR{@)rehz&Kk4CMnT_-r7#xjyMsE90`whTYj0mJ@bGX}^?=+q*X1 z?DE`ZFmHdpqL+I63f_*$<;546Ofq#sbmx3aKF#F|?}_hX0I-?yR!DKyf=<8A9D7&) zao?f}jh=LGSkKyKSt`Q!FH^&IToxQ01WoP1SlNPbDQarWyD@X|nthWrKv~64&5RT) zfycwwtKYvlTK#BXbEj@^k%71#9~J*oSD|;MQpjUDa1cduW~0569ejI1Mcpw_^8R)Y zR44fLg`4e?ju}%giB=@~5!K=oAhGZUOFxE%J008a;mZOV_Dko7HoXUxAgZVcC{_by zK6#mDt6`S^a7<#!#1FWUMUd3Zq$GehroxKfbUvH`j(_G)YJ0DE1>t)ie+W~sYq@f? zSlXE5FSScL!rr=v<^tp~u}I_Q?%*zQ%bcNh28 zpP-$Yi||H85Ak5AcQIj`BGfT^TGt%q@@WMZ<5;<@`?Is^=~Pjuth(6yRG_^5_2urJ zU>~-cM()4QG%J)0y-yTZuhB2bP_8E2q7b5Mg@^96A+#nF$7bI&kRxS;odKVAJFZfy8u5KKsh5 z>yGrU`!sy9((ZQxwyU(wXU(&6>OHfezvxL>32xC-v)cl$CXMqLNB4womHOG2g?uXD z<--`;YQph~@{scgv0#1O;eDHxk+_p0{7foLH2xtn(A)YdDJY2Fj0uxdkNk zo-c1#)G`e(oa-zDd*X3w`G$SV%W(Le>TXW^1#-(NwY`&Xucyb&hDu&9_23tZh}MzN zl9N!c{T6A)@4RCzG8^m$RdbUOk1ux`sIF9<)a z!7T|J#e?MH5d2-kJvaViQc?QA38q@L2ivzkG}>|cRXDg&lzaG62sNS>CflJ^Cfwh; zW(5*SWbN06joO3VUyhk-b?hqNH087BR>{>;BSTq%(5{}3mQ{%;`XIP-e+US-NBYU% z2V2*1w`F?vW-7Kcl-m;rK$^8vjx}<~u44Yr{RZEIs)2tTe%xV<#NxuDx zm=!=bO_SS%zUbjR{6CpQEuAnmMUE<;YsjiWXJJ{Zy>ZMfhe6YY+t(&B{DKDN6;zLj z0_0{ilr(#&MBI_dPM}Ozyvk_6=Q1!W?tV0aK27N}yPE z880nG;>yWv(cVeQ{ZF)|8ioiO%oBRFSr2X9aE?FLZM^Vg=dUMv?eRrBlcc(TQ^IQ{ z35O$I9((ii4SP3ikI-Wn!RE6wG}Lfh62XkBq&CS` z8HT}ZCR_tKetIQye3l~|X-rQ8e6j&+5C`Xzin$NOWUui0Bpq)|BwqZWh;J7zkwVPE z;lZLg&twVUMorbJmmbV109bA^t)icm@m}vo33o1h{Zk?IDMMzY< zV&JiU-bHAOfkZoITO+%HyN~!#)e4is(mPUcGM@oNO3RT}2 zMJ+We#00StFVUReKx*}`Ox>%oC(gD-WpYmu9f03cv+@b!rc3@tlM=mEfx~N@_WL$c z%i(HQIx&*{6Q3#iRapXp$b4gkmlB3*?xz}66N*@uO41&Gs@bZZ{Lpu?-_9aA7)x|E zlN5}G`=+|B!^~-P@p992T)5-s*kuQ&*p_4mh#58Tk!Oc3(P0Nos{ImfV#NbvLAO8v za}Z+B#WgePYxVy&Wiic30f?6J+LBR3MC8n#7Le?jQnV zI;wWj9m!Y+oJr*m`B~58CSmI``)A8CYpWN?CsmGnu7`D61XU-(ik99mrWm%=MW)lD zAkDW(_zW;y>Of=qpkc&0=m8^V%4(H!`or(G!_(fk86!I;p^kwJhEUBHR4dh+7%MFZ z96A@HV~iB|`3D9%1uSlb+xE0L3-e$Cfjd%=2HpfG3wjw#+a%D%MMot=vRnAbb!)P` z4nsr;TMp;UorVeAsTe{R9;T|ic+IY>=@KBPMsaxE*4*Smc?A8=KsCNaeBJ$s{z_j- z=GCO&A1iEF#Hz!DqEnKj1cm9UnqQOEt9;Tjxx>A0OwpqNMRs{p^W}hXI4L+~B0z!RZvO)9bZjCT_+3@L?H+-3R7sxT3l1XGn~@3F`wrQ1S|SeF$1~Zw<=S*0GI4pXdX1DlL#a z{}@V(vAJOcp~x47C^YN{nSUxj%Nx^U@`)=2Ey@H+V+9Oru-yokJMX@wfHL0m6GJAIX9wbhFJTn(9Maz#p(gu2}W)sR=Bm+PC{ECHCUMC ztfMT(u>lQQ^bXgT%We&7nz(zt3q@H>EMddw!}CTjv;lq>z&(wYS*i z!I;2g8Eo82o3lBu#Moke{uz|K>DO>qrVQgT^45gvreU#yNq-Vl1SipzijyW#lcErS zGeW?`uqb>EJ7MWlH0iB-GQ38w<(M0%ENkg;CcL63zc4bW`z^xx%V9zUdYY;tdEoRM z&N+?rTk**mo9#ag+pcee$-la9}-N!m=LG=RIb)_3G0D5I^)Fyi$^WHqbS-6-3d%PK_)_(_TTpvT$ z>{I7cs#Lp<%j^~UMCUGZCzgCJp%t0b3p~3UXjowaDJx928Cz7e`L4lh6=KsKX*km+ z+rSM+YBYac>%zCUyJEobl;0S>5+czoNi>IhrtwFlDL^)UDU*pAYwpKnYQFuACsR9U zm_&0b%n@TWhzDCnDp(@;*McFmWlB57=`u&VYms5Gi=HmsynjkYS5bzTb}cpuWN z4JLqLw^`db>PS*a8^`oM(L8lWq%dEzKR#ZJmr+);m7`&I5_epIHq#}Sn zD{54YgL}BuV*8KoBT@svGgE1T+gdn>)kIe-X=0fai$$KzQ+JS~3~3jbu}OajTvBHx z9i26lT8!o8MX}nUu_qeY zRaa!sTXyzZ{UQORDG0q%H*`#pRe!v3R>B=1Jf0%h@c&Sk_y~_MSk9+Zk5mXy$-I<@ zFnNyLXi{6-?AdrXRF-EjIU@zYK3D$D?U*;=cG4vDO*2yT=t=)a!Kd5c*{6->Cx@MS z_C9Og!H}}d78M_U-1Jt3kV;Ke$*P;M0?nNCM8?V0u^}g&@YT@H94nMp4!0d{pvYg>c=w z1ci1#`e1L14p=(HvCk2h=8}T=BjxX%zJ_?)^4}p2zt9qYb@65?d3#mXP4e8?^0vfm z!I|J9_h9WItXo1Es{i^=!POlErKv<&k=4De2cL_HSPvN+>ynL;PE2ND6KkiX@+Y%dX zQ#(avE*JZYsWR&UA=mjV-XLO`xf`okJ+rYgj{AMEls(`_V-j@DB>~Fh5nS6-Z;iz> z>oDOPchaVV__4n4AQBOIYX7X0pE)TzdrueGW^Y$^ zNHu9pyURAmY~S=-R`_fqRA@`q)W(XLiekuUs4?>RIe0;D$(OMu0S~C5RQRM$EDjdc zBxa&v>8ZYH=-V{;1IgiP%)o$-2&W;ysmw68Ji}IODyGGL$hC~FjN721uLk&tVOGkW znKm%#YFo)Qc`k&#c%vttl#p6g`Cw(igi`QOm*|*TtFN5UQcur_Vl@SQO-Gr#e&OFa zK@?BJBUfC7k3cOL1nc-1On9aPhQP#Un9cO~E^b|(S+^;Il!s?5s*M5;D^qb8j8qL` zkh22zDQg)t-o~OD5o1i(rrX`80}cDH>-cG2?L1q z4WM1Ob)r%K%-wz?-yin8`SsC7NypX2qAJut^O56-4P`T%eU3>~?LBJ|Jo-+JSUyoW z_v`P=my#35t|9wVJA!;f%*kNy>2S5_Ym!Mg)g@BGWJc!rrz93pxDpi83?FkY{*nsw zUn^CtK3Oh4SWy)(VoT-;JtdTR${HGnYk}_D#qTH-Rz*PvjZ60=CMc+U>+&#ZhMYjT zj~&o=cgK@zwCmHse`*c$!nit^gGSspx^6GqYNsnmk!YX{44!*H0JAz@aTtdEx)src zeA|i$5-RW^TBT^~%-?$r&FpTSsP$$A%8(B2Z12@IyFI(|))C+|swh{#z3VD+?p3on z7C97h0h?7AsZ20HNP_vq?#rhAOgtyOTt>sn2#SMVlAOl!zcM;pqSx@Uvk*pr1nQB; ziU|0@Z`E=ftd^d|vYtu2KM>KNX(CuBo;Zki-_kT2b0uB@xT}lh;c)sb7yHZ~lK}6v z3=5`rqx?8{33Mw-3^1d#^<3iYZ1wszSq^V7qg-~ItQ*JRsXnWis~kPxKj>$XncJ(* zeC>~pN$utTc~OGB+fO6Ou*0picEV02Ns^CpAPXw>r6V7;kNbwtEGjCq^%v?WM49YY zmR}q(R^I%ND#;3k)n8j_Od2q>0yS%~h6#vGonskXmgKmD|5;U(7WjRtZ3sPIAD70= zc=0JvIgdC#HDT*)#^v%BS4W{bRoh_WK~Tybv>l^o?Y2{}Z2R)EZQ)z?8o4uydv~wI?v@Wyj)ts$_nC<2$vb+7 z?K!|>io!vqH}NVmbX$D+U}dj7;sOLtd~9LJZ~22YpeV6w?EE=~ND3otXleqW@gi_t zeaMcbmm57tr*O4rD#Ig1$!K>H0PB9^Nl7^)(Ep z|MNhGT^__{TBPFrtAGvOMkXIB)`&}?>iYr-iQjSXnJgtO)M#PpN&nHA3}$~=`)qT? z`=qCR6=6|}w%3LhDD$Du4EfE#=bjqKOG9wOoFj9`sqa|C-ouZ4w@1fK6dxA0I0Hh9 z*$*#+D@;W`b1xGU$BdLhvh9b`5G*|A8%+7vcX4&_7Wb0nfnFokuR0qP^{t?IF;hiG zFs$CSfZ@_ca$;-J`gK-zC>j^Af?q~!kc|19uR8k!haQ7eXQ$~Z z$eER|O2*)Hv1)M8cO_|#oCj(z2PKWrH}vKf?--eLdahdUe-ChV>)9(xDg z;(gK2I86OO0{agA23_Koc3C3hJMffZ(>OibeW-$;4&O8v(MJ_a-W7myyrE{nUx%b_ z%z`vWh6$3gzO(;-lY}t(n|k>dUiNVT$mr_%9CfCe|JRdEjO?NKFT7uFjz;P}_~&#< zg}*g_HgQehE1a_ibp||GMh6Bry|ejb6D}ML&c*mfi2omK@f(mLZ(TItZ6sR}|9DwR z8*cbF5O?c$jsG=}?k31YD!4VPle60n90L14AANr{{_(2xUP~kGe~v^L{ULtqk`%;0 z!%|H3A5iK$f6qMnKi=V3PWnG+0q?!zPp?W_>$Sgmn)FX__ur##{`yHje0wE$LPy&_ zq%nqd{x8;)b?-iJ65p|`q&5Bz^^`}4{x9~6)|mPu_doXgA#(Gj_R6>+x&Od<>qN(w za;0?|5BU9g;~&QU*P;J9^grS7?+X2Qg?>wz|EAo{g!*sF{eQ2am;bAV`j)-gvPH~k zbD;OX_4MBc>E8zF-;Vd+j`#n63v=kdwlEv&TefTwiHbYsl!zC;->PK$vs!rYy)y@f StHI}6u3ZL)zhAiXxlC^BfR@Uq)C3}(G7-dTsVG!a3I zA%?;*3?u8id%#l3r6 zq_rHW1#8oApuz39-KQn8Pem>1Lx6q7nnG^PUO}h)f{MKnPjt>VjEWR~w6U(X$-nTC z=P}>wqv4m%FfttAInAhXona^Q<+FlM-FDbQP9GcFKr*!^W|5H-6Uev;%>0sMo1dMr~^F>)F2JdHXeZ~diwMSn&YE)K}sTsbmk>JnG6N{B*x6&Sa;vyNHQ9 zsknAsz;IHHzs9!IoMYipwNg_}O;}}Zc$w5@x{G1|kyuSDL?CQjTy#7-GW>p{;Eyy4 zWY*{qfdE9!!Nedq-YO&Mm z?`bvzM|j08y%R;PS=Q$pC1NJW0tN7d0sUlX%uu%ewL zph<-@R{~s%jOv>xq6E3#PbGhNrcF72;i;ZT#iY9yx;S^SUM|{$$-P`m@U{#9Y^)r2 ziE3be?KT1Nws}}TXLJBun)>{tdiZT6YoYPWWekY184q|!WTXFJUw{4FCGPWV>$&43g6mMr3Z76eb)}D095nh>ccUG-zVd$?~YRb6kB_ zGFR{6(^3Y^_sxA>`qX>nVR|xO?doalakf3+s7@Dl2EvknI;VnZhxJOpW*mn&UwlRS3UB-|2G^UkfcLnM?#h23}Nsf5d3O`*`g zDm%)P%_X`*$=b_}ZQY$P?z8E)kgAV%?A&Fpp_&>&+)qF5q&+?HM7O#h9Ej{Zv4n*$ ziAA!K1g<)9zxC1dD?sa4WidivjL2b*4!&e*evCcmhvD+NjOTxOhVS-6OD?A=mqxl? z6qFWle$Sn0QQ9?YtY-=fGR|z#ZujGzt6IMfd7&m-02Nq_!GX+`p9b<4Xh`PmqL7&U=;JYyYmwv;1%-@!?prVf13~?&y%^p1)^-t47ULa}Dv#5ar?&_x27- zP69)2uG5-od|-$}HL-4uc=Zv&TTrQ`+e^o}?xC-Dc<`D8=H+VCz`?vqV(SIWDfPI2 z->z98dCxvnQR7Trxv8hFX)`vz09q@j=Go5HRA3+9Va5W9Uh54N=X^N!_h~>@ofSTC zb=q;gQXk)I1z!y@cFRNC*^*ARu9F`G#1kebl@BsQMANh%?Fc~d@n8}2GqH%`3kcfC zlf59B4XnD=Sfl@fo2pcLeqRoa)JxRYE2&6SsOKN4m|0FA_(JwjcUEDXkK30UYquJ9 z)2t$b{dhU;eR^6|#qeG)51^ZkT&R3O;&i_MJAO_8@FmWbiLc-O+=8u|Tc(LZ>>p%g zpSlXe7AV)Z)O)sy9x+mbb@Y560!nJZ=51tK?l zV^CJi^pJuiN1CIktnq>^R>KQzY7xTS6FR`1r=6&6$i*h<9!~;xG?nXozcM6p+(~@> zst0dnPo($i)Dt6Z5$r2w?`L$yJYPLp7Qx~=XFw>EZS5aTvgMk zc04GtLbf*6zQ0jX2Q1qlbFw>+j_bh}PuZ?FtX{j%cB`m7A>m+G=l~vBE^YfA0nHUQ z@xeZ2AC@ku7y+7u1)_-=YBFr#-aIev4Af2K1sOQN<3y|kmLM!MexWB6XGEE4ElZJi zUTI;>sx@)pN{k5}W1($hd?kP$j7z{V?kcjU@K0cm=y0 z-Bj7iSS4G64#vIzk;+4tl@7C2qDB*&T|cE?{l}?sjyDQ-3GG6if|%9fhJl^yOJ$e3H5Fk4IyS`W%%)4+kx2b$>_)7GUrqDj-nI)PhKc&}wqW9jdX0=Y0 zK|k;K+*{OowqysxBF~npz+B)0o8NVKNjO~v(^(5etFkU_t}Pzk_o74qB#UT%h8m?l z6mimzFJPRk^4C?$SH~~XP8!l^VTi89!-dNJx>p0^pVNb*!qv$gM%+6S{BxV0rUxgQ zsz|u#ekor|){<+w;I-gS7&rQi){b-Bn3UF8X^#qp=LglnWb&X15uX@ zChN*VAUCg&C2+Y{m2}A8P;0nox1_;jD70}Jm!K|?BhDI0G~@ifDG1Mh3&JW>t`L^M z^uZ(1c_<=AvP}${716pp=NMwr__k;+RvBxHMIW}*eU~^F)_**hX0hC<6y0jV#-wmB z2QWt5ifWp4dx0U>QDBxn#1}DctaEd(i3i^7qLU>27fCvnq{d=ibqj(dVW6wimA)2K zh3IvNf$tv@zs*1#faQht%W9AQ&)nZPO!GQ;aZZAyLiSRp|+edY~cbC%k zEcoUMsAZMCT4R62&7XHqS@4}H(L9LWA&$~ICd2m?2)`4`S$&t_n)} z1}N!Pl4b;TMsWN4b0bt?%h6p6;ca3{c0ElhG3B{ARp7Q*zxS#Y5MbD^IJI{X!bseFAo%(chT{3)cLom%U>d2sEvPaTJgPk zaNFjcbOO{0m?%MvQ3IHCg>F;-TWL-(nY1vw5z6XPk zqAJckwdq@ec_w=U=8WCw10*?VADMT$!whZ#u)n{N3QChQc} z6Si%mLVJ3IS`kebFakoDH?T&eG~Ie`txTc3+9%Nk9a2YpisAGRDt`R?4a0tIp?rT= z7-uM!(ZgT~*|7fz@O!tt0egC+TM@pgO}i5P(Ysxej9zV<@le2Gh&y{2IAqA7r4!p{ z%dX!08GTR_ZmMl$r#>x6y1GR@kcpsX zP@akb?4WTg2)LVMIq*RZm;2}jYQ(v)=jFEfuUT2Q7U$M{zb1$g>1T_T@!A@I{{8uY zSBjl(5iF3RWsabMkC^t!KTOY)zh_T4L59|D!RV22KNu;Zum=reg3TJy-A0D}0R5NM zA*b`vrbtGkghXQeH9j1=5?0rnf!OnVn*j)(*ZYeC>j;xiY?#7`nol?i`wy5`d4S=< zuQi^(5peb5S>p}^1Cv}eT(Qt?+|9B8*l_$GNwTVAxvtm%71k83@4TuFm)40ObCmT1 zvovE9-angR5`Jy%8k9IZ`MH=Fh=e&d@_+k+OZQ@0<5sQNI$(zVe_emW=yE0SKH{ZR zz8dacMdr36KGNH`iy42=9KD86_`QLhyPllbifXn_{4Yb*RCeHA+d&`o$F*S0y0w+| zpe@6?MSrXJ;D|STkuj=y%zu{3uve4^s{!9W^~vlI-X6FP zzcP)s+*P6Zhf+sQ7XQO;VC@RbQpv#98bM~YWZ;tz4Egh5=dLTqUlX5yb+2IX*{<8q z-~ET}47~B;yQ{dhM{uBu-;wqfLq0#pgFRR>?!&n7ull$BpSE*p=6d^sZAAA0L+78- z>DGyDp5wi?MP{PmHp5r_X3szD=E-2#o7pXz)Aj$tnSVG(5`TNn(?9eGxWu%TIQX~i z?5*IvG_p;95wHHkG2*n|7;icjzXo^${AafOU*k&PUtEdbZ27;&mB4S7{v~8T*>W4v z|GQiX{FKsvXUm@qXZ7FbN>Km*60(0`%l|d51U9wH|Aj68*SHe+pD4@!0#^e66J_~7 z;7Y5JJ(U}cHB}pbqiK~C+K5bLU-b1&UO!>5r5miS?1={a*YNH%{6d$W=$Kcw(Wa9g z@QU>{QD(ubxz;P6pPoa)GK>Yg$N9Ol;7jZQ3T8y?ED%(iqeRzX`Q5*jw#+RnVj#H| z$9*&JlhGR9ik_*Uf6IqCNaZZLi_fEf(EA{OU3uXZ`x4s*3jPAG37BA3ZgVF~^_AAN z4lLWn@N2@KUEXxBPh9%F&YKJ{Y7He?&8yS>u-VhR2CU3=c$$DE-GL6!Irf@(g5cFG z0An}-8vB4fpng8_j#uglomhLpgwan6nST~Ep^yAk@1CQZ2a%UxSb4U}`h*Ser2Q}O zfm3SrS7v;7zuP4|1^Oc{ftwa)zOmqkqJ8v*c~=k0DiI=vd}naTiXW5Mk`GJe!Y&V6 zjuK{kXV&M4QZ2$bOP`ikc{v#agx+%hniqObV-fxuPgPH?$&eEX;-Y6eU$>e z&}XmPMv_&U>0Au5ZVG&CExd4M)6|)$fHHK`zb+TbokMr3t{eqZH@3yi=|lYBhx9f+f1eXafFCmt9?d2b+LkgASUz<46%p;w%x)I5A)&ll{qW+MwNt)FC zx$#7#67c0xY5I^ih2pvKwZz_keBVE{1N)a<;L)UkR(uh~4r1~s&Zi4YfJaq0)I z4)!liT*$P=_+I+1Pq)bdSHT1_oh8mV9sElFzvZ}zG#0-MhQ%)mhWsg%K}rdBFVt(* zcG^G~$g_04gfAJw4EJoHe6z+gl9c;yh39;Oq3eV{E~7QV zRm2>c&UQAPq4X)Lr_9?2KM~`?JvNFO!UOAgpE^pk8`)J>-p~7Ls_?M`o5Sn}#U*t; z#PliR5<7k0=w0|g@|w6p@l)h6m_PA_JZ)0Q#k*bE8b|W=HnVrj_(Td-a_RWoLSlxXLcKQ0 z`Q*3Lb>iw91uTAH;K}5EubMhN@@hZj-5j}8uhc~Y_Yh}Ec@;E?y%FCCfSY)ML=Ufq zh+79Dch{M3?tb>??)#Q2QEGH`5wGf%S~gpv4yqs$_q2aYV_7r88-gsSjlBTg-7;aV zq_m2AbqQcSzC8${>m3=(ZMqA?0wD`pjw4CBXn3+q%gnT!Q`U4em<$?TXi@;CJi)?) zcD6-o0^f+oCee=l6lW(*iuqY^tP`5xMj#-!@;^zxU!$%&b$5LcT4B}ipD6|4fbRo6 zkvPBk;dF&5qkEtrbRt*C9;kttCxoa3Zpy4i-41@tiHyzo1U$p7yjIW|kTvG~Oj85_ zZ&J!svX#t|mK2Kn{mgm)8m>A-tjHA$<+(Kea{R&qHNgwT>1pSE;TgN~kHzEekon!| z>_c$4QeO!xRLN699AsMX$X?OaE_h_M3#fFu+7H`fqyz6)c6Ce2fT3}gIDgXLJ*ObP zJzg;X;koHAE)^rbW^YNpGXQncjbHBLTrr_Y*2SkafPk>b_L`O(ayCrPl%4Xs94GLM zbXdg~ekzZyB6b8EWZ81RO^yW^vOp?1N$pXpQ3@;r3!{4eGx$17VA)i5YW@{F)Ljjt zA+S8y3eB!E$WvGePalFR56$_yY}}!eOYAL^4`^AHO#pd^-VZr9f~hUtIG$(bWVHP? zeKaj+9O^ZhjjEuaR*p-A-l*W)Y}?pHqD1}AV{OZgiAExrlaQt;6yUcXWXP+#+Z z;Fdwpb%OG8a+|!w3SbHS7d{H9w`qo)f_|VPWh=keJ0dMy?a@7V{8f=cX;};{T+M6@b8Og$`Q4QrMiX1GRF0vn7$lV7|ko1%P6<&%~3V)j17A+sy zBH8A5;4gp05Q&`35gSn)`+h}d5w0;@`+mKO2#eqiy*UYvqUBE=%8ONL4ymq5RE*wZML-%c=b? zRaC%cvaV`_vO%L!fa({@3s_;~hf;Gsx%@7lafJ;B%4haCjP1jCdcR!LjD_pz$ zqswB{=hf`Y7@#}vqpSor$$wQ2y8NktkQd_-cdOx=n4>;>`Jcr0n=4l51I12H4^hhi zO15#u(qsP&)#qnN=W00r zkl)(zjsP%2Nxh`#`4LehmNFL!WLA(MWzkh$mF_XdRjVF)zF#G0+*4H6X1O4p3Z!KFEb@4Xet03fx6q-Vh?-OisTOkJXqVs z%K4-mNi`eJNv^fty0)UP?20Z>jodsRA5*_TBKC$72GyY-Tpte%)}M5|1nQ7imOQ`Q1czmJLz4emGVwkyPd-RooN$*FTF>JH&@3 zbiMqi9f$6BXk@-hN?#ln%1oTCm91QXd6li@tvBY;y7Z_Edh4Hobpn)@f;PPz{ooU$ zV2OYjpeM**pyxOFMo{s)M%Bg|@H(6MHEmRnyzrQ{{A?XxQ!wJwJ0G(M!bG>R%i5^m z;Rnk#+}WY0#5fXyp=!l^(OgF^W|RPLk= z@q?RIGoP~Y$>xc}BwLa|9tXVrbc2hva9fbZTX7%kkcCJ0qV;%75PEUQAZ2xdz8_A+ z_o4L!VE#j$(p&WOT4Ep!fuGHPK_%SvHOqS!Y9=ggp4U>EE7xZ(`qL6_Zlzjk*A-2; zT&m&5V}N)C;5N#;?UhPbB#<_RtcRh#1CCR!$wA_k>xVafgbK76Rwc6w29N!1l&a;t zK?0~VK1i&a-3r+&FU$Bm!AJ?=m5^CBHJ2RHYkDH`ty&|M zhh#O`D_+g73+>1yY|+w!YrV){0U_O70s)45o<|bhrrs;pF991fE?qgeFrtKvU6QsN zv<&37WV!Sow&K2D(zvO;iL)kEYl-8EC}gRS3h~lmWTu9kp!t{#qa5pO6%DuX)rTa$ zF?SSk%1lFqCDIf|=g+o{6=AuJqH_HMa^XD?JrZ7#TD?#CmYw*s4Qka!8vvQ{L1C{d z{s;grnANbPERRZ93yr>Ok&@VVxJekDzT6xLD9}h6h0L_wZ2*Krnab@VB&S~r7(I|hq*yc)670y|wTk83N%w!)U zNmDTe4kgj^-?Nc?q^S9GS_g$j-w?)CHon-!C%y+(!a}FaL&P#@61K?OIiv}(wmwdS z!9`!1Ws{k9QSM4#8M<8Sx5WSzu~i__qbr?@!&X1FDa(uh!Mh*fG3D?`UfIf~OUV*_ zYlA3zr55PM;(VjI-1(?Ll2^jq+R#RTgw6rBd+Es;x_4S^s+NPQBKb`9BIbxdUo4`= z&qFCKPz+_8*Z(6!wj$jSNVeM%yZUBWeEpNSB?OZ1g(}0RA>V=!F++_r!@!F8MtZUc zVS)v}j=!MOsF^T6Q*uk91w0HFMqka}YXuJ@fFF~oG|lD_UH>51)=-cilLt@}7DWOr zZKE--h0B<&;(;nu#Wd%lx!loN6tLzMUxg|sq)ehT<g8mD@PtOW4oHs)pu^x%F4n1zzc5wTaq7F z#-SF_N0by=C(w8#4B?%SxsU6?eYuX_The~12~`RifQG5V_Fc*xH_8nA{G>2Bf*IoPF31{%=KAqypXXomCifEF{wS+j^R*R1Xmw5UMLSro z568f}QoOX3glrUJC0rqT!q}4MuN;z0&Fxy!#4V zk5Q%c1M6h2`_=Y7Z60(Z657Ogp=*u>!Mi23*%(@`kjY zjrTCb6I}e~yEs~X2InnbCp=ME{&-j;!Y$|rAYpmkz}qWTI4vp|a)VU)Xck^g&a_8rS0cx~{yGA#dKfL}@d<@(eXudpfmhvs>F8v+TQVTiTRMOX#S; zU&}k6UR}+M&!bJ|Me&5qE|8+8K#<;44L8l?d5Fk-=>fJZiM}aN+uQ;mw{sG`HrCr_ zpofJ!vfufC4I{ewndOZ2baE&*iyqW;HqDc`q@LPDB{YgSo*SJk%b@uV&JWtw{Mz~}f?a~$+CGTgoxUT_mZj^g$Jah@EJ#Z6*7c!5M{|ce5@j}1)(1C3~J%H+kT~9RNF&1-4(A9LPn9!ND@f4396lpP00vlzDtn}%R zsah|2S2pkz;bA^K(3q7yrNSw43K@V63 ziqeyhS*~_e33tNzF!svxeYVKp>9`VMcOBEac(&mjDAlJfn43zhYZ}&%mBWHgejjI? ze|Kb*gU>{XL$tJt@6j87Wc2)#YAa?4wNvisu$ULx(a{+fPn_(NL|XejDG3Hl2L1Y) zEN`mEjD)HblpC^2oZSHEHY!S}j0N96L<6P6NUn|x)E`r&{bbw6A!;#efjIZ1`=2yy zkwQ#}D{p+sD<4DHptFA)A?LA3$9^`nw9-M3EoVeAMX=N2j{)Omftuk}0K#?P&a(}u;PCd{9; z`7gQK79IoBj5E~1Y4NJ{Y`UW~pr^=dAD!*?;0I_qMGZhvjnI`xG)H{`rJ~IiiT#9C z2ZRC;D+-{a7tiQsk%K(FJ6&78J;t1O{c9f8M`?B;5Y|e*Zjh+~uUPmBNYNEbu~+$@ zk|=05uIj;AEgwwiDkzm4IxK{XiHnL`*F5~DeDa>=UkLP z$5JS7+@DeIgz@0HXTiFCr{vQWu<4%$-j+36vL-L)5+Vd8`#8xz))vb^6mo>^a7S10 zd+!0)A>jSED8aq0BEPccfuGzRKTF4KAA&H{U@V&nt(hmNSI2!D*@WGu z>d!FAMLP=a4=;huvP~= zbSLrjij|dT7QYo5jq-5?ldII34OJ!Ikh48?lz1OqFdRwDHxtmhhG4nbgDj7_+^Y7< z690(dYZbLWrn^&$Zlx3PVYTI8l+|;v7ue9li8?icgpb^$I~CZhj{FodP-%_{Vm?0~ z=*v~~Ur+~%X%&O#>|ZyyJRBJCtJTJJCNUdB8x*DuYSjiM zLkXywWv^N(AFtrS-LdU$9-`uh94$pQ?A}KijgoZX4({YQOFO;O-WO$6fyEpsB}-sG-4=i`KtJ8f|LYBej^IH(mjUIHiF8==5UaF zT3TXOcrR69JaHbFmj!ZebwC~rv!o1UtLV9#LICm&oYF`r7$*U< zLC^+BeUlA{DHXZXO0JiAT@z}H^*FsdHCj5p3a8&qKe7rb^DR&rn8J!@*!!Bu>`(Ta zSu54uV23n-8Y58BO+!w?$o>%~@%D8$YImFyG;dqU+@;+2g*+~h&pTS z<6I+`4fT$JPO(;85l;UKEyDs-JT1fPf4o#Hon1k(M7sMwI#sEFpJ+V{Eb~IwzRHd+ z)H@hufs*-reW2~lQkwm7Kt_mPy*osHl8KY4F)LP1qwqK%J^YMx9loBrW|GOZ6TO8&JxIc3%r+7*lK>@BxcyttZU^?+dKo z2x{#EIHcu}4el)AX{}wMH#6j3Y>~ntdE)E8*vw?b2_WEI9~he`NxeXqW^t`s+w^#P zwE!PR$h_1)!f!qylZ+aomCaPD>qZUu&V+J!_J&35t>$p9!Bx>(o~92leFxJKjkXWc zSaKJmIQlgV%gC#PeoHHNb!`*j#!pI&`n6MRVq@byn(v-ryTo@}B+Gg=TVhuWs44-u zw`VDzwUn&)y^E_X)iCgP?;+P?Yz8fuvIP;BRWWkT`{?-R5G0 z;efCJ=FlORe*sOZf>ntn$Mp4odH51clwRBft8PWqn~73j8hx6q(r&jEXM>!-3TCkX zGjb(is{7iOGXrwpk>5p>EiL#9B5-8@c+>K08oDSg2yc~Fw|t>r03?zu(3i6vzIGbK z2K{V#*-YkwAOAu;JpZtvny@YLOElg}DsL_57XS(8QfSP+DZf8Y^9oq^{g1mj=(-Ug z!}14L$J3to4+tdWkWHSmOTju}{eKPeQb_094cDVQ_s1BqtIDdfuKb<30z_(-@ z6P;K4hwTg;p>W@o+(vZjKON($&eA=4-@vcmTD=7RX*>T*TnYRqTpUUEzt5E?@24uv z6tV+)iW?akz`n%d(aWjZU`=SGHIeqacEUENX_a76+lb@~1^5cYDm#9T5Q`|As7%7josVW4@_!yy5qUne?3L)+M&oK81{t0% zgmo&*_}+pr2fl5@AqnOWzJ*nQN)_eb|1^G^YC8G48uJ{ps0rUa*L`anwfE=dRIeV4 zEEEeAV}nEFZf&O5fnO92xXm~!RlE4X5V8>{HsNkkX!ggPf=7Mu$Vt^y_mzRYPWw)5 zD^!3gxM$=sCOH&)FwAhfdgRH!u&V-k17}bFsMd)g`j314sQUh%)rvPrl-l^irtbhu z-|SDG|55dG#sy!ptxI6*PRzmnT_W3|y_c949>gM3)W&z<-=GAy<3_D`_xLDkhFb@-w7gMQW>{@dswWAY}i27rUObJVe+Z`Sy z(Jxy=7`72%{{sK{`ES6T#dby9Ber~d!N)T*id%}?Hys%-y#GuZ3&@5te55ZdkC zk?Bq6cq{ikA&Tx312dk~Bx+K6gt(E*&6ZNQJKf@dW=`^Oh{T8ooLc(R zQs#&4f+~ACtkxk=VvvU|9mZ7^@NW${HqS?^=aySNa4z04LvbDV6l>CLJ_w0@j{k1^)6P^>%OB!2eGQw`;=D8Dw@=6x7j+1@IeS)bFdzao~X#}=Ti`|f$ zi#~mZROfAcXyOSfkFUpAslv&3tF~7C7zA2hS-oAr!~V(+L<`yO0qm~B3*;wrr+L#N z>vUvMdijd9$J3NFN1ATj`A3?%BhAvjXwFX_vSI|)p%#<~1Q^kWdAy!DoI-vBMfNC6 z3{S^Qraw=Bncl1!Z;f4soEHl8n=scxi<}?%@GhI--Hc^bWI{P1cJ!UIwZ4*dW~h6H z9zo7odJ#Hbk=}#^@cwC4Ji$qoi+6gYWS?G-knqjbzexEz-MZB@**MiP&>Ku>Zvv{D zhVDNhU#F|R>b+pE60sxSN2*D!Y~URdHoamT{Q(7U`QTeg2ruW0&~LAhH%<1srr7L^XK5N!?VY8eBN9ttz(+{o8=r1X@8aY+BS^h7SNM>C zQn+JKpYLdQ5QvA8^OSAjRWGQ0ju|cPDR~%iujxX8O%>+05Gvf{ zUK!x&Hhk}1t4Nxxp-XqCndbb$Qzn7u1(+5#O}Nvt_K0{zY4Uw-Inqh~Kv-@S9gB9} zB7kk!!Y+*Xb!fE)zpFSA)Pe>Fz&XS3Pd;&y`^!+gfER1))Vvy&rl$b|t49l3F%rhD z*K@hOE5N!D6z-wau;iwTYevVkXaoWXN_d%>baA)|wODRmawA09jSo?l41&+%1FooZ zYlJ#X63>WLVj#f1yPW%-?=ju%K~=`7F&C=IPR<+$`IX*@z&>Abk;v6ehu`N$RD)sa zw8rCeq3_Bt&o~3gllN{#SsY(_HhCw%>ouv7`9UKuI^Bc6A8Q{Yi(&;Nu4!3ju_kFP zPri@)S?xKBOl*nuaqBARiZJSSjMB=%WdBvnIuY3rCyeAyW5qnCZ@H*+dmE+xLd91V{LM@sI{_5-S%hoBd9=FF*gTaiwN;V&PI)N}6Q$3%zI z=ck7Ps9`PFmyq}LsI2#702m4j7uzV-c8mcUfnqPvlXdUPA_OD&s-*xy%VG=X$+p0k za*eok+XqpFpN-xs`%2ba?wRS)5P8+`5!IGba_6zcY?wW=K3Z(m5W;18KO zxMvj^)_<&Cb!|R;_#=N-^vH|2Z?y?A_XaWH9HgAg=FiN(nrH*S0D+}SVc%CEjox|# zy0Wo?Si%|9>dlnMi$Ylb$x)+ygs`AG`RCq=_EC9XjZPGHVbl=1cjE3&xqd1nmYb_g zN=lM^%mR_pPTHjA4t;Nf>t@2CZg{H@?Viwr7t5MTh^A>i%$YRMvIczr9gl3%zw8a> z>ZM_IC9{!t0NA$K)AQ|>cl>&%FEVFe%@hbfJcSrpqvZ&z%Vz0)0}BTT4wI%}v7AcS zd3!S%mM+1V+EN9U3rV)UD7WDnLfly9t_0(52(U99I!} z-XBKy<^mQ^faHXDjktx>KUnoJAgSu>YsT@s_%ivC663gn(-$+=lF_PZTu6Hcl>0VF z3qL>ZV5qM$eH|`0;#xen8pWZQ`@*5YC(28K8A2A9?dLTf0_zM8a=WV|pM{9pXveSW z%Y*tLd{ZBYfYvQayy~_`W)JB0SWy}5bm536#&RC{FdMJbrpUU)qR51BuTczN>VV2O z$xP&X8OgEzmYnGsjJljapxE1D*ix^X5{GT7U0eq28c7~Ab4%7LHshIX{9nY5E-0=Y zgM&J#Lf*Ud@?g6qHnrb-kfYaMDYT1qIe|j&6igR-q+F#RSZ~mxzShgsM;w| zOz3Q;X|%fTiX(pC!$vjZJS*7o*Kp$$=iaWA_eKIuQj5H}rV^OAWk&g($pSG!pu7E6 zl<)4Y&`xm(Oj|uwE8|?~)9#M!2_}TX6%JQBV}7}y694P)PKAVUP|-4hnG_Gdc~K{n z!%4bVVrf;XW-J(O6WAjZV;aQ93^AnylT4t;qi+f~nKRy6Osj;_p^+Te?8B=b9BEq4 zf|egF0EmWxZhbB{w93jG7zTGw@A}u6=73mur+e&Q_`uCoCd|_HtkbCQI$S!0j=|Uq zc0-8*BZrEaq!YkZu=9cio3+|!T5_fZ{_nz#9Kp)&!236eKx_>Zfo|*!_R;5BlzZV( zg45#?f9KIpCacA;C`cAwH-$s$N!}>`t`}z%nDO6*^_~E^?p6@Mp!Iqbx^s1@YQ7X| z*<0Q#e=6=uOq!%j-e}MM#Us)V2sPP;MiQOme^&>N5Ak7j*2ma2#qSByX>iR7EWdsK zJ}}d>)7}?dS)5yp4zXM`iCO$u5iBVuq}e^r5&iM9{tCMLDxB@H+f=tLTT)@GnF9#B zXkq}+eX0)LkoV>Z4dLWTFH(B(wQCJF9><#Fb>*GsUK_+rDg@(Vczec6>?Sge1RwUa z)PF7E+EQcmbd_+W>x!+E!oCF)!^dy#{`-F zgEM7Yox@V;<@$P^Nkq41g#YNvJAM!IvIKeKyHKo$UHru9kWB3^V)w!8Z2Q?Dc(28{`ll>C|LdN zr^L9SP-9^U3^vE2)ymd=yBi}!B`-ZUb3izNl>UrximQ$W%P>6lJ+e7*15q`hi@Y&4 zKzGn}d1w4NC6@7!L-v-X6=7(cw_Kk@L^lrXRh3SobKlPmT;tfjfyqZ$h^`&GFC6Kx z@=h(rE27d&Bg6U<+8z>=Dt)oB*V{cE8Zs574pwga!Vv)`jTRoKSI+M{XD(_gjpcOv zs^5AsY3{;OGtg#XgvvHVN@_EUp{0T%h-OLzdi(HRL9o%G3ce5b?9{K5bxdvgo;RS3 z^jICb>j>&a0o|9`EcNf2BXY)SErq-~u1>!-)jY^nm@XILzN!|pG%DuFNs-qxsI%OI zqUYD;e#9#FQGe&w8NRJPu+GT_Mk_cHn{7%m)mV?va{=@=$Z>bNPsNZyZ$}_ld`!es zl1Qb8Wy6Kb+c<_Mu&2z7u@WbV~G^s#j+{JoUXs0q%>Q$&SEH)W1(9lY;5PUoc zpZ~jC$McnboN+3<*7#MrcXbQAYJiaA`i7d_2d=L7^d2{U%Ux|?PXXapLmrLvgGx_? zL#Utgr{|Naz*t4N_841|Tcfetbx}iGhDeU5%~`>nD4Y1zh`-#cMM<&JE$MLnU>!-9 z42`|ImO7C@OT`gpF9luiq{7P)^vJLJ({Ec1TGh>T*Yk7qs|JWgFw&rcIGO^kTt)0p~37D2X=~tDG zr4#(;z#u@8o}6kbN|PQu^Jh3vyoL5iXgAOsn_U`fV+7MiktDsgl>^P9+`0dnH039?vQn$eTZwx8ec zKyr+2-8Udq*0>o|Z|&_aBVTyS3We9bHKotod2SO1{`=UBj>m57fDD@)4s3lH1LSx{ zG5&r9{?X1H>mJ!O_RRu(9T4 zr)?~M?N5;m+)d7b1-D1^gx7g|HmBY84CsD9YL_498PgT#4*SX*{?y{D!Z!SMGm=jE77C}!MgAJ;}f#zcgAcU^XB>AvZ4+T$aAH!OkPvy z*lZ8__0~x`z~hxWDVbQfBNGZM(dk*;CSmRSbG;J#U#baq^=(go_CDUleq>zcEY|jd zX`E>9vtJGTn?f5PdN$vm*IdB7gw{hK??Ko~0eUQxi2>+6D7&0LRSqjH#>59S9qZj# z`HBy&fk@MxZ(&-_Ek@D5IkP&Nxi?l)lyv_CHc+g|bMIL6*9?TnZ(@M=0OW_+o59>t z9Z#fKhnc^HB6xql+__7kRJCxRmOEbfEev1@!A99;^5CX>*-<5bgeHGClM^i3@o~3+ zASUBzg9kFNKR_0q^QZh}wU6cc)4tCmZi|-+pIwKiUpmw`ZN-l1{*%nk=VcW6bO{}v z9RKMKKPE$mu`J~4^!5G$KeQ);5MpzPAdzU{5#HO%z| zAFk@UdfYKvP%}nJ6PSMtlRC<7Q}f!*{s?N2Q2SHVTeS~HYNt$69ZLo`TRXPYp_A>- zK=O0M0JSISHwk}cHGuzEZTo-TC;mTe$oRajli};1{X_8v^o@-f|UzN$LO)ddq1W;XfvsBCD6fweaRe zO!nYHM$&lJy?x0j^&ba~z79lJfxj0r$FU^;=-QmfSaxkTlv}&V-V(ZbBTseDQInTy z6cBeh+$fx9F1*^RFk|L#D77aLcB;n3kMx*D_ab^-M>5Dk=GvQ(+kL>hHkFNzxEOQe z5@{B^RKGVuN^rSZNxDBcp?^;Pl<4Kugp9lq3t98j1m_w_R=Tu`WK>_~!>mWkg9tMm z!vcQB(!FX;=^djR0ZO05XU3nH5%)!ko%hFc*>bc~vz||fu}U-E;-(SUo%=ZS{nw%&tI59l z9$Dp|k<}dTOlS!5UM(}D^@orH!8Qs!(0IbgLi!I`Khsg^q@{AA16^z@UMQXBC z&q1c;b%@NBg9+Vk;2^CMKL;^U3Am~O*RY*=I1V#FjyDLV+|;*#ye4MsOr*t-rAp%L z=xM0_l~w0BX8dYj_Rl(hGf%#1AbIEE2gKvX778u$#r`=_Hw3XQZ)95lkqoxPM{2m$ z$deX_#oV6oW3G}po#}RvZmSyt$%7RCZxFKE408hroXIy_`!?54#4Plq0uV;@>B1@Y^n1)bb(_2ZK=DZb>Z)`E_f<;%lOq(Jq3 z-{KGo`YU%sEnL5N&_%YBX(DKCkP={;mvOLDFD_XW(PF_#iZX~CTJ7=LD=M2;*5=0r z{3y;;Qg{xf&CS|I3$Z}PC!v=25)kdU=!iuhJc)LJ6nn`PB+QzfLLay%+eJxB(%qV# z;v~IYGhXakyuMz^U2}VF;1NwE$JGxfpCO=ekwg$q6*Q6c@C<=P!rY3+J5xT7>>Pr@ z5!`zmCrQOsFi$o%e&|^c#|2aZr?^(z)yL-r&2dG^i{+sYM_IfpED3ClMa~=6YhwLv z{%f4EF0bm8V3}i0q`o%)@5#Po_lb04?RzHB#jZt4Asgk3#Ke55)PvGJwo3(YcN)dC z^M#4&GyPa7?GuxDlgks<3L+u&!RL|rC|63^hPTWz2(v}g*`iHx9vCR(0k4&NE==dO zHrmuBG|7?iBnUlaGD>e|HIGwHQAhK-d&|pUA)bB5!Iq;k(trur?~Q&s12%|F$5_To zNz#;OSH|jRrZl9>X^SrR!cFcNX2~H=nfG6)<49OH5^y{|XP9K5S2tGhFf1m}eQn|v z4McNFSE)1xc>t$X7Tk*}jdoko=D<95uxMR&vZFr+Q;MCNtpkbC6u+@+e#JK&7zRgVqDv7k=HErj9z*Dei6a+BQUy3gaoG3Z8Bz|{zfndEIwTKH!zg&~ zamZW*9IPWXI&B`bNDj;sY?(6PDPydaQAioDnAH+)H2{F*Py!1I!_sJ}Kk37Ji5EDol+IS6S{~)nokJ;RU zZ7ufl-k>&I_5W$_yWg5hyR~&JsK_u@6hU+l5NSgb>93B0h>#Ja6QUwD6bS^Rgl)qz zQbZu3qf`+?NhpSrV50?yln_EFIuHVcB7qPSNb>FIIp2BzfODOn-d}TFu=ifi>g!(j zGgCOw48mYbihu!HRk4jRECTF%nZHZBaUIG4x3C(DmT_Fgv;uj$v=@bXiuJ`0PW$c- z2)iLhf4h-z6Y)~a+qM<-B1m{MTfe}#IbZilLuqfQKrrUaFVR8yl{o~!cJr3-O;Z^Ia_?sfLPY3}1^YEKgmTWJ5y8a}6(^n9j&Qerb!O{MWF z_^Ce;LBaaK{x{`S_?bq!O@vzh?ZC)FYEn=}xWeSHcZw2YI$4f2D)K;Kw%93>KILo& zmT=^CE5?9}IS70YZ4=@m;>LRkFW!Vc4apZ<;8BmMEykoc;gRyX1R6vvsDhcToycp{ z1)JcSI0;&JW@?8k|7NEe@{vnqIa+-wiu7n|%PUc>ytx$*T&Ve559Qd=i9RfE(PX9{ z%f|N62c9e3gWI9YdZKlZ$87KbJ5x6%adDu)BB(as+I;Sbv1ZnU47Ncu9V)6!_zP%1 z5jQ>To25ciO16svDd8%os8ynM15*I|!L;XT4{7IaAGE}87D?dZkNZWX&y-7MvlXD- z<;SoMoZ8}|($@mE*>U4C=Va~Qt8SiX1!3Z%l6o)*)LlO97gY@8H(Gmre~(d#MsG7r z=%1b~n-^u}CnS%_<7Ylozp9B}g81`|3fKv2>6Rd4<4^*V|3T~KIst=iSd1b`foV)b zHX5{)rA-CE5!=`y3ZaPU7Sht$vlga1g5_!;4K5Xu)%<2tbI&}(hOO#r?MqZ#56n-w z7a$Pe$Y@JoV9xiEe_39>Q+6I?FsA)Rw0YSpEO+=*E&~{g(ut*4u+201xhcVmAr9Ft zyVjS)S&jGI8LejA;@4iML2GHW3}t!#_2abkfyWt@xiC@d7E6!Q&-aT~Axjyk7yMgf zt~@{Cvw-=GMlL)6Hm!0c`Ae>wi$w&d2N=;k!L!`>;6Y9|6|-em!EU@c&*z{09CFb( zrr?7i;b4jAAO+GkWQYV4jxeN*It%gC!6vYS?#9H`c6+IYs5Iv8z}QZAHD&3^aWn9r zaKxfAr>XmI$1~@u_@(*a`mYr8!3RfsV|`cgs=0fvNk_kDO;YC$^jEXsqeWASNZD7 zUPUcRA=|FlUR(q-xPF_Zi5P8A!oVG5{u229Q=!^zu$6dIOP!GwW*YY zfOBu@$)39=lZ}hkOF1f$E0@`H{70~<{OaX zGIemOutq$H?B_BEAatR=x%csOCws{v;G3(C9U=Fe4|b(v&(p|r4QP-2H5~J1_sbYN z{rq|>I}73o9h_v;g+s1`nR%j@R4!0Vy~5;ZEo#wyU} zZ@89;REdY5x1@678c5J7zN4n(VhV#VxBtVzu^=&OTKroM%tE}Gtz~?_f$DM5v3IF3 z_obt1PHk*NgcaBZ1*-jjdHNjOh4SQI?ktb;&a&X73cCyrE8wz9mHU|c>o$@@MQh{h zMc(Xg`vJkn=J^*|X+E-UbYU)Y`Vq&?FV6*BEjnC?wP0!Oqdn1vwQ*DCWA=chm7mzn z?cIJNC!-3p(|tns>#0y`f~ToVL0Z~zgE??1(|{B|U3>(9`bVo+_OKnTRz8^plwDiH z_)+{f2SB%BzIJqZ@Y@vaM(DF%N^(6_wWTsG5!SB*xfg$Bp^-rcN(*q4elb=P;_s6#3NKEEGh1&9V|8gf^sRB4^;xu`9n25sjGr+1 zs(_!r76UGUyI6QRWQstp*#@!mgb(ayr2Iij<1=p#QW-y46yJb}5sW0p`em&~n~Lw< z7%t5DN}_Bi-Dv6XyLvB1x>LlCkydAJcmkcGchgIMDhX~!L+@?^QIMLTzdjJg-SZl8 z&l8)4kLhZ6Jp7QT+(%uBOxGWcE3YTs(V`h(XpY~(8nge3jTQNgTID_{e6)EeKo)Dl z-t8#<;*V!R~YmTNLDnw*#)!2K1@P^BkTE(Jx?DgMqZVv<2@)IySy3afyj4Lx3ZlLLZ}6Dq9Re;)^H!s6G{RmlBO*$d5E%%t<8kC2<$3!`J4m^3o_ z4@&zd*9~WbOFD^pZ=!X9r6CXRo7prEMe`Nwvw>i-tM67p=dx@DiaDY71(gi5*>AB~ z@z{i9iP}pkM)+GZjp=VgSOltic*`JuJSPlJExkD_Y7V9vuLZQ<(?dNCc__BP2FE^> zt?`;#!KR~5`bbBE%O&HvP_vWMY>*CUi;iq=FR#c zPws$c*p_B&;-(z@so0CHR~iiyl9h@AT8UJ}v*5F41n$B%@`oL)EEtIoe=@>M1D4LvM(#QkXzNBQ(gZi!CGLMzRq^jobmkRpID>*(oauk= zH5b6`>n=c-IE^K!OCo-gTwgPz=Edc|271;e{6w-f#3>JNW!5aX)$KzF$xixc01gnr znp<0Ld-_)eocAmzaP(6(5lsIzVNm*A_ZQ%XZMo&dKqvsLYxB7U8dc9Ri0n&jy%dn` zx;_+?d&K-JTW^F6#2ozYxe9`wor7~b3~Gb2#tBSSw_q};N?L;?cfq9yc*&7qr)Xwf z6?C!v&HRN)?GVjJd$fz=jR?BeIYU=X$Wu%+Buiu!l<@ZZU!P)M zKYR!1I@oq0y(v%8fh)D5XPs#0?a}h4VeG*w4(Tnm4-8?;&G)Y|gg*rSypcXe8e}VP zxV>AfHIBsQ$oUP6*hGMwfl$m~VTW8F(`#HymrC-HBZ(}DK5PA=-d+8o+esqgvbtc( zx8p;YxQ9{|5Lzfv4q<-IN|~Jc!SfHjm_4yFuP)zdy|eY;$-WC(F6|kxLgU`Q6!d$q z+t>P!cM+)qdpHORnXm7@*3MPW^Vw6BVA4n3a%HMf+@A^5BuI!>hsbC`XJbERsr{-90#^Fy5MI;eSpgn% zPZk_`FlcE%C!@;T&C3H6NB10Qx*MIk>F(y8n&2%e6dbwr`6peBYkJDd(cseN{Bz(4 zy|--0|8~i9n}m!fA^fc!3SAX)Chome=$K7+KvAlN*tstb)AYYsyZt5PnlYj-mj`CU zEW`UVe3A|ZCMBwzF*(c5ka96nBLB9AjbeMqW}w7brNrH(hI;|uu{$;MX~0K0bLxVzBVI=yTq)c7#H%HUeIq1Mxo17NGowAD6PKgc^P zss+p{EQG2?vuXiu!kUDb%H6-~MP>^=#UvJT#5JnfrA4L|65-XBg{+yVG=d?kaS3s( z#8*KJ@cW$3DNsomi)0jC9Dp94~>qZ4{XD}s`M{bF>ZL2P2yE>QV)?VllOEeH~ z4lZ~u>!4;U+$S6AOmw{)eWje~@%w+|_28VxQ_%$oW=+*>Uj-XZ4*b9CI}g*4eGV1-Pp+@qcn_sc z&%0E;s_e6ERB`@n>`j5XX?!Uw>XuuP(-`8QXVw`|`N8zSFaVklklhA=gAO{4PWirI z0i{#dQ=Q~9&W&6Q;jiX+V#gE_yDskHdKxTFsketw1|QR|Ltj{dn8~@7 zMZH*Gh1e|(SL+7sDW|x!_L;eC{j*On+$||LYcA`*RWn`+lX2;5aa!Z(ocCDPTl)wUHr~#?3#?6*Jvw9;rD142pX<~G zGj7BkOi8yyo=Buu9djTQ!G%y3pE>@^;T5ZEyYs~Pru;YR4Gz}8_7#6GrP-NEyTNTgML*v|Ji-caeS^MA1pe@-Be57cpco|njO-Q zlV=Gm&$V1g3Sz)Tzp*b6gLY%j#XtCXYPOPCdx8NG=@q)dZ$NfRkW=qL?Nr8SFtcSb zxr9_G9^gfh0p;{sE7L?oUeg?dwg`>}>{NP4gz;-Zn5kFSP%9NCeW>C_A@tPYSe+3E zKX{Pjhc8={Dm@S*0e%=lsZKYjo9Mc^ssjFO7tTuB*uWirx$#eXeeVkCw(*TxqD|O7 zKBC|W?s4CT7*LYgMyQm_mOj?49Xsy&lsKFLzO_=4N6;?gEBWT^Co7XLnyIuo%r5ph z9ZB5DiqL=MOOQ0KtnT}Zx~jkTcvOV2vfgZI_NuB20SzCT=MoGm>u7O7F?TKn%_iVV zP~Sfk9Lg(gey)_v9dfm}2xe9k>vsmIytToeN&vu=qTdHSsl-T}=38V6P_ywcgQs2| zWxD17(a8y0(oA!3){*Wy{nvnBE2SfU}Majec9CgdtslrkA z8$-?|5X7ZZ)R-T02Eg@cDZ@JXHRBsX@%)&Wtm%T1`Ucolp2McUdUZ_YQg!wz>`qtr zSAzRC@2qBI2|H}01y3*dYo5OQd@t$RNvn$v7YkK(KD>6!%446d)`HUK21RoPzqNTh zj~@M;^&$ElQ!jRLzB`x38XZFwtEUe1;&28iNyJy18plw z5&E6y3TD>kM6X@RAD~vfAQ#I}%Cpfh_7@_$4Q!50V#|2KMJlG* zp7{6rr*R=yp9OqoLWrkeNd;@)K)N*Y>A$tj!~nsZ4DJ`v?7o<&Hf}gnwh&jP33t}f zq3JV%PO>Nd#KfoIf*f+z8|^&Yu0uj79C1PlHoB6^1j$3vL}&1$YK`+eZ>9B{9>-am zlZk)CE!4qQqYhCh#&@bv3rh9uV&)PM z&wER9SqRQvi}*^TQSWw0|O1^USB0b^9p9cdz)mc)rveWOw@-tHI^E{fUx@eYH-b#XX zyx`dp)QN?4B6P8!?&_(MiApqD1aOVvZN;$QD$G5{z&zpFBh-N>A(-U}T1ZWgjg*3f>;XY4>pK_kDnoamAww@b1vd| z?&#%HJeM5T$Qlrgm{QTwuO)31YB4OX{tB`^T<}_UVNZQM)yI5L7@rsCH>~=aafSJm zIJ%<=yVe^e5+n|+RW&uYYkI7=FP;vekIh}uck`2LjGSU5P^Ff)R$o@BbS9e!zOT9z2Io5sv>_HxWORfo-OroDhBIEz=6+KD($>n@=6fv%xzM; zhoX1%BGnjnd#X&9psZxGzF37`_p94GWmY3HEi_XBcz1)ujhd@b54(58w(QS!V9!@t z&R1NFXi5|lBcmJ!^$e}P7ao3dp8Tg^XJOVs?OgoqsI;7@w?X6*E>Ah&&xG+cQs%#eI#5T-_H(Q0SaS5 zCcJh02Yl*ihBp2?e-EIonzgSM{W;T!EP~gF+%e=uaM-5vCiw&{fkMAy{7!kZCIJMI zYqHkDf_t0_$)yOzxwR^{w_%g!^bT+kS{HYXH~ zO1%x{;M8ZyQnU=wTgpMM0fiosQQww4S4wFe2>Xo=wfCOaRDsaYPiZMS;N5Trl_6b& z^&1;2I!XCRUt=8ohX-okV&&`FpsyG;&MyNeXA|4CNT0-?ABDgK`BVYyQRQCfucD1b zr3YhSQ={P&Sc8eSG)eLJL}yZ%{t8Y&+bHu=>`$09V=GB50Y%Egu5N*y@AP`klp#)tKV@o3%4ROD^ zijE4u$EVLY-0{4Mop}F_`RJ&iOf=XPTu2UW;5f&8BVct40ysWUao1bB2!79pg$D7J z*skS-xGp!D7a}A-mzNo|mSiN-fb9j2n%$wn#63uA8V00 zO-ERYW_m_Ob64YDj8+c0_i9?#hsRv7hpoK7ld4mSAiQvbxX7+3u?Q@$4rqtR`su#B z385;%eHcD9B|S%7s&bEVmgaXfC50Qmc5LG(d_gURAQPDc7gpQ`=>8EvyXA9`K?LJM z>5_TtGT>Js&%EAy8XVSo%^Tq~mpBf$E@AOa)a#+LrFEW*T_>Xj{7Jy6srk=fT^Fsa zcb$jV7rtN;TI$oVd6tP$es0Kmb2Gr2KKOTKa9q=^pF$?aSt0C;J!LZcK8)&JXIN`( z-Eno#+tMf6aeOM^89UZ#>oERZHv6azcsn5JUo((#_>t~&BcUR(&5rhc(9_RN`2c1EWDQ=if zoZ(u=p1Exn(EVW5*}LhTNPs4nT3J%y6!S6#dI#v-0nocE4PcZhc4q`fPQMv_&O_f0 zH|z6p^ou0vhRChS8$VeVmi+2$4m~>kbXl!QdI$Db(6`6$y3LqYX>-kwz0lj9vaxzR zYC}1Iy&iad{mtl3EGnlKd(~<(bv<|<6ySC2K*GZHDgpJVmr0+Gv|q9~cmeV7{mhu! zU{)j06?emwQ(sMsM9bt$Bp6^0)ygFl1qItSj9iGl{q?bl_`-Y~-}C4j)Kj96M0e*z z#&vlFvzx%FZDmd?7gR8+XDpWPb)RT_6yy!l^4l}z`J%qu=Qym%e1*Zlz%pmhD3y9< z{upIq&~#A* zj5{gbV|>}%mp;7@VwRyXh;;?Q)zq~@c+0T%6fKO;om|6Td$1B+Pv&`{pdx={i&MGgMbQ-inx6g7GrGy$QSg{fy0QCG@Y>{i<{wg*fL$ zGJ*yLh^HKT11L0AV^$#`c*k6U?MkMZn3~@nmXe*$J&%#e*B8kSX|J3SBJ~bV<^Cb& zRsn$W1mx)adoM=75lcy2?N1J_yVaYFE59F60o9a+C|vO)KF-rAh+6YJ9T(dlzuiG~ z^GaJPqg7%4h1D-xckOJJd9oPX7rp!mv#$hkcw+0P+_S`W-R9MPh#*Bz=yOVTQ9~(= zBQF^Co*;(`!h@g3{YI%+duLcxsTtRwE>W$RVT6cfAza0SuqMkgSBg0gct7jo zzJ{E(ea9_FHii?HffM#OH#WXViP0E#_lap!il-9u;@!28-bgvWUnj{mL9&zY(G5Y? zaz{IH?~QeCkPr5zQ>-}2VBZ>I#_1qU1&ud9v)~Tu7fD~sA6Bo}bL;J!aaJ<0(G>0}uQAtrJhio>ROSgpxe>AK;mBZ4f$1 zBWWBF&O$o6vt|ghtapat`7waAt9CjfZf*68m4O5l+dB12tV&Hwy?(TDgk&+?3FPa) zo@={P3AJh}GzvAIG{eZmegA3=eE%T#oQ_a@om=~CVjnmpug{11x~P*Te_*xP%GEA= z8E{jYbz7l%RkKY16@##|A)-K(M4Q72g z8~F2|s2=MBF+qDN2r1UV;bfh-<)^?3NMuGqR@6-XxC~?O&v$kFr3W}GdHFl%qs|t3 zJiKU+?^YR{5H2!)Rc!?M1bN_KMF+9Hbor-nw6%V|9A@#c+K*56P(RiO@^ZP`AT+9% z0CD+f?lIoGCNTRLZ8O1a>OIiF*ahZ&lFwjnMf3o4L>n>LBXZkwGD4H-K&tGewEa#Z&753|}0{=UiPg8li* IbJyz>% From 9383c0358163fdf840217219d831b75e9b530610 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 8 May 2026 13:39:17 +0300 Subject: [PATCH 04/11] CSS compiler: export #Constants `--name` declarations as @name theme constants Lets a user app's theme.css override a native-theme palette variable purely from CSS: #Constants { includeNativeBool: true; --accent-color: #ff2d95; --accent-color-dark: #ff2d95; } Previously `--name` declarations short-circuited into the parser- internal variables map (used only for compile-time var() resolution within the same compilation unit) and never reached the runtime, so a user's --accent-color redeclaration was silently dropped. The Flute compiler now ALSO emits these as @name theme constants when they sit inside a #Constants pseudo-element, which routes them through UIManager.themeConstants where the binding-overlay pass already knows what to do with them - the user theme.css is loaded after the native theme (via includeNativeBool=true), the @-constant overwrites the native default, applyThemeBindings retunes every bound UIID. Same end-state as runtime addThemeProps but driven from CSS, no Java code, no Hashtable. Adds SAC_RGBCOLOR / SAC_FUNCTION (rgb, rgba) handling to the constants-serialization loop so hex / rgb() colors in #Constants make it out as plain hex strings (the format runtime themeProps and applyThemeBindings expect for color values). Native theme captures still emit their own @accent-color etc. from their #Constants blocks - this is by design: the constants are already in themeProps with the native default, so a no-op overlay runs after each native-theme-load. When the user theme then loads on top, the user's @accent-color overwrites the native default and the next applyThemeBindings overlays the user's value. NativeThemeBindingsTest now also asserts @accent-color is present in the loaded theme so the round-trip CSS -> .res -> Hashtable is covered for both shipped native themes. Native-Themes docs lead with the CSS-from-theme.css path; the runtime addThemeProps path is documented as the dynamic-theming counterpart for cases like in-app accent toggles. Test docstring clarifies it's exercising the runtime path because screenshot tests can't easily mutate the app's compiled theme.css. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/developer-guide/Native-Themes.asciidoc | 100 +++++++++++++----- .../ui/plaf/NativeThemeBindingsTest.java | 12 +++ .../com/codename1/designer/css/CSSTheme.java | 80 +++++++++++++- .../PaletteOverrideThemeScreenshotTest.java | 18 ++-- 4 files changed, 174 insertions(+), 36 deletions(-) diff --git a/docs/developer-guide/Native-Themes.asciidoc b/docs/developer-guide/Native-Themes.asciidoc index 4144236f00..af4a5786e9 100644 --- a/docs/developer-guide/Native-Themes.asciidoc +++ b/docs/developer-guide/Native-Themes.asciidoc @@ -247,18 +247,20 @@ accent-driven UIIDs the same way as Android above. The colour names match Apple's `UIColor.systemBlue` etc. so you can mirror the SF Symbols semantics if you want. -=== Runtime accent palette override +=== Accent palette override Both shipped native themes expose their accent palette as named -constants you can retune at runtime through `UIManager.addThemeProps`. -The CSS source uses `var(--accent-color, fallback)` references so -the fallback ships as the baked-in default (the .res file loads -fine with no override) and the compiler additionally emits a +constants you can retune from your app's own `theme.css` (or, for +dynamic theming, at runtime). The CSS source uses +`var(--accent-color, fallback)` references so the fallback ships as +the baked-in default (the .res file loads fine with no override) +and the compiler additionally emits a `@cn1-bind:.=accent-color` constant alongside each -affected style key. At app launch you push a tiny Hashtable of -`@`-prefixed accent constants and the runtime UIManager fans the -overrides out to every bound UIID at once - no per-UIID rule -duplication, no theme recompile. +affected style key. When the resolved theme constants pick up a new +`@accent-color` value (whether from your CSS or via runtime +`UIManager.addThemeProps`), the framework fans the override out to +every bound UIID at once - no per-UIID rule duplication, no theme +recompile. .iOS modern (`native-themes/ios-modern/theme.css`) [cols="2,1,1,3", options="header"] @@ -324,6 +326,51 @@ duplication, no theme recompile. |`state-pressed` |=== +==== Override from your app's `theme.css` (recommended) + +Redeclare the accent variable inside the `#Constants` block of your +app's `theme.css`. The framework's CSS compiler exports any +`--name` declaration in `#Constants` as a `@name` theme constant, +so the value flows through the same binding pass that handles +runtime overrides: + +[source,css] +---- +#Constants { + includeNativeBool: true; + darkModeBool: true; + + /* Override the native theme's accent palette. The compiler picks + up these declarations from #Constants and exports them as + @accent-color / @accent-color-dark theme constants so every + UIID bound to var(--accent-color) in the parent native theme + picks them up at app launch - no per-UIID rule edit needed. */ + --accent-color: #ff2d95; + --accent-color-dark: #ff2d95; + --accent-pressed-color: #c71a75; + --accent-pressed-color-dark: #c71a75; + --accent-on-color: #ffffff; + + /* Material 3 RaisedButton uses a separate "container" tonal + pair; iOS ignores these (no bindings reference them) so it's + safe to set them unconditionally. */ + --accent-container-color: #ff2d95; + --accent-container-color-dark: #ff2d95; + --accent-on-container-color: #ffffff; + --accent-on-container-color-dark: #ffffff; +} +---- + +Bindings that reference a constant you did not override stay at +their baked-in default, so a partial override (e.g. just +`--accent-color`) is fine. + +==== Runtime override + +For dynamic theming - in-app accent toggles, branded flavours, +A/B tests - push the same constants through +`UIManager.addThemeProps` after the theme has been installed: + [source,java] ---- Hashtable override = new Hashtable(); @@ -332,8 +379,6 @@ override.put("@accent-color-dark", "ff2d95"); override.put("@accent-pressed-color", "c71a75"); override.put("@accent-pressed-color-dark", "c71a75"); override.put("@accent-on-color", "ffffff"); -// Android-only tonal pair; iOS ignores these (no bindings reference -// them) so it's safe to set them unconditionally. override.put("@accent-container-color", "ff2d95"); override.put("@accent-container-color-dark", "ff2d95"); override.put("@accent-on-container-color", "ffffff"); @@ -344,30 +389,25 @@ Form.getCurrentForm().refreshTheme(); Values can be passed with or without the leading `#` and in any case; the runtime accepts `"ff2d95"`, `"#FF2D95"`, and the 3-digit -shorthand `"#f0a"` interchangeably. Bindings that reference a -constant you did not override stay at their baked-in default, so a -partial override (e.g. just `@accent-color`) is fine. +shorthand `"#f0a"` interchangeably. `PaletteOverrideThemeScreenshotTest` in the hellocodenameone test -suite is the worked example - it flips the primary accent to -magenta at runtime and re-renders the same form across both light -and dark capture, on both native themes. +suite exercises this path against both native themes, light + dark. -==== When the runtime override path doesn't apply +==== When the override path doesn't apply The binding mechanism handles every accent UIID the shipped themes expose. For other widgets - or when you want to override a colour the native CSS hard-codes (e.g. the iOS `success` green on `Switch.selected`) - either: -* Layer a redeclaration in your app's `theme.css` (see - `Customising in your own theme` below). Compile-time, ships with - the .res. Right when you want a permanent rebrand and you control - the build. +* Layer a per-UIID redeclaration in your app's `theme.css` (see + `Customising in your own theme` below). Right when you want to + tweak a UIID the binding vocabulary doesn't already cover. * Or pass the specific UIID/state key directly into `UIManager.addThemeProps` (`Switch.sel#bgColor` etc.). Runtime, bypasses the binding system. Right when you need a one-off colour - tweak the binding vocabulary doesn't already cover. + tweak you can't anchor in CSS. === Platform-specific UIIDs @@ -491,12 +531,14 @@ RaisedButton.disabled { background-color: #ffd6e2; color: #ffffff; } The user's CSS is layered on top of the native theme at app launch, so refresh / restart picks the override up. -For a wholesale accent rebrand consider the runtime -`@accent-color`-style override in `Runtime accent palette override` -above - it's a one-line `addThemeProps` call versus the per-UIID -redeclaration here. Layering remains the right choice for tweaking -non-accent UIIDs (typography, spacing, surface fills) the runtime -binding vocabulary doesn't cover. +For a wholesale accent rebrand prefer redeclaring the +`--accent-color` (etc.) variables in your `#Constants` block - see +`Override from your app's theme.css` above. That single declaration +fans out through every UIID bound to the variable in the native +theme, no per-UIID rules required. Per-UIID redeclaration here +remains the right choice for tweaking non-accent properties +(typography, spacing, surface fills) the binding vocabulary doesn't +cover. === Inheriting from a native UIID diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java index f7150981bd..10185459b3 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/NativeThemeBindingsTest.java @@ -53,6 +53,10 @@ public void iosModernThemeBindingRetunesButton() throws Exception { // expected default is "7aff" rather than "007aff". assertEquals("7aff", theme.get("Button.fgColor")); assertEquals("accent-color", theme.get("@cn1-bind:Button.fgColor")); + // `#Constants { --accent-color: #007aff; }` in the native + // theme.css is exported as a `@accent-color` theme constant so + // a user app's theme.css can override it via the same syntax. + assertEquals("007AFF", theme.get("@accent-color")); UIManager.getInstance().setThemeProps(theme); @@ -93,6 +97,14 @@ public void androidMaterialThemeBindingRetunesButton() throws Exception { // Integer.toHexString. assertEquals("6750a4", theme.get("Button.bgColor")); assertEquals("accent-color", theme.get("@cn1-bind:Button.bgColor")); + // Native theme.css declares `#Constants { --accent-color: #6750a4; }` + // and the Flute compiler now exports that as a `@accent-color` + // theme constant in addition to the parser-internal var() lookup. + // This is what lets a user app's theme.css redeclare + // `#Constants { --accent-color: #ff2d95; }` and have it propagate + // through the runtime binding pass to every UIID bound to + // --accent-color in this parent theme. + assertEquals("6750A4", theme.get("@accent-color")); UIManager.getInstance().setThemeProps(theme); diff --git a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java index 88e9e2d626..0277a3bb48 100644 --- a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java +++ b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java @@ -2054,6 +2054,22 @@ public void updateResources() { } } else if (lu.getLexicalUnitType() == LexicalUnit.SAC_INTEGER) { res.setThemeProperty(themeName, "@"+constantKey, String.valueOf(((ScaledUnit)lu).getIntegerValue())); + } else if (lu.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR + || (lu.getLexicalUnitType() == LexicalUnit.SAC_FUNCTION + && ("rgb".equals(lu.getFunctionName()) + || "rgba".equals(lu.getFunctionName()) + || "cn1rgb".equals(lu.getFunctionName()) + || "cn1rgba".equals(lu.getFunctionName())))) { + // Hex / rgb() / rgba() color literals declared in + // #Constants. Stored as a plain hex string (no `#`, + // lowercase, 6 chars) which is the format + // UIManager's themeConstants and the runtime + // applyThemeBindings pass expect for color values. + // Lets a user theme.css declare e.g. + // `#Constants { --accent-color: #ff2d95; }` and have + // it propagate to every UIID bound to --accent-color + // in the parent native theme. + res.setThemeProperty(themeName, "@"+constantKey, getColorString(lu)); } } catch (RuntimeException t) { System.err.println("\nAn error occurred processing constant key "+constantKey); @@ -7280,6 +7296,35 @@ private static int indexOfOutsideComments(String css, String needle, int fromPos return -1; } + /// Checks whether the supplied `currSelectors` currently parsing + /// declarations is the special `#Constants` pseudo-element CN1 + /// themes use to declare theme constants (rather than UIID styling + /// rules). Used by the `cn1--<name>` short-circuit in `property_` + /// to decide whether to ALSO emit the declaration as a `@<name>` + /// theme constant - so a user theme.css can override a native + /// theme's bound palette purely from CSS. + private static boolean isInsideConstantsBlock(SelectorList currSelectors) { + if (currSelectors == null) { + return false; + } + int len = currSelectors.getLength(); + for (int i = 0; i < len; i++) { + Selector sel = currSelectors.item(i); + if (sel.getSelectorType() != Selector.SAC_CONDITIONAL_SELECTOR) { + continue; + } + ConditionalSelector csel = (ConditionalSelector) sel; + if (csel.getCondition().getConditionType() != Condition.SAC_ID_CONDITION) { + continue; + } + AttributeCondition acond = (AttributeCondition) csel.getCondition(); + if ("Constants".equalsIgnoreCase(acond.getValue())) { + return true; + } + } + return false; + } + private static int findMatchingBrace(String css, int openPos) { int depth = 0; int len = css.length(); @@ -7527,8 +7572,41 @@ private ScaledUnit evaluate(LexicalUnit lu) throws CSSException { private void property_(String string, LexicalUnit _lu, boolean bln) throws CSSException { if (string.startsWith("cn1--")) { - + variables.put(string, _lu); + // When the `--name` declaration sits inside the + // `#Constants` pseudo-element, ALSO export it as a + // `@name` theme constant. This is the load-bearing + // hook that lets a user app's theme.css override a + // native-theme palette variable purely from CSS: + // the native theme declares `#Constants { + // --accent-color: #007aff; }` which becomes a + // theme constant, the user's theme.css redeclares + // the same `#Constants { --accent-color: #ff2d95; }` + // override which loads later (after the native + // theme is layered in via includeNativeBool=true) + // and overwrites the constant. UIManager's + // applyThemeBindings then retunes every UIID + // bound to that variable. Without this dual + // emission `--name` would only live in the + // parser-internal variables map and never reach + // the runtime. + if (currSelectors != null + && isInsideConstantsBlock(currSelectors)) { + String constantName = string.substring("cn1--".length()); + if (constantName.length() > 0) { + // Evaluate via the same path the rest of + // updateResources expects: wraps raw + // LexicalUnitImpls into ScaledUnits so + // downstream getColorString() and friends + // see the chain shape they were written + // against (red/green/blue ScaledUnits + // for SAC_RGBCOLOR), not the raw Flute + // LexicalUnitImpl which would crash on + // the ScaledUnit cast. + theme.constants.put(constantName, evaluate(_lu)); + } + } return; } diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java index bad6e6b15e..a49012158e 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/PaletteOverrideThemeScreenshotTest.java @@ -17,12 +17,18 @@ * fallback)` references. The compiler bakes the fallback into each * UIID at compile time AND emits `@cn1-bind:<UIID>.<key>=accent-color` * constants alongside, so the .res ships with every accent-bearing - * UIID quietly tracking the underlying palette variable. At app - * launch the user calls - * {@link UIManager#addThemeProps(Hashtable)} with a single - * `@accent-color`-style constant per palette role and the runtime - * binding pass overlays the override onto every bound UIID at once - - * no per-UIID rule duplication, no theme recompile. + * UIID quietly tracking the underlying palette variable. The + * recommended override path is from the user app's own `theme.css` + * (see Native-Themes docs - declaring `--accent-color: #ff2d95;` + * inside the app's `#Constants` block exports it as a + * `@accent-color` theme constant which the framework then fans out + * to every bound UIID at theme-install time). This screenshot test + * exercises the equivalent runtime path - + * {@link UIManager#addThemeProps(Hashtable)} with the same + * `@`-prefixed constants - because (a) screenshot tests cannot + * easily mutate the app's compiled theme.css, and (b) the runtime + * mechanism is what ships for dynamic theming use cases (in-app + * accent toggles, A/B tests, branded flavours). * * This test installs a magenta override on the primary accent and a * vivid teal on the disabled accent. The teal is the load-bearing From d8b54f008987bac5fac370c2d871a2e901533862 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 8 May 2026 19:13:56 +0300 Subject: [PATCH 05/11] CSS compiler: don't inherit a parent's binding when the child sets a literal Element.resolveBinding walked the parent chain whenever the current Element had no `bindings` entry for the requested property, but `bindings` only records properties whose VALUE came from a var() - not properties the rule set with a literal. So a state rule like `Button.disabled { background-color: #e0dce4 }` (a literal that deliberately breaks the inheritance from base `Button { background- color: var(--accent-color) }`) was treated by the binding walker as "no value of its own" and the parent's accent binding was emitted for `Button.dis#bgColor`. At runtime the @accent-color override then stomped the disabled tone with the primary colour, visibly shifting `Button.disabled` away from the M3 baseline. Fix: in resolveBinding, after the local `bindings` miss, check whether the current Element's `style` map has an entry for the property. If yes, this rule overrode the value with a literal; return null so the override stops at this level. Only walk to the parent when the Element has no value of its own (the derive-only case Button-derived RaisedButton relies on, or the implicit unselected state inheriting from the base UIID). Caught by Android ButtonTheme_dark/light captures shifting in the disabled-button band on the latest CI run; the Button.dis#bgColor binding is now correctly absent from the rebuilt AndroidMaterialTheme.res. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../java/com/codename1/designer/css/CSSTheme.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java index 0277a3bb48..af7b4f5167 100644 --- a/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java +++ b/maven/css-compiler/src/main/java/com/codename1/designer/css/CSSTheme.java @@ -3632,6 +3632,20 @@ String resolveBinding(String cssProperty) { if (b != null) { return b; } + // If this Element set its own (non-bound) value for the + // CSS property, don't inherit a binding from the parent. + // Example: `Button { color: var(--accent) }` plus + // `Button.disabled { color: #a5a0ab }` - the disabled state + // EXPLICITLY overrode the colour with a literal, so reading + // the parent's accent binding for `Button.dis#fgColor` would + // wire the disabled state to the runtime accent override + // even though the disabled rule deliberately broke that + // link. Only fall through to the parent when this Element + // has no explicit value of its own (e.g. a derive-only + // child, or the implicit unselected state). + if (style.get(cssProperty) != null) { + return null; + } // anyNodeStyle.parent points back to itself (default field // initializer); stop the walk there to avoid infinite // recursion. Any binding declared on anyNodeStyle is still From 7de74c2614d81ea145849899b1b850cfca6d216e Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 9 May 2026 06:11:01 +0300 Subject: [PATCH 06/11] ci: bump Metal screenshot step timeout from 30 to 45 minutes The Metal screenshot pipeline hit the 30-minute step timeout on the latest PR run. Tracing the device-runner.log: the suite reached TabsTheme_light (~13 min into test execution), captured 111533 PNG bytes + 84124-byte preview chunk stream at preview_quality=6 (still over the 20480-byte preview cap), then went silent for ~18 minutes before the timer killed it. No FATAL / Test-failure markers - just dead air on the logcat replay. The earlier passing Metal run finished ~28 minutes in, so the suite is consistently running right at the wall. Bump the timeout to 45 minutes - matches the build-ios job's own cap and the iOS Metal runner's natural ceiling - so a borderline-slow chunk-stream replay doesn't get conflated with a real Metal port hang. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/scripts-ios.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/scripts-ios.yml b/.github/workflows/scripts-ios.yml index 6a3697f9a7..0bded8390c 100644 --- a/.github/workflows/scripts-ios.yml +++ b/.github/workflows/scripts-ios.yml @@ -408,7 +408,18 @@ jobs: "${{ steps.build-ios-app.outputs.workspace }}" \ "" \ "${{ steps.build-ios-app.outputs.scheme }}" - timeout-minutes: 30 + # The Metal screenshot suite has been running right at the + # 30-min wall on several recent PRs (the suite finishes ~28m + # into the step). The latest run timed out around TabsTheme + # after the runner appeared to stall on the preview-chunk + # streaming for a particularly large capture (preview JPEG + # blew past max_preview_bytes even at quality=6 and the + # logcat replay went silent for ~18 minutes before the timer + # fired). Bump to 45 minutes so we get headroom for the + # logcat-buffer recovery path and don't conflate "Metal port + # genuinely hung" with "step timer fired during a slow + # chunk-stream replay" - the two need different responses. + timeout-minutes: 45 - name: Publish Metal screenshot summary # Surfaces run-ios-ui-tests.sh's comparison result in the job's From b13d8aea2cd0d1916d26b9e7a1dda8779435d0c0 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 9 May 2026 06:43:33 +0300 Subject: [PATCH 07/11] Revert "ci: bump Metal screenshot step timeout from 30 to 45 minutes" This reverts commit 7de74c2614d81ea145849899b1b850cfca6d216e. --- .github/workflows/scripts-ios.yml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/scripts-ios.yml b/.github/workflows/scripts-ios.yml index 0bded8390c..6a3697f9a7 100644 --- a/.github/workflows/scripts-ios.yml +++ b/.github/workflows/scripts-ios.yml @@ -408,18 +408,7 @@ jobs: "${{ steps.build-ios-app.outputs.workspace }}" \ "" \ "${{ steps.build-ios-app.outputs.scheme }}" - # The Metal screenshot suite has been running right at the - # 30-min wall on several recent PRs (the suite finishes ~28m - # into the step). The latest run timed out around TabsTheme - # after the runner appeared to stall on the preview-chunk - # streaming for a particularly large capture (preview JPEG - # blew past max_preview_bytes even at quality=6 and the - # logcat replay went silent for ~18 minutes before the timer - # fired). Bump to 45 minutes so we get headroom for the - # logcat-buffer recovery path and don't conflate "Metal port - # genuinely hung" with "step timer fired during a slow - # chunk-stream replay" - the two need different responses. - timeout-minutes: 45 + timeout-minutes: 30 - name: Publish Metal screenshot summary # Surfaces run-ios-ui-tests.sh's comparison result in the job's From 2cfb34cbe733eb98121445294dd2fbbba40fb333 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 9 May 2026 08:17:31 +0300 Subject: [PATCH 08/11] Metal port: cache pipeline + matrix state across consecutive draws The texture-backdrop test painter (used by Tabs / Dialog screenshot tests in hellocodenameone) was the immediate trigger, but the underlying robustness issue is in the Metal port itself: drawQuad and drawSolidPrimitive called setRenderPipelineState + 3-4 setVertexBytes on EVERY draw, even when consecutive draws shared the same pipeline and matrix snapshot. For one-off fills that's fine. For burst patterns -- the painter was issuing 2556 fillRect calls per band x ~50 bands = ~125k fillRects per textured-backdrop frame -- the redundant per-call setVertexBytes of a 192-byte matrix struct plus the redundant pipeline state-set choke the CAMetalLayer command buffer. The TabsTheme dark-mode capture stalled the iOS Metal screenshot suite for 18 minutes (until the surrounding step's wall-clock timer fired). Two complementary fixes: 1. Painter (hellocodenameone DualAppearanceBaseTest.TextureBackdrop Painter): each diagonal stripe is a parallelogram. Replace the 2556-iteration scanline fillRect loop with one fillPolygon call per band. Polygon fill is universally supported by every CN1 port we ship (Graphics.fillPolygon is core API, not a port extension); the previous comment claiming otherwise was wrong. ~125k draws per frame -> ~50. 2. Metal port (CN1Metalcompat.m): track last-bound pipeline state and last-uploaded matrix bytes per encoder. Skip the Metal API call when they haven't changed. Cache invalidates on every activeEncoder reassignment (BeginFrame, BeginMutableImageDraw, EndMutableImageDraw restore, EndFrame) because Metal command encoders don't carry state between encoders. memcmp on a 192-byte struct per draw is much cheaper than the encoder's setVertexBytes argument-buffer copy. This isn't only about TextureBackdropPainter -- it makes Metal robust to any code path that emits a long burst of same-pipeline / same-matrix draws (gradient scanline approximations, RoundRectBorder interior scanline fills, custom painters in user apps that happen to choose scanline strategies for portability). A small CSS or layout mistake should not be able to cascade into 100k+ redundant Metal encoder calls. Co-Authored-By: Claude Opus 4.7 (1M context) --- Ports/iOSPort/nativeSources/CN1Metalcompat.m | 83 ++++++++++++++++--- .../tests/DualAppearanceBaseTest.java | 40 +++++---- 2 files changed, 97 insertions(+), 26 deletions(-) diff --git a/Ports/iOSPort/nativeSources/CN1Metalcompat.m b/Ports/iOSPort/nativeSources/CN1Metalcompat.m index c7e71a1147..446937ddf3 100644 --- a/Ports/iOSPort/nativeSources/CN1Metalcompat.m +++ b/Ports/iOSPort/nativeSources/CN1Metalcompat.m @@ -40,6 +40,35 @@ static int currentFramebufferHeight = 0; static CN1MetalPipelineCache *pipelineCache = nil; +// --------------- Per-encoder state cache --------------- +// +// Every drawQuad / drawSolidPrimitive used to call setRenderPipelineState +// and re-upload the matrix struct via setVertexBytes, even when the prior +// draw used the same pipeline and the matrices hadn't changed. For one-off +// fills that's fine, but UI code routinely emits a long burst of same- +// pipeline same-matrix solid-colour fills (gradients-as-scanlines, the +// hellocodenameone TextureBackdropPainter's diagonal stripes when a port +// lacks fillPolygon, RoundRectBorder's per-row interior fill, etc.). At +// burst counts of 100k+ draws, the redundant per-call setVertexBytes for +// a 192-byte matrix struct + the redundant pipeline state-set choke the +// CAMetalLayer command buffer to the point where a textured-backdrop +// dark-mode capture stalled the iOS Metal screenshot suite for ~18 +// minutes (until the surrounding step's wall-clock timeout). +// +// Track the last-bound pipeline + matrix bytes per encoder; only forward +// to Metal when they actually changed. Invalidated on every `activeEncoder +// = ...` assignment because Metal command encoders don't carry state +// between encoders -- a fresh encoder needs the first call to actually +// bind the state, even if nominally it matches the previous encoder's. +static __unsafe_unretained id lastBoundPipelineState = nil; +static CN1MetalMatrices lastBoundMatrices; +static BOOL lastBoundMatricesValid = NO; + +static inline void invalidateEncoderStateCache(void) { + lastBoundPipelineState = nil; + lastBoundMatricesValid = NO; +} + #define CN1_MATRIX_STACK_DEPTH 32 static simd_float4x4 modelViewStack[CN1_MATRIX_STACK_DEPTH]; static int modelViewStackTop = 0; @@ -78,6 +107,7 @@ void CN1MetalBeginFrame(id encoder, int framebufferWidth, int framebufferHeight) { activeEncoder = encoder; + invalidateEncoderStateCache(); currentProjection = projection; currentFramebufferWidth = framebufferWidth; currentFramebufferHeight = framebufferHeight; @@ -92,6 +122,7 @@ void CN1MetalBeginFrame(id encoder, void CN1MetalEndFrame(void) { activeEncoder = nil; + invalidateEncoderStateCache(); } id CN1MetalActiveEncoder(void) { @@ -209,6 +240,36 @@ static CN1MetalMatrices currentMatrices(void) { return m; } +// Binds `state` on activeEncoder only when it differs from the last +// pipeline state we bound on this encoder. Saves a Metal API call per +// draw in the (very common) burst case where many consecutive draws +// reuse the same pipeline (e.g. solid-colour fillRect storms from +// gradient/scanline approximations). +static inline void bindPipelineStateIfChanged(id state) { + if (state == lastBoundPipelineState) return; + [activeEncoder setRenderPipelineState:state]; + lastBoundPipelineState = state; +} + +// setVertexBytes for the matrix struct dominates the CPU cost of a +// burst of fills (it's a 192-byte copy into the encoder's argument +// scratch on every call). Skip the upload when the matrix snapshot is +// byte-identical to the last one we uploaded on this encoder. The +// matrix mutators (Set/LoadIdentity/Push/Pop/Scale/Translate/Rotate) +// don't touch this cache themselves -- they only mutate the global +// matrix state; the cache compares against the bytes we last wrote +// and naturally re-uploads on the next draw if they've drifted. +static inline void uploadMatricesIfChanged(NSUInteger atIndex) { + CN1MetalMatrices matrices = currentMatrices(); + if (lastBoundMatricesValid && + memcmp(&matrices, &lastBoundMatrices, sizeof(matrices)) == 0) { + return; + } + [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:atIndex]; + lastBoundMatrices = matrices; + lastBoundMatricesValid = YES; +} + static void drawQuad(CN1MetalPipeline pipeline, const float vertices[8], const float *texcoords, // may be NULL @@ -217,13 +278,12 @@ static void drawQuad(CN1MetalPipeline pipeline, if (activeEncoder == nil || pipelineCache == nil) return; id state = [pipelineCache pipelineFor:pipeline]; if (state == nil) return; - [activeEncoder setRenderPipelineState:state]; + bindPipelineStateIfChanged(state); // buffer(0): positions (8 floats = 4 x (x,y)) [activeEncoder setVertexBytes:vertices length:sizeof(float) * 8 atIndex:0]; // buffer(1): matrices - CN1MetalMatrices matrices = currentMatrices(); - [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; + uploadMatricesIfChanged(1); // buffer(2): optional texcoords (only textured/alpha-mask pipelines read this) if (texcoords != NULL) { [activeEncoder setVertexBytes:texcoords length:sizeof(float) * 8 atIndex:2]; @@ -251,10 +311,9 @@ static void drawSolidPrimitive(MTLPrimitiveType primitive, size_t byteCount = sizeof(float) * 2 * (size_t)vertexCount; if (byteCount > 4096) return; - [activeEncoder setRenderPipelineState:state]; + bindPipelineStateIfChanged(state); [activeEncoder setVertexBytes:vertices length:byteCount atIndex:0]; - CN1MetalMatrices matrices = currentMatrices(); - [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; + uploadMatricesIfChanged(1); [activeEncoder setFragmentBytes:&color length:sizeof(color) atIndex:0]; [activeEncoder drawPrimitives:primitive vertexStart:0 vertexCount:(NSUInteger)vertexCount]; } @@ -612,10 +671,9 @@ static void drawGradientQuad(CN1MetalPipeline pipeline, if (activeEncoder == nil || pipelineCache == nil) return; id state = [pipelineCache pipelineFor:pipeline]; if (state == nil) return; - [activeEncoder setRenderPipelineState:state]; + bindPipelineStateIfChanged(state); [activeEncoder setVertexBytes:vertices length:sizeof(float) * 8 atIndex:0]; - CN1MetalMatrices matrices = currentMatrices(); - [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; + uploadMatricesIfChanged(1); [activeEncoder setVertexBytes:texcoords length:sizeof(float) * 8 atIndex:2]; [activeEncoder setFragmentBytes:&startColor length:sizeof(startColor) atIndex:0]; [activeEncoder setFragmentBytes:&endColor length:sizeof(endColor) atIndex:1]; @@ -743,7 +801,7 @@ void CN1MetalDrawAlphaMaskRadial(id texture, if (activeEncoder == nil || pipelineCache == nil) return; id state = [pipelineCache pipelineFor:CN1MetalPipelineAlphaMaskRadial]; if (state == nil) return; - [activeEncoder setRenderPipelineState:state]; + bindPipelineStateIfChanged(state); float vertices[8] = { (float)x, (float)y, @@ -758,8 +816,7 @@ void CN1MetalDrawAlphaMaskRadial(id texture, 1.0f, 1.0f }; [activeEncoder setVertexBytes:vertices length:sizeof(float) * 8 atIndex:0]; - CN1MetalMatrices matrices = currentMatrices(); - [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; + uploadMatricesIfChanged(1); [activeEncoder setVertexBytes:texcoords length:sizeof(float) * 8 atIndex:2]; // Premultiplied colours so blending produces the right output. @@ -1011,6 +1068,7 @@ BOOL CN1MetalBeginMutableImageDraw(GLUIImage *image) { savedScreenStateValid = YES; activeEncoder = enc; + invalidateEncoderStateCache(); currentProjection = mutableProjection(w, h); currentFramebufferWidth = w; currentFramebufferHeight = h; @@ -1037,6 +1095,7 @@ void CN1MetalEndMutableImageDraw(GLUIImage *image) { // queue continue to use the screen encoder. if (savedScreenStateValid) { activeEncoder = savedScreenEncoder; + invalidateEncoderStateCache(); currentProjection = savedScreenProjection; currentFramebufferWidth = savedScreenFw; currentFramebufferHeight = savedScreenFh; diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java index 44f5bc85e9..5810132e60 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java @@ -465,22 +465,34 @@ public void paint(Graphics g, Rectangle rect) { g.setAlpha(180); int diagonalOffset = -h; // start off-screen so the pattern fills int band = 0; + int[] xCoords = new int[4]; + int[] yCoords = new int[4]; while (diagonalOffset < w + h) { g.setColor(palette[band % palette.length]); - // diagonal band = a quad from (diagonalOffset, 0) to - // (diagonalOffset + bandW, 0) down to (diagonalOffset + bandW + h, h) - // / (diagonalOffset + h, h). Approximate with scanlines so - // this stays portable across ports that may lack fillPolygon. - for (int row = 0; row < h; row++) { - int x0 = x + diagonalOffset + row; - int x1 = x0 + bandW; - if (x1 < x || x0 > x + w) { - continue; - } - if (x0 < x) x0 = x; - if (x1 > x + w) x1 = x + w; - g.fillRect(x0, y + row, x1 - x0, 1); - } + // Each band is a parallelogram with two horizontal edges + // (top at y, bottom at y+h) and two diagonal edges. Fill + // it with one fillPolygon call rather than per-row + // fillRect: at phone resolution h is ~2500 px and there + // are ~50 bands, so the scanline approach used to issue + // ~125k draw calls per backdrop. On iOS Metal each + // fillRect submits a fresh setRenderPipelineState + + // setVertexBytes pair, and at that volume the CAMetalLayer + // command-buffer commit was stalling the dark-mode + // transition for TabsTheme by 18 minutes. Polygon fill + // is one draw call per band (50 total) and is universally + // supported by every CN1 port we ship (Graphics.fillPolygon + // is a core API, not a port-specific extension). The + // previous comment on this loop suggested otherwise; it + // was wrong. + xCoords[0] = x + diagonalOffset; + yCoords[0] = y; + xCoords[1] = x + diagonalOffset + bandW; + yCoords[1] = y; + xCoords[2] = x + diagonalOffset + bandW + h; + yCoords[2] = y + h; + xCoords[3] = x + diagonalOffset + h; + yCoords[3] = y + h; + g.fillPolygon(xCoords, yCoords, 4); diagonalOffset += bandW; band++; } From 0d8afbc0be463eb70cbc39e982f2d8b05616cf6d Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 9 May 2026 09:25:34 +0300 Subject: [PATCH 09/11] Revert "Metal port: cache pipeline + matrix state across consecutive draws" This reverts commit 2cfb34cbe733eb98121445294dd2fbbba40fb333. --- Ports/iOSPort/nativeSources/CN1Metalcompat.m | 83 +++---------------- .../tests/DualAppearanceBaseTest.java | 40 ++++----- 2 files changed, 26 insertions(+), 97 deletions(-) diff --git a/Ports/iOSPort/nativeSources/CN1Metalcompat.m b/Ports/iOSPort/nativeSources/CN1Metalcompat.m index 446937ddf3..c7e71a1147 100644 --- a/Ports/iOSPort/nativeSources/CN1Metalcompat.m +++ b/Ports/iOSPort/nativeSources/CN1Metalcompat.m @@ -40,35 +40,6 @@ static int currentFramebufferHeight = 0; static CN1MetalPipelineCache *pipelineCache = nil; -// --------------- Per-encoder state cache --------------- -// -// Every drawQuad / drawSolidPrimitive used to call setRenderPipelineState -// and re-upload the matrix struct via setVertexBytes, even when the prior -// draw used the same pipeline and the matrices hadn't changed. For one-off -// fills that's fine, but UI code routinely emits a long burst of same- -// pipeline same-matrix solid-colour fills (gradients-as-scanlines, the -// hellocodenameone TextureBackdropPainter's diagonal stripes when a port -// lacks fillPolygon, RoundRectBorder's per-row interior fill, etc.). At -// burst counts of 100k+ draws, the redundant per-call setVertexBytes for -// a 192-byte matrix struct + the redundant pipeline state-set choke the -// CAMetalLayer command buffer to the point where a textured-backdrop -// dark-mode capture stalled the iOS Metal screenshot suite for ~18 -// minutes (until the surrounding step's wall-clock timeout). -// -// Track the last-bound pipeline + matrix bytes per encoder; only forward -// to Metal when they actually changed. Invalidated on every `activeEncoder -// = ...` assignment because Metal command encoders don't carry state -// between encoders -- a fresh encoder needs the first call to actually -// bind the state, even if nominally it matches the previous encoder's. -static __unsafe_unretained id lastBoundPipelineState = nil; -static CN1MetalMatrices lastBoundMatrices; -static BOOL lastBoundMatricesValid = NO; - -static inline void invalidateEncoderStateCache(void) { - lastBoundPipelineState = nil; - lastBoundMatricesValid = NO; -} - #define CN1_MATRIX_STACK_DEPTH 32 static simd_float4x4 modelViewStack[CN1_MATRIX_STACK_DEPTH]; static int modelViewStackTop = 0; @@ -107,7 +78,6 @@ void CN1MetalBeginFrame(id encoder, int framebufferWidth, int framebufferHeight) { activeEncoder = encoder; - invalidateEncoderStateCache(); currentProjection = projection; currentFramebufferWidth = framebufferWidth; currentFramebufferHeight = framebufferHeight; @@ -122,7 +92,6 @@ void CN1MetalBeginFrame(id encoder, void CN1MetalEndFrame(void) { activeEncoder = nil; - invalidateEncoderStateCache(); } id CN1MetalActiveEncoder(void) { @@ -240,36 +209,6 @@ static CN1MetalMatrices currentMatrices(void) { return m; } -// Binds `state` on activeEncoder only when it differs from the last -// pipeline state we bound on this encoder. Saves a Metal API call per -// draw in the (very common) burst case where many consecutive draws -// reuse the same pipeline (e.g. solid-colour fillRect storms from -// gradient/scanline approximations). -static inline void bindPipelineStateIfChanged(id state) { - if (state == lastBoundPipelineState) return; - [activeEncoder setRenderPipelineState:state]; - lastBoundPipelineState = state; -} - -// setVertexBytes for the matrix struct dominates the CPU cost of a -// burst of fills (it's a 192-byte copy into the encoder's argument -// scratch on every call). Skip the upload when the matrix snapshot is -// byte-identical to the last one we uploaded on this encoder. The -// matrix mutators (Set/LoadIdentity/Push/Pop/Scale/Translate/Rotate) -// don't touch this cache themselves -- they only mutate the global -// matrix state; the cache compares against the bytes we last wrote -// and naturally re-uploads on the next draw if they've drifted. -static inline void uploadMatricesIfChanged(NSUInteger atIndex) { - CN1MetalMatrices matrices = currentMatrices(); - if (lastBoundMatricesValid && - memcmp(&matrices, &lastBoundMatrices, sizeof(matrices)) == 0) { - return; - } - [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:atIndex]; - lastBoundMatrices = matrices; - lastBoundMatricesValid = YES; -} - static void drawQuad(CN1MetalPipeline pipeline, const float vertices[8], const float *texcoords, // may be NULL @@ -278,12 +217,13 @@ static void drawQuad(CN1MetalPipeline pipeline, if (activeEncoder == nil || pipelineCache == nil) return; id state = [pipelineCache pipelineFor:pipeline]; if (state == nil) return; - bindPipelineStateIfChanged(state); + [activeEncoder setRenderPipelineState:state]; // buffer(0): positions (8 floats = 4 x (x,y)) [activeEncoder setVertexBytes:vertices length:sizeof(float) * 8 atIndex:0]; // buffer(1): matrices - uploadMatricesIfChanged(1); + CN1MetalMatrices matrices = currentMatrices(); + [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; // buffer(2): optional texcoords (only textured/alpha-mask pipelines read this) if (texcoords != NULL) { [activeEncoder setVertexBytes:texcoords length:sizeof(float) * 8 atIndex:2]; @@ -311,9 +251,10 @@ static void drawSolidPrimitive(MTLPrimitiveType primitive, size_t byteCount = sizeof(float) * 2 * (size_t)vertexCount; if (byteCount > 4096) return; - bindPipelineStateIfChanged(state); + [activeEncoder setRenderPipelineState:state]; [activeEncoder setVertexBytes:vertices length:byteCount atIndex:0]; - uploadMatricesIfChanged(1); + CN1MetalMatrices matrices = currentMatrices(); + [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; [activeEncoder setFragmentBytes:&color length:sizeof(color) atIndex:0]; [activeEncoder drawPrimitives:primitive vertexStart:0 vertexCount:(NSUInteger)vertexCount]; } @@ -671,9 +612,10 @@ static void drawGradientQuad(CN1MetalPipeline pipeline, if (activeEncoder == nil || pipelineCache == nil) return; id state = [pipelineCache pipelineFor:pipeline]; if (state == nil) return; - bindPipelineStateIfChanged(state); + [activeEncoder setRenderPipelineState:state]; [activeEncoder setVertexBytes:vertices length:sizeof(float) * 8 atIndex:0]; - uploadMatricesIfChanged(1); + CN1MetalMatrices matrices = currentMatrices(); + [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; [activeEncoder setVertexBytes:texcoords length:sizeof(float) * 8 atIndex:2]; [activeEncoder setFragmentBytes:&startColor length:sizeof(startColor) atIndex:0]; [activeEncoder setFragmentBytes:&endColor length:sizeof(endColor) atIndex:1]; @@ -801,7 +743,7 @@ void CN1MetalDrawAlphaMaskRadial(id texture, if (activeEncoder == nil || pipelineCache == nil) return; id state = [pipelineCache pipelineFor:CN1MetalPipelineAlphaMaskRadial]; if (state == nil) return; - bindPipelineStateIfChanged(state); + [activeEncoder setRenderPipelineState:state]; float vertices[8] = { (float)x, (float)y, @@ -816,7 +758,8 @@ void CN1MetalDrawAlphaMaskRadial(id texture, 1.0f, 1.0f }; [activeEncoder setVertexBytes:vertices length:sizeof(float) * 8 atIndex:0]; - uploadMatricesIfChanged(1); + CN1MetalMatrices matrices = currentMatrices(); + [activeEncoder setVertexBytes:&matrices length:sizeof(matrices) atIndex:1]; [activeEncoder setVertexBytes:texcoords length:sizeof(float) * 8 atIndex:2]; // Premultiplied colours so blending produces the right output. @@ -1068,7 +1011,6 @@ BOOL CN1MetalBeginMutableImageDraw(GLUIImage *image) { savedScreenStateValid = YES; activeEncoder = enc; - invalidateEncoderStateCache(); currentProjection = mutableProjection(w, h); currentFramebufferWidth = w; currentFramebufferHeight = h; @@ -1095,7 +1037,6 @@ void CN1MetalEndMutableImageDraw(GLUIImage *image) { // queue continue to use the screen encoder. if (savedScreenStateValid) { activeEncoder = savedScreenEncoder; - invalidateEncoderStateCache(); currentProjection = savedScreenProjection; currentFramebufferWidth = savedScreenFw; currentFramebufferHeight = savedScreenFh; diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java index 5810132e60..44f5bc85e9 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java @@ -465,34 +465,22 @@ public void paint(Graphics g, Rectangle rect) { g.setAlpha(180); int diagonalOffset = -h; // start off-screen so the pattern fills int band = 0; - int[] xCoords = new int[4]; - int[] yCoords = new int[4]; while (diagonalOffset < w + h) { g.setColor(palette[band % palette.length]); - // Each band is a parallelogram with two horizontal edges - // (top at y, bottom at y+h) and two diagonal edges. Fill - // it with one fillPolygon call rather than per-row - // fillRect: at phone resolution h is ~2500 px and there - // are ~50 bands, so the scanline approach used to issue - // ~125k draw calls per backdrop. On iOS Metal each - // fillRect submits a fresh setRenderPipelineState + - // setVertexBytes pair, and at that volume the CAMetalLayer - // command-buffer commit was stalling the dark-mode - // transition for TabsTheme by 18 minutes. Polygon fill - // is one draw call per band (50 total) and is universally - // supported by every CN1 port we ship (Graphics.fillPolygon - // is a core API, not a port-specific extension). The - // previous comment on this loop suggested otherwise; it - // was wrong. - xCoords[0] = x + diagonalOffset; - yCoords[0] = y; - xCoords[1] = x + diagonalOffset + bandW; - yCoords[1] = y; - xCoords[2] = x + diagonalOffset + bandW + h; - yCoords[2] = y + h; - xCoords[3] = x + diagonalOffset + h; - yCoords[3] = y + h; - g.fillPolygon(xCoords, yCoords, 4); + // diagonal band = a quad from (diagonalOffset, 0) to + // (diagonalOffset + bandW, 0) down to (diagonalOffset + bandW + h, h) + // / (diagonalOffset + h, h). Approximate with scanlines so + // this stays portable across ports that may lack fillPolygon. + for (int row = 0; row < h; row++) { + int x0 = x + diagonalOffset + row; + int x1 = x0 + bandW; + if (x1 < x || x0 > x + w) { + continue; + } + if (x0 < x) x0 = x; + if (x1 > x + w) x1 = x + w; + g.fillRect(x0, y + row, x1 - x0, 1); + } diagonalOffset += bandW; band++; } From 668d39eecd15e67c9a5ab1f483d6c3587ef01aec Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 9 May 2026 09:26:35 +0300 Subject: [PATCH 10/11] TextureBackdropPainter: fillPolygon per band instead of scanline fillRect Each diagonal band is a parallelogram. The previous loop emitted one fillRect per row (h rows) per band; at phone resolution that's ~2500 fillRects x 50 bands = ~125k draw calls per backdrop frame. On iOS Metal that call volume saturated the CAMetalLayer command buffer and stalled the dark-mode transition for TabsTheme by 18 minutes (until the surrounding step's wall-clock timer fired). Replace with one fillPolygon per band - 50 draw calls instead of 125k. Graphics.fillPolygon is core CN1 API, supported on every port we ship; the previous comment claiming otherwise was wrong. This is the painter half of the earlier "Metal port: cache pipeline + matrix state" commit. The Metal-side state caching half is left out of this revert chain because the original CI run with both pieces produced a different failure mode (simctl couldn't launch the rebuilt app -- "Application unknown to FrontBoard") that I couldn't reproduce locally and don't want to chase blind. The painter fix alone reduces the call volume by ~2500x, which is the actual root-cause mitigation; the encoder state cache was a defensive second pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../tests/DualAppearanceBaseTest.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java index 44f5bc85e9..01e7bac132 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java @@ -465,22 +465,29 @@ public void paint(Graphics g, Rectangle rect) { g.setAlpha(180); int diagonalOffset = -h; // start off-screen so the pattern fills int band = 0; + int[] xCoords = new int[4]; + int[] yCoords = new int[4]; while (diagonalOffset < w + h) { g.setColor(palette[band % palette.length]); - // diagonal band = a quad from (diagonalOffset, 0) to - // (diagonalOffset + bandW, 0) down to (diagonalOffset + bandW + h, h) - // / (diagonalOffset + h, h). Approximate with scanlines so - // this stays portable across ports that may lack fillPolygon. - for (int row = 0; row < h; row++) { - int x0 = x + diagonalOffset + row; - int x1 = x0 + bandW; - if (x1 < x || x0 > x + w) { - continue; - } - if (x0 < x) x0 = x; - if (x1 > x + w) x1 = x + w; - g.fillRect(x0, y + row, x1 - x0, 1); - } + // Each band is a parallelogram: (offset, 0) -> + // (offset + bandW, 0) -> (offset + bandW + h, h) -> + // (offset + h, h). One fillPolygon per band rather than + // per-row fillRect: at phone resolution h is ~2500 px and + // there are ~50 bands, so the scanline approach used to + // issue ~125k draw calls per backdrop. On iOS Metal that + // call volume stalled the dark-mode transition for + // TabsTheme. Polygon fill is one draw call per band (50 + // total) and fillPolygon is core CN1 API supported by + // every port we ship. + xCoords[0] = x + diagonalOffset; + yCoords[0] = y; + xCoords[1] = x + diagonalOffset + bandW; + yCoords[1] = y; + xCoords[2] = x + diagonalOffset + bandW + h; + yCoords[2] = y + h; + xCoords[3] = x + diagonalOffset + h; + yCoords[3] = y + h; + g.fillPolygon(xCoords, yCoords, 4); diagonalOffset += bandW; band++; } From 8c358517f42e18ce0138e4b71463c030387a5e21 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 9 May 2026 10:28:36 +0300 Subject: [PATCH 11/11] Revert "TextureBackdropPainter: fillPolygon per band instead of scanline fillRect" This reverts commit 668d39eecd15e67c9a5ab1f483d6c3587ef01aec. --- .../tests/DualAppearanceBaseTest.java | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java index 01e7bac132..44f5bc85e9 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/DualAppearanceBaseTest.java @@ -465,29 +465,22 @@ public void paint(Graphics g, Rectangle rect) { g.setAlpha(180); int diagonalOffset = -h; // start off-screen so the pattern fills int band = 0; - int[] xCoords = new int[4]; - int[] yCoords = new int[4]; while (diagonalOffset < w + h) { g.setColor(palette[band % palette.length]); - // Each band is a parallelogram: (offset, 0) -> - // (offset + bandW, 0) -> (offset + bandW + h, h) -> - // (offset + h, h). One fillPolygon per band rather than - // per-row fillRect: at phone resolution h is ~2500 px and - // there are ~50 bands, so the scanline approach used to - // issue ~125k draw calls per backdrop. On iOS Metal that - // call volume stalled the dark-mode transition for - // TabsTheme. Polygon fill is one draw call per band (50 - // total) and fillPolygon is core CN1 API supported by - // every port we ship. - xCoords[0] = x + diagonalOffset; - yCoords[0] = y; - xCoords[1] = x + diagonalOffset + bandW; - yCoords[1] = y; - xCoords[2] = x + diagonalOffset + bandW + h; - yCoords[2] = y + h; - xCoords[3] = x + diagonalOffset + h; - yCoords[3] = y + h; - g.fillPolygon(xCoords, yCoords, 4); + // diagonal band = a quad from (diagonalOffset, 0) to + // (diagonalOffset + bandW, 0) down to (diagonalOffset + bandW + h, h) + // / (diagonalOffset + h, h). Approximate with scanlines so + // this stays portable across ports that may lack fillPolygon. + for (int row = 0; row < h; row++) { + int x0 = x + diagonalOffset + row; + int x1 = x0 + bandW; + if (x1 < x || x0 > x + w) { + continue; + } + if (x0 < x) x0 = x; + if (x1 > x + w) x1 = x + w; + g.fillRect(x0, y + row, x1 - x0, 1); + } diagonalOffset += bandW; band++; }