maplibre-gl 3.2.1 → 3.3.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/build/generate-struct-arrays.ts +6 -3
- package/build/generate-style-code.ts +7 -8
- package/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp-worker.js.map +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-csp.js.map +1 -1
- package/dist/maplibre-gl-dev.js +565 -243
- package/dist/maplibre-gl-dev.js.map +1 -1
- package/dist/maplibre-gl.d.ts +111 -57
- package/dist/maplibre-gl.js +4 -4
- package/dist/maplibre-gl.js.map +1 -1
- package/package.json +20 -20
- package/src/data/array_types.g.ts +110 -24
- package/src/data/bucket/circle_bucket.ts +1 -0
- package/src/data/bucket/line_bucket.ts +1 -0
- package/src/data/bucket/symbol_attributes.ts +7 -1
- package/src/data/bucket/symbol_bucket.ts +5 -1
- package/src/data/feature_index.ts +1 -0
- package/src/data/program_configuration.ts +1 -0
- package/src/data/segment.ts +2 -0
- package/src/geo/transform.ts +1 -0
- package/src/gl/context.ts +1 -0
- package/src/gl/framebuffer.ts +1 -0
- package/src/gl/index_buffer.ts +1 -0
- package/src/gl/render_pool.ts +2 -1
- package/src/gl/vertex_buffer.ts +1 -0
- package/src/render/draw_symbol.ts +8 -9
- package/src/render/image_atlas.ts +1 -0
- package/src/render/line_atlas.ts +1 -0
- package/src/render/painter.ts +1 -0
- package/src/render/program.ts +1 -0
- package/src/render/render_to_texture.ts +31 -14
- package/src/render/terrain.ts +3 -0
- package/src/render/texture.ts +1 -0
- package/src/render/uniform_binding.ts +2 -0
- package/src/render/vertex_array_object.ts +1 -0
- package/src/shaders/symbol_sdf.fragment.glsl +9 -3
- package/src/shaders/symbol_sdf.fragment.glsl.g.ts +1 -1
- package/src/source/canvas_source.ts +1 -3
- package/src/source/geojson_source.ts +1 -3
- package/src/source/image_source.ts +2 -4
- package/src/source/source_cache.ts +1 -0
- package/src/source/source_state.ts +1 -0
- package/src/source/terrain_source_cache.ts +1 -0
- package/src/source/tile.ts +1 -0
- package/src/source/tile_cache.ts +1 -1
- package/src/source/tile_id.ts +1 -0
- package/src/source/vector_tile_worker_source.test.ts +79 -0
- package/src/source/vector_tile_worker_source.ts +26 -1
- package/src/source/worker_source.ts +1 -0
- package/src/style/evaluation_parameters.ts +1 -0
- package/src/style/properties.ts +18 -0
- package/src/style/style.ts +1 -0
- package/src/style/style_glyph.ts +1 -0
- package/src/style/style_layer/background_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/circle_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/fill_extrusion_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/fill_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/heatmap_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/hillshade_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/line_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/raster_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/symbol_style_layer_properties.g.ts +4 -6
- package/src/style/style_layer/variable_text_anchor.test.ts +117 -0
- package/src/style/style_layer/variable_text_anchor.ts +163 -0
- package/src/symbol/collision_index.ts +1 -0
- package/src/symbol/grid_index.ts +1 -0
- package/src/symbol/placement.ts +52 -40
- package/src/symbol/symbol_layout.ts +42 -116
- package/src/ui/camera.ts +8 -8
- package/src/ui/handler/box_zoom.ts +1 -3
- package/src/ui/handler/click_zoom.ts +1 -3
- package/src/ui/handler/keyboard.ts +1 -3
- package/src/ui/handler/scroll_zoom.ts +1 -3
- package/src/ui/handler/shim/dblclick_zoom.ts +1 -3
- package/src/ui/handler/shim/drag_pan.ts +1 -3
- package/src/ui/handler/shim/drag_rotate.ts +1 -3
- package/src/ui/handler/shim/two_fingers_touch.ts +1 -3
- package/src/ui/handler/transform-provider.ts +1 -0
- package/src/ui/handler/two_fingers_touch.ts +1 -3
- package/src/ui/map.ts +7 -6
- package/src/util/ajax.test.ts +33 -0
- package/src/util/ajax.ts +5 -0
- package/src/util/image.ts +1 -0
- package/src/util/image_request.ts +2 -2
- package/src/util/performance.ts +1 -2
- package/src/util/struct_array.ts +5 -1
- package/src/util/test/mock_fetch.ts +51 -0
|
@@ -13,7 +13,6 @@ import {addDynamicAttributes} from '../data/bucket/symbol_bucket';
|
|
|
13
13
|
|
|
14
14
|
import {getAnchorAlignment, WritingMode} from '../symbol/shaping';
|
|
15
15
|
import ONE_EM from '../symbol/one_em';
|
|
16
|
-
import {evaluateVariableOffset, TextAnchor} from '../symbol/symbol_layout';
|
|
17
16
|
|
|
18
17
|
import {
|
|
19
18
|
SymbolIconUniformsType,
|
|
@@ -37,6 +36,7 @@ import type {SymbolLayerSpecification} from '@maplibre/maplibre-gl-style-spec';
|
|
|
37
36
|
import type {Transform} from '../geo/transform';
|
|
38
37
|
import type {ColorMode} from '../gl/color_mode';
|
|
39
38
|
import type {Program} from './program';
|
|
39
|
+
import type {TextAnchor} from '../style/style_layer/variable_text_anchor';
|
|
40
40
|
|
|
41
41
|
type SymbolTileRenderState = {
|
|
42
42
|
segments: SegmentVector;
|
|
@@ -65,11 +65,11 @@ export function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: S
|
|
|
65
65
|
// Disable the stencil test so that labels aren't clipped to tile boundaries.
|
|
66
66
|
const stencilMode = StencilMode.disabled;
|
|
67
67
|
const colorMode = painter.colorModeForRenderPass();
|
|
68
|
-
const
|
|
68
|
+
const hasVariablePlacement = layer._unevaluatedLayout.hasValue('text-variable-anchor') || layer._unevaluatedLayout.hasValue('text-variable-anchor-offset');
|
|
69
69
|
|
|
70
70
|
//Compute variable-offsets before painting since icons and text data positioning
|
|
71
71
|
//depend on each other in this case.
|
|
72
|
-
if (
|
|
72
|
+
if (hasVariablePlacement) {
|
|
73
73
|
updateVariableAnchors(coords, painter, layer, sourceCache,
|
|
74
74
|
layer.layout.get('text-rotation-alignment'),
|
|
75
75
|
layer.layout.get('text-pitch-alignment'),
|
|
@@ -117,10 +117,9 @@ function calculateVariableRenderShift(
|
|
|
117
117
|
const {horizontalAlign, verticalAlign} = getAnchorAlignment(anchor);
|
|
118
118
|
const shiftX = -(horizontalAlign - 0.5) * width;
|
|
119
119
|
const shiftY = -(verticalAlign - 0.5) * height;
|
|
120
|
-
const variableOffset = evaluateVariableOffset(anchor, textOffset);
|
|
121
120
|
return new Point(
|
|
122
|
-
(shiftX / textBoxScale +
|
|
123
|
-
(shiftY / textBoxScale +
|
|
121
|
+
(shiftX / textBoxScale + textOffset[0]) * renderTextSize,
|
|
122
|
+
(shiftY / textBoxScale + textOffset[1]) * renderTextSize
|
|
124
123
|
);
|
|
125
124
|
}
|
|
126
125
|
|
|
@@ -281,7 +280,7 @@ function drawLayerSymbols(
|
|
|
281
280
|
|
|
282
281
|
const depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
|
|
283
282
|
|
|
284
|
-
const
|
|
283
|
+
const hasVariablePlacement = layer._unevaluatedLayout.hasValue('text-variable-anchor') || layer._unevaluatedLayout.hasValue('text-variable-anchor-offset');
|
|
285
284
|
|
|
286
285
|
const tileRenderState: Array<SymbolTileRenderState> = [];
|
|
287
286
|
|
|
@@ -332,7 +331,7 @@ function drawLayerSymbols(
|
|
|
332
331
|
const labelPlaneMatrix = symbolProjection.getLabelPlaneMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, s);
|
|
333
332
|
const glCoordMatrix = symbolProjection.getGlCoordMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, s);
|
|
334
333
|
|
|
335
|
-
const hasVariableAnchors =
|
|
334
|
+
const hasVariableAnchors = hasVariablePlacement && bucket.hasTextData();
|
|
336
335
|
const updateTextFitIcon = layer.layout.get('icon-text-fit') !== 'none' &&
|
|
337
336
|
hasVariableAnchors &&
|
|
338
337
|
bucket.hasIconData();
|
|
@@ -344,7 +343,7 @@ function drawLayerSymbols(
|
|
|
344
343
|
}
|
|
345
344
|
|
|
346
345
|
const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor),
|
|
347
|
-
uLabelPlaneMatrix = (alongLine || (isText &&
|
|
346
|
+
uLabelPlaneMatrix = (alongLine || (isText && hasVariablePlacement) || updateTextFitIcon) ? identityMat4 : labelPlaneMatrix,
|
|
348
347
|
uglCoordMatrix = painter.translatePosMatrix(glCoordMatrix, tile, translate, translateAnchor, true);
|
|
349
348
|
|
|
350
349
|
const hasHalo = isSDF && layer.paint.get(isText ? 'text-halo-width' : 'icon-halo-width').constantOr(1) !== 0;
|
package/src/render/line_atlas.ts
CHANGED
package/src/render/painter.ts
CHANGED
package/src/render/program.ts
CHANGED
|
@@ -9,7 +9,9 @@ import {RenderPool} from '../gl/render_pool';
|
|
|
9
9
|
import {Texture} from './texture';
|
|
10
10
|
import type {StyleLayer} from '../style/style_layer';
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* lookup table which layers should rendered to texture
|
|
14
|
+
*/
|
|
13
15
|
const LAYERS: { [keyof in StyleLayer['type']]?: boolean } = {
|
|
14
16
|
background: true,
|
|
15
17
|
fill: true,
|
|
@@ -19,30 +21,45 @@ const LAYERS: { [keyof in StyleLayer['type']]?: boolean } = {
|
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
|
-
*
|
|
24
|
+
* @internal
|
|
25
|
+
* A helper class to help define what should be rendered to texture and how
|
|
23
26
|
*/
|
|
24
27
|
export class RenderToTexture {
|
|
25
28
|
painter: Painter;
|
|
26
29
|
terrain: Terrain;
|
|
27
30
|
pool: RenderPool;
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
/**
|
|
32
|
+
* coordsDescendingInv contains a list of all tiles which should be rendered for one render-to-texture tile
|
|
33
|
+
* e.g. render 4 raster-tiles with size 256px to the 512px render-to-texture tile
|
|
34
|
+
*/
|
|
30
35
|
_coordsDescendingInv: {[_: string]: {[_:string]: Array<OverscaledTileID>}};
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
/**
|
|
37
|
+
* create a string representation of all to tiles rendered to render-to-texture tiles
|
|
38
|
+
* this string representation is used to check if tile should be re-rendered.
|
|
39
|
+
*/
|
|
33
40
|
_coordsDescendingInvStr: {[_: string]: {[_:string]: string}};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
/**
|
|
42
|
+
* store for render-stacks
|
|
43
|
+
* a render stack is a set of layers which should be rendered into one texture
|
|
44
|
+
* every stylesheet can have multiple stacks. A new stack is created if layers which should
|
|
45
|
+
* not rendered to texture sit inbetween layers which should rendered to texture. e.g. hillshading or symbols
|
|
46
|
+
*/
|
|
38
47
|
_stacks: Array<Array<string>>;
|
|
39
|
-
|
|
48
|
+
/**
|
|
49
|
+
* remember the previous processed layer to check if a new stack is needed
|
|
50
|
+
*/
|
|
40
51
|
_prevType: string;
|
|
41
|
-
|
|
52
|
+
/**
|
|
53
|
+
* a list of tiles that can potentially rendered
|
|
54
|
+
*/
|
|
42
55
|
_renderableTiles: Array<Tile>;
|
|
43
|
-
|
|
56
|
+
/**
|
|
57
|
+
* a list of tiles that should be rendered to screen in the next render-call
|
|
58
|
+
*/
|
|
44
59
|
_rttTiles: Array<Tile>;
|
|
45
|
-
|
|
60
|
+
/**
|
|
61
|
+
* a list of all layer-ids which should be rendered
|
|
62
|
+
*/
|
|
46
63
|
_renderableLayerIds: Array<string>;
|
|
47
64
|
|
|
48
65
|
constructor(painter: Painter, terrain: Terrain) {
|
package/src/render/terrain.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type {TerrainSpecification} from '@maplibre/maplibre-gl-style-spec';
|
|
|
21
21
|
import {LngLat, earthRadius} from '../geo/lng_lat';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
+
* @internal
|
|
24
25
|
* A terrain GPU related object
|
|
25
26
|
*/
|
|
26
27
|
export type TerrainData = {
|
|
@@ -36,6 +37,7 @@ export type TerrainData = {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/**
|
|
40
|
+
* @internal
|
|
39
41
|
* A terrain mesh object
|
|
40
42
|
*/
|
|
41
43
|
export type TerrainMesh = {
|
|
@@ -45,6 +47,7 @@ export type TerrainMesh = {
|
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/**
|
|
50
|
+
* @internal
|
|
48
51
|
* This is the main class which handles most of the 3D Terrain logic. It has the following topics:
|
|
49
52
|
* 1) loads raster-dem tiles via the internal sourceCache this.sourceCache
|
|
50
53
|
* 2) creates a depth-framebuffer, which is used to calculate the visibility of coordinates
|
package/src/render/texture.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type UniformValues<Us extends {}> = $ObjMap<Us, <V>(u: Uniform<V>) => V>;
|
|
|
11
11
|
export type UniformLocations = {[_: string]: WebGLUniformLocation};
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
+
* @internal
|
|
14
15
|
* A base uniform abstract class
|
|
15
16
|
*/
|
|
16
17
|
abstract class Uniform<T> {
|
|
@@ -150,6 +151,7 @@ export {
|
|
|
150
151
|
};
|
|
151
152
|
|
|
152
153
|
/**
|
|
154
|
+
* @internal
|
|
153
155
|
* A uniform bindings
|
|
154
156
|
*/
|
|
155
157
|
export type UniformBindings = {[_: string]: Uniform<any>};
|
|
@@ -33,16 +33,22 @@ void main() {
|
|
|
33
33
|
|
|
34
34
|
lowp vec4 color = fill_color;
|
|
35
35
|
highp float gamma = EDGE_GAMMA / (fontScale * u_gamma_scale);
|
|
36
|
-
lowp float
|
|
36
|
+
lowp float inner_edge = (256.0 - 64.0) / 256.0;
|
|
37
37
|
if (u_is_halo) {
|
|
38
38
|
color = halo_color;
|
|
39
39
|
gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * u_gamma_scale);
|
|
40
|
-
|
|
40
|
+
inner_edge = inner_edge + gamma * gamma_scale;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
lowp float dist = texture(u_texture, tex).a;
|
|
44
44
|
highp float gamma_scaled = gamma * gamma_scale;
|
|
45
|
-
highp float alpha = smoothstep(
|
|
45
|
+
highp float alpha = smoothstep(inner_edge - gamma_scaled, inner_edge + gamma_scaled, dist);
|
|
46
|
+
if (u_is_halo) {
|
|
47
|
+
// When drawing halos, we want the inside of the halo to be transparent as well
|
|
48
|
+
// in case the text fill is transparent.
|
|
49
|
+
lowp float halo_edge = (6.0 - halo_width / fontScale) / SDF_PX;
|
|
50
|
+
alpha = min(smoothstep(halo_edge - gamma_scaled, halo_edge + gamma_scaled, dist), 1.0 - alpha);
|
|
51
|
+
}
|
|
46
52
|
|
|
47
53
|
fragColor = color * (alpha * opacity * fade_opacity);
|
|
48
54
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is generated. Edit build/generate-shaders.ts, then run `npm run codegen`.
|
|
2
|
-
export default '#define SDF_PX 8.0\nuniform bool u_is_halo;uniform sampler2D u_texture;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;uniform bool u_is_text;varying vec2 v_data0;varying vec3 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nfloat EDGE_GAMMA=0.105/u_device_pixel_ratio;vec2 tex=v_data0.xy;float gamma_scale=v_data1.x;float size=v_data1.y;float fade_opacity=v_data1[2];float fontScale=u_is_text ? size/24.0 : size;lowp vec4 color=fill_color;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float
|
|
2
|
+
export default '#define SDF_PX 8.0\nuniform bool u_is_halo;uniform sampler2D u_texture;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;uniform bool u_is_text;varying vec2 v_data0;varying vec3 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nfloat EDGE_GAMMA=0.105/u_device_pixel_ratio;vec2 tex=v_data0.xy;float gamma_scale=v_data1.x;float size=v_data1.y;float fade_opacity=v_data1[2];float fontScale=u_is_text ? size/24.0 : size;lowp vec4 color=fill_color;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float inner_edge=(256.0-64.0)/256.0;if (u_is_halo) {color=halo_color;gamma=(halo_blur*1.19/SDF_PX+EDGE_GAMMA)/(fontScale*u_gamma_scale);inner_edge=inner_edge+gamma*gamma_scale;}lowp float dist=texture2D(u_texture,tex).a;highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(inner_edge-gamma_scaled,inner_edge+gamma_scaled,dist);if (u_is_halo) {lowp float halo_edge=(6.0-halo_width/fontScale)/SDF_PX;alpha=min(smoothstep(halo_edge-gamma_scaled,halo_edge+gamma_scaled,dist),1.0-alpha);}gl_FragColor=color*(alpha*opacity*fade_opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}';
|
|
@@ -81,9 +81,7 @@ export class CanvasSource extends ImageSource {
|
|
|
81
81
|
pause: () => void;
|
|
82
82
|
_playing: boolean;
|
|
83
83
|
|
|
84
|
-
/**
|
|
85
|
-
* @hidden
|
|
86
|
-
*/
|
|
84
|
+
/** @internal */
|
|
87
85
|
constructor(id: string, options: CanvasSourceSpecification, dispatcher: Dispatcher, eventedParent: Evented) {
|
|
88
86
|
super(id, options, dispatcher, eventedParent);
|
|
89
87
|
|
|
@@ -138,9 +138,7 @@ export class GeoJSONSource extends Evented implements Source {
|
|
|
138
138
|
_collectResourceTiming: boolean;
|
|
139
139
|
_removed: boolean;
|
|
140
140
|
|
|
141
|
-
/**
|
|
142
|
-
* @hidden
|
|
143
|
-
*/
|
|
141
|
+
/** @internal */
|
|
144
142
|
constructor(id: string, options: GeoJSONSourceOptions, dispatcher: Dispatcher, eventedParent: Evented) {
|
|
145
143
|
super();
|
|
146
144
|
|
|
@@ -109,9 +109,7 @@ export class ImageSource extends Evented implements Source {
|
|
|
109
109
|
_loaded: boolean;
|
|
110
110
|
_request: Cancelable;
|
|
111
111
|
|
|
112
|
-
/**
|
|
113
|
-
* @hidden
|
|
114
|
-
*/
|
|
112
|
+
/** @internal */
|
|
115
113
|
constructor(id: string, options: ImageSourceSpecification | VideoSourceSpecification | CanvasSourceSpecification, dispatcher: Dispatcher, eventedParent: Evented) {
|
|
116
114
|
super();
|
|
117
115
|
this.id = id;
|
|
@@ -317,7 +315,7 @@ export class ImageSource extends Evented implements Source {
|
|
|
317
315
|
* Given a list of coordinates, get their center as a coordinate.
|
|
318
316
|
*
|
|
319
317
|
* @returns centerpoint
|
|
320
|
-
* @
|
|
318
|
+
* @internal
|
|
321
319
|
*/
|
|
322
320
|
export function getCoordinatesCenterTileID(coords: Array<MercatorCoordinate>) {
|
|
323
321
|
let minX = Infinity;
|
|
@@ -6,6 +6,7 @@ export type FeatureStates = {[featureId: string]: FeatureState};
|
|
|
6
6
|
export type LayerFeatureStates = {[layer: string]: FeatureStates};
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
+
* @internal
|
|
9
10
|
* SourceFeatureState manages the state and pending changes
|
|
10
11
|
* to features in a source, separated by source layer.
|
|
11
12
|
* stateChanges and deletedStates batch all changes to the tile (updates and removes, respectively)
|
package/src/source/tile.ts
CHANGED
|
@@ -47,6 +47,7 @@ import {ExpiryData} from '../util/ajax';
|
|
|
47
47
|
export type TileState = 'loading' | 'loaded' | 'reloading' | 'unloaded' | 'errored' | 'expired';
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
+
* @internal
|
|
50
51
|
* A tile object is the combination of a Coordinate, which defines
|
|
51
52
|
* its place, as well as a unique ID and data tracking for its content
|
|
52
53
|
*/
|
package/src/source/tile_cache.ts
CHANGED
|
@@ -2,10 +2,10 @@ import {OverscaledTileID} from './tile_id';
|
|
|
2
2
|
import type {Tile} from './tile';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
+
* @internal
|
|
5
6
|
* A [least-recently-used cache](http://en.wikipedia.org/wiki/Cache_algorithms)
|
|
6
7
|
* with hash lookup made possible by keeping a list of keys in parallel to
|
|
7
8
|
* an array of dictionary of values
|
|
8
|
-
*
|
|
9
9
|
*/
|
|
10
10
|
export class TileCache {
|
|
11
11
|
max: number;
|
package/src/source/tile_id.ts
CHANGED
|
@@ -87,6 +87,85 @@ describe('vector tile worker source', () => {
|
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
test('VectorTileWorkerSource#loadTile reparses tile if the reloadTile has been called during parsing', (done) => {
|
|
90
|
+
const rawTileData = new Uint8Array([]);
|
|
91
|
+
function loadVectorData(params, callback) {
|
|
92
|
+
return callback(null, {
|
|
93
|
+
vectorTile: {
|
|
94
|
+
layers: {
|
|
95
|
+
test: {
|
|
96
|
+
version: 2,
|
|
97
|
+
name: 'test',
|
|
98
|
+
extent: 8192,
|
|
99
|
+
length: 1,
|
|
100
|
+
feature: (featureIndex: number) => ({
|
|
101
|
+
extent: 8192,
|
|
102
|
+
type: 1,
|
|
103
|
+
id: featureIndex,
|
|
104
|
+
properties: {
|
|
105
|
+
name: 'test'
|
|
106
|
+
},
|
|
107
|
+
loadGeometry () {
|
|
108
|
+
return [[{x: 0, y: 0}]];
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} as any as vt.VectorTile,
|
|
114
|
+
rawData: rawTileData
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const layerIndex = new StyleLayerIndex([{
|
|
119
|
+
id: 'test',
|
|
120
|
+
source: 'source',
|
|
121
|
+
'source-layer': 'test',
|
|
122
|
+
type: 'symbol',
|
|
123
|
+
layout: {
|
|
124
|
+
'icon-image': 'hello',
|
|
125
|
+
'text-font': ['StandardFont-Bold'],
|
|
126
|
+
'text-field': '{name}'
|
|
127
|
+
}
|
|
128
|
+
}]);
|
|
129
|
+
|
|
130
|
+
const send = jest.fn().mockImplementation((type: string, data: unknown, callback: Function) => {
|
|
131
|
+
const res = setTimeout(() => callback(null,
|
|
132
|
+
type === 'getImages' ?
|
|
133
|
+
{'hello': {width: 1, height: 1, data: new Uint8Array([0])}} :
|
|
134
|
+
{'StandardFont-Bold': {width: 1, height: 1, data: new Uint8Array([0])}}
|
|
135
|
+
));
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
cancel: () => clearTimeout(res)
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const actor = {
|
|
143
|
+
send
|
|
144
|
+
} as unknown as Actor;
|
|
145
|
+
const source = new VectorTileWorkerSource(actor, layerIndex, ['hello'], loadVectorData);
|
|
146
|
+
source.loadTile({
|
|
147
|
+
source: 'source',
|
|
148
|
+
uid: 0,
|
|
149
|
+
tileID: {overscaledZ: 0, wrap: 0, canonical: {x: 0, y: 0, z: 0, w: 0}},
|
|
150
|
+
request: {url: 'http://localhost:2900/faketile.pbf'}
|
|
151
|
+
} as any as WorkerTileParameters, () => {
|
|
152
|
+
done.fail('should not be called');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
source.reloadTile({
|
|
156
|
+
source: 'source',
|
|
157
|
+
uid: '0',
|
|
158
|
+
tileID: {overscaledZ: 0, wrap: 0, canonical: {x: 0, y: 0, z: 0, w: 0}},
|
|
159
|
+
} as any as WorkerTileParameters, (err, res) => {
|
|
160
|
+
expect(err).toBeFalsy();
|
|
161
|
+
expect(res).toBeDefined();
|
|
162
|
+
expect(res.rawTileData).toBeDefined();
|
|
163
|
+
expect(res.rawTileData).toStrictEqual(rawTileData);
|
|
164
|
+
done();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('VectorTileWorkerSource#loadTile reparses tile if reloadTile is called during reparsing', (done) => {
|
|
90
169
|
const rawTileData = new Uint8Array([]);
|
|
91
170
|
function loadVectorData(params, callback) {
|
|
92
171
|
return callback(null, {
|
|
@@ -24,6 +24,12 @@ export type LoadVectorTileResult = {
|
|
|
24
24
|
resourceTiming?: Array<PerformanceResourceTiming>;
|
|
25
25
|
} & ExpiryData;
|
|
26
26
|
|
|
27
|
+
type FetchingState = {
|
|
28
|
+
rawTileData: ArrayBuffer;
|
|
29
|
+
cacheControl: ExpiryData;
|
|
30
|
+
resourceTiming: any;
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
/**
|
|
28
34
|
* The callback when finished loading vector data
|
|
29
35
|
*/
|
|
@@ -66,6 +72,7 @@ export class VectorTileWorkerSource implements WorkerSource {
|
|
|
66
72
|
layerIndex: StyleLayerIndex;
|
|
67
73
|
availableImages: Array<string>;
|
|
68
74
|
loadVectorData: LoadVectorData;
|
|
75
|
+
fetching: {[_: string]: FetchingState };
|
|
69
76
|
loading: {[_: string]: WorkerTile};
|
|
70
77
|
loaded: {[_: string]: WorkerTile};
|
|
71
78
|
|
|
@@ -80,6 +87,7 @@ export class VectorTileWorkerSource implements WorkerSource {
|
|
|
80
87
|
this.layerIndex = layerIndex;
|
|
81
88
|
this.availableImages = availableImages;
|
|
82
89
|
this.loadVectorData = loadVectorData || loadVectorTile;
|
|
90
|
+
this.fetching = {};
|
|
83
91
|
this.loading = {};
|
|
84
92
|
this.loaded = {};
|
|
85
93
|
}
|
|
@@ -124,6 +132,7 @@ export class VectorTileWorkerSource implements WorkerSource {
|
|
|
124
132
|
|
|
125
133
|
workerTile.vectorTile = response.vectorTile;
|
|
126
134
|
workerTile.parse(response.vectorTile, this.layerIndex, this.availableImages, this.actor, (err, result) => {
|
|
135
|
+
delete this.fetching[uid];
|
|
127
136
|
if (err || !result) return callback(err);
|
|
128
137
|
|
|
129
138
|
// Transferring a copy of rawTileData because the worker needs to retain its copy.
|
|
@@ -132,6 +141,8 @@ export class VectorTileWorkerSource implements WorkerSource {
|
|
|
132
141
|
|
|
133
142
|
this.loaded = this.loaded || {};
|
|
134
143
|
this.loaded[uid] = workerTile;
|
|
144
|
+
// keep the original fetching state so that reload tile can pick it up if the original parse is cancelled by reloads' parse
|
|
145
|
+
this.fetching[uid] = {rawTileData, cacheControl, resourceTiming};
|
|
135
146
|
}) as AbortVectorData;
|
|
136
147
|
}
|
|
137
148
|
|
|
@@ -145,7 +156,21 @@ export class VectorTileWorkerSource implements WorkerSource {
|
|
|
145
156
|
const workerTile = loaded[uid];
|
|
146
157
|
workerTile.showCollisionBoxes = params.showCollisionBoxes;
|
|
147
158
|
if (workerTile.status === 'parsing') {
|
|
148
|
-
workerTile.parse(workerTile.vectorTile, this.layerIndex, this.availableImages, this.actor,
|
|
159
|
+
workerTile.parse(workerTile.vectorTile, this.layerIndex, this.availableImages, this.actor, (err, result) => {
|
|
160
|
+
if (err || !result) return callback(err, result);
|
|
161
|
+
|
|
162
|
+
// if we have cancelled the original parse, make sure to pass the rawTileData from the original fetch
|
|
163
|
+
let parseResult;
|
|
164
|
+
if (this.fetching[uid]) {
|
|
165
|
+
const {rawTileData, cacheControl, resourceTiming} = this.fetching[uid];
|
|
166
|
+
delete this.fetching[uid];
|
|
167
|
+
parseResult = extend({rawTileData: rawTileData.slice(0)}, result, cacheControl, resourceTiming);
|
|
168
|
+
} else {
|
|
169
|
+
parseResult = result;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
callback(null, parseResult);
|
|
173
|
+
});
|
|
149
174
|
} else if (workerTile.status === 'done') {
|
|
150
175
|
// if there was no vector tile data on the initial load, don't try and re-parse tile
|
|
151
176
|
if (workerTile.vectorTile) {
|