Repository navigation
feat(drawer): embed tiled base maps in SVG output on every platform - #45
Merged
Merged
Conversation
Move the tiled base map compositor off CoreGraphics into a pure-Swift `renderTiledBaseMapBitmap` that both the CGImage path and `drawSVG` share. `drawSVG` now composites the cached tiles at the drawer's size, encodes them as PNG via swift-png and emits an `<image>` with a base64 data URI beneath the vector content, so librsvg and other offline rasterisers show the base map without fetching tiles. The `.baseMap` and `.tiledBaseMap` content cases are no longer gated on CoreGraphics, `prefetchTiles(for:)` is public (plus a `[Content]` overload), `TileImage.pngDecoder` is available everywhere and the `URLTemplateTileSource` convenience initialiser picks it on non-Apple platforms. swift-png stays below 4.5 because its newer dependencies need Swift 6.0 tools while CI still builds with 5.10. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
swift-png 4.5 depends on packages whose manifests need Swift 6.0 tools, and no 4.4.x release resolves on a Swift 5.10 toolchain either (its swift-hash dependency has the same requirement). Swift 5 compilers are no longer supported, so the Linux matrix is 6.2 and 6.0 and swift-png follows its latest line. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Member
Author
|
Suggested squash-merge commit message: |
Key-restricted tile services such as MapTiler check the Origin of every request, so callers need a way to set headers beyond User-Agent. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The compositor probed the whole 2^z × 2^z tile grid of the shared cache before each render, one lock acquisition per cell. At world zooms that is nothing; at zoom 14 it is 268 million lookups and a four-gigabyte array, so a street-level render took minutes. It now asks the cache for the tiles it holds for that source and zoom and indexes a compact grid over their extent. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The <image> carried the same base64 data URI in both `href` and `xlink:href`, doubling every SVG with a base map (2.3 MB for an 860 KB PNG). `xlink:href` alone is read by every renderer, librsvg included; plain `href` is SVG 2 only, so it was the redundant one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Maparoni's MCP tools now return map renders as PNGs (maparoni/lambdaroni#285): the Lambda produces SVG through
GeoDrawer.drawSVGon Amazon Linux and Phoenix rasterises it with rsvg-convert.drawSVGskipped raster base maps entirely, and all tile compositing lived behindcanImport(CoreGraphics), so the chat renders were vector-only.The way
The per-pixel tile compositor is now pure Swift (
renderTiledBaseMapBitmap), shared by the existing CoreGraphics path and bydrawSVG, which composites the cached tiles into one bitmap, encodes it as PNG with swift-png and emits an<image>with a base64 data URI beneath the vector content. Embedding rather than linking matters because librsvg refuses remote fetches but happily decodes data URIs.Along the way the
.baseMap/.tiledBaseMapcontent cases lose their CoreGraphics gate,prefetchTiles(for:)becomes public (with a[Content]overload for callers that just want everything fetched before a sync draw),TileImage.pngDecoderis available on every platform, and theURLTemplateTileSourceconvenience initialiser falls back to it off Apple platforms..baseMapis still omitted from SVG.Swift 5 compilers are dropped. swift-png's dependencies need Swift 6.0 tools, and no older swift-png resolves on 5.10 either, so the Linux CI matrix is now 6.2 and 6.0.
Testing
swift teston macOS (64 tests) and inswift:6.3-amazonlinux2023via Docker (77 tests) both pass. The newTiledBaseMapSVGTestsrender a 2×2StaticTileSourcegrid to SVG, check the<image>precedes the<path>, and decode the embedded PNG to confirm the west/east tiles landed where expected./formaggio/run.svgneeds to opt into a tiled base map, and GeoLogicKit'sGeoJSON+SVG.swiftcontinent-scale minimum bounding box makes small maps render as dots.🤖 Generated with Claude Code