@mapwhit/tilerenderer 1.3.0 → 1.5.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 (46) hide show
  1. package/build/min/package.json +1 -1
  2. package/package.json +1 -1
  3. package/src/data/array_types.js +115 -64
  4. package/src/data/bucket/circle_bucket.js +42 -5
  5. package/src/data/bucket/fill_bucket.js +31 -13
  6. package/src/data/bucket/fill_extrusion_bucket.js +8 -6
  7. package/src/data/bucket/line_bucket.js +38 -14
  8. package/src/data/bucket/symbol_attributes.js +13 -5
  9. package/src/data/bucket/symbol_bucket.js +112 -40
  10. package/src/data/bucket/symbol_collision_buffers.js +1 -1
  11. package/src/data/bucket.js +3 -1
  12. package/src/data/feature_index.js +24 -11
  13. package/src/data/segment.js +15 -7
  14. package/src/index.js +23 -23
  15. package/src/render/draw_circle.js +45 -4
  16. package/src/render/draw_symbol.js +190 -22
  17. package/src/render/painter.js +1 -1
  18. package/src/source/geojson_source.js +118 -21
  19. package/src/source/geojson_source_diff.js +148 -0
  20. package/src/source/geojson_tiler.js +89 -0
  21. package/src/source/rtl_text_plugin.js +133 -66
  22. package/src/source/source.js +16 -5
  23. package/src/source/source_cache.js +6 -6
  24. package/src/source/source_state.js +4 -2
  25. package/src/source/tile.js +5 -3
  26. package/src/source/vector_tile_source.js +2 -0
  27. package/src/source/worker_tile.js +6 -2
  28. package/src/style/evaluation_parameters.js +2 -3
  29. package/src/style/pauseable_placement.js +39 -7
  30. package/src/style/style.js +34 -23
  31. package/src/style/style_layer/circle_style_layer_properties.js +8 -1
  32. package/src/style/style_layer/fill_style_layer_properties.js +8 -1
  33. package/src/style/style_layer/line_style_layer_properties.js +4 -0
  34. package/src/style/style_layer/symbol_style_layer_properties.js +17 -2
  35. package/src/style-spec/reference/v8.json +161 -4
  36. package/src/symbol/one_em.js +4 -0
  37. package/src/symbol/placement.js +406 -173
  38. package/src/symbol/projection.js +3 -3
  39. package/src/symbol/quads.js +1 -6
  40. package/src/symbol/shaping.js +18 -29
  41. package/src/symbol/symbol_layout.js +243 -81
  42. package/src/symbol/transform_text.js +3 -4
  43. package/src/util/config.js +1 -9
  44. package/src/util/script_detection.js +19 -7
  45. package/src/util/vectortile_to_geojson.js +3 -4
  46. package/src/source/geojson_worker_source.js +0 -97
@@ -5,7 +5,7 @@ import ImageManager from '../render/image_manager.js';
5
5
  import LineAtlas from '../render/line_atlas.js';
6
6
  import { queryRenderedFeatures, queryRenderedSymbols, querySourceFeatures } from '../source/query_features.js';
7
7
  import { resources } from '../source/resources/index.js';
8
- import plugin from '../source/rtl_text_plugin.js';
8
+ import { rtlPluginLoader } from '../source/rtl_text_plugin.js';
9
9
  import { getType as getSourceType, setType as setSourceType } from '../source/source.js';
10
10
  import SourceCache from '../source/source_cache.js';
11
11
  import CrossTileSymbolIndex from '../symbol/cross_tile_symbol_index.js';
@@ -42,6 +42,7 @@ class Style extends Evented {
42
42
  });
43
43
  #layerIndex = new StyleLayerIndex();
44
44
  #opsQueue = [];
45
+ #rtlPluginLoadedHandler;
45
46
 
