527 changes: 520 additions & 7 deletions CHANGELOG.md

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ These actions are explicitly forbidden in OpenStreetMap Carto spaces:
- Insulting, demeaning, hateful, or threatening remarks.
- Discrimination based on age, disability, gender, nationality, ethnicity, religion, sexuality, or similar personal characteristic.
- Bullying or systematic harassment.
- Revealing private information about other participants without explicit permission ("doxxing").
- Unwelcome sexual advances.
- Incitement to any of these.

Expand All @@ -62,7 +63,7 @@ When using the OpenStreetMap Carto spaces you should act in the spirit of the va

The OpenStreetMap Carto maintainers are responsible for handling conduct-related issues. Their goal is to de-escalate conflicts and try to resolve issues to the satisfaction of all parties.

If you encounter a conduct-related issue, you should report it to the maintainers by sending them [all an email](mailto:openstreetmap-carto@gravitystorm.co.uk,penorman@mac.com,info@matthijsmelissen.nl,matkoniecz@gmail.com,chris_hormann@gmx.de,daniel@xn--ko-wla.pl,nebulon42@mailbox.org).
If you encounter a conduct-related issue, you should report it to the maintainers by sending them [all an email](mailto:openstreetmap-carto@gravitystorm.co.uk,chris_hormann@gmx.de,daniel@xn--ko-wla.pl,sommerluk@gmail.com,joseph.eisenberg@gmail.com). In the event that you wish to make a complaint against a maintainer, you may instead contact the other maintainers.

**Note that the goal of the Code of Conduct and the maintainers is to resolve conflicts in the most harmonious way possible.** We hope that in most cases issues may be resolved through polite discussion and mutual agreement. Bans and other forceful measures are to be employed only as a last resort.

Expand All @@ -77,6 +78,6 @@ Changes to the Code of Conduct should be proposed as pull requests.

## Acknowledgements

This document is based on the [Go Code of Conduct](https://golang.org/conduct), which in turn has parts derived from the Code of Conduct documents of the Django, FreeBSD, and Rust projects.
This document is based on the [Go Community Code of Conduct](https://go.dev/conduct), which in turn has parts derived from the Code of Conduct documents of the Django, FreeBSD, and Rust projects.

This documented is licensed under the Creative Commons Attribution 3.0 License.
84 changes: 59 additions & 25 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# OpenStreetMap Carto contribution guidelines

## Reporting issues

As OpenStreetMap data is always changing, rendering bug reports should **always**
contain a cropped screenshot of the problem, and a link to the area. Don't assume
that we will see exactly what you see. If a particular OSM object is an issue,
the issue should contain the tagging of the object.

## Workflow

We operate the "Fork & Pull" model explained at
Expand All @@ -10,16 +17,24 @@ You should fork the project into your own repo, create a topic branch
there and then make one or more pull requests back to the gravitystorm repository.
Your pull requests will then be reviewed and discussed.

## Reporting issues
Pull requests that change the cartography should contain a few images selected
to show the changes. The easiest way to make these is by taking screenshots and
cropping them, then pasting them into the issue. Avoid adding an overwhelming
number of screenshots.

As OpenStreetMap data is always changing, rendering bug reports should **always**
contain a cropped screenshot of the problem, and a link to the area. Don't assume
that we will see exactly what you see. If a particular OSM object is an issue,
the issue should contain the tagging of the object.
The images are not intended to replace reviewing changes in Kosmtik or TileMill,
but to provide an overview.

### Previews

Some changes benefit from a review over a wider area and many zooms, where static
images might not be sufficient and a demo layer is necessary. pnorman has a server
which can host layers and has some data from parts of the world loaded. Before
requesting this in a pull request, make sure that it is in a stable condition.

## Easy pickings

Some [easy issues](https://github.com/gravitystorm/openstreetmap-carto/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) have been selected
Some [easy issues](https://github.com/gravitystorm/openstreetmap-carto/labels/good%20first%20issue) have been selected
that are particularly suitable for new contributors to get familiar with the project's code base and the contribution process.

## Editing layers
Expand Down Expand Up @@ -101,6 +116,27 @@ instead of
}
}
```
* Use the PostgreSQL quoting syntax for attributes (columns) and string-values of selectors.
Use no quotes or double quotes for attributes (columns) and single quotes for string-values.
For Example:

```mss
#layer[entrance = 'yes'] {
marker-width: 6.0;
}
#layer["generator:source" = 'wind'] {
marker-width: 8.0;
}
```
instead of
```mss
#layer[entrance = "yes"] {
marker-width: 6.0;
}
#layer['generator:source' = 'wind'] {
marker-width: 8.0;
}
```

## SQL style guidelines
Because SQL within JSON or YAML will not generally be syntax highlighted, indentation and caps are particularly important.
Expand Down Expand Up @@ -133,8 +169,8 @@ Because SQL within JSON or YAML will not generally be syntax highlighted, indent
### External icon design resources
The project's goals and design philsophy are different from other projects, but some external resources with general information about icon design are:

* [Maki Icons Design Guidelines](https://www.mapbox.com/maki-icons/guidelines/)
* [GNOME Icon Design Guildelines](https://developer.gnome.org/hig/stable/icons-and-artwork.html.en)
* [Maki Icons Design Guidelines](https://labs.mapbox.com/maki-icons/guidelines/)
* [GNOME Icon Design Guildelines](https://developer.gnome.org/hig/guidelines/ui-icons.html)

## Typography

Expand All @@ -144,22 +180,29 @@ size should be ≥ 10 (legibility).
### Multi-line labels

Additional to text-size we have to set text-wrap-width and text-line-spacing.
For both, the absolute value is meaningless; it should be interpreted relative
to the font size (em):
For both, the absolute value is quite meaningless; it should rather be
interpreted relative to the font size (em) that has been set in “text-size”:
```mss
text-size: 10;
text-wrap-width: 30; // 3.0 em
text-line-spacing: -1.5; // -0.15 em
```
- The text-size is 10, so we have: 1 em = 10
- The text-wrap-width should be 3.0 em, so we have: 3.0 * 10 = 30
- The text-line-spacing should be -0.15 em, so we have: -0.15 * 10 = -1.5

If text-size increases on higher zoom levels the other parameters also have
to be adjusted:
to be adjusted to guarantee the same line wrap and same relative line spacing:
```mss
text-size: 12;
text-wrap-width: 36; // 3.0 em
text-line-spacing: -1.8; // -0.15 em
```

Usually, with higher zoom levels we increase the line length
(text-wrap-width in em). Following an old typography convention, we use narrow
(text-wrap-width measured in em!).

Following an old typography convention, we use narrow
line spacing for short lines and wider line spacing for longer lines.
```mss
text-size: 15;
Expand All @@ -172,19 +215,10 @@ cartographic usage; therefore we reduce the line spacing. Currently, the
line spacing ranges from -0.15 em to -0.05 em. (Even at -0.15 em, collisions
are seldom and even then the text stays legible).

## Pull requests
## Syntax highlighting

Pull requests that change the cartography should contain a few images selected
to show the changes. The easiest way to make these is by taking screenshots and
cropping them, then pasting them into the issue. Avoid adding an overwhelming
number of screenshots.

The images are not intended to replace reviewing changes in Kosmtik or TileMill,
but to provide an overview.
Most of the style development happens within CartoCSS MSS and MML files. Syntax highlighting can make editing more pleasant.

### Previews
Editors based on KDE Frameworks (Kate, KWrite, KDevelop…) provide syntax highlighting for CartoCSS MSS out-of-the-box, and starting with KF 5.100 also for CartoCSS MML including SQL highlighting within the YAML structure.

