maplibre-gl 3.4.0 → 3.4.1

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.
@@ -1,4 +1,4 @@
1
- /* MapLibre GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v3.4.0/LICENSE.txt */
1
+ /* MapLibre GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v3.4.1/LICENSE.txt */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -465,6 +465,52 @@ UnitBezier.prototype = {
465
465
 
466
466
  var UnitBezier$1 = /*@__PURE__*/getDefaultExportFromCjs(unitbezier);
467
467
 
468
+ let supportsOffscreenCanvas;
469
+ function offscreenCanvasSupported() {
470
+ if (supportsOffscreenCanvas == null) {
471
+ supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' &&
472
+ new OffscreenCanvas(1, 1).getContext('2d') &&
473
+ typeof createImageBitmap === 'function';
474
+ }
475
+ return supportsOffscreenCanvas;
476
+ }
477
+
478
+ let offscreenCanvasDistorted;
479
+ /**
480
+ * Some browsers don't return the exact pixels from a canvas to prevent user fingerprinting (see #3185).
481
+ * This function writes pixels to an OffscreenCanvas and reads them back using getImageData, returning false
482
+ * if they don't match.
483
+ *
484
+ * @returns true if the browser supports OffscreenCanvas but it distorts getImageData results, false otherwise.
485
+ */
486
+ function isOffscreenCanvasDistorted() {
487
+ if (offscreenCanvasDistorted == null) {
488
+ offscreenCanvasDistorted = false;
489
+ if (offscreenCanvasSupported()) {
490
+ const size = 5;
491
+ const canvas = new OffscreenCanvas(size, size);
492
+ const context = canvas.getContext('2d', { willReadFrequently: true });
493
+ if (context) {
494
+ // fill each pixel with an RGB value that should make the byte at index i equal to i (except alpha channel):
495
+ // [0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 10, 255, ...]
496
+ for (let i = 0; i < size * size; i++) {
497
+ const base = i * 4;
498
+ context.fillStyle = `rgb(${base},${base + 1},${base + 2})`;
499
+ context.fillRect(i % size, Math.floor(i / size), 1, 1);
500
+ }
501
+ const data = context.getImageData(0, 0, size, size).data;
502
+ for (let i = 0; i < size * size * 4; i++) {
503
+ if (i % 4 !== 3 && data[i] !== i) {
504
+ offscreenCanvasDistorted = true;
505
+ break;
506
+ }
507
+ }
508
+ }
509
+ }
510
+ }
511
+ return offscreenCanvasDistorted || false;
512
+ }
513
+
468
514
  /**
469
515
  * Given a value `t` that varies between 0 and 1, return
470
516
  * an interpolation function that eases between 0 and 1 in a pleasing
@@ -934,6 +980,139 @@ function arrayBufferToImage(data, callback) {
934
980
  const blob = new Blob([new Uint8Array(data)], { type: 'image/png' });
935
981
  img.src = data.byteLength ? URL.createObjectURL(blob) : transparentPngUrl;
936
982
  }
983
+ /**
984
+ * Computes the webcodecs VideoFrame API options to select a rectangle out of
985
+ * an image and write it into the destination rectangle.
986
+ *
987
+ * Rect (x/y/width/height) select the overlapping rectangle from the source image
988
+ * and layout (offset/stride) write that overlapping rectangle to the correct place
989
+ * in the destination image.
990
+ *
991
+ * Offset is the byte offset in the dest image that the first pixel appears at
992
+ * and stride is the number of bytes to the start of the next row:
993
+ * ┌───────────┐
994
+ * │ dest │
995
+ * │ ┌───┼───────┐
996
+ * │offset→│▓▓▓│ source│
997
+ * │ │▓▓▓│ │
998
+ * │ └───┼───────┘
999
+ * │stride ⇠╌╌╌│
1000
+ * │╌╌╌╌╌╌→ │
1001
+ * └───────────┘
1002
+ *
1003
+ * @param image - source image containing a width and height attribute
1004
+ * @param x - top-left x coordinate to read from the image
1005
+ * @param y - top-left y coordinate to read from the image
1006
+ * @param width - width of the rectangle to read from the image
1007
+ * @param height - height of the rectangle to read from the image
1008
+ * @returns the layout and rect options to pass into VideoFrame API
1009
+ */
1010
+ function computeVideoFrameParameters(image, x, y, width, height) {
1011
+ const destRowOffset = Math.max(-x, 0) * 4;
1012
+ const firstSourceRow = Math.max(0, y);
1013
+ const firstDestRow = firstSourceRow - y;
1014
+ const offset = firstDestRow * width * 4 + destRowOffset;
1015
+ const stride = width * 4;
1016
+ const sourceLeft = Math.max(0, x);
1017
+ const sourceTop = Math.max(0, y);
1018
+ const sourceRight = Math.min(image.width, x + width);
1019
+ const sourceBottom = Math.min(image.height, y + height);
1020
+ return {
1021
+ rect: {
1022
+ x: sourceLeft,
1023
+ y: sourceTop,
1024
+ width: sourceRight - sourceLeft,
1025
+ height: sourceBottom - sourceTop
1026
+ },
1027
+ layout: [{ offset, stride }]
1028
+ };
1029
+ }
1030
+ /**
1031
+ * Reads pixels from an ImageBitmap/Image/canvas using webcodec VideoFrame API.
1032
+ *
1033
+ * @param data - image, imagebitmap, or canvas to parse
1034
+ * @param x - top-left x coordinate to read from the image
1035
+ * @param y - top-left y coordinate to read from the image
1036
+ * @param width - width of the rectangle to read from the image
1037
+ * @param height - height of the rectangle to read from the image
1038
+ * @returns a promise containing the parsed RGBA pixel values of the image, or the error if an error occurred
1039
+ */
1040
+ async function readImageUsingVideoFrame(image, x, y, width, height) {
1041
+ if (typeof VideoFrame === 'undefined') {
1042
+ throw new Error('VideoFrame not supported');
1043
+ }
1044
+ const frame = new VideoFrame(image, { timestamp: 0 });
1045
+ try {
1046
+ const format = frame === null || frame === void 0 ? void 0 : frame.format;
1047
+ if (!format || !(format.startsWith('BGR') || format.startsWith('RGB'))) {
1048
+ throw new Error(`Unrecognized format ${format}`);
1049
+ }
1050
+ const swapBR = format.startsWith('BGR');
1051
+ const result = new Uint8ClampedArray(width * height * 4);
1052
+ await frame.copyTo(result, computeVideoFrameParameters(image, x, y, width, height));
1053
+ if (swapBR) {
1054
+ for (let i = 0; i < result.length; i += 4) {
1055
+ const tmp = result[i];
1056
+ result[i] = result[i + 2];
1057
+ result[i + 2] = tmp;
1058
+ }
1059
+ }
1060
+ return result;
1061
+ }
1062
+ finally {
1063
+ frame.close();
1064
+ }
1065
+ }
1066
+ let offscreenCanvas;
1067
+ let offscreenCanvasContext;
1068
+ /**
1069
+ * Reads pixels from an ImageBitmap/Image/canvas using OffscreenCanvas
1070
+ *
1071
+ * @param data - image, imagebitmap, or canvas to parse
1072
+ * @param x - top-left x coordinate to read from the image
1073
+ * @param y - top-left y coordinate to read from the image
1074
+ * @param width - width of the rectangle to read from the image
1075
+ * @param height - height of the rectangle to read from the image
1076
+ * @returns a promise containing the parsed RGBA pixel values of the image, or the error if an error occurred
1077
+ */
1078
+ function readImageDataUsingOffscreenCanvas(imgBitmap, x, y, width, height) {
1079
+ const origWidth = imgBitmap.width;
1080
+ const origHeight = imgBitmap.height;
1081
+ // Lazily initialize OffscreenCanvas
1082
+ if (!offscreenCanvas || !offscreenCanvasContext) {
1083
+ // Dem tiles are typically 256x256
1084
+ offscreenCanvas = new OffscreenCanvas(origWidth, origHeight);
1085
+ offscreenCanvasContext = offscreenCanvas.getContext('2d', { willReadFrequently: true });
1086
+ }
1087
+ offscreenCanvas.width = origWidth;
1088
+ offscreenCanvas.height = origHeight;
1089
+ offscreenCanvasContext.drawImage(imgBitmap, 0, 0, origWidth, origHeight);
1090
+ const imgData = offscreenCanvasContext.getImageData(x, y, width, height);
1091
+ offscreenCanvasContext.clearRect(0, 0, origWidth, origHeight);
1092
+ return imgData.data;
1093
+ }
1094
+ /**
1095
+ * Reads RGBA pixels from an preferring OffscreenCanvas, but falling back to VideoFrame if supported and
1096
+ * the browser is mangling OffscreenCanvas getImageData results.
1097
+ *
1098
+ * @param data - image, imagebitmap, or canvas to parse
1099
+ * @param x - top-left x coordinate to read from the image
1100
+ * @param y - top-left y coordinate to read from the image
1101
+ * @param width - width of the rectangle to read from the image
1102
+ * @param height - height of the rectangle to read from the image
1103
+ * @returns a promise containing the parsed RGBA pixel values of the image
1104
+ */
1105
+ async function getImageData(image, x, y, width, height) {
1106
+ if (isOffscreenCanvasDistorted()) {
1107
+ try {
1108
+ return await readImageUsingVideoFrame(image, x, y, width, height);
1109
+ }
1110
+ catch (e) {
1111
+ // fall back to OffscreenCanvas
1112
+ }
1113
+ }
1114
+ return readImageDataUsingOffscreenCanvas(image, x, y, width, height);
1115
+ }
937
1116
 
938
1117
  const now = typeof performance !== 'undefined' && performance && performance.now ?
939
1118
  performance.now.bind(performance) :
@@ -29998,10 +30177,11 @@ function getGlyphQuads(anchor, shaping, textOffset, layer, alongLine, feature, i
29998
30177
  verticalizedLabelOffset = builtInOffset;
29999
30178
  builtInOffset = [0, 0];
30000
30179
  }
30180
+ const textureScale = positionedGlyph.metrics.isDoubleResolution ? 2 : 1;
30001
30181
  const x1 = (positionedGlyph.metrics.left - rectBuffer) * positionedGlyph.scale - halfAdvance + builtInOffset[0];
30002
30182
  const y1 = (-positionedGlyph.metrics.top - rectBuffer) * positionedGlyph.scale + builtInOffset[1];
30003
- const x2 = x1 + textureRect.w * positionedGlyph.scale / pixelRatio;
30004
- const y2 = y1 + textureRect.h * positionedGlyph.scale / pixelRatio;
30183
+ const x2 = x1 + textureRect.w / textureScale * positionedGlyph.scale / pixelRatio;
30184
+ const y2 = y1 + textureRect.h / textureScale * positionedGlyph.scale / pixelRatio;
30005
30185
  const tl = new Point$2(x1, y1);
30006
30186
  const tr = new Point$2(x2, y1);
30007
30187
  const bl = new Point$2(x1, y2);
@@ -31403,6 +31583,7 @@ exports.getAnchorAlignment = getAnchorAlignment;
31403
31583
  exports.getAnchorJustification = getAnchorJustification;
31404
31584
  exports.getArrayBuffer = getArrayBuffer;
31405
31585
  exports.getDefaultExportFromCjs = getDefaultExportFromCjs;
31586
+ exports.getImageData = getImageData;
31406
31587
  exports.getJSON = getJSON;
31407
31588
  exports.getOverlapMode = getOverlapMode;
31408
31589
  exports.getProtocolAction = getProtocolAction;
@@ -31414,6 +31595,7 @@ exports.identity = identity$2;
31414
31595
  exports.interpolate = interpolate;
31415
31596
  exports.invert = invert$2;
31416
31597
  exports.isImageBitmap = isImageBitmap;
31598
+ exports.isOffscreenCanvasDistorted = isOffscreenCanvasDistorted;
31417
31599
  exports.isSafari = isSafari;
31418
31600
  exports.isWorker = isWorker;
31419
31601
  exports.keysDifference = keysDifference;
@@ -31428,6 +31610,7 @@ exports.mul$1 = mul$3;
31428
31610
  exports.multiply = multiply$5;
31429
31611
  exports.nextPowerOfTwo = nextPowerOfTwo;
31430
31612
  exports.normalize = normalize$4;
31613
+ exports.offscreenCanvasSupported = offscreenCanvasSupported;
31431
31614
  exports.operations = operations;
31432
31615
  exports.ortho = ortho;
31433
31616
  exports.parseCacheControl = parseCacheControl;
@@ -31440,6 +31623,7 @@ exports.plugin = plugin;
31440
31623
  exports.pointGeometry = pointGeometry;
31441
31624
  exports.polygonIntersectsPolygon = polygonIntersectsPolygon;
31442
31625
  exports.potpack = potpack;
31626
+ exports.readImageUsingVideoFrame = readImageUsingVideoFrame;
31443
31627
  exports.register = register;
31444
31628
  exports.registerForPluginStateChange = registerForPluginStateChange;
31445
31629
  exports.renderColorRamp = renderColorRamp;
@@ -31922,30 +32106,18 @@ class RasterDEMTileWorkerSource {
31922
32106
  constructor() {
31923
32107
  this.loaded = {};
31924
32108
  }
31925
- loadTile(params, callback) {
32109
+ async loadTile(params, callback) {
31926
32110
  const { uid, encoding, rawImageData, redFactor, greenFactor, blueFactor, baseShift } = params;
31927
- // Main thread will transfer ImageBitmap if offscreen decode with OffscreenCanvas is supported, else it will transfer an already decoded image.
31928
- const imagePixels = performance.isImageBitmap(rawImageData) ? this.getImageData(rawImageData) : rawImageData;
32111
+ const width = rawImageData.width + 2;
32112
+ const height = rawImageData.height + 2;
32113
+ const imagePixels = performance.isImageBitmap(rawImageData) ?
32114
+ new performance.RGBAImage({ width, height }, await performance.getImageData(rawImageData, -1, -1, width, height)) :
32115
+ rawImageData;
31929
32116
  const dem = new performance.DEMData(uid, imagePixels, encoding, redFactor, greenFactor, blueFactor, baseShift);
31930
32117
  this.loaded = this.loaded || {};
31931
32118
  this.loaded[uid] = dem;
31932
32119
  callback(null, dem);
31933
32120
  }
31934
- getImageData(imgBitmap) {
31935
- // Lazily initialize OffscreenCanvas
31936
- if (!this.offscreenCanvas || !this.offscreenCanvasContext) {
31937
- // Dem tiles are typically 256x256
31938
- this.offscreenCanvas = new OffscreenCanvas(imgBitmap.width, imgBitmap.height);
31939
- this.offscreenCanvasContext = this.offscreenCanvas.getContext('2d', { willReadFrequently: true });
31940
- }
31941
- this.offscreenCanvas.width = imgBitmap.width;
31942
- this.offscreenCanvas.height = imgBitmap.height;
31943
- this.offscreenCanvasContext.drawImage(imgBitmap, 0, 0, imgBitmap.width, imgBitmap.height);
31944
- // Insert an additional 1px padding around the image to allow backfilling for neighboring data.
31945
- const imgData = this.offscreenCanvasContext.getImageData(-1, -1, imgBitmap.width + 2, imgBitmap.height + 2);
31946
- this.offscreenCanvasContext.clearRect(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height);
31947
- return new performance.RGBAImage({ width: imgData.width, height: imgData.height }, imgData.data);
31948
- }
31949
32121
  removeTile(params) {
31950
32122
  const loaded = this.loaded, uid = params.uid;
31951
32123
  if (loaded && loaded[uid]) {
@@ -34131,7 +34303,7 @@ define(['./shared'], (function (performance) { 'use strict';
34131
34303
 
34132
34304
  var name = "maplibre-gl";
34133
34305
  var description = "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library";
34134
- var version$2 = "3.4.0";
34306
+ var version$2 = "3.4.1";
34135
34307
  var main = "dist/maplibre-gl.js";
34136
34308
  var style = "dist/maplibre-gl.css";
34137
34309
  var license = "BSD-3-Clause";
@@ -34174,7 +34346,7 @@ var devDependencies = {
34174
34346
  "@mapbox/mvt-fixtures": "^3.10.0",
34175
34347
  "@rollup/plugin-commonjs": "^25.0.5",
34176
34348
  "@rollup/plugin-json": "^6.0.1",
34177
- "@rollup/plugin-node-resolve": "^15.2.2",
34349
+ "@rollup/plugin-node-resolve": "^15.2.3",
34178
34350
  "@rollup/plugin-replace": "^5.0.3",
34179
34351
  "@rollup/plugin-strip": "^3.0.3",
34180
34352
  "@rollup/plugin-terser": "^0.4.4",
@@ -34192,12 +34364,12 @@ var devDependencies = {
34192
34364
  "@types/minimist": "^1.2.3",
34193
34365
  "@types/murmurhash-js": "^1.0.4",
34194
34366
  "@types/nise": "^1.4.2",
34195
- "@types/node": "^20.8.2",
34367
+ "@types/node": "^20.8.3",
34196
34368
  "@types/offscreencanvas": "^2019.7.1",
34197
34369
  "@types/pixelmatch": "^5.2.4",
34198
34370
  "@types/pngjs": "^6.0.2",
34199
34371
  "@types/react": "^18.2.25",
34200
- "@types/react-dom": "^18.2.10",
34372
+ "@types/react-dom": "^18.2.11",
34201
34373
  "@types/request": "^2.48.9",
34202
34374
  "@types/shuffle-seed": "^1.1.0",
34203
34375
  "@types/window-or-global": "^1.0.4",
@@ -34209,10 +34381,10 @@ var devDependencies = {
34209
34381
  cssnano: "^6.0.1",
34210
34382
  d3: "^7.8.5",
34211
34383
  "d3-queue": "^3.0.7",
34212
- "devtools-protocol": "^0.0.1205644",
34384
+ "devtools-protocol": "^0.0.1206220",
34213
34385
  diff: "^5.1.0",
34214
34386
  "dts-bundle-generator": "^8.0.1",
34215
- eslint: "^8.50.0",
34387
+ eslint: "^8.51.0",
34216
34388
  "eslint-config-mourner": "^3.0.0",
34217
34389
  "eslint-plugin-html": "^7.1.0",
34218
34390
  "eslint-plugin-import": "^2.28.1",
@@ -34241,10 +34413,10 @@ var devDependencies = {
34241
34413
  "postcss-cli": "^10.1.0",
34242
34414
  "postcss-inline-svg": "^6.0.0",
34243
34415
  "pretty-bytes": "^6.1.1",
34244
- puppeteer: "^21.3.6",
34416
+ puppeteer: "^21.3.8",
34245
34417
  react: "^18.2.0",
34246
34418
  "react-dom": "^18.2.0",
34247
- rollup: "^3.29.4",
34419
+ rollup: "^4.0.2",
34248
34420
  "rollup-plugin-sourcemaps": "^0.6.3",
34249
34421
  rw: "^1.3.3",
34250
34422
  semver: "^7.5.4",
@@ -34256,7 +34428,7 @@ var devDependencies = {
34256
34428
  "ts-jest": "^29.1.1",
34257
34429
  "ts-node": "^10.9.1",
34258
34430
  tslib: "^2.6.2",
34259
- typedoc: "^0.25.1",
34431
+ typedoc: "^0.25.2",
34260
34432
  "typedoc-plugin-markdown": "^3.16.0",
34261
34433
  "typedoc-plugin-missing-exports": "^2.1.0",
34262
34434
  typescript: "^5.2.2"
@@ -35456,6 +35628,9 @@ class GlyphManager {
35456
35628
  if (!this._doesCharSupportLocalGlyph(id)) {
35457
35629
  return;
35458
35630
  }
35631
+ // Client-generated glyphs are rendered at 2x texture scale,
35632
+ // because CJK glyphs are more detailed than others.
35633
+ const textureScale = 2;
35459
35634
  let tinySDF = entry.tinySDF;
35460
35635
  if (!tinySDF) {
35461
35636
  let fontWeight = '400';
@@ -35469,9 +35644,9 @@ class GlyphManager {
35469
35644
  fontWeight = '200';
35470
35645
  }
35471
35646
  tinySDF = entry.tinySDF = new GlyphManager.TinySDF({
35472
- fontSize: 24,
35473
- buffer: 3,
35474
- radius: 8,
35647
+ fontSize: 24 * textureScale,
35648
+ buffer: 3 * textureScale,
35649
+ radius: 8 * textureScale,
35475
35650
  cutoff: 0.25,
35476
35651
  fontFamily,
35477
35652
  fontWeight
@@ -35491,16 +35666,18 @@ class GlyphManager {
35491
35666
  * To approximately align TinySDF glyphs with server-provided glyphs, we use this baseline adjustment
35492
35667
  * factor calibrated to be in between DIN Pro and Arial Unicode (but closer to Arial Unicode)
35493
35668
  */
35494
- const topAdjustment = 27;
35669
+ const topAdjustment = 27.5;
35670
+ const leftAdjustment = 0.5;
35495
35671
  return {
35496
35672
  id,
35497
- bitmap: new performance.AlphaImage({ width: char.width || 30, height: char.height || 30 }, char.data),
35673
+ bitmap: new performance.AlphaImage({ width: char.width || 30 * textureScale, height: char.height || 30 * textureScale }, char.data),
35498
35674
  metrics: {
35499
- width: char.glyphWidth || 24,
35500
- height: char.glyphHeight || 24,
35501
- left: char.glyphLeft || 0,
35502
- top: char.glyphTop - topAdjustment || -8,
35503
- advance: char.glyphAdvance || 24
35675
+ width: char.glyphWidth / textureScale || 24,
35676
+ height: char.glyphHeight / textureScale || 24,
35677
+ left: (char.glyphLeft / textureScale + leftAdjustment) || 0,
35678
+ top: char.glyphTop / textureScale - topAdjustment || -8,
35679
+ advance: char.glyphAdvance / textureScale || 24,
35680
+ isDoubleResolution: true
35504
35681
  }
35505
35682
  };
35506
35683
  }
@@ -36457,16 +36634,6 @@ class RasterTileSource extends performance.Evented {
36457
36634
  }
36458
36635
  }
36459
36636
 
36460
- let supportsOffscreenCanvas;
36461
- function offscreenCanvasSupported() {
36462
- if (supportsOffscreenCanvas == null) {
36463
- supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' &&
36464
- new OffscreenCanvas(1, 1).getContext('2d') &&
36465
- typeof createImageBitmap === 'function';
36466
- }
36467
- return supportsOffscreenCanvas;
36468
- }
36469
-
36470
36637
  /**
36471
36638
  * A source containing raster DEM tiles (See the [Style Specification](https://maplibre.org/maplibre-style-spec/) for detailed documentation of options.)
36472
36639
  * This source can be used to show hillshading and 3D terrain
@@ -36497,9 +36664,9 @@ class RasterDEMTileSource extends RasterTileSource {
36497
36664
  }
36498
36665
  loadTile(tile, callback) {
36499
36666
  const url = tile.tileID.canonical.url(this.tiles, this.map.getPixelRatio(), this.scheme);
36500
- tile.request = ImageRequest.getImage(this.map._requestManager.transformRequest(url, ResourceType.Tile), imageLoaded.bind(this), this.map._refreshExpiredTiles);
36667
+ const request = this.map._requestManager.transformRequest(url, ResourceType.Tile);
36501
36668
  tile.neighboringTiles = this._getNeighboringTiles(tile.tileID);
36502
- function imageLoaded(err, img) {
36669
+ tile.request = ImageRequest.getImage(request, async (err, img, expiry) => {
36503
36670
  delete tile.request;
36504
36671
  if (tile.aborted) {
36505
36672
  tile.state = 'unloaded';
@@ -36511,11 +36678,9 @@ class RasterDEMTileSource extends RasterTileSource {
36511
36678
  }
36512
36679
  else if (img) {
36513
36680
  if (this.map._refreshExpiredTiles)
36514
- tile.setExpiryData(img);
36515
- delete img.cacheControl;
36516
- delete img.expires;
36517
- const transfer = performance.isImageBitmap(img) && offscreenCanvasSupported();
36518
- const rawImageData = transfer ? img : performance.browser.getImageData(img, 1);
36681
+ tile.setExpiryData(expiry);
36682
+ const transfer = performance.isImageBitmap(img) && performance.offscreenCanvasSupported();
36683
+ const rawImageData = transfer ? img : await readImageNow(img);
36519
36684
  const params = {
36520
36685
  uid: tile.uid,
36521
36686
  coord: tile.tileID,
@@ -36529,9 +36694,22 @@ class RasterDEMTileSource extends RasterTileSource {
36529
36694
  };
36530
36695
  if (!tile.actor || tile.state === 'expired') {
36531
36696
  tile.actor = this.dispatcher.getActor();
36532
- tile.actor.send('loadDEMTile', params, done.bind(this));
36697
+ tile.actor.send('loadDEMTile', params, done);
36533
36698
  }
36534
36699
  }
36700
+ }, this.map._refreshExpiredTiles);
36701
+ async function readImageNow(img) {
36702
+ if (typeof VideoFrame !== 'undefined' && performance.isOffscreenCanvasDistorted()) {
36703
+ const width = img.width + 2;
36704
+ const height = img.height + 2;
36705
+ try {
36706
+ return new performance.RGBAImage({ width, height }, await performance.readImageUsingVideoFrame(img, -1, -1, width, height));
36707
+ }
36708
+ catch (e) {
36709
+ // fall-back to browser canvas decoding
36710
+ }
36711
+ }
36712
+ return performance.browser.getImageData(img, 1);
36535
36713
  }
36536
36714
  function done(err, data) {
36537
36715
  if (err) {
@@ -42065,6 +42243,8 @@ class Style extends performance.Evented {
42065
42243
  this[op.command].apply(this, op.args);
42066
42244
  }
42067
42245
  this.stylesheet = nextState;
42246
+ // reset serialization field, to be populated only when needed
42247
+ this._serializedLayers = null;
42068
42248
  return true;
42069
42249
  }
42070
42250
  addImage(id, image) {