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.
Files changed (88) hide show
  1. package/build/generate-struct-arrays.ts +6 -3
  2. package/build/generate-style-code.ts +7 -8
  3. package/dist/maplibre-gl-csp-worker.js +1 -1
  4. package/dist/maplibre-gl-csp-worker.js.map +1 -1
  5. package/dist/maplibre-gl-csp.js +1 -1
  6. package/dist/maplibre-gl-csp.js.map +1 -1
  7. package/dist/maplibre-gl-dev.js +565 -243
  8. package/dist/maplibre-gl-dev.js.map +1 -1
  9. package/dist/maplibre-gl.d.ts +111 -57
  10. package/dist/maplibre-gl.js +4 -4
  11. package/dist/maplibre-gl.js.map +1 -1
  12. package/package.json +20 -20
  13. package/src/data/array_types.g.ts +110 -24
  14. package/src/data/bucket/circle_bucket.ts +1 -0
  15. package/src/data/bucket/line_bucket.ts +1 -0
  16. package/src/data/bucket/symbol_attributes.ts +7 -1
  17. package/src/data/bucket/symbol_bucket.ts +5 -1
  18. package/src/data/feature_index.ts +1 -0
  19. package/src/data/program_configuration.ts +1 -0
  20. package/src/data/segment.ts +2 -0
  21. package/src/geo/transform.ts +1 -0
  22. package/src/gl/context.ts +1 -0
  23. package/src/gl/framebuffer.ts +1 -0
  24. package/src/gl/index_buffer.ts +1 -0
  25. package/src/gl/render_pool.ts +2 -1
  26. package/src/gl/vertex_buffer.ts +1 -0
  27. package/src/render/draw_symbol.ts +8 -9
  28. package/src/render/image_atlas.ts +1 -0
  29. package/src/render/line_atlas.ts +1 -0
  30. package/src/render/painter.ts +1 -0
  31. package/src/render/program.ts +1 -0
  32. package/src/render/render_to_texture.ts +31 -14
  33. package/src/render/terrain.ts +3 -0
  34. package/src/render/texture.ts +1 -0
  35. package/src/render/uniform_binding.ts +2 -0
  36. package/src/render/vertex_array_object.ts +1 -0
  37. package/src/shaders/symbol_sdf.fragment.glsl +9 -3
  38. package/src/shaders/symbol_sdf.fragment.glsl.g.ts +1 -1
  39. package/src/source/canvas_source.ts +1 -3
  40. package/src/source/geojson_source.ts +1 -3
  41. package/src/source/image_source.ts +2 -4
  42. package/src/source/source_cache.ts +1 -0
  43. package/src/source/source_state.ts +1 -0
  44. package/src/source/terrain_source_cache.ts +1 -0
  45. package/src/source/tile.ts +1 -0
  46. package/src/source/tile_cache.ts +1 -1
  47. package/src/source/tile_id.ts +1 -0
  48. package/src/source/vector_tile_worker_source.test.ts +79 -0
  49. package/src/source/vector_tile_worker_source.ts +26 -1
  50. package/src/source/worker_source.ts +1 -0
  51. package/src/style/evaluation_parameters.ts +1 -0
  52. package/src/style/properties.ts +18 -0
  53. package/src/style/style.ts +1 -0
  54. package/src/style/style_glyph.ts +1 -0
  55. package/src/style/style_layer/background_style_layer_properties.g.ts +1 -6
  56. package/src/style/style_layer/circle_style_layer_properties.g.ts +1 -6
  57. package/src/style/style_layer/fill_extrusion_style_layer_properties.g.ts +1 -6
  58. package/src/style/style_layer/fill_style_layer_properties.g.ts +1 -6
  59. package/src/style/style_layer/heatmap_style_layer_properties.g.ts +1 -6
  60. package/src/style/style_layer/hillshade_style_layer_properties.g.ts +1 -6
  61. package/src/style/style_layer/line_style_layer_properties.g.ts +1 -6
  62. package/src/style/style_layer/raster_style_layer_properties.g.ts +1 -6
  63. package/src/style/style_layer/symbol_style_layer_properties.g.ts +4 -6
  64. package/src/style/style_layer/variable_text_anchor.test.ts +117 -0
  65. package/src/style/style_layer/variable_text_anchor.ts +163 -0
  66. package/src/symbol/collision_index.ts +1 -0
  67. package/src/symbol/grid_index.ts +1 -0
  68. package/src/symbol/placement.ts +52 -40
  69. package/src/symbol/symbol_layout.ts +42 -116
  70. package/src/ui/camera.ts +8 -8
  71. package/src/ui/handler/box_zoom.ts +1 -3
  72. package/src/ui/handler/click_zoom.ts +1 -3
  73. package/src/ui/handler/keyboard.ts +1 -3
  74. package/src/ui/handler/scroll_zoom.ts +1 -3
  75. package/src/ui/handler/shim/dblclick_zoom.ts +1 -3
  76. package/src/ui/handler/shim/drag_pan.ts +1 -3
  77. package/src/ui/handler/shim/drag_rotate.ts +1 -3
  78. package/src/ui/handler/shim/two_fingers_touch.ts +1 -3
  79. package/src/ui/handler/transform-provider.ts +1 -0
  80. package/src/ui/handler/two_fingers_touch.ts +1 -3
  81. package/src/ui/map.ts +7 -6
  82. package/src/util/ajax.test.ts +33 -0
  83. package/src/util/ajax.ts +5 -0
  84. package/src/util/image.ts +1 -0
  85. package/src/util/image_request.ts +2 -2
  86. package/src/util/performance.ts +1 -2
  87. package/src/util/struct_array.ts +5 -1
  88. 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 variablePlacement = layer.layout.get('text-variable-anchor');
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 (variablePlacement) {
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 + variableOffset[0]) * renderTextSize,
123
- (shiftY / textBoxScale + variableOffset[1]) * renderTextSize
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 variablePlacement = layer.layout.get('text-variable-anchor');
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 = variablePlacement && bucket.hasTextData();
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 && variablePlacement) || updateTextFitIcon) ? identityMat4 : labelPlaneMatrix,
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;
@@ -61,6 +61,7 @@ export class ImagePosition {
61
61
  }
