tileserver-gl-light 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:10-stretch
1
+ FROM node:16-bullseye
2
2
 
3
3
  ENV NODE_ENV="production"
4
4
  ENV CHOKIDAR_USEPOLLING=1
@@ -6,8 +6,9 @@ ENV CHOKIDAR_INTERVAL=500
6
6
  EXPOSE 80
7
7
  VOLUME /data
8
8
  WORKDIR /data
9
- ENTRYPOINT ["node", "/usr/src/app/", "-p", "80"]
9
+ ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"]
10
10
 
11
11
  RUN mkdir -p /usr/src/app
12
12
  COPY / /usr/src/app
13
13
  RUN cd /usr/src/app && npm install --production
14
+ RUN ["chmod", "+x", "/usr/src/app/docker-entrypoint.sh"]
package/Dockerfile_test CHANGED
@@ -2,7 +2,7 @@
2
2
  # Simply run "docker build -f Dockerfile_test ."
3
3
  # WARNING: sometimes it fails with a core dumped exception
4
4
 
5
- FROM node:10-stretch
5
+ FROM node:16-bullseye
6
6
 
7
7
  RUN apt-get -qq update \
8
8
  && DEBIAN_FRONTEND=noninteractive apt-get -y install \
@@ -17,6 +17,7 @@ RUN apt-get -qq update \
17
17
  libllvm3.9 \
18
18
  libprotobuf-dev \
19
19
  libxxf86vm-dev \
20
+ libopengl0 \
20
21
  xvfb \
21
22
  && apt-get clean
22
23
 
