maplibre-gl 2.0.2 → 2.1.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 (132) hide show
  1. package/build/generate-struct-arrays.ts +1 -1
  2. package/build/post-ts-build.js +0 -9
  3. package/build/release-notes.js +7 -32
  4. package/dist/maplibre-gl.css +1 -1
  5. package/dist/maplibre-gl.d.ts +57 -219
  6. package/dist/maplibre-gl.js +4 -4
  7. package/dist/maplibre-gl.js.map +1 -1
  8. package/package.json +37 -53
  9. package/src/css/maplibre-gl.css +21 -21
  10. package/src/data/array_types.ts +1 -1
  11. package/src/data/bucket/circle_bucket.ts +1 -1
  12. package/src/data/bucket/fill_bucket.test.ts +1 -1
  13. package/src/data/bucket/fill_bucket.ts +1 -1
  14. package/src/data/bucket/fill_extrusion_bucket.ts +1 -1
  15. package/src/data/bucket/line_bucket.test.ts +1 -1
  16. package/src/data/bucket/line_bucket.ts +1 -1
  17. package/src/data/bucket/symbol_bucket.test.ts +1 -1
  18. package/src/data/bucket/symbol_bucket.ts +4 -4
  19. package/src/data/bucket.ts +1 -1
  20. package/src/data/evaluation_feature.ts +1 -1
  21. package/src/data/feature_index.ts +1 -1
  22. package/src/data/load_geometry.ts +1 -1
  23. package/src/data/program_configuration.ts +1 -1
  24. package/src/geo/edge_insets.ts +1 -1
  25. package/src/geo/transform.test.ts +1 -1
  26. package/src/geo/transform.ts +1 -1
  27. package/src/index.ts +1 -1
  28. package/src/render/draw_debug.ts +1 -1
  29. package/src/render/draw_symbol.ts +1 -1
  30. package/src/render/glyph_manager.ts +1 -1
  31. package/src/render/painter.ts +5 -3
  32. package/src/render/program/circle_program.ts +1 -1
  33. package/src/render/program/line_program.ts +3 -3
  34. package/src/render/program/symbol_program.ts +1 -1
  35. package/src/source/geojson_source.test.ts +29 -1
  36. package/src/source/geojson_source.ts +2 -4
  37. package/src/source/geojson_wrapper.ts +1 -1
  38. package/src/source/image_source.test.ts +153 -0
  39. package/src/source/query_features.test.ts +1 -1
  40. package/src/source/query_features.ts +1 -1
  41. package/src/source/raster_dem_tile_source.test.ts +2 -1
  42. package/src/source/raster_dem_tile_source.ts +1 -1
  43. package/src/source/raster_tile_source.test.ts +2 -1
  44. package/src/source/raster_tile_source.ts +1 -1
  45. package/src/source/source_cache.test.ts +2 -2
  46. package/src/source/source_cache.ts +1 -1
  47. package/src/source/tile.test.ts +1 -1
  48. package/src/source/tile.ts +1 -1
  49. package/src/source/tile_id.test.ts +10 -12
  50. package/src/source/tile_id.ts +3 -3
  51. package/src/source/vector_tile_source.test.ts +2 -1
  52. package/src/source/vector_tile_source.ts +2 -2
  53. package/src/source/vector_tile_worker_source.test.ts +306 -0
  54. package/src/style/load_sprite.ts +2 -1
  55. package/src/style/properties.ts +1 -1
  56. package/src/style/query_utils.ts +1 -1
  57. package/src/style/style.test.ts +4 -0
  58. package/src/style/style.ts +1 -1
  59. package/src/style/style_layer/circle_style_layer.ts +1 -1
  60. package/src/style/style_layer/custom_style_layer.ts +2 -2
  61. package/src/style/style_layer/fill_extrusion_style_layer.ts +2 -2
  62. package/src/style/style_layer/fill_style_layer.ts +1 -1
  63. package/src/style/style_layer/line_style_layer.ts +1 -1
  64. package/src/style/style_layer/symbol_style_layer.ts +19 -0
  65. package/src/style/style_layer/symbol_style_layer_properties.ts +6 -0
  66. package/src/style/style_layer.ts +1 -1
  67. package/src/style-spec/CHANGELOG.md +6 -0
  68. package/src/style-spec/expression/index.ts +1 -1
  69. package/src/style-spec/feature_filter/feature_filter.test.ts +1 -1
  70. package/src/style-spec/migrate.test.ts +112 -0
  71. package/src/style-spec/package.json +1 -1
  72. package/src/style-spec/reference/v8.json +68 -2
  73. package/src/style-spec/style-spec.ts +0 -3
  74. package/src/style-spec/types.ts +2 -0
  75. package/src/style-spec/validate_spec.test.ts +29 -0
  76. package/src/symbol/anchor.ts +1 -1
  77. package/src/symbol/check_max_angle.test.ts +1 -1
  78. package/src/symbol/check_max_angle.ts +1 -1
  79. package/src/symbol/clip_line.test.ts +1 -1
  80. package/src/symbol/clip_line.ts +1 -1
  81. package/src/symbol/collision_feature.test.ts +1 -1
  82. package/src/symbol/collision_feature.ts +1 -1
  83. package/src/symbol/collision_index.ts +20 -20
  84. package/src/symbol/get_anchors.test.ts +1 -1
  85. package/src/symbol/get_anchors.ts +1 -1
  86. package/src/symbol/grid_index.test.ts +42 -19
  87. package/src/symbol/grid_index.ts +62 -33
  88. package/src/symbol/mergelines.test.ts +1 -1
  89. package/src/symbol/path_interpolator.test.ts +1 -1
  90. package/src/symbol/path_interpolator.ts +1 -1
  91. package/src/symbol/placement.ts +83 -54
  92. package/src/symbol/projection.ts +1 -1
  93. package/src/symbol/quads.ts +1 -1
  94. package/src/symbol/symbol_layout.ts +1 -1
  95. package/src/symbol/symbol_style_layer.test.ts +48 -1
  96. package/src/ui/camera.test.ts +0 -8
  97. package/src/ui/camera.ts +13 -3
  98. package/src/ui/control/navigation_control.ts +1 -1
  99. package/src/ui/events.ts +1 -1
  100. package/src/ui/handler/box_zoom.ts +1 -1
  101. package/src/ui/handler/click_zoom.ts +1 -1
  102. package/src/ui/handler/handler_util.ts +1 -1
  103. package/src/ui/handler/map_event.ts +1 -1
  104. package/src/ui/handler/mouse.ts +1 -1
  105. package/src/ui/handler/scroll_zoom.ts +1 -1
  106. package/src/ui/handler/tap_drag_zoom.ts +1 -1
  107. package/src/ui/handler/tap_recognizer.ts +1 -1
  108. package/src/ui/handler/tap_zoom.ts +1 -1
  109. package/src/ui/handler/touch_pan.ts +1 -1
  110. package/src/ui/handler/touch_zoom_rotate.ts +1 -1
  111. package/src/ui/handler_inertia.ts +1 -1
  112. package/src/ui/handler_manager.ts +1 -1
  113. package/src/ui/map.test.ts +61 -0
  114. package/src/ui/map.ts +35 -10
  115. package/src/ui/marker.test.ts +1 -1
  116. package/src/ui/marker.ts +2 -1
  117. package/src/ui/popup.test.ts +1 -1
  118. package/src/ui/popup.ts +2 -2
  119. package/src/util/ajax.test.ts +206 -0
  120. package/src/util/classify_rings.test.ts +1 -1
  121. package/src/util/classify_rings.ts +1 -1
  122. package/src/util/dom.ts +1 -1
  123. package/src/util/find_pole_of_inaccessibility.test.ts +1 -1
  124. package/src/util/find_pole_of_inaccessibility.ts +1 -1
  125. package/src/util/intersection_tests.ts +1 -1
  126. package/src/util/smart_wrap.ts +1 -1
  127. package/src/util/test/util.ts +14 -0
  128. package/src/util/util.test.ts +1 -1
  129. package/src/util/util.ts +1 -1
  130. package/CHANGELOG.md +0 -2585
  131. package/src/types/packages-types/vector-tile/index.d.ts +0 -27
  132. package/src/util/point.ts +0 -349
