Inkline Maps renders local OpenStreetMap XML extracts into PNG and SVG images.
It runs offline and needs no tile server, network request, or runtime credential.
Use one repeatable pipeline for local map previews and style experiments.
Change the plain-text style sheet without changing Kotlin code.
The sample extract shows water, roads, buildings, and labels.
The renderer assembles relation members into closed outer and inner rings.
The inner rings become holes in both PNG and SVG output.
| Part | Responsibility |
|---|---|
| OSM parser | Reads nodes, ways, relations, and tags with StAX. |
| Multipolygon assembler | Joins relation way members into deterministic outer and inner rings. |
| Projection | Maps coordinates with Web Mercator. |
| Style sheet | Converts simple key-value rules into map colors and widths. |
| Renderer | Draws ordered layers with Java2D or SVG elements. |
| Command line | Selects input, style, and output paths. |
The renderer draws water first, buildings second, roads third, and labels last.
The renderer uses even-odd fill rules to preserve multipolygon holes.
Install Java 17 or newer.
The wrapper downloads Gradle 9.2.1 when needed.
Windows:
.\gradlew.bat test
macOS or Linux:
bash gradlew test
Run the PNG command:
.\gradlew.bat run --args="--input src/main/resources/samples/sample-city.osm --style src/main/resources/samples/inkline.style --output build/demo/sample-city.png"
Run the SVG command:
.\gradlew.bat run --args="--input src/main/resources/samples/sample-city.osm --style src/main/resources/samples/inkline.style --output build/demo/sample-city.svg"
Open the generated files under build/demo.
Sample output:
Rendered 25 nodes and 13 ways to .../build/demo/sample-city.png
Copy the sample style and edit its values.
canvas.background=#efe8d9
water.fill=#a8d5df
road.primary.stroke=#9b4f45
label.size=20
Render again with the edited style path.
The parser accepts #RRGGBB and #AARRGGBB colors.
The test suite covers XML parsing, relation assembly, projection math, style parsing, and PNG or SVG output.
Run all tests:
.\gradlew.bat test
The snapshot test compares rendered pixels with a committed PNG golden file.
The multipolygon tests check reversed way direction, inner rings, relation labels, and SVG fill rules.
GitHub Actions runs tests and the Gradle build on pushes to main and pull requests.
The parser supports nodes, ways, relations, and tags.
The assembler supports multipolygon relations with way members and outer or inner roles.
It ignores nested relations, relation types other than multipolygon, turn restrictions, and coastline assembly.
It skips incomplete outer rings instead of drawing partial geometry.
The renderer uses one viewport and one label layer.
It does not fetch tiles or geocode names.
Complete:
- Parse multipolygon relations and their way members.
- Assemble open member ways into outer and inner rings.
- Render multipolygon holes in PNG and SVG output.
Remaining:
- Add scale-aware label placement.
- Add command options for viewport bounds.
- Add more style selectors for land-use classes.
Apache License 2.0.