Some changes benefit from a review over a wider area and many zooms, where static
images might not be sufficient and a demo layer is necessary. pnorman has a server
which can host layers and has some data from parts of the world loaded. Before
requesting this in a pull request, make sure that it is in a stable condition.
Also, Yohan Boniface [has developed](https://github.com/yohanboniface/carto-atom) highlighting for CartoCSS MSS for editors that use the TextMate Language Grammar for syntax highlighting: Atom (install package “language-carto”), Visual Studio Code, Jetbrains…
85 changes: 58 additions & 27 deletions DOCKER.md

Large diffs are not rendered by default.

27 changes: 13 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
FROM ubuntu:xenial
FROM ubuntu:focal

# https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
ARG DEBIAN_FRONTEND=noninteractive

# Style dependencies
RUN apt-get update && apt-get install --no-install-recommends -y \
unzip curl ca-certificates gnupg python postgresql-client \
fonts-noto-cjk fonts-noto-hinted fonts-noto-unhinted ttf-unifont \
mapnik-utils \
&& rm -rf /var/lib/apt/lists/*

# Node.js 6.x LTS
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash \
&& apt-get install --no-install-recommends -y nodejs \
&& rm -rf /var/lib/apt/lists/*
ca-certificates curl gnupg postgresql-client python3 python3-distutils \
fonts-hanazono fonts-noto-cjk fonts-noto-hinted fonts-noto-unhinted \
mapnik-utils nodejs npm ttf-unifont unzip git && rm -rf /var/lib/apt/lists/*

# Kosmtik with plugins
RUN npm install -g kosmtik
# Kosmtik with plugins, forcing prefix to /usr because Ubuntu sets
# npm prefix to /usr/local, which breaks the install
# We install kosmtik not from release channel, but directly from a specific commit on github.
RUN npm set prefix /usr && npm install -g --unsafe-perm "git+https://git@github.com/kosmtik/kosmtik.git"

WORKDIR /usr/lib/node_modules/kosmtik/
WORKDIR /usr/lib/node_modules/kosmtik/
RUN kosmtik plugins --install kosmtik-overpass-layer \
--install kosmtik-fetch-remote \
--install kosmtik-overlay \
--install kosmtik-open-in-josm \
--install kosmtik-map-compare \
--install kosmtik-map-compare \
--install kosmtik-osm-data-overlay \
--install kosmtik-mapnik-reference \
--install kosmtik-geojson-overlay \
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.db
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
FROM mdillon/postgis:9.6
FROM postgis/postgis:10-2.5-alpine

ADD ./scripts/tune-postgis.sh /docker-entrypoint-initdb.d
COPY ./scripts/tune-postgis.sh /docker-entrypoint-initdb.d/tune-postgis.sh
18 changes: 14 additions & 4 deletions Dockerfile.import
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
FROM ubuntu:xenial
FROM ubuntu:bionic

RUN apt-get update && apt-get install --no-install-recommends -y \
curl ca-certificates osm2pgsql postgresql-client \
&& rm -rf /var/lib/apt/lists/*
ca-certificates curl gnupg && rm -rf /var/lib/apt/lists/*

ADD openstreetmap-carto.style /
RUN echo 'deb http://ppa.launchpad.net/osmadmins/ppa/ubuntu bionic main\n\
deb-src http://ppa.launchpad.net/osmadmins/ppa/ubuntu bionic main' > \
/etc/apt/sources.list.d/osmadmins-ppa.list

RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 \
--recv A438A16C88C6BE41CB1616B8D57F48750AC4F2CB

RUN apt-get update && apt-get install --no-install-recommends -y \
osm2pgsql gdal-bin python3-psycopg2 python3-yaml unzip \
python3-requests postgresql-client && rm -rf /var/lib/apt/lists/*

ADD openstreetmap-carto-flex.lua /

RUN mkdir -p /openstreetmap-carto
WORKDIR /openstreetmap-carto
Expand Down
174 changes: 81 additions & 93 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,139 +1,127 @@
# Installation

This document describes how to manually configure your system for running openstreetmap-carto. If you prefer quick, platform independent setup for a development environment, without the need to install and configure tools by hand, follow a Docker installation guide in [DOCKER.md](https://github.com/gravitystorm/openstreetmap-carto/blob/master/DOCKER.md).
This document describes how to manually configure your system for running OpenStreetMap Carto. If you prefer quick, platform independent setup for a development environment, without the need to install and configure tools by hand, follow a Docker installation guide in [DOCKER.md](DOCKER.md).

## OpenStreetMap data
You need OpenStreetMap data loaded into a PostGIS database (see below for [dependencies](#dependencies)). These stylesheets expect a database generated with osm2pgsql using the pgsql backend (table names of `planet_osm_point`, etc), the default database name (`gis`), and the [lua transforms](https://github.com/openstreetmap/osm2pgsql/blob/master/docs/lua.md) documented in the instructions below.
You need OpenStreetMap data loaded into a PostGIS database (see below for [dependencies](#dependencies)). These stylesheets expect a database generated with osm2pgsql using the flex backend.

Start by creating a database
Start by creating a database, we are using the database name `gis` here:

```
```sh
sudo -u postgres createuser -s $USER
createdb gis
```

Enable PostGIS and hstore extensions with

```
```sh
psql -d gis -c 'CREATE EXTENSION postgis; CREATE EXTENSION hstore;'
```

then grab some OSM data. It's probably easiest to grab an PBF of OSM data from [Geofabrik](https://download.geofabrik.de/). Once you've done that, import with osm2pgsql:
Then, grab some OSM data; It's probably easiest to grab an PBF of OSM data from [Geofabrik](https://download.geofabrik.de/). Once you've done that, import with osm2pgsql:

```sh
osm2pgsql -O flex -S openstreetmap-carto-flex.lua -d gis ~/path/to/data.osm.pbf
```
osm2pgsql -G --hstore --style openstreetmap-carto.style --tag-transform-script openstreetmap-carto.lua -d gis ~/path/to/data.osm.pbf
```

You can find a more detailed guide to setting up a database and loading data with osm2pgsql at [switch2osm.org](https://switch2osm.org/manually-building-a-tile-server-16-04-2-lts/).
You can find a more detailed guide to setting up a database and loading data with osm2pgsql at [switch2osm.org](https://switch2osm.org/serving-tiles/manually-building-a-tile-server-16-04-2-lts/).

### Disable JIT

We do not recommend [PostgreSQL JIT](https://www.postgresql.org/docs/current/jit-reason.html), which is on by default in PostgreSQL 12 and higher. JIT is benifitial for slow queries where executing the SQL takes substantial time and that time is not spent in function calls. This is not the case for rendering, where most time is spent either fetching from disk, in PostGIS functions, or the query is fast. In theory, the query planner will only use JIT on slower queries, but it is known to get the type of queries map rendering requires wrong.

Disabling JIT is **essential** for use with Kosmtik and other style development tools.

JIT can be disabled with `psql -d gis -c 'ALTER SYSTEM SET jit=off;' -c 'SELECT pg_reload_conf();'` or any other means of adjusting the PostgreSQL config.

### Custom indexes
Custom indexes are not required, but will speed up rendering, particularly for full planet databases, heavy load, or other production environments. They will not be as helpful with development using small extracts.
Custom indexes are required for rendering performance and are essential on full planet databases. These are generated by the `scripts/indexes.py` script, see `scripts/indexes.py --help` for various advanced options, but the command below will work to create the indexes on a new installation:

```
```sh
psql -d gis -f indexes.sql
```

## Scripted download
Some features are rendered using preprocessed shapefiles.

To obtain them you can run the following script.
The indexes can be created in parallel with

```
scripts/get-shapefiles.py
```sh
scripts/indexes.py -0 | xargs -0 -P0 -I{} psql -d gis -c "{}"
```

This script downloads necessary files, generates and populates the *data* directory with all needed shapefiles, including indexing them through *shapeindex*.
### Database functions
Some functions need to be loaded into the database for current versions. These can be added / re-loaded at any point using:

## Manual download
```sh
psql -d gis -f functions.sql
```

You can also download them manually at the following paths:
## Scripted download
Some features are rendered using preprocessed shapefiles.

* [`world_bnd_m.shp`, `places.shp`, `world_boundaries_m.shp`](https://planet.openstreetmap.org/historical-shapefiles/world_boundaries-spherical.tgz)
* [`simplified_land_polygons.shp`](http://data.openstreetmapdata.com/simplified-land-polygons-complete-3857.zip) (updated daily)
* [`ne_110m_admin_0_boundary_lines_land.shp`](http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_boundary_lines_land.zip)
* [`land_polygons.shp`](http://data.openstreetmapdata.com/land-polygons-split-3857.zip) (updated daily)
* [`icesheet_polygons.shp`](http://data.openstreetmapdata.com/antarctica-icesheet-polygons-3857.zip)
* [`icesheet_outlines.shp`](http://data.openstreetmapdata.com/antarctica-icesheet-outlines-3857.zip)
To download them and import them into the database you can run the following script:

The repeated www.naturalearthdata.com in the Natural Earth shapefiles is correct.
```sh
scripts/get-external-data.py
```

Put these shapefiles at `path/to/openstreetmap-carto/data`.
The script downloads shapefiles, loads them into the database, and sets up the tables for rendering. Additional script options and corresponding documentation is available by invoking `scripts/get-external-data.py --help`.

## Fonts
The stylesheet uses Noto, an openly licensed font family from Google with support for multiple scripts. The stylesheet uses Noto's "Sans" style where available. If not available, this stylesheet uses another appropriate style of the Noto family. The "UI" version is used where available, with its vertical metrics which fit better with Latin text.

DejaVu Sans is used as an optional fallback font for systems without Noto Sans. If all the Noto fonts are installed, it should never be used. Noto Naskh Arabic UI is used an an optional fallback font for systems without Noto Sans Arabic.
The stylesheet uses Noto, an openly licensed font family from Google with support for multiple scripts. The stylesheet uses Noto's "Sans" style where available. If not available, this stylesheet uses another appropriate style from the Noto family. The "UI" version is used where available, as its vertical metrics fit better with Latin text.

Hanazono is used a fallback for seldom used CJK characters that are not covered by Noto.

Unifont is used as a last resort fallback, with it's excellent coverage, common presence on machines, and ugly look.

### Installation on Ubuntu/Debian
For more details, see the documentation at [fonts.mss](style/fonts.mss).

On Ubuntu 16.04 or Debian Testing you can download and install most of the required fonts
To download the fonts, run the following script

```
sudo apt-get install fonts-noto-cjk fonts-noto-hinted fonts-noto-unhinted fonts-hanazono ttf-unifont
scripts/get-fonts.sh
```

Noto Emoji Regular can be downloaded [from the Noto Emoji repository](https://github.com/googlei18n/noto-emoji).

It might be useful to have a more recent version of the fonts for [rare non-latin scripts](#non-latin-scripts). The current upstream font release has also some more scripts and style variants than in the Ubuntu package. It can be installed [from source](https://github.com/googlei18n/noto-fonts/blob/master/FAQ.md#where-are-the-fonts).

DejaVu is packaged as `fonts-dejavu-core`.

### Installation on other operation systems

The fonts can be downloaded here:

* [Noto homepage](https://www.google.com/get/noto/) and [Noto github repositories](https://github.com/googlei18n?utf8=%E2%9C%93&q=noto)
* [DejaVu homepage](http://dejavu-fonts.org/)
* [Hanazono homepage](http://fonts.jp/hanazono/)
* [Unifont homepage](http://unifoundry.com/)

After the download, you have to install the font files in the usual way of your operation system.

### Non-latin scripts

For proper rendering of non-latin scripts, particularly those with complicated diacritics and tone marks the requirements are

* FreeType 2.6.2 or later for CJK characters

* A recent enough version of Noto with coverage for the scripts needed.

## Dependencies

For development, a style design studio is needed.
* [Kosmtik](https://github.com/kosmtik/kosmtik) - Kosmtik can be launched with `node index.js serve path/to/openstreetmap-carto/project.mml`

[TileMill](https://tilemill-project.github.io/tilemill/) is not officially supported, but you may be able to use a recent TileMill version by copying or symlinking the project directly into your Mapbox/project directory.

To display any map a database containing OpenStreetMap data and some utilities are required

To display *any* map, a database containing OpenStreetMap data and some utilities are required:
* [PostgreSQL](https://www.postgresql.org/)
* [PostGIS](https://postgis.net/)
* [osm2pgsql](https://github.com/openstreetmap/osm2pgsql#installing) to [import your data](https://switch2osm.org/loading-osm-data/) into a PostGIS database
* `curl` and `unzip` for downloading and decompressing files
* shapeindex (a companion utility to Mapnik found in the `mapnik-utils` package) for indexing downloaded shapefiles

### Optional development dependencies

Some colours, SVGs and other files are generated with helper scripts. Not all users will need these dependencies

* Python and Ruby to run helper scripts
* [Color Math](https://github.com/gtaylor/python-colormath) and [numpy](http://www.numpy.org/) if running generate_road_colors.py helper script (may be obtained with `pip install colormath numpy`)

### Additional deployment dependencies

For deployment, CartoCSS and Mapnik are required.

* [CartoCSS](https://github.com/mapbox/carto) >= 0.18.0 (we're using YAML)
* [Mapnik](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) >= 3.0

With CartoCSS you compile these sources into a Mapnik compatible XML file. When running CartoCSS, specify the Mapnik API version you are using (at least 3.0.0: `carto -a "3.0.0"`).

If you're calling Mapnik in your own program, remember to load the XML file in non strict mode. This way, fonts declared with alternative names will only generate warnings, not errors. For instance, using the Python bindings, this becomes:

```python
mapnik.load_map(mapnik.Map(width, height), xml_filename, False) # False for non-strict mode
```
* [`osm2pgsql`](https://github.com/openstreetmap/osm2pgsql#installing)>=`1.8.0` to [import your data](https://switch2osm.org/serving-tiles/updating-as-people-edit-osm2pgsql-replication/) into a PostGIS database
* [Python 3](https://www.python.org/downloads/) with the `psycopg2`, `pyyaml`, and `requests` libraries (`python3-psycopg2`, `python3-pyyaml`, `python3-requests` packages on Debian-derived systems)
```bash
python3 -m pip install --break-system-packages --user pyyaml requests psycopg2
```
* [`ogr2ogr`](https://gdal.org/en/latest/download.html) for loading shapefiles into the database (`gdal-bin` on Debian-derived systems)

### For development (style design studio)

* [Kosmtik](https://github.com/kosmtik/kosmtik)
* Install it:
```bash
git clone https://github.com/kosmtik/kosmtik
cd kosmtik
npm install
```
* _The 0.0.17 release of Kosmtik wouldn't be enough because we need up-to-date CartoCSS and Mapnik versions._
* Launch it:
```bash
node index.js serve path/to/openstreetmap-carto/project.mml
```
* [TileMill](https://tilemill-project.github.io/tilemill/)
* Not officially supported, but you may be able to use a recent TileMill version by copying or symlinking the project directly into your Mapbox/project directory.
#### Optional
Some colours, SVGs and other files are generated with helper scripts. Not all users will need these dependencies.
* [Python](https://www.python.org/downloads/)
* [`generate_road_colours.py`](./scripts/generate_road_colours.py) and [`generate_unpaved_patterns.py`](./scripts/generate_unpaved_patterns.py) depend on [Color Math](https://github.com/gtaylor/python-colormath) and [`numpy`](https://numpy.org/). To install these, run:
```bash
python3 -m pip install --break-system-packages --user colormath numpy
```
### For deployment
CartoCSS and Mapnik are required for deployment.
* [CartoCSS](https://github.com/mapbox/carto) >= `1.2.0` *(we're using YAML)*
* [Mapnik](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) >= `3.0.22`

With CartoCSS, these sources are compiled into a Mapnik compatible XML file. When running CartoCSS, specify the Mapnik API version you are using (at least 3.0.22: `carto -a "3.0.22"`).
47 changes: 27 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

![screenshot](https://raw.github.com/gravitystorm/openstreetmap-carto/master/preview.png)

These are the CartoCSS map stylesheets for the Standard map layer on [OpenStreetMap.org](https://www.openstreetmap.org).
These are the CartoCSS map stylesheets for the Standard map layer on [OpenStreetMap.org](https://www.openstreetmap.org/).

The general purpose, the cartographic design goals and guidelines for this style are outlined in [CARTOGRAPHY.md](CARTOGRAPHY.md).

These stylesheets can be used in your own cartography projects, and are designed
to be easily customised. They work with [Kosmtik](https://github.com/kosmtik/kosmtik)
and also with the command-line [CartoCSS](https://github.com/mapbox/carto) processor.

Since August 2013 these stylesheets have been used on the OSMF tileservers (tile.openstreetmap.org), and
Since August 2013 these stylesheets have been used on the [OSMF tileservers](https://operations.osmfoundation.org/policies/tiles/) (tile.openstreetmap.org), and
are updated from each point release. They supersede the previous [XML-based stylesheets](https://github.com/openstreetmap/mapnik-stylesheets).

# Installation

You need a PostGIS database populated with OpenStreetMap data along with auxillary shapefiles.
You need a PostGIS database populated with OpenStreetMap data along with auxillary shapefiles.
See [INSTALL.md](INSTALL.md).

# Contributing
Expand All @@ -35,7 +37,7 @@ cartographic project you can expect the following:
shapefiles and fonts but will not contain changes that require software or
database upgrades.
* MAJOR: Any change the requires reloading a database, or upgrading software
dependecies will trigger a major version change.
dependencies will trigger a major version change.

# Roadmap

Expand All @@ -58,18 +60,19 @@ versions.

Care has been taken to not get too clever with variables and expressions. While
these often make it easier to customise, experience has shown that over-cleverness
(e.g. [interpolated entities][cleverness]) can discourage contributions.

[issues]: https://github.com/gravitystorm/openstreetmap-carto/issues
[cleverness]: https://github.com/openstreetmap/mapnik-stylesheets/blob/master/inc/settings.xml.inc.template#L16
(e.g. [interpolated entities](https://github.com/openstreetmap/mapnik-stylesheets/blob/master/inc/settings.xml.inc.template#L16)) can discourage contributions.

## Database schema change (v4.x)

The v4.x series includes [osm2pgsql lua transforms](https://github.com/openstreetmap/osm2pgsql/blob/master/docs/lua.md)
and a hstore column with all other tags, allowing use of more OpenStreetMap data. Users need
The v4.x series includes [osm2pgsql lua transforms](https://osm2pgsql.org/doc/manual.html#lua-tag-transformations)
and a hstore column with all other tags, allowing use of more OpenStreetMap data. Users need
to reload their databases, v3.x compatibility is not maintained.

There are over [300 open requests][issues], some that have been open for years.
## Database schema change (v5.x)

The v5.x series updates Lua tag transforms, linestring and polygon decisions have changed.

There are over [500 open requests](https://github.com/gravitystorm/openstreetmap-carto/issues), some that have been open for years.
These need reviewing and dividing into obvious fixes, or additional new features
that need some cartographic judgement.

Expand All @@ -78,18 +81,22 @@ that need some cartographic judgement.
There are many open-source stylesheets written for creating OpenStreetMap-based
maps using Mapnik, many based on this project. Some alternatives are:

* [OSM-Bright](https://github.com/mapbox/osm-bright)
* [XML-based stylesheets](https://trac.openstreetmap.org/browser/subversion/applications/rendering/mapnik)
* [osmfr-cartocss](https://github.com/cquest/osmfr-cartocss)
* [openstreetmap-carto-german](https://github.com/giggls/openstreetmap-carto-de)
* [OSM Bright](https://github.com/geofabrik/osm-bright)
* [XML-based stylesheets](https://github.com/openstreetmap/mapnik-stylesheets)
* [OpenStreetMap "FR" Carto](https://github.com/cquest/osmfr-cartocss)
* [OpenStreetMap Carto German](https://github.com/giggls/openstreetmap-carto-de)

# Maintainers

* Andy Allan [@gravitystorm](https://github.com/gravitystorm/)
* Matthijs Melissen [@matthijsmelissen](https://github.com/matthijsmelissen/)
* Paul Norman [@pnorman](https://github.com/pnorman/)
* Mateusz Konieczny [@matkoniecz](https://github.com/matkoniecz/)
* Andy Allan [@gravitystorm](https://github.com/gravitystorm)
* Daniel Koć [@kocio-pl](https://github.com/kocio-pl)
* Christoph Hormann [@imagico](https://github.com/imagico)
* Michael Glanznig [@nebulon42](https://github.com/nebulon42)
* Lukas Sommer [@sommerluk](https://github.com/sommerluk)
* Joseph Eisenberg [@jeisenbe](https://github.com/jeisenbe)

## Previous maintainers

* Paul Norman [@pnorman](https://github.com/pnorman)
* Michael Glanznig [@nebulon42](https://github.com/nebulon42)
* Matthijs Melissen [@matthijsmelissen](https://github.com/matthijsmelissen)
* Mateusz Konieczny [@matkoniecz](https://github.com/matkoniecz)
16 changes: 8 additions & 8 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@ Decide among the maintainers if a new release is due.

# Notifications

1. Notify OSMF tile server admins [with an issue on OpenStreetMap Chef](https://github.com/openstreetmap/chef/issues/new?title=New%20openstreetmap-carto%20release,%20$NEW_RELEASE&body=A%20new%20version%20of%20openstreetmap-carto,%20[$NEW_RELEASE]%28https://github.com/gravitystorm/openstreetmap-carto/releases/tag/$NEW_RELEASE%29,%20has%20been%20released.). Add any deployment-related changes like new shapefiles or font changes to the ticket.
1. Notify OSMF tile server admins [with an issue on OpenStreetMap Chef](https://github.com/openstreetmap/chef/issues/new?title=New%20OpenStreetMap%20Carto%20release,%20$NEW_RELEASE&body=A%20new%20version%20of%20OpenStreetMap%20Carto,%20[$NEW_RELEASE]%28https://github.com/gravitystorm/openstreetmap-carto/releases/tag/$NEW_RELEASE%29,%20has%20been%20released.). Add any deployment-related changes like new shapefiles or font changes to the ticket.

2. Write an email to dev@openstreetmap.org and talk@openstreetmap.org with the subject "OpenStreetMap Carto release $NEW_VERSION" and the body

```
Dear all,
Today, $NEW_VERSION of the OpenStreetMap Carto stylesheet (the default
stylesheet on the OSM website) has been released. Once changes are deployed
on the openstreetmap.org it will take couple of days before all tiles
show the new rendering.
stylesheet on the OSM website) has been released. Once changes are
deployed on the openstreetmap.org it will take couple of days before
all tiles show the new rendering.
If the tile server admins have rolled out the new version, change it to:
Today, $NEW_VERSION of the openstreetmap-carto stylesheet (the default
stylesheet on the OSM website) has been released and rolled out
to the openstreetmap.org servers. It might take a couple of days
before all tiles show the new rendering.
Today, $NEW_VERSION of the OpenStreetMap Carto stylesheet (the default
stylesheet on the OSM website) has been released and rolled out
to the openstreetmap.org servers. It might take a couple of days
before all tiles show the new rendering.
Changes include
*A list of changes*
Expand Down
10 changes: 5 additions & 5 deletions USECASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ As we are still experimenting with this way of design, this document is restrict
| Looking up province/state location|Province/state names and borders|Country borders | z6, z7 |
| Looking up city location | City names | Coastlines, country names, country borders | z5, z6, z7 |
| Long distance road trip planning | Motorways | City names | z6, z7 |
| Understanding what the area looks like | Natural areas (woods, grass, scrubs, heath, ice, lakes, rocks, sands etc.) <br/> natural lines (big rivers) <br/> semi-natural areas (farmlands, vineyards, orchards, parks etc.) <br/> semi-natural lines (big canals) | Coastlines, relief | z5, z6, z7 |

This gives us the following features:

* z5: Map subject: Country names, country borders, city names. Map context: seas, oceans.
* z5 in USA: Map subject: Province/state names and borders. Map context: Country names, country borders, seas oceans
* z6: Map subject: Country names, country borders, province/state names and borders, motorways, city names. Map context: Seas, oceans, country borders, city names.
* z7: Map subject: Province/state names and borders, city names, motorways. Map context: Seas, oceans, country names, country borders.
* z5: Map subject: Country names, country borders, city names, (semi-)natural areas+lines. Map context: seas, oceans, relief.
* z5 in USA: Map subject: Province/state names and borders, (semi-)natural areas+lines. Map context: Country names, country borders, seas oceans, relief.
* z6: Map subject: Country names, country borders, province/state names and borders, motorways, city names, (semi-)natural areas+lines. Map context: Seas, oceans, country borders, city names, relief.
* z7: Map subject: Province/state names and borders, city names, motorways, (semi-)natural areas+lines. Map context: Seas, oceans, country names, country borders, relief.

Some features that we currently render for which we do not (yet) have a use case:

* Province/state names and borders (except USA) on z5
* Minor water areas on z5/6/7
* Island names on z5/6/7
254 changes: 0 additions & 254 deletions admin.mss

This file was deleted.

106 changes: 0 additions & 106 deletions aerialways.mss

This file was deleted.

5 changes: 4 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version: '2'
services:
kosmtik:
image: kosmtik:v1
platform: linux/amd64
build:
context: .
dockerfile: Dockerfile
Expand All @@ -10,7 +11,7 @@ services:
depends_on:
- db
ports:
- "6789:6789"
- "127.0.0.1:6789:6789"
environment:
- PGHOST=db
- PGUSER=postgres
Expand All @@ -20,6 +21,7 @@ services:
context: .
dockerfile: Dockerfile.db
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
- PG_WORK_MEM
- PG_MAINTENANCE_WORK_MEM
import:
Expand All @@ -39,3 +41,4 @@ services:
- OSM2PGSQL_CACHE
- OSM2PGSQL_NUMPROC
- OSM2PGSQL_DATAFILE
- EXTERNAL_DATA_SCRIPT_FLAGS
81 changes: 81 additions & 0 deletions external-data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
settings:
temp_schema: loading
schema: public
data_dir: data
database: gis
metadata_table: external_data
sources:
simplified_water_polygons:
# The type of file this source is
type: shp
# Where to get it
url: https://osmdata.openstreetmap.de/download/simplified-water-polygons-split-3857.zip
# The location within the archive
file: simplified-water-polygons-split-3857/simplified_water_polygons.shp
archive:
format: zip
# Files to extract from the archive
files:
- simplified-water-polygons-split-3857/simplified_water_polygons.cpg
- simplified-water-polygons-split-3857/simplified_water_polygons.dbf
- simplified-water-polygons-split-3857/simplified_water_polygons.prj
- simplified-water-polygons-split-3857/simplified_water_polygons.shp
- simplified-water-polygons-split-3857/simplified_water_polygons.shx
water_polygons:
type: shp
url: https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip
file: water-polygons-split-3857/water_polygons.shp
archive:
format: zip
files:
- water-polygons-split-3857/water_polygons.cpg
- water-polygons-split-3857/water_polygons.dbf
- water-polygons-split-3857/water_polygons.prj
- water-polygons-split-3857/water_polygons.shp
- water-polygons-split-3857/water_polygons.shx
icesheet_polygons:
type: shp
url: https://osmdata.openstreetmap.de/download/antarctica-icesheet-polygons-3857.zip
file: antarctica-icesheet-polygons-3857/icesheet_polygons.shp
archive:
format: zip
files:
- antarctica-icesheet-polygons-3857/icesheet_polygons.cpg
- antarctica-icesheet-polygons-3857/icesheet_polygons.dbf
- antarctica-icesheet-polygons-3857/icesheet_polygons.prj
- antarctica-icesheet-polygons-3857/icesheet_polygons.shp
- antarctica-icesheet-polygons-3857/icesheet_polygons.shx
icesheet_outlines:
type: shp
url: https://osmdata.openstreetmap.de/download/antarctica-icesheet-outlines-3857.zip
file: antarctica-icesheet-outlines-3857/icesheet_outlines.shp
ogropts:
- "-explodecollections"
archive:
format: zip
files:
- antarctica-icesheet-outlines-3857/icesheet_outlines.cpg
- antarctica-icesheet-outlines-3857/icesheet_outlines.dbf
- antarctica-icesheet-outlines-3857/icesheet_outlines.prj
- antarctica-icesheet-outlines-3857/icesheet_outlines.shp
- antarctica-icesheet-outlines-3857/icesheet_outlines.shx

ne_110m_admin_0_boundary_lines_land:
type: shp
url: https://naturalearth.s3.amazonaws.com/110m_cultural/ne_110m_admin_0_boundary_lines_land.zip
file: ne_110m_admin_0_boundary_lines_land.shp
ogropts: &ne_opts
- "--config"
- "SHAPE_ENCODING"
- "WINDOWS-1252"
- "-explodecollections"
# needs reprojecting
- '-t_srs'
- 'EPSG:3857'
archive:
format: zip
files:
- ne_110m_admin_0_boundary_lines_land.dbf
- ne_110m_admin_0_boundary_lines_land.prj
- ne_110m_admin_0_boundary_lines_land.shp
- ne_110m_admin_0_boundary_lines_land.shx
74 changes: 74 additions & 0 deletions functions.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* Additional database functions for openstreetmap-carto */

/* Access functions below adapted from https://github.com/imagico/osm-carto-alternative-colors/tree/591c861112b4e5d44badd108f4cd1409146bca0b/sql/roads.sql */

/* Simplified 'yes', 'destination', 'no', 'unrecognised', NULL scale for access restriction
'no' is returned if the rendering for highway category does not support 'restricted'.
NULL is functionally equivalent to 'yes', but indicates the absence of a restriction
rather than a positive access = yes. 'unrecognised' corresponds to an uninterpretable
access restriction e.g. access=unknown or motorcar=occasionally */
CREATE OR REPLACE FUNCTION carto_int_access(accessvalue text, allow_restricted boolean)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT
CASE
WHEN accessvalue IN ('yes', 'designated', 'permissive') THEN 'yes'
WHEN accessvalue IN ('destination', 'delivery', 'customers') THEN
CASE WHEN allow_restricted = TRUE THEN 'restricted' ELSE 'yes' END
WHEN accessvalue IN ('no', 'permit', 'private', 'agricultural', 'forestry', 'agricultural;forestry') THEN 'no'
WHEN accessvalue IS NULL THEN NULL
ELSE 'unrecognised'
END
$$;

/* Try to promote path to cycleway (if bicycle allowed), then bridleway (if horse)
This duplicates existing behaviour where designated access is required */
CREATE OR REPLACE FUNCTION carto_path_type(bicycle text, horse text)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT
CASE
WHEN bicycle IN ('designated') THEN 'cycleway'
WHEN horse IN ('designated') THEN 'bridleway'
ELSE 'path'
END
$$;

/* Return int_access value which will be used to determine access marking.
Return values are documented above for carto_int_access function.
Note that the code handling the promotion of highway=path assumes that
promotion to cycleway or bridleway is based on the value of bicycle or
horse respectively. A more general formulation would be, for example,
WHEN 'cycleway' THEN carto_int_access(COALESCE(NULLIF(bicycle, 'unknown'), "access"), FALSE) */
CREATE OR REPLACE FUNCTION carto_highway_int_access(highway text, "access" text, foot text, bicycle text, horse text, motorcar text, motor_vehicle text, vehicle text)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT
CASE
WHEN highway IN ('motorway', 'motorway_link', 'trunk', 'trunk_link', 'primary', 'primary_link', 'secondary',
'secondary_link', 'tertiary', 'tertiary_link', 'residential', 'unclassified', 'living_street', 'service', 'road') THEN
carto_int_access(
COALESCE(
NULLIF(motorcar, 'unknown'),
NULLIF(motor_vehicle, 'unknown'),
NULLIF(vehicle, 'unknown'),
"access"), TRUE)
WHEN highway = 'path' THEN
CASE carto_path_type(bicycle, horse)
WHEN 'cycleway' THEN carto_int_access(bicycle, FALSE)
WHEN 'bridleway' THEN carto_int_access(horse, FALSE)
ELSE carto_int_access(COALESCE(NULLIF(foot, 'unknown'), "access"), FALSE)
END
WHEN highway IN ('pedestrian', 'footway', 'steps') THEN carto_int_access(COALESCE(NULLIF(foot, 'unknown'), "access"), FALSE)
WHEN highway = 'cycleway' THEN carto_int_access(COALESCE(NULLIF(bicycle, 'unknown'), "access"), FALSE)
WHEN highway = 'bridleway' THEN carto_int_access(COALESCE(NULLIF(horse, 'unknown'), "access"), FALSE)
ELSE carto_int_access("access", TRUE)
END
$$;
58 changes: 17 additions & 41 deletions indexes.sql
Original file line number Diff line number Diff line change
@@ -1,42 +1,18 @@
-- These are optional but suggested indexes for rendering OpenStreetMap Carto
-- with a full planet database.
-- These are indexes for rendering performance with OpenStreetMap Carto.
-- This file is generated with scripts/indexes.py

CREATE INDEX planet_osm_roads_admin
ON planet_osm_roads USING GIST (way)
WHERE boundary = 'administrative';
CREATE INDEX planet_osm_roads_roads_ref
ON planet_osm_roads USING GIST (way)
WHERE highway IS NOT NULL AND ref IS NOT NULL;
CREATE INDEX planet_osm_roads_admin_low
ON planet_osm_roads USING GIST (way)
WHERE boundary = 'administrative' AND admin_level IN ('0', '1', '2', '3', '4');
CREATE INDEX planet_osm_line_ferry
ON planet_osm_line USING GIST (way)
WHERE route = 'ferry';
CREATE INDEX planet_osm_line_river
ON planet_osm_line USING GIST (way)
WHERE waterway = 'river';
CREATE INDEX planet_osm_line_name
ON planet_osm_line USING GIST (way)
WHERE name IS NOT NULL;
CREATE INDEX planet_osm_polygon_water
ON planet_osm_polygon USING GIST (way)
WHERE waterway IN ('dock', 'riverbank', 'canal')
OR landuse IN ('reservoir', 'basin')
OR "natural" IN ('water', 'glacier');
CREATE INDEX planet_osm_polygon_military
ON planet_osm_polygon USING GIST (way)
WHERE landuse = 'military';
CREATE INDEX planet_osm_polygon_nobuilding
ON planet_osm_polygon USING GIST (way)
WHERE building IS NULL;
CREATE INDEX planet_osm_polygon_name
ON planet_osm_polygon USING GIST (way)
WHERE name IS NOT NULL;
CREATE INDEX planet_osm_polygon_way_area_z6
ON planet_osm_polygon USING GIST (way)
WHERE way_area > 59750;
CREATE INDEX planet_osm_point_place
ON planet_osm_point USING GIST (way)
WHERE place IS NOT NULL AND name IS NOT NULL;
CREATE INDEX planet_osm_line_ferry ON planet_osm_line USING GIST (way) WHERE route = 'ferry' AND osm_id > 0;
CREATE INDEX planet_osm_line_label ON planet_osm_line USING GIST (way) WHERE name IS NOT NULL OR ref IS NOT NULL;
CREATE INDEX planet_osm_line_river ON planet_osm_line USING GIST (way) WHERE waterway = 'river';
CREATE INDEX planet_osm_line_waterway ON planet_osm_line USING GIST (way) WHERE waterway IN ('river', 'canal', 'stream', 'drain', 'ditch');
CREATE INDEX planet_osm_point_place ON planet_osm_point USING GIST (way) WHERE place IS NOT NULL AND name IS NOT NULL;
CREATE INDEX planet_osm_polygon_admin ON planet_osm_polygon USING GIST (ST_PointOnSurface(way)) WHERE name IS NOT NULL AND boundary = 'administrative' AND admin_level IN ('0', '1', '2', '3', '4');
CREATE INDEX planet_osm_polygon_military ON planet_osm_polygon USING GIST (way) WHERE (landuse = 'military' OR military = 'danger_area') AND building IS NULL;
CREATE INDEX planet_osm_polygon_name ON planet_osm_polygon USING GIST (ST_PointOnSurface(way)) WHERE name IS NOT NULL;
CREATE INDEX planet_osm_polygon_name_z6 ON planet_osm_polygon USING GIST (ST_PointOnSurface(way)) WHERE name IS NOT NULL AND way_area > 5980000;
CREATE INDEX planet_osm_polygon_nobuilding ON planet_osm_polygon USING GIST (way) WHERE building IS NULL;
CREATE INDEX planet_osm_polygon_water ON planet_osm_polygon USING GIST (way) WHERE waterway IN ('dock', 'riverbank', 'canal') OR landuse IN ('reservoir', 'basin') OR "natural" IN ('water', 'glacier');
CREATE INDEX planet_osm_polygon_way_area_z10 ON planet_osm_polygon USING GIST (way) WHERE way_area > 23300;
CREATE INDEX planet_osm_polygon_way_area_z6 ON planet_osm_polygon USING GIST (way) WHERE way_area > 5980000;
CREATE INDEX planet_osm_roads_admin ON planet_osm_roads USING GIST (way) WHERE boundary = 'administrative';
CREATE INDEX planet_osm_roads_admin_low ON planet_osm_roads USING GIST (way) WHERE boundary = 'administrative' AND admin_level IN ('0', '1', '2', '3', '4');
CREATE INDEX planet_osm_roads_roads_ref ON planet_osm_roads USING GIST (way) WHERE highway IS NOT NULL AND ref IS NOT NULL;
27 changes: 17 additions & 10 deletions indexes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,35 @@ point:
place:
where: place IS NOT NULL AND name IS NOT NULL
line:
name:
where: name IS NOT NULL
label:
where: name IS NOT NULL OR ref IS NOT NULL
ferry:
where: route = 'ferry'
where: route = 'ferry' AND osm_id > 0
river:
where: waterway = 'river'
waterway:
where: waterway IN ('river', 'canal', 'stream', 'drain', 'ditch')
polygon:
# The polygon table is by far the largest, and generally the slowest
name:
function: ST_PointOnSurface(way)
where: name IS NOT NULL
name_z6:
function: ST_PointOnSurface(way)
where: name IS NOT NULL AND way_area > 5980000
admin:
function: ST_PointOnSurface(way)
where: name IS NOT NULL AND boundary = 'administrative' AND admin_level IN ('0', '1', '2', '3', '4')
nobuilding:
where: building IS NULL
military:
where: landuse = 'military'
where: (landuse = 'military' OR military = 'danger_area') AND building IS NULL
water:
# The indentation here makes sense in the SQL output
where: |-
waterway IN ('dock', 'riverbank', 'canal')
OR landuse IN ('reservoir', 'basin')
OR "natural" IN ('water', 'glacier')
where: waterway IN ('dock', 'riverbank', 'canal') OR landuse IN ('reservoir', 'basin') OR "natural" IN ('water', 'glacier')
way_area_z6:
where: way_area > 59750
where: way_area > 5980000
way_area_z10:
where: way_area > 23300
roads:
# The roads table only has a subset of data, so it's just got some low-zoom
# indexes and some fairly selective ones for high zoom
Expand Down
689 changes: 689 additions & 0 deletions openstreetmap-carto-flex.lua

Large diffs are not rendered by default.

421 changes: 0 additions & 421 deletions openstreetmap-carto.lua

This file was deleted.

55 changes: 0 additions & 55 deletions openstreetmap-carto.style

This file was deleted.

4 changes: 4 additions & 0 deletions patterns/allotments.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions patterns/danger_red_hatch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions patterns/dog_park.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/grave_yard_christian.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/grave_yard_generic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/grave_yard_jewish.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/grave_yard_muslim.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/grey_vertical_hatch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/intermittent_water.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions patterns/military_red_hatch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions patterns/orchard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions patterns/plant_nursery.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions patterns/vineyard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2,286 changes: 1,082 additions & 1,204 deletions project.mml

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions scripts/change-fonts-cjk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/sh
set -e

FONTDIR="./fonts"

mkdir -p "${FONTDIR}"

# download filename url
download() {
## Download if newer, and if curl fails, clean up and exit
curl --fail --compressed -A "get-fonts.sh/osm-carto" -o "$1" -z "$1" -L "$2" || { echo "Failed to download $1 $2"; rm -f "$1"; exit 1; }
}

case "$1" in
ja)
download "${FONTDIR}/NotoSansCJKjp-Regular.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf"
download "${FONTDIR}/NotoSansCJKjp-Bold.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Bold.otf"
sed -i "s/Noto Sans CJK \(JP\|KR\|SC\|TC\|HK\)/Noto Sans CJK JP/g" ./style/fonts.mss
;;
ko)
download "${FONTDIR}/NotoSansCJKkr-Regular.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/Korean/NotoSansCJKkr-Regular.otf"
download "${FONTDIR}/NotoSansCJKkr-Bold.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/Korean/NotoSansCJKkr-Bold.otf"
sed -i "s/Noto Sans CJK \(JP\|KR\|SC\|TC\|HK\)/Noto Sans CJK KR/g" ./style/fonts.mss
;;
zh-[Hh]ans)
download "${FONTDIR}/NotoSansCJKsc-Regular.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf"
download "${FONTDIR}/NotoSansCJKsc-Bold.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Bold.otf"
sed -i "s/Noto Sans CJK \(JP\|KR\|SC\|TC\|HK\)/Noto Sans CJK SC/g" ./style/fonts.mss
;;
zh-[Hh]ant-[Tt][Ww])
download "${FONTDIR}/NotoSansCJKtc-Regular.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/TraditionalChinese/NotoSansCJKtc-Regular.otf"
download "${FONTDIR}/NotoSansCJKtc-Bold.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/TraditionalChinese/NotoSansCJKtc-Bold.otf"
sed -i "s/Noto Sans CJK \(JP\|KR\|SC\|TC\|HK\)/Noto Sans CJK TC/g" ./style/fonts.mss
;;
zh-[Hh]ant-[Hh][Kk])
download "${FONTDIR}/NotoSansCJKhk-Regular.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Regular.otf"
download "${FONTDIR}/NotoSansCJKhk-Bold.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Bold.otf"
sed -i "s/Noto Sans CJK \(JP\|KR\|SC\|TC\|HK\)/Noto Sans CJK HK/g" ./style/fonts.mss
;;
*)
echo "Usage: change-fonts-cjk.sh ja|ko|zh-Hans|zh-Hant-TW|zh-Hant-HK"
exit 1
;;
esac