@@ -1,4 +1,5 @@
1
1
  import CollisionIndex from './collision_index';
2
+ import type {FeatureKey} from './collision_index';
2
3
  import EXTENT from '../data/extent';
3
4
  import * as symbolSize from './symbol_size';
4
5
  import * as projection from './projection';
@@ -7,11 +8,12 @@ import {getAnchorAlignment, WritingMode} from './shaping';
7
8
  import {mat4} from 'gl-matrix';
8
9
  import assert from 'assert';
9
10
  import pixelsToTileUnits from '../source/pixels_to_tile_units';
10
- import Point from '../util/point';
11
+ import Point from '@mapbox/point-geometry';
11
12
  import type Transform from '../geo/transform';
12
13
  import type StyleLayer from '../style/style_layer';
13
14
  import {PossiblyEvaluated} from '../style/properties';
14
15
  import type {SymbolLayoutProps, SymbolLayoutPropsPossiblyEvaluated} from '../style/style_layer/symbol_style_layer_properties';
16
+ import {getOverlapMode, OverlapMode} from '../style/style_layer/symbol_style_layer';
15
17
 
16
18
  import type Tile from '../source/tile';
17
19
  import SymbolBucket, {CollisionArrays, SingleCollisionBox} from '../data/bucket/symbol_bucket';