62
62
 
63
63
  /**
64
+ * @internal
64
65
  * A class holding all the images
65
66
  */
66
67
  export class ImageAtlas {
@@ -12,6 +12,7 @@ type DashEntry = {
12
12
  }
13
13
 
14
14
  /**
15
+ * @internal
15
16
  * A LineAtlas lets us reuse rendered dashed lines
16
17
  * by writing many of them to a texture and then fetching their positions
17
18
  * using {@link LineAtlas#getDash}.
@@ -61,6 +61,7 @@ type PainterOptions = {
61
61
  };
62
62
 
63
63
  /**
64
+ * @internal
64
65
  * Initialize a new painter object.
65
66
  */
66
67
  export class Painter {
@@ -30,6 +30,7 @@ function getTokenizedAttributesAndUniforms(array: Array<string>): Array<string>
30
30
  }
31
31
 
32
32
  /**
33
+ * @internal
33
34
  * A webgl program to execute in the GPU space
34
35
  */
35
36
  export class Program<Us extends UniformBindings> {
@@ -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
- // lookup table which layers should rendered to texture
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
- * RenderToTexture
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
- // coordsDescendingInv contains a list of all tiles which should be rendered for one render-to-texture tile
29
- // e.g. render 4 raster-tiles with size 256px to the 512px render-to-texture tile
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
- // create a string representation of all to tiles rendered to render-to-texture tiles
32
- // this string representation is used to check if tile should be re-rendered.
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
- // store for render-stacks
35
- // a render stack is a set of layers which should be rendered into one texture
36
- // every stylesheet can have multiple stacks. A new stack is created if layers which should
37
- // not rendered to texture sit inbetween layers which should rendered to texture. e.g. hillshading or symbols
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
- // remember the previous processed layer to check if a new stack is needed
48
+ /**
49
+ * remember the previous processed layer to check if a new stack is needed
50
+ */
40
51
  _prevType: string;
41
- // a list of tiles that can potentially rendered
52
+ /**
53
+ * a list of tiles that can potentially rendered
54
+ */
42
55
  _renderableTiles: Array<Tile>;
43
- // a list of tiles that should be rendered to screen in the next render-call
56
+ /**
57
+ * a list of tiles that should be rendered to screen in the next render-call
58
+ */
44
59
  _rttTiles: Array<Tile>;
45
- // a list of all layer-ids which should be rendered
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) {
@@ -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
@@ -16,6 +16,7 @@ type DataTextureImage = RGBAImage | AlphaImage | EmptyImage;
16
16
  export type TextureImage = TexImageSource | DataTextureImage;
17
17
 
18
18
  /**
19
+ * @internal
19
20
  * A `Texture` GL related object
20
21
  */
21
22
  export class Texture {
@@ -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>};
@@ -5,6 +5,7 @@ import type {IndexBuffer} from '../gl/index_buffer';
5
5
  import type {Context} from '../gl/context';
6
6
 
7
7
  /**
8
+ * @internal
8
9
  * A vertex array object used to pass data to the webgl code
9
10
  */
10
11
  export class VertexArrayObject {
@@ -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 buff = (256.0 - 64.0) / 256.0;
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
- buff = (6.0 - halo_width / fontScale) / SDF_PX;
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(buff - gamma_scaled, buff + gamma_scaled, dist);
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 buff=(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);buff=(6.0-halo_width/fontScale)/SDF_PX;}lowp float dist=texture2D(u_texture,tex).a;highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(buff-gamma_scaled,buff+gamma_scaled,dist);gl_FragColor=color*(alpha*opacity*fade_opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}';
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
- * @hidden
318
+ * @internal
321
319
  */
322
320
  export function getCoordinatesCenterTileID(coords: Array<MercatorCoordinate>) {
323
321
  let minX = Infinity;
@@ -25,6 +25,7 @@ import {Terrain} from '../render/terrain';
25
25
  import {config} from '../util/config';
26
26
 
27
27
  /**
28
+ * @internal
28
29
  * `SourceCache` is responsible for
29
30
  *
30
31
  * - creating an instance of `Source`
@@ -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)
@@ -8,6 +8,7 @@ import type {SourceCache} from '../source/source_cache';
8
8
  import {Terrain} from '../render/terrain';
9
9
 
10
10
  /**
11
+ * @internal
11
12
  * This class is a helper for the Terrain-class, it:
12
13
  * - loads raster-dem tiles
13
14
  * - manages all renderToTexture tiles.
@@ -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
  */
@@ -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;
@@ -64,6 +64,7 @@ export class CanonicalTileID implements ICanonicalTileID {
64
64
  }
65
65
 
66
66
  /**
67
+ * @internal
67
68
  * An unwrapped tile identifier
68
69
  */
69
70
  export class UnwrappedTileID {
@@ -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, callback);
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) {
@@ -41,6 +41,7 @@ export type WorkerDEMTileParameters = TileParameters & {
41
41
  };
42
42
 
43
43
  /**
44
+ * @internal
44
45
  * The worker tile's result type
45
46
  */
46
47
  export type WorkerTileResult = {
@@ -11,6 +11,7 @@ export type CrossfadeParameters = {
11
11
  };
12
12
 
13
13
  /**
14
+ * @internal
14
15
  * A parameter that can be evaluated to a value
15
16
  */
16
17
  export class EvaluationParameters {