46
47
  constructor(map, options = {}) {
47
48
  super();
@@ -63,9 +64,8 @@ class Style extends Evented {
63
64
  this._updatedLayers = new Map();
64
65
  this._removedLayers = new Map();
65
66
  this._resetUpdates();
66
-
67
- this._rtlTextPluginCallbackUnregister = plugin.registerForPluginAvailability(this._reloadSources.bind(this));
68
-
67
+ this.#rtlPluginLoadedHandler = this.#rtlPluginLoaded.bind(this);
68
+ rtlPluginLoader.on('RTLPluginLoaded', this.#rtlPluginLoadedHandler);
69
69
  this.on('data', event => {
70
70
  if (event.dataType !== 'source' || event.sourceDataType !== 'metadata') {
71
71
  return;
@@ -89,6 +89,18 @@ class Style extends Evented {
89
89
  });
90
90
  }
91
91
 
92
+ #rtlPluginLoaded() {
93
+ for (const sourceCache of Object.values(this._sources)) {
94
+ const { type } = sourceCache.getSource();
95
+ if (type === 'vector' || type === 'geojson') {
96
+ // Non-vector sources don't have any symbols buckets to reload when the RTL text plugin loads
97
+ // They also load more quickly, so they're more likely to have already displaying tiles
98
+ // that would be unnecessarily booted by the plugin load event
99
+ sourceCache.reload(); // Should be a no-op if the plugin loads before any tiles load
100
+ }
101
+ }
102
+ }
103
+
92
104
  setGlobalStateProperty(name, value) {
93
105
  if (!this._loaded) {
94
106
  this.#opsQueue.push(() => this.setGlobalStateProperty(name, value));
@@ -784,13 +796,13 @@ class Style extends Evented {
784
796
  return this.getLayer(layer).getPaintProperty(name);
785
797
  }
786
798
 
787
- setFeatureState(feature, state) {
799
+ setFeatureState(target, state) {
788
800
  if (!this._loaded) {
789
- this.#opsQueue.push(() => this.setFeatureState(feature, state));
801
+ this.#opsQueue.push(() => this.setFeatureState(target, state));
790
802
  return;
791
803
  }
792
- const sourceId = feature.source;
793
- const sourceLayer = feature.sourceLayer;
804
+ const sourceId = target.source;
805
+ const sourceLayer = target.sourceLayer;
794
806
  const sourceCache = this._sources[sourceId];
795
807
 
796
808
  if (sourceCache === undefined) {
@@ -806,12 +818,12 @@ class Style extends Evented {
806
818
  this.fire(new ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
807
819
  return;
808
820
  }
809
- if (feature.id == null || feature.id === '') {
821
+ if (target.id === undefined) {
810
822
  this.fire(new ErrorEvent(new Error('The feature id parameter must be provided.')));
811
823
  return;
812
824
  }
813
825
 
814
- sourceCache.setFeatureState(sourceLayer, feature.id, state);
826
+ sourceCache.setFeatureState(sourceLayer, target.id, state);
815
827
  }
816
828
 
817
829
  removeFeatureState(target, key) {
@@ -843,12 +855,12 @@ class Style extends Evented {
843
855
  sourceCache.removeFeatureState(sourceLayer, target.id, key);
844
856
  }
845
857
 
846
- getFeatureState(feature) {
858
+ getFeatureState(target) {
847
859
  if (!this._loaded) {
848
860
  return;
849
861
  }
850
- const sourceId = feature.source;
851
- const sourceLayer = feature.sourceLayer;
862
+ const sourceId = target.source;
863
+ const sourceLayer = target.sourceLayer;
852
864
  const sourceCache = this._sources[sourceId];
853
865
 
854
866
  if (sourceCache === undefined) {
@@ -861,7 +873,11 @@ class Style extends Evented {
861
873
  return;
862
874
  }
863
875
 
864
- return sourceCache.getFeatureState(sourceLayer, feature.id);
876
+ if (target.id === undefined) {
877
+ this.fire(new ErrorEvent(new Error('The feature id parameter must be provided.')));
878
+ }
879
+
880
+ return sourceCache.getFeatureState(sourceLayer, target.id);
865
881
  }
866
882
 
867
883
  getTransition() {
@@ -1039,7 +1055,7 @@ class Style extends Evented {
1039
1055
  }
1040
1056
 
1041
1057
  _remove() {
1042
- this._rtlTextPluginCallbackUnregister?.();
1058
+ rtlPluginLoader.off('RTLPluginLoaded', this.#rtlPluginLoadedHandler);
1043
1059
  for (const id in this._sources) {
1044
1060
  this._sources[id].clearTiles();
1045
1061
  }
@@ -1060,12 +1076,6 @@ class Style extends Evented {
1060
1076
  }
1061
1077
  }
1062
1078
 
1063
- _reloadSources() {
1064
- for (const sourceCache of Object.values(this._sources)) {
1065
- sourceCache.reload(); // Should be a no-op if called before any tiles load
1066
- }
1067
- }
1068
-
1069
1079
  _generateCollisionBoxes() {
1070
1080
  for (const id in this._sources) {
1071
1081
  this._reloadSource(id);
@@ -1117,7 +1127,8 @@ class Style extends Evented {
1117
1127
  forceFullPlacement,
1118
1128
  showCollisionBoxes,
1119
1129
  fadeDuration,
1120
- crossSourceCollisions
1130
+ crossSourceCollisions,
1131
+ this.placement
1121
1132
  );
1122
1133
  this._layerOrderChanged = false;
1123
1134
  }
@@ -1132,7 +1143,7 @@ class Style extends Evented {
1132
1143
  this.pauseablePlacement.continuePlacement(Array.from(this._layers.values()), layerTiles);
1133
1144
 
1134
1145
  if (this.pauseablePlacement.isDone()) {
1135
- this.placement = this.pauseablePlacement.commit(this.placement, browser.now());
1146
+ this.placement = this.pauseablePlacement.commit(browser.now());
1136
1147
  placementCommitted = true;
1137
1148
  }
1138
1149
 
@@ -2,6 +2,13 @@
2
2
 
3
3
  import { DataConstantProperty, DataDrivenProperty, Properties } from '../properties.js';
4
4
 
5
+ const layout = new Properties({
6
+ 'circle-sort-key': new DataDrivenProperty({
7
+ type: 'number',
8
+ expression: { parameters: ['zoom', 'feature'] }
9
+ })
10
+ });
11
+
5
12
  const paint = new Properties({
6
13
  'circle-radius': new DataDrivenProperty({
7
14
  type: 'number',
@@ -73,4 +80,4 @@ const paint = new Properties({
73
80
  })
74
81
  });
75
82
 
76
- export default { paint };
83
+ export default { paint, layout };
@@ -2,6 +2,13 @@
2
2
 
3
3
  import { CrossFadedDataDrivenProperty, DataConstantProperty, DataDrivenProperty, Properties } from '../properties.js';
4
4
 
5
+ const layout = new Properties({
6
+ 'fill-sort-key': new DataDrivenProperty({
7
+ type: 'number',
8
+ expression: { parameters: ['zoom', 'feature'] }
9
+ })
10
+ });
11
+
5
12
  const paint = new Properties({
6
13
  'fill-antialias': new DataConstantProperty({ type: 'boolean', default: true, expression: { parameters: ['zoom'] } }),
7
14
  'fill-opacity': new DataDrivenProperty({
@@ -42,4 +49,4 @@ const paint = new Properties({
42
49
  })
43
50
  });
44
51
 
45
- export default { paint };
52
+ export default { paint, layout };
@@ -31,6 +31,10 @@ const layout = new Properties({
31
31
  type: 'number',
32
32
  default: 1.05,
33
33
  expression: { interpolated: true, parameters: ['zoom'] }
34
+ }),
35
+ 'line-sort-key': new DataDrivenProperty({
36
+ type: 'number',
37
+ expression: { parameters: ['zoom', 'feature'] }
34
38
  })
35
39
  });
36
40
  const paint = new Properties({
@@ -19,10 +19,14 @@ const layout = new Properties({
19
19
  default: false,
20
20
  expression: { parameters: ['zoom'] }
21
21
  }),
22
+ 'symbol-sort-key': new DataDrivenProperty({
23
+ type: 'number',
24
+ expression: { parameters: ['zoom', 'feature'] }
25
+ }),
22
26
  'symbol-z-order': new DataConstantProperty({
23
27
  type: 'enum',
24
- values: ['viewport-y', 'source'],
25
- default: 'viewport-y',
28
+ values: ['auto', 'viewport-y', 'source'],
29
+ default: 'auto',
26
30
  expression: { parameters: ['zoom'] }
27
31
  }),
28
32
  'icon-allow-overlap': new DataConstantProperty({
@@ -149,6 +153,17 @@ const layout = new Properties({
149
153
  default: 'center',
150
154
  expression: { parameters: ['zoom', 'feature'] }
151
155
  }),
156
+ 'text-radial-offset': new DataDrivenProperty({
157
+ type: 'number',
158
+ default: 0,
159
+ expression: { interpolated: true, parameters: ['zoom', 'feature'] }
160
+ }),
161
+ 'text-variable-anchor': new DataConstantProperty({
162
+ type: 'array',
163
+ value: 'enum',
164
+ values: ['center', 'left', 'right', 'top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],
165
+ expression: { parameters: ['zoom'] }
166
+ }),
152
167
  'text-anchor': new DataDrivenProperty({
153
168
  type: 'enum',
154
169
  values: ['center', 'left', 'right', 'top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],
@@ -337,6 +337,10 @@
337
337
  "default": "mapbox",
338
338
  "doc": "The encoding used by this source. Mapbox Terrain RGB is used by default"
339
339
  },
340
+ "promoteId": {
341
+ "type": "promoteId",
342
+ "doc": "A property to use as a feature id (for feature state). Either a property name, or an object of the form `{<sourceLayer>: <propertyName>}`."
343
+ },
340
344
  "*": {
341
345
  "type": "*",
342
346
  "doc": "Other keys to configure the data source."
@@ -395,9 +399,13 @@
395
399
  "doc": "Whether to calculate line distance metrics. This is required for line layers that specify `line-gradient` values."
396
400
  },
397
401
  "generateId": {
398
- "type": "boolean",
399
- "default": false,
400
- "doc": "Whether to generate ids for the geojson features. When enabled, the `feature.id` property will be auto assigned based on it's index in the `features` array, over-writing any previous values."
402
+ "type": "boolean",
403
+ "default": false,
404
+ "doc": "Whether to generate ids for the geojson features. When enabled, the `feature.id` property will be auto assigned based on its index in the `features` array, over-writing any previous values."
405
+ },
406
+ "promoteId": {
407
+ "type": "promoteId",
408
+ "doc": "A property to use as a feature id (for feature state). Either a property name, or an object of the form `{<sourceLayer>: <propertyName>}`."
401
409
  }
402
410
  },
403
411
  "source_video": {
@@ -650,6 +658,21 @@
650
658
  }
651
659
  },
652
660
  "layout_fill": {
661
+ "fill-sort-key": {
662
+ "type": "number",
663
+ "doc": "Sorts features in ascending order based on this value. Features with a higher sort key will appear above features with a lower sort key.",
664
+ "sdk-support": {
665
+ "js": "1.2.0"
666
+ },
667
+ "expression": {
668
+ "interpolated": false,
669
+ "parameters": [
670
+ "zoom",
671
+ "feature"
672
+ ]
673
+ },
674
+ "property-type": "data-driven"
675
+ },
653
676
  "visibility": {
654
677
  "type": "enum",
655
678
  "values": {
@@ -680,6 +703,21 @@
680
703
  }
681
704
  },
682
705
  "layout_circle": {
706
+ "circle-sort-key": {
707
+ "type": "number",
708
+ "doc": "Sorts features in ascending order based on this value. Features with a higher sort key will appear above features with a lower sort key.",
709
+ "sdk-support": {
710
+ "js": "1.2.0"
711
+ },
712
+ "expression": {
713
+ "interpolated": false,
714
+ "parameters": [
715
+ "zoom",
716
+ "feature"
717
+ ]
718
+ },
719
+ "property-type": "data-driven"
720
+ },
683
721
  "visibility": {
684
722
  "type": "enum",
685
723
  "values": {
@@ -892,6 +930,21 @@
892
930
  },
893
931
  "property-type": "data-constant"
894
932
  },
933
+ "line-sort-key": {
934
+ "type": "number",
935
+ "doc": "Sorts features in ascending order based on this value. Features with a higher sort key will appear above features with a lower sort key.",
936
+ "sdk-support": {
937
+ "js": "1.2.0"
938
+ },
939
+ "expression": {
940
+ "interpolated": false,
941
+ "parameters": [
942
+ "zoom",
943
+ "feature"
944
+ ]
945
+ },
946
+ "property-type": "data-driven"
947
+ },
895
948
  "visibility": {
896
949
  "type": "enum",
897
950
  "values": {
@@ -1007,9 +1060,27 @@
1007
1060
  },
1008
1061
  "property-type": "data-constant"
1009
1062
  },
1063
+ "symbol-sort-key": {
1064
+ "type": "number",
1065
+ "doc": "Sorts features in ascending order based on this value. Features with a higher sort key will appear above features with a lower sort key wehn they overlap. Features with a lower sort key will have priority over other features when doing placement.",
1066
+ "sdk-support": {
1067
+ "js": "0.53.0"
1068
+ },
1069
+ "expression": {
1070
+ "interpolated": false,
1071
+ "parameters": [
1072
+ "zoom",
1073
+ "feature"
1074
+ ]
1075
+ },
1076
+ "property-type": "data-driven"
1077
+ },
1010
1078
  "symbol-z-order": {
1011
1079
  "type": "enum",
1012
1080
  "values": {
1081
+ "auto": {
1082
+ "doc": "If `symbol-sort-key` is set, sort based on that. Otherwise sort symbols by their position relative to the viewport."
1083
+ },
1013
1084
  "viewport-y": {
1014
1085
  "doc": "Symbols will be sorted by their y-position relative to the viewport."
1015
1086
  },
@@ -1017,7 +1088,7 @@
1017
1088
  "doc": "Symbols will be rendered in the same order as the source data with no sorting applied."
1018
1089
  }
1019
1090
  },
1020
- "default": "viewport-y",
1091
+ "default": "auto",
1021
1092
  "doc": "Controls the order in which overlapping symbols in the same layer are rendered",
1022
1093
  "sdk-support": {
1023
1094
  "basic functionality": {
@@ -1810,6 +1881,92 @@
1810
1881
  },
1811
1882
  "property-type": "data-driven"
1812
1883
  },
1884
+ "text-radial-offset": {
1885
+ "type": "number",
1886
+ "units": "ems",
1887
+ "default": 0,
1888
+ "doc": "Radial offset of text, in the direction of the symbol's anchor. Useful in combination with `text-variable-anchor`, which defaults to using the two-dimensional `text-offset` if present.",
1889
+ "sdk-support": {
1890
+ "basic functionality": {
1891
+ "js": "0.54.0",
1892
+ "android": "7.4.0",
1893
+ "ios": "4.10.0"
1894
+ },
1895
+ "data-driven styling": {
1896
+ "js": "0.54.0",
1897
+ "android": "7.4.0",
1898
+ "ios": "4.10.0"
1899
+ }
1900
+ },
1901
+ "requires": [
1902
+ "text-field"
1903
+ ],
1904
+ "property-type": "data-driven",
1905
+ "expression": {
1906
+ "interpolated": true,
1907
+ "parameters": [
1908
+ "zoom",
1909
+ "feature"
1910
+ ]
1911
+ }
1912
+ },
1913
+ "text-variable-anchor": {
1914
+ "type": "array",
1915
+ "value": "enum",
1916
+ "values": {
1917
+ "center": {
1918
+ "doc": "The center of the text is placed closest to the anchor."
1919
+ },
1920
+ "left": {
1921
+ "doc": "The left side of the text is placed closest to the anchor."
1922
+ },
1923
+ "right": {
1924
+ "doc": "The right side of the text is placed closest to the anchor."
1925
+ },
1926
+ "top": {
1927
+ "doc": "The top of the text is placed closest to the anchor."
1928
+ },
1929
+ "bottom": {
1930
+ "doc": "The bottom of the text is placed closest to the anchor."
1931
+ },
1932
+ "top-left": {
1933
+ "doc": "The top left corner of the text is placed closest to the anchor."
1934
+ },
1935
+ "top-right": {
1936
+ "doc": "The top right corner of the text is placed closest to the anchor."
1937
+ },
1938
+ "bottom-left": {
1939
+ "doc": "The bottom left corner of the text is placed closest to the anchor."
1940
+ },
1941
+ "bottom-right": {
1942
+ "doc": "The bottom right corner of the text is placed closest to the anchor."
1943
+ }
1944
+ },
1945
+ "requires": [
1946
+ "text-field",
1947
+ {
1948
+ "symbol-placement": [
1949
+ "point"
1950
+ ]
1951
+ }
1952
+ ],
1953
+ "doc": "To increase the chance of placing high-priority labels on the map, you can provide an array of `text-anchor` locations: the renderer will attempt to place the label at each location, in order, before moving onto the next label. Use `text-justify: auto` to choose justification based on anchor position. To apply an offset, use the `text-radial-offset` or the two-dimensional `text-offset`.",
1954
+ "sdk-support": {
1955
+ "basic functionality": {
1956
+ "js": "0.54.0",
1957
+ "android": "7.4.0",
1958
+ "ios": "4.10.0"
1959
+ }
1960
+ },
1961
+ "expression": {
1962
+ "interpolated": false,
1963
+ "parameters": [
1964
+ "zoom"
1965
+ ]
1966
+ },
1967
+ "example": ["center", "left", "right"],
1968
+ "property-type": "data-constant"
1969
+ },
1813
1970
  "text-anchor": {
1814
1971
  "type": "enum",
1815
1972
  "values": {
@@ -0,0 +1,4 @@
1
+ //
2
+ // ONE_EM constant used to go between "em" units used in style spec and "points" used internally for layout
3
+
4
+ export default 24;