echo "Done."
18 changes: 10 additions & 8 deletions scripts/docker-startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ PG_MAINTENANCE_WORK_MEM=${PG_MAINTENANCE_WORK_MEM:-256MB}
OSM2PGSQL_CACHE=${OSM2PGSQL_CACHE:-512}
OSM2PGSQL_NUMPROC=${OSM2PGSQL_NUMPROC:-1}
OSM2PGSQL_DATAFILE=${OSM2PGSQL_DATAFILE:-data.osm.pbf}
EXTERNAL_DATA_SCRIPT_FLAGS=${EXTERNAL_DATA_SCRIPT_FLAGS:-}
EOF
chmod a+rw .env
export OSM2PGSQL_CACHE=${OSM2PGSQL_CACHE:-512}
Expand All @@ -42,23 +43,24 @@ EOF
osm2pgsql \
--cache $OSM2PGSQL_CACHE \
--number-processes $OSM2PGSQL_NUMPROC \
--hstore \
--multi-geometry \
--database gis \
--slim \
--drop \
--style openstreetmap-carto.style \
--tag-transform-script openstreetmap-carto.lua \
--output flex \
--style openstreetmap-carto-flex.lua \
$OSM2PGSQL_DATAFILE

# Downloading and importing needed shapefiles
scripts/get-external-data.py $EXTERNAL_DATA_SCRIPT_FLAGS