@@ -10,12 +10,24 @@ handle() {
10
10
 
11
11
  trap handle INT TERM
12
12
 
13
+ refresh() {
14
+ SIGNAL=$(( $? - 128 ))
15
+ echo "Caught signal ${SIGNAL}, refreshing"
16
+ kill -s ${SIGNAL} $(pidof node) 2>/dev/null
17
+ }
18
+
19
+ trap refresh HUP
20
+
13
21
  if ! which -- "${1}"; then
14
22
  # first arg is not an executable
15
- xvfb-run -a --server-args="-screen 0 1024x768x24" -- node /app/ "$@" &
23
+ node /usr/src/app/ -p 80 "$@" &
16
24
  # Wait exits immediately on signals which have traps set. Store return value and wait
17
25
  # again for all jobs to actually complete before continuing.
18
26
  wait $! || RETVAL=$?
27
+ while [ ${RETVAL} = 129 ] ; do
28
+ # Refressh signal HUP received. Continue waiting for signals.
29
+ wait $! || RETVAL=$?
30
+ done
19
31
  wait
20
32
  exit ${RETVAL}
21
33
  fi
package/docs/conf.py CHANGED
@@ -44,7 +44,7 @@ master_doc = 'index'
44
44
 
45
45
  # General information about the project.
46
46
  project = u'TileServer GL'
47
- copyright = u'2016, Klokan Technologies GmbH'
47
+ copyright = u'2022, MapTiler.com'
48
48
 
49
49
  # The version info for the project you're documenting, acts as replacement for
50
50
  # |version| and |release|, also used in various other places throughout the
@@ -197,7 +197,7 @@ latex_elements = {
197
197
  # author, documentclass [howto, manual, or own class]).
198
198
  latex_documents = [
199
199
  ('index', 'TileServerGL.tex', u'TileServer GL Documentation',
200
- u'Klokan Technologies GmbH', 'manual'),
200
+ u'MapTiler.com', 'manual'),
201
201
  ]
202
202
 
203
203
  # The name of an image file (relative to this directory) to place at the top of
@@ -227,7 +227,7 @@ latex_documents = [
227
227
  # (source start file, name, description, authors, manual section).
228
228
  man_pages = [
229
229
  ('index', 'tileservergl', u'TileServer GL Documentation',
230
- [u'Klokan Technologies GmbH'], 1)
230
+ [u'MapTiler.com'], 1)
231
231
  ]
232
232
 
233
233
  # If true, show URL addresses after external links.
@@ -241,7 +241,7 @@ man_pages = [
241
241
  # dir menu entry, description, category)
242
242
  texinfo_documents = [
243
243
  ('index', 'TileServerGL', u'TileServer GL Documentation',
244
- u'Klokan Technologies GmbH', 'TileServerGL', 'One line description of project.',
244
+ u'MapTiler.com', 'TileServerGL', 'One line description of project.',
245
245
  'Miscellaneous'),
246
246
  ]
247
247
 
@@ -26,11 +26,30 @@ Native dependencies
26
26
  There are some native dependencies that you need to make sure are installed if you plan to run the TileServer GL natively without docker.
27
27
  The precise package names you need to install may differ on various platforms.
28
28
 
29
- These are required on Debian 9:
30
- * ``build-essential``
29
+ These are required on Debian 11:
30
+ * ``libgles2-mesa``
31
+ * ``libegl1``
32
+ * ``xvfb``
33
+ * ``xauth``
34
+ * ``libopengl0``
35
+ * ``libcurl4``
36
+ * ``curl``
37
+ * ``libuv1-dev``
38
+ * ``libc6-dev``
39
+ * ``http://archive.ubuntu.com/ubuntu/pool/main/libj/libjpeg-turbo/libjpeg-turbo8_2.0.3-0ubuntu1_amd64.deb``
40
+ * ``http://archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu66_66.1-2ubuntu2_amd64.deb``
41
+
42
+ These are required on Ubuntu 20.04:
31
43
  * ``libcairo2-dev``
32
- * ``libprotobuf-dev``
33
-
44
+ * ``libjpeg8-dev``
45
+ * ``libpango1.0-dev``
46
+ * ``libgif-dev``
47
+ * ``build-essential``
48
+ * ``g++``
49
+ * ``xvfb``
50
+ * ``libgles2-mesa-dev``
51
+ * ``libgbm-dev``
52
+ * ``libxxf86vm-dev``
34
53
 
35
54
  ``tileserver-gl-light`` on npm
36
55
  ==============================
package/docs/usage.rst CHANGED
@@ -29,8 +29,10 @@ Default preview style and configuration
29
29
  - If no configuration file is specified, a default preview style (compatible with openmaptiles) is used.
30
30
  - If no mbtiles file is specified (and is not found in the current working directory), a sample file is downloaded (showing the Zurich area)
31
31
 
32
- Reloading configuration
32
+ Reloading the configuration
33
33
  ======
34
34
 
35
35
  It is possible to reload the configuration file without restarting the whole process by sending a SIGHUP signal to the node process.
36
- However, this does not currently work when running the tileserver-gl docker container (the signal is not passed to the subprocess, see https://github.com/maptiler/tileserver-gl/issues/420#issuecomment-597507663).
36
+
37
+ - The `docker kill -s HUP tileserver-gl` command can be used when running the tileserver-gl docker container.
38
+ - The `docker-compose kill -s HUP tileserver-gl-service-name` can be used when tileserver-gl is run as a docker-compose service.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tileserver-gl-light",
3
- "version": "3.1.0",
3
+ "version": "4.0.0",
4
4
  "description": "Map tile server for JSON GL styles - serving vector tiles",
5
5
  "main": "src/main.js",
6
6
  "bin": "src/main.js",
@@ -18,23 +18,23 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@mapbox/glyph-pbf-composite": "0.0.3",
21
- "@mapbox/mapbox-gl-style-spec": "13.12.0",
22
- "@mapbox/mbtiles": "0.11.0",
23
- "@mapbox/sphericalmercator": "1.1.0",
21
+ "@maplibre/maplibre-gl-style-spec": "17.0.1",
22
+ "@mapbox/mbtiles": "0.12.1",
23
+ "@mapbox/sphericalmercator": "1.2.0",
24
24
  "@mapbox/vector-tile": "1.3.1",
25
25
  "advanced-pool": "0.3.3",
26
- "chokidar": "3.3.1",
26
+ "chokidar": "3.5.3",
27
27
  "clone": "2.1.2",
28
- "color": "3.1.2",
29
- "commander": "4.1.1",
28
+ "color": "4.2.3",
29
+ "commander": "9.4.0",
30
30
  "cors": "2.8.5",
31
31
  "esm": "3.2.25",
32
- "express": "4.17.1",
33
- "handlebars": "4.7.3",
32
+ "express": "4.18.1",
33
+ "handlebars": "4.7.7",
34
34
  "http-shutdown": "1.2.2",
35
- "morgan": "1.9.1",
35
+ "morgan": "1.10.0",
36
36
  "pbf": "3.2.1",
37
- "proj4": "2.6.0",
37
+ "proj4": "2.8.0",
38
38
  "request": "2.88.2",
39
39
  "tileserver-gl-styles": "2.0.0"
40
40
  }
@@ -0,0 +1,243 @@
1
+ // @class TileLayer
2
+
3
+ L.TileLayer.mergeOptions({
4
+ // @option keepBuffer
5
+ // The amount of tiles outside the visible map area to be kept in the stitched
6
+ // `TileLayer`.
7
+
8
+ // @option dumpToCanvas: Boolean = true
9
+ // Whether to dump loaded tiles to a `<canvas>` to prevent some rendering
10
+ // artifacts. (Disabled by default in IE)
11
+ dumpToCanvas: L.Browser.canvas && !L.Browser.ie,
12
+ });
13
+
14
+ L.TileLayer.include({
15
+ _onUpdateLevel: function(z, zoom) {
16
+ if (this.options.dumpToCanvas) {
17
+ this._levels[z].canvas.style.zIndex =
18
+ this.options.maxZoom - Math.abs(zoom - z);
19
+ }
20
+ },
21
+
22
+ _onRemoveLevel: function(z) {
23
+ if (this.options.dumpToCanvas) {
24
+ L.DomUtil.remove(this._levels[z].canvas);
25
+ }
26
+ },
27
+
28
+ _onCreateLevel: function(level) {
29
+ if (this.options.dumpToCanvas) {
30
+ level.canvas = L.DomUtil.create(
31
+ "canvas",
32
+ "leaflet-tile-container leaflet-zoom-animated",
33
+ this._container
34
+ );
35
+ level.ctx = level.canvas.getContext("2d");
36
+ this._resetCanvasSize(level);
37
+ }
38
+ },
39
+
40
+ _removeTile: function(key) {
41
+ if (this.options.dumpToCanvas) {
42
+ var tile = this._tiles[key];
43
+ var level = this._levels[tile.coords.z];
44
+ var tileSize = this.getTileSize();
45
+
46
+ if (level) {
47
+ // Where in the canvas should this tile go?
48
+ var offset = L.point(tile.coords.x, tile.coords.y)
49
+ .subtract(level.canvasRange.min)
50
+ .scaleBy(this.getTileSize());
51
+
52
+ level.ctx.clearRect(offset.x, offset.y, tileSize.x, tileSize.y);
53
+ }
54
+ }
55
+
56
+ L.GridLayer.prototype._removeTile.call(this, key);
57
+ },
58
+
59
+ _resetCanvasSize: function(level) {
60
+ var buff = this.options.keepBuffer,
61
+ pixelBounds = this._getTiledPixelBounds(this._map.getCenter()),
62
+ tileRange = this._pxBoundsToTileRange(pixelBounds),
63
+ tileSize = this.getTileSize();
64
+
65
+ tileRange.min = tileRange.min.subtract([buff, buff]); // This adds the no-prune buffer
66
+ tileRange.max = tileRange.max.add([buff + 1, buff + 1]);
67
+
68
+ var pixelRange = L.bounds(
69
+ tileRange.min.scaleBy(tileSize),
70
+ tileRange.max.add([1, 1]).scaleBy(tileSize) // This prevents an off-by-one when checking if tiles are inside
71
+ ),
72
+ mustRepositionCanvas = false,
73
+ neededSize = pixelRange.max.subtract(pixelRange.min);
74
+
75
+ // Resize the canvas, if needed, and only to make it bigger.
76
+ if (
77
+ neededSize.x > level.canvas.width ||
78
+ neededSize.y > level.canvas.height
79
+ ) {
80
+ // Resizing canvases erases the currently drawn content, I'm afraid.
81
+ // To keep it, dump the pixels to another canvas, then display it on
82
+ // top. This could be done with getImageData/putImageData, but that
83
+ // would break for tainted canvases (in non-CORS tilesets)
84
+ var oldSize = { x: level.canvas.width, y: level.canvas.height };
85
+ // console.info('Resizing canvas from ', oldSize, 'to ', neededSize);
86
+
87
+ var tmpCanvas = L.DomUtil.create("canvas");
88
+ tmpCanvas.style.width = (tmpCanvas.width = oldSize.x) + "px";
89
+ tmpCanvas.style.height = (tmpCanvas.height = oldSize.y) + "px";
90
+ tmpCanvas.getContext("2d").drawImage(level.canvas, 0, 0);
91
+ // var data = level.ctx.getImageData(0, 0, oldSize.x, oldSize.y);
92
+
93
+ level.canvas.style.width = (level.canvas.width = neededSize.x) + "px";
94
+ level.canvas.style.height = (level.canvas.height = neededSize.y) + "px";
95
+ level.ctx.drawImage(tmpCanvas, 0, 0);
96
+ // level.ctx.putImageData(data, 0, 0, 0, 0, oldSize.x, oldSize.y);
97
+ }
98
+
99
+ // Translate the canvas contents if it's moved around
100
+ if (level.canvasRange) {
101
+ var offset = level.canvasRange.min
102
+ .subtract(tileRange.min)
103
+ .scaleBy(this.getTileSize());
104
+
105
+ // console.info('Offsetting by ', offset);
106
+
107
+ if (!L.Browser.safari) {
108
+ // By default, canvases copy things "on top of" existing pixels, but we want
109
+ // this to *replace* the existing pixels when doing a drawImage() call.
110
+ // This will also clear the sides, so no clearRect() calls are needed to make room
111
+ // for the new tiles.
112
+ level.ctx.globalCompositeOperation = "copy";
113
+ level.ctx.drawImage(level.canvas, offset.x, offset.y);
114
+ level.ctx.globalCompositeOperation = "source-over";
115
+ } else {
116
+ // Safari clears the canvas when copying from itself :-(
117
+ if (!this._tmpCanvas) {
118
+ var t = (this._tmpCanvas = L.DomUtil.create("canvas"));
119
+ t.width = level.canvas.width;
120
+ t.height = level.canvas.height;
121
+ this._tmpContext = t.getContext("2d");
122
+ }
123
+ this._tmpContext.clearRect(
124
+ 0,
125
+ 0,
126
+ level.canvas.width,
127
+ level.canvas.height
128
+ );
129
+ this._tmpContext.drawImage(level.canvas, 0, 0);
130
+ level.ctx.clearRect(0, 0, level.canvas.width, level.canvas.height);
131
+ level.ctx.drawImage(this._tmpCanvas, offset.x, offset.y);
132
+ }
133
+
134
+ mustRepositionCanvas = true; // Wait until new props are set
135
+ }
136
+
137
+ level.canvasRange = tileRange;
138
+ level.canvasPxRange = pixelRange;
139
+ level.canvasOrigin = pixelRange.min;
140
+
141
+ // console.log('Canvas tile range: ', level, tileRange.min, tileRange.max );
142
+ // console.log('Canvas pixel range: ', pixelRange.min, pixelRange.max );
143
+ // console.log('Level origin: ', level.origin );
144
+
145
+ if (mustRepositionCanvas) {
146
+ this._setCanvasZoomTransform(
147
+ level,
148
+ this._map.getCenter(),
149
+ this._map.getZoom()
150
+ );
151
+ }
152
+ },
153
+
154
+ /// set transform/position of canvas, in addition to the transform/position of the individual tile container
155
+ _setZoomTransform: function(level, center, zoom) {
156
+ L.GridLayer.prototype._setZoomTransform.call(this, level, center, zoom);
157
+ if (this.options.dumpToCanvas) {
158
+ this._setCanvasZoomTransform(level, center, zoom);
159
+ }
160
+ },
161
+
162
+ // This will get called twice:
163
+ // * From _setZoomTransform
164
+ // * When the canvas has shifted due to a new tile being loaded
165
+ _setCanvasZoomTransform: function(level, center, zoom) {
166
+ // console.log('_setCanvasZoomTransform', level, center, zoom);
167
+ if (!level.canvasOrigin) {
168
+ return;
169
+ }
170
+ var scale = this._map.getZoomScale(zoom, level.zoom),
171
+ translate = level.canvasOrigin
172
+ .multiplyBy(scale)
173
+ .subtract(this._map._getNewPixelOrigin(center, zoom))
174
+ .round();
175
+
176
+ if (L.Browser.any3d) {
177
+ L.DomUtil.setTransform(level.canvas, translate, scale);
178
+ } else {
179
+ L.DomUtil.setPosition(level.canvas, translate);
180
+ }
181
+ },
182
+
183
+ _onOpaqueTile: function(tile) {
184
+ if (!this.options.dumpToCanvas) {
185
+ return;
186
+ }
187
+
188
+ // Guard against an NS_ERROR_NOT_AVAILABLE (or similar) exception
189
+ // when a non-image-tile has been loaded (e.g. a WMS error).
190
+ // Checking for tile.el.complete is not enough, as it has been
191
+ // already marked as loaded and ready somehow.
192
+ try {
193
+ this.dumpPixels(tile.coords, tile.el);
194
+ } catch (ex) {
195
+ return this.fire("tileerror", {
196
+ error: "Could not copy tile pixels: " + ex,
197
+ tile: tile,
198
+ coods: tile.coords,
199
+ });
200
+ }
201
+
202
+ // If dumping the pixels was successful, then hide the tile.
203
+ // Do not remove the tile itself, as it is needed to check if the whole
204
+ // level (and its canvas) should be removed (via level.el.children.length)
205
+ tile.el.style.display = "none";
206
+ },
207
+
208
+ // @section Extension methods
209
+ // @uninheritable
210
+
211
+ // @method dumpPixels(coords: Object, imageSource: CanvasImageSource): this
212
+ // Dumps pixels from the given `CanvasImageSource` into the layer, into
213
+ // the space for the tile represented by the `coords` tile coordinates (an object
214
+ // like `{x: Number, y: Number, z: Number}`; the image source must have the
215
+ // same size as the `tileSize` option for the layer. Has no effect if `dumpToCanvas`
216
+ // is `false`.
217
+ dumpPixels: function(coords, imageSource) {
218
+ var level = this._levels[coords.z],
219
+ tileSize = this.getTileSize();
220
+
221
+ if (!level.canvasRange || !this.options.dumpToCanvas) {
222
+ return;
223
+ }
224
+
225
+ // Check if the tile is inside the currently visible map bounds
226
+ // There is a possible race condition when tiles are loaded after they
227
+ // have been panned outside of the map.
228
+ if (!level.canvasRange.contains(coords)) {
229
+ this._resetCanvasSize(level);
230
+ }
231
+
232
+ // Where in the canvas should this tile go?
233
+ var offset = L.point(coords.x, coords.y)
234
+ .subtract(level.canvasRange.min)
235
+ .scaleBy(this.getTileSize());
236
+
237
+ level.ctx.drawImage(imageSource, offset.x, offset.y, tileSize.x, tileSize.y);
238
+
239
+ // TODO: Clear the pixels of other levels' canvases where they overlap
240
+ // this newly dumped tile.
241
+ return this;
242
+ },
243
+ });