@@ -99,7 +101,7 @@ export class RetainedQueryData {
99
101
 
100
102
  type CollisionGroup = {
101
103
  ID: number;
102
- predicate?: any;
104
+ predicate?: (key: FeatureKey) => boolean;
103
105
  };
104
106
 
105
107
  class CollisionGroups {
@@ -181,20 +183,20 @@ export type VariableOffset = {
181
183
  };
182
184
 
183
185
  type TileLayerParameters = {
184
- bucket: SymbolBucket;
185
- layout: PossiblyEvaluated<SymbolLayoutProps, SymbolLayoutPropsPossiblyEvaluated>;
186
- posMatrix: mat4;
187
- textLabelPlaneMatrix: mat4;
188
- labelToScreenMatrix: mat4;
189
- scale: number;
190
- textPixelRatio: number;
191
- holdingForFade: boolean;
192
- collisionBoxArray: CollisionBoxArray;
193
- partiallyEvaluatedTextSize: {
194
- uSize: number;
195
- uSizeT: number;
196
- };
197
- collisionGroup: CollisionGroup;
186
+ bucket: SymbolBucket;
187
+ layout: PossiblyEvaluated<SymbolLayoutProps, SymbolLayoutPropsPossiblyEvaluated>;
188
+ posMatrix: mat4;
189
+ textLabelPlaneMatrix: mat4;
190
+ labelToScreenMatrix: mat4;
191
+ scale: number;
192
+ textPixelRatio: number;
193
+ holdingForFade: boolean;
194
+ collisionBoxArray: CollisionBoxArray;
195
+ partiallyEvaluatedTextSize: {
196
+ uSize: number;
197
+ uSizeT: number;
198
+ };
199
+ collisionGroup: CollisionGroup;
198
200
  };
199
201
 
200
202
  export type BucketPart = {
@@ -344,7 +346,7 @@ export class Placement {
344
346
  textPixelRatio: number,
345
347
  posMatrix: mat4,
346
348
  collisionGroup: CollisionGroup,
347
- textAllowOverlap: boolean,
349
+ textOverlapMode: OverlapMode,
348
350
  symbolInstance: SymbolInstance,
349
351
  bucket: SymbolBucket,
350
352
  orientation: number,
@@ -364,14 +366,14 @@ export class Placement {
364
366
  shiftVariableCollisionBox(
365
367
  textBox, shift.x, shift.y,
366
368
  rotateWithMap, pitchWithMap, this.transform.angle),
367
- textAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
369
+ textOverlapMode, textPixelRatio, posMatrix, collisionGroup.predicate);
368
370
 
369
371
  if (iconBox) {
370
372
  const placedIconBoxes = this.collisionIndex.placeCollisionBox(
371
373
  shiftVariableCollisionBox(
372
374
  iconBox, shift.x, shift.y,
373
375
  rotateWithMap, pitchWithMap, this.transform.angle),
374
- textAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
376
+ textOverlapMode, textPixelRatio, posMatrix, collisionGroup.predicate);
375
377
  if (placedIconBoxes.box.length === 0) return;
376
378
  }
377
379
 
@@ -424,8 +426,10 @@ export class Placement {
424
426
 
425
427
  const textOptional = layout.get('text-optional');
426
428
  const iconOptional = layout.get('icon-optional');
427
- const textAllowOverlap = layout.get('text-allow-overlap');
428
- const iconAllowOverlap = layout.get('icon-allow-overlap');
429
+ const textOverlapMode = getOverlapMode(layout, 'text-overlap', 'text-allow-overlap');
430
+ const textAlwaysOverlap = textOverlapMode === 'always';
431
+ const iconOverlapMode = getOverlapMode(layout, 'icon-overlap', 'icon-allow-overlap');
432
+ const iconAlwaysOverlap = iconOverlapMode === 'always';
429
433
  const rotateWithMap = layout.get('text-rotation-alignment') === 'map';
430
434
  const pitchWithMap = layout.get('text-pitch-alignment') === 'map';
431
435
  const hasIconTextFit = layout.get('icon-text-fit') !== 'none';
@@ -445,8 +449,8 @@ export class Placement {
445
449
  // This is the reverse of our normal policy of "fade in on pan", but should look like any other
446
450
  // collision and hopefully not be too noticeable.
447
451
  // See https://github.com/mapbox/mapbox-gl-js/issues/7172
448
- const alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || iconOptional);
449
- const alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || textOptional);
452
+ const alwaysShowText = textAlwaysOverlap && (iconAlwaysOverlap || !bucket.hasIconData() || iconOptional);
453
+ const alwaysShowIcon = iconAlwaysOverlap && (textAlwaysOverlap || !bucket.hasTextData() || textOptional);
450
454
 
451
455
  if (!bucket.collisionArrays && collisionBoxArray) {
452
456
  bucket.deserializeCollisionBoxes(collisionBoxArray);
@@ -519,8 +523,12 @@ export class Placement {
519
523
 
520
524
  if (!layout.get('text-variable-anchor')) {
521
525
  const placeBox = (collisionTextBox, orientation) => {
522
- const placedFeature = this.collisionIndex.placeCollisionBox(collisionTextBox, textAllowOverlap,
523
- textPixelRatio, posMatrix, collisionGroup.predicate);
526
+ const placedFeature = this.collisionIndex.placeCollisionBox(
527
+ collisionTextBox,
528
+ textOverlapMode,
529
+ textPixelRatio,
530
+ posMatrix,
531
+ collisionGroup.predicate);
524
532
  if (placedFeature && placedFeature.box && placedFeature.box.length) {
525
533
  this.markUsedOrientation(bucket, orientation, symbolInstance);
526
534
  this.placedOrientations[symbolInstance.crossTileID] = orientation;
@@ -562,20 +570,20 @@ export class Placement {
562
570
  const height = collisionTextBox.y2 - collisionTextBox.y1;
563
571
  const textBoxScale = symbolInstance.textBoxScale;
564
572
 
565
- const variableIconBox = hasIconTextFit && !iconAllowOverlap ? collisionIconBox : null;
573
+ const variableIconBox = hasIconTextFit && (iconOverlapMode === 'never') ? collisionIconBox : null;
566
574
 
567
575
  let placedBox: {
568
576
  box: Array<number>;
569
577
  offscreen: boolean;
570
578
  } = {box: [], offscreen: false};
571
- const placementAttempts = textAllowOverlap ? anchors.length * 2 : anchors.length;
579
+ const placementAttempts = (textOverlapMode !== 'never') ? anchors.length * 2 : anchors.length;
572
580
  for (let i = 0; i < placementAttempts; ++i) {
573
581
  const anchor = anchors[i % anchors.length];
574
- const allowOverlap = (i >= anchors.length);
582
+ const overlapMode = (i >= anchors.length) ? textOverlapMode : 'never';
575
583
  const result = this.attemptAnchorPlacement(
576
584
  anchor, collisionTextBox, width, height,
577
585
  textBoxScale, rotateWithMap, pitchWithMap, textPixelRatio, posMatrix,
578
- collisionGroup, allowOverlap, symbolInstance, bucket, orientation, variableIconBox);
586
+ collisionGroup, overlapMode, symbolInstance, bucket, orientation, variableIconBox);
579
587
 
580
588
  if (result) {
581
589
  placedBox = result.placedGlyphBoxes;
@@ -637,26 +645,27 @@ export class Placement {
637
645
  const textPixelPadding = layout.get('text-padding');
638
646
  const circlePixelDiameter = symbolInstance.collisionCircleDiameter;
639
647
 
640
- placedGlyphCircles = this.collisionIndex.placeCollisionCircles(textAllowOverlap,
641
- placedSymbol,
642
- bucket.lineVertexArray,
643
- bucket.glyphOffsetArray,
644
- fontSize,
645
- posMatrix,
646
- textLabelPlaneMatrix,
647
- labelToScreenMatrix,
648
- showCollisionBoxes,
649
- pitchWithMap,
650
- collisionGroup.predicate,
651
- circlePixelDiameter,
652
- textPixelPadding);
648
+ placedGlyphCircles = this.collisionIndex.placeCollisionCircles(
649
+ textOverlapMode,
650
+ placedSymbol,
651
+ bucket.lineVertexArray,
652
+ bucket.glyphOffsetArray,
653
+ fontSize,
654
+ posMatrix,
655
+ textLabelPlaneMatrix,
656
+ labelToScreenMatrix,
657
+ showCollisionBoxes,
658
+ pitchWithMap,
659
+ collisionGroup.predicate,
660
+ circlePixelDiameter,
661
+ textPixelPadding);
653
662
 
654
663
  assert(!placedGlyphCircles.circles.length || (!placedGlyphCircles.collisionDetected || showCollisionBoxes));
655
- // If text-allow-overlap is set, force "placedCircles" to true
664
+ // If text-overlap is set to 'always', force "placedCircles" to true
656
665
  // In theory there should always be at least one circle placed
657
666
  // in this case, but for now quirks in text-anchor
658
667
  // and text-offset may prevent that from being true.
659
- placeText = textAllowOverlap || (placedGlyphCircles.circles.length > 0 && !placedGlyphCircles.collisionDetected);
668
+ placeText = textAlwaysOverlap || (placedGlyphCircles.circles.length > 0 && !placedGlyphCircles.collisionDetected);
660
669
  offscreen = offscreen && placedGlyphCircles.offscreen;
661
670
  }
662
671
 
@@ -673,7 +682,7 @@ export class Placement {
673
682
  rotateWithMap, pitchWithMap, this.transform.angle) :
674
683
  iconBox;
675
684
  return this.collisionIndex.placeCollisionBox(shiftedIconBox,
676
- iconAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
685
+ iconOverlapMode, textPixelRatio, posMatrix, collisionGroup.predicate);
677
686
  };
678
687
 
679
688
  if (placedVerticalText && placedVerticalText.box && placedVerticalText.box.length && collisionArrays.verticalIconBox) {
@@ -701,22 +710,42 @@ export class Placement {
701
710
 
702
711
  if (placeText && placedGlyphBoxes && placedGlyphBoxes.box) {
703
712
  if (placedVerticalText && placedVerticalText.box && verticalTextFeatureIndex) {
704
- this.collisionIndex.insertCollisionBox(placedGlyphBoxes.box, layout.get('text-ignore-placement'),
705
- bucket.bucketInstanceId, verticalTextFeatureIndex, collisionGroup.ID);
713
+ this.collisionIndex.insertCollisionBox(
714
+ placedGlyphBoxes.box,
715
+ textOverlapMode,
716
+ layout.get('text-ignore-placement'),
717
+ bucket.bucketInstanceId,
718
+ verticalTextFeatureIndex,
719
+ collisionGroup.ID);
706
720
  } else {
707
- this.collisionIndex.insertCollisionBox(placedGlyphBoxes.box, layout.get('text-ignore-placement'),
708
- bucket.bucketInstanceId, textFeatureIndex, collisionGroup.ID);
721
+ this.collisionIndex.insertCollisionBox(
722
+ placedGlyphBoxes.box,
723
+ textOverlapMode,
724
+ layout.get('text-ignore-placement'),
725
+ bucket.bucketInstanceId,
726
+ textFeatureIndex,
727
+ collisionGroup.ID);
709
728
  }
710
729
 
711
730
  }
712
731
  if (placeIcon && placedIconBoxes) {
713
- this.collisionIndex.insertCollisionBox(placedIconBoxes.box, layout.get('icon-ignore-placement'),
714
- bucket.bucketInstanceId, iconFeatureIndex, collisionGroup.ID);
732
+ this.collisionIndex.insertCollisionBox(
733
+ placedIconBoxes.box,
734
+ iconOverlapMode,
735
+ layout.get('icon-ignore-placement'),
736
+ bucket.bucketInstanceId,
737
+ iconFeatureIndex,
738
+ collisionGroup.ID);
715
739
  }
716
740
  if (placedGlyphCircles) {
717
741
  if (placeText) {
718
- this.collisionIndex.insertCollisionCircles(placedGlyphCircles.circles, layout.get('text-ignore-placement'),
719
- bucket.bucketInstanceId, textFeatureIndex, collisionGroup.ID);
742
+ this.collisionIndex.insertCollisionCircles(
743
+ placedGlyphCircles.circles,
744
+ textOverlapMode,
745
+ layout.get('text-ignore-placement'),
746
+ bucket.bucketInstanceId,
747
+ textFeatureIndex,
748
+ collisionGroup.ID);
720
749
  }
721
750
 
722
751
  if (showCollisionBoxes) {
@@ -887,7 +916,7 @@ export class Placement {
887
916
  updateLayerOpacities(styleLayer: StyleLayer, tiles: Array<Tile>) {
888
917
  const seenCrossTileIDs = {};
889
918
  for (const tile of tiles) {
890
- const symbolBucket = (tile.getBucket(styleLayer) as SymbolBucket);
919
+ const symbolBucket = tile.getBucket(styleLayer) as SymbolBucket;
891
920
  if (symbolBucket && tile.latestFeatureIndex && styleLayer.id === symbolBucket.layerIds[0]) {
892
921
  this.updateBucketOpacities(symbolBucket, seenCrossTileIDs, tile.collisionBoxArray);
893
922
  }
@@ -1,4 +1,4 @@
1
- import Point from '../util/point';
1
+ import Point from '@mapbox/point-geometry';
2
2
 
3
3
  import {mat4, vec4} from 'gl-matrix';
4
4
  import * as symbolSize from './symbol_size';
@@ -1,4 +1,4 @@
1
- import Point from '../util/point';
1
+ import Point from '@mapbox/point-geometry';
2
2
 
3
3
  import {GLYPH_PBF_BORDER} from '../style/parse_glyph_pbf';
4
4
 
@@ -28,7 +28,7 @@ import type {ImagePosition} from '../render/image_atlas';
28
28
  import type {GlyphPosition} from '../render/glyph_atlas';
29
29
  import type {PossiblyEvaluatedPropertyValue} from '../style/properties';
30
30
 
31
- import Point from '../util/point';
31
+ import Point from '@mapbox/point-geometry';
32
32
  import murmur3 from 'murmurhash-js';
33
33
 
34
34
  // The symbol layout process needs `text-size` evaluated at up to five different zoom levels, and
@@ -1,4 +1,4 @@
1
- import SymbolStyleLayer from '../style/style_layer/symbol_style_layer';
1
+ import SymbolStyleLayer, {getOverlapMode} from '../style/style_layer/symbol_style_layer';
2
2
  import FormatSectionOverride from '../style/format_section_override';
3
3
  import properties, {SymbolPaintPropsPossiblyEvaluated} from '../style/style_layer/symbol_style_layer_properties';
4
4
  import ZoomHistory from '../style/zoom_history';
@@ -101,3 +101,50 @@ describe('hasPaintOverrides', () => {
101
101
  });
102
102
 
103
103
  });
104
+
105
+ describe('getOverlapMode', () => {
106
+ test('defaults - no props set', () => {
107
+ const props = {};
108
+ const layer = createSymbolLayer(props);
109
+
110
+ expect(getOverlapMode(layer.layout, 'icon-overlap', 'icon-allow-overlap')).toBe('never');
111
+ expect(getOverlapMode(layer.layout, 'text-overlap', 'text-allow-overlap')).toBe('never');
112
+ });
113
+
114
+ test('-allow-overlap set', () => {
115
+ const props = {layout: {'icon-allow-overlap': false, 'text-allow-overlap': true}};
116
+ const layer = createSymbolLayer(props);
117
+
118
+ expect(getOverlapMode(layer.layout, 'icon-overlap', 'icon-allow-overlap')).toBe('never');
119
+ expect(getOverlapMode(layer.layout, 'text-overlap', 'text-allow-overlap')).toBe('always');
120
+ });
121
+
122
+ test('-overlap set', () => {
123
+ let props = {layout: {'icon-overlap': 'never', 'text-overlap': 'always'}};
124
+ let layer = createSymbolLayer(props);
125
+
126
+ expect(getOverlapMode(layer.layout, 'icon-overlap', 'icon-allow-overlap')).toBe('never');
127
+ expect(getOverlapMode(layer.layout, 'text-overlap', 'text-allow-overlap')).toBe('always');
128
+
129
+ props = {layout: {'icon-overlap': 'always', 'text-overlap': 'cooperative'}};
130
+ layer = createSymbolLayer(props);
131
+
132
+ expect(getOverlapMode(layer.layout, 'icon-overlap', 'icon-allow-overlap')).toBe('always');
133
+ expect(getOverlapMode(layer.layout, 'text-overlap', 'text-allow-overlap')).toBe('cooperative');
134
+ });
135
+
136
+ test('-overlap beats -allow-overlap', () => {
137
+ const props = {
138
+ layout: {
139
+ 'icon-overlap': 'never',
140
+ 'icon-allow-overlap': true,
141
+ 'text-overlap': 'cooperative',
142
+ 'text-allow-overlap': false
143
+ }
144
+ };
145
+ const layer = createSymbolLayer(props);
146
+
147
+ expect(getOverlapMode(layer.layout, 'icon-overlap', 'icon-allow-overlap')).toBe('never');
148
+ expect(getOverlapMode(layer.layout, 'text-overlap', 'text-allow-overlap')).toBe('cooperative');
149
+ });
150
+ });
@@ -1777,14 +1777,6 @@ describe('#cameraForBounds', () => {
1777
1777
  expect(fixedLngLat(transform.center, 4)).toEqual({lng: -100.5, lat: 44.4717});
1778
1778
  });
1779
1779
 
1780
- test('offset as object', () => {
1781
- const camera = createCamera();
1782
- const bb = [[-133, 16], [-68, 50]];
1783
- const transform = camera.cameraForBounds(bb, {offset: {x: 0, y: 100}});
1784
-
1785
- expect(fixedLngLat(transform.center, 4)).toEqual({lng: -100.5, lat: 44.4717});
1786
- });
1787
-
1788
1780
  test('offset and padding', () => {
1789
1781
  const camera = createCamera();
1790
1782
  const bb = [[-133, 16], [-68, 50]];
package/src/ui/camera.ts CHANGED
@@ -3,7 +3,7 @@ import {number as interpolate} from '../style-spec/util/interpolate';
3
3
  import browser from '../util/browser';
4
4
  import LngLat from '../geo/lng_lat';
5
5
  import LngLatBounds from '../geo/lng_lat_bounds';
6
- import Point, {PointLike} from '../util/point';
6
+ import Point from '@mapbox/point-geometry';
7
7
  import {Event, Evented} from '../util/evented';
8
8
  import assert from 'assert';
9
9
  import {Debug} from '../util/debug';
@@ -14,6 +14,16 @@ import type {LngLatBoundsLike} from '../geo/lng_lat_bounds';
14
14
  import type {TaskID} from '../util/task_queue';
15
15
  import type {PaddingOptions} from '../geo/edge_insets';
16
16
 
17
+ /**
18
+ * A [Point](https://github.com/mapbox/point-geometry) or an array of two numbers representing `x` and `y` screen coordinates in pixels.
19
+ *
20
+ * @typedef {(Point | [number, number])} PointLike
21
+ * @example
22
+ * var p1 = new Point(-77, 38); // a PointLike which is a Point
23
+ * var p2 = [-77, 38]; // a PointLike which is an array of two numbers
24
+ */
25
+ export type PointLike = Point | [number, number];
26
+
17
27
  export type RequireAtLeastOne<T> = { [K in keyof T]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<keyof T, K>>>; }[keyof T];
18
28
 
19
29
  /**
@@ -599,7 +609,7 @@ abstract class Camera extends Evented {
599
609
  * @memberof Map#
600
610
  * @param bounds Center these bounds in the viewport and use the highest
601
611
  * zoom level up to and including `Map#getMaxZoom()` that fits them in the viewport.
602
- * @param {Object} [options] Options supports all properties from {@link AnimationOptions} and {@link CameraOptions} in addition to the fields below.
612
+ * @param {FitBoundsOptions} [options] Options supports all properties from {@link AnimationOptions} and {@link CameraOptions} in addition to the fields below.
603
613
  * @param {number | PaddingOptions} [options.padding] The amount of padding in pixels to add to the given bounds.
604
614
  * @param {boolean} [options.linear=false] If `true`, the map transitions using
605
615
  * {@link Map#easeTo}. If `false`, the map transitions using {@link Map#flyTo}. See
@@ -955,7 +965,7 @@ abstract class Camera extends Evented {
955
965
  * unless 'options' includes `essential: true`.
956
966
  *
957
967
  * @memberof Map#
958
- * @param {Object} options Options describing the destination and animation of the transition.
968
+ * @param {FlyToOptions} options Options describing the destination and animation of the transition.
959
969
  * Accepts {@link CameraOptions}, {@link AnimationOptions},
960
970
  * and the following additional options.
961
971
  * @param {number} [options.curve=1.42] The zooming "curve" that will occur along the
@@ -1,4 +1,4 @@
1
- import Point from '../../util/point';
1
+ import Point from '@mapbox/point-geometry';
2
2
 
3
3
  import DOM from '../../util/dom';
4
4
  import {extend, bindAll} from '../../util/util';
package/src/ui/events.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {Event} from '../util/evented';
2
2
 
3
3
  import DOM from '../util/dom';
4
- import Point from '../util/point';
4
+ import Point from '@mapbox/point-geometry';
5
5
  import {extend} from '../util/util';
6
6
 
7
7
  import type Map from './map';
@@ -3,7 +3,7 @@ import DOM from '../../util/dom';
3
3
  import {Event} from '../../util/evented';
4
4
 
5
5
  import type Map from '../map';
6
- import type Point from '../../util/point';
6
+ import type Point from '@mapbox/point-geometry';
7
7
 
8
8
  /**
9
9
  * The `BoxZoomHandler` allows the user to zoom the map to fit within a bounding box.
@@ -1,4 +1,4 @@
1
- import type Point from '../../util/point';
1
+ import type Point from '@mapbox/point-geometry';
2
2
  import type Map from '../map';
3
3
 
4
4
  export default class ClickZoomHandler {
@@ -1,5 +1,5 @@
1
1
  import assert from 'assert';
2
- import Point from '../../util/point';
2
+ import Point from '@mapbox/point-geometry';
3
3
 
4
4
  export function indexTouches(touches: Array<Touch>, points: Array<Point>) {
5
5
  assert(touches.length === points.length);
@@ -1,7 +1,7 @@
1
1
  import {MapMouseEvent, MapTouchEvent, MapWheelEvent} from '../events';
2
2
  import {Handler} from '../handler_manager';
3
3
  import type Map from '../map';
4
- import type Point from '../../util/point';
4
+ import type Point from '@mapbox/point-geometry';
5
5
 
6
6
  export class MapEventHandler implements Handler {
7
7
 
@@ -1,5 +1,5 @@
1
1
  import DOM from '../../util/dom';
2
- import type Point from '../../util/point';
2
+ import type Point from '@mapbox/point-geometry';
3
3
 
4
4
  const LEFT_BUTTON = 0;
5
5
  const RIGHT_BUTTON = 2;
@@ -8,7 +8,7 @@ import LngLat from '../../geo/lng_lat';
8
8
 
9
9
  import type Map from '../map';
10
10
  import type HandlerManager from '../handler_manager';
11
- import type Point from '../../util/point';
11
+ import type Point from '@mapbox/point-geometry';
12
12
 
13
13
  // deltaY value for mouse scroll wheel identification
14
14
  const wheelZoomDelta = 4.000244140625;
@@ -1,5 +1,5 @@
1
1
  import {TapRecognizer, MAX_TAP_INTERVAL} from './tap_recognizer';
2
- import type Point from '../../util/point';
2
+ import type Point from '@mapbox/point-geometry';
3
3
 
4
4
  export default class TapDragZoomHandler {
5
5
 
@@ -1,4 +1,4 @@
1
- import Point from '../../util/point';
1
+ import Point from '@mapbox/point-geometry';
2
2
  import {indexTouches} from './handler_util';
3
3
 
4
4
  function getCentroid(points: Array<Point>) {
@@ -1,5 +1,5 @@
1
1
  import {TapRecognizer} from './tap_recognizer';
2
- import type Point from '../../util/point';
2
+ import type Point from '@mapbox/point-geometry';
3
3
  import type Map from '../map';
4
4
 
5
5
  export default class TapZoomHandler {
@@ -1,4 +1,4 @@
1
- import Point from '../../util/point';
1
+ import Point from '@mapbox/point-geometry';
2
2
  import {indexTouches} from './handler_util';
3
3
 
4
4
  export default class TouchPanHandler {
@@ -1,4 +1,4 @@
1
- import Point from '../../util/point';
1
+ import Point from '@mapbox/point-geometry';
2
2
  import DOM from '../../util/dom';
3
3
 
4
4
  class TwoTouchHandler {
@@ -1,7 +1,7 @@
1
1
  import browser from '../util/browser';
2
2
  import type Map from './map';
3
3
  import {bezier, clamp, extend} from '../util/util';
4
- import Point from '../util/point';
4
+ import Point from '@mapbox/point-geometry';
5
5
  import type {DragPanOptions} from './handler/shim/drag_pan';
6
6
 
7
7
  const defaultInertiaOptions = {
@@ -17,7 +17,7 @@ import DragPanHandler from './handler/shim/drag_pan';
17
17
  import DragRotateHandler from './handler/shim/drag_rotate';
18
18
  import TouchZoomRotateHandler from './handler/shim/touch_zoom_rotate';
19
19
  import {bindAll, extend} from '../util/util';
20
- import Point from '../util/point';
20
+ import Point from '@mapbox/point-geometry';
21
21
  import assert from 'assert';
22
22
 
23
23
  export type InputEvent = MouseEvent | TouchEvent | KeyboardEvent | WheelEvent;
@@ -2048,6 +2048,67 @@ describe('Map', () => {
2048
2048
  });
2049
2049
  });
2050
2050
 
2051
+ describe('setPixelRatio', () => {
2052
+ test('resizes canvas', () => {
2053
+ const container = window.document.createElement('div');
2054
+ Object.defineProperty(container, 'clientWidth', {value: 512});
2055
+ Object.defineProperty(container, 'clientHeight', {value: 512});
2056
+ const map = createMap({container, pixelRatio: 1});
2057
+ expect(map.getCanvas().width).toBe(512);
2058
+ expect(map.getCanvas().height).toBe(512);
2059
+ map.setPixelRatio(2);
2060
+ expect(map.getCanvas().width).toBe(1024);
2061
+ expect(map.getCanvas().height).toBe(1024);
2062
+ });
2063
+
2064
+ test('resizes painter', () => {
2065
+ const container = window.document.createElement('div');
2066
+ Object.defineProperty(container, 'clientWidth', {value: 512});
2067
+ Object.defineProperty(container, 'clientHeight', {value: 512});
2068
+ const map = createMap({container, pixelRatio: 1});
2069
+ expect(map.painter.pixelRatio).toBe(1);
2070
+ expect(map.painter.width).toBe(512);
2071
+ expect(map.painter.height).toBe(512);
2072
+ map.setPixelRatio(2);
2073
+ expect(map.painter.pixelRatio).toBe(2);
2074
+ expect(map.painter.width).toBe(1024);
2075
+ expect(map.painter.height).toBe(1024);
2076
+ });
2077
+ });
2078
+
2079
+ describe('getPixelRatio', () => {
2080
+ test('returns the pixel ratio', () => {
2081
+ const map = createMap({pixelRatio: 1});
2082
+ expect(map.getPixelRatio()).toBe(1);
2083
+ map.setPixelRatio(2);
2084
+ expect(map.getPixelRatio()).toBe(2);
2085
+ });
2086
+ });
2087
+
2088
+ test('pixel ratio defaults to devicePixelRatio', () => {
2089
+ const map = createMap();
2090
+ expect(map.getPixelRatio()).toBe(devicePixelRatio);
2091
+ });
2092
+
2093
+ test('canvas has the expected size', () => {
2094
+ const container = window.document.createElement('div');
2095
+ Object.defineProperty(container, 'clientWidth', {value: 512});
2096
+ Object.defineProperty(container, 'clientHeight', {value: 512});
2097
+ const map = createMap({container, pixelRatio: 2});
2098
+ expect(map.getCanvas().width).toBe(1024);
2099
+ expect(map.getCanvas().height).toBe(1024);
2100
+ });
2101
+
2102
+ test('painter has the expected size and pixel ratio', () => {
2103
+ const container = window.document.createElement('div');
2104
+ Object.defineProperty(container, 'clientWidth', {value: 512});
2105
+ Object.defineProperty(container, 'clientHeight', {value: 512});
2106
+ const map = createMap({container, pixelRatio: 2});
2107
+ expect(map.painter.pixelRatio).toBe(2);
2108
+ expect(map.painter.width).toBe(1024);
2109
+ expect(map.painter.height).toBe(1024);
2110
+ });
2111
+
2051
2112
  });
2052
2113
 
2053
2114
  function createStyle() {