# Download fonts
scripts/get-fonts.sh
;;

kosmtik)
# Downloading needed shapefiles
python scripts/get-shapefiles.py -n

# Creating default Kosmtik settings file
if [ ! -e ".kosmtik-config.yml" ]; then
cp /tmp/.kosmtik-config.yml .kosmtik-config.yml
cp /tmp/.kosmtik-config.yml .kosmtik-config.yml
fi
export KOSMTIK_CONFIGPATH=".kosmtik-config.yml"

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Thu, 01 Jan 1970 00:00:00 GMT
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Thu, 01 Jan 1970 00:00:00 GMT
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Thu, 01 Jan 1970 00:00:00 GMT
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Thu, 01 Jan 1970 00:00:00 GMT
Binary file added scripts/empty_files/water-polygons-split-3857.zip
Binary file not shown.
1 change: 1 addition & 0 deletions scripts/empty_files/water-polygons-split-3857.zip.lastmod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Thu, 01 Jan 1970 00:00:00 GMT
30 changes: 15 additions & 15 deletions scripts/generate_road_colours.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3

# Generates a set of highway colors to be stored in road-colors-generated.mss.

Expand Down Expand Up @@ -32,7 +32,7 @@ def rgb_error(self):

def load_settings():
"""Read the settings from YAML."""
return yaml.load(open('road-colors.yaml', 'r'))
return yaml.safe_load(open('road-colors.yaml', 'r'))

