Repository navigation
Headless CSS compiler: no display, no browser, no designer jar - #5965
shai-almog wants to merge 42 commits into
Conversation
The CSS compiler paints a rule that has no native theme equivalent into an image and slices it. That painting was done by a CEF browser, which needs a display. This package paints the same box -- backgrounds, gradients, per-side borders, elliptical radii, outer and inset shadows, border images -- with Java2D into a BufferedImage, and runs under java.awt.headless=true. It depends on the JDK only. Nothing uses it yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A rule the theme format cannot express natively (cn1-9patch, a blurred or inset shadow, an image or unsupported gradient behind a radius) is now painted by the in-tree rasterizer instead of a CEF screenshot. The geometry the browser path used is kept exactly -- a 640x960 page, a 100px default height, the same shadow margins and unit scales -- because the 9-piece slices are computed from the size of the image it produces. HeadlessCssCompilerImplementation becomes the one implementation the compiler runs on: it decodes and scales images with ImageIO, and pins the unit conversion to the value application themes were always compiled with (measured against the released compiler: 5px/mm, medium density). The framework's own native themes were built with a different conversion and keep it through setNativeThemeUnits, so neither set of themes changes size. EditableResources no longer opens Swing dialogs itself; the resource editor installs them through ResourceEditorUi. Bugs this uncovered, fixed here: - updateResources cleared the border/bgImage keys createImageBorders had just stored, so a generated image was written to the file and never used. - States and UIIDs sharing one generated image read it from a record that had never been given one. - radial-gradient: the two-colour parser looped forever on a first argument that is not a keyword, and the multi-stop parser dropped the first colour of a gradient with no shape or position. - getImageBorderInsets looped forever on a non-function token after a gradient. - @import was parsed and ignored; local imports are now inlined. - The background shorthand read no-repeat and position keywords as colours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…igner CN1CSSCLI opened a JFrame and booted JavaSEPort for every compile, which is why a build that only compiles CSS needed xvfb. It now installs the headless implementation, sets java.awt.headless itself, and depends on the engine and project-model only. The module also takes over the runnable jar-with-dependencies from css-compiler; NoCefCSSCLI is gone, and the native-themes scripts run this CLI with -no-raster -native-theme-units. Merge, localization, the up-to-date skip, the compile lock and watch mode are kept. The positional form Ant builds used is refused by name; -css, -stateless and -no-cef are accepted and ignored so an older simulator or plugin still works against this jar. main() no longer calls System.exit from the middle of a compile: run() returns a status, which is what the resource editor now calls. Fixed on the way: - A change to a localization bundle alone never recompiled the theme. - Watch mode snapshots its sources before compiling, so an edit made during a compile is not lost, and watches imported files and bundles too. - The merged stylesheet is rewritten only when its content changes. The three CSS classes left in CodenameOneDesigner had no callers and are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CSSWatcher forks CN1CSSCLI from the classpath the Maven or Gradle plugin supplies, headless, and nothing else: the fallback that ran the designer jar is removed, and a project whose build supplies no compiler gets one line saying so. A child that keeps dying is restarted at most three times in ten seconds instead of forever. MavenUtils.isRunningInMaven() recognised a generated project only by the codename1.designer.jar property its pom forwarded. It now also asks the project layout, so the templates can stop passing that property without live reload and hot reload going quiet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CSS compiler runs with no display, no browser and no JavaSE port, so build steps stop borrowing a virtual one, and two smoke legs now clear DISPLAY to keep it that way. - Drop xvfb from build-only steps (linux-build-run prepare job, windows-cross-build-run, scripts-javascript, port-status-nightly, designer, the framework/catalog/build legs of archetype-smoke and gradle-smoke, the fidelity app build, the demos' process-classes, the Settings tests in pr.yml) and from build-android-app.sh and build-android-port.sh. Steps that start the simulator, run cn1:test, take screenshots or drive a browser keep it. - Guard: cn1app-staged-jar-test.sh and gradle-cn1lib-test.sh run with DISPLAY and WAYLAND_DISPLAY cleared; so do the designer.yml CLI check and the Settings tests. - Kept where a PUBLISHED plugin compiles the CSS: starter-canary.yml, and website/build.sh when it is not bootstrapping the workspace. - Port scripts install -pl css-cli -am instead of -pl designer -am: the css goal forks the CLI from the local repository, the designer is not part of any build. - Native theme steps build -pl css-cli -am; path filters that named maven/css-compiler also name maven/css-cli. - Developer guide: the compiler is headless and paints generated images itself; document @import of local stylesheets. native-themes/README.md and CLAUDE.md describe -no-raster / -native-theme-units. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d46066eb8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ds compiling A merged build mirrors each input's directory and points url()s into the mirror. A stylesheet imported from outside that directory brought url()s that climbed out of the mirror and named files nothing had copied, so the compile failed. Those files are now copied into the mirror one by one. An SVG or Lottie background on a rule that needs a generated image failed the build, because the compiler never decodes those files. The layer is now left out of the generated image with a warning naming the file. The generated image keeps painting only the first background-image layer at the top left corner: no position is ever stored and only the head of the value was ever rendered. Comments at both places say why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Native fidelity (Android, Material 3)54 pairs compared -- median 95.6%, worst 91.3% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
createImage(String) opened its argument as a file. Nothing in the compiler calls it with a location on disk, and its contract is a resource in the jar, so it no longer touches the file system. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Compared 12 screenshots: 12 matched. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Cloudflare Preview
|
|
@codex review |
|
Compared 185 screenshots: 185 matched. Benchmark ResultsDetailed Performance Metrics
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9c44d38b29
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Compared 185 screenshots: 185 matched. Benchmark ResultsDetailed Performance Metrics
ParparVM vs HotSpot (JDK 25): Windows x64Runner CPU: AMD64 Family 25 Model 17 Stepping 1, AuthenticAMD (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in
Result: no regression |
|
Compared 170 screenshots: 170 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
|
Compared 206 screenshots: 206 matched. |
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 185 screenshots: 185 matched. ParparVM vs HotSpot (JDK 25): Linux x64Runner CPU: INTEL(R) XEON(R) PLATINUM 8573C (baseline 1 performance regression:
Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in
A change that moves performance ON PURPOSE records the new baseline in Result: performance regression |
|
Compared 185 screenshots: 185 matched. ParparVM vs HotSpot (JDK 25): Linux arm64Runner CPU: Neoverse-N2 (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in
Result: no regression |
|
Compared 185 screenshots: 185 matched. Benchmark ResultsDetailed Performance Metrics
ParparVM vs HotSpot (JDK 25): Windows arm64Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in
Result: no regression |
Native fidelity (ios-27-metal)68 pairs compared -- median 94.6%, worst 74.5% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
Native fidelity (iOS Modern, Metal)68 pairs compared -- median 95.0%, worst 83.5% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: df423ba822
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… and root opacity in generated images A pattern fill is tiled; a mask keeps to its region; a gradient with an href takes its coordinates, units and transform from the one it names, not only its stops; text is stroked as well as filled; the opacity of the root element fades the finished drawing. The url() of an @import is no longer scanned as an image by the build's staleness check: with a query after it, it named a file that is never there and made every build stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b22dd9341
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s in the texture path An <svg> inside an SVG is laid out in its own box, fitted by its view box and cut off at the box's edges, instead of being skipped with everything in it. background-repeat: space with more tiles than are drawn one by one repeated the bare tile; what repeats now is the tile and its gap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 70db9626bb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s and symbol fitting in generated images An element with a filter is drawn through it; marker-start, -mid and -end are drawn on the points of a line; currentColor is the element's color; a percentage in a shape is a share of the viewport; a length in in, cm, mm, pt or pc is that many pixels; a gradient repeats or reflects when its spreadMethod says; a symbol is fitted by its preserveAspectRatio. Two findings about CSS backgrounds are answered in comments: the order of redeclared background properties and a second gradient layer are both as the page the browser was given had them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 32faa3d8e3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…election; deleted localization bundles leave the theme A <tspan> is placed and styled on its own; clip-rule decides the holes of a clip path; an important declaration in a style attribute beats one in a rule; a dotLottie archive shows the animation its manifest picks, at build time and in generated images alike; a localization bundle whose files are gone is taken out of a theme rebuilt on the previous output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
When a generated-image SVG specifies a transform through an inline style or embedded stylesheet, such as .moved { transform: rotate(45deg); }, this reads only the XML transform attribute. Stylesheet declarations are folded into the style value later and StyleParser does not retain transform, so the element is painted at its untransformed geometry even though the removed browser renderer applied the CSS transform.
When a generated-image SVG wraps artwork in an <a> element, this default branch skips the whole element and consumes all of its children. The hyperlink itself need not be interactive in a raster image, but its paths and shapes must still be drawn; otherwise linked regions disappear entirely compared with the removed browser renderer, so parse <a> as a styled container while ignoring its navigation behavior.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… of another file; multi-images of an outside import; url() in a string is no dependency A stroke with vector-effect: non-scaling-stroke keeps its width; the colour after a reference to nothing is painted; a filter reads FillPaint and StrokePaint; a <use> draws an element of an SVG file beside its own. A merged build copies a multi-image directory that an import from outside the input directory names. The build's staleness check no longer takes url(...) written inside a CSS string for a file. Markers stay per element, not per subpath, with the reason in a comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7838626a7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s and clip path transforms; a native theme part's import is found beside the part Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1bc7681e65
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…eir box; end hard stops; use inside a clip path; xml:space=preserve Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
When an SVG wraps artwork in a standard <a> element, this fallback skips the entire subtree instead of treating the anchor like a group. For example, <a href="..."><rect .../></a> produces no rectangle at all in a generated background, whereas the removed browser renderer displayed the linked artwork; ignore the hyperlink behavior but retain and paint its graphical children.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… viewport; an outside multi-image directory is as new as its images Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9863cf6f79
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…age stroke widths Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 312531ac9e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…t written inside a string is no dependency Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |




















































































































































































































































































































































































Compiling
css/theme.csstotheme.resno longer opens a window, boots the JavaSE port, starts a browser or needs the designer jar. The Maven and Gradle css goals and the simulator's live reload all fork one headless compiler that runs underjava.awt.headless=truewith no display.What changed
com.codename1.designer.css.CN1CSSCLI(artifactcodenameone-css-cli, both names kept as the contract between the simulator and the plugin-supplied classpath) no longer creates aJFrameor initialisesJavaSEPort.NoCefCSSCLI,WebviewSnapshotter,SimpleWebServerandcapture.jsare deleted.css-clino longer depends oncodenameone-javase.cn1-9patch,cn1-image-border, non-nativebox-shadow, per-side borders, some gradients, percentage sizes) is rendered by a new pure-Java2D rasterizer,com.codename1.designer.css.raster, using the page geometry the browser capture used, so image sizes and 9-piece slices are unchanged.EditableResourcesandEditorFontreport through aResourceEditorUihook; the Swing implementation lives in the Designer.CSSWatcherforks only the headless CLI. The designer-jar fallback is gone and a child that keeps exiting is restarted a bounded number of times.-Dcodename1.designer.jaris removed from the archetype, the initializr and the in-repo apps.-no-raster -native-theme-unitsand rebuild byte-identical.xvfb-runis removed where CSS was the only reason for it.archetype-smoke.ymlandgradle-smoke.ymlrun a CSS build withDISPLAYandWAYLAND_DISPLAYcleared as a regression guard.The command line is
-input a.css[,b.css] -output x.res [-merge f] [-l dir] [-watch].-css,-statelessand-no-cefare accepted and ignored. The positional form is refused with a pointer to-input/-output. Exit status is 0, 1 for a stylesheet that failed to compile, 2 for a bad command line.Bugs fixed along the way
updateResourcesdeleted theX.border/X.bgImagekeyscreateImageBordershad just written, so generated borders were dropped from the theme. Apps that rely on generated borders may look different, because the borders are back.radial-gradienthung the compiler in three forms, and the multi-stop parser dropped the first colour of a plain one.@importwas silently ignored; local imports are now inlined, with relativeurl()s rebased and cycles reported.background: url(x.png) no-repeatfailed the compile.Not changed
Samples/SampleProjectTemplate/build.xml,tests/TestNativeInterfaces/build.xml) stay on the frozen designer jar.starter-canary.yml, andscripts/website/build.shwhen it is not bootstrapping workspace snapshots, keep xvfb: they build with a published plugin.Testing
css-compilerandcss-clitests, both run with-Djava.awt.headless=true, including a forked compile under-verbose:classasserting that no Swing component,FrameorWindowclass loads.CSSWatcher/MavenUtilstests,CompileCSSMojoTest, the core CSS unit tests.cssgoal onscripts/hellocodenameonewithDISPLAYunset.build-engine,project-modeland both plugins; copyright, control-character, author-tag and since-tag gates.Not exercised locally: the Gradle
cn1Csspath end to end, live reload against a real forked compiler, the Designer GUI at runtime, and pixel similarity to the browser-rendered output.🤖 Generated with Claude Code