Repository navigation
maps: lay road names along the road, and zoom past the tile data - #5902
Conversation
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>
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Cloudflare Preview
|
|
Compared 157 screenshots: 157 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
|
Compared 172 screenshots: 172 matched. ParparVM vs HotSpot (JDK 25): Linux x64Runner CPU: AMD EPYC 9V74 80-Core Processor (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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in
Result: no regression |
|
Compared 172 screenshots: 172 matched. Benchmark ResultsDetailed Performance Metrics
ParparVM vs HotSpot (JDK 25): Windows x64Runner CPU: AMD64 Family 25 Model 1 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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in
Result: no regression |
|
Compared 172 screenshots: 172 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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in
Result: no regression |
|
Compared 193 screenshots: 193 matched. |
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 150 screenshots: 150 matched. |
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 223 screenshots: 223 matched. |
… 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>
|
Compared 166 screenshots: 166 matched. Benchmark Results
Detailed Performance Metrics
ParparVM vs HotSpot (JDK 25): macOS arm64Runner CPU: Apple M1 (Virtual) (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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in
Result: no regression |
|
Compared 154 screenshots: 154 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 172 screenshots: 172 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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in
Result: no regression |
|
@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. |
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>
There was a problem hiding this comment.
💡 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".
…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>
|
@codex review |
There was a problem hiding this comment.
💡 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".
…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>
|
Compared 172 screenshots: 172 matched. Benchmark ResultsDetailed Performance Metrics
|
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>
|
@codex review |
There was a problem hiding this comment.
💡 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".
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>
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
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
Changes
LabelEngine.placeAlongLine). Line features now carry their geometry inLabelCandidate.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.VectorMapEngine.paintis split intopaintTiles+paintLabels.MapViewdraws the tiles, then polygons, circles and polylines, then basemap labels, then markers and marker labels.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.Behaviour changes to note
MapStyle.fromJsonstyles now scale with the pixel ratio.Testing
RoadLabelTest(11 tests) covers:com.codename1.mapstests pass.core-unittestsverify passes (SpotBugs, PMD, Checkstyle), as doesgenerate-quality-report.py.MapViewover 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_namegeometry is simplified, and the simplification shows once the map is 32–64x past its data.🤖 Generated with Claude Code