azure-maps-control
Version:
Map SDK for Azure Maps
1,151 lines (1,073 loc) • 5.15 MB
JavaScript
/*!
MICROSOFT SOFTWARE LICENSE TERMS
MICROSOFT AZURE MAPS WEB SDK
These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.
1. INSTALLATION AND USE RIGHTS.
a) General. You may install and use any number of copies of the software to develop and test your applications.
b) User Region Parameters. The software will allow you to select from a View list to set the map view within your application for a given customer. By default the View parameter (also referred to as “user region parameter” is set to “Unified”. Countries/Regions that are not on the View list will default to the “Unified” View. It is your responsibility to determine the location of your users, and then set the View parameter correctly for that location. The View parameter must be used in compliance with applicable laws, including those regarding mapping, of the country where maps, images and other data and third party content that You are authorized to access via the software is made available.
c) Third Party Software. The software may include third party applications that Microsoft, not the third party, licenses to you under this agreement. Any included notices for third party applications are for your information only.
d) Microsoft Online Subscription Agreement. Some features of the software provide access to, or rely on, Microsoft Azure Services. The use of those services (but not the software) is governed by the separate terms and privacy policies associated with your Microsoft Azure subscription. The services may not be available in all regions. For more information see https://go.microsoft.com/fwLink/?LinkID=522330&clcid=0x9.
2. DISTRIBUTABLE CODE. The software is comprised of “Distributable Code”. “Distributable Code” is code that you are permitted to distribute in applications you develop if you comply with the terms below and otherwise set forth in these license terms.
a) Distribution Rights.
i. You may copy and distribute the object code form of the software.
i. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications.
b) Distribution Requirements. For any code you distribute, you must:
i. add significant primary functionality to it in your applications;
ii. require distributors and external end users to agree to terms that protect it and Microsoft at least as much as this agreement; and
iii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code.
c) Distribution Restrictions. You may not:
i. use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or
ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it.
3. DATA COLLECTION. The software may collect information about you and your use of the software and send that to Microsoft. Microsoft may use this information to provide services and improve Microsoft’s products and services. Your opt-out rights, if any, are described in the product documentation. Some features in the software may enable collection of data from users of your applications that access or use the software. If you use these features to enable data collection in your applications, you must comply with applicable law, including getting any required user consent, and maintain a prominent privacy policy that accurately informs users about how you use, collect, and share their data. You can learn more about Microsoft’s data collection and use in the product documentation and the Microsoft Privacy Statement at https://go.microsoft.com/fwlink/?LinkId=512132. You agree to comply with all applicable provisions of the Microsoft Privacy Statement.
4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to):
a) work around any technical limitations in the software that only allow you to use it in certain ways;
b) reverse engineer, decompile, or disassemble the software, or attempt to do so, except and only to the extent permitted by licensing terms governing the use of open-source components that may be included with the software;
c) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;
d) use the software in any way that is against the law or to create or propagate malware; or
e) share, publish, distribute, or lend the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone hosted solution for others to use, or transfer the software or this agreement to any third party.
5. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit http://aka.ms/exporting.
6. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind.
7. UPDATES. The software may periodically check for updates, and download and install them for you. You may obtain updates only from Microsoft or authorized sources. Microsoft may need to update your system to provide you with updates. You agree to receive these automatic updates without any additional notice. Updates may not include or support all existing software features, services, or peripheral devices.
8. ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software.
9. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles. If you acquired the software in any other country, its laws apply. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court. If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court.
10. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you:
a) Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights.
b) Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software.
c) Germany and Austria.
i. Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software.
ii. Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law.
Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence.
11. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
12. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES.
This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law.
It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages.
Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French.
Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français.
EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues.
LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
Cette limitation concerne:
• tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et
• les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur.
Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard.
EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas.
*/
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function getAugmentedNamespace(n) {
if (n.__esModule) return n;
var f = n.default;
if (typeof f == "function") {
var a = function a () {
if (this instanceof a) {
return Reflect.construct(f, arguments, this.constructor);
}
return f.apply(this, arguments);
};
a.prototype = f.prototype;
} else a = {};
Object.defineProperty(a, '__esModule', {value: true});
Object.keys(n).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(n, k);
Object.defineProperty(a, k, d.get ? d : {
enumerable: true,
get: function () {
return n[k];
}
});
});
return a;
}
var azuremapsMaplibreGlDev = {exports: {}};
/* Build timestamp: Mon, 22 Apr 2024 08:56:33 GMT */
(function (module, exports) {
/**
* The Azure Maps fork of MapLibre GL JS
* @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v4.1.2/LICENSE.txt
*/
(function (global, factory) {
module.exports = factory() ;
})(commonjsGlobal, (function () {
/* eslint-disable */
var maplibregl = {};
var modules = {};
function define(moduleName, _dependencies, moduleFactory) {
modules[moduleName] = moduleFactory;
// to get the list of modules see generated dist/maplibre-gl-dev.js file (look for `define(` calls)
if (moduleName !== 'index') {
return;
}
// we assume that when an index module is initializing then other modules are loaded already
var workerBundleString = 'var sharedModule = {}; (' + modules.shared + ')(sharedModule); (' + modules.worker + ')(sharedModule);';
var sharedModule = {};
// the order of arguments of a module factory depends on rollup (it decides who is whose dependency)
// to check the correct order, see dist/maplibre-gl-dev.js file (look for `define(` calls)
// we assume that for our 3 chunks it will generate 3 modules and their order is predefined like the following
modules.shared(sharedModule);
modules.index(maplibregl, sharedModule);
if (typeof window !== 'undefined') {
maplibregl.setWorkerUrl(window.URL.createObjectURL(new Blob([workerBundleString], { type: 'text/javascript' })));
}
return maplibregl;
}
define('shared', ['exports'], (function (exports) {
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
function getDefaultExportFromCjs$1 (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var pointGeometry = Point$1;
/**
* A standalone point geometry with useful accessor, comparison, and
* modification methods.
*
* @class Point
* @param {Number} x the x-coordinate. this could be longitude or screen
* pixels, or any other sort of unit.
* @param {Number} y the y-coordinate. this could be latitude or screen
* pixels, or any other sort of unit.
* @example
* var point = new Point(-77, 38);
*/
function Point$1(x, y) {
this.x = x;
this.y = y;
}
Point$1.prototype = {
/**
* Clone this point, returning a new point that can be modified
* without affecting the old one.
* @return {Point} the clone
*/
clone: function() { return new Point$1(this.x, this.y); },
/**
* Add this point's x & y coordinates to another point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
add: function(p) { return this.clone()._add(p); },
/**
* Subtract this point's x & y coordinates to from point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
sub: function(p) { return this.clone()._sub(p); },
/**
* Multiply this point's x & y coordinates by point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
multByPoint: function(p) { return this.clone()._multByPoint(p); },
/**
* Divide this point's x & y coordinates by point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
divByPoint: function(p) { return this.clone()._divByPoint(p); },
/**
* Multiply this point's x & y coordinates by a factor,
* yielding a new point.
* @param {Point} k factor
* @return {Point} output point
*/
mult: function(k) { return this.clone()._mult(k); },
/**
* Divide this point's x & y coordinates by a factor,
* yielding a new point.
* @param {Point} k factor
* @return {Point} output point
*/
div: function(k) { return this.clone()._div(k); },
/**
* Rotate this point around the 0, 0 origin by an angle a,
* given in radians
* @param {Number} a angle to rotate around, in radians
* @return {Point} output point
*/
rotate: function(a) { return this.clone()._rotate(a); },
/**
* Rotate this point around p point by an angle a,
* given in radians
* @param {Number} a angle to rotate around, in radians
* @param {Point} p Point to rotate around
* @return {Point} output point
*/
rotateAround: function(a,p) { return this.clone()._rotateAround(a,p); },
/**
* Multiply this point by a 4x1 transformation matrix
* @param {Array<Number>} m transformation matrix
* @return {Point} output point
*/
matMult: function(m) { return this.clone()._matMult(m); },
/**
* Calculate this point but as a unit vector from 0, 0, meaning
* that the distance from the resulting point to the 0, 0
* coordinate will be equal to 1 and the angle from the resulting
* point to the 0, 0 coordinate will be the same as before.
* @return {Point} unit vector point
*/
unit: function() { return this.clone()._unit(); },
/**
* Compute a perpendicular point, where the new y coordinate
* is the old x coordinate and the new x coordinate is the old y
* coordinate multiplied by -1
* @return {Point} perpendicular point
*/
perp: function() { return this.clone()._perp(); },
/**
* Return a version of this point with the x & y coordinates
* rounded to integers.
* @return {Point} rounded point
*/
round: function() { return this.clone()._round(); },
/**
* Return the magitude of this point: this is the Euclidean
* distance from the 0, 0 coordinate to this point's x and y
* coordinates.
* @return {Number} magnitude
*/
mag: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
/**
* Judge whether this point is equal to another point, returning
* true or false.
* @param {Point} other the other point
* @return {boolean} whether the points are equal
*/
equals: function(other) {
return this.x === other.x &&
this.y === other.y;
},
/**
* Calculate the distance from this point to another point
* @param {Point} p the other point
* @return {Number} distance
*/
dist: function(p) {
return Math.sqrt(this.distSqr(p));
},
/**
* Calculate the distance from this point to another point,
* without the square root step. Useful if you're comparing
* relative distances.
* @param {Point} p the other point
* @return {Number} distance
*/
distSqr: function(p) {
var dx = p.x - this.x,
dy = p.y - this.y;
return dx * dx + dy * dy;
},
/**
* Get the angle from the 0, 0 coordinate to this point, in radians
* coordinates.
* @return {Number} angle
*/
angle: function() {
return Math.atan2(this.y, this.x);
},
/**
* Get the angle from this point to another point, in radians
* @param {Point} b the other point
* @return {Number} angle
*/
angleTo: function(b) {
return Math.atan2(this.y - b.y, this.x - b.x);
},
/**
* Get the angle between this point and another point, in radians
* @param {Point} b the other point
* @return {Number} angle
*/
angleWith: function(b) {
return this.angleWithSep(b.x, b.y);
},
/*
* Find the angle of the two vectors, solving the formula for
* the cross product a x b = |a||b|sin(θ) for θ.
* @param {Number} x the x-coordinate
* @param {Number} y the y-coordinate
* @return {Number} the angle in radians
*/
angleWithSep: function(x, y) {
return Math.atan2(
this.x * y - this.y * x,
this.x * x + this.y * y);
},
_matMult: function(m) {
var x = m[0] * this.x + m[1] * this.y,
y = m[2] * this.x + m[3] * this.y;
this.x = x;
this.y = y;
return this;
},
_add: function(p) {
this.x += p.x;
this.y += p.y;
return this;
},
_sub: function(p) {
this.x -= p.x;
this.y -= p.y;
return this;
},
_mult: function(k) {
this.x *= k;
this.y *= k;
return this;
},
_div: function(k) {
this.x /= k;
this.y /= k;
return this;
},
_multByPoint: function(p) {
this.x *= p.x;
this.y *= p.y;
return this;
},
_divByPoint: function(p) {
this.x /= p.x;
this.y /= p.y;
return this;
},
_unit: function() {
this._div(this.mag());
return this;
},
_perp: function() {
var y = this.y;
this.y = this.x;
this.x = -y;
return this;
},
_rotate: function(angle) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = cos * this.x - sin * this.y,
y = sin * this.x + cos * this.y;
this.x = x;
this.y = y;
return this;
},
_rotateAround: function(angle, p) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
this.x = x;
this.y = y;
return this;
},
_round: function() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return this;
}
};
/**
* Construct a point from an array if necessary, otherwise if the input
* is already a Point, or an unknown type, return it unchanged
* @param {Array<Number>|Point|*} a any kind of input value
* @return {Point} constructed point, or passed-through value.
* @example
* // this
* var point = Point.convert([0, 1]);
* // is equivalent to
* var point = new Point(0, 1);
*/
Point$1.convert = function (a) {
if (a instanceof Point$1) {
return a;
}
if (Array.isArray(a)) {
return new Point$1(a[0], a[1]);
}
return a;
};
var Point$2 = /*@__PURE__*/getDefaultExportFromCjs$1(pointGeometry);
var unitbezier$1 = UnitBezier$2;
function UnitBezier$2(p1x, p1y, p2x, p2y) {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx - this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
this.p1x = p1x;
this.p1y = p1y;
this.p2x = p2x;
this.p2y = p2y;
}
UnitBezier$2.prototype = {
sampleCurveX: function (t) {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((this.ax * t + this.bx) * t + this.cx) * t;
},
sampleCurveY: function (t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
},
sampleCurveDerivativeX: function (t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
},
solveCurveX: function (x, epsilon) {
if (epsilon === undefined) epsilon = 1e-6;
if (x < 0.0) return 0.0;
if (x > 1.0) return 1.0;
var t = x;
// First try a few iterations of Newton's method - normally very fast.
for (var i = 0; i < 8; i++) {
var x2 = this.sampleCurveX(t) - x;
if (Math.abs(x2) < epsilon) return t;
var d2 = this.sampleCurveDerivativeX(t);
if (Math.abs(d2) < 1e-6) break;
t = t - x2 / d2;
}
// Fall back to the bisection method for reliability.
var t0 = 0.0;
var t1 = 1.0;
t = x;
for (i = 0; i < 20; i++) {
x2 = this.sampleCurveX(t);
if (Math.abs(x2 - x) < epsilon) break;
if (x > x2) {
t0 = t;
} else {
t1 = t;
}
t = (t1 - t0) * 0.5 + t0;
}
return t;
},
solve: function (x, epsilon) {
return this.sampleCurveY(this.solveCurveX(x, epsilon));
}
};
var UnitBezier$3 = /*@__PURE__*/getDefaultExportFromCjs$1(unitbezier$1);
let supportsOffscreenCanvas;
function offscreenCanvasSupported() {
if (supportsOffscreenCanvas == null) {
supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' &&
new OffscreenCanvas(1, 1).getContext('2d') &&
typeof createImageBitmap === 'function';
}
return supportsOffscreenCanvas;
}
let offscreenCanvasDistorted;
/**
* Some browsers don't return the exact pixels from a canvas to prevent user fingerprinting (see #3185).
* This function writes pixels to an OffscreenCanvas and reads them back using getImageData, returning false
* if they don't match.
*
* @returns true if the browser supports OffscreenCanvas but it distorts getImageData results, false otherwise.
*/
function isOffscreenCanvasDistorted() {
if (offscreenCanvasDistorted == null) {
offscreenCanvasDistorted = false;
if (offscreenCanvasSupported()) {
const size = 5;
const canvas = new OffscreenCanvas(size, size);
const context = canvas.getContext('2d', { willReadFrequently: true });
if (context) {
// fill each pixel with an RGB value that should make the byte at index i equal to i (except alpha channel):
// [0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 10, 255, ...]
for (let i = 0; i < size * size; i++) {
const base = i * 4;
context.fillStyle = `rgb(${base},${base + 1},${base + 2})`;
context.fillRect(i % size, Math.floor(i / size), 1, 1);
}
const data = context.getImageData(0, 0, size, size).data;
for (let i = 0; i < size * size * 4; i++) {
if (i % 4 !== 3 && data[i] !== i) {
offscreenCanvasDistorted = true;
break;
}
}
}
}
}
return offscreenCanvasDistorted || false;
}
/**
* Given a value `t` that varies between 0 and 1, return
* an interpolation function that eases between 0 and 1 in a pleasing
* cubic in-out fashion.
*/
function easeCubicInOut(t) {
if (t <= 0)
return 0;
if (t >= 1)
return 1;
const t2 = t * t, t3 = t2 * t;
return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75);
}
/**
* Given given (x, y), (x1, y1) control points for a bezier curve,
* return a function that interpolates along that curve.
*
* @param p1x - control point 1 x coordinate
* @param p1y - control point 1 y coordinate
* @param p2x - control point 2 x coordinate
* @param p2y - control point 2 y coordinate
*/
function bezier$1(p1x, p1y, p2x, p2y) {
const bezier = new UnitBezier$3(p1x, p1y, p2x, p2y);
return function (t) {
return bezier.solve(t);
};
}
/**
* A default bezier-curve powered easing function with
* control points (0.25, 0.1) and (0.25, 1)
*/
const defaultEasing = bezier$1(0.25, 0.1, 0.25, 1);
/**
* constrain n to the given range via min + max
*
* @param n - value
* @param min - the minimum value to be returned
* @param max - the maximum value to be returned
* @returns the clamped value
*/
function clamp$1(n, min, max) {
return Math.min(max, Math.max(min, n));
}
/**
* constrain n to the given range, excluding the minimum, via modular arithmetic
*
* @param n - value
* @param min - the minimum value to be returned, exclusive
* @param max - the maximum value to be returned, inclusive
* @returns constrained number
*/
function wrap(n, min, max) {
const d = max - min;
const w = ((n - min) % d + d) % d + min;
return (w === min) ? max : w;
}
/**
* Compute the difference between the keys in one object and the keys
* in another object.
*
* @returns keys difference
*/
function keysDifference(obj, other) {
const difference = [];
for (const i in obj) {
if (!(i in other)) {
difference.push(i);
}
}
return difference;
}
function extend(dest, ...sources) {
for (const src of sources) {
for (const k in src) {
dest[k] = src[k];
}
}
return dest;
}
/**
* Given an object and a number of properties as strings, return version
* of that object with only those properties.
*
* @param src - the object
* @param properties - an array of property names chosen
* to appear on the resulting object.
* @returns object with limited properties.
* @example
* ```ts
* let foo = { name: 'Charlie', age: 10 };
* let justName = pick(foo, ['name']); // justName = { name: 'Charlie' }
* ```
*/
function pick(src, properties) {
const result = {};
for (let i = 0; i < properties.length; i++) {
const k = properties[i];
if (k in src) {
result[k] = src[k];
}
}
return result;
}
let id = 1;
/**
* Return a unique numeric id, starting at 1 and incrementing with
* each call.
*
* @returns unique numeric id.
*/
function uniqueId() {
return id++;
}
/**
* Return whether a given value is a power of two
*/
function isPowerOfTwo(value) {
return (Math.log(value) / Math.LN2) % 1 === 0;
}
/**
* Return the next power of two, or the input value if already a power of two
*/
function nextPowerOfTwo(value) {
if (value <= 1)
return 1;
return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
}
/**
* Create an object by mapping all the values of an existing object while
* preserving their keys.
*/
function mapObject(input, iterator, context) {
const output = {};
for (const key in input) {
output[key] = iterator.call(context || this, input[key], key, input);
}
return output;
}
/**
* Create an object by filtering out values of an existing object.
*/
function filterObject(input, iterator, context) {
const output = {};
for (const key in input) {
if (iterator.call(context || this, input[key], key, input)) {
output[key] = input[key];
}
}
return output;
}
/**
* Deeply compares two object literals.
* @param a - first object literal to be compared
* @param b - second object literal to be compared
* @returns true if the two object literals are deeply equal, false otherwise
*/
function deepEqual$1(a, b) {
if (Array.isArray(a)) {
if (!Array.isArray(b) || a.length !== b.length)
return false;
for (let i = 0; i < a.length; i++) {
if (!deepEqual$1(a[i], b[i]))
return false;
}
return true;
}
if (typeof a === 'object' && a !== null && b !== null) {
if (!(typeof b === 'object'))
return false;
const keys = Object.keys(a);
if (keys.length !== Object.keys(b).length)
return false;
for (const key in a) {
if (!deepEqual$1(a[key], b[key]))
return false;
}
return true;
}
return a === b;
}
/**
* Deeply clones two objects.
*/
function clone$9(input) {
if (Array.isArray(input)) {
return input.map(clone$9);
}
else if (typeof input === 'object' && input) {
return mapObject(input, clone$9);
}
else {
return input;
}
}
/**
* Check if two arrays have at least one common element.
*/
function arraysIntersect(a, b) {
for (let l = 0; l < a.length; l++) {
if (b.indexOf(a[l]) >= 0)
return true;
}
return false;
}
/**
* Print a warning message to the console and ensure duplicate warning messages
* are not printed.
*/
const warnOnceHistory = {};
function warnOnce(message) {
if (!warnOnceHistory[message]) {
// console isn't defined in some WebWorkers, see #2558
if (typeof console !== 'undefined')
console.warn(message);
warnOnceHistory[message] = true;
}
}
/**
* Indicates if the provided Points are in a counter clockwise (true) or clockwise (false) order
*
* @returns true for a counter clockwise set of points
*/
// http://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
function isCounterClockwise(a, b, c) {
return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
}
/**
* For two lines a and b in 2d space, defined by any two points along the lines,
* find the intersection point, or return null if the lines are parallel
*
* @param a1 - First point on line a
* @param a2 - Second point on line a
* @param b1 - First point on line b
* @param b2 - Second point on line b
*
* @returns the intersection point of the two lines or null if they are parallel
*/
function findLineIntersection(a1, a2, b1, b2) {
const aDeltaY = a2.y - a1.y;
const aDeltaX = a2.x - a1.x;
const bDeltaY = b2.y - b1.y;
const bDeltaX = b2.x - b1.x;
const denominator = (bDeltaY * aDeltaX) - (bDeltaX * aDeltaY);
if (denominator === 0) {
// Lines are parallel
return null;
}
const originDeltaY = a1.y - b1.y;
const originDeltaX = a1.x - b1.x;
const aInterpolation = (bDeltaX * originDeltaY - bDeltaY * originDeltaX) / denominator;
// Find intersection by projecting out from origin of first segment
return new Point$2(a1.x + (aInterpolation * aDeltaX), a1.y + (aInterpolation * aDeltaY));
}
/**
* Returns the signed area for the polygon ring. Positive areas are exterior rings and
* have a clockwise winding. Negative areas are interior rings and have a counter clockwise
* ordering.
*
* @param ring - Exterior or interior ring
*/
function calculateSignedArea(ring) {
let sum = 0;
for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
p1 = ring[i];
p2 = ring[j];
sum += (p2.x - p1.x) * (p1.y + p2.y);
}
return sum;
}
/**
* Converts spherical coordinates to cartesian coordinates.
*
* @param spherical - Spherical coordinates, in [radial, azimuthal, polar]
* @returns cartesian coordinates in [x, y, z]
*/
function sphericalToCartesian([r, azimuthal, polar]) {
// We abstract "north"/"up" (compass-wise) to be 0° when really this is 90° (π/2):
// correct for that here
azimuthal += 90;
// Convert azimuthal and polar angles to radians
azimuthal *= Math.PI / 180;
polar *= Math.PI / 180;
return {
x: r * Math.cos(azimuthal) * Math.sin(polar),
y: r * Math.sin(azimuthal) * Math.sin(polar),
z: r * Math.cos(polar)
};
}
/**
* Returns true if the when run in the web-worker context.
*
* @returns `true` if the when run in the web-worker context.
*/
function isWorker(self) {
// @ts-ignore
return typeof WorkerGlobalScope !== 'undefined' && typeof self !== 'undefined' && self instanceof WorkerGlobalScope;
}
/**
* Parses data from 'Cache-Control' headers.
*
* @param cacheControl - Value of 'Cache-Control' header
* @returns object containing parsed header info.
*/
function parseCacheControl(cacheControl) {
// Taken from [Wreck](https://github.com/hapijs/wreck)
const re = /(?:^|(?:\s*\,\s*))([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g;
const header = {};
cacheControl.replace(re, ($0, $1, $2, $3) => {
const value = $2 || $3;
header[$1] = value ? value.toLowerCase() : true;
return '';
});
if (header['max-age']) {
const maxAge = parseInt(header['max-age'], 10);
if (isNaN(maxAge))
delete header['max-age'];
else
header['max-age'] = maxAge;
}
return header;
}
let _isSafari = null;
/**
* Returns true when run in WebKit derived browsers.
* This is used as a workaround for a memory leak in Safari caused by using Transferable objects to
* transfer data between WebWorkers and the main thread.
* https://github.com/mapbox/mapbox-gl-js/issues/8771
*
* This should be removed once the underlying Safari issue is fixed.
*
* @param scope - Since this function is used both on the main thread and WebWorker context,
* let the calling scope pass in the global scope object.
* @returns `true` when run in WebKit derived browsers.
*/
function isSafari(scope) {
if (_isSafari == null) {
const userAgent = scope.navigator ? scope.navigator.userAgent : null;
_isSafari = !!scope.safari ||
!!(userAgent && (/\b(iPad|iPhone|iPod)\b/.test(userAgent) || (!!userAgent.match('Safari') && !userAgent.match('Chrome'))));
}
return _isSafari;
}
function isImageBitmap(image) {
return typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap;
}
/**
* Converts an ArrayBuffer to an ImageBitmap.
*
* Used mostly for testing purposes only, because mocking libs don't know how to work with ArrayBuffers, but work
* perfectly fine with ImageBitmaps. Might also be used for environments (other than testing) not supporting
* ArrayBuffers.
*
* @param data - Data to convert
* @returns - A promise resolved when the conversion is finished
*/
const arrayBufferToImageBitmap = (data) => __awaiter(void 0, void 0, void 0, function* () {
if (data.byteLength === 0) {
return createImageBitmap(new ImageData(1, 1));
}
const blob = new Blob([new Uint8Array(data)], { type: 'image/png' });
try {
return createImageBitmap(blob);
}
catch (e) {
throw new Error(`Could not load image because of ${e.message}. Please make sure to use a supported image type such as PNG or JPEG. Note that SVGs are not supported.`);
}
});
const transparentPngUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII=';
/**
* Converts an ArrayBuffer to an HTMLImageElement.
*
* Used mostly for testing purposes only, because mocking libs don't know how to work with ArrayBuffers, but work
* perfectly fine with ImageBitmaps. Might also be used for environments (other than testing) not supporting
* ArrayBuffers.
*
* @param data - Data to convert
* @returns - A promise resolved when the conversion is finished
*/
const arrayBufferToImage = (data) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve(img);
URL.revokeObjectURL(img.src);
// prevent image dataURI memory leak in Safari;
// but don't free the image immediately because it might be uploaded in the next frame
// https://github.com/mapbox/mapbox-gl-js/issues/10226
img.onload = null;
window.requestAnimationFrame(() => { img.src = transparentPngUrl; });
};
img.onerror = () => reject(new Error('Could not load image. Please make sure to use a supported image type such as PNG or JPEG. Note that SVGs are not supported.'));
const blob = new Blob([new Uint8Array(data)], { type: 'image/png' });
img.src = data.byteLength ? URL.createObjectURL(blob) : transparentPngUrl;
});
};
/**
* Computes the webcodecs VideoFrame API options to select a rectangle out of
* an image and write it into the destination rectangle.
*
* Rect (x/y/width/height) select the overlapping rectangle from the source image
* and layout (offset/stride) write that overlapping rectangle to the correct place
* in the destination image.
*
* Offset is the byte offset in the dest image that the first pixel appears at
* and stride is the number of bytes to the start of the next row:
* ┌───────────┐
* │ dest │
* │ ┌───┼───────┐
* │offset→│▓▓▓│ source│
* │ │▓▓▓│ │
* │ └───┼───────┘
* │stride ⇠╌╌╌│
* │╌╌╌╌╌╌→ │
* └───────────┘
*
* @param image - source image containing a width and height attribute
* @param x - top-left x coordinate to read from the image
* @param y - top-left y coordinate to read from the image
* @param width - width of the rectangle to read from the image
* @param height - height of the rectangle to read from the image
* @returns the layout and rect options to pass into VideoFrame API
*/
function computeVideoFrameParameters(image, x, y, width, height) {
const destRowOffset = Math.max(-x, 0) * 4;
const firstSourceRow = Math.max(0, y);
const firstDestRow = firstSourceRow - y;
const offset = firstDestRow * width * 4 + destRowOffset;
const stride = width * 4;
const sourceLeft = Math.max(0, x);
const sourceTop = Math.max(0, y);
const sourceRight = Math.min(image.width, x + width);
const sourceBottom = Math.min(image.height, y + height);
return {
rect: {
x: sourceLeft,
y: sourceTop,
width: sourceRight - sourceLeft,
height: sourceBottom - sourceTop
},
layout: [{ offset, stride }]
};
}
/**
* Reads pixels from an ImageBitmap/Image/canvas using webcodec VideoFrame API.
*
* @param data - image, imagebitmap, or canvas to parse
* @param x - top-left x coordinate to read from the image
* @param y - top-left y coordinate to read from the image
* @param width - width of the rectangle to read from the image
* @param height - height of the rectangle to read from the image
* @returns a promise containing the parsed RGBA pixel values of the image, or the error if an error occurred
*/
function readImageUsingVideoFrame(image, x, y, width, height) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof VideoFrame === 'undefined') {
throw new Error('VideoFrame not supported');
}
const frame = new VideoFrame(image, { timestamp: 0 });
try {
const format = frame === null || frame === void 0 ? void 0 : frame.format;
if (!format || !(format.startsWith('BGR') || format.startsWith('RGB'))) {
throw new Error(`Unrecognized format ${format}`);
}
const swapBR = format.startsWith('BGR');
const result = new Uint8ClampedArray(width * height * 4);
yield frame.copyTo(result, computeVideoFrameParameters(image, x, y, width, height));
if (swapBR) {
for (let i = 0; i < result.length; i += 4) {
const tmp = result[i];
result[i] = result[i + 2];
result[i + 2] = tmp;
}
}
return result;
}
finally {
frame.close();
}
});
}
let offscreenCanvas;
let offscreenCanvasContext;
/**
* Reads pixels from an ImageBitmap/Image/canvas using OffscreenCanvas
*
* @param data - image, imagebitmap, or canvas to parse
* @param x - top-left x coordinate to read from the image
* @param y - top-left y coordinate to read from the image
* @param width - width of the rectangle to read from the image
* @param height - height of the rectangle to read from the image
* @returns a promise containing the parsed RGBA pixel values of the image, or the error if an error occurred
*/
function readImageDataUsingOffscreenCanvas(imgBitmap, x, y, width, height) {
const origWidth = imgBitmap.width;
const origHeight = imgBitmap.height;
// Lazily initialize OffscreenCanvas
if (!offscreenCanvas || !offscreenCanvasContext) {
// Dem tiles are typically 256x256
offscreenCanvas = new OffscreenCanvas(origWidth, origHeight);
offscreenCanvasContext = offscreenCanvas.getContext('2d', { willReadFrequently: true });
}
offscreenCanvas.width = origWidth;
offscreenCanvas.height = origHeight;
offscreenCanvasContext.drawImage(imgBitmap, 0, 0, origWidth, origHeight);
const imgData = offscreenCanvasContext.getImageData(x, y, width, height);
offscreenCanvasContext.clearRect(0, 0, origWidth, origHeight);
return imgData.data;
}
/**
* Reads RGBA pixels from an preferring OffscreenCanvas, but falling back to VideoFrame if supported and
* the browser is mangling OffscreenCanvas getImageData results.
*
* @param data - image, imagebitmap, or canvas to parse
* @param x - top-left x coordinate to read from the image
* @param y - top-left y coordinate to read from the image
* @param width - width of the rectangle to read from the image
* @param height - height of the rectangle to read from the image
* @returns a promise containing the parsed RGBA pixel values of the image
*/
function getImageData(image, x, y, width, height) {
return __awaiter(this, void 0, void 0, function* () {
if (isOffscreenCanvasDistorted()) {
try {
return yield readImageUsingVideoFrame(image, x, y, width, height);
}
catch (e) {
// fall back to OffscreenCanvas
}
}
return readImageDataUsingOffscreenCanvas(image, x, y, width, height);
});
}
/**
* This method is used in order to register an event listener using a lambda function.
* The return value will allow unsubscribing from the event, without the need to store the method reference.
* @param target - The target
* @param message - The message
* @param listener - The listener
* @param options - The options
* @returns a subscription object that can be used to unsubscribe from the event
*/
function subscribe(target, message, listener, options) {
target.addEventListener(message, listener, options);
return {
unsubscribe: () => {
target.removeEventListener(message, listener, options);
}
};
}
/**
* This method converts degrees to radians.
* The return value is the radian value.
* @param degrees - The number of degrees
* @returns radians
*/
function degreesToRadians(degrees) {
return degrees * Math.PI / 180;
}
/**
* An error message to use when an operation is aborted
*/
const ABORT_ERROR = 'AbortError';
/**
* Check if an error i