Skip to content

Commit e8127dc

Browse files
authored
Use a positioned glyph font encoding for Devanagari (#265)
* Add pmap:script * Add pgf * FontRegistry as Singleton * Keep original Unicode in , store encoded strings in * Download zip ball * Store pgf names and versions in tilejson metadata * Bump minor version, add changelog
1 parent b68f446 commit e8127dc

File tree

13 files changed

+586
-14
lines changed

13 files changed

+586
-14
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Tiles v3.7.0
2+
------
3+
- Use a positioned glyph font encoding for Devanagari via @wipfli [#265]
4+
15
Tiles v3.6.0
26
------
37
- More places kinds (port from Tilezen), refine zoom levels via @nvkelso [#259]

SEMANTIC-VERSIONING.md

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Upon our version `1.0.0` release Protomaps Basemap makes the following promises
6666
1. **Simplification** within `kind` **values** at zooms 16 (or max zoom) by removing `common`, `common-optional`, and `optional` **properties** by merging or other method
6767
1. **Change** of <= -3 (earlier) to default `min_zoom` or `max_zoom` **values** to determine when `kind` is included
6868
1. **Change** of >= +2 (later) to default `min_zoom` or `max_zoom` **values** to determine when `kind` is included
69+
1. **Change** of version of a positioned glyph font for an already included script
6970

7071
#### MINOR version increments:
7172

@@ -81,6 +82,7 @@ Upon our version `1.0.0` release Protomaps Basemap makes the following promises
8182
1. **Change** of <= -2 (earlier) to `min_zoom` or `max_zoom` **values** to determine when `kind` is included
8283
1. **Change** of >= +1 (later) to default `min_zoom` or `max_zoom` **values** to determine when `kind` is included
8384
1. **Change** the maximum Tilezen zoom (currently zoom 16).
85+
1. **Add** new positioned glyph font script
8486

8587
#### PATCH version increments
8688

tiles/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
<eclipse>
105105
<version>4.21.0</version>
106106
<!--suppress UnresolvedMavenProperty -->
107-
<file>${maven.multiModuleProjectDirectory}/eclipse-formatter.xml</file>
107+
<file>${project.basedir}/eclipse-formatter.xml</file>
108108
</eclipse>
109109
</java>
110110
<markdown>

tiles/src/main/java/com/protomaps/basemap/Basemap.java

+29-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
import com.protomaps.basemap.layers.Roads;
2020
import com.protomaps.basemap.layers.Transit;
2121
import com.protomaps.basemap.layers.Water;
22+
import com.protomaps.basemap.text.FontRegistry;
2223
import java.nio.file.Path;
24+
import java.util.HashMap;
25+
import java.util.List;
26+
import java.util.Map;
2327

2428

2529
public class Basemap extends ForwardingProfile {
@@ -97,7 +101,7 @@ public String description() {
97101

98102
@Override
99103
public String version() {
100-
return "3.6.0";
104+
return "3.7.0";
101105
}
102106

103107
@Override
@@ -112,6 +116,21 @@ public String attribution() {
112116
""".trim();
113117
}
114118

119+
@Override
120+
public Map<String, String> extraArchiveMetadata() {
121+
Map<String, String> result = new HashMap<>();
122+
123+
FontRegistry fontRegistry = FontRegistry.getInstance();
124+
List<String> scripts = fontRegistry.getScripts();
125+
126+
for (String script : scripts) {
127+
result.put("pgf:" + script.toLowerCase() + ":name", fontRegistry.getName(script));
128+
result.put("pgf:" + script.toLowerCase() + ":version", fontRegistry.getVersion(script));
129+
}
130+
131+
return result;
132+
}
133+
115134
public static void main(String[] args) {
116135
run(Arguments.fromArgsOrConfigFile(args));
117136
}
@@ -137,14 +156,22 @@ static void run(Arguments args) {
137156
.addGeoPackageSource("landcover", sourcesDir.resolve("daylight-landcover.gpkg"),
138157
"https://r2-public.protomaps.com/datasets/daylight-landcover.gpkg");
139158

140-
Downloader.create(planetiler.config()).add("ne", neUrl, nePath).run();
159+
Path pgfEncodingZip = sourcesDir.resolve("pgf-encoding.zip");
160+
Downloader.create(planetiler.config()).add("ne", neUrl, nePath)
161+
.add("pgf-encoding", "https://wipfli.github.io/pgf-encoding/pgf-encoding.zip", pgfEncodingZip)
162+
.run();
141163
// .add("qrank", "https://qrank.wmcloud.org/download/qrank.csv.gz", sourcesDir.resolve("qrank.csv.gz")).run();
142164

143165
var tmpDir = nePath.resolveSibling(nePath.getFileName() + "-unzipped");
144166
var naturalEarthDb = NaturalEarthDb.fromSqlite(nePath, tmpDir);
145167
// var qrankDb = QrankDb.fromCsv(sourcesDir.resolve("qrank.csv.gz"));
146168
var qrankDb = QrankDb.empty();
147169

170+
FontRegistry fontRegistry = FontRegistry.getInstance();
171+
fontRegistry.setZipFilePath(pgfEncodingZip.toString());
172+
173+
fontRegistry.loadFontBundle("NotoSansDevanagari-Regular", "1", "Devanagari");
174+
148175
planetiler.setProfile(new Basemap(naturalEarthDb, qrankDb)).setOutput(Path.of(area + ".pmtiles"))
149176
.run();
150177
}

tiles/src/main/java/com/protomaps/basemap/layers/Places.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import com.protomaps.basemap.names.NeNames;
1414
import com.protomaps.basemap.names.OsmNames;
1515
import com.protomaps.basemap.names.Script;
16+
import com.protomaps.basemap.text.FontRegistry;
17+
import com.protomaps.basemap.text.TextEngine;
1618
import java.util.List;
1719
import java.util.Map;
1820
import java.util.concurrent.atomic.AtomicInteger;
@@ -138,11 +140,19 @@ public void processNe(SourceFeature sf, FeatureCollector features) {
138140
// since all these are locality, we hard code kindRank to 2 (needs to match OSM section below)
139141
.setSortKey(getSortKey(minZoom, 2, populationRank, population, sf.getString("name")));
140142

141-
var script = Script.getScript(sf.getTag("name").toString());
143+
String name = sf.getTag("name").toString();
144+
var script = Script.getScript(name);
145+
142146
if (!script.equals("Latin") && !script.equals("Generic")) {
143147
feat.setAttr("pmap:script", script);
148+
FontRegistry fontRegistry = FontRegistry.getInstance();
149+
if (fontRegistry.getScripts().contains(script)) {
150+
String encodedName = TextEngine.encodeRegisteredScripts(name);
151+
feat.setAttr("pmap:pgf:name", encodedName);
152+
}
144153
}
145154

155+
146156
// NOTE: The buffer needs to be consistent with the innteral grid pixel sizes
147157
feat.setPointLabelGridPixelSize(LOCALITY_GRID_SIZE_ZOOM_FUNCTION)
148158
.setPointLabelGridLimit(LOCALITY_GRID_LIMIT_ZOOM_FUNCTION)

tiles/src/main/java/com/protomaps/basemap/names/NeNames.java

+28-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.onthegomap.planetiler.FeatureCollector;
44
import com.onthegomap.planetiler.reader.SourceFeature;
5+
import com.protomaps.basemap.text.FontRegistry;
6+
import com.protomaps.basemap.text.TextEngine;
57
import java.util.Map;
68

79
public class NeNames {
@@ -10,17 +12,38 @@ private NeNames() {}
1012

1113
public static FeatureCollector.Feature setNeNames(FeatureCollector.Feature feature, SourceFeature sf,
1214
int minZoom) {
15+
FontRegistry fontRegistry = FontRegistry.getInstance();
16+
1317
for (Map.Entry<String, Object> tag : sf.tags().entrySet()) {
14-
var key = tag.getKey();
18+
String key = tag.getKey().toString();
19+
if (sf.getTag(key) == null) {
20+
continue;
21+
}
22+
String value = sf.getTag(key).toString();
23+
var script = Script.getScript(value);
24+
25+
if (key.startsWith("name_")) {
26+
key = key.replace("_", ":");
27+
}
28+
1529
if (key.equals("name")) {
16-
feature.setAttrWithMinzoom(key, sf.getTag(key), minZoom);
30+
feature.setAttrWithMinzoom("name", value, minZoom);
1731

18-
var script = Script.getScript(sf.getTag(key).toString());
1932
if (!script.equals("Latin") && !script.equals("Generic")) {
2033
feature.setAttrWithMinzoom("pmap:script", script, minZoom);
2134
}
22-
} else if (key.startsWith("name_")) {
23-
feature.setAttrWithMinzoom(key.replace("_", ":"), sf.getTag(key), minZoom);
35+
36+
String encodedValue = TextEngine.encodeRegisteredScripts(value);
37+
feature.setAttrWithMinzoom("pmap:pgf:name", encodedValue, minZoom);
38+
}
39+
40+
if (key.startsWith("name:")) {
41+
feature.setAttrWithMinzoom(key, value, minZoom);
42+
43+
if (fontRegistry.getScripts().contains(script)) {
44+
String encodedValue = TextEngine.encodeRegisteredScripts(value);
45+
feature.setAttrWithMinzoom("pmap:pgf:" + key, encodedValue, minZoom);
46+
}
2447
}
2548
}
2649

tiles/src/main/java/com/protomaps/basemap/names/OsmNames.java

+20-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.onthegomap.planetiler.FeatureCollector;
44
import com.onthegomap.planetiler.reader.SourceFeature;
5+
import com.protomaps.basemap.text.FontRegistry;
6+
import com.protomaps.basemap.text.TextEngine;
57
import java.text.NumberFormat;
68
import java.text.ParsePosition;
79
import java.util.Map;
@@ -12,19 +14,32 @@ private OsmNames() {}
1214

1315
public static FeatureCollector.Feature setOsmNames(FeatureCollector.Feature feature, SourceFeature sf,
1416
int minZoom) {
17+
FontRegistry fontRegistry = FontRegistry.getInstance();
1518
for (Map.Entry<String, Object> tag : sf.tags().entrySet()) {
1619
var key = tag.getKey();
17-
// Full names of places (default and translations)
18-
if (key.equals("name") || key.startsWith("name:")) {
19-
feature.setAttrWithMinzoom(key, sf.getTag(key), minZoom);
20-
}
20+
String value = sf.getTag(key).toString();
21+
var script = Script.getScript(value);
2122

2223
if (key.equals("name")) {
23-
var script = Script.getScript(sf.getTag(key).toString());
24+
feature.setAttrWithMinzoom("name", value, minZoom);
25+
2426
if (!script.equals("Latin") && !script.equals("Generic")) {
2527
feature.setAttrWithMinzoom("pmap:script", script, minZoom);
2628
}
29+
30+
String encodedValue = TextEngine.encodeRegisteredScripts(value);
31+
feature.setAttrWithMinzoom("pmap:pgf:name", encodedValue, minZoom);
32+
}
33+
34+
if (key.startsWith("name:")) {
35+
feature.setAttrWithMinzoom(key, value, minZoom);
36+
37+
if (fontRegistry.getScripts().contains(script)) {
38+
String encodedValue = TextEngine.encodeRegisteredScripts(value);
39+
feature.setAttrWithMinzoom("pmap:pgf:" + key, encodedValue, minZoom);
40+
}
2741
}
42+
2843
}
2944
return feature;
3045
}

tiles/src/main/java/com/protomaps/basemap/names/Script.java

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.protomaps.basemap.names;
22

3+
34
public class Script {
45

56
private Script() {}

0 commit comments

Comments
 (0)