Skip to content

maps: lay road names along the road, and zoom past the tile data - #5902

Merged
shai-almog merged 12 commits into
masterfrom
maps-road-labels-overzoom
Sep 30, 2026
Merged

shai-almog merged 12 commits into
masterfrom
maps-road-labels-overzoom

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Addresses discussion #5848: on MapView, street names floated beside the roads instead of running along them, and the map would not zoom in past ~15.

Causes

  • Every basemap label, road names included, was horizontal text at a single anchor point.
  • The default OpenFreeMap vector source serves data up to z14, and the engine clamped the camera to the source's deepest level.

Changes

  • Road names follow the road (LabelEngine.placeAlongLine). Line features now carry their geometry in LabelCandidate.path. At paint time the name is laid out starting from the middle of the line, and repeats every 256 logical px along long roads. A straight run is drawn as one rotated string, so kerning is kept. On a bend each glyph is placed and rotated on the curve. Text is kept upright. A copy is dropped when the turn between neighbouring glyphs exceeds 45 degrees, and when the same name was placed less than a repeat away (tiles each carry their own piece of a long road). Ports without affine support keep the old horizontal label at the midpoint.
  • Labels above routes. VectorMapEngine.paint is split into paintTiles + paintLabels. MapView draws the tiles, then polygons, circles and polylines, then basemap labels, then markers and marker labels.
  • Overzoom. For vector sources, getMaxZoom() is now the source maximum + 6, capped at 22. A tile deeper than the source's data is cut from its deepest ancestor. TileRenderer.renderTile(..., subX, subY, depth) redraws that ancestor's geometry at the larger scale and culls parts outside the piece. Decoded ancestors are kept in a small LRU cache and requests for the same ancestor share one fetch. The ancestor's labels serve all of its pieces. Raster sources are unchanged.
  • Line widths are logical pixels scaled by the raster size, as text sizes already were. The default road widths extend past z18 (10 px at z18, 22 at z20).

Behaviour changes to note

  • The default road widths look different: thicker on high-density screens at z14, and wider at street level.
  • Line widths in custom MapStyle.fromJson styles now scale with the pixel ratio.

Testing

  • RoadLabelTest (11 tests) covers:
    • the text direction and the upright flip
    • per-glyph placement on a curve
    • the sharp-corner drop, with a straight-road control
    • the too-short case, repeats and the same-name spacing
    • the non-affine fallback
    • road geometry in world pixels
    • sub-tile rendering and culling
    • the vector vs raster zoom cap
    • one ancestor fetch per overzoomed area
  • Revert probes: removing the upright flip or the same-name spacing each fails its test.
  • All 120 com.codename1.maps tests pass. core-unittests verify passes (SpotBugs, PMD, Checkstyle), as does generate-quality-report.py.
  • Rendered a live JavaSE MapView over the route area from the discussion at z14–z20.

Known limit: at z19–20 a name can sit a few pixels off its road. OpenMapTiles' transportation_name geometry is simplified, and the simplification shows once the map is 32–64x past its data.

🤖 Generated with Claude Code

shai-almog and others added 2 commits September 25, 2026 21:51
Road names were drawn as horizontal text at one point per road, so on a
MapView they floated beside the streets instead of following them. They
are now laid along the road: from the middle of the line, repeated along
long roads, each glyph following a bend, kept upright, dropped on sharp
corners and kept a repeat apart from the same name. Ports without affine
transforms keep the horizontal label.

Basemap labels now draw above routes and shapes (and below pins), via the
new VectorMapEngine.paintTiles/paintLabels split.

Vector maps also zoom up to six levels past the deepest level the source
serves (capped at 22): the deepest tile's geometry is redrawn for each
smaller piece, so OpenFreeMap (data to z14) reaches z20 with sharp roads.
Each ancestor tile is fetched and decoded once for all its pieces.

Line widths are now logical pixels scaled by the pixel ratio, and the
default road widths keep growing past z18.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

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

Generated automatically by the PR CI workflow.

@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

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

Developer Guide quality checks:

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

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 157 screenshots: 157 matched.