def generate_colours(settings, section):
"""Generate colour ranges.
Expand All @@ -50,7 +50,7 @@ def generate_colours(settings, section):
max_h = settings['hue'][1]

delta_h = (max_h - min_h) / colour_divisions

h = min_h
for name in road_classes:
hues[name] = h
Expand All @@ -69,15 +69,15 @@ def generate_colours(settings, section):
# the roads get brighter towards the lower end of the classification.

classes = settings['classes'][section]
for cls, params in classes.iteritems():
for cls, params in sorted(classes.items()):
l = params['lightness']
c = params['chroma']
line_colour_infos[cls] = ColourInfo(start_l = l[0], end_l = l[1], start_c = c[0], end_c = c[1])

# Colours for the MSS
colours = OrderedDict()

for line_name, line_colour_info in line_colour_infos.iteritems():
for line_name, line_colour_info in line_colour_infos.items():
c = line_colour_info.start_c
delta_c = (line_colour_info.end_c - line_colour_info.start_c) / colour_divisions
l = line_colour_info.start_l
Expand All @@ -102,20 +102,20 @@ def main():
colours = generate_colours(settings, 'mss')

# Print a warning about the nature of these definitions.
print "/* This is generated code, do not change this file manually. */"
print "/* */"
print "/* To change these definitions, alter road-colors.yaml and run: */"
print "/* */"
print "/* ./scripts/generate_road_colours.py > road-colors-generated.mss */"
print "/* */"

for line_name, line_colours in colours.iteritems():
for name, colour in line_colours.iteritems():
print("/* This is generated code, do not change this file manually. */")
print("/* */")
print("/* To change these definitions, alter road-colors.yaml and run: */")
print("/* */")
print("/* scripts/generate_road_colours.py > style/road-colors-generated.mss */")
print("/* */")

for line_name, line_colours in colours.items():
for name, colour in line_colours.items():
if args.verbose:
line = "@{name}-{line_name}: {rgb}; // {lch}, error {delta:.1f}"
else:
line = "@{name}-{line_name}: {rgb};"
print line.format(name = name, line_name=line_name, rgb = colour.rgb(), lch = colour.lch(), delta = colour.rgb_error())
print((line.format(name = name, line_name=line_name, rgb = colour.rgb(), lch = colour.lch(), delta = colour.rgb_error())))

if __name__ == "__main__":
main()
22 changes: 11 additions & 11 deletions scripts/generate_shields.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3

# Generate highway shields as SVG files in symbols/shields.

Expand Down Expand Up @@ -47,8 +47,8 @@ def main():
config['tertiary'] = {}

# Colour values generated by generate_road_colours.py.
for line_name, line_colours in colours.iteritems():
for name, colour in line_colours.iteritems():
for line_name, line_colours in colours.items():
for name, colour in line_colours.items():
config[name][line_name] = colour.rgb()

# changes for different size versions
Expand Down Expand Up @@ -84,9 +84,9 @@ def main():
shield_height = 2 * vars['padding_y'] + math.ceil(vars['font_height'] * height)

svg = lxml.etree.Element('svg', nsmap=svgnsmap)
svg.set('width', '100%')
svg.set('height', '100%')
svg.set('viewBox', '0 0 ' + str(shield_width + vars['stroke_width']) + ' ' + str(shield_height + vars['stroke_width']))
svg.set('width', str(shield_width + vars['stroke_width']))
svg.set('height', str(shield_height + vars['stroke_width']))
svg.set('viewBox', '0 0 ' + str(shield_width + vars['stroke_width']) + ' ' + str(shield_height + vars['stroke_width']))

if vars['stroke_width'] > 0:
offset_x = vars['stroke_width'] / 2.0
Expand All @@ -103,13 +103,13 @@ def main():
if vars['rounded_corners'] > 0:
shield.set('rx', str(vars['rounded_corners']))
shield.set('ry', str(vars['rounded_corners']))
shield.set('id', 'shield')

shield.set('fill', vars['fill'])

stroke = ''
if vars['stroke_width'] > 0:
stroke = 'stroke:' + vars['stroke_fill'] + ';stroke-width:' + str(vars['stroke_width']) + ';'

shield.set('style', 'fill:' + vars['fill'] + ';' + stroke)
shield.set('stroke', vars['stroke_fill'])
shield.set('stroke-width', str(vars['stroke_width']))

svg.append(shield)

Expand All @@ -121,7 +121,7 @@ def main():

# save file
try:
shieldfile = open(os.path.join(os.path.dirname(__file__), config['global']['output_dir'] + filename), 'w')
shieldfile = open(os.path.join(os.path.dirname(__file__), config['global']['output_dir'] + filename), 'wb')
shieldfile.write(lxml.etree.tostring(svg, encoding='utf-8', xml_declaration=True, pretty_print=True))
shieldfile.close()
except IOError:
Expand Down
143 changes: 143 additions & 0 deletions scripts/generate_unpaved_patterns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/usr/bin/env python3

# Colours for unpaved roads

# This reads some color variables from some .mss files and also reads
# symbols/unpaved/unpaved.svg and generates colourized versions of
# the unpaved pattern for all road types and saves them in the symbols/unpaved
# folder. Existing files of the same name are overwritten!
#
# This script produces patterns that perceptually have the same overall
# brightness as the original road color. Therefor, the pattern foreground
# is darker than the original color, and the pattern background lighter than
# the original color. This script does its very best, but the same overall
# brightness is not always possible (for example for white roads) and also
# depends on the monitor gammut on which the pattern is finally displayed.
#
# Usage: Call this script in the main directory of openstreetmap-carto
# without further parameters.
#
# Customize:
# You can customize this script by changing the first variables of in the main()
# function (color_names, file_names, darken, brighten_darken_ratio).

from colormath.color_objects import LabColor, sRGBColor
from colormath.color_conversions import convert_color

# def get_color_value_by_name(variable_name, file_names):
#
# Searches in MSS files for variable values with the given name. Returns
# the first value it finds. Only supports very basic syntax like:
# @test: 12; # Comment
# which would return "12".
#
# Paramaters:
# variable_name: the name of the variable for which we search the value
# file_names: list of files where we search for the variable value
#
# Return value: the variable value (if any)
def get_color_value_by_name(variable_name, file_names):
for files in file_names:
with open(files) as f:
for line in f:
if line.startswith("@" + variable_name + ":"):
temp = line.strip("@" + variable_name + ":").split(";")[0].strip()
# test if the value length is okay (#abc or #aabbcc)
if (len(temp) == 4) or (len(temp)== 7):
# remove the first character (#)
temp = temp[1:]
# expand value like #abc to #aabbcc
if len(temp) == 3:
temp = temp[0] + temp [0] + temp [1] + temp [1] + temp [2] + temp [2]
# make sure that the content is really a (lowercase) hex value
if all(c in set("0123456789abcdef") for c in temp):
# if so, return the hex value with a leading "#"
return ("#" + temp)

# Takes an RGB hex values, applies the indicated Lab lightness change and returns the result as RGB hex value again
# def change_lightness(base_color_rgb_hex, lightness_change):
#
# Changes the lightness of a given color. This function
# tries to do a perceptual transformation.
#
# Paramaters:
# base_color_rgb_hex: An RGB hex value like #1212ab
# lightness_change: A number (positive or negative), interpreted as change to the lightness component like in Lab perceptual color space (range: 0..100)
#
# Return value: The RGB hex value with the lightness change applied. If the lightness change leaves
# us with an out-of-gammut value, it is clipped to make sure to be within the RGB gammut. So the return
# value is guarantied to be always a valid RGB value.
def change_lightness(base_color_rgb_hex, lightness_change):
base_color_lab = convert_color(sRGBColor.new_from_rgb_hex(base_color_rgb_hex), LabColor)
new_color_lab = LabColor(
base_color_lab.lab_l + lightness_change, # This value might be out of gammut and therefor invalid
base_color_lab.lab_a,
base_color_lab.lab_b,
base_color_lab.observer,
base_color_lab.illuminant)
new_color_rgb = convert_color(new_color_lab, sRGBColor) # This value might be out of gammut and therefor invalid
# use the "clamped" values which means they are within the gammut and therefor valid
new_color_rgb_clamped = sRGBColor(
new_color_rgb.clamped_rgb_r,
new_color_rgb.clamped_rgb_g,
new_color_rgb.clamped_rgb_b)
return new_color_rgb_clamped.get_rgb_hex()

def main():

# List of names of color variables in mss code for which we will generate patterns
color_names = {
'motorway-low-zoom',
'trunk-low-zoom',
'primary-low-zoom',
'motorway-fill',
'trunk-fill',
'primary-fill',
'secondary-fill',
'platform-fill',
'aeroway-fill',
'road-fill',
'pedestrian-fill',
'living-street-fill',
'raceway-fill',
'residential-fill'
}

# List of names of mss files in which we search for color variables
file_names = {
'style/roads.mss',
'style/road-colors-generated.mss'
}

# The value by which the original color is darkened for the pattern foreground
# This value should always be negative.
darken = -60

# The pattern foreground occupies less space than the background. So lightening
# the background has to be less intense than darkening the foreground. This
# value is multiplied with the negative value of "darken" to get a value for
# "brighten", so brighten_darken_ration must also be negative to make sure
# the "brighten" result is positive. This value should (only) be changed when
# the pattern itself is changed.
brighten_darken_ratio = -0.065

# actual code
for color_name in color_names:
print("\nColor name: " + color_name)
original_color_value = get_color_value_by_name(color_name, file_names)
print("Plain color: " + original_color_value)
pattern_colors = [change_lightness(original_color_value, darken),
change_lightness(original_color_value, darken * brighten_darken_ratio)]
print("Colors for pattern: " + str(pattern_colors))
if pattern_colors:
with open('symbols/unpaved/unpaved.svg', 'rt') as fin:
with open('symbols/unpaved/unpaved_' + color_name + '.svg', 'wt') as fout:
for line in fin:
temp = line
temp = temp.replace('#0000ff', pattern_colors[0])
temp = temp.replace('fill:none', 'fill:' + pattern_colors[1])
fout.write(temp)
print("Pattern file: " + 'symbols/unpaved/unpaved_' + color_name + '.svg')

if __name__ == "__main__":
main()
405 changes: 405 additions & 0 deletions scripts/get-external-data.py

Large diffs are not rendered by default.

132 changes: 132 additions & 0 deletions scripts/get-fonts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/bin/sh
set -e

FONTDIR="./fonts"

mkdir -p "${FONTDIR}"

# download filename url
download() {
## Download if newer, and if curl fails, clean up and exit
curl --fail --compressed -A "get-fonts.sh/osm-carto" -o "$1" -z "$1" -L "$2" || { echo "Failed to download $1 $2"; rm -f "$1"; exit 1; }
}

# TTF Hinted Noto Fonts

# Fonts available in regular, bold, and italic
REGULAR_BOLD_ITALIC="NotoSans"

# Fonts available in regular and bold
REGULAR_BOLD="NotoSansAdlamUnjoined
NotoSansArabicUI
NotoSansArmenian
NotoSansBalinese
NotoSansBamum
NotoSansBengaliUI
NotoSansCanadianAboriginal
NotoSansCham
NotoSansCherokee
NotoSansDevanagariUI
NotoSansEthiopic
NotoSansGeorgian
NotoSansGujaratiUI
NotoSansGurmukhiUI
NotoSansHebrew
NotoSansJavanese
NotoSansKannadaUI
NotoSansKayahLi
NotoSansKhmerUI
NotoSansLaoUI
NotoSansLisu
NotoSansMalayalamUI
NotoSansMyanmarUI
NotoSansOlChiki
NotoSansOriyaUI
NotoSansSinhalaUI
NotoSansSundanese
NotoSansSymbols
NotoSansTaiTham
NotoSansTamilUI
NotoSansTeluguUI
NotoSansThaana
NotoSansThaiUI
NotoSerifTibetan"

# Fonts with regular and black, but no bold
REGULAR_BLACK="NotoSansSyriac"

# Fonts only available in regular
REGULAR="NotoSansBatak
NotoSansBuginese
NotoSansBuhid
NotoSansChakma
NotoSansCoptic
NotoSansHanunoo
NotoSansLepcha
NotoSansLimbu
NotoSansMandaic
NotoSansMongolian
NotoSansNewTaiLue
NotoSansNKo
NotoSansOsage
NotoSansOsmanya
NotoSansSamaritan
NotoSansSaurashtra
NotoSansShavian
NotoSansSymbols2
NotoSansTagalog
NotoSansTagbanwa
NotoSansTaiLe
NotoSansTaiViet
NotoSansTifinagh
NotoSansVai
NotoSansYi"

# Download the fonts in the lists above

for font in $REGULAR_BOLD_ITALIC; do
regular="$font-Regular.ttf"
bold="$font-Bold.ttf"
italic="$font-Italic.ttf"
download "${FONTDIR}/${regular}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${regular}"
download "${FONTDIR}/${bold}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${bold}"
download "${FONTDIR}/${italic}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${italic}"
done

for font in $REGULAR_BOLD; do
regular="$font-Regular.ttf"
bold="$font-Bold.ttf"
download "${FONTDIR}/${regular}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${regular}"
download "${FONTDIR}/${bold}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${bold}"
done

for font in $REGULAR_BLACK; do
regular="$font-Regular.ttf"
black="$font-Black.ttf"
download "${FONTDIR}/${regular}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${regular}"
download "${FONTDIR}/${black}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${black}"
done

for font in $REGULAR; do
regular="$font-Regular.ttf"
download "${FONTDIR}/${regular}" "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/${font}/${regular}"
done

# Other noto fonts which don't follow the URL pattern above
download "${FONTDIR}/NotoSansCJKjp-Regular.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf"
download "${FONTDIR}/NotoSansCJKjp-Bold.otf" "https://github.com/googlefonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Bold.otf"

# Fonts in zipfiles need a temporary directory
TMPDIR=$(mktemp -d -t get-fonts.XXXXXXXXX)
trap "rm -rf ${TMPDIR} ${FONTDIR}/static" EXIT

# Noto Emoji B&W isn't available as a separate download, so we need to download the package and unzip it
curl --fail -A "get-fonts.sh/osm-carto" -o "${TMPDIR}/Noto_Emoji.zip" -L 'https://fonts.google.com/download?family=Noto%20Emoji'

unzip -oqq "${TMPDIR}/Noto_Emoji.zip" static/NotoEmoji-Regular.ttf static/NotoEmoji-Bold.ttf -d "${FONTDIR}"
mv "${FONTDIR}/static/NotoEmoji-Regular.ttf" "${FONTDIR}"
mv "${FONTDIR}/static/NotoEmoji-Bold.ttf" "${FONTDIR}"

curl --fail -A "get-fonts.sh/osm-carto" -o "${TMPDIR}/hanazono.zip" -L 'https://mirrors.dotsrc.org/osdn/hanazono-font/68253/hanazono-20170904.zip'

unzip -oqq "${TMPDIR}/hanazono.zip" HanaMinA.ttf HanaMinB.ttf -d "${FONTDIR}"
Loading