Native Android coverage

  • 📊 Line coverage: 9.37% (9331/99611 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.10% (47834/525841), branch 3.60% (1794/49819), complexity 3.58% (1899/53096), method 5.52% (1542/27918), class 11.04% (413/3742)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.37% (9331/99611 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.10% (47834/525841), branch 3.60% (1794/49819), complexity 3.58% (1899/53096), method 5.52% (1542/27918), class 11.04% (413/3742)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 274ms / native 157ms = 1.7x speedup
SIMD float-mul (64K x300) java 221ms / native 124ms = 1.7x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 77.000 ms
Base64 CN1 decode 84.000 ms
Base64 native encode 379.000 ms
Base64 encode ratio (CN1/native) 0.203x (79.7% faster)
Base64 native decode 271.000 ms
Base64 decode ratio (CN1/native) 0.310x (69.0% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

ParparVM vs HotSpot (JDK 25): Linux x64

Runner CPU: AMD EPYC 9V74 80-Core Processor (baseline linux-x64@amd-epyc-9v74-80-core-processor)

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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in vm/selfhost/perf-baseline.json (more, for a row whose calibration runs were noisier; the file records it), and for RAM also more than 0.05x above it in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.92x (base 0.90x, +3.1%) 0.90x (base 0.79x, +15.0%) ok
translator (self) 4 0.47x (base 0.52x, -8.0%) 0.53x (base 0.52x, +0.7%) ok
intArithmetic 4 1.10x (base 1.10x, -0.0%) 0.05x (base 0.06x, -1.9%) ok
longArithmetic 4 1.08x (base 1.08x, +0.0%) 0.05x (base 0.06x, -1.0%) ok
mathTranscendental 4 1.10x (base 1.09x, +0.7%) 0.08x (base 0.07x, +14.6%) ok
arraySequential 4 2.64x (base 2.81x, -6.1%) 0.36x (base 0.35x, +0.4%) ok
arrayRandom 4 1.09x (base 1.02x, +6.0%) 0.21x (base 0.21x, -1.9%) ok
objectAllocation 4 4.77x (base 4.76x, +0.2%) 0.41x (base 0.39x, +6.7%) ok
valueEscape 4 0.10x (base 0.10x, -0.0%) 0.05x (base 0.06x, -5.9%) ok
hashMapChurn 4 1.10x (base 1.10x, +0.0%) 0.10x (base 0.10x, -5.3%) ok
stringBuilding 4 1.48x (base 1.49x, -0.6%) 0.26x (base 0.26x, -0.3%) ok
recursion 4 1.24x (base 1.24x, +0.0%) 0.06x (base 0.06x, -0.2%) ok
quicksort 4 1.07x (base 1.07x, -0.2%) 0.11x (base 0.11x, +0.5%) ok

Result: no regression

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 71ms / native 6ms = 11.8x speedup
SIMD float-mul (64K x300) java 57ms / native 4ms = 14.2x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 87.000 ms
Base64 CN1 decode 127.000 ms
Base64 SIMD encode 119.000 ms
Base64 encode ratio (SIMD/CN1) 1.368x (36.8% slower)
Base64 SIMD decode 112.000 ms
Base64 decode ratio (SIMD/CN1) 0.882x (11.8% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 14.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.286x (71.4% faster)
Image applyMask (SIMD off) 27.000 ms
Image applyMask (SIMD on) 28.000 ms
Image applyMask ratio (SIMD on/off) 1.037x (3.7% slower)
Image modifyAlpha (SIMD off) 42.000 ms
Image modifyAlpha (SIMD on) 21.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.500x (50.0% faster)
Image modifyAlpha removeColor (SIMD off) 39.000 ms
Image modifyAlpha removeColor (SIMD on) 19.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.487x (51.3% faster)

ParparVM vs HotSpot (JDK 25): Windows x64

Runner CPU: AMD64 Family 25 Model 1 Stepping 1, AuthenticAMD (baseline windows-x64@amd64-family-25-model-1-authenticamd)

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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in vm/selfhost/perf-baseline.json (more, for a row whose calibration runs were noisier; the file records it), and for RAM also more than 0.05x above it in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.12x (base 1.26x, -11.1%) 0.89x (base 0.81x, +11.0%) ok
translator (self) 4 0.60x (base 0.61x, -2.0%) 0.54x (base 0.54x, -0.8%) ok
intArithmetic 4 1.10x (base 1.10x, -0.0%) 0.06x (base 0.06x, -0.6%) ok
longArithmetic 4 1.08x (base 1.08x, -0.0%) 0.05x (base 0.05x, -0.2%) ok
mathTranscendental 4 0.79x (base 0.79x, -0.2%) 0.06x (base 0.06x, +5.1%) ok
arraySequential 4 1.34x (base 1.38x, -2.6%) 0.38x (base 0.39x, -0.1%) ok
arrayRandom 4 0.94x (base 0.97x, -3.4%) 0.23x (base 0.23x, +0.1%) ok
objectAllocation 4 4.95x (base 5.02x, -1.6%) 0.40x (base 0.39x, +2.7%) ok
valueEscape 4 0.10x (base 0.10x, +0.2%) 0.04x (base 0.04x, -0.4%) ok
hashMapChurn 4 1.79x (base 1.80x, -0.6%) 0.09x (base 0.09x, -4.2%) ok
stringBuilding 4 1.16x (base 1.21x, -3.9%) 0.27x (base 0.32x, -17.1%) better than baseline
recursion 4 1.49x (base 1.49x, +0.0%) 0.06x (base 0.06x, -0.8%) ok
quicksort 4 1.14x (base 1.13x, +0.9%) 0.12x (base 0.12x, -0.5%) ok

Result: no regression

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 48ms / native 3ms = 16.0x speedup
SIMD float-mul (64K x300) java 49ms / native 3ms = 16.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 60.000 ms
Base64 CN1 decode 70.000 ms
Base64 SIMD encode 78.000 ms
Base64 encode ratio (SIMD/CN1) 1.300x (30.0% slower)
Base64 SIMD decode 69.000 ms
Base64 decode ratio (SIMD/CN1) 0.986x (1.4% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.500x (50.0% faster)
Image applyMask (SIMD off) 12.000 ms
Image applyMask (SIMD on) 15.000 ms
Image applyMask ratio (SIMD on/off) 1.250x (25.0% slower)
Image modifyAlpha (SIMD off) 16.000 ms
Image modifyAlpha (SIMD on) 8.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.500x (50.0% faster)
Image modifyAlpha removeColor (SIMD off) 19.000 ms
Image modifyAlpha removeColor (SIMD on) 8.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.421x (57.9% faster)

ParparVM vs HotSpot (JDK 25): Windows arm64

Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline windows-arm64@armv8-64-bit-family-8-model-d49-microsoft-corporation)

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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in vm/selfhost/perf-baseline.json (more, for a row whose calibration runs were noisier; the file records it), and for RAM also more than 0.05x above it in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.09x (base 1.11x, -1.3%) 0.91x (base 0.90x, +0.7%) ok
translator (self) 4 0.76x (base 0.75x, +1.2%) 0.49x (base 0.54x, -9.2%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.06x (base 0.06x, +0.0%) ok
longArithmetic 4 0.80x (base 0.80x, +0.1%) 0.06x (base 0.06x, +0.5%) ok
mathTranscendental 4 0.72x (base 0.72x, -0.0%) 0.06x (base 0.06x, +0.2%) ok
arraySequential 4 0.37x (base 0.39x, -7.2%) 0.39x (base 0.39x, -0.2%) ok
arrayRandom 4 0.94x (base 0.94x, +0.1%) 0.23x (base 0.23x, +0.0%) ok
objectAllocation 4 2.89x (base 2.73x, +5.6%) 0.44x (base 0.46x, -4.9%) ok
valueEscape 4 0.76x (base 0.76x, +0.0%) 0.05x (base 0.05x, -0.5%) ok
hashMapChurn 4 1.00x (base 0.98x, +1.2%) 0.12x (base 0.12x, -0.7%) ok
stringBuilding 4 1.44x (base 1.43x, +1.1%) 0.27x (base 0.27x, +0.1%) ok
recursion 4 1.46x (base 1.46x, -0.2%) 0.06x (base 0.07x, -0.7%) ok
quicksort 4 1.00x (base 1.00x, +0.4%) 0.12x (base 0.12x, -0.2%) ok

Result: no regression

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 2000 ms
Simulator Boot (Run) 1000 ms
App Install 23000 ms
App Launch 11000 ms
Test Execution 470000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 253ms / native 7ms = 36.1x speedup
SIMD float-mul (64K x300) java 243ms / native 6ms = 40.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 76.000 ms
Base64 CN1 decode 66.000 ms
Base64 native encode 1244.000 ms
Base64 encode ratio (CN1/native) 0.061x (93.9% faster)
Base64 native decode 1178.000 ms
Base64 decode ratio (CN1/native) 0.056x (94.4% faster)
Base64 SIMD encode 63.000 ms
Base64 encode ratio (SIMD/CN1) 0.829x (17.1% faster)
Base64 SIMD decode 64.000 ms
Base64 decode ratio (SIMD/CN1) 0.970x (3.0% faster)
Base64 encode ratio (SIMD/native) 0.051x (94.9% faster)
Base64 decode ratio (SIMD/native) 0.054x (94.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 8.000 ms
Image createMask (SIMD on) 7.000 ms
Image createMask ratio (SIMD on/off) 0.875x (12.5% faster)
Image applyMask (SIMD off) 1344.000 ms
Image applyMask (SIMD on) 57.000 ms
Image applyMask ratio (SIMD on/off) 0.042x (95.8% faster)
Image modifyAlpha (SIMD off) 630.000 ms
Image modifyAlpha (SIMD on) 31.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.049x (95.1% faster)
Image modifyAlpha removeColor (SIMD off) 47.000 ms
Image modifyAlpha removeColor (SIMD on) 41.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.872x (12.8% faster)

@shai-almog

shai-almog commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 110000 ms
Simulator Boot (Run) 1000 ms
App Install 20000 ms
App Launch 5000 ms
Test Execution 499000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 54ms / native 3ms = 18.0x speedup
SIMD float-mul (64K x300) java 55ms / native 2ms = 27.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 61.000 ms
Base64 CN1 decode 58.000 ms
Base64 native encode 1268.000 ms
Base64 encode ratio (CN1/native) 0.048x (95.2% faster)
Base64 native decode 1053.000 ms
Base64 decode ratio (CN1/native) 0.055x (94.5% faster)
Base64 SIMD encode 93.000 ms
Base64 encode ratio (SIMD/CN1) 1.525x (52.5% slower)
Base64 SIMD decode 47.000 ms
Base64 decode ratio (SIMD/CN1) 0.810x (19.0% faster)
Base64 encode ratio (SIMD/native) 0.073x (92.7% faster)
Base64 decode ratio (SIMD/native) 0.045x (95.5% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.500x (50.0% faster)
Image applyMask (SIMD off) 398.000 ms
Image applyMask (SIMD on) 501.000 ms
Image applyMask ratio (SIMD on/off) 1.259x (25.9% slower)
Image modifyAlpha (SIMD off) 46.000 ms
Image modifyAlpha (SIMD on) 53.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.152x (15.2% slower)
Image modifyAlpha removeColor (SIMD off) 403.000 ms
Image modifyAlpha removeColor (SIMD on) 32.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.079x (92.1% faster)

@shai-almog

shai-almog commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

… labels

Captures taken from CI run artifacts of this branch (macos-ui-tests,
mac-catalyst-ui-tests). The other ports' map goldens pass within their
existing .tolerance sidecars.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

shai-almog commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD float-mul (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 45.000 ms
Base64 CN1 decode 56.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.571x (42.9% faster)
Image applyMask (SIMD off) 47.000 ms
Image applyMask (SIMD on) 37.000 ms
Image applyMask ratio (SIMD on/off) 0.787x (21.3% faster)
Image modifyAlpha (SIMD off) 39.000 ms
Image modifyAlpha (SIMD on) 27.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.692x (30.8% faster)
Image modifyAlpha removeColor (SIMD off) 37.000 ms
Image modifyAlpha removeColor (SIMD on) 37.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.000x (0.0% slower)

ParparVM vs HotSpot (JDK 25): macOS arm64

Runner CPU: Apple M1 (Virtual) (baseline macos-arm64)

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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in vm/selfhost/perf-baseline.json (more, for a row whose calibration runs were noisier; the file records it), and for RAM also more than 0.05x above it in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (HelloCodenameOne) 3 0.86x (base 0.96x, -9.6%) 1.27x (base 1.34x, -5.4%) ok
translator (self) 3 0.54x (base 0.54x, +0.9%) 0.71x (base 0.74x, -3.4%) ok
intArithmetic 3 1.04x (base 1.03x, +1.0%) 0.12x (base 0.12x, +0.6%) ok
longArithmetic 3 1.02x (base 1.03x, -0.1%) 0.12x (base 0.11x, +2.8%) ok
mathTranscendental 3 0.99x (base 1.01x, -1.3%) 0.12x (base 0.12x, +0.6%) ok
arraySequential 3 0.45x (base 0.42x, +7.0%) 0.52x (base 0.53x, -0.4%) ok
arrayRandom 3 1.00x (base 0.99x, +1.4%) 0.32x (base 0.32x, -0.3%) ok
objectAllocation 3 3.80x (base 3.70x, +2.9%) 0.49x (base 0.48x, +2.1%) ok
valueEscape 3 0.51x (base 0.51x, -0.0%) 0.09x (base 0.09x, -1.1%) ok
hashMapChurn 3 1.06x (base 1.18x, -9.7%) 0.07x (base 0.07x, +9.3%) ok
stringBuilding 3 0.91x (base 0.84x, +8.1%) 0.47x (base 0.54x, -13.7%) ok
recursion 3 1.25x (base 1.24x, +1.5%) 0.12x (base 0.12x, -0.1%) ok
quicksort 3 1.01x (base 1.01x, -0.1%) 0.11x (base 0.11x, -0.7%) ok

Result: no regression

@shai-almog

shai-almog commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 73ms / native 4ms = 18.2x speedup
SIMD float-mul (64K x300) java 84ms / native 5ms = 16.8x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 65.000 ms
Base64 CN1 decode 63.000 ms
Base64 native encode 892.000 ms
Base64 encode ratio (CN1/native) 0.073x (92.7% faster)
Base64 native decode 373.000 ms
Base64 decode ratio (CN1/native) 0.169x (83.1% faster)
Base64 SIMD encode 81.000 ms
Base64 encode ratio (SIMD/CN1) 1.246x (24.6% slower)
Base64 SIMD decode 70.000 ms
Base64 decode ratio (SIMD/CN1) 1.111x (11.1% slower)
Base64 encode ratio (SIMD/native) 0.091x (90.9% faster)
Base64 decode ratio (SIMD/native) 0.188x (81.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.182x (81.8% faster)
Image applyMask (SIMD off) 68.000 ms
Image applyMask (SIMD on) 49.000 ms
Image applyMask ratio (SIMD on/off) 0.721x (27.9% faster)
Image modifyAlpha (SIMD off) 43.000 ms
Image modifyAlpha (SIMD on) 50.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.163x (16.3% slower)
Image modifyAlpha removeColor (SIMD off) 60.000 ms
Image modifyAlpha removeColor (SIMD on) 53.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.883x (11.7% faster)

@shai-almog

shai-almog commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

ParparVM vs HotSpot (JDK 25): Linux arm64

Runner CPU: Neoverse-N2 (baseline linux-arm64@neoverse-n2)

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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in vm/selfhost/perf-baseline.json (more, for a row whose calibration runs were noisier; the file records it), and for RAM also more than 0.05x above it in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.95x (base 0.93x, +2.0%) 0.85x (base 0.87x, -2.1%) ok
translator (self) 4 0.63x (base 0.62x, +0.3%) 0.54x (base 0.54x, +0.5%) ok
intArithmetic 4 1.04x (base 1.04x, -0.1%) 0.03x (base 0.03x, +0.4%) ok
longArithmetic 4 0.79x (base 0.79x, -0.0%) 0.03x (base 0.03x, +2.6%) ok
mathTranscendental 4 1.10x (base 1.10x, -0.0%) 0.03x (base 0.03x, +1.7%) ok
arraySequential 4 0.37x (base 0.36x, +3.1%) 0.37x (base 0.37x, -0.1%) ok
arrayRandom 4 0.94x (base 0.94x, +0.0%) 0.20x (base 0.20x, +0.2%) ok
objectAllocation 4 3.13x (base 3.04x, +2.9%) 0.24x (base 0.24x, +0.7%) ok
valueEscape 4 0.51x (base 0.51x, -0.1%) 0.03x (base 0.03x, +0.9%) ok
hashMapChurn 4 0.84x (base 0.84x, -0.7%) 0.11x (base 0.12x, -5.6%) ok
stringBuilding 4 1.41x (base 1.36x, +3.4%) 0.26x (base 0.26x, +0.1%) ok
recursion 4 1.44x (base 1.43x, +0.2%) 0.03x (base 0.04x, -1.0%) ok
quicksort 4 1.00x (base 0.99x, +0.4%) 0.09x (base 0.09x, -0.1%) ok

Result: no regression

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-30T09:43:11.262174Z 95206f6 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

The built-in styles already skip ferry lines (class=ferry), but the street-name
rules still labelled them, so names such as "Sausalito - San Francisco Ferry
Building" were laid along an invisible route across open water.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0e9a95199

ℹ️ 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".

Comment thread CodenameOne/src/com/codename1/maps/vector/VectorMapEngine.java Outdated
Comment thread CodenameOne/src/com/codename1/maps/vector/LabelEngine.java Outdated
…whole

Overzoomed labels were extracted once from the parent tile at the source's
deepest zoom, so a symbol layer's minzoom/maxzoom and text size were judged
there: a layer starting above the source maximum never appeared, and one
ending at it stayed visible at every overzoom level. They are now extracted
per displayed zoom (visibility and size at that zoom, anchors still in the
parent's world pixels) and cached per zoom and parent.

On a curve, road names were drawn one UTF-16 char at a time, which breaks
Arabic joining, Hebrew ordering, combining marks and surrogate pairs. Only
text whose chars render the same alone (Latin, Greek, Cyrillic, CJK without
combining marks) is laid glyph by glyph; anything else is drawn whole along
the chord, where the platform shapes it, and only where the road stays
within half a line of that chord.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6dc9bcee1a

ℹ️ 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".

Comment thread CodenameOne/src/com/codename1/maps/vector/LabelEngine.java
Comment thread CodenameOne/src/com/codename1/maps/vector/VectorMapEngine.java
Comment thread CodenameOne/src/com/codename1/maps/vector/VectorMapEngine.java
shai-almog and others added 4 commits September 30, 2026 09:41
…t zoom cap

- Without affine transforms a road name was placed at the whole path's
  midpoint, which for an overzoomed road is usually far off screen. It now
  goes at the middle of the longest run of the road inside the viewport.
- A tile past the source's deepest zoom joined only another overzoom fetch of
  its ancestor, so zooming in while the deepest tile was still loading
  downloaded and decoded it twice (and zooming back out did the same the other
  way). Both kinds of request now share one waiting list per deepest tile; a
  failed fetch fails every piece waiting on it.
- getMaxZoom never lowers a source's own deepest level below it, so a source
  serving past zoom 22 kept its own maximum while the docs promised 22. The
  cap limits overzoom only; the javadoc and the guide now say so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Captures from this branch's CI run (macos-ui-tests); the only change against
the previous goldens is the ferry route names over the bay, which the built-in
styles no longer label.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The hosted Windows x64 pool handed a run an Intel model 106 (Ice Lake) runner,
which had no rows, so the gate failed with NO BASELINE on every benchmark.
Rows added by calibrate-perf-baseline.py from that run's perf-results.json;
every other row is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

shai-almog commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 62ms / native 5ms = 12.4x speedup
SIMD float-mul (64K x300) java 56ms / native 5ms = 11.2x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 75.000 ms
Base64 CN1 decode 90.000 ms
Base64 SIMD encode 106.000 ms
Base64 encode ratio (SIMD/CN1) 1.413x (41.3% slower)
Base64 SIMD decode 104.000 ms
Base64 decode ratio (SIMD/CN1) 1.156x (15.6% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 5.000 ms
Image createMask ratio (SIMD on/off) 0.455x (54.5% faster)
Image applyMask (SIMD off) 28.000 ms
Image applyMask (SIMD on) 26.000 ms
Image applyMask ratio (SIMD on/off) 0.929x (7.1% faster)
Image modifyAlpha (SIMD off) 30.000 ms
Image modifyAlpha (SIMD on) 22.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.733x (26.7% faster)
Image modifyAlpha removeColor (SIMD off) 37.000 ms
Image modifyAlpha removeColor (SIMD on) 21.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.568x (43.2% faster)

The waiter list is read through casts, and ParparVM's casts are unchecked, so
none may sit under a catch(Throwable); check-cast-semantics.sh failed PR CI on
the two in applyTileResult.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fb563a263

ℹ️ 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".

Comment thread CodenameOne/src/com/codename1/maps/vector/LabelEngine.java Outdated
The per-glyph range 0x3000-0x9FFF included the kana voicing marks
(U+3099/U+309A) and the ideographic tone marks (U+302A-302F), so a decomposed
name such as ha + dakuten drew the mark as a separate rotated glyph instead of
on its base. Those marks now send the name to whole-string drawing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 95206f6e11

ℹ️ 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".

@github-actions

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • ✅ Tests: 740 total, 0 failed, 57 skipped

Benchmark Results

  • Execution Time: 14892 ms

  • Hotspots (Top 20 sampled methods):

    • 6.35% com.codename1.tools.translator.IteratorEscape.ctorOnlyStoresParamsIntoThis (84 samples)
    • 5.82% com.codename1.tools.translator.BytecodeMethod.equals (77 samples)
    • 3.78% java.lang.StringBuilder.append (50 samples)
    • 3.33% org.objectweb.asm.tree.analysis.Frame.merge (44 samples)
    • 3.25% java.util.ArrayList.indexOf (43 samples)
    • 2.80% java.lang.String.equals (37 samples)
    • 2.80% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (37 samples)
    • 2.57% java.util.HashMap.hash (34 samples)
    • 1.81% java.io.FileOutputStream.open0 (24 samples)
    • 1.74% java.lang.System.identityHashCode (23 samples)
    • 1.51% com.codename1.tools.translator.IteratorEscape.mangle (20 samples)
    • 1.44% org.objectweb.asm.tree.analysis.SourceInterpreter.merge (19 samples)
    • 1.44% com.codename1.tools.translator.BytecodeMethod.appendCMethodPrefix (19 samples)
    • 1.36% java.util.HashMap.putVal (18 samples)
    • 1.36% com.codename1.tools.translator.BytecodeMethod.updateInlinableFieldDependencies (18 samples)
    • 1.28% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (17 samples)
    • 1.28% java.io.FileOutputStream.writeBytes (17 samples)
    • 1.28% com.codename1.tools.translator.ByteCodeClass.fillVirtualMethodTable (17 samples)
    • 1.21% com.codename1.tools.translator.JavascriptReachability.enqueueResolved (16 samples)
    • 1.06% com.codename1.tools.translator.ByteCodeClass.generateCCode (14 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

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

Generated automatically by the PR CI workflow.

@shai-almog
shai-almog merged commit 38a0d9c into master Sep 30, 2026
58 checks passed
@shai-almog
shai-almog deleted the maps-road-labels-overzoom branch September 30, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant