/* Mapbox GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/mapbox/mapbox-gl-js/blob/v1.13.3/LICENSE.txt */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.mapboxgl = factory());
}(this, (function () { 'use strict';

/* eslint-disable */

var shared, worker, mapboxgl;
// define gets called three times: one for each chunk. we rely on the order
// they're imported to know which is which
function define(_, chunk) {
if (!shared) {
    shared = chunk;
} else if (!worker) {
    worker = chunk;
} else {
    var workerBundleString = 'var sharedChunk = {}; (' + shared + ')(sharedChunk); (' + worker + ')(sharedChunk);'

    var sharedChunk = {};
    shared(sharedChunk);
    mapboxgl = chunk(sharedChunk);
    if (typeof window !== 'undefined') {
        mapboxgl.workerUrl = window.URL.createObjectURL(new Blob([workerBundleString], { type: 'text/javascript' }));
    }
}
}


define(['exports'], function (exports) { 'use strict';

function createCommonjsModule(fn, module) {
	return module = { exports: {} }, fn(module, module.exports), module.exports;
}

var version = "1.13.3";

var unitbezier = UnitBezier;
function UnitBezier(p1x, p1y, p2x, p2y) {
    this.cx = 3 * p1x;
    this.bx = 3 * (p2x - p1x) - this.cx;
    this.ax = 1 - this.cx - this.bx;
    this.cy = 3 * p1y;
    this.by = 3 * (p2y - p1y) - this.cy;
    this.ay = 1 - this.cy - this.by;
    this.p1x = p1x;
    this.p1y = p2y;
    this.p2x = p2x;
    this.p2y = p2y;
}
UnitBezier.prototype.sampleCurveX = function (t) {
    return ((this.ax * t + this.bx) * t + this.cx) * t;
};
UnitBezier.prototype.sampleCurveY = function (t) {
    return ((this.ay * t + this.by) * t + this.cy) * t;
};
UnitBezier.prototype.sampleCurveDerivativeX = function (t) {
    return (3 * this.ax * t + 2 * this.bx) * t + this.cx;
};
UnitBezier.prototype.solveCurveX = function (x, epsilon) {
    if (typeof epsilon === 'undefined') {
        epsilon = 0.000001;
    }
    var t0, t1, t2, x2, i;
    for (t2 = x, i = 0; i < 8; i++) {
        x2 = this.sampleCurveX(t2) - x;
        if (Math.abs(x2) < epsilon) {
            return t2;
        }
        var d2 = this.sampleCurveDerivativeX(t2);
        if (Math.abs(d2) < 0.000001) {
            break;
        }
        t2 = t2 - x2 / d2;
    }
    t0 = 0;
    t1 = 1;
    t2 = x;
    if (t2 < t0) {
        return t0;
    }
    if (t2 > t1) {
        return t1;
    }
    while (t0 < t1) {
        x2 = this.sampleCurveX(t2);
        if (Math.abs(x2 - x) < epsilon) {
            return t2;
        }
        if (x > x2) {
            t0 = t2;
        } else {
            t1 = t2;
        }
        t2 = (t1 - t0) * 0.5 + t0;
    }
    return t2;
};
UnitBezier.prototype.solve = function (x, epsilon) {
    return this.sampleCurveY(this.solveCurveX(x, epsilon));
};

var pointGeometry = Point;
function Point(x, y) {
    this.x = x;
    this.y = y;
}
Point.prototype = {
    clone: function () {
        return new Point(this.x, this.y);
    },
    add: function (p) {
        return this.clone()._add(p);
    },
    sub: function (p) {
        return this.clone()._sub(p);
    },
    multByPoint: function (p) {
        return this.clone()._multByPoint(p);
    },
    divByPoint: function (p) {
        return this.clone()._divByPoint(p);
    },
    mult: function (k) {
        return this.clone()._mult(k);
    },
    div: function (k) {
        return this.clone()._div(k);
    },
    rotate: function (a) {
        return this.clone()._rotate(a);
    },
    rotateAround: function (a, p) {
        return this.clone()._rotateAround(a, p);
    },
    matMult: function (m) {
        return this.clone()._matMult(m);
    },
    unit: function () {
        return this.clone()._unit();
    },
    perp: function () {
        return this.clone()._perp();
    },
    round: function () {
        return this.clone()._round();
    },
    mag: function () {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    },
    equals: function (other) {
        return this.x === other.x && this.y === other.y;
    },
    dist: function (p) {
        return Math.sqrt(this.distSqr(p));
    },
    distSqr: function (p) {
        var dx = p.x - this.x, dy = p.y - this.y;
        return dx * dx + dy * dy;
    },
    angle: function () {
        return Math.atan2(this.y, this.x);
    },
    angleTo: function (b) {
        return Math.atan2(this.y - b.y, this.x - b.x);
    },
    angleWith: function (b) {
        return this.angleWithSep(b.x, b.y);
    },
    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;
    }
};
Point.convert = function (a) {
    if (a instanceof Point) {
        return a;
    }
    if (Array.isArray(a)) {
        return new Point(a[0], a[1]);
    }
    return a;
};

var window$1 = typeof self !== 'undefined' ? self : {};

function deepEqual(a, b) {
    if (Array.isArray(a)) {
        if (!Array.isArray(b) || a.length !== b.length) {
            return false;
        }
        for (var i = 0; i < a.length; i++) {
            if (!deepEqual(a[i], b[i])) {
                return false;
            }
        }
        return true;
    }
    if (typeof a === 'object' && a !== null && b !== null) {
        if (!(typeof b === 'object')) {
            return false;
        }
        var keys = Object.keys(a);
        if (keys.length !== Object.keys(b).length) {
            return false;
        }
        for (var key in a) {
            if (!deepEqual(a[key], b[key])) {
                return false;
            }
        }
        return true;
    }
    return a === b;
}

var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
function easeCubicInOut(t) {
    if (t <= 0) {
        return 0;
    }
    if (t >= 1) {
        return 1;
    }
    var t2 = t * t, t3 = t2 * t;
    return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75);
}
function bezier(p1x, p1y, p2x, p2y) {
    var bezier = new unitbezier(p1x, p1y, p2x, p2y);
    return function (t) {
        return bezier.solve(t);
    };
}
var ease = bezier(0.25, 0.1, 0.25, 1);
function clamp(n, min, max) {
    return Math.min(max, Math.max(min, n));
}
function wrap(n, min, max) {
    var d = max - min;
    var w = ((n - min) % d + d) % d + min;
    return w === min ? max : w;
}
function asyncAll(array, fn, callback) {
    if (!array.length) {
        return callback(null, []);
    }
    var remaining = array.length;
    var results = new Array(array.length);
    var error = null;
    array.forEach(function (item, i) {
        fn(item, function (err, result) {
            if (err) {
                error = err;
            }
            results[i] = result;
            if (--remaining === 0) {
                callback(error, results);
            }
        });
    });
}
function values(obj) {
    var result = [];
    for (var k in obj) {
        result.push(obj[k]);
    }
    return result;
}
function keysDifference(obj, other) {
    var difference = [];
    for (var i in obj) {
        if (!(i in other)) {
            difference.push(i);
        }
    }
    return difference;
}
function extend(dest) {
    var sources = [], len = arguments.length - 1;
    while (len-- > 0)
        sources[len] = arguments[len + 1];
    for (var i = 0, list = sources; i < list.length; i += 1) {
        var src = list[i];
        for (var k in src) {
            dest[k] = src[k];
        }
    }
    return dest;
}
function pick(src, properties) {
    var result = {};
    for (var i = 0; i < properties.length; i++) {
        var k = properties[i];
        if (k in src) {
            result[k] = src[k];
        }
    }
    return result;
}
var id = 1;
function uniqueId() {
    return id++;
}
function uuid() {
    function b(a) {
        return a ? (a ^ Math.random() * 16 >> a / 4).toString(16) : ([10000000] + -[1000] + -4000 + -8000 + -100000000000).replace(/[018]/g, b);
    }
    return b();
}
function nextPowerOfTwo(value) {
    if (value <= 1) {
        return 1;
    }
    return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
}
function validateUuid(str) {
    return str ? /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str) : false;
}
function bindAll(fns, context) {
    fns.forEach(function (fn) {
        if (!context[fn]) {
            return;
        }
        context[fn] = context[fn].bind(context);
    });
}
function endsWith(string, suffix) {
    return string.indexOf(suffix, string.length - suffix.length) !== -1;
}
function mapObject(input, iterator, context) {
    var output = {};
    for (var key in input) {
        output[key] = iterator.call(context || this, input[key], key, input);
    }
    return output;
}
function filterObject(input, iterator, context) {
    var output = {};
    for (var key in input) {
        if (iterator.call(context || this, input[key], key, input)) {
            output[key] = input[key];
        }
    }
    return output;
}
function clone(input) {
    if (Array.isArray(input)) {
        return input.map(clone);
    } else if (typeof input === 'object' && input) {
        return mapObject(input, clone);
    } else {
        return input;
    }
}
function arraysIntersect(a, b) {
    for (var l = 0; l < a.length; l++) {
        if (b.indexOf(a[l]) >= 0) {
            return true;
        }
    }
    return false;
}
var warnOnceHistory = {};
function warnOnce(message) {
    if (!warnOnceHistory[message]) {
        if (typeof console !== 'undefined') {
            console.warn(message);
        }
        warnOnceHistory[message] = true;
    }
}
function isCounterClockwise(a, b, c) {
    return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
}
function calculateSignedArea(ring) {
    var sum = 0;
    for (var i = 0, len = ring.length, j = len - 1, p1 = void 0, p2 = void 0; i < len; j = i++) {
        p1 = ring[i];
        p2 = ring[j];
        sum += (p2.x - p1.x) * (p1.y + p2.y);
    }
    return sum;
}
function sphericalToCartesian(ref) {
    var r = ref[0];
    var azimuthal = ref[1];
    var polar = ref[2];
    azimuthal += 90;
    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)
    };
}
function isWorker() {
    return typeof WorkerGlobalScope !== 'undefined' && typeof self !== 'undefined' && self instanceof WorkerGlobalScope;
}
function parseCacheControl(cacheControl) {
    var re = /(?:^|(?:\s*\,\s*))([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g;
    var header = {};
    cacheControl.replace(re, function ($0, $1, $2, $3) {
        var value = $2 || $3;
        header[$1] = value ? value.toLowerCase() : true;
        return '';
    });
    if (header['max-age']) {
        var maxAge = parseInt(header['max-age'], 10);
        if (isNaN(maxAge)) {
            delete header['max-age'];
        } else {
            header['max-age'] = maxAge;
        }
    }
    return header;
}
var _isSafari = null;
function isSafari(scope) {
    if (_isSafari == null) {
        var 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 storageAvailable(type) {
    try {
        var storage = window$1[type];
        storage.setItem('_mapbox_test_', 1);
        storage.removeItem('_mapbox_test_');
        return true;
    } catch (e) {
        return false;
    }
}
function b64EncodeUnicode(str) {
    return window$1.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
        return String.fromCharCode(Number('0x' + p1));
    }));
}
function b64DecodeUnicode(str) {
    return decodeURIComponent(window$1.atob(str).split('').map(function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

var now = window$1.performance && window$1.performance.now ? window$1.performance.now.bind(window$1.performance) : Date.now.bind(Date);
var raf = window$1.requestAnimationFrame || window$1.mozRequestAnimationFrame || window$1.webkitRequestAnimationFrame || window$1.msRequestAnimationFrame;
var cancel = window$1.cancelAnimationFrame || window$1.mozCancelAnimationFrame || window$1.webkitCancelAnimationFrame || window$1.msCancelAnimationFrame;
var linkEl;
var reducedMotionQuery;
var exported = {
    now: now,
    frame: function frame(fn) {
        var frame = raf(fn);
        return {
            cancel: function () {
                return cancel(frame);
            }
        };
    },
    getImageData: function getImageData(img, padding) {
        if (padding === void 0)
            padding = 0;
        var canvas = window$1.document.createElement('canvas');
        var context = canvas.getContext('2d');
        if (!context) {
            throw new Error('failed to create canvas 2d context');
        }
        canvas.width = img.width;
        canvas.height = img.height;
        context.drawImage(img, 0, 0, img.width, img.height);
        return context.getImageData(-padding, -padding, img.width + 2 * padding, img.height + 2 * padding);
    },
    resolveURL: function resolveURL(path) {
        if (!linkEl) {
            linkEl = window$1.document.createElement('a');
        }
        linkEl.href = path;
        return linkEl.href;
    },
    hardwareConcurrency: window$1.navigator && window$1.navigator.hardwareConcurrency || 4,
    get devicePixelRatio() {
        return window$1.devicePixelRatio;
    },
    get prefersReducedMotion() {
        if (!window$1.matchMedia) {
            return false;
        }
        if (reducedMotionQuery == null) {
            reducedMotionQuery = window$1.matchMedia('(prefers-reduced-motion: reduce)');
        }
        return reducedMotionQuery.matches;
    }
};

var config = {
    API_URL: 'https://api.mapbox.com',
    get EVENTS_URL() {
        if (!this.API_URL) {
            return null;
        }
        if (this.API_URL.indexOf('https://api.mapbox.cn') === 0) {
            return 'https://events.mapbox.cn/events/v2';
        } else if (this.API_URL.indexOf('https://api.mapbox.com') === 0) {
            return 'https://events.mapbox.com/events/v2';
        } else {
            return null;
        }
    },
    FEEDBACK_URL: 'https://apps.mapbox.com/feedback',
    REQUIRE_ACCESS_TOKEN: true,
    ACCESS_TOKEN: null,
    MAX_PARALLEL_IMAGE_REQUESTS: 16
};

var exported$1 = {
    supported: false,
    testSupport: testSupport
};
var glForTesting;
var webpCheckComplete = false;
var webpImgTest;
var webpImgTestOnloadComplete = false;
if (window$1.document) {
    webpImgTest = window$1.document.createElement('img');
    webpImgTest.onload = function () {
        if (glForTesting) {
            testWebpTextureUpload(glForTesting);
        }
        glForTesting = null;
        webpImgTestOnloadComplete = true;
    };
    webpImgTest.onerror = function () {
        webpCheckComplete = true;
        glForTesting = null;
    };
    webpImgTest.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA=';
}
function testSupport(gl) {
    if (webpCheckComplete || !webpImgTest) {
        return;
    }
    if (webpImgTestOnloadComplete) {
        testWebpTextureUpload(gl);
    } else {
        glForTesting = gl;
    }
}
function testWebpTextureUpload(gl) {
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    try {
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, webpImgTest);
        if (gl.isContextLost()) {
            return;
        }
        exported$1.supported = true;
    } catch (e) {
    }
    gl.deleteTexture(texture);
    webpCheckComplete = true;
}

var SKU_ID = '01';
function createSkuToken() {
    var TOKEN_VERSION = '1';
    var base62chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var sessionRandomizer = '';
    for (var i = 0; i < 10; i++) {
        sessionRandomizer += base62chars[Math.floor(Math.random() * 62)];
    }
    var expiration = 12 * 60 * 60 * 1000;
    var token = [
        TOKEN_VERSION,
        SKU_ID,
        sessionRandomizer
    ].join('');
    var tokenExpiresAt = Date.now() + expiration;
    return {
        token: token,
        tokenExpiresAt: tokenExpiresAt
    };
}

var RequestManager = function RequestManager(transformRequestFn, customAccessToken) {
    this._transformRequestFn = transformRequestFn;
    this._customAccessToken = customAccessToken;
    this._createSkuToken();
};
RequestManager.prototype._createSkuToken = function _createSkuToken() {
    var skuToken = createSkuToken();
    this._skuToken = skuToken.token;
    this._skuTokenExpiresAt = skuToken.tokenExpiresAt;
};
RequestManager.prototype._isSkuTokenExpired = function _isSkuTokenExpired() {
    return Date.now() > this._skuTokenExpiresAt;
};
RequestManager.prototype.transformRequest = function transformRequest(url, type) {
    if (this._transformRequestFn) {
        return this._transformRequestFn(url, type) || { url: url };
    }
    return { url: url };
};
RequestManager.prototype.normalizeStyleURL = function normalizeStyleURL(url, accessToken) {
    if (!isMapboxURL(url)) {
        return url;
    }
    var urlObject = parseUrl(url);
    urlObject.path = '/styles/v1' + urlObject.path;
    return this._makeAPIURL(urlObject, this._customAccessToken || accessToken);
};
RequestManager.prototype.normalizeGlyphsURL = function normalizeGlyphsURL(url, accessToken) {
    if (!isMapboxURL(url)) {
        return url;
    }
    var urlObject = parseUrl(url);
    urlObject.path = '/fonts/v1' + urlObject.path;
    return this._makeAPIURL(urlObject, this._customAccessToken || accessToken);
};
RequestManager.prototype.normalizeSourceURL = function normalizeSourceURL(url, accessToken) {
    if (!isMapboxURL(url)) {
        return url;
    }
    var urlObject = parseUrl(url);
    urlObject.path = '/v4/' + urlObject.authority + '.json';
    urlObject.params.push('secure');
    return this._makeAPIURL(urlObject, this._customAccessToken || accessToken);
};
RequestManager.prototype.normalizeSpriteURL = function normalizeSpriteURL(url, format, extension, accessToken) {
    var urlObject = parseUrl(url);
    if (!isMapboxURL(url)) {
        urlObject.path += '' + format + extension;
        return formatUrl(urlObject);
    }
    urlObject.path = '/styles/v1' + urlObject.path + '/sprite' + format + extension;
    return this._makeAPIURL(urlObject, this._customAccessToken || accessToken);
};
RequestManager.prototype.normalizeTileURL = function normalizeTileURL(tileURL, tileSize) {
    if (this._isSkuTokenExpired()) {
        this._createSkuToken();
    }
    if (tileURL && !isMapboxURL(tileURL)) {
        return tileURL;
    }
    var urlObject = parseUrl(tileURL);
    var imageExtensionRe = /(\.(png|jpg)\d*)(?=$)/;
    var tileURLAPIPrefixRe = /^.+\/v4\//;
    var suffix = exported.devicePixelRatio >= 2 || tileSize === 512 ? '@2x' : '';
    var extension = exported$1.supported ? '.webp' : '$1';
    urlObject.path = urlObject.path.replace(imageExtensionRe, '' + suffix + extension);
    urlObject.path = urlObject.path.replace(tileURLAPIPrefixRe, '/');
    urlObject.path = '/v4' + urlObject.path;
    var accessToken = this._customAccessToken || getAccessToken(urlObject.params) || config.ACCESS_TOKEN;
    if (config.REQUIRE_ACCESS_TOKEN && accessToken && this._skuToken) {
        urlObject.params.push('sku=' + this._skuToken);
    }
    return this._makeAPIURL(urlObject, accessToken);
};
RequestManager.prototype.canonicalizeTileURL = function canonicalizeTileURL(url, removeAccessToken) {
    var version = '/v4/';
    var extensionRe = /\.[\w]+$/;
    var urlObject = parseUrl(url);
    if (!urlObject.path.match(/(^\/v4\/)/) || !urlObject.path.match(extensionRe)) {
        return url;
    }
    var result = 'mapbox://tiles/';
    result += urlObject.path.replace(version, '');
    var params = urlObject.params;
    if (removeAccessToken) {
        params = params.filter(function (p) {
            return !p.match(/^access_token=/);
        });
    }
    if (params.length) {
        result += '?' + params.join('&');
    }
    return result;
};
RequestManager.prototype.canonicalizeTileset = function canonicalizeTileset(tileJSON, sourceURL) {
    var removeAccessToken = sourceURL ? isMapboxURL(sourceURL) : false;
    var canonical = [];
    for (var i = 0, list = tileJSON.tiles || []; i < list.length; i += 1) {
        var url = list[i];
        if (isMapboxHTTPURL(url)) {
            canonical.push(this.canonicalizeTileURL(url, removeAccessToken));
        } else {
            canonical.push(url);
        }
    }
    return canonical;
};
RequestManager.prototype._makeAPIURL = function _makeAPIURL(urlObject, accessToken) {
    var help = 'See https://www.mapbox.com/api-documentation/#access-tokens-and-token-scopes';
    var apiUrlObject = parseUrl(config.API_URL);
    urlObject.protocol = apiUrlObject.protocol;
    urlObject.authority = apiUrlObject.authority;
    if (urlObject.protocol === 'http') {
        var i = urlObject.params.indexOf('secure');
        if (i >= 0) {
            urlObject.params.splice(i, 1);
        }
    }
    if (apiUrlObject.path !== '/') {
        urlObject.path = '' + apiUrlObject.path + urlObject.path;
    }
    if (!config.REQUIRE_ACCESS_TOKEN) {
        return formatUrl(urlObject);
    }
    accessToken = accessToken || config.ACCESS_TOKEN;
    if (!accessToken) {
        throw new Error('An API access token is required to use Mapbox GL. ' + help);
    }
    if (accessToken[0] === 's') {
        throw new Error('Use a public access token (pk.*) with Mapbox GL, not a secret access token (sk.*). ' + help);
    }
    urlObject.params = urlObject.params.filter(function (d) {
        return d.indexOf('access_token') === -1;
    });
    urlObject.params.push('access_token=' + accessToken);
    return formatUrl(urlObject);
};
function isMapboxURL(url) {
    return url.indexOf('mapbox:') === 0;
}
var mapboxHTTPURLRe = /^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/|\?|$)/i;
function isMapboxHTTPURL(url) {
    return mapboxHTTPURLRe.test(url);
}
function hasCacheDefeatingSku(url) {
    return url.indexOf('sku=') > 0 && isMapboxHTTPURL(url);
}
function getAccessToken(params) {
    for (var i = 0, list = params; i < list.length; i += 1) {
        var param = list[i];
        var match = param.match(/^access_token=(.*)$/);
        if (match) {
            return match[1];
        }
    }
    return null;
}
var urlRe = /^(\w+):\/\/([^/?]*)(\/[^?]+)?\??(.+)?/;
function parseUrl(url) {
    var parts = url.match(urlRe);
    if (!parts) {
        throw new Error('Unable to parse URL object');
    }
    return {
        protocol: parts[1],
        authority: parts[2],
        path: parts[3] || '/',
        params: parts[4] ? parts[4].split('&') : []
    };
}
function formatUrl(obj) {
    var params = obj.params.length ? '?' + obj.params.join('&') : '';
    return obj.protocol + '://' + obj.authority + obj.path + params;
}
var telemEventKey = 'mapbox.eventData';
function parseAccessToken(accessToken) {
    if (!accessToken) {
        return null;
    }
    var parts = accessToken.split('.');
    if (!parts || parts.length !== 3) {
        return null;
    }
    try {
        var jsonData = JSON.parse(b64DecodeUnicode(parts[1]));
        return jsonData;
    } catch (e) {
        return null;
    }
}
var TelemetryEvent = function TelemetryEvent(type) {
    this.type = type;
    this.anonId = null;
    this.eventData = {};
    this.queue = [];
    this.pendingRequest = null;
};
TelemetryEvent.prototype.getStorageKey = function getStorageKey(domain) {
    var tokenData = parseAccessToken(config.ACCESS_TOKEN);
    var u = '';
    if (tokenData && tokenData['u']) {
        u = b64EncodeUnicode(tokenData['u']);
    } else {
        u = config.ACCESS_TOKEN || '';
    }
    return domain ? telemEventKey + '.' + domain + ':' + u : telemEventKey + ':' + u;
};
TelemetryEvent.prototype.fetchEventData = function fetchEventData() {
    var isLocalStorageAvailable = storageAvailable('localStorage');
    var storageKey = this.getStorageKey();
    var uuidKey = this.getStorageKey('uuid');
    if (isLocalStorageAvailable) {
        try {
            var data = window$1.localStorage.getItem(storageKey);
            if (data) {
                this.eventData = JSON.parse(data);
            }
            var uuid = window$1.localStorage.getItem(uuidKey);
            if (uuid) {
                this.anonId = uuid;
            }
        } catch (e) {
            warnOnce('Unable to read from LocalStorage');
        }
    }
};
TelemetryEvent.prototype.saveEventData = function saveEventData() {
    var isLocalStorageAvailable = storageAvailable('localStorage');
    var storageKey = this.getStorageKey();
    var uuidKey = this.getStorageKey('uuid');
    if (isLocalStorageAvailable) {
        try {
            window$1.localStorage.setItem(uuidKey, this.anonId);
            if (Object.keys(this.eventData).length >= 1) {
                window$1.localStorage.setItem(storageKey, JSON.stringify(this.eventData));
            }
        } catch (e) {
            warnOnce('Unable to write to LocalStorage');
        }
    }
};
TelemetryEvent.prototype.processRequests = function processRequests(_) {
};
TelemetryEvent.prototype.postEvent = function postEvent(timestamp, additionalPayload, callback, customAccessToken) {
    var this$1 = this;
    if (!config.EVENTS_URL) {
        return;
    }
    var eventsUrlObject = parseUrl(config.EVENTS_URL);
    eventsUrlObject.params.push('access_token=' + (customAccessToken || config.ACCESS_TOKEN || ''));
    var payload = {
        event: this.type,
        created: new Date(timestamp).toISOString(),
        sdkIdentifier: 'mapbox-gl-js',
        sdkVersion: version,
        skuId: SKU_ID,
        userId: this.anonId
    };
    var finalPayload = additionalPayload ? extend(payload, additionalPayload) : payload;
    var request = {
        url: formatUrl(eventsUrlObject),
        headers: { 'Content-Type': 'text/plain' },
        body: JSON.stringify([finalPayload])
    };
    this.pendingRequest = postData(request, function (error) {
        this$1.pendingRequest = null;
        callback(error);
        this$1.saveEventData();
        this$1.processRequests(customAccessToken);
    });
};
TelemetryEvent.prototype.queueRequest = function queueRequest(event, customAccessToken) {
    this.queue.push(event);
    this.processRequests(customAccessToken);
};
var MapLoadEvent = function (TelemetryEvent) {
    function MapLoadEvent() {
        TelemetryEvent.call(this, 'map.load');
        this.success = {};
        this.skuToken = '';
    }
    if (TelemetryEvent)
        MapLoadEvent.__proto__ = TelemetryEvent;
    MapLoadEvent.prototype = Object.create(TelemetryEvent && TelemetryEvent.prototype);
    MapLoadEvent.prototype.constructor = MapLoadEvent;
    MapLoadEvent.prototype.postMapLoadEvent = function postMapLoadEvent(tileUrls, mapId, skuToken, customAccessToken) {
        this.skuToken = skuToken;
        var accessTokenIsSet = !!(customAccessToken || config.ACCESS_TOKEN);
        var usesMapboxTiles = Array.isArray(tileUrls) && tileUrls.some(function (url) {
            return isMapboxURL(url) || isMapboxHTTPURL(url);
        });
        if (config.EVENTS_URL && accessTokenIsSet && usesMapboxTiles) {
            this.queueRequest({
                id: mapId,
                timestamp: Date.now()
            }, customAccessToken);
        }
    };
    MapLoadEvent.prototype.processRequests = function processRequests(customAccessToken) {
        var this$1 = this;
        if (this.pendingRequest || this.queue.length === 0) {
            return;
        }
        var ref = this.queue.shift();
        var id = ref.id;
        var timestamp = ref.timestamp;
        if (id && this.success[id]) {
            return;
        }
        if (!this.anonId) {
            this.fetchEventData();
        }
        if (!validateUuid(this.anonId)) {
            this.anonId = uuid();
        }
        this.postEvent(timestamp, { skuToken: this.skuToken }, function (err) {
            if (!err) {
                if (id) {
                    this$1.success[id] = true;
                }
            }
        }, customAccessToken);
    };
    return MapLoadEvent;
}(TelemetryEvent);
var TurnstileEvent = function (TelemetryEvent) {
    function TurnstileEvent(customAccessToken) {
        TelemetryEvent.call(this, 'appUserTurnstile');
        this._customAccessToken = customAccessToken;
    }
    if (TelemetryEvent)
        TurnstileEvent.__proto__ = TelemetryEvent;
    TurnstileEvent.prototype = Object.create(TelemetryEvent && TelemetryEvent.prototype);
    TurnstileEvent.prototype.constructor = TurnstileEvent;
    TurnstileEvent.prototype.postTurnstileEvent = function postTurnstileEvent(tileUrls, customAccessToken) {
        if (config.EVENTS_URL && config.ACCESS_TOKEN && Array.isArray(tileUrls) && tileUrls.some(function (url) {
                return isMapboxURL(url) || isMapboxHTTPURL(url);
            })) {
            this.queueRequest(Date.now(), customAccessToken);
        }
    };
    TurnstileEvent.prototype.processRequests = function processRequests(customAccessToken) {
        var this$1 = this;
        if (this.pendingRequest || this.queue.length === 0) {
            return;
        }
        if (!this.anonId || !this.eventData.lastSuccess || !this.eventData.tokenU) {
            this.fetchEventData();
        }
        var tokenData = parseAccessToken(config.ACCESS_TOKEN);
        var tokenU = tokenData ? tokenData['u'] : config.ACCESS_TOKEN;
        var dueForEvent = tokenU !== this.eventData.tokenU;
        if (!validateUuid(this.anonId)) {
            this.anonId = uuid();
            dueForEvent = true;
        }
        var nextUpdate = this.queue.shift();
        if (this.eventData.lastSuccess) {
            var lastUpdate = new Date(this.eventData.lastSuccess);
            var nextDate = new Date(nextUpdate);
            var daysElapsed = (nextUpdate - this.eventData.lastSuccess) / (24 * 60 * 60 * 1000);
            dueForEvent = dueForEvent || daysElapsed >= 1 || daysElapsed < -1 || lastUpdate.getDate() !== nextDate.getDate();
        } else {
            dueForEvent = true;
        }
        if (!dueForEvent) {
            return this.processRequests();
        }
        this.postEvent(nextUpdate, { 'enabled.telemetry': false }, function (err) {
            if (!err) {
                this$1.eventData.lastSuccess = nextUpdate;
                this$1.eventData.tokenU = tokenU;
            }
        }, customAccessToken);
    };
    return TurnstileEvent;
}(TelemetryEvent);
var turnstileEvent_ = new TurnstileEvent();
var postTurnstileEvent = turnstileEvent_.postTurnstileEvent.bind(turnstileEvent_);
var mapLoadEvent_ = new MapLoadEvent();
var postMapLoadEvent = mapLoadEvent_.postMapLoadEvent.bind(mapLoadEvent_);

var CACHE_NAME = 'mapbox-tiles';
var cacheLimit = 500;
var cacheCheckThreshold = 50;
var MIN_TIME_UNTIL_EXPIRY = 1000 * 60 * 7;
var sharedCache;
function cacheOpen() {
    if (window$1.caches && !sharedCache) {
        sharedCache = window$1.caches.open(CACHE_NAME);
    }
}
var responseConstructorSupportsReadableStream;
function prepareBody(response, callback) {
    if (responseConstructorSupportsReadableStream === undefined) {
        try {
            new Response(new ReadableStream());
            responseConstructorSupportsReadableStream = true;
        } catch (e) {
            responseConstructorSupportsReadableStream = false;
        }
    }
    if (responseConstructorSupportsReadableStream) {
        callback(response.body);
    } else {
        response.blob().then(callback);
    }
}
function cachePut(request, response, requestTime) {
    cacheOpen();
    if (!sharedCache) {
        return;
    }
    var options = {
        status: response.status,
        statusText: response.statusText,
        headers: new window$1.Headers()
    };
    response.headers.forEach(function (v, k) {
        return options.headers.set(k, v);
    });
    var cacheControl = parseCacheControl(response.headers.get('Cache-Control') || '');
    if (cacheControl['no-store']) {
        return;
    }
    if (cacheControl['max-age']) {
        options.headers.set('Expires', new Date(requestTime + cacheControl['max-age'] * 1000).toUTCString());
    }
    var timeUntilExpiry = new Date(options.headers.get('Expires')).getTime() - requestTime;
    if (timeUntilExpiry < MIN_TIME_UNTIL_EXPIRY) {
        return;
    }
    prepareBody(response, function (body) {
        var clonedResponse = new window$1.Response(body, options);
        cacheOpen();
        if (!sharedCache) {
            return;
        }
        sharedCache.then(function (cache) {
            return cache.put(stripQueryParameters(request.url), clonedResponse);
        }).catch(function (e) {
            return warnOnce(e.message);
        });
    });
}
function stripQueryParameters(url) {
    var start = url.indexOf('?');
    return start < 0 ? url : url.slice(0, start);
}
function cacheGet(request, callback) {
    cacheOpen();
    if (!sharedCache) {
        return callback(null);
    }
    var strippedURL = stripQueryParameters(request.url);
    sharedCache.then(function (cache) {
        cache.match(strippedURL).then(function (response) {
            var fresh = isFresh(response);
            cache.delete(strippedURL);
            if (fresh) {
                cache.put(strippedURL, response.clone());
            }
            callback(null, response, fresh);
        }).catch(callback);
    }).catch(callback);
}
function isFresh(response) {
    if (!response) {
        return false;
    }
    var expires = new Date(response.headers.get('Expires') || 0);
    var cacheControl = parseCacheControl(response.headers.get('Cache-Control') || '');
    return expires > Date.now() && !cacheControl['no-cache'];
}
var globalEntryCounter = Infinity;
function cacheEntryPossiblyAdded(dispatcher) {
    globalEntryCounter++;
    if (globalEntryCounter > cacheCheckThreshold) {
        dispatcher.getActor().send('enforceCacheSizeLimit', cacheLimit);
        globalEntryCounter = 0;
    }
}
function enforceCacheSizeLimit(limit) {
    cacheOpen();
    if (!sharedCache) {
        return;
    }
    sharedCache.then(function (cache) {
        cache.keys().then(function (keys) {
            for (var i = 0; i < keys.length - limit; i++) {
                cache.delete(keys[i]);
            }
        });
    });
}
function clearTileCache(callback) {
    var promise = window$1.caches.delete(CACHE_NAME);
    if (callback) {
        promise.catch(callback).then(function () {
            return callback();
        });
    }
}
function setCacheLimits(limit, checkThreshold) {
    cacheLimit = limit;
    cacheCheckThreshold = checkThreshold;
}

var supportsOffscreenCanvas;
function offscreenCanvasSupported() {
    if (supportsOffscreenCanvas == null) {
        supportsOffscreenCanvas = window$1.OffscreenCanvas && new window$1.OffscreenCanvas(1, 1).getContext('2d') && typeof window$1.createImageBitmap === 'function';
    }
    return supportsOffscreenCanvas;
}

var ResourceType = {
    Unknown: 'Unknown',
    Style: 'Style',
    Source: 'Source',
    Tile: 'Tile',
    Glyphs: 'Glyphs',
    SpriteImage: 'SpriteImage',
    SpriteJSON: 'SpriteJSON',
    Image: 'Image'
};
if (typeof Object.freeze == 'function') {
    Object.freeze(ResourceType);
}
var AJAXError = function (Error) {
    function AJAXError(message, status, url) {
        if (status === 401 && isMapboxHTTPURL(url)) {
            message += ': you may have provided an invalid Mapbox access token. See https://www.mapbox.com/api-documentation/#access-tokens-and-token-scopes';
        }
        Error.call(this, message);
        this.status = status;
        this.url = url;
        this.name = this.constructor.name;
        this.message = message;
    }
    if (Error)
        AJAXError.__proto__ = Error;
    AJAXError.prototype = Object.create(Error && Error.prototype);
    AJAXError.prototype.constructor = AJAXError;
    AJAXError.prototype.toString = function toString() {
        return this.name + ': ' + this.message + ' (' + this.status + '): ' + this.url;
    };
    return AJAXError;
}(Error);
var getReferrer = isWorker() ? function () {
    return self.worker && self.worker.referrer;
} : function () {
    return (window$1.location.protocol === 'blob:' ? window$1.parent : window$1).location.href;
};
var isFileURL = function (url) {
    return /^file:/.test(url) || /^file:/.test(getReferrer()) && !/^\w+:/.test(url);
};
function makeFetchRequest(requestParameters, callback) {
    var controller = new window$1.AbortController();
    var request = new window$1.Request(requestParameters.url, {
        method: requestParameters.method || 'GET',
        body: requestParameters.body,
        credentials: requestParameters.credentials,
        headers: requestParameters.headers,
        referrer: getReferrer(),
        signal: controller.signal
    });
    var complete = false;
    var aborted = false;
    var cacheIgnoringSearch = hasCacheDefeatingSku(request.url);
    if (requestParameters.type === 'json') {
        request.headers.set('Accept', 'application/json');
    }
    var validateOrFetch = function (err, cachedResponse, responseIsFresh) {
        if (aborted) {
            return;
        }
        if (err) {
            if (err.message !== 'SecurityError') {
                warnOnce(err);
            }
        }
        if (cachedResponse && responseIsFresh) {
            return finishRequest(cachedResponse);
        }
        var requestTime = Date.now();
        window$1.fetch(request).then(function (response) {
            if (response.ok) {
                var cacheableResponse = cacheIgnoringSearch ? response.clone() : null;
                return finishRequest(response, cacheableResponse, requestTime);
            } else {
                return callback(new AJAXError(response.statusText, response.status, requestParameters.url));
            }
        }).catch(function (error) {
            if (error.code === 20) {
                return;
            }
            callback(new Error(error.message));
        });
    };
    var finishRequest = function (response, cacheableResponse, requestTime) {
        (requestParameters.type === 'arrayBuffer' ? response.arrayBuffer() : requestParameters.type === 'json' ? response.json() : response.text()).then(function (result) {
            if (aborted) {
                return;
            }
            if (cacheableResponse && requestTime) {
                cachePut(request, cacheableResponse, requestTime);
            }
            complete = true;
            callback(null, result, response.headers.get('Cache-Control'), response.headers.get('Expires'));
        }).catch(function (err) {
            if (!aborted) {
                callback(new Error(err.message));
            }
        });
    };
    if (cacheIgnoringSearch) {
        cacheGet(request, validateOrFetch);
    } else {
        validateOrFetch(null, null);
    }
    return {
        cancel: function () {
            aborted = true;
            if (!complete) {
                controller.abort();
            }
        }
    };
}
function makeXMLHttpRequest(requestParameters, callback) {
    var xhr = new window$1.XMLHttpRequest();
    xhr.open(requestParameters.method || 'GET', requestParameters.url, true);
    if (requestParameters.type === 'arrayBuffer') {
        xhr.responseType = 'arraybuffer';
    }
    for (var k in requestParameters.headers) {
        xhr.setRequestHeader(k, requestParameters.headers[k]);
    }
    if (requestParameters.type === 'json') {
        xhr.responseType = 'text';
        xhr.setRequestHeader('Accept', 'application/json');
    }
    xhr.withCredentials = requestParameters.credentials === 'include';
    xhr.onerror = function () {
        callback(new Error(xhr.statusText));
    };
    xhr.onload = function () {
        if ((xhr.status >= 200 && xhr.status < 300 || xhr.status === 0) && xhr.response !== null) {
            var data = xhr.response;
            if (requestParameters.type === 'json') {
                try {
                    data = JSON.parse(xhr.response);
                } catch (err) {
                    return callback(err);
                }
            }
            callback(null, data, xhr.getResponseHeader('Cache-Control'), xhr.getResponseHeader('Expires'));
        } else {
            callback(new AJAXError(xhr.statusText, xhr.status, requestParameters.url));
        }
    };
    xhr.send(requestParameters.body);
    return {
        cancel: function () {
            return xhr.abort();
        }
    };
}
var makeRequest = function (requestParameters, callback) {
    if (!isFileURL(requestParameters.url)) {
        if (window$1.fetch && window$1.Request && window$1.AbortController && window$1.Request.prototype.hasOwnProperty('signal')) {
            return makeFetchRequest(requestParameters, callback);
        }
        if (isWorker() && self.worker && self.worker.actor) {
            var queueOnMainThread = true;
            return self.worker.actor.send('getResource', requestParameters, callback, undefined, queueOnMainThread);
        }
    }
    return makeXMLHttpRequest(requestParameters, callback);
};
var getJSON = function (requestParameters, callback) {
    return makeRequest(extend(requestParameters, { type: 'json' }), callback);
};
var getArrayBuffer = function (requestParameters, callback) {
    return makeRequest(extend(requestParameters, { type: 'arrayBuffer' }), callback);
};
var postData = function (requestParameters, callback) {
    return makeRequest(extend(requestParameters, { method: 'POST' }), callback);
};
function sameOrigin(url) {
    var a = window$1.document.createElement('a');
    a.href = url;
    return a.protocol === window$1.document.location.protocol && a.host === window$1.document.location.host;
}
var transparentPngUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII=';
function arrayBufferToImage(data, callback, cacheControl, expires) {
    var img = new window$1.Image();
    var URL = window$1.URL;
    img.onload = function () {
        callback(null, img);
        URL.revokeObjectURL(img.src);
        img.onload = null;
        window$1.requestAnimationFrame(function () {
            img.src = transparentPngUrl;
        });
    };
    img.onerror = function () {
        return callback(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.'));
    };
    var blob = new window$1.Blob([new Uint8Array(data)], { type: 'image/png' });
    img.cacheControl = cacheControl;
    img.expires = expires;
    img.src = data.byteLength ? URL.createObjectURL(blob) : transparentPngUrl;
}
function arrayBufferToImageBitmap(data, callback) {
    var blob = new window$1.Blob([new Uint8Array(data)], { type: 'image/png' });
    window$1.createImageBitmap(blob).then(function (imgBitmap) {
        callback(null, imgBitmap);
    }).catch(function (e) {
        callback(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.'));
    });
}
var imageQueue, numImageRequests;
var resetImageRequestQueue = function () {
    imageQueue = [];
    numImageRequests = 0;
};
resetImageRequestQueue();
var getImage = function (requestParameters, callback) {
    if (exported$1.supported) {
        if (!requestParameters.headers) {
            requestParameters.headers = {};
        }
        requestParameters.headers.accept = 'image/webp,*/*';
    }
    if (numImageRequests >= config.MAX_PARALLEL_IMAGE_REQUESTS) {
        var queued = {
            requestParameters: requestParameters,
            callback: callback,
            cancelled: false,
            cancel: function cancel() {
                this.cancelled = true;
            }
        };
        imageQueue.push(queued);
        return queued;
    }
    numImageRequests++;
    var advanced = false;
    var advanceImageRequestQueue = function () {
        if (advanced) {
            return;
        }
        advanced = true;
        numImageRequests--;
        while (imageQueue.length && numImageRequests < config.MAX_PARALLEL_IMAGE_REQUESTS) {
            var request = imageQueue.shift();
            var requestParameters = request.requestParameters;
            var callback = request.callback;
            var cancelled = request.cancelled;
            if (!cancelled) {
                request.cancel = getImage(requestParameters, callback).cancel;
            }
        }
    };
    var request = getArrayBuffer(requestParameters, function (err, data, cacheControl, expires) {
        advanceImageRequestQueue();
        if (err) {
            callback(err);
        } else if (data) {
            if (offscreenCanvasSupported()) {
                arrayBufferToImageBitmap(data, callback);
            } else {
                arrayBufferToImage(data, callback, cacheControl, expires);
            }
        }
    });
    return {
        cancel: function () {
            request.cancel();
            advanceImageRequestQueue();
        }
    };
};
var getVideo = function (urls, callback) {
    var video = window$1.document.createElement('video');
    video.muted = true;
    video.onloadstart = function () {
        callback(null, video);
    };
    for (var i = 0; i < urls.length; i++) {
        var s = window$1.document.createElement('source');
        if (!sameOrigin(urls[i])) {
            video.crossOrigin = 'Anonymous';
        }
        s.src = urls[i];
        video.appendChild(s);
    }
    return {
        cancel: function () {
        }
    };
};

function _addEventListener(type, listener, listenerList) {
    var listenerExists = listenerList[type] && listenerList[type].indexOf(listener) !== -1;
    if (!listenerExists) {
        listenerList[type] = listenerList[type] || [];
        listenerList[type].push(listener);
    }
}
function _removeEventListener(type, listener, listenerList) {
    if (listenerList && listenerList[type]) {
        var index = listenerList[type].indexOf(listener);
        if (index !== -1) {
            listenerList[type].splice(index, 1);
        }
    }
}
var Event = function Event(type, data) {
    if (data === void 0)
        data = {};
    extend(this, data);
    this.type = type;
};
var ErrorEvent = function (Event) {
    function ErrorEvent(error, data) {
        if (data === void 0)
            data = {};
        Event.call(this, 'error', extend({ error: error }, data));
    }
    if (Event)
        ErrorEvent.__proto__ = Event;
    ErrorEvent.prototype = Object.create(Event && Event.prototype);
    ErrorEvent.prototype.constructor = ErrorEvent;
    return ErrorEvent;
}(Event);
var Evented = function Evented() {
};
Evented.prototype.on = function on(type, listener) {
    this._listeners = this._listeners || {};
    _addEventListener(type, listener, this._listeners);
    return this;
};
Evented.prototype.off = function off(type, listener) {
    _removeEventListener(type, listener, this._listeners);
    _removeEventListener(type, listener, this._oneTimeListeners);
    return this;
};
Evented.prototype.once = function once(type, listener) {
    this._oneTimeListeners = this._oneTimeListeners || {};
    _addEventListener(type, listener, this._oneTimeListeners);
    return this;
};
Evented.prototype.fire = function fire(event, properties) {
    if (typeof event === 'string') {
        event = new Event(event, properties || {});
    }
    var type = event.type;
    if (this.listens(type)) {
        event.target = this;
        var listeners = this._listeners && this._listeners[type] ? this._listeners[type].slice() : [];
        for (var i = 0, list = listeners; i < list.length; i += 1) {
            var listener = list[i];
            listener.call(this, event);
        }
        var oneTimeListeners = this._oneTimeListeners && this._oneTimeListeners[type] ? this._oneTimeListeners[type].slice() : [];
        for (var i$1 = 0, list$1 = oneTimeListeners; i$1 < list$1.length; i$1 += 1) {
            var listener$1 = list$1[i$1];
            _removeEventListener(type, listener$1, this._oneTimeListeners);
            listener$1.call(this, event);
        }
        var parent = this._eventedParent;
        if (parent) {
            extend(event, typeof this._eventedParentData === 'function' ? this._eventedParentData() : this._eventedParentData);
            parent.fire(event);
        }
    } else if (event instanceof ErrorEvent) {
        console.error(event.error);
    }
    return this;
};
Evented.prototype.listens = function listens(type) {
    return this._listeners && this._listeners[type] && this._listeners[type].length > 0 || this._oneTimeListeners && this._oneTimeListeners[type] && this._oneTimeListeners[type].length > 0 || this._eventedParent && this._eventedParent.listens(type);
};
Evented.prototype.setEventedParent = function setEventedParent(parent, data) {
    this._eventedParent = parent;
    this._eventedParentData = data;
    return this;
};

var $version = 8;
var $root = {
	version: {
		required: true,
		type: "enum",
		values: [
			8
		]
	},
	name: {
		type: "string"
	},
	metadata: {
		type: "*"
	},
	center: {
		type: "array",
		value: "number"
	},
	zoom: {
		type: "number"
	},
	bearing: {
		type: "number",
		"default": 0,
		period: 360,
		units: "degrees"
	},
	pitch: {
		type: "number",
		"default": 0,
		units: "degrees"
	},
	light: {
		type: "light"
	},
	sources: {
		required: true,
		type: "sources"
	},
	sprite: {
		type: "string"
	},
	glyphs: {
		type: "string"
	},
	transition: {
		type: "transition"
	},
	layers: {
		required: true,
		type: "array",
		value: "layer"
	}
};
var sources = {
	"*": {
		type: "source"
	}
};
var source = [
	"source_vector",
	"source_raster",
	"source_raster_dem",
	"source_geojson",
	"source_video",
	"source_image"
];
var source_vector = {
	type: {
		required: true,
		type: "enum",
		values: {
			vector: {
			}
		}
	},
	url: {
		type: "string"
	},
	tiles: {
		type: "array",
		value: "string"
	},
	bounds: {
		type: "array",
		value: "number",
		length: 4,
		"default": [
			-180,
			-85.051129,
			180,
			85.051129
		]
	},
	scheme: {
		type: "enum",
		values: {
			xyz: {
			},
			tms: {
			}
		},
		"default": "xyz"
	},
	minzoom: {
		type: "number",
		"default": 0
	},
	maxzoom: {
		type: "number",
		"default": 22
	},
	attribution: {
		type: "string"
	},
	promoteId: {
		type: "promoteId"
	},
	volatile: {
		type: "boolean",
		"default": false
	},
	"*": {
		type: "*"
	}
};
var source_raster = {
	type: {
		required: true,
		type: "enum",
		values: {
			raster: {
			}
		}
	},
	url: {
		type: "string"
	},
	tiles: {
		type: "array",
		value: "string"
	},
	bounds: {
		type: "array",
		value: "number",
		length: 4,
		"default": [
			-180,
			-85.051129,
			180,
			85.051129
		]
	},
	minzoom: {
		type: "number",
		"default": 0
	},
	maxzoom: {
		type: "number",
		"default": 22
	},
	tileSize: {
		type: "number",
		"default": 512,
		units: "pixels"
	},
	scheme: {
		type: "enum",
		values: {
			xyz: {
			},
			tms: {
			}
		},
		"default": "xyz"
	},
	attribution: {
		type: "string"
	},
	volatile: {
		type: "boolean",
		"default": false
	},
	"*": {
		type: "*"
	}
};
var source_raster_dem = {
	type: {
		required: true,
		type: "enum",
		values: {
			"raster-dem": {
			}
		}
	},
	url: {
		type: "string"
	},
	tiles: {
		type: "array",
		value: "string"
	},
	bounds: {
		type: "array",
		value: "number",
		length: 4,
		"default": [
			-180,
			-85.051129,
			180,
			85.051129
		]
	},
	minzoom: {
		type: "number",
		"default": 0
	},
	maxzoom: {
		type: "number",
		"default": 22
	},
	tileSize: {
		type: "number",
		"default": 512,
		units: "pixels"
	},
	attribution: {
		type: "string"
	},
	encoding: {
		type: "enum",
		values: {
			terrarium: {
			},
			mapbox: {
			}
		},
		"default": "mapbox"
	},
	volatile: {
		type: "boolean",
		"default": false
	},
	"*": {
		type: "*"
	}
};
var source_geojson = {
	type: {
		required: true,
		type: "enum",
		values: {
			geojson: {
			}
		}
	},
	data: {
		type: "*"
	},
	maxzoom: {
		type: "number",
		"default": 18
	},
	attribution: {
		type: "string"
	},
	buffer: {
		type: "number",
		"default": 128,
		maximum: 512,
		minimum: 0
	},
	filter: {
		type: "*"
	},
	tolerance: {
		type: "number",
		"default": 0.375
	},
	cluster: {
		type: "boolean",
		"default": false
	},
	clusterRadius: {
		type: "number",
		"default": 50,
		minimum: 0
	},
	clusterMaxZoom: {
		type: "number"
	},
	clusterMinPoints: {
		type: "number"
	},
	clusterProperties: {
		type: "*"
	},
	lineMetrics: {
		type: "boolean",
		"default": false
	},
	generateId: {
		type: "boolean",
		"default": false
	},
	promoteId: {
		type: "promoteId"
	}
};
var source_video = {
	type: {
		required: true,
		type: "enum",
		values: {
			video: {
			}
		}
	},
	urls: {
		required: true,
		type: "array",
		value: "string"
	},
	coordinates: {
		required: true,
		type: "array",
		length: 4,
		value: {
			type: "array",
			length: 2,
			value: "number"
		}
	}
};
var source_image = {
	type: {
		required: true,
		type: "enum",
		values: {
			image: {
			}
		}
	},
	url: {
		required: true,
		type: "string"
	},
	coordinates: {
		required: true,
		type: "array",
		length: 4,
		value: {
			type: "array",
			length: 2,
			value: "number"
		}
	}
};
var layer = {
	id: {
		type: "string",
		required: true
	},
	type: {
		type: "enum",
		values: {
			fill: {
			},
			line: {
			},
			symbol: {
			},
			circle: {
			},
			heatmap: {
			},
			"fill-extrusion": {
			},
			raster: {
			},
			hillshade: {
			},
			background: {
			}
		},
		required: true
	},
	metadata: {
		type: "*"
	},
	source: {
		type: "string"
	},
	"source-layer": {
		type: "string"
	},
	minzoom: {
		type: "number",
		minimum: 0,
		maximum: 24
	},
	maxzoom: {
		type: "number",
		minimum: 0,
		maximum: 24
	},
	filter: {
		type: "filter"
	},
	layout: {
		type: "layout"
	},
	paint: {
		type: "paint"
	}
};
var layout = [
	"layout_fill",
	"layout_line",
	"layout_circle",
	"layout_heatmap",
	"layout_fill-extrusion",
	"layout_symbol",
	"layout_raster",
	"layout_hillshade",
	"layout_background"
];
var layout_background = {
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_fill = {
	"fill-sort-key": {
		type: "number",
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_circle = {
	"circle-sort-key": {
		type: "number",
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_heatmap = {
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_line = {
	"line-cap": {
		type: "enum",
		values: {
			butt: {
			},
			round: {
			},
			square: {
			}
		},
		"default": "butt",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"line-join": {
		type: "enum",
		values: {
			bevel: {
			},
			round: {
			},
			miter: {
			}
		},
		"default": "miter",
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"line-miter-limit": {
		type: "number",
		"default": 2,
		requires: [
			{
				"line-join": "miter"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"line-round-limit": {
		type: "number",
		"default": 1.05,
		requires: [
			{
				"line-join": "round"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"line-sort-key": {
		type: "number",
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_symbol = {
	"symbol-placement": {
		type: "enum",
		values: {
			point: {
			},
			line: {
			},
			"line-center": {
			}
		},
		"default": "point",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"symbol-spacing": {
		type: "number",
		"default": 250,
		minimum: 1,
		units: "pixels",
		requires: [
			{
				"symbol-placement": "line"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"symbol-avoid-edges": {
		type: "boolean",
		"default": false,
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"symbol-sort-key": {
		type: "number",
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"symbol-z-order": {
		type: "enum",
		values: {
			auto: {
			},
			"viewport-y": {
			},
			source: {
			}
		},
		"default": "auto",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-allow-overlap": {
		type: "boolean",
		"default": false,
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-ignore-placement": {
		type: "boolean",
		"default": false,
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-optional": {
		type: "boolean",
		"default": false,
		requires: [
			"icon-image",
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-rotation-alignment": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			},
			auto: {
			}
		},
		"default": "auto",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-size": {
		type: "number",
		"default": 1,
		minimum: 0,
		units: "factor of the original icon size",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"icon-text-fit": {
		type: "enum",
		values: {
			none: {
			},
			width: {
			},
			height: {
			},
			both: {
			}
		},
		"default": "none",
		requires: [
			"icon-image",
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-text-fit-padding": {
		type: "array",
		value: "number",
		length: 4,
		"default": [
			0,
			0,
			0,
			0
		],
		units: "pixels",
		requires: [
			"icon-image",
			"text-field",
			{
				"icon-text-fit": [
					"both",
					"width",
					"height"
				]
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-image": {
		type: "resolvedImage",
		tokens: true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"icon-rotate": {
		type: "number",
		"default": 0,
		period: 360,
		units: "degrees",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"icon-padding": {
		type: "number",
		"default": 2,
		minimum: 0,
		units: "pixels",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-keep-upright": {
		type: "boolean",
		"default": false,
		requires: [
			"icon-image",
			{
				"icon-rotation-alignment": "map"
			},
			{
				"symbol-placement": [
					"line",
					"line-center"
				]
			}
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-offset": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"icon-anchor": {
		type: "enum",
		values: {
			center: {
			},
			left: {
			},
			right: {
			},
			top: {
			},
			bottom: {
			},
			"top-left": {
			},
			"top-right": {
			},
			"bottom-left": {
			},
			"bottom-right": {
			}
		},
		"default": "center",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"icon-pitch-alignment": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			},
			auto: {
			}
		},
		"default": "auto",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-pitch-alignment": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			},
			auto: {
			}
		},
		"default": "auto",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-rotation-alignment": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			},
			auto: {
			}
		},
		"default": "auto",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-field": {
		type: "formatted",
		"default": "",
		tokens: true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-font": {
		type: "array",
		value: "string",
		"default": [
			"Open Sans Regular",
			"Arial Unicode MS Regular"
		],
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-size": {
		type: "number",
		"default": 16,
		minimum: 0,
		units: "pixels",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-max-width": {
		type: "number",
		"default": 10,
		minimum: 0,
		units: "ems",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-line-height": {
		type: "number",
		"default": 1.2,
		units: "ems",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-letter-spacing": {
		type: "number",
		"default": 0,
		units: "ems",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-justify": {
		type: "enum",
		values: {
			auto: {
			},
			left: {
			},
			center: {
			},
			right: {
			}
		},
		"default": "center",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-radial-offset": {
		type: "number",
		units: "ems",
		"default": 0,
		requires: [
			"text-field"
		],
		"property-type": "data-driven",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		}
	},
	"text-variable-anchor": {
		type: "array",
		value: "enum",
		values: {
			center: {
			},
			left: {
			},
			right: {
			},
			top: {
			},
			bottom: {
			},
			"top-left": {
			},
			"top-right": {
			},
			"bottom-left": {
			},
			"bottom-right": {
			}
		},
		requires: [
			"text-field",
			{
				"symbol-placement": [
					"point"
				]
			}
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-anchor": {
		type: "enum",
		values: {
			center: {
			},
			left: {
			},
			right: {
			},
			top: {
			},
			bottom: {
			},
			"top-left": {
			},
			"top-right": {
			},
			"bottom-left": {
			},
			"bottom-right": {
			}
		},
		"default": "center",
		requires: [
			"text-field",
			{
				"!": "text-variable-anchor"
			}
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-max-angle": {
		type: "number",
		"default": 45,
		units: "degrees",
		requires: [
			"text-field",
			{
				"symbol-placement": [
					"line",
					"line-center"
				]
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-writing-mode": {
		type: "array",
		value: "enum",
		values: {
			horizontal: {
			},
			vertical: {
			}
		},
		requires: [
			"text-field",
			{
				"symbol-placement": [
					"point"
				]
			}
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-rotate": {
		type: "number",
		"default": 0,
		period: 360,
		units: "degrees",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-padding": {
		type: "number",
		"default": 2,
		minimum: 0,
		units: "pixels",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-keep-upright": {
		type: "boolean",
		"default": true,
		requires: [
			"text-field",
			{
				"text-rotation-alignment": "map"
			},
			{
				"symbol-placement": [
					"line",
					"line-center"
				]
			}
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-transform": {
		type: "enum",
		values: {
			none: {
			},
			uppercase: {
			},
			lowercase: {
			}
		},
		"default": "none",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-offset": {
		type: "array",
		value: "number",
		units: "ems",
		length: 2,
		"default": [
			0,
			0
		],
		requires: [
			"text-field",
			{
				"!": "text-radial-offset"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "data-driven"
	},
	"text-allow-overlap": {
		type: "boolean",
		"default": false,
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-ignore-placement": {
		type: "boolean",
		"default": false,
		requires: [
			"text-field"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-optional": {
		type: "boolean",
		"default": false,
		requires: [
			"text-field",
			"icon-image"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_raster = {
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var layout_hillshade = {
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
};
var filter = {
	type: "array",
	value: "*"
};
var filter_operator = {
	type: "enum",
	values: {
		"==": {
		},
		"!=": {
		},
		">": {
		},
		">=": {
		},
		"<": {
		},
		"<=": {
		},
		"in": {
		},
		"!in": {
		},
		all: {
		},
		any: {
		},
		none: {
		},
		has: {
		},
		"!has": {
		},
		within: {
		}
	}
};
var geometry_type = {
	type: "enum",
	values: {
		Point: {
		},
		LineString: {
		},
		Polygon: {
		}
	}
};
var function_stop = {
	type: "array",
	minimum: 0,
	maximum: 24,
	value: [
		"number",
		"color"
	],
	length: 2
};
var expression = {
	type: "array",
	value: "*",
	minimum: 1
};
var light = {
	anchor: {
		type: "enum",
		"default": "viewport",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"property-type": "data-constant",
		transition: false,
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		}
	},
	position: {
		type: "array",
		"default": [
			1.15,
			210,
			30
		],
		length: 3,
		value: "number",
		"property-type": "data-constant",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		}
	},
	color: {
		type: "color",
		"property-type": "data-constant",
		"default": "#ffffff",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		transition: true
	},
	intensity: {
		type: "number",
		"property-type": "data-constant",
		"default": 0.5,
		minimum: 0,
		maximum: 1,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		transition: true
	}
};
var paint = [
	"paint_fill",
	"paint_line",
	"paint_circle",
	"paint_heatmap",
	"paint_fill-extrusion",
	"paint_symbol",
	"paint_raster",
	"paint_hillshade",
	"paint_background"
];
var paint_fill = {
	"fill-antialias": {
		type: "boolean",
		"default": true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"fill-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"fill-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		requires: [
			{
				"!": "fill-pattern"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"fill-outline-color": {
		type: "color",
		transition: true,
		requires: [
			{
				"!": "fill-pattern"
			},
			{
				"fill-antialias": true
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"fill-translate": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"fill-translate-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		requires: [
			"fill-translate"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"fill-pattern": {
		type: "resolvedImage",
		transition: true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "cross-faded-data-driven"
	}
};
var paint_line = {
	"line-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"line-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		requires: [
			{
				"!": "line-pattern"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"line-translate": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"line-translate-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		requires: [
			"line-translate"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"line-width": {
		type: "number",
		"default": 1,
		minimum: 0,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"line-gap-width": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"line-offset": {
		type: "number",
		"default": 0,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"line-blur": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"line-dasharray": {
		type: "array",
		value: "number",
		minimum: 0,
		transition: true,
		units: "line widths",
		requires: [
			{
				"!": "line-pattern"
			}
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "cross-faded"
	},
	"line-pattern": {
		type: "resolvedImage",
		transition: true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "cross-faded-data-driven"
	},
	"line-gradient": {
		type: "color",
		transition: false,
		requires: [
			{
				"!": "line-dasharray"
			},
			{
				"!": "line-pattern"
			},
			{
				source: "geojson",
				has: {
					lineMetrics: true
				}
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"line-progress"
			]
		},
		"property-type": "color-ramp"
	}
};
var paint_circle = {
	"circle-radius": {
		type: "number",
		"default": 5,
		minimum: 0,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"circle-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"circle-blur": {
		type: "number",
		"default": 0,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"circle-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"circle-translate": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"circle-translate-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		requires: [
			"circle-translate"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"circle-pitch-scale": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"circle-pitch-alignment": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "viewport",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"circle-stroke-width": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"circle-stroke-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"circle-stroke-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	}
};
var paint_heatmap = {
	"heatmap-radius": {
		type: "number",
		"default": 30,
		minimum: 1,
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"heatmap-weight": {
		type: "number",
		"default": 1,
		minimum: 0,
		transition: false,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"heatmap-intensity": {
		type: "number",
		"default": 1,
		minimum: 0,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"heatmap-color": {
		type: "color",
		"default": [
			"interpolate",
			[
				"linear"
			],
			[
				"heatmap-density"
			],
			0,
			"rgba(0, 0, 255, 0)",
			0.1,
			"royalblue",
			0.3,
			"cyan",
			0.5,
			"lime",
			0.7,
			"yellow",
			1,
			"red"
		],
		transition: false,
		expression: {
			interpolated: true,
			parameters: [
				"heatmap-density"
			]
		},
		"property-type": "color-ramp"
	},
	"heatmap-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	}
};
var paint_symbol = {
	"icon-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"icon-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"icon-halo-color": {
		type: "color",
		"default": "rgba(0, 0, 0, 0)",
		transition: true,
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"icon-halo-width": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"icon-halo-blur": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"icon-translate": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		transition: true,
		units: "pixels",
		requires: [
			"icon-image"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"icon-translate-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		requires: [
			"icon-image",
			"icon-translate"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"text-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		overridable: true,
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"text-halo-color": {
		type: "color",
		"default": "rgba(0, 0, 0, 0)",
		transition: true,
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"text-halo-width": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"text-halo-blur": {
		type: "number",
		"default": 0,
		minimum: 0,
		transition: true,
		units: "pixels",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"text-translate": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		transition: true,
		units: "pixels",
		requires: [
			"text-field"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"text-translate-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		requires: [
			"text-field",
			"text-translate"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	}
};
var paint_raster = {
	"raster-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-hue-rotate": {
		type: "number",
		"default": 0,
		period: 360,
		transition: true,
		units: "degrees",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-brightness-min": {
		type: "number",
		"default": 0,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-brightness-max": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-saturation": {
		type: "number",
		"default": 0,
		minimum: -1,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-contrast": {
		type: "number",
		"default": 0,
		minimum: -1,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-resampling": {
		type: "enum",
		values: {
			linear: {
			},
			nearest: {
			}
		},
		"default": "linear",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"raster-fade-duration": {
		type: "number",
		"default": 300,
		minimum: 0,
		transition: false,
		units: "milliseconds",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	}
};
var paint_hillshade = {
	"hillshade-illumination-direction": {
		type: "number",
		"default": 335,
		minimum: 0,
		maximum: 359,
		transition: false,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"hillshade-illumination-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "viewport",
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"hillshade-exaggeration": {
		type: "number",
		"default": 0.5,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"hillshade-shadow-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"hillshade-highlight-color": {
		type: "color",
		"default": "#FFFFFF",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"hillshade-accent-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	}
};
var paint_background = {
	"background-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		requires: [
			{
				"!": "background-pattern"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"background-pattern": {
		type: "resolvedImage",
		transition: true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "cross-faded"
	},
	"background-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	}
};
var transition = {
	duration: {
		type: "number",
		"default": 300,
		minimum: 0,
		units: "milliseconds"
	},
	delay: {
		type: "number",
		"default": 0,
		minimum: 0,
		units: "milliseconds"
	}
};
var promoteId = {
	"*": {
		type: "string"
	}
};
var spec = {
	$version: $version,
	$root: $root,
	sources: sources,
	source: source,
	source_vector: source_vector,
	source_raster: source_raster,
	source_raster_dem: source_raster_dem,
	source_geojson: source_geojson,
	source_video: source_video,
	source_image: source_image,
	layer: layer,
	layout: layout,
	layout_background: layout_background,
	layout_fill: layout_fill,
	layout_circle: layout_circle,
	layout_heatmap: layout_heatmap,
	"layout_fill-extrusion": {
	visibility: {
		type: "enum",
		values: {
			visible: {
			},
			none: {
			}
		},
		"default": "visible",
		"property-type": "constant"
	}
},
	layout_line: layout_line,
	layout_symbol: layout_symbol,
	layout_raster: layout_raster,
	layout_hillshade: layout_hillshade,
	filter: filter,
	filter_operator: filter_operator,
	geometry_type: geometry_type,
	"function": {
	expression: {
		type: "expression"
	},
	stops: {
		type: "array",
		value: "function_stop"
	},
	base: {
		type: "number",
		"default": 1,
		minimum: 0
	},
	property: {
		type: "string",
		"default": "$zoom"
	},
	type: {
		type: "enum",
		values: {
			identity: {
			},
			exponential: {
			},
			interval: {
			},
			categorical: {
			}
		},
		"default": "exponential"
	},
	colorSpace: {
		type: "enum",
		values: {
			rgb: {
			},
			lab: {
			},
			hcl: {
			}
		},
		"default": "rgb"
	},
	"default": {
		type: "*",
		required: false
	}
},
	function_stop: function_stop,
	expression: expression,
	light: light,
	paint: paint,
	paint_fill: paint_fill,
	"paint_fill-extrusion": {
	"fill-extrusion-opacity": {
		type: "number",
		"default": 1,
		minimum: 0,
		maximum: 1,
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"fill-extrusion-color": {
		type: "color",
		"default": "#000000",
		transition: true,
		requires: [
			{
				"!": "fill-extrusion-pattern"
			}
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"fill-extrusion-translate": {
		type: "array",
		value: "number",
		length: 2,
		"default": [
			0,
			0
		],
		transition: true,
		units: "pixels",
		expression: {
			interpolated: true,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"fill-extrusion-translate-anchor": {
		type: "enum",
		values: {
			map: {
			},
			viewport: {
			}
		},
		"default": "map",
		requires: [
			"fill-extrusion-translate"
		],
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	},
	"fill-extrusion-pattern": {
		type: "resolvedImage",
		transition: true,
		expression: {
			interpolated: false,
			parameters: [
				"zoom",
				"feature"
			]
		},
		"property-type": "cross-faded-data-driven"
	},
	"fill-extrusion-height": {
		type: "number",
		"default": 0,
		minimum: 0,
		units: "meters",
		transition: true,
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"fill-extrusion-base": {
		type: "number",
		"default": 0,
		minimum: 0,
		units: "meters",
		transition: true,
		requires: [
			"fill-extrusion-height"
		],
		expression: {
			interpolated: true,
			parameters: [
				"zoom",
				"feature",
				"feature-state"
			]
		},
		"property-type": "data-driven"
	},
	"fill-extrusion-vertical-gradient": {
		type: "boolean",
		"default": true,
		transition: false,
		expression: {
			interpolated: false,
			parameters: [
				"zoom"
			]
		},
		"property-type": "data-constant"
	}
},
	paint_line: paint_line,
	paint_circle: paint_circle,
	paint_heatmap: paint_heatmap,
	paint_symbol: paint_symbol,
	paint_raster: paint_raster,
	paint_hillshade: paint_hillshade,
	paint_background: paint_background,
	transition: transition,
	"property-type": {
	"data-driven": {
		type: "property-type"
	},
	"cross-faded": {
		type: "property-type"
	},
	"cross-faded-data-driven": {
		type: "property-type"
	},
	"color-ramp": {
		type: "property-type"
	},
	"data-constant": {
		type: "property-type"
	},
	constant: {
		type: "property-type"
	}
},
	promoteId: promoteId
};

var ValidationError = function ValidationError(key, value, message, identifier) {
    this.message = (key ? key + ': ' : '') + message;
    if (identifier) {
        this.identifier = identifier;
    }
    if (value !== null && value !== undefined && value.__line__) {
        this.line = value.__line__;
    }
};

function validateConstants(options) {
    var key = options.key;
    var constants = options.value;
    if (constants) {
        return [new ValidationError(key, constants, 'constants have been deprecated as of v8')];
    } else {
        return [];
    }
}

function extend$1 (output) {
    var inputs = [], len = arguments.length - 1;
    while (len-- > 0)
        inputs[len] = arguments[len + 1];
    for (var i = 0, list = inputs; i < list.length; i += 1) {
        var input = list[i];
        for (var k in input) {
            output[k] = input[k];
        }
    }
    return output;
}

function unbundle(value) {
    if (value instanceof Number || value instanceof String || value instanceof Boolean) {
        return value.valueOf();
    } else {
        return value;
    }
}
function deepUnbundle(value) {
    if (Array.isArray(value)) {
        return value.map(deepUnbundle);
    } else if (value instanceof Object && !(value instanceof Number || value instanceof String || value instanceof Boolean)) {
        var unbundledValue = {};
        for (var key in value) {
            unbundledValue[key] = deepUnbundle(value[key]);
        }
        return unbundledValue;
    }
    return unbundle(value);
}

var ParsingError = function (Error) {
    function ParsingError(key, message) {
        Error.call(this, message);
        this.message = message;
        this.key = key;
    }
    if (Error)
        ParsingError.__proto__ = Error;
    ParsingError.prototype = Object.create(Error && Error.prototype);
    ParsingError.prototype.constructor = ParsingError;
    return ParsingError;
}(Error);

var Scope = function Scope(parent, bindings) {
    if (bindings === void 0)
        bindings = [];
    this.parent = parent;
    this.bindings = {};
    for (var i = 0, list = bindings; i < list.length; i += 1) {
        var ref = list[i];
        var name = ref[0];
        var expression = ref[1];
        this.bindings[name] = expression;
    }
};
Scope.prototype.concat = function concat(bindings) {
    return new Scope(this, bindings);
};
Scope.prototype.get = function get(name) {
    if (this.bindings[name]) {
        return this.bindings[name];
    }
    if (this.parent) {
        return this.parent.get(name);
    }
    throw new Error(name + ' not found in scope.');
};
Scope.prototype.has = function has(name) {
    if (this.bindings[name]) {
        return true;
    }
    return this.parent ? this.parent.has(name) : false;
};

var NullType = { kind: 'null' };
var NumberType = { kind: 'number' };
var StringType = { kind: 'string' };
var BooleanType = { kind: 'boolean' };
var ColorType = { kind: 'color' };
var ObjectType = { kind: 'object' };
var ValueType = { kind: 'value' };
var ErrorType = { kind: 'error' };
var CollatorType = { kind: 'collator' };
var FormattedType = { kind: 'formatted' };
var ResolvedImageType = { kind: 'resolvedImage' };
function array(itemType, N) {
    return {
        kind: 'array',
        itemType: itemType,
        N: N
    };
}
function toString(type) {
    if (type.kind === 'array') {
        var itemType = toString(type.itemType);
        return typeof type.N === 'number' ? 'array<' + itemType + ', ' + type.N + '>' : type.itemType.kind === 'value' ? 'array' : 'array<' + itemType + '>';
    } else {
        return type.kind;
    }
}
var valueMemberTypes = [
    NullType,
    NumberType,
    StringType,
    BooleanType,
    ColorType,
    FormattedType,
    ObjectType,
    array(ValueType),
    ResolvedImageType
];
function checkSubtype(expected, t) {
    if (t.kind === 'error') {
        return null;
    } else if (expected.kind === 'array') {
        if (t.kind === 'array' && (t.N === 0 && t.itemType.kind === 'value' || !checkSubtype(expected.itemType, t.itemType)) && (typeof expected.N !== 'number' || expected.N === t.N)) {
            return null;
        }
    } else if (expected.kind === t.kind) {
        return null;
    } else if (expected.kind === 'value') {
        for (var i = 0, list = valueMemberTypes; i < list.length; i += 1) {
            var memberType = list[i];
            if (!checkSubtype(memberType, t)) {
                return null;
            }
        }
    }
    return 'Expected ' + toString(expected) + ' but found ' + toString(t) + ' instead.';
}
function isValidType(provided, allowedTypes) {
    return allowedTypes.some(function (t) {
        return t.kind === provided.kind;
    });
}
function isValidNativeType(provided, allowedTypes) {
    return allowedTypes.some(function (t) {
        if (t === 'null') {
            return provided === null;
        } else if (t === 'array') {
            return Array.isArray(provided);
        } else if (t === 'object') {
            return provided && !Array.isArray(provided) && typeof provided === 'object';
        } else {
            return t === typeof provided;
        }
    });
}

var csscolorparser = createCommonjsModule(function (module, exports) {
var kCSSColorTable = {
    'transparent': [
        0,
        0,
        0,
        0
    ],
    'aliceblue': [
        240,
        248,
        255,
        1
    ],
    'antiquewhite': [
        250,
        235,
        215,
        1
    ],
    'aqua': [
        0,
        255,
        255,
        1
    ],
    'aquamarine': [
        127,
        255,
        212,
        1
    ],
    'azure': [
        240,
        255,
        255,
        1
    ],
    'beige': [
        245,
        245,
        220,
        1
    ],
    'bisque': [
        255,
        228,
        196,
        1
    ],
    'black': [
        0,
        0,
        0,
        1
    ],
    'blanchedalmond': [
        255,
        235,
        205,
        1
    ],
    'blue': [
        0,
        0,
        255,
        1
    ],
    'blueviolet': [
        138,
        43,
        226,
        1
    ],
    'brown': [
        165,
        42,
        42,
        1
    ],
    'burlywood': [
        222,
        184,
        135,
        1
    ],
    'cadetblue': [
        95,
        158,
        160,
        1
    ],
    'chartreuse': [
        127,
        255,
        0,
        1
    ],
    'chocolate': [
        210,
        105,
        30,
        1
    ],
    'coral': [
        255,
        127,
        80,
        1
    ],
    'cornflowerblue': [
        100,
        149,
        237,
        1
    ],
    'cornsilk': [
        255,
        248,
        220,
        1
    ],
    'crimson': [
        220,
        20,
        60,
        1
    ],
    'cyan': [
        0,
        255,
        255,
        1
    ],
    'darkblue': [
        0,
        0,
        139,
        1
    ],
    'darkcyan': [
        0,
        139,
        139,
        1
    ],
    'darkgoldenrod': [
        184,
        134,
        11,
        1
    ],
    'darkgray': [
        169,
        169,
        169,
        1
    ],
    'darkgreen': [
        0,
        100,
        0,
        1
    ],
    'darkgrey': [
        169,
        169,
        169,
        1
    ],
    'darkkhaki': [
        189,
        183,
        107,
        1
    ],
    'darkmagenta': [
        139,
        0,
        139,
        1
    ],
    'darkolivegreen': [
        85,
        107,
        47,
        1
    ],
    'darkorange': [
        255,
        140,
        0,
        1
    ],
    'darkorchid': [
        153,
        50,
        204,
        1
    ],
    'darkred': [
        139,
        0,
        0,
        1
    ],
    'darksalmon': [
        233,
        150,
        122,
        1
    ],
    'darkseagreen': [
        143,
        188,
        143,
        1
    ],
    'darkslateblue': [
        72,
        61,
        139,
        1
    ],
    'darkslategray': [
        47,
        79,
        79,
        1
    ],
    'darkslategrey': [
        47,
        79,
        79,
        1
    ],
    'darkturquoise': [
        0,
        206,
        209,
        1
    ],
    'darkviolet': [
        148,
        0,
        211,
        1
    ],
    'deeppink': [
        255,
        20,
        147,
        1
    ],
    'deepskyblue': [
        0,
        191,
        255,
        1
    ],
    'dimgray': [
        105,
        105,
        105,
        1
    ],
    'dimgrey': [
        105,
        105,
        105,
        1
    ],
    'dodgerblue': [
        30,
        144,
        255,
        1
    ],
    'firebrick': [
        178,
        34,
        34,
        1
    ],
    'floralwhite': [
        255,
        250,
        240,
        1
    ],
    'forestgreen': [
        34,
        139,
        34,
        1
    ],
    'fuchsia': [
        255,
        0,
        255,
        1
    ],
    'gainsboro': [
        220,
        220,
        220,
        1
    ],
    'ghostwhite': [
        248,
        248,
        255,
        1
    ],
    'gold': [
        255,
        215,
        0,
        1
    ],
    'goldenrod': [
        218,
        165,
        32,
        1
    ],
    'gray': [
        128,
        128,
        128,
        1
    ],
    'green': [
        0,
        128,
        0,
        1
    ],
    'greenyellow': [
        173,
        255,
        47,
        1
    ],
    'grey': [
        128,
        128,
        128,
        1
    ],
    'honeydew': [
        240,
        255,
        240,
        1
    ],
    'hotpink': [
        255,
        105,
        180,
        1
    ],
    'indianred': [
        205,
        92,
        92,
        1
    ],
    'indigo': [
        75,
        0,
        130,
        1
    ],
    'ivory': [
        255,
        255,
        240,
        1
    ],
    'khaki': [
        240,
        230,
        140,
        1
    ],
    'lavender': [
        230,
        230,
        250,
        1
    ],
    'lavenderblush': [
        255,
        240,
        245,
        1
    ],
    'lawngreen': [
        124,
        252,
        0,
        1
    ],
    'lemonchiffon': [
        255,
        250,
        205,
        1
    ],
    'lightblue': [
        173,
        216,
        230,
        1
    ],
    'lightcoral': [
        240,
        128,
        128,
        1
    ],
    'lightcyan': [
        224,
        255,
        255,
        1
    ],
    'lightgoldenrodyellow': [
        250,
        250,
        210,
        1
    ],
    'lightgray': [
        211,
        211,
        211,
        1
    ],
    'lightgreen': [
        144,
        238,
        144,
        1
    ],
    'lightgrey': [
        211,
        211,
        211,
        1
    ],
    'lightpink': [
        255,
        182,
        193,
        1
    ],
    'lightsalmon': [
        255,
        160,
        122,
        1
    ],
    'lightseagreen': [
        32,
        178,
        170,
        1
    ],
    'lightskyblue': [
        135,
        206,
        250,
        1
    ],
    'lightslategray': [
        119,
        136,
        153,
        1
    ],
    'lightslategrey': [
        119,
        136,
        153,
        1
    ],
    'lightsteelblue': [
        176,
        196,
        222,
        1
    ],
    'lightyellow': [
        255,
        255,
        224,
        1
    ],
    'lime': [
        0,
        255,
        0,
        1
    ],
    'limegreen': [
        50,
        205,
        50,
        1
    ],
    'linen': [
        250,
        240,
        230,
        1
    ],
    'magenta': [
        255,
        0,
        255,
        1
    ],
    'maroon': [
        128,
        0,
        0,
        1
    ],
    'mediumaquamarine': [
        102,
        205,
        170,
        1
    ],
    'mediumblue': [
        0,
        0,
        205,
        1
    ],
    'mediumorchid': [
        186,
        85,
        211,
        1
    ],
    'mediumpurple': [
        147,
        112,
        219,
        1
    ],
    'mediumseagreen': [
        60,
        179,
        113,
        1
    ],
    'mediumslateblue': [
        123,
        104,
        238,
        1
    ],
    'mediumspringgreen': [
        0,
        250,
        154,
        1
    ],
    'mediumturquoise': [
        72,
        209,
        204,
        1
    ],
    'mediumvioletred': [
        199,
        21,
        133,
        1
    ],
    'midnightblue': [
        25,
        25,
        112,
        1
    ],
    'mintcream': [
        245,
        255,
        250,
        1
    ],
    'mistyrose': [
        255,
        228,
        225,
        1
    ],
    'moccasin': [
        255,
        228,
        181,
        1
    ],
    'navajowhite': [
        255,
        222,
        173,
        1
    ],
    'navy': [
        0,
        0,
        128,
        1
    ],
    'oldlace': [
        253,
        245,
        230,
        1
    ],
    'olive': [
        128,
        128,
        0,
        1
    ],
    'olivedrab': [
        107,
        142,
        35,
        1
    ],
    'orange': [
        255,
        165,
        0,
        1
    ],
    'orangered': [
        255,
        69,
        0,
        1
    ],
    'orchid': [
        218,
        112,
        214,
        1
    ],
    'palegoldenrod': [
        238,
        232,
        170,
        1
    ],
    'palegreen': [
        152,
        251,
        152,
        1
    ],
    'paleturquoise': [
        175,
        238,
        238,
        1
    ],
    'palevioletred': [
        219,
        112,
        147,
        1
    ],
    'papayawhip': [
        255,
        239,
        213,
        1
    ],
    'peachpuff': [
        255,
        218,
        185,
        1
    ],
    'peru': [
        205,
        133,
        63,
        1
    ],
    'pink': [
        255,
        192,
        203,
        1
    ],
    'plum': [
        221,
        160,
        221,
        1
    ],
    'powderblue': [
        176,
        224,
        230,
        1
    ],
    'purple': [
        128,
        0,
        128,
        1
    ],
    'rebeccapurple': [
        102,
        51,
        153,
        1
    ],
    'red': [
        255,
        0,
        0,
        1
    ],
    'rosybrown': [
        188,
        143,
        143,
        1
    ],
    'royalblue': [
        65,
        105,
        225,
        1
    ],
    'saddlebrown': [
        139,
        69,
        19,
        1
    ],
    'salmon': [
        250,
        128,
        114,
        1
    ],
    'sandybrown': [
        244,
        164,
        96,
        1
    ],
    'seagreen': [
        46,
        139,
        87,
        1
    ],
    'seashell': [
        255,
        245,
        238,
        1
    ],
    'sienna': [
        160,
        82,
        45,
        1
    ],
    'silver': [
        192,
        192,
        192,
        1
    ],
    'skyblue': [
        135,
        206,
        235,
        1
    ],
    'slateblue': [
        106,
        90,
        205,
        1
    ],
    'slategray': [
        112,
        128,
        144,
        1
    ],
    'slategrey': [
        112,
        128,
        144,
        1
    ],
    'snow': [
        255,
        250,
        250,
        1
    ],
    'springgreen': [
        0,
        255,
        127,
        1
    ],
    'steelblue': [
        70,
        130,
        180,
        1
    ],
    'tan': [
        210,
        180,
        140,
        1
    ],
    'teal': [
        0,
        128,
        128,
        1
    ],
    'thistle': [
        216,
        191,
        216,
        1
    ],
    'tomato': [
        255,
        99,
        71,
        1
    ],
    'turquoise': [
        64,
        224,
        208,
        1
    ],
    'violet': [
        238,
        130,
        238,
        1
    ],
    'wheat': [
        245,
        222,
        179,
        1
    ],
    'white': [
        255,
        255,
        255,
        1
    ],
    'whitesmoke': [
        245,
        245,
        245,
        1
    ],
    'yellow': [
        255,
        255,
        0,
        1
    ],
    'yellowgreen': [
        154,
        205,
        50,
        1
    ]
};
function clamp_css_byte(i) {
    i = Math.round(i);
    return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clamp_css_float(f) {
    return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parse_css_int(str) {
    if (str[str.length - 1] === '%') {
        return clamp_css_byte(parseFloat(str) / 100 * 255);
    }
    return clamp_css_byte(parseInt(str));
}
function parse_css_float(str) {
    if (str[str.length - 1] === '%') {
        return clamp_css_float(parseFloat(str) / 100);
    }
    return clamp_css_float(parseFloat(str));
}
function css_hue_to_rgb(m1, m2, h) {
    if (h < 0) {
        h += 1;
    } else if (h > 1) {
        h -= 1;
    }
    if (h * 6 < 1) {
        return m1 + (m2 - m1) * h * 6;
    }
    if (h * 2 < 1) {
        return m2;
    }
    if (h * 3 < 2) {
        return m1 + (m2 - m1) * (2 / 3 - h) * 6;
    }
    return m1;
}
function parseCSSColor(css_str) {
    var str = css_str.replace(/ /g, '').toLowerCase();
    if (str in kCSSColorTable) {
        return kCSSColorTable[str].slice();
    }
    if (str[0] === '#') {
        if (str.length === 4) {
            var iv = parseInt(str.substr(1), 16);
            if (!(iv >= 0 && iv <= 4095)) {
                return null;
            }
            return [
                (iv & 3840) >> 4 | (iv & 3840) >> 8,
                iv & 240 | (iv & 240) >> 4,
                iv & 15 | (iv & 15) << 4,
                1
            ];
        } else if (str.length === 7) {
            var iv = parseInt(str.substr(1), 16);
            if (!(iv >= 0 && iv <= 16777215)) {
                return null;
            }
            return [
                (iv & 16711680) >> 16,
                (iv & 65280) >> 8,
                iv & 255,
                1
            ];
        }
        return null;
    }
    var op = str.indexOf('('), ep = str.indexOf(')');
    if (op !== -1 && ep + 1 === str.length) {
        var fname = str.substr(0, op);
        var params = str.substr(op + 1, ep - (op + 1)).split(',');
        var alpha = 1;
        switch (fname) {
        case 'rgba':
            if (params.length !== 4) {
                return null;
            }
            alpha = parse_css_float(params.pop());
        case 'rgb':
            if (params.length !== 3) {
                return null;
            }
            return [
                parse_css_int(params[0]),
                parse_css_int(params[1]),
                parse_css_int(params[2]),
                alpha
            ];
        case 'hsla':
            if (params.length !== 4) {
                return null;
            }
            alpha = parse_css_float(params.pop());
        case 'hsl':
            if (params.length !== 3) {
                return null;
            }
            var h = (parseFloat(params[0]) % 360 + 360) % 360 / 360;
            var s = parse_css_float(params[1]);
            var l = parse_css_float(params[2]);
            var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
            var m1 = l * 2 - m2;
            return [
                clamp_css_byte(css_hue_to_rgb(m1, m2, h + 1 / 3) * 255),
                clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),
                clamp_css_byte(css_hue_to_rgb(m1, m2, h - 1 / 3) * 255),
                alpha
            ];
        default:
            return null;
        }
    }
    return null;
}
try {
    exports.parseCSSColor = parseCSSColor;
} catch (e) {
}
});
var csscolorparser_1 = csscolorparser.parseCSSColor;

var Color = function Color(r, g, b, a) {
    if (a === void 0)
        a = 1;
    this.r = r;
    this.g = g;
    this.b = b;
    this.a = a;
};
Color.parse = function parse(input) {
    if (!input) {
        return undefined;
    }
    if (input instanceof Color) {
        return input;
    }
    if (typeof input !== 'string') {
        return undefined;
    }
    var rgba = csscolorparser_1(input);
    if (!rgba) {
        return undefined;
    }
    return new Color(rgba[0] / 255 * rgba[3], rgba[1] / 255 * rgba[3], rgba[2] / 255 * rgba[3], rgba[3]);
};
Color.prototype.toString = function toString() {
    var ref = this.toArray();
    var r = ref[0];
    var g = ref[1];
    var b = ref[2];
    var a = ref[3];
    return 'rgba(' + Math.round(r) + ',' + Math.round(g) + ',' + Math.round(b) + ',' + a + ')';
};
Color.prototype.toArray = function toArray() {
    var ref = this;
    var r = ref.r;
    var g = ref.g;
    var b = ref.b;
    var a = ref.a;
    return a === 0 ? [
        0,
        0,
        0,
        0
    ] : [
        r * 255 / a,
        g * 255 / a,
        b * 255 / a,
        a
    ];
};
Color.black = new Color(0, 0, 0, 1);
Color.white = new Color(1, 1, 1, 1);
Color.transparent = new Color(0, 0, 0, 0);
Color.red = new Color(1, 0, 0, 1);

var Collator = function Collator(caseSensitive, diacriticSensitive, locale) {
    if (caseSensitive) {
        this.sensitivity = diacriticSensitive ? 'variant' : 'case';
    } else {
        this.sensitivity = diacriticSensitive ? 'accent' : 'base';
    }
    this.locale = locale;
    this.collator = new Intl.Collator(this.locale ? this.locale : [], {
        sensitivity: this.sensitivity,
        usage: 'search'
    });
};
Collator.prototype.compare = function compare(lhs, rhs) {
    return this.collator.compare(lhs, rhs);
};
Collator.prototype.resolvedLocale = function resolvedLocale() {
    return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale;
};

var FormattedSection = function FormattedSection(text, image, scale, fontStack, textColor) {
    this.text = text;
    this.image = image;
    this.scale = scale;
    this.fontStack = fontStack;
    this.textColor = textColor;
};
var Formatted = function Formatted(sections) {
    this.sections = sections;
};
Formatted.fromString = function fromString(unformatted) {
    return new Formatted([new FormattedSection(unformatted, null, null, null, null)]);
};
Formatted.prototype.isEmpty = function isEmpty() {
    if (this.sections.length === 0) {
        return true;
    }
    return !this.sections.some(function (section) {
        return section.text.length !== 0 || section.image && section.image.name.length !== 0;
    });
};
Formatted.factory = function factory(text) {
    if (text instanceof Formatted) {
        return text;
    } else {
        return Formatted.fromString(text);
    }
};
Formatted.prototype.toString = function toString() {
    if (this.sections.length === 0) {
        return '';
    }
    return this.sections.map(function (section) {
        return section.text;
    }).join('');
};
Formatted.prototype.serialize = function serialize() {
    var serialized = ['format'];
    for (var i = 0, list = this.sections; i < list.length; i += 1) {
        var section = list[i];
        if (section.image) {
            serialized.push([
                'image',
                section.image.name
            ]);
            continue;
        }
        serialized.push(section.text);
        var options = {};
        if (section.fontStack) {
            options['text-font'] = [
                'literal',
                section.fontStack.split(',')
            ];
        }
        if (section.scale) {
            options['font-scale'] = section.scale;
        }
        if (section.textColor) {
            options['text-color'] = ['rgba'].concat(section.textColor.toArray());
        }
        serialized.push(options);
    }
    return serialized;
};

var ResolvedImage = function ResolvedImage(options) {
    this.name = options.name;
    this.available = options.available;
};
ResolvedImage.prototype.toString = function toString() {
    return this.name;
};
ResolvedImage.fromString = function fromString(name) {
    if (!name) {
        return null;
    }
    return new ResolvedImage({
        name: name,
        available: false
    });
};
ResolvedImage.prototype.serialize = function serialize() {
    return [
        'image',
        this.name
    ];
};

function validateRGBA(r, g, b, a) {
    if (!(typeof r === 'number' && r >= 0 && r <= 255 && typeof g === 'number' && g >= 0 && g <= 255 && typeof b === 'number' && b >= 0 && b <= 255)) {
        var value = typeof a === 'number' ? [
            r,
            g,
            b,
            a
        ] : [
            r,
            g,
            b
        ];
        return 'Invalid rgba value [' + value.join(', ') + ']: \'r\', \'g\', and \'b\' must be between 0 and 255.';
    }
    if (!(typeof a === 'undefined' || typeof a === 'number' && a >= 0 && a <= 1)) {
        return 'Invalid rgba value [' + [
            r,
            g,
            b,
            a
        ].join(', ') + ']: \'a\' must be between 0 and 1.';
    }
    return null;
}
function isValue(mixed) {
    if (mixed === null) {
        return true;
    } else if (typeof mixed === 'string') {
        return true;
    } else if (typeof mixed === 'boolean') {
        return true;
    } else if (typeof mixed === 'number') {
        return true;
    } else if (mixed instanceof Color) {
        return true;
    } else if (mixed instanceof Collator) {
        return true;
    } else if (mixed instanceof Formatted) {
        return true;
    } else if (mixed instanceof ResolvedImage) {
        return true;
    } else if (Array.isArray(mixed)) {
        for (var i = 0, list = mixed; i < list.length; i += 1) {
            var item = list[i];
            if (!isValue(item)) {
                return false;
            }
        }
        return true;
    } else if (typeof mixed === 'object') {
        for (var key in mixed) {
            if (!isValue(mixed[key])) {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}
function typeOf(value) {
    if (value === null) {
        return NullType;
    } else if (typeof value === 'string') {
        return StringType;
    } else if (typeof value === 'boolean') {
        return BooleanType;
    } else if (typeof value === 'number') {
        return NumberType;
    } else if (value instanceof Color) {
        return ColorType;
    } else if (value instanceof Collator) {
        return CollatorType;
    } else if (value instanceof Formatted) {
        return FormattedType;
    } else if (value instanceof ResolvedImage) {
        return ResolvedImageType;
    } else if (Array.isArray(value)) {
        var length = value.length;
        var itemType;
        for (var i = 0, list = value; i < list.length; i += 1) {
            var item = list[i];
            var t = typeOf(item);
            if (!itemType) {
                itemType = t;
            } else if (itemType === t) {
                continue;
            } else {
                itemType = ValueType;
                break;
            }
        }
        return array(itemType || ValueType, length);
    } else {
        return ObjectType;
    }
}
function toString$1(value) {
    var type = typeof value;
    if (value === null) {
        return '';
    } else if (type === 'string' || type === 'number' || type === 'boolean') {
        return String(value);
    } else if (value instanceof Color || value instanceof Formatted || value instanceof ResolvedImage) {
        return value.toString();
    } else {
        return JSON.stringify(value);
    }
}

var Literal = function Literal(type, value) {
    this.type = type;
    this.value = value;
};
Literal.parse = function parse(args, context) {
    if (args.length !== 2) {
        return context.error('\'literal\' expression requires exactly one argument, but found ' + (args.length - 1) + ' instead.');
    }
    if (!isValue(args[1])) {
        return context.error('invalid value');
    }
    var value = args[1];
    var type = typeOf(value);
    var expected = context.expectedType;
    if (type.kind === 'array' && type.N === 0 && expected && expected.kind === 'array' && (typeof expected.N !== 'number' || expected.N === 0)) {
        type = expected;
    }
    return new Literal(type, value);
};
Literal.prototype.evaluate = function evaluate() {
    return this.value;
};
Literal.prototype.eachChild = function eachChild() {
};
Literal.prototype.outputDefined = function outputDefined() {
    return true;
};
Literal.prototype.serialize = function serialize() {
    if (this.type.kind === 'array' || this.type.kind === 'object') {
        return [
            'literal',
            this.value
        ];
    } else if (this.value instanceof Color) {
        return ['rgba'].concat(this.value.toArray());
    } else if (this.value instanceof Formatted) {
        return this.value.serialize();
    } else {
        return this.value;
    }
};

var RuntimeError = function RuntimeError(message) {
    this.name = 'ExpressionEvaluationError';
    this.message = message;
};
RuntimeError.prototype.toJSON = function toJSON() {
    return this.message;
};

var types = {
    string: StringType,
    number: NumberType,
    boolean: BooleanType,
    object: ObjectType
};
var Assertion = function Assertion(type, args) {
    this.type = type;
    this.args = args;
};
Assertion.parse = function parse(args, context) {
    if (args.length < 2) {
        return context.error('Expected at least one argument.');
    }
    var i = 1;
    var type;
    var name = args[0];
    if (name === 'array') {
        var itemType;
        if (args.length > 2) {
            var type$1 = args[1];
            if (typeof type$1 !== 'string' || !(type$1 in types) || type$1 === 'object') {
                return context.error('The item type argument of "array" must be one of string, number, boolean', 1);
            }
            itemType = types[type$1];
            i++;
        } else {
            itemType = ValueType;
        }
        var N;
        if (args.length > 3) {
            if (args[2] !== null && (typeof args[2] !== 'number' || args[2] < 0 || args[2] !== Math.floor(args[2]))) {
                return context.error('The length argument to "array" must be a positive integer literal', 2);
            }
            N = args[2];
            i++;
        }
        type = array(itemType, N);
    } else {
        type = types[name];
    }
    var parsed = [];
    for (; i < args.length; i++) {
        var input = context.parse(args[i], i, ValueType);
        if (!input) {
            return null;
        }
        parsed.push(input);
    }
    return new Assertion(type, parsed);
};
Assertion.prototype.evaluate = function evaluate(ctx) {
    for (var i = 0; i < this.args.length; i++) {
        var value = this.args[i].evaluate(ctx);
        var error = checkSubtype(this.type, typeOf(value));
        if (!error) {
            return value;
        } else if (i === this.args.length - 1) {
            throw new RuntimeError('Expected value to be of type ' + toString(this.type) + ', but found ' + toString(typeOf(value)) + ' instead.');
        }
    }
    return null;
};
Assertion.prototype.eachChild = function eachChild(fn) {
    this.args.forEach(fn);
};
Assertion.prototype.outputDefined = function outputDefined() {
    return this.args.every(function (arg) {
        return arg.outputDefined();
    });
};
Assertion.prototype.serialize = function serialize() {
    var type = this.type;
    var serialized = [type.kind];
    if (type.kind === 'array') {
        var itemType = type.itemType;
        if (itemType.kind === 'string' || itemType.kind === 'number' || itemType.kind === 'boolean') {
            serialized.push(itemType.kind);
            var N = type.N;
            if (typeof N === 'number' || this.args.length > 1) {
                serialized.push(N);
            }
        }
    }
    return serialized.concat(this.args.map(function (arg) {
        return arg.serialize();
    }));
};

var FormatExpression = function FormatExpression(sections) {
    this.type = FormattedType;
    this.sections = sections;
};
FormatExpression.parse = function parse(args, context) {
    if (args.length < 2) {
        return context.error('Expected at least one argument.');
    }
    var firstArg = args[1];
    if (!Array.isArray(firstArg) && typeof firstArg === 'object') {
        return context.error('First argument must be an image or text section.');
    }
    var sections = [];
    var nextTokenMayBeObject = false;
    for (var i = 1; i <= args.length - 1; ++i) {
        var arg = args[i];
        if (nextTokenMayBeObject && typeof arg === 'object' && !Array.isArray(arg)) {
            nextTokenMayBeObject = false;
            var scale = null;
            if (arg['font-scale']) {
                scale = context.parse(arg['font-scale'], 1, NumberType);
                if (!scale) {
                    return null;
                }
            }
            var font = null;
            if (arg['text-font']) {
                font = context.parse(arg['text-font'], 1, array(StringType));
                if (!font) {
                    return null;
                }
            }
            var textColor = null;
            if (arg['text-color']) {
                textColor = context.parse(arg['text-color'], 1, ColorType);
                if (!textColor) {
                    return null;
                }
            }
            var lastExpression = sections[sections.length - 1];
            lastExpression.scale = scale;
            lastExpression.font = font;
            lastExpression.textColor = textColor;
        } else {
            var content = context.parse(args[i], 1, ValueType);
            if (!content) {
                return null;
            }
            var kind = content.type.kind;
            if (kind !== 'string' && kind !== 'value' && kind !== 'null' && kind !== 'resolvedImage') {
                return context.error('Formatted text type must be \'string\', \'value\', \'image\' or \'null\'.');
            }
            nextTokenMayBeObject = true;
            sections.push({
                content: content,
                scale: null,
                font: null,
                textColor: null
            });
        }
    }
    return new FormatExpression(sections);
};
FormatExpression.prototype.evaluate = function evaluate(ctx) {
    var evaluateSection = function (section) {
        var evaluatedContent = section.content.evaluate(ctx);
        if (typeOf(evaluatedContent) === ResolvedImageType) {
            return new FormattedSection('', evaluatedContent, null, null, null);
        }
        return new FormattedSection(toString$1(evaluatedContent), null, section.scale ? section.scale.evaluate(ctx) : null, section.font ? section.font.evaluate(ctx).join(',') : null, section.textColor ? section.textColor.evaluate(ctx) : null);
    };
    return new Formatted(this.sections.map(evaluateSection));
};
FormatExpression.prototype.eachChild = function eachChild(fn) {
    for (var i = 0, list = this.sections; i < list.length; i += 1) {
        var section = list[i];
        fn(section.content);
        if (section.scale) {
            fn(section.scale);
        }
        if (section.font) {
            fn(section.font);
        }
        if (section.textColor) {
            fn(section.textColor);
        }
    }
};
FormatExpression.prototype.outputDefined = function outputDefined() {
    return false;
};
FormatExpression.prototype.serialize = function serialize() {
    var serialized = ['format'];
    for (var i = 0, list = this.sections; i < list.length; i += 1) {
        var section = list[i];
        serialized.push(section.content.serialize());
        var options = {};
        if (section.scale) {
            options['font-scale'] = section.scale.serialize();
        }
        if (section.font) {
            options['text-font'] = section.font.serialize();
        }
        if (section.textColor) {
            options['text-color'] = section.textColor.serialize();
        }
        serialized.push(options);
    }
    return serialized;
};

var ImageExpression = function ImageExpression(input) {
    this.type = ResolvedImageType;
    this.input = input;
};
ImageExpression.parse = function parse(args, context) {
    if (args.length !== 2) {
        return context.error('Expected two arguments.');
    }
    var name = context.parse(args[1], 1, StringType);
    if (!name) {
        return context.error('No image name provided.');
    }
    return new ImageExpression(name);
};
ImageExpression.prototype.evaluate = function evaluate(ctx) {
    var evaluatedImageName = this.input.evaluate(ctx);
    var value = ResolvedImage.fromString(evaluatedImageName);
    if (value && ctx.availableImages) {
        value.available = ctx.availableImages.indexOf(evaluatedImageName) > -1;
    }
    return value;
};
ImageExpression.prototype.eachChild = function eachChild(fn) {
    fn(this.input);
};
ImageExpression.prototype.outputDefined = function outputDefined() {
    return false;
};
ImageExpression.prototype.serialize = function serialize() {
    return [
        'image',
        this.input.serialize()
    ];
};

var types$1 = {
    'to-boolean': BooleanType,
    'to-color': ColorType,
    'to-number': NumberType,
    'to-string': StringType
};
var Coercion = function Coercion(type, args) {
    this.type = type;
    this.args = args;
};
Coercion.parse = function parse(args, context) {
    if (args.length < 2) {
        return context.error('Expected at least one argument.');
    }
    var name = args[0];
    if ((name === 'to-boolean' || name === 'to-string') && args.length !== 2) {
        return context.error('Expected one argument.');
    }
    var type = types$1[name];
    var parsed = [];
    for (var i = 1; i < args.length; i++) {
        var input = context.parse(args[i], i, ValueType);
        if (!input) {
            return null;
        }
        parsed.push(input);
    }
    return new Coercion(type, parsed);
};
Coercion.prototype.evaluate = function evaluate(ctx) {
    if (this.type.kind === 'boolean') {
        return Boolean(this.args[0].evaluate(ctx));
    } else if (this.type.kind === 'color') {
        var input;
        var error;
        for (var i = 0, list = this.args; i < list.length; i += 1) {
            var arg = list[i];
            input = arg.evaluate(ctx);
            error = null;
            if (input instanceof Color) {
                return input;
            } else if (typeof input === 'string') {
                var c = ctx.parseColor(input);
                if (c) {
                    return c;
                }
            } else if (Array.isArray(input)) {
                if (input.length < 3 || input.length > 4) {
                    error = 'Invalid rbga value ' + JSON.stringify(input) + ': expected an array containing either three or four numeric values.';
                } else {
                    error = validateRGBA(input[0], input[1], input[2], input[3]);
                }
                if (!error) {
                    return new Color(input[0] / 255, input[1] / 255, input[2] / 255, input[3]);
                }
            }
        }
        throw new RuntimeError(error || 'Could not parse color from value \'' + (typeof input === 'string' ? input : String(JSON.stringify(input))) + '\'');
    } else if (this.type.kind === 'number') {
        var value = null;
        for (var i$1 = 0, list$1 = this.args; i$1 < list$1.length; i$1 += 1) {
            var arg$1 = list$1[i$1];
            value = arg$1.evaluate(ctx);
            if (value === null) {
                return 0;
            }
            var num = Number(value);
            if (isNaN(num)) {
                continue;
            }
            return num;
        }
        throw new RuntimeError('Could not convert ' + JSON.stringify(value) + ' to number.');
    } else if (this.type.kind === 'formatted') {
        return Formatted.fromString(toString$1(this.args[0].evaluate(ctx)));
    } else if (this.type.kind === 'resolvedImage') {
        return ResolvedImage.fromString(toString$1(this.args[0].evaluate(ctx)));
    } else {
        return toString$1(this.args[0].evaluate(ctx));
    }
};
Coercion.prototype.eachChild = function eachChild(fn) {
    this.args.forEach(fn);
};
Coercion.prototype.outputDefined = function outputDefined() {
    return this.args.every(function (arg) {
        return arg.outputDefined();
    });
};
Coercion.prototype.serialize = function serialize() {
    if (this.type.kind === 'formatted') {
        return new FormatExpression([{
                content: this.args[0],
                scale: null,
                font: null,
                textColor: null
            }]).serialize();
    }
    if (this.type.kind === 'resolvedImage') {
        return new ImageExpression(this.args[0]).serialize();
    }
    var serialized = ['to-' + this.type.kind];
    this.eachChild(function (child) {
        serialized.push(child.serialize());
    });
    return serialized;
};

var geometryTypes = [
    'Unknown',
    'Point',
    'LineString',
    'Polygon'
];
var EvaluationContext = function EvaluationContext() {
    this.globals = null;
    this.feature = null;
    this.featureState = null;
    this.formattedSection = null;
    this._parseColorCache = {};
    this.availableImages = null;
    this.canonical = null;
};
EvaluationContext.prototype.id = function id() {
    return this.feature && 'id' in this.feature ? this.feature.id : null;
};
EvaluationContext.prototype.geometryType = function geometryType() {
    return this.feature ? typeof this.feature.type === 'number' ? geometryTypes[this.feature.type] : this.feature.type : null;
};
EvaluationContext.prototype.geometry = function geometry() {
    return this.feature && 'geometry' in this.feature ? this.feature.geometry : null;
};
EvaluationContext.prototype.canonicalID = function canonicalID() {
    return this.canonical;
};
EvaluationContext.prototype.properties = function properties() {
    return this.feature && this.feature.properties || {};
};
EvaluationContext.prototype.parseColor = function parseColor(input) {
    var cached = this._parseColorCache[input];
    if (!cached) {
        cached = this._parseColorCache[input] = Color.parse(input);
    }
    return cached;
};

var CompoundExpression = function CompoundExpression(name, type, evaluate, args) {
    this.name = name;
    this.type = type;
    this._evaluate = evaluate;
    this.args = args;
};
CompoundExpression.prototype.evaluate = function evaluate(ctx) {
    return this._evaluate(ctx, this.args);
};
CompoundExpression.prototype.eachChild = function eachChild(fn) {
    this.args.forEach(fn);
};
CompoundExpression.prototype.outputDefined = function outputDefined() {
    return false;
};
CompoundExpression.prototype.serialize = function serialize() {
    return [this.name].concat(this.args.map(function (arg) {
        return arg.serialize();
    }));
};
CompoundExpression.parse = function parse(args, context) {
    var ref$1;
    var op = args[0];
    var definition = CompoundExpression.definitions[op];
    if (!definition) {
        return context.error('Unknown expression "' + op + '". If you wanted a literal array, use ["literal", [...]].', 0);
    }
    var type = Array.isArray(definition) ? definition[0] : definition.type;
    var availableOverloads = Array.isArray(definition) ? [[
            definition[1],
            definition[2]
        ]] : definition.overloads;
    var overloads = availableOverloads.filter(function (ref) {
        var signature = ref[0];
        return !Array.isArray(signature) || signature.length === args.length - 1;
    });
    var signatureContext = null;
    for (var i$3 = 0, list = overloads; i$3 < list.length; i$3 += 1) {
        var ref = list[i$3];
        var params = ref[0];
        var evaluate = ref[1];
        signatureContext = new ParsingContext(context.registry, context.path, null, context.scope);
        var parsedArgs = [];
        var argParseFailed = false;
        for (var i = 1; i < args.length; i++) {
            var arg = args[i];
            var expectedType = Array.isArray(params) ? params[i - 1] : params.type;
            var parsed = signatureContext.parse(arg, 1 + parsedArgs.length, expectedType);
            if (!parsed) {
                argParseFailed = true;
                break;
            }
            parsedArgs.push(parsed);
        }
        if (argParseFailed) {
            continue;
        }
        if (Array.isArray(params)) {
            if (params.length !== parsedArgs.length) {
                signatureContext.error('Expected ' + params.length + ' arguments, but found ' + parsedArgs.length + ' instead.');
                continue;
            }
        }
        for (var i$1 = 0; i$1 < parsedArgs.length; i$1++) {
            var expected = Array.isArray(params) ? params[i$1] : params.type;
            var arg$1 = parsedArgs[i$1];
            signatureContext.concat(i$1 + 1).checkSubtype(expected, arg$1.type);
        }
        if (signatureContext.errors.length === 0) {
            return new CompoundExpression(op, type, evaluate, parsedArgs);
        }
    }
    if (overloads.length === 1) {
        (ref$1 = context.errors).push.apply(ref$1, signatureContext.errors);
    } else {
        var expected$1 = overloads.length ? overloads : availableOverloads;
        var signatures = expected$1.map(function (ref) {
            var params = ref[0];
            return stringifySignature(params);
        }).join(' | ');
        var actualTypes = [];
        for (var i$2 = 1; i$2 < args.length; i$2++) {
            var parsed$1 = context.parse(args[i$2], 1 + actualTypes.length);
            if (!parsed$1) {
                return null;
            }
            actualTypes.push(toString(parsed$1.type));
        }
        context.error('Expected arguments of type ' + signatures + ', but found (' + actualTypes.join(', ') + ') instead.');
    }
    return null;
};
CompoundExpression.register = function register(registry, definitions) {
    CompoundExpression.definitions = definitions;
    for (var name in definitions) {
        registry[name] = CompoundExpression;
    }
};
function stringifySignature(signature) {
    if (Array.isArray(signature)) {
        return '(' + signature.map(toString).join(', ') + ')';
    } else {
        return '(' + toString(signature.type) + '...)';
    }
}

var CollatorExpression = function CollatorExpression(caseSensitive, diacriticSensitive, locale) {
    this.type = CollatorType;
    this.locale = locale;
    this.caseSensitive = caseSensitive;
    this.diacriticSensitive = diacriticSensitive;
};
CollatorExpression.parse = function parse(args, context) {
    if (args.length !== 2) {
        return context.error('Expected one argument.');
    }
    var options = args[1];
    if (typeof options !== 'object' || Array.isArray(options)) {
        return context.error('Collator options argument must be an object.');
    }
    var caseSensitive = context.parse(options['case-sensitive'] === undefined ? false : options['case-sensitive'], 1, BooleanType);
    if (!caseSensitive) {
        return null;
    }
    var diacriticSensitive = context.parse(options['diacritic-sensitive'] === undefined ? false : options['diacritic-sensitive'], 1, BooleanType);
    if (!diacriticSensitive) {
        return null;
    }
    var locale = null;
    if (options['locale']) {
        locale = context.parse(options['locale'], 1, StringType);
        if (!locale) {
            return null;
        }
    }
    return new CollatorExpression(caseSensitive, diacriticSensitive, locale);
};
CollatorExpression.prototype.evaluate = function evaluate(ctx) {
    return new Collator(this.caseSensitive.evaluate(ctx), this.diacriticSensitive.evaluate(ctx), this.locale ? this.locale.evaluate(ctx) : null);
};
CollatorExpression.prototype.eachChild = function eachChild(fn) {
    fn(this.caseSensitive);
    fn(this.diacriticSensitive);
    if (this.locale) {
        fn(this.locale);
    }
};
CollatorExpression.prototype.outputDefined = function outputDefined() {
    return false;
};
CollatorExpression.prototype.serialize = function serialize() {
    var options = {};
    options['case-sensitive'] = this.caseSensitive.serialize();
    options['diacritic-sensitive'] = this.diacriticSensitive.serialize();
    if (this.locale) {
        options['locale'] = this.locale.serialize();
    }
    return [
        'collator',
        options
    ];
};

var EXTENT = 8192;
function updateBBox(bbox, coord) {
    bbox[0] = Math.min(bbox[0], coord[0]);
    bbox[1] = Math.min(bbox[1], coord[1]);
    bbox[2] = Math.max(bbox[2], coord[0]);
    bbox[3] = Math.max(bbox[3], coord[1]);
}
function mercatorXfromLng(lng) {
    return (180 + lng) / 360;
}
function mercatorYfromLat(lat) {
    return (180 - 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360))) / 360;
}
function boxWithinBox(bbox1, bbox2) {
    if (bbox1[0] <= bbox2[0]) {
        return false;
    }
    if (bbox1[2] >= bbox2[2]) {
        return false;
    }
    if (bbox1[1] <= bbox2[1]) {
        return false;
    }
    if (bbox1[3] >= bbox2[3]) {
        return false;
    }
    return true;
}
function getTileCoordinates(p, canonical) {
    var x = mercatorXfromLng(p[0]);
    var y = mercatorYfromLat(p[1]);
    var tilesAtZoom = Math.pow(2, canonical.z);
    return [
        Math.round(x * tilesAtZoom * EXTENT),
        Math.round(y * tilesAtZoom * EXTENT)
    ];
}
function onBoundary(p, p1, p2) {
    var x1 = p[0] - p1[0];
    var y1 = p[1] - p1[1];
    var x2 = p[0] - p2[0];
    var y2 = p[1] - p2[1];
    return x1 * y2 - x2 * y1 === 0 && x1 * x2 <= 0 && y1 * y2 <= 0;
}
function rayIntersect(p, p1, p2) {
    return p1[1] > p[1] !== p2[1] > p[1] && p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0];
}
function pointWithinPolygon(point, rings) {
    var inside = false;
    for (var i = 0, len = rings.length; i < len; i++) {
        var ring = rings[i];
        for (var j = 0, len2 = ring.length; j < len2 - 1; j++) {
            if (onBoundary(point, ring[j], ring[j + 1])) {
                return false;
            }
            if (rayIntersect(point, ring[j], ring[j + 1])) {
                inside = !inside;
            }
        }
    }
    return inside;
}
function pointWithinPolygons(point, polygons) {
    for (var i = 0; i < polygons.length; i++) {
        if (pointWithinPolygon(point, polygons[i])) {
            return true;
        }
    }
    return false;
}
function perp(v1, v2) {
    return v1[0] * v2[1] - v1[1] * v2[0];
}
function twoSided(p1, p2, q1, q2) {
    var x1 = p1[0] - q1[0];
    var y1 = p1[1] - q1[1];
    var x2 = p2[0] - q1[0];
    var y2 = p2[1] - q1[1];
    var x3 = q2[0] - q1[0];
    var y3 = q2[1] - q1[1];
    var det1 = x1 * y3 - x3 * y1;
    var det2 = x2 * y3 - x3 * y2;
    if (det1 > 0 && det2 < 0 || det1 < 0 && det2 > 0) {
        return true;
    }
    return false;
}
function lineIntersectLine(a, b, c, d) {
    var vectorP = [
        b[0] - a[0],
        b[1] - a[1]
    ];
    var vectorQ = [
        d[0] - c[0],
        d[1] - c[1]
    ];
    if (perp(vectorQ, vectorP) === 0) {
        return false;
    }
    if (twoSided(a, b, c, d) && twoSided(c, d, a, b)) {
        return true;
    }
    return false;
}
function lineIntersectPolygon(p1, p2, polygon) {
    for (var i = 0, list = polygon; i < list.length; i += 1) {
        var ring = list[i];
        for (var j = 0; j < ring.length - 1; ++j) {
            if (lineIntersectLine(p1, p2, ring[j], ring[j + 1])) {
                return true;
            }
        }
    }
    return false;
}
function lineStringWithinPolygon(line, polygon) {
    for (var i = 0; i < line.length; ++i) {
        if (!pointWithinPolygon(line[i], polygon)) {
            return false;
        }
    }
    for (var i$1 = 0; i$1 < line.length - 1; ++i$1) {
        if (lineIntersectPolygon(line[i$1], line[i$1 + 1], polygon)) {
            return false;
        }
    }
    return true;
}
function lineStringWithinPolygons(line, polygons) {
    for (var i = 0; i < polygons.length; i++) {
        if (lineStringWithinPolygon(line, polygons[i])) {
            return true;
        }
    }
    return false;
}
function getTilePolygon(coordinates, bbox, canonical) {
    var polygon = [];
    for (var i = 0; i < coordinates.length; i++) {
        var ring = [];
        for (var j = 0; j < coordinates[i].length; j++) {
            var coord = getTileCoordinates(coordinates[i][j], canonical);
            updateBBox(bbox, coord);
            ring.push(coord);
        }
        polygon.push(ring);
    }
    return polygon;
}
function getTilePolygons(coordinates, bbox, canonical) {
    var polygons = [];
    for (var i = 0; i < coordinates.length; i++) {
        var polygon = getTilePolygon(coordinates[i], bbox, canonical);
        polygons.push(polygon);
    }
    return polygons;
}
function updatePoint(p, bbox, polyBBox, worldSize) {
    if (p[0] < polyBBox[0] || p[0] > polyBBox[2]) {
        var halfWorldSize = worldSize * 0.5;
        var shift = p[0] - polyBBox[0] > halfWorldSize ? -worldSize : polyBBox[0] - p[0] > halfWorldSize ? worldSize : 0;
        if (shift === 0) {
            shift = p[0] - polyBBox[2] > halfWorldSize ? -worldSize : polyBBox[2] - p[0] > halfWorldSize ? worldSize : 0;
        }
        p[0] += shift;
    }
    updateBBox(bbox, p);
}
function resetBBox(bbox) {
    bbox[0] = bbox[1] = Infinity;
    bbox[2] = bbox[3] = -Infinity;
}
function getTilePoints(geometry, pointBBox, polyBBox, canonical) {
    var worldSize = Math.pow(2, canonical.z) * EXTENT;
    var shifts = [
        canonical.x * EXTENT,
        canonical.y * EXTENT
    ];
    var tilePoints = [];
    for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
        var points = list$1[i$1];
        for (var i = 0, list = points; i < list.length; i += 1) {
            var point = list[i];
            var p = [
                point.x + shifts[0],
                point.y + shifts[1]
            ];
            updatePoint(p, pointBBox, polyBBox, worldSize);
            tilePoints.push(p);
        }
    }
    return tilePoints;
}
function getTileLines(geometry, lineBBox, polyBBox, canonical) {
    var worldSize = Math.pow(2, canonical.z) * EXTENT;
    var shifts = [
        canonical.x * EXTENT,
        canonical.y * EXTENT
    ];
    var tileLines = [];
    for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
        var line = list$1[i$1];
        var tileLine = [];
        for (var i = 0, list = line; i < list.length; i += 1) {
            var point = list[i];
            var p = [
                point.x + shifts[0],
                point.y + shifts[1]
            ];
            updateBBox(lineBBox, p);
            tileLine.push(p);
        }
        tileLines.push(tileLine);
    }
    if (lineBBox[2] - lineBBox[0] <= worldSize / 2) {
        resetBBox(lineBBox);
        for (var i$3 = 0, list$3 = tileLines; i$3 < list$3.length; i$3 += 1) {
            var line$1 = list$3[i$3];
            for (var i$2 = 0, list$2 = line$1; i$2 < list$2.length; i$2 += 1) {
                var p$1 = list$2[i$2];
                updatePoint(p$1, lineBBox, polyBBox, worldSize);
            }
        }
    }
    return tileLines;
}
function pointsWithinPolygons(ctx, polygonGeometry) {
    var pointBBox = [
        Infinity,
        Infinity,
        -Infinity,
        -Infinity
    ];
    var polyBBox = [
        Infinity,
        Infinity,
        -Infinity,
        -Infinity
    ];
    var canonical = ctx.canonicalID();
    if (polygonGeometry.type === 'Polygon') {
        var tilePolygon = getTilePolygon(polygonGeometry.coordinates, polyBBox, canonical);
        var tilePoints = getTilePoints(ctx.geometry(), pointBBox, polyBBox, canonical);
        if (!boxWithinBox(pointBBox, polyBBox)) {
            return false;
        }
        for (var i = 0, list = tilePoints; i < list.length; i += 1) {
            var point = list[i];
            if (!pointWithinPolygon(point, tilePolygon)) {
                return false;
            }
        }
    }
    if (polygonGeometry.type === 'MultiPolygon') {
        var tilePolygons = getTilePolygons(polygonGeometry.coordinates, polyBBox, canonical);
        var tilePoints$1 = getTilePoints(ctx.geometry(), pointBBox, polyBBox, canonical);
        if (!boxWithinBox(pointBBox, polyBBox)) {
            return false;
        }
        for (var i$1 = 0, list$1 = tilePoints$1; i$1 < list$1.length; i$1 += 1) {
            var point$1 = list$1[i$1];
            if (!pointWithinPolygons(point$1, tilePolygons)) {
                return false;
            }
        }
    }
    return true;
}
function linesWithinPolygons(ctx, polygonGeometry) {
    var lineBBox = [
        Infinity,
        Infinity,
        -Infinity,
        -Infinity
    ];
    var polyBBox = [
        Infinity,
        Infinity,
        -Infinity,
        -Infinity
    ];
    var canonical = ctx.canonicalID();
    if (polygonGeometry.type === 'Polygon') {
        var tilePolygon = getTilePolygon(polygonGeometry.coordinates, polyBBox, canonical);
        var tileLines = getTileLines(ctx.geometry(), lineBBox, polyBBox, canonical);
        if (!boxWithinBox(lineBBox, polyBBox)) {
            return false;
        }
        for (var i = 0, list = tileLines; i < list.length; i += 1) {
            var line = list[i];
            if (!lineStringWithinPolygon(line, tilePolygon)) {
                return false;
            }
        }
    }
    if (polygonGeometry.type === 'MultiPolygon') {
        var tilePolygons = getTilePolygons(polygonGeometry.coordinates, polyBBox, canonical);
        var tileLines$1 = getTileLines(ctx.geometry(), lineBBox, polyBBox, canonical);
        if (!boxWithinBox(lineBBox, polyBBox)) {
            return false;
        }
        for (var i$1 = 0, list$1 = tileLines$1; i$1 < list$1.length; i$1 += 1) {
            var line$1 = list$1[i$1];
            if (!lineStringWithinPolygons(line$1, tilePolygons)) {
                return false;
            }
        }
    }
    return true;
}
var Within = function Within(geojson, geometries) {
    this.type = BooleanType;
    this.geojson = geojson;
    this.geometries = geometries;
};
Within.parse = function parse(args, context) {
    if (args.length !== 2) {
        return context.error('\'within\' expression requires exactly one argument, but found ' + (args.length - 1) + ' instead.');
    }
    if (isValue(args[1])) {
        var geojson = args[1];
        if (geojson.type === 'FeatureCollection') {
            for (var i = 0; i < geojson.features.length; ++i) {
                var type = geojson.features[i].geometry.type;
                if (type === 'Polygon' || type === 'MultiPolygon') {
                    return new Within(geojson, geojson.features[i].geometry);
                }
            }
        } else if (geojson.type === 'Feature') {
            var type$1 = geojson.geometry.type;
            if (type$1 === 'Polygon' || type$1 === 'MultiPolygon') {
                return new Within(geojson, geojson.geometry);
            }
        } else if (geojson.type === 'Polygon' || geojson.type === 'MultiPolygon') {
            return new Within(geojson, geojson);
        }
    }
    return context.error('\'within\' expression requires valid geojson object that contains polygon geometry type.');
};
Within.prototype.evaluate = function evaluate(ctx) {
    if (ctx.geometry() != null && ctx.canonicalID() != null) {
        if (ctx.geometryType() === 'Point') {
            return pointsWithinPolygons(ctx, this.geometries);
        } else if (ctx.geometryType() === 'LineString') {
            return linesWithinPolygons(ctx, this.geometries);
        }
    }
    return false;
};
Within.prototype.eachChild = function eachChild() {
};
Within.prototype.outputDefined = function outputDefined() {
    return true;
};
Within.prototype.serialize = function serialize() {
    return [
        'within',
        this.geojson
    ];
};

function isFeatureConstant(e) {
    if (e instanceof CompoundExpression) {
        if (e.name === 'get' && e.args.length === 1) {
            return false;
        } else if (e.name === 'feature-state') {
            return false;
        } else if (e.name === 'has' && e.args.length === 1) {
            return false;
        } else if (e.name === 'properties' || e.name === 'geometry-type' || e.name === 'id') {
            return false;
        } else if (/^filter-/.test(e.name)) {
            return false;
        }
    }
    if (e instanceof Within) {
        return false;
    }
    var result = true;
    e.eachChild(function (arg) {
        if (result && !isFeatureConstant(arg)) {
            result = false;
        }
    });
    return result;
}
function isStateConstant(e) {
    if (e instanceof CompoundExpression) {
        if (e.name === 'feature-state') {
            return false;
        }
    }
    var result = true;
    e.eachChild(function (arg) {
        if (result && !isStateConstant(arg)) {
            result = false;
        }
    });
    return result;
}
function isGlobalPropertyConstant(e, properties) {
    if (e instanceof CompoundExpression && properties.indexOf(e.name) >= 0) {
        return false;
    }
    var result = true;
    e.eachChild(function (arg) {
        if (result && !isGlobalPropertyConstant(arg, properties)) {
            result = false;
        }
    });
    return result;
}

var Var = function Var(name, boundExpression) {
    this.type = boundExpression.type;
    this.name = name;
    this.boundExpression = boundExpression;
};
Var.parse = function parse(args, context) {
    if (args.length !== 2 || typeof args[1] !== 'string') {
        return context.error('\'var\' expression requires exactly one string literal argument.');
    }
    var name = args[1];
    if (!context.scope.has(name)) {
        return context.error('Unknown variable "' + name + '". Make sure "' + name + '" has been bound in an enclosing "let" expression before using it.', 1);
    }
    return new Var(name, context.scope.get(name));
};
Var.prototype.evaluate = function evaluate(ctx) {
    return this.boundExpression.evaluate(ctx);
};
Var.prototype.eachChild = function eachChild() {
};
Var.prototype.outputDefined = function outputDefined() {
    return false;
};
Var.prototype.serialize = function serialize() {
    return [
        'var',
        this.name
    ];
};

var ParsingContext = function ParsingContext(registry, path, expectedType, scope, errors) {
    if (path === void 0)
        path = [];
    if (scope === void 0)
        scope = new Scope();
    if (errors === void 0)
        errors = [];
    this.registry = registry;
    this.path = path;
    this.key = path.map(function (part) {
        return '[' + part + ']';
    }).join('');
    this.scope = scope;
    this.errors = errors;
    this.expectedType = expectedType;
};
ParsingContext.prototype.parse = function parse(expr, index, expectedType, bindings, options) {
    if (options === void 0)
        options = {};
    if (index) {
        return this.concat(index, expectedType, bindings)._parse(expr, options);
    }
    return this._parse(expr, options);
};
ParsingContext.prototype._parse = function _parse(expr, options) {
    if (expr === null || typeof expr === 'string' || typeof expr === 'boolean' || typeof expr === 'number') {
        expr = [
            'literal',
            expr
        ];
    }
    function annotate(parsed, type, typeAnnotation) {
        if (typeAnnotation === 'assert') {
            return new Assertion(type, [parsed]);
        } else if (typeAnnotation === 'coerce') {
            return new Coercion(type, [parsed]);
        } else {
            return parsed;
        }
    }
    if (Array.isArray(expr)) {
        if (expr.length === 0) {
            return this.error('Expected an array with at least one element. If you wanted a literal array, use ["literal", []].');
        }
        var op = expr[0];
        if (typeof op !== 'string') {
            this.error('Expression name must be a string, but found ' + typeof op + ' instead. If you wanted a literal array, use ["literal", [...]].', 0);
            return null;
        }
        var Expr = this.registry[op];
        if (Expr) {
            var parsed = Expr.parse(expr, this);
            if (!parsed) {
                return null;
            }
            if (this.expectedType) {
                var expected = this.expectedType;
                var actual = parsed.type;
                if ((expected.kind === 'string' || expected.kind === 'number' || expected.kind === 'boolean' || expected.kind === 'object' || expected.kind === 'array') && actual.kind === 'value') {
                    parsed = annotate(parsed, expected, options.typeAnnotation || 'assert');
                } else if ((expected.kind === 'color' || expected.kind === 'formatted' || expected.kind === 'resolvedImage') && (actual.kind === 'value' || actual.kind === 'string')) {
                    parsed = annotate(parsed, expected, options.typeAnnotation || 'coerce');
                } else if (this.checkSubtype(expected, actual)) {
                    return null;
                }
            }
            if (!(parsed instanceof Literal) && parsed.type.kind !== 'resolvedImage' && isConstant(parsed)) {
                var ec = new EvaluationContext();
                try {
                    parsed = new Literal(parsed.type, parsed.evaluate(ec));
                } catch (e) {
                    this.error(e.message);
                    return null;
                }
            }
            return parsed;
        }
        return this.error('Unknown expression "' + op + '". If you wanted a literal array, use ["literal", [...]].', 0);
    } else if (typeof expr === 'undefined') {
        return this.error('\'undefined\' value invalid. Use null instead.');
    } else if (typeof expr === 'object') {
        return this.error('Bare objects invalid. Use ["literal", {...}] instead.');
    } else {
        return this.error('Expected an array, but found ' + typeof expr + ' instead.');
    }
};
ParsingContext.prototype.concat = function concat(index, expectedType, bindings) {
    var path = typeof index === 'number' ? this.path.concat(index) : this.path;
    var scope = bindings ? this.scope.concat(bindings) : this.scope;
    return new ParsingContext(this.registry, path, expectedType || null, scope, this.errors);
};
ParsingContext.prototype.error = function error(error$1) {
    var keys = [], len = arguments.length - 1;
    while (len-- > 0)
        keys[len] = arguments[len + 1];
    var key = '' + this.key + keys.map(function (k) {
        return '[' + k + ']';
    }).join('');
    this.errors.push(new ParsingError(key, error$1));
};
ParsingContext.prototype.checkSubtype = function checkSubtype$1(expected, t) {
    var error = checkSubtype(expected, t);
    if (error) {
        this.error(error);
    }
    return error;
};
function isConstant(expression) {
    if (expression instanceof Var) {
        return isConstant(expression.boundExpression);
    } else if (expression instanceof CompoundExpression && expression.name === 'error') {
        return false;
    } else if (expression instanceof CollatorExpression) {
        return false;
    } else if (expression instanceof Within) {
        return false;
    }
    var isTypeAnnotation = expression instanceof Coercion || expression instanceof Assertion;
    var childrenConstant = true;
    expression.eachChild(function (child) {
        if (isTypeAnnotation) {
            childrenConstant = childrenConstant && isConstant(child);
        } else {
            childrenConstant = childrenConstant && child instanceof Literal;
        }
    });
    if (!childrenConstant) {
        return false;
    }
    return isFeatureConstant(expression) && isGlobalPropertyConstant(expression, [
        'zoom',
        'heatmap-density',
        'line-progress',
        'accumulated',
        'is-supported-script'
    ]);
}

function findStopLessThanOrEqualTo(stops, input) {
    var lastIndex = stops.length - 1;
    var lowerIndex = 0;
    var upperIndex = lastIndex;
    var currentIndex = 0;
    var currentValue, nextValue;
    while (lowerIndex <= upperIndex) {
        currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
        currentValue = stops[currentIndex];
        nextValue = stops[currentIndex + 1];
        if (currentValue <= input) {
            if (currentIndex === lastIndex || input < nextValue) {
                return currentIndex;
            }
            lowerIndex = currentIndex + 1;
        } else if (currentValue > input) {
            upperIndex = currentIndex - 1;
        } else {
            throw new RuntimeError('Input is not a number.');
        }
    }
    return 0;
}

var Step = function Step(type, input, stops) {
    this.type = type;
    this.input = input;
    this.labels = [];
    this.outputs = [];
    for (var i = 0, list = stops; i < list.length; i += 1) {
        var ref = list[i];
        var label = ref[0];
        var expression = ref[1];
        this.labels.push(label);
        this.outputs.push(expression);
    }
};
Step.parse = function parse(args, context) {
    if (args.length - 1 < 4) {
        return context.error('Expected at least 4 arguments, but found only ' + (args.length - 1) + '.');
    }
    if ((args.length - 1) % 2 !== 0) {
        return context.error('Expected an even number of arguments.');
    }
    var input = context.parse(args[1], 1, NumberType);
    if (!input) {
        return null;
    }
    var stops = [];
    var outputType = null;
    if (context.expectedType && context.expectedType.kind !== 'value') {
        outputType = context.expectedType;
    }
    for (var i = 1; i < args.length; i += 2) {
        var label = i === 1 ? -Infinity : args[i];
        var value = args[i + 1];
        var labelKey = i;
        var valueKey = i + 1;
        if (typeof label !== 'number') {
            return context.error('Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
        }
        if (stops.length && stops[stops.length - 1][0] >= label) {
            return context.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.', labelKey);
        }
        var parsed = context.parse(value, valueKey, outputType);
        if (!parsed) {
            return null;
        }
        outputType = outputType || parsed.type;
        stops.push([
            label,
            parsed
        ]);
    }
    return new Step(outputType, input, stops);
};
Step.prototype.evaluate = function evaluate(ctx) {
    var labels = this.labels;
    var outputs = this.outputs;
    if (labels.length === 1) {
        return outputs[0].evaluate(ctx);
    }
    var value = this.input.evaluate(ctx);
    if (value <= labels[0]) {
        return outputs[0].evaluate(ctx);
    }
    var stopCount = labels.length;
    if (value >= labels[stopCount - 1]) {
        return outputs[stopCount - 1].evaluate(ctx);
    }
    var index = findStopLessThanOrEqualTo(labels, value);
    return outputs[index].evaluate(ctx);
};
Step.prototype.eachChild = function eachChild(fn) {
    fn(this.input);
    for (var i = 0, list = this.outputs; i < list.length; i += 1) {
        var expression = list[i];
        fn(expression);
    }
};
Step.prototype.outputDefined = function outputDefined() {
    return this.outputs.every(function (out) {
        return out.outputDefined();
    });
};
Step.prototype.serialize = function serialize() {
    var serialized = [
        'step',
        this.input.serialize()
    ];
    for (var i = 0; i < this.labels.length; i++) {
        if (i > 0) {
            serialized.push(this.labels[i]);
        }
        serialized.push(this.outputs[i].serialize());
    }
    return serialized;
};

function number(a, b, t) {
    return a * (1 - t) + b * t;
}
function color(from, to, t) {
    return new Color(number(from.r, to.r, t), number(from.g, to.g, t), number(from.b, to.b, t), number(from.a, to.a, t));
}
function array$1(from, to, t) {
    return from.map(function (d, i) {
        return number(d, to[i], t);
    });
}

var interpolate = /*#__PURE__*/Object.freeze({
__proto__: null,
number: number,
color: color,
array: array$1
});

var Xn = 0.95047, Yn = 1, Zn = 1.08883, t0 = 4 / 29, t1 = 6 / 29, t2 = 3 * t1 * t1, t3 = t1 * t1 * t1, deg2rad = Math.PI / 180, rad2deg = 180 / Math.PI;
function xyz2lab(t) {
    return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
}
function lab2xyz(t) {
    return t > t1 ? t * t * t : t2 * (t - t0);
}
function xyz2rgb(x) {
    return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
}
function rgb2xyz(x) {
    x /= 255;
    return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
function rgbToLab(rgbColor) {
    var b = rgb2xyz(rgbColor.r), a = rgb2xyz(rgbColor.g), l = rgb2xyz(rgbColor.b), x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.072175 * l) / Yn), z = xyz2lab((0.0193339 * b + 0.119192 * a + 0.9503041 * l) / Zn);
    return {
        l: 116 * y - 16,
        a: 500 * (x - y),
        b: 200 * (y - z),
        alpha: rgbColor.a
    };
}
function labToRgb(labColor) {
    var y = (labColor.l + 16) / 116, x = isNaN(labColor.a) ? y : y + labColor.a / 500, z = isNaN(labColor.b) ? y : y - labColor.b / 200;
    y = Yn * lab2xyz(y);
    x = Xn * lab2xyz(x);
    z = Zn * lab2xyz(z);
    return new Color(xyz2rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z), xyz2rgb(-0.969266 * x + 1.8760108 * y + 0.041556 * z), xyz2rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z), labColor.alpha);
}
function interpolateLab(from, to, t) {
    return {
        l: number(from.l, to.l, t),
        a: number(from.a, to.a, t),
        b: number(from.b, to.b, t),
        alpha: number(from.alpha, to.alpha, t)
    };
}
function rgbToHcl(rgbColor) {
    var ref = rgbToLab(rgbColor);
    var l = ref.l;
    var a = ref.a;
    var b = ref.b;
    var h = Math.atan2(b, a) * rad2deg;
    return {
        h: h < 0 ? h + 360 : h,
        c: Math.sqrt(a * a + b * b),
        l: l,
        alpha: rgbColor.a
    };
}
function hclToRgb(hclColor) {
    var h = hclColor.h * deg2rad, c = hclColor.c, l = hclColor.l;
    return labToRgb({
        l: l,
        a: Math.cos(h) * c,
        b: Math.sin(h) * c,
        alpha: hclColor.alpha
    });
}
function interpolateHue(a, b, t) {
    var d = b - a;
    return a + t * (d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d);
}
function interpolateHcl(from, to, t) {
    return {
        h: interpolateHue(from.h, to.h, t),
        c: number(from.c, to.c, t),
        l: number(from.l, to.l, t),
        alpha: number(from.alpha, to.alpha, t)
    };
}
var lab = {
    forward: rgbToLab,
    reverse: labToRgb,
    interpolate: interpolateLab
};
var hcl = {
    forward: rgbToHcl,
    reverse: hclToRgb,
    interpolate: interpolateHcl
};

var colorSpaces = /*#__PURE__*/Object.freeze({
__proto__: null,
lab: lab,
hcl: hcl
});

var Interpolate = function Interpolate(type, operator, interpolation, input, stops) {
    this.type = type;
    this.operator = operator;
    this.interpolation = interpolation;
    this.input = input;
    this.labels = [];
    this.outputs = [];
    for (var i = 0, list = stops; i < list.length; i += 1) {
        var ref = list[i];
        var label = ref[0];
        var expression = ref[1];
        this.labels.push(label);
        this.outputs.push(expression);
    }
};
Interpolate.interpolationFactor = function interpolationFactor(interpolation, input, lower, upper) {
    var t = 0;
    if (interpolation.name === 'exponential') {
        t = exponentialInterpolation(input, interpolation.base, lower, upper);
    } else if (interpolation.name === 'linear') {
        t = exponentialInterpolation(input, 1, lower, upper);
    } else if (interpolation.name === 'cubic-bezier') {
        var c = interpolation.controlPoints;
        var ub = new unitbezier(c[0], c[1], c[2], c[3]);
        t = ub.solve(exponentialInterpolation(input, 1, lower, upper));
    }
    return t;
};
Interpolate.parse = function parse(args, context) {
    var operator = args[0];
    var interpolation = args[1];
    var input = args[2];
    var rest = args.slice(3);
    if (!Array.isArray(interpolation) || interpolation.length === 0) {
        return context.error('Expected an interpolation type expression.', 1);
    }
    if (interpolation[0] === 'linear') {
        interpolation = { name: 'linear' };
    } else if (interpolation[0] === 'exponential') {
        var base = interpolation[1];
        if (typeof base !== 'number') {
            return context.error('Exponential interpolation requires a numeric base.', 1, 1);
        }
        interpolation = {
            name: 'exponential',
            base: base
        };
    } else if (interpolation[0] === 'cubic-bezier') {
        var controlPoints = interpolation.slice(1);
        if (controlPoints.length !== 4 || controlPoints.some(function (t) {
                return typeof t !== 'number' || t < 0 || t > 1;
            })) {
            return context.error('Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.', 1);
        }
        interpolation = {
            name: 'cubic-bezier',
            controlPoints: controlPoints
        };
    } else {
        return context.error('Unknown interpolation type ' + String(interpolation[0]), 1, 0);
    }
    if (args.length - 1 < 4) {
        return context.error('Expected at least 4 arguments, but found only ' + (args.length - 1) + '.');
    }
    if ((args.length - 1) % 2 !== 0) {
        return context.error('Expected an even number of arguments.');
    }
    input = context.parse(input, 2, NumberType);
    if (!input) {
        return null;
    }
    var stops = [];
    var outputType = null;
    if (operator === 'interpolate-hcl' || operator === 'interpolate-lab') {
        outputType = ColorType;
    } else if (context.expectedType && context.expectedType.kind !== 'value') {
        outputType = context.expectedType;
    }
    for (var i = 0; i < rest.length; i += 2) {
        var label = rest[i];
        var value = rest[i + 1];
        var labelKey = i + 3;
        var valueKey = i + 4;
        if (typeof label !== 'number') {
            return context.error('Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
        }
        if (stops.length && stops[stops.length - 1][0] >= label) {
            return context.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.', labelKey);
        }
        var parsed = context.parse(value, valueKey, outputType);
        if (!parsed) {
            return null;
        }
        outputType = outputType || parsed.type;
        stops.push([
            label,
            parsed
        ]);
    }
    if (outputType.kind !== 'number' && outputType.kind !== 'color' && !(outputType.kind === 'array' && outputType.itemType.kind === 'number' && typeof outputType.N === 'number')) {
        return context.error('Type ' + toString(outputType) + ' is not interpolatable.');
    }
    return new Interpolate(outputType, operator, interpolation, input, stops);
};
Interpolate.prototype.evaluate = function evaluate(ctx) {
    var labels = this.labels;
    var outputs = this.outputs;
    if (labels.length === 1) {
        return outputs[0].evaluate(ctx);
    }
    var value = this.input.evaluate(ctx);
    if (value <= labels[0]) {
        return outputs[0].evaluate(ctx);
    }
    var stopCount = labels.length;
    if (value >= labels[stopCount - 1]) {
        return outputs[stopCount - 1].evaluate(ctx);
    }
    var index = findStopLessThanOrEqualTo(labels, value);
    var lower = labels[index];
    var upper = labels[index + 1];
    var t = Interpolate.interpolationFactor(this.interpolation, value, lower, upper);
    var outputLower = outputs[index].evaluate(ctx);
    var outputUpper = outputs[index + 1].evaluate(ctx);
    if (this.operator === 'interpolate') {
        return interpolate[this.type.kind.toLowerCase()](outputLower, outputUpper, t);
    } else if (this.operator === 'interpolate-hcl') {
        return hcl.reverse(hcl.interpolate(hcl.forward(outputLower), hcl.forward(outputUpper), t));
    } else {
        return lab.reverse(lab.interpolate(lab.forward(outputLower), lab.forward(outputUpper), t));
    }
};
Interpolate.prototype.eachChild = function eachChild(fn) {
    fn(this.input);
    for (var i = 0, list = this.outputs; i < list.length; i += 1) {
        var expression = list[i];
        fn(expression);
    }
};
Interpolate.prototype.outputDefined = function outputDefined() {
    return this.outputs.every(function (out) {
        return out.outputDefined();
    });
};
Interpolate.prototype.serialize = function serialize() {
    var interpolation;
    if (this.interpolation.name === 'linear') {
        interpolation = ['linear'];
    } else if (this.interpolation.name === 'exponential') {
        if (this.interpolation.base === 1) {
            interpolation = ['linear'];
        } else {
            interpolation = [
                'exponential',
                this.interpolation.base
            ];
        }
    } else {
        interpolation = ['cubic-bezier'].concat(this.interpolation.controlPoints);
    }
    var serialized = [
        this.operator,
        interpolation,
        this.input.serialize()
    ];
    for (var i = 0; i < this.labels.length; i++) {
        serialized.push(this.labels[i], this.outputs[i].serialize());
    }
    return serialized;
};
function exponentialInterpolation(input, base, lowerValue, upperValue) {
    var difference = upperValue - lowerValue;
    var progress = input - lowerValue;
    if (difference === 0) {
        return 0;
    } else if (base === 1) {
        return progress / difference;
    } else {
        return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
    }
}

var Coalesce = function Coalesce(type, args) {
    this.type = type;
    this.args = args;
};
Coalesce.parse = function parse(args, context) {
    if (args.length < 2) {
        return context.error('Expectected at least one argument.');
    }
    var outputType = null;
    var expectedType = context.expectedType;
    if (expectedType && expectedType.kind !== 'value') {
        outputType = expectedType;
    }
    var parsedArgs = [];
    for (var i = 0, list = args.slice(1); i < list.length; i += 1) {
        var arg = list[i];
        var parsed = context.parse(arg, 1 + parsedArgs.length, outputType, undefined, { typeAnnotation: 'omit' });
        if (!parsed) {
            return null;
        }
        outputType = outputType || parsed.type;
        parsedArgs.push(parsed);
    }
    var needsAnnotation = expectedType && parsedArgs.some(function (arg) {
        return checkSubtype(expectedType, arg.type);
    });
    return needsAnnotation ? new Coalesce(ValueType, parsedArgs) : new Coalesce(outputType, parsedArgs);
};
Coalesce.prototype.evaluate = function evaluate(ctx) {
    var result = null;
    var argCount = 0;
    var requestedImageName;
    for (var i = 0, list = this.args; i < list.length; i += 1) {
        var arg = list[i];
        argCount++;
        result = arg.evaluate(ctx);
        if (result && result instanceof ResolvedImage && !result.available) {
            if (!requestedImageName) {
                requestedImageName = result.name;
            }
            result = null;
            if (argCount === this.args.length) {
                result = requestedImageName;
            }
        }
        if (result !== null) {
            break;
        }
    }
    return result;
};
Coalesce.prototype.eachChild = function eachChild(fn) {
    this.args.forEach(fn);
};
Coalesce.prototype.outputDefined = function outputDefined() {
    return this.args.every(function (arg) {
        return arg.outputDefined();
    });
};
Coalesce.prototype.serialize = function serialize() {
    var serialized = ['coalesce'];
    this.eachChild(function (child) {
        serialized.push(child.serialize());
    });
    return serialized;
};

var Let = function Let(bindings, result) {
    this.type = result.type;
    this.bindings = [].concat(bindings);
    this.result = result;
};
Let.prototype.evaluate = function evaluate(ctx) {
    return this.result.evaluate(ctx);
};
Let.prototype.eachChild = function eachChild(fn) {
    for (var i = 0, list = this.bindings; i < list.length; i += 1) {
        var binding = list[i];
        fn(binding[1]);
    }
    fn(this.result);
};
Let.parse = function parse(args, context) {
    if (args.length < 4) {
        return context.error('Expected at least 3 arguments, but found ' + (args.length - 1) + ' instead.');
    }
    var bindings = [];
    for (var i = 1; i < args.length - 1; i += 2) {
        var name = args[i];
        if (typeof name !== 'string') {
            return context.error('Expected string, but found ' + typeof name + ' instead.', i);
        }
        if (/[^a-zA-Z0-9_]/.test(name)) {
            return context.error('Variable names must contain only alphanumeric characters or \'_\'.', i);
        }
        var value = context.parse(args[i + 1], i + 1);
        if (!value) {
            return null;
        }
        bindings.push([
            name,
            value
        ]);
    }
    var result = context.parse(args[args.length - 1], args.length - 1, context.expectedType, bindings);
    if (!result) {
        return null;
    }
    return new Let(bindings, result);
};
Let.prototype.outputDefined = function outputDefined() {
    return this.result.outputDefined();
};
Let.prototype.serialize = function serialize() {
    var serialized = ['let'];
    for (var i = 0, list = this.bindings; i < list.length; i += 1) {
        var ref = list[i];
        var name = ref[0];
        var expr = ref[1];
        serialized.push(name, expr.serialize());
    }
    serialized.push(this.result.serialize());
    return serialized;
};

var At = function At(type, index, input) {
    this.type = type;
    this.index = index;
    this.input = input;
};
At.parse = function parse(args, context) {
    if (args.length !== 3) {
        return context.error('Expected 2 arguments, but found ' + (args.length - 1) + ' instead.');
    }
    var index = context.parse(args[1], 1, NumberType);
    var input = context.parse(args[2], 2, array(context.expectedType || ValueType));
    if (!index || !input) {
        return null;
    }
    var t = input.type;
    return new At(t.itemType, index, input);
};
At.prototype.evaluate = function evaluate(ctx) {
    var index = this.index.evaluate(ctx);
    var array = this.input.evaluate(ctx);
    if (index < 0) {
        throw new RuntimeError('Array index out of bounds: ' + index + ' < 0.');
    }
    if (index >= array.length) {
        throw new RuntimeError('Array index out of bounds: ' + index + ' > ' + (array.length - 1) + '.');
    }
    if (index !== Math.floor(index)) {
        throw new RuntimeError('Array index must be an integer, but found ' + index + ' instead.');
    }
    return array[index];
};
At.prototype.eachChild = function eachChild(fn) {
    fn(this.index);
    fn(this.input);
};
At.prototype.outputDefined = function outputDefined() {
    return false;
};
At.prototype.serialize = function serialize() {
    return [
        'at',
        this.index.serialize(),
        this.input.serialize()
    ];
};

var In = function In(needle, haystack) {
    this.type = BooleanType;
    this.needle = needle;
    this.haystack = haystack;
};
In.parse = function parse(args, context) {
    if (args.length !== 3) {
        return context.error('Expected 2 arguments, but found ' + (args.length - 1) + ' instead.');
    }
    var needle = context.parse(args[1], 1, ValueType);
    var haystack = context.parse(args[2], 2, ValueType);
    if (!needle || !haystack) {
        return null;
    }
    if (!isValidType(needle.type, [
            BooleanType,
            StringType,
            NumberType,
            NullType,
            ValueType
        ])) {
        return context.error('Expected first argument to be of type boolean, string, number or null, but found ' + toString(needle.type) + ' instead');
    }
    return new In(needle, haystack);
};
In.prototype.evaluate = function evaluate(ctx) {
    var needle = this.needle.evaluate(ctx);
    var haystack = this.haystack.evaluate(ctx);
    if (!haystack) {
        return false;
    }
    if (!isValidNativeType(needle, [
            'boolean',
            'string',
            'number',
            'null'
        ])) {
        throw new RuntimeError('Expected first argument to be of type boolean, string, number or null, but found ' + toString(typeOf(needle)) + ' instead.');
    }
    if (!isValidNativeType(haystack, [
            'string',
            'array'
        ])) {
        throw new RuntimeError('Expected second argument to be of type array or string, but found ' + toString(typeOf(haystack)) + ' instead.');
    }
    return haystack.indexOf(needle) >= 0;
};
In.prototype.eachChild = function eachChild(fn) {
    fn(this.needle);
    fn(this.haystack);
};
In.prototype.outputDefined = function outputDefined() {
    return true;
};
In.prototype.serialize = function serialize() {
    return [
        'in',
        this.needle.serialize(),
        this.haystack.serialize()
    ];
};

var IndexOf = function IndexOf(needle, haystack, fromIndex) {
    this.type = NumberType;
    this.needle = needle;
    this.haystack = haystack;
    this.fromIndex = fromIndex;
};
IndexOf.parse = function parse(args, context) {
    if (args.length <= 2 || args.length >= 5) {
        return context.error('Expected 3 or 4 arguments, but found ' + (args.length - 1) + ' instead.');
    }
    var needle = context.parse(args[1], 1, ValueType);
    var haystack = context.parse(args[2], 2, ValueType);
    if (!needle || !haystack) {
        return null;
    }
    if (!isValidType(needle.type, [
            BooleanType,
            StringType,
            NumberType,
            NullType,
            ValueType
        ])) {
        return context.error('Expected first argument to be of type boolean, string, number or null, but found ' + toString(needle.type) + ' instead');
    }
    if (args.length === 4) {
        var fromIndex = context.parse(args[3], 3, NumberType);
        if (!fromIndex) {
            return null;
        }
        return new IndexOf(needle, haystack, fromIndex);
    } else {
        return new IndexOf(needle, haystack);
    }
};
IndexOf.prototype.evaluate = function evaluate(ctx) {
    var needle = this.needle.evaluate(ctx);
    var haystack = this.haystack.evaluate(ctx);
    if (!isValidNativeType(needle, [
            'boolean',
            'string',
            'number',
            'null'
        ])) {
        throw new RuntimeError('Expected first argument to be of type boolean, string, number or null, but found ' + toString(typeOf(needle)) + ' instead.');
    }
    if (!isValidNativeType(haystack, [
            'string',
            'array'
        ])) {
        throw new RuntimeError('Expected second argument to be of type array or string, but found ' + toString(typeOf(haystack)) + ' instead.');
    }
    if (this.fromIndex) {
        var fromIndex = this.fromIndex.evaluate(ctx);
        return haystack.indexOf(needle, fromIndex);
    }
    return haystack.indexOf(needle);
};
IndexOf.prototype.eachChild = function eachChild(fn) {
    fn(this.needle);
    fn(this.haystack);
    if (this.fromIndex) {
        fn(this.fromIndex);
    }
};
IndexOf.prototype.outputDefined = function outputDefined() {
    return false;
};
IndexOf.prototype.serialize = function serialize() {
    if (this.fromIndex != null && this.fromIndex !== undefined) {
        var fromIndex = this.fromIndex.serialize();
        return [
            'index-of',
            this.needle.serialize(),
            this.haystack.serialize(),
            fromIndex
        ];
    }
    return [
        'index-of',
        this.needle.serialize(),
        this.haystack.serialize()
    ];
};

var Match = function Match(inputType, outputType, input, cases, outputs, otherwise) {
    this.inputType = inputType;
    this.type = outputType;
    this.input = input;
    this.cases = cases;
    this.outputs = outputs;
    this.otherwise = otherwise;
};
Match.parse = function parse(args, context) {
    if (args.length < 5) {
        return context.error('Expected at least 4 arguments, but found only ' + (args.length - 1) + '.');
    }
    if (args.length % 2 !== 1) {
        return context.error('Expected an even number of arguments.');
    }
    var inputType;
    var outputType;
    if (context.expectedType && context.expectedType.kind !== 'value') {
        outputType = context.expectedType;
    }
    var cases = {};
    var outputs = [];
    for (var i = 2; i < args.length - 1; i += 2) {
        var labels = args[i];
        var value = args[i + 1];
        if (!Array.isArray(labels)) {
            labels = [labels];
        }
        var labelContext = context.concat(i);
        if (labels.length === 0) {
            return labelContext.error('Expected at least one branch label.');
        }
        for (var i$1 = 0, list = labels; i$1 < list.length; i$1 += 1) {
            var label = list[i$1];
            if (typeof label !== 'number' && typeof label !== 'string') {
                return labelContext.error('Branch labels must be numbers or strings.');
            } else if (typeof label === 'number' && Math.abs(label) > Number.MAX_SAFE_INTEGER) {
                return labelContext.error('Branch labels must be integers no larger than ' + Number.MAX_SAFE_INTEGER + '.');
            } else if (typeof label === 'number' && Math.floor(label) !== label) {
                return labelContext.error('Numeric branch labels must be integer values.');
            } else if (!inputType) {
                inputType = typeOf(label);
            } else if (labelContext.checkSubtype(inputType, typeOf(label))) {
                return null;
            }
            if (typeof cases[String(label)] !== 'undefined') {
                return labelContext.error('Branch labels must be unique.');
            }
            cases[String(label)] = outputs.length;
        }
        var result = context.parse(value, i, outputType);
        if (!result) {
            return null;
        }
        outputType = outputType || result.type;
        outputs.push(result);
    }
    var input = context.parse(args[1], 1, ValueType);
    if (!input) {
        return null;
    }
    var otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
    if (!otherwise) {
        return null;
    }
    if (input.type.kind !== 'value' && context.concat(1).checkSubtype(inputType, input.type)) {
        return null;
    }
    return new Match(inputType, outputType, input, cases, outputs, otherwise);
};
Match.prototype.evaluate = function evaluate(ctx) {
    var input = this.input.evaluate(ctx);
    var output = typeOf(input) === this.inputType && this.outputs[this.cases[input]] || this.otherwise;
    return output.evaluate(ctx);
};
Match.prototype.eachChild = function eachChild(fn) {
    fn(this.input);
    this.outputs.forEach(fn);
    fn(this.otherwise);
};
Match.prototype.outputDefined = function outputDefined() {
    return this.outputs.every(function (out) {
        return out.outputDefined();
    }) && this.otherwise.outputDefined();
};
Match.prototype.serialize = function serialize() {
    var this$1 = this;
    var serialized = [
        'match',
        this.input.serialize()
    ];
    var sortedLabels = Object.keys(this.cases).sort();
    var groupedByOutput = [];
    var outputLookup = {};
    for (var i = 0, list = sortedLabels; i < list.length; i += 1) {
        var label = list[i];
        var outputIndex = outputLookup[this.cases[label]];
        if (outputIndex === undefined) {
            outputLookup[this.cases[label]] = groupedByOutput.length;
            groupedByOutput.push([
                this.cases[label],
                [label]
            ]);
        } else {
            groupedByOutput[outputIndex][1].push(label);
        }
    }
    var coerceLabel = function (label) {
        return this$1.inputType.kind === 'number' ? Number(label) : label;
    };
    for (var i$1 = 0, list$1 = groupedByOutput; i$1 < list$1.length; i$1 += 1) {
        var ref = list$1[i$1];
        var outputIndex = ref[0];
        var labels = ref[1];
        if (labels.length === 1) {
            serialized.push(coerceLabel(labels[0]));
        } else {
            serialized.push(labels.map(coerceLabel));
        }
        serialized.push(this.outputs[outputIndex$1].serialize());
    }
    serialized.push(this.otherwise.serialize());
    return serialized;
};

var Case = function Case(type, branches, otherwise) {
    this.type = type;
    this.branches = branches;
    this.otherwise = otherwise;
};
Case.parse = function parse(args, context) {
    if (args.length < 4) {
        return context.error('Expected at least 3 arguments, but found only ' + (args.length - 1) + '.');
    }
    if (args.length % 2 !== 0) {
        return context.error('Expected an odd number of arguments.');
    }
    var outputType;
    if (context.expectedType && context.expectedType.kind !== 'value') {
        outputType = context.expectedType;
    }
    var branches = [];
    for (var i = 1; i < args.length - 1; i += 2) {
        var test = context.parse(args[i], i, BooleanType);
        if (!test) {
            return null;
        }
        var result = context.parse(args[i + 1], i + 1, outputType);
        if (!result) {
            return null;
        }
        branches.push([
            test,
            result
        ]);
        outputType = outputType || result.type;
    }
    var otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
    if (!otherwise) {
        return null;
    }
    return new Case(outputType, branches, otherwise);
};
Case.prototype.evaluate = function evaluate(ctx) {
    for (var i = 0, list = this.branches; i < list.length; i += 1) {
        var ref = list[i];
        var test = ref[0];
        var expression = ref[1];
        if (test.evaluate(ctx)) {
            return expression.evaluate(ctx);
        }
    }
    return this.otherwise.evaluate(ctx);
};
Case.prototype.eachChild = function eachChild(fn) {
    for (var i = 0, list = this.branches; i < list.length; i += 1) {
        var ref = list[i];
        var test = ref[0];
        var expression = ref[1];
        fn(test);
        fn(expression);
    }
    fn(this.otherwise);
};
Case.prototype.outputDefined = function outputDefined() {
    return this.branches.every(function (ref) {
        var _ = ref[0];
        var out = ref[1];
        return out.outputDefined();
    }) && this.otherwise.outputDefined();
};
Case.prototype.serialize = function serialize() {
    var serialized = ['case'];
    this.eachChild(function (child) {
        serialized.push(child.serialize());
    });
    return serialized;
};

var Slice = function Slice(type, input, beginIndex, endIndex) {
    this.type = type;
    this.input = input;
    this.beginIndex = beginIndex;
    this.endIndex = endIndex;
};
Slice.parse = function parse(args, context) {
    if (args.length <= 2 || args.length >= 5) {
        return context.error('Expected 3 or 4 arguments, but found ' + (args.length - 1) + ' instead.');
    }
    var input = context.parse(args[1], 1, ValueType);
    var beginIndex = context.parse(args[2], 2, NumberType);
    if (!input || !beginIndex) {
        return null;
    }
    if (!isValidType(input.type, [
            array(ValueType),
            StringType,
            ValueType
        ])) {
        return context.error('Expected first argument to be of type array or string, but found ' + toString(input.type) + ' instead');
    }
    if (args.length === 4) {
        var endIndex = context.parse(args[3], 3, NumberType);
        if (!endIndex) {
            return null;
        }
        return new Slice(input.type, input, beginIndex, endIndex);
    } else {
        return new Slice(input.type, input, beginIndex);
    }
};
Slice.prototype.evaluate = function evaluate(ctx) {
    var input = this.input.evaluate(ctx);
    var beginIndex = this.beginIndex.evaluate(ctx);
    if (!isValidNativeType(input, [
            'string',
            'array'
        ])) {
        throw new RuntimeError('Expected first argument to be of type array or string, but found ' + toString(typeOf(input)) + ' instead.');
    }
    if (this.endIndex) {
        var endIndex = this.endIndex.evaluate(ctx);
        return input.slice(beginIndex, endIndex);
    }
    return input.slice(beginIndex);
};
Slice.prototype.eachChild = function eachChild(fn) {
    fn(this.input);
    fn(this.beginIndex);
    if (this.endIndex) {
        fn(this.endIndex);
    }
};
Slice.prototype.outputDefined = function outputDefined() {
    return false;
};
Slice.prototype.serialize = function serialize() {
    if (this.endIndex != null && this.endIndex !== undefined) {
        var endIndex = this.endIndex.serialize();
        return [
            'slice',
            this.input.serialize(),
            this.beginIndex.serialize(),
            endIndex
        ];
    }
    return [
        'slice',
        this.input.serialize(),
        this.beginIndex.serialize()
    ];
};

function isComparableType(op, type) {
    if (op === '==' || op === '!=') {
        return type.kind === 'boolean' || type.kind === 'string' || type.kind === 'number' || type.kind === 'null' || type.kind === 'value';
    } else {
        return type.kind === 'string' || type.kind === 'number' || type.kind === 'value';
    }
}
function eq(ctx, a, b) {
    return a === b;
}
function neq(ctx, a, b) {
    return a !== b;
}
function lt(ctx, a, b) {
    return a < b;
}
function gt(ctx, a, b) {
    return a > b;
}
function lteq(ctx, a, b) {
    return a <= b;
}
function gteq(ctx, a, b) {
    return a >= b;
}
function eqCollate(ctx, a, b, c) {
    return c.compare(a, b) === 0;
}
function neqCollate(ctx, a, b, c) {
    return !eqCollate(ctx, a, b, c);
}
function ltCollate(ctx, a, b, c) {
    return c.compare(a, b) < 0;
}
function gtCollate(ctx, a, b, c) {
    return c.compare(a, b) > 0;
}
function lteqCollate(ctx, a, b, c) {
    return c.compare(a, b) <= 0;
}
function gteqCollate(ctx, a, b, c) {
    return c.compare(a, b) >= 0;
}
function makeComparison(op, compareBasic, compareWithCollator) {
    var isOrderComparison = op !== '==' && op !== '!=';
    return function () {
        function Comparison(lhs, rhs, collator) {
            this.type = BooleanType;
            this.lhs = lhs;
            this.rhs = rhs;
            this.collator = collator;
            this.hasUntypedArgument = lhs.type.kind === 'value' || rhs.type.kind === 'value';
        }
        Comparison.parse = function parse(args, context) {
            if (args.length !== 3 && args.length !== 4) {
                return context.error('Expected two or three arguments.');
            }
            var op = args[0];
            var lhs = context.parse(args[1], 1, ValueType);
            if (!lhs) {
                return null;
            }
            if (!isComparableType(op, lhs.type)) {
                return context.concat(1).error('"' + op + '" comparisons are not supported for type \'' + toString(lhs.type) + '\'.');
            }
            var rhs = context.parse(args[2], 2, ValueType);
            if (!rhs) {
                return null;
            }
            if (!isComparableType(op, rhs.type)) {
                return context.concat(2).error('"' + op + '" comparisons are not supported for type \'' + toString(rhs.type) + '\'.');
            }
            if (lhs.type.kind !== rhs.type.kind && lhs.type.kind !== 'value' && rhs.type.kind !== 'value') {
                return context.error('Cannot compare types \'' + toString(lhs.type) + '\' and \'' + toString(rhs.type) + '\'.');
            }
            if (isOrderComparison) {
                if (lhs.type.kind === 'value' && rhs.type.kind !== 'value') {
                    lhs = new Assertion(rhs.type, [lhs]);
                } else if (lhs.type.kind !== 'value' && rhs.type.kind === 'value') {
                    rhs = new Assertion(lhs.type, [rhs]);
                }
            }
            var collator = null;
            if (args.length === 4) {
                if (lhs.type.kind !== 'string' && rhs.type.kind !== 'string' && lhs.type.kind !== 'value' && rhs.type.kind !== 'value') {
                    return context.error('Cannot use collator to compare non-string types.');
                }
                collator = context.parse(args[3], 3, CollatorType);
                if (!collator) {
                    return null;
                }
            }
            return new Comparison(lhs, rhs, collator);
        };
        Comparison.prototype.evaluate = function evaluate(ctx) {
            var lhs = this.lhs.evaluate(ctx);
            var rhs = this.rhs.evaluate(ctx);
            if (isOrderComparison && this.hasUntypedArgument) {
                var lt = typeOf(lhs);
                var rt = typeOf(rhs);
                if (lt.kind !== rt.kind || !(lt.kind === 'string' || lt.kind === 'number')) {
                    throw new RuntimeError('Expected arguments for "' + op + '" to be (string, string) or (number, number), but found (' + lt.kind + ', ' + rt.kind + ') instead.');
                }
            }
            if (this.collator && !isOrderComparison && this.hasUntypedArgument) {
                var lt$1 = typeOf(lhs);
                var rt$1 = typeOf(rhs);
                if (lt$1.kind !== 'string' || rt$1.kind !== 'string') {
                    return compareBasic(ctx, lhs, rhs);
                }
            }
            return this.collator ? compareWithCollator(ctx, lhs, rhs, this.collator.evaluate(ctx)) : compareBasic(ctx, lhs, rhs);
        };
        Comparison.prototype.eachChild = function eachChild(fn) {
            fn(this.lhs);
            fn(this.rhs);
            if (this.collator) {
                fn(this.collator);
            }
        };
        Comparison.prototype.outputDefined = function outputDefined() {
            return true;
        };
        Comparison.prototype.serialize = function serialize() {
            var serialized = [op];
            this.eachChild(function (child) {
                serialized.push(child.serialize());
            });
            return serialized;
        };
        return Comparison;
    }();
}
var Equals = makeComparison('==', eq, eqCollate);
var NotEquals = makeComparison('!=', neq, neqCollate);
var LessThan = makeComparison('<', lt, ltCollate);
var GreaterThan = makeComparison('>', gt, gtCollate);
var LessThanOrEqual = makeComparison('<=', lteq, lteqCollate);
var GreaterThanOrEqual = makeComparison('>=', gteq, gteqCollate);

var NumberFormat = function NumberFormat(number, locale, currency, minFractionDigits, maxFractionDigits) {
    this.type = StringType;
    this.number = number;
    this.locale = locale;
    this.currency = currency;
    this.minFractionDigits = minFractionDigits;
    this.maxFractionDigits = maxFractionDigits;
};
NumberFormat.parse = function parse(args, context) {
    if (args.length !== 3) {
        return context.error('Expected two arguments.');
    }
    var number = context.parse(args[1], 1, NumberType);
    if (!number) {
        return null;
    }
    var options = args[2];
    if (typeof options !== 'object' || Array.isArray(options)) {
        return context.error('NumberFormat options argument must be an object.');
    }
    var locale = null;
    if (options['locale']) {
        locale = context.parse(options['locale'], 1, StringType);
        if (!locale) {
            return null;
        }
    }
    var currency = null;
    if (options['currency']) {
        currency = context.parse(options['currency'], 1, StringType);
        if (!currency) {
            return null;
        }
    }
    var minFractionDigits = null;
    if (options['min-fraction-digits']) {
        minFractionDigits = context.parse(options['min-fraction-digits'], 1, NumberType);
        if (!minFractionDigits) {
            return null;
        }
    }
    var maxFractionDigits = null;
    if (options['max-fraction-digits']) {
        maxFractionDigits = context.parse(options['max-fraction-digits'], 1, NumberType);
        if (!maxFractionDigits) {
            return null;
        }
    }
    return new NumberFormat(number, locale, currency, minFractionDigits, maxFractionDigits);
};
NumberFormat.prototype.evaluate = function evaluate(ctx) {
    return new Intl.NumberFormat(this.locale ? this.locale.evaluate(ctx) : [], {
        style: this.currency ? 'currency' : 'decimal',
        currency: this.currency ? this.currency.evaluate(ctx) : undefined,
        minimumFractionDigits: this.minFractionDigits ? this.minFractionDigits.evaluate(ctx) : undefined,
        maximumFractionDigits: this.maxFractionDigits ? this.maxFractionDigits.evaluate(ctx) : undefined
    }).format(this.number.evaluate(ctx));
};
NumberFormat.prototype.eachChild = function eachChild(fn) {
    fn(this.number);
    if (this.locale) {
        fn(this.locale);
    }
    if (this.currency) {
        fn(this.currency);
    }
    if (this.minFractionDigits) {
        fn(this.minFractionDigits);
    }
    if (this.maxFractionDigits) {
        fn(this.maxFractionDigits);
    }
};
NumberFormat.prototype.outputDefined = function outputDefined() {
    return false;
};
NumberFormat.prototype.serialize = function serialize() {
    var options = {};
    if (this.locale) {
        options['locale'] = this.locale.serialize();
    }
    if (this.currency) {
        options['currency'] = this.currency.serialize();
    }
    if (this.minFractionDigits) {
        options['min-fraction-digits'] = this.minFractionDigits.serialize();
    }
    if (this.maxFractionDigits) {
        options['max-fraction-digits'] = this.maxFractionDigits.serialize();
    }
    return [
        'number-format',
        this.number.serialize(),
        options
    ];
};

var Length = function Length(input) {
    this.type = NumberType;
    this.input = input;
};
Length.parse = function parse(args, context) {
    if (args.length !== 2) {
        return context.error('Expected 1 argument, but found ' + (args.length - 1) + ' instead.');
    }
    var input = context.parse(args[1], 1);
    if (!input) {
        return null;
    }
    if (input.type.kind !== 'array' && input.type.kind !== 'string' && input.type.kind !== 'value') {
        return context.error('Expected argument of type string or array, but found ' + toString(input.type) + ' instead.');
    }
    return new Length(input);
};
Length.prototype.evaluate = function evaluate(ctx) {
    var input = this.input.evaluate(ctx);
    if (typeof input === 'string') {
        return input.length;
    } else if (Array.isArray(input)) {
        return input.length;
    } else {
        throw new RuntimeError('Expected value to be of type string or array, but found ' + toString(typeOf(input)) + ' instead.');
    }
};
Length.prototype.eachChild = function eachChild(fn) {
    fn(this.input);
};
Length.prototype.outputDefined = function outputDefined() {
    return false;
};
Length.prototype.serialize = function serialize() {
    var serialized = ['length'];
    this.eachChild(function (child) {
        serialized.push(child.serialize());
    });
    return serialized;
};

var expressions = {
    '==': Equals,
    '!=': NotEquals,
    '>': GreaterThan,
    '<': LessThan,
    '>=': GreaterThanOrEqual,
    '<=': LessThanOrEqual,
    'array': Assertion,
    'at': At,
    'boolean': Assertion,
    'case': Case,
    'coalesce': Coalesce,
    'collator': CollatorExpression,
    'format': FormatExpression,
    'image': ImageExpression,
    'in': In,
    'index-of': IndexOf,
    'interpolate': Interpolate,
    'interpolate-hcl': Interpolate,
    'interpolate-lab': Interpolate,
    'length': Length,
    'let': Let,
    'literal': Literal,
    'match': Match,
    'number': Assertion,
    'number-format': NumberFormat,
    'object': Assertion,
    'slice': Slice,
    'step': Step,
    'string': Assertion,
    'to-boolean': Coercion,
    'to-color': Coercion,
    'to-number': Coercion,
    'to-string': Coercion,
    'var': Var,
    'within': Within
};
function rgba(ctx, ref) {
    var r = ref[0];
    var g = ref[1];
    var b = ref[2];
    var a = ref[3];
    r = r.evaluate(ctx);
    g = g.evaluate(ctx);
    b = b.evaluate(ctx);
    var alpha = a ? a.evaluate(ctx) : 1;
    var error = validateRGBA(r, g, b, alpha);
    if (error) {
        throw new RuntimeError(error);
    }
    return new Color(r / 255 * alpha, g / 255 * alpha, b / 255 * alpha, alpha);
}
function has(key, obj) {
    return key in obj;
}
function get(key, obj) {
    var v = obj[key];
    return typeof v === 'undefined' ? null : v;
}
function binarySearch(v, a, i, j) {
    while (i <= j) {
        var m = i + j >> 1;
        if (a[m] === v) {
            return true;
        }
        if (a[m] > v) {
            j = m - 1;
        } else {
            i = m + 1;
        }
    }
    return false;
}
function varargs(type) {
    return { type: type };
}
CompoundExpression.register(expressions, {
    'error': [
        ErrorType,
        [StringType],
        function (ctx, ref) {
            var v = ref[0];
            throw new RuntimeError(v.evaluate(ctx));
        }
    ],
    'typeof': [
        StringType,
        [ValueType],
        function (ctx, ref) {
            var v = ref[0];
            return toString(typeOf(v.evaluate(ctx)));
        }
    ],
    'to-rgba': [
        array(NumberType, 4),
        [ColorType],
        function (ctx, ref) {
            var v = ref[0];
            return v.evaluate(ctx).toArray();
        }
    ],
    'rgb': [
        ColorType,
        [
            NumberType,
            NumberType,
            NumberType
        ],
        rgba
    ],
    'rgba': [
        ColorType,
        [
            NumberType,
            NumberType,
            NumberType,
            NumberType
        ],
        rgba
    ],
    'has': {
        type: BooleanType,
        overloads: [
            [
                [StringType],
                function (ctx, ref) {
                    var key = ref[0];
                    return has(key.evaluate(ctx), ctx.properties());
                }
            ],
            [
                [
                    StringType,
                    ObjectType
                ],
                function (ctx, ref) {
                    var key = ref[0];
                    var obj = ref[1];
                    return has(key.evaluate(ctx), obj.evaluate(ctx));
                }
            ]
        ]
    },
    'get': {
        type: ValueType,
        overloads: [
            [
                [StringType],
                function (ctx, ref) {
                    var key = ref[0];
                    return get(key.evaluate(ctx), ctx.properties());
                }
            ],
            [
                [
                    StringType,
                    ObjectType
                ],
                function (ctx, ref) {
                    var key = ref[0];
                    var obj = ref[1];
                    return get(key.evaluate(ctx), obj.evaluate(ctx));
                }
            ]
        ]
    },
    'feature-state': [
        ValueType,
        [StringType],
        function (ctx, ref) {
            var key = ref[0];
            return get(key.evaluate(ctx), ctx.featureState || {});
        }
    ],
    'properties': [
        ObjectType,
        [],
        function (ctx) {
            return ctx.properties();
        }
    ],
    'geometry-type': [
        StringType,
        [],
        function (ctx) {
            return ctx.geometryType();
        }
    ],
    'id': [
        ValueType,
        [],
        function (ctx) {
            return ctx.id();
        }
    ],
    'zoom': [
        NumberType,
        [],
        function (ctx) {
            return ctx.globals.zoom;
        }
    ],
    'heatmap-density': [
        NumberType,
        [],
        function (ctx) {
            return ctx.globals.heatmapDensity || 0;
        }
    ],
    'line-progress': [
        NumberType,
        [],
        function (ctx) {
            return ctx.globals.lineProgress || 0;
        }
    ],
    'accumulated': [
        ValueType,
        [],
        function (ctx) {
            return ctx.globals.accumulated === undefined ? null : ctx.globals.accumulated;
        }
    ],
    '+': [
        NumberType,
        varargs(NumberType),
        function (ctx, args) {
            var result = 0;
            for (var i = 0, list = args; i < list.length; i += 1) {
                var arg = list[i];
                result += arg.evaluate(ctx);
            }
            return result;
        }
    ],
    '*': [
        NumberType,
        varargs(NumberType),
        function (ctx, args) {
            var result = 1;
            for (var i = 0, list = args; i < list.length; i += 1) {
                var arg = list[i];
                result *= arg.evaluate(ctx);
            }
            return result;
        }
    ],
    '-': {
        type: NumberType,
        overloads: [
            [
                [
                    NumberType,
                    NumberType
                ],
                function (ctx, ref) {
                    var a = ref[0];
                    var b = ref[1];
                    return a.evaluate(ctx) - b.evaluate(ctx);
                }
            ],
            [
                [NumberType],
                function (ctx, ref) {
                    var a = ref[0];
                    return -a.evaluate(ctx);
                }
            ]
        ]
    },
    '/': [
        NumberType,
        [
            NumberType,
            NumberType
        ],
        function (ctx, ref) {
            var a = ref[0];
            var b = ref[1];
            return a.evaluate(ctx) / b.evaluate(ctx);
        }
    ],
    '%': [
        NumberType,
        [
            NumberType,
            NumberType
        ],
        function (ctx, ref) {
            var a = ref[0];
            var b = ref[1];
            return a.evaluate(ctx) % b.evaluate(ctx);
        }
    ],
    'ln2': [
        NumberType,
        [],
        function () {
            return Math.LN2;
        }
    ],
    'pi': [
        NumberType,
        [],
        function () {
            return Math.PI;
        }
    ],
    'e': [
        NumberType,
        [],
        function () {
            return Math.E;
        }
    ],
    '^': [
        NumberType,
        [
            NumberType,
            NumberType
        ],
        function (ctx, ref) {
            var b = ref[0];
            var e = ref[1];
            return Math.pow(b.evaluate(ctx), e.evaluate(ctx));
        }
    ],
    'sqrt': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var x = ref[0];
            return Math.sqrt(x.evaluate(ctx));
        }
    ],
    'log10': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.log(n.evaluate(ctx)) / Math.LN10;
        }
    ],
    'ln': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.log(n.evaluate(ctx));
        }
    ],
    'log2': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.log(n.evaluate(ctx)) / Math.LN2;
        }
    ],
    'sin': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.sin(n.evaluate(ctx));
        }
    ],
    'cos': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.cos(n.evaluate(ctx));
        }
    ],
    'tan': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.tan(n.evaluate(ctx));
        }
    ],
    'asin': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.asin(n.evaluate(ctx));
        }
    ],
    'acos': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.acos(n.evaluate(ctx));
        }
    ],
    'atan': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.atan(n.evaluate(ctx));
        }
    ],
    'min': [
        NumberType,
        varargs(NumberType),
        function (ctx, args) {
            return Math.min.apply(Math, args.map(function (arg) {
                return arg.evaluate(ctx);
            }));
        }
    ],
    'max': [
        NumberType,
        varargs(NumberType),
        function (ctx, args) {
            return Math.max.apply(Math, args.map(function (arg) {
                return arg.evaluate(ctx);
            }));
        }
    ],
    'abs': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.abs(n.evaluate(ctx));
        }
    ],
    'round': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            var v = n.evaluate(ctx);
            return v < 0 ? -Math.round(-v) : Math.round(v);
        }
    ],
    'floor': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.floor(n.evaluate(ctx));
        }
    ],
    'ceil': [
        NumberType,
        [NumberType],
        function (ctx, ref) {
            var n = ref[0];
            return Math.ceil(n.evaluate(ctx));
        }
    ],
    'filter-==': [
        BooleanType,
        [
            StringType,
            ValueType
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            return ctx.properties()[k.value] === v.value;
        }
    ],
    'filter-id-==': [
        BooleanType,
        [ValueType],
        function (ctx, ref) {
            var v = ref[0];
            return ctx.id() === v.value;
        }
    ],
    'filter-type-==': [
        BooleanType,
        [StringType],
        function (ctx, ref) {
            var v = ref[0];
            return ctx.geometryType() === v.value;
        }
    ],
    'filter-<': [
        BooleanType,
        [
            StringType,
            ValueType
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            var a = ctx.properties()[k.value];
            var b = v.value;
            return typeof a === typeof b && a < b;
        }
    ],
    'filter-id-<': [
        BooleanType,
        [ValueType],
        function (ctx, ref) {
            var v = ref[0];
            var a = ctx.id();
            var b = v.value;
            return typeof a === typeof b && a < b;
        }
    ],
    'filter->': [
        BooleanType,
        [
            StringType,
            ValueType
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            var a = ctx.properties()[k.value];
            var b = v.value;
            return typeof a === typeof b && a > b;
        }
    ],
    'filter-id->': [
        BooleanType,
        [ValueType],
        function (ctx, ref) {
            var v = ref[0];
            var a = ctx.id();
            var b = v.value;
            return typeof a === typeof b && a > b;
        }
    ],
    'filter-<=': [
        BooleanType,
        [
            StringType,
            ValueType
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            var a = ctx.properties()[k.value];
            var b = v.value;
            return typeof a === typeof b && a <= b;
        }
    ],
    'filter-id-<=': [
        BooleanType,
        [ValueType],
        function (ctx, ref) {
            var v = ref[0];
            var a = ctx.id();
            var b = v.value;
            return typeof a === typeof b && a <= b;
        }
    ],
    'filter->=': [
        BooleanType,
        [
            StringType,
            ValueType
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            var a = ctx.properties()[k.value];
            var b = v.value;
            return typeof a === typeof b && a >= b;
        }
    ],
    'filter-id->=': [
        BooleanType,
        [ValueType],
        function (ctx, ref) {
            var v = ref[0];
            var a = ctx.id();
            var b = v.value;
            return typeof a === typeof b && a >= b;
        }
    ],
    'filter-has': [
        BooleanType,
        [ValueType],
        function (ctx, ref) {
            var k = ref[0];
            return k.value in ctx.properties();
        }
    ],
    'filter-has-id': [
        BooleanType,
        [],
        function (ctx) {
            return ctx.id() !== null && ctx.id() !== undefined;
        }
    ],
    'filter-type-in': [
        BooleanType,
        [array(StringType)],
        function (ctx, ref) {
            var v = ref[0];
            return v.value.indexOf(ctx.geometryType()) >= 0;
        }
    ],
    'filter-id-in': [
        BooleanType,
        [array(ValueType)],
        function (ctx, ref) {
            var v = ref[0];
            return v.value.indexOf(ctx.id()) >= 0;
        }
    ],
    'filter-in-small': [
        BooleanType,
        [
            StringType,
            array(ValueType)
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            return v.value.indexOf(ctx.properties()[k.value]) >= 0;
        }
    ],
    'filter-in-large': [
        BooleanType,
        [
            StringType,
            array(ValueType)
        ],
        function (ctx, ref) {
            var k = ref[0];
            var v = ref[1];
            return binarySearch(ctx.properties()[k.value], v.value, 0, v.value.length - 1);
        }
    ],
    'all': {
        type: BooleanType,
        overloads: [
            [
                [
                    BooleanType,
                    BooleanType
                ],
                function (ctx, ref) {
                    var a = ref[0];
                    var b = ref[1];
                    return a.evaluate(ctx) && b.evaluate(ctx);
                }
            ],
            [
                varargs(BooleanType),
                function (ctx, args) {
                    for (var i = 0, list = args; i < list.length; i += 1) {
                        var arg = list[i];
                        if (!arg.evaluate(ctx)) {
                            return false;
                        }
                    }
                    return true;
                }
            ]
        ]
    },
    'any': {
        type: BooleanType,
        overloads: [
            [
                [
                    BooleanType,
                    BooleanType
                ],
                function (ctx, ref) {
                    var a = ref[0];
                    var b = ref[1];
                    return a.evaluate(ctx) || b.evaluate(ctx);
                }
            ],
            [
                varargs(BooleanType),
                function (ctx, args) {
                    for (var i = 0, list = args; i < list.length; i += 1) {
                        var arg = list[i];
                        if (arg.evaluate(ctx)) {
                            return true;
                        }
                    }
                    return false;
                }
            ]
        ]
    },
    '!': [
        BooleanType,
        [BooleanType],
        function (ctx, ref) {
            var b = ref[0];
            return !b.evaluate(ctx);
        }
    ],
    'is-supported-script': [
        BooleanType,
        [StringType],
        function (ctx, ref) {
            var s = ref[0];
            var isSupportedScript = ctx.globals && ctx.globals.isSupportedScript;
            if (isSupportedScript) {
                return isSupportedScript(s.evaluate(ctx));
            }
            return true;
        }
    ],
    'upcase': [
        StringType,
        [StringType],
        function (ctx, ref) {
            var s = ref[0];
            return s.evaluate(ctx).toUpperCase();
        }
    ],
    'downcase': [
        StringType,
        [StringType],
        function (ctx, ref) {
            var s = ref[0];
            return s.evaluate(ctx).toLowerCase();
        }
    ],
    'concat': [
        StringType,
        varargs(ValueType),
        function (ctx, args) {
            return args.map(function (arg) {
                return toString$1(arg.evaluate(ctx));
            }).join('');
        }
    ],
    'resolved-locale': [
        StringType,
        [CollatorType],
        function (ctx, ref) {
            var collator = ref[0];
            return collator.evaluate(ctx).resolvedLocale();
        }
    ]
});

function success(value) {
    return {
        result: 'success',
        value: value
    };
}
function error(value) {
    return {
        result: 'error',
        value: value
    };
}

function supportsPropertyExpression(spec) {
    return spec['property-type'] === 'data-driven' || spec['property-type'] === 'cross-faded-data-driven';
}
function supportsZoomExpression(spec) {
    return !!spec.expression && spec.expression.parameters.indexOf('zoom') > -1;
}
function supportsInterpolation(spec) {
    return !!spec.expression && spec.expression.interpolated;
}

function getType(val) {
    if (val instanceof Number) {
        return 'number';
    } else if (val instanceof String) {
        return 'string';
    } else if (val instanceof Boolean) {
        return 'boolean';
    } else if (Array.isArray(val)) {
        return 'array';
    } else if (val === null) {
        return 'null';
    } else {
        return typeof val;
    }
}

function isFunction(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function identityFunction(x) {
    return x;
}
function createFunction(parameters, propertySpec) {
    var isColor = propertySpec.type === 'color';
    var zoomAndFeatureDependent = parameters.stops && typeof parameters.stops[0][0] === 'object';
    var featureDependent = zoomAndFeatureDependent || parameters.property !== undefined;
    var zoomDependent = zoomAndFeatureDependent || !featureDependent;
    var type = parameters.type || (supportsInterpolation(propertySpec) ? 'exponential' : 'interval');
    if (isColor) {
        parameters = extend$1({}, parameters);
        if (parameters.stops) {
            parameters.stops = parameters.stops.map(function (stop) {
                return [
                    stop[0],
                    Color.parse(stop[1])
                ];
            });
        }
        if (parameters.default) {
            parameters.default = Color.parse(parameters.default);
        } else {
            parameters.default = Color.parse(propertySpec.default);
        }
    }
    if (parameters.colorSpace && parameters.colorSpace !== 'rgb' && !colorSpaces[parameters.colorSpace]) {
        throw new Error('Unknown color space: ' + parameters.colorSpace);
    }
    var innerFun;
    var hashedStops;
    var categoricalKeyType;
    if (type === 'exponential') {
        innerFun = evaluateExponentialFunction;
    } else if (type === 'interval') {
        innerFun = evaluateIntervalFunction;
    } else if (type === 'categorical') {
        innerFun = evaluateCategoricalFunction;
        hashedStops = Object.create(null);
        for (var i = 0, list = parameters.stops; i < list.length; i += 1) {
            var stop = list[i];
            hashedStops[stop[0]] = stop[1];
        }
        categoricalKeyType = typeof parameters.stops[0][0];
    } else if (type === 'identity') {
        innerFun = evaluateIdentityFunction;
    } else {
        throw new Error('Unknown function type "' + type + '"');
    }
    if (zoomAndFeatureDependent) {
        var featureFunctions = {};
        var zoomStops = [];
        for (var s = 0; s < parameters.stops.length; s++) {
            var stop$1 = parameters.stops[s];
            var zoom = stop$1[0].zoom;
            if (featureFunctions[zoom] === undefined) {
                featureFunctions[zoom] = {
                    zoom: zoom,
                    type: parameters.type,
                    property: parameters.property,
                    default: parameters.default,
                    stops: []
                };
                zoomStops.push(zoom);
            }
            featureFunctions[zoom].stops.push([
                stop$1[0].value,
                stop$1[1]
            ]);
        }
        var featureFunctionStops = [];
        for (var i$1 = 0, list$1 = zoomStops; i$1 < list$1.length; i$1 += 1) {
            var z = list$1[i$1];
            featureFunctionStops.push([
                featureFunctions[z].zoom,
                createFunction(featureFunctions[z], propertySpec)
            ]);
        }
        var interpolationType = { name: 'linear' };
        return {
            kind: 'composite',
            interpolationType: interpolationType,
            interpolationFactor: Interpolate.interpolationFactor.bind(undefined, interpolationType),
            zoomStops: featureFunctionStops.map(function (s) {
                return s[0];
            }),
            evaluate: function evaluate(ref, properties) {
                var zoom = ref.zoom;
                return evaluateExponentialFunction({
                    stops: featureFunctionStops,
                    base: parameters.base
                }, propertySpec, zoom).evaluate(zoom, properties);
            }
        };
    } else if (zoomDependent) {
        var interpolationType$1 = type === 'exponential' ? {
            name: 'exponential',
            base: parameters.base !== undefined ? parameters.base : 1
        } : null;
        return {
            kind: 'camera',
            interpolationType: interpolationType$1,
            interpolationFactor: Interpolate.interpolationFactor.bind(undefined, interpolationType$1),
            zoomStops: parameters.stops.map(function (s) {
                return s[0];
            }),
            evaluate: function (ref) {
                var zoom = ref.zoom;
                return innerFun(parameters, propertySpec, zoom, hashedStops, categoricalKeyType);
            }
        };
    } else {
        return {
            kind: 'source',
            evaluate: function evaluate(_, feature) {
                var value = feature && feature.properties ? feature.properties[parameters.property] : undefined;
                if (value === undefined) {
                    return coalesce(parameters.default, propertySpec.default);
                }
                return innerFun(parameters, propertySpec, value, hashedStops, categoricalKeyType);
            }
        };
    }
}
function coalesce(a, b, c) {
    if (a !== undefined) {
        return a;
    }
    if (b !== undefined) {
        return b;
    }
    if (c !== undefined) {
        return c;
    }
}
function evaluateCategoricalFunction(parameters, propertySpec, input, hashedStops, keyType) {
    var evaluated = typeof input === keyType ? hashedStops[input] : undefined;
    return coalesce(evaluated, parameters.default, propertySpec.default);
}
function evaluateIntervalFunction(parameters, propertySpec, input) {
    if (getType(input) !== 'number') {
        return coalesce(parameters.default, propertySpec.default);
    }
    var n = parameters.stops.length;
    if (n === 1) {
        return parameters.stops[0][1];
    }
    if (input <= parameters.stops[0][0]) {
        return parameters.stops[0][1];
    }
    if (input >= parameters.stops[n - 1][0]) {
        return parameters.stops[n - 1][1];
    }
    var index = findStopLessThanOrEqualTo(parameters.stops.map(function (stop) {
        return stop[0];
    }), input);
    return parameters.stops[index][1];
}
function evaluateExponentialFunction(parameters, propertySpec, input) {
    var base = parameters.base !== undefined ? parameters.base : 1;
    if (getType(input) !== 'number') {
        return coalesce(parameters.default, propertySpec.default);
    }
    var n = parameters.stops.length;
    if (n === 1) {
        return parameters.stops[0][1];
    }
    if (input <= parameters.stops[0][0]) {
        return parameters.stops[0][1];
    }
    if (input >= parameters.stops[n - 1][0]) {
        return parameters.stops[n - 1][1];
    }
    var index = findStopLessThanOrEqualTo(parameters.stops.map(function (stop) {
        return stop[0];
    }), input);
    var t = interpolationFactor(input, base, parameters.stops[index][0], parameters.stops[index + 1][0]);
    var outputLower = parameters.stops[index][1];
    var outputUpper = parameters.stops[index + 1][1];
    var interp = interpolate[propertySpec.type] || identityFunction;
    if (parameters.colorSpace && parameters.colorSpace !== 'rgb') {
        var colorspace = colorSpaces[parameters.colorSpace];
        interp = function (a, b) {
            return colorspace.reverse(colorspace.interpolate(colorspace.forward(a), colorspace.forward(b), t));
        };
    }
    if (typeof outputLower.evaluate === 'function') {
        return {
            evaluate: function evaluate() {
                var args = [], len = arguments.length;
                while (len--)
                    args[len] = arguments[len];
                var evaluatedLower = outputLower.evaluate.apply(undefined, args);
                var evaluatedUpper = outputUpper.evaluate.apply(undefined, args);
                if (evaluatedLower === undefined || evaluatedUpper === undefined) {
                    return undefined;
                }
                return interp(evaluatedLower, evaluatedUpper, t);
            }
        };
    }
    return interp(outputLower, outputUpper, t);
}
function evaluateIdentityFunction(parameters, propertySpec, input) {
    if (propertySpec.type === 'color') {
        input = Color.parse(input);
    } else if (propertySpec.type === 'formatted') {
        input = Formatted.fromString(input.toString());
    } else if (propertySpec.type === 'resolvedImage') {
        input = ResolvedImage.fromString(input.toString());
    } else if (getType(input) !== propertySpec.type && (propertySpec.type !== 'enum' || !propertySpec.values[input])) {
        input = undefined;
    }
    return coalesce(input, parameters.default, propertySpec.default);
}
function interpolationFactor(input, base, lowerValue, upperValue) {
    var difference = upperValue - lowerValue;
    var progress = input - lowerValue;
    if (difference === 0) {
        return 0;
    } else if (base === 1) {
        return progress / difference;
    } else {
        return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
    }
}

var StyleExpression = function StyleExpression(expression, propertySpec) {
    this.expression = expression;
    this._warningHistory = {};
    this._evaluator = new EvaluationContext();
    this._defaultValue = propertySpec ? getDefaultValue(propertySpec) : null;
    this._enumValues = propertySpec && propertySpec.type === 'enum' ? propertySpec.values : null;
};
StyleExpression.prototype.evaluateWithoutErrorHandling = function evaluateWithoutErrorHandling(globals, feature, featureState, canonical, availableImages, formattedSection) {
    this._evaluator.globals = globals;
    this._evaluator.feature = feature;
    this._evaluator.featureState = featureState;
    this._evaluator.canonical = canonical;
    this._evaluator.availableImages = availableImages || null;
    this._evaluator.formattedSection = formattedSection;
    return this.expression.evaluate(this._evaluator);
};
StyleExpression.prototype.evaluate = function evaluate(globals, feature, featureState, canonical, availableImages, formattedSection) {
    this._evaluator.globals = globals;
    this._evaluator.feature = feature || null;
    this._evaluator.featureState = featureState || null;
    this._evaluator.canonical = canonical;
    this._evaluator.availableImages = availableImages || null;
    this._evaluator.formattedSection = formattedSection || null;
    try {
        var val = this.expression.evaluate(this._evaluator);
        if (val === null || val === undefined || typeof val === 'number' && val !== val) {
            return this._defaultValue;
        }
        if (this._enumValues && !(val in this._enumValues)) {
            throw new RuntimeError('Expected value to be one of ' + Object.keys(this._enumValues).map(function (v) {
                return JSON.stringify(v);
            }).join(', ') + ', but found ' + JSON.stringify(val) + ' instead.');
        }
        return val;
    } catch (e) {
        if (!this._warningHistory[e.message]) {
            this._warningHistory[e.message] = true;
            if (typeof console !== 'undefined') {
                console.warn(e.message);
            }
        }
        return this._defaultValue;
    }
};
function isExpression(expression) {
    return Array.isArray(expression) && expression.length > 0 && typeof expression[0] === 'string' && expression[0] in expressions;
}
function createExpression(expression, propertySpec) {
    var parser = new ParsingContext(expressions, [], propertySpec ? getExpectedType(propertySpec) : undefined);
    var parsed = parser.parse(expression, undefined, undefined, undefined, propertySpec && propertySpec.type === 'string' ? { typeAnnotation: 'coerce' } : undefined);
    if (!parsed) {
        return error(parser.errors);
    }
    return success(new StyleExpression(parsed, propertySpec));
}
var ZoomConstantExpression = function ZoomConstantExpression(kind, expression) {
    this.kind = kind;
    this._styleExpression = expression;
    this.isStateDependent = kind !== 'constant' && !isStateConstant(expression.expression);
};
ZoomConstantExpression.prototype.evaluateWithoutErrorHandling = function evaluateWithoutErrorHandling(globals, feature, featureState, canonical, availableImages, formattedSection) {
    return this._styleExpression.evaluateWithoutErrorHandling(globals, feature, featureState, canonical, availableImages, formattedSection);
};
ZoomConstantExpression.prototype.evaluate = function evaluate(globals, feature, featureState, canonical, availableImages, formattedSection) {
    return this._styleExpression.evaluate(globals, feature, featureState, canonical, availableImages, formattedSection);
};
var ZoomDependentExpression = function ZoomDependentExpression(kind, expression, zoomStops, interpolationType) {
    this.kind = kind;
    this.zoomStops = zoomStops;
    this._styleExpression = expression;
    this.isStateDependent = kind !== 'camera' && !isStateConstant(expression.expression);
    this.interpolationType = interpolationType;
};
ZoomDependentExpression.prototype.evaluateWithoutErrorHandling = function evaluateWithoutErrorHandling(globals, feature, featureState, canonical, availableImages, formattedSection) {
    return this._styleExpression.evaluateWithoutErrorHandling(globals, feature, featureState, canonical, availableImages, formattedSection);
};
ZoomDependentExpression.prototype.evaluate = function evaluate(globals, feature, featureState, canonical, availableImages, formattedSection) {
    return this._styleExpression.evaluate(globals, feature, featureState, canonical, availableImages, formattedSection);
};
ZoomDependentExpression.prototype.interpolationFactor = function interpolationFactor(input, lower, upper) {
    if (this.interpolationType) {
        return Interpolate.interpolationFactor(this.interpolationType, input, lower, upper);
    } else {
        return 0;
    }
};
function createPropertyExpression(expression, propertySpec) {
    expression = createExpression(expression, propertySpec);
    if (expression.result === 'error') {
        return expression;
    }
    var parsed = expression.value.expression;
    var isFeatureConstant$1 = isFeatureConstant(parsed);
    if (!isFeatureConstant$1 && !supportsPropertyExpression(propertySpec)) {
        return error([new ParsingError('', 'data expressions not supported')]);
    }
    var isZoomConstant = isGlobalPropertyConstant(parsed, ['zoom']);
    if (!isZoomConstant && !supportsZoomExpression(propertySpec)) {
        return error([new ParsingError('', 'zoom expressions not supported')]);
    }
    var zoomCurve = findZoomCurve(parsed);
    if (!zoomCurve && !isZoomConstant) {
        return error([new ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.')]);
    } else if (zoomCurve instanceof ParsingError) {
        return error([zoomCurve]);
    } else if (zoomCurve instanceof Interpolate && !supportsInterpolation(propertySpec)) {
        return error([new ParsingError('', '"interpolate" expressions cannot be used with this property')]);
    }
    if (!zoomCurve) {
        return success(isFeatureConstant$1 ? new ZoomConstantExpression('constant', expression.value) : new ZoomConstantExpression('source', expression.value));
    }
    var interpolationType = zoomCurve instanceof Interpolate ? zoomCurve.interpolation : undefined;
    return success(isFeatureConstant$1 ? new ZoomDependentExpression('camera', expression.value, zoomCurve.labels, interpolationType) : new ZoomDependentExpression('composite', expression.value, zoomCurve.labels, interpolationType));
}
var StylePropertyFunction = function StylePropertyFunction(parameters, specification) {
    this._parameters = parameters;
    this._specification = specification;
    extend$1(this, createFunction(this._parameters, this._specification));
};
StylePropertyFunction.deserialize = function deserialize(serialized) {
    return new StylePropertyFunction(serialized._parameters, serialized._specification);
};
StylePropertyFunction.serialize = function serialize(input) {
    return {
        _parameters: input._parameters,
        _specification: input._specification
    };
};
function normalizePropertyExpression(value, specification) {
    if (isFunction(value)) {
        return new StylePropertyFunction(value, specification);
    } else if (isExpression(value)) {
        var expression = createPropertyExpression(value, specification);
        if (expression.result === 'error') {
            throw new Error(expression.value.map(function (err) {
                return err.key + ': ' + err.message;
            }).join(', '));
        }
        return expression.value;
    } else {
        var constant = value;
        if (typeof value === 'string' && specification.type === 'color') {
            constant = Color.parse(value);
        }
        return {
            kind: 'constant',
            evaluate: function () {
                return constant;
            }
        };
    }
}
function findZoomCurve(expression) {
    var result = null;
    if (expression instanceof Let) {
        result = findZoomCurve(expression.result);
    } else if (expression instanceof Coalesce) {
        for (var i = 0, list = expression.args; i < list.length; i += 1) {
            var arg = list[i];
            result = findZoomCurve(arg);
            if (result) {
                break;
            }
        }
    } else if ((expression instanceof Step || expression instanceof Interpolate) && expression.input instanceof CompoundExpression && expression.input.name === 'zoom') {
        result = expression;
    }
    if (result instanceof ParsingError) {
        return result;
    }
    expression.eachChild(function (child) {
        var childResult = findZoomCurve(child);
        if (childResult instanceof ParsingError) {
            result = childResult;
        } else if (!result && childResult) {
            result = new ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.');
        } else if (result && childResult && result !== childResult) {
            result = new ParsingError('', 'Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.');
        }
    });
    return result;
}
function getExpectedType(spec) {
    var types = {
        color: ColorType,
        string: StringType,
        number: NumberType,
        enum: StringType,
        boolean: BooleanType,
        formatted: FormattedType,
        resolvedImage: ResolvedImageType
    };
    if (spec.type === 'array') {
        return array(types[spec.value] || ValueType, spec.length);
    }
    return types[spec.type];
}
function getDefaultValue(spec) {
    if (spec.type === 'color' && isFunction(spec.default)) {
        return new Color(0, 0, 0, 0);
    } else if (spec.type === 'color') {
        return Color.parse(spec.default) || null;
    } else if (spec.default === undefined) {
        return null;
    } else {
        return spec.default;
    }
}

function validateObject(options) {
    var key = options.key;
    var object = options.value;
    var elementSpecs = options.valueSpec || {};
    var elementValidators = options.objectElementValidators || {};
    var style = options.style;
    var styleSpec = options.styleSpec;
    var errors = [];
    var type = getType(object);
    if (type !== 'object') {
        return [new ValidationError(key, object, 'object expected, ' + type + ' found')];
    }
    for (var objectKey in object) {
        var elementSpecKey = objectKey.split('.')[0];
        var elementSpec = elementSpecs[elementSpecKey] || elementSpecs['*'];
        var validateElement = void 0;
        if (elementValidators[elementSpecKey]) {
            validateElement = elementValidators[elementSpecKey];
        } else if (elementSpecs[elementSpecKey]) {
            validateElement = validate;
        } else if (elementValidators['*']) {
            validateElement = elementValidators['*'];
        } else if (elementSpecs['*']) {
            validateElement = validate;
        } else {
            errors.push(new ValidationError(key, object[objectKey], 'unknown property "' + objectKey + '"'));
            continue;
        }
        errors = errors.concat(validateElement({
            key: (key ? key + '.' : key) + objectKey,
            value: object[objectKey],
            valueSpec: elementSpec,
            style: style,
            styleSpec: styleSpec,
            object: object,
            objectKey: objectKey
        }, object));
    }
    for (var elementSpecKey$1 in elementSpecs) {
        if (elementValidators[elementSpecKey$1]) {
            continue;
        }
        if (elementSpecs[elementSpecKey$1].required && elementSpecs[elementSpecKey$1]['default'] === undefined && object[elementSpecKey$1] === undefined) {
            errors.push(new ValidationError(key, object, 'missing required property "' + elementSpecKey$1 + '"'));
        }
    }
    return errors;
}

function validateArray(options) {
    var array = options.value;
    var arraySpec = options.valueSpec;
    var style = options.style;
    var styleSpec = options.styleSpec;
    var key = options.key;
    var validateArrayElement = options.arrayElementValidator || validate;
    if (getType(array) !== 'array') {
        return [new ValidationError(key, array, 'array expected, ' + getType(array) + ' found')];
    }
    if (arraySpec.length && array.length !== arraySpec.length) {
        return [new ValidationError(key, array, 'array length ' + arraySpec.length + ' expected, length ' + array.length + ' found')];
    }
    if (arraySpec['min-length'] && array.length < arraySpec['min-length']) {
        return [new ValidationError(key, array, 'array length at least ' + arraySpec['min-length'] + ' expected, length ' + array.length + ' found')];
    }
    var arrayElementSpec = {
        'type': arraySpec.value,
        'values': arraySpec.values
    };
    if (styleSpec.$version < 7) {
        arrayElementSpec.function = arraySpec.function;
    }
    if (getType(arraySpec.value) === 'object') {
        arrayElementSpec = arraySpec.value;
    }
    var errors = [];
    for (var i = 0; i < array.length; i++) {
        errors = errors.concat(validateArrayElement({
            array: array,
            arrayIndex: i,
            value: array[i],
            valueSpec: arrayElementSpec,
            style: style,
            styleSpec: styleSpec,
            key: key + '[' + i + ']'
        }));
    }
    return errors;
}

function validateNumber(options) {
    var key = options.key;
    var value = options.value;
    var valueSpec = options.valueSpec;
    var type = getType(value);
    if (type === 'number' && value !== value) {
        type = 'NaN';
    }
    if (type !== 'number') {
        return [new ValidationError(key, value, 'number expected, ' + type + ' found')];
    }
    if ('minimum' in valueSpec && value < valueSpec.minimum) {
        return [new ValidationError(key, value, value + ' is less than the minimum value ' + valueSpec.minimum)];
    }
    if ('maximum' in valueSpec && value > valueSpec.maximum) {
        return [new ValidationError(key, value, value + ' is greater than the maximum value ' + valueSpec.maximum)];
    }
    return [];
}

function validateFunction(options) {
    var functionValueSpec = options.valueSpec;
    var functionType = unbundle(options.value.type);
    var stopKeyType;
    var stopDomainValues = {};
    var previousStopDomainValue;
    var previousStopDomainZoom;
    var isZoomFunction = functionType !== 'categorical' && options.value.property === undefined;
    var isPropertyFunction = !isZoomFunction;
    var isZoomAndPropertyFunction = getType(options.value.stops) === 'array' && getType(options.value.stops[0]) === 'array' && getType(options.value.stops[0][0]) === 'object';
    var errors = validateObject({
        key: options.key,
        value: options.value,
        valueSpec: options.styleSpec.function,
        style: options.style,
        styleSpec: options.styleSpec,
        objectElementValidators: {
            stops: validateFunctionStops,
            default: validateFunctionDefault
        }
    });
    if (functionType === 'identity' && isZoomFunction) {
        errors.push(new ValidationError(options.key, options.value, 'missing required property "property"'));
    }
    if (functionType !== 'identity' && !options.value.stops) {
        errors.push(new ValidationError(options.key, options.value, 'missing required property "stops"'));
    }
    if (functionType === 'exponential' && options.valueSpec.expression && !supportsInterpolation(options.valueSpec)) {
        errors.push(new ValidationError(options.key, options.value, 'exponential functions not supported'));
    }
    if (options.styleSpec.$version >= 8) {
        if (isPropertyFunction && !supportsPropertyExpression(options.valueSpec)) {
            errors.push(new ValidationError(options.key, options.value, 'property functions not supported'));
        } else if (isZoomFunction && !supportsZoomExpression(options.valueSpec)) {
            errors.push(new ValidationError(options.key, options.value, 'zoom functions not supported'));
        }
    }
    if ((functionType === 'categorical' || isZoomAndPropertyFunction) && options.value.property === undefined) {
        errors.push(new ValidationError(options.key, options.value, '"property" property is required'));
    }
    return errors;
    function validateFunctionStops(options) {
        if (functionType === 'identity') {
            return [new ValidationError(options.key, options.value, 'identity function may not have a "stops" property')];
        }
        var errors = [];
        var value = options.value;
        errors = errors.concat(validateArray({
            key: options.key,
            value: value,
            valueSpec: options.valueSpec,
            style: options.style,
            styleSpec: options.styleSpec,
            arrayElementValidator: validateFunctionStop
        }));
        if (getType(value) === 'array' && value.length === 0) {
            errors.push(new ValidationError(options.key, value, 'array must have at least one stop'));
        }
        return errors;
    }
    function validateFunctionStop(options) {
        var errors = [];
        var value = options.value;
        var key = options.key;
        if (getType(value) !== 'array') {
            return [new ValidationError(key, value, 'array expected, ' + getType(value) + ' found')];
        }
        if (value.length !== 2) {
            return [new ValidationError(key, value, 'array length 2 expected, length ' + value.length + ' found')];
        }
        if (isZoomAndPropertyFunction) {
            if (getType(value[0]) !== 'object') {
                return [new ValidationError(key, value, 'object expected, ' + getType(value[0]) + ' found')];
            }
            if (value[0].zoom === undefined) {
                return [new ValidationError(key, value, 'object stop key must have zoom')];
            }
            if (value[0].value === undefined) {
                return [new ValidationError(key, value, 'object stop key must have value')];
            }
            if (previousStopDomainZoom && previousStopDomainZoom > unbundle(value[0].zoom)) {
                return [new ValidationError(key, value[0].zoom, 'stop zoom values must appear in ascending order')];
            }
            if (unbundle(value[0].zoom) !== previousStopDomainZoom) {
                previousStopDomainZoom = unbundle(value[0].zoom);
                previousStopDomainValue = undefined;
                stopDomainValues = {};
            }
            errors = errors.concat(validateObject({
                key: key + '[0]',
                value: value[0],
                valueSpec: { zoom: {} },
                style: options.style,
                styleSpec: options.styleSpec,
                objectElementValidators: {
                    zoom: validateNumber,
                    value: validateStopDomainValue
                }
            }));
        } else {
            errors = errors.concat(validateStopDomainValue({
                key: key + '[0]',
                value: value[0],
                valueSpec: {},
                style: options.style,
                styleSpec: options.styleSpec
            }, value));
        }
        if (isExpression(deepUnbundle(value[1]))) {
            return errors.concat([new ValidationError(key + '[1]', value[1], 'expressions are not allowed in function stops.')]);
        }
        return errors.concat(validate({
            key: key + '[1]',
            value: value[1],
            valueSpec: functionValueSpec,
            style: options.style,
            styleSpec: options.styleSpec
        }));
    }
    function validateStopDomainValue(options, stop) {
        var type = getType(options.value);
        var value = unbundle(options.value);
        var reportValue = options.value !== null ? options.value : stop;
        if (!stopKeyType) {
            stopKeyType = type;
        } else if (type !== stopKeyType) {
            return [new ValidationError(options.key, reportValue, type + ' stop domain type must match previous stop domain type ' + stopKeyType)];
        }
        if (type !== 'number' && type !== 'string' && type !== 'boolean') {
            return [new ValidationError(options.key, reportValue, 'stop domain value must be a number, string, or boolean')];
        }
        if (type !== 'number' && functionType !== 'categorical') {
            var message = 'number expected, ' + type + ' found';
            if (supportsPropertyExpression(functionValueSpec) && functionType === undefined) {
                message += '\nIf you intended to use a categorical function, specify `"type": "categorical"`.';
            }
            return [new ValidationError(options.key, reportValue, message)];
        }
        if (functionType === 'categorical' && type === 'number' && (!isFinite(value) || Math.floor(value) !== value)) {
            return [new ValidationError(options.key, reportValue, 'integer expected, found ' + value)];
        }
        if (functionType !== 'categorical' && type === 'number' && previousStopDomainValue !== undefined && value < previousStopDomainValue) {
            return [new ValidationError(options.key, reportValue, 'stop domain values must appear in ascending order')];
        } else {
            previousStopDomainValue = value;
        }
        if (functionType === 'categorical' && value in stopDomainValues) {
            return [new ValidationError(options.key, reportValue, 'stop domain values must be unique')];
        } else {
            stopDomainValues[value] = true;
        }
        return [];
    }
    function validateFunctionDefault(options) {
        return validate({
            key: options.key,
            value: options.value,
            valueSpec: functionValueSpec,
            style: options.style,
            styleSpec: options.styleSpec
        });
    }
}

function validateExpression(options) {
    var expression = (options.expressionContext === 'property' ? createPropertyExpression : createExpression)(deepUnbundle(options.value), options.valueSpec);
    if (expression.result === 'error') {
        return expression.value.map(function (error) {
            return new ValidationError('' + options.key + error.key, options.value, error.message);
        });
    }
    var expressionObj = expression.value.expression || expression.value._styleExpression.expression;
    if (options.expressionContext === 'property' && options.propertyKey === 'text-font' && !expressionObj.outputDefined()) {
        return [new ValidationError(options.key, options.value, 'Invalid data expression for "' + options.propertyKey + '". Output values must be contained as literals within the expression.')];
    }
    if (options.expressionContext === 'property' && options.propertyType === 'layout' && !isStateConstant(expressionObj)) {
        return [new ValidationError(options.key, options.value, '"feature-state" data expressions are not supported with layout properties.')];
    }
    if (options.expressionContext === 'filter' && !isStateConstant(expressionObj)) {
        return [new ValidationError(options.key, options.value, '"feature-state" data expressions are not supported with filters.')];
    }
    if (options.expressionContext && options.expressionContext.indexOf('cluster') === 0) {
        if (!isGlobalPropertyConstant(expressionObj, [
                'zoom',
                'feature-state'
            ])) {
            return [new ValidationError(options.key, options.value, '"zoom" and "feature-state" expressions are not supported with cluster properties.')];
        }
        if (options.expressionContext === 'cluster-initial' && !isFeatureConstant(expressionObj)) {
            return [new ValidationError(options.key, options.value, 'Feature data expressions are not supported with initial expression part of cluster properties.')];
        }
    }
    return [];
}

function validateBoolean(options) {
    var value = options.value;
    var key = options.key;
    var type = getType(value);
    if (type !== 'boolean') {
        return [new ValidationError(key, value, 'boolean expected, ' + type + ' found')];
    }
    return [];
}

function validateColor(options) {
    var key = options.key;
    var value = options.value;
    var type = getType(value);
    if (type !== 'string') {
        return [new ValidationError(key, value, 'color expected, ' + type + ' found')];
    }
    if (csscolorparser_1(value) === null) {
        return [new ValidationError(key, value, 'color expected, "' + value + '" found')];
    }
    return [];
}

function validateEnum(options) {
    var key = options.key;
    var value = options.value;
    var valueSpec = options.valueSpec;
    var errors = [];
    if (Array.isArray(valueSpec.values)) {
        if (valueSpec.values.indexOf(unbundle(value)) === -1) {
            errors.push(new ValidationError(key, value, 'expected one of [' + valueSpec.values.join(', ') + '], ' + JSON.stringify(value) + ' found'));
        }
    } else {
        if (Object.keys(valueSpec.values).indexOf(unbundle(value)) === -1) {
            errors.push(new ValidationError(key, value, 'expected one of [' + Object.keys(valueSpec.values).join(', ') + '], ' + JSON.stringify(value) + ' found'));
        }
    }
    return errors;
}

function isExpressionFilter(filter) {
    if (filter === true || filter === false) {
        return true;
    }
    if (!Array.isArray(filter) || filter.length === 0) {
        return false;
    }
    switch (filter[0]) {
    case 'has':
        return filter.length >= 2 && filter[1] !== '$id' && filter[1] !== '$type';
    case 'in':
        return filter.length >= 3 && (typeof filter[1] !== 'string' || Array.isArray(filter[2]));
    case '!in':
    case '!has':
    case 'none':
        return false;
    case '==':
    case '!=':
    case '>':
    case '>=':
    case '<':
    case '<=':
        return filter.length !== 3 || (Array.isArray(filter[1]) || Array.isArray(filter[2]));
    case 'any':
    case 'all':
        for (var i = 0, list = filter.slice(1); i < list.length; i += 1) {
            var f = list[i];
            if (!isExpressionFilter(f) && typeof f !== 'boolean') {
                return false;
            }
        }
        return true;
    default:
        return true;
    }
}
var filterSpec = {
    'type': 'boolean',
    'default': false,
    'transition': false,
    'property-type': 'data-driven',
    'expression': {
        'interpolated': false,
        'parameters': [
            'zoom',
            'feature'
        ]
    }
};
function createFilter(filter) {
    if (filter === null || filter === undefined) {
        return {
            filter: function () {
                return true;
            },
            needGeometry: false
        };
    }
    if (!isExpressionFilter(filter)) {
        filter = convertFilter(filter);
    }
    var compiled = createExpression(filter, filterSpec);
    if (compiled.result === 'error') {
        throw new Error(compiled.value.map(function (err) {
            return err.key + ': ' + err.message;
        }).join(', '));
    } else {
        var needGeometry = geometryNeeded(filter);
        return {
            filter: function (globalProperties, feature, canonical) {
                return compiled.value.evaluate(globalProperties, feature, {}, canonical);
            },
            needGeometry: needGeometry
        };
    }
}
function compare(a, b) {
    return a < b ? -1 : a > b ? 1 : 0;
}
function geometryNeeded(filter) {
    if (!Array.isArray(filter)) {
        return false;
    }
    if (filter[0] === 'within') {
        return true;
    }
    for (var index = 1; index < filter.length; index++) {
        if (geometryNeeded(filter[index])) {
            return true;
        }
    }
    return false;
}
function convertFilter(filter) {
    if (!filter) {
        return true;
    }
    var op = filter[0];
    if (filter.length <= 1) {
        return op !== 'any';
    }
    var converted = op === '==' ? convertComparisonOp(filter[1], filter[2], '==') : op === '!=' ? convertNegation(convertComparisonOp(filter[1], filter[2], '==')) : op === '<' || op === '>' || op === '<=' || op === '>=' ? convertComparisonOp(filter[1], filter[2], op) : op === 'any' ? convertDisjunctionOp(filter.slice(1)) : op === 'all' ? ['all'].concat(filter.slice(1).map(convertFilter)) : op === 'none' ? ['all'].concat(filter.slice(1).map(convertFilter).map(convertNegation)) : op === 'in' ? convertInOp(filter[1], filter.slice(2)) : op === '!in' ? convertNegation(convertInOp(filter[1], filter.slice(2))) : op === 'has' ? convertHasOp(filter[1]) : op === '!has' ? convertNegation(convertHasOp(filter[1])) : op === 'within' ? filter : true;
    return converted;
}
function convertComparisonOp(property, value, op) {
    switch (property) {
    case '$type':
        return [
            'filter-type-' + op,
            value
        ];
    case '$id':
        return [
            'filter-id-' + op,
            value
        ];
    default:
        return [
            'filter-' + op,
            property,
            value
        ];
    }
}
function convertDisjunctionOp(filters) {
    return ['any'].concat(filters.map(convertFilter));
}
function convertInOp(property, values) {
    if (values.length === 0) {
        return false;
    }
    switch (property) {
    case '$type':
        return [
            'filter-type-in',
            [
                'literal',
                values
            ]
        ];
    case '$id':
        return [
            'filter-id-in',
            [
                'literal',
                values
            ]
        ];
    default:
        if (values.length > 200 && !values.some(function (v) {
                return typeof v !== typeof values[0];
            })) {
            return [
                'filter-in-large',
                property,
                [
                    'literal',
                    values.sort(compare)
                ]
            ];
        } else {
            return [
                'filter-in-small',
                property,
                [
                    'literal',
                    values
                ]
            ];
        }
    }
}
function convertHasOp(property) {
    switch (property) {
    case '$type':
        return true;
    case '$id':
        return ['filter-has-id'];
    default:
        return [
            'filter-has',
            property
        ];
    }
}
function convertNegation(filter) {
    return [
        '!',
        filter
    ];
}

function validateFilter(options) {
    if (isExpressionFilter(deepUnbundle(options.value))) {
        return validateExpression(extend$1({}, options, {
            expressionContext: 'filter',
            valueSpec: { value: 'boolean' }
        }));
    } else {
        return validateNonExpressionFilter(options);
    }
}
function validateNonExpressionFilter(options) {
    var value = options.value;
    var key = options.key;
    if (getType(value) !== 'array') {
        return [new ValidationError(key, value, 'array expected, ' + getType(value) + ' found')];
    }
    var styleSpec = options.styleSpec;
    var type;
    var errors = [];
    if (value.length < 1) {
        return [new ValidationError(key, value, 'filter array must have at least 1 element')];
    }
    errors = errors.concat(validateEnum({
        key: key + '[0]',
        value: value[0],
        valueSpec: styleSpec.filter_operator,
        style: options.style,
        styleSpec: options.styleSpec
    }));
    switch (unbundle(value[0])) {
    case '<':
    case '<=':
    case '>':
    case '>=':
        if (value.length >= 2 && unbundle(value[1]) === '$type') {
            errors.push(new ValidationError(key, value, '"$type" cannot be use with operator "' + value[0] + '"'));
        }
    case '==':
    case '!=':
        if (value.length !== 3) {
            errors.push(new ValidationError(key, value, 'filter array for operator "' + value[0] + '" must have 3 elements'));
        }
    case 'in':
    case '!in':
        if (value.length >= 2) {
            type = getType(value[1]);
            if (type !== 'string') {
                errors.push(new ValidationError(key + '[1]', value[1], 'string expected, ' + type + ' found'));
            }
        }
        for (var i = 2; i < value.length; i++) {
            type = getType(value[i]);
            if (unbundle(value[1]) === '$type') {
                errors = errors.concat(validateEnum({
                    key: key + '[' + i + ']',
                    value: value[i],
                    valueSpec: styleSpec.geometry_type,
                    style: options.style,
                    styleSpec: options.styleSpec
                }));
            } else if (type !== 'string' && type !== 'number' && type !== 'boolean') {
                errors.push(new ValidationError(key + '[' + i + ']', value[i], 'string, number, or boolean expected, ' + type + ' found'));
            }
        }
        break;
    case 'any':
    case 'all':
    case 'none':
        for (var i$1 = 1; i$1 < value.length; i$1++) {
            errors = errors.concat(validateNonExpressionFilter({
                key: key + '[' + i$1 + ']',
                value: value[i$1],
                style: options.style,
                styleSpec: options.styleSpec
            }));
        }
        break;
    case 'has':
    case '!has':
        type = getType(value[1]);
        if (value.length !== 2) {
            errors.push(new ValidationError(key, value, 'filter array for "' + value[0] + '" operator must have 2 elements'));
        } else if (type !== 'string') {
            errors.push(new ValidationError(key + '[1]', value[1], 'string expected, ' + type + ' found'));
        }
        break;
    case 'within':
        type = getType(value[1]);
        if (value.length !== 2) {
            errors.push(new ValidationError(key, value, 'filter array for "' + value[0] + '" operator must have 2 elements'));
        } else if (type !== 'object') {
            errors.push(new ValidationError(key + '[1]', value[1], 'object expected, ' + type + ' found'));
        }
        break;
    }
    return errors;
}

function validateProperty(options, propertyType) {
    var key = options.key;
    var style = options.style;
    var styleSpec = options.styleSpec;
    var value = options.value;
    var propertyKey = options.objectKey;
    var layerSpec = styleSpec[propertyType + '_' + options.layerType];
    if (!layerSpec) {
        return [];
    }
    var transitionMatch = propertyKey.match(/^(.*)-transition$/);
    if (propertyType === 'paint' && transitionMatch && layerSpec[transitionMatch[1]] && layerSpec[transitionMatch[1]].transition) {
        return validate({
            key: key,
            value: value,
            valueSpec: styleSpec.transition,
            style: style,
            styleSpec: styleSpec
        });
    }
    var valueSpec = options.valueSpec || layerSpec[propertyKey];
    if (!valueSpec) {
        return [new ValidationError(key, value, 'unknown property "' + propertyKey + '"')];
    }
    var tokenMatch;
    if (getType(value) === 'string' && supportsPropertyExpression(valueSpec) && !valueSpec.tokens && (tokenMatch = /^{([^}]+)}$/.exec(value))) {
        return [new ValidationError(key, value, '"' + propertyKey + '" does not support interpolation syntax\n' + 'Use an identity property function instead: `{ "type": "identity", "property": ' + JSON.stringify(tokenMatch[1]) + ' }`.')];
    }
    var errors = [];
    if (options.layerType === 'symbol') {
        if (propertyKey === 'text-field' && style && !style.glyphs) {
            errors.push(new ValidationError(key, value, 'use of "text-field" requires a style "glyphs" property'));
        }
        if (propertyKey === 'text-font' && isFunction(deepUnbundle(value)) && unbundle(value.type) === 'identity') {
            errors.push(new ValidationError(key, value, '"text-font" does not support identity functions'));
        }
    }
    return errors.concat(validate({
        key: options.key,
        value: value,
        valueSpec: valueSpec,
        style: style,
        styleSpec: styleSpec,
        expressionContext: 'property',
        propertyType: propertyType,
        propertyKey: propertyKey
    }));
}

function validatePaintProperty(options) {
    return validateProperty(options, 'paint');
}

function validateLayoutProperty(options) {
    return validateProperty(options, 'layout');
}

function validateLayer(options) {
    var errors = [];
    var layer = options.value;
    var key = options.key;
    var style = options.style;
    var styleSpec = options.styleSpec;
    if (!layer.type && !layer.ref) {
        errors.push(new ValidationError(key, layer, 'either "type" or "ref" is required'));
    }
    var type = unbundle(layer.type);
    var ref = unbundle(layer.ref);
    if (layer.id) {
        var layerId = unbundle(layer.id);
        for (var i = 0; i < options.arrayIndex; i++) {
            var otherLayer = style.layers[i];
            if (unbundle(otherLayer.id) === layerId) {
                errors.push(new ValidationError(key, layer.id, 'duplicate layer id "' + layer.id + '", previously used at line ' + otherLayer.id.__line__));
            }
        }
    }
    if ('ref' in layer) {
        [
            'type',
            'source',
            'source-layer',
            'filter',
            'layout'
        ].forEach(function (p) {
            if (p in layer) {
                errors.push(new ValidationError(key, layer[p], '"' + p + '" is prohibited for ref layers'));
            }
        });
        var parent;
        style.layers.forEach(function (layer) {
            if (unbundle(layer.id) === ref) {
                parent = layer;
            }
        });
        if (!parent) {
            errors.push(new ValidationError(key, layer.ref, 'ref layer "' + ref + '" not found'));
        } else if (parent.ref) {
            errors.push(new ValidationError(key, layer.ref, 'ref cannot reference another ref layer'));
        } else {
            type = unbundle(parent.type);
        }
    } else if (type !== 'background') {
        if (!layer.source) {
            errors.push(new ValidationError(key, layer, 'missing required property "source"'));
        } else {
            var source = style.sources && style.sources[layer.source];
            var sourceType = source && unbundle(source.type);
            if (!source) {
                errors.push(new ValidationError(key, layer.source, 'source "' + layer.source + '" not found'));
            } else if (sourceType === 'vector' && type === 'raster') {
                errors.push(new ValidationError(key, layer.source, 'layer "' + layer.id + '" requires a raster source'));
            } else if (sourceType === 'raster' && type !== 'raster') {
                errors.push(new ValidationError(key, layer.source, 'layer "' + layer.id + '" requires a vector source'));
            } else if (sourceType === 'vector' && !layer['source-layer']) {
                errors.push(new ValidationError(key, layer, 'layer "' + layer.id + '" must specify a "source-layer"'));
            } else if (sourceType === 'raster-dem' && type !== 'hillshade') {
                errors.push(new ValidationError(key, layer.source, 'raster-dem source can only be used with layer type \'hillshade\'.'));
            } else if (type === 'line' && layer.paint && layer.paint['line-gradient'] && (sourceType !== 'geojson' || !source.lineMetrics)) {
                errors.push(new ValidationError(key, layer, 'layer "' + layer.id + '" specifies a line-gradient, which requires a GeoJSON source with `lineMetrics` enabled.'));
            }
        }
    }
    errors = errors.concat(validateObject({
        key: key,
        value: layer,
        valueSpec: styleSpec.layer,
        style: options.style,
        styleSpec: options.styleSpec,
        objectElementValidators: {
            '*': function _() {
                return [];
            },
            type: function type() {
                return validate({
                    key: key + '.type',
                    value: layer.type,
                    valueSpec: styleSpec.layer.type,
                    style: options.style,
                    styleSpec: options.styleSpec,
                    object: layer,
                    objectKey: 'type'
                });
            },
            filter: validateFilter,
            layout: function layout(options) {
                return validateObject({
                    layer: layer,
                    key: options.key,
                    value: options.value,
                    style: options.style,
                    styleSpec: options.styleSpec,
                    objectElementValidators: {
                        '*': function _(options) {
                            return validateLayoutProperty(extend$1({ layerType: type }, options));
                        }
                    }
                });
            },
            paint: function paint(options) {
                return validateObject({
                    layer: layer,
                    key: options.key,
                    value: options.value,
                    style: options.style,
                    styleSpec: options.styleSpec,
                    objectElementValidators: {
                        '*': function _(options) {
                            return validatePaintProperty(extend$1({ layerType: type }, options));
                        }
                    }
                });
            }
        }
    }));
    return errors;
}

function validateString(options) {
    var value = options.value;
    var key = options.key;
    var type = getType(value);
    if (type !== 'string') {
        return [new ValidationError(key, value, 'string expected, ' + type + ' found')];
    }
    return [];
}

var objectElementValidators = { promoteId: validatePromoteId };
function validateSource(options) {
    var value = options.value;
    var key = options.key;
    var styleSpec = options.styleSpec;
    var style = options.style;
    if (!value.type) {
        return [new ValidationError(key, value, '"type" is required')];
    }
    var type = unbundle(value.type);
    var errors;
    switch (type) {
    case 'vector':
    case 'raster':
    case 'raster-dem':
        errors = validateObject({
            key: key,
            value: value,
            valueSpec: styleSpec['source_' + type.replace('-', '_')],
            style: options.style,
            styleSpec: styleSpec,
            objectElementValidators: objectElementValidators
        });
        return errors;
    case 'geojson':
        errors = validateObject({
            key: key,
            value: value,
            valueSpec: styleSpec.source_geojson,
            style: style,
            styleSpec: styleSpec,
            objectElementValidators: objectElementValidators
        });
        if (value.cluster) {
            for (var prop in value.clusterProperties) {
                var ref = value.clusterProperties[prop];
                var operator = ref[0];
                var mapExpr = ref[1];
                var reduceExpr = typeof operator === 'string' ? [
                    operator,
                    ['accumulated'],
                    [
                        'get',
                        prop
                    ]
                ] : operator;
                errors.push.apply(errors, validateExpression({
                    key: key + '.' + prop + '.map',
                    value: mapExpr,
                    expressionContext: 'cluster-map'
                }));
                errors.push.apply(errors, validateExpression({
                    key: key + '.' + prop + '.reduce',
                    value: reduceExpr,
                    expressionContext: 'cluster-reduce'
                }));
            }
        }
        return errors;
    case 'video':
        return validateObject({
            key: key,
            value: value,
            valueSpec: styleSpec.source_video,
            style: style,
            styleSpec: styleSpec
        });
    case 'image':
        return validateObject({
            key: key,
            value: value,
            valueSpec: styleSpec.source_image,
            style: style,
            styleSpec: styleSpec
        });
    case 'canvas':
        return [new ValidationError(key, null, 'Please use runtime APIs to add canvas sources, rather than including them in stylesheets.', 'source.canvas')];
    default:
        return validateEnum({
            key: key + '.type',
            value: value.type,
            valueSpec: {
                values: [
                    'vector',
                    'raster',
                    'raster-dem',
                    'geojson',
                    'video',
                    'image'
                ]
            },
            style: style,
            styleSpec: styleSpec
        });
    }
}
function validatePromoteId(ref) {
    var key = ref.key;
    var value = ref.value;
    if (getType(value) === 'string') {
        return validateString({
            key: key,
            value: value
        });
    } else {
        var errors = [];
        for (var prop in value) {
            errors.push.apply(errors, validateString({
                key: key + '.' + prop,
                value: value[prop]
            }));
        }
        return errors;
    }
}

function validateLight(options) {
    var light = options.value;
    var styleSpec = options.styleSpec;
    var lightSpec = styleSpec.light;
    var style = options.style;
    var errors = [];
    var rootType = getType(light);
    if (light === undefined) {
        return errors;
    } else if (rootType !== 'object') {
        errors = errors.concat([new ValidationError('light', light, 'object expected, ' + rootType + ' found')]);
        return errors;
    }
    for (var key in light) {
        var transitionMatch = key.match(/^(.*)-transition$/);
        if (transitionMatch && lightSpec[transitionMatch[1]] && lightSpec[transitionMatch[1]].transition) {
            errors = errors.concat(validate({
                key: key,
                value: light[key],
                valueSpec: styleSpec.transition,
                style: style,
                styleSpec: styleSpec
            }));
        } else if (lightSpec[key]) {
            errors = errors.concat(validate({
                key: key,
                value: light[key],
                valueSpec: lightSpec[key],
                style: style,
                styleSpec: styleSpec
            }));
        } else {
            errors = errors.concat([new ValidationError(key, light[key], 'unknown property "' + key + '"')]);
        }
    }
    return errors;
}

function validateFormatted(options) {
    if (validateString(options).length === 0) {
        return [];
    }
    return validateExpression(options);
}

function validateImage(options) {
    if (validateString(options).length === 0) {
        return [];
    }
    return validateExpression(options);
}

var VALIDATORS = {
    '*': function _() {
        return [];
    },
    'array': validateArray,
    'boolean': validateBoolean,
    'number': validateNumber,
    'color': validateColor,
    'constants': validateConstants,
    'enum': validateEnum,
    'filter': validateFilter,
    'function': validateFunction,
    'layer': validateLayer,
    'object': validateObject,
    'source': validateSource,
    'light': validateLight,
    'string': validateString,
    'formatted': validateFormatted,
    'resolvedImage': validateImage
};
function validate(options) {
    var value = options.value;
    var valueSpec = options.valueSpec;
    var styleSpec = options.styleSpec;
    if (valueSpec.expression && isFunction(unbundle(value))) {
        return validateFunction(options);
    } else if (valueSpec.expression && isExpression(deepUnbundle(value))) {
        return validateExpression(options);
    } else if (valueSpec.type && VALIDATORS[valueSpec.type]) {
        return VALIDATORS[valueSpec.type](options);
    } else {
        var valid = validateObject(extend$1({}, options, { valueSpec: valueSpec.type ? styleSpec[valueSpec.type] : valueSpec }));
        return valid;
    }
}

function validateGlyphsURL (options) {
    var value = options.value;
    var key = options.key;
    var errors = validateString(options);
    if (errors.length) {
        return errors;
    }
    if (value.indexOf('{fontstack}') === -1) {
        errors.push(new ValidationError(key, value, '"glyphs" url must include a "{fontstack}" token'));
    }
    if (value.indexOf('{range}') === -1) {
        errors.push(new ValidationError(key, value, '"glyphs" url must include a "{range}" token'));
    }
    return errors;
}

function validateStyleMin(style, styleSpec) {
    if (styleSpec === void 0)
        styleSpec = spec;
    var errors = [];
    errors = errors.concat(validate({
        key: '',
        value: style,
        valueSpec: styleSpec.$root,
        styleSpec: styleSpec,
        style: style,
        objectElementValidators: {
            glyphs: validateGlyphsURL,
            '*': function _() {
                return [];
            }
        }
    }));
    if (style.constants) {
        errors = errors.concat(validateConstants({
            key: 'constants',
            value: style.constants,
            style: style,
            styleSpec: styleSpec
        }));
    }
    return sortErrors(errors);
}
validateStyleMin.source = wrapCleanErrors(validateSource);
validateStyleMin.light = wrapCleanErrors(validateLight);
validateStyleMin.layer = wrapCleanErrors(validateLayer);
validateStyleMin.filter = wrapCleanErrors(validateFilter);
validateStyleMin.paintProperty = wrapCleanErrors(validatePaintProperty);
validateStyleMin.layoutProperty = wrapCleanErrors(validateLayoutProperty);
function sortErrors(errors) {
    return [].concat(errors).sort(function (a, b) {
        return a.line - b.line;
    });
}
function wrapCleanErrors(inner) {
    return function () {
        var args = [], len = arguments.length;
        while (len--)
            args[len] = arguments[len];
        return sortErrors(inner.apply(this, args));
    };
}

var validateStyle = validateStyleMin;
var validateLight$1 = validateStyle.light;
var validatePaintProperty$1 = validateStyle.paintProperty;
var validateLayoutProperty$1 = validateStyle.layoutProperty;
function emitValidationErrors(emitter, errors) {
    var hasErrors = false;
    if (errors && errors.length) {
        for (var i = 0, list = errors; i < list.length; i += 1) {
            var error = list[i];
            emitter.fire(new ErrorEvent(new Error(error.message)));
            hasErrors = true;
        }
    }
    return hasErrors;
}

var gridIndex = GridIndex;
var NUM_PARAMS = 3;
function GridIndex(extent, n, padding) {
    var cells = this.cells = [];
    if (extent instanceof ArrayBuffer) {
        this.arrayBuffer = extent;
        var array = new Int32Array(this.arrayBuffer);
        extent = array[0];
        n = array[1];
        padding = array[2];
        this.d = n + 2 * padding;
        for (var k = 0; k < this.d * this.d; k++) {
            var start = array[NUM_PARAMS + k];
            var end = array[NUM_PARAMS + k + 1];
            cells.push(start === end ? null : array.subarray(start, end));
        }
        var keysOffset = array[NUM_PARAMS + cells.length];
        var bboxesOffset = array[NUM_PARAMS + cells.length + 1];
        this.keys = array.subarray(keysOffset, bboxesOffset);
        this.bboxes = array.subarray(bboxesOffset);
        this.insert = this._insertReadonly;
    } else {
        this.d = n + 2 * padding;
        for (var i = 0; i < this.d * this.d; i++) {
            cells.push([]);
        }
        this.keys = [];
        this.bboxes = [];
    }
    this.n = n;
    this.extent = extent;
    this.padding = padding;
    this.scale = n / extent;
    this.uid = 0;
    var p = padding / n * extent;
    this.min = -p;
    this.max = extent + p;
}
GridIndex.prototype.insert = function (key, x1, y1, x2, y2) {
    this._forEachCell(x1, y1, x2, y2, this._insertCell, this.uid++);
    this.keys.push(key);
    this.bboxes.push(x1);
    this.bboxes.push(y1);
    this.bboxes.push(x2);
    this.bboxes.push(y2);
};
GridIndex.prototype._insertReadonly = function () {
    throw 'Cannot insert into a GridIndex created from an ArrayBuffer.';
};
GridIndex.prototype._insertCell = function (x1, y1, x2, y2, cellIndex, uid) {
    this.cells[cellIndex].push(uid);
};
GridIndex.prototype.query = function (x1, y1, x2, y2, intersectionTest) {
    var min = this.min;
    var max = this.max;
    if (x1 <= min && y1 <= min && max <= x2 && max <= y2 && !intersectionTest) {
        return Array.prototype.slice.call(this.keys);
    } else {
        var result = [];
        var seenUids = {};
        this._forEachCell(x1, y1, x2, y2, this._queryCell, result, seenUids, intersectionTest);
        return result;
    }
};
GridIndex.prototype._queryCell = function (x1, y1, x2, y2, cellIndex, result, seenUids, intersectionTest) {
    var cell = this.cells[cellIndex];
    if (cell !== null) {
        var keys = this.keys;
        var bboxes = this.bboxes;
        for (var u = 0; u < cell.length; u++) {
            var uid = cell[u];
            if (seenUids[uid] === undefined) {
                var offset = uid * 4;
                if (intersectionTest ? intersectionTest(bboxes[offset + 0], bboxes[offset + 1], bboxes[offset + 2], bboxes[offset + 3]) : x1 <= bboxes[offset + 2] && y1 <= bboxes[offset + 3] && x2 >= bboxes[offset + 0] && y2 >= bboxes[offset + 1]) {
                    seenUids[uid] = true;
                    result.push(keys[uid]);
                } else {
                    seenUids[uid] = false;
                }
            }
        }
    }
};
GridIndex.prototype._forEachCell = function (x1, y1, x2, y2, fn, arg1, arg2, intersectionTest) {
    var cx1 = this._convertToCellCoord(x1);
    var cy1 = this._convertToCellCoord(y1);
    var cx2 = this._convertToCellCoord(x2);
    var cy2 = this._convertToCellCoord(y2);
    for (var x = cx1; x <= cx2; x++) {
        for (var y = cy1; y <= cy2; y++) {
            var cellIndex = this.d * y + x;
            if (intersectionTest && !intersectionTest(this._convertFromCellCoord(x), this._convertFromCellCoord(y), this._convertFromCellCoord(x + 1), this._convertFromCellCoord(y + 1))) {
                continue;
            }
            if (fn.call(this, x1, y1, x2, y2, cellIndex, arg1, arg2, intersectionTest)) {
                return;
            }
        }
    }
};
GridIndex.prototype._convertFromCellCoord = function (x) {
    return (x - this.padding) / this.scale;
};
GridIndex.prototype._convertToCellCoord = function (x) {
    return Math.max(0, Math.min(this.d - 1, Math.floor(x * this.scale) + this.padding));
};
GridIndex.prototype.toArrayBuffer = function () {
    if (this.arrayBuffer) {
        return this.arrayBuffer;
    }
    var cells = this.cells;
    var metadataLength = NUM_PARAMS + this.cells.length + 1 + 1;
    var totalCellLength = 0;
    for (var i = 0; i < this.cells.length; i++) {
        totalCellLength += this.cells[i].length;
    }
    var array = new Int32Array(metadataLength + totalCellLength + this.keys.length + this.bboxes.length);
    array[0] = this.extent;
    array[1] = this.n;
    array[2] = this.padding;
    var offset = metadataLength;
    for (var k = 0; k < cells.length; k++) {
        var cell = cells[k];
        array[NUM_PARAMS + k] = offset;
        array.set(cell, offset);
        offset += cell.length;
    }
    array[NUM_PARAMS + cells.length] = offset;
    array.set(this.keys, offset);
    offset += this.keys.length;
    array[NUM_PARAMS + cells.length + 1] = offset;
    array.set(this.bboxes, offset);
    offset += this.bboxes.length;
    return array.buffer;
};

var ImageData = window$1.ImageData;
var ImageBitmap = window$1.ImageBitmap;
var registry = {};
function register(name, klass, options) {
    if (options === void 0)
        options = {};
    Object.defineProperty(klass, '_classRegistryKey', {
        value: name,
        writeable: false
    });
    registry[name] = {
        klass: klass,
        omit: options.omit || [],
        shallow: options.shallow || []
    };
}
register('Object', Object);
gridIndex.serialize = function serialize(grid, transferables) {
    var buffer = grid.toArrayBuffer();
    if (transferables) {
        transferables.push(buffer);
    }
    return { buffer: buffer };
};
gridIndex.deserialize = function deserialize(serialized) {
    return new gridIndex(serialized.buffer);
};
register('Grid', gridIndex);
register('Color', Color);
register('Error', Error);
register('ResolvedImage', ResolvedImage);
register('StylePropertyFunction', StylePropertyFunction);
register('StyleExpression', StyleExpression, { omit: ['_evaluator'] });
register('ZoomDependentExpression', ZoomDependentExpression);
register('ZoomConstantExpression', ZoomConstantExpression);
register('CompoundExpression', CompoundExpression, { omit: ['_evaluate'] });
for (var name in expressions) {
    if (expressions[name]._classRegistryKey) {
        continue;
    }
    register('Expression_' + name, expressions[name]);
}
function isArrayBuffer(val) {
    return val && typeof ArrayBuffer !== 'undefined' && (val instanceof ArrayBuffer || val.constructor && val.constructor.name === 'ArrayBuffer');
}
function isImageBitmap(val) {
    return ImageBitmap && val instanceof ImageBitmap;
}
function serialize(input, transferables) {
    if (input === null || input === undefined || typeof input === 'boolean' || typeof input === 'number' || typeof input === 'string' || input instanceof Boolean || input instanceof Number || input instanceof String || input instanceof Date || input instanceof RegExp) {
        return input;
    }
    if (isArrayBuffer(input) || isImageBitmap(input)) {
        if (transferables) {
            transferables.push(input);
        }
        return input;
    }
    if (ArrayBuffer.isView(input)) {
        var view = input;
        if (transferables) {
            transferables.push(view.buffer);
        }
        return view;
    }
    if (input instanceof ImageData) {
        if (transferables) {
            transferables.push(input.data.buffer);
        }
        return input;
    }
    if (Array.isArray(input)) {
        var serialized = [];
        for (var i = 0, list = input; i < list.length; i += 1) {
            var item = list[i];
            serialized.push(serialize(item, transferables));
        }
        return serialized;
    }
    if (typeof input === 'object') {
        var klass = input.constructor;
        var name = klass._classRegistryKey;
        if (!name) {
            throw new Error('can\'t serialize object of unregistered class');
        }
        var properties = klass.serialize ? klass.serialize(input, transferables) : {};
        if (!klass.serialize) {
            for (var key in input) {
                if (!input.hasOwnProperty(key)) {
                    continue;
                }
                if (registry[name].omit.indexOf(key) >= 0) {
                    continue;
                }
                var property = input[key];
                properties[key] = registry[name].shallow.indexOf(key) >= 0 ? property : serialize(property, transferables);
            }
            if (input instanceof Error) {
                properties.message = input.message;
            }
        }
        if (properties.$name) {
            throw new Error('$name property is reserved for worker serialization logic.');
        }
        if (name !== 'Object') {
            properties.$name = name;
        }
        return properties;
    }
    throw new Error('can\'t serialize object of type ' + typeof input);
}
function deserialize(input) {
    if (input === null || input === undefined || typeof input === 'boolean' || typeof input === 'number' || typeof input === 'string' || input instanceof Boolean || input instanceof Number || input instanceof String || input instanceof Date || input instanceof RegExp || isArrayBuffer(input) || isImageBitmap(input) || ArrayBuffer.isView(input) || input instanceof ImageData) {
        return input;
    }
    if (Array.isArray(input)) {
        return input.map(deserialize);
    }
    if (typeof input === 'object') {
        var name = input.$name || 'Object';
        var ref = registry[name];
        var klass = ref.klass;
        if (!klass) {
            throw new Error('can\'t deserialize unregistered class ' + name);
        }
        if (klass.deserialize) {
            return klass.deserialize(input);
        }
        var result = Object.create(klass.prototype);
        for (var i = 0, list = Object.keys(input); i < list.length; i += 1) {
            var key = list[i];
            if (key === '$name') {
                continue;
            }
            var value = input[key];
            result[key] = registry[name].shallow.indexOf(key) >= 0 ? value : deserialize(value);
        }
        return result;
    }
    throw new Error('can\'t deserialize object of type ' + typeof input);
}

var ZoomHistory = function ZoomHistory() {
    this.first = true;
};
ZoomHistory.prototype.update = function update(z, now) {
    var floorZ = Math.floor(z);
    if (this.first) {
        this.first = false;
        this.lastIntegerZoom = floorZ;
        this.lastIntegerZoomTime = 0;
        this.lastZoom = z;
        this.lastFloorZoom = floorZ;
        return true;
    }
    if (this.lastFloorZoom > floorZ) {
        this.lastIntegerZoom = floorZ + 1;
        this.lastIntegerZoomTime = now;
    } else if (this.lastFloorZoom < floorZ) {
        this.lastIntegerZoom = floorZ;
        this.lastIntegerZoomTime = now;
    }
    if (z !== this.lastZoom) {
        this.lastZoom = z;
        this.lastFloorZoom = floorZ;
        return true;
    }
    return false;
};

var unicodeBlockLookup = {
    'Latin-1 Supplement': function (char) {
        return char >= 128 && char <= 255;
    },
    'Arabic': function (char) {
        return char >= 1536 && char <= 1791;
    },
    'Arabic Supplement': function (char) {
        return char >= 1872 && char <= 1919;
    },
    'Arabic Extended-A': function (char) {
        return char >= 2208 && char <= 2303;
    },
    'Hangul Jamo': function (char) {
        return char >= 4352 && char <= 4607;
    },
    'Unified Canadian Aboriginal Syllabics': function (char) {
        return char >= 5120 && char <= 5759;
    },
    'Khmer': function (char) {
        return char >= 6016 && char <= 6143;
    },
    'Unified Canadian Aboriginal Syllabics Extended': function (char) {
        return char >= 6320 && char <= 6399;
    },
    'General Punctuation': function (char) {
        return char >= 8192 && char <= 8303;
    },
    'Letterlike Symbols': function (char) {
        return char >= 8448 && char <= 8527;
    },
    'Number Forms': function (char) {
        return char >= 8528 && char <= 8591;
    },
    'Miscellaneous Technical': function (char) {
        return char >= 8960 && char <= 9215;
    },
    'Control Pictures': function (char) {
        return char >= 9216 && char <= 9279;
    },
    'Optical Character Recognition': function (char) {
        return char >= 9280 && char <= 9311;
    },
    'Enclosed Alphanumerics': function (char) {
        return char >= 9312 && char <= 9471;
    },
    'Geometric Shapes': function (char) {
        return char >= 9632 && char <= 9727;
    },
    'Miscellaneous Symbols': function (char) {
        return char >= 9728 && char <= 9983;
    },
    'Miscellaneous Symbols and Arrows': function (char) {
        return char >= 11008 && char <= 11263;
    },
    'CJK Radicals Supplement': function (char) {
        return char >= 11904 && char <= 12031;
    },
    'Kangxi Radicals': function (char) {
        return char >= 12032 && char <= 12255;
    },
    'Ideographic Description Characters': function (char) {
        return char >= 12272 && char <= 12287;
    },
    'CJK Symbols and Punctuation': function (char) {
        return char >= 12288 && char <= 12351;
    },
    'Hiragana': function (char) {
        return char >= 12352 && char <= 12447;
    },
    'Katakana': function (char) {
        return char >= 12448 && char <= 12543;
    },
    'Bopomofo': function (char) {
        return char >= 12544 && char <= 12591;
    },
    'Hangul Compatibility Jamo': function (char) {
        return char >= 12592 && char <= 12687;
    },
    'Kanbun': function (char) {
        return char >= 12688 && char <= 12703;
    },
    'Bopomofo Extended': function (char) {
        return char >= 12704 && char <= 12735;
    },
    'CJK Strokes': function (char) {
        return char >= 12736 && char <= 12783;
    },
    'Katakana Phonetic Extensions': function (char) {
        return char >= 12784 && char <= 12799;
    },
    'Enclosed CJK Letters and Months': function (char) {
        return char >= 12800 && char <= 13055;
    },
    'CJK Compatibility': function (char) {
        return char >= 13056 && char <= 13311;
    },
    'CJK Unified Ideographs Extension A': function (char) {
        return char >= 13312 && char <= 19903;
    },
    'Yijing Hexagram Symbols': function (char) {
        return char >= 19904 && char <= 19967;
    },
    'CJK Unified Ideographs': function (char) {
        return char >= 19968 && char <= 40959;
    },
    'Yi Syllables': function (char) {
        return char >= 40960 && char <= 42127;
    },
    'Yi Radicals': function (char) {
        return char >= 42128 && char <= 42191;
    },
    'Hangul Jamo Extended-A': function (char) {
        return char >= 43360 && char <= 43391;
    },
    'Hangul Syllables': function (char) {
        return char >= 44032 && char <= 55215;
    },
    'Hangul Jamo Extended-B': function (char) {
        return char >= 55216 && char <= 55295;
    },
    'Private Use Area': function (char) {
        return char >= 57344 && char <= 63743;
    },
    'CJK Compatibility Ideographs': function (char) {
        return char >= 63744 && char <= 64255;
    },
    'Arabic Presentation Forms-A': function (char) {
        return char >= 64336 && char <= 65023;
    },
    'Vertical Forms': function (char) {
        return char >= 65040 && char <= 65055;
    },
    'CJK Compatibility Forms': function (char) {
        return char >= 65072 && char <= 65103;
    },
    'Small Form Variants': function (char) {
        return char >= 65104 && char <= 65135;
    },
    'Arabic Presentation Forms-B': function (char) {
        return char >= 65136 && char <= 65279;
    },
    'Halfwidth and Fullwidth Forms': function (char) {
        return char >= 65280 && char <= 65519;
    }
};

function allowsVerticalWritingMode(chars) {
    for (var i = 0, list = chars; i < list.length; i += 1) {
        var char = list[i];
        if (charHasUprightVerticalOrientation(char.charCodeAt(0))) {
            return true;
        }
    }
    return false;
}
function allowsLetterSpacing(chars) {
    for (var i = 0, list = chars; i < list.length; i += 1) {
        var char = list[i];
        if (!charAllowsLetterSpacing(char.charCodeAt(0))) {
            return false;
        }
    }
    return true;
}
function charAllowsLetterSpacing(char) {
    if (unicodeBlockLookup['Arabic'](char)) {
        return false;
    }
    if (unicodeBlockLookup['Arabic Supplement'](char)) {
        return false;
    }
    if (unicodeBlockLookup['Arabic Extended-A'](char)) {
        return false;
    }
    if (unicodeBlockLookup['Arabic Presentation Forms-A'](char)) {
        return false;
    }
    if (unicodeBlockLookup['Arabic Presentation Forms-B'](char)) {
        return false;
    }
    return true;
}
function charAllowsIdeographicBreaking(char) {
    if (char < 11904) {
        return false;
    }
    if (unicodeBlockLookup['Bopomofo Extended'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Bopomofo'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Compatibility Forms'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Compatibility Ideographs'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Compatibility'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Radicals Supplement'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Strokes'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Symbols and Punctuation'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Unified Ideographs Extension A'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Unified Ideographs'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Enclosed CJK Letters and Months'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Halfwidth and Fullwidth Forms'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hiragana'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Ideographic Description Characters'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Kangxi Radicals'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Katakana Phonetic Extensions'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Katakana'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Vertical Forms'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Yi Radicals'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Yi Syllables'](char)) {
        return true;
    }
    return false;
}
function charHasUprightVerticalOrientation(char) {
    if (char === 746 || char === 747) {
        return true;
    }
    if (char < 4352) {
        return false;
    }
    if (unicodeBlockLookup['Bopomofo Extended'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Bopomofo'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Compatibility Forms'](char)) {
        if (!(char >= 65097 && char <= 65103)) {
            return true;
        }
    }
    if (unicodeBlockLookup['CJK Compatibility Ideographs'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Compatibility'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Radicals Supplement'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Strokes'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Symbols and Punctuation'](char)) {
        if (!(char >= 12296 && char <= 12305) && !(char >= 12308 && char <= 12319) && char !== 12336) {
            return true;
        }
    }
    if (unicodeBlockLookup['CJK Unified Ideographs Extension A'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Unified Ideographs'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Enclosed CJK Letters and Months'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hangul Compatibility Jamo'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hangul Jamo Extended-A'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hangul Jamo Extended-B'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hangul Jamo'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hangul Syllables'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Hiragana'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Ideographic Description Characters'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Kanbun'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Kangxi Radicals'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Katakana Phonetic Extensions'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Katakana'](char)) {
        if (char !== 12540) {
            return true;
        }
    }
    if (unicodeBlockLookup['Halfwidth and Fullwidth Forms'](char)) {
        if (char !== 65288 && char !== 65289 && char !== 65293 && !(char >= 65306 && char <= 65310) && char !== 65339 && char !== 65341 && char !== 65343 && !(char >= 65371 && char <= 65503) && char !== 65507 && !(char >= 65512 && char <= 65519)) {
            return true;
        }
    }
    if (unicodeBlockLookup['Small Form Variants'](char)) {
        if (!(char >= 65112 && char <= 65118) && !(char >= 65123 && char <= 65126)) {
            return true;
        }
    }
    if (unicodeBlockLookup['Unified Canadian Aboriginal Syllabics'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Unified Canadian Aboriginal Syllabics Extended'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Vertical Forms'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Yijing Hexagram Symbols'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Yi Syllables'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Yi Radicals'](char)) {
        return true;
    }
    return false;
}
function charHasNeutralVerticalOrientation(char) {
    if (unicodeBlockLookup['Latin-1 Supplement'](char)) {
        if (char === 167 || char === 169 || char === 174 || char === 177 || char === 188 || char === 189 || char === 190 || char === 215 || char === 247) {
            return true;
        }
    }
    if (unicodeBlockLookup['General Punctuation'](char)) {
        if (char === 8214 || char === 8224 || char === 8225 || char === 8240 || char === 8241 || char === 8251 || char === 8252 || char === 8258 || char === 8263 || char === 8264 || char === 8265 || char === 8273) {
            return true;
        }
    }
    if (unicodeBlockLookup['Letterlike Symbols'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Number Forms'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Miscellaneous Technical'](char)) {
        if (char >= 8960 && char <= 8967 || char >= 8972 && char <= 8991 || char >= 8996 && char <= 9000 || char === 9003 || char >= 9085 && char <= 9114 || char >= 9150 && char <= 9165 || char === 9167 || char >= 9169 && char <= 9179 || char >= 9186 && char <= 9215) {
            return true;
        }
    }
    if (unicodeBlockLookup['Control Pictures'](char) && char !== 9251) {
        return true;
    }
    if (unicodeBlockLookup['Optical Character Recognition'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Enclosed Alphanumerics'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Geometric Shapes'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Miscellaneous Symbols'](char)) {
        if (!(char >= 9754 && char <= 9759)) {
            return true;
        }
    }
    if (unicodeBlockLookup['Miscellaneous Symbols and Arrows'](char)) {
        if (char >= 11026 && char <= 11055 || char >= 11088 && char <= 11097 || char >= 11192 && char <= 11243) {
            return true;
        }
    }
    if (unicodeBlockLookup['CJK Symbols and Punctuation'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Katakana'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Private Use Area'](char)) {
        return true;
    }
    if (unicodeBlockLookup['CJK Compatibility Forms'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Small Form Variants'](char)) {
        return true;
    }
    if (unicodeBlockLookup['Halfwidth and Fullwidth Forms'](char)) {
        return true;
    }
    if (char === 8734 || char === 8756 || char === 8757 || char >= 9984 && char <= 10087 || char >= 10102 && char <= 10131 || char === 65532 || char === 65533) {
        return true;
    }
    return false;
}
function charHasRotatedVerticalOrientation(char) {
    return !(charHasUprightVerticalOrientation(char) || charHasNeutralVerticalOrientation(char));
}
function charInComplexShapingScript(char) {
    return unicodeBlockLookup['Arabic'](char) || unicodeBlockLookup['Arabic Supplement'](char) || unicodeBlockLookup['Arabic Extended-A'](char) || unicodeBlockLookup['Arabic Presentation Forms-A'](char) || unicodeBlockLookup['Arabic Presentation Forms-B'](char);
}
function charInRTLScript(char) {
    return char >= 1424 && char <= 2303 || unicodeBlockLookup['Arabic Presentation Forms-A'](char) || unicodeBlockLookup['Arabic Presentation Forms-B'](char);
}
function charInSupportedScript(char, canRenderRTL) {
    if (!canRenderRTL && charInRTLScript(char)) {
        return false;
    }
    if (char >= 2304 && char <= 3583 || char >= 3840 && char <= 4255 || unicodeBlockLookup['Khmer'](char)) {
        return false;
    }
    return true;
}
function stringContainsRTLText(chars) {
    for (var i = 0, list = chars; i < list.length; i += 1) {
        var char = list[i];
        if (charInRTLScript(char.charCodeAt(0))) {
            return true;
        }
    }
    return false;
}
function isStringInSupportedScript(chars, canRenderRTL) {
    for (var i = 0, list = chars; i < list.length; i += 1) {
        var char = list[i];
        if (!charInSupportedScript(char.charCodeAt(0), canRenderRTL)) {
            return false;
        }
    }
    return true;
}

var status = {
    unavailable: 'unavailable',
    deferred: 'deferred',
    loading: 'loading',
    loaded: 'loaded',
    error: 'error'
};
var _completionCallback = null;
var pluginStatus = status.unavailable;
var pluginURL = null;
var triggerPluginCompletionEvent = function (error) {
    if (error && typeof error === 'string' && error.indexOf('NetworkError') > -1) {
        pluginStatus = status.error;
    }
    if (_completionCallback) {
        _completionCallback(error);
    }
};
function sendPluginStateToWorker() {
    evented.fire(new Event('pluginStateChange', {
        pluginStatus: pluginStatus,
        pluginURL: pluginURL
    }));
}
var evented = new Evented();
var getRTLTextPluginStatus = function () {
    return pluginStatus;
};
var registerForPluginStateChange = function (callback) {
    callback({
        pluginStatus: pluginStatus,
        pluginURL: pluginURL
    });
    evented.on('pluginStateChange', callback);
    return callback;
};
var setRTLTextPlugin = function (url, callback, deferred) {
    if (deferred === void 0)
        deferred = false;
    if (pluginStatus === status.deferred || pluginStatus === status.loading || pluginStatus === status.loaded) {
        throw new Error('setRTLTextPlugin cannot be called multiple times.');
    }
    pluginURL = exported.resolveURL(url);
    pluginStatus = status.deferred;
    _completionCallback = callback;
    sendPluginStateToWorker();
    if (!deferred) {
        downloadRTLTextPlugin();
    }
};
var downloadRTLTextPlugin = function () {
    if (pluginStatus !== status.deferred || !pluginURL) {
        throw new Error('rtl-text-plugin cannot be downloaded unless a pluginURL is specified');
    }
    pluginStatus = status.loading;
    sendPluginStateToWorker();
    if (pluginURL) {
        getArrayBuffer({ url: pluginURL }, function (error) {
            if (error) {
                triggerPluginCompletionEvent(error);
            } else {
                pluginStatus = status.loaded;
                sendPluginStateToWorker();
            }
        });
    }
};
var plugin = {
    applyArabicShaping: null,
    processBidirectionalText: null,
    processStyledBidirectionalText: null,
    isLoaded: function isLoaded() {
        return pluginStatus === status.loaded || plugin.applyArabicShaping != null;
    },
    isLoading: function isLoading() {
        return pluginStatus === status.loading;
    },
    setState: function setState(state) {
        pluginStatus = state.pluginStatus;
        pluginURL = state.pluginURL;
    },
    isParsed: function isParsed() {
        return plugin.applyArabicShaping != null && plugin.processBidirectionalText != null && plugin.processStyledBidirectionalText != null;
    },
    getPluginURL: function getPluginURL() {
        return pluginURL;
    }
};
var lazyLoadRTLTextPlugin = function () {
    if (!plugin.isLoading() && !plugin.isLoaded() && getRTLTextPluginStatus() === 'deferred') {
        downloadRTLTextPlugin();
    }
};

var EvaluationParameters = function EvaluationParameters(zoom, options) {
    this.zoom = zoom;
    if (options) {
        this.now = options.now;
        this.fadeDuration = options.fadeDuration;
        this.zoomHistory = options.zoomHistory;
        this.transition = options.transition;
    } else {
        this.now = 0;
        this.fadeDuration = 0;
        this.zoomHistory = new ZoomHistory();
        this.transition = {};
    }
};
EvaluationParameters.prototype.isSupportedScript = function isSupportedScript(str) {
    return isStringInSupportedScript(str, plugin.isLoaded());
};
EvaluationParameters.prototype.crossFadingFactor = function crossFadingFactor() {
    if (this.fadeDuration === 0) {
        return 1;
    } else {
        return Math.min((this.now - this.zoomHistory.lastIntegerZoomTime) / this.fadeDuration, 1);
    }
};
EvaluationParameters.prototype.getCrossfadeParameters = function getCrossfadeParameters() {
    var z = this.zoom;
    var fraction = z - Math.floor(z);
    var t = this.crossFadingFactor();
    return z > this.zoomHistory.lastIntegerZoom ? {
        fromScale: 2,
        toScale: 1,
        t: fraction + (1 - fraction) * t
    } : {
        fromScale: 0.5,
        toScale: 1,
        t: 1 - (1 - t) * fraction
    };
};

var PropertyValue = function PropertyValue(property, value) {
    this.property = property;
    this.value = value;
    this.expression = normalizePropertyExpression(value === undefined ? property.specification.default : value, property.specification);
};
PropertyValue.prototype.isDataDriven = function isDataDriven() {
    return this.expression.kind === 'source' || this.expression.kind === 'composite';
};
PropertyValue.prototype.possiblyEvaluate = function possiblyEvaluate(parameters, canonical, availableImages) {
    return this.property.possiblyEvaluate(this, parameters, canonical, availableImages);
};
var TransitionablePropertyValue = function TransitionablePropertyValue(property) {
    this.property = property;
    this.value = new PropertyValue(property, undefined);
};
TransitionablePropertyValue.prototype.transitioned = function transitioned(parameters, prior) {
    return new TransitioningPropertyValue(this.property, this.value, prior, extend({}, parameters.transition, this.transition), parameters.now);
};
TransitionablePropertyValue.prototype.untransitioned = function untransitioned() {
    return new TransitioningPropertyValue(this.property, this.value, null, {}, 0);
};
var Transitionable = function Transitionable(properties) {
    this._properties = properties;
    this._values = Object.create(properties.defaultTransitionablePropertyValues);
};
Transitionable.prototype.getValue = function getValue(name) {
    return clone(this._values[name].value.value);
};
Transitionable.prototype.setValue = function setValue(name, value) {
    if (!this._values.hasOwnProperty(name)) {
        this._values[name] = new TransitionablePropertyValue(this._values[name].property);
    }
    this._values[name].value = new PropertyValue(this._values[name].property, value === null ? undefined : clone(value));
};
Transitionable.prototype.getTransition = function getTransition(name) {
    return clone(this._values[name].transition);
};
Transitionable.prototype.setTransition = function setTransition(name, value) {
    if (!this._values.hasOwnProperty(name)) {
        this._values[name] = new TransitionablePropertyValue(this._values[name].property);
    }
    this._values[name].transition = clone(value) || undefined;
};
Transitionable.prototype.serialize = function serialize() {
    var result = {};
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        var value = this.getValue(property);
        if (value !== undefined) {
            result[property] = value;
        }
        var transition = this.getTransition(property);
        if (transition !== undefined) {
            result[property + '-transition'] = transition;
        }
    }
    return result;
};
Transitionable.prototype.transitioned = function transitioned(parameters, prior) {
    var result = new Transitioning(this._properties);
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        result._values[property] = this._values[property].transitioned(parameters, prior._values[property]);
    }
    return result;
};
Transitionable.prototype.untransitioned = function untransitioned() {
    var result = new Transitioning(this._properties);
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        result._values[property] = this._values[property].untransitioned();
    }
    return result;
};
var TransitioningPropertyValue = function TransitioningPropertyValue(property, value, prior, transition, now) {
    this.property = property;
    this.value = value;
    this.begin = now + transition.delay || 0;
    this.end = this.begin + transition.duration || 0;
    if (property.specification.transition && (transition.delay || transition.duration)) {
        this.prior = prior;
    }
};
TransitioningPropertyValue.prototype.possiblyEvaluate = function possiblyEvaluate(parameters, canonical, availableImages) {
    var now = parameters.now || 0;
    var finalValue = this.value.possiblyEvaluate(parameters, canonical, availableImages);
    var prior = this.prior;
    if (!prior) {
        return finalValue;
    } else if (now > this.end) {
        this.prior = null;
        return finalValue;
    } else if (this.value.isDataDriven()) {
        this.prior = null;
        return finalValue;
    } else if (now < this.begin) {
        return prior.possiblyEvaluate(parameters, canonical, availableImages);
    } else {
        var t = (now - this.begin) / (this.end - this.begin);
        return this.property.interpolate(prior.possiblyEvaluate(parameters, canonical, availableImages), finalValue, easeCubicInOut(t));
    }
};
var Transitioning = function Transitioning(properties) {
    this._properties = properties;
    this._values = Object.create(properties.defaultTransitioningPropertyValues);
};
Transitioning.prototype.possiblyEvaluate = function possiblyEvaluate(parameters, canonical, availableImages) {
    var result = new PossiblyEvaluated(this._properties);
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        result._values[property] = this._values[property].possiblyEvaluate(parameters, canonical, availableImages);
    }
    return result;
};
Transitioning.prototype.hasTransition = function hasTransition() {
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        if (this._values[property].prior) {
            return true;
        }
    }
    return false;
};
var Layout = function Layout(properties) {
    this._properties = properties;
    this._values = Object.create(properties.defaultPropertyValues);
};
Layout.prototype.getValue = function getValue(name) {
    return clone(this._values[name].value);
};
Layout.prototype.setValue = function setValue(name, value) {
    this._values[name] = new PropertyValue(this._values[name].property, value === null ? undefined : clone(value));
};
Layout.prototype.serialize = function serialize() {
    var result = {};
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        var value = this.getValue(property);
        if (value !== undefined) {
            result[property] = value;
        }
    }
    return result;
};
Layout.prototype.possiblyEvaluate = function possiblyEvaluate(parameters, canonical, availableImages) {
    var result = new PossiblyEvaluated(this._properties);
    for (var i = 0, list = Object.keys(this._values); i < list.length; i += 1) {
        var property = list[i];
        result._values[property] = this._values[property].possiblyEvaluate(parameters, canonical, availableImages);
    }
    return result;
};
var PossiblyEvaluatedPropertyValue = function PossiblyEvaluatedPropertyValue(property, value, parameters) {
    this.property = property;
    this.value = value;
    this.parameters = parameters;
};
PossiblyEvaluatedPropertyValue.prototype.isConstant = function isConstant() {
    return this.value.kind === 'constant';
};
PossiblyEvaluatedPropertyValue.prototype.constantOr = function constantOr(value) {
    if (this.value.kind === 'constant') {
        return this.value.value;
    } else {
        return value;
    }
};
PossiblyEvaluatedPropertyValue.prototype.evaluate = function evaluate(feature, featureState, canonical, availableImages) {
    return this.property.evaluate(this.value, this.parameters, feature, featureState, canonical, availableImages);
};
var PossiblyEvaluated = function PossiblyEvaluated(properties) {
    this._properties = properties;
    this._values = Object.create(properties.defaultPossiblyEvaluatedValues);
};
PossiblyEvaluated.prototype.get = function get(name) {
    return this._values[name];
};
var DataConstantProperty = function DataConstantProperty(specification) {
    this.specification = specification;
};
DataConstantProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters) {
    return value.expression.evaluate(parameters);
};
DataConstantProperty.prototype.interpolate = function interpolate$1(a, b, t) {
    var interp = interpolate[this.specification.type];
    if (interp) {
        return interp(a, b, t);
    } else {
        return a;
    }
};
var DataDrivenProperty = function DataDrivenProperty(specification, overrides) {
    this.specification = specification;
    this.overrides = overrides;
};
DataDrivenProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters, canonical, availableImages) {
    if (value.expression.kind === 'constant' || value.expression.kind === 'camera') {
        return new PossiblyEvaluatedPropertyValue(this, {
            kind: 'constant',
            value: value.expression.evaluate(parameters, null, {}, canonical, availableImages)
        }, parameters);
    } else {
        return new PossiblyEvaluatedPropertyValue(this, value.expression, parameters);
    }
};
DataDrivenProperty.prototype.interpolate = function interpolate$2(a, b, t) {
    if (a.value.kind !== 'constant' || b.value.kind !== 'constant') {
        return a;
    }
    if (a.value.value === undefined || b.value.value === undefined) {
        return new PossiblyEvaluatedPropertyValue(this, {
            kind: 'constant',
            value: undefined
        }, a.parameters);
    }
    var interp = interpolate[this.specification.type];
    if (interp) {
        return new PossiblyEvaluatedPropertyValue(this, {
            kind: 'constant',
            value: interp(a.value.value, b.value.value, t)
        }, a.parameters);
    } else {
        return a;
    }
};
DataDrivenProperty.prototype.evaluate = function evaluate(value, parameters, feature, featureState, canonical, availableImages) {
    if (value.kind === 'constant') {
        return value.value;
    } else {
        return value.evaluate(parameters, feature, featureState, canonical, availableImages);
    }
};
var CrossFadedDataDrivenProperty = function (DataDrivenProperty) {
    function CrossFadedDataDrivenProperty() {
        DataDrivenProperty.apply(this, arguments);
    }
    if (DataDrivenProperty)
        CrossFadedDataDrivenProperty.__proto__ = DataDrivenProperty;
    CrossFadedDataDrivenProperty.prototype = Object.create(DataDrivenProperty && DataDrivenProperty.prototype);
    CrossFadedDataDrivenProperty.prototype.constructor = CrossFadedDataDrivenProperty;
    CrossFadedDataDrivenProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters, canonical, availableImages) {
        if (value.value === undefined) {
            return new PossiblyEvaluatedPropertyValue(this, {
                kind: 'constant',
                value: undefined
            }, parameters);
        } else if (value.expression.kind === 'constant') {
            var evaluatedValue = value.expression.evaluate(parameters, null, {}, canonical, availableImages);
            var isImageExpression = value.property.specification.type === 'resolvedImage';
            var constantValue = isImageExpression && typeof evaluatedValue !== 'string' ? evaluatedValue.name : evaluatedValue;
            var constant = this._calculate(constantValue, constantValue, constantValue, parameters);
            return new PossiblyEvaluatedPropertyValue(this, {
                kind: 'constant',
                value: constant
            }, parameters);
        } else if (value.expression.kind === 'camera') {
            var cameraVal = this._calculate(value.expression.evaluate({ zoom: parameters.zoom - 1 }), value.expression.evaluate({ zoom: parameters.zoom }), value.expression.evaluate({ zoom: parameters.zoom + 1 }), parameters);
            return new PossiblyEvaluatedPropertyValue(this, {
                kind: 'constant',
                value: cameraVal
            }, parameters);
        } else {
            return new PossiblyEvaluatedPropertyValue(this, value.expression, parameters);
        }
    };
    CrossFadedDataDrivenProperty.prototype.evaluate = function evaluate(value, globals, feature, featureState, canonical, availableImages) {
        if (value.kind === 'source') {
            var constant = value.evaluate(globals, feature, featureState, canonical, availableImages);
            return this._calculate(constant, constant, constant, globals);
        } else if (value.kind === 'composite') {
            return this._calculate(value.evaluate({ zoom: Math.floor(globals.zoom) - 1 }, feature, featureState), value.evaluate({ zoom: Math.floor(globals.zoom) }, feature, featureState), value.evaluate({ zoom: Math.floor(globals.zoom) + 1 }, feature, featureState), globals);
        } else {
            return value.value;
        }
    };
    CrossFadedDataDrivenProperty.prototype._calculate = function _calculate(min, mid, max, parameters) {
        var z = parameters.zoom;
        return z > parameters.zoomHistory.lastIntegerZoom ? {
            from: min,
            to: mid
        } : {
            from: max,
            to: mid
        };
    };
    CrossFadedDataDrivenProperty.prototype.interpolate = function interpolate(a) {
        return a;
    };
    return CrossFadedDataDrivenProperty;
}(DataDrivenProperty);
var CrossFadedProperty = function CrossFadedProperty(specification) {
    this.specification = specification;
};
CrossFadedProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters, canonical, availableImages) {
    if (value.value === undefined) {
        return undefined;
    } else if (value.expression.kind === 'constant') {
        var constant = value.expression.evaluate(parameters, null, {}, canonical, availableImages);
        return this._calculate(constant, constant, constant, parameters);
    } else {
        return this._calculate(value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom - 1), parameters)), value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom), parameters)), value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom + 1), parameters)), parameters);
    }
};
CrossFadedProperty.prototype._calculate = function _calculate(min, mid, max, parameters) {
    var z = parameters.zoom;
    return z > parameters.zoomHistory.lastIntegerZoom ? {
        from: min,
        to: mid
    } : {
        from: max,
        to: mid
    };
};
CrossFadedProperty.prototype.interpolate = function interpolate(a) {
    return a;
};
var ColorRampProperty = function ColorRampProperty(specification) {
    this.specification = specification;
};
ColorRampProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters, canonical, availableImages) {
    return !!value.expression.evaluate(parameters, null, {}, canonical, availableImages);
};
ColorRampProperty.prototype.interpolate = function interpolate() {
    return false;
};
var Properties = function Properties(properties) {
    this.properties = properties;
    this.defaultPropertyValues = {};
    this.defaultTransitionablePropertyValues = {};
    this.defaultTransitioningPropertyValues = {};
    this.defaultPossiblyEvaluatedValues = {};
    this.overridableProperties = [];
    for (var property in properties) {
        var prop = properties[property];
        if (prop.specification.overridable) {
            this.overridableProperties.push(property);
        }
        var defaultPropertyValue = this.defaultPropertyValues[property] = new PropertyValue(prop, undefined);
        var defaultTransitionablePropertyValue = this.defaultTransitionablePropertyValues[property] = new TransitionablePropertyValue(prop);
        this.defaultTransitioningPropertyValues[property] = defaultTransitionablePropertyValue.untransitioned();
        this.defaultPossiblyEvaluatedValues[property] = defaultPropertyValue.possiblyEvaluate({});
    }
};
register('DataDrivenProperty', DataDrivenProperty);
register('DataConstantProperty', DataConstantProperty);
register('CrossFadedDataDrivenProperty', CrossFadedDataDrivenProperty);
register('CrossFadedProperty', CrossFadedProperty);
register('ColorRampProperty', ColorRampProperty);

var TRANSITION_SUFFIX = '-transition';
var StyleLayer = function (Evented) {
    function StyleLayer(layer, properties) {
        Evented.call(this);
        this.id = layer.id;
        this.type = layer.type;
        this._featureFilter = {
            filter: function () {
                return true;
            },
            needGeometry: false
        };
        if (layer.type === 'custom') {
            return;
        }
        layer = layer;
        this.metadata = layer.metadata;
        this.minzoom = layer.minzoom;
        this.maxzoom = layer.maxzoom;
        if (layer.type !== 'background') {
            this.source = layer.source;
            this.sourceLayer = layer['source-layer'];
            this.filter = layer.filter;
        }
        if (properties.layout) {
            this._unevaluatedLayout = new Layout(properties.layout);
        }
        if (properties.paint) {
            this._transitionablePaint = new Transitionable(properties.paint);
            for (var property in layer.paint) {
                this.setPaintProperty(property, layer.paint[property], { validate: false });
            }
            for (var property$1 in layer.layout) {
                this.setLayoutProperty(property$1, layer.layout[property$1], { validate: false });
            }
            this._transitioningPaint = this._transitionablePaint.untransitioned();
            this.paint = new PossiblyEvaluated(properties.paint);
        }
    }
    if (Evented)
        StyleLayer.__proto__ = Evented;
    StyleLayer.prototype = Object.create(Evented && Evented.prototype);
    StyleLayer.prototype.constructor = StyleLayer;
    StyleLayer.prototype.getCrossfadeParameters = function getCrossfadeParameters() {
        return this._crossfadeParameters;
    };
    StyleLayer.prototype.getLayoutProperty = function getLayoutProperty(name) {
        if (name === 'visibility') {
            return this.visibility;
        }
        return this._unevaluatedLayout.getValue(name);
    };
    StyleLayer.prototype.setLayoutProperty = function setLayoutProperty(name, value, options) {
        if (options === void 0)
            options = {};
        if (value !== null && value !== undefined) {
            var key = 'layers.' + this.id + '.layout.' + name;
            if (this._validate(validateLayoutProperty$1, key, name, value, options)) {
                return;
            }
        }
        if (name === 'visibility') {
            this.visibility = value;
            return;
        }
        this._unevaluatedLayout.setValue(name, value);
    };
    StyleLayer.prototype.getPaintProperty = function getPaintProperty(name) {
        if (endsWith(name, TRANSITION_SUFFIX)) {
            return this._transitionablePaint.getTransition(name.slice(0, -TRANSITION_SUFFIX.length));
        } else {
            return this._transitionablePaint.getValue(name);
        }
    };
    StyleLayer.prototype.setPaintProperty = function setPaintProperty(name, value, options) {
        if (options === void 0)
            options = {};
        if (value !== null && value !== undefined) {
            var key = 'layers.' + this.id + '.paint.' + name;
            if (this._validate(validatePaintProperty$1, key, name, value, options)) {
                return false;
            }
        }
        if (endsWith(name, TRANSITION_SUFFIX)) {
            this._transitionablePaint.setTransition(name.slice(0, -TRANSITION_SUFFIX.length), value || undefined);
            return false;
        } else {
            var transitionable = this._transitionablePaint._values[name];
            var isCrossFadedProperty = transitionable.property.specification['property-type'] === 'cross-faded-data-driven';
            var wasDataDriven = transitionable.value.isDataDriven();
            var oldValue = transitionable.value;
            this._transitionablePaint.setValue(name, value);
            this._handleSpecialPaintPropertyUpdate(name);
            var newValue = this._transitionablePaint._values[name].value;
            var isDataDriven = newValue.isDataDriven();
            return isDataDriven || wasDataDriven || isCrossFadedProperty || this._handleOverridablePaintPropertyUpdate(name, oldValue, newValue);
        }
    };
    StyleLayer.prototype._handleSpecialPaintPropertyUpdate = function _handleSpecialPaintPropertyUpdate(_) {
    };
    StyleLayer.prototype._handleOverridablePaintPropertyUpdate = function _handleOverridablePaintPropertyUpdate(name, oldValue, newValue) {
        return false;
    };
    StyleLayer.prototype.isHidden = function isHidden(zoom) {
        if (this.minzoom && zoom < this.minzoom) {
            return true;
        }
        if (this.maxzoom && zoom >= this.maxzoom) {
            return true;
        }
        return this.visibility === 'none';
    };
    StyleLayer.prototype.updateTransitions = function updateTransitions(parameters) {
        this._transitioningPaint = this._transitionablePaint.transitioned(parameters, this._transitioningPaint);
    };
    StyleLayer.prototype.hasTransition = function hasTransition() {
        return this._transitioningPaint.hasTransition();
    };
    StyleLayer.prototype.recalculate = function recalculate(parameters, availableImages) {
        if (parameters.getCrossfadeParameters) {
            this._crossfadeParameters = parameters.getCrossfadeParameters();
        }
        if (this._unevaluatedLayout) {
            this.layout = this._unevaluatedLayout.possiblyEvaluate(parameters, undefined, availableImages);
        }
        this.paint = this._transitioningPaint.possiblyEvaluate(parameters, undefined, availableImages);
    };
    StyleLayer.prototype.serialize = function serialize() {
        var output = {
            'id': this.id,
            'type': this.type,
            'source': this.source,
            'source-layer': this.sourceLayer,
            'metadata': this.metadata,
            'minzoom': this.minzoom,
            'maxzoom': this.maxzoom,
            'filter': this.filter,
            'layout': this._unevaluatedLayout && this._unevaluatedLayout.serialize(),
            'paint': this._transitionablePaint && this._transitionablePaint.serialize()
        };
        if (this.visibility) {
            output.layout = output.layout || {};
            output.layout.visibility = this.visibility;
        }
        return filterObject(output, function (value, key) {
            return value !== undefined && !(key === 'layout' && !Object.keys(value).length) && !(key === 'paint' && !Object.keys(value).length);
        });
    };
    StyleLayer.prototype._validate = function _validate(validate, key, name, value, options) {
        if (options === void 0)
            options = {};
        if (options && options.validate === false) {
            return false;
        }
        return emitValidationErrors(this, validate.call(validateStyle, {
            key: key,
            layerType: this.type,
            objectKey: name,
            value: value,
            styleSpec: spec,
            style: {
                glyphs: true,
                sprite: true
            }
        }));
    };
    StyleLayer.prototype.is3D = function is3D() {
        return false;
    };
    StyleLayer.prototype.isTileClipped = function isTileClipped() {
        return false;
    };
    StyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass() {
        return false;
    };
    StyleLayer.prototype.resize = function resize() {
    };
    StyleLayer.prototype.isStateDependent = function isStateDependent() {
        for (var property in this.paint._values) {
            var value = this.paint.get(property);
            if (!(value instanceof PossiblyEvaluatedPropertyValue) || !supportsPropertyExpression(value.property.specification)) {
                continue;
            }
            if ((value.value.kind === 'source' || value.value.kind === 'composite') && value.value.isStateDependent) {
                return true;
            }
        }
        return false;
    };
    return StyleLayer;
}(Evented);

var viewTypes = {
    'Int8': Int8Array,
    'Uint8': Uint8Array,
    'Int16': Int16Array,
    'Uint16': Uint16Array,
    'Int32': Int32Array,
    'Uint32': Uint32Array,
    'Float32': Float32Array
};
var Struct = function Struct(structArray, index) {
    this._structArray = structArray;
    this._pos1 = index * this.size;
    this._pos2 = this._pos1 / 2;
    this._pos4 = this._pos1 / 4;
    this._pos8 = this._pos1 / 8;
};
var DEFAULT_CAPACITY = 128;
var RESIZE_MULTIPLIER = 5;
var StructArray = function StructArray() {
    this.isTransferred = false;
    this.capacity = -1;
    this.resize(0);
};
StructArray.serialize = function serialize(array, transferables) {
    array._trim();
    if (transferables) {
        array.isTransferred = true;
        transferables.push(array.arrayBuffer);
    }
    return {
        length: array.length,
        arrayBuffer: array.arrayBuffer
    };
};
StructArray.deserialize = function deserialize(input) {
    var structArray = Object.create(this.prototype);
    structArray.arrayBuffer = input.arrayBuffer;
    structArray.length = input.length;
    structArray.capacity = input.arrayBuffer.byteLength / structArray.bytesPerElement;
    structArray._refreshViews();
    return structArray;
};
StructArray.prototype._trim = function _trim() {
    if (this.length !== this.capacity) {
        this.capacity = this.length;
        this.arrayBuffer = this.arrayBuffer.slice(0, this.length * this.bytesPerElement);
        this._refreshViews();
    }
};
StructArray.prototype.clear = function clear() {
    this.length = 0;
};
StructArray.prototype.resize = function resize(n) {
    this.reserve(n);
    this.length = n;
};
StructArray.prototype.reserve = function reserve(n) {
    if (n > this.capacity) {
        this.capacity = Math.max(n, Math.floor(this.capacity * RESIZE_MULTIPLIER), DEFAULT_CAPACITY);
        this.arrayBuffer = new ArrayBuffer(this.capacity * this.bytesPerElement);
        var oldUint8Array = this.uint8;
        this._refreshViews();
        if (oldUint8Array) {
            this.uint8.set(oldUint8Array);
        }
    }
};
StructArray.prototype._refreshViews = function _refreshViews() {
    throw new Error('_refreshViews() must be implemented by each concrete StructArray layout');
};
function createLayout(members, alignment) {
    if (alignment === void 0)
        alignment = 1;
    var offset = 0;
    var maxSize = 0;
    var layoutMembers = members.map(function (member) {
        var typeSize = sizeOf(member.type);
        var memberOffset = offset = align(offset, Math.max(alignment, typeSize));
        var components = member.components || 1;
        maxSize = Math.max(maxSize, typeSize);
        offset += typeSize * components;
        return {
            name: member.name,
            type: member.type,
            components: components,
            offset: memberOffset
        };
    });
    var size = align(offset, Math.max(maxSize, alignment));
    return {
        members: layoutMembers,
        size: size,
        alignment: alignment
    };
}
function sizeOf(type) {
    return viewTypes[type].BYTES_PER_ELEMENT;
}
function align(offset, size) {
    return Math.ceil(offset / size) * size;
}

var StructArrayLayout2i4 = function (StructArray) {
    function StructArrayLayout2i4() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2i4.__proto__ = StructArray;
    StructArrayLayout2i4.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2i4.prototype.constructor = StructArrayLayout2i4;
    StructArrayLayout2i4.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout2i4.prototype.emplaceBack = function emplaceBack(v0, v1) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1);
    };
    StructArrayLayout2i4.prototype.emplace = function emplace(i, v0, v1) {
        var o2 = i * 2;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        return i;
    };
    return StructArrayLayout2i4;
}(StructArray);
StructArrayLayout2i4.prototype.bytesPerElement = 4;
register('StructArrayLayout2i4', StructArrayLayout2i4);
var StructArrayLayout4i8 = function (StructArray) {
    function StructArrayLayout4i8() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout4i8.__proto__ = StructArray;
    StructArrayLayout4i8.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout4i8.prototype.constructor = StructArrayLayout4i8;
    StructArrayLayout4i8.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout4i8.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3);
    };
    StructArrayLayout4i8.prototype.emplace = function emplace(i, v0, v1, v2, v3) {
        var o2 = i * 4;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        this.int16[o2 + 3] = v3;
        return i;
    };
    return StructArrayLayout4i8;
}(StructArray);
StructArrayLayout4i8.prototype.bytesPerElement = 8;
register('StructArrayLayout4i8', StructArrayLayout4i8);
var StructArrayLayout2i4i12 = function (StructArray) {
    function StructArrayLayout2i4i12() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2i4i12.__proto__ = StructArray;
    StructArrayLayout2i4i12.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2i4i12.prototype.constructor = StructArrayLayout2i4i12;
    StructArrayLayout2i4i12.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout2i4i12.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5);
    };
    StructArrayLayout2i4i12.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5) {
        var o2 = i * 6;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        this.int16[o2 + 3] = v3;
        this.int16[o2 + 4] = v4;
        this.int16[o2 + 5] = v5;
        return i;
    };
    return StructArrayLayout2i4i12;
}(StructArray);
StructArrayLayout2i4i12.prototype.bytesPerElement = 12;
register('StructArrayLayout2i4i12', StructArrayLayout2i4i12);
var StructArrayLayout2i4ub8 = function (StructArray) {
    function StructArrayLayout2i4ub8() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2i4ub8.__proto__ = StructArray;
    StructArrayLayout2i4ub8.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2i4ub8.prototype.constructor = StructArrayLayout2i4ub8;
    StructArrayLayout2i4ub8.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout2i4ub8.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5);
    };
    StructArrayLayout2i4ub8.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5) {
        var o2 = i * 4;
        var o1 = i * 8;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.uint8[o1 + 4] = v2;
        this.uint8[o1 + 5] = v3;
        this.uint8[o1 + 6] = v4;
        this.uint8[o1 + 7] = v5;
        return i;
    };
    return StructArrayLayout2i4ub8;
}(StructArray);
StructArrayLayout2i4ub8.prototype.bytesPerElement = 8;
register('StructArrayLayout2i4ub8', StructArrayLayout2i4ub8);
var StructArrayLayout2f8 = function (StructArray) {
    function StructArrayLayout2f8() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2f8.__proto__ = StructArray;
    StructArrayLayout2f8.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2f8.prototype.constructor = StructArrayLayout2f8;
    StructArrayLayout2f8.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout2f8.prototype.emplaceBack = function emplaceBack(v0, v1) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1);
    };
    StructArrayLayout2f8.prototype.emplace = function emplace(i, v0, v1) {
        var o4 = i * 2;
        this.float32[o4 + 0] = v0;
        this.float32[o4 + 1] = v1;
        return i;
    };
    return StructArrayLayout2f8;
}(StructArray);
StructArrayLayout2f8.prototype.bytesPerElement = 8;
register('StructArrayLayout2f8', StructArrayLayout2f8);
var StructArrayLayout10ui20 = function (StructArray) {
    function StructArrayLayout10ui20() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout10ui20.__proto__ = StructArray;
    StructArrayLayout10ui20.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout10ui20.prototype.constructor = StructArrayLayout10ui20;
    StructArrayLayout10ui20.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout10ui20.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
    };
    StructArrayLayout10ui20.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
        var o2 = i * 10;
        this.uint16[o2 + 0] = v0;
        this.uint16[o2 + 1] = v1;
        this.uint16[o2 + 2] = v2;
        this.uint16[o2 + 3] = v3;
        this.uint16[o2 + 4] = v4;
        this.uint16[o2 + 5] = v5;
        this.uint16[o2 + 6] = v6;
        this.uint16[o2 + 7] = v7;
        this.uint16[o2 + 8] = v8;
        this.uint16[o2 + 9] = v9;
        return i;
    };
    return StructArrayLayout10ui20;
}(StructArray);
StructArrayLayout10ui20.prototype.bytesPerElement = 20;
register('StructArrayLayout10ui20', StructArrayLayout10ui20);
var StructArrayLayout4i4ui4i24 = function (StructArray) {
    function StructArrayLayout4i4ui4i24() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout4i4ui4i24.__proto__ = StructArray;
    StructArrayLayout4i4ui4i24.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout4i4ui4i24.prototype.constructor = StructArrayLayout4i4ui4i24;
    StructArrayLayout4i4ui4i24.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout4i4ui4i24.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
    };
    StructArrayLayout4i4ui4i24.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) {
        var o2 = i * 12;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        this.int16[o2 + 3] = v3;
        this.uint16[o2 + 4] = v4;
        this.uint16[o2 + 5] = v5;
        this.uint16[o2 + 6] = v6;
        this.uint16[o2 + 7] = v7;
        this.int16[o2 + 8] = v8;
        this.int16[o2 + 9] = v9;
        this.int16[o2 + 10] = v10;
        this.int16[o2 + 11] = v11;
        return i;
    };
    return StructArrayLayout4i4ui4i24;
}(StructArray);
StructArrayLayout4i4ui4i24.prototype.bytesPerElement = 24;
register('StructArrayLayout4i4ui4i24', StructArrayLayout4i4ui4i24);
var StructArrayLayout3f12 = function (StructArray) {
    function StructArrayLayout3f12() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout3f12.__proto__ = StructArray;
    StructArrayLayout3f12.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout3f12.prototype.constructor = StructArrayLayout3f12;
    StructArrayLayout3f12.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout3f12.prototype.emplaceBack = function emplaceBack(v0, v1, v2) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2);
    };
    StructArrayLayout3f12.prototype.emplace = function emplace(i, v0, v1, v2) {
        var o4 = i * 3;
        this.float32[o4 + 0] = v0;
        this.float32[o4 + 1] = v1;
        this.float32[o4 + 2] = v2;
        return i;
    };
    return StructArrayLayout3f12;
}(StructArray);
StructArrayLayout3f12.prototype.bytesPerElement = 12;
register('StructArrayLayout3f12', StructArrayLayout3f12);
var StructArrayLayout1ul4 = function (StructArray) {
    function StructArrayLayout1ul4() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout1ul4.__proto__ = StructArray;
    StructArrayLayout1ul4.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout1ul4.prototype.constructor = StructArrayLayout1ul4;
    StructArrayLayout1ul4.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.uint32 = new Uint32Array(this.arrayBuffer);
    };
    StructArrayLayout1ul4.prototype.emplaceBack = function emplaceBack(v0) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0);
    };
    StructArrayLayout1ul4.prototype.emplace = function emplace(i, v0) {
        var o4 = i * 1;
        this.uint32[o4 + 0] = v0;
        return i;
    };
    return StructArrayLayout1ul4;
}(StructArray);
StructArrayLayout1ul4.prototype.bytesPerElement = 4;
register('StructArrayLayout1ul4', StructArrayLayout1ul4);
var StructArrayLayout6i1ul2ui20 = function (StructArray) {
    function StructArrayLayout6i1ul2ui20() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout6i1ul2ui20.__proto__ = StructArray;
    StructArrayLayout6i1ul2ui20.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout6i1ul2ui20.prototype.constructor = StructArrayLayout6i1ul2ui20;
    StructArrayLayout6i1ul2ui20.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
        this.uint32 = new Uint32Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout6i1ul2ui20.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8);
    };
    StructArrayLayout6i1ul2ui20.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8) {
        var o2 = i * 10;
        var o4 = i * 5;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        this.int16[o2 + 3] = v3;
        this.int16[o2 + 4] = v4;
        this.int16[o2 + 5] = v5;
        this.uint32[o4 + 3] = v6;
        this.uint16[o2 + 8] = v7;
        this.uint16[o2 + 9] = v8;
        return i;
    };
    return StructArrayLayout6i1ul2ui20;
}(StructArray);
StructArrayLayout6i1ul2ui20.prototype.bytesPerElement = 20;
register('StructArrayLayout6i1ul2ui20', StructArrayLayout6i1ul2ui20);
var StructArrayLayout2i2i2i12 = function (StructArray) {
    function StructArrayLayout2i2i2i12() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2i2i2i12.__proto__ = StructArray;
    StructArrayLayout2i2i2i12.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2i2i2i12.prototype.constructor = StructArrayLayout2i2i2i12;
    StructArrayLayout2i2i2i12.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout2i2i2i12.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5);
    };
    StructArrayLayout2i2i2i12.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5) {
        var o2 = i * 6;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        this.int16[o2 + 3] = v3;
        this.int16[o2 + 4] = v4;
        this.int16[o2 + 5] = v5;
        return i;
    };
    return StructArrayLayout2i2i2i12;
}(StructArray);
StructArrayLayout2i2i2i12.prototype.bytesPerElement = 12;
register('StructArrayLayout2i2i2i12', StructArrayLayout2i2i2i12);
var StructArrayLayout2f1f2i16 = function (StructArray) {
    function StructArrayLayout2f1f2i16() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2f1f2i16.__proto__ = StructArray;
    StructArrayLayout2f1f2i16.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2f1f2i16.prototype.constructor = StructArrayLayout2f1f2i16;
    StructArrayLayout2f1f2i16.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout2f1f2i16.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4);
    };
    StructArrayLayout2f1f2i16.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4) {
        var o4 = i * 4;
        var o2 = i * 8;
        this.float32[o4 + 0] = v0;
        this.float32[o4 + 1] = v1;
        this.float32[o4 + 2] = v2;
        this.int16[o2 + 6] = v3;
        this.int16[o2 + 7] = v4;
        return i;
    };
    return StructArrayLayout2f1f2i16;
}(StructArray);
StructArrayLayout2f1f2i16.prototype.bytesPerElement = 16;
register('StructArrayLayout2f1f2i16', StructArrayLayout2f1f2i16);
var StructArrayLayout2ub2f12 = function (StructArray) {
    function StructArrayLayout2ub2f12() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2ub2f12.__proto__ = StructArray;
    StructArrayLayout2ub2f12.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2ub2f12.prototype.constructor = StructArrayLayout2ub2f12;
    StructArrayLayout2ub2f12.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout2ub2f12.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3);
    };
    StructArrayLayout2ub2f12.prototype.emplace = function emplace(i, v0, v1, v2, v3) {
        var o1 = i * 12;
        var o4 = i * 3;
        this.uint8[o1 + 0] = v0;
        this.uint8[o1 + 1] = v1;
        this.float32[o4 + 1] = v2;
        this.float32[o4 + 2] = v3;
        return i;
    };
    return StructArrayLayout2ub2f12;
}(StructArray);
StructArrayLayout2ub2f12.prototype.bytesPerElement = 12;
register('StructArrayLayout2ub2f12', StructArrayLayout2ub2f12);
var StructArrayLayout3ui6 = function (StructArray) {
    function StructArrayLayout3ui6() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout3ui6.__proto__ = StructArray;
    StructArrayLayout3ui6.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout3ui6.prototype.constructor = StructArrayLayout3ui6;
    StructArrayLayout3ui6.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout3ui6.prototype.emplaceBack = function emplaceBack(v0, v1, v2) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2);
    };
    StructArrayLayout3ui6.prototype.emplace = function emplace(i, v0, v1, v2) {
        var o2 = i * 3;
        this.uint16[o2 + 0] = v0;
        this.uint16[o2 + 1] = v1;
        this.uint16[o2 + 2] = v2;
        return i;
    };
    return StructArrayLayout3ui6;
}(StructArray);
StructArrayLayout3ui6.prototype.bytesPerElement = 6;
register('StructArrayLayout3ui6', StructArrayLayout3ui6);
var StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48 = function (StructArray) {
    function StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.__proto__ = StructArray;
    StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype.constructor = StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48;
    StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
        this.uint32 = new Uint32Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16);
    };
    StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) {
        var o2 = i * 24;
        var o4 = i * 12;
        var o1 = i * 48;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.uint16[o2 + 2] = v2;
        this.uint16[o2 + 3] = v3;
        this.uint32[o4 + 2] = v4;
        this.uint32[o4 + 3] = v5;
        this.uint32[o4 + 4] = v6;
        this.uint16[o2 + 10] = v7;
        this.uint16[o2 + 11] = v8;
        this.uint16[o2 + 12] = v9;
        this.float32[o4 + 7] = v10;
        this.float32[o4 + 8] = v11;
        this.uint8[o1 + 36] = v12;
        this.uint8[o1 + 37] = v13;
        this.uint8[o1 + 38] = v14;
        this.uint32[o4 + 10] = v15;
        this.int16[o2 + 22] = v16;
        return i;
    };
    return StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48;
}(StructArray);
StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype.bytesPerElement = 48;
register('StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48', StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48);
var StructArrayLayout8i15ui1ul4f68 = function (StructArray) {
    function StructArrayLayout8i15ui1ul4f68() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout8i15ui1ul4f68.__proto__ = StructArray;
    StructArrayLayout8i15ui1ul4f68.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout8i15ui1ul4f68.prototype.constructor = StructArrayLayout8i15ui1ul4f68;
    StructArrayLayout8i15ui1ul4f68.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
        this.uint32 = new Uint32Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout8i15ui1ul4f68.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
    };
    StructArrayLayout8i15ui1ul4f68.prototype.emplace = function emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) {
        var o2 = i * 34;
        var o4 = i * 17;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        this.int16[o2 + 3] = v3;
        this.int16[o2 + 4] = v4;
        this.int16[o2 + 5] = v5;
        this.int16[o2 + 6] = v6;
        this.int16[o2 + 7] = v7;
        this.uint16[o2 + 8] = v8;
        this.uint16[o2 + 9] = v9;
        this.uint16[o2 + 10] = v10;
        this.uint16[o2 + 11] = v11;
        this.uint16[o2 + 12] = v12;
        this.uint16[o2 + 13] = v13;
        this.uint16[o2 + 14] = v14;
        this.uint16[o2 + 15] = v15;
        this.uint16[o2 + 16] = v16;
        this.uint16[o2 + 17] = v17;
        this.uint16[o2 + 18] = v18;
        this.uint16[o2 + 19] = v19;
        this.uint16[o2 + 20] = v20;
        this.uint16[o2 + 21] = v21;
        this.uint16[o2 + 22] = v22;
        this.uint32[o4 + 12] = v23;
        this.float32[o4 + 13] = v24;
        this.float32[o4 + 14] = v25;
        this.float32[o4 + 15] = v26;
        this.float32[o4 + 16] = v27;
        return i;
    };
    return StructArrayLayout8i15ui1ul4f68;
}(StructArray);
StructArrayLayout8i15ui1ul4f68.prototype.bytesPerElement = 68;
register('StructArrayLayout8i15ui1ul4f68', StructArrayLayout8i15ui1ul4f68);
var StructArrayLayout1f4 = function (StructArray) {
    function StructArrayLayout1f4() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout1f4.__proto__ = StructArray;
    StructArrayLayout1f4.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout1f4.prototype.constructor = StructArrayLayout1f4;
    StructArrayLayout1f4.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout1f4.prototype.emplaceBack = function emplaceBack(v0) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0);
    };
    StructArrayLayout1f4.prototype.emplace = function emplace(i, v0) {
        var o4 = i * 1;
        this.float32[o4 + 0] = v0;
        return i;
    };
    return StructArrayLayout1f4;
}(StructArray);
StructArrayLayout1f4.prototype.bytesPerElement = 4;
register('StructArrayLayout1f4', StructArrayLayout1f4);
var StructArrayLayout3i6 = function (StructArray) {
    function StructArrayLayout3i6() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout3i6.__proto__ = StructArray;
    StructArrayLayout3i6.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout3i6.prototype.constructor = StructArrayLayout3i6;
    StructArrayLayout3i6.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.int16 = new Int16Array(this.arrayBuffer);
    };
    StructArrayLayout3i6.prototype.emplaceBack = function emplaceBack(v0, v1, v2) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2);
    };
    StructArrayLayout3i6.prototype.emplace = function emplace(i, v0, v1, v2) {
        var o2 = i * 3;
        this.int16[o2 + 0] = v0;
        this.int16[o2 + 1] = v1;
        this.int16[o2 + 2] = v2;
        return i;
    };
    return StructArrayLayout3i6;
}(StructArray);
StructArrayLayout3i6.prototype.bytesPerElement = 6;
register('StructArrayLayout3i6', StructArrayLayout3i6);
var StructArrayLayout1ul2ui8 = function (StructArray) {
    function StructArrayLayout1ul2ui8() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout1ul2ui8.__proto__ = StructArray;
    StructArrayLayout1ul2ui8.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout1ul2ui8.prototype.constructor = StructArrayLayout1ul2ui8;
    StructArrayLayout1ul2ui8.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.uint32 = new Uint32Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout1ul2ui8.prototype.emplaceBack = function emplaceBack(v0, v1, v2) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2);
    };
    StructArrayLayout1ul2ui8.prototype.emplace = function emplace(i, v0, v1, v2) {
        var o4 = i * 2;
        var o2 = i * 4;
        this.uint32[o4 + 0] = v0;
        this.uint16[o2 + 2] = v1;
        this.uint16[o2 + 3] = v2;
        return i;
    };
    return StructArrayLayout1ul2ui8;
}(StructArray);
StructArrayLayout1ul2ui8.prototype.bytesPerElement = 8;
register('StructArrayLayout1ul2ui8', StructArrayLayout1ul2ui8);
var StructArrayLayout2ui4 = function (StructArray) {
    function StructArrayLayout2ui4() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout2ui4.__proto__ = StructArray;
    StructArrayLayout2ui4.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout2ui4.prototype.constructor = StructArrayLayout2ui4;
    StructArrayLayout2ui4.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout2ui4.prototype.emplaceBack = function emplaceBack(v0, v1) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1);
    };
    StructArrayLayout2ui4.prototype.emplace = function emplace(i, v0, v1) {
        var o2 = i * 2;
        this.uint16[o2 + 0] = v0;
        this.uint16[o2 + 1] = v1;
        return i;
    };
    return StructArrayLayout2ui4;
}(StructArray);
StructArrayLayout2ui4.prototype.bytesPerElement = 4;
register('StructArrayLayout2ui4', StructArrayLayout2ui4);
var StructArrayLayout1ui2 = function (StructArray) {
    function StructArrayLayout1ui2() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout1ui2.__proto__ = StructArray;
    StructArrayLayout1ui2.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout1ui2.prototype.constructor = StructArrayLayout1ui2;
    StructArrayLayout1ui2.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.uint16 = new Uint16Array(this.arrayBuffer);
    };
    StructArrayLayout1ui2.prototype.emplaceBack = function emplaceBack(v0) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0);
    };
    StructArrayLayout1ui2.prototype.emplace = function emplace(i, v0) {
        var o2 = i * 1;
        this.uint16[o2 + 0] = v0;
        return i;
    };
    return StructArrayLayout1ui2;
}(StructArray);
StructArrayLayout1ui2.prototype.bytesPerElement = 2;
register('StructArrayLayout1ui2', StructArrayLayout1ui2);
var StructArrayLayout4f16 = function (StructArray) {
    function StructArrayLayout4f16() {
        StructArray.apply(this, arguments);
    }
    if (StructArray)
        StructArrayLayout4f16.__proto__ = StructArray;
    StructArrayLayout4f16.prototype = Object.create(StructArray && StructArray.prototype);
    StructArrayLayout4f16.prototype.constructor = StructArrayLayout4f16;
    StructArrayLayout4f16.prototype._refreshViews = function _refreshViews() {
        this.uint8 = new Uint8Array(this.arrayBuffer);
        this.float32 = new Float32Array(this.arrayBuffer);
    };
    StructArrayLayout4f16.prototype.emplaceBack = function emplaceBack(v0, v1, v2, v3) {
        var i = this.length;
        this.resize(i + 1);
        return this.emplace(i, v0, v1, v2, v3);
    };
    StructArrayLayout4f16.prototype.emplace = function emplace(i, v0, v1, v2, v3) {
        var o4 = i * 4;
        this.float32[o4 + 0] = v0;
        this.float32[o4 + 1] = v1;
        this.float32[o4 + 2] = v2;
        this.float32[o4 + 3] = v3;
        return i;
    };
    return StructArrayLayout4f16;
}(StructArray);
StructArrayLayout4f16.prototype.bytesPerElement = 16;
register('StructArrayLayout4f16', StructArrayLayout4f16);
var CollisionBoxStruct = function (Struct) {
    function CollisionBoxStruct() {
        Struct.apply(this, arguments);
    }
    if (Struct)
        CollisionBoxStruct.__proto__ = Struct;
    CollisionBoxStruct.prototype = Object.create(Struct && Struct.prototype);
    CollisionBoxStruct.prototype.constructor = CollisionBoxStruct;
    var prototypeAccessors = {
        anchorPointX: { configurable: true },
        anchorPointY: { configurable: true },
        x1: { configurable: true },
        y1: { configurable: true },
        x2: { configurable: true },
        y2: { configurable: true },
        featureIndex: { configurable: true },
        sourceLayerIndex: { configurable: true },
        bucketIndex: { configurable: true },
        anchorPoint: { configurable: true }
    };
    prototypeAccessors.anchorPointX.get = function () {
        return this._structArray.int16[this._pos2 + 0];
    };
    prototypeAccessors.anchorPointY.get = function () {
        return this._structArray.int16[this._pos2 + 1];
    };
    prototypeAccessors.x1.get = function () {
        return this._structArray.int16[this._pos2 + 2];
    };
    prototypeAccessors.y1.get = function () {
        return this._structArray.int16[this._pos2 + 3];
    };
    prototypeAccessors.x2.get = function () {
        return this._structArray.int16[this._pos2 + 4];
    };
    prototypeAccessors.y2.get = function () {
        return this._structArray.int16[this._pos2 + 5];
    };
    prototypeAccessors.featureIndex.get = function () {
        return this._structArray.uint32[this._pos4 + 3];
    };
    prototypeAccessors.sourceLayerIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 8];
    };
    prototypeAccessors.bucketIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 9];
    };
    prototypeAccessors.anchorPoint.get = function () {
        return new pointGeometry(this.anchorPointX, this.anchorPointY);
    };
    Object.defineProperties(CollisionBoxStruct.prototype, prototypeAccessors);
    return CollisionBoxStruct;
}(Struct);
CollisionBoxStruct.prototype.size = 20;
var CollisionBoxArray = function (StructArrayLayout6i1ul2ui20) {
    function CollisionBoxArray() {
        StructArrayLayout6i1ul2ui20.apply(this, arguments);
    }
    if (StructArrayLayout6i1ul2ui20)
        CollisionBoxArray.__proto__ = StructArrayLayout6i1ul2ui20;
    CollisionBoxArray.prototype = Object.create(StructArrayLayout6i1ul2ui20 && StructArrayLayout6i1ul2ui20.prototype);
    CollisionBoxArray.prototype.constructor = CollisionBoxArray;
    CollisionBoxArray.prototype.get = function get(index) {
        return new CollisionBoxStruct(this, index);
    };
    return CollisionBoxArray;
}(StructArrayLayout6i1ul2ui20);
register('CollisionBoxArray', CollisionBoxArray);
var PlacedSymbolStruct = function (Struct) {
    function PlacedSymbolStruct() {
        Struct.apply(this, arguments);
    }
    if (Struct)
        PlacedSymbolStruct.__proto__ = Struct;
    PlacedSymbolStruct.prototype = Object.create(Struct && Struct.prototype);
    PlacedSymbolStruct.prototype.constructor = PlacedSymbolStruct;
    var prototypeAccessors$1 = {
        anchorX: { configurable: true },
        anchorY: { configurable: true },
        glyphStartIndex: { configurable: true },
        numGlyphs: { configurable: true },
        vertexStartIndex: { configurable: true },
        lineStartIndex: { configurable: true },
        lineLength: { configurable: true },
        segment: { configurable: true },
        lowerSize: { configurable: true },
        upperSize: { configurable: true },
        lineOffsetX: { configurable: true },
        lineOffsetY: { configurable: true },
        writingMode: { configurable: true },
        placedOrientation: { configurable: true },
        hidden: { configurable: true },
        crossTileID: { configurable: true },
        associatedIconIndex: { configurable: true }
    };
    prototypeAccessors$1.anchorX.get = function () {
        return this._structArray.int16[this._pos2 + 0];
    };
    prototypeAccessors$1.anchorY.get = function () {
        return this._structArray.int16[this._pos2 + 1];
    };
    prototypeAccessors$1.glyphStartIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 2];
    };
    prototypeAccessors$1.numGlyphs.get = function () {
        return this._structArray.uint16[this._pos2 + 3];
    };
    prototypeAccessors$1.vertexStartIndex.get = function () {
        return this._structArray.uint32[this._pos4 + 2];
    };
    prototypeAccessors$1.lineStartIndex.get = function () {
        return this._structArray.uint32[this._pos4 + 3];
    };
    prototypeAccessors$1.lineLength.get = function () {
        return this._structArray.uint32[this._pos4 + 4];
    };
    prototypeAccessors$1.segment.get = function () {
        return this._structArray.uint16[this._pos2 + 10];
    };
    prototypeAccessors$1.lowerSize.get = function () {
        return this._structArray.uint16[this._pos2 + 11];
    };
    prototypeAccessors$1.upperSize.get = function () {
        return this._structArray.uint16[this._pos2 + 12];
    };
    prototypeAccessors$1.lineOffsetX.get = function () {
        return this._structArray.float32[this._pos4 + 7];
    };
    prototypeAccessors$1.lineOffsetY.get = function () {
        return this._structArray.float32[this._pos4 + 8];
    };
    prototypeAccessors$1.writingMode.get = function () {
        return this._structArray.uint8[this._pos1 + 36];
    };
    prototypeAccessors$1.placedOrientation.get = function () {
        return this._structArray.uint8[this._pos1 + 37];
    };
    prototypeAccessors$1.placedOrientation.set = function (x) {
        this._structArray.uint8[this._pos1 + 37] = x;
    };
    prototypeAccessors$1.hidden.get = function () {
        return this._structArray.uint8[this._pos1 + 38];
    };
    prototypeAccessors$1.hidden.set = function (x) {
        this._structArray.uint8[this._pos1 + 38] = x;
    };
    prototypeAccessors$1.crossTileID.get = function () {
        return this._structArray.uint32[this._pos4 + 10];
    };
    prototypeAccessors$1.crossTileID.set = function (x) {
        this._structArray.uint32[this._pos4 + 10] = x;
    };
    prototypeAccessors$1.associatedIconIndex.get = function () {
        return this._structArray.int16[this._pos2 + 22];
    };
    Object.defineProperties(PlacedSymbolStruct.prototype, prototypeAccessors$1);
    return PlacedSymbolStruct;
}(Struct);
PlacedSymbolStruct.prototype.size = 48;
var PlacedSymbolArray = function (StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48) {
    function PlacedSymbolArray() {
        StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.apply(this, arguments);
    }
    if (StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48)
        PlacedSymbolArray.__proto__ = StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48;
    PlacedSymbolArray.prototype = Object.create(StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48 && StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48.prototype);
    PlacedSymbolArray.prototype.constructor = PlacedSymbolArray;
    PlacedSymbolArray.prototype.get = function get(index) {
        return new PlacedSymbolStruct(this, index);
    };
    return PlacedSymbolArray;
}(StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48);
register('PlacedSymbolArray', PlacedSymbolArray);
var SymbolInstanceStruct = function (Struct) {
    function SymbolInstanceStruct() {
        Struct.apply(this, arguments);
    }
    if (Struct)
        SymbolInstanceStruct.__proto__ = Struct;
    SymbolInstanceStruct.prototype = Object.create(Struct && Struct.prototype);
    SymbolInstanceStruct.prototype.constructor = SymbolInstanceStruct;
    var prototypeAccessors$2 = {
        anchorX: { configurable: true },
        anchorY: { configurable: true },
        rightJustifiedTextSymbolIndex: { configurable: true },
        centerJustifiedTextSymbolIndex: { configurable: true },
        leftJustifiedTextSymbolIndex: { configurable: true },
        verticalPlacedTextSymbolIndex: { configurable: true },
        placedIconSymbolIndex: { configurable: true },
        verticalPlacedIconSymbolIndex: { configurable: true },
        key: { configurable: true },
        textBoxStartIndex: { configurable: true },
        textBoxEndIndex: { configurable: true },
        verticalTextBoxStartIndex: { configurable: true },
        verticalTextBoxEndIndex: { configurable: true },
        iconBoxStartIndex: { configurable: true },
        iconBoxEndIndex: { configurable: true },
        verticalIconBoxStartIndex: { configurable: true },
        verticalIconBoxEndIndex: { configurable: true },
        featureIndex: { configurable: true },
        numHorizontalGlyphVertices: { configurable: true },
        numVerticalGlyphVertices: { configurable: true },
        numIconVertices: { configurable: true },
        numVerticalIconVertices: { configurable: true },
        useRuntimeCollisionCircles: { configurable: true },
        crossTileID: { configurable: true },
        textBoxScale: { configurable: true },
        textOffset0: { configurable: true },
        textOffset1: { configurable: true },
        collisionCircleDiameter: { configurable: true }
    };
    prototypeAccessors$2.anchorX.get = function () {
        return this._structArray.int16[this._pos2 + 0];
    };
    prototypeAccessors$2.anchorY.get = function () {
        return this._structArray.int16[this._pos2 + 1];
    };
    prototypeAccessors$2.rightJustifiedTextSymbolIndex.get = function () {
        return this._structArray.int16[this._pos2 + 2];
    };
    prototypeAccessors$2.centerJustifiedTextSymbolIndex.get = function () {
        return this._structArray.int16[this._pos2 + 3];
    };
    prototypeAccessors$2.leftJustifiedTextSymbolIndex.get = function () {
        return this._structArray.int16[this._pos2 + 4];
    };
    prototypeAccessors$2.verticalPlacedTextSymbolIndex.get = function () {
        return this._structArray.int16[this._pos2 + 5];
    };
    prototypeAccessors$2.placedIconSymbolIndex.get = function () {
        return this._structArray.int16[this._pos2 + 6];
    };
    prototypeAccessors$2.verticalPlacedIconSymbolIndex.get = function () {
        return this._structArray.int16[this._pos2 + 7];
    };
    prototypeAccessors$2.key.get = function () {
        return this._structArray.uint16[this._pos2 + 8];
    };
    prototypeAccessors$2.textBoxStartIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 9];
    };
    prototypeAccessors$2.textBoxEndIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 10];
    };
    prototypeAccessors$2.verticalTextBoxStartIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 11];
    };
    prototypeAccessors$2.verticalTextBoxEndIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 12];
    };
    prototypeAccessors$2.iconBoxStartIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 13];
    };
    prototypeAccessors$2.iconBoxEndIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 14];
    };
    prototypeAccessors$2.verticalIconBoxStartIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 15];
    };
    prototypeAccessors$2.verticalIconBoxEndIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 16];
    };
    prototypeAccessors$2.featureIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 17];
    };
    prototypeAccessors$2.numHorizontalGlyphVertices.get = function () {
        return this._structArray.uint16[this._pos2 + 18];
    };
    prototypeAccessors$2.numVerticalGlyphVertices.get = function () {
        return this._structArray.uint16[this._pos2 + 19];
    };
    prototypeAccessors$2.numIconVertices.get = function () {
        return this._structArray.uint16[this._pos2 + 20];
    };
    prototypeAccessors$2.numVerticalIconVertices.get = function () {
        return this._structArray.uint16[this._pos2 + 21];
    };
    prototypeAccessors$2.useRuntimeCollisionCircles.get = function () {
        return this._structArray.uint16[this._pos2 + 22];
    };
    prototypeAccessors$2.crossTileID.get = function () {
        return this._structArray.uint32[this._pos4 + 12];
    };
    prototypeAccessors$2.crossTileID.set = function (x) {
        this._structArray.uint32[this._pos4 + 12] = x;
    };
    prototypeAccessors$2.textBoxScale.get = function () {
        return this._structArray.float32[this._pos4 + 13];
    };
    prototypeAccessors$2.textOffset0.get = function () {
        return this._structArray.float32[this._pos4 + 14];
    };
    prototypeAccessors$2.textOffset1.get = function () {
        return this._structArray.float32[this._pos4 + 15];
    };
    prototypeAccessors$2.collisionCircleDiameter.get = function () {
        return this._structArray.float32[this._pos4 + 16];
    };
    Object.defineProperties(SymbolInstanceStruct.prototype, prototypeAccessors$2);
    return SymbolInstanceStruct;
}(Struct);
SymbolInstanceStruct.prototype.size = 68;
var SymbolInstanceArray = function (StructArrayLayout8i15ui1ul4f68) {
    function SymbolInstanceArray() {
        StructArrayLayout8i15ui1ul4f68.apply(this, arguments);
    }
    if (StructArrayLayout8i15ui1ul4f68)
        SymbolInstanceArray.__proto__ = StructArrayLayout8i15ui1ul4f68;
    SymbolInstanceArray.prototype = Object.create(StructArrayLayout8i15ui1ul4f68 && StructArrayLayout8i15ui1ul4f68.prototype);
    SymbolInstanceArray.prototype.constructor = SymbolInstanceArray;
    SymbolInstanceArray.prototype.get = function get(index) {
        return new SymbolInstanceStruct(this, index);
    };
    return SymbolInstanceArray;
}(StructArrayLayout8i15ui1ul4f68);
register('SymbolInstanceArray', SymbolInstanceArray);
var GlyphOffsetArray = function (StructArrayLayout1f4) {
    function GlyphOffsetArray() {
        StructArrayLayout1f4.apply(this, arguments);
    }
    if (StructArrayLayout1f4)
        GlyphOffsetArray.__proto__ = StructArrayLayout1f4;
    GlyphOffsetArray.prototype = Object.create(StructArrayLayout1f4 && StructArrayLayout1f4.prototype);
    GlyphOffsetArray.prototype.constructor = GlyphOffsetArray;
    GlyphOffsetArray.prototype.getoffsetX = function getoffsetX(index) {
        return this.float32[index * 1 + 0];
    };
    return GlyphOffsetArray;
}(StructArrayLayout1f4);
register('GlyphOffsetArray', GlyphOffsetArray);
var SymbolLineVertexArray = function (StructArrayLayout3i6) {
    function SymbolLineVertexArray() {
        StructArrayLayout3i6.apply(this, arguments);
    }
    if (StructArrayLayout3i6)
        SymbolLineVertexArray.__proto__ = StructArrayLayout3i6;
    SymbolLineVertexArray.prototype = Object.create(StructArrayLayout3i6 && StructArrayLayout3i6.prototype);
    SymbolLineVertexArray.prototype.constructor = SymbolLineVertexArray;
    SymbolLineVertexArray.prototype.getx = function getx(index) {
        return this.int16[index * 3 + 0];
    };
    SymbolLineVertexArray.prototype.gety = function gety(index) {
        return this.int16[index * 3 + 1];
    };
    SymbolLineVertexArray.prototype.gettileUnitDistanceFromAnchor = function gettileUnitDistanceFromAnchor(index) {
        return this.int16[index * 3 + 2];
    };
    return SymbolLineVertexArray;
}(StructArrayLayout3i6);
register('SymbolLineVertexArray', SymbolLineVertexArray);
var FeatureIndexStruct = function (Struct) {
    function FeatureIndexStruct() {
        Struct.apply(this, arguments);
    }
    if (Struct)
        FeatureIndexStruct.__proto__ = Struct;
    FeatureIndexStruct.prototype = Object.create(Struct && Struct.prototype);
    FeatureIndexStruct.prototype.constructor = FeatureIndexStruct;
    var prototypeAccessors$3 = {
        featureIndex: { configurable: true },
        sourceLayerIndex: { configurable: true },
        bucketIndex: { configurable: true }
    };
    prototypeAccessors$3.featureIndex.get = function () {
        return this._structArray.uint32[this._pos4 + 0];
    };
    prototypeAccessors$3.sourceLayerIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 2];
    };
    prototypeAccessors$3.bucketIndex.get = function () {
        return this._structArray.uint16[this._pos2 + 3];
    };
    Object.defineProperties(FeatureIndexStruct.prototype, prototypeAccessors$3);
    return FeatureIndexStruct;
}(Struct);
FeatureIndexStruct.prototype.size = 8;
var FeatureIndexArray = function (StructArrayLayout1ul2ui8) {
    function FeatureIndexArray() {
        StructArrayLayout1ul2ui8.apply(this, arguments);
    }
    if (StructArrayLayout1ul2ui8)
        FeatureIndexArray.__proto__ = StructArrayLayout1ul2ui8;
    FeatureIndexArray.prototype = Object.create(StructArrayLayout1ul2ui8 && StructArrayLayout1ul2ui8.prototype);
    FeatureIndexArray.prototype.constructor = FeatureIndexArray;
    FeatureIndexArray.prototype.get = function get(index) {
        return new FeatureIndexStruct(this, index);
    };
    return FeatureIndexArray;
}(StructArrayLayout1ul2ui8);
register('FeatureIndexArray', FeatureIndexArray);

var layout$1 = createLayout([{
        name: 'a_pos',
        components: 2,
        type: 'Int16'
    }], 4);
var members = layout$1.members;

var SegmentVector = function SegmentVector(segments) {
    if (segments === void 0)
        segments = [];
    this.segments = segments;
};
SegmentVector.prototype.prepareSegment = function prepareSegment(numVertices, layoutVertexArray, indexArray, sortKey) {
    var segment = this.segments[this.segments.length - 1];
    if (numVertices > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) {
        warnOnce('Max vertices per segment is ' + SegmentVector.MAX_VERTEX_ARRAY_LENGTH + ': bucket requested ' + numVertices);
    }
    if (!segment || segment.vertexLength + numVertices > SegmentVector.MAX_VERTEX_ARRAY_LENGTH || segment.sortKey !== sortKey) {
        segment = {
            vertexOffset: layoutVertexArray.length,
            primitiveOffset: indexArray.length,
            vertexLength: 0,
            primitiveLength: 0
        };
        if (sortKey !== undefined) {
            segment.sortKey = sortKey;
        }
        this.segments.push(segment);
    }
    return segment;
};
SegmentVector.prototype.get = function get() {
    return this.segments;
};
SegmentVector.prototype.destroy = function destroy() {
    for (var i = 0, list = this.segments; i < list.length; i += 1) {
        var segment = list[i];
        for (var k in segment.vaos) {
            segment.vaos[k].destroy();
        }
    }
};
SegmentVector.simpleSegment = function simpleSegment(vertexOffset, primitiveOffset, vertexLength, primitiveLength) {
    return new SegmentVector([{
            vertexOffset: vertexOffset,
            primitiveOffset: primitiveOffset,
            vertexLength: vertexLength,
            primitiveLength: primitiveLength,
            vaos: {},
            sortKey: 0
        }]);
};
SegmentVector.MAX_VERTEX_ARRAY_LENGTH = Math.pow(2, 16) - 1;
register('SegmentVector', SegmentVector);

function packUint8ToFloat(a, b) {
    a = clamp(Math.floor(a), 0, 255);
    b = clamp(Math.floor(b), 0, 255);
    return 256 * a + b;
}

var patternAttributes = createLayout([
    {
        name: 'a_pattern_from',
        components: 4,
        type: 'Uint16'
    },
    {
        name: 'a_pattern_to',
        components: 4,
        type: 'Uint16'
    },
    {
        name: 'a_pixel_ratio_from',
        components: 1,
        type: 'Uint16'
    },
    {
        name: 'a_pixel_ratio_to',
        components: 1,
        type: 'Uint16'
    }
]);

var murmurhash3_gc = createCommonjsModule(function (module) {
function murmurhash3_32_gc(key, seed) {
    var remainder, bytes, h1, h1b, c1, c2, k1, i;
    remainder = key.length & 3;
    bytes = key.length - remainder;
    h1 = seed;
    c1 = 3432918353;
    c2 = 461845907;
    i = 0;
    while (i < bytes) {
        k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
        ++i;
        k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
        k1 = k1 << 15 | k1 >>> 17;
        k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
        h1 ^= k1;
        h1 = h1 << 13 | h1 >>> 19;
        h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
        h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
    }
    k1 = 0;
    switch (remainder) {
    case 3:
        k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
    case 2:
        k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
    case 1:
        k1 ^= key.charCodeAt(i) & 255;
        k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
        k1 = k1 << 15 | k1 >>> 17;
        k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
        h1 ^= k1;
    }
    h1 ^= key.length;
    h1 ^= h1 >>> 16;
    h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
    h1 ^= h1 >>> 13;
    h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
    h1 ^= h1 >>> 16;
    return h1 >>> 0;
}
{
    module.exports = murmurhash3_32_gc;
}
});

var murmurhash2_gc = createCommonjsModule(function (module) {
function murmurhash2_32_gc(str, seed) {
    var l = str.length, h = seed ^ l, i = 0, k;
    while (l >= 4) {
        k = str.charCodeAt(i) & 255 | (str.charCodeAt(++i) & 255) << 8 | (str.charCodeAt(++i) & 255) << 16 | (str.charCodeAt(++i) & 255) << 24;
        k = (k & 65535) * 1540483477 + (((k >>> 16) * 1540483477 & 65535) << 16);
        k ^= k >>> 24;
        k = (k & 65535) * 1540483477 + (((k >>> 16) * 1540483477 & 65535) << 16);
        h = (h & 65535) * 1540483477 + (((h >>> 16) * 1540483477 & 65535) << 16) ^ k;
        l -= 4;
        ++i;
    }
    switch (l) {
    case 3:
        h ^= (str.charCodeAt(i + 2) & 255) << 16;
    case 2:
        h ^= (str.charCodeAt(i + 1) & 255) << 8;
    case 1:
        h ^= str.charCodeAt(i) & 255;
        h = (h & 65535) * 1540483477 + (((h >>> 16) * 1540483477 & 65535) << 16);
    }
    h ^= h >>> 13;
    h = (h & 65535) * 1540483477 + (((h >>> 16) * 1540483477 & 65535) << 16);
    h ^= h >>> 15;
    return h >>> 0;
}
{
    module.exports = murmurhash2_32_gc;
}
});

var murmurhashJs = murmurhash3_gc;
var murmur3_1 = murmurhash3_gc;
var murmur2_1 = murmurhash2_gc;
murmurhashJs.murmur3 = murmur3_1;
murmurhashJs.murmur2 = murmur2_1;

var FeaturePositionMap = function FeaturePositionMap() {
    this.ids = [];
    this.positions = [];
    this.indexed = false;
};
FeaturePositionMap.prototype.add = function add(id, index, start, end) {
    this.ids.push(getNumericId(id));
    this.positions.push(index, start, end);
};
FeaturePositionMap.prototype.getPositions = function getPositions(id) {
    var intId = getNumericId(id);
    var i = 0;
    var j = this.ids.length - 1;
    while (i < j) {
        var m = i + j >> 1;
        if (this.ids[m] >= intId) {
            j = m;
        } else {
            i = m + 1;
        }
    }
    var positions = [];
    while (this.ids[i] === intId) {
        var index = this.positions[3 * i];
        var start = this.positions[3 * i + 1];
        var end = this.positions[3 * i + 2];
        positions.push({
            index: index,
            start: start,
            end: end
        });
        i++;
    }
    return positions;
};
FeaturePositionMap.serialize = function serialize(map, transferables) {
    var ids = new Float64Array(map.ids);
    var positions = new Uint32Array(map.positions);
    sort(ids, positions, 0, ids.length - 1);
    if (transferables) {
        transferables.push(ids.buffer, positions.buffer);
    }
    return {
        ids: ids,
        positions: positions
    };
};
FeaturePositionMap.deserialize = function deserialize(obj) {
    var map = new FeaturePositionMap();
    map.ids = obj.ids;
    map.positions = obj.positions;
    map.indexed = true;
    return map;
};
var MAX_SAFE_INTEGER$1 = Math.pow(2, 53) - 1;
function getNumericId(value) {
    var numValue = +value;
    if (!isNaN(numValue) && numValue <= MAX_SAFE_INTEGER$1) {
        return numValue;
    }
    return murmurhashJs(String(value));
}
function sort(ids, positions, left, right) {
    while (left < right) {
        var pivot = ids[left + right >> 1];
        var i = left - 1;
        var j = right + 1;
        while (true) {
            do {
                i++;
            } while (ids[i] < pivot);
            do {
                j--;
            } while (ids[j] > pivot);
            if (i >= j) {
                break;
            }
            swap(ids, i, j);
            swap(positions, 3 * i, 3 * j);
            swap(positions, 3 * i + 1, 3 * j + 1);
            swap(positions, 3 * i + 2, 3 * j + 2);
        }
        if (j - left < right - j) {
            sort(ids, positions, left, j);
            left = j + 1;
        } else {
            sort(ids, positions, j + 1, right);
            right = j;
        }
    }
}
function swap(arr, i, j) {
    var tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
register('FeaturePositionMap', FeaturePositionMap);

var Uniform = function Uniform(context, location) {
    this.gl = context.gl;
    this.location = location;
};
var Uniform1i = function (Uniform) {
    function Uniform1i(context, location) {
        Uniform.call(this, context, location);
        this.current = 0;
    }
    if (Uniform)
        Uniform1i.__proto__ = Uniform;
    Uniform1i.prototype = Object.create(Uniform && Uniform.prototype);
    Uniform1i.prototype.constructor = Uniform1i;
    Uniform1i.prototype.set = function set(v) {
        if (this.current !== v) {
            this.current = v;
            this.gl.uniform1i(this.location, v);
        }
    };
    return Uniform1i;
}(Uniform);
var Uniform1f = function (Uniform) {
    function Uniform1f(context, location) {
        Uniform.call(this, context, location);
        this.current = 0;
    }
    if (Uniform)
        Uniform1f.__proto__ = Uniform;
    Uniform1f.prototype = Object.create(Uniform && Uniform.prototype);
    Uniform1f.prototype.constructor = Uniform1f;
    Uniform1f.prototype.set = function set(v) {
        if (this.current !== v) {
            this.current = v;
            this.gl.uniform1f(this.location, v);
        }
    };
    return Uniform1f;
}(Uniform);
var Uniform2f = function (Uniform) {
    function Uniform2f(context, location) {
        Uniform.call(this, context, location);
        this.current = [
            0,
            0
        ];
    }
    if (Uniform)
        Uniform2f.__proto__ = Uniform;
    Uniform2f.prototype = Object.create(Uniform && Uniform.prototype);
    Uniform2f.prototype.constructor = Uniform2f;
    Uniform2f.prototype.set = function set(v) {
        if (v[0] !== this.current[0] || v[1] !== this.current[1]) {
            this.current = v;
            this.gl.uniform2f(this.location, v[0], v[1]);
        }
    };
    return Uniform2f;
}(Uniform);
var Uniform3f = function (Uniform) {
    function Uniform3f(context, location) {
        Uniform.call(this, context, location);
        this.current = [
            0,
            0,
            0
        ];
    }
    if (Uniform)
        Uniform3f.__proto__ = Uniform;
    Uniform3f.prototype = Object.create(Uniform && Uniform.prototype);
    Uniform3f.prototype.constructor = Uniform3f;
    Uniform3f.prototype.set = function set(v) {
        if (v[0] !== this.current[0] || v[1] !== this.current[1] || v[2] !== this.current[2]) {
            this.current = v;
            this.gl.uniform3f(this.location, v[0], v[1], v[2]);
        }
    };
    return Uniform3f;
}(Uniform);
var Uniform4f = function (Uniform) {
    function Uniform4f(context, location) {
        Uniform.call(this, context, location);
        this.current = [
            0,
            0,
            0,
            0
        ];
    }
    if (Uniform)
        Uniform4f.__proto__ = Uniform;
    Uniform4f.prototype = Object.create(Uniform && Uniform.prototype);
    Uniform4f.prototype.constructor = Uniform4f;
    Uniform4f.prototype.set = function set(v) {
        if (v[0] !== this.current[0] || v[1] !== this.current[1] || v[2] !== this.current[2] || v[3] !== this.current[3]) {
            this.current = v;
            this.gl.uniform4f(this.location, v[0], v[1], v[2], v[3]);
        }
    };
    return Uniform4f;
}(Uniform);
var UniformColor = function (Uniform) {
    function UniformColor(context, location) {
        Uniform.call(this, context, location);
        this.current = Color.transparent;
    }
    if (Uniform)
        UniformColor.__proto__ = Uniform;
    UniformColor.prototype = Object.create(Uniform && Uniform.prototype);
    UniformColor.prototype.constructor = UniformColor;
    UniformColor.prototype.set = function set(v) {
        if (v.r !== this.current.r || v.g !== this.current.g || v.b !== this.current.b || v.a !== this.current.a) {
            this.current = v;
            this.gl.uniform4f(this.location, v.r, v.g, v.b, v.a);
        }
    };
    return UniformColor;
}(Uniform);
var emptyMat4 = new Float32Array(16);
var UniformMatrix4f = function (Uniform) {
    function UniformMatrix4f(context, location) {
        Uniform.call(this, context, location);
        this.current = emptyMat4;
    }
    if (Uniform)
        UniformMatrix4f.__proto__ = Uniform;
    UniformMatrix4f.prototype = Object.create(Uniform && Uniform.prototype);
    UniformMatrix4f.prototype.constructor = UniformMatrix4f;
    UniformMatrix4f.prototype.set = function set(v) {
        if (v[12] !== this.current[12] || v[0] !== this.current[0]) {
            this.current = v;
            this.gl.uniformMatrix4fv(this.location, false, v);
            return;
        }
        for (var i = 1; i < 16; i++) {
            if (v[i] !== this.current[i]) {
                this.current = v;
                this.gl.uniformMatrix4fv(this.location, false, v);
                break;
            }
        }
    };
    return UniformMatrix4f;
}(Uniform);

function packColor(color) {
    return [
        packUint8ToFloat(255 * color.r, 255 * color.g),
        packUint8ToFloat(255 * color.b, 255 * color.a)
    ];
}
var ConstantBinder = function ConstantBinder(value, names, type) {
    this.value = value;
    this.uniformNames = names.map(function (name) {
        return 'u_' + name;
    });
    this.type = type;
};
ConstantBinder.prototype.setUniform = function setUniform(uniform, globals, currentValue) {
    uniform.set(currentValue.constantOr(this.value));
};
ConstantBinder.prototype.getBinding = function getBinding(context, location, _) {
    return this.type === 'color' ? new UniformColor(context, location) : new Uniform1f(context, location);
};
var CrossFadedConstantBinder = function CrossFadedConstantBinder(value, names) {
    this.uniformNames = names.map(function (name) {
        return 'u_' + name;
    });
    this.patternFrom = null;
    this.patternTo = null;
    this.pixelRatioFrom = 1;
    this.pixelRatioTo = 1;
};
CrossFadedConstantBinder.prototype.setConstantPatternPositions = function setConstantPatternPositions(posTo, posFrom) {
    this.pixelRatioFrom = posFrom.pixelRatio;
    this.pixelRatioTo = posTo.pixelRatio;
    this.patternFrom = posFrom.tlbr;
    this.patternTo = posTo.tlbr;
};
CrossFadedConstantBinder.prototype.setUniform = function setUniform(uniform, globals, currentValue, uniformName) {
    var pos = uniformName === 'u_pattern_to' ? this.patternTo : uniformName === 'u_pattern_from' ? this.patternFrom : uniformName === 'u_pixel_ratio_to' ? this.pixelRatioTo : uniformName === 'u_pixel_ratio_from' ? this.pixelRatioFrom : null;
    if (pos) {
        uniform.set(pos);
    }
};
CrossFadedConstantBinder.prototype.getBinding = function getBinding(context, location, name) {
    return name.substr(0, 9) === 'u_pattern' ? new Uniform4f(context, location) : new Uniform1f(context, location);
};
var SourceExpressionBinder = function SourceExpressionBinder(expression, names, type, PaintVertexArray) {
    this.expression = expression;
    this.type = type;
    this.maxValue = 0;
    this.paintVertexAttributes = names.map(function (name) {
        return {
            name: 'a_' + name,
            type: 'Float32',
            components: type === 'color' ? 2 : 1,
            offset: 0
        };
    });
    this.paintVertexArray = new PaintVertexArray();
};
SourceExpressionBinder.prototype.populatePaintArray = function populatePaintArray(newLength, feature, imagePositions, canonical, formattedSection) {
    var start = this.paintVertexArray.length;
    var value = this.expression.evaluate(new EvaluationParameters(0), feature, {}, canonical, [], formattedSection);
    this.paintVertexArray.resize(newLength);
    this._setPaintValue(start, newLength, value);
};
SourceExpressionBinder.prototype.updatePaintArray = function updatePaintArray(start, end, feature, featureState) {
    var value = this.expression.evaluate({ zoom: 0 }, feature, featureState);
    this._setPaintValue(start, end, value);
};
SourceExpressionBinder.prototype._setPaintValue = function _setPaintValue(start, end, value) {
    if (this.type === 'color') {
        var color = packColor(value);
        for (var i = start; i < end; i++) {
            this.paintVertexArray.emplace(i, color[0], color[1]);
        }
    } else {
        for (var i$1 = start; i$1 < end; i$1++) {
            this.paintVertexArray.emplace(i$1, value);
        }
        this.maxValue = Math.max(this.maxValue, Math.abs(value));
    }
};
SourceExpressionBinder.prototype.upload = function upload(context) {
    if (this.paintVertexArray && this.paintVertexArray.arrayBuffer) {
        if (this.paintVertexBuffer && this.paintVertexBuffer.buffer) {
            this.paintVertexBuffer.updateData(this.paintVertexArray);
        } else {
            this.paintVertexBuffer = context.createVertexBuffer(this.paintVertexArray, this.paintVertexAttributes, this.expression.isStateDependent);
        }
    }
};
SourceExpressionBinder.prototype.destroy = function destroy() {
    if (this.paintVertexBuffer) {
        this.paintVertexBuffer.destroy();
    }
};
var CompositeExpressionBinder = function CompositeExpressionBinder(expression, names, type, useIntegerZoom, zoom, PaintVertexArray) {
    this.expression = expression;
    this.uniformNames = names.map(function (name) {
        return 'u_' + name + '_t';
    });
    this.type = type;
    this.useIntegerZoom = useIntegerZoom;
    this.zoom = zoom;
    this.maxValue = 0;
    this.paintVertexAttributes = names.map(function (name) {
        return {
            name: 'a_' + name,
            type: 'Float32',
            components: type === 'color' ? 4 : 2,
            offset: 0
        };
    });
    this.paintVertexArray = new PaintVertexArray();
};
CompositeExpressionBinder.prototype.populatePaintArray = function populatePaintArray(newLength, feature, imagePositions, canonical, formattedSection) {
    var min = this.expression.evaluate(new EvaluationParameters(this.zoom), feature, {}, canonical, [], formattedSection);
    var max = this.expression.evaluate(new EvaluationParameters(this.zoom + 1), feature, {}, canonical, [], formattedSection);
    var start = this.paintVertexArray.length;
    this.paintVertexArray.resize(newLength);
    this._setPaintValue(start, newLength, min, max);
};
CompositeExpressionBinder.prototype.updatePaintArray = function updatePaintArray(start, end, feature, featureState) {
    var min = this.expression.evaluate({ zoom: this.zoom }, feature, featureState);
    var max = this.expression.evaluate({ zoom: this.zoom + 1 }, feature, featureState);
    this._setPaintValue(start, end, min, max);
};
CompositeExpressionBinder.prototype._setPaintValue = function _setPaintValue(start, end, min, max) {
    if (this.type === 'color') {
        var minColor = packColor(min);
        var maxColor = packColor(max);
        for (var i = start; i < end; i++) {
            this.paintVertexArray.emplace(i, minColor[0], minColor[1], maxColor[0], maxColor[1]);
        }
    } else {
        for (var i$1 = start; i$1 < end; i$1++) {
            this.paintVertexArray.emplace(i$1, min, max);
        }
        this.maxValue = Math.max(this.maxValue, Math.abs(min), Math.abs(max));
    }
};
CompositeExpressionBinder.prototype.upload = function upload(context) {
    if (this.paintVertexArray && this.paintVertexArray.arrayBuffer) {
        if (this.paintVertexBuffer && this.paintVertexBuffer.buffer) {
            this.paintVertexBuffer.updateData(this.paintVertexArray);
        } else {
            this.paintVertexBuffer = context.createVertexBuffer(this.paintVertexArray, this.paintVertexAttributes, this.expression.isStateDependent);
        }
    }
};
CompositeExpressionBinder.prototype.destroy = function destroy() {
    if (this.paintVertexBuffer) {
        this.paintVertexBuffer.destroy();
    }
};
CompositeExpressionBinder.prototype.setUniform = function setUniform(uniform, globals) {
    var currentZoom = this.useIntegerZoom ? Math.floor(globals.zoom) : globals.zoom;
    var factor = clamp(this.expression.interpolationFactor(currentZoom, this.zoom, this.zoom + 1), 0, 1);
    uniform.set(factor);
};
CompositeExpressionBinder.prototype.getBinding = function getBinding(context, location, _) {
    return new Uniform1f(context, location);
};
var CrossFadedCompositeBinder = function CrossFadedCompositeBinder(expression, type, useIntegerZoom, zoom, PaintVertexArray, layerId) {
    this.expression = expression;
    this.type = type;
    this.useIntegerZoom = useIntegerZoom;
    this.zoom = zoom;
    this.layerId = layerId;
    this.zoomInPaintVertexArray = new PaintVertexArray();
    this.zoomOutPaintVertexArray = new PaintVertexArray();
};
CrossFadedCompositeBinder.prototype.populatePaintArray = function populatePaintArray(length, feature, imagePositions) {
    var start = this.zoomInPaintVertexArray.length;
    this.zoomInPaintVertexArray.resize(length);
    this.zoomOutPaintVertexArray.resize(length);
    this._setPaintValues(start, length, feature.patterns && feature.patterns[this.layerId], imagePositions);
};
CrossFadedCompositeBinder.prototype.updatePaintArray = function updatePaintArray(start, end, feature, featureState, imagePositions) {
    this._setPaintValues(start, end, feature.patterns && feature.patterns[this.layerId], imagePositions);
};
CrossFadedCompositeBinder.prototype._setPaintValues = function _setPaintValues(start, end, patterns, positions) {
    if (!positions || !patterns) {
        return;
    }
    var min = patterns.min;
    var mid = patterns.mid;
    var max = patterns.max;
    var imageMin = positions[min];
    var imageMid = positions[mid];
    var imageMax = positions[max];
    if (!imageMin || !imageMid || !imageMax) {
        return;
    }
    for (var i = start; i < end; i++) {
        this.zoomInPaintVertexArray.emplace(i, imageMid.tl[0], imageMid.tl[1], imageMid.br[0], imageMid.br[1], imageMin.tl[0], imageMin.tl[1], imageMin.br[0], imageMin.br[1], imageMid.pixelRatio, imageMin.pixelRatio);
        this.zoomOutPaintVertexArray.emplace(i, imageMid.tl[0], imageMid.tl[1], imageMid.br[0], imageMid.br[1], imageMax.tl[0], imageMax.tl[1], imageMax.br[0], imageMax.br[1], imageMid.pixelRatio, imageMax.pixelRatio);
    }
};
CrossFadedCompositeBinder.prototype.upload = function upload(context) {
    if (this.zoomInPaintVertexArray && this.zoomInPaintVertexArray.arrayBuffer && this.zoomOutPaintVertexArray && this.zoomOutPaintVertexArray.arrayBuffer) {
        this.zoomInPaintVertexBuffer = context.createVertexBuffer(this.zoomInPaintVertexArray, patternAttributes.members, this.expression.isStateDependent);
        this.zoomOutPaintVertexBuffer = context.createVertexBuffer(this.zoomOutPaintVertexArray, patternAttributes.members, this.expression.isStateDependent);
    }
};
CrossFadedCompositeBinder.prototype.destroy = function destroy() {
    if (this.zoomOutPaintVertexBuffer) {
        this.zoomOutPaintVertexBuffer.destroy();
    }
    if (this.zoomInPaintVertexBuffer) {
        this.zoomInPaintVertexBuffer.destroy();
    }
};
var ProgramConfiguration = function ProgramConfiguration(layer, zoom, filterProperties) {
    this.binders = {};
    this._buffers = [];
    var keys = [];
    for (var property in layer.paint._values) {
        if (!filterProperties(property)) {
            continue;
        }
        var value = layer.paint.get(property);
        if (!(value instanceof PossiblyEvaluatedPropertyValue) || !supportsPropertyExpression(value.property.specification)) {
            continue;
        }
        var names = paintAttributeNames(property, layer.type);
        var expression = value.value;
        var type = value.property.specification.type;
        var useIntegerZoom = value.property.useIntegerZoom;
        var propType = value.property.specification['property-type'];
        var isCrossFaded = propType === 'cross-faded' || propType === 'cross-faded-data-driven';
        if (expression.kind === 'constant') {
            this.binders[property] = isCrossFaded ? new CrossFadedConstantBinder(expression.value, names) : new ConstantBinder(expression.value, names, type);
            keys.push('/u_' + property);
        } else if (expression.kind === 'source' || isCrossFaded) {
            var StructArrayLayout = layoutType(property, type, 'source');
            this.binders[property] = isCrossFaded ? new CrossFadedCompositeBinder(expression, type, useIntegerZoom, zoom, StructArrayLayout, layer.id) : new SourceExpressionBinder(expression, names, type, StructArrayLayout);
            keys.push('/a_' + property);
        } else {
            var StructArrayLayout$1 = layoutType(property, type, 'composite');
            this.binders[property] = new CompositeExpressionBinder(expression, names, type, useIntegerZoom, zoom, StructArrayLayout$1);
            keys.push('/z_' + property);
        }
    }
    this.cacheKey = keys.sort().join('');
};
ProgramConfiguration.prototype.getMaxValue = function getMaxValue(property) {
    var binder = this.binders[property];
    return binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder ? binder.maxValue : 0;
};
ProgramConfiguration.prototype.populatePaintArrays = function populatePaintArrays(newLength, feature, imagePositions, canonical, formattedSection) {
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder || binder instanceof CrossFadedCompositeBinder) {
            binder.populatePaintArray(newLength, feature, imagePositions, canonical, formattedSection);
        }
    }
};
ProgramConfiguration.prototype.setConstantPatternPositions = function setConstantPatternPositions(posTo, posFrom) {
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof CrossFadedConstantBinder) {
            binder.setConstantPatternPositions(posTo, posFrom);
        }
    }
};
ProgramConfiguration.prototype.updatePaintArrays = function updatePaintArrays(featureStates, featureMap, vtLayer, layer, imagePositions) {
    var dirty = false;
    for (var id in featureStates) {
        var positions = featureMap.getPositions(id);
        for (var i = 0, list = positions; i < list.length; i += 1) {
            var pos = list[i];
            var feature = vtLayer.feature(pos.index);
            for (var property in this.binders) {
                var binder = this.binders[property];
                if ((binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder || binder instanceof CrossFadedCompositeBinder) && binder.expression.isStateDependent === true) {
                    var value = layer.paint.get(property);
                    binder.expression = value.value;
                    binder.updatePaintArray(pos.start, pos.end, feature, featureStates[id], imagePositions);
                    dirty = true;
                }
            }
        }
    }
    return dirty;
};
ProgramConfiguration.prototype.defines = function defines() {
    var result = [];
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof ConstantBinder || binder instanceof CrossFadedConstantBinder) {
            result.push.apply(result, binder.uniformNames.map(function (name) {
                return '#define HAS_UNIFORM_' + name;
            }));
        }
    }
    return result;
};
ProgramConfiguration.prototype.getBinderAttributes = function getBinderAttributes() {
    var result = [];
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder) {
            for (var i = 0; i < binder.paintVertexAttributes.length; i++) {
                result.push(binder.paintVertexAttributes[i].name);
            }
        } else if (binder instanceof CrossFadedCompositeBinder) {
            for (var i$1 = 0; i$1 < patternAttributes.members.length; i$1++) {
                result.push(patternAttributes.members[i$1].name);
            }
        }
    }
    return result;
};
ProgramConfiguration.prototype.getBinderUniforms = function getBinderUniforms() {
    var uniforms = [];
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof ConstantBinder || binder instanceof CrossFadedConstantBinder || binder instanceof CompositeExpressionBinder) {
            for (var i = 0, list = binder.uniformNames; i < list.length; i += 1) {
                var uniformName = list[i];
                uniforms.push(uniformName);
            }
        }
    }
    return uniforms;
};
ProgramConfiguration.prototype.getPaintVertexBuffers = function getPaintVertexBuffers() {
    return this._buffers;
};
ProgramConfiguration.prototype.getUniforms = function getUniforms(context, locations) {
    var uniforms = [];
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof ConstantBinder || binder instanceof CrossFadedConstantBinder || binder instanceof CompositeExpressionBinder) {
            for (var i = 0, list = binder.uniformNames; i < list.length; i += 1) {
                var name = list[i];
                if (locations[name]) {
                    var binding = binder.getBinding(context, locations[name], name);
                    uniforms.push({
                        name: name,
                        property: property,
                        binding: binding
                    });
                }
            }
        }
    }
    return uniforms;
};
ProgramConfiguration.prototype.setUniforms = function setUniforms(context, binderUniforms, properties, globals) {
    for (var i = 0, list = binderUniforms; i < list.length; i += 1) {
        var ref = list[i];
        var name = ref.name;
        var property = ref.property;
        var binding = ref.binding;
        this.binders[property].setUniform(binding, globals, properties.get(property), name);
    }
};
ProgramConfiguration.prototype.updatePaintBuffers = function updatePaintBuffers(crossfade) {
    this._buffers = [];
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (crossfade && binder instanceof CrossFadedCompositeBinder) {
            var patternVertexBuffer = crossfade.fromScale === 2 ? binder.zoomInPaintVertexBuffer : binder.zoomOutPaintVertexBuffer;
            if (patternVertexBuffer) {
                this._buffers.push(patternVertexBuffer);
            }
        } else if ((binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder) && binder.paintVertexBuffer) {
            this._buffers.push(binder.paintVertexBuffer);
        }
    }
};
ProgramConfiguration.prototype.upload = function upload(context) {
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder || binder instanceof CrossFadedCompositeBinder) {
            binder.upload(context);
        }
    }
    this.updatePaintBuffers();
};
ProgramConfiguration.prototype.destroy = function destroy() {
    for (var property in this.binders) {
        var binder = this.binders[property];
        if (binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder || binder instanceof CrossFadedCompositeBinder) {
            binder.destroy();
        }
    }
};
var ProgramConfigurationSet = function ProgramConfigurationSet(layers, zoom, filterProperties) {
    if (filterProperties === void 0)
        filterProperties = function () {
            return true;
        };
    this.programConfigurations = {};
    for (var i = 0, list = layers; i < list.length; i += 1) {
        var layer = list[i];
        this.programConfigurations[layer.id] = new ProgramConfiguration(layer, zoom, filterProperties);
    }
    this.needsUpload = false;
    this._featureMap = new FeaturePositionMap();
    this._bufferOffset = 0;
};
ProgramConfigurationSet.prototype.populatePaintArrays = function populatePaintArrays(length, feature, index, imagePositions, canonical, formattedSection) {
    for (var key in this.programConfigurations) {
        this.programConfigurations[key].populatePaintArrays(length, feature, imagePositions, canonical, formattedSection);
    }
    if (feature.id !== undefined) {
        this._featureMap.add(feature.id, index, this._bufferOffset, length);
    }
    this._bufferOffset = length;
    this.needsUpload = true;
};
ProgramConfigurationSet.prototype.updatePaintArrays = function updatePaintArrays(featureStates, vtLayer, layers, imagePositions) {
    for (var i = 0, list = layers; i < list.length; i += 1) {
        var layer = list[i];
        this.needsUpload = this.programConfigurations[layer.id].updatePaintArrays(featureStates, this._featureMap, vtLayer, layer, imagePositions) || this.needsUpload;
    }
};
ProgramConfigurationSet.prototype.get = function get(layerId) {
    return this.programConfigurations[layerId];
};
ProgramConfigurationSet.prototype.upload = function upload(context) {
    if (!this.needsUpload) {
        return;
    }
    for (var layerId in this.programConfigurations) {
        this.programConfigurations[layerId].upload(context);
    }
    this.needsUpload = false;
};
ProgramConfigurationSet.prototype.destroy = function destroy() {
    for (var layerId in this.programConfigurations) {
        this.programConfigurations[layerId].destroy();
    }
};
function paintAttributeNames(property, type) {
    var attributeNameExceptions = {
        'text-opacity': ['opacity'],
        'icon-opacity': ['opacity'],
        'text-color': ['fill_color'],
        'icon-color': ['fill_color'],
        'text-halo-color': ['halo_color'],
        'icon-halo-color': ['halo_color'],
        'text-halo-blur': ['halo_blur'],
        'icon-halo-blur': ['halo_blur'],
        'text-halo-width': ['halo_width'],
        'icon-halo-width': ['halo_width'],
        'line-gap-width': ['gapwidth'],
        'line-pattern': [
            'pattern_to',
            'pattern_from',
            'pixel_ratio_to',
            'pixel_ratio_from'
        ],
        'fill-pattern': [
            'pattern_to',
            'pattern_from',
            'pixel_ratio_to',
            'pixel_ratio_from'
        ],
        'fill-extrusion-pattern': [
            'pattern_to',
            'pattern_from',
            'pixel_ratio_to',
            'pixel_ratio_from'
        ]
    };
    return attributeNameExceptions[property] || [property.replace(type + '-', '').replace(/-/g, '_')];
}
function getLayoutException(property) {
    var propertyExceptions = {
        'line-pattern': {
            'source': StructArrayLayout10ui20,
            'composite': StructArrayLayout10ui20
        },
        'fill-pattern': {
            'source': StructArrayLayout10ui20,
            'composite': StructArrayLayout10ui20
        },
        'fill-extrusion-pattern': {
            'source': StructArrayLayout10ui20,
            'composite': StructArrayLayout10ui20
        }
    };
    return propertyExceptions[property];
}
function layoutType(property, type, binderType) {
    var defaultLayouts = {
        'color': {
            'source': StructArrayLayout2f8,
            'composite': StructArrayLayout4f16
        },
        'number': {
            'source': StructArrayLayout1f4,
            'composite': StructArrayLayout2f8
        }
    };
    var layoutException = getLayoutException(property);
    return layoutException && layoutException[binderType] || defaultLayouts[type][binderType];
}
register('ConstantBinder', ConstantBinder);
register('CrossFadedConstantBinder', CrossFadedConstantBinder);
register('SourceExpressionBinder', SourceExpressionBinder);
register('CrossFadedCompositeBinder', CrossFadedCompositeBinder);
register('CompositeExpressionBinder', CompositeExpressionBinder);
register('ProgramConfiguration', ProgramConfiguration, { omit: ['_buffers'] });
register('ProgramConfigurationSet', ProgramConfigurationSet);

var EXTENT$1 = 8192;

var BITS = 15;
var MAX = Math.pow(2, BITS - 1) - 1;
var MIN = -MAX - 1;
function loadGeometry(feature) {
    var scale = EXTENT$1 / feature.extent;
    var geometry = feature.loadGeometry();
    for (var r = 0; r < geometry.length; r++) {
        var ring = geometry[r];
        for (var p = 0; p < ring.length; p++) {
            var point = ring[p];
            var x = Math.round(point.x * scale);
            var y = Math.round(point.y * scale);
            point.x = clamp(x, MIN, MAX);
            point.y = clamp(y, MIN, MAX);
            if (x < point.x || x > point.x + 1 || y < point.y || y > point.y + 1) {
                warnOnce('Geometry exceeds allowed extent, reduce your vector tile buffer size');
            }
        }
    }
    return geometry;
}

function toEvaluationFeature(feature, needGeometry) {
    return {
        type: feature.type,
        id: feature.id,
        properties: feature.properties,
        geometry: needGeometry ? loadGeometry(feature) : []
    };
}

function addCircleVertex(layoutVertexArray, x, y, extrudeX, extrudeY) {
    layoutVertexArray.emplaceBack(x * 2 + (extrudeX + 1) / 2, y * 2 + (extrudeY + 1) / 2);
}
var CircleBucket = function CircleBucket(options) {
    this.zoom = options.zoom;
    this.overscaling = options.overscaling;
    this.layers = options.layers;
    this.layerIds = this.layers.map(function (layer) {
        return layer.id;
    });
    this.index = options.index;
    this.hasPattern = false;
    this.layoutVertexArray = new StructArrayLayout2i4();
    this.indexArray = new StructArrayLayout3ui6();
    this.segments = new SegmentVector();
    this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
    this.stateDependentLayerIds = this.layers.filter(function (l) {
        return l.isStateDependent();
    }).map(function (l) {
        return l.id;
    });
};
CircleBucket.prototype.populate = function populate(features, options, canonical) {
    var styleLayer = this.layers[0];
    var bucketFeatures = [];
    var circleSortKey = null;
    if (styleLayer.type === 'circle') {
        circleSortKey = styleLayer.layout.get('circle-sort-key');
    }
    for (var i = 0, list = features; i < list.length; i += 1) {
        var ref = list[i];
        var feature = ref.feature;
        var id = ref.id;
        var index = ref.index;
        var sourceLayerIndex = ref.sourceLayerIndex;
        var needGeometry = this.layers[0]._featureFilter.needGeometry;
        var evaluationFeature = toEvaluationFeature(feature, needGeometry);
        if (!this.layers[0]._featureFilter.filter(new EvaluationParameters(this.zoom), evaluationFeature, canonical)) {
            continue;
        }
        var sortKey = circleSortKey ? circleSortKey.evaluate(evaluationFeature, {}, canonical) : undefined;
        var bucketFeature = {
            id: id,
            properties: feature.properties,
            type: feature.type,
            sourceLayerIndex: sourceLayerIndex,
            index: index,
            geometry: needGeometry ? evaluationFeature.geometry : loadGeometry(feature),
            patterns: {},
            sortKey: sortKey
        };
        bucketFeatures.push(bucketFeature);
    }
    if (circleSortKey) {
        bucketFeatures.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
    for (var i$1 = 0, list$1 = bucketFeatures; i$1 < list$1.length; i$1 += 1) {
        var bucketFeature$1 = list$1[i$1];
        var ref$1 = bucketFeature$1;
        var geometry = ref$1.geometry;
        var index$1 = ref$1.index;
        var sourceLayerIndex$1 = ref$1.sourceLayerIndex;
        var feature$1 = features[index$1].feature;
        this.addFeature(bucketFeature$1, geometry, index$1, canonical);
        options.featureIndex.insert(feature$1, geometry, index$1, sourceLayerIndex$1, this.index);
    }
};
CircleBucket.prototype.update = function update(states, vtLayer, imagePositions) {
    if (!this.stateDependentLayers.length) {
        return;
    }
    this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
};
CircleBucket.prototype.isEmpty = function isEmpty() {
    return this.layoutVertexArray.length === 0;
};
CircleBucket.prototype.uploadPending = function uploadPending() {
    return !this.uploaded || this.programConfigurations.needsUpload;
};
CircleBucket.prototype.upload = function upload(context) {
    if (!this.uploaded) {
        this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members);
        this.indexBuffer = context.createIndexBuffer(this.indexArray);
    }
    this.programConfigurations.upload(context);
    this.uploaded = true;
};
CircleBucket.prototype.destroy = function destroy() {
    if (!this.layoutVertexBuffer) {
        return;
    }
    this.layoutVertexBuffer.destroy();
    this.indexBuffer.destroy();
    this.programConfigurations.destroy();
    this.segments.destroy();
};
CircleBucket.prototype.addFeature = function addFeature(feature, geometry, index, canonical) {
    for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
        var ring = list$1[i$1];
        for (var i = 0, list = ring; i < list.length; i += 1) {
            var point = list[i];
            var x = point.x;
            var y = point.y;
            if (x < 0 || x >= EXTENT$1 || y < 0 || y >= EXTENT$1) {
                continue;
            }
            var segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray, feature.sortKey);
            var index$1 = segment.vertexLength;
            addCircleVertex(this.layoutVertexArray, x, y, -1, -1);
            addCircleVertex(this.layoutVertexArray, x, y, 1, -1);
            addCircleVertex(this.layoutVertexArray, x, y, 1, 1);
            addCircleVertex(this.layoutVertexArray, x, y, -1, 1);
            this.indexArray.emplaceBack(index$1, index$1 + 1, index$1 + 2);
            this.indexArray.emplaceBack(index$1, index$1 + 3, index$1 + 2);
            segment.vertexLength += 4;
            segment.primitiveLength += 2;
        }
    }
    this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, {}, canonical);
};
register('CircleBucket', CircleBucket, { omit: ['layers'] });

function polygonIntersectsPolygon(polygonA, polygonB) {
    for (var i = 0; i < polygonA.length; i++) {
        if (polygonContainsPoint(polygonB, polygonA[i])) {
            return true;
        }
    }
    for (var i$1 = 0; i$1 < polygonB.length; i$1++) {
        if (polygonContainsPoint(polygonA, polygonB[i$1])) {
            return true;
        }
    }
    if (lineIntersectsLine(polygonA, polygonB)) {
        return true;
    }
    return false;
}
function polygonIntersectsBufferedPoint(polygon, point, radius) {
    if (polygonContainsPoint(polygon, point)) {
        return true;
    }
    if (pointIntersectsBufferedLine(point, polygon, radius)) {
        return true;
    }
    return false;
}
function polygonIntersectsMultiPolygon(polygon, multiPolygon) {
    if (polygon.length === 1) {
        return multiPolygonContainsPoint(multiPolygon, polygon[0]);
    }
    for (var m = 0; m < multiPolygon.length; m++) {
        var ring = multiPolygon[m];
        for (var n = 0; n < ring.length; n++) {
            if (polygonContainsPoint(polygon, ring[n])) {
                return true;
            }
        }
    }
    for (var i = 0; i < polygon.length; i++) {
        if (multiPolygonContainsPoint(multiPolygon, polygon[i])) {
            return true;
        }
    }
    for (var k = 0; k < multiPolygon.length; k++) {
        if (lineIntersectsLine(polygon, multiPolygon[k])) {
            return true;
        }
    }
    return false;
}
function polygonIntersectsBufferedMultiLine(polygon, multiLine, radius) {
    for (var i = 0; i < multiLine.length; i++) {
        var line = multiLine[i];
        if (polygon.length >= 3) {
            for (var k = 0; k < line.length; k++) {
                if (polygonContainsPoint(polygon, line[k])) {
                    return true;
                }
            }
        }
        if (lineIntersectsBufferedLine(polygon, line, radius)) {
            return true;
        }
    }
    return false;
}
function lineIntersectsBufferedLine(lineA, lineB, radius) {
    if (lineA.length > 1) {
        if (lineIntersectsLine(lineA, lineB)) {
            return true;
        }
        for (var j = 0; j < lineB.length; j++) {
            if (pointIntersectsBufferedLine(lineB[j], lineA, radius)) {
                return true;
            }
        }
    }
    for (var k = 0; k < lineA.length; k++) {
        if (pointIntersectsBufferedLine(lineA[k], lineB, radius)) {
            return true;
        }
    }
    return false;
}
function lineIntersectsLine(lineA, lineB) {
    if (lineA.length === 0 || lineB.length === 0) {
        return false;
    }
    for (var i = 0; i < lineA.length - 1; i++) {
        var a0 = lineA[i];
        var a1 = lineA[i + 1];
        for (var j = 0; j < lineB.length - 1; j++) {
            var b0 = lineB[j];
            var b1 = lineB[j + 1];
            if (lineSegmentIntersectsLineSegment(a0, a1, b0, b1)) {
                return true;
            }
        }
    }
    return false;
}
function lineSegmentIntersectsLineSegment(a0, a1, b0, b1) {
    return isCounterClockwise(a0, b0, b1) !== isCounterClockwise(a1, b0, b1) && isCounterClockwise(a0, a1, b0) !== isCounterClockwise(a0, a1, b1);
}
function pointIntersectsBufferedLine(p, line, radius) {
    var radiusSquared = radius * radius;
    if (line.length === 1) {
        return p.distSqr(line[0]) < radiusSquared;
    }
    for (var i = 1; i < line.length; i++) {
        var v = line[i - 1], w = line[i];
        if (distToSegmentSquared(p, v, w) < radiusSquared) {
            return true;
        }
    }
    return false;
}
function distToSegmentSquared(p, v, w) {
    var l2 = v.distSqr(w);
    if (l2 === 0) {
        return p.distSqr(v);
    }
    var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
    if (t < 0) {
        return p.distSqr(v);
    }
    if (t > 1) {
        return p.distSqr(w);
    }
    return p.distSqr(w.sub(v)._mult(t)._add(v));
}
function multiPolygonContainsPoint(rings, p) {
    var c = false, ring, p1, p2;
    for (var k = 0; k < rings.length; k++) {
        ring = rings[k];
        for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
            p1 = ring[i];
            p2 = ring[j];
            if (p1.y > p.y !== p2.y > p.y && p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x) {
                c = !c;
            }
        }
    }
    return c;
}
function polygonContainsPoint(ring, p) {
    var c = false;
    for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
        var p1 = ring[i];
        var p2 = ring[j];
        if (p1.y > p.y !== p2.y > p.y && p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x) {
            c = !c;
        }
    }
    return c;
}
function polygonIntersectsBox(ring, boxX1, boxY1, boxX2, boxY2) {
    for (var i$1 = 0, list = ring; i$1 < list.length; i$1 += 1) {
        var p = list[i$1];
        if (boxX1 <= p.x && boxY1 <= p.y && boxX2 >= p.x && boxY2 >= p.y) {
            return true;
        }
    }
    var corners = [
        new pointGeometry(boxX1, boxY1),
        new pointGeometry(boxX1, boxY2),
        new pointGeometry(boxX2, boxY2),
        new pointGeometry(boxX2, boxY1)
    ];
    if (ring.length > 2) {
        for (var i$2 = 0, list$1 = corners; i$2 < list$1.length; i$2 += 1) {
            var corner = list$1[i$2];
            if (polygonContainsPoint(ring, corner)) {
                return true;
            }
        }
    }
    for (var i = 0; i < ring.length - 1; i++) {
        var p1 = ring[i];
        var p2 = ring[i + 1];
        if (edgeIntersectsBox(p1, p2, corners)) {
            return true;
        }
    }
    return false;
}
function edgeIntersectsBox(e1, e2, corners) {
    var tl = corners[0];
    var br = corners[2];
    if (e1.x < tl.x && e2.x < tl.x || e1.x > br.x && e2.x > br.x || e1.y < tl.y && e2.y < tl.y || e1.y > br.y && e2.y > br.y) {
        return false;
    }
    var dir = isCounterClockwise(e1, e2, corners[0]);
    return dir !== isCounterClockwise(e1, e2, corners[1]) || dir !== isCounterClockwise(e1, e2, corners[2]) || dir !== isCounterClockwise(e1, e2, corners[3]);
}

function getMaximumPaintValue(property, layer, bucket) {
    var value = layer.paint.get(property).value;
    if (value.kind === 'constant') {
        return value.value;
    } else {
        return bucket.programConfigurations.get(layer.id).getMaxValue(property);
    }
}
function translateDistance(translate) {
    return Math.sqrt(translate[0] * translate[0] + translate[1] * translate[1]);
}
function translate(queryGeometry, translate, translateAnchor, bearing, pixelsToTileUnits) {
    if (!translate[0] && !translate[1]) {
        return queryGeometry;
    }
    var pt = pointGeometry.convert(translate)._mult(pixelsToTileUnits);
    if (translateAnchor === 'viewport') {
        pt._rotate(-bearing);
    }
    var translated = [];
    for (var i = 0; i < queryGeometry.length; i++) {
        var point = queryGeometry[i];
        translated.push(point.sub(pt));
    }
    return translated;
}

var layout$2 = new Properties({ 'circle-sort-key': new DataDrivenProperty(spec['layout_circle']['circle-sort-key']) });
var paint$1 = new Properties({
    'circle-radius': new DataDrivenProperty(spec['paint_circle']['circle-radius']),
    'circle-color': new DataDrivenProperty(spec['paint_circle']['circle-color']),
    'circle-blur': new DataDrivenProperty(spec['paint_circle']['circle-blur']),
    'circle-opacity': new DataDrivenProperty(spec['paint_circle']['circle-opacity']),
    'circle-translate': new DataConstantProperty(spec['paint_circle']['circle-translate']),
    'circle-translate-anchor': new DataConstantProperty(spec['paint_circle']['circle-translate-anchor']),
    'circle-pitch-scale': new DataConstantProperty(spec['paint_circle']['circle-pitch-scale']),
    'circle-pitch-alignment': new DataConstantProperty(spec['paint_circle']['circle-pitch-alignment']),
    'circle-stroke-width': new DataDrivenProperty(spec['paint_circle']['circle-stroke-width']),
    'circle-stroke-color': new DataDrivenProperty(spec['paint_circle']['circle-stroke-color']),
    'circle-stroke-opacity': new DataDrivenProperty(spec['paint_circle']['circle-stroke-opacity'])
});
var properties = {
    paint: paint$1,
    layout: layout$2
};

var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
if (!Math.hypot) {
    Math.hypot = function () {
        var arguments$1 = arguments;
        var y = 0, i = arguments.length;
        while (i--) {
            y += arguments$1[i] * arguments$1[i];
        }
        return Math.sqrt(y);
    };
}

function create() {
    var out = new ARRAY_TYPE(4);
    if (ARRAY_TYPE != Float32Array) {
        out[1] = 0;
        out[2] = 0;
    }
    out[0] = 1;
    out[3] = 1;
    return out;
}
function rotate(out, a, rad) {
    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
    var s = Math.sin(rad);
    var c = Math.cos(rad);
    out[0] = a0 * c + a2 * s;
    out[1] = a1 * c + a3 * s;
    out[2] = a0 * -s + a2 * c;
    out[3] = a1 * -s + a3 * c;
    return out;
}

function create$1() {
    var out = new ARRAY_TYPE(9);
    if (ARRAY_TYPE != Float32Array) {
        out[1] = 0;
        out[2] = 0;
        out[3] = 0;
        out[5] = 0;
        out[6] = 0;
        out[7] = 0;
    }
    out[0] = 1;
    out[4] = 1;
    out[8] = 1;
    return out;
}
function fromRotation(out, rad) {
    var s = Math.sin(rad), c = Math.cos(rad);
    out[0] = c;
    out[1] = s;
    out[2] = 0;
    out[3] = -s;
    out[4] = c;
    out[5] = 0;
    out[6] = 0;
    out[7] = 0;
    out[8] = 1;
    return out;
}

function create$2() {
    var out = new ARRAY_TYPE(16);
    if (ARRAY_TYPE != Float32Array) {
        out[1] = 0;
        out[2] = 0;
        out[3] = 0;
        out[4] = 0;
        out[6] = 0;
        out[7] = 0;
        out[8] = 0;
        out[9] = 0;
        out[11] = 0;
        out[12] = 0;
        out[13] = 0;
        out[14] = 0;
    }
    out[0] = 1;
    out[5] = 1;
    out[10] = 1;
    out[15] = 1;
    return out;
}
function clone$1(a) {
    var out = new ARRAY_TYPE(16);
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[4] = a[4];
    out[5] = a[5];
    out[6] = a[6];
    out[7] = a[7];
    out[8] = a[8];
    out[9] = a[9];
    out[10] = a[10];
    out[11] = a[11];
    out[12] = a[12];
    out[13] = a[13];
    out[14] = a[14];
    out[15] = a[15];
    return out;
}
function identity(out) {
    out[0] = 1;
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[5] = 1;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[10] = 1;
    out[11] = 0;
    out[12] = 0;
    out[13] = 0;
    out[14] = 0;
    out[15] = 1;
    return out;
}
function invert(out, a) {
    var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
    var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
    var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
    var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
    var b00 = a00 * a11 - a01 * a10;
    var b01 = a00 * a12 - a02 * a10;
    var b02 = a00 * a13 - a03 * a10;
    var b03 = a01 * a12 - a02 * a11;
    var b04 = a01 * a13 - a03 * a11;
    var b05 = a02 * a13 - a03 * a12;
    var b06 = a20 * a31 - a21 * a30;
    var b07 = a20 * a32 - a22 * a30;
    var b08 = a20 * a33 - a23 * a30;
    var b09 = a21 * a32 - a22 * a31;
    var b10 = a21 * a33 - a23 * a31;
    var b11 = a22 * a33 - a23 * a32;
    var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    if (!det) {
        return null;
    }
    det = 1 / det;
    out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
    out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
    out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
    out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
    out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
    out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
    out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
    out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
    out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
    out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
    out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
    out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
    out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
    out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
    out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
    out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
    return out;
}
function multiply(out, a, b) {
    var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
    var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
    var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
    var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
    var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
    out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[4];
    b1 = b[5];
    b2 = b[6];
    b3 = b[7];
    out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[8];
    b1 = b[9];
    b2 = b[10];
    b3 = b[11];
    out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[12];
    b1 = b[13];
    b2 = b[14];
    b3 = b[15];
    out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    return out;
}
function translate$1(out, a, v) {
    var x = v[0], y = v[1], z = v[2];
    var a00, a01, a02, a03;
    var a10, a11, a12, a13;
    var a20, a21, a22, a23;
    if (a === out) {
        out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
        out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
        out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
        out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
    } else {
        a00 = a[0];
        a01 = a[1];
        a02 = a[2];
        a03 = a[3];
        a10 = a[4];
        a11 = a[5];
        a12 = a[6];
        a13 = a[7];
        a20 = a[8];
        a21 = a[9];
        a22 = a[10];
        a23 = a[11];
        out[0] = a00;
        out[1] = a01;
        out[2] = a02;
        out[3] = a03;
        out[4] = a10;
        out[5] = a11;
        out[6] = a12;
        out[7] = a13;
        out[8] = a20;
        out[9] = a21;
        out[10] = a22;
        out[11] = a23;
        out[12] = a00 * x + a10 * y + a20 * z + a[12];
        out[13] = a01 * x + a11 * y + a21 * z + a[13];
        out[14] = a02 * x + a12 * y + a22 * z + a[14];
        out[15] = a03 * x + a13 * y + a23 * z + a[15];
    }
    return out;
}
function scale(out, a, v) {
    var x = v[0], y = v[1], z = v[2];
    out[0] = a[0] * x;
    out[1] = a[1] * x;
    out[2] = a[2] * x;
    out[3] = a[3] * x;
    out[4] = a[4] * y;
    out[5] = a[5] * y;
    out[6] = a[6] * y;
    out[7] = a[7] * y;
    out[8] = a[8] * z;
    out[9] = a[9] * z;
    out[10] = a[10] * z;
    out[11] = a[11] * z;
    out[12] = a[12];
    out[13] = a[13];
    out[14] = a[14];
    out[15] = a[15];
    return out;
}
function rotateX(out, a, rad) {
    var s = Math.sin(rad);
    var c = Math.cos(rad);
    var a10 = a[4];
    var a11 = a[5];
    var a12 = a[6];
    var a13 = a[7];
    var a20 = a[8];
    var a21 = a[9];
    var a22 = a[10];
    var a23 = a[11];
    if (a !== out) {
        out[0] = a[0];
        out[1] = a[1];
        out[2] = a[2];
        out[3] = a[3];
        out[12] = a[12];
        out[13] = a[13];
        out[14] = a[14];
        out[15] = a[15];
    }
    out[4] = a10 * c + a20 * s;
    out[5] = a11 * c + a21 * s;
    out[6] = a12 * c + a22 * s;
    out[7] = a13 * c + a23 * s;
    out[8] = a20 * c - a10 * s;
    out[9] = a21 * c - a11 * s;
    out[10] = a22 * c - a12 * s;
    out[11] = a23 * c - a13 * s;
    return out;
}
function rotateZ(out, a, rad) {
    var s = Math.sin(rad);
    var c = Math.cos(rad);
    var a00 = a[0];
    var a01 = a[1];
    var a02 = a[2];
    var a03 = a[3];
    var a10 = a[4];
    var a11 = a[5];
    var a12 = a[6];
    var a13 = a[7];
    if (a !== out) {
        out[8] = a[8];
        out[9] = a[9];
        out[10] = a[10];
        out[11] = a[11];
        out[12] = a[12];
        out[13] = a[13];
        out[14] = a[14];
        out[15] = a[15];
    }
    out[0] = a00 * c + a10 * s;
    out[1] = a01 * c + a11 * s;
    out[2] = a02 * c + a12 * s;
    out[3] = a03 * c + a13 * s;
    out[4] = a10 * c - a00 * s;
    out[5] = a11 * c - a01 * s;
    out[6] = a12 * c - a02 * s;
    out[7] = a13 * c - a03 * s;
    return out;
}
function perspective(out, fovy, aspect, near, far) {
    var f = 1 / Math.tan(fovy / 2), nf;
    out[0] = f / aspect;
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[5] = f;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[11] = -1;
    out[12] = 0;
    out[13] = 0;
    out[15] = 0;
    if (far != null && far !== Infinity) {
        nf = 1 / (near - far);
        out[10] = (far + near) * nf;
        out[14] = 2 * far * near * nf;
    } else {
        out[10] = -1;
        out[14] = -2 * near;
    }
    return out;
}
function ortho(out, left, right, bottom, top, near, far) {
    var lr = 1 / (left - right);
    var bt = 1 / (bottom - top);
    var nf = 1 / (near - far);
    out[0] = -2 * lr;
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[5] = -2 * bt;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[10] = 2 * nf;
    out[11] = 0;
    out[12] = (left + right) * lr;
    out[13] = (top + bottom) * bt;
    out[14] = (far + near) * nf;
    out[15] = 1;
    return out;
}
var mul = multiply;

function create$3() {
    var out = new ARRAY_TYPE(3);
    if (ARRAY_TYPE != Float32Array) {
        out[0] = 0;
        out[1] = 0;
        out[2] = 0;
    }
    return out;
}
function clone$2(a) {
    var out = new ARRAY_TYPE(3);
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    return out;
}
function add(out, a, b) {
    out[0] = a[0] + b[0];
    out[1] = a[1] + b[1];
    out[2] = a[2] + b[2];
    return out;
}
function subtract(out, a, b) {
    out[0] = a[0] - b[0];
    out[1] = a[1] - b[1];
    out[2] = a[2] - b[2];
    return out;
}
function scale$1(out, a, b) {
    out[0] = a[0] * b;
    out[1] = a[1] * b;
    out[2] = a[2] * b;
    return out;
}
function normalize(out, a) {
    var x = a[0];
    var y = a[1];
    var z = a[2];
    var len = x * x + y * y + z * z;
    if (len > 0) {
        len = 1 / Math.sqrt(len);
    }
    out[0] = a[0] * len;
    out[1] = a[1] * len;
    out[2] = a[2] * len;
    return out;
}
function dot(a, b) {
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
function cross(out, a, b) {
    var ax = a[0], ay = a[1], az = a[2];
    var bx = b[0], by = b[1], bz = b[2];
    out[0] = ay * bz - az * by;
    out[1] = az * bx - ax * bz;
    out[2] = ax * by - ay * bx;
    return out;
}
function transformMat3(out, a, m) {
    var x = a[0], y = a[1], z = a[2];
    out[0] = x * m[0] + y * m[3] + z * m[6];
    out[1] = x * m[1] + y * m[4] + z * m[7];
    out[2] = x * m[2] + y * m[5] + z * m[8];
    return out;
}
var sub = subtract;
var forEach = function () {
    var vec = create$3();
    return function (a, stride, offset, count, fn, arg) {
        var i, l;
        if (!stride) {
            stride = 3;
        }
        if (!offset) {
            offset = 0;
        }
        if (count) {
            l = Math.min(count * stride + offset, a.length);
        } else {
            l = a.length;
        }
        for (i = offset; i < l; i += stride) {
            vec[0] = a[i];
            vec[1] = a[i + 1];
            vec[2] = a[i + 2];
            fn(vec, vec, arg);
            a[i] = vec[0];
            a[i + 1] = vec[1];
            a[i + 2] = vec[2];
        }
        return a;
    };
}();

function create$4() {
    var out = new ARRAY_TYPE(4);
    if (ARRAY_TYPE != Float32Array) {
        out[0] = 0;
        out[1] = 0;
        out[2] = 0;
        out[3] = 0;
    }
    return out;
}
function scale$2(out, a, b) {
    out[0] = a[0] * b;
    out[1] = a[1] * b;
    out[2] = a[2] * b;
    out[3] = a[3] * b;
    return out;
}
function dot$1(a, b) {
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
function transformMat4(out, a, m) {
    var x = a[0], y = a[1], z = a[2], w = a[3];
    out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
    out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
    out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
    out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
    return out;
}
var forEach$1 = function () {
    var vec = create$4();
    return function (a, stride, offset, count, fn, arg) {
        var i, l;
        if (!stride) {
            stride = 4;
        }
        if (!offset) {
            offset = 0;
        }
        if (count) {
            l = Math.min(count * stride + offset, a.length);
        } else {
            l = a.length;
        }
        for (i = offset; i < l; i += stride) {
            vec[0] = a[i];
            vec[1] = a[i + 1];
            vec[2] = a[i + 2];
            vec[3] = a[i + 3];
            fn(vec, vec, arg);
            a[i] = vec[0];
            a[i + 1] = vec[1];
            a[i + 2] = vec[2];
            a[i + 3] = vec[3];
        }
        return a;
    };
}();

function create$5() {
    var out = new ARRAY_TYPE(2);
    if (ARRAY_TYPE != Float32Array) {
        out[0] = 0;
        out[1] = 0;
    }
    return out;
}
function squaredLength(a) {
    var x = a[0], y = a[1];
    return x * x + y * y;
}
var sqrLen = squaredLength;
var forEach$2 = function () {
    var vec = create$5();
    return function (a, stride, offset, count, fn, arg) {
        var i, l;
        if (!stride) {
            stride = 2;
        }
        if (!offset) {
            offset = 0;
        }
        if (count) {
            l = Math.min(count * stride + offset, a.length);
        } else {
            l = a.length;
        }
        for (i = offset; i < l; i += stride) {
            vec[0] = a[i];
            vec[1] = a[i + 1];
            fn(vec, vec, arg);
            a[i] = vec[0];
            a[i + 1] = vec[1];
        }
        return a;
    };
}();

var CircleStyleLayer = function (StyleLayer) {
    function CircleStyleLayer(layer) {
        StyleLayer.call(this, layer, properties);
    }
    if (StyleLayer)
        CircleStyleLayer.__proto__ = StyleLayer;
    CircleStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    CircleStyleLayer.prototype.constructor = CircleStyleLayer;
    CircleStyleLayer.prototype.createBucket = function createBucket(parameters) {
        return new CircleBucket(parameters);
    };
    CircleStyleLayer.prototype.queryRadius = function queryRadius(bucket) {
        var circleBucket = bucket;
        return getMaximumPaintValue('circle-radius', this, circleBucket) + getMaximumPaintValue('circle-stroke-width', this, circleBucket) + translateDistance(this.paint.get('circle-translate'));
    };
    CircleStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature(queryGeometry, feature, featureState, geometry, zoom, transform, pixelsToTileUnits, pixelPosMatrix) {
        var translatedPolygon = translate(queryGeometry, this.paint.get('circle-translate'), this.paint.get('circle-translate-anchor'), transform.angle, pixelsToTileUnits);
        var radius = this.paint.get('circle-radius').evaluate(feature, featureState);
        var stroke = this.paint.get('circle-stroke-width').evaluate(feature, featureState);
        var size = radius + stroke;
        var alignWithMap = this.paint.get('circle-pitch-alignment') === 'map';
        var transformedPolygon = alignWithMap ? translatedPolygon : projectQueryGeometry(translatedPolygon, pixelPosMatrix);
        var transformedSize = alignWithMap ? size * pixelsToTileUnits : size;
        for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
            var ring = list$1[i$1];
            for (var i = 0, list = ring; i < list.length; i += 1) {
                var point = list[i];
                var transformedPoint = alignWithMap ? point : projectPoint(point, pixelPosMatrix);
                var adjustedSize = transformedSize;
                var projectedCenter = transformMat4([], [
                    point.x,
                    point.y,
                    0,
                    1
                ], pixelPosMatrix);
                if (this.paint.get('circle-pitch-scale') === 'viewport' && this.paint.get('circle-pitch-alignment') === 'map') {
                    adjustedSize *= projectedCenter[3] / transform.cameraToCenterDistance;
                } else if (this.paint.get('circle-pitch-scale') === 'map' && this.paint.get('circle-pitch-alignment') === 'viewport') {
                    adjustedSize *= transform.cameraToCenterDistance / projectedCenter[3];
                }
                if (polygonIntersectsBufferedPoint(transformedPolygon, transformedPoint, adjustedSize)) {
                    return true;
                }
            }
        }
        return false;
    };
    return CircleStyleLayer;
}(StyleLayer);
function projectPoint(p, pixelPosMatrix) {
    var point = transformMat4([], [
        p.x,
        p.y,
        0,
        1
    ], pixelPosMatrix);
    return new pointGeometry(point[0] / point[3], point[1] / point[3]);
}
function projectQueryGeometry(queryGeometry, pixelPosMatrix) {
    return queryGeometry.map(function (p) {
        return projectPoint(p, pixelPosMatrix);
    });
}

var HeatmapBucket = function (CircleBucket) {
    function HeatmapBucket() {
        CircleBucket.apply(this, arguments);
    }
    if (CircleBucket)
        HeatmapBucket.__proto__ = CircleBucket;
    HeatmapBucket.prototype = Object.create(CircleBucket && CircleBucket.prototype);
    HeatmapBucket.prototype.constructor = HeatmapBucket;
    return HeatmapBucket;
}(CircleBucket);
register('HeatmapBucket', HeatmapBucket, { omit: ['layers'] });

function createImage(image, ref, channels, data) {
    var width = ref.width;
    var height = ref.height;
    if (!data) {
        data = new Uint8Array(width * height * channels);
    } else if (data instanceof Uint8ClampedArray) {
        data = new Uint8Array(data.buffer);
    } else if (data.length !== width * height * channels) {
        throw new RangeError('mismatched image size');
    }
    image.width = width;
    image.height = height;
    image.data = data;
    return image;
}
function resizeImage(image, ref, channels) {
    var width = ref.width;
    var height = ref.height;
    if (width === image.width && height === image.height) {
        return;
    }
    var newImage = createImage({}, {
        width: width,
        height: height
    }, channels);
    copyImage(image, newImage, {
        x: 0,
        y: 0
    }, {
        x: 0,
        y: 0
    }, {
        width: Math.min(image.width, width),
        height: Math.min(image.height, height)
    }, channels);
    image.width = width;
    image.height = height;
    image.data = newImage.data;
}
function copyImage(srcImg, dstImg, srcPt, dstPt, size, channels) {
    if (size.width === 0 || size.height === 0) {
        return dstImg;
    }
    if (size.width > srcImg.width || size.height > srcImg.height || srcPt.x > srcImg.width - size.width || srcPt.y > srcImg.height - size.height) {
        throw new RangeError('out of range source coordinates for image copy');
    }
    if (size.width > dstImg.width || size.height > dstImg.height || dstPt.x > dstImg.width - size.width || dstPt.y > dstImg.height - size.height) {
        throw new RangeError('out of range destination coordinates for image copy');
    }
    var srcData = srcImg.data;
    var dstData = dstImg.data;
    for (var y = 0; y < size.height; y++) {
        var srcOffset = ((srcPt.y + y) * srcImg.width + srcPt.x) * channels;
        var dstOffset = ((dstPt.y + y) * dstImg.width + dstPt.x) * channels;
        for (var i = 0; i < size.width * channels; i++) {
            dstData[dstOffset + i] = srcData[srcOffset + i];
        }
    }
    return dstImg;
}
var AlphaImage = function AlphaImage(size, data) {
    createImage(this, size, 1, data);
};
AlphaImage.prototype.resize = function resize(size) {
    resizeImage(this, size, 1);
};
AlphaImage.prototype.clone = function clone() {
    return new AlphaImage({
        width: this.width,
        height: this.height
    }, new Uint8Array(this.data));
};
AlphaImage.copy = function copy(srcImg, dstImg, srcPt, dstPt, size) {
    copyImage(srcImg, dstImg, srcPt, dstPt, size, 1);
};
var RGBAImage = function RGBAImage(size, data) {
    createImage(this, size, 4, data);
};
RGBAImage.prototype.resize = function resize(size) {
    resizeImage(this, size, 4);
};
RGBAImage.prototype.replace = function replace(data, copy) {
    if (copy) {
        this.data.set(data);
    } else if (data instanceof Uint8ClampedArray) {
        this.data = new Uint8Array(data.buffer);
    } else {
        this.data = data;
    }
};
RGBAImage.prototype.clone = function clone() {
    return new RGBAImage({
        width: this.width,
        height: this.height
    }, new Uint8Array(this.data));
};
RGBAImage.copy = function copy(srcImg, dstImg, srcPt, dstPt, size) {
    copyImage(srcImg, dstImg, srcPt, dstPt, size, 4);
};
register('AlphaImage', AlphaImage);
register('RGBAImage', RGBAImage);

var paint$2 = new Properties({
    'heatmap-radius': new DataDrivenProperty(spec['paint_heatmap']['heatmap-radius']),
    'heatmap-weight': new DataDrivenProperty(spec['paint_heatmap']['heatmap-weight']),
    'heatmap-intensity': new DataConstantProperty(spec['paint_heatmap']['heatmap-intensity']),
    'heatmap-color': new ColorRampProperty(spec['paint_heatmap']['heatmap-color']),
    'heatmap-opacity': new DataConstantProperty(spec['paint_heatmap']['heatmap-opacity'])
});
var properties$1 = { paint: paint$2 };

function renderColorRamp(params) {
    var evaluationGlobals = {};
    var width = params.resolution || 256;
    var height = params.clips ? params.clips.length : 1;
    var image = params.image || new RGBAImage({
        width: width,
        height: height
    });
    var renderPixel = function (stride, index, progress) {
        evaluationGlobals[params.evaluationKey] = progress;
        var pxColor = params.expression.evaluate(evaluationGlobals);
        image.data[stride + index + 0] = Math.floor(pxColor.r * 255 / pxColor.a);
        image.data[stride + index + 1] = Math.floor(pxColor.g * 255 / pxColor.a);
        image.data[stride + index + 2] = Math.floor(pxColor.b * 255 / pxColor.a);
        image.data[stride + index + 3] = Math.floor(pxColor.a * 255);
    };
    if (!params.clips) {
        for (var i = 0, j = 0; i < width; i++, j += 4) {
            var progress = i / (width - 1);
            renderPixel(0, j, progress);
        }
    } else {
        for (var clip = 0, stride = 0; clip < height; ++clip, stride += width * 4) {
            for (var i$1 = 0, j$1 = 0; i$1 < width; i$1++, j$1 += 4) {
                var progress$1 = i$1 / (width - 1);
                var ref = params.clips[clip];
                var start = ref.start;
                var end = ref.end;
                var evaluationProgress = start * (1 - progress$1) + end * progress$1;
                renderPixel(stride, j$1, evaluationProgress);
            }
        }
    }
    return image;
}

var HeatmapStyleLayer = function (StyleLayer) {
    function HeatmapStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$1);
        this._updateColorRamp();
    }
    if (StyleLayer)
        HeatmapStyleLayer.__proto__ = StyleLayer;
    HeatmapStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    HeatmapStyleLayer.prototype.constructor = HeatmapStyleLayer;
    HeatmapStyleLayer.prototype.createBucket = function createBucket(options) {
        return new HeatmapBucket(options);
    };
    HeatmapStyleLayer.prototype._handleSpecialPaintPropertyUpdate = function _handleSpecialPaintPropertyUpdate(name) {
        if (name === 'heatmap-color') {
            this._updateColorRamp();
        }
    };
    HeatmapStyleLayer.prototype._updateColorRamp = function _updateColorRamp() {
        var expression = this._transitionablePaint._values['heatmap-color'].value.expression;
        this.colorRamp = renderColorRamp({
            expression: expression,
            evaluationKey: 'heatmapDensity',
            image: this.colorRamp
        });
        this.colorRampTexture = null;
    };
    HeatmapStyleLayer.prototype.resize = function resize() {
        if (this.heatmapFbo) {
            this.heatmapFbo.destroy();
            this.heatmapFbo = null;
        }
    };
    HeatmapStyleLayer.prototype.queryRadius = function queryRadius() {
        return 0;
    };
    HeatmapStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature() {
        return false;
    };
    HeatmapStyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass() {
        return this.paint.get('heatmap-opacity') !== 0 && this.visibility !== 'none';
    };
    return HeatmapStyleLayer;
}(StyleLayer);

var paint$3 = new Properties({
    'hillshade-illumination-direction': new DataConstantProperty(spec['paint_hillshade']['hillshade-illumination-direction']),
    'hillshade-illumination-anchor': new DataConstantProperty(spec['paint_hillshade']['hillshade-illumination-anchor']),
    'hillshade-exaggeration': new DataConstantProperty(spec['paint_hillshade']['hillshade-exaggeration']),
    'hillshade-shadow-color': new DataConstantProperty(spec['paint_hillshade']['hillshade-shadow-color']),
    'hillshade-highlight-color': new DataConstantProperty(spec['paint_hillshade']['hillshade-highlight-color']),
    'hillshade-accent-color': new DataConstantProperty(spec['paint_hillshade']['hillshade-accent-color'])
});
var properties$2 = { paint: paint$3 };

var HillshadeStyleLayer = function (StyleLayer) {
    function HillshadeStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$2);
    }
    if (StyleLayer)
        HillshadeStyleLayer.__proto__ = StyleLayer;
    HillshadeStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    HillshadeStyleLayer.prototype.constructor = HillshadeStyleLayer;
    HillshadeStyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass() {
        return this.paint.get('hillshade-exaggeration') !== 0 && this.visibility !== 'none';
    };
    return HillshadeStyleLayer;
}(StyleLayer);

var layout$3 = createLayout([{
        name: 'a_pos',
        components: 2,
        type: 'Int16'
    }], 4);
var members$1 = layout$3.members;

var earcut_1 = earcut;
var default_1 = earcut;
function earcut(data, holeIndices, dim) {
    dim = dim || 2;
    var hasHoles = holeIndices && holeIndices.length, outerLen = hasHoles ? holeIndices[0] * dim : data.length, outerNode = linkedList(data, 0, outerLen, dim, true), triangles = [];
    if (!outerNode || outerNode.next === outerNode.prev) {
        return triangles;
    }
    var minX, minY, maxX, maxY, x, y, invSize;
    if (hasHoles) {
        outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
    }
    if (data.length > 80 * dim) {
        minX = maxX = data[0];
        minY = maxY = data[1];
        for (var i = dim; i < outerLen; i += dim) {
            x = data[i];
            y = data[i + 1];
            if (x < minX) {
                minX = x;
            }
            if (y < minY) {
                minY = y;
            }
            if (x > maxX) {
                maxX = x;
            }
            if (y > maxY) {
                maxY = y;
            }
        }
        invSize = Math.max(maxX - minX, maxY - minY);
        invSize = invSize !== 0 ? 1 / invSize : 0;
    }
    earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
    return triangles;
}
function linkedList(data, start, end, dim, clockwise) {
    var i, last;
    if (clockwise === signedArea(data, start, end, dim) > 0) {
        for (i = start; i < end; i += dim) {
            last = insertNode(i, data[i], data[i + 1], last);
        }
    } else {
        for (i = end - dim; i >= start; i -= dim) {
            last = insertNode(i, data[i], data[i + 1], last);
        }
    }
    if (last && equals(last, last.next)) {
        removeNode(last);
        last = last.next;
    }
    return last;
}
function filterPoints(start, end) {
    if (!start) {
        return start;
    }
    if (!end) {
        end = start;
    }
    var p = start, again;
    do {
        again = false;
        if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
            removeNode(p);
            p = end = p.prev;
            if (p === p.next) {
                break;
            }
            again = true;
        } else {
            p = p.next;
        }
    } while (again || p !== end);
    return end;
}
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
    if (!ear) {
        return;
    }
    if (!pass && invSize) {
        indexCurve(ear, minX, minY, invSize);
    }
    var stop = ear, prev, next;
    while (ear.prev !== ear.next) {
        prev = ear.prev;
        next = ear.next;
        if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
            triangles.push(prev.i / dim);
            triangles.push(ear.i / dim);
            triangles.push(next.i / dim);
            removeNode(ear);
            ear = next.next;
            stop = next.next;
            continue;
        }
        ear = next;
        if (ear === stop) {
            if (!pass) {
                earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
            } else if (pass === 1) {
                ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
                earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
            } else if (pass === 2) {
                splitEarcut(ear, triangles, dim, minX, minY, invSize);
            }
            break;
        }
    }
}
function isEar(ear) {
    var a = ear.prev, b = ear, c = ear.next;
    if (area(a, b, c) >= 0) {
        return false;
    }
    var p = ear.next.next;
    while (p !== ear.prev) {
        if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) {
            return false;
        }
        p = p.next;
    }
    return true;
}
function isEarHashed(ear, minX, minY, invSize) {
    var a = ear.prev, b = ear, c = ear.next;
    if (area(a, b, c) >= 0) {
        return false;
    }
    var minTX = a.x < b.x ? a.x < c.x ? a.x : c.x : b.x < c.x ? b.x : c.x, minTY = a.y < b.y ? a.y < c.y ? a.y : c.y : b.y < c.y ? b.y : c.y, maxTX = a.x > b.x ? a.x > c.x ? a.x : c.x : b.x > c.x ? b.x : c.x, maxTY = a.y > b.y ? a.y > c.y ? a.y : c.y : b.y > c.y ? b.y : c.y;
    var minZ = zOrder(minTX, minTY, minX, minY, invSize), maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
    var p = ear.prevZ, n = ear.nextZ;
    while (p && p.z >= minZ && n && n.z <= maxZ) {
        if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) {
            return false;
        }
        p = p.prevZ;
        if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) {
            return false;
        }
        n = n.nextZ;
    }
    while (p && p.z >= minZ) {
        if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) {
            return false;
        }
        p = p.prevZ;
    }
    while (n && n.z <= maxZ) {
        if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) {
            return false;
        }
        n = n.nextZ;
    }
    return true;
}
function cureLocalIntersections(start, triangles, dim) {
    var p = start;
    do {
        var a = p.prev, b = p.next.next;
        if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
            triangles.push(a.i / dim);
            triangles.push(p.i / dim);
            triangles.push(b.i / dim);
            removeNode(p);
            removeNode(p.next);
            p = start = b;
        }
        p = p.next;
    } while (p !== start);
    return filterPoints(p);
}
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
    var a = start;
    do {
        var b = a.next.next;
        while (b !== a.prev) {
            if (a.i !== b.i && isValidDiagonal(a, b)) {
                var c = splitPolygon(a, b);
                a = filterPoints(a, a.next);
                c = filterPoints(c, c.next);
                earcutLinked(a, triangles, dim, minX, minY, invSize);
                earcutLinked(c, triangles, dim, minX, minY, invSize);
                return;
            }
            b = b.next;
        }
        a = a.next;
    } while (a !== start);
}
function eliminateHoles(data, holeIndices, outerNode, dim) {
    var queue = [], i, len, start, end, list;
    for (i = 0, len = holeIndices.length; i < len; i++) {
        start = holeIndices[i] * dim;
        end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
        list = linkedList(data, start, end, dim, false);
        if (list === list.next) {
            list.steiner = true;
        }
        queue.push(getLeftmost(list));
    }
    queue.sort(compareX);
    for (i = 0; i < queue.length; i++) {
        eliminateHole(queue[i], outerNode);
        outerNode = filterPoints(outerNode, outerNode.next);
    }
    return outerNode;
}
function compareX(a, b) {
    return a.x - b.x;
}
function eliminateHole(hole, outerNode) {
    outerNode = findHoleBridge(hole, outerNode);
    if (outerNode) {
        var b = splitPolygon(outerNode, hole);
        filterPoints(outerNode, outerNode.next);
        filterPoints(b, b.next);
    }
}
function findHoleBridge(hole, outerNode) {
    var p = outerNode, hx = hole.x, hy = hole.y, qx = -Infinity, m;
    do {
        if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
            var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
            if (x <= hx && x > qx) {
                qx = x;
                if (x === hx) {
                    if (hy === p.y) {
                        return p;
                    }
                    if (hy === p.next.y) {
                        return p.next;
                    }
                }
                m = p.x < p.next.x ? p : p.next;
            }
        }
        p = p.next;
    } while (p !== outerNode);
    if (!m) {
        return null;
    }
    if (hx === qx) {
        return m;
    }
    var stop = m, mx = m.x, my = m.y, tanMin = Infinity, tan;
    p = m;
    do {
        if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
            tan = Math.abs(hy - p.y) / (hx - p.x);
            if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
                m = p;
                tanMin = tan;
            }
        }
        p = p.next;
    } while (p !== stop);
    return m;
}
function sectorContainsSector(m, p) {
    return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
}
function indexCurve(start, minX, minY, invSize) {
    var p = start;
    do {
        if (p.z === null) {
            p.z = zOrder(p.x, p.y, minX, minY, invSize);
        }
        p.prevZ = p.prev;
        p.nextZ = p.next;
        p = p.next;
    } while (p !== start);
    p.prevZ.nextZ = null;
    p.prevZ = null;
    sortLinked(p);
}
function sortLinked(list) {
    var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
    do {
        p = list;
        list = null;
        tail = null;
        numMerges = 0;
        while (p) {
            numMerges++;
            q = p;
            pSize = 0;
            for (i = 0; i < inSize; i++) {
                pSize++;
                q = q.nextZ;
                if (!q) {
                    break;
                }
            }
            qSize = inSize;
            while (pSize > 0 || qSize > 0 && q) {
                if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
                    e = p;
                    p = p.nextZ;
                    pSize--;
                } else {
                    e = q;
                    q = q.nextZ;
                    qSize--;
                }
                if (tail) {
                    tail.nextZ = e;
                } else {
                    list = e;
                }
                e.prevZ = tail;
                tail = e;
            }
            p = q;
        }
        tail.nextZ = null;
        inSize *= 2;
    } while (numMerges > 1);
    return list;
}
function zOrder(x, y, minX, minY, invSize) {
    x = 32767 * (x - minX) * invSize;
    y = 32767 * (y - minY) * invSize;
    x = (x | x << 8) & 16711935;
    x = (x | x << 4) & 252645135;
    x = (x | x << 2) & 858993459;
    x = (x | x << 1) & 1431655765;
    y = (y | y << 8) & 16711935;
    y = (y | y << 4) & 252645135;
    y = (y | y << 2) & 858993459;
    y = (y | y << 1) & 1431655765;
    return x | y << 1;
}
function getLeftmost(start) {
    var p = start, leftmost = start;
    do {
        if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) {
            leftmost = p;
        }
        p = p.next;
    } while (p !== start);
    return leftmost;
}
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
    return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
}
function isValidDiagonal(a, b) {
    return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && (area(a.prev, a, b.prev) || area(a, b.prev, b)) || equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
}
function area(p, q, r) {
    return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
}
function equals(p1, p2) {
    return p1.x === p2.x && p1.y === p2.y;
}
function intersects(p1, q1, p2, q2) {
    var o1 = sign(area(p1, q1, p2));
    var o2 = sign(area(p1, q1, q2));
    var o3 = sign(area(p2, q2, p1));
    var o4 = sign(area(p2, q2, q1));
    if (o1 !== o2 && o3 !== o4) {
        return true;
    }
    if (o1 === 0 && onSegment(p1, p2, q1)) {
        return true;
    }
    if (o2 === 0 && onSegment(p1, q2, q1)) {
        return true;
    }
    if (o3 === 0 && onSegment(p2, p1, q2)) {
        return true;
    }
    if (o4 === 0 && onSegment(p2, q1, q2)) {
        return true;
    }
    return false;
}
function onSegment(p, q, r) {
    return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
}
function sign(num) {
    return num > 0 ? 1 : num < 0 ? -1 : 0;
}
function intersectsPolygon(a, b) {
    var p = a;
    do {
        if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) {
            return true;
        }
        p = p.next;
    } while (p !== a);
    return false;
}
function locallyInside(a, b) {
    return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
}
function middleInside(a, b) {
    var p = a, inside = false, px = (a.x + b.x) / 2, py = (a.y + b.y) / 2;
    do {
        if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x) {
            inside = !inside;
        }
        p = p.next;
    } while (p !== a);
    return inside;
}
function splitPolygon(a, b) {
    var a2 = new Node(a.i, a.x, a.y), b2 = new Node(b.i, b.x, b.y), an = a.next, bp = b.prev;
    a.next = b;
    b.prev = a;
    a2.next = an;
    an.prev = a2;
    b2.next = a2;
    a2.prev = b2;
    bp.next = b2;
    b2.prev = bp;
    return b2;
}
function insertNode(i, x, y, last) {
    var p = new Node(i, x, y);
    if (!last) {
        p.prev = p;
        p.next = p;
    } else {
        p.next = last.next;
        p.prev = last;
        last.next.prev = p;
        last.next = p;
    }
    return p;
}
function removeNode(p) {
    p.next.prev = p.prev;
    p.prev.next = p.next;
    if (p.prevZ) {
        p.prevZ.nextZ = p.nextZ;
    }
    if (p.nextZ) {
        p.nextZ.prevZ = p.prevZ;
    }
}
function Node(i, x, y) {
    this.i = i;
    this.x = x;
    this.y = y;
    this.prev = null;
    this.next = null;
    this.z = null;
    this.prevZ = null;
    this.nextZ = null;
    this.steiner = false;
}
earcut.deviation = function (data, holeIndices, dim, triangles) {
    var hasHoles = holeIndices && holeIndices.length;
    var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
    var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
    if (hasHoles) {
        for (var i = 0, len = holeIndices.length; i < len; i++) {
            var start = holeIndices[i] * dim;
            var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
            polygonArea -= Math.abs(signedArea(data, start, end, dim));
        }
    }
    var trianglesArea = 0;
    for (i = 0; i < triangles.length; i += 3) {
        var a = triangles[i] * dim;
        var b = triangles[i + 1] * dim;
        var c = triangles[i + 2] * dim;
        trianglesArea += Math.abs((data[a] - data[c]) * (data[b + 1] - data[a + 1]) - (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
    }
    return polygonArea === 0 && trianglesArea === 0 ? 0 : Math.abs((trianglesArea - polygonArea) / polygonArea);
};
function signedArea(data, start, end, dim) {
    var sum = 0;
    for (var i = start, j = end - dim; i < end; i += dim) {
        sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
        j = i;
    }
    return sum;
}
earcut.flatten = function (data) {
    var dim = data[0][0].length, result = {
            vertices: [],
            holes: [],
            dimensions: dim
        }, holeIndex = 0;
    for (var i = 0; i < data.length; i++) {
        for (var j = 0; j < data[i].length; j++) {
            for (var d = 0; d < dim; d++) {
                result.vertices.push(data[i][j][d]);
            }
        }
        if (i > 0) {
            holeIndex += data[i - 1].length;
            result.holes.push(holeIndex);
        }
    }
    return result;
};
earcut_1.default = default_1;

function quickselect(arr, k, left, right, compare) {
    quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
}
function quickselectStep(arr, k, left, right, compare) {
    while (right > left) {
        if (right - left > 600) {
            var n = right - left + 1;
            var m = k - left + 1;
            var z = Math.log(n);
            var s = 0.5 * Math.exp(2 * z / 3);
            var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
            var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
            var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
            quickselectStep(arr, k, newLeft, newRight, compare);
        }
        var t = arr[k];
        var i = left;
        var j = right;
        swap$1(arr, left, k);
        if (compare(arr[right], t) > 0) {
            swap$1(arr, left, right);
        }
        while (i < j) {
            swap$1(arr, i, j);
            i++;
            j--;
            while (compare(arr[i], t) < 0) {
                i++;
            }
            while (compare(arr[j], t) > 0) {
                j--;
            }
        }
        if (compare(arr[left], t) === 0) {
            swap$1(arr, left, j);
        } else {
            j++;
            swap$1(arr, j, right);
        }
        if (j <= k) {
            left = j + 1;
        }
        if (k <= j) {
            right = j - 1;
        }
    }
}
function swap$1(arr, i, j) {
    var tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
function defaultCompare(a, b) {
    return a < b ? -1 : a > b ? 1 : 0;
}

function classifyRings(rings, maxRings) {
    var len = rings.length;
    if (len <= 1) {
        return [rings];
    }
    var polygons = [];
    var polygon, ccw;
    for (var i = 0; i < len; i++) {
        var area = calculateSignedArea(rings[i]);
        if (area === 0) {
            continue;
        }
        rings[i].area = Math.abs(area);
        if (ccw === undefined) {
            ccw = area < 0;
        }
        if (ccw === area < 0) {
            if (polygon) {
                polygons.push(polygon);
            }
            polygon = [rings[i]];
        } else {
            polygon.push(rings[i]);
        }
    }
    if (polygon) {
        polygons.push(polygon);
    }
    if (maxRings > 1) {
        for (var j = 0; j < polygons.length; j++) {
            if (polygons[j].length <= maxRings) {
                continue;
            }
            quickselect(polygons[j], maxRings, 1, polygons[j].length - 1, compareAreas);
            polygons[j] = polygons[j].slice(0, maxRings);
        }
    }
    return polygons;
}
function compareAreas(a, b) {
    return b.area - a.area;
}

function hasPattern(type, layers, options) {
    var patterns = options.patternDependencies;
    var hasPattern = false;
    for (var i = 0, list = layers; i < list.length; i += 1) {
        var layer = list[i];
        var patternProperty = layer.paint.get(type + '-pattern');
        if (!patternProperty.isConstant()) {
            hasPattern = true;
        }
        var constantPattern = patternProperty.constantOr(null);
        if (constantPattern) {
            hasPattern = true;
            patterns[constantPattern.to] = true;
            patterns[constantPattern.from] = true;
        }
    }
    return hasPattern;
}
function addPatternDependencies(type, layers, patternFeature, zoom, options) {
    var patterns = options.patternDependencies;
    for (var i = 0, list = layers; i < list.length; i += 1) {
        var layer = list[i];
        var patternProperty = layer.paint.get(type + '-pattern');
        var patternPropertyValue = patternProperty.value;
        if (patternPropertyValue.kind !== 'constant') {
            var min = patternPropertyValue.evaluate({ zoom: zoom - 1 }, patternFeature, {}, options.availableImages);
            var mid = patternPropertyValue.evaluate({ zoom: zoom }, patternFeature, {}, options.availableImages);
            var max = patternPropertyValue.evaluate({ zoom: zoom + 1 }, patternFeature, {}, options.availableImages);
            min = min && min.name ? min.name : min;
            mid = mid && mid.name ? mid.name : mid;
            max = max && max.name ? max.name : max;
            patterns[min] = true;
            patterns[mid] = true;
            patterns[max] = true;
            patternFeature.patterns[layer.id] = {
                min: min,
                mid: mid,
                max: max
            };
        }
    }
    return patternFeature;
}

var EARCUT_MAX_RINGS = 500;
var FillBucket = function FillBucket(options) {
    this.zoom = options.zoom;
    this.overscaling = options.overscaling;
    this.layers = options.layers;
    this.layerIds = this.layers.map(function (layer) {
        return layer.id;
    });
    this.index = options.index;
    this.hasPattern = false;
    this.patternFeatures = [];
    this.layoutVertexArray = new StructArrayLayout2i4();
    this.indexArray = new StructArrayLayout3ui6();
    this.indexArray2 = new StructArrayLayout2ui4();
    this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
    this.segments = new SegmentVector();
    this.segments2 = new SegmentVector();
    this.stateDependentLayerIds = this.layers.filter(function (l) {
        return l.isStateDependent();
    }).map(function (l) {
        return l.id;
    });
};
FillBucket.prototype.populate = function populate(features, options, canonical) {
    this.hasPattern = hasPattern('fill', this.layers, options);
    var fillSortKey = this.layers[0].layout.get('fill-sort-key');
    var bucketFeatures = [];
    for (var i = 0, list = features; i < list.length; i += 1) {
        var ref = list[i];
        var feature = ref.feature;
        var id = ref.id;
        var index = ref.index;
        var sourceLayerIndex = ref.sourceLayerIndex;
        var needGeometry = this.layers[0]._featureFilter.needGeometry;
        var evaluationFeature = toEvaluationFeature(feature, needGeometry);
        if (!this.layers[0]._featureFilter.filter(new EvaluationParameters(this.zoom), evaluationFeature, canonical)) {
            continue;
        }
        var sortKey = fillSortKey ? fillSortKey.evaluate(evaluationFeature, {}, canonical, options.availableImages) : undefined;
        var bucketFeature = {
            id: id,
            properties: feature.properties,
            type: feature.type,
            sourceLayerIndex: sourceLayerIndex,
            index: index,
            geometry: needGeometry ? evaluationFeature.geometry : loadGeometry(feature),
            patterns: {},
            sortKey: sortKey
        };
        bucketFeatures.push(bucketFeature);
    }
    if (fillSortKey) {
        bucketFeatures.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
    for (var i$1 = 0, list$1 = bucketFeatures; i$1 < list$1.length; i$1 += 1) {
        var bucketFeature$1 = list$1[i$1];
        var ref$1 = bucketFeature$1;
        var geometry = ref$1.geometry;
        var index$1 = ref$1.index;
        var sourceLayerIndex$1 = ref$1.sourceLayerIndex;
        if (this.hasPattern) {
            var patternFeature = addPatternDependencies('fill', this.layers, bucketFeature$1, this.zoom, options);
            this.patternFeatures.push(patternFeature);
        } else {
            this.addFeature(bucketFeature$1, geometry, index$1, canonical, {});
        }
        var feature$1 = features[index$1].feature;
        options.featureIndex.insert(feature$1, geometry, index$1, sourceLayerIndex$1, this.index);
    }
};
FillBucket.prototype.update = function update(states, vtLayer, imagePositions) {
    if (!this.stateDependentLayers.length) {
        return;
    }
    this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
};
FillBucket.prototype.addFeatures = function addFeatures(options, canonical, imagePositions) {
    for (var i = 0, list = this.patternFeatures; i < list.length; i += 1) {
        var feature = list[i];
        this.addFeature(feature, feature.geometry, feature.index, canonical, imagePositions);
    }
};
FillBucket.prototype.isEmpty = function isEmpty() {
    return this.layoutVertexArray.length === 0;
};
FillBucket.prototype.uploadPending = function uploadPending() {
    return !this.uploaded || this.programConfigurations.needsUpload;
};
FillBucket.prototype.upload = function upload(context) {
    if (!this.uploaded) {
        this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members$1);
        this.indexBuffer = context.createIndexBuffer(this.indexArray);
        this.indexBuffer2 = context.createIndexBuffer(this.indexArray2);
    }
    this.programConfigurations.upload(context);
    this.uploaded = true;
};
FillBucket.prototype.destroy = function destroy() {
    if (!this.layoutVertexBuffer) {
        return;
    }
    this.layoutVertexBuffer.destroy();
    this.indexBuffer.destroy();
    this.indexBuffer2.destroy();
    this.programConfigurations.destroy();
    this.segments.destroy();
    this.segments2.destroy();
};
FillBucket.prototype.addFeature = function addFeature(feature, geometry, index, canonical, imagePositions) {
    for (var i$4 = 0, list$2 = classifyRings(geometry, EARCUT_MAX_RINGS); i$4 < list$2.length; i$4 += 1) {
        var polygon = list$2[i$4];
        var numVertices = 0;
        for (var i$2 = 0, list = polygon; i$2 < list.length; i$2 += 1) {
            var ring = list[i$2];
            numVertices += ring.length;
        }
        var triangleSegment = this.segments.prepareSegment(numVertices, this.layoutVertexArray, this.indexArray);
        var triangleIndex = triangleSegment.vertexLength;
        var flattened = [];
        var holeIndices = [];
        for (var i$3 = 0, list$1 = polygon; i$3 < list$1.length; i$3 += 1) {
            var ring$1 = list$1[i$3];
            if (ring$1.length === 0) {
                continue;
            }
            if (ring$1 !== polygon[0]) {
                holeIndices.push(flattened.length / 2);
            }
            var lineSegment = this.segments2.prepareSegment(ring$1.length, this.layoutVertexArray, this.indexArray2);
            var lineIndex = lineSegment.vertexLength;
            this.layoutVertexArray.emplaceBack(ring$1[0].x, ring$1[0].y);
            this.indexArray2.emplaceBack(lineIndex + ring$1.length - 1, lineIndex);
            flattened.push(ring$1[0].x);
            flattened.push(ring$1[0].y);
            for (var i = 1; i < ring$1.length; i++) {
                this.layoutVertexArray.emplaceBack(ring$1[i].x, ring$1[i].y);
                this.indexArray2.emplaceBack(lineIndex + i - 1, lineIndex + i);
                flattened.push(ring$1[i].x);
                flattened.push(ring$1[i].y);
            }
            lineSegment.vertexLength += ring$1.length;
            lineSegment.primitiveLength += ring$1.length;
        }
        var indices = earcut_1(flattened, holeIndices);
        for (var i$1 = 0; i$1 < indices.length; i$1 += 3) {
            this.indexArray.emplaceBack(triangleIndex + indices[i$1], triangleIndex + indices[i$1 + 1], triangleIndex + indices[i$1 + 2]);
        }
        triangleSegment.vertexLength += numVertices;
        triangleSegment.primitiveLength += indices.length / 3;
    }
    this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, canonical);
};
register('FillBucket', FillBucket, {
    omit: [
        'layers',
        'patternFeatures'
    ]
});

var layout$4 = new Properties({ 'fill-sort-key': new DataDrivenProperty(spec['layout_fill']['fill-sort-key']) });
var paint$4 = new Properties({
    'fill-antialias': new DataConstantProperty(spec['paint_fill']['fill-antialias']),
    'fill-opacity': new DataDrivenProperty(spec['paint_fill']['fill-opacity']),
    'fill-color': new DataDrivenProperty(spec['paint_fill']['fill-color']),
    'fill-outline-color': new DataDrivenProperty(spec['paint_fill']['fill-outline-color']),
    'fill-translate': new DataConstantProperty(spec['paint_fill']['fill-translate']),
    'fill-translate-anchor': new DataConstantProperty(spec['paint_fill']['fill-translate-anchor']),
    'fill-pattern': new CrossFadedDataDrivenProperty(spec['paint_fill']['fill-pattern'])
});
var properties$3 = {
    paint: paint$4,
    layout: layout$4
};

var FillStyleLayer = function (StyleLayer) {
    function FillStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$3);
    }
    if (StyleLayer)
        FillStyleLayer.__proto__ = StyleLayer;
    FillStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    FillStyleLayer.prototype.constructor = FillStyleLayer;
    FillStyleLayer.prototype.recalculate = function recalculate(parameters, availableImages) {
        StyleLayer.prototype.recalculate.call(this, parameters, availableImages);
        var outlineColor = this.paint._values['fill-outline-color'];
        if (outlineColor.value.kind === 'constant' && outlineColor.value.value === undefined) {
            this.paint._values['fill-outline-color'] = this.paint._values['fill-color'];
        }
    };
    FillStyleLayer.prototype.createBucket = function createBucket(parameters) {
        return new FillBucket(parameters);
    };
    FillStyleLayer.prototype.queryRadius = function queryRadius() {
        return translateDistance(this.paint.get('fill-translate'));
    };
    FillStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature(queryGeometry, feature, featureState, geometry, zoom, transform, pixelsToTileUnits) {
        var translatedPolygon = translate(queryGeometry, this.paint.get('fill-translate'), this.paint.get('fill-translate-anchor'), transform.angle, pixelsToTileUnits);
        return polygonIntersectsMultiPolygon(translatedPolygon, geometry);
    };
    FillStyleLayer.prototype.isTileClipped = function isTileClipped() {
        return true;
    };
    return FillStyleLayer;
}(StyleLayer);

var layout$5 = createLayout([
    {
        name: 'a_pos',
        components: 2,
        type: 'Int16'
    },
    {
        name: 'a_normal_ed',
        components: 4,
        type: 'Int16'
    }
], 4);
var members$2 = layout$5.members;

var vectortilefeature = VectorTileFeature;
function VectorTileFeature(pbf, end, extent, keys, values) {
    this.properties = {};
    this.extent = extent;
    this.type = 0;
    this._pbf = pbf;
    this._geometry = -1;
    this._keys = keys;
    this._values = values;
    pbf.readFields(readFeature, this, end);
}
function readFeature(tag, feature, pbf) {
    if (tag == 1) {
        feature.id = pbf.readVarint();
    } else if (tag == 2) {
        readTag(pbf, feature);
    } else if (tag == 3) {
        feature.type = pbf.readVarint();
    } else if (tag == 4) {
        feature._geometry = pbf.pos;
    }
}
function readTag(pbf, feature) {
    var end = pbf.readVarint() + pbf.pos;
    while (pbf.pos < end) {
        var key = feature._keys[pbf.readVarint()], value = feature._values[pbf.readVarint()];
        feature.properties[key] = value;
    }
}
VectorTileFeature.types = [
    'Unknown',
    'Point',
    'LineString',
    'Polygon'
];
VectorTileFeature.prototype.loadGeometry = function () {
    var pbf = this._pbf;
    pbf.pos = this._geometry;
    var end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, y = 0, lines = [], line;
    while (pbf.pos < end) {
        if (length <= 0) {
            var cmdLen = pbf.readVarint();
            cmd = cmdLen & 7;
            length = cmdLen >> 3;
        }
        length--;
        if (cmd === 1 || cmd === 2) {
            x += pbf.readSVarint();
            y += pbf.readSVarint();
            if (cmd === 1) {
                if (line) {
                    lines.push(line);
                }
                line = [];
            }
            line.push(new pointGeometry(x, y));
        } else if (cmd === 7) {
            if (line) {
                line.push(line[0].clone());
            }
        } else {
            throw new Error('unknown command ' + cmd);
        }
    }
    if (line) {
        lines.push(line);
    }
    return lines;
};
VectorTileFeature.prototype.bbox = function () {
    var pbf = this._pbf;
    pbf.pos = this._geometry;
    var end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, y = 0, x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity;
    while (pbf.pos < end) {
        if (length <= 0) {
            var cmdLen = pbf.readVarint();
            cmd = cmdLen & 7;
            length = cmdLen >> 3;
        }
        length--;
        if (cmd === 1 || cmd === 2) {
            x += pbf.readSVarint();
            y += pbf.readSVarint();
            if (x < x1) {
                x1 = x;
            }
            if (x > x2) {
                x2 = x;
            }
            if (y < y1) {
                y1 = y;
            }
            if (y > y2) {
                y2 = y;
            }
        } else if (cmd !== 7) {
            throw new Error('unknown command ' + cmd);
        }
    }
    return [
        x1,
        y1,
        x2,
        y2
    ];
};
VectorTileFeature.prototype.toGeoJSON = function (x, y, z) {
    var size = this.extent * Math.pow(2, z), x0 = this.extent * x, y0 = this.extent * y, coords = this.loadGeometry(), type = VectorTileFeature.types[this.type], i, j;
    function project(line) {
        for (var j = 0; j < line.length; j++) {
            var p = line[j], y2 = 180 - (p.y + y0) * 360 / size;
            line[j] = [
                (p.x + x0) * 360 / size - 180,
                360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90
            ];
        }
    }
    switch (this.type) {
    case 1:
        var points = [];
        for (i = 0; i < coords.length; i++) {
            points[i] = coords[i][0];
        }
        coords = points;
        project(coords);
        break;
    case 2:
        for (i = 0; i < coords.length; i++) {
            project(coords[i]);
        }
        break;
    case 3:
        coords = classifyRings$1(coords);
        for (i = 0; i < coords.length; i++) {
            for (j = 0; j < coords[i].length; j++) {
                project(coords[i][j]);
            }
        }
        break;
    }
    if (coords.length === 1) {
        coords = coords[0];
    } else {
        type = 'Multi' + type;
    }
    var result = {
        type: 'Feature',
        geometry: {
            type: type,
            coordinates: coords
        },
        properties: this.properties
    };
    if ('id' in this) {
        result.id = this.id;
    }
    return result;
};
function classifyRings$1(rings) {
    var len = rings.length;
    if (len <= 1) {
        return [rings];
    }
    var polygons = [], polygon, ccw;
    for (var i = 0; i < len; i++) {
        var area = signedArea$1(rings[i]);
        if (area === 0) {
            continue;
        }
        if (ccw === undefined) {
            ccw = area < 0;
        }
        if (ccw === area < 0) {
            if (polygon) {
                polygons.push(polygon);
            }
            polygon = [rings[i]];
        } else {
            polygon.push(rings[i]);
        }
    }
    if (polygon) {
        polygons.push(polygon);
    }
    return polygons;
}
function signedArea$1(ring) {
    var sum = 0;
    for (var 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;
}

var vectortilelayer = VectorTileLayer;
function VectorTileLayer(pbf, end) {
    this.version = 1;
    this.name = null;
    this.extent = 4096;
    this.length = 0;
    this._pbf = pbf;
    this._keys = [];
    this._values = [];
    this._features = [];
    pbf.readFields(readLayer, this, end);
    this.length = this._features.length;
}
function readLayer(tag, layer, pbf) {
    if (tag === 15) {
        layer.version = pbf.readVarint();
    } else if (tag === 1) {
        layer.name = pbf.readString();
    } else if (tag === 5) {
        layer.extent = pbf.readVarint();
    } else if (tag === 2) {
        layer._features.push(pbf.pos);
    } else if (tag === 3) {
        layer._keys.push(pbf.readString());
    } else if (tag === 4) {
        layer._values.push(readValueMessage(pbf));
    }
}
function readValueMessage(pbf) {
    var value = null, end = pbf.readVarint() + pbf.pos;
    while (pbf.pos < end) {
        var tag = pbf.readVarint() >> 3;
        value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;
    }
    return value;
}
VectorTileLayer.prototype.feature = function (i) {
    if (i < 0 || i >= this._features.length) {
        throw new Error('feature index out of bounds');
    }
    this._pbf.pos = this._features[i];
    var end = this._pbf.readVarint() + this._pbf.pos;
    return new vectortilefeature(this._pbf, end, this.extent, this._keys, this._values);
};

var vectortile = VectorTile;
function VectorTile(pbf, end) {
    this.layers = pbf.readFields(readTile, {}, end);
}
function readTile(tag, layers, pbf) {
    if (tag === 3) {
        var layer = new vectortilelayer(pbf, pbf.readVarint() + pbf.pos);
        if (layer.length) {
            layers[layer.name] = layer;
        }
    }
}

var VectorTile$1 = vectortile;
var VectorTileFeature$1 = vectortilefeature;
var VectorTileLayer$1 = vectortilelayer;

var vectorTile = {
	VectorTile: VectorTile$1,
	VectorTileFeature: VectorTileFeature$1,
	VectorTileLayer: VectorTileLayer$1
};

var vectorTileFeatureTypes = vectorTile.VectorTileFeature.types;
var EARCUT_MAX_RINGS$1 = 500;
var FACTOR = Math.pow(2, 13);
function addVertex(vertexArray, x, y, nx, ny, nz, t, e) {
    vertexArray.emplaceBack(x, y, Math.floor(nx * FACTOR) * 2 + t, ny * FACTOR * 2, nz * FACTOR * 2, Math.round(e));
}
var FillExtrusionBucket = function FillExtrusionBucket(options) {
    this.zoom = options.zoom;
    this.overscaling = options.overscaling;
    this.layers = options.layers;
    this.layerIds = this.layers.map(function (layer) {
        return layer.id;
    });
    this.index = options.index;
    this.hasPattern = false;
    this.layoutVertexArray = new StructArrayLayout2i4i12();
    this.indexArray = new StructArrayLayout3ui6();
    this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
    this.segments = new SegmentVector();
    this.stateDependentLayerIds = this.layers.filter(function (l) {
        return l.isStateDependent();
    }).map(function (l) {
        return l.id;
    });
};
FillExtrusionBucket.prototype.populate = function populate(features, options, canonical) {
    this.features = [];
    this.hasPattern = hasPattern('fill-extrusion', this.layers, options);
    for (var i = 0, list = features; i < list.length; i += 1) {
        var ref = list[i];
        var feature = ref.feature;
        var id = ref.id;
        var index = ref.index;
        var sourceLayerIndex = ref.sourceLayerIndex;
        var needGeometry = this.layers[0]._featureFilter.needGeometry;
        var evaluationFeature = toEvaluationFeature(feature, needGeometry);
        if (!this.layers[0]._featureFilter.filter(new EvaluationParameters(this.zoom), evaluationFeature, canonical)) {
            continue;
        }
        var bucketFeature = {
            id: id,
            sourceLayerIndex: sourceLayerIndex,
            index: index,
            geometry: needGeometry ? evaluationFeature.geometry : loadGeometry(feature),
            properties: feature.properties,
            type: feature.type,
            patterns: {}
        };
        if (this.hasPattern) {
            this.features.push(addPatternDependencies('fill-extrusion', this.layers, bucketFeature, this.zoom, options));
        } else {
            this.addFeature(bucketFeature, bucketFeature.geometry, index, canonical, {});
        }
        options.featureIndex.insert(feature, bucketFeature.geometry, index, sourceLayerIndex, this.index, true);
    }
};
FillExtrusionBucket.prototype.addFeatures = function addFeatures(options, canonical, imagePositions) {
    for (var i = 0, list = this.features; i < list.length; i += 1) {
        var feature = list[i];
        var geometry = feature.geometry;
        this.addFeature(feature, geometry, feature.index, canonical, imagePositions);
    }
};
FillExtrusionBucket.prototype.update = function update(states, vtLayer, imagePositions) {
    if (!this.stateDependentLayers.length) {
        return;
    }
    this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
};
FillExtrusionBucket.prototype.isEmpty = function isEmpty() {
    return this.layoutVertexArray.length === 0;
};
FillExtrusionBucket.prototype.uploadPending = function uploadPending() {
    return !this.uploaded || this.programConfigurations.needsUpload;
};
FillExtrusionBucket.prototype.upload = function upload(context) {
    if (!this.uploaded) {
        this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members$2);
        this.indexBuffer = context.createIndexBuffer(this.indexArray);
    }
    this.programConfigurations.upload(context);
    this.uploaded = true;
};
FillExtrusionBucket.prototype.destroy = function destroy() {
    if (!this.layoutVertexBuffer) {
        return;
    }
    this.layoutVertexBuffer.destroy();
    this.indexBuffer.destroy();
    this.programConfigurations.destroy();
    this.segments.destroy();
};
FillExtrusionBucket.prototype.addFeature = function addFeature(feature, geometry, index, canonical, imagePositions) {
    for (var i$4 = 0, list$3 = classifyRings(geometry, EARCUT_MAX_RINGS$1); i$4 < list$3.length; i$4 += 1) {
        var polygon = list$3[i$4];
        var numVertices = 0;
        for (var i$1 = 0, list = polygon; i$1 < list.length; i$1 += 1) {
            var ring = list[i$1];
            numVertices += ring.length;
        }
        var segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray);
        for (var i$2 = 0, list$1 = polygon; i$2 < list$1.length; i$2 += 1) {
            var ring$1 = list$1[i$2];
            if (ring$1.length === 0) {
                continue;
            }
            if (isEntirelyOutside(ring$1)) {
                continue;
            }
            var edgeDistance = 0;
            for (var p = 0; p < ring$1.length; p++) {
                var p1 = ring$1[p];
                if (p >= 1) {
                    var p2 = ring$1[p - 1];
                    if (!isBoundaryEdge(p1, p2)) {
                        if (segment.vertexLength + 4 > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) {
                            segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray);
                        }
                        var perp = p1.sub(p2)._perp()._unit();
                        var dist = p2.dist(p1);
                        if (edgeDistance + dist > 32768) {
                            edgeDistance = 0;
                        }
                        addVertex(this.layoutVertexArray, p1.x, p1.y, perp.x, perp.y, 0, 0, edgeDistance);
                        addVertex(this.layoutVertexArray, p1.x, p1.y, perp.x, perp.y, 0, 1, edgeDistance);
                        edgeDistance += dist;
                        addVertex(this.layoutVertexArray, p2.x, p2.y, perp.x, perp.y, 0, 0, edgeDistance);
                        addVertex(this.layoutVertexArray, p2.x, p2.y, perp.x, perp.y, 0, 1, edgeDistance);
                        var bottomRight = segment.vertexLength;
                        this.indexArray.emplaceBack(bottomRight, bottomRight + 2, bottomRight + 1);
                        this.indexArray.emplaceBack(bottomRight + 1, bottomRight + 2, bottomRight + 3);
                        segment.vertexLength += 4;
                        segment.primitiveLength += 2;
                    }
                }
            }
        }
        if (segment.vertexLength + numVertices > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) {
            segment = this.segments.prepareSegment(numVertices, this.layoutVertexArray, this.indexArray);
        }
        if (vectorTileFeatureTypes[feature.type] !== 'Polygon') {
            continue;
        }
        var flattened = [];
        var holeIndices = [];
        var triangleIndex = segment.vertexLength;
        for (var i$3 = 0, list$2 = polygon; i$3 < list$2.length; i$3 += 1) {
            var ring$2 = list$2[i$3];
            if (ring$2.length === 0) {
                continue;
            }
            if (ring$2 !== polygon[0]) {
                holeIndices.push(flattened.length / 2);
            }
            for (var i = 0; i < ring$2.length; i++) {
                var p$1 = ring$2[i];
                addVertex(this.layoutVertexArray, p$1.x, p$1.y, 0, 0, 1, 1, 0);
                flattened.push(p$1.x);
                flattened.push(p$1.y);
            }
        }
        var indices = earcut_1(flattened, holeIndices);
        for (var j = 0; j < indices.length; j += 3) {
            this.indexArray.emplaceBack(triangleIndex + indices[j], triangleIndex + indices[j + 2], triangleIndex + indices[j + 1]);
        }
        segment.primitiveLength += indices.length / 3;
        segment.vertexLength += numVertices;
    }
    this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, canonical);
};
register('FillExtrusionBucket', FillExtrusionBucket, {
    omit: [
        'layers',
        'features'
    ]
});
function isBoundaryEdge(p1, p2) {
    return p1.x === p2.x && (p1.x < 0 || p1.x > EXTENT$1) || p1.y === p2.y && (p1.y < 0 || p1.y > EXTENT$1);
}
function isEntirelyOutside(ring) {
    return ring.every(function (p) {
        return p.x < 0;
    }) || ring.every(function (p) {
        return p.x > EXTENT$1;
    }) || ring.every(function (p) {
        return p.y < 0;
    }) || ring.every(function (p) {
        return p.y > EXTENT$1;
    });
}

var paint$5 = new Properties({
    'fill-extrusion-opacity': new DataConstantProperty(spec['paint_fill-extrusion']['fill-extrusion-opacity']),
    'fill-extrusion-color': new DataDrivenProperty(spec['paint_fill-extrusion']['fill-extrusion-color']),
    'fill-extrusion-translate': new DataConstantProperty(spec['paint_fill-extrusion']['fill-extrusion-translate']),
    'fill-extrusion-translate-anchor': new DataConstantProperty(spec['paint_fill-extrusion']['fill-extrusion-translate-anchor']),
    'fill-extrusion-pattern': new CrossFadedDataDrivenProperty(spec['paint_fill-extrusion']['fill-extrusion-pattern']),
    'fill-extrusion-height': new DataDrivenProperty(spec['paint_fill-extrusion']['fill-extrusion-height']),
    'fill-extrusion-base': new DataDrivenProperty(spec['paint_fill-extrusion']['fill-extrusion-base']),
    'fill-extrusion-vertical-gradient': new DataConstantProperty(spec['paint_fill-extrusion']['fill-extrusion-vertical-gradient'])
});
var properties$4 = { paint: paint$5 };

var FillExtrusionStyleLayer = function (StyleLayer) {
    function FillExtrusionStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$4);
    }
    if (StyleLayer)
        FillExtrusionStyleLayer.__proto__ = StyleLayer;
    FillExtrusionStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    FillExtrusionStyleLayer.prototype.constructor = FillExtrusionStyleLayer;
    FillExtrusionStyleLayer.prototype.createBucket = function createBucket(parameters) {
        return new FillExtrusionBucket(parameters);
    };
    FillExtrusionStyleLayer.prototype.queryRadius = function queryRadius() {
        return translateDistance(this.paint.get('fill-extrusion-translate'));
    };
    FillExtrusionStyleLayer.prototype.is3D = function is3D() {
        return true;
    };
    FillExtrusionStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature(queryGeometry, feature, featureState, geometry, zoom, transform, pixelsToTileUnits, pixelPosMatrix) {
        var translatedPolygon = translate(queryGeometry, this.paint.get('fill-extrusion-translate'), this.paint.get('fill-extrusion-translate-anchor'), transform.angle, pixelsToTileUnits);
        var height = this.paint.get('fill-extrusion-height').evaluate(feature, featureState);
        var base = this.paint.get('fill-extrusion-base').evaluate(feature, featureState);
        var projectedQueryGeometry = projectQueryGeometry$1(translatedPolygon, pixelPosMatrix, transform, 0);
        var projected = projectExtrusion(geometry, base, height, pixelPosMatrix);
        var projectedBase = projected[0];
        var projectedTop = projected[1];
        return checkIntersection(projectedBase, projectedTop, projectedQueryGeometry);
    };
    return FillExtrusionStyleLayer;
}(StyleLayer);
function dot$2(a, b) {
    return a.x * b.x + a.y * b.y;
}
function getIntersectionDistance(projectedQueryGeometry, projectedFace) {
    if (projectedQueryGeometry.length === 1) {
        var i = 0;
        var a = projectedFace[i++];
        var b;
        while (!b || a.equals(b)) {
            b = projectedFace[i++];
            if (!b) {
                return Infinity;
            }
        }
        for (; i < projectedFace.length; i++) {
            var c = projectedFace[i];
            var p = projectedQueryGeometry[0];
            var ab = b.sub(a);
            var ac = c.sub(a);
            var ap = p.sub(a);
            var dotABAB = dot$2(ab, ab);
            var dotABAC = dot$2(ab, ac);
            var dotACAC = dot$2(ac, ac);
            var dotAPAB = dot$2(ap, ab);
            var dotAPAC = dot$2(ap, ac);
            var denom = dotABAB * dotACAC - dotABAC * dotABAC;
            var v = (dotACAC * dotAPAB - dotABAC * dotAPAC) / denom;
            var w = (dotABAB * dotAPAC - dotABAC * dotAPAB) / denom;
            var u = 1 - v - w;
            var distance = a.z * u + b.z * v + c.z * w;
            if (isFinite(distance)) {
                return distance;
            }
        }
        return Infinity;
    } else {
        var closestDistance = Infinity;
        for (var i$1 = 0, list = projectedFace; i$1 < list.length; i$1 += 1) {
            var p$1 = list[i$1];
            closestDistance = Math.min(closestDistance, p$1.z);
        }
        return closestDistance;
    }
}
function checkIntersection(projectedBase, projectedTop, projectedQueryGeometry) {
    var closestDistance = Infinity;
    if (polygonIntersectsMultiPolygon(projectedQueryGeometry, projectedTop)) {
        closestDistance = getIntersectionDistance(projectedQueryGeometry, projectedTop[0]);
    }
    for (var r = 0; r < projectedTop.length; r++) {
        var ringTop = projectedTop[r];
        var ringBase = projectedBase[r];
        for (var p = 0; p < ringTop.length - 1; p++) {
            var topA = ringTop[p];
            var topB = ringTop[p + 1];
            var baseA = ringBase[p];
            var baseB = ringBase[p + 1];
            var face = [
                topA,
                topB,
                baseB,
                baseA,
                topA
            ];
            if (polygonIntersectsPolygon(projectedQueryGeometry, face)) {
                closestDistance = Math.min(closestDistance, getIntersectionDistance(projectedQueryGeometry, face));
            }
        }
    }
    return closestDistance === Infinity ? false : closestDistance;
}
function projectExtrusion(geometry, zBase, zTop, m) {
    var projectedBase = [];
    var projectedTop = [];
    var baseXZ = m[8] * zBase;
    var baseYZ = m[9] * zBase;
    var baseZZ = m[10] * zBase;
    var baseWZ = m[11] * zBase;
    var topXZ = m[8] * zTop;
    var topYZ = m[9] * zTop;
    var topZZ = m[10] * zTop;
    var topWZ = m[11] * zTop;
    for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
        var r = list$1[i$1];
        var ringBase = [];
        var ringTop = [];
        for (var i = 0, list = r; i < list.length; i += 1) {
            var p = list[i];
            var x = p.x;
            var y = p.y;
            var sX = m[0] * x + m[4] * y + m[12];
            var sY = m[1] * x + m[5] * y + m[13];
            var sZ = m[2] * x + m[6] * y + m[14];
            var sW = m[3] * x + m[7] * y + m[15];
            var baseX = sX + baseXZ;
            var baseY = sY + baseYZ;
            var baseZ = sZ + baseZZ;
            var baseW = sW + baseWZ;
            var topX = sX + topXZ;
            var topY = sY + topYZ;
            var topZ = sZ + topZZ;
            var topW = sW + topWZ;
            var b = new pointGeometry(baseX / baseW, baseY / baseW);
            b.z = baseZ / baseW;
            ringBase.push(b);
            var t = new pointGeometry(topX / topW, topY / topW);
            t.z = topZ / topW;
            ringTop.push(t);
        }
        projectedBase.push(ringBase);
        projectedTop.push(ringTop);
    }
    return [
        projectedBase,
        projectedTop
    ];
}
function projectQueryGeometry$1(queryGeometry, pixelPosMatrix, transform, z) {
    var projectedQueryGeometry = [];
    for (var i = 0, list = queryGeometry; i < list.length; i += 1) {
        var p = list[i];
        var v = [
            p.x,
            p.y,
            z,
            1
        ];
        transformMat4(v, v, pixelPosMatrix);
        projectedQueryGeometry.push(new pointGeometry(v[0] / v[3], v[1] / v[3]));
    }
    return projectedQueryGeometry;
}

var lineLayoutAttributes = createLayout([
    {
        name: 'a_pos_normal',
        components: 2,
        type: 'Int16'
    },
    {
        name: 'a_data',
        components: 4,
        type: 'Uint8'
    }
], 4);
var members$3 = lineLayoutAttributes.members;

var lineLayoutAttributesExt = createLayout([
    {
        name: 'a_uv_x',
        components: 1,
        type: 'Float32'
    },
    {
        name: 'a_split_index',
        components: 1,
        type: 'Float32'
    }
]);
var members$4 = lineLayoutAttributesExt.members;

var vectorTileFeatureTypes$1 = vectorTile.VectorTileFeature.types;
var EXTRUDE_SCALE = 63;
var COS_HALF_SHARP_CORNER = Math.cos(75 / 2 * (Math.PI / 180));
var SHARP_CORNER_OFFSET = 15;
var DEG_PER_TRIANGLE = 20;
var LINE_DISTANCE_BUFFER_BITS = 15;
var LINE_DISTANCE_SCALE = 1 / 2;
var MAX_LINE_DISTANCE = Math.pow(2, LINE_DISTANCE_BUFFER_BITS - 1) / LINE_DISTANCE_SCALE;
var LineBucket = function LineBucket(options) {
    var this$1 = this;
    this.zoom = options.zoom;
    this.overscaling = options.overscaling;
    this.layers = options.layers;
    this.layerIds = this.layers.map(function (layer) {
        return layer.id;
    });
    this.index = options.index;
    this.hasPattern = false;
    this.patternFeatures = [];
    this.lineClipsArray = [];
    this.gradients = {};
    this.layers.forEach(function (layer) {
        this$1.gradients[layer.id] = {};
    });
    this.layoutVertexArray = new StructArrayLayout2i4ub8();
    this.layoutVertexArray2 = new StructArrayLayout2f8();
    this.indexArray = new StructArrayLayout3ui6();
    this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
    this.segments = new SegmentVector();
    this.maxLineLength = 0;
    this.stateDependentLayerIds = this.layers.filter(function (l) {
        return l.isStateDependent();
    }).map(function (l) {
        return l.id;
    });
};
LineBucket.prototype.populate = function populate(features, options, canonical) {
    this.hasPattern = hasPattern('line', this.layers, options);
    var lineSortKey = this.layers[0].layout.get('line-sort-key');
    var bucketFeatures = [];
    for (var i = 0, list = features; i < list.length; i += 1) {
        var ref = list[i];
        var feature = ref.feature;
        var id = ref.id;
        var index = ref.index;
        var sourceLayerIndex = ref.sourceLayerIndex;
        var needGeometry = this.layers[0]._featureFilter.needGeometry;
        var evaluationFeature = toEvaluationFeature(feature, needGeometry);
        if (!this.layers[0]._featureFilter.filter(new EvaluationParameters(this.zoom), evaluationFeature, canonical)) {
            continue;
        }
        var sortKey = lineSortKey ? lineSortKey.evaluate(evaluationFeature, {}, canonical) : undefined;
        var bucketFeature = {
            id: id,
            properties: feature.properties,
            type: feature.type,
            sourceLayerIndex: sourceLayerIndex,
            index: index,
            geometry: needGeometry ? evaluationFeature.geometry : loadGeometry(feature),
            patterns: {},
            sortKey: sortKey
        };
        bucketFeatures.push(bucketFeature);
    }
    if (lineSortKey) {
        bucketFeatures.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
    for (var i$1 = 0, list$1 = bucketFeatures; i$1 < list$1.length; i$1 += 1) {
        var bucketFeature$1 = list$1[i$1];
        var ref$1 = bucketFeature$1;
        var geometry = ref$1.geometry;
        var index$1 = ref$1.index;
        var sourceLayerIndex$1 = ref$1.sourceLayerIndex;
        if (this.hasPattern) {
            var patternBucketFeature = addPatternDependencies('line', this.layers, bucketFeature$1, this.zoom, options);
            this.patternFeatures.push(patternBucketFeature);
        } else {
            this.addFeature(bucketFeature$1, geometry, index$1, canonical, {});
        }
        var feature$1 = features[index$1].feature;
        options.featureIndex.insert(feature$1, geometry, index$1, sourceLayerIndex$1, this.index);
    }
};
LineBucket.prototype.update = function update(states, vtLayer, imagePositions) {
    if (!this.stateDependentLayers.length) {
        return;
    }
    this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
};
LineBucket.prototype.addFeatures = function addFeatures(options, canonical, imagePositions) {
    for (var i = 0, list = this.patternFeatures; i < list.length; i += 1) {
        var feature = list[i];
        this.addFeature(feature, feature.geometry, feature.index, canonical, imagePositions);
    }
};
LineBucket.prototype.isEmpty = function isEmpty() {
    return this.layoutVertexArray.length === 0;
};
LineBucket.prototype.uploadPending = function uploadPending() {
    return !this.uploaded || this.programConfigurations.needsUpload;
};
LineBucket.prototype.upload = function upload(context) {
    if (!this.uploaded) {
        if (this.layoutVertexArray2.length !== 0) {
            this.layoutVertexBuffer2 = context.createVertexBuffer(this.layoutVertexArray2, members$4);
        }
        this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members$3);
        this.indexBuffer = context.createIndexBuffer(this.indexArray);
    }
    this.programConfigurations.upload(context);
    this.uploaded = true;
};
LineBucket.prototype.destroy = function destroy() {
    if (!this.layoutVertexBuffer) {
        return;
    }
    this.layoutVertexBuffer.destroy();
    this.indexBuffer.destroy();
    this.programConfigurations.destroy();
    this.segments.destroy();
};
LineBucket.prototype.lineFeatureClips = function lineFeatureClips(feature) {
    if (!!feature.properties && feature.properties.hasOwnProperty('mapbox_clip_start') && feature.properties.hasOwnProperty('mapbox_clip_end')) {
        var start = +feature.properties['mapbox_clip_start'];
        var end = +feature.properties['mapbox_clip_end'];
        return {
            start: start,
            end: end
        };
    }
};
LineBucket.prototype.addFeature = function addFeature(feature, geometry, index, canonical, imagePositions) {
    var layout = this.layers[0].layout;
    var join = layout.get('line-join').evaluate(feature, {});
    var cap = layout.get('line-cap');
    var miterLimit = layout.get('line-miter-limit');
    var roundLimit = layout.get('line-round-limit');
    this.lineClips = this.lineFeatureClips(feature);
    for (var i = 0, list = geometry; i < list.length; i += 1) {
        var line = list[i];
        this.addLine(line, feature, join, cap, miterLimit, roundLimit);
    }
    this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, canonical);
};
LineBucket.prototype.addLine = function addLine(vertices, feature, join, cap, miterLimit, roundLimit) {
    this.distance = 0;
    this.scaledDistance = 0;
    this.totalDistance = 0;
    if (this.lineClips) {
        this.lineClipsArray.push(this.lineClips);
        for (var i = 0; i < vertices.length - 1; i++) {
            this.totalDistance += vertices[i].dist(vertices[i + 1]);
        }
        this.updateScaledDistance();
        this.maxLineLength = Math.max(this.maxLineLength, this.totalDistance);
    }
    var isPolygon = vectorTileFeatureTypes$1[feature.type] === 'Polygon';
    var len = vertices.length;
    while (len >= 2 && vertices[len - 1].equals(vertices[len - 2])) {
        len--;
    }
    var first = 0;
    while (first < len - 1 && vertices[first].equals(vertices[first + 1])) {
        first++;
    }
    if (len < (isPolygon ? 3 : 2)) {
        return;
    }
    if (join === 'bevel') {
        miterLimit = 1.05;
    }
    var sharpCornerOffset = this.overscaling <= 16 ? SHARP_CORNER_OFFSET * EXTENT$1 / (512 * this.overscaling) : 0;
    var segment = this.segments.prepareSegment(len * 10, this.layoutVertexArray, this.indexArray);
    var currentVertex;
    var prevVertex = undefined;
    var nextVertex = undefined;
    var prevNormal = undefined;
    var nextNormal = undefined;
    this.e1 = this.e2 = -1;
    if (isPolygon) {
        currentVertex = vertices[len - 2];
        nextNormal = vertices[first].sub(currentVertex)._unit()._perp();
    }
    for (var i$1 = first; i$1 < len; i$1++) {
        nextVertex = i$1 === len - 1 ? isPolygon ? vertices[first + 1] : undefined : vertices[i$1 + 1];
        if (nextVertex && vertices[i$1].equals(nextVertex)) {
            continue;
        }
        if (nextNormal) {
            prevNormal = nextNormal;
        }
        if (currentVertex) {
            prevVertex = currentVertex;
        }
        currentVertex = vertices[i$1];
        nextNormal = nextVertex ? nextVertex.sub(currentVertex)._unit()._perp() : prevNormal;
        prevNormal = prevNormal || nextNormal;
        var joinNormal = prevNormal.add(nextNormal);
        if (joinNormal.x !== 0 || joinNormal.y !== 0) {
            joinNormal._unit();
        }
        var cosAngle = prevNormal.x * nextNormal.x + prevNormal.y * nextNormal.y;
        var cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y;
        var miterLength = cosHalfAngle !== 0 ? 1 / cosHalfAngle : Infinity;
        var approxAngle = 2 * Math.sqrt(2 - 2 * cosHalfAngle);
        var isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevVertex && nextVertex;
        var lineTurnsLeft = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x > 0;
        if (isSharpCorner && i$1 > first) {
            var prevSegmentLength = currentVertex.dist(prevVertex);
            if (prevSegmentLength > 2 * sharpCornerOffset) {
                var newPrevVertex = currentVertex.sub(currentVertex.sub(prevVertex)._mult(sharpCornerOffset / prevSegmentLength)._round());
                this.updateDistance(prevVertex, newPrevVertex);
                this.addCurrentVertex(newPrevVertex, prevNormal, 0, 0, segment);
                prevVertex = newPrevVertex;
            }
        }
        var middleVertex = prevVertex && nextVertex;
        var currentJoin = middleVertex ? join : isPolygon ? 'butt' : cap;
        if (middleVertex && currentJoin === 'round') {
            if (miterLength < roundLimit) {
                currentJoin = 'miter';
            } else if (miterLength <= 2) {
                currentJoin = 'fakeround';
            }
        }
        if (currentJoin === 'miter' && miterLength > miterLimit) {
            currentJoin = 'bevel';
        }
        if (currentJoin === 'bevel') {
            if (miterLength > 2) {
                currentJoin = 'flipbevel';
            }
            if (miterLength < miterLimit) {
                currentJoin = 'miter';
            }
        }
        if (prevVertex) {
            this.updateDistance(prevVertex, currentVertex);
        }
        if (currentJoin === 'miter') {
            joinNormal._mult(miterLength);
            this.addCurrentVertex(currentVertex, joinNormal, 0, 0, segment);
        } else if (currentJoin === 'flipbevel') {
            if (miterLength > 100) {
                joinNormal = nextNormal.mult(-1);
            } else {
                var bevelLength = miterLength * prevNormal.add(nextNormal).mag() / prevNormal.sub(nextNormal).mag();
                joinNormal._perp()._mult(bevelLength * (lineTurnsLeft ? -1 : 1));
            }
            this.addCurrentVertex(currentVertex, joinNormal, 0, 0, segment);
            this.addCurrentVertex(currentVertex, joinNormal.mult(-1), 0, 0, segment);
        } else if (currentJoin === 'bevel' || currentJoin === 'fakeround') {
            var offset = -Math.sqrt(miterLength * miterLength - 1);
            var offsetA = lineTurnsLeft ? offset : 0;
            var offsetB = lineTurnsLeft ? 0 : offset;
            if (prevVertex) {
                this.addCurrentVertex(currentVertex, prevNormal, offsetA, offsetB, segment);
            }
            if (currentJoin === 'fakeround') {
                var n = Math.round(approxAngle * 180 / Math.PI / DEG_PER_TRIANGLE);
                for (var m = 1; m < n; m++) {
                    var t = m / n;
                    if (t !== 0.5) {
                        var t2 = t - 0.5;
                        var A = 1.0904 + cosAngle * (-3.2452 + cosAngle * (3.55645 - cosAngle * 1.43519));
                        var B = 0.848013 + cosAngle * (-1.06021 + cosAngle * 0.215638);
                        t = t + t * t2 * (t - 1) * (A * t2 * t2 + B);
                    }
                    var extrude = nextNormal.sub(prevNormal)._mult(t)._add(prevNormal)._unit()._mult(lineTurnsLeft ? -1 : 1);
                    this.addHalfVertex(currentVertex, extrude.x, extrude.y, false, lineTurnsLeft, 0, segment);
                }
            }
            if (nextVertex) {
                this.addCurrentVertex(currentVertex, nextNormal, -offsetA, -offsetB, segment);
            }
        } else if (currentJoin === 'butt') {
            this.addCurrentVertex(currentVertex, joinNormal, 0, 0, segment);
        } else if (currentJoin === 'square') {
            var offset$1 = prevVertex ? 1 : -1;
            this.addCurrentVertex(currentVertex, joinNormal, offset$1, offset$1, segment);
        } else if (currentJoin === 'round') {
            if (prevVertex) {
                this.addCurrentVertex(currentVertex, prevNormal, 0, 0, segment);
                this.addCurrentVertex(currentVertex, prevNormal, 1, 1, segment, true);
            }
            if (nextVertex) {
                this.addCurrentVertex(currentVertex, nextNormal, -1, -1, segment, true);
                this.addCurrentVertex(currentVertex, nextNormal, 0, 0, segment);
            }
        }
        if (isSharpCorner && i$1 < len - 1) {
            var nextSegmentLength = currentVertex.dist(nextVertex);
            if (nextSegmentLength > 2 * sharpCornerOffset) {
                var newCurrentVertex = currentVertex.add(nextVertex.sub(currentVertex)._mult(sharpCornerOffset / nextSegmentLength)._round());
                this.updateDistance(currentVertex, newCurrentVertex);
                this.addCurrentVertex(newCurrentVertex, nextNormal, 0, 0, segment);
                currentVertex = newCurrentVertex;
            }
        }
    }
};
LineBucket.prototype.addCurrentVertex = function addCurrentVertex(p, normal, endLeft, endRight, segment, round) {
    if (round === void 0)
        round = false;
    var leftX = normal.x + normal.y * endLeft;
    var leftY = normal.y - normal.x * endLeft;
    var rightX = -normal.x + normal.y * endRight;
    var rightY = -normal.y - normal.x * endRight;
    this.addHalfVertex(p, leftX, leftY, round, false, endLeft, segment);
    this.addHalfVertex(p, rightX, rightY, round, true, -endRight, segment);
    if (this.distance > MAX_LINE_DISTANCE / 2 && this.totalDistance === 0) {
        this.distance = 0;
        this.addCurrentVertex(p, normal, endLeft, endRight, segment, round);
    }
};
LineBucket.prototype.addHalfVertex = function addHalfVertex(ref, extrudeX, extrudeY, round, up, dir, segment) {
    var x = ref.x;
    var y = ref.y;
    var totalDistance = this.lineClips ? this.scaledDistance * (MAX_LINE_DISTANCE - 1) : this.scaledDistance;
    var linesofarScaled = totalDistance * LINE_DISTANCE_SCALE;
    this.layoutVertexArray.emplaceBack((x << 1) + (round ? 1 : 0), (y << 1) + (up ? 1 : 0), Math.round(EXTRUDE_SCALE * extrudeX) + 128, Math.round(EXTRUDE_SCALE * extrudeY) + 128, (dir === 0 ? 0 : dir < 0 ? -1 : 1) + 1 | (linesofarScaled & 63) << 2, linesofarScaled >> 6);
    if (this.lineClips) {
        var progressRealigned = this.scaledDistance - this.lineClips.start;
        var endClipRealigned = this.lineClips.end - this.lineClips.start;
        var uvX = progressRealigned / endClipRealigned;
        this.layoutVertexArray2.emplaceBack(uvX, this.lineClipsArray.length);
    }
    var e = segment.vertexLength++;
    if (this.e1 >= 0 && this.e2 >= 0) {
        this.indexArray.emplaceBack(this.e1, this.e2, e);
        segment.primitiveLength++;
    }
    if (up) {
        this.e2 = e;
    } else {
        this.e1 = e;
    }
};
LineBucket.prototype.updateScaledDistance = function updateScaledDistance() {
    this.scaledDistance = this.lineClips ? this.lineClips.start + (this.lineClips.end - this.lineClips.start) * this.distance / this.totalDistance : this.distance;
};
LineBucket.prototype.updateDistance = function updateDistance(prev, next) {
    this.distance += prev.dist(next);
    this.updateScaledDistance();
};
register('LineBucket', LineBucket, {
    omit: [
        'layers',
        'patternFeatures'
    ]
});

var layout$6 = new Properties({
    'line-cap': new DataConstantProperty(spec['layout_line']['line-cap']),
    'line-join': new DataDrivenProperty(spec['layout_line']['line-join']),
    'line-miter-limit': new DataConstantProperty(spec['layout_line']['line-miter-limit']),
    'line-round-limit': new DataConstantProperty(spec['layout_line']['line-round-limit']),
    'line-sort-key': new DataDrivenProperty(spec['layout_line']['line-sort-key'])
});
var paint$6 = new Properties({
    'line-opacity': new DataDrivenProperty(spec['paint_line']['line-opacity']),
    'line-color': new DataDrivenProperty(spec['paint_line']['line-color']),
    'line-translate': new DataConstantProperty(spec['paint_line']['line-translate']),
    'line-translate-anchor': new DataConstantProperty(spec['paint_line']['line-translate-anchor']),
    'line-width': new DataDrivenProperty(spec['paint_line']['line-width']),
    'line-gap-width': new DataDrivenProperty(spec['paint_line']['line-gap-width']),
    'line-offset': new DataDrivenProperty(spec['paint_line']['line-offset']),
    'line-blur': new DataDrivenProperty(spec['paint_line']['line-blur']),
    'line-dasharray': new CrossFadedProperty(spec['paint_line']['line-dasharray']),
    'line-pattern': new CrossFadedDataDrivenProperty(spec['paint_line']['line-pattern']),
    'line-gradient': new ColorRampProperty(spec['paint_line']['line-gradient'])
});
var properties$5 = {
    paint: paint$6,
    layout: layout$6
};

var LineFloorwidthProperty = function (DataDrivenProperty) {
    function LineFloorwidthProperty() {
        DataDrivenProperty.apply(this, arguments);
    }
    if (DataDrivenProperty)
        LineFloorwidthProperty.__proto__ = DataDrivenProperty;
    LineFloorwidthProperty.prototype = Object.create(DataDrivenProperty && DataDrivenProperty.prototype);
    LineFloorwidthProperty.prototype.constructor = LineFloorwidthProperty;
    LineFloorwidthProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters) {
        parameters = new EvaluationParameters(Math.floor(parameters.zoom), {
            now: parameters.now,
            fadeDuration: parameters.fadeDuration,
            zoomHistory: parameters.zoomHistory,
            transition: parameters.transition
        });
        return DataDrivenProperty.prototype.possiblyEvaluate.call(this, value, parameters);
    };
    LineFloorwidthProperty.prototype.evaluate = function evaluate(value, globals, feature, featureState) {
        globals = extend({}, globals, { zoom: Math.floor(globals.zoom) });
        return DataDrivenProperty.prototype.evaluate.call(this, value, globals, feature, featureState);
    };
    return LineFloorwidthProperty;
}(DataDrivenProperty);
var lineFloorwidthProperty = new LineFloorwidthProperty(properties$5.paint.properties['line-width'].specification);
lineFloorwidthProperty.useIntegerZoom = true;
var LineStyleLayer = function (StyleLayer) {
    function LineStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$5);
        this.gradientVersion = 0;
    }
    if (StyleLayer)
        LineStyleLayer.__proto__ = StyleLayer;
    LineStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    LineStyleLayer.prototype.constructor = LineStyleLayer;
    LineStyleLayer.prototype._handleSpecialPaintPropertyUpdate = function _handleSpecialPaintPropertyUpdate(name) {
        if (name === 'line-gradient') {
            var expression = this._transitionablePaint._values['line-gradient'].value.expression;
            this.stepInterpolant = expression._styleExpression.expression instanceof Step;
            this.gradientVersion = (this.gradientVersion + 1) % MAX_SAFE_INTEGER;
        }
    };
    LineStyleLayer.prototype.gradientExpression = function gradientExpression() {
        return this._transitionablePaint._values['line-gradient'].value.expression;
    };
    LineStyleLayer.prototype.recalculate = function recalculate(parameters, availableImages) {
        StyleLayer.prototype.recalculate.call(this, parameters, availableImages);
        this.paint._values['line-floorwidth'] = lineFloorwidthProperty.possiblyEvaluate(this._transitioningPaint._values['line-width'].value, parameters);
    };
    LineStyleLayer.prototype.createBucket = function createBucket(parameters) {
        return new LineBucket(parameters);
    };
    LineStyleLayer.prototype.queryRadius = function queryRadius(bucket) {
        var lineBucket = bucket;
        var width = getLineWidth(getMaximumPaintValue('line-width', this, lineBucket), getMaximumPaintValue('line-gap-width', this, lineBucket));
        var offset = getMaximumPaintValue('line-offset', this, lineBucket);
        return width / 2 + Math.abs(offset) + translateDistance(this.paint.get('line-translate'));
    };
    LineStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature(queryGeometry, feature, featureState, geometry, zoom, transform, pixelsToTileUnits) {
        var translatedPolygon = translate(queryGeometry, this.paint.get('line-translate'), this.paint.get('line-translate-anchor'), transform.angle, pixelsToTileUnits);
        var halfWidth = pixelsToTileUnits / 2 * getLineWidth(this.paint.get('line-width').evaluate(feature, featureState), this.paint.get('line-gap-width').evaluate(feature, featureState));
        var lineOffset = this.paint.get('line-offset').evaluate(feature, featureState);
        if (lineOffset) {
            geometry = offsetLine(geometry, lineOffset * pixelsToTileUnits);
        }
        return polygonIntersectsBufferedMultiLine(translatedPolygon, geometry, halfWidth);
    };
    LineStyleLayer.prototype.isTileClipped = function isTileClipped() {
        return true;
    };
    return LineStyleLayer;
}(StyleLayer);
function getLineWidth(lineWidth, lineGapWidth) {
    if (lineGapWidth > 0) {
        return lineGapWidth + 2 * lineWidth;
    } else {
        return lineWidth;
    }
}
function offsetLine(rings, offset) {
    var newRings = [];
    var zero = new pointGeometry(0, 0);
    for (var k = 0; k < rings.length; k++) {
        var ring = rings[k];
        var newRing = [];
        for (var i = 0; i < ring.length; i++) {
            var a = ring[i - 1];
            var b = ring[i];
            var c = ring[i + 1];
            var aToB = i === 0 ? zero : b.sub(a)._unit()._perp();
            var bToC = i === ring.length - 1 ? zero : c.sub(b)._unit()._perp();
            var extrude = aToB._add(bToC)._unit();
            var cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y;
            extrude._mult(1 / cosHalfAngle);
            newRing.push(extrude._mult(offset)._add(b));
        }
        newRings.push(newRing);
    }
    return newRings;
}

var symbolLayoutAttributes = createLayout([
    {
        name: 'a_pos_offset',
        components: 4,
        type: 'Int16'
    },
    {
        name: 'a_data',
        components: 4,
        type: 'Uint16'
    },
    {
        name: 'a_pixeloffset',
        components: 4,
        type: 'Int16'
    }
], 4);
var dynamicLayoutAttributes = createLayout([{
        name: 'a_projected_pos',
        components: 3,
        type: 'Float32'
    }], 4);
var placementOpacityAttributes = createLayout([{
        name: 'a_fade_opacity',
        components: 1,
        type: 'Uint32'
    }], 4);
var collisionVertexAttributes = createLayout([
    {
        name: 'a_placed',
        components: 2,
        type: 'Uint8'
    },
    {
        name: 'a_shift',
        components: 2,
        type: 'Float32'
    }
]);
var collisionBox = createLayout([
    {
        type: 'Int16',
        name: 'anchorPointX'
    },
    {
        type: 'Int16',
        name: 'anchorPointY'
    },
    {
        type: 'Int16',
        name: 'x1'
    },
    {
        type: 'Int16',
        name: 'y1'
    },
    {
        type: 'Int16',
        name: 'x2'
    },
    {
        type: 'Int16',
        name: 'y2'
    },
    {
        type: 'Uint32',
        name: 'featureIndex'
    },
    {
        type: 'Uint16',
        name: 'sourceLayerIndex'
    },
    {
        type: 'Uint16',
        name: 'bucketIndex'
    }
]);
var collisionBoxLayout = createLayout([
    {
        name: 'a_pos',
        components: 2,
        type: 'Int16'
    },
    {
        name: 'a_anchor_pos',
        components: 2,
        type: 'Int16'
    },
    {
        name: 'a_extrude',
        components: 2,
        type: 'Int16'
    }
], 4);
var collisionCircleLayout = createLayout([
    {
        name: 'a_pos',
        components: 2,
        type: 'Float32'
    },
    {
        name: 'a_radius',
        components: 1,
        type: 'Float32'
    },
    {
        name: 'a_flags',
        components: 2,
        type: 'Int16'
    }
], 4);
var quadTriangle = createLayout([{
        name: 'triangle',
        components: 3,
        type: 'Uint16'
    }]);
var placement = createLayout([
    {
        type: 'Int16',
        name: 'anchorX'
    },
    {
        type: 'Int16',
        name: 'anchorY'
    },
    {
        type: 'Uint16',
        name: 'glyphStartIndex'
    },
    {
        type: 'Uint16',
        name: 'numGlyphs'
    },
    {
        type: 'Uint32',
        name: 'vertexStartIndex'
    },
    {
        type: 'Uint32',
        name: 'lineStartIndex'
    },
    {
        type: 'Uint32',
        name: 'lineLength'
    },
    {
        type: 'Uint16',
        name: 'segment'
    },
    {
        type: 'Uint16',
        name: 'lowerSize'
    },
    {
        type: 'Uint16',
        name: 'upperSize'
    },
    {
        type: 'Float32',
        name: 'lineOffsetX'
    },
    {
        type: 'Float32',
        name: 'lineOffsetY'
    },
    {
        type: 'Uint8',
        name: 'writingMode'
    },
    {
        type: 'Uint8',
        name: 'placedOrientation'
    },
    {
        type: 'Uint8',
        name: 'hidden'
    },
    {
        type: 'Uint32',
        name: 'crossTileID'
    },
    {
        type: 'Int16',
        name: 'associatedIconIndex'
    }
]);
var symbolInstance = createLayout([
    {
        type: 'Int16',
        name: 'anchorX'
    },
    {
        type: 'Int16',
        name: 'anchorY'
    },
    {
        type: 'Int16',
        name: 'rightJustifiedTextSymbolIndex'
    },
    {
        type: 'Int16',
        name: 'centerJustifiedTextSymbolIndex'
    },
    {
        type: 'Int16',
        name: 'leftJustifiedTextSymbolIndex'
    },
    {
        type: 'Int16',
        name: 'verticalPlacedTextSymbolIndex'
    },
    {
        type: 'Int16',
        name: 'placedIconSymbolIndex'
    },
    {
        type: 'Int16',
        name: 'verticalPlacedIconSymbolIndex'
    },
    {
        type: 'Uint16',
        name: 'key'
    },
    {
        type: 'Uint16',
        name: 'textBoxStartIndex'
    },
    {
        type: 'Uint16',
        name: 'textBoxEndIndex'
    },
    {
        type: 'Uint16',
        name: 'verticalTextBoxStartIndex'
    },
    {
        type: 'Uint16',
        name: 'verticalTextBoxEndIndex'
    },
    {
        type: 'Uint16',
        name: 'iconBoxStartIndex'
    },
    {
        type: 'Uint16',
        name: 'iconBoxEndIndex'
    },
    {
        type: 'Uint16',
        name: 'verticalIconBoxStartIndex'
    },
    {
        type: 'Uint16',
        name: 'verticalIconBoxEndIndex'
    },
    {
        type: 'Uint16',
        name: 'featureIndex'
    },
    {
        type: 'Uint16',
        name: 'numHorizontalGlyphVertices'
    },
    {
        type: 'Uint16',
        name: 'numVerticalGlyphVertices'
    },
    {
        type: 'Uint16',
        name: 'numIconVertices'
    },
    {
        type: 'Uint16',
        name: 'numVerticalIconVertices'
    },
    {
        type: 'Uint16',
        name: 'useRuntimeCollisionCircles'
    },
    {
        type: 'Uint32',
        name: 'crossTileID'
    },
    {
        type: 'Float32',
        name: 'textBoxScale'
    },
    {
        type: 'Float32',
        components: 2,
        name: 'textOffset'
    },
    {
        type: 'Float32',
        name: 'collisionCircleDiameter'
    }
]);
var glyphOffset = createLayout([{
        type: 'Float32',
        name: 'offsetX'
    }]);
var lineVertex = createLayout([
    {
        type: 'Int16',
        name: 'x'
    },
    {
        type: 'Int16',
        name: 'y'
    },
    {
        type: 'Int16',
        name: 'tileUnitDistanceFromAnchor'
    }
]);

function transformText(text, layer, feature) {
    var transform = layer.layout.get('text-transform').evaluate(feature, {});
    if (transform === 'uppercase') {
        text = text.toLocaleUpperCase();
    } else if (transform === 'lowercase') {
        text = text.toLocaleLowerCase();
    }
    if (plugin.applyArabicShaping) {
        text = plugin.applyArabicShaping(text);
    }
    return text;
}
function transformText$1 (text, layer, feature) {
    text.sections.forEach(function (section) {
        section.text = transformText(section.text, layer, feature);
    });
    return text;
}

function mergeLines (features) {
    var leftIndex = {};
    var rightIndex = {};
    var mergedFeatures = [];
    var mergedIndex = 0;
    function add(k) {
        mergedFeatures.push(features[k]);
        mergedIndex++;
    }
    function mergeFromRight(leftKey, rightKey, geom) {
        var i = rightIndex[leftKey];
        delete rightIndex[leftKey];
        rightIndex[rightKey] = i;
        mergedFeatures[i].geometry[0].pop();
        mergedFeatures[i].geometry[0] = mergedFeatures[i].geometry[0].concat(geom[0]);
        return i;
    }
    function mergeFromLeft(leftKey, rightKey, geom) {
        var i = leftIndex[rightKey];
        delete leftIndex[rightKey];
        leftIndex[leftKey] = i;
        mergedFeatures[i].geometry[0].shift();
        mergedFeatures[i].geometry[0] = geom[0].concat(mergedFeatures[i].geometry[0]);
        return i;
    }
    function getKey(text, geom, onRight) {
        var point = onRight ? geom[0][geom[0].length - 1] : geom[0][0];
        return text + ':' + point.x + ':' + point.y;
    }
    for (var k = 0; k < features.length; k++) {
        var feature = features[k];
        var geom = feature.geometry;
        var text = feature.text ? feature.text.toString() : null;
        if (!text) {
            add(k);
            continue;
        }
        var leftKey = getKey(text, geom), rightKey = getKey(text, geom, true);
        if (leftKey in rightIndex && rightKey in leftIndex && rightIndex[leftKey] !== leftIndex[rightKey]) {
            var j = mergeFromLeft(leftKey, rightKey, geom);
            var i = mergeFromRight(leftKey, rightKey, mergedFeatures[j].geometry);
            delete leftIndex[leftKey];
            delete rightIndex[rightKey];
            rightIndex[getKey(text, mergedFeatures[i].geometry, true)] = i;
            mergedFeatures[j].geometry = null;
        } else if (leftKey in rightIndex) {
            mergeFromRight(leftKey, rightKey, geom);
        } else if (rightKey in leftIndex) {
            mergeFromLeft(leftKey, rightKey, geom);
        } else {
            add(k);
            leftIndex[leftKey] = mergedIndex - 1;
            rightIndex[rightKey] = mergedIndex - 1;
        }
    }
    return mergedFeatures.filter(function (f) {
        return f.geometry;
    });
}

var verticalizedCharacterMap = {
    '!': '\uFE15',
    '#': '\uFF03',
    '$': '\uFF04',
    '%': '\uFF05',
    '&': '\uFF06',
    '(': '\uFE35',
    ')': '\uFE36',
    '*': '\uFF0A',
    '+': '\uFF0B',
    ',': '\uFE10',
    '-': '\uFE32',
    '.': '\u30FB',
    '/': '\uFF0F',
    ':': '\uFE13',
    ';': '\uFE14',
    '<': '\uFE3F',
    '=': '\uFF1D',
    '>': '\uFE40',
    '?': '\uFE16',
    '@': '\uFF20',
    '[': '\uFE47',
    '\\': '\uFF3C',
    ']': '\uFE48',
    '^': '\uFF3E',
    '_': '︳',
    '`': '\uFF40',
    '{': '\uFE37',
    '|': '\u2015',
    '}': '\uFE38',
    '~': '\uFF5E',
    '\xA2': '\uFFE0',
    '\xA3': '\uFFE1',
    '\xA5': '\uFFE5',
    '\xA6': '\uFFE4',
    '\xAC': '\uFFE2',
    '\xAF': '\uFFE3',
    '\u2013': '\uFE32',
    '\u2014': '\uFE31',
    '\u2018': '\uFE43',
    '\u2019': '\uFE44',
    '\u201C': '\uFE41',
    '\u201D': '\uFE42',
    '\u2026': '\uFE19',
    '\u2027': '\u30FB',
    '\u20A9': '\uFFE6',
    '\u3001': '\uFE11',
    '\u3002': '\uFE12',
    '\u3008': '\uFE3F',
    '\u3009': '\uFE40',
    '\u300A': '\uFE3D',
    '\u300B': '\uFE3E',
    '\u300C': '\uFE41',
    '\u300D': '\uFE42',
    '\u300E': '\uFE43',
    '\u300F': '\uFE44',
    '\u3010': '\uFE3B',
    '\u3011': '\uFE3C',
    '\u3014': '\uFE39',
    '\u3015': '\uFE3A',
    '\u3016': '\uFE17',
    '\u3017': '\uFE18',
    '\uFF01': '\uFE15',
    '\uFF08': '\uFE35',
    '\uFF09': '\uFE36',
    '\uFF0C': '\uFE10',
    '\uFF0D': '\uFE32',
    '\uFF0E': '\u30FB',
    '\uFF1A': '\uFE13',
    '\uFF1B': '\uFE14',
    '\uFF1C': '\uFE3F',
    '\uFF1E': '\uFE40',
    '\uFF1F': '\uFE16',
    '\uFF3B': '\uFE47',
    '\uFF3D': '\uFE48',
    '＿': '︳',
    '\uFF5B': '\uFE37',
    '\uFF5C': '\u2015',
    '\uFF5D': '\uFE38',
    '\uFF5F': '\uFE35',
    '\uFF60': '\uFE36',
    '\uFF61': '\uFE12',
    '\uFF62': '\uFE41',
    '\uFF63': '\uFE42'
};
function verticalizePunctuation(input) {
    var output = '';
    for (var i = 0; i < input.length; i++) {
        var nextCharCode = input.charCodeAt(i + 1) || null;
        var prevCharCode = input.charCodeAt(i - 1) || null;
        var canReplacePunctuation = (!nextCharCode || !charHasRotatedVerticalOrientation(nextCharCode) || verticalizedCharacterMap[input[i + 1]]) && (!prevCharCode || !charHasRotatedVerticalOrientation(prevCharCode) || verticalizedCharacterMap[input[i - 1]]);
        if (canReplacePunctuation && verticalizedCharacterMap[input[i]]) {
            output += verticalizedCharacterMap[input[i]];
        } else {
            output += input[i];
        }
    }
    return output;
}

var ONE_EM = 24;

var read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m;
    var eLen = nBytes * 8 - mLen - 1;
    var eMax = (1 << eLen) - 1;
    var eBias = eMax >> 1;
    var nBits = -7;
    var i = isLE ? nBytes - 1 : 0;
    var d = isLE ? -1 : 1;
    var s = buffer[offset + i];
    i += d;
    e = s & (1 << -nBits) - 1;
    s >>= -nBits;
    nBits += eLen;
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {
    }
    m = e & (1 << -nBits) - 1;
    e >>= -nBits;
    nBits += mLen;
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {
    }
    if (e === 0) {
        e = 1 - eBias;
    } else if (e === eMax) {
        return m ? NaN : (s ? -1 : 1) * Infinity;
    } else {
        m = m + Math.pow(2, mLen);
        e = e - eBias;
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
var write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c;
    var eLen = nBytes * 8 - mLen - 1;
    var eMax = (1 << eLen) - 1;
    var eBias = eMax >> 1;
    var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
    var i = isLE ? 0 : nBytes - 1;
    var d = isLE ? 1 : -1;
    var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;
    value = Math.abs(value);
    if (isNaN(value) || value === Infinity) {
        m = isNaN(value) ? 1 : 0;
        e = eMax;
    } else {
        e = Math.floor(Math.log(value) / Math.LN2);
        if (value * (c = Math.pow(2, -e)) < 1) {
            e--;
            c *= 2;
        }
        if (e + eBias >= 1) {
            value += rt / c;
        } else {
            value += rt * Math.pow(2, 1 - eBias);
        }
        if (value * c >= 2) {
            e++;
            c /= 2;
        }
        if (e + eBias >= eMax) {
            m = 0;
            e = eMax;
        } else if (e + eBias >= 1) {
            m = (value * c - 1) * Math.pow(2, mLen);
            e = e + eBias;
        } else {
            m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
            e = 0;
        }
    }
    for (; mLen >= 8; buffer[offset + i] = m & 255, i += d, m /= 256, mLen -= 8) {
    }
    e = e << mLen | m;
    eLen += mLen;
    for (; eLen > 0; buffer[offset + i] = e & 255, i += d, e /= 256, eLen -= 8) {
    }
    buffer[offset + i - d] |= s * 128;
};

var ieee754 = {
	read: read,
	write: write
};

var pbf = Pbf;

function Pbf(buf) {
    this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
    this.pos = 0;
    this.type = 0;
    this.length = this.buf.length;
}
Pbf.Varint = 0;
Pbf.Fixed64 = 1;
Pbf.Bytes = 2;
Pbf.Fixed32 = 5;
var SHIFT_LEFT_32 = (1 << 16) * (1 << 16), SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
var TEXT_DECODER_MIN_LENGTH = 12;
var utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');
Pbf.prototype = {
    destroy: function () {
        this.buf = null;
    },
    readFields: function (readField, result, end) {
        end = end || this.length;
        while (this.pos < end) {
            var val = this.readVarint(), tag = val >> 3, startPos = this.pos;
            this.type = val & 7;
            readField(tag, result, this);
            if (this.pos === startPos) {
                this.skip(val);
            }
        }
        return result;
    },
    readMessage: function (readField, result) {
        return this.readFields(readField, result, this.readVarint() + this.pos);
    },
    readFixed32: function () {
        var val = readUInt32(this.buf, this.pos);
        this.pos += 4;
        return val;
    },
    readSFixed32: function () {
        var val = readInt32(this.buf, this.pos);
        this.pos += 4;
        return val;
    },
    readFixed64: function () {
        var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
        this.pos += 8;
        return val;
    },
    readSFixed64: function () {
        var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
        this.pos += 8;
        return val;
    },
    readFloat: function () {
        var val = ieee754.read(this.buf, this.pos, true, 23, 4);
        this.pos += 4;
        return val;
    },
    readDouble: function () {
        var val = ieee754.read(this.buf, this.pos, true, 52, 8);
        this.pos += 8;
        return val;
    },
    readVarint: function (isSigned) {
        var buf = this.buf, val, b;
        b = buf[this.pos++];
        val = b & 127;
        if (b < 128) {
            return val;
        }
        b = buf[this.pos++];
        val |= (b & 127) << 7;
        if (b < 128) {
            return val;
        }
        b = buf[this.pos++];
        val |= (b & 127) << 14;
        if (b < 128) {
            return val;
        }
        b = buf[this.pos++];
        val |= (b & 127) << 21;
        if (b < 128) {
            return val;
        }
        b = buf[this.pos];
        val |= (b & 15) << 28;
        return readVarintRemainder(val, isSigned, this);
    },
    readVarint64: function () {
        return this.readVarint(true);
    },
    readSVarint: function () {
        var num = this.readVarint();
        return num % 2 === 1 ? (num + 1) / -2 : num / 2;
    },
    readBoolean: function () {
        return Boolean(this.readVarint());
    },
    readString: function () {
        var end = this.readVarint() + this.pos;
        var pos = this.pos;
        this.pos = end;
        if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
            return readUtf8TextDecoder(this.buf, pos, end);
        }
        return readUtf8(this.buf, pos, end);
    },
    readBytes: function () {
        var end = this.readVarint() + this.pos, buffer = this.buf.subarray(this.pos, end);
        this.pos = end;
        return buffer;
    },
    readPackedVarint: function (arr, isSigned) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readVarint(isSigned));
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readVarint(isSigned));
        }
        return arr;
    },
    readPackedSVarint: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readSVarint());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readSVarint());
        }
        return arr;
    },
    readPackedBoolean: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readBoolean());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readBoolean());
        }
        return arr;
    },
    readPackedFloat: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readFloat());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readFloat());
        }
        return arr;
    },
    readPackedDouble: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readDouble());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readDouble());
        }
        return arr;
    },
    readPackedFixed32: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readFixed32());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readFixed32());
        }
        return arr;
    },
    readPackedSFixed32: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readSFixed32());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readSFixed32());
        }
        return arr;
    },
    readPackedFixed64: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readFixed64());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readFixed64());
        }
        return arr;
    },
    readPackedSFixed64: function (arr) {
        if (this.type !== Pbf.Bytes) {
            return arr.push(this.readSFixed64());
        }
        var end = readPackedEnd(this);
        arr = arr || [];
        while (this.pos < end) {
            arr.push(this.readSFixed64());
        }
        return arr;
    },
    skip: function (val) {
        var type = val & 7;
        if (type === Pbf.Varint) {
            while (this.buf[this.pos++] > 127) {
            }
        } else if (type === Pbf.Bytes) {
            this.pos = this.readVarint() + this.pos;
        } else if (type === Pbf.Fixed32) {
            this.pos += 4;
        } else if (type === Pbf.Fixed64) {
            this.pos += 8;
        } else {
            throw new Error('Unimplemented type: ' + type);
        }
    },
    writeTag: function (tag, type) {
        this.writeVarint(tag << 3 | type);
    },
    realloc: function (min) {
        var length = this.length || 16;
        while (length < this.pos + min) {
            length *= 2;
        }
        if (length !== this.length) {
            var buf = new Uint8Array(length);
            buf.set(this.buf);
            this.buf = buf;
            this.length = length;
        }
    },
    finish: function () {
        this.length = this.pos;
        this.pos = 0;
        return this.buf.subarray(0, this.length);
    },
    writeFixed32: function (val) {
        this.realloc(4);
        writeInt32(this.buf, val, this.pos);
        this.pos += 4;
    },
    writeSFixed32: function (val) {
        this.realloc(4);
        writeInt32(this.buf, val, this.pos);
        this.pos += 4;
    },
    writeFixed64: function (val) {
        this.realloc(8);
        writeInt32(this.buf, val & -1, this.pos);
        writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
        this.pos += 8;
    },
    writeSFixed64: function (val) {
        this.realloc(8);
        writeInt32(this.buf, val & -1, this.pos);
        writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
        this.pos += 8;
    },
    writeVarint: function (val) {
        val = +val || 0;
        if (val > 268435455 || val < 0) {
            writeBigVarint(val, this);
            return;
        }
        this.realloc(4);
        this.buf[this.pos++] = val & 127 | (val > 127 ? 128 : 0);
        if (val <= 127) {
            return;
        }
        this.buf[this.pos++] = (val >>>= 7) & 127 | (val > 127 ? 128 : 0);
        if (val <= 127) {
            return;
        }
        this.buf[this.pos++] = (val >>>= 7) & 127 | (val > 127 ? 128 : 0);
        if (val <= 127) {
            return;
        }
        this.buf[this.pos++] = val >>> 7 & 127;
    },
    writeSVarint: function (val) {
        this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
    },
    writeBoolean: function (val) {
        this.writeVarint(Boolean(val));
    },
    writeString: function (str) {
        str = String(str);
        this.realloc(str.length * 4);
        this.pos++;
        var startPos = this.pos;
        this.pos = writeUtf8(this.buf, str, this.pos);
        var len = this.pos - startPos;
        if (len >= 128) {
            makeRoomForExtraLength(startPos, len, this);
        }
        this.pos = startPos - 1;
        this.writeVarint(len);
        this.pos += len;
    },
    writeFloat: function (val) {
        this.realloc(4);
        ieee754.write(this.buf, val, this.pos, true, 23, 4);
        this.pos += 4;
    },
    writeDouble: function (val) {
        this.realloc(8);
        ieee754.write(this.buf, val, this.pos, true, 52, 8);
        this.pos += 8;
    },
    writeBytes: function (buffer) {
        var len = buffer.length;
        this.writeVarint(len);
        this.realloc(len);
        for (var i = 0; i < len; i++) {
            this.buf[this.pos++] = buffer[i];
        }
    },
    writeRawMessage: function (fn, obj) {
        this.pos++;
        var startPos = this.pos;
        fn(obj, this);
        var len = this.pos - startPos;
        if (len >= 128) {
            makeRoomForExtraLength(startPos, len, this);
        }
        this.pos = startPos - 1;
        this.writeVarint(len);
        this.pos += len;
    },
    writeMessage: function (tag, fn, obj) {
        this.writeTag(tag, Pbf.Bytes);
        this.writeRawMessage(fn, obj);
    },
    writePackedVarint: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedVarint, arr);
        }
    },
    writePackedSVarint: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedSVarint, arr);
        }
    },
    writePackedBoolean: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedBoolean, arr);
        }
    },
    writePackedFloat: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedFloat, arr);
        }
    },
    writePackedDouble: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedDouble, arr);
        }
    },
    writePackedFixed32: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedFixed32, arr);
        }
    },
    writePackedSFixed32: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedSFixed32, arr);
        }
    },
    writePackedFixed64: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedFixed64, arr);
        }
    },
    writePackedSFixed64: function (tag, arr) {
        if (arr.length) {
            this.writeMessage(tag, writePackedSFixed64, arr);
        }
    },
    writeBytesField: function (tag, buffer) {
        this.writeTag(tag, Pbf.Bytes);
        this.writeBytes(buffer);
    },
    writeFixed32Field: function (tag, val) {
        this.writeTag(tag, Pbf.Fixed32);
        this.writeFixed32(val);
    },
    writeSFixed32Field: function (tag, val) {
        this.writeTag(tag, Pbf.Fixed32);
        this.writeSFixed32(val);
    },
    writeFixed64Field: function (tag, val) {
        this.writeTag(tag, Pbf.Fixed64);
        this.writeFixed64(val);
    },
    writeSFixed64Field: function (tag, val) {
        this.writeTag(tag, Pbf.Fixed64);
        this.writeSFixed64(val);
    },
    writeVarintField: function (tag, val) {
        this.writeTag(tag, Pbf.Varint);
        this.writeVarint(val);
    },
    writeSVarintField: function (tag, val) {
        this.writeTag(tag, Pbf.Varint);
        this.writeSVarint(val);
    },
    writeStringField: function (tag, str) {
        this.writeTag(tag, Pbf.Bytes);
        this.writeString(str);
    },
    writeFloatField: function (tag, val) {
        this.writeTag(tag, Pbf.Fixed32);
        this.writeFloat(val);
    },
    writeDoubleField: function (tag, val) {
        this.writeTag(tag, Pbf.Fixed64);
        this.writeDouble(val);
    },
    writeBooleanField: function (tag, val) {
        this.writeVarintField(tag, Boolean(val));
    }
};
function readVarintRemainder(l, s, p) {
    var buf = p.buf, h, b;
    b = buf[p.pos++];
    h = (b & 112) >> 4;
    if (b < 128) {
        return toNum(l, h, s);
    }
    b = buf[p.pos++];
    h |= (b & 127) << 3;
    if (b < 128) {
        return toNum(l, h, s);
    }
    b = buf[p.pos++];
    h |= (b & 127) << 10;
    if (b < 128) {
        return toNum(l, h, s);
    }
    b = buf[p.pos++];
    h |= (b & 127) << 17;
    if (b < 128) {
        return toNum(l, h, s);
    }
    b = buf[p.pos++];
    h |= (b & 127) << 24;
    if (b < 128) {
        return toNum(l, h, s);
    }
    b = buf[p.pos++];
    h |= (b & 1) << 31;
    if (b < 128) {
        return toNum(l, h, s);
    }
    throw new Error('Expected varint not more than 10 bytes');
}
function readPackedEnd(pbf) {
    return pbf.type === Pbf.Bytes ? pbf.readVarint() + pbf.pos : pbf.pos + 1;
}
function toNum(low, high, isSigned) {
    if (isSigned) {
        return high * 4294967296 + (low >>> 0);
    }
    return (high >>> 0) * 4294967296 + (low >>> 0);
}
function writeBigVarint(val, pbf) {
    var low, high;
    if (val >= 0) {
        low = val % 4294967296 | 0;
        high = val / 4294967296 | 0;
    } else {
        low = ~(-val % 4294967296);
        high = ~(-val / 4294967296);
        if (low ^ 4294967295) {
            low = low + 1 | 0;
        } else {
            low = 0;
            high = high + 1 | 0;
        }
    }
    if (val >= 18446744073709552000 || val < -18446744073709552000) {
        throw new Error('Given varint doesn\'t fit into 10 bytes');
    }
    pbf.realloc(10);
    writeBigVarintLow(low, high, pbf);
    writeBigVarintHigh(high, pbf);
}
function writeBigVarintLow(low, high, pbf) {
    pbf.buf[pbf.pos++] = low & 127 | 128;
    low >>>= 7;
    pbf.buf[pbf.pos++] = low & 127 | 128;
    low >>>= 7;
    pbf.buf[pbf.pos++] = low & 127 | 128;
    low >>>= 7;
    pbf.buf[pbf.pos++] = low & 127 | 128;
    low >>>= 7;
    pbf.buf[pbf.pos] = low & 127;
}
function writeBigVarintHigh(high, pbf) {
    var lsb = (high & 7) << 4;
    pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 128 : 0);
    if (!high) {
        return;
    }
    pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
    if (!high) {
        return;
    }
    pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
    if (!high) {
        return;
    }
    pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
    if (!high) {
        return;
    }
    pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
    if (!high) {
        return;
    }
    pbf.buf[pbf.pos++] = high & 127;
}
function makeRoomForExtraLength(startPos, len, pbf) {
    var extraLen = len <= 16383 ? 1 : len <= 2097151 ? 2 : len <= 268435455 ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7));
    pbf.realloc(extraLen);
    for (var i = pbf.pos - 1; i >= startPos; i--) {
        pbf.buf[i + extraLen] = pbf.buf[i];
    }
}
function writePackedVarint(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeVarint(arr[i]);
    }
}
function writePackedSVarint(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeSVarint(arr[i]);
    }
}
function writePackedFloat(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeFloat(arr[i]);
    }
}
function writePackedDouble(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeDouble(arr[i]);
    }
}
function writePackedBoolean(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeBoolean(arr[i]);
    }
}
function writePackedFixed32(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeFixed32(arr[i]);
    }
}
function writePackedSFixed32(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeSFixed32(arr[i]);
    }
}
function writePackedFixed64(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeFixed64(arr[i]);
    }
}
function writePackedSFixed64(arr, pbf) {
    for (var i = 0; i < arr.length; i++) {
        pbf.writeSFixed64(arr[i]);
    }
}
function readUInt32(buf, pos) {
    return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + buf[pos + 3] * 16777216;
}
function writeInt32(buf, val, pos) {
    buf[pos] = val;
    buf[pos + 1] = val >>> 8;
    buf[pos + 2] = val >>> 16;
    buf[pos + 3] = val >>> 24;
}
function readInt32(buf, pos) {
    return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + (buf[pos + 3] << 24);
}
function readUtf8(buf, pos, end) {
    var str = '';
    var i = pos;
    while (i < end) {
        var b0 = buf[i];
        var c = null;
        var bytesPerSequence = b0 > 239 ? 4 : b0 > 223 ? 3 : b0 > 191 ? 2 : 1;
        if (i + bytesPerSequence > end) {
            break;
        }
        var b1, b2, b3;
        if (bytesPerSequence === 1) {
            if (b0 < 128) {
                c = b0;
            }
        } else if (bytesPerSequence === 2) {
            b1 = buf[i + 1];
            if ((b1 & 192) === 128) {
                c = (b0 & 31) << 6 | b1 & 63;
                if (c <= 127) {
                    c = null;
                }
            }
        } else if (bytesPerSequence === 3) {
            b1 = buf[i + 1];
            b2 = buf[i + 2];
            if ((b1 & 192) === 128 && (b2 & 192) === 128) {
                c = (b0 & 15) << 12 | (b1 & 63) << 6 | b2 & 63;
                if (c <= 2047 || c >= 55296 && c <= 57343) {
                    c = null;
                }
            }
        } else if (bytesPerSequence === 4) {
            b1 = buf[i + 1];
            b2 = buf[i + 2];
            b3 = buf[i + 3];
            if ((b1 & 192) === 128 && (b2 & 192) === 128 && (b3 & 192) === 128) {
                c = (b0 & 15) << 18 | (b1 & 63) << 12 | (b2 & 63) << 6 | b3 & 63;
                if (c <= 65535 || c >= 1114112) {
                    c = null;
                }
            }
        }
        if (c === null) {
            c = 65533;
            bytesPerSequence = 1;
        } else if (c > 65535) {
            c -= 65536;
            str += String.fromCharCode(c >>> 10 & 1023 | 55296);
            c = 56320 | c & 1023;
        }
        str += String.fromCharCode(c);
        i += bytesPerSequence;
    }
    return str;
}
function readUtf8TextDecoder(buf, pos, end) {
    return utf8TextDecoder.decode(buf.subarray(pos, end));
}
function writeUtf8(buf, str, pos) {
    for (var i = 0, c, lead; i < str.length; i++) {
        c = str.charCodeAt(i);
        if (c > 55295 && c < 57344) {
            if (lead) {
                if (c < 56320) {
                    buf[pos++] = 239;
                    buf[pos++] = 191;
                    buf[pos++] = 189;
                    lead = c;
                    continue;
                } else {
                    c = lead - 55296 << 10 | c - 56320 | 65536;
                    lead = null;
                }
            } else {
                if (c > 56319 || i + 1 === str.length) {
                    buf[pos++] = 239;
                    buf[pos++] = 191;
                    buf[pos++] = 189;
                } else {
                    lead = c;
                }
                continue;
            }
        } else if (lead) {
            buf[pos++] = 239;
            buf[pos++] = 191;
            buf[pos++] = 189;
            lead = null;
        }
        if (c < 128) {
            buf[pos++] = c;
        } else {
            if (c < 2048) {
                buf[pos++] = c >> 6 | 192;
            } else {
                if (c < 65536) {
                    buf[pos++] = c >> 12 | 224;
                } else {
                    buf[pos++] = c >> 18 | 240;
                    buf[pos++] = c >> 12 & 63 | 128;
                }
                buf[pos++] = c >> 6 & 63 | 128;
            }
            buf[pos++] = c & 63 | 128;
        }
    }
    return pos;
}

var border = 3;
function readFontstacks(tag, glyphs, pbf) {
    if (tag === 1) {
        pbf.readMessage(readFontstack, glyphs);
    }
}
function readFontstack(tag, glyphs, pbf) {
    if (tag === 3) {
        var ref = pbf.readMessage(readGlyph, {});
        var id = ref.id;
        var bitmap = ref.bitmap;
        var width = ref.width;
        var height = ref.height;
        var left = ref.left;
        var top = ref.top;
        var advance = ref.advance;
        glyphs.push({
            id: id,
            bitmap: new AlphaImage({
                width: width + 2 * border,
                height: height + 2 * border
            }, bitmap),
            metrics: {
                width: width,
                height: height,
                left: left,
                top: top,
                advance: advance
            }
        });
    }
}
function readGlyph(tag, glyph, pbf) {
    if (tag === 1) {
        glyph.id = pbf.readVarint();
    } else if (tag === 2) {
        glyph.bitmap = pbf.readBytes();
    } else if (tag === 3) {
        glyph.width = pbf.readVarint();
    } else if (tag === 4) {
        glyph.height = pbf.readVarint();
    } else if (tag === 5) {
        glyph.left = pbf.readSVarint();
    } else if (tag === 6) {
        glyph.top = pbf.readSVarint();
    } else if (tag === 7) {
        glyph.advance = pbf.readVarint();
    }
}
function parseGlyphPBF (data) {
    return new pbf(data).readFields(readFontstacks, []);
}
var GLYPH_PBF_BORDER = border;

function potpack(boxes) {

    // calculate total box area and maximum box width
    var area = 0;
    var maxWidth = 0;

    for (var i$1 = 0, list = boxes; i$1 < list.length; i$1 += 1) {
        var box = list[i$1];

        area += box.w * box.h;
        maxWidth = Math.max(maxWidth, box.w);
    }

    // sort the boxes for insertion by height, descending
    boxes.sort(function (a, b) { return b.h - a.h; });

    // aim for a squarish resulting container,
    // slightly adjusted for sub-100% space utilization
    var startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);

    // start with a single empty space, unbounded at the bottom
    var spaces = [{x: 0, y: 0, w: startWidth, h: Infinity}];

    var width = 0;
    var height = 0;

    for (var i$2 = 0, list$1 = boxes; i$2 < list$1.length; i$2 += 1) {
        // look through spaces backwards so that we check smaller spaces first
        var box$1 = list$1[i$2];

        for (var i = spaces.length - 1; i >= 0; i--) {
            var space = spaces[i];

            // look for empty spaces that can accommodate the current box
            if (box$1.w > space.w || box$1.h > space.h) { continue; }

            // found the space; add the box to its top-left corner
            // |-------|-------|
            // |  box  |       |
            // |_______|       |
            // |         space |
            // |_______________|
            box$1.x = space.x;
            box$1.y = space.y;

            height = Math.max(height, box$1.y + box$1.h);
            width = Math.max(width, box$1.x + box$1.w);

            if (box$1.w === space.w && box$1.h === space.h) {
                // space matches the box exactly; remove it
                var last = spaces.pop();
                if (i < spaces.length) { spaces[i] = last; }

            } else if (box$1.h === space.h) {
                // space matches the box height; update it accordingly
                // |-------|---------------|
                // |  box  | updated space |
                // |_______|_______________|
                space.x += box$1.w;
                space.w -= box$1.w;

            } else if (box$1.w === space.w) {
                // space matches the box width; update it accordingly
                // |---------------|
                // |      box      |
                // |_______________|
                // | updated space |
                // |_______________|
                space.y += box$1.h;
                space.h -= box$1.h;

            } else {
                // otherwise the box splits the space into two spaces
                // |-------|-----------|
                // |  box  | new space |
                // |_______|___________|
                // | updated space     |
                // |___________________|
                spaces.push({
                    x: space.x + box$1.w,
                    y: space.y,
                    w: space.w - box$1.w,
                    h: box$1.h
                });
                space.y += box$1.h;
                space.h -= box$1.h;
            }
            break;
        }
    }

    return {
        w: width, // container width
        h: height, // container height
        fill: (area / (width * height)) || 0 // space utilization
    };
}

var IMAGE_PADDING = 1;
var ImagePosition = function ImagePosition(paddedRect, ref) {
    var pixelRatio = ref.pixelRatio;
    var version = ref.version;
    var stretchX = ref.stretchX;
    var stretchY = ref.stretchY;
    var content = ref.content;
    this.paddedRect = paddedRect;
    this.pixelRatio = pixelRatio;
    this.stretchX = stretchX;
    this.stretchY = stretchY;
    this.content = content;
    this.version = version;
};
var prototypeAccessors = {
    tl: { configurable: true },
    br: { configurable: true },
    tlbr: { configurable: true },
    displaySize: { configurable: true }
};
prototypeAccessors.tl.get = function () {
    return [
        this.paddedRect.x + IMAGE_PADDING,
        this.paddedRect.y + IMAGE_PADDING
    ];
};
prototypeAccessors.br.get = function () {
    return [
        this.paddedRect.x + this.paddedRect.w - IMAGE_PADDING,
        this.paddedRect.y + this.paddedRect.h - IMAGE_PADDING
    ];
};
prototypeAccessors.tlbr.get = function () {
    return this.tl.concat(this.br);
};
prototypeAccessors.displaySize.get = function () {
    return [
        (this.paddedRect.w - IMAGE_PADDING * 2) / this.pixelRatio,
        (this.paddedRect.h - IMAGE_PADDING * 2) / this.pixelRatio
    ];
};
Object.defineProperties(ImagePosition.prototype, prototypeAccessors);
var ImageAtlas = function ImageAtlas(icons, patterns) {
    var iconPositions = {}, patternPositions = {};
    this.haveRenderCallbacks = [];
    var bins = [];
    this.addImages(icons, iconPositions, bins);
    this.addImages(patterns, patternPositions, bins);
    var ref = potpack(bins);
    var w = ref.w;
    var h = ref.h;
    var image = new RGBAImage({
        width: w || 1,
        height: h || 1
    });
    for (var id in icons) {
        var src = icons[id];
        var bin = iconPositions[id].paddedRect;
        RGBAImage.copy(src.data, image, {
            x: 0,
            y: 0
        }, {
            x: bin.x + IMAGE_PADDING,
            y: bin.y + IMAGE_PADDING
        }, src.data);
    }
    for (var id$1 in patterns) {
        var src$1 = patterns[id$1];
        var bin$1 = patternPositions[id$1].paddedRect;
        var x = bin$1.x + IMAGE_PADDING, y = bin$1.y + IMAGE_PADDING, w$1 = src$1.data.width, h$1 = src$1.data.height;
        RGBAImage.copy(src$1.data, image, {
            x: 0,
            y: 0
        }, {
            x: x,
            y: y
        }, src$1.data);
        RGBAImage.copy(src$1.data, image, {
            x: 0,
            y: h$1 - 1
        }, {
            x: x,
            y: y - 1
        }, {
            width: w$1,
            height: 1
        });
        RGBAImage.copy(src$1.data, image, {
            x: 0,
            y: 0
        }, {
            x: x,
            y: y + h$1
        }, {
            width: w$1,
            height: 1
        });
        RGBAImage.copy(src$1.data, image, {
            x: w$1 - 1,
            y: 0
        }, {
            x: x - 1,
            y: y
        }, {
            width: 1,
            height: h$1
        });
        RGBAImage.copy(src$1.data, image, {
            x: 0,
            y: 0
        }, {
            x: x + w$1,
            y: y
        }, {
            width: 1,
            height: h$1
        });
    }
    this.image = image;
    this.iconPositions = iconPositions;
    this.patternPositions = patternPositions;
};
ImageAtlas.prototype.addImages = function addImages(images, positions, bins) {
    for (var id in images) {
        var src = images[id];
        var bin = {
            x: 0,
            y: 0,
            w: src.data.width + 2 * IMAGE_PADDING,
            h: src.data.height + 2 * IMAGE_PADDING
        };
        bins.push(bin);
        positions[id] = new ImagePosition(bin, src);
        if (src.hasRenderCallback) {
            this.haveRenderCallbacks.push(id);
        }
    }
};
ImageAtlas.prototype.patchUpdatedImages = function patchUpdatedImages(imageManager, texture) {
    imageManager.dispatchRenderCallbacks(this.haveRenderCallbacks);
    for (var name in imageManager.updatedImages) {
        this.patchUpdatedImage(this.iconPositions[name], imageManager.getImage(name), texture);
        this.patchUpdatedImage(this.patternPositions[name], imageManager.getImage(name), texture);
    }
};
ImageAtlas.prototype.patchUpdatedImage = function patchUpdatedImage(position, image, texture) {
    if (!position || !image) {
        return;
    }
    if (position.version === image.version) {
        return;
    }
    position.version = image.version;
    var ref = position.tl;
    var x = ref[0];
    var y = ref[1];
    texture.update(image.data, undefined, {
        x: x,
        y: y
    });
};
register('ImagePosition', ImagePosition);
register('ImageAtlas', ImageAtlas);

var WritingMode = {
    horizontal: 1,
    vertical: 2,
    horizontalOnly: 3
};
var SHAPING_DEFAULT_OFFSET = -17;
function isEmpty(positionedLines) {
    for (var i = 0, list = positionedLines; i < list.length; i += 1) {
        var line = list[i];
        if (line.positionedGlyphs.length !== 0) {
            return false;
        }
    }
    return true;
}
var PUAbegin = 57344;
var PUAend = 63743;
var SectionOptions = function SectionOptions() {
    this.scale = 1;
    this.fontStack = '';
    this.imageName = null;
};
SectionOptions.forText = function forText(scale, fontStack) {
    var textOptions = new SectionOptions();
    textOptions.scale = scale || 1;
    textOptions.fontStack = fontStack;
    return textOptions;
};
SectionOptions.forImage = function forImage(imageName) {
    var imageOptions = new SectionOptions();
    imageOptions.imageName = imageName;
    return imageOptions;
};
var TaggedString = function TaggedString() {
    this.text = '';
    this.sectionIndex = [];
    this.sections = [];
    this.imageSectionID = null;
};
TaggedString.fromFeature = function fromFeature(text, defaultFontStack) {
    var result = new TaggedString();
    for (var i = 0; i < text.sections.length; i++) {
        var section = text.sections[i];
        if (!section.image) {
            result.addTextSection(section, defaultFontStack);
        } else {
            result.addImageSection(section);
        }
    }
    return result;
};
TaggedString.prototype.length = function length() {
    return this.text.length;
};
TaggedString.prototype.getSection = function getSection(index) {
    return this.sections[this.sectionIndex[index]];
};
TaggedString.prototype.getSectionIndex = function getSectionIndex(index) {
    return this.sectionIndex[index];
};
TaggedString.prototype.getCharCode = function getCharCode(index) {
    return this.text.charCodeAt(index);
};
TaggedString.prototype.verticalizePunctuation = function verticalizePunctuation$1() {
    this.text = verticalizePunctuation(this.text);
};
TaggedString.prototype.trim = function trim() {
    var beginningWhitespace = 0;
    for (var i = 0; i < this.text.length && whitespace[this.text.charCodeAt(i)]; i++) {
        beginningWhitespace++;
    }
    var trailingWhitespace = this.text.length;
    for (var i$1 = this.text.length - 1; i$1 >= 0 && i$1 >= beginningWhitespace && whitespace[this.text.charCodeAt(i$1)]; i$1--) {
        trailingWhitespace--;
    }
    this.text = this.text.substring(beginningWhitespace, trailingWhitespace);
    this.sectionIndex = this.sectionIndex.slice(beginningWhitespace, trailingWhitespace);
};
TaggedString.prototype.substring = function substring(start, end) {
    var substring = new TaggedString();
    substring.text = this.text.substring(start, end);
    substring.sectionIndex = this.sectionIndex.slice(start, end);
    substring.sections = this.sections;
    return substring;
};
TaggedString.prototype.toString = function toString() {
    return this.text;
};
TaggedString.prototype.getMaxScale = function getMaxScale() {
    var this$1 = this;
    return this.sectionIndex.reduce(function (max, index) {
        return Math.max(max, this$1.sections[index].scale);
    }, 0);
};
TaggedString.prototype.addTextSection = function addTextSection(section, defaultFontStack) {
    this.text += section.text;
    this.sections.push(SectionOptions.forText(section.scale, section.fontStack || defaultFontStack));
    var index = this.sections.length - 1;
    for (var i = 0; i < section.text.length; ++i) {
        this.sectionIndex.push(index);
    }
};
TaggedString.prototype.addImageSection = function addImageSection(section) {
    var imageName = section.image ? section.image.name : '';
    if (imageName.length === 0) {
        warnOnce('Can\'t add FormattedSection with an empty image.');
        return;
    }
    var nextImageSectionCharCode = this.getNextImageSectionCharCode();
    if (!nextImageSectionCharCode) {
        warnOnce('Reached maximum number of images ' + (PUAend - PUAbegin + 2));
        return;
    }
    this.text += String.fromCharCode(nextImageSectionCharCode);
    this.sections.push(SectionOptions.forImage(imageName));
    this.sectionIndex.push(this.sections.length - 1);
};
TaggedString.prototype.getNextImageSectionCharCode = function getNextImageSectionCharCode() {
    if (!this.imageSectionID) {
        this.imageSectionID = PUAbegin;
        return this.imageSectionID;
    }
    if (this.imageSectionID >= PUAend) {
        return null;
    }
    return ++this.imageSectionID;
};
function breakLines(input, lineBreakPoints) {
    var lines = [];
    var text = input.text;
    var start = 0;
    for (var i = 0, list = lineBreakPoints; i < list.length; i += 1) {
        var lineBreak = list[i];
        lines.push(input.substring(start, lineBreak));
        start = lineBreak;
    }
    if (start < text.length) {
        lines.push(input.substring(start, text.length));
    }
    return lines;
}
function shapeText(text, glyphMap, glyphPositions, imagePositions, defaultFontStack, maxWidth, lineHeight, textAnchor, textJustify, spacing, translate, writingMode, allowVerticalPlacement, symbolPlacement, layoutTextSize, layoutTextSizeThisZoom) {
    var logicalInput = TaggedString.fromFeature(text, defaultFontStack);
    if (writingMode === WritingMode.vertical) {
        logicalInput.verticalizePunctuation();
    }
    var lines;
    var processBidirectionalText = plugin.processBidirectionalText;
    var processStyledBidirectionalText = plugin.processStyledBidirectionalText;
    if (processBidirectionalText && logicalInput.sections.length === 1) {
        lines = [];
        var untaggedLines = processBidirectionalText(logicalInput.toString(), determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, symbolPlacement, layoutTextSize));
        for (var i$1 = 0, list = untaggedLines; i$1 < list.length; i$1 += 1) {
            var line = list[i$1];
            var taggedLine = new TaggedString();
            taggedLine.text = line;
            taggedLine.sections = logicalInput.sections;
            for (var i = 0; i < line.length; i++) {
                taggedLine.sectionIndex.push(0);
            }
            lines.push(taggedLine);
        }
    } else if (processStyledBidirectionalText) {
        lines = [];
        var processedLines = processStyledBidirectionalText(logicalInput.text, logicalInput.sectionIndex, determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, symbolPlacement, layoutTextSize));
        for (var i$2 = 0, list$1 = processedLines; i$2 < list$1.length; i$2 += 1) {
            var line$1 = list$1[i$2];
            var taggedLine$1 = new TaggedString();
            taggedLine$1.text = line$1[0];
            taggedLine$1.sectionIndex = line$1[1];
            taggedLine$1.sections = logicalInput.sections;
            lines.push(taggedLine$1);
        }
    } else {
        lines = breakLines(logicalInput, determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, symbolPlacement, layoutTextSize));
    }
    var positionedLines = [];
    var shaping = {
        positionedLines: positionedLines,
        text: logicalInput.toString(),
        top: translate[1],
        bottom: translate[1],
        left: translate[0],
        right: translate[0],
        writingMode: writingMode,
        iconsInText: false,
        verticalizable: false
    };
    shapeLines(shaping, glyphMap, glyphPositions, imagePositions, lines, lineHeight, textAnchor, textJustify, writingMode, spacing, allowVerticalPlacement, layoutTextSizeThisZoom);
    if (isEmpty(positionedLines)) {
        return false;
    }
    return shaping;
}
var whitespace = {};
whitespace[9] = true;
whitespace[10] = true;
whitespace[11] = true;
whitespace[12] = true;
whitespace[13] = true;
whitespace[32] = true;
var breakable = {};
breakable[10] = true;
breakable[32] = true;
breakable[38] = true;
breakable[40] = true;
breakable[41] = true;
breakable[43] = true;
breakable[45] = true;
breakable[47] = true;
breakable[173] = true;
breakable[183] = true;
breakable[8203] = true;
breakable[8208] = true;
breakable[8211] = true;
breakable[8231] = true;
function getGlyphAdvance(codePoint, section, glyphMap, imagePositions, spacing, layoutTextSize) {
    if (!section.imageName) {
        var positions = glyphMap[section.fontStack];
        var glyph = positions && positions[codePoint];
        if (!glyph) {
            return 0;
        }
        return glyph.metrics.advance * section.scale + spacing;
    } else {
        var imagePosition = imagePositions[section.imageName];
        if (!imagePosition) {
            return 0;
        }
        return imagePosition.displaySize[0] * section.scale * ONE_EM / layoutTextSize + spacing;
    }
}
function determineAverageLineWidth(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize) {
    var totalWidth = 0;
    for (var index = 0; index < logicalInput.length(); index++) {
        var section = logicalInput.getSection(index);
        totalWidth += getGlyphAdvance(logicalInput.getCharCode(index), section, glyphMap, imagePositions, spacing, layoutTextSize);
    }
    var lineCount = Math.max(1, Math.ceil(totalWidth / maxWidth));
    return totalWidth / lineCount;
}
function calculateBadness(lineWidth, targetWidth, penalty, isLastBreak) {
    var raggedness = Math.pow(lineWidth - targetWidth, 2);
    if (isLastBreak) {
        if (lineWidth < targetWidth) {
            return raggedness / 2;
        } else {
            return raggedness * 2;
        }
    }
    return raggedness + Math.abs(penalty) * penalty;
}
function calculatePenalty(codePoint, nextCodePoint, penalizableIdeographicBreak) {
    var penalty = 0;
    if (codePoint === 10) {
        penalty -= 10000;
    }
    if (penalizableIdeographicBreak) {
        penalty += 150;
    }
    if (codePoint === 40 || codePoint === 65288) {
        penalty += 50;
    }
    if (nextCodePoint === 41 || nextCodePoint === 65289) {
        penalty += 50;
    }
    return penalty;
}
function evaluateBreak(breakIndex, breakX, targetWidth, potentialBreaks, penalty, isLastBreak) {
    var bestPriorBreak = null;
    var bestBreakBadness = calculateBadness(breakX, targetWidth, penalty, isLastBreak);
    for (var i = 0, list = potentialBreaks; i < list.length; i += 1) {
        var potentialBreak = list[i];
        var lineWidth = breakX - potentialBreak.x;
        var breakBadness = calculateBadness(lineWidth, targetWidth, penalty, isLastBreak) + potentialBreak.badness;
        if (breakBadness <= bestBreakBadness) {
            bestPriorBreak = potentialBreak;
            bestBreakBadness = breakBadness;
        }
    }
    return {
        index: breakIndex,
        x: breakX,
        priorBreak: bestPriorBreak,
        badness: bestBreakBadness
    };
}
function leastBadBreaks(lastLineBreak) {
    if (!lastLineBreak) {
        return [];
    }
    return leastBadBreaks(lastLineBreak.priorBreak).concat(lastLineBreak.index);
}
function determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, symbolPlacement, layoutTextSize) {
    if (symbolPlacement !== 'point') {
        return [];
    }
    if (!logicalInput) {
        return [];
    }
    var potentialLineBreaks = [];
    var targetWidth = determineAverageLineWidth(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize);
    var hasServerSuggestedBreakpoints = logicalInput.text.indexOf('\u200B') >= 0;
    var currentX = 0;
    for (var i = 0; i < logicalInput.length(); i++) {
        var section = logicalInput.getSection(i);
        var codePoint = logicalInput.getCharCode(i);
        if (!whitespace[codePoint]) {
            currentX += getGlyphAdvance(codePoint, section, glyphMap, imagePositions, spacing, layoutTextSize);
        }
        if (i < logicalInput.length() - 1) {
            var ideographicBreak = charAllowsIdeographicBreaking(codePoint);
            if (breakable[codePoint] || ideographicBreak || section.imageName) {
                potentialLineBreaks.push(evaluateBreak(i + 1, currentX, targetWidth, potentialLineBreaks, calculatePenalty(codePoint, logicalInput.getCharCode(i + 1), ideographicBreak && hasServerSuggestedBreakpoints), false));
            }
        }
    }
    return leastBadBreaks(evaluateBreak(logicalInput.length(), currentX, targetWidth, potentialLineBreaks, 0, true));
}
function getAnchorAlignment(anchor) {
    var horizontalAlign = 0.5, verticalAlign = 0.5;
    switch (anchor) {
    case 'right':
    case 'top-right':
    case 'bottom-right':
        horizontalAlign = 1;
        break;
    case 'left':
    case 'top-left':
    case 'bottom-left':
        horizontalAlign = 0;
        break;
    }
    switch (anchor) {
    case 'bottom':
    case 'bottom-right':
    case 'bottom-left':
        verticalAlign = 1;
        break;
    case 'top':
    case 'top-right':
    case 'top-left':
        verticalAlign = 0;
        break;
    }
    return {
        horizontalAlign: horizontalAlign,
        verticalAlign: verticalAlign
    };
}
function shapeLines(shaping, glyphMap, glyphPositions, imagePositions, lines, lineHeight, textAnchor, textJustify, writingMode, spacing, allowVerticalPlacement, layoutTextSizeThisZoom) {
    var x = 0;
    var y = SHAPING_DEFAULT_OFFSET;
    var maxLineLength = 0;
    var maxLineHeight = 0;
    var justify = textJustify === 'right' ? 1 : textJustify === 'left' ? 0 : 0.5;
    var lineIndex = 0;
    for (var i$1 = 0, list = lines; i$1 < list.length; i$1 += 1) {
        var line = list[i$1];
        line.trim();
        var lineMaxScale = line.getMaxScale();
        var maxLineOffset = (lineMaxScale - 1) * ONE_EM;
        var positionedLine = {
            positionedGlyphs: [],
            lineOffset: 0
        };
        shaping.positionedLines[lineIndex] = positionedLine;
        var positionedGlyphs = positionedLine.positionedGlyphs;
        var lineOffset = 0;
        if (!line.length()) {
            y += lineHeight;
            ++lineIndex;
            continue;
        }
        for (var i = 0; i < line.length(); i++) {
            var section = line.getSection(i);
            var sectionIndex = line.getSectionIndex(i);
            var codePoint = line.getCharCode(i);
            var baselineOffset = 0;
            var metrics = null;
            var rect = null;
            var imageName = null;
            var verticalAdvance = ONE_EM;
            var vertical = !(writingMode === WritingMode.horizontal || !allowVerticalPlacement && !charHasUprightVerticalOrientation(codePoint) || allowVerticalPlacement && (whitespace[codePoint] || charInComplexShapingScript(codePoint)));
            if (!section.imageName) {
                var positions = glyphPositions[section.fontStack];
                var glyphPosition = positions && positions[codePoint];
                if (glyphPosition && glyphPosition.rect) {
                    rect = glyphPosition.rect;
                    metrics = glyphPosition.metrics;
                } else {
                    var glyphs = glyphMap[section.fontStack];
                    var glyph = glyphs && glyphs[codePoint];
                    if (!glyph) {
                        continue;
                    }
                    metrics = glyph.metrics;
                }
                baselineOffset = (lineMaxScale - section.scale) * ONE_EM;
            } else {
                var imagePosition = imagePositions[section.imageName];
                if (!imagePosition) {
                    continue;
                }
                imageName = section.imageName;
                shaping.iconsInText = shaping.iconsInText || true;
                rect = imagePosition.paddedRect;
                var size = imagePosition.displaySize;
                section.scale = section.scale * ONE_EM / layoutTextSizeThisZoom;
                metrics = {
                    width: size[0],
                    height: size[1],
                    left: IMAGE_PADDING,
                    top: -GLYPH_PBF_BORDER,
                    advance: vertical ? size[1] : size[0]
                };
                var imageOffset = ONE_EM - size[1] * section.scale;
                baselineOffset = maxLineOffset + imageOffset;
                verticalAdvance = metrics.advance;
                var offset = vertical ? size[0] * section.scale - ONE_EM * lineMaxScale : size[1] * section.scale - ONE_EM * lineMaxScale;
                if (offset > 0 && offset > lineOffset) {
                    lineOffset = offset;
                }
            }
            if (!vertical) {
                positionedGlyphs.push({
                    glyph: codePoint,
                    imageName: imageName,
                    x: x,
                    y: y + baselineOffset,
                    vertical: vertical,
                    scale: section.scale,
                    fontStack: section.fontStack,
                    sectionIndex: sectionIndex,
                    metrics: metrics,
                    rect: rect
                });
                x += metrics.advance * section.scale + spacing;
            } else {
                shaping.verticalizable = true;
                positionedGlyphs.push({
                    glyph: codePoint,
                    imageName: imageName,
                    x: x,
                    y: y + baselineOffset,
                    vertical: vertical,
                    scale: section.scale,
                    fontStack: section.fontStack,
                    sectionIndex: sectionIndex,
                    metrics: metrics,
                    rect: rect
                });
                x += verticalAdvance * section.scale + spacing;
            }
        }
        if (positionedGlyphs.length !== 0) {
            var lineLength = x - spacing;
            maxLineLength = Math.max(lineLength, maxLineLength);
            justifyLine(positionedGlyphs, 0, positionedGlyphs.length - 1, justify, lineOffset);
        }
        x = 0;
        var currentLineHeight = lineHeight * lineMaxScale + lineOffset;
        positionedLine.lineOffset = Math.max(lineOffset, maxLineOffset);
        y += currentLineHeight;
        maxLineHeight = Math.max(currentLineHeight, maxLineHeight);
        ++lineIndex;
    }
    var height = y - SHAPING_DEFAULT_OFFSET;
    var ref = getAnchorAlignment(textAnchor);
    var horizontalAlign = ref.horizontalAlign;
    var verticalAlign = ref.verticalAlign;
    align$1(shaping.positionedLines, justify, horizontalAlign, verticalAlign, maxLineLength, maxLineHeight, lineHeight, height, lines.length);
    shaping.top += -verticalAlign * height;
    shaping.bottom = shaping.top + height;
    shaping.left += -horizontalAlign * maxLineLength;
    shaping.right = shaping.left + maxLineLength;
}
function justifyLine(positionedGlyphs, start, end, justify, lineOffset) {
    if (!justify && !lineOffset) {
        return;
    }
    var lastPositionedGlyph = positionedGlyphs[end];
    var lastAdvance = lastPositionedGlyph.metrics.advance * lastPositionedGlyph.scale;
    var lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify;
    for (var j = start; j <= end; j++) {
        positionedGlyphs[j].x -= lineIndent;
        positionedGlyphs[j].y += lineOffset;
    }
}
function align$1(positionedLines, justify, horizontalAlign, verticalAlign, maxLineLength, maxLineHeight, lineHeight, blockHeight, lineCount) {
    var shiftX = (justify - horizontalAlign) * maxLineLength;
    var shiftY = 0;
    if (maxLineHeight !== lineHeight) {
        shiftY = -blockHeight * verticalAlign - SHAPING_DEFAULT_OFFSET;
    } else {
        shiftY = (-verticalAlign * lineCount + 0.5) * lineHeight;
    }
    for (var i$1 = 0, list$1 = positionedLines; i$1 < list$1.length; i$1 += 1) {
        var line = list$1[i$1];
        for (var i = 0, list = line.positionedGlyphs; i < list.length; i += 1) {
            var positionedGlyph = list[i];
            positionedGlyph.x += shiftX;
            positionedGlyph.y += shiftY;
        }
    }
}
function shapeIcon(image, iconOffset, iconAnchor) {
    var ref = getAnchorAlignment(iconAnchor);
    var horizontalAlign = ref.horizontalAlign;
    var verticalAlign = ref.verticalAlign;
    var dx = iconOffset[0];
    var dy = iconOffset[1];
    var x1 = dx - image.displaySize[0] * horizontalAlign;
    var x2 = x1 + image.displaySize[0];
    var y1 = dy - image.displaySize[1] * verticalAlign;
    var y2 = y1 + image.displaySize[1];
    return {
        image: image,
        top: y1,
        bottom: y2,
        left: x1,
        right: x2
    };
}
function fitIconToText(shapedIcon, shapedText, textFit, padding, iconOffset, fontScale) {
    var image = shapedIcon.image;
    var collisionPadding;
    if (image.content) {
        var content = image.content;
        var pixelRatio = image.pixelRatio || 1;
        collisionPadding = [
            content[0] / pixelRatio,
            content[1] / pixelRatio,
            image.displaySize[0] - content[2] / pixelRatio,
            image.displaySize[1] - content[3] / pixelRatio
        ];
    }
    var textLeft = shapedText.left * fontScale;
    var textRight = shapedText.right * fontScale;
    var top, right, bottom, left;
    if (textFit === 'width' || textFit === 'both') {
        left = iconOffset[0] + textLeft - padding[3];
        right = iconOffset[0] + textRight + padding[1];
    } else {
        left = iconOffset[0] + (textLeft + textRight - image.displaySize[0]) / 2;
        right = left + image.displaySize[0];
    }
    var textTop = shapedText.top * fontScale;
    var textBottom = shapedText.bottom * fontScale;
    if (textFit === 'height' || textFit === 'both') {
        top = iconOffset[1] + textTop - padding[0];
        bottom = iconOffset[1] + textBottom + padding[2];
    } else {
        top = iconOffset[1] + (textTop + textBottom - image.displaySize[1]) / 2;
        bottom = top + image.displaySize[1];
    }
    return {
        image: image,
        top: top,
        right: right,
        bottom: bottom,
        left: left,
        collisionPadding: collisionPadding
    };
}

var Anchor = function (Point) {
    function Anchor(x, y, angle, segment) {
        Point.call(this, x, y);
        this.angle = angle;
        if (segment !== undefined) {
            this.segment = segment;
        }
    }
    if (Point)
        Anchor.__proto__ = Point;
    Anchor.prototype = Object.create(Point && Point.prototype);
    Anchor.prototype.constructor = Anchor;
    Anchor.prototype.clone = function clone() {
        return new Anchor(this.x, this.y, this.angle, this.segment);
    };
    return Anchor;
}(pointGeometry);
register('Anchor', Anchor);

var SIZE_PACK_FACTOR = 128;
function getSizeData(tileZoom, value) {
    var expression = value.expression;
    if (expression.kind === 'constant') {
        var layoutSize = expression.evaluate(new EvaluationParameters(tileZoom + 1));
        return {
            kind: 'constant',
            layoutSize: layoutSize
        };
    } else if (expression.kind === 'source') {
        return { kind: 'source' };
    } else {
        var zoomStops = expression.zoomStops;
        var interpolationType = expression.interpolationType;
        var lower = 0;
        while (lower < zoomStops.length && zoomStops[lower] <= tileZoom) {
            lower++;
        }
        lower = Math.max(0, lower - 1);
        var upper = lower;
        while (upper < zoomStops.length && zoomStops[upper] < tileZoom + 1) {
            upper++;
        }
        upper = Math.min(zoomStops.length - 1, upper);
        var minZoom = zoomStops[lower];
        var maxZoom = zoomStops[upper];
        if (expression.kind === 'composite') {
            return {
                kind: 'composite',
                minZoom: minZoom,
                maxZoom: maxZoom,
                interpolationType: interpolationType
            };
        }
        var minSize = expression.evaluate(new EvaluationParameters(minZoom));
        var maxSize = expression.evaluate(new EvaluationParameters(maxZoom));
        return {
            kind: 'camera',
            minZoom: minZoom,
            maxZoom: maxZoom,
            minSize: minSize,
            maxSize: maxSize,
            interpolationType: interpolationType
        };
    }
}
function evaluateSizeForFeature(sizeData, ref, ref$1) {
    var uSize = ref.uSize;
    var uSizeT = ref.uSizeT;
    var lowerSize = ref$1.lowerSize;
    var upperSize = ref$1.upperSize;
    if (sizeData.kind === 'source') {
        return lowerSize / SIZE_PACK_FACTOR;
    } else if (sizeData.kind === 'composite') {
        return number(lowerSize / SIZE_PACK_FACTOR, upperSize / SIZE_PACK_FACTOR, uSizeT);
    }
    return uSize;
}
function evaluateSizeForZoom(sizeData, zoom) {
    var uSizeT = 0;
    var uSize = 0;
    if (sizeData.kind === 'constant') {
        uSize = sizeData.layoutSize;
    } else if (sizeData.kind !== 'source') {
        var interpolationType = sizeData.interpolationType;
        var minZoom = sizeData.minZoom;
        var maxZoom = sizeData.maxZoom;
        var t = !interpolationType ? 0 : clamp(Interpolate.interpolationFactor(interpolationType, zoom, minZoom, maxZoom), 0, 1);
        if (sizeData.kind === 'camera') {
            uSize = number(sizeData.minSize, sizeData.maxSize, t);
        } else {
            uSizeT = t;
        }
    }
    return {
        uSizeT: uSizeT,
        uSize: uSize
    };
}

var symbolSize = /*#__PURE__*/Object.freeze({
__proto__: null,
getSizeData: getSizeData,
evaluateSizeForFeature: evaluateSizeForFeature,
evaluateSizeForZoom: evaluateSizeForZoom,
SIZE_PACK_FACTOR: SIZE_PACK_FACTOR
});

function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
    if (anchor.segment === undefined) {
        return true;
    }
    var p = anchor;
    var index = anchor.segment + 1;
    var anchorDistance = 0;
    while (anchorDistance > -labelLength / 2) {
        index--;
        if (index < 0) {
            return false;
        }
        anchorDistance -= line[index].dist(p);
        p = line[index];
    }
    anchorDistance += line[index].dist(line[index + 1]);
    index++;
    var recentCorners = [];
    var recentAngleDelta = 0;
    while (anchorDistance < labelLength / 2) {
        var prev = line[index - 1];
        var current = line[index];
        var next = line[index + 1];
        if (!next) {
            return false;
        }
        var angleDelta = prev.angleTo(current) - current.angleTo(next);
        angleDelta = Math.abs((angleDelta + 3 * Math.PI) % (Math.PI * 2) - Math.PI);
        recentCorners.push({
            distance: anchorDistance,
            angleDelta: angleDelta
        });
        recentAngleDelta += angleDelta;
        while (anchorDistance - recentCorners[0].distance > windowSize) {
            recentAngleDelta -= recentCorners.shift().angleDelta;
        }
        if (recentAngleDelta > maxAngle) {
            return false;
        }
        index++;
        anchorDistance += current.dist(next);
    }
    return true;
}

function getLineLength(line) {
    var lineLength = 0;
    for (var k = 0; k < line.length - 1; k++) {
        lineLength += line[k].dist(line[k + 1]);
    }
    return lineLength;
}
function getAngleWindowSize(shapedText, glyphSize, boxScale) {
    return shapedText ? 3 / 5 * glyphSize * boxScale : 0;
}
function getShapedLabelLength(shapedText, shapedIcon) {
    return Math.max(shapedText ? shapedText.right - shapedText.left : 0, shapedIcon ? shapedIcon.right - shapedIcon.left : 0);
}
function getCenterAnchor(line, maxAngle, shapedText, shapedIcon, glyphSize, boxScale) {
    var angleWindowSize = getAngleWindowSize(shapedText, glyphSize, boxScale);
    var labelLength = getShapedLabelLength(shapedText, shapedIcon) * boxScale;
    var prevDistance = 0;
    var centerDistance = getLineLength(line) / 2;
    for (var i = 0; i < line.length - 1; i++) {
        var a = line[i], b = line[i + 1];
        var segmentDistance = a.dist(b);
        if (prevDistance + segmentDistance > centerDistance) {
            var t = (centerDistance - prevDistance) / segmentDistance, x = number(a.x, b.x, t), y = number(a.y, b.y, t);
            var anchor = new Anchor(x, y, b.angleTo(a), i);
            anchor._round();
            if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) {
                return anchor;
            } else {
                return;
            }
        }
        prevDistance += segmentDistance;
    }
}
function getAnchors(line, spacing, maxAngle, shapedText, shapedIcon, glyphSize, boxScale, overscaling, tileExtent) {
    var angleWindowSize = getAngleWindowSize(shapedText, glyphSize, boxScale);
    var shapedLabelLength = getShapedLabelLength(shapedText, shapedIcon);
    var labelLength = shapedLabelLength * boxScale;
    var isLineContinued = line[0].x === 0 || line[0].x === tileExtent || line[0].y === 0 || line[0].y === tileExtent;
    if (spacing - labelLength < spacing / 4) {
        spacing = labelLength + spacing / 4;
    }
    var fixedExtraOffset = glyphSize * 2;
    var offset = !isLineContinued ? (shapedLabelLength / 2 + fixedExtraOffset) * boxScale * overscaling % spacing : spacing / 2 * overscaling % spacing;
    return resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength, isLineContinued, false, tileExtent);
}
function resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength, isLineContinued, placeAtMiddle, tileExtent) {
    var halfLabelLength = labelLength / 2;
    var lineLength = getLineLength(line);
    var distance = 0, markedDistance = offset - spacing;
    var anchors = [];
    for (var i = 0; i < line.length - 1; i++) {
        var a = line[i], b = line[i + 1];
        var segmentDist = a.dist(b), angle = b.angleTo(a);
        while (markedDistance + spacing < distance + segmentDist) {
            markedDistance += spacing;
            var t = (markedDistance - distance) / segmentDist, x = number(a.x, b.x, t), y = number(a.y, b.y, t);
            if (x >= 0 && x < tileExtent && y >= 0 && y < tileExtent && markedDistance - halfLabelLength >= 0 && markedDistance + halfLabelLength <= lineLength) {
                var anchor = new Anchor(x, y, angle, i);
                anchor._round();
                if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) {
                    anchors.push(anchor);
                }
            }
        }
        distance += segmentDist;
    }
    if (!placeAtMiddle && !anchors.length && !isLineContinued) {
        anchors = resample(line, distance / 2, spacing, angleWindowSize, maxAngle, labelLength, isLineContinued, true, tileExtent);
    }
    return anchors;
}

function clipLine(lines, x1, y1, x2, y2) {
    var clippedLines = [];
    for (var l = 0; l < lines.length; l++) {
        var line = lines[l];
        var clippedLine = void 0;
        for (var i = 0; i < line.length - 1; i++) {
            var p0 = line[i];
            var p1 = line[i + 1];
            if (p0.x < x1 && p1.x < x1) {
                continue;
            } else if (p0.x < x1) {
                p0 = new pointGeometry(x1, p0.y + (p1.y - p0.y) * ((x1 - p0.x) / (p1.x - p0.x)))._round();
            } else if (p1.x < x1) {
                p1 = new pointGeometry(x1, p0.y + (p1.y - p0.y) * ((x1 - p0.x) / (p1.x - p0.x)))._round();
            }
            if (p0.y < y1 && p1.y < y1) {
                continue;
            } else if (p0.y < y1) {
                p0 = new pointGeometry(p0.x + (p1.x - p0.x) * ((y1 - p0.y) / (p1.y - p0.y)), y1)._round();
            } else if (p1.y < y1) {
                p1 = new pointGeometry(p0.x + (p1.x - p0.x) * ((y1 - p0.y) / (p1.y - p0.y)), y1)._round();
            }
            if (p0.x >= x2 && p1.x >= x2) {
                continue;
            } else if (p0.x >= x2) {
                p0 = new pointGeometry(x2, p0.y + (p1.y - p0.y) * ((x2 - p0.x) / (p1.x - p0.x)))._round();
            } else if (p1.x >= x2) {
                p1 = new pointGeometry(x2, p0.y + (p1.y - p0.y) * ((x2 - p0.x) / (p1.x - p0.x)))._round();
            }
            if (p0.y >= y2 && p1.y >= y2) {
                continue;
            } else if (p0.y >= y2) {
                p0 = new pointGeometry(p0.x + (p1.x - p0.x) * ((y2 - p0.y) / (p1.y - p0.y)), y2)._round();
            } else if (p1.y >= y2) {
                p1 = new pointGeometry(p0.x + (p1.x - p0.x) * ((y2 - p0.y) / (p1.y - p0.y)), y2)._round();
            }
            if (!clippedLine || !p0.equals(clippedLine[clippedLine.length - 1])) {
                clippedLine = [p0];
                clippedLines.push(clippedLine);
            }
            clippedLine.push(p1);
        }
    }
    return clippedLines;
}

var border$1 = IMAGE_PADDING;
function getIconQuads(shapedIcon, iconRotate, isSDFIcon, hasIconTextFit) {
    var quads = [];
    var image = shapedIcon.image;
    var pixelRatio = image.pixelRatio;
    var imageWidth = image.paddedRect.w - 2 * border$1;
    var imageHeight = image.paddedRect.h - 2 * border$1;
    var iconWidth = shapedIcon.right - shapedIcon.left;
    var iconHeight = shapedIcon.bottom - shapedIcon.top;
    var stretchX = image.stretchX || [[
            0,
            imageWidth
        ]];
    var stretchY = image.stretchY || [[
            0,
            imageHeight
        ]];
    var reduceRanges = function (sum, range) {
        return sum + range[1] - range[0];
    };
    var stretchWidth = stretchX.reduce(reduceRanges, 0);
    var stretchHeight = stretchY.reduce(reduceRanges, 0);
    var fixedWidth = imageWidth - stretchWidth;
    var fixedHeight = imageHeight - stretchHeight;
    var stretchOffsetX = 0;
    var stretchContentWidth = stretchWidth;
    var stretchOffsetY = 0;
    var stretchContentHeight = stretchHeight;
    var fixedOffsetX = 0;
    var fixedContentWidth = fixedWidth;
    var fixedOffsetY = 0;
    var fixedContentHeight = fixedHeight;
    if (image.content && hasIconTextFit) {
        var content = image.content;
        stretchOffsetX = sumWithinRange(stretchX, 0, content[0]);
        stretchOffsetY = sumWithinRange(stretchY, 0, content[1]);
        stretchContentWidth = sumWithinRange(stretchX, content[0], content[2]);
        stretchContentHeight = sumWithinRange(stretchY, content[1], content[3]);
        fixedOffsetX = content[0] - stretchOffsetX;
        fixedOffsetY = content[1] - stretchOffsetY;
        fixedContentWidth = content[2] - content[0] - stretchContentWidth;
        fixedContentHeight = content[3] - content[1] - stretchContentHeight;
    }
    var makeBox = function (left, top, right, bottom) {
        var leftEm = getEmOffset(left.stretch - stretchOffsetX, stretchContentWidth, iconWidth, shapedIcon.left);
        var leftPx = getPxOffset(left.fixed - fixedOffsetX, fixedContentWidth, left.stretch, stretchWidth);
        var topEm = getEmOffset(top.stretch - stretchOffsetY, stretchContentHeight, iconHeight, shapedIcon.top);
        var topPx = getPxOffset(top.fixed - fixedOffsetY, fixedContentHeight, top.stretch, stretchHeight);
        var rightEm = getEmOffset(right.stretch - stretchOffsetX, stretchContentWidth, iconWidth, shapedIcon.left);
        var rightPx = getPxOffset(right.fixed - fixedOffsetX, fixedContentWidth, right.stretch, stretchWidth);
        var bottomEm = getEmOffset(bottom.stretch - stretchOffsetY, stretchContentHeight, iconHeight, shapedIcon.top);
        var bottomPx = getPxOffset(bottom.fixed - fixedOffsetY, fixedContentHeight, bottom.stretch, stretchHeight);
        var tl = new pointGeometry(leftEm, topEm);
        var tr = new pointGeometry(rightEm, topEm);
        var br = new pointGeometry(rightEm, bottomEm);
        var bl = new pointGeometry(leftEm, bottomEm);
        var pixelOffsetTL = new pointGeometry(leftPx / pixelRatio, topPx / pixelRatio);
        var pixelOffsetBR = new pointGeometry(rightPx / pixelRatio, bottomPx / pixelRatio);
        var angle = iconRotate * Math.PI / 180;
        if (angle) {
            var sin = Math.sin(angle), cos = Math.cos(angle), matrix = [
                    cos,
                    -sin,
                    sin,
                    cos
                ];
            tl._matMult(matrix);
            tr._matMult(matrix);
            bl._matMult(matrix);
            br._matMult(matrix);
        }
        var x1 = left.stretch + left.fixed;
        var x2 = right.stretch + right.fixed;
        var y1 = top.stretch + top.fixed;
        var y2 = bottom.stretch + bottom.fixed;
        var subRect = {
            x: image.paddedRect.x + border$1 + x1,
            y: image.paddedRect.y + border$1 + y1,
            w: x2 - x1,
            h: y2 - y1
        };
        var minFontScaleX = fixedContentWidth / pixelRatio / iconWidth;
        var minFontScaleY = fixedContentHeight / pixelRatio / iconHeight;
        return {
            tl: tl,
            tr: tr,
            bl: bl,
            br: br,
            tex: subRect,
            writingMode: undefined,
            glyphOffset: [
                0,
                0
            ],
            sectionIndex: 0,
            pixelOffsetTL: pixelOffsetTL,
            pixelOffsetBR: pixelOffsetBR,
            minFontScaleX: minFontScaleX,
            minFontScaleY: minFontScaleY,
            isSDF: isSDFIcon
        };
    };
    if (!hasIconTextFit || !image.stretchX && !image.stretchY) {
        quads.push(makeBox({
            fixed: 0,
            stretch: -1
        }, {
            fixed: 0,
            stretch: -1
        }, {
            fixed: 0,
            stretch: imageWidth + 1
        }, {
            fixed: 0,
            stretch: imageHeight + 1
        }));
    } else {
        var xCuts = stretchZonesToCuts(stretchX, fixedWidth, stretchWidth);
        var yCuts = stretchZonesToCuts(stretchY, fixedHeight, stretchHeight);
        for (var xi = 0; xi < xCuts.length - 1; xi++) {
            var x1 = xCuts[xi];
            var x2 = xCuts[xi + 1];
            for (var yi = 0; yi < yCuts.length - 1; yi++) {
                var y1 = yCuts[yi];
                var y2 = yCuts[yi + 1];
                quads.push(makeBox(x1, y1, x2, y2));
            }
        }
    }
    return quads;
}
function sumWithinRange(ranges, min, max) {
    var sum = 0;
    for (var i = 0, list = ranges; i < list.length; i += 1) {
        var range = list[i];
        sum += Math.max(min, Math.min(max, range[1])) - Math.max(min, Math.min(max, range[0]));
    }
    return sum;
}
function stretchZonesToCuts(stretchZones, fixedSize, stretchSize) {
    var cuts = [{
            fixed: -border$1,
            stretch: 0
        }];
    for (var i = 0, list = stretchZones; i < list.length; i += 1) {
        var ref = list[i];
        var c1 = ref[0];
        var c2 = ref[1];
        var last = cuts[cuts.length - 1];
        cuts.push({
            fixed: c1 - last.stretch,
            stretch: last.stretch
        });
        cuts.push({
            fixed: c1 - last.stretch,
            stretch: last.stretch + (c2 - c1)
        });
    }
    cuts.push({
        fixed: fixedSize + border$1,
        stretch: stretchSize
    });
    return cuts;
}
function getEmOffset(stretchOffset, stretchSize, iconSize, iconOffset) {
    return stretchOffset / stretchSize * iconSize + iconOffset;
}
function getPxOffset(fixedOffset, fixedSize, stretchOffset, stretchSize) {
    return fixedOffset - fixedSize * stretchOffset / stretchSize;
}
function getGlyphQuads(anchor, shaping, textOffset, layer, alongLine, feature, imageMap, allowVerticalPlacement) {
    var textRotate = layer.layout.get('text-rotate').evaluate(feature, {}) * Math.PI / 180;
    var quads = [];
    for (var i$1 = 0, list$1 = shaping.positionedLines; i$1 < list$1.length; i$1 += 1) {
        var line = list$1[i$1];
        for (var i = 0, list = line.positionedGlyphs; i < list.length; i += 1) {
            var positionedGlyph = list[i];
            if (!positionedGlyph.rect) {
                continue;
            }
            var textureRect = positionedGlyph.rect || {};
            var glyphPadding = 1;
            var rectBuffer = GLYPH_PBF_BORDER + glyphPadding;
            var isSDF = true;
            var pixelRatio = 1;
            var lineOffset = 0;
            var rotateVerticalGlyph = (alongLine || allowVerticalPlacement) && positionedGlyph.vertical;
            var halfAdvance = positionedGlyph.metrics.advance * positionedGlyph.scale / 2;
            if (allowVerticalPlacement && shaping.verticalizable) {
                var scaledGlyphOffset = (positionedGlyph.scale - 1) * ONE_EM;
                var imageOffset = (ONE_EM - positionedGlyph.metrics.width * positionedGlyph.scale) / 2;
                lineOffset = line.lineOffset / 2 - (positionedGlyph.imageName ? -imageOffset : scaledGlyphOffset);
            }
            if (positionedGlyph.imageName) {
                var image = imageMap[positionedGlyph.imageName];
                isSDF = image.sdf;
                pixelRatio = image.pixelRatio;
                rectBuffer = IMAGE_PADDING / pixelRatio;
            }
            var glyphOffset = alongLine ? [
                positionedGlyph.x + halfAdvance,
                positionedGlyph.y
            ] : [
                0,
                0
            ];
            var builtInOffset = alongLine ? [
                0,
                0
            ] : [
                positionedGlyph.x + halfAdvance + textOffset[0],
                positionedGlyph.y + textOffset[1] - lineOffset
            ];
            var verticalizedLabelOffset = [
                0,
                0
            ];
            if (rotateVerticalGlyph) {
                verticalizedLabelOffset = builtInOffset;
                builtInOffset = [
                    0,
                    0
                ];
            }
            var x1 = (positionedGlyph.metrics.left - rectBuffer) * positionedGlyph.scale - halfAdvance + builtInOffset[0];
            var y1 = (-positionedGlyph.metrics.top - rectBuffer) * positionedGlyph.scale + builtInOffset[1];
            var x2 = x1 + textureRect.w * positionedGlyph.scale / pixelRatio;
            var y2 = y1 + textureRect.h * positionedGlyph.scale / pixelRatio;
            var tl = new pointGeometry(x1, y1);
            var tr = new pointGeometry(x2, y1);
            var bl = new pointGeometry(x1, y2);
            var br = new pointGeometry(x2, y2);
            if (rotateVerticalGlyph) {
                var center = new pointGeometry(-halfAdvance, halfAdvance - SHAPING_DEFAULT_OFFSET);
                var verticalRotation = -Math.PI / 2;
                var xHalfWidthOffsetCorrection = ONE_EM / 2 - halfAdvance;
                var yImageOffsetCorrection = positionedGlyph.imageName ? xHalfWidthOffsetCorrection : 0;
                var halfWidthOffsetCorrection = new pointGeometry(5 - SHAPING_DEFAULT_OFFSET - xHalfWidthOffsetCorrection, -yImageOffsetCorrection);
                var verticalOffsetCorrection = new (Function.prototype.bind.apply(pointGeometry, [null].concat(verticalizedLabelOffset)))();
                tl._rotateAround(verticalRotation, center)._add(halfWidthOffsetCorrection)._add(verticalOffsetCorrection);
                tr._rotateAround(verticalRotation, center)._add(halfWidthOffsetCorrection)._add(verticalOffsetCorrection);
                bl._rotateAround(verticalRotation, center)._add(halfWidthOffsetCorrection)._add(verticalOffsetCorrection);
                br._rotateAround(verticalRotation, center)._add(halfWidthOffsetCorrection)._add(verticalOffsetCorrection);
            }
            if (textRotate) {
                var sin = Math.sin(textRotate), cos = Math.cos(textRotate), matrix = [
                        cos,
                        -sin,
                        sin,
                        cos
                    ];
                tl._matMult(matrix);
                tr._matMult(matrix);
                bl._matMult(matrix);
                br._matMult(matrix);
            }
            var pixelOffsetTL = new pointGeometry(0, 0);
            var pixelOffsetBR = new pointGeometry(0, 0);
            var minFontScaleX = 0;
            var minFontScaleY = 0;
            quads.push({
                tl: tl,
                tr: tr,
                bl: bl,
                br: br,
                tex: textureRect,
                writingMode: shaping.writingMode,
                glyphOffset: glyphOffset,
                sectionIndex: positionedGlyph.sectionIndex,
                isSDF: isSDF,
                pixelOffsetTL: pixelOffsetTL,
                pixelOffsetBR: pixelOffsetBR,
                minFontScaleX: minFontScaleX,
                minFontScaleY: minFontScaleY
            });
        }
    }
    return quads;
}

var CollisionFeature = function CollisionFeature(collisionBoxArray, anchor, featureIndex, sourceLayerIndex, bucketIndex, shaped, boxScale, padding, alignLine, rotate) {
    this.boxStartIndex = collisionBoxArray.length;
    if (alignLine) {
        var top = shaped.top;
        var bottom = shaped.bottom;
        var collisionPadding = shaped.collisionPadding;
        if (collisionPadding) {
            top -= collisionPadding[1];
            bottom += collisionPadding[3];
        }
        var height = bottom - top;
        if (height > 0) {
            height = Math.max(10, height);
            this.circleDiameter = height;
        }
    } else {
        var y1 = shaped.top * boxScale - padding;
        var y2 = shaped.bottom * boxScale + padding;
        var x1 = shaped.left * boxScale - padding;
        var x2 = shaped.right * boxScale + padding;
        var collisionPadding$1 = shaped.collisionPadding;
        if (collisionPadding$1) {
            x1 -= collisionPadding$1[0] * boxScale;
            y1 -= collisionPadding$1[1] * boxScale;
            x2 += collisionPadding$1[2] * boxScale;
            y2 += collisionPadding$1[3] * boxScale;
        }
        if (rotate) {
            var tl = new pointGeometry(x1, y1);
            var tr = new pointGeometry(x2, y1);
            var bl = new pointGeometry(x1, y2);
            var br = new pointGeometry(x2, y2);
            var rotateRadians = rotate * Math.PI / 180;
            tl._rotate(rotateRadians);
            tr._rotate(rotateRadians);
            bl._rotate(rotateRadians);
            br._rotate(rotateRadians);
            x1 = Math.min(tl.x, tr.x, bl.x, br.x);
            x2 = Math.max(tl.x, tr.x, bl.x, br.x);
            y1 = Math.min(tl.y, tr.y, bl.y, br.y);
            y2 = Math.max(tl.y, tr.y, bl.y, br.y);
        }
        collisionBoxArray.emplaceBack(anchor.x, anchor.y, x1, y1, x2, y2, featureIndex, sourceLayerIndex, bucketIndex);
    }
    this.boxEndIndex = collisionBoxArray.length;
};

var TinyQueue = function TinyQueue(data, compare) {
    if (data === void 0)
        data = [];
    if (compare === void 0)
        compare = defaultCompare$1;
    this.data = data;
    this.length = this.data.length;
    this.compare = compare;
    if (this.length > 0) {
        for (var i = (this.length >> 1) - 1; i >= 0; i--) {
            this._down(i);
        }
    }
};
TinyQueue.prototype.push = function push(item) {
    this.data.push(item);
    this.length++;
    this._up(this.length - 1);
};
TinyQueue.prototype.pop = function pop() {
    if (this.length === 0) {
        return undefined;
    }
    var top = this.data[0];
    var bottom = this.data.pop();
    this.length--;
    if (this.length > 0) {
        this.data[0] = bottom;
        this._down(0);
    }
    return top;
};
TinyQueue.prototype.peek = function peek() {
    return this.data[0];
};
TinyQueue.prototype._up = function _up(pos) {
    var ref = this;
    var data = ref.data;
    var compare = ref.compare;
    var item = data[pos];
    while (pos > 0) {
        var parent = pos - 1 >> 1;
        var current = data[parent];
        if (compare(item, current) >= 0) {
            break;
        }
        data[pos] = current;
        pos = parent;
    }
    data[pos] = item;
};
TinyQueue.prototype._down = function _down(pos) {
    var ref = this;
    var data = ref.data;
    var compare = ref.compare;
    var halfLength = this.length >> 1;
    var item = data[pos];
    while (pos < halfLength) {
        var left = (pos << 1) + 1;
        var best = data[left];
        var right = left + 1;
        if (right < this.length && compare(data[right], best) < 0) {
            left = right;
            best = data[right];
        }
        if (compare(best, item) >= 0) {
            break;
        }
        data[pos] = best;
        pos = left;
    }
    data[pos] = item;
};
function defaultCompare$1(a, b) {
    return a < b ? -1 : a > b ? 1 : 0;
}

function findPoleOfInaccessibility (polygonRings, precision, debug) {
    if (precision === void 0)
        precision = 1;
    if (debug === void 0)
        debug = false;
    var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
    var outerRing = polygonRings[0];
    for (var i = 0; i < outerRing.length; i++) {
        var p = outerRing[i];
        if (!i || p.x < minX) {
            minX = p.x;
        }
        if (!i || p.y < minY) {
            minY = p.y;
        }
        if (!i || p.x > maxX) {
            maxX = p.x;
        }
        if (!i || p.y > maxY) {
            maxY = p.y;
        }
    }
    var width = maxX - minX;
    var height = maxY - minY;
    var cellSize = Math.min(width, height);
    var h = cellSize / 2;
    var cellQueue = new TinyQueue([], compareMax);
    if (cellSize === 0) {
        return new pointGeometry(minX, minY);
    }
    for (var x = minX; x < maxX; x += cellSize) {
        for (var y = minY; y < maxY; y += cellSize) {
            cellQueue.push(new Cell(x + h, y + h, h, polygonRings));
        }
    }
    var bestCell = getCentroidCell(polygonRings);
    var numProbes = cellQueue.length;
    while (cellQueue.length) {
        var cell = cellQueue.pop();
        if (cell.d > bestCell.d || !bestCell.d) {
            bestCell = cell;
            if (debug) {
                console.log('found best %d after %d probes', Math.round(10000 * cell.d) / 10000, numProbes);
            }
        }
        if (cell.max - bestCell.d <= precision) {
            continue;
        }
        h = cell.h / 2;
        cellQueue.push(new Cell(cell.p.x - h, cell.p.y - h, h, polygonRings));
        cellQueue.push(new Cell(cell.p.x + h, cell.p.y - h, h, polygonRings));
        cellQueue.push(new Cell(cell.p.x - h, cell.p.y + h, h, polygonRings));
        cellQueue.push(new Cell(cell.p.x + h, cell.p.y + h, h, polygonRings));
        numProbes += 4;
    }
    if (debug) {
        console.log('num probes: ' + numProbes);
        console.log('best distance: ' + bestCell.d);
    }
    return bestCell.p;
}
function compareMax(a, b) {
    return b.max - a.max;
}
function Cell(x, y, h, polygon) {
    this.p = new pointGeometry(x, y);
    this.h = h;
    this.d = pointToPolygonDist(this.p, polygon);
    this.max = this.d + this.h * Math.SQRT2;
}
function pointToPolygonDist(p, polygon) {
    var inside = false;
    var minDistSq = Infinity;
    for (var k = 0; k < polygon.length; k++) {
        var ring = polygon[k];
        for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
            var a = ring[i];
            var b = ring[j];
            if (a.y > p.y !== b.y > p.y && p.x < (b.x - a.x) * (p.y - a.y) / (b.y - a.y) + a.x) {
                inside = !inside;
            }
            minDistSq = Math.min(minDistSq, distToSegmentSquared(p, a, b));
        }
    }
    return (inside ? 1 : -1) * Math.sqrt(minDistSq);
}
function getCentroidCell(polygon) {
    var area = 0;
    var x = 0;
    var y = 0;
    var points = polygon[0];
    for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
        var a = points[i];
        var b = points[j];
        var f = a.x * b.y - b.x * a.y;
        x += (a.x + b.x) * f;
        y += (a.y + b.y) * f;
        area += f * 3;
    }
    return new Cell(x / area, y / area, 0, polygon);
}

var baselineOffset = 7;
var INVALID_TEXT_OFFSET = Number.POSITIVE_INFINITY;
function evaluateVariableOffset(anchor, offset) {
    function fromRadialOffset(anchor, radialOffset) {
        var x = 0, y = 0;
        if (radialOffset < 0) {
            radialOffset = 0;
        }
        var hypotenuse = radialOffset / Math.sqrt(2);
        switch (anchor) {
        case 'top-right':
        case 'top-left':
            y = hypotenuse - baselineOffset;
            break;
        case 'bottom-right':
        case 'bottom-left':
            y = -hypotenuse + baselineOffset;
            break;
        case 'bottom':
            y = -radialOffset + baselineOffset;
            break;
        case 'top':
            y = radialOffset - baselineOffset;
            break;
        }
        switch (anchor) {
        case 'top-right':
        case 'bottom-right':
            x = -hypotenuse;
            break;
        case 'top-left':
        case 'bottom-left':
            x = hypotenuse;
            break;
        case 'left':
            x = radialOffset;
            break;
        case 'right':
            x = -radialOffset;
            break;
        }
        return [
            x,
            y
        ];
    }
    function fromTextOffset(anchor, offsetX, offsetY) {
        var x = 0, y = 0;
        offsetX = Math.abs(offsetX);
        offsetY = Math.abs(offsetY);
        switch (anchor) {
        case 'top-right':
        case 'top-left':
        case 'top':
            y = offsetY - baselineOffset;
            break;
        case 'bottom-right':
        case 'bottom-left':
        case 'bottom':
            y = -offsetY + baselineOffset;
            break;
        }
        switch (anchor) {
        case 'top-right':
        case 'bottom-right':
        case 'right':
            x = -offsetX;
            break;
        case 'top-left':
        case 'bottom-left':
        case 'left':
            x = offsetX;
            break;
        }
        return [
            x,
            y
        ];
    }
    return offset[1] !== INVALID_TEXT_OFFSET ? fromTextOffset(anchor, offset[0], offset[1]) : fromRadialOffset(anchor, offset[0]);
}
function performSymbolLayout(bucket, glyphMap, glyphPositions, imageMap, imagePositions, showCollisionBoxes, canonical) {
    bucket.createArrays();
    var tileSize = 512 * bucket.overscaling;
    bucket.tilePixelRatio = EXTENT$1 / tileSize;
    bucket.compareText = {};
    bucket.iconsNeedLinear = false;
    var layout = bucket.layers[0].layout;
    var unevaluatedLayoutValues = bucket.layers[0]._unevaluatedLayout._values;
    var sizes = {};
    if (bucket.textSizeData.kind === 'composite') {
        var ref = bucket.textSizeData;
        var minZoom = ref.minZoom;
        var maxZoom = ref.maxZoom;
        sizes.compositeTextSizes = [
            unevaluatedLayoutValues['text-size'].possiblyEvaluate(new EvaluationParameters(minZoom), canonical),
            unevaluatedLayoutValues['text-size'].possiblyEvaluate(new EvaluationParameters(maxZoom), canonical)
        ];
    }
    if (bucket.iconSizeData.kind === 'composite') {
        var ref$1 = bucket.iconSizeData;
        var minZoom$1 = ref$1.minZoom;
        var maxZoom$1 = ref$1.maxZoom;
        sizes.compositeIconSizes = [
            unevaluatedLayoutValues['icon-size'].possiblyEvaluate(new EvaluationParameters(minZoom$1), canonical),
            unevaluatedLayoutValues['icon-size'].possiblyEvaluate(new EvaluationParameters(maxZoom$1), canonical)
        ];
    }
    sizes.layoutTextSize = unevaluatedLayoutValues['text-size'].possiblyEvaluate(new EvaluationParameters(bucket.zoom + 1), canonical);
    sizes.layoutIconSize = unevaluatedLayoutValues['icon-size'].possiblyEvaluate(new EvaluationParameters(bucket.zoom + 1), canonical);
    sizes.textMaxSize = unevaluatedLayoutValues['text-size'].possiblyEvaluate(new EvaluationParameters(18));
    var lineHeight = layout.get('text-line-height') * ONE_EM;
    var textAlongLine = layout.get('text-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point';
    var keepUpright = layout.get('text-keep-upright');
    var textSize = layout.get('text-size');
    var loop = function () {
        var feature = list[i$1];
        var fontstack = layout.get('text-font').evaluate(feature, {}, canonical).join(',');
        var layoutTextSizeThisZoom = textSize.evaluate(feature, {}, canonical);
        var layoutTextSize = sizes.layoutTextSize.evaluate(feature, {}, canonical);
        var layoutIconSize = sizes.layoutIconSize.evaluate(feature, {}, canonical);
        var shapedTextOrientations = {
            horizontal: {},
            vertical: undefined
        };
        var text = feature.text;
        var textOffset = [
            0,
            0
        ];
        if (text) {
            var unformattedText = text.toString();
            var spacing = layout.get('text-letter-spacing').evaluate(feature, {}, canonical) * ONE_EM;
            var spacingIfAllowed = allowsLetterSpacing(unformattedText) ? spacing : 0;
            var textAnchor = layout.get('text-anchor').evaluate(feature, {}, canonical);
            var variableTextAnchor = layout.get('text-variable-anchor');
            if (!variableTextAnchor) {
                var radialOffset = layout.get('text-radial-offset').evaluate(feature, {}, canonical);
                if (radialOffset) {
                    textOffset = evaluateVariableOffset(textAnchor, [
                        radialOffset * ONE_EM,
                        INVALID_TEXT_OFFSET
                    ]);
                } else {
                    textOffset = layout.get('text-offset').evaluate(feature, {}, canonical).map(function (t) {
                        return t * ONE_EM;
                    });
                }
            }
            var textJustify = textAlongLine ? 'center' : layout.get('text-justify').evaluate(feature, {}, canonical);
            var symbolPlacement = layout.get('symbol-placement');
            var maxWidth = symbolPlacement === 'point' ? layout.get('text-max-width').evaluate(feature, {}, canonical) * ONE_EM : 0;
            var addVerticalShapingForPointLabelIfNeeded = function () {
                if (bucket.allowVerticalPlacement && allowsVerticalWritingMode(unformattedText)) {
                    shapedTextOrientations.vertical = shapeText(text, glyphMap, glyphPositions, imagePositions, fontstack, maxWidth, lineHeight, textAnchor, 'left', spacingIfAllowed, textOffset, WritingMode.vertical, true, symbolPlacement, layoutTextSize, layoutTextSizeThisZoom);
                }
            };
            if (!textAlongLine && variableTextAnchor) {
                var justifications = textJustify === 'auto' ? variableTextAnchor.map(function (a) {
                    return getAnchorJustification(a);
                }) : [textJustify];
                var singleLine = false;
                for (var i = 0; i < justifications.length; i++) {
                    var justification = justifications[i];
                    if (shapedTextOrientations.horizontal[justification]) {
                        continue;
                    }
                    if (singleLine) {
                        shapedTextOrientations.horizontal[justification] = shapedTextOrientations.horizontal[0];
                    } else {
                        var shaping = shapeText(text, glyphMap, glyphPositions, imagePositions, fontstack, maxWidth, lineHeight, 'center', justification, spacingIfAllowed, textOffset, WritingMode.horizontal, false, symbolPlacement, layoutTextSize, layoutTextSizeThisZoom);
                        if (shaping) {
                            shapedTextOrientations.horizontal[justification] = shaping;
                            singleLine = shaping.positionedLines.length === 1;
                        }
                    }
                }
                addVerticalShapingForPointLabelIfNeeded();
            } else {
                if (textJustify === 'auto') {
                    textJustify = getAnchorJustification(textAnchor);
                }
                var shaping$1 = shapeText(text, glyphMap, glyphPositions, imagePositions, fontstack, maxWidth, lineHeight, textAnchor, textJustify, spacingIfAllowed, textOffset, WritingMode.horizontal, false, symbolPlacement, layoutTextSize, layoutTextSizeThisZoom);
                if (shaping$1) {
                    shapedTextOrientations.horizontal[textJustify] = shaping$1;
                }
                addVerticalShapingForPointLabelIfNeeded();
                if (allowsVerticalWritingMode(unformattedText) && textAlongLine && keepUpright) {
                    shapedTextOrientations.vertical = shapeText(text, glyphMap, glyphPositions, imagePositions, fontstack, maxWidth, lineHeight, textAnchor, textJustify, spacingIfAllowed, textOffset, WritingMode.vertical, false, symbolPlacement, layoutTextSize, layoutTextSizeThisZoom);
                }
            }
        }
        var shapedIcon = void 0;
        var isSDFIcon = false;
        if (feature.icon && feature.icon.name) {
            var image = imageMap[feature.icon.name];
            if (image) {
                shapedIcon = shapeIcon(imagePositions[feature.icon.name], layout.get('icon-offset').evaluate(feature, {}, canonical), layout.get('icon-anchor').evaluate(feature, {}, canonical));
                isSDFIcon = image.sdf;
                if (bucket.sdfIcons === undefined) {
                    bucket.sdfIcons = image.sdf;
                } else if (bucket.sdfIcons !== image.sdf) {
                    warnOnce('Style sheet warning: Cannot mix SDF and non-SDF icons in one buffer');
                }
                if (image.pixelRatio !== bucket.pixelRatio) {
                    bucket.iconsNeedLinear = true;
                } else if (layout.get('icon-rotate').constantOr(1) !== 0) {
                    bucket.iconsNeedLinear = true;
                }
            }
        }
        var shapedText = getDefaultHorizontalShaping(shapedTextOrientations.horizontal) || shapedTextOrientations.vertical;
        bucket.iconsInText = shapedText ? shapedText.iconsInText : false;
        if (shapedText || shapedIcon) {
            addFeature(bucket, feature, shapedTextOrientations, shapedIcon, imageMap, sizes, layoutTextSize, layoutIconSize, textOffset, isSDFIcon, canonical);
        }
    };
    for (var i$1 = 0, list = bucket.features; i$1 < list.length; i$1 += 1)
        loop();
    if (showCollisionBoxes) {
        bucket.generateCollisionDebugBuffers();
    }
}
function getAnchorJustification(anchor) {
    switch (anchor) {
    case 'right':
    case 'top-right':
    case 'bottom-right':
        return 'right';
    case 'left':
    case 'top-left':
    case 'bottom-left':
        return 'left';
    }
    return 'center';
}
function addFeature(bucket, feature, shapedTextOrientations, shapedIcon, imageMap, sizes, layoutTextSize, layoutIconSize, textOffset, isSDFIcon, canonical) {
    var textMaxSize = sizes.textMaxSize.evaluate(feature, {});
    if (textMaxSize === undefined) {
        textMaxSize = layoutTextSize;
    }
    var layout = bucket.layers[0].layout;
    var iconOffset = layout.get('icon-offset').evaluate(feature, {}, canonical);
    var defaultHorizontalShaping = getDefaultHorizontalShaping(shapedTextOrientations.horizontal);
    var glyphSize = 24, fontScale = layoutTextSize / glyphSize, textBoxScale = bucket.tilePixelRatio * fontScale, textMaxBoxScale = bucket.tilePixelRatio * textMaxSize / glyphSize, iconBoxScale = bucket.tilePixelRatio * layoutIconSize, symbolMinDistance = bucket.tilePixelRatio * layout.get('symbol-spacing'), textPadding = layout.get('text-padding') * bucket.tilePixelRatio, iconPadding = layout.get('icon-padding') * bucket.tilePixelRatio, textMaxAngle = layout.get('text-max-angle') / 180 * Math.PI, textAlongLine = layout.get('text-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point', iconAlongLine = layout.get('icon-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point', symbolPlacement = layout.get('symbol-placement'), textRepeatDistance = symbolMinDistance / 2;
    var iconTextFit = layout.get('icon-text-fit');
    var verticallyShapedIcon;
    if (shapedIcon && iconTextFit !== 'none') {
        if (bucket.allowVerticalPlacement && shapedTextOrientations.vertical) {
            verticallyShapedIcon = fitIconToText(shapedIcon, shapedTextOrientations.vertical, iconTextFit, layout.get('icon-text-fit-padding'), iconOffset, fontScale);
        }
        if (defaultHorizontalShaping) {
            shapedIcon = fitIconToText(shapedIcon, defaultHorizontalShaping, iconTextFit, layout.get('icon-text-fit-padding'), iconOffset, fontScale);
        }
    }
    var addSymbolAtAnchor = function (line, anchor) {
        if (anchor.x < 0 || anchor.x >= EXTENT$1 || anchor.y < 0 || anchor.y >= EXTENT$1) {
            return;
        }
        addSymbol(bucket, anchor, line, shapedTextOrientations, shapedIcon, imageMap, verticallyShapedIcon, bucket.layers[0], bucket.collisionBoxArray, feature.index, feature.sourceLayerIndex, bucket.index, textBoxScale, textPadding, textAlongLine, textOffset, iconBoxScale, iconPadding, iconAlongLine, iconOffset, feature, sizes, isSDFIcon, canonical, layoutTextSize);
    };
    if (symbolPlacement === 'line') {
        for (var i$1 = 0, list$1 = clipLine(feature.geometry, 0, 0, EXTENT$1, EXTENT$1); i$1 < list$1.length; i$1 += 1) {
            var line = list$1[i$1];
            var anchors = getAnchors(line, symbolMinDistance, textMaxAngle, shapedTextOrientations.vertical || defaultHorizontalShaping, shapedIcon, glyphSize, textMaxBoxScale, bucket.overscaling, EXTENT$1);
            for (var i = 0, list = anchors; i < list.length; i += 1) {
                var anchor = list[i];
                var shapedText = defaultHorizontalShaping;
                if (!shapedText || !anchorIsTooClose(bucket, shapedText.text, textRepeatDistance, anchor)) {
                    addSymbolAtAnchor(line, anchor);
                }
            }
        }
    } else if (symbolPlacement === 'line-center') {
        for (var i$2 = 0, list$2 = feature.geometry; i$2 < list$2.length; i$2 += 1) {
            var line$1 = list$2[i$2];
            if (line$1.length > 1) {
                var anchor$1 = getCenterAnchor(line$1, textMaxAngle, shapedTextOrientations.vertical || defaultHorizontalShaping, shapedIcon, glyphSize, textMaxBoxScale);
                if (anchor$1) {
                    addSymbolAtAnchor(line$1, anchor$1);
                }
            }
        }
    } else if (feature.type === 'Polygon') {
        for (var i$3 = 0, list$3 = classifyRings(feature.geometry, 0); i$3 < list$3.length; i$3 += 1) {
            var polygon = list$3[i$3];
            var poi = findPoleOfInaccessibility(polygon, 16);
            addSymbolAtAnchor(polygon[0], new Anchor(poi.x, poi.y, 0));
        }
    } else if (feature.type === 'LineString') {
        for (var i$4 = 0, list$4 = feature.geometry; i$4 < list$4.length; i$4 += 1) {
            var line$2 = list$4[i$4];
            addSymbolAtAnchor(line$2, new Anchor(line$2[0].x, line$2[0].y, 0));
        }
    } else if (feature.type === 'Point') {
        for (var i$6 = 0, list$6 = feature.geometry; i$6 < list$6.length; i$6 += 1) {
            var points = list$6[i$6];
            for (var i$5 = 0, list$5 = points; i$5 < list$5.length; i$5 += 1) {
                var point = list$5[i$5];
                addSymbolAtAnchor([point], new Anchor(point.x, point.y, 0));
            }
        }
    }
}
var MAX_GLYPH_ICON_SIZE = 255;
var MAX_PACKED_SIZE = MAX_GLYPH_ICON_SIZE * SIZE_PACK_FACTOR;
function addTextVertices(bucket, anchor, shapedText, imageMap, layer, textAlongLine, feature, textOffset, lineArray, writingMode, placementTypes, placedTextSymbolIndices, placedIconIndex, sizes, canonical) {
    var glyphQuads = getGlyphQuads(anchor, shapedText, textOffset, layer, textAlongLine, feature, imageMap, bucket.allowVerticalPlacement);
    var sizeData = bucket.textSizeData;
    var textSizeData = null;
    if (sizeData.kind === 'source') {
        textSizeData = [SIZE_PACK_FACTOR * layer.layout.get('text-size').evaluate(feature, {})];
        if (textSizeData[0] > MAX_PACKED_SIZE) {
            warnOnce(bucket.layerIds[0] + ': Value for "text-size" is >= ' + MAX_GLYPH_ICON_SIZE + '. Reduce your "text-size".');
        }
    } else if (sizeData.kind === 'composite') {
        textSizeData = [
            SIZE_PACK_FACTOR * sizes.compositeTextSizes[0].evaluate(feature, {}, canonical),
            SIZE_PACK_FACTOR * sizes.compositeTextSizes[1].evaluate(feature, {}, canonical)
        ];
        if (textSizeData[0] > MAX_PACKED_SIZE || textSizeData[1] > MAX_PACKED_SIZE) {
            warnOnce(bucket.layerIds[0] + ': Value for "text-size" is >= ' + MAX_GLYPH_ICON_SIZE + '. Reduce your "text-size".');
        }
    }
    bucket.addSymbols(bucket.text, glyphQuads, textSizeData, textOffset, textAlongLine, feature, writingMode, anchor, lineArray.lineStartIndex, lineArray.lineLength, placedIconIndex, canonical);
    for (var i = 0, list = placementTypes; i < list.length; i += 1) {
        var placementType = list[i];
        placedTextSymbolIndices[placementType] = bucket.text.placedSymbolArray.length - 1;
    }
    return glyphQuads.length * 4;
}
function getDefaultHorizontalShaping(horizontalShaping) {
    for (var justification in horizontalShaping) {
        return horizontalShaping[justification];
    }
    return null;
}
function addSymbol(bucket, anchor, line, shapedTextOrientations, shapedIcon, imageMap, verticallyShapedIcon, layer, collisionBoxArray, featureIndex, sourceLayerIndex, bucketIndex, textBoxScale, textPadding, textAlongLine, textOffset, iconBoxScale, iconPadding, iconAlongLine, iconOffset, feature, sizes, isSDFIcon, canonical, layoutTextSize) {
    var assign;
    var lineArray = bucket.addToLineVertexArray(anchor, line);
    var textCollisionFeature, iconCollisionFeature, verticalTextCollisionFeature, verticalIconCollisionFeature;
    var numIconVertices = 0;
    var numVerticalIconVertices = 0;
    var numHorizontalGlyphVertices = 0;
    var numVerticalGlyphVertices = 0;
    var placedIconSymbolIndex = -1;
    var verticalPlacedIconSymbolIndex = -1;
    var placedTextSymbolIndices = {};
    var key = murmurhashJs('');
    var textOffset0 = 0;
    var textOffset1 = 0;
    if (layer._unevaluatedLayout.getValue('text-radial-offset') === undefined) {
        assign = layer.layout.get('text-offset').evaluate(feature, {}, canonical).map(function (t) {
            return t * ONE_EM;
        }), textOffset0 = assign[0], textOffset1 = assign[1];
    } else {
        textOffset0 = layer.layout.get('text-radial-offset').evaluate(feature, {}, canonical) * ONE_EM;
        textOffset1 = INVALID_TEXT_OFFSET;
    }
    if (bucket.allowVerticalPlacement && shapedTextOrientations.vertical) {
        var textRotation = layer.layout.get('text-rotate').evaluate(feature, {}, canonical);
        var verticalTextRotation = textRotation + 90;
        var verticalShaping = shapedTextOrientations.vertical;
        verticalTextCollisionFeature = new CollisionFeature(collisionBoxArray, anchor, featureIndex, sourceLayerIndex, bucketIndex, verticalShaping, textBoxScale, textPadding, textAlongLine, verticalTextRotation);
        if (verticallyShapedIcon) {
            verticalIconCollisionFeature = new CollisionFeature(collisionBoxArray, anchor, featureIndex, sourceLayerIndex, bucketIndex, verticallyShapedIcon, iconBoxScale, iconPadding, textAlongLine, verticalTextRotation);
        }
    }
    if (shapedIcon) {
        var iconRotate = layer.layout.get('icon-rotate').evaluate(feature, {});
        var hasIconTextFit = layer.layout.get('icon-text-fit') !== 'none';
        var iconQuads = getIconQuads(shapedIcon, iconRotate, isSDFIcon, hasIconTextFit);
        var verticalIconQuads = verticallyShapedIcon ? getIconQuads(verticallyShapedIcon, iconRotate, isSDFIcon, hasIconTextFit) : undefined;
        iconCollisionFeature = new CollisionFeature(collisionBoxArray, anchor, featureIndex, sourceLayerIndex, bucketIndex, shapedIcon, iconBoxScale, iconPadding, false, iconRotate);
        numIconVertices = iconQuads.length * 4;
        var sizeData = bucket.iconSizeData;
        var iconSizeData = null;
        if (sizeData.kind === 'source') {
            iconSizeData = [SIZE_PACK_FACTOR * layer.layout.get('icon-size').evaluate(feature, {})];
            if (iconSizeData[0] > MAX_PACKED_SIZE) {
                warnOnce(bucket.layerIds[0] + ': Value for "icon-size" is >= ' + MAX_GLYPH_ICON_SIZE + '. Reduce your "icon-size".');
            }
        } else if (sizeData.kind === 'composite') {
            iconSizeData = [
                SIZE_PACK_FACTOR * sizes.compositeIconSizes[0].evaluate(feature, {}, canonical),
                SIZE_PACK_FACTOR * sizes.compositeIconSizes[1].evaluate(feature, {}, canonical)
            ];
            if (iconSizeData[0] > MAX_PACKED_SIZE || iconSizeData[1] > MAX_PACKED_SIZE) {
                warnOnce(bucket.layerIds[0] + ': Value for "icon-size" is >= ' + MAX_GLYPH_ICON_SIZE + '. Reduce your "icon-size".');
            }
        }
        bucket.addSymbols(bucket.icon, iconQuads, iconSizeData, iconOffset, iconAlongLine, feature, false, anchor, lineArray.lineStartIndex, lineArray.lineLength, -1, canonical);
        placedIconSymbolIndex = bucket.icon.placedSymbolArray.length - 1;
        if (verticalIconQuads) {
            numVerticalIconVertices = verticalIconQuads.length * 4;
            bucket.addSymbols(bucket.icon, verticalIconQuads, iconSizeData, iconOffset, iconAlongLine, feature, WritingMode.vertical, anchor, lineArray.lineStartIndex, lineArray.lineLength, -1, canonical);
            verticalPlacedIconSymbolIndex = bucket.icon.placedSymbolArray.length - 1;
        }
    }
    for (var justification in shapedTextOrientations.horizontal) {
        var shaping = shapedTextOrientations.horizontal[justification];
        if (!textCollisionFeature) {
            key = murmurhashJs(shaping.text);
            var textRotate = layer.layout.get('text-rotate').evaluate(feature, {}, canonical);
            textCollisionFeature = new CollisionFeature(collisionBoxArray, anchor, featureIndex, sourceLayerIndex, bucketIndex, shaping, textBoxScale, textPadding, textAlongLine, textRotate);
        }
        var singleLine = shaping.positionedLines.length === 1;
        numHorizontalGlyphVertices += addTextVertices(bucket, anchor, shaping, imageMap, layer, textAlongLine, feature, textOffset, lineArray, shapedTextOrientations.vertical ? WritingMode.horizontal : WritingMode.horizontalOnly, singleLine ? Object.keys(shapedTextOrientations.horizontal) : [justification], placedTextSymbolIndices, placedIconSymbolIndex, sizes, canonical);
        if (singleLine) {
            break;
        }
    }
    if (shapedTextOrientations.vertical) {
        numVerticalGlyphVertices += addTextVertices(bucket, anchor, shapedTextOrientations.vertical, imageMap, layer, textAlongLine, feature, textOffset, lineArray, WritingMode.vertical, ['vertical'], placedTextSymbolIndices, verticalPlacedIconSymbolIndex, sizes, canonical);
    }
    var textBoxStartIndex = textCollisionFeature ? textCollisionFeature.boxStartIndex : bucket.collisionBoxArray.length;
    var textBoxEndIndex = textCollisionFeature ? textCollisionFeature.boxEndIndex : bucket.collisionBoxArray.length;
    var verticalTextBoxStartIndex = verticalTextCollisionFeature ? verticalTextCollisionFeature.boxStartIndex : bucket.collisionBoxArray.length;
    var verticalTextBoxEndIndex = verticalTextCollisionFeature ? verticalTextCollisionFeature.boxEndIndex : bucket.collisionBoxArray.length;
    var iconBoxStartIndex = iconCollisionFeature ? iconCollisionFeature.boxStartIndex : bucket.collisionBoxArray.length;
    var iconBoxEndIndex = iconCollisionFeature ? iconCollisionFeature.boxEndIndex : bucket.collisionBoxArray.length;
    var verticalIconBoxStartIndex = verticalIconCollisionFeature ? verticalIconCollisionFeature.boxStartIndex : bucket.collisionBoxArray.length;
    var verticalIconBoxEndIndex = verticalIconCollisionFeature ? verticalIconCollisionFeature.boxEndIndex : bucket.collisionBoxArray.length;
    var collisionCircleDiameter = -1;
    var getCollisionCircleHeight = function (feature, prevHeight) {
        if (feature && feature.circleDiameter) {
            return Math.max(feature.circleDiameter, prevHeight);
        }
        return prevHeight;
    };
    collisionCircleDiameter = getCollisionCircleHeight(textCollisionFeature, collisionCircleDiameter);
    collisionCircleDiameter = getCollisionCircleHeight(verticalTextCollisionFeature, collisionCircleDiameter);
    collisionCircleDiameter = getCollisionCircleHeight(iconCollisionFeature, collisionCircleDiameter);
    collisionCircleDiameter = getCollisionCircleHeight(verticalIconCollisionFeature, collisionCircleDiameter);
    var useRuntimeCollisionCircles = collisionCircleDiameter > -1 ? 1 : 0;
    if (useRuntimeCollisionCircles) {
        collisionCircleDiameter *= layoutTextSize / ONE_EM;
    }
    if (bucket.glyphOffsetArray.length >= SymbolBucket.MAX_GLYPHS) {
        warnOnce('Too many glyphs being rendered in a tile. See https://github.com/mapbox/mapbox-gl-js/issues/2907');
    }
    if (feature.sortKey !== undefined) {
        bucket.addToSortKeyRanges(bucket.symbolInstances.length, feature.sortKey);
    }
    bucket.symbolInstances.emplaceBack(anchor.x, anchor.y, placedTextSymbolIndices.right >= 0 ? placedTextSymbolIndices.right : -1, placedTextSymbolIndices.center >= 0 ? placedTextSymbolIndices.center : -1, placedTextSymbolIndices.left >= 0 ? placedTextSymbolIndices.left : -1, placedTextSymbolIndices.vertical || -1, placedIconSymbolIndex, verticalPlacedIconSymbolIndex, key, textBoxStartIndex, textBoxEndIndex, verticalTextBoxStartIndex, verticalTextBoxEndIndex, iconBoxStartIndex, iconBoxEndIndex, verticalIconBoxStartIndex, verticalIconBoxEndIndex, featureIndex, numHorizontalGlyphVertices, numVerticalGlyphVertices, numIconVertices, numVerticalIconVertices, useRuntimeCollisionCircles, 0, textBoxScale, textOffset0, textOffset1, collisionCircleDiameter);
}
function anchorIsTooClose(bucket, text, repeatDistance, anchor) {
    var compareText = bucket.compareText;
    if (!(text in compareText)) {
        compareText[text] = [];
    } else {
        var otherAnchors = compareText[text];
        for (var k = otherAnchors.length - 1; k >= 0; k--) {
            if (anchor.dist(otherAnchors[k]) < repeatDistance) {
                return true;
            }
        }
    }
    compareText[text].push(anchor);
    return false;
}

var vectorTileFeatureTypes$2 = vectorTile.VectorTileFeature.types;
var shaderOpacityAttributes = [{
        name: 'a_fade_opacity',
        components: 1,
        type: 'Uint8',
        offset: 0
    }];
function addVertex$1(array, anchorX, anchorY, ox, oy, tx, ty, sizeVertex, isSDF, pixelOffsetX, pixelOffsetY, minFontScaleX, minFontScaleY) {
    var aSizeX = sizeVertex ? Math.min(MAX_PACKED_SIZE, Math.round(sizeVertex[0])) : 0;
    var aSizeY = sizeVertex ? Math.min(MAX_PACKED_SIZE, Math.round(sizeVertex[1])) : 0;
    array.emplaceBack(anchorX, anchorY, Math.round(ox * 32), Math.round(oy * 32), tx, ty, (aSizeX << 1) + (isSDF ? 1 : 0), aSizeY, pixelOffsetX * 16, pixelOffsetY * 16, minFontScaleX * 256, minFontScaleY * 256);
}
function addDynamicAttributes(dynamicLayoutVertexArray, p, angle) {
    dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
    dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
    dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
    dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
}
function containsRTLText(formattedText) {
    for (var i = 0, list = formattedText.sections; i < list.length; i += 1) {
        var section = list[i];
        if (stringContainsRTLText(section.text)) {
            return true;
        }
    }
    return false;
}
var SymbolBuffers = function SymbolBuffers(programConfigurations) {
    this.layoutVertexArray = new StructArrayLayout4i4ui4i24();
    this.indexArray = new StructArrayLayout3ui6();
    this.programConfigurations = programConfigurations;
    this.segments = new SegmentVector();
    this.dynamicLayoutVertexArray = new StructArrayLayout3f12();
    this.opacityVertexArray = new StructArrayLayout1ul4();
    this.placedSymbolArray = new PlacedSymbolArray();
};
SymbolBuffers.prototype.isEmpty = function isEmpty() {
    return this.layoutVertexArray.length === 0 && this.indexArray.length === 0 && this.dynamicLayoutVertexArray.length === 0 && this.opacityVertexArray.length === 0;
};
SymbolBuffers.prototype.upload = function upload(context, dynamicIndexBuffer, upload$1, update) {
    if (this.isEmpty()) {
        return;
    }
    if (upload$1) {
        this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, symbolLayoutAttributes.members);
        this.indexBuffer = context.createIndexBuffer(this.indexArray, dynamicIndexBuffer);
        this.dynamicLayoutVertexBuffer = context.createVertexBuffer(this.dynamicLayoutVertexArray, dynamicLayoutAttributes.members, true);
        this.opacityVertexBuffer = context.createVertexBuffer(this.opacityVertexArray, shaderOpacityAttributes, true);
        this.opacityVertexBuffer.itemSize = 1;
    }
    if (upload$1 || update) {
        this.programConfigurations.upload(context);
    }
};
SymbolBuffers.prototype.destroy = function destroy() {
    if (!this.layoutVertexBuffer) {
        return;
    }
    this.layoutVertexBuffer.destroy();
    this.indexBuffer.destroy();
    this.programConfigurations.destroy();
    this.segments.destroy();
    this.dynamicLayoutVertexBuffer.destroy();
    this.opacityVertexBuffer.destroy();
};
register('SymbolBuffers', SymbolBuffers);
var CollisionBuffers = function CollisionBuffers(LayoutArray, layoutAttributes, IndexArray) {
    this.layoutVertexArray = new LayoutArray();
    this.layoutAttributes = layoutAttributes;
    this.indexArray = new IndexArray();
    this.segments = new SegmentVector();
    this.collisionVertexArray = new StructArrayLayout2ub2f12();
};
CollisionBuffers.prototype.upload = function upload(context) {
    this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, this.layoutAttributes);
    this.indexBuffer = context.createIndexBuffer(this.indexArray);
    this.collisionVertexBuffer = context.createVertexBuffer(this.collisionVertexArray, collisionVertexAttributes.members, true);
};
CollisionBuffers.prototype.destroy = function destroy() {
    if (!this.layoutVertexBuffer) {
        return;
    }
    this.layoutVertexBuffer.destroy();
    this.indexBuffer.destroy();
    this.segments.destroy();
    this.collisionVertexBuffer.destroy();
};
register('CollisionBuffers', CollisionBuffers);
var SymbolBucket = function SymbolBucket(options) {
    this.collisionBoxArray = options.collisionBoxArray;
    this.zoom = options.zoom;
    this.overscaling = options.overscaling;
    this.layers = options.layers;
    this.layerIds = this.layers.map(function (layer) {
        return layer.id;
    });
    this.index = options.index;
    this.pixelRatio = options.pixelRatio;
    this.sourceLayerIndex = options.sourceLayerIndex;
    this.hasPattern = false;
    this.hasRTLText = false;
    this.sortKeyRanges = [];
    this.collisionCircleArray = [];
    this.placementInvProjMatrix = identity([]);
    this.placementViewportMatrix = identity([]);
    var layer = this.layers[0];
    var unevaluatedLayoutValues = layer._unevaluatedLayout._values;
    this.textSizeData = getSizeData(this.zoom, unevaluatedLayoutValues['text-size']);
    this.iconSizeData = getSizeData(this.zoom, unevaluatedLayoutValues['icon-size']);
    var layout = this.layers[0].layout;
    var sortKey = layout.get('symbol-sort-key');
    var zOrder = layout.get('symbol-z-order');
    this.canOverlap = layout.get('text-allow-overlap') || layout.get('icon-allow-overlap') || layout.get('text-ignore-placement') || layout.get('icon-ignore-placement');
    this.sortFeaturesByKey = zOrder !== 'viewport-y' && sortKey.constantOr(1) !== undefined;
    var zOrderByViewportY = zOrder === 'viewport-y' || zOrder === 'auto' && !this.sortFeaturesByKey;
    this.sortFeaturesByY = zOrderByViewportY && this.canOverlap;
    if (layout.get('symbol-placement') === 'point') {
        this.writingModes = layout.get('text-writing-mode').map(function (wm) {
            return WritingMode[wm];
        });
    }
    this.stateDependentLayerIds = this.layers.filter(function (l) {
        return l.isStateDependent();
    }).map(function (l) {
        return l.id;
    });
    this.sourceID = options.sourceID;
};
SymbolBucket.prototype.createArrays = function createArrays() {
    this.text = new SymbolBuffers(new ProgramConfigurationSet(this.layers, this.zoom, function (property) {
        return /^text/.test(property);
    }));
    this.icon = new SymbolBuffers(new ProgramConfigurationSet(this.layers, this.zoom, function (property) {
        return /^icon/.test(property);
    }));
    this.glyphOffsetArray = new GlyphOffsetArray();
    this.lineVertexArray = new SymbolLineVertexArray();
    this.symbolInstances = new SymbolInstanceArray();
};
SymbolBucket.prototype.calculateGlyphDependencies = function calculateGlyphDependencies(text, stack, textAlongLine, allowVerticalPlacement, doesAllowVerticalWritingMode) {
    for (var i = 0; i < text.length; i++) {
        stack[text.charCodeAt(i)] = true;
        if ((textAlongLine || allowVerticalPlacement) && doesAllowVerticalWritingMode) {
            var verticalChar = verticalizedCharacterMap[text.charAt(i)];
            if (verticalChar) {
                stack[verticalChar.charCodeAt(0)] = true;
            }
        }
    }
};
SymbolBucket.prototype.populate = function populate(features, options, canonical) {
    var layer = this.layers[0];
    var layout = layer.layout;
    var textFont = layout.get('text-font');
    var textField = layout.get('text-field');
    var iconImage = layout.get('icon-image');
    var hasText = (textField.value.kind !== 'constant' || textField.value.value instanceof Formatted && !textField.value.value.isEmpty() || textField.value.value.toString().length > 0) && (textFont.value.kind !== 'constant' || textFont.value.value.length > 0);
    var hasIcon = iconImage.value.kind !== 'constant' || !!iconImage.value.value || Object.keys(iconImage.parameters).length > 0;
    var symbolSortKey = layout.get('symbol-sort-key');
    this.features = [];
    if (!hasText && !hasIcon) {
        return;
    }
    var icons = options.iconDependencies;
    var stacks = options.glyphDependencies;
    var availableImages = options.availableImages;
    var globalProperties = new EvaluationParameters(this.zoom);
    for (var i$1 = 0, list$1 = features; i$1 < list$1.length; i$1 += 1) {
        var ref = list$1[i$1];
        var feature = ref.feature;
        var id = ref.id;
        var index = ref.index;
        var sourceLayerIndex = ref.sourceLayerIndex;
        var needGeometry = layer._featureFilter.needGeometry;
        var evaluationFeature = toEvaluationFeature(feature, needGeometry);
        if (!layer._featureFilter.filter(globalProperties, evaluationFeature, canonical)) {
            continue;
        }
        if (!needGeometry) {
            evaluationFeature.geometry = loadGeometry(feature);
        }
        var text = void 0;
        if (hasText) {
            var resolvedTokens = layer.getValueAndResolveTokens('text-field', evaluationFeature, canonical, availableImages);
            var formattedText = Formatted.factory(resolvedTokens);
            if (containsRTLText(formattedText)) {
                this.hasRTLText = true;
            }
            if (!this.hasRTLText || getRTLTextPluginStatus() === 'unavailable' || this.hasRTLText && plugin.isParsed()) {
                text = transformText$1(formattedText, layer, evaluationFeature);
            }
        }
        var icon = void 0;
        if (hasIcon) {
            var resolvedTokens$1 = layer.getValueAndResolveTokens('icon-image', evaluationFeature, canonical, availableImages);
            if (resolvedTokens$1 instanceof ResolvedImage) {
                icon = resolvedTokens$1;
            } else {
                icon = ResolvedImage.fromString(resolvedTokens$1);
            }
        }
        if (!text && !icon) {
            continue;
        }
        var sortKey = this.sortFeaturesByKey ? symbolSortKey.evaluate(evaluationFeature, {}, canonical) : undefined;
        var symbolFeature = {
            id: id,
            text: text,
            icon: icon,
            index: index,
            sourceLayerIndex: sourceLayerIndex,
            geometry: evaluationFeature.geometry,
            properties: feature.properties,
            type: vectorTileFeatureTypes$2[feature.type],
            sortKey: sortKey
        };
        this.features.push(symbolFeature);
        if (icon) {
            icons[icon.name] = true;
        }
        if (text) {
            var fontStack = textFont.evaluate(evaluationFeature, {}, canonical).join(',');
            var textAlongLine = layout.get('text-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point';
            this.allowVerticalPlacement = this.writingModes && this.writingModes.indexOf(WritingMode.vertical) >= 0;
            for (var i = 0, list = text.sections; i < list.length; i += 1) {
                var section = list[i];
                if (!section.image) {
                    var doesAllowVerticalWritingMode = allowsVerticalWritingMode(text.toString());
                    var sectionFont = section.fontStack || fontStack;
                    var sectionStack = stacks[sectionFont] = stacks[sectionFont] || {};
                    this.calculateGlyphDependencies(section.text, sectionStack, textAlongLine, this.allowVerticalPlacement, doesAllowVerticalWritingMode);
                } else {
                    icons[section.image.name] = true;
                }
            }
        }
    }
    if (layout.get('symbol-placement') === 'line') {
        this.features = mergeLines(this.features);
    }
    if (this.sortFeaturesByKey) {
        this.features.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
};
SymbolBucket.prototype.update = function update(states, vtLayer, imagePositions) {
    if (!this.stateDependentLayers.length) {
        return;
    }
    this.text.programConfigurations.updatePaintArrays(states, vtLayer, this.layers, imagePositions);
    this.icon.programConfigurations.updatePaintArrays(states, vtLayer, this.layers, imagePositions);
};
SymbolBucket.prototype.isEmpty = function isEmpty() {
    return this.symbolInstances.length === 0 && !this.hasRTLText;
};
SymbolBucket.prototype.uploadPending = function uploadPending() {
    return !this.uploaded || this.text.programConfigurations.needsUpload || this.icon.programConfigurations.needsUpload;
};
SymbolBucket.prototype.upload = function upload(context) {
    if (!this.uploaded && this.hasDebugData()) {
        this.textCollisionBox.upload(context);
        this.iconCollisionBox.upload(context);
    }
    this.text.upload(context, this.sortFeaturesByY, !this.uploaded, this.text.programConfigurations.needsUpload);
    this.icon.upload(context, this.sortFeaturesByY, !this.uploaded, this.icon.programConfigurations.needsUpload);
    this.uploaded = true;
};
SymbolBucket.prototype.destroyDebugData = function destroyDebugData() {
    this.textCollisionBox.destroy();
    this.iconCollisionBox.destroy();
};
SymbolBucket.prototype.destroy = function destroy() {
    this.text.destroy();
    this.icon.destroy();
    if (this.hasDebugData()) {
        this.destroyDebugData();
    }
};
SymbolBucket.prototype.addToLineVertexArray = function addToLineVertexArray(anchor, line) {
    var lineStartIndex = this.lineVertexArray.length;
    if (anchor.segment !== undefined) {
        var sumForwardLength = anchor.dist(line[anchor.segment + 1]);
        var sumBackwardLength = anchor.dist(line[anchor.segment]);
        var vertices = {};
        for (var i = anchor.segment + 1; i < line.length; i++) {
            vertices[i] = {
                x: line[i].x,
                y: line[i].y,
                tileUnitDistanceFromAnchor: sumForwardLength
            };
            if (i < line.length - 1) {
                sumForwardLength += line[i + 1].dist(line[i]);
            }
        }
        for (var i$1 = anchor.segment || 0; i$1 >= 0; i$1--) {
            vertices[i$1] = {
                x: line[i$1].x,
                y: line[i$1].y,
                tileUnitDistanceFromAnchor: sumBackwardLength
            };
            if (i$1 > 0) {
                sumBackwardLength += line[i$1 - 1].dist(line[i$1]);
            }
        }
        for (var i$2 = 0; i$2 < line.length; i$2++) {
            var vertex = vertices[i$2];
            this.lineVertexArray.emplaceBack(vertex.x, vertex.y, vertex.tileUnitDistanceFromAnchor);
        }
    }
    return {
        lineStartIndex: lineStartIndex,
        lineLength: this.lineVertexArray.length - lineStartIndex
    };
};
SymbolBucket.prototype.addSymbols = function addSymbols(arrays, quads, sizeVertex, lineOffset, alongLine, feature, writingMode, labelAnchor, lineStartIndex, lineLength, associatedIconIndex, canonical) {
    var indexArray = arrays.indexArray;
    var layoutVertexArray = arrays.layoutVertexArray;
    var segment = arrays.segments.prepareSegment(4 * quads.length, layoutVertexArray, indexArray, this.canOverlap ? feature.sortKey : undefined);
    var glyphOffsetArrayStart = this.glyphOffsetArray.length;
    var vertexStartIndex = segment.vertexLength;
    var angle = this.allowVerticalPlacement && writingMode === WritingMode.vertical ? Math.PI / 2 : 0;
    var sections = feature.text && feature.text.sections;
    for (var i = 0; i < quads.length; i++) {
        var ref = quads[i];
        var tl = ref.tl;
        var tr = ref.tr;
        var bl = ref.bl;
        var br = ref.br;
        var tex = ref.tex;
        var pixelOffsetTL = ref.pixelOffsetTL;
        var pixelOffsetBR = ref.pixelOffsetBR;
        var minFontScaleX = ref.minFontScaleX;
        var minFontScaleY = ref.minFontScaleY;
        var glyphOffset = ref.glyphOffset;
        var isSDF = ref.isSDF;
        var sectionIndex = ref.sectionIndex;
        var index = segment.vertexLength;
        var y = glyphOffset[1];
        addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, tl.x, y + tl.y, tex.x, tex.y, sizeVertex, isSDF, pixelOffsetTL.x, pixelOffsetTL.y, minFontScaleX, minFontScaleY);
        addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, tr.x, y + tr.y, tex.x + tex.w, tex.y, sizeVertex, isSDF, pixelOffsetBR.x, pixelOffsetTL.y, minFontScaleX, minFontScaleY);
        addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, bl.x, y + bl.y, tex.x, tex.y + tex.h, sizeVertex, isSDF, pixelOffsetTL.x, pixelOffsetBR.y, minFontScaleX, minFontScaleY);
        addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, br.x, y + br.y, tex.x + tex.w, tex.y + tex.h, sizeVertex, isSDF, pixelOffsetBR.x, pixelOffsetBR.y, minFontScaleX, minFontScaleY);
        addDynamicAttributes(arrays.dynamicLayoutVertexArray, labelAnchor, angle);
        indexArray.emplaceBack(index, index + 1, index + 2);
        indexArray.emplaceBack(index + 1, index + 2, index + 3);
        segment.vertexLength += 4;
        segment.primitiveLength += 2;
        this.glyphOffsetArray.emplaceBack(glyphOffset[0]);
        if (i === quads.length - 1 || sectionIndex !== quads[i + 1].sectionIndex) {
            arrays.programConfigurations.populatePaintArrays(layoutVertexArray.length, feature, feature.index, {}, canonical, sections && sections[sectionIndex]);
        }
    }
    arrays.placedSymbolArray.emplaceBack(labelAnchor.x, labelAnchor.y, glyphOffsetArrayStart, this.glyphOffsetArray.length - glyphOffsetArrayStart, vertexStartIndex, lineStartIndex, lineLength, labelAnchor.segment, sizeVertex ? sizeVertex[0] : 0, sizeVertex ? sizeVertex[1] : 0, lineOffset[0], lineOffset[1], writingMode, 0, false, 0, associatedIconIndex);
};
SymbolBucket.prototype._addCollisionDebugVertex = function _addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, point, anchorX, anchorY, extrude) {
    collisionVertexArray.emplaceBack(0, 0);
    return layoutVertexArray.emplaceBack(point.x, point.y, anchorX, anchorY, Math.round(extrude.x), Math.round(extrude.y));
};
SymbolBucket.prototype.addCollisionDebugVertices = function addCollisionDebugVertices(x1, y1, x2, y2, arrays, boxAnchorPoint, symbolInstance) {
    var segment = arrays.segments.prepareSegment(4, arrays.layoutVertexArray, arrays.indexArray);
    var index = segment.vertexLength;
    var layoutVertexArray = arrays.layoutVertexArray;
    var collisionVertexArray = arrays.collisionVertexArray;
    var anchorX = symbolInstance.anchorX;
    var anchorY = symbolInstance.anchorY;
    this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new pointGeometry(x1, y1));
    this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new pointGeometry(x2, y1));
    this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new pointGeometry(x2, y2));
    this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new pointGeometry(x1, y2));
    segment.vertexLength += 4;
    var indexArray = arrays.indexArray;
    indexArray.emplaceBack(index, index + 1);
    indexArray.emplaceBack(index + 1, index + 2);
    indexArray.emplaceBack(index + 2, index + 3);
    indexArray.emplaceBack(index + 3, index);
    segment.primitiveLength += 4;
};
SymbolBucket.prototype.addDebugCollisionBoxes = function addDebugCollisionBoxes(startIndex, endIndex, symbolInstance, isText) {
    for (var b = startIndex; b < endIndex; b++) {
        var box = this.collisionBoxArray.get(b);
        var x1 = box.x1;
        var y1 = box.y1;
        var x2 = box.x2;
        var y2 = box.y2;
        this.addCollisionDebugVertices(x1, y1, x2, y2, isText ? this.textCollisionBox : this.iconCollisionBox, box.anchorPoint, symbolInstance);
    }
};
SymbolBucket.prototype.generateCollisionDebugBuffers = function generateCollisionDebugBuffers() {
    if (this.hasDebugData()) {
        this.destroyDebugData();
    }
    this.textCollisionBox = new CollisionBuffers(StructArrayLayout2i2i2i12, collisionBoxLayout.members, StructArrayLayout2ui4);
    this.iconCollisionBox = new CollisionBuffers(StructArrayLayout2i2i2i12, collisionBoxLayout.members, StructArrayLayout2ui4);
    for (var i = 0; i < this.symbolInstances.length; i++) {
        var symbolInstance = this.symbolInstances.get(i);
        this.addDebugCollisionBoxes(symbolInstance.textBoxStartIndex, symbolInstance.textBoxEndIndex, symbolInstance, true);
        this.addDebugCollisionBoxes(symbolInstance.verticalTextBoxStartIndex, symbolInstance.verticalTextBoxEndIndex, symbolInstance, true);
        this.addDebugCollisionBoxes(symbolInstance.iconBoxStartIndex, symbolInstance.iconBoxEndIndex, symbolInstance, false);
        this.addDebugCollisionBoxes(symbolInstance.verticalIconBoxStartIndex, symbolInstance.verticalIconBoxEndIndex, symbolInstance, false);
    }
};
SymbolBucket.prototype._deserializeCollisionBoxesForSymbol = function _deserializeCollisionBoxesForSymbol(collisionBoxArray, textStartIndex, textEndIndex, verticalTextStartIndex, verticalTextEndIndex, iconStartIndex, iconEndIndex, verticalIconStartIndex, verticalIconEndIndex) {
    var collisionArrays = {};
    for (var k = textStartIndex; k < textEndIndex; k++) {
        var box = collisionBoxArray.get(k);
        collisionArrays.textBox = {
            x1: box.x1,
            y1: box.y1,
            x2: box.x2,
            y2: box.y2,
            anchorPointX: box.anchorPointX,
            anchorPointY: box.anchorPointY
        };
        collisionArrays.textFeatureIndex = box.featureIndex;
        break;
    }
    for (var k$1 = verticalTextStartIndex; k$1 < verticalTextEndIndex; k$1++) {
        var box$1 = collisionBoxArray.get(k$1);
        collisionArrays.verticalTextBox = {
            x1: box$1.x1,
            y1: box$1.y1,
            x2: box$1.x2,
            y2: box$1.y2,
            anchorPointX: box$1.anchorPointX,
            anchorPointY: box$1.anchorPointY
        };
        collisionArrays.verticalTextFeatureIndex = box$1.featureIndex;
        break;
    }
    for (var k$2 = iconStartIndex; k$2 < iconEndIndex; k$2++) {
        var box$2 = collisionBoxArray.get(k$2);
        collisionArrays.iconBox = {
            x1: box$2.x1,
            y1: box$2.y1,
            x2: box$2.x2,
            y2: box$2.y2,
            anchorPointX: box$2.anchorPointX,
            anchorPointY: box$2.anchorPointY
        };
        collisionArrays.iconFeatureIndex = box$2.featureIndex;
        break;
    }
    for (var k$3 = verticalIconStartIndex; k$3 < verticalIconEndIndex; k$3++) {
        var box$3 = collisionBoxArray.get(k$3);
        collisionArrays.verticalIconBox = {
            x1: box$3.x1,
            y1: box$3.y1,
            x2: box$3.x2,
            y2: box$3.y2,
            anchorPointX: box$3.anchorPointX,
            anchorPointY: box$3.anchorPointY
        };
        collisionArrays.verticalIconFeatureIndex = box$3.featureIndex;
        break;
    }
    return collisionArrays;
};
SymbolBucket.prototype.deserializeCollisionBoxes = function deserializeCollisionBoxes(collisionBoxArray) {
    this.collisionArrays = [];
    for (var i = 0; i < this.symbolInstances.length; i++) {
        var symbolInstance = this.symbolInstances.get(i);
        this.collisionArrays.push(this._deserializeCollisionBoxesForSymbol(collisionBoxArray, symbolInstance.textBoxStartIndex, symbolInstance.textBoxEndIndex, symbolInstance.verticalTextBoxStartIndex, symbolInstance.verticalTextBoxEndIndex, symbolInstance.iconBoxStartIndex, symbolInstance.iconBoxEndIndex, symbolInstance.verticalIconBoxStartIndex, symbolInstance.verticalIconBoxEndIndex));
    }
};
SymbolBucket.prototype.hasTextData = function hasTextData() {
    return this.text.segments.get().length > 0;
};
SymbolBucket.prototype.hasIconData = function hasIconData() {
    return this.icon.segments.get().length > 0;
};
SymbolBucket.prototype.hasDebugData = function hasDebugData() {
    return this.textCollisionBox && this.iconCollisionBox;
};
SymbolBucket.prototype.hasTextCollisionBoxData = function hasTextCollisionBoxData() {
    return this.hasDebugData() && this.textCollisionBox.segments.get().length > 0;
};
SymbolBucket.prototype.hasIconCollisionBoxData = function hasIconCollisionBoxData() {
    return this.hasDebugData() && this.iconCollisionBox.segments.get().length > 0;
};
SymbolBucket.prototype.addIndicesForPlacedSymbol = function addIndicesForPlacedSymbol(iconOrText, placedSymbolIndex) {
    var placedSymbol = iconOrText.placedSymbolArray.get(placedSymbolIndex);
    var endIndex = placedSymbol.vertexStartIndex + placedSymbol.numGlyphs * 4;
    for (var vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) {
        iconOrText.indexArray.emplaceBack(vertexIndex, vertexIndex + 1, vertexIndex + 2);
        iconOrText.indexArray.emplaceBack(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);
    }
};
SymbolBucket.prototype.getSortedSymbolIndexes = function getSortedSymbolIndexes(angle) {
    if (this.sortedAngle === angle && this.symbolInstanceIndexes !== undefined) {
        return this.symbolInstanceIndexes;
    }
    var sin = Math.sin(angle);
    var cos = Math.cos(angle);
    var rotatedYs = [];
    var featureIndexes = [];
    var result = [];
    for (var i = 0; i < this.symbolInstances.length; ++i) {
        result.push(i);
        var symbolInstance = this.symbolInstances.get(i);
        rotatedYs.push(Math.round(sin * symbolInstance.anchorX + cos * symbolInstance.anchorY) | 0);
        featureIndexes.push(symbolInstance.featureIndex);
    }
    result.sort(function (aIndex, bIndex) {
        return rotatedYs[aIndex] - rotatedYs[bIndex] || featureIndexes[bIndex] - featureIndexes[aIndex];
    });
    return result;
};
SymbolBucket.prototype.addToSortKeyRanges = function addToSortKeyRanges(symbolInstanceIndex, sortKey) {
    var last = this.sortKeyRanges[this.sortKeyRanges.length - 1];
    if (last && last.sortKey === sortKey) {
        last.symbolInstanceEnd = symbolInstanceIndex + 1;
    } else {
        this.sortKeyRanges.push({
            sortKey: sortKey,
            symbolInstanceStart: symbolInstanceIndex,
            symbolInstanceEnd: symbolInstanceIndex + 1
        });
    }
};
SymbolBucket.prototype.sortFeatures = function sortFeatures(angle) {
    var this$1 = this;
    if (!this.sortFeaturesByY) {
        return;
    }
    if (this.sortedAngle === angle) {
        return;
    }
    if (this.text.segments.get().length > 1 || this.icon.segments.get().length > 1) {
        return;
    }
    this.symbolInstanceIndexes = this.getSortedSymbolIndexes(angle);
    this.sortedAngle = angle;
    this.text.indexArray.clear();
    this.icon.indexArray.clear();
    this.featureSortOrder = [];
    for (var i$1 = 0, list = this.symbolInstanceIndexes; i$1 < list.length; i$1 += 1) {
        var i = list[i$1];
        var symbolInstance = this.symbolInstances.get(i);
        this.featureSortOrder.push(symbolInstance.featureIndex);
        [
            symbolInstance.rightJustifiedTextSymbolIndex,
            symbolInstance.centerJustifiedTextSymbolIndex,
            symbolInstance.leftJustifiedTextSymbolIndex
        ].forEach(function (index, i, array) {
            if (index >= 0 && array.indexOf(index) === i) {
                this$1.addIndicesForPlacedSymbol(this$1.text, index);
            }
        });
        if (symbolInstance.verticalPlacedTextSymbolIndex >= 0) {
            this.addIndicesForPlacedSymbol(this.text, symbolInstance.verticalPlacedTextSymbolIndex);
        }
        if (symbolInstance.placedIconSymbolIndex >= 0) {
            this.addIndicesForPlacedSymbol(this.icon, symbolInstance.placedIconSymbolIndex);
        }
        if (symbolInstance.verticalPlacedIconSymbolIndex >= 0) {
            this.addIndicesForPlacedSymbol(this.icon, symbolInstance.verticalPlacedIconSymbolIndex);
        }
    }
    if (this.text.indexBuffer) {
        this.text.indexBuffer.updateData(this.text.indexArray);
    }
    if (this.icon.indexBuffer) {
        this.icon.indexBuffer.updateData(this.icon.indexArray);
    }
};
register('SymbolBucket', SymbolBucket, {
    omit: [
        'layers',
        'collisionBoxArray',
        'features',
        'compareText'
    ]
});
SymbolBucket.MAX_GLYPHS = 65535;
SymbolBucket.addDynamicAttributes = addDynamicAttributes;

function resolveTokens(properties, text) {
    return text.replace(/{([^{}]+)}/g, function (match, key) {
        return key in properties ? String(properties[key]) : '';
    });
}

var layout$7 = new Properties({
    'symbol-placement': new DataConstantProperty(spec['layout_symbol']['symbol-placement']),
    'symbol-spacing': new DataConstantProperty(spec['layout_symbol']['symbol-spacing']),
    'symbol-avoid-edges': new DataConstantProperty(spec['layout_symbol']['symbol-avoid-edges']),
    'symbol-sort-key': new DataDrivenProperty(spec['layout_symbol']['symbol-sort-key']),
    'symbol-z-order': new DataConstantProperty(spec['layout_symbol']['symbol-z-order']),
    'icon-allow-overlap': new DataConstantProperty(spec['layout_symbol']['icon-allow-overlap']),
    'icon-ignore-placement': new DataConstantProperty(spec['layout_symbol']['icon-ignore-placement']),
    'icon-optional': new DataConstantProperty(spec['layout_symbol']['icon-optional']),
    'icon-rotation-alignment': new DataConstantProperty(spec['layout_symbol']['icon-rotation-alignment']),
    'icon-size': new DataDrivenProperty(spec['layout_symbol']['icon-size']),
    'icon-text-fit': new DataConstantProperty(spec['layout_symbol']['icon-text-fit']),
    'icon-text-fit-padding': new DataConstantProperty(spec['layout_symbol']['icon-text-fit-padding']),
    'icon-image': new DataDrivenProperty(spec['layout_symbol']['icon-image']),
    'icon-rotate': new DataDrivenProperty(spec['layout_symbol']['icon-rotate']),
    'icon-padding': new DataConstantProperty(spec['layout_symbol']['icon-padding']),
    'icon-keep-upright': new DataConstantProperty(spec['layout_symbol']['icon-keep-upright']),
    'icon-offset': new DataDrivenProperty(spec['layout_symbol']['icon-offset']),
    'icon-anchor': new DataDrivenProperty(spec['layout_symbol']['icon-anchor']),
    'icon-pitch-alignment': new DataConstantProperty(spec['layout_symbol']['icon-pitch-alignment']),
    'text-pitch-alignment': new DataConstantProperty(spec['layout_symbol']['text-pitch-alignment']),
    'text-rotation-alignment': new DataConstantProperty(spec['layout_symbol']['text-rotation-alignment']),
    'text-field': new DataDrivenProperty(spec['layout_symbol']['text-field']),
    'text-font': new DataDrivenProperty(spec['layout_symbol']['text-font']),
    'text-size': new DataDrivenProperty(spec['layout_symbol']['text-size']),
    'text-max-width': new DataDrivenProperty(spec['layout_symbol']['text-max-width']),
    'text-line-height': new DataConstantProperty(spec['layout_symbol']['text-line-height']),
    'text-letter-spacing': new DataDrivenProperty(spec['layout_symbol']['text-letter-spacing']),
    'text-justify': new DataDrivenProperty(spec['layout_symbol']['text-justify']),
    'text-radial-offset': new DataDrivenProperty(spec['layout_symbol']['text-radial-offset']),
    'text-variable-anchor': new DataConstantProperty(spec['layout_symbol']['text-variable-anchor']),
    'text-anchor': new DataDrivenProperty(spec['layout_symbol']['text-anchor']),
    'text-max-angle': new DataConstantProperty(spec['layout_symbol']['text-max-angle']),
    'text-writing-mode': new DataConstantProperty(spec['layout_symbol']['text-writing-mode']),
    'text-rotate': new DataDrivenProperty(spec['layout_symbol']['text-rotate']),
    'text-padding': new DataConstantProperty(spec['layout_symbol']['text-padding']),
    'text-keep-upright': new DataConstantProperty(spec['layout_symbol']['text-keep-upright']),
    'text-transform': new DataDrivenProperty(spec['layout_symbol']['text-transform']),
    'text-offset': new DataDrivenProperty(spec['layout_symbol']['text-offset']),
    'text-allow-overlap': new DataConstantProperty(spec['layout_symbol']['text-allow-overlap']),
    'text-ignore-placement': new DataConstantProperty(spec['layout_symbol']['text-ignore-placement']),
    'text-optional': new DataConstantProperty(spec['layout_symbol']['text-optional'])
});
var paint$7 = new Properties({
    'icon-opacity': new DataDrivenProperty(spec['paint_symbol']['icon-opacity']),
    'icon-color': new DataDrivenProperty(spec['paint_symbol']['icon-color']),
    'icon-halo-color': new DataDrivenProperty(spec['paint_symbol']['icon-halo-color']),
    'icon-halo-width': new DataDrivenProperty(spec['paint_symbol']['icon-halo-width']),
    'icon-halo-blur': new DataDrivenProperty(spec['paint_symbol']['icon-halo-blur']),
    'icon-translate': new DataConstantProperty(spec['paint_symbol']['icon-translate']),
    'icon-translate-anchor': new DataConstantProperty(spec['paint_symbol']['icon-translate-anchor']),
    'text-opacity': new DataDrivenProperty(spec['paint_symbol']['text-opacity']),
    'text-color': new DataDrivenProperty(spec['paint_symbol']['text-color'], {
        runtimeType: ColorType,
        getOverride: function (o) {
            return o.textColor;
        },
        hasOverride: function (o) {
            return !!o.textColor;
        }
    }),
    'text-halo-color': new DataDrivenProperty(spec['paint_symbol']['text-halo-color']),
    'text-halo-width': new DataDrivenProperty(spec['paint_symbol']['text-halo-width']),
    'text-halo-blur': new DataDrivenProperty(spec['paint_symbol']['text-halo-blur']),
    'text-translate': new DataConstantProperty(spec['paint_symbol']['text-translate']),
    'text-translate-anchor': new DataConstantProperty(spec['paint_symbol']['text-translate-anchor'])
});
var properties$6 = {
    paint: paint$7,
    layout: layout$7
};

var FormatSectionOverride = function FormatSectionOverride(defaultValue) {
    this.type = defaultValue.property.overrides ? defaultValue.property.overrides.runtimeType : NullType;
    this.defaultValue = defaultValue;
};
FormatSectionOverride.prototype.evaluate = function evaluate(ctx) {
    if (ctx.formattedSection) {
        var overrides = this.defaultValue.property.overrides;
        if (overrides && overrides.hasOverride(ctx.formattedSection)) {
            return overrides.getOverride(ctx.formattedSection);
        }
    }
    if (ctx.feature && ctx.featureState) {
        return this.defaultValue.evaluate(ctx.feature, ctx.featureState);
    }
    return this.defaultValue.property.specification.default;
};
FormatSectionOverride.prototype.eachChild = function eachChild(fn) {
    if (!this.defaultValue.isConstant()) {
        var expr = this.defaultValue.value;
        fn(expr._styleExpression.expression);
    }
};
FormatSectionOverride.prototype.outputDefined = function outputDefined() {
    return false;
};
FormatSectionOverride.prototype.serialize = function serialize() {
    return null;
};
register('FormatSectionOverride', FormatSectionOverride, { omit: ['defaultValue'] });

var SymbolStyleLayer = function (StyleLayer) {
    function SymbolStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$6);
    }
    if (StyleLayer)
        SymbolStyleLayer.__proto__ = StyleLayer;
    SymbolStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    SymbolStyleLayer.prototype.constructor = SymbolStyleLayer;
    SymbolStyleLayer.prototype.recalculate = function recalculate(parameters, availableImages) {
        StyleLayer.prototype.recalculate.call(this, parameters, availableImages);
        if (this.layout.get('icon-rotation-alignment') === 'auto') {
            if (this.layout.get('symbol-placement') !== 'point') {
                this.layout._values['icon-rotation-alignment'] = 'map';
            } else {
                this.layout._values['icon-rotation-alignment'] = 'viewport';
            }
        }
        if (this.layout.get('text-rotation-alignment') === 'auto') {
            if (this.layout.get('symbol-placement') !== 'point') {
                this.layout._values['text-rotation-alignment'] = 'map';
            } else {
                this.layout._values['text-rotation-alignment'] = 'viewport';
            }
        }
        if (this.layout.get('text-pitch-alignment') === 'auto') {
            this.layout._values['text-pitch-alignment'] = this.layout.get('text-rotation-alignment');
        }
        if (this.layout.get('icon-pitch-alignment') === 'auto') {
            this.layout._values['icon-pitch-alignment'] = this.layout.get('icon-rotation-alignment');
        }
        if (this.layout.get('symbol-placement') === 'point') {
            var writingModes = this.layout.get('text-writing-mode');
            if (writingModes) {
                var deduped = [];
                for (var i = 0, list = writingModes; i < list.length; i += 1) {
                    var m = list[i];
                    if (deduped.indexOf(m) < 0) {
                        deduped.push(m);
                    }
                }
                this.layout._values['text-writing-mode'] = deduped;
            } else {
                this.layout._values['text-writing-mode'] = ['horizontal'];
            }
        }
        this._setPaintOverrides();
    };
    SymbolStyleLayer.prototype.getValueAndResolveTokens = function getValueAndResolveTokens(name, feature, canonical, availableImages) {
        var value = this.layout.get(name).evaluate(feature, {}, canonical, availableImages);
        var unevaluated = this._unevaluatedLayout._values[name];
        if (!unevaluated.isDataDriven() && !isExpression(unevaluated.value) && value) {
            return resolveTokens(feature.properties, value);
        }
        return value;
    };
    SymbolStyleLayer.prototype.createBucket = function createBucket(parameters) {
        return new SymbolBucket(parameters);
    };
    SymbolStyleLayer.prototype.queryRadius = function queryRadius() {
        return 0;
    };
    SymbolStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature() {
        return false;
    };
    SymbolStyleLayer.prototype._setPaintOverrides = function _setPaintOverrides() {
        for (var i = 0, list = properties$6.paint.overridableProperties; i < list.length; i += 1) {
            var overridable = list[i];
            if (!SymbolStyleLayer.hasPaintOverride(this.layout, overridable)) {
                continue;
            }
            var overriden = this.paint.get(overridable);
            var override = new FormatSectionOverride(overriden);
            var styleExpression = new StyleExpression(override, overriden.property.specification);
            var expression = null;
            if (overriden.value.kind === 'constant' || overriden.value.kind === 'source') {
                expression = new ZoomConstantExpression('source', styleExpression);
            } else {
                expression = new ZoomDependentExpression('composite', styleExpression, overriden.value.zoomStops, overriden.value._interpolationType);
            }
            this.paint._values[overridable] = new PossiblyEvaluatedPropertyValue(overriden.property, expression, overriden.parameters);
        }
    };
    SymbolStyleLayer.prototype._handleOverridablePaintPropertyUpdate = function _handleOverridablePaintPropertyUpdate(name, oldValue, newValue) {
        if (!this.layout || oldValue.isDataDriven() || newValue.isDataDriven()) {
            return false;
        }
        return SymbolStyleLayer.hasPaintOverride(this.layout, name);
    };
    SymbolStyleLayer.hasPaintOverride = function hasPaintOverride(layout, propertyName) {
        var textField = layout.get('text-field');
        var property = properties$6.paint.properties[propertyName];
        var hasOverrides = false;
        var checkSections = function (sections) {
            for (var i = 0, list = sections; i < list.length; i += 1) {
                var section = list[i];
                if (property.overrides && property.overrides.hasOverride(section)) {
                    hasOverrides = true;
                    return;
                }
            }
        };
        if (textField.value.kind === 'constant' && textField.value.value instanceof Formatted) {
            checkSections(textField.value.value.sections);
        } else if (textField.value.kind === 'source') {
            var checkExpression = function (expression) {
                if (hasOverrides) {
                    return;
                }
                if (expression instanceof Literal && typeOf(expression.value) === FormattedType) {
                    var formatted = expression.value;
                    checkSections(formatted.sections);
                } else if (expression instanceof FormatExpression) {
                    checkSections(expression.sections);
                } else {
                    expression.eachChild(checkExpression);
                }
            };
            var expr = textField.value;
            if (expr._styleExpression) {
                checkExpression(expr._styleExpression.expression);
            }
        }
        return hasOverrides;
    };
    return SymbolStyleLayer;
}(StyleLayer);

var paint$8 = new Properties({
    'background-color': new DataConstantProperty(spec['paint_background']['background-color']),
    'background-pattern': new CrossFadedProperty(spec['paint_background']['background-pattern']),
    'background-opacity': new DataConstantProperty(spec['paint_background']['background-opacity'])
});
var properties$7 = { paint: paint$8 };

var BackgroundStyleLayer = function (StyleLayer) {
    function BackgroundStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$7);
    }
    if (StyleLayer)
        BackgroundStyleLayer.__proto__ = StyleLayer;
    BackgroundStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    BackgroundStyleLayer.prototype.constructor = BackgroundStyleLayer;
    return BackgroundStyleLayer;
}(StyleLayer);

var paint$9 = new Properties({
    'raster-opacity': new DataConstantProperty(spec['paint_raster']['raster-opacity']),
    'raster-hue-rotate': new DataConstantProperty(spec['paint_raster']['raster-hue-rotate']),
    'raster-brightness-min': new DataConstantProperty(spec['paint_raster']['raster-brightness-min']),
    'raster-brightness-max': new DataConstantProperty(spec['paint_raster']['raster-brightness-max']),
    'raster-saturation': new DataConstantProperty(spec['paint_raster']['raster-saturation']),
    'raster-contrast': new DataConstantProperty(spec['paint_raster']['raster-contrast']),
    'raster-resampling': new DataConstantProperty(spec['paint_raster']['raster-resampling']),
    'raster-fade-duration': new DataConstantProperty(spec['paint_raster']['raster-fade-duration'])
});
var properties$8 = { paint: paint$9 };

var RasterStyleLayer = function (StyleLayer) {
    function RasterStyleLayer(layer) {
        StyleLayer.call(this, layer, properties$8);
    }
    if (StyleLayer)
        RasterStyleLayer.__proto__ = StyleLayer;
    RasterStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    RasterStyleLayer.prototype.constructor = RasterStyleLayer;
    return RasterStyleLayer;
}(StyleLayer);

function validateCustomStyleLayer(layerObject) {
    var errors = [];
    var id = layerObject.id;
    if (id === undefined) {
        errors.push({ message: 'layers.' + id + ': missing required property "id"' });
    }
    if (layerObject.render === undefined) {
        errors.push({ message: 'layers.' + id + ': missing required method "render"' });
    }
    if (layerObject.renderingMode && layerObject.renderingMode !== '2d' && layerObject.renderingMode !== '3d') {
        errors.push({ message: 'layers.' + id + ': property "renderingMode" must be either "2d" or "3d"' });
    }
    return errors;
}
var CustomStyleLayer = function (StyleLayer) {
    function CustomStyleLayer(implementation) {
        StyleLayer.call(this, implementation, {});
        this.implementation = implementation;
    }
    if (StyleLayer)
        CustomStyleLayer.__proto__ = StyleLayer;
    CustomStyleLayer.prototype = Object.create(StyleLayer && StyleLayer.prototype);
    CustomStyleLayer.prototype.constructor = CustomStyleLayer;
    CustomStyleLayer.prototype.is3D = function is3D() {
        return this.implementation.renderingMode === '3d';
    };
    CustomStyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass() {
        return this.implementation.prerender !== undefined;
    };
    CustomStyleLayer.prototype.recalculate = function recalculate() {
    };
    CustomStyleLayer.prototype.updateTransitions = function updateTransitions() {
    };
    CustomStyleLayer.prototype.hasTransition = function hasTransition() {
    };
    CustomStyleLayer.prototype.serialize = function serialize() {
    };
    CustomStyleLayer.prototype.onAdd = function onAdd(map) {
        if (this.implementation.onAdd) {
            this.implementation.onAdd(map, map.painter.context.gl);
        }
    };
    CustomStyleLayer.prototype.onRemove = function onRemove(map) {
        if (this.implementation.onRemove) {
            this.implementation.onRemove(map, map.painter.context.gl);
        }
    };
    return CustomStyleLayer;
}(StyleLayer);

var subclasses = {
    circle: CircleStyleLayer,
    heatmap: HeatmapStyleLayer,
    hillshade: HillshadeStyleLayer,
    fill: FillStyleLayer,
    'fill-extrusion': FillExtrusionStyleLayer,
    line: LineStyleLayer,
    symbol: SymbolStyleLayer,
    background: BackgroundStyleLayer,
    raster: RasterStyleLayer
};
function createStyleLayer(layer) {
    if (layer.type === 'custom') {
        return new CustomStyleLayer(layer);
    } else {
        return new subclasses[layer.type](layer);
    }
}

var HTMLImageElement = window$1.HTMLImageElement;
var HTMLCanvasElement = window$1.HTMLCanvasElement;
var HTMLVideoElement = window$1.HTMLVideoElement;
var ImageData$1 = window$1.ImageData;
var ImageBitmap$1 = window$1.ImageBitmap;
var Texture = function Texture(context, image, format, options) {
    this.context = context;
    this.format = format;
    this.texture = context.gl.createTexture();
    this.update(image, options);
};
Texture.prototype.update = function update(image, options, position) {
    var width = image.width;
    var height = image.height;
    var resize = (!this.size || this.size[0] !== width || this.size[1] !== height) && !position;
    var ref = this;
    var context = ref.context;
    var gl = context.gl;
    this.useMipmap = Boolean(options && options.useMipmap);
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    context.pixelStoreUnpackFlipY.set(false);
    context.pixelStoreUnpack.set(1);
    context.pixelStoreUnpackPremultiplyAlpha.set(this.format === gl.RGBA && (!options || options.premultiply !== false));
    if (resize) {
        this.size = [
            width,
            height
        ];
        if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || image instanceof ImageData$1 || ImageBitmap$1 && image instanceof ImageBitmap$1) {
            gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, gl.UNSIGNED_BYTE, image);
        } else {
            gl.texImage2D(gl.TEXTURE_2D, 0, this.format, width, height, 0, this.format, gl.UNSIGNED_BYTE, image.data);
        }
    } else {
        var ref$1 = position || {
            x: 0,
            y: 0
        };
        var x = ref$1.x;
        var y = ref$1.y;
        if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || image instanceof ImageData$1 || ImageBitmap$1 && image instanceof ImageBitmap$1) {
            gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, gl.RGBA, gl.UNSIGNED_BYTE, image);
        } else {
            gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, image.data);
        }
    }
    if (this.useMipmap && this.isSizePowerOfTwo()) {
        gl.generateMipmap(gl.TEXTURE_2D);
    }
};
Texture.prototype.bind = function bind(filter, wrap, minFilter) {
    var ref = this;
    var context = ref.context;
    var gl = context.gl;
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    if (minFilter === gl.LINEAR_MIPMAP_NEAREST && !this.isSizePowerOfTwo()) {
        minFilter = gl.LINEAR;
    }
    if (filter !== this.filter) {
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter || filter);
        this.filter = filter;
    }
    if (wrap !== this.wrap) {
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);
        this.wrap = wrap;
    }
};
Texture.prototype.isSizePowerOfTwo = function isSizePowerOfTwo() {
    return this.size[0] === this.size[1] && Math.log(this.size[0]) / Math.LN2 % 1 === 0;
};
Texture.prototype.destroy = function destroy() {
    var ref = this.context;
    var gl = ref.gl;
    gl.deleteTexture(this.texture);
    this.texture = null;
};

var ThrottledInvoker = function ThrottledInvoker(callback) {
    var this$1 = this;
    this._callback = callback;
    this._triggered = false;
    if (typeof MessageChannel !== 'undefined') {
        this._channel = new MessageChannel();
        this._channel.port2.onmessage = function () {
            this$1._triggered = false;
            this$1._callback();
        };
    }
};
ThrottledInvoker.prototype.trigger = function trigger() {
    var this$1 = this;
    if (!this._triggered) {
        this._triggered = true;
        if (this._channel) {
            this._channel.port1.postMessage(true);
        } else {
            setTimeout(function () {
                this$1._triggered = false;
                this$1._callback();
            }, 0);
        }
    }
};
ThrottledInvoker.prototype.remove = function remove() {
    delete this._channel;
    this._callback = function () {
    };
};

var Actor = function Actor(target, parent, mapId) {
    this.target = target;
    this.parent = parent;
    this.mapId = mapId;
    this.callbacks = {};
    this.tasks = {};
    this.taskQueue = [];
    this.cancelCallbacks = {};
    bindAll([
        'receive',
        'process'
    ], this);
    this.invoker = new ThrottledInvoker(this.process);
    this.target.addEventListener('message', this.receive, false);
    this.globalScope = isWorker() ? target : window$1;
};
Actor.prototype.send = function send(type, data, callback, targetMapId, mustQueue) {
    var this$1 = this;
    if (mustQueue === void 0)
        mustQueue = false;
    var id = Math.round(Math.random() * 1000000000000000000).toString(36).substring(0, 10);
    if (callback) {
        this.callbacks[id] = callback;
    }
    var buffers = isSafari(this.globalScope) ? undefined : [];
    this.target.postMessage({
        id: id,
        type: type,
        hasCallback: !!callback,
        targetMapId: targetMapId,
        mustQueue: mustQueue,
        sourceMapId: this.mapId,
        data: serialize(data, buffers)
    }, buffers);
    return {
        cancel: function () {
            if (callback) {
                delete this$1.callbacks[id];
            }
            this$1.target.postMessage({
                id: id,
                type: '<cancel>',
                targetMapId: targetMapId,
                sourceMapId: this$1.mapId
            });
        }
    };
};
Actor.prototype.receive = function receive(message) {
    var data = message.data, id = data.id;
    if (!id) {
        return;
    }
    if (data.targetMapId && this.mapId !== data.targetMapId) {
        return;
    }
    if (data.type === '<cancel>') {
        delete this.tasks[id];
        var cancel = this.cancelCallbacks[id];
        delete this.cancelCallbacks[id];
        if (cancel) {
            cancel();
        }
    } else {
        if (isWorker() || data.mustQueue) {
            this.tasks[id] = data;
            this.taskQueue.push(id);
            this.invoker.trigger();
        } else {
            this.processTask(id, data);
        }
    }
};
Actor.prototype.process = function process() {
    if (!this.taskQueue.length) {
        return;
    }
    var id = this.taskQueue.shift();
    var task = this.tasks[id];
    delete this.tasks[id];
    if (this.taskQueue.length) {
        this.invoker.trigger();
    }
    if (!task) {
        return;
    }
    this.processTask(id, task);
};
Actor.prototype.processTask = function processTask(id, task) {
    var this$1 = this;
    if (task.type === '<response>') {
        var callback = this.callbacks[id];
        delete this.callbacks[id];
        if (callback) {
            if (task.error) {
                callback(deserialize(task.error));
            } else {
                callback(null, deserialize(task.data));
            }
        }
    } else {
        var completed = false;
        var buffers = isSafari(this.globalScope) ? undefined : [];
        var done = task.hasCallback ? function (err, data) {
            completed = true;
            delete this$1.cancelCallbacks[id];
            this$1.target.postMessage({
                id: id,
                type: '<response>',
                sourceMapId: this$1.mapId,
                error: err ? serialize(err) : null,
                data: serialize(data, buffers)
            }, buffers);
        } : function (_) {
            completed = true;
        };
        var callback$1 = null;
        var params = deserialize(task.data);
        if (this.parent[task.type]) {
            callback$1 = this.parent[task.type](task.sourceMapId, params, done);
        } else if (this.parent.getWorkerSource) {
            var keys = task.type.split('.');
            var scope = this.parent.getWorkerSource(task.sourceMapId, keys[0], params.source);
            callback$1 = scope[keys[1]](params, done);
        } else {
            done(new Error('Could not find function ' + task.type));
        }
        if (!completed && callback$1 && callback$1.cancel) {
            this.cancelCallbacks[id] = callback$1.cancel;
        }
    }
};
Actor.prototype.remove = function remove() {
    this.invoker.remove();
    this.target.removeEventListener('message', this.receive, false);
};

/**
 * getTileBBox
 *
 * @param    {Number}  x  Tile coordinate x
 * @param    {Number}  y  Tile coordinate y
 * @param    {Number}  z  Tile zoom
 * @returns  {String}  String of the bounding box
 */
function getTileBBox(x, y, z) {
    // for Google/OSM tile scheme we need to alter the y
    y = (Math.pow(2, z) - y - 1);

    var min = getMercCoords(x * 256, y * 256, z),
        max = getMercCoords((x + 1) * 256, (y + 1) * 256, z);

    return min[0] + ',' + min[1] + ',' + max[0] + ',' + max[1];
}


/**
 * getMercCoords
 *
 * @param    {Number}  x  Pixel coordinate x
 * @param    {Number}  y  Pixel coordinate y
 * @param    {Number}  z  Tile zoom
 * @returns  {Array}   [x, y]
 */
function getMercCoords(x, y, z) {
    var resolution = (2 * Math.PI * 6378137 / 256) / Math.pow(2, z),
        merc_x = (x * resolution - 2 * Math.PI  * 6378137 / 2.0),
        merc_y = (y * resolution - 2 * Math.PI  * 6378137 / 2.0);

    return [merc_x, merc_y];
}

var LngLatBounds = function LngLatBounds(sw, ne) {
    if (!sw) ; else if (ne) {
        this.setSouthWest(sw).setNorthEast(ne);
    } else if (sw.length === 4) {
        this.setSouthWest([
            sw[0],
            sw[1]
        ]).setNorthEast([
            sw[2],
            sw[3]
        ]);
    } else {
        this.setSouthWest(sw[0]).setNorthEast(sw[1]);
    }
};
LngLatBounds.prototype.setNorthEast = function setNorthEast(ne) {
    this._ne = ne instanceof LngLat ? new LngLat(ne.lng, ne.lat) : LngLat.convert(ne);
    return this;
};
LngLatBounds.prototype.setSouthWest = function setSouthWest(sw) {
    this._sw = sw instanceof LngLat ? new LngLat(sw.lng, sw.lat) : LngLat.convert(sw);
    return this;
};
LngLatBounds.prototype.extend = function extend(obj) {
    var sw = this._sw, ne = this._ne;
    var sw2, ne2;
    if (obj instanceof LngLat) {
        sw2 = obj;
        ne2 = obj;
    } else if (obj instanceof LngLatBounds) {
        sw2 = obj._sw;
        ne2 = obj._ne;
        if (!sw2 || !ne2) {
            return this;
        }
    } else {
        if (Array.isArray(obj)) {
            if (obj.length === 4 || obj.every(Array.isArray)) {
                var lngLatBoundsObj = obj;
                return this.extend(LngLatBounds.convert(lngLatBoundsObj));
            } else {
                var lngLatObj = obj;
                return this.extend(LngLat.convert(lngLatObj));
            }
        }
        return this;
    }
    if (!sw && !ne) {
        this._sw = new LngLat(sw2.lng, sw2.lat);
        this._ne = new LngLat(ne2.lng, ne2.lat);
    } else {
        sw.lng = Math.min(sw2.lng, sw.lng);
        sw.lat = Math.min(sw2.lat, sw.lat);
        ne.lng = Math.max(ne2.lng, ne.lng);
        ne.lat = Math.max(ne2.lat, ne.lat);
    }
    return this;
};
LngLatBounds.prototype.getCenter = function getCenter() {
    return new LngLat((this._sw.lng + this._ne.lng) / 2, (this._sw.lat + this._ne.lat) / 2);
};
LngLatBounds.prototype.getSouthWest = function getSouthWest() {
    return this._sw;
};
LngLatBounds.prototype.getNorthEast = function getNorthEast() {
    return this._ne;
};
LngLatBounds.prototype.getNorthWest = function getNorthWest() {
    return new LngLat(this.getWest(), this.getNorth());
};
LngLatBounds.prototype.getSouthEast = function getSouthEast() {
    return new LngLat(this.getEast(), this.getSouth());
};
LngLatBounds.prototype.getWest = function getWest() {
    return this._sw.lng;
};
LngLatBounds.prototype.getSouth = function getSouth() {
    return this._sw.lat;
};
LngLatBounds.prototype.getEast = function getEast() {
    return this._ne.lng;
};
LngLatBounds.prototype.getNorth = function getNorth() {
    return this._ne.lat;
};
LngLatBounds.prototype.toArray = function toArray() {
    return [
        this._sw.toArray(),
        this._ne.toArray()
    ];
};
LngLatBounds.prototype.toString = function toString() {
    return 'LngLatBounds(' + this._sw.toString() + ', ' + this._ne.toString() + ')';
};
LngLatBounds.prototype.isEmpty = function isEmpty() {
    return !(this._sw && this._ne);
};
LngLatBounds.prototype.contains = function contains(lnglat) {
    var ref = LngLat.convert(lnglat);
    var lng = ref.lng;
    var lat = ref.lat;
    var containsLatitude = this._sw.lat <= lat && lat <= this._ne.lat;
    var containsLongitude = this._sw.lng <= lng && lng <= this._ne.lng;
    if (this._sw.lng > this._ne.lng) {
        containsLongitude = this._sw.lng >= lng && lng >= this._ne.lng;
    }
    return containsLatitude && containsLongitude;
};
LngLatBounds.convert = function convert(input) {
    if (!input || input instanceof LngLatBounds) {
        return input;
    }
    return new LngLatBounds(input);
};

var earthRadius = 6371008.8;
var LngLat = function LngLat(lng, lat) {
    if (isNaN(lng) || isNaN(lat)) {
        throw new Error('Invalid LngLat object: (' + lng + ', ' + lat + ')');
    }
    this.lng = +lng;
    this.lat = +lat;
    if (this.lat > 90 || this.lat < -90) {
        throw new Error('Invalid LngLat latitude value: must be between -90 and 90');
    }
};
LngLat.prototype.wrap = function wrap$1() {
    return new LngLat(wrap(this.lng, -180, 180), this.lat);
};
LngLat.prototype.toArray = function toArray() {
    return [
        this.lng,
        this.lat
    ];
};
LngLat.prototype.toString = function toString() {
    return 'LngLat(' + this.lng + ', ' + this.lat + ')';
};
LngLat.prototype.distanceTo = function distanceTo(lngLat) {
    var rad = Math.PI / 180;
    var lat1 = this.lat * rad;
    var lat2 = lngLat.lat * rad;
    var a = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos((lngLat.lng - this.lng) * rad);
    var maxMeters = earthRadius * Math.acos(Math.min(a, 1));
    return maxMeters;
};
LngLat.prototype.toBounds = function toBounds(radius) {
    if (radius === void 0)
        radius = 0;
    var earthCircumferenceInMetersAtEquator = 40075017;
    var latAccuracy = 360 * radius / earthCircumferenceInMetersAtEquator, lngAccuracy = latAccuracy / Math.cos(Math.PI / 180 * this.lat);
    return new LngLatBounds(new LngLat(this.lng - lngAccuracy, this.lat - latAccuracy), new LngLat(this.lng + lngAccuracy, this.lat + latAccuracy));
};
LngLat.convert = function convert(input) {
    if (input instanceof LngLat) {
        return input;
    }
    if (Array.isArray(input) && (input.length === 2 || input.length === 3)) {
        return new LngLat(Number(input[0]), Number(input[1]));
    }
    if (!Array.isArray(input) && typeof input === 'object' && input !== null) {
        return new LngLat(Number('lng' in input ? input.lng : input.lon), Number(input.lat));
    }
    throw new Error('`LngLatLike` argument must be specified as a LngLat instance, an object {lng: <lng>, lat: <lat>}, an object {lon: <lng>, lat: <lat>}, or an array of [<lng>, <lat>]');
};

var earthCircumfrence = 2 * Math.PI * earthRadius;
function circumferenceAtLatitude(latitude) {
    return earthCircumfrence * Math.cos(latitude * Math.PI / 180);
}
function mercatorXfromLng$1(lng) {
    return (180 + lng) / 360;
}
function mercatorYfromLat$1(lat) {
    return (180 - 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360))) / 360;
}
function mercatorZfromAltitude(altitude, lat) {
    return altitude / circumferenceAtLatitude(lat);
}
function lngFromMercatorX(x) {
    return x * 360 - 180;
}
function latFromMercatorY(y) {
    var y2 = 180 - y * 360;
    return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;
}
function altitudeFromMercatorZ(z, y) {
    return z * circumferenceAtLatitude(latFromMercatorY(y));
}
function mercatorScale(lat) {
    return 1 / Math.cos(lat * Math.PI / 180);
}
var MercatorCoordinate = function MercatorCoordinate(x, y, z) {
    if (z === void 0)
        z = 0;
    this.x = +x;
    this.y = +y;
    this.z = +z;
};
MercatorCoordinate.fromLngLat = function fromLngLat(lngLatLike, altitude) {
    if (altitude === void 0)
        altitude = 0;
    var lngLat = LngLat.convert(lngLatLike);
    return new MercatorCoordinate(mercatorXfromLng$1(lngLat.lng), mercatorYfromLat$1(lngLat.lat), mercatorZfromAltitude(altitude, lngLat.lat));
};
MercatorCoordinate.prototype.toLngLat = function toLngLat() {
    return new LngLat(lngFromMercatorX(this.x), latFromMercatorY(this.y));
};
MercatorCoordinate.prototype.toAltitude = function toAltitude() {
    return altitudeFromMercatorZ(this.z, this.y);
};
MercatorCoordinate.prototype.meterInMercatorCoordinateUnits = function meterInMercatorCoordinateUnits() {
    return 1 / earthCircumfrence * mercatorScale(latFromMercatorY(this.y));
};

var CanonicalTileID = function CanonicalTileID(z, x, y) {
    this.z = z;
    this.x = x;
    this.y = y;
    this.key = calculateKey(0, z, z, x, y);
};
CanonicalTileID.prototype.equals = function equals(id) {
    return this.z === id.z && this.x === id.x && this.y === id.y;
};
CanonicalTileID.prototype.url = function url(urls, scheme) {
    var bbox = getTileBBox(this.x, this.y, this.z);
    var quadkey = getQuadkey(this.z, this.x, this.y);
    return urls[(this.x + this.y) % urls.length].replace('{prefix}', (this.x % 16).toString(16) + (this.y % 16).toString(16)).replace('{z}', String(this.z)).replace('{x}', String(this.x)).replace('{y}', String(scheme === 'tms' ? Math.pow(2, this.z) - this.y - 1 : this.y)).replace('{quadkey}', quadkey).replace('{bbox-epsg-3857}', bbox);
};
CanonicalTileID.prototype.getTilePoint = function getTilePoint(coord) {
    var tilesAtZoom = Math.pow(2, this.z);
    return new pointGeometry((coord.x * tilesAtZoom - this.x) * EXTENT$1, (coord.y * tilesAtZoom - this.y) * EXTENT$1);
};
CanonicalTileID.prototype.toString = function toString() {
    return this.z + '/' + this.x + '/' + this.y;
};
var UnwrappedTileID = function UnwrappedTileID(wrap, canonical) {
    this.wrap = wrap;
    this.canonical = canonical;
    this.key = calculateKey(wrap, canonical.z, canonical.z, canonical.x, canonical.y);
};
var OverscaledTileID = function OverscaledTileID(overscaledZ, wrap, z, x, y) {
    this.overscaledZ = overscaledZ;
    this.wrap = wrap;
    this.canonical = new CanonicalTileID(z, +x, +y);
    this.key = calculateKey(wrap, overscaledZ, z, x, y);
};
OverscaledTileID.prototype.equals = function equals(id) {
    return this.overscaledZ === id.overscaledZ && this.wrap === id.wrap && this.canonical.equals(id.canonical);
};
OverscaledTileID.prototype.scaledTo = function scaledTo(targetZ) {
    var zDifference = this.canonical.z - targetZ;
    if (targetZ > this.canonical.z) {
        return new OverscaledTileID(targetZ, this.wrap, this.canonical.z, this.canonical.x, this.canonical.y);
    } else {
        return new OverscaledTileID(targetZ, this.wrap, targetZ, this.canonical.x >> zDifference, this.canonical.y >> zDifference);
    }
};
OverscaledTileID.prototype.calculateScaledKey = function calculateScaledKey(targetZ, withWrap) {
    var zDifference = this.canonical.z - targetZ;
    if (targetZ > this.canonical.z) {
        return calculateKey(this.wrap * +withWrap, targetZ, this.canonical.z, this.canonical.x, this.canonical.y);
    } else {
        return calculateKey(this.wrap * +withWrap, targetZ, targetZ, this.canonical.x >> zDifference, this.canonical.y >> zDifference);
    }
};
OverscaledTileID.prototype.isChildOf = function isChildOf(parent) {
    if (parent.wrap !== this.wrap) {
        return false;
    }
    var zDifference = this.canonical.z - parent.canonical.z;
    return parent.overscaledZ === 0 || parent.overscaledZ < this.overscaledZ && parent.canonical.x === this.canonical.x >> zDifference && parent.canonical.y === this.canonical.y >> zDifference;
};
OverscaledTileID.prototype.children = function children(sourceMaxZoom) {
    if (this.overscaledZ >= sourceMaxZoom) {
        return [new OverscaledTileID(this.overscaledZ + 1, this.wrap, this.canonical.z, this.canonical.x, this.canonical.y)];
    }
    var z = this.canonical.z + 1;
    var x = this.canonical.x * 2;
    var y = this.canonical.y * 2;
    return [
        new OverscaledTileID(z, this.wrap, z, x, y),
        new OverscaledTileID(z, this.wrap, z, x + 1, y),
        new OverscaledTileID(z, this.wrap, z, x, y + 1),
        new OverscaledTileID(z, this.wrap, z, x + 1, y + 1)
    ];
};
OverscaledTileID.prototype.isLessThan = function isLessThan(rhs) {
    if (this.wrap < rhs.wrap) {
        return true;
    }
    if (this.wrap > rhs.wrap) {
        return false;
    }
    if (this.overscaledZ < rhs.overscaledZ) {
        return true;
    }
    if (this.overscaledZ > rhs.overscaledZ) {
        return false;
    }
    if (this.canonical.x < rhs.canonical.x) {
        return true;
    }
    if (this.canonical.x > rhs.canonical.x) {
        return false;
    }
    if (this.canonical.y < rhs.canonical.y) {
        return true;
    }
    return false;
};
OverscaledTileID.prototype.wrapped = function wrapped() {
    return new OverscaledTileID(this.overscaledZ, 0, this.canonical.z, this.canonical.x, this.canonical.y);
};
OverscaledTileID.prototype.unwrapTo = function unwrapTo(wrap) {
    return new OverscaledTileID(this.overscaledZ, wrap, this.canonical.z, this.canonical.x, this.canonical.y);
};
OverscaledTileID.prototype.overscaleFactor = function overscaleFactor() {
    return Math.pow(2, this.overscaledZ - this.canonical.z);
};
OverscaledTileID.prototype.toUnwrapped = function toUnwrapped() {
    return new UnwrappedTileID(this.wrap, this.canonical);
};
OverscaledTileID.prototype.toString = function toString() {
    return this.overscaledZ + '/' + this.canonical.x + '/' + this.canonical.y;
};
OverscaledTileID.prototype.getTilePoint = function getTilePoint(coord) {
    return this.canonical.getTilePoint(new MercatorCoordinate(coord.x - this.wrap, coord.y));
};
function calculateKey(wrap, overscaledZ, z, x, y) {
    wrap *= 2;
    if (wrap < 0) {
        wrap = wrap * -1 - 1;
    }
    var dim = 1 << z;
    return (dim * dim * wrap + dim * y + x).toString(36) + z.toString(36) + overscaledZ.toString(36);
}
function getQuadkey(z, x, y) {
    var quadkey = '', mask;
    for (var i = z; i > 0; i--) {
        mask = 1 << i - 1;
        quadkey += (x & mask ? 1 : 0) + (y & mask ? 2 : 0);
    }
    return quadkey;
}
register('CanonicalTileID', CanonicalTileID);
register('OverscaledTileID', OverscaledTileID, { omit: ['posMatrix'] });

var DEMData = function DEMData(uid, data, encoding) {
    this.uid = uid;
    if (data.height !== data.width) {
        throw new RangeError('DEM tiles must be square');
    }
    if (encoding && encoding !== 'mapbox' && encoding !== 'terrarium') {
        return warnOnce('"' + encoding + '" is not a valid encoding type. Valid types include "mapbox" and "terrarium".');
    }
    this.stride = data.height;
    var dim = this.dim = data.height - 2;
    this.data = new Uint32Array(data.data.buffer);
    this.encoding = encoding || 'mapbox';
    for (var x = 0; x < dim; x++) {
        this.data[this._idx(-1, x)] = this.data[this._idx(0, x)];
        this.data[this._idx(dim, x)] = this.data[this._idx(dim - 1, x)];
        this.data[this._idx(x, -1)] = this.data[this._idx(x, 0)];
        this.data[this._idx(x, dim)] = this.data[this._idx(x, dim - 1)];
    }
    this.data[this._idx(-1, -1)] = this.data[this._idx(0, 0)];
    this.data[this._idx(dim, -1)] = this.data[this._idx(dim - 1, 0)];
    this.data[this._idx(-1, dim)] = this.data[this._idx(0, dim - 1)];
    this.data[this._idx(dim, dim)] = this.data[this._idx(dim - 1, dim - 1)];
};
DEMData.prototype.get = function get(x, y) {
    var pixels = new Uint8Array(this.data.buffer);
    var index = this._idx(x, y) * 4;
    var unpack = this.encoding === 'terrarium' ? this._unpackTerrarium : this._unpackMapbox;
    return unpack(pixels[index], pixels[index + 1], pixels[index + 2]);
};
DEMData.prototype.getUnpackVector = function getUnpackVector() {
    return this.encoding === 'terrarium' ? [
        256,
        1,
        1 / 256,
        32768
    ] : [
        6553.6,
        25.6,
        0.1,
        10000
    ];
};
DEMData.prototype._idx = function _idx(x, y) {
    if (x < -1 || x >= this.dim + 1 || y < -1 || y >= this.dim + 1) {
        throw new RangeError('out of range source coordinates for DEM data');
    }
    return (y + 1) * this.stride + (x + 1);
};
DEMData.prototype._unpackMapbox = function _unpackMapbox(r, g, b) {
    return (r * 256 * 256 + g * 256 + b) / 10 - 10000;
};
DEMData.prototype._unpackTerrarium = function _unpackTerrarium(r, g, b) {
    return r * 256 + g + b / 256 - 32768;
};
DEMData.prototype.getPixels = function getPixels() {
    return new RGBAImage({
        width: this.stride,
        height: this.stride
    }, new Uint8Array(this.data.buffer));
};
DEMData.prototype.backfillBorder = function backfillBorder(borderTile, dx, dy) {
    if (this.dim !== borderTile.dim) {
        throw new Error('dem dimension mismatch');
    }
    var xMin = dx * this.dim, xMax = dx * this.dim + this.dim, yMin = dy * this.dim, yMax = dy * this.dim + this.dim;
    switch (dx) {
    case -1:
        xMin = xMax - 1;
        break;
    case 1:
        xMax = xMin + 1;
        break;
    }
    switch (dy) {
    case -1:
        yMin = yMax - 1;
        break;
    case 1:
        yMax = yMin + 1;
        break;
    }
    var ox = -dx * this.dim;
    var oy = -dy * this.dim;
    for (var y = yMin; y < yMax; y++) {
        for (var x = xMin; x < xMax; x++) {
            this.data[this._idx(x, y)] = borderTile.data[this._idx(x + ox, y + oy)];
        }
    }
};
register('DEMData', DEMData);

function deserialize$1(input, style) {
    var output = {};
    if (!style) {
        return output;
    }
    var loop = function () {
        var bucket = list$1[i$1];
        var layers = bucket.layerIds.map(function (id) {
            return style.getLayer(id);
        }).filter(Boolean);
        if (layers.length === 0) {
            return;
        }
        bucket.layers = layers;
        if (bucket.stateDependentLayerIds) {
            bucket.stateDependentLayers = bucket.stateDependentLayerIds.map(function (lId) {
                return layers.filter(function (l) {
                    return l.id === lId;
                })[0];
            });
        }
        for (var i = 0, list = layers; i < list.length; i += 1) {
            var layer = list[i];
            output[layer.id] = bucket;
        }
    };
    for (var i$1 = 0, list$1 = input; i$1 < list$1.length; i$1 += 1)
        loop();
    return output;
}

var DictionaryCoder = function DictionaryCoder(strings) {
    this._stringToNumber = {};
    this._numberToString = [];
    for (var i = 0; i < strings.length; i++) {
        var string = strings[i];
        this._stringToNumber[string] = i;
        this._numberToString[i] = string;
    }
};
DictionaryCoder.prototype.encode = function encode(string) {
    return this._stringToNumber[string];
};
DictionaryCoder.prototype.decode = function decode(n) {
    return this._numberToString[n];
};

var Feature = function Feature(vectorTileFeature, z, x, y, id) {
    this.type = 'Feature';
    this._vectorTileFeature = vectorTileFeature;
    vectorTileFeature._z = z;
    vectorTileFeature._x = x;
    vectorTileFeature._y = y;
    this.properties = vectorTileFeature.properties;
    this.id = id;
};
var prototypeAccessors$1 = { geometry: { configurable: true } };
prototypeAccessors$1.geometry.get = function () {
    if (this._geometry === undefined) {
        this._geometry = this._vectorTileFeature.toGeoJSON(this._vectorTileFeature._x, this._vectorTileFeature._y, this._vectorTileFeature._z).geometry;
    }
    return this._geometry;
};
prototypeAccessors$1.geometry.set = function (g) {
    this._geometry = g;
};
Feature.prototype.toJSON = function toJSON() {
    var json = { geometry: this.geometry };
    for (var i in this) {
        if (i === '_geometry' || i === '_vectorTileFeature') {
            continue;
        }
        json[i] = this[i];
    }
    return json;
};
Object.defineProperties(Feature.prototype, prototypeAccessors$1);

var SourceFeatureState = function SourceFeatureState() {
    this.state = {};
    this.stateChanges = {};
    this.deletedStates = {};
};
SourceFeatureState.prototype.updateState = function updateState(sourceLayer, featureId, newState) {
    var feature = String(featureId);
    this.stateChanges[sourceLayer] = this.stateChanges[sourceLayer] || {};
    this.stateChanges[sourceLayer][feature] = this.stateChanges[sourceLayer][feature] || {};
    extend(this.stateChanges[sourceLayer][feature], newState);
    if (this.deletedStates[sourceLayer] === null) {
        this.deletedStates[sourceLayer] = {};
        for (var ft in this.state[sourceLayer]) {
            if (ft !== feature) {
                this.deletedStates[sourceLayer][ft] = null;
            }
        }
    } else {
        var featureDeletionQueued = this.deletedStates[sourceLayer] && this.deletedStates[sourceLayer][feature] === null;
        if (featureDeletionQueued) {
            this.deletedStates[sourceLayer][feature] = {};
            for (var prop in this.state[sourceLayer][feature]) {
                if (!newState[prop]) {
                    this.deletedStates[sourceLayer][feature][prop] = null;
                }
            }
        } else {
            for (var key in newState) {
                var deletionInQueue = this.deletedStates[sourceLayer] && this.deletedStates[sourceLayer][feature] && this.deletedStates[sourceLayer][feature][key] === null;
                if (deletionInQueue) {
                    delete this.deletedStates[sourceLayer][feature][key];
                }
            }
        }
    }
};
SourceFeatureState.prototype.removeFeatureState = function removeFeatureState(sourceLayer, featureId, key) {
    var sourceLayerDeleted = this.deletedStates[sourceLayer] === null;
    if (sourceLayerDeleted) {
        return;
    }
    var feature = String(featureId);
    this.deletedStates[sourceLayer] = this.deletedStates[sourceLayer] || {};
    if (key && featureId !== undefined) {
        if (this.deletedStates[sourceLayer][feature] !== null) {
            this.deletedStates[sourceLayer][feature] = this.deletedStates[sourceLayer][feature] || {};
            this.deletedStates[sourceLayer][feature][key] = null;
        }
    } else if (featureId !== undefined) {
        var updateInQueue = this.stateChanges[sourceLayer] && this.stateChanges[sourceLayer][feature];
        if (updateInQueue) {
            this.deletedStates[sourceLayer][feature] = {};
            for (key in this.stateChanges[sourceLayer][feature]) {
                this.deletedStates[sourceLayer][feature][key] = null;
            }
        } else {
            this.deletedStates[sourceLayer][feature] = null;
        }
    } else {
        this.deletedStates[sourceLayer] = null;
    }
};
SourceFeatureState.prototype.getState = function getState(sourceLayer, featureId) {
    var feature = String(featureId);
    var base = this.state[sourceLayer] || {};
    var changes = this.stateChanges[sourceLayer] || {};
    var reconciledState = extend({}, base[feature], changes[feature]);
    if (this.deletedStates[sourceLayer] === null) {
        return {};
    } else if (this.deletedStates[sourceLayer]) {
        var featureDeletions = this.deletedStates[sourceLayer][featureId];
        if (featureDeletions === null) {
            return {};
        }
        for (var prop in featureDeletions) {
            delete reconciledState[prop];
        }
    }
    return reconciledState;
};
SourceFeatureState.prototype.initializeTileState = function initializeTileState(tile, painter) {
    tile.setFeatureState(this.state, painter);
};
SourceFeatureState.prototype.coalesceChanges = function coalesceChanges(tiles, painter) {
    var featuresChanged = {};
    for (var sourceLayer in this.stateChanges) {
        this.state[sourceLayer] = this.state[sourceLayer] || {};
        var layerStates = {};
        for (var feature in this.stateChanges[sourceLayer]) {
            if (!this.state[sourceLayer][feature]) {
                this.state[sourceLayer][feature] = {};
            }
            extend(this.state[sourceLayer][feature], this.stateChanges[sourceLayer][feature]);
            layerStates[feature] = this.state[sourceLayer][feature];
        }
        featuresChanged[sourceLayer] = layerStates;
    }
    for (var sourceLayer$1 in this.deletedStates) {
        this.state[sourceLayer$1] = this.state[sourceLayer$1] || {};
        var layerStates$1 = {};
        if (this.deletedStates[sourceLayer$1] === null) {
            for (var ft in this.state[sourceLayer$1]) {
                layerStates$1[ft] = {};
                this.state[sourceLayer$1][ft] = {};
            }
        } else {
            for (var feature$1 in this.deletedStates[sourceLayer$1]) {
                var deleteWholeFeatureState = this.deletedStates[sourceLayer$1][feature$1] === null;
                if (deleteWholeFeatureState) {
                    this.state[sourceLayer$1][feature$1] = {};
                } else {
                    for (var i = 0, list = Object.keys(this.deletedStates[sourceLayer$1][feature$1]); i < list.length; i += 1) {
                        var key = list[i];
                        delete this.state[sourceLayer$1][feature$1][key];
                    }
                }
                layerStates$1[feature$1] = this.state[sourceLayer$1][feature$1];
            }
        }
        featuresChanged[sourceLayer$1] = featuresChanged[sourceLayer$1] || {};
        extend(featuresChanged[sourceLayer$1], layerStates$1);
    }
    this.stateChanges = {};
    this.deletedStates = {};
    if (Object.keys(featuresChanged).length === 0) {
        return;
    }
    for (var id in tiles) {
        var tile = tiles[id];
        tile.setFeatureState(featuresChanged, painter);
    }
};

var FeatureIndex = function FeatureIndex(tileID, promoteId) {
    this.tileID = tileID;
    this.x = tileID.canonical.x;
    this.y = tileID.canonical.y;
    this.z = tileID.canonical.z;
    this.grid = new gridIndex(EXTENT$1, 16, 0);
    this.grid3D = new gridIndex(EXTENT$1, 16, 0);
    this.featureIndexArray = new FeatureIndexArray();
    this.promoteId = promoteId;
};
FeatureIndex.prototype.insert = function insert(feature, geometry, featureIndex, sourceLayerIndex, bucketIndex, is3D) {
    var key = this.featureIndexArray.length;
    this.featureIndexArray.emplaceBack(featureIndex, sourceLayerIndex, bucketIndex);
    var grid = is3D ? this.grid3D : this.grid;
    for (var r = 0; r < geometry.length; r++) {
        var ring = geometry[r];
        var bbox = [
            Infinity,
            Infinity,
            -Infinity,
            -Infinity
        ];
        for (var i = 0; i < ring.length; i++) {
            var p = ring[i];
            bbox[0] = Math.min(bbox[0], p.x);
            bbox[1] = Math.min(bbox[1], p.y);
            bbox[2] = Math.max(bbox[2], p.x);
            bbox[3] = Math.max(bbox[3], p.y);
        }
        if (bbox[0] < EXTENT$1 && bbox[1] < EXTENT$1 && bbox[2] >= 0 && bbox[3] >= 0) {
            grid.insert(key, bbox[0], bbox[1], bbox[2], bbox[3]);
        }
    }
};
FeatureIndex.prototype.loadVTLayers = function loadVTLayers() {
    if (!this.vtLayers) {
        this.vtLayers = new vectorTile.VectorTile(new pbf(this.rawTileData)).layers;
        this.sourceLayerCoder = new DictionaryCoder(this.vtLayers ? Object.keys(this.vtLayers).sort() : ['_geojsonTileLayer']);
    }
    return this.vtLayers;
};
FeatureIndex.prototype.query = function query(args, styleLayers, serializedLayers, sourceFeatureState) {
    var this$1 = this;
    this.loadVTLayers();
    var params = args.params || {}, pixelsToTileUnits = EXTENT$1 / args.tileSize / args.scale, filter = createFilter(params.filter);
    var queryGeometry = args.queryGeometry;
    var queryPadding = args.queryPadding * pixelsToTileUnits;
    var bounds = getBounds(queryGeometry);
    var matching = this.grid.query(bounds.minX - queryPadding, bounds.minY - queryPadding, bounds.maxX + queryPadding, bounds.maxY + queryPadding);
    var cameraBounds = getBounds(args.cameraQueryGeometry);
    var matching3D = this.grid3D.query(cameraBounds.minX - queryPadding, cameraBounds.minY - queryPadding, cameraBounds.maxX + queryPadding, cameraBounds.maxY + queryPadding, function (bx1, by1, bx2, by2) {
        return polygonIntersectsBox(args.cameraQueryGeometry, bx1 - queryPadding, by1 - queryPadding, bx2 + queryPadding, by2 + queryPadding);
    });
    for (var i = 0, list = matching3D; i < list.length; i += 1) {
        var key = list[i];
        matching.push(key);
    }
    matching.sort(topDownFeatureComparator);
    var result = {};
    var previousIndex;
    var loop = function (k) {
        var index = matching[k];
        if (index === previousIndex) {
            return;
        }
        previousIndex = index;
        var match = this$1.featureIndexArray.get(index);
        var featureGeometry = null;
        this$1.loadMatchingFeature(result, match.bucketIndex, match.sourceLayerIndex, match.featureIndex, filter, params.layers, params.availableImages, styleLayers, serializedLayers, sourceFeatureState, function (feature, styleLayer, featureState) {
            if (!featureGeometry) {
                featureGeometry = loadGeometry(feature);
            }
            return styleLayer.queryIntersectsFeature(queryGeometry, feature, featureState, featureGeometry, this$1.z, args.transform, pixelsToTileUnits, args.pixelPosMatrix);
        });
    };
    for (var k = 0; k < matching.length; k++)
        loop(k);
    return result;
};
FeatureIndex.prototype.loadMatchingFeature = function loadMatchingFeature(result, bucketIndex, sourceLayerIndex, featureIndex, filter, filterLayerIDs, availableImages, styleLayers, serializedLayers, sourceFeatureState, intersectionTest) {
    var layerIDs = this.bucketLayerIDs[bucketIndex];
    if (filterLayerIDs && !arraysIntersect(filterLayerIDs, layerIDs)) {
        return;
    }
    var sourceLayerName = this.sourceLayerCoder.decode(sourceLayerIndex);
    var sourceLayer = this.vtLayers[sourceLayerName];
    var feature = sourceLayer.feature(featureIndex);
    if (filter.needGeometry) {
        var evaluationFeature = toEvaluationFeature(feature, true);
        if (!filter.filter(new EvaluationParameters(this.tileID.overscaledZ), evaluationFeature, this.tileID.canonical)) {
            return;
        }
    } else if (!filter.filter(new EvaluationParameters(this.tileID.overscaledZ), feature)) {
        return;
    }
    var id = this.getId(feature, sourceLayerName);
    for (var l = 0; l < layerIDs.length; l++) {
        var layerID = layerIDs[l];
        if (filterLayerIDs && filterLayerIDs.indexOf(layerID) < 0) {
            continue;
        }
        var styleLayer = styleLayers[layerID];
        if (!styleLayer) {
            continue;
        }
        var featureState = {};
        if (id !== undefined && sourceFeatureState) {
            featureState = sourceFeatureState.getState(styleLayer.sourceLayer || '_geojsonTileLayer', id);
        }
        var serializedLayer = extend({}, serializedLayers[layerID]);
        serializedLayer.paint = evaluateProperties(serializedLayer.paint, styleLayer.paint, feature, featureState, availableImages);
        serializedLayer.layout = evaluateProperties(serializedLayer.layout, styleLayer.layout, feature, featureState, availableImages);
        var intersectionZ = !intersectionTest || intersectionTest(feature, styleLayer, featureState);
        if (!intersectionZ) {
            continue;
        }
        var geojsonFeature = new Feature(feature, this.z, this.x, this.y, id);
        geojsonFeature.layer = serializedLayer;
        var layerResult = result[layerID];
        if (layerResult === undefined) {
            layerResult = result[layerID] = [];
        }
        layerResult.push({
            featureIndex: featureIndex,
            feature: geojsonFeature,
            intersectionZ: intersectionZ
        });
    }
};
FeatureIndex.prototype.lookupSymbolFeatures = function lookupSymbolFeatures(symbolFeatureIndexes, serializedLayers, bucketIndex, sourceLayerIndex, filterSpec, filterLayerIDs, availableImages, styleLayers) {
    var result = {};
    this.loadVTLayers();
    var filter = createFilter(filterSpec);
    for (var i = 0, list = symbolFeatureIndexes; i < list.length; i += 1) {
        var symbolFeatureIndex = list[i];
        this.loadMatchingFeature(result, bucketIndex, sourceLayerIndex, symbolFeatureIndex, filter, filterLayerIDs, availableImages, styleLayers, serializedLayers);
    }
    return result;
};
FeatureIndex.prototype.hasLayer = function hasLayer(id) {
    for (var i$1 = 0, list$1 = this.bucketLayerIDs; i$1 < list$1.length; i$1 += 1) {
        var layerIDs = list$1[i$1];
        for (var i = 0, list = layerIDs; i < list.length; i += 1) {
            var layerID = list[i];
            if (id === layerID) {
                return true;
            }
        }
    }
    return false;
};
FeatureIndex.prototype.getId = function getId(feature, sourceLayerId) {
    var id = feature.id;
    if (this.promoteId) {
        var propName = typeof this.promoteId === 'string' ? this.promoteId : this.promoteId[sourceLayerId];
        id = feature.properties[propName];
        if (typeof id === 'boolean') {
            id = Number(id);
        }
    }
    return id;
};
register('FeatureIndex', FeatureIndex, {
    omit: [
        'rawTileData',
        'sourceLayerCoder'
    ]
});
function evaluateProperties(serializedProperties, styleLayerProperties, feature, featureState, availableImages) {
    return mapObject(serializedProperties, function (property, key) {
        var prop = styleLayerProperties instanceof PossiblyEvaluated ? styleLayerProperties.get(key) : null;
        return prop && prop.evaluate ? prop.evaluate(feature, featureState, availableImages) : prop;
    });
}
function getBounds(geometry) {
    var minX = Infinity;
    var minY = Infinity;
    var maxX = -Infinity;
    var maxY = -Infinity;
    for (var i = 0, list = geometry; i < list.length; i += 1) {
        var p = list[i];
        minX = Math.min(minX, p.x);
        minY = Math.min(minY, p.y);
        maxX = Math.max(maxX, p.x);
        maxY = Math.max(maxY, p.y);
    }
    return {
        minX: minX,
        minY: minY,
        maxX: maxX,
        maxY: maxY
    };
}
function topDownFeatureComparator(a, b) {
    return b - a;
}

var CLOCK_SKEW_RETRY_TIMEOUT = 30000;
var Tile = function Tile(tileID, size) {
    this.tileID = tileID;
    this.uid = uniqueId();
    this.uses = 0;
    this.tileSize = size;
    this.buckets = {};
    this.expirationTime = null;
    this.queryPadding = 0;
    this.hasSymbolBuckets = false;
    this.hasRTLText = false;
    this.dependencies = {};
    this.expiredRequestCount = 0;
    this.state = 'loading';
};
Tile.prototype.registerFadeDuration = function registerFadeDuration(duration) {
    var fadeEndTime = duration + this.timeAdded;
    if (fadeEndTime < exported.now()) {
        return;
    }
    if (this.fadeEndTime && fadeEndTime < this.fadeEndTime) {
        return;
    }
    this.fadeEndTime = fadeEndTime;
};
Tile.prototype.wasRequested = function wasRequested() {
    return this.state === 'errored' || this.state === 'loaded' || this.state === 'reloading';
};
Tile.prototype.loadVectorData = function loadVectorData(data, painter, justReloaded) {
    if (this.hasData()) {
        this.unloadVectorData();
    }
    this.state = 'loaded';
    if (!data) {
        this.collisionBoxArray = new CollisionBoxArray();
        return;
    }
    if (data.featureIndex) {
        this.latestFeatureIndex = data.featureIndex;
        if (data.rawTileData) {
            this.latestRawTileData = data.rawTileData;
            this.latestFeatureIndex.rawTileData = data.rawTileData;
        } else if (this.latestRawTileData) {
            this.latestFeatureIndex.rawTileData = this.latestRawTileData;
        }
    }
    this.collisionBoxArray = data.collisionBoxArray;
    this.buckets = deserialize$1(data.buckets, painter.style);
    this.hasSymbolBuckets = false;
    for (var id in this.buckets) {
        var bucket = this.buckets[id];
        if (bucket instanceof SymbolBucket) {
            this.hasSymbolBuckets = true;
            if (justReloaded) {
                bucket.justReloaded = true;
            } else {
                break;
            }
        }
    }
    this.hasRTLText = false;
    if (this.hasSymbolBuckets) {
        for (var id$1 in this.buckets) {
            var bucket$1 = this.buckets[id$1];
            if (bucket$1 instanceof SymbolBucket) {
                if (bucket$1.hasRTLText) {
                    this.hasRTLText = true;
                    lazyLoadRTLTextPlugin();
                    break;
                }
            }
        }
    }
    this.queryPadding = 0;
    for (var id$2 in this.buckets) {
        var bucket$2 = this.buckets[id$2];
        this.queryPadding = Math.max(this.queryPadding, painter.style.getLayer(id$2).queryRadius(bucket$2));
    }
    if (data.imageAtlas) {
        this.imageAtlas = data.imageAtlas;
    }
    if (data.glyphAtlasImage) {
        this.glyphAtlasImage = data.glyphAtlasImage;
    }
};
Tile.prototype.unloadVectorData = function unloadVectorData() {
    for (var id in this.buckets) {
        this.buckets[id].destroy();
    }
    this.buckets = {};
    if (this.imageAtlasTexture) {
        this.imageAtlasTexture.destroy();
    }
    if (this.imageAtlas) {
        this.imageAtlas = null;
    }
    if (this.glyphAtlasTexture) {
        this.glyphAtlasTexture.destroy();
    }
    this.latestFeatureIndex = null;
    this.state = 'unloaded';
};
Tile.prototype.getBucket = function getBucket(layer) {
    return this.buckets[layer.id];
};
Tile.prototype.upload = function upload(context) {
    for (var id in this.buckets) {
        var bucket = this.buckets[id];
        if (bucket.uploadPending()) {
            bucket.upload(context);
        }
    }
    var gl = context.gl;
    if (this.imageAtlas && !this.imageAtlas.uploaded) {
        this.imageAtlasTexture = new Texture(context, this.imageAtlas.image, gl.RGBA);
        this.imageAtlas.uploaded = true;
    }
    if (this.glyphAtlasImage) {
        this.glyphAtlasTexture = new Texture(context, this.glyphAtlasImage, gl.ALPHA);
        this.glyphAtlasImage = null;
    }
};
Tile.prototype.prepare = function prepare(imageManager) {
    if (this.imageAtlas) {
        this.imageAtlas.patchUpdatedImages(imageManager, this.imageAtlasTexture);
    }
};
Tile.prototype.queryRenderedFeatures = function queryRenderedFeatures(layers, serializedLayers, sourceFeatureState, queryGeometry, cameraQueryGeometry, scale, params, transform, maxPitchScaleFactor, pixelPosMatrix) {
    if (!this.latestFeatureIndex || !this.latestFeatureIndex.rawTileData) {
        return {};
    }
    return this.latestFeatureIndex.query({
        queryGeometry: queryGeometry,
        cameraQueryGeometry: cameraQueryGeometry,
        scale: scale,
        tileSize: this.tileSize,
        pixelPosMatrix: pixelPosMatrix,
        transform: transform,
        params: params,
        queryPadding: this.queryPadding * maxPitchScaleFactor
    }, layers, serializedLayers, sourceFeatureState);
};
Tile.prototype.querySourceFeatures = function querySourceFeatures(result, params) {
    var featureIndex = this.latestFeatureIndex;
    if (!featureIndex || !featureIndex.rawTileData) {
        return;
    }
    var vtLayers = featureIndex.loadVTLayers();
    var sourceLayer = params ? params.sourceLayer : '';
    var layer = vtLayers._geojsonTileLayer || vtLayers[sourceLayer];
    if (!layer) {
        return;
    }
    var filter = createFilter(params && params.filter);
    var ref = this.tileID.canonical;
    var z = ref.z;
    var x = ref.x;
    var y = ref.y;
    var coord = {
        z: z,
        x: x,
        y: y
    };
    for (var i = 0; i < layer.length; i++) {
        var feature = layer.feature(i);
        if (filter.needGeometry) {
            var evaluationFeature = toEvaluationFeature(feature, true);
            if (!filter.filter(new EvaluationParameters(this.tileID.overscaledZ), evaluationFeature, this.tileID.canonical)) {
                continue;
            }
        } else if (!filter.filter(new EvaluationParameters(this.tileID.overscaledZ), feature)) {
            continue;
        }
        var id = featureIndex.getId(feature, sourceLayer);
        var geojsonFeature = new Feature(feature, z, x, y, id);
        geojsonFeature.tile = coord;
        result.push(geojsonFeature);
    }
};
Tile.prototype.hasData = function hasData() {
    return this.state === 'loaded' || this.state === 'reloading' || this.state === 'expired';
};
Tile.prototype.patternsLoaded = function patternsLoaded() {
    return this.imageAtlas && !!Object.keys(this.imageAtlas.patternPositions).length;
};
Tile.prototype.setExpiryData = function setExpiryData(data) {
    var prior = this.expirationTime;
    if (data.cacheControl) {
        var parsedCC = parseCacheControl(data.cacheControl);
        if (parsedCC['max-age']) {
            this.expirationTime = Date.now() + parsedCC['max-age'] * 1000;
        }
    } else if (data.expires) {
        this.expirationTime = new Date(data.expires).getTime();
    }
    if (this.expirationTime) {
        var now = Date.now();
        var isExpired = false;
        if (this.expirationTime > now) {
            isExpired = false;
        } else if (!prior) {
            isExpired = true;
        } else if (this.expirationTime < prior) {
            isExpired = true;
        } else {
            var delta = this.expirationTime - prior;
            if (!delta) {
                isExpired = true;
            } else {
                this.expirationTime = now + Math.max(delta, CLOCK_SKEW_RETRY_TIMEOUT);
            }
        }
        if (isExpired) {
            this.expiredRequestCount++;
            this.state = 'expired';
        } else {
            this.expiredRequestCount = 0;
        }
    }
};
Tile.prototype.getExpiryTimeout = function getExpiryTimeout() {
    if (this.expirationTime) {
        if (this.expiredRequestCount) {
            return 1000 * (1 << Math.min(this.expiredRequestCount - 1, 31));
        } else {
            return Math.min(this.expirationTime - new Date().getTime(), Math.pow(2, 31) - 1);
        }
    }
};
Tile.prototype.setFeatureState = function setFeatureState(states, painter) {
    if (!this.latestFeatureIndex || !this.latestFeatureIndex.rawTileData || Object.keys(states).length === 0) {
        return;
    }
    var vtLayers = this.latestFeatureIndex.loadVTLayers();
    for (var id in this.buckets) {
        if (!painter.style.hasLayer(id)) {
            continue;
        }
        var bucket = this.buckets[id];
        var sourceLayerId = bucket.layers[0]['sourceLayer'] || '_geojsonTileLayer';
        var sourceLayer = vtLayers[sourceLayerId];
        var sourceLayerStates = states[sourceLayerId];
        if (!sourceLayer || !sourceLayerStates || Object.keys(sourceLayerStates).length === 0) {
            continue;
        }
        bucket.update(sourceLayerStates, sourceLayer, this.imageAtlas && this.imageAtlas.patternPositions || {});
        var layer = painter && painter.style && painter.style.getLayer(id);
        if (layer) {
            this.queryPadding = Math.max(this.queryPadding, layer.queryRadius(bucket));
        }
    }
};
Tile.prototype.holdingForFade = function holdingForFade() {
    return this.symbolFadeHoldUntil !== undefined;
};
Tile.prototype.symbolFadeFinished = function symbolFadeFinished() {
    return !this.symbolFadeHoldUntil || this.symbolFadeHoldUntil < exported.now();
};
Tile.prototype.clearFadeHold = function clearFadeHold() {
    this.symbolFadeHoldUntil = undefined;
};
Tile.prototype.setHoldDuration = function setHoldDuration(duration) {
    this.symbolFadeHoldUntil = exported.now() + duration;
};
Tile.prototype.setDependencies = function setDependencies(namespace, dependencies) {
    var index = {};
    for (var i = 0, list = dependencies; i < list.length; i += 1) {
        var dep = list[i];
        index[dep] = true;
    }
    this.dependencies[namespace] = index;
};
Tile.prototype.hasDependency = function hasDependency(namespaces, keys) {
    for (var i$1 = 0, list$1 = namespaces; i$1 < list$1.length; i$1 += 1) {
        var namespace = list$1[i$1];
        var dependencies = this.dependencies[namespace];
        if (dependencies) {
            for (var i = 0, list = keys; i < list.length; i += 1) {
                var key = list[i];
                if (dependencies[key]) {
                    return true;
                }
            }
        }
    }
    return false;
};

var refProperties = [
    'type',
    'source',
    'source-layer',
    'minzoom',
    'maxzoom',
    'filter',
    'layout'
];

var performance = window$1.performance;
var RequestPerformance = function RequestPerformance(request) {
    this._marks = {
        start: [
            request.url,
            'start'
        ].join('#'),
        end: [
            request.url,
            'end'
        ].join('#'),
        measure: request.url.toString()
    };
    performance.mark(this._marks.start);
};
RequestPerformance.prototype.finish = function finish() {
    performance.mark(this._marks.end);
    var resourceTimingData = performance.getEntriesByName(this._marks.measure);
    if (resourceTimingData.length === 0) {
        performance.measure(this._marks.measure, this._marks.start, this._marks.end);
        resourceTimingData = performance.getEntriesByName(this._marks.measure);
        performance.clearMarks(this._marks.start);
        performance.clearMarks(this._marks.end);
        performance.clearMeasures(this._marks.measure);
    }
    return resourceTimingData;
};

exports.Actor = Actor;
exports.AlphaImage = AlphaImage;
exports.CanonicalTileID = CanonicalTileID;
exports.CollisionBoxArray = CollisionBoxArray;
exports.Color = Color;
exports.DEMData = DEMData;
exports.DataConstantProperty = DataConstantProperty;
exports.DictionaryCoder = DictionaryCoder;
exports.EXTENT = EXTENT$1;
exports.ErrorEvent = ErrorEvent;
exports.EvaluationParameters = EvaluationParameters;
exports.Event = Event;
exports.Evented = Evented;
exports.FeatureIndex = FeatureIndex;
exports.FillBucket = FillBucket;
exports.FillExtrusionBucket = FillExtrusionBucket;
exports.ImageAtlas = ImageAtlas;
exports.ImagePosition = ImagePosition;
exports.LineBucket = LineBucket;
exports.LngLat = LngLat;
exports.LngLatBounds = LngLatBounds;
exports.MercatorCoordinate = MercatorCoordinate;
exports.ONE_EM = ONE_EM;
exports.OverscaledTileID = OverscaledTileID;
exports.Point = pointGeometry;
exports.Point$1 = pointGeometry;
exports.Properties = Properties;
exports.Protobuf = pbf;
exports.RGBAImage = RGBAImage;
exports.RequestManager = RequestManager;
exports.RequestPerformance = RequestPerformance;
exports.ResourceType = ResourceType;
exports.SegmentVector = SegmentVector;
exports.SourceFeatureState = SourceFeatureState;
exports.StructArrayLayout1ui2 = StructArrayLayout1ui2;
exports.StructArrayLayout2f1f2i16 = StructArrayLayout2f1f2i16;
exports.StructArrayLayout2i4 = StructArrayLayout2i4;
exports.StructArrayLayout3ui6 = StructArrayLayout3ui6;
exports.StructArrayLayout4i8 = StructArrayLayout4i8;
exports.SymbolBucket = SymbolBucket;
exports.Texture = Texture;
exports.Tile = Tile;
exports.Transitionable = Transitionable;
exports.Uniform1f = Uniform1f;
exports.Uniform1i = Uniform1i;
exports.Uniform2f = Uniform2f;
exports.Uniform3f = Uniform3f;
exports.Uniform4f = Uniform4f;
exports.UniformColor = UniformColor;
exports.UniformMatrix4f = UniformMatrix4f;
exports.UnwrappedTileID = UnwrappedTileID;
exports.ValidationError = ValidationError;
exports.WritingMode = WritingMode;
exports.ZoomHistory = ZoomHistory;
exports.add = add;
exports.addDynamicAttributes = addDynamicAttributes;
exports.asyncAll = asyncAll;
exports.bezier = bezier;
exports.bindAll = bindAll;
exports.browser = exported;
exports.cacheEntryPossiblyAdded = cacheEntryPossiblyAdded;
exports.clamp = clamp;
exports.clearTileCache = clearTileCache;
exports.clipLine = clipLine;
exports.clone = clone$1;
exports.clone$1 = clone;
exports.clone$2 = clone$2;
exports.collisionCircleLayout = collisionCircleLayout;
exports.config = config;
exports.create = create$2;
exports.create$1 = create$1;
exports.create$2 = create;
exports.createCommonjsModule = createCommonjsModule;
exports.createExpression = createExpression;
exports.createLayout = createLayout;
exports.createStyleLayer = createStyleLayer;
exports.cross = cross;
exports.deepEqual = deepEqual;
exports.dot = dot;
exports.dot$1 = dot$1;
exports.ease = ease;
exports.emitValidationErrors = emitValidationErrors;
exports.endsWith = endsWith;
exports.enforceCacheSizeLimit = enforceCacheSizeLimit;
exports.evaluateSizeForFeature = evaluateSizeForFeature;
exports.evaluateSizeForZoom = evaluateSizeForZoom;
exports.evaluateVariableOffset = evaluateVariableOffset;
exports.evented = evented;
exports.extend = extend;
exports.featureFilter = createFilter;
exports.filterObject = filterObject;
exports.fromRotation = fromRotation;
exports.getAnchorAlignment = getAnchorAlignment;
exports.getAnchorJustification = getAnchorJustification;
exports.getArrayBuffer = getArrayBuffer;
exports.getImage = getImage;
exports.getJSON = getJSON;
exports.getRTLTextPluginStatus = getRTLTextPluginStatus;
exports.getReferrer = getReferrer;
exports.getVideo = getVideo;
exports.identity = identity;
exports.invert = invert;
exports.isChar = unicodeBlockLookup;
exports.isMapboxURL = isMapboxURL;
exports.keysDifference = keysDifference;
exports.makeRequest = makeRequest;
exports.mapObject = mapObject;
exports.mercatorXfromLng = mercatorXfromLng$1;
exports.mercatorYfromLat = mercatorYfromLat$1;
exports.mercatorZfromAltitude = mercatorZfromAltitude;
exports.mul = mul;
exports.multiply = multiply;
exports.mvt = vectorTile;
exports.nextPowerOfTwo = nextPowerOfTwo;
exports.normalize = normalize;
exports.number = number;
exports.offscreenCanvasSupported = offscreenCanvasSupported;
exports.ortho = ortho;
exports.parseGlyphPBF = parseGlyphPBF;
exports.pbf = pbf;
exports.performSymbolLayout = performSymbolLayout;
exports.perspective = perspective;
exports.pick = pick;
exports.plugin = plugin;
exports.polygonIntersectsPolygon = polygonIntersectsPolygon;
exports.postMapLoadEvent = postMapLoadEvent;
exports.postTurnstileEvent = postTurnstileEvent;
exports.potpack = potpack;
exports.refProperties = refProperties;
exports.register = register;
exports.registerForPluginStateChange = registerForPluginStateChange;
exports.renderColorRamp = renderColorRamp;
exports.rotate = rotate;
exports.rotateX = rotateX;
exports.rotateZ = rotateZ;
exports.scale = scale;
exports.scale$1 = scale$2;
exports.scale$2 = scale$1;
exports.setCacheLimits = setCacheLimits;
exports.setRTLTextPlugin = setRTLTextPlugin;
exports.sphericalToCartesian = sphericalToCartesian;
exports.sqrLen = sqrLen;
exports.styleSpec = spec;
exports.sub = sub;
exports.symbolSize = symbolSize;
exports.transformMat3 = transformMat3;
exports.transformMat4 = transformMat4;
exports.translate = translate$1;
exports.triggerPluginCompletionEvent = triggerPluginCompletionEvent;
exports.uniqueId = uniqueId;
exports.validateCustomStyleLayer = validateCustomStyleLayer;
exports.validateLight = validateLight$1;
exports.validateStyle = validateStyle;
exports.values = values;
exports.vectorTile = vectorTile;
exports.version = version;
exports.warnOnce = warnOnce;
exports.webpSupported = exported$1;
exports.window = window$1;
exports.wrap = wrap;

});

define(['./shared'], function (performance) { 'use strict';

function stringify(obj) {
    var type = typeof obj;
    if (type === 'number' || type === 'boolean' || type === 'string' || obj === undefined || obj === null) {
        return JSON.stringify(obj);
    }
    if (Array.isArray(obj)) {
        var str$1 = '[';
        for (var i$1 = 0, list = obj; i$1 < list.length; i$1 += 1) {
            var val = list[i$1];
            str$1 += stringify(val) + ',';
        }
        return str$1 + ']';
    }
    var keys = Object.keys(obj).sort();
    var str = '{';
    for (var i = 0; i < keys.length; i++) {
        str += JSON.stringify(keys[i]) + ':' + stringify(obj[keys[i]]) + ',';
    }
    return str + '}';
}
function getKey(layer) {
    var key = '';
    for (var i = 0, list = performance.refProperties; i < list.length; i += 1) {
        var k = list[i];
        key += '/' + stringify(layer[k]);
    }
    return key;
}
function groupByLayout(layers, cachedKeys) {
    var groups = {};
    for (var i = 0; i < layers.length; i++) {
        var k = cachedKeys && cachedKeys[layers[i].id] || getKey(layers[i]);
        if (cachedKeys) {
            cachedKeys[layers[i].id] = k;
        }
        var group = groups[k];
        if (!group) {
            group = groups[k] = [];
        }
        group.push(layers[i]);
    }
    var result = [];
    for (var k$1 in groups) {
        result.push(groups[k$1]);
    }
    return result;
}

var StyleLayerIndex = function StyleLayerIndex(layerConfigs) {
    this.keyCache = {};
    if (layerConfigs) {
        this.replace(layerConfigs);
    }
};
StyleLayerIndex.prototype.replace = function replace(layerConfigs) {
    this._layerConfigs = {};
    this._layers = {};
    this.update(layerConfigs, []);
};
StyleLayerIndex.prototype.update = function update(layerConfigs, removedIds) {
    var this$1 = this;
    for (var i = 0, list = layerConfigs; i < list.length; i += 1) {
        var layerConfig = list[i];
        this._layerConfigs[layerConfig.id] = layerConfig;
        var layer = this._layers[layerConfig.id] = performance.createStyleLayer(layerConfig);
        layer._featureFilter = performance.featureFilter(layer.filter);
        if (this.keyCache[layerConfig.id]) {
            delete this.keyCache[layerConfig.id];
        }
    }
    for (var i$1 = 0, list$1 = removedIds; i$1 < list$1.length; i$1 += 1) {
        var id = list$1[i$1];
        delete this.keyCache[id];
        delete this._layerConfigs[id];
        delete this._layers[id];
    }
    this.familiesBySource = {};
    var groups = groupByLayout(performance.values(this._layerConfigs), this.keyCache);
    for (var i$2 = 0, list$2 = groups; i$2 < list$2.length; i$2 += 1) {
        var layerConfigs$1 = list$2[i$2];
        var layers = layerConfigs$1.map(function (layerConfig) {
            return this$1._layers[layerConfig.id];
        });
        var layer$1 = layers[0];
        if (layer$1.visibility === 'none') {
            continue;
        }
        var sourceId = layer$1.source || '';
        var sourceGroup = this.familiesBySource[sourceId];
        if (!sourceGroup) {
            sourceGroup = this.familiesBySource[sourceId] = {};
        }
        var sourceLayerId = layer$1.sourceLayer || '_geojsonTileLayer';
        var sourceLayerFamilies = sourceGroup[sourceLayerId];
        if (!sourceLayerFamilies) {
            sourceLayerFamilies = sourceGroup[sourceLayerId] = [];
        }
        sourceLayerFamilies.push(layers);
    }
};

var padding = 1;
var GlyphAtlas = function GlyphAtlas(stacks) {
    var positions = {};
    var bins = [];
    for (var stack in stacks) {
        var glyphs = stacks[stack];
        var stackPositions = positions[stack] = {};
        for (var id in glyphs) {
            var src = glyphs[+id];
            if (!src || src.bitmap.width === 0 || src.bitmap.height === 0) {
                continue;
            }
            var bin = {
                x: 0,
                y: 0,
                w: src.bitmap.width + 2 * padding,
                h: src.bitmap.height + 2 * padding
            };
            bins.push(bin);
            stackPositions[id] = {
                rect: bin,
                metrics: src.metrics
            };
        }
    }
    var ref = performance.potpack(bins);
    var w = ref.w;
    var h = ref.h;
    var image = new performance.AlphaImage({
        width: w || 1,
        height: h || 1
    });
    for (var stack$1 in stacks) {
        var glyphs$1 = stacks[stack$1];
        for (var id$1 in glyphs$1) {
            var src$1 = glyphs$1[+id$1];
            if (!src$1 || src$1.bitmap.width === 0 || src$1.bitmap.height === 0) {
                continue;
            }
            var bin$1 = positions[stack$1][id$1].rect;
            performance.AlphaImage.copy(src$1.bitmap, image, {
                x: 0,
                y: 0
            }, {
                x: bin$1.x + padding,
                y: bin$1.y + padding
            }, src$1.bitmap);
        }
    }
    this.image = image;
    this.positions = positions;
};
performance.register('GlyphAtlas', GlyphAtlas);

var WorkerTile = function WorkerTile(params) {
    this.tileID = new performance.OverscaledTileID(params.tileID.overscaledZ, params.tileID.wrap, params.tileID.canonical.z, params.tileID.canonical.x, params.tileID.canonical.y);
    this.uid = params.uid;
    this.zoom = params.zoom;
    this.pixelRatio = params.pixelRatio;
    this.tileSize = params.tileSize;
    this.source = params.source;
    this.overscaling = this.tileID.overscaleFactor();
    this.showCollisionBoxes = params.showCollisionBoxes;
    this.collectResourceTiming = !!params.collectResourceTiming;
    this.returnDependencies = !!params.returnDependencies;
    this.promoteId = params.promoteId;
};
WorkerTile.prototype.parse = function parse(data, layerIndex, availableImages, actor, callback) {
    var this$1 = this;
    this.status = 'parsing';
    this.data = data;
    this.collisionBoxArray = new performance.CollisionBoxArray();
    var sourceLayerCoder = new performance.DictionaryCoder(Object.keys(data.layers).sort());
    var featureIndex = new performance.FeatureIndex(this.tileID, this.promoteId);
    featureIndex.bucketLayerIDs = [];
    var buckets = {};
    var options = {
        featureIndex: featureIndex,
        iconDependencies: {},
        patternDependencies: {},
        glyphDependencies: {},
        availableImages: availableImages
    };
    var layerFamilies = layerIndex.familiesBySource[this.source];
    for (var sourceLayerId in layerFamilies) {
        var sourceLayer = data.layers[sourceLayerId];
        if (!sourceLayer) {
            continue;
        }
        if (sourceLayer.version === 1) {
            performance.warnOnce('Vector tile source "' + this.source + '" layer "' + sourceLayerId + '" ' + 'does not use vector tile spec v2 and therefore may have some rendering errors.');
        }
        var sourceLayerIndex = sourceLayerCoder.encode(sourceLayerId);
        var features = [];
        for (var index = 0; index < sourceLayer.length; index++) {
            var feature = sourceLayer.feature(index);
            var id = featureIndex.getId(feature, sourceLayerId);
            features.push({
                feature: feature,
                id: id,
                index: index,
                sourceLayerIndex: sourceLayerIndex
            });
        }
        for (var i = 0, list = layerFamilies[sourceLayerId]; i < list.length; i += 1) {
            var family = list[i];
            var layer = family[0];
            if (layer.minzoom && this.zoom < Math.floor(layer.minzoom)) {
                continue;
            }
            if (layer.maxzoom && this.zoom >= layer.maxzoom) {
                continue;
            }
            if (layer.visibility === 'none') {
                continue;
            }
            recalculateLayers(family, this.zoom, availableImages);
            var bucket = buckets[layer.id] = layer.createBucket({
                index: featureIndex.bucketLayerIDs.length,
                layers: family,
                zoom: this.zoom,
                pixelRatio: this.pixelRatio,
                overscaling: this.overscaling,
                collisionBoxArray: this.collisionBoxArray,
                sourceLayerIndex: sourceLayerIndex,
                sourceID: this.source
            });
            bucket.populate(features, options, this.tileID.canonical);
            featureIndex.bucketLayerIDs.push(family.map(function (l) {
                return l.id;
            }));
        }
    }
    var error;
    var glyphMap;
    var iconMap;
    var patternMap;
    var stacks = performance.mapObject(options.glyphDependencies, function (glyphs) {
        return Object.keys(glyphs).map(Number);
    });
    if (Object.keys(stacks).length) {
        actor.send('getGlyphs', {
            uid: this.uid,
            stacks: stacks
        }, function (err, result) {
            if (!error) {
                error = err;
                glyphMap = result;
                maybePrepare.call(this$1);
            }
        });
    } else {
        glyphMap = {};
    }
    var icons = Object.keys(options.iconDependencies);
    if (icons.length) {
        actor.send('getImages', {
            icons: icons,
            source: this.source,
            tileID: this.tileID,
            type: 'icons'
        }, function (err, result) {
            if (!error) {
                error = err;
                iconMap = result;
                maybePrepare.call(this$1);
            }
        });
    } else {
        iconMap = {};
    }
    var patterns = Object.keys(options.patternDependencies);
    if (patterns.length) {
        actor.send('getImages', {
            icons: patterns,
            source: this.source,
            tileID: this.tileID,
            type: 'patterns'
        }, function (err, result) {
            if (!error) {
                error = err;
                patternMap = result;
                maybePrepare.call(this$1);
            }
        });
    } else {
        patternMap = {};
    }
    maybePrepare.call(this);
    function maybePrepare() {
        if (error) {
            return callback(error);
        } else if (glyphMap && iconMap && patternMap) {
            var glyphAtlas = new GlyphAtlas(glyphMap);
            var imageAtlas = new performance.ImageAtlas(iconMap, patternMap);
            for (var key in buckets) {
                var bucket = buckets[key];
                if (bucket instanceof performance.SymbolBucket) {
                    recalculateLayers(bucket.layers, this.zoom, availableImages);
                    performance.performSymbolLayout(bucket, glyphMap, glyphAtlas.positions, iconMap, imageAtlas.iconPositions, this.showCollisionBoxes, this.tileID.canonical);
                } else if (bucket.hasPattern && (bucket instanceof performance.LineBucket || bucket instanceof performance.FillBucket || bucket instanceof performance.FillExtrusionBucket)) {
                    recalculateLayers(bucket.layers, this.zoom, availableImages);
                    bucket.addFeatures(options, this.tileID.canonical, imageAtlas.patternPositions);
                }
            }
            this.status = 'done';
            callback(null, {
                buckets: performance.values(buckets).filter(function (b) {
                    return !b.isEmpty();
                }),
                featureIndex: featureIndex,
                collisionBoxArray: this.collisionBoxArray,
                glyphAtlasImage: glyphAtlas.image,
                imageAtlas: imageAtlas,
                glyphMap: this.returnDependencies ? glyphMap : null,
                iconMap: this.returnDependencies ? iconMap : null,
                glyphPositions: this.returnDependencies ? glyphAtlas.positions : null
            });
        }
    }
};
function recalculateLayers(layers, zoom, availableImages) {
    var parameters = new performance.EvaluationParameters(zoom);
    for (var i = 0, list = layers; i < list.length; i += 1) {
        var layer = list[i];
        layer.recalculate(parameters, availableImages);
    }
}

function loadVectorTile(params, callback) {
    var request = performance.getArrayBuffer(params.request, function (err, data, cacheControl, expires) {
        if (err) {
            callback(err);
        } else if (data) {
            callback(null, {
                vectorTile: new performance.vectorTile.VectorTile(new performance.pbf(data)),
                rawData: data,
                cacheControl: cacheControl,
                expires: expires
            });
        }
    });
    return function () {
        request.cancel();
        callback();
    };
}
var VectorTileWorkerSource = function VectorTileWorkerSource(actor, layerIndex, availableImages, loadVectorData) {
    this.actor = actor;
    this.layerIndex = layerIndex;
    this.availableImages = availableImages;
    this.loadVectorData = loadVectorData || loadVectorTile;
    this.loading = {};
    this.loaded = {};
};
VectorTileWorkerSource.prototype.loadTile = function loadTile(params, callback) {
    var this$1 = this;
    var uid = params.uid;
    if (!this.loading) {
        this.loading = {};
    }
    var perf = params && params.request && params.request.collectResourceTiming ? new performance.RequestPerformance(params.request) : false;
    var workerTile = this.loading[uid] = new WorkerTile(params);
    workerTile.abort = this.loadVectorData(params, function (err, response) {
        delete this$1.loading[uid];
        if (err || !response) {
            workerTile.status = 'done';
            this$1.loaded[uid] = workerTile;
            return callback(err);
        }
        var rawTileData = response.rawData;
        var cacheControl = {};
        if (response.expires) {
            cacheControl.expires = response.expires;
        }
        if (response.cacheControl) {
            cacheControl.cacheControl = response.cacheControl;
        }
        var resourceTiming = {};
        if (perf) {
            var resourceTimingData = perf.finish();
            if (resourceTimingData) {
                resourceTiming.resourceTiming = JSON.parse(JSON.stringify(resourceTimingData));
            }
        }
        workerTile.vectorTile = response.vectorTile;
        workerTile.parse(response.vectorTile, this$1.layerIndex, this$1.availableImages, this$1.actor, function (err, result) {
            if (err || !result) {
                return callback(err);
            }
            callback(null, performance.extend({ rawTileData: rawTileData.slice(0) }, result, cacheControl, resourceTiming));
        });
        this$1.loaded = this$1.loaded || {};
        this$1.loaded[uid] = workerTile;
    });
};
VectorTileWorkerSource.prototype.reloadTile = function reloadTile(params, callback) {
    var this$1 = this;
    var loaded = this.loaded, uid = params.uid, vtSource = this;
    if (loaded && loaded[uid]) {
        var workerTile = loaded[uid];
        workerTile.showCollisionBoxes = params.showCollisionBoxes;
        var done = function (err, data) {
            var reloadCallback = workerTile.reloadCallback;
            if (reloadCallback) {
                delete workerTile.reloadCallback;
                workerTile.parse(workerTile.vectorTile, vtSource.layerIndex, this$1.availableImages, vtSource.actor, reloadCallback);
            }
            callback(err, data);
        };
        if (workerTile.status === 'parsing') {
            workerTile.reloadCallback = done;
        } else if (workerTile.status === 'done') {
            if (workerTile.vectorTile) {
                workerTile.parse(workerTile.vectorTile, this.layerIndex, this.availableImages, this.actor, done);
            } else {
                done();
            }
        }
    }
};
VectorTileWorkerSource.prototype.abortTile = function abortTile(params, callback) {
    var loading = this.loading, uid = params.uid;
    if (loading && loading[uid] && loading[uid].abort) {
        loading[uid].abort();
        delete loading[uid];
    }
    callback();
};
VectorTileWorkerSource.prototype.removeTile = function removeTile(params, callback) {
    var loaded = this.loaded, uid = params.uid;
    if (loaded && loaded[uid]) {
        delete loaded[uid];
    }
    callback();
};

var ImageBitmap = performance.window.ImageBitmap;
var RasterDEMTileWorkerSource = function RasterDEMTileWorkerSource() {
    this.loaded = {};
};
RasterDEMTileWorkerSource.prototype.loadTile = function loadTile(params, callback) {
    var uid = params.uid;
    var encoding = params.encoding;
    var rawImageData = params.rawImageData;
    var imagePixels = ImageBitmap && rawImageData instanceof ImageBitmap ? this.getImageData(rawImageData) : rawImageData;
    var dem = new performance.DEMData(uid, imagePixels, encoding);
    this.loaded = this.loaded || {};
    this.loaded[uid] = dem;
    callback(null, dem);
};
RasterDEMTileWorkerSource.prototype.getImageData = function getImageData(imgBitmap) {
    if (!this.offscreenCanvas || !this.offscreenCanvasContext) {
        this.offscreenCanvas = new OffscreenCanvas(imgBitmap.width, imgBitmap.height);
        this.offscreenCanvasContext = this.offscreenCanvas.getContext('2d');
    }
    this.offscreenCanvas.width = imgBitmap.width;
    this.offscreenCanvas.height = imgBitmap.height;
    this.offscreenCanvasContext.drawImage(imgBitmap, 0, 0, imgBitmap.width, imgBitmap.height);
    var imgData = this.offscreenCanvasContext.getImageData(-1, -1, imgBitmap.width + 2, imgBitmap.height + 2);
    this.offscreenCanvasContext.clearRect(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height);
    return new performance.RGBAImage({
        width: imgData.width,
        height: imgData.height
    }, imgData.data);
};
RasterDEMTileWorkerSource.prototype.removeTile = function removeTile(params) {
    var loaded = this.loaded, uid = params.uid;
    if (loaded && loaded[uid]) {
        delete loaded[uid];
    }
};

var geojsonRewind = rewind;
function rewind(gj, outer) {
    var type = gj && gj.type, i;
    if (type === 'FeatureCollection') {
        for (i = 0; i < gj.features.length; i++) {
            rewind(gj.features[i], outer);
        }
    } else if (type === 'GeometryCollection') {
        for (i = 0; i < gj.geometries.length; i++) {
            rewind(gj.geometries[i], outer);
        }
    } else if (type === 'Feature') {
        rewind(gj.geometry, outer);
    } else if (type === 'Polygon') {
        rewindRings(gj.coordinates, outer);
    } else if (type === 'MultiPolygon') {
        for (i = 0; i < gj.coordinates.length; i++) {
            rewindRings(gj.coordinates[i], outer);
        }
    }
    return gj;
}
function rewindRings(rings, outer) {
    if (rings.length === 0) {
        return;
    }
    rewindRing(rings[0], outer);
    for (var i = 1; i < rings.length; i++) {
        rewindRing(rings[i], !outer);
    }
}
function rewindRing(ring, dir) {
    var area = 0, err = 0;
    for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
        var k = (ring[i][0] - ring[j][0]) * (ring[j][1] + ring[i][1]);
        var m = area + k;
        err += Math.abs(area) >= Math.abs(k) ? area - m + k : k - m + area;
        area = m;
    }
    if (area + err >= 0 !== !!dir) {
        ring.reverse();
    }
}

var toGeoJSON = performance.vectorTile.VectorTileFeature.prototype.toGeoJSON;
var FeatureWrapper = function FeatureWrapper(feature) {
    this._feature = feature;
    this.extent = performance.EXTENT;
    this.type = feature.type;
    this.properties = feature.tags;
    if ('id' in feature && !isNaN(feature.id)) {
        this.id = parseInt(feature.id, 10);
    }
};
FeatureWrapper.prototype.loadGeometry = function loadGeometry() {
    if (this._feature.type === 1) {
        var geometry = [];
        for (var i = 0, list = this._feature.geometry; i < list.length; i += 1) {
            var point = list[i];
            geometry.push([new performance.Point$1(point[0], point[1])]);
        }
        return geometry;
    } else {
        var geometry$1 = [];
        for (var i$2 = 0, list$2 = this._feature.geometry; i$2 < list$2.length; i$2 += 1) {
            var ring = list$2[i$2];
            var newRing = [];
            for (var i$1 = 0, list$1 = ring; i$1 < list$1.length; i$1 += 1) {
                var point$1 = list$1[i$1];
                newRing.push(new performance.Point$1(point$1[0], point$1[1]));
            }
            geometry$1.push(newRing);
        }
        return geometry$1;
    }
};
FeatureWrapper.prototype.toGeoJSON = function toGeoJSON$1(x, y, z) {
    return toGeoJSON.call(this, x, y, z);
};
var GeoJSONWrapper = function GeoJSONWrapper(features) {
    this.layers = { '_geojsonTileLayer': this };
    this.name = '_geojsonTileLayer';
    this.extent = performance.EXTENT;
    this.length = features.length;
    this._features = features;
};
GeoJSONWrapper.prototype.feature = function feature(i) {
    return new FeatureWrapper(this._features[i]);
};

var VectorTileFeature = performance.vectorTile.VectorTileFeature;
var geojson_wrapper = GeoJSONWrapper$1;
function GeoJSONWrapper$1(features, options) {
    this.options = options || {};
    this.features = features;
    this.length = features.length;
}
GeoJSONWrapper$1.prototype.feature = function (i) {
    return new FeatureWrapper$1(this.features[i], this.options.extent);
};
function FeatureWrapper$1(feature, extent) {
    this.id = typeof feature.id === 'number' ? feature.id : undefined;
    this.type = feature.type;
    this.rawGeometry = feature.type === 1 ? [feature.geometry] : feature.geometry;
    this.properties = feature.tags;
    this.extent = extent || 4096;
}
FeatureWrapper$1.prototype.loadGeometry = function () {
    var rings = this.rawGeometry;
    this.geometry = [];
    for (var i = 0; i < rings.length; i++) {
        var ring = rings[i];
        var newRing = [];
        for (var j = 0; j < ring.length; j++) {
            newRing.push(new performance.Point$1(ring[j][0], ring[j][1]));
        }
        this.geometry.push(newRing);
    }
    return this.geometry;
};
FeatureWrapper$1.prototype.bbox = function () {
    if (!this.geometry) {
        this.loadGeometry();
    }
    var rings = this.geometry;
    var x1 = Infinity;
    var x2 = -Infinity;
    var y1 = Infinity;
    var y2 = -Infinity;
    for (var i = 0; i < rings.length; i++) {
        var ring = rings[i];
        for (var j = 0; j < ring.length; j++) {
            var coord = ring[j];
            x1 = Math.min(x1, coord.x);
            x2 = Math.max(x2, coord.x);
            y1 = Math.min(y1, coord.y);
            y2 = Math.max(y2, coord.y);
        }
    }
    return [
        x1,
        y1,
        x2,
        y2
    ];
};
FeatureWrapper$1.prototype.toGeoJSON = VectorTileFeature.prototype.toGeoJSON;

var vtPbf = fromVectorTileJs;
var fromVectorTileJs_1 = fromVectorTileJs;
var fromGeojsonVt_1 = fromGeojsonVt;
var GeoJSONWrapper_1 = geojson_wrapper;
function fromVectorTileJs(tile) {
    var out = new performance.pbf();
    writeTile(tile, out);
    return out.finish();
}
function fromGeojsonVt(layers, options) {
    options = options || {};
    var l = {};
    for (var k in layers) {
        l[k] = new geojson_wrapper(layers[k].features, options);
        l[k].name = k;
        l[k].version = options.version;
        l[k].extent = options.extent;
    }
    return fromVectorTileJs({ layers: l });
}
function writeTile(tile, pbf) {
    for (var key in tile.layers) {
        pbf.writeMessage(3, writeLayer, tile.layers[key]);
    }
}
function writeLayer(layer, pbf) {
    pbf.writeVarintField(15, layer.version || 1);
    pbf.writeStringField(1, layer.name || '');
    pbf.writeVarintField(5, layer.extent || 4096);
    var i;
    var context = {
        keys: [],
        values: [],
        keycache: {},
        valuecache: {}
    };
    for (i = 0; i < layer.length; i++) {
        context.feature = layer.feature(i);
        pbf.writeMessage(2, writeFeature, context);
    }
    var keys = context.keys;
    for (i = 0; i < keys.length; i++) {
        pbf.writeStringField(3, keys[i]);
    }
    var values = context.values;
    for (i = 0; i < values.length; i++) {
        pbf.writeMessage(4, writeValue, values[i]);
    }
}
function writeFeature(context, pbf) {
    var feature = context.feature;
    if (feature.id !== undefined) {
        pbf.writeVarintField(1, feature.id);
    }
    pbf.writeMessage(2, writeProperties, context);
    pbf.writeVarintField(3, feature.type);
    pbf.writeMessage(4, writeGeometry, feature);
}
function writeProperties(context, pbf) {
    var feature = context.feature;
    var keys = context.keys;
    var values = context.values;
    var keycache = context.keycache;
    var valuecache = context.valuecache;
    for (var key in feature.properties) {
        var keyIndex = keycache[key];
        if (typeof keyIndex === 'undefined') {
            keys.push(key);
            keyIndex = keys.length - 1;
            keycache[key] = keyIndex;
        }
        pbf.writeVarint(keyIndex);
        var value = feature.properties[key];
        var type = typeof value;
        if (type !== 'string' && type !== 'boolean' && type !== 'number') {
            value = JSON.stringify(value);
        }
        var valueKey = type + ':' + value;
        var valueIndex = valuecache[valueKey];
        if (typeof valueIndex === 'undefined') {
            values.push(value);
            valueIndex = values.length - 1;
            valuecache[valueKey] = valueIndex;
        }
        pbf.writeVarint(valueIndex);
    }
}
function command(cmd, length) {
    return (length << 3) + (cmd & 7);
}
function zigzag(num) {
    return num << 1 ^ num >> 31;
}
function writeGeometry(feature, pbf) {
    var geometry = feature.loadGeometry();
    var type = feature.type;
    var x = 0;
    var y = 0;
    var rings = geometry.length;
    for (var r = 0; r < rings; r++) {
        var ring = geometry[r];
        var count = 1;
        if (type === 1) {
            count = ring.length;
        }
        pbf.writeVarint(command(1, count));
        var lineCount = type === 3 ? ring.length - 1 : ring.length;
        for (var i = 0; i < lineCount; i++) {
            if (i === 1 && type !== 1) {
                pbf.writeVarint(command(2, lineCount - 1));
            }
            var dx = ring[i].x - x;
            var dy = ring[i].y - y;
            pbf.writeVarint(zigzag(dx));
            pbf.writeVarint(zigzag(dy));
            x += dx;
            y += dy;
        }
        if (type === 3) {
            pbf.writeVarint(command(7, 1));
        }
    }
}
function writeValue(value, pbf) {
    var type = typeof value;
    if (type === 'string') {
        pbf.writeStringField(1, value);
    } else if (type === 'boolean') {
        pbf.writeBooleanField(7, value);
    } else if (type === 'number') {
        if (value % 1 !== 0) {
            pbf.writeDoubleField(3, value);
        } else if (value < 0) {
            pbf.writeSVarintField(6, value);
        } else {
            pbf.writeVarintField(5, value);
        }
    }
}
vtPbf.fromVectorTileJs = fromVectorTileJs_1;
vtPbf.fromGeojsonVt = fromGeojsonVt_1;
vtPbf.GeoJSONWrapper = GeoJSONWrapper_1;

function sortKD(ids, coords, nodeSize, left, right, depth) {
    if (right - left <= nodeSize) {
        return;
    }
    var m = left + right >> 1;
    select(ids, coords, m, left, right, depth % 2);
    sortKD(ids, coords, nodeSize, left, m - 1, depth + 1);
    sortKD(ids, coords, nodeSize, m + 1, right, depth + 1);
}
function select(ids, coords, k, left, right, inc) {
    while (right > left) {
        if (right - left > 600) {
            var n = right - left + 1;
            var m = k - left + 1;
            var z = Math.log(n);
            var s = 0.5 * Math.exp(2 * z / 3);
            var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
            var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
            var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
            select(ids, coords, k, newLeft, newRight, inc);
        }
        var t = coords[2 * k + inc];
        var i = left;
        var j = right;
        swapItem(ids, coords, left, k);
        if (coords[2 * right + inc] > t) {
            swapItem(ids, coords, left, right);
        }
        while (i < j) {
            swapItem(ids, coords, i, j);
            i++;
            j--;
            while (coords[2 * i + inc] < t) {
                i++;
            }
            while (coords[2 * j + inc] > t) {
                j--;
            }
        }
        if (coords[2 * left + inc] === t) {
            swapItem(ids, coords, left, j);
        } else {
            j++;
            swapItem(ids, coords, j, right);
        }
        if (j <= k) {
            left = j + 1;
        }
        if (k <= j) {
            right = j - 1;
        }
    }
}
function swapItem(ids, coords, i, j) {
    swap(ids, i, j);
    swap(coords, 2 * i, 2 * j);
    swap(coords, 2 * i + 1, 2 * j + 1);
}
function swap(arr, i, j) {
    var tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

function range(ids, coords, minX, minY, maxX, maxY, nodeSize) {
    var stack = [
        0,
        ids.length - 1,
        0
    ];
    var result = [];
    var x, y;
    while (stack.length) {
        var axis = stack.pop();
        var right = stack.pop();
        var left = stack.pop();
        if (right - left <= nodeSize) {
            for (var i = left; i <= right; i++) {
                x = coords[2 * i];
                y = coords[2 * i + 1];
                if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
                    result.push(ids[i]);
                }
            }
            continue;
        }
        var m = Math.floor((left + right) / 2);
        x = coords[2 * m];
        y = coords[2 * m + 1];
        if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
            result.push(ids[m]);
        }
        var nextAxis = (axis + 1) % 2;
        if (axis === 0 ? minX <= x : minY <= y) {
            stack.push(left);
            stack.push(m - 1);
            stack.push(nextAxis);
        }
        if (axis === 0 ? maxX >= x : maxY >= y) {
            stack.push(m + 1);
            stack.push(right);
            stack.push(nextAxis);
        }
    }
    return result;
}

function within(ids, coords, qx, qy, r, nodeSize) {
    var stack = [
        0,
        ids.length - 1,
        0
    ];
    var result = [];
    var r2 = r * r;
    while (stack.length) {
        var axis = stack.pop();
        var right = stack.pop();
        var left = stack.pop();
        if (right - left <= nodeSize) {
            for (var i = left; i <= right; i++) {
                if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) {
                    result.push(ids[i]);
                }
            }
            continue;
        }
        var m = Math.floor((left + right) / 2);
        var x = coords[2 * m];
        var y = coords[2 * m + 1];
        if (sqDist(x, y, qx, qy) <= r2) {
            result.push(ids[m]);
        }
        var nextAxis = (axis + 1) % 2;
        if (axis === 0 ? qx - r <= x : qy - r <= y) {
            stack.push(left);
            stack.push(m - 1);
            stack.push(nextAxis);
        }
        if (axis === 0 ? qx + r >= x : qy + r >= y) {
            stack.push(m + 1);
            stack.push(right);
            stack.push(nextAxis);
        }
    }
    return result;
}
function sqDist(ax, ay, bx, by) {
    var dx = ax - bx;
    var dy = ay - by;
    return dx * dx + dy * dy;
}

var defaultGetX = function (p) {
    return p[0];
};
var defaultGetY = function (p) {
    return p[1];
};
var KDBush = function KDBush(points, getX, getY, nodeSize, ArrayType) {
    if (getX === void 0)
        getX = defaultGetX;
    if (getY === void 0)
        getY = defaultGetY;
    if (nodeSize === void 0)
        nodeSize = 64;
    if (ArrayType === void 0)
        ArrayType = Float64Array;
    this.nodeSize = nodeSize;
    this.points = points;
    var IndexArrayType = points.length < 65536 ? Uint16Array : Uint32Array;
    var ids = this.ids = new IndexArrayType(points.length);
    var coords = this.coords = new ArrayType(points.length * 2);
    for (var i = 0; i < points.length; i++) {
        ids[i] = i;
        coords[2 * i] = getX(points[i]);
        coords[2 * i + 1] = getY(points[i]);
    }
    sortKD(ids, coords, nodeSize, 0, ids.length - 1, 0);
};
KDBush.prototype.range = function range$1(minX, minY, maxX, maxY) {
    return range(this.ids, this.coords, minX, minY, maxX, maxY, this.nodeSize);
};
KDBush.prototype.within = function within$1(x, y, r) {
    return within(this.ids, this.coords, x, y, r, this.nodeSize);
};

var defaultOptions = {
    minZoom: 0,
    maxZoom: 16,
    minPoints: 2,
    radius: 40,
    extent: 512,
    nodeSize: 64,
    log: false,
    generateId: false,
    reduce: null,
    map: function (props) {
        return props;
    }
};
var Supercluster = function Supercluster(options) {
    this.options = extend(Object.create(defaultOptions), options);
    this.trees = new Array(this.options.maxZoom + 1);
};
Supercluster.prototype.load = function load(points) {
    var ref = this.options;
    var log = ref.log;
    var minZoom = ref.minZoom;
    var maxZoom = ref.maxZoom;
    var nodeSize = ref.nodeSize;
    if (log) {
        console.time('total time');
    }
    var timerId = 'prepare ' + points.length + ' points';
    if (log) {
        console.time(timerId);
    }
    this.points = points;
    var clusters = [];
    for (var i = 0; i < points.length; i++) {
        if (!points[i].geometry) {
            continue;
        }
        clusters.push(createPointCluster(points[i], i));
    }
    this.trees[maxZoom + 1] = new KDBush(clusters, getX, getY, nodeSize, Float32Array);
    if (log) {
        console.timeEnd(timerId);
    }
    for (var z = maxZoom; z >= minZoom; z--) {
        var now = +Date.now();
        clusters = this._cluster(clusters, z);
        this.trees[z] = new KDBush(clusters, getX, getY, nodeSize, Float32Array);
        if (log) {
            console.log('z%d: %d clusters in %dms', z, clusters.length, +Date.now() - now);
        }
    }
    if (log) {
        console.timeEnd('total time');
    }
    return this;
};
Supercluster.prototype.getClusters = function getClusters(bbox, zoom) {
    var minLng = ((bbox[0] + 180) % 360 + 360) % 360 - 180;
    var minLat = Math.max(-90, Math.min(90, bbox[1]));
    var maxLng = bbox[2] === 180 ? 180 : ((bbox[2] + 180) % 360 + 360) % 360 - 180;
    var maxLat = Math.max(-90, Math.min(90, bbox[3]));
    if (bbox[2] - bbox[0] >= 360) {
        minLng = -180;
        maxLng = 180;
    } else if (minLng > maxLng) {
        var easternHem = this.getClusters([
            minLng,
            minLat,
            180,
            maxLat
        ], zoom);
        var westernHem = this.getClusters([
            -180,
            minLat,
            maxLng,
            maxLat
        ], zoom);
        return easternHem.concat(westernHem);
    }
    var tree = this.trees[this._limitZoom(zoom)];
    var ids = tree.range(lngX(minLng), latY(maxLat), lngX(maxLng), latY(minLat));
    var clusters = [];
    for (var i = 0, list = ids; i < list.length; i += 1) {
        var id = list[i];
        var c = tree.points[id];
        clusters.push(c.numPoints ? getClusterJSON(c) : this.points[c.index]);
    }
    return clusters;
};
Supercluster.prototype.getChildren = function getChildren(clusterId) {
    var originId = this._getOriginId(clusterId);
    var originZoom = this._getOriginZoom(clusterId);
    var errorMsg = 'No cluster with the specified id.';
    var index = this.trees[originZoom];
    if (!index) {
        throw new Error(errorMsg);
    }
    var origin = index.points[originId];
    if (!origin) {
        throw new Error(errorMsg);
    }
    var r = this.options.radius / (this.options.extent * Math.pow(2, originZoom - 1));
    var ids = index.within(origin.x, origin.y, r);
    var children = [];
    for (var i = 0, list = ids; i < list.length; i += 1) {
        var id = list[i];
        var c = index.points[id];
        if (c.parentId === clusterId) {
            children.push(c.numPoints ? getClusterJSON(c) : this.points[c.index]);
        }
    }
    if (children.length === 0) {
        throw new Error(errorMsg);
    }
    return children;
};
Supercluster.prototype.getLeaves = function getLeaves(clusterId, limit, offset) {
    limit = limit || 10;
    offset = offset || 0;
    var leaves = [];
    this._appendLeaves(leaves, clusterId, limit, offset, 0);
    return leaves;
};
Supercluster.prototype.getTile = function getTile(z, x, y) {
    var tree = this.trees[this._limitZoom(z)];
    var z2 = Math.pow(2, z);
    var ref = this.options;
    var extent = ref.extent;
    var radius = ref.radius;
    var p = radius / extent;
    var top = (y - p) / z2;
    var bottom = (y + 1 + p) / z2;
    var tile = { features: [] };
    this._addTileFeatures(tree.range((x - p) / z2, top, (x + 1 + p) / z2, bottom), tree.points, x, y, z2, tile);
    if (x === 0) {
        this._addTileFeatures(tree.range(1 - p / z2, top, 1, bottom), tree.points, z2, y, z2, tile);
    }
    if (x === z2 - 1) {
        this._addTileFeatures(tree.range(0, top, p / z2, bottom), tree.points, -1, y, z2, tile);
    }
    return tile.features.length ? tile : null;
};
Supercluster.prototype.getClusterExpansionZoom = function getClusterExpansionZoom(clusterId) {
    var expansionZoom = this._getOriginZoom(clusterId) - 1;
    while (expansionZoom <= this.options.maxZoom) {
        var children = this.getChildren(clusterId);
        expansionZoom++;
        if (children.length !== 1) {
            break;
        }
        clusterId = children[0].properties.cluster_id;
    }
    return expansionZoom;
};
Supercluster.prototype._appendLeaves = function _appendLeaves(result, clusterId, limit, offset, skipped) {
    var children = this.getChildren(clusterId);
    for (var i = 0, list = children; i < list.length; i += 1) {
        var child = list[i];
        var props = child.properties;
        if (props && props.cluster) {
            if (skipped + props.point_count <= offset) {
                skipped += props.point_count;
            } else {
                skipped = this._appendLeaves(result, props.cluster_id, limit, offset, skipped);
            }
        } else if (skipped < offset) {
            skipped++;
        } else {
            result.push(child);
        }
        if (result.length === limit) {
            break;
        }
    }
    return skipped;
};
Supercluster.prototype._addTileFeatures = function _addTileFeatures(ids, points, x, y, z2, tile) {
    for (var i$1 = 0, list = ids; i$1 < list.length; i$1 += 1) {
        var i = list[i$1];
        var c = points[i];
        var isCluster = c.numPoints;
        var f = {
            type: 1,
            geometry: [[
                    Math.round(this.options.extent * (c.x * z2 - x)),
                    Math.round(this.options.extent * (c.y * z2 - y))
                ]],
            tags: isCluster ? getClusterProperties(c) : this.points[c.index].properties
        };
        var id = void 0;
        if (isCluster) {
            id = c.id;
        } else if (this.options.generateId) {
            id = c.index;
        } else if (this.points[c.index].id) {
            id = this.points[c.index].id;
        }
        if (id !== undefined) {
            f.id = id;
        }
        tile.features.push(f);
    }
};
Supercluster.prototype._limitZoom = function _limitZoom(z) {
    return Math.max(this.options.minZoom, Math.min(+z, this.options.maxZoom + 1));
};
Supercluster.prototype._cluster = function _cluster(points, zoom) {
    var clusters = [];
    var ref = this.options;
    var radius = ref.radius;
    var extent = ref.extent;
    var reduce = ref.reduce;
    var minPoints = ref.minPoints;
    var r = radius / (extent * Math.pow(2, zoom));
    for (var i = 0; i < points.length; i++) {
        var p = points[i];
        if (p.zoom <= zoom) {
            continue;
        }
        p.zoom = zoom;
        var tree = this.trees[zoom + 1];
        var neighborIds = tree.within(p.x, p.y, r);
        var numPointsOrigin = p.numPoints || 1;
        var numPoints = numPointsOrigin;
        for (var i$1 = 0, list = neighborIds; i$1 < list.length; i$1 += 1) {
            var neighborId = list[i$1];
            var b = tree.points[neighborId];
            if (b.zoom > zoom) {
                numPoints += b.numPoints || 1;
            }
        }
        if (numPoints >= minPoints) {
            var wx = p.x * numPointsOrigin;
            var wy = p.y * numPointsOrigin;
            var clusterProperties = reduce && numPointsOrigin > 1 ? this._map(p, true) : null;
            var id = (i << 5) + (zoom + 1) + this.points.length;
            for (var i$2 = 0, list$1 = neighborIds; i$2 < list$1.length; i$2 += 1) {
                var neighborId$1 = list$1[i$2];
                var b$1 = tree.points[neighborId$1];
                if (b$1.zoom <= zoom) {
                    continue;
                }
                b$1.zoom = zoom;
                var numPoints2 = b$1.numPoints || 1;
                wx += b$1.x * numPoints2;
                wy += b$1.y * numPoints2;
                b$1.parentId = id;
                if (reduce) {
                    if (!clusterProperties) {
                        clusterProperties = this._map(p, true);
                    }
                    reduce(clusterProperties, this._map(b$1));
                }
            }
            p.parentId = id;
            clusters.push(createCluster(wx / numPoints, wy / numPoints, id, numPoints, clusterProperties));
        } else {
            clusters.push(p);
            if (numPoints > 1) {
                for (var i$3 = 0, list$2 = neighborIds; i$3 < list$2.length; i$3 += 1) {
                    var neighborId$2 = list$2[i$3];
                    var b$2 = tree.points[neighborId$2];
                    if (b$2.zoom <= zoom) {
                        continue;
                    }
                    b$2.zoom = zoom;
                    clusters.push(b$2);
                }
            }
        }
    }
    return clusters;
};
Supercluster.prototype._getOriginId = function _getOriginId(clusterId) {
    return clusterId - this.points.length >> 5;
};
Supercluster.prototype._getOriginZoom = function _getOriginZoom(clusterId) {
    return (clusterId - this.points.length) % 32;
};
Supercluster.prototype._map = function _map(point, clone) {
    if (point.numPoints) {
        return clone ? extend({}, point.properties) : point.properties;
    }
    var original = this.points[point.index].properties;
    var result = this.options.map(original);
    return clone && result === original ? extend({}, result) : result;
};
function createCluster(x, y, id, numPoints, properties) {
    return {
        x: x,
        y: y,
        zoom: Infinity,
        id: id,
        parentId: -1,
        numPoints: numPoints,
        properties: properties
    };
}
function createPointCluster(p, id) {
    var ref = p.geometry.coordinates;
    var x = ref[0];
    var y = ref[1];
    return {
        x: lngX(x),
        y: latY(y),
        zoom: Infinity,
        index: id,
        parentId: -1
    };
}
function getClusterJSON(cluster) {
    return {
        type: 'Feature',
        id: cluster.id,
        properties: getClusterProperties(cluster),
        geometry: {
            type: 'Point',
            coordinates: [
                xLng(cluster.x),
                yLat(cluster.y)
            ]
        }
    };
}
function getClusterProperties(cluster) {
    var count = cluster.numPoints;
    var abbrev = count >= 10000 ? Math.round(count / 1000) + 'k' : count >= 1000 ? Math.round(count / 100) / 10 + 'k' : count;
    return extend(extend({}, cluster.properties), {
        cluster: true,
        cluster_id: cluster.id,
        point_count: count,
        point_count_abbreviated: abbrev
    });
}
function lngX(lng) {
    return lng / 360 + 0.5;
}
function latY(lat) {
    var sin = Math.sin(lat * Math.PI / 180);
    var y = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
    return y < 0 ? 0 : y > 1 ? 1 : y;
}
function xLng(x) {
    return (x - 0.5) * 360;
}
function yLat(y) {
    var y2 = (180 - y * 360) * Math.PI / 180;
    return 360 * Math.atan(Math.exp(y2)) / Math.PI - 90;
}
function extend(dest, src) {
    for (var id in src) {
        dest[id] = src[id];
    }
    return dest;
}
function getX(p) {
    return p.x;
}
function getY(p) {
    return p.y;
}

function simplify(coords, first, last, sqTolerance) {
    var maxSqDist = sqTolerance;
    var mid = last - first >> 1;
    var minPosToMid = last - first;
    var index;
    var ax = coords[first];
    var ay = coords[first + 1];
    var bx = coords[last];
    var by = coords[last + 1];
    for (var i = first + 3; i < last; i += 3) {
        var d = getSqSegDist(coords[i], coords[i + 1], ax, ay, bx, by);
        if (d > maxSqDist) {
            index = i;
            maxSqDist = d;
        } else if (d === maxSqDist) {
            var posToMid = Math.abs(i - mid);
            if (posToMid < minPosToMid) {
                index = i;
                minPosToMid = posToMid;
            }
        }
    }
    if (maxSqDist > sqTolerance) {
        if (index - first > 3) {
            simplify(coords, first, index, sqTolerance);
        }
        coords[index + 2] = maxSqDist;
        if (last - index > 3) {
            simplify(coords, index, last, sqTolerance);
        }
    }
}
function getSqSegDist(px, py, x, y, bx, by) {
    var dx = bx - x;
    var dy = by - y;
    if (dx !== 0 || dy !== 0) {
        var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
        if (t > 1) {
            x = bx;
            y = by;
        } else if (t > 0) {
            x += dx * t;
            y += dy * t;
        }
    }
    dx = px - x;
    dy = py - y;
    return dx * dx + dy * dy;
}

function createFeature(id, type, geom, tags) {
    var feature = {
        id: typeof id === 'undefined' ? null : id,
        type: type,
        geometry: geom,
        tags: tags,
        minX: Infinity,
        minY: Infinity,
        maxX: -Infinity,
        maxY: -Infinity
    };
    calcBBox(feature);
    return feature;
}
function calcBBox(feature) {
    var geom = feature.geometry;
    var type = feature.type;
    if (type === 'Point' || type === 'MultiPoint' || type === 'LineString') {
        calcLineBBox(feature, geom);
    } else if (type === 'Polygon' || type === 'MultiLineString') {
        for (var i = 0; i < geom.length; i++) {
            calcLineBBox(feature, geom[i]);
        }
    } else if (type === 'MultiPolygon') {
        for (i = 0; i < geom.length; i++) {
            for (var j = 0; j < geom[i].length; j++) {
                calcLineBBox(feature, geom[i][j]);
            }
        }
    }
}
function calcLineBBox(feature, geom) {
    for (var i = 0; i < geom.length; i += 3) {
        feature.minX = Math.min(feature.minX, geom[i]);
        feature.minY = Math.min(feature.minY, geom[i + 1]);
        feature.maxX = Math.max(feature.maxX, geom[i]);
        feature.maxY = Math.max(feature.maxY, geom[i + 1]);
    }
}

function convert(data, options) {
    var features = [];
    if (data.type === 'FeatureCollection') {
        for (var i = 0; i < data.features.length; i++) {
            convertFeature(features, data.features[i], options, i);
        }
    } else if (data.type === 'Feature') {
        convertFeature(features, data, options);
    } else {
        convertFeature(features, { geometry: data }, options);
    }
    return features;
}
function convertFeature(features, geojson, options, index) {
    if (!geojson.geometry) {
        return;
    }
    var coords = geojson.geometry.coordinates;
    var type = geojson.geometry.type;
    var tolerance = Math.pow(options.tolerance / ((1 << options.maxZoom) * options.extent), 2);
    var geometry = [];
    var id = geojson.id;
    if (options.promoteId) {
        id = geojson.properties[options.promoteId];
    } else if (options.generateId) {
        id = index || 0;
    }
    if (type === 'Point') {
        convertPoint(coords, geometry);
    } else if (type === 'MultiPoint') {
        for (var i = 0; i < coords.length; i++) {
            convertPoint(coords[i], geometry);
        }
    } else if (type === 'LineString') {
        convertLine(coords, geometry, tolerance, false);
    } else if (type === 'MultiLineString') {
        if (options.lineMetrics) {
            for (i = 0; i < coords.length; i++) {
                geometry = [];
                convertLine(coords[i], geometry, tolerance, false);
                features.push(createFeature(id, 'LineString', geometry, geojson.properties));
            }
            return;
        } else {
            convertLines(coords, geometry, tolerance, false);
        }
    } else if (type === 'Polygon') {
        convertLines(coords, geometry, tolerance, true);
    } else if (type === 'MultiPolygon') {
        for (i = 0; i < coords.length; i++) {
            var polygon = [];
            convertLines(coords[i], polygon, tolerance, true);
            geometry.push(polygon);
        }
    } else if (type === 'GeometryCollection') {
        for (i = 0; i < geojson.geometry.geometries.length; i++) {
            convertFeature(features, {
                id: id,
                geometry: geojson.geometry.geometries[i],
                properties: geojson.properties
            }, options, index);
        }
        return;
    } else {
        throw new Error('Input data is not a valid GeoJSON object.');
    }
    features.push(createFeature(id, type, geometry, geojson.properties));
}
function convertPoint(coords, out) {
    out.push(projectX(coords[0]));
    out.push(projectY(coords[1]));
    out.push(0);
}
function convertLine(ring, out, tolerance, isPolygon) {
    var x0, y0;
    var size = 0;
    for (var j = 0; j < ring.length; j++) {
        var x = projectX(ring[j][0]);
        var y = projectY(ring[j][1]);
        out.push(x);
        out.push(y);
        out.push(0);
        if (j > 0) {
            if (isPolygon) {
                size += (x0 * y - x * y0) / 2;
            } else {
                size += Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2));
            }
        }
        x0 = x;
        y0 = y;
    }
    var last = out.length - 3;
    out[2] = 1;
    simplify(out, 0, last, tolerance);
    out[last + 2] = 1;
    out.size = Math.abs(size);
    out.start = 0;
    out.end = out.size;
}
function convertLines(rings, out, tolerance, isPolygon) {
    for (var i = 0; i < rings.length; i++) {
        var geom = [];
        convertLine(rings[i], geom, tolerance, isPolygon);
        out.push(geom);
    }
}
function projectX(x) {
    return x / 360 + 0.5;
}
function projectY(y) {
    var sin = Math.sin(y * Math.PI / 180);
    var y2 = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
    return y2 < 0 ? 0 : y2 > 1 ? 1 : y2;
}

function clip(features, scale, k1, k2, axis, minAll, maxAll, options) {
    k1 /= scale;
    k2 /= scale;
    if (minAll >= k1 && maxAll < k2) {
        return features;
    } else if (maxAll < k1 || minAll >= k2) {
        return null;
    }
    var clipped = [];
    for (var i = 0; i < features.length; i++) {
        var feature = features[i];
        var geometry = feature.geometry;
        var type = feature.type;
        var min = axis === 0 ? feature.minX : feature.minY;
        var max = axis === 0 ? feature.maxX : feature.maxY;
        if (min >= k1 && max < k2) {
            clipped.push(feature);
            continue;
        } else if (max < k1 || min >= k2) {
            continue;
        }
        var newGeometry = [];
        if (type === 'Point' || type === 'MultiPoint') {
            clipPoints(geometry, newGeometry, k1, k2, axis);
        } else if (type === 'LineString') {
            clipLine(geometry, newGeometry, k1, k2, axis, false, options.lineMetrics);
        } else if (type === 'MultiLineString') {
            clipLines(geometry, newGeometry, k1, k2, axis, false);
        } else if (type === 'Polygon') {
            clipLines(geometry, newGeometry, k1, k2, axis, true);
        } else if (type === 'MultiPolygon') {
            for (var j = 0; j < geometry.length; j++) {
                var polygon = [];
                clipLines(geometry[j], polygon, k1, k2, axis, true);
                if (polygon.length) {
                    newGeometry.push(polygon);
                }
            }
        }
        if (newGeometry.length) {
            if (options.lineMetrics && type === 'LineString') {
                for (j = 0; j < newGeometry.length; j++) {
                    clipped.push(createFeature(feature.id, type, newGeometry[j], feature.tags));
                }
                continue;
            }
            if (type === 'LineString' || type === 'MultiLineString') {
                if (newGeometry.length === 1) {
                    type = 'LineString';
                    newGeometry = newGeometry[0];
                } else {
                    type = 'MultiLineString';
                }
            }
            if (type === 'Point' || type === 'MultiPoint') {
                type = newGeometry.length === 3 ? 'Point' : 'MultiPoint';
            }
            clipped.push(createFeature(feature.id, type, newGeometry, feature.tags));
        }
    }
    return clipped.length ? clipped : null;
}
function clipPoints(geom, newGeom, k1, k2, axis) {
    for (var i = 0; i < geom.length; i += 3) {
        var a = geom[i + axis];
        if (a >= k1 && a <= k2) {
            newGeom.push(geom[i]);
            newGeom.push(geom[i + 1]);
            newGeom.push(geom[i + 2]);
        }
    }
}
function clipLine(geom, newGeom, k1, k2, axis, isPolygon, trackMetrics) {
    var slice = newSlice(geom);
    var intersect = axis === 0 ? intersectX : intersectY;
    var len = geom.start;
    var segLen, t;
    for (var i = 0; i < geom.length - 3; i += 3) {
        var ax = geom[i];
        var ay = geom[i + 1];
        var az = geom[i + 2];
        var bx = geom[i + 3];
        var by = geom[i + 4];
        var a = axis === 0 ? ax : ay;
        var b = axis === 0 ? bx : by;
        var exited = false;
        if (trackMetrics) {
            segLen = Math.sqrt(Math.pow(ax - bx, 2) + Math.pow(ay - by, 2));
        }
        if (a < k1) {
            if (b > k1) {
                t = intersect(slice, ax, ay, bx, by, k1);
                if (trackMetrics) {
                    slice.start = len + segLen * t;
                }
            }
        } else if (a > k2) {
            if (b < k2) {
                t = intersect(slice, ax, ay, bx, by, k2);
                if (trackMetrics) {
                    slice.start = len + segLen * t;
                }
            }
        } else {
            addPoint(slice, ax, ay, az);
        }
        if (b < k1 && a >= k1) {
            t = intersect(slice, ax, ay, bx, by, k1);
            exited = true;
        }
        if (b > k2 && a <= k2) {
            t = intersect(slice, ax, ay, bx, by, k2);
            exited = true;
        }
        if (!isPolygon && exited) {
            if (trackMetrics) {
                slice.end = len + segLen * t;
            }
            newGeom.push(slice);
            slice = newSlice(geom);
        }
        if (trackMetrics) {
            len += segLen;
        }
    }
    var last = geom.length - 3;
    ax = geom[last];
    ay = geom[last + 1];
    az = geom[last + 2];
    a = axis === 0 ? ax : ay;
    if (a >= k1 && a <= k2) {
        addPoint(slice, ax, ay, az);
    }
    last = slice.length - 3;
    if (isPolygon && last >= 3 && (slice[last] !== slice[0] || slice[last + 1] !== slice[1])) {
        addPoint(slice, slice[0], slice[1], slice[2]);
    }
    if (slice.length) {
        newGeom.push(slice);
    }
}
function newSlice(line) {
    var slice = [];
    slice.size = line.size;
    slice.start = line.start;
    slice.end = line.end;
    return slice;
}
function clipLines(geom, newGeom, k1, k2, axis, isPolygon) {
    for (var i = 0; i < geom.length; i++) {
        clipLine(geom[i], newGeom, k1, k2, axis, isPolygon, false);
    }
}
function addPoint(out, x, y, z) {
    out.push(x);
    out.push(y);
    out.push(z);
}
function intersectX(out, ax, ay, bx, by, x) {
    var t = (x - ax) / (bx - ax);
    out.push(x);
    out.push(ay + (by - ay) * t);
    out.push(1);
    return t;
}
function intersectY(out, ax, ay, bx, by, y) {
    var t = (y - ay) / (by - ay);
    out.push(ax + (bx - ax) * t);
    out.push(y);
    out.push(1);
    return t;
}

function wrap(features, options) {
    var buffer = options.buffer / options.extent;
    var merged = features;
    var left = clip(features, 1, -1 - buffer, buffer, 0, -1, 2, options);
    var right = clip(features, 1, 1 - buffer, 2 + buffer, 0, -1, 2, options);
    if (left || right) {
        merged = clip(features, 1, -buffer, 1 + buffer, 0, -1, 2, options) || [];
        if (left) {
            merged = shiftFeatureCoords(left, 1).concat(merged);
        }
        if (right) {
            merged = merged.concat(shiftFeatureCoords(right, -1));
        }
    }
    return merged;
}
function shiftFeatureCoords(features, offset) {
    var newFeatures = [];
    for (var i = 0; i < features.length; i++) {
        var feature = features[i], type = feature.type;
        var newGeometry;
        if (type === 'Point' || type === 'MultiPoint' || type === 'LineString') {
            newGeometry = shiftCoords(feature.geometry, offset);
        } else if (type === 'MultiLineString' || type === 'Polygon') {
            newGeometry = [];
            for (var j = 0; j < feature.geometry.length; j++) {
                newGeometry.push(shiftCoords(feature.geometry[j], offset));
            }
        } else if (type === 'MultiPolygon') {
            newGeometry = [];
            for (j = 0; j < feature.geometry.length; j++) {
                var newPolygon = [];
                for (var k = 0; k < feature.geometry[j].length; k++) {
                    newPolygon.push(shiftCoords(feature.geometry[j][k], offset));
                }
                newGeometry.push(newPolygon);
            }
        }
        newFeatures.push(createFeature(feature.id, type, newGeometry, feature.tags));
    }
    return newFeatures;
}
function shiftCoords(points, offset) {
    var newPoints = [];
    newPoints.size = points.size;
    if (points.start !== undefined) {
        newPoints.start = points.start;
        newPoints.end = points.end;
    }
    for (var i = 0; i < points.length; i += 3) {
        newPoints.push(points[i] + offset, points[i + 1], points[i + 2]);
    }
    return newPoints;
}

function transformTile(tile, extent) {
    if (tile.transformed) {
        return tile;
    }
    var z2 = 1 << tile.z, tx = tile.x, ty = tile.y, i, j, k;
    for (i = 0; i < tile.features.length; i++) {
        var feature = tile.features[i], geom = feature.geometry, type = feature.type;
        feature.geometry = [];
        if (type === 1) {
            for (j = 0; j < geom.length; j += 2) {
                feature.geometry.push(transformPoint(geom[j], geom[j + 1], extent, z2, tx, ty));
            }
        } else {
            for (j = 0; j < geom.length; j++) {
                var ring = [];
                for (k = 0; k < geom[j].length; k += 2) {
                    ring.push(transformPoint(geom[j][k], geom[j][k + 1], extent, z2, tx, ty));
                }
                feature.geometry.push(ring);
            }
        }
    }
    tile.transformed = true;
    return tile;
}
function transformPoint(x, y, extent, z2, tx, ty) {
    return [
        Math.round(extent * (x * z2 - tx)),
        Math.round(extent * (y * z2 - ty))
    ];
}

function createTile(features, z, tx, ty, options) {
    var tolerance = z === options.maxZoom ? 0 : options.tolerance / ((1 << z) * options.extent);
    var tile = {
        features: [],
        numPoints: 0,
        numSimplified: 0,
        numFeatures: 0,
        source: null,
        x: tx,
        y: ty,
        z: z,
        transformed: false,
        minX: 2,
        minY: 1,
        maxX: -1,
        maxY: 0
    };
    for (var i = 0; i < features.length; i++) {
        tile.numFeatures++;
        addFeature(tile, features[i], tolerance, options);
        var minX = features[i].minX;
        var minY = features[i].minY;
        var maxX = features[i].maxX;
        var maxY = features[i].maxY;
        if (minX < tile.minX) {
            tile.minX = minX;
        }
        if (minY < tile.minY) {
            tile.minY = minY;
        }
        if (maxX > tile.maxX) {
            tile.maxX = maxX;
        }
        if (maxY > tile.maxY) {
            tile.maxY = maxY;
        }
    }
    return tile;
}
function addFeature(tile, feature, tolerance, options) {
    var geom = feature.geometry, type = feature.type, simplified = [];
    if (type === 'Point' || type === 'MultiPoint') {
        for (var i = 0; i < geom.length; i += 3) {
            simplified.push(geom[i]);
            simplified.push(geom[i + 1]);
            tile.numPoints++;
            tile.numSimplified++;
        }
    } else if (type === 'LineString') {
        addLine(simplified, geom, tile, tolerance, false, false);
    } else if (type === 'MultiLineString' || type === 'Polygon') {
        for (i = 0; i < geom.length; i++) {
            addLine(simplified, geom[i], tile, tolerance, type === 'Polygon', i === 0);
        }
    } else if (type === 'MultiPolygon') {
        for (var k = 0; k < geom.length; k++) {
            var polygon = geom[k];
            for (i = 0; i < polygon.length; i++) {
                addLine(simplified, polygon[i], tile, tolerance, true, i === 0);
            }
        }
    }
    if (simplified.length) {
        var tags = feature.tags || null;
        if (type === 'LineString' && options.lineMetrics) {
            tags = {};
            for (var key in feature.tags) {
                tags[key] = feature.tags[key];
            }
            tags['mapbox_clip_start'] = geom.start / geom.size;
            tags['mapbox_clip_end'] = geom.end / geom.size;
        }
        var tileFeature = {
            geometry: simplified,
            type: type === 'Polygon' || type === 'MultiPolygon' ? 3 : type === 'LineString' || type === 'MultiLineString' ? 2 : 1,
            tags: tags
        };
        if (feature.id !== null) {
            tileFeature.id = feature.id;
        }
        tile.features.push(tileFeature);
    }
}
function addLine(result, geom, tile, tolerance, isPolygon, isOuter) {
    var sqTolerance = tolerance * tolerance;
    if (tolerance > 0 && geom.size < (isPolygon ? sqTolerance : tolerance)) {
        tile.numPoints += geom.length / 3;
        return;
    }
    var ring = [];
    for (var i = 0; i < geom.length; i += 3) {
        if (tolerance === 0 || geom[i + 2] > sqTolerance) {
            tile.numSimplified++;
            ring.push(geom[i]);
            ring.push(geom[i + 1]);
        }
        tile.numPoints++;
    }
    if (isPolygon) {
        rewind$1(ring, isOuter);
    }
    result.push(ring);
}
function rewind$1(ring, clockwise) {
    var area = 0;
    for (var i = 0, len = ring.length, j = len - 2; i < len; j = i, i += 2) {
        area += (ring[i] - ring[j]) * (ring[i + 1] + ring[j + 1]);
    }
    if (area > 0 === clockwise) {
        for (i = 0, len = ring.length; i < len / 2; i += 2) {
            var x = ring[i];
            var y = ring[i + 1];
            ring[i] = ring[len - 2 - i];
            ring[i + 1] = ring[len - 1 - i];
            ring[len - 2 - i] = x;
            ring[len - 1 - i] = y;
        }
    }
}

function geojsonvt(data, options) {
    return new GeoJSONVT(data, options);
}
function GeoJSONVT(data, options) {
    options = this.options = extend$1(Object.create(this.options), options);
    var debug = options.debug;
    if (debug) {
        console.time('preprocess data');
    }
    if (options.maxZoom < 0 || options.maxZoom > 24) {
        throw new Error('maxZoom should be in the 0-24 range');
    }
    if (options.promoteId && options.generateId) {
        throw new Error('promoteId and generateId cannot be used together.');
    }
    var features = convert(data, options);
    this.tiles = {};
    this.tileCoords = [];
    if (debug) {
        console.timeEnd('preprocess data');
        console.log('index: maxZoom: %d, maxPoints: %d', options.indexMaxZoom, options.indexMaxPoints);
        console.time('generate tiles');
        this.stats = {};
        this.total = 0;
    }
    features = wrap(features, options);
    if (features.length) {
        this.splitTile(features, 0, 0, 0);
    }
    if (debug) {
        if (features.length) {
            console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints);
        }
        console.timeEnd('generate tiles');
        console.log('tiles generated:', this.total, JSON.stringify(this.stats));
    }
}
GeoJSONVT.prototype.options = {
    maxZoom: 14,
    indexMaxZoom: 5,
    indexMaxPoints: 100000,
    tolerance: 3,
    extent: 4096,
    buffer: 64,
    lineMetrics: false,
    promoteId: null,
    generateId: false,
    debug: 0
};
GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) {
    var stack = [
            features,
            z,
            x,
            y
        ], options = this.options, debug = options.debug;
    while (stack.length) {
        y = stack.pop();
        x = stack.pop();
        z = stack.pop();
        features = stack.pop();
        var z2 = 1 << z, id = toID(z, x, y), tile = this.tiles[id];
        if (!tile) {
            if (debug > 1) {
                console.time('creation');
            }
            tile = this.tiles[id] = createTile(features, z, x, y, options);
            this.tileCoords.push({
                z: z,
                x: x,
                y: y
            });
            if (debug) {
                if (debug > 1) {
                    console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)', z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified);
                    console.timeEnd('creation');
                }
                var key = 'z' + z;
                this.stats[key] = (this.stats[key] || 0) + 1;
                this.total++;
            }
        }
        tile.source = features;
        if (!cz) {
            if (z === options.indexMaxZoom || tile.numPoints <= options.indexMaxPoints) {
                continue;
            }
        } else {
            if (z === options.maxZoom || z === cz) {
                continue;
            }
            var m = 1 << cz - z;
            if (x !== Math.floor(cx / m) || y !== Math.floor(cy / m)) {
                continue;
            }
        }
        tile.source = null;
        if (features.length === 0) {
            continue;
        }
        if (debug > 1) {
            console.time('clipping');
        }
        var k1 = 0.5 * options.buffer / options.extent, k2 = 0.5 - k1, k3 = 0.5 + k1, k4 = 1 + k1, tl, bl, tr, br, left, right;
        tl = bl = tr = br = null;
        left = clip(features, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, options);
        right = clip(features, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, options);
        features = null;
        if (left) {
            tl = clip(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, options);
            bl = clip(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, options);
            left = null;
        }
        if (right) {
            tr = clip(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, options);
            br = clip(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, options);
            right = null;
        }
        if (debug > 1) {
            console.timeEnd('clipping');
        }
        stack.push(tl || [], z + 1, x * 2, y * 2);
        stack.push(bl || [], z + 1, x * 2, y * 2 + 1);
        stack.push(tr || [], z + 1, x * 2 + 1, y * 2);
        stack.push(br || [], z + 1, x * 2 + 1, y * 2 + 1);
    }
};
GeoJSONVT.prototype.getTile = function (z, x, y) {
    var options = this.options, extent = options.extent, debug = options.debug;
    if (z < 0 || z > 24) {
        return null;
    }
    var z2 = 1 << z;
    x = (x % z2 + z2) % z2;
    var id = toID(z, x, y);
    if (this.tiles[id]) {
        return transformTile(this.tiles[id], extent);
    }
    if (debug > 1) {
        console.log('drilling down to z%d-%d-%d', z, x, y);
    }
    var z0 = z, x0 = x, y0 = y, parent;
    while (!parent && z0 > 0) {
        z0--;
        x0 = Math.floor(x0 / 2);
        y0 = Math.floor(y0 / 2);
        parent = this.tiles[toID(z0, x0, y0)];
    }
    if (!parent || !parent.source) {
        return null;
    }
    if (debug > 1) {
        console.log('found parent tile z%d-%d-%d', z0, x0, y0);
    }
    if (debug > 1) {
        console.time('drilling down');
    }
    this.splitTile(parent.source, z0, x0, y0, z, x, y);
    if (debug > 1) {
        console.timeEnd('drilling down');
    }
    return this.tiles[id] ? transformTile(this.tiles[id], extent) : null;
};
function toID(z, x, y) {
    return ((1 << z) * y + x) * 32 + z;
}
function extend$1(dest, src) {
    for (var i in src) {
        dest[i] = src[i];
    }
    return dest;
}

function loadGeoJSONTile(params, callback) {
    var canonical = params.tileID.canonical;
    if (!this._geoJSONIndex) {
        return callback(null, null);
    }
    var geoJSONTile = this._geoJSONIndex.getTile(canonical.z, canonical.x, canonical.y);
    if (!geoJSONTile) {
        return callback(null, null);
    }
    var geojsonWrapper = new GeoJSONWrapper(geoJSONTile.features);
    var pbf = vtPbf(geojsonWrapper);
    if (pbf.byteOffset !== 0 || pbf.byteLength !== pbf.buffer.byteLength) {
        pbf = new Uint8Array(pbf);
    }
    callback(null, {
        vectorTile: geojsonWrapper,
        rawData: pbf.buffer
    });
}
var GeoJSONWorkerSource = function (VectorTileWorkerSource) {
    function GeoJSONWorkerSource(actor, layerIndex, availableImages, loadGeoJSON) {
        VectorTileWorkerSource.call(this, actor, layerIndex, availableImages, loadGeoJSONTile);
        if (loadGeoJSON) {
            this.loadGeoJSON = loadGeoJSON;
        }
    }
    if (VectorTileWorkerSource)
        GeoJSONWorkerSource.__proto__ = VectorTileWorkerSource;
    GeoJSONWorkerSource.prototype = Object.create(VectorTileWorkerSource && VectorTileWorkerSource.prototype);
    GeoJSONWorkerSource.prototype.constructor = GeoJSONWorkerSource;
    GeoJSONWorkerSource.prototype.loadData = function loadData(params, callback) {
        if (this._pendingCallback) {
            this._pendingCallback(null, { abandoned: true });
        }
        this._pendingCallback = callback;
        this._pendingLoadDataParams = params;
        if (this._state && this._state !== 'Idle') {
            this._state = 'NeedsLoadData';
        } else {
            this._state = 'Coalescing';
            this._loadData();
        }
    };
    GeoJSONWorkerSource.prototype._loadData = function _loadData() {
        var this$1 = this;
        if (!this._pendingCallback || !this._pendingLoadDataParams) {
            return;
        }
        var callback = this._pendingCallback;
        var params = this._pendingLoadDataParams;
        delete this._pendingCallback;
        delete this._pendingLoadDataParams;
        var perf = params && params.request && params.request.collectResourceTiming ? new performance.RequestPerformance(params.request) : false;
        this.loadGeoJSON(params, function (err, data) {
            if (err || !data) {
                return callback(err);
            } else if (typeof data !== 'object') {
                return callback(new Error('Input data given to \'' + params.source + '\' is not a valid GeoJSON object.'));
            } else {
                geojsonRewind(data, true);
                try {
                    if (params.filter) {
                        var compiled = performance.createExpression(params.filter, {
                            type: 'boolean',
                            'property-type': 'data-driven',
                            overridable: false,
                            transition: false
                        });
                        if (compiled.result === 'error') {
                            throw new Error(compiled.value.map(function (err) {
                                return err.key + ': ' + err.message;
                            }).join(', '));
                        }
                        var features = data.features.filter(function (feature) {
                            return compiled.value.evaluate({ zoom: 0 }, feature);
                        });
                        data = {
                            type: 'FeatureCollection',
                            features: features
                        };
                    }
                    this$1._geoJSONIndex = params.cluster ? new Supercluster(getSuperclusterOptions(params)).load(data.features) : geojsonvt(data, params.geojsonVtOptions);
                } catch (err) {
                    return callback(err);
                }
                this$1.loaded = {};
                var result = {};
                if (perf) {
                    var resourceTimingData = perf.finish();
                    if (resourceTimingData) {
                        result.resourceTiming = {};
                        result.resourceTiming[params.source] = JSON.parse(JSON.stringify(resourceTimingData));
                    }
                }
                callback(null, result);
            }
        });
    };
    GeoJSONWorkerSource.prototype.coalesce = function coalesce() {
        if (this._state === 'Coalescing') {
            this._state = 'Idle';
        } else if (this._state === 'NeedsLoadData') {
            this._state = 'Coalescing';
            this._loadData();
        }
    };
    GeoJSONWorkerSource.prototype.reloadTile = function reloadTile(params, callback) {
        var loaded = this.loaded, uid = params.uid;
        if (loaded && loaded[uid]) {
            return VectorTileWorkerSource.prototype.reloadTile.call(this, params, callback);
        } else {
            return this.loadTile(params, callback);
        }
    };
    GeoJSONWorkerSource.prototype.loadGeoJSON = function loadGeoJSON(params, callback) {
        if (params.request) {
            performance.getJSON(params.request, callback);
        } else if (typeof params.data === 'string') {
            try {
                return callback(null, JSON.parse(params.data));
            } catch (e) {
                return callback(new Error('Input data given to \'' + params.source + '\' is not a valid GeoJSON object.'));
            }
        } else {
            return callback(new Error('Input data given to \'' + params.source + '\' is not a valid GeoJSON object.'));
        }
    };
    GeoJSONWorkerSource.prototype.removeSource = function removeSource(params, callback) {
        if (this._pendingCallback) {
            this._pendingCallback(null, { abandoned: true });
        }
        callback();
    };
    GeoJSONWorkerSource.prototype.getClusterExpansionZoom = function getClusterExpansionZoom(params, callback) {
        try {
            callback(null, this._geoJSONIndex.getClusterExpansionZoom(params.clusterId));
        } catch (e) {
            callback(e);
        }
    };
    GeoJSONWorkerSource.prototype.getClusterChildren = function getClusterChildren(params, callback) {
        try {
            callback(null, this._geoJSONIndex.getChildren(params.clusterId));
        } catch (e) {
            callback(e);
        }
    };
    GeoJSONWorkerSource.prototype.getClusterLeaves = function getClusterLeaves(params, callback) {
        try {
            callback(null, this._geoJSONIndex.getLeaves(params.clusterId, params.limit, params.offset));
        } catch (e) {
            callback(e);
        }
    };
    return GeoJSONWorkerSource;
}(VectorTileWorkerSource);
function getSuperclusterOptions(ref) {
    var superclusterOptions = ref.superclusterOptions;
    var clusterProperties = ref.clusterProperties;
    if (!clusterProperties || !superclusterOptions) {
        return superclusterOptions;
    }
    var mapExpressions = {};
    var reduceExpressions = {};
    var globals = {
        accumulated: null,
        zoom: 0
    };
    var feature = { properties: null };
    var propertyNames = Object.keys(clusterProperties);
    for (var i = 0, list = propertyNames; i < list.length; i += 1) {
        var key = list[i];
        var ref$1 = clusterProperties[key];
        var operator = ref$1[0];
        var mapExpression = ref$1[1];
        var mapExpressionParsed = performance.createExpression(mapExpression);
        var reduceExpressionParsed = performance.createExpression(typeof operator === 'string' ? [
            operator,
            ['accumulated'],
            [
                'get',
                key
            ]
        ] : operator);
        mapExpressions[key] = mapExpressionParsed.value;
        reduceExpressions[key] = reduceExpressionParsed.value;
    }
    superclusterOptions.map = function (pointProperties) {
        feature.properties = pointProperties;
        var properties = {};
        for (var i = 0, list = propertyNames; i < list.length; i += 1) {
            var key = list[i];
            properties[key] = mapExpressions[key].evaluate(globals, feature);
        }
        return properties;
    };
    superclusterOptions.reduce = function (accumulated, clusterProperties) {
        feature.properties = clusterProperties;
        for (var i = 0, list = propertyNames; i < list.length; i += 1) {
            var key = list[i];
            globals.accumulated = accumulated[key];
            accumulated[key] = reduceExpressions[key].evaluate(globals, feature);
        }
    };
    return superclusterOptions;
}

var Worker = function Worker(self) {
    var this$1 = this;
    this.self = self;
    this.actor = new performance.Actor(self, this);
    this.layerIndexes = {};
    this.availableImages = {};
    this.workerSourceTypes = {
        vector: VectorTileWorkerSource,
        geojson: GeoJSONWorkerSource
    };
    this.workerSources = {};
    this.demWorkerSources = {};
    this.self.registerWorkerSource = function (name, WorkerSource) {
        if (this$1.workerSourceTypes[name]) {
            throw new Error('Worker source with name "' + name + '" already registered.');
        }
        this$1.workerSourceTypes[name] = WorkerSource;
    };
    this.self.registerRTLTextPlugin = function (rtlTextPlugin) {
        if (performance.plugin.isParsed()) {
            throw new Error('RTL text plugin already registered.');
        }
        performance.plugin['applyArabicShaping'] = rtlTextPlugin.applyArabicShaping;
        performance.plugin['processBidirectionalText'] = rtlTextPlugin.processBidirectionalText;
        performance.plugin['processStyledBidirectionalText'] = rtlTextPlugin.processStyledBidirectionalText;
    };
};
Worker.prototype.setReferrer = function setReferrer(mapID, referrer) {
    this.referrer = referrer;
};
Worker.prototype.setImages = function setImages(mapId, images, callback) {
    this.availableImages[mapId] = images;
    for (var workerSource in this.workerSources[mapId]) {
        var ws = this.workerSources[mapId][workerSource];
        for (var source in ws) {
            ws[source].availableImages = images;
        }
    }
    callback();
};
Worker.prototype.setLayers = function setLayers(mapId, layers, callback) {
    this.getLayerIndex(mapId).replace(layers);
    callback();
};
Worker.prototype.updateLayers = function updateLayers(mapId, params, callback) {
    this.getLayerIndex(mapId).update(params.layers, params.removedIds);
    callback();
};
Worker.prototype.loadTile = function loadTile(mapId, params, callback) {
    this.getWorkerSource(mapId, params.type, params.source).loadTile(params, callback);
};
Worker.prototype.loadDEMTile = function loadDEMTile(mapId, params, callback) {
    this.getDEMWorkerSource(mapId, params.source).loadTile(params, callback);
};
Worker.prototype.reloadTile = function reloadTile(mapId, params, callback) {
    this.getWorkerSource(mapId, params.type, params.source).reloadTile(params, callback);
};
Worker.prototype.abortTile = function abortTile(mapId, params, callback) {
    this.getWorkerSource(mapId, params.type, params.source).abortTile(params, callback);
};
Worker.prototype.removeTile = function removeTile(mapId, params, callback) {
    this.getWorkerSource(mapId, params.type, params.source).removeTile(params, callback);
};
Worker.prototype.removeDEMTile = function removeDEMTile(mapId, params) {
    this.getDEMWorkerSource(mapId, params.source).removeTile(params);
};
Worker.prototype.removeSource = function removeSource(mapId, params, callback) {
    if (!this.workerSources[mapId] || !this.workerSources[mapId][params.type] || !this.workerSources[mapId][params.type][params.source]) {
        return;
    }
    var worker = this.workerSources[mapId][params.type][params.source];
    delete this.workerSources[mapId][params.type][params.source];
    if (worker.removeSource !== undefined) {
        worker.removeSource(params, callback);
    } else {
        callback();
    }
};
Worker.prototype.loadWorkerSource = function loadWorkerSource(map, params, callback) {
    try {
        this.self.importScripts(params.url);
        callback();
    } catch (e) {
        callback(e.toString());
    }
};
Worker.prototype.syncRTLPluginState = function syncRTLPluginState(map, state, callback) {
    try {
        performance.plugin.setState(state);
        var pluginURL = performance.plugin.getPluginURL();
        if (performance.plugin.isLoaded() && !performance.plugin.isParsed() && pluginURL != null) {
            this.self.importScripts(pluginURL);
            var complete = performance.plugin.isParsed();
            var error = complete ? undefined : new Error('RTL Text Plugin failed to import scripts from ' + pluginURL);
            callback(error, complete);
        }
    } catch (e) {
        callback(e.toString());
    }
};
Worker.prototype.getAvailableImages = function getAvailableImages(mapId) {
    var availableImages = this.availableImages[mapId];
    if (!availableImages) {
        availableImages = [];
    }
    return availableImages;
};
Worker.prototype.getLayerIndex = function getLayerIndex(mapId) {
    var layerIndexes = this.layerIndexes[mapId];
    if (!layerIndexes) {
        layerIndexes = this.layerIndexes[mapId] = new StyleLayerIndex();
    }
    return layerIndexes;
};
Worker.prototype.getWorkerSource = function getWorkerSource(mapId, type, source) {
    var this$1 = this;
    if (!this.workerSources[mapId]) {
        this.workerSources[mapId] = {};
    }
    if (!this.workerSources[mapId][type]) {
        this.workerSources[mapId][type] = {};
    }
    if (!this.workerSources[mapId][type][source]) {
        var actor = {
            send: function (type, data, callback) {
                this$1.actor.send(type, data, callback, mapId);
            }
        };
        this.workerSources[mapId][type][source] = new this.workerSourceTypes[type](actor, this.getLayerIndex(mapId), this.getAvailableImages(mapId));
    }
    return this.workerSources[mapId][type][source];
};
Worker.prototype.getDEMWorkerSource = function getDEMWorkerSource(mapId, source) {
    if (!this.demWorkerSources[mapId]) {
        this.demWorkerSources[mapId] = {};
    }
    if (!this.demWorkerSources[mapId][source]) {
        this.demWorkerSources[mapId][source] = new RasterDEMTileWorkerSource();
    }
    return this.demWorkerSources[mapId][source];
};
Worker.prototype.enforceCacheSizeLimit = function enforceCacheSizeLimit$1(mapId, limit) {
    performance.enforceCacheSizeLimit(limit);
};
if (typeof WorkerGlobalScope !== 'undefined' && typeof self !== 'undefined' && self instanceof WorkerGlobalScope) {
    self.worker = new Worker(self);
}

return Worker;

});

define(['./shared'], function (performance) { 'use strict';

var mapboxGlSupported = performance.createCommonjsModule(function (module) {
if ( module.exports) {
    module.exports = isSupported;
} else if (window) {
    window.mapboxgl = window.mapboxgl || {};
    window.mapboxgl.supported = isSupported;
    window.mapboxgl.notSupportedReason = notSupportedReason;
}
function isSupported(options) {
    return !notSupportedReason(options);
}
function notSupportedReason(options) {
    if (!isBrowser()) {
        return 'not a browser';
    }
    if (!isArraySupported()) {
        return 'insufficent Array support';
    }
    if (!isFunctionSupported()) {
        return 'insufficient Function support';
    }
    if (!isObjectSupported()) {
        return 'insufficient Object support';
    }
    if (!isJSONSupported()) {
        return 'insufficient JSON support';
    }
    if (!isWorkerSupported()) {
        return 'insufficient worker support';
    }
    if (!isUint8ClampedArraySupported()) {
        return 'insufficient Uint8ClampedArray support';
    }
    if (!isArrayBufferSupported()) {
        return 'insufficient ArrayBuffer support';
    }
    if (!isCanvasGetImageDataSupported()) {
        return 'insufficient Canvas/getImageData support';
    }
    if (!isWebGLSupportedCached(options && options.failIfMajorPerformanceCaveat)) {
        return 'insufficient WebGL support';
    }
}
function isBrowser() {
    return typeof window !== 'undefined' && typeof document !== 'undefined';
}
function isArraySupported() {
    return Array.prototype && Array.prototype.every && Array.prototype.filter && Array.prototype.forEach && Array.prototype.indexOf && Array.prototype.lastIndexOf && Array.prototype.map && Array.prototype.some && Array.prototype.reduce && Array.prototype.reduceRight && Array.isArray;
}
function isFunctionSupported() {
    return Function.prototype && Function.prototype.bind;
}
function isObjectSupported() {
    return Object.keys && Object.create && Object.getPrototypeOf && Object.getOwnPropertyNames && Object.isSealed && Object.isFrozen && Object.isExtensible && Object.getOwnPropertyDescriptor && Object.defineProperty && Object.defineProperties && Object.seal && Object.freeze && Object.preventExtensions;
}
function isJSONSupported() {
    return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON;
}
function isWorkerSupported() {
    if (!('Worker' in window && 'Blob' in window && 'URL' in window)) {
        return false;
    }
    var blob = new Blob([''], { type: 'text/javascript' });
    var workerURL = URL.createObjectURL(blob);
    var supported;
    var worker;
    try {
        worker = new Worker(workerURL);
        supported = true;
    } catch (e) {
        supported = false;
    }
    if (worker) {
        worker.terminate();
    }
    URL.revokeObjectURL(workerURL);
    return supported;
}
function isUint8ClampedArraySupported() {
    return 'Uint8ClampedArray' in window;
}
function isArrayBufferSupported() {
    return ArrayBuffer.isView;
}
function isCanvasGetImageDataSupported() {
    var canvas = document.createElement('canvas');
    canvas.width = canvas.height = 1;
    var context = canvas.getContext('2d');
    if (!context) {
        return false;
    }
    var imageData = context.getImageData(0, 0, 1, 1);
    return imageData && imageData.width === canvas.width;
}
var isWebGLSupportedCache = {};
function isWebGLSupportedCached(failIfMajorPerformanceCaveat) {
    if (isWebGLSupportedCache[failIfMajorPerformanceCaveat] === undefined) {
        isWebGLSupportedCache[failIfMajorPerformanceCaveat] = isWebGLSupported(failIfMajorPerformanceCaveat);
    }
    return isWebGLSupportedCache[failIfMajorPerformanceCaveat];
}
isSupported.webGLContextAttributes = {
    antialias: false,
    alpha: true,
    stencil: true,
    depth: true
};
function getWebGLContext(failIfMajorPerformanceCaveat) {
    var canvas = document.createElement('canvas');
    var attributes = Object.create(isSupported.webGLContextAttributes);
    attributes.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat;
    if (canvas.probablySupportsContext) {
        return canvas.probablySupportsContext('webgl', attributes) || canvas.probablySupportsContext('experimental-webgl', attributes);
    } else if (canvas.supportsContext) {
        return canvas.supportsContext('webgl', attributes) || canvas.supportsContext('experimental-webgl', attributes);
    } else {
        return canvas.getContext('webgl', attributes) || canvas.getContext('experimental-webgl', attributes);
    }
}
function isWebGLSupported(failIfMajorPerformanceCaveat) {
    var gl = getWebGLContext(failIfMajorPerformanceCaveat);
    if (!gl) {
        return false;
    }
    var shader = gl.createShader(gl.VERTEX_SHADER);
    if (!shader || gl.isContextLost()) {
        return false;
    }
    gl.shaderSource(shader, 'void main() {}');
    gl.compileShader(shader);
    return gl.getShaderParameter(shader, gl.COMPILE_STATUS) === true;
}
});

var DOM = {};
DOM.create = function (tagName, className, container) {
    var el = performance.window.document.createElement(tagName);
    if (className !== undefined) {
        el.className = className;
    }
    if (container) {
        container.appendChild(el);
    }
    return el;
};
DOM.createNS = function (namespaceURI, tagName) {
    var el = performance.window.document.createElementNS(namespaceURI, tagName);
    return el;
};
var docStyle = performance.window.document && performance.window.document.documentElement.style;
function testProp(props) {
    if (!docStyle) {
        return props[0];
    }
    for (var i = 0; i < props.length; i++) {
        if (props[i] in docStyle) {
            return props[i];
        }
    }
    return props[0];
}
var selectProp = testProp([
    'userSelect',
    'MozUserSelect',
    'WebkitUserSelect',
    'msUserSelect'
]);
var userSelect;
DOM.disableDrag = function () {
    if (docStyle && selectProp) {
        userSelect = docStyle[selectProp];
        docStyle[selectProp] = 'none';
    }
};
DOM.enableDrag = function () {
    if (docStyle && selectProp) {
        docStyle[selectProp] = userSelect;
    }
};
var transformProp = testProp([
    'transform',
    'WebkitTransform'
]);
DOM.setTransform = function (el, value) {
    el.style[transformProp] = value;
};
var passiveSupported = false;
try {
    var options$1 = Object.defineProperty({}, 'passive', {
        get: function get() {
            passiveSupported = true;
        }
    });
    performance.window.addEventListener('test', options$1, options$1);
    performance.window.removeEventListener('test', options$1, options$1);
} catch (err) {
    passiveSupported = false;
}
DOM.addEventListener = function (target, type, callback, options) {
    if (options === void 0)
        options = {};
    if ('passive' in options && passiveSupported) {
        target.addEventListener(type, callback, options);
    } else {
        target.addEventListener(type, callback, options.capture);
    }
};
DOM.removeEventListener = function (target, type, callback, options) {
    if (options === void 0)
        options = {};
    if ('passive' in options && passiveSupported) {
        target.removeEventListener(type, callback, options);
    } else {
        target.removeEventListener(type, callback, options.capture);
    }
};
var suppressClick = function (e) {
    e.preventDefault();
    e.stopPropagation();
    performance.window.removeEventListener('click', suppressClick, true);
};
DOM.suppressClick = function () {
    performance.window.addEventListener('click', suppressClick, true);
    performance.window.setTimeout(function () {
        performance.window.removeEventListener('click', suppressClick, true);
    }, 0);
};
DOM.mousePos = function (el, e) {
    var rect = el.getBoundingClientRect();
    return new performance.Point(e.clientX - rect.left - el.clientLeft, e.clientY - rect.top - el.clientTop);
};
DOM.touchPos = function (el, touches) {
    var rect = el.getBoundingClientRect(), points = [];
    for (var i = 0; i < touches.length; i++) {
        points.push(new performance.Point(touches[i].clientX - rect.left - el.clientLeft, touches[i].clientY - rect.top - el.clientTop));
    }
    return points;
};
DOM.mouseButton = function (e) {
    if (typeof performance.window.InstallTrigger !== 'undefined' && e.button === 2 && e.ctrlKey && performance.window.navigator.platform.toUpperCase().indexOf('MAC') >= 0) {
        return 0;
    }
    return e.button;
};
DOM.remove = function (node) {
    if (node.parentNode) {
        node.parentNode.removeChild(node);
    }
};

function loadSprite (baseURL, requestManager, callback) {
    var json, image, error;
    var format = performance.browser.devicePixelRatio > 1 ? '@2x' : '';
    var jsonRequest = performance.getJSON(requestManager.transformRequest(requestManager.normalizeSpriteURL(baseURL, format, '.json'), performance.ResourceType.SpriteJSON), function (err, data) {
        jsonRequest = null;
        if (!error) {
            error = err;
            json = data;
            maybeComplete();
        }
    });
    var imageRequest = performance.getImage(requestManager.transformRequest(requestManager.normalizeSpriteURL(baseURL, format, '.png'), performance.ResourceType.SpriteImage), function (err, img) {
        imageRequest = null;
        if (!error) {
            error = err;
            image = img;
            maybeComplete();
        }
    });
    function maybeComplete() {
        if (error) {
            callback(error);
        } else if (json && image) {
            var imageData = performance.browser.getImageData(image);
            var result = {};
            for (var id in json) {
                var ref = json[id];
                var width = ref.width;
                var height = ref.height;
                var x = ref.x;
                var y = ref.y;
                var sdf = ref.sdf;
                var pixelRatio = ref.pixelRatio;
                var stretchX = ref.stretchX;
                var stretchY = ref.stretchY;
                var content = ref.content;
                var data = new performance.RGBAImage({
                    width: width,
                    height: height
                });
                performance.RGBAImage.copy(imageData, data, {
                    x: x,
                    y: y
                }, {
                    x: 0,
                    y: 0
                }, {
                    width: width,
                    height: height
                });
                result[id] = {
                    data: data,
                    pixelRatio: pixelRatio,
                    sdf: sdf,
                    stretchX: stretchX,
                    stretchY: stretchY,
                    content: content
                };
            }
            callback(null, result);
        }
    }
    return {
        cancel: function cancel() {
            if (jsonRequest) {
                jsonRequest.cancel();
                jsonRequest = null;
            }
            if (imageRequest) {
                imageRequest.cancel();
                imageRequest = null;
            }
        }
    };
}

function renderStyleImage(image) {
    var userImage = image.userImage;
    if (userImage && userImage.render) {
        var updated = userImage.render();
        if (updated) {
            image.data.replace(new Uint8Array(userImage.data.buffer));
            return true;
        }
    }
    return false;
}

var padding = 1;
var ImageManager = function (Evented) {
    function ImageManager() {
        Evented.call(this);
        this.images = {};
        this.updatedImages = {};
        this.callbackDispatchedThisFrame = {};
        this.loaded = false;
        this.requestors = [];
        this.patterns = {};
        this.atlasImage = new performance.RGBAImage({
            width: 1,
            height: 1
        });
        this.dirty = true;
    }
    if (Evented)
        ImageManager.__proto__ = Evented;
    ImageManager.prototype = Object.create(Evented && Evented.prototype);
    ImageManager.prototype.constructor = ImageManager;
    ImageManager.prototype.isLoaded = function isLoaded() {
        return this.loaded;
    };
    ImageManager.prototype.setLoaded = function setLoaded(loaded) {
        if (this.loaded === loaded) {
            return;
        }
        this.loaded = loaded;
        if (loaded) {
            for (var i = 0, list = this.requestors; i < list.length; i += 1) {
                var ref = list[i];
                var ids = ref.ids;
                var callback = ref.callback;
                this._notify(ids, callback);
            }
            this.requestors = [];
        }
    };
    ImageManager.prototype.getImage = function getImage(id) {
        return this.images[id];
    };
    ImageManager.prototype.addImage = function addImage(id, image) {
        if (this._validate(id, image)) {
            this.images[id] = image;
        }
    };
    ImageManager.prototype._validate = function _validate(id, image) {
        var valid = true;
        if (!this._validateStretch(image.stretchX, image.data && image.data.width)) {
            this.fire(new performance.ErrorEvent(new Error('Image "' + id + '" has invalid "stretchX" value')));
            valid = false;
        }
        if (!this._validateStretch(image.stretchY, image.data && image.data.height)) {
            this.fire(new performance.ErrorEvent(new Error('Image "' + id + '" has invalid "stretchY" value')));
            valid = false;
        }
        if (!this._validateContent(image.content, image)) {
            this.fire(new performance.ErrorEvent(new Error('Image "' + id + '" has invalid "content" value')));
            valid = false;
        }
        return valid;
    };
    ImageManager.prototype._validateStretch = function _validateStretch(stretch, size) {
        if (!stretch) {
            return true;
        }
        var last = 0;
        for (var i = 0, list = stretch; i < list.length; i += 1) {
            var part = list[i];
            if (part[0] < last || part[1] < part[0] || size < part[1]) {
                return false;
            }
            last = part[1];
        }
        return true;
    };
    ImageManager.prototype._validateContent = function _validateContent(content, image) {
        if (!content) {
            return true;
        }
        if (content.length !== 4) {
            return false;
        }
        if (content[0] < 0 || image.data.width < content[0]) {
            return false;
        }
        if (content[1] < 0 || image.data.height < content[1]) {
            return false;
        }
        if (content[2] < 0 || image.data.width < content[2]) {
            return false;
        }
        if (content[3] < 0 || image.data.height < content[3]) {
            return false;
        }
        if (content[2] < content[0]) {
            return false;
        }
        if (content[3] < content[1]) {
            return false;
        }
        return true;
    };
    ImageManager.prototype.updateImage = function updateImage(id, image) {
        var oldImage = this.images[id];
        image.version = oldImage.version + 1;
        this.images[id] = image;
        this.updatedImages[id] = true;
    };
    ImageManager.prototype.removeImage = function removeImage(id) {
        var image = this.images[id];
        delete this.images[id];
        delete this.patterns[id];
        if (image.userImage && image.userImage.onRemove) {
            image.userImage.onRemove();
        }
    };
    ImageManager.prototype.listImages = function listImages() {
        return Object.keys(this.images);
    };
    ImageManager.prototype.getImages = function getImages(ids, callback) {
        var hasAllDependencies = true;
        if (!this.isLoaded()) {
            for (var i = 0, list = ids; i < list.length; i += 1) {
                var id = list[i];
                if (!this.images[id]) {
                    hasAllDependencies = false;
                }
            }
        }
        if (this.isLoaded() || hasAllDependencies) {
            this._notify(ids, callback);
        } else {
            this.requestors.push({
                ids: ids,
                callback: callback
            });
        }
    };
    ImageManager.prototype._notify = function _notify(ids, callback) {
        var response = {};
        for (var i = 0, list = ids; i < list.length; i += 1) {
            var id = list[i];
            if (!this.images[id]) {
                this.fire(new performance.Event('styleimagemissing', { id: id }));
            }
            var image = this.images[id];
            if (image) {
                response[id] = {
                    data: image.data.clone(),
                    pixelRatio: image.pixelRatio,
                    sdf: image.sdf,
                    version: image.version,
                    stretchX: image.stretchX,
                    stretchY: image.stretchY,
                    content: image.content,
                    hasRenderCallback: Boolean(image.userImage && image.userImage.render)
                };
            } else {
                performance.warnOnce('Image "' + id + '" could not be loaded. Please make sure you have added the image with map.addImage() or a "sprite" property in your style. You can provide missing images by listening for the "styleimagemissing" map event.');
            }
        }
        callback(null, response);
    };
    ImageManager.prototype.getPixelSize = function getPixelSize() {
        var ref = this.atlasImage;
        var width = ref.width;
        var height = ref.height;
        return {
            width: width,
            height: height
        };
    };
    ImageManager.prototype.getPattern = function getPattern(id) {
        var pattern = this.patterns[id];
        var image = this.getImage(id);
        if (!image) {
            return null;
        }
        if (pattern && pattern.position.version === image.version) {
            return pattern.position;
        }
        if (!pattern) {
            var w = image.data.width + padding * 2;
            var h = image.data.height + padding * 2;
            var bin = {
                w: w,
                h: h,
                x: 0,
                y: 0
            };
            var position = new performance.ImagePosition(bin, image);
            this.patterns[id] = {
                bin: bin,
                position: position
            };
        } else {
            pattern.position.version = image.version;
        }
        this._updatePatternAtlas();
        return this.patterns[id].position;
    };
    ImageManager.prototype.bind = function bind(context) {
        var gl = context.gl;
        if (!this.atlasTexture) {
            this.atlasTexture = new performance.Texture(context, this.atlasImage, gl.RGBA);
        } else if (this.dirty) {
            this.atlasTexture.update(this.atlasImage);
            this.dirty = false;
        }
        this.atlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
    };
    ImageManager.prototype._updatePatternAtlas = function _updatePatternAtlas() {
        var bins = [];
        for (var id in this.patterns) {
            bins.push(this.patterns[id].bin);
        }
        var ref = performance.potpack(bins);
        var w = ref.w;
        var h = ref.h;
        var dst = this.atlasImage;
        dst.resize({
            width: w || 1,
            height: h || 1
        });
        for (var id$1 in this.patterns) {
            var ref$1 = this.patterns[id$1];
            var bin = ref$1.bin;
            var x = bin.x + padding;
            var y = bin.y + padding;
            var src = this.images[id$1].data;
            var w$1 = src.width;
            var h$1 = src.height;
            performance.RGBAImage.copy(src, dst, {
                x: 0,
                y: 0
            }, {
                x: x,
                y: y
            }, {
                width: w$1,
                height: h$1
            });
            performance.RGBAImage.copy(src, dst, {
                x: 0,
                y: h$1 - 1
            }, {
                x: x,
                y: y - 1
            }, {
                width: w$1,
                height: 1
            });
            performance.RGBAImage.copy(src, dst, {
                x: 0,
                y: 0
            }, {
                x: x,
                y: y + h$1
            }, {
                width: w$1,
                height: 1
            });
            performance.RGBAImage.copy(src, dst, {
                x: w$1 - 1,
                y: 0
            }, {
                x: x - 1,
                y: y
            }, {
                width: 1,
                height: h$1
            });
            performance.RGBAImage.copy(src, dst, {
                x: 0,
                y: 0
            }, {
                x: x + w$1,
                y: y
            }, {
                width: 1,
                height: h$1
            });
        }
        this.dirty = true;
    };
    ImageManager.prototype.beginFrame = function beginFrame() {
        this.callbackDispatchedThisFrame = {};
    };
    ImageManager.prototype.dispatchRenderCallbacks = function dispatchRenderCallbacks(ids) {
        for (var i = 0, list = ids; i < list.length; i += 1) {
            var id = list[i];
            if (this.callbackDispatchedThisFrame[id]) {
                continue;
            }
            this.callbackDispatchedThisFrame[id] = true;
            var image = this.images[id];
            var updated = renderStyleImage(image);
            if (updated) {
                this.updateImage(id, image);
            }
        }
    };
    return ImageManager;
}(performance.Evented);

function loadGlyphRange (fontstack, range, urlTemplate, requestManager, callback) {
    var begin = range * 256;
    var end = begin + 255;
    var request = requestManager.transformRequest(requestManager.normalizeGlyphsURL(urlTemplate).replace('{fontstack}', fontstack).replace('{range}', begin + '-' + end), performance.ResourceType.Glyphs);
    performance.getArrayBuffer(request, function (err, data) {
        if (err) {
            callback(err);
        } else if (data) {
            var glyphs = {};
            for (var i = 0, list = performance.parseGlyphPBF(data); i < list.length; i += 1) {
                var glyph = list[i];
                glyphs[glyph.id] = glyph;
            }
            callback(null, glyphs);
        }
    });
}

var tinySdf = TinySDF;
var default_1 = TinySDF;
var INF = 100000000000000000000;
function TinySDF(fontSize, buffer, radius, cutoff, fontFamily, fontWeight) {
    this.fontSize = fontSize || 24;
    this.buffer = buffer === undefined ? 3 : buffer;
    this.cutoff = cutoff || 0.25;
    this.fontFamily = fontFamily || 'sans-serif';
    this.fontWeight = fontWeight || 'normal';
    this.radius = radius || 8;
    var size = this.size = this.fontSize + this.buffer * 2;
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.canvas.height = size;
    this.ctx = this.canvas.getContext('2d');
    this.ctx.font = this.fontWeight + ' ' + this.fontSize + 'px ' + this.fontFamily;
    this.ctx.textBaseline = 'middle';
    this.ctx.fillStyle = 'black';
    this.gridOuter = new Float64Array(size * size);
    this.gridInner = new Float64Array(size * size);
    this.f = new Float64Array(size);
    this.d = new Float64Array(size);
    this.z = new Float64Array(size + 1);
    this.v = new Int16Array(size);
    this.middle = Math.round(size / 2 * (navigator.userAgent.indexOf('Gecko/') >= 0 ? 1.2 : 1));
}
TinySDF.prototype.draw = function (char) {
    this.ctx.clearRect(0, 0, this.size, this.size);
    this.ctx.fillText(char, this.buffer, this.middle);
    var imgData = this.ctx.getImageData(0, 0, this.size, this.size);
    var alphaChannel = new Uint8ClampedArray(this.size * this.size);
    for (var i = 0; i < this.size * this.size; i++) {
        var a = imgData.data[i * 4 + 3] / 255;
        this.gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2);
        this.gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2);
    }
    edt(this.gridOuter, this.size, this.size, this.f, this.d, this.v, this.z);
    edt(this.gridInner, this.size, this.size, this.f, this.d, this.v, this.z);
    for (i = 0; i < this.size * this.size; i++) {
        var d = this.gridOuter[i] - this.gridInner[i];
        alphaChannel[i] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this.radius + this.cutoff))));
    }
    return alphaChannel;
};
function edt(data, width, height, f, d, v, z) {
    for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
            f[y] = data[y * width + x];
        }
        edt1d(f, d, v, z, height);
        for (y = 0; y < height; y++) {
            data[y * width + x] = d[y];
        }
    }
    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            f[x] = data[y * width + x];
        }
        edt1d(f, d, v, z, width);
        for (x = 0; x < width; x++) {
            data[y * width + x] = Math.sqrt(d[x]);
        }
    }
}
function edt1d(f, d, v, z, n) {
    v[0] = 0;
    z[0] = -INF;
    z[1] = +INF;
    for (var q = 1, k = 0; q < n; q++) {
        var s = (f[q] + q * q - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
        while (s <= z[k]) {
            k--;
            s = (f[q] + q * q - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
        }
        k++;
        v[k] = q;
        z[k] = s;
        z[k + 1] = +INF;
    }
    for (q = 0, k = 0; q < n; q++) {
        while (z[k + 1] < q) {
            k++;
        }
        d[q] = (q - v[k]) * (q - v[k]) + f[v[k]];
    }
}
tinySdf.default = default_1;

var GlyphManager = function GlyphManager(requestManager, localIdeographFontFamily) {
    this.requestManager = requestManager;
    this.localIdeographFontFamily = localIdeographFontFamily;
    this.entries = {};
};
GlyphManager.prototype.setURL = function setURL(url) {
    this.url = url;
};
GlyphManager.prototype.getGlyphs = function getGlyphs(glyphs, callback) {
    var this$1 = this;
    var all = [];
    for (var stack in glyphs) {
        for (var i = 0, list = glyphs[stack]; i < list.length; i += 1) {
            var id = list[i];
            all.push({
                stack: stack,
                id: id
            });
        }
    }
    performance.asyncAll(all, function (ref, callback) {
        var stack = ref.stack;
        var id = ref.id;
        var entry = this$1.entries[stack];
        if (!entry) {
            entry = this$1.entries[stack] = {
                glyphs: {},
                requests: {},
                ranges: {}
            };
        }
        var glyph = entry.glyphs[id];
        if (glyph !== undefined) {
            callback(null, {
                stack: stack,
                id: id,
                glyph: glyph
            });
            return;
        }
        glyph = this$1._tinySDF(entry, stack, id);
        if (glyph) {
            entry.glyphs[id] = glyph;
            callback(null, {
                stack: stack,
                id: id,
                glyph: glyph
            });
            return;
        }
        var range = Math.floor(id / 256);
        if (range * 256 > 65535) {
            callback(new Error('glyphs > 65535 not supported'));
            return;
        }
        if (entry.ranges[range]) {
            callback(null, {
                stack: stack,
                id: id,
                glyph: glyph
            });
            return;
        }
        var requests = entry.requests[range];
        if (!requests) {
            requests = entry.requests[range] = [];
            GlyphManager.loadGlyphRange(stack, range, this$1.url, this$1.requestManager, function (err, response) {
                if (response) {
                    for (var id in response) {
                        if (!this$1._doesCharSupportLocalGlyph(+id)) {
                            entry.glyphs[+id] = response[+id];
                        }
                    }
                    entry.ranges[range] = true;
                }
                for (var i = 0, list = requests; i < list.length; i += 1) {
                    var cb = list[i];
                    cb(err, response);
                }
                delete entry.requests[range];
            });
        }
        requests.push(function (err, result) {
            if (err) {
                callback(err);
            } else if (result) {
                callback(null, {
                    stack: stack,
                    id: id,
                    glyph: result[id] || null
                });
            }
        });
    }, function (err, glyphs) {
        if (err) {
            callback(err);
        } else if (glyphs) {
            var result = {};
            for (var i = 0, list = glyphs; i < list.length; i += 1) {
                var ref = list[i];
                var stack = ref.stack;
                var id = ref.id;
                var glyph = ref.glyph;
                (result[stack] || (result[stack] = {}))[id] = glyph && {
                    id: glyph.id,
                    bitmap: glyph.bitmap.clone(),
                    metrics: glyph.metrics
                };
            }
            callback(null, result);
        }
    });
};
GlyphManager.prototype._doesCharSupportLocalGlyph = function _doesCharSupportLocalGlyph(id) {
    return !!this.localIdeographFontFamily && (performance.isChar['CJK Unified Ideographs'](id) || performance.isChar['Hangul Syllables'](id) || performance.isChar['Hiragana'](id) || performance.isChar['Katakana'](id));
};
GlyphManager.prototype._tinySDF = function _tinySDF(entry, stack, id) {
    var family = this.localIdeographFontFamily;
    if (!family) {
        return;
    }
    if (!this._doesCharSupportLocalGlyph(id)) {
        return;
    }
    var tinySDF = entry.tinySDF;
    if (!tinySDF) {
        var fontWeight = '400';
        if (/bold/i.test(stack)) {
            fontWeight = '900';
        } else if (/medium/i.test(stack)) {
            fontWeight = '500';
        } else if (/light/i.test(stack)) {
            fontWeight = '200';
        }
        tinySDF = entry.tinySDF = new GlyphManager.TinySDF(24, 3, 8, 0.25, family, fontWeight);
    }
    return {
        id: id,
        bitmap: new performance.AlphaImage({
            width: 30,
            height: 30
        }, tinySDF.draw(String.fromCharCode(id))),
        metrics: {
            width: 24,
            height: 24,
            left: 0,
            top: -8,
            advance: 24
        }
    };
};
GlyphManager.loadGlyphRange = loadGlyphRange;
GlyphManager.TinySDF = tinySdf;

var LightPositionProperty = function LightPositionProperty() {
    this.specification = performance.styleSpec.light.position;
};
LightPositionProperty.prototype.possiblyEvaluate = function possiblyEvaluate(value, parameters) {
    return performance.sphericalToCartesian(value.expression.evaluate(parameters));
};
LightPositionProperty.prototype.interpolate = function interpolate$1(a, b, t) {
    return {
        x: performance.number(a.x, b.x, t),
        y: performance.number(a.y, b.y, t),
        z: performance.number(a.z, b.z, t)
    };
};
var properties = new performance.Properties({
    'anchor': new performance.DataConstantProperty(performance.styleSpec.light.anchor),
    'position': new LightPositionProperty(),
    'color': new performance.DataConstantProperty(performance.styleSpec.light.color),
    'intensity': new performance.DataConstantProperty(performance.styleSpec.light.intensity)
});
var TRANSITION_SUFFIX = '-transition';
var Light = function (Evented) {
    function Light(lightOptions) {
        Evented.call(this);
        this._transitionable = new performance.Transitionable(properties);
        this.setLight(lightOptions);
        this._transitioning = this._transitionable.untransitioned();
    }
    if (Evented)
        Light.__proto__ = Evented;
    Light.prototype = Object.create(Evented && Evented.prototype);
    Light.prototype.constructor = Light;
    Light.prototype.getLight = function getLight() {
        return this._transitionable.serialize();
    };
    Light.prototype.setLight = function setLight(light, options) {
        if (options === void 0)
            options = {};
        if (this._validate(performance.validateLight, light, options)) {
            return;
        }
        for (var name in light) {
            var value = light[name];
            if (performance.endsWith(name, TRANSITION_SUFFIX)) {
                this._transitionable.setTransition(name.slice(0, -TRANSITION_SUFFIX.length), value);
            } else {
                this._transitionable.setValue(name, value);
            }
        }
    };
    Light.prototype.updateTransitions = function updateTransitions(parameters) {
        this._transitioning = this._transitionable.transitioned(parameters, this._transitioning);
    };
    Light.prototype.hasTransition = function hasTransition() {
        return this._transitioning.hasTransition();
    };
    Light.prototype.recalculate = function recalculate(parameters) {
        this.properties = this._transitioning.possiblyEvaluate(parameters);
    };
    Light.prototype._validate = function _validate(validate, value, options) {
        if (options && options.validate === false) {
            return false;
        }
        return performance.emitValidationErrors(this, validate.call(performance.validateStyle, performance.extend({
            value: value,
            style: {
                glyphs: true,
                sprite: true
            },
            styleSpec: performance.styleSpec
        })));
    };
    return Light;
}(performance.Evented);

var LineAtlas = function LineAtlas(width, height) {
    this.width = width;
    this.height = height;
    this.nextRow = 0;
    this.data = new Uint8Array(this.width * this.height);
    this.dashEntry = {};
};
LineAtlas.prototype.getDash = function getDash(dasharray, round) {
    var key = dasharray.join(',') + String(round);
    if (!this.dashEntry[key]) {
        this.dashEntry[key] = this.addDash(dasharray, round);
    }
    return this.dashEntry[key];
};
LineAtlas.prototype.getDashRanges = function getDashRanges(dasharray, lineAtlasWidth, stretch) {
    var oddDashArray = dasharray.length % 2 === 1;
    var ranges = [];
    var left = oddDashArray ? -dasharray[dasharray.length - 1] * stretch : 0;
    var right = dasharray[0] * stretch;
    var isDash = true;
    ranges.push({
        left: left,
        right: right,
        isDash: isDash,
        zeroLength: dasharray[0] === 0
    });
    var currentDashLength = dasharray[0];
    for (var i = 1; i < dasharray.length; i++) {
        isDash = !isDash;
        var dashLength = dasharray[i];
        left = currentDashLength * stretch;
        currentDashLength += dashLength;
        right = currentDashLength * stretch;
        ranges.push({
            left: left,
            right: right,
            isDash: isDash,
            zeroLength: dashLength === 0
        });
    }
    return ranges;
};
LineAtlas.prototype.addRoundDash = function addRoundDash(ranges, stretch, n) {
    var halfStretch = stretch / 2;
    for (var y = -n; y <= n; y++) {
        var row = this.nextRow + n + y;
        var index = this.width * row;
        var currIndex = 0;
        var range = ranges[currIndex];
        for (var x = 0; x < this.width; x++) {
            if (x / range.right > 1) {
                range = ranges[++currIndex];
            }
            var distLeft = Math.abs(x - range.left);
            var distRight = Math.abs(x - range.right);
            var minDist = Math.min(distLeft, distRight);
            var signedDistance = void 0;
            var distMiddle = y / n * (halfStretch + 1);
            if (range.isDash) {
                var distEdge = halfStretch - Math.abs(distMiddle);
                signedDistance = Math.sqrt(minDist * minDist + distEdge * distEdge);
            } else {
                signedDistance = halfStretch - Math.sqrt(minDist * minDist + distMiddle * distMiddle);
            }
            this.data[index + x] = Math.max(0, Math.min(255, signedDistance + 128));
        }
    }
};
LineAtlas.prototype.addRegularDash = function addRegularDash(ranges) {
    for (var i = ranges.length - 1; i >= 0; --i) {
        var part = ranges[i];
        var next = ranges[i + 1];
        if (part.zeroLength) {
            ranges.splice(i, 1);
        } else if (next && next.isDash === part.isDash) {
            next.left = part.left;
            ranges.splice(i, 1);
        }
    }
    var first = ranges[0];
    var last = ranges[ranges.length - 1];
    if (first.isDash === last.isDash) {
        first.left = last.left - this.width;
        last.right = first.right + this.width;
    }
    var index = this.width * this.nextRow;
    var currIndex = 0;
    var range = ranges[currIndex];
    for (var x = 0; x < this.width; x++) {
        if (x / range.right > 1) {
            range = ranges[++currIndex];
        }
        var distLeft = Math.abs(x - range.left);
        var distRight = Math.abs(x - range.right);
        var minDist = Math.min(distLeft, distRight);
        var signedDistance = range.isDash ? minDist : -minDist;
        this.data[index + x] = Math.max(0, Math.min(255, signedDistance + 128));
    }
};
LineAtlas.prototype.addDash = function addDash(dasharray, round) {
    var n = round ? 7 : 0;
    var height = 2 * n + 1;
    if (this.nextRow + height > this.height) {
        performance.warnOnce('LineAtlas out of space');
        return null;
    }
    var length = 0;
    for (var i = 0; i < dasharray.length; i++) {
        length += dasharray[i];
    }
    if (length !== 0) {
        var stretch = this.width / length;
        var ranges = this.getDashRanges(dasharray, this.width, stretch);
        if (round) {
            this.addRoundDash(ranges, stretch, n);
        } else {
            this.addRegularDash(ranges);
        }
    }
    var dashEntry = {
        y: (this.nextRow + n + 0.5) / this.height,
        height: 2 * n / this.height,
        width: length
    };
    this.nextRow += height;
    this.dirty = true;
    return dashEntry;
};
LineAtlas.prototype.bind = function bind(context) {
    var gl = context.gl;
    if (!this.texture) {
        this.texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, this.texture);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, this.width, this.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, this.data);
    } else {
        gl.bindTexture(gl.TEXTURE_2D, this.texture);
        if (this.dirty) {
            this.dirty = false;
            gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.ALPHA, gl.UNSIGNED_BYTE, this.data);
        }
    }
};

var Dispatcher = function Dispatcher(workerPool, parent) {
    this.workerPool = workerPool;
    this.actors = [];
    this.currentActor = 0;
    this.id = performance.uniqueId();
    var workers = this.workerPool.acquire(this.id);
    for (var i = 0; i < workers.length; i++) {
        var worker = workers[i];
        var actor = new Dispatcher.Actor(worker, parent, this.id);
        actor.name = 'Worker ' + i;
        this.actors.push(actor);
    }
};
Dispatcher.prototype.broadcast = function broadcast(type, data, cb) {
    cb = cb || function () {
    };
    performance.asyncAll(this.actors, function (actor, done) {
        actor.send(type, data, done);
    }, cb);
};
Dispatcher.prototype.getActor = function getActor() {
    this.currentActor = (this.currentActor + 1) % this.actors.length;
    return this.actors[this.currentActor];
};
Dispatcher.prototype.remove = function remove() {
    this.actors.forEach(function (actor) {
        actor.remove();
    });
    this.actors = [];
    this.workerPool.release(this.id);
};
Dispatcher.Actor = performance.Actor;

function loadTileJSON (options, requestManager, callback) {
    var loaded = function (err, tileJSON) {
        if (err) {
            return callback(err);
        } else if (tileJSON) {
            var result = performance.pick(performance.extend(tileJSON, options), [
                'tiles',
                'minzoom',
                'maxzoom',
                'attribution',
                'mapbox_logo',
                'bounds',
                'scheme',
                'tileSize',
                'encoding'
            ]);
            if (tileJSON.vector_layers) {
                result.vectorLayers = tileJSON.vector_layers;
                result.vectorLayerIds = result.vectorLayers.map(function (layer) {
                    return layer.id;
                });
            }
            result.tiles = requestManager.canonicalizeTileset(result, options.url);
            callback(null, result);
        }
    };
    if (options.url) {
        return performance.getJSON(requestManager.transformRequest(requestManager.normalizeSourceURL(options.url), performance.ResourceType.Source), loaded);
    } else {
        return performance.browser.frame(function () {
            return loaded(null, options);
        });
    }
}

var TileBounds = function TileBounds(bounds, minzoom, maxzoom) {
    this.bounds = performance.LngLatBounds.convert(this.validateBounds(bounds));
    this.minzoom = minzoom || 0;
    this.maxzoom = maxzoom || 24;
};
TileBounds.prototype.validateBounds = function validateBounds(bounds) {
    if (!Array.isArray(bounds) || bounds.length !== 4) {
        return [
            -180,
            -90,
            180,
            90
        ];
    }
    return [
        Math.max(-180, bounds[0]),
        Math.max(-90, bounds[1]),
        Math.min(180, bounds[2]),
        Math.min(90, bounds[3])
    ];
};
TileBounds.prototype.contains = function contains(tileID) {
    var worldSize = Math.pow(2, tileID.z);
    var level = {
        minX: Math.floor(performance.mercatorXfromLng(this.bounds.getWest()) * worldSize),
        minY: Math.floor(performance.mercatorYfromLat(this.bounds.getNorth()) * worldSize),
        maxX: Math.ceil(performance.mercatorXfromLng(this.bounds.getEast()) * worldSize),
        maxY: Math.ceil(performance.mercatorYfromLat(this.bounds.getSouth()) * worldSize)
    };
    var hit = tileID.x >= level.minX && tileID.x < level.maxX && tileID.y >= level.minY && tileID.y < level.maxY;
    return hit;
};

var VectorTileSource = function (Evented) {
    function VectorTileSource(id, options, dispatcher, eventedParent) {
        Evented.call(this);
        this.id = id;
        this.dispatcher = dispatcher;
        this.type = 'vector';
        this.minzoom = 0;
        this.maxzoom = 22;
        this.scheme = 'xyz';
        this.tileSize = 512;
        this.reparseOverscaled = true;
        this.isTileClipped = true;
        this._loaded = false;
        performance.extend(this, performance.pick(options, [
            'url',
            'scheme',
            'tileSize',
            'promoteId'
        ]));
        this._options = performance.extend({ type: 'vector' }, options);
        this._collectResourceTiming = options.collectResourceTiming;
        if (this.tileSize !== 512) {
            throw new Error('vector tile sources must have a tileSize of 512');
        }
        this.setEventedParent(eventedParent);
    }
    if (Evented)
        VectorTileSource.__proto__ = Evented;
    VectorTileSource.prototype = Object.create(Evented && Evented.prototype);
    VectorTileSource.prototype.constructor = VectorTileSource;
    VectorTileSource.prototype.load = function load() {
        var this$1 = this;
        this._loaded = false;
        this.fire(new performance.Event('dataloading', { dataType: 'source' }));
        this._tileJSONRequest = loadTileJSON(this._options, this.map._requestManager, function (err, tileJSON) {
            this$1._tileJSONRequest = null;
            this$1._loaded = true;
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
            } else if (tileJSON) {
                performance.extend(this$1, tileJSON);
                if (tileJSON.bounds) {
                    this$1.tileBounds = new TileBounds(tileJSON.bounds, this$1.minzoom, this$1.maxzoom);
                }
                performance.postTurnstileEvent(tileJSON.tiles, this$1.map._requestManager._customAccessToken);
                performance.postMapLoadEvent(tileJSON.tiles, this$1.map._getMapId(), this$1.map._requestManager._skuToken, this$1.map._requestManager._customAccessToken);
                this$1.fire(new performance.Event('data', {
                    dataType: 'source',
                    sourceDataType: 'metadata'
                }));
                this$1.fire(new performance.Event('data', {
                    dataType: 'source',
                    sourceDataType: 'content'
                }));
            }
        });
    };
    VectorTileSource.prototype.loaded = function loaded() {
        return this._loaded;
    };
    VectorTileSource.prototype.hasTile = function hasTile(tileID) {
        return !this.tileBounds || this.tileBounds.contains(tileID.canonical);
    };
    VectorTileSource.prototype.onAdd = function onAdd(map) {
        this.map = map;
        this.load();
    };
    VectorTileSource.prototype.setSourceProperty = function setSourceProperty(callback) {
        if (this._tileJSONRequest) {
            this._tileJSONRequest.cancel();
        }
        callback();
        var sourceCache = this.map.style.sourceCaches[this.id];
        sourceCache.clearTiles();
        this.load();
    };
    VectorTileSource.prototype.setTiles = function setTiles(tiles) {
        var this$1 = this;
        this.setSourceProperty(function () {
            this$1._options.tiles = tiles;
        });
        return this;
    };
    VectorTileSource.prototype.setUrl = function setUrl(url) {
        var this$1 = this;
        this.setSourceProperty(function () {
            this$1.url = url;
            this$1._options.url = url;
        });
        return this;
    };
    VectorTileSource.prototype.onRemove = function onRemove() {
        if (this._tileJSONRequest) {
            this._tileJSONRequest.cancel();
            this._tileJSONRequest = null;
        }
    };
    VectorTileSource.prototype.serialize = function serialize() {
        return performance.extend({}, this._options);
    };
    VectorTileSource.prototype.loadTile = function loadTile(tile, callback) {
        var url = this.map._requestManager.normalizeTileURL(tile.tileID.canonical.url(this.tiles, this.scheme));
        var params = {
            request: this.map._requestManager.transformRequest(url, performance.ResourceType.Tile),
            uid: tile.uid,
            tileID: tile.tileID,
            zoom: tile.tileID.overscaledZ,
            tileSize: this.tileSize * tile.tileID.overscaleFactor(),
            type: this.type,
            source: this.id,
            pixelRatio: performance.browser.devicePixelRatio,
            showCollisionBoxes: this.map.showCollisionBoxes,
            promoteId: this.promoteId
        };
        params.request.collectResourceTiming = this._collectResourceTiming;
        if (!tile.actor || tile.state === 'expired') {
            tile.actor = this.dispatcher.getActor();
            tile.request = tile.actor.send('loadTile', params, done.bind(this));
        } else if (tile.state === 'loading') {
            tile.reloadCallback = callback;
        } else {
            tile.request = tile.actor.send('reloadTile', params, done.bind(this));
        }
        function done(err, data) {
            delete tile.request;
            if (tile.aborted) {
                return callback(null);
            }
            if (err && err.status !== 404) {
                return callback(err);
            }
            if (data && data.resourceTiming) {
                tile.resourceTiming = data.resourceTiming;
            }
            if (this.map._refreshExpiredTiles && data) {
                tile.setExpiryData(data);
            }
            tile.loadVectorData(data, this.map.painter);
            performance.cacheEntryPossiblyAdded(this.dispatcher);
            callback(null);
            if (tile.reloadCallback) {
                this.loadTile(tile, tile.reloadCallback);
                tile.reloadCallback = null;
            }
        }
    };
    VectorTileSource.prototype.abortTile = function abortTile(tile) {
        if (tile.request) {
            tile.request.cancel();
            delete tile.request;
        }
        if (tile.actor) {
            tile.actor.send('abortTile', {
                uid: tile.uid,
                type: this.type,
                source: this.id
            }, undefined);
        }
    };
    VectorTileSource.prototype.unloadTile = function unloadTile(tile) {
        tile.unloadVectorData();
        if (tile.actor) {
            tile.actor.send('removeTile', {
                uid: tile.uid,
                type: this.type,
                source: this.id
            }, undefined);
        }
    };
    VectorTileSource.prototype.hasTransition = function hasTransition() {
        return false;
    };
    return VectorTileSource;
}(performance.Evented);

var RasterTileSource = function (Evented) {
    function RasterTileSource(id, options, dispatcher, eventedParent) {
        Evented.call(this);
        this.id = id;
        this.dispatcher = dispatcher;
        this.setEventedParent(eventedParent);
        this.type = 'raster';
        this.minzoom = 0;
        this.maxzoom = 22;
        this.roundZoom = true;
        this.scheme = 'xyz';
        this.tileSize = 512;
        this._loaded = false;
        this._options = performance.extend({ type: 'raster' }, options);
        performance.extend(this, performance.pick(options, [
            'url',
            'scheme',
            'tileSize'
        ]));
    }
    if (Evented)
        RasterTileSource.__proto__ = Evented;
    RasterTileSource.prototype = Object.create(Evented && Evented.prototype);
    RasterTileSource.prototype.constructor = RasterTileSource;
    RasterTileSource.prototype.load = function load() {
        var this$1 = this;
        this._loaded = false;
        this.fire(new performance.Event('dataloading', { dataType: 'source' }));
        this._tileJSONRequest = loadTileJSON(this._options, this.map._requestManager, function (err, tileJSON) {
            this$1._tileJSONRequest = null;
            this$1._loaded = true;
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
            } else if (tileJSON) {
                performance.extend(this$1, tileJSON);
                if (tileJSON.bounds) {
                    this$1.tileBounds = new TileBounds(tileJSON.bounds, this$1.minzoom, this$1.maxzoom);
                }
                performance.postTurnstileEvent(tileJSON.tiles);
                performance.postMapLoadEvent(tileJSON.tiles, this$1.map._getMapId(), this$1.map._requestManager._skuToken);
                this$1.fire(new performance.Event('data', {
                    dataType: 'source',
                    sourceDataType: 'metadata'
                }));
                this$1.fire(new performance.Event('data', {
                    dataType: 'source',
                    sourceDataType: 'content'
                }));
            }
        });
    };
    RasterTileSource.prototype.loaded = function loaded() {
        return this._loaded;
    };
    RasterTileSource.prototype.onAdd = function onAdd(map) {
        this.map = map;
        this.load();
    };
    RasterTileSource.prototype.onRemove = function onRemove() {
        if (this._tileJSONRequest) {
            this._tileJSONRequest.cancel();
            this._tileJSONRequest = null;
        }
    };
    RasterTileSource.prototype.serialize = function serialize() {
        return performance.extend({}, this._options);
    };
    RasterTileSource.prototype.hasTile = function hasTile(tileID) {
        return !this.tileBounds || this.tileBounds.contains(tileID.canonical);
    };
    RasterTileSource.prototype.loadTile = function loadTile(tile, callback) {
        var this$1 = this;
        var url = this.map._requestManager.normalizeTileURL(tile.tileID.canonical.url(this.tiles, this.scheme), this.tileSize);
        tile.request = performance.getImage(this.map._requestManager.transformRequest(url, performance.ResourceType.Tile), function (err, img) {
            delete tile.request;
            if (tile.aborted) {
                tile.state = 'unloaded';
                callback(null);
            } else if (err) {
                tile.state = 'errored';
                callback(err);
            } else if (img) {
                if (this$1.map._refreshExpiredTiles) {
                    tile.setExpiryData(img);
                }
                delete img.cacheControl;
                delete img.expires;
                var context = this$1.map.painter.context;
                var gl = context.gl;
                tile.texture = this$1.map.painter.getTileTexture(img.width);
                if (tile.texture) {
                    tile.texture.update(img, { useMipmap: true });
                } else {
                    tile.texture = new performance.Texture(context, img, gl.RGBA, { useMipmap: true });
                    tile.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
                    if (context.extTextureFilterAnisotropic) {
                        gl.texParameterf(gl.TEXTURE_2D, context.extTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, context.extTextureFilterAnisotropicMax);
                    }
                }
                tile.state = 'loaded';
                performance.cacheEntryPossiblyAdded(this$1.dispatcher);
                callback(null);
            }
        });
    };
    RasterTileSource.prototype.abortTile = function abortTile(tile, callback) {
        if (tile.request) {
            tile.request.cancel();
            delete tile.request;
        }
        callback();
    };
    RasterTileSource.prototype.unloadTile = function unloadTile(tile, callback) {
        if (tile.texture) {
            this.map.painter.saveTileTexture(tile.texture);
        }
        callback();
    };
    RasterTileSource.prototype.hasTransition = function hasTransition() {
        return false;
    };
    return RasterTileSource;
}(performance.Evented);

var RasterDEMTileSource = function (RasterTileSource) {
    function RasterDEMTileSource(id, options, dispatcher, eventedParent) {
        RasterTileSource.call(this, id, options, dispatcher, eventedParent);
        this.type = 'raster-dem';
        this.maxzoom = 22;
        this._options = performance.extend({ type: 'raster-dem' }, options);
        this.encoding = options.encoding || 'mapbox';
    }
    if (RasterTileSource)
        RasterDEMTileSource.__proto__ = RasterTileSource;
    RasterDEMTileSource.prototype = Object.create(RasterTileSource && RasterTileSource.prototype);
    RasterDEMTileSource.prototype.constructor = RasterDEMTileSource;
    RasterDEMTileSource.prototype.serialize = function serialize() {
        return {
            type: 'raster-dem',
            url: this.url,
            tileSize: this.tileSize,
            tiles: this.tiles,
            bounds: this.bounds,
            encoding: this.encoding
        };
    };
    RasterDEMTileSource.prototype.loadTile = function loadTile(tile, callback) {
        var url = this.map._requestManager.normalizeTileURL(tile.tileID.canonical.url(this.tiles, this.scheme), this.tileSize);
        tile.request = performance.getImage(this.map._requestManager.transformRequest(url, performance.ResourceType.Tile), imageLoaded.bind(this));
        tile.neighboringTiles = this._getNeighboringTiles(tile.tileID);
        function imageLoaded(err, img) {
            delete tile.request;
            if (tile.aborted) {
                tile.state = 'unloaded';
                callback(null);
            } else if (err) {
                tile.state = 'errored';
                callback(err);
            } else if (img) {
                if (this.map._refreshExpiredTiles) {
                    tile.setExpiryData(img);
                }
                delete img.cacheControl;
                delete img.expires;
                var transfer = performance.window.ImageBitmap && img instanceof performance.window.ImageBitmap && performance.offscreenCanvasSupported();
                var rawImageData = transfer ? img : performance.browser.getImageData(img, 1);
                var params = {
                    uid: tile.uid,
                    coord: tile.tileID,
                    source: this.id,
                    rawImageData: rawImageData,
                    encoding: this.encoding
                };
                if (!tile.actor || tile.state === 'expired') {
                    tile.actor = this.dispatcher.getActor();
                    tile.actor.send('loadDEMTile', params, done.bind(this));
                }
            }
        }
        function done(err, dem) {
            if (err) {
                tile.state = 'errored';
                callback(err);
            }
            if (dem) {
                tile.dem = dem;
                tile.needsHillshadePrepare = true;
                tile.state = 'loaded';
                callback(null);
            }
        }
    };
    RasterDEMTileSource.prototype._getNeighboringTiles = function _getNeighboringTiles(tileID) {
        var canonical = tileID.canonical;
        var dim = Math.pow(2, canonical.z);
        var px = (canonical.x - 1 + dim) % dim;
        var pxw = canonical.x === 0 ? tileID.wrap - 1 : tileID.wrap;
        var nx = (canonical.x + 1 + dim) % dim;
        var nxw = canonical.x + 1 === dim ? tileID.wrap + 1 : tileID.wrap;
        var neighboringTiles = {};
        neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, pxw, canonical.z, px, canonical.y).key] = { backfilled: false };
        neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, nxw, canonical.z, nx, canonical.y).key] = { backfilled: false };
        if (canonical.y > 0) {
            neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, pxw, canonical.z, px, canonical.y - 1).key] = { backfilled: false };
            neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, tileID.wrap, canonical.z, canonical.x, canonical.y - 1).key] = { backfilled: false };
            neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, nxw, canonical.z, nx, canonical.y - 1).key] = { backfilled: false };
        }
        if (canonical.y + 1 < dim) {
            neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, pxw, canonical.z, px, canonical.y + 1).key] = { backfilled: false };
            neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, tileID.wrap, canonical.z, canonical.x, canonical.y + 1).key] = { backfilled: false };
            neighboringTiles[new performance.OverscaledTileID(tileID.overscaledZ, nxw, canonical.z, nx, canonical.y + 1).key] = { backfilled: false };
        }
        return neighboringTiles;
    };
    RasterDEMTileSource.prototype.unloadTile = function unloadTile(tile) {
        if (tile.demTexture) {
            this.map.painter.saveTileTexture(tile.demTexture);
        }
        if (tile.fbo) {
            tile.fbo.destroy();
            delete tile.fbo;
        }
        if (tile.dem) {
            delete tile.dem;
        }
        delete tile.neighboringTiles;
        tile.state = 'unloaded';
        if (tile.actor) {
            tile.actor.send('removeDEMTile', {
                uid: tile.uid,
                source: this.id
            });
        }
    };
    return RasterDEMTileSource;
}(RasterTileSource);

var GeoJSONSource = function (Evented) {
    function GeoJSONSource(id, options, dispatcher, eventedParent) {
        Evented.call(this);
        this.id = id;
        this.type = 'geojson';
        this.minzoom = 0;
        this.maxzoom = 18;
        this.tileSize = 512;
        this.isTileClipped = true;
        this.reparseOverscaled = true;
        this._removed = false;
        this._loaded = false;
        this.actor = dispatcher.getActor();
        this.setEventedParent(eventedParent);
        this._data = options.data;
        this._options = performance.extend({}, options);
        this._collectResourceTiming = options.collectResourceTiming;
        this._resourceTiming = [];
        if (options.maxzoom !== undefined) {
            this.maxzoom = options.maxzoom;
        }
        if (options.type) {
            this.type = options.type;
        }
        if (options.attribution) {
            this.attribution = options.attribution;
        }
        this.promoteId = options.promoteId;
        var scale = performance.EXTENT / this.tileSize;
        this.workerOptions = performance.extend({
            source: this.id,
            cluster: options.cluster || false,
            geojsonVtOptions: {
                buffer: (options.buffer !== undefined ? options.buffer : 128) * scale,
                tolerance: (options.tolerance !== undefined ? options.tolerance : 0.375) * scale,
                extent: performance.EXTENT,
                maxZoom: this.maxzoom,
                lineMetrics: options.lineMetrics || false,
                generateId: options.generateId || false
            },
            superclusterOptions: {
                maxZoom: options.clusterMaxZoom !== undefined ? Math.min(options.clusterMaxZoom, this.maxzoom - 1) : this.maxzoom - 1,
                minPoints: Math.max(2, options.clusterMinPoints || 2),
                extent: performance.EXTENT,
                radius: (options.clusterRadius || 50) * scale,
                log: false,
                generateId: options.generateId || false
            },
            clusterProperties: options.clusterProperties,
            filter: options.filter
        }, options.workerOptions);
    }
    if (Evented)
        GeoJSONSource.__proto__ = Evented;
    GeoJSONSource.prototype = Object.create(Evented && Evented.prototype);
    GeoJSONSource.prototype.constructor = GeoJSONSource;
    GeoJSONSource.prototype.load = function load() {
        var this$1 = this;
        this.fire(new performance.Event('dataloading', { dataType: 'source' }));
        this._updateWorkerData(function (err) {
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
                return;
            }
            var data = {
                dataType: 'source',
                sourceDataType: 'metadata'
            };
            if (this$1._collectResourceTiming && this$1._resourceTiming && this$1._resourceTiming.length > 0) {
                data.resourceTiming = this$1._resourceTiming;
                this$1._resourceTiming = [];
            }
            this$1.fire(new performance.Event('data', data));
        });
    };
    GeoJSONSource.prototype.onAdd = function onAdd(map) {
        this.map = map;
        this.load();
    };
    GeoJSONSource.prototype.setData = function setData(data) {
        var this$1 = this;
        this._data = data;
        this.fire(new performance.Event('dataloading', { dataType: 'source' }));
        this._updateWorkerData(function (err) {
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
                return;
            }
            var data = {
                dataType: 'source',
                sourceDataType: 'content'
            };
            if (this$1._collectResourceTiming && this$1._resourceTiming && this$1._resourceTiming.length > 0) {
                data.resourceTiming = this$1._resourceTiming;
                this$1._resourceTiming = [];
            }
            this$1.fire(new performance.Event('data', data));
        });
        return this;
    };
    GeoJSONSource.prototype.getClusterExpansionZoom = function getClusterExpansionZoom(clusterId, callback) {
        this.actor.send('geojson.getClusterExpansionZoom', {
            clusterId: clusterId,
            source: this.id
        }, callback);
        return this;
    };
    GeoJSONSource.prototype.getClusterChildren = function getClusterChildren(clusterId, callback) {
        this.actor.send('geojson.getClusterChildren', {
            clusterId: clusterId,
            source: this.id
        }, callback);
        return this;
    };
    GeoJSONSource.prototype.getClusterLeaves = function getClusterLeaves(clusterId, limit, offset, callback) {
        this.actor.send('geojson.getClusterLeaves', {
            source: this.id,
            clusterId: clusterId,
            limit: limit,
            offset: offset
        }, callback);
        return this;
    };
    GeoJSONSource.prototype._updateWorkerData = function _updateWorkerData(callback) {
        var this$1 = this;
        this._loaded = false;
        var options = performance.extend({}, this.workerOptions);
        var data = this._data;
        if (typeof data === 'string') {
            options.request = this.map._requestManager.transformRequest(performance.browser.resolveURL(data), performance.ResourceType.Source);
            options.request.collectResourceTiming = this._collectResourceTiming;
        } else {
            options.data = JSON.stringify(data);
        }
        this.actor.send(this.type + '.loadData', options, function (err, result) {
            if (this$1._removed || result && result.abandoned) {
                return;
            }
            this$1._loaded = true;
            if (result && result.resourceTiming && result.resourceTiming[this$1.id]) {
                this$1._resourceTiming = result.resourceTiming[this$1.id].slice(0);
            }
            this$1.actor.send(this$1.type + '.coalesce', { source: options.source }, null);
            callback(err);
        });
    };
    GeoJSONSource.prototype.loaded = function loaded() {
        return this._loaded;
    };
    GeoJSONSource.prototype.loadTile = function loadTile(tile, callback) {
        var this$1 = this;
        var message = !tile.actor ? 'loadTile' : 'reloadTile';
        tile.actor = this.actor;
        var params = {
            type: this.type,
            uid: tile.uid,
            tileID: tile.tileID,
            zoom: tile.tileID.overscaledZ,
            maxZoom: this.maxzoom,
            tileSize: this.tileSize,
            source: this.id,
            pixelRatio: performance.browser.devicePixelRatio,
            showCollisionBoxes: this.map.showCollisionBoxes,
            promoteId: this.promoteId
        };
        tile.request = this.actor.send(message, params, function (err, data) {
            delete tile.request;
            tile.unloadVectorData();
            if (tile.aborted) {
                return callback(null);
            }
            if (err) {
                return callback(err);
            }
            tile.loadVectorData(data, this$1.map.painter, message === 'reloadTile');
            return callback(null);
        });
    };
    GeoJSONSource.prototype.abortTile = function abortTile(tile) {
        if (tile.request) {
            tile.request.cancel();
            delete tile.request;
        }
        tile.aborted = true;
    };
    GeoJSONSource.prototype.unloadTile = function unloadTile(tile) {
        tile.unloadVectorData();
        this.actor.send('removeTile', {
            uid: tile.uid,
            type: this.type,
            source: this.id
        });
    };
    GeoJSONSource.prototype.onRemove = function onRemove() {
        this._removed = true;
        this.actor.send('removeSource', {
            type: this.type,
            source: this.id
        });
    };
    GeoJSONSource.prototype.serialize = function serialize() {
        return performance.extend({}, this._options, {
            type: this.type,
            data: this._data
        });
    };
    GeoJSONSource.prototype.hasTransition = function hasTransition() {
        return false;
    };
    return GeoJSONSource;
}(performance.Evented);

var rasterBoundsAttributes = performance.createLayout([
    {
        name: 'a_pos',
        type: 'Int16',
        components: 2
    },
    {
        name: 'a_texture_pos',
        type: 'Int16',
        components: 2
    }
]);

var ImageSource = function (Evented) {
    function ImageSource(id, options, dispatcher, eventedParent) {
        Evented.call(this);
        this.id = id;
        this.dispatcher = dispatcher;
        this.coordinates = options.coordinates;
        this.type = 'image';
        this.minzoom = 0;
        this.maxzoom = 22;
        this.tileSize = 512;
        this.tiles = {};
        this._loaded = false;
        this.setEventedParent(eventedParent);
        this.options = options;
    }
    if (Evented)
        ImageSource.__proto__ = Evented;
    ImageSource.prototype = Object.create(Evented && Evented.prototype);
    ImageSource.prototype.constructor = ImageSource;
    ImageSource.prototype.load = function load(newCoordinates, successCallback) {
        var this$1 = this;
        this._loaded = false;
        this.fire(new performance.Event('dataloading', { dataType: 'source' }));
        this.url = this.options.url;
        performance.getImage(this.map._requestManager.transformRequest(this.url, performance.ResourceType.Image), function (err, image) {
            this$1._loaded = true;
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
            } else if (image) {
                this$1.image = image;
                if (newCoordinates) {
                    this$1.coordinates = newCoordinates;
                }
                if (successCallback) {
                    successCallback();
                }
                this$1._finishLoading();
            }
        });
    };
    ImageSource.prototype.loaded = function loaded() {
        return this._loaded;
    };
    ImageSource.prototype.updateImage = function updateImage(options) {
        var this$1 = this;
        if (!this.image || !options.url) {
            return this;
        }
        this.options.url = options.url;
        this.load(options.coordinates, function () {
            this$1.texture = null;
        });
        return this;
    };
    ImageSource.prototype._finishLoading = function _finishLoading() {
        if (this.map) {
            this.setCoordinates(this.coordinates);
            this.fire(new performance.Event('data', {
                dataType: 'source',
                sourceDataType: 'metadata'
            }));
        }
    };
    ImageSource.prototype.onAdd = function onAdd(map) {
        this.map = map;
        this.load();
    };
    ImageSource.prototype.setCoordinates = function setCoordinates(coordinates) {
        var this$1 = this;
        this.coordinates = coordinates;
        var cornerCoords = coordinates.map(performance.MercatorCoordinate.fromLngLat);
        this.tileID = getCoordinatesCenterTileID(cornerCoords);
        this.minzoom = this.maxzoom = this.tileID.z;
        var tileCoords = cornerCoords.map(function (coord) {
            return this$1.tileID.getTilePoint(coord)._round();
        });
        this._boundsArray = new performance.StructArrayLayout4i8();
        this._boundsArray.emplaceBack(tileCoords[0].x, tileCoords[0].y, 0, 0);
        this._boundsArray.emplaceBack(tileCoords[1].x, tileCoords[1].y, performance.EXTENT, 0);
        this._boundsArray.emplaceBack(tileCoords[3].x, tileCoords[3].y, 0, performance.EXTENT);
        this._boundsArray.emplaceBack(tileCoords[2].x, tileCoords[2].y, performance.EXTENT, performance.EXTENT);
        if (this.boundsBuffer) {
            this.boundsBuffer.destroy();
            delete this.boundsBuffer;
        }
        this.fire(new performance.Event('data', {
            dataType: 'source',
            sourceDataType: 'content'
        }));
        return this;
    };
    ImageSource.prototype.prepare = function prepare() {
        if (Object.keys(this.tiles).length === 0 || !this.image) {
            return;
        }
        var context = this.map.painter.context;
        var gl = context.gl;
        if (!this.boundsBuffer) {
            this.boundsBuffer = context.createVertexBuffer(this._boundsArray, rasterBoundsAttributes.members);
        }
        if (!this.boundsSegments) {
            this.boundsSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 2);
        }
        if (!this.texture) {
            this.texture = new performance.Texture(context, this.image, gl.RGBA);
            this.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
        }
        for (var w in this.tiles) {
            var tile = this.tiles[w];
            if (tile.state !== 'loaded') {
                tile.state = 'loaded';
                tile.texture = this.texture;
            }
        }
    };
    ImageSource.prototype.loadTile = function loadTile(tile, callback) {
        if (this.tileID && this.tileID.equals(tile.tileID.canonical)) {
            this.tiles[String(tile.tileID.wrap)] = tile;
            tile.buckets = {};
            callback(null);
        } else {
            tile.state = 'errored';
            callback(null);
        }
    };
    ImageSource.prototype.serialize = function serialize() {
        return {
            type: 'image',
            url: this.options.url,
            coordinates: this.coordinates
        };
    };
    ImageSource.prototype.hasTransition = function hasTransition() {
        return false;
    };
    return ImageSource;
}(performance.Evented);
function getCoordinatesCenterTileID(coords) {
    var minX = Infinity;
    var minY = Infinity;
    var maxX = -Infinity;
    var maxY = -Infinity;
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        minX = Math.min(minX, coord.x);
        minY = Math.min(minY, coord.y);
        maxX = Math.max(maxX, coord.x);
        maxY = Math.max(maxY, coord.y);
    }
    var dx = maxX - minX;
    var dy = maxY - minY;
    var dMax = Math.max(dx, dy);
    var zoom = Math.max(0, Math.floor(-Math.log(dMax) / Math.LN2));
    var tilesAtZoom = Math.pow(2, zoom);
    return new performance.CanonicalTileID(zoom, Math.floor((minX + maxX) / 2 * tilesAtZoom), Math.floor((minY + maxY) / 2 * tilesAtZoom));
}

var VideoSource = function (ImageSource) {
    function VideoSource(id, options, dispatcher, eventedParent) {
        ImageSource.call(this, id, options, dispatcher, eventedParent);
        this.roundZoom = true;
        this.type = 'video';
        this.options = options;
    }
    if (ImageSource)
        VideoSource.__proto__ = ImageSource;
    VideoSource.prototype = Object.create(ImageSource && ImageSource.prototype);
    VideoSource.prototype.constructor = VideoSource;
    VideoSource.prototype.load = function load() {
        var this$1 = this;
        this._loaded = false;
        var options = this.options;
        this.urls = [];
        for (var i = 0, list = options.urls; i < list.length; i += 1) {
            var url = list[i];
            this.urls.push(this.map._requestManager.transformRequest(url, performance.ResourceType.Source).url);
        }
        performance.getVideo(this.urls, function (err, video) {
            this$1._loaded = true;
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
            } else if (video) {
                this$1.video = video;
                this$1.video.loop = true;
                this$1.video.setAttribute('playsinline', '');
                this$1.video.addEventListener('playing', function () {
                    this$1.map.triggerRepaint();
                });
                if (this$1.map) {
                    this$1.video.play();
                }
                this$1._finishLoading();
            }
        });
    };
    VideoSource.prototype.pause = function pause() {
        if (this.video) {
            this.video.pause();
        }
    };
    VideoSource.prototype.play = function play() {
        if (this.video) {
            this.video.play();
        }
    };
    VideoSource.prototype.seek = function seek(seconds) {
        if (this.video) {
            var seekableRange = this.video.seekable;
            if (seconds < seekableRange.start(0) || seconds > seekableRange.end(0)) {
                this.fire(new performance.ErrorEvent(new performance.ValidationError('sources.' + this.id, null, 'Playback for this video can be set only between the ' + seekableRange.start(0) + ' and ' + seekableRange.end(0) + '-second mark.')));
            } else {
                this.video.currentTime = seconds;
            }
        }
    };
    VideoSource.prototype.getVideo = function getVideo() {
        return this.video;
    };
    VideoSource.prototype.onAdd = function onAdd(map) {
        if (this.map) {
            return;
        }
        this.map = map;
        this.load();
        if (this.video) {
            this.video.play();
            this.setCoordinates(this.coordinates);
        }
    };
    VideoSource.prototype.prepare = function prepare() {
        if (Object.keys(this.tiles).length === 0 || this.video.readyState < 2) {
            return;
        }
        var context = this.map.painter.context;
        var gl = context.gl;
        if (!this.boundsBuffer) {
            this.boundsBuffer = context.createVertexBuffer(this._boundsArray, rasterBoundsAttributes.members);
        }
        if (!this.boundsSegments) {
            this.boundsSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 2);
        }
        if (!this.texture) {
            this.texture = new performance.Texture(context, this.video, gl.RGBA);
            this.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
        } else if (!this.video.paused) {
            this.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
            gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.video);
        }
        for (var w in this.tiles) {
            var tile = this.tiles[w];
            if (tile.state !== 'loaded') {
                tile.state = 'loaded';
                tile.texture = this.texture;
            }
        }
    };
    VideoSource.prototype.serialize = function serialize() {
        return {
            type: 'video',
            urls: this.urls,
            coordinates: this.coordinates
        };
    };
    VideoSource.prototype.hasTransition = function hasTransition() {
        return this.video && !this.video.paused;
    };
    return VideoSource;
}(ImageSource);

var CanvasSource = function (ImageSource) {
    function CanvasSource(id, options, dispatcher, eventedParent) {
        ImageSource.call(this, id, options, dispatcher, eventedParent);
        if (!options.coordinates) {
            this.fire(new performance.ErrorEvent(new performance.ValidationError('sources.' + id, null, 'missing required property "coordinates"')));
        } else if (!Array.isArray(options.coordinates) || options.coordinates.length !== 4 || options.coordinates.some(function (c) {
                return !Array.isArray(c) || c.length !== 2 || c.some(function (l) {
                    return typeof l !== 'number';
                });
            })) {
            this.fire(new performance.ErrorEvent(new performance.ValidationError('sources.' + id, null, '"coordinates" property must be an array of 4 longitude/latitude array pairs')));
        }
        if (options.animate && typeof options.animate !== 'boolean') {
            this.fire(new performance.ErrorEvent(new performance.ValidationError('sources.' + id, null, 'optional "animate" property must be a boolean value')));
        }
        if (!options.canvas) {
            this.fire(new performance.ErrorEvent(new performance.ValidationError('sources.' + id, null, 'missing required property "canvas"')));
        } else if (typeof options.canvas !== 'string' && !(options.canvas instanceof performance.window.HTMLCanvasElement)) {
            this.fire(new performance.ErrorEvent(new performance.ValidationError('sources.' + id, null, '"canvas" must be either a string representing the ID of the canvas element from which to read, or an HTMLCanvasElement instance')));
        }
        this.options = options;
        this.animate = options.animate !== undefined ? options.animate : true;
    }
    if (ImageSource)
        CanvasSource.__proto__ = ImageSource;
    CanvasSource.prototype = Object.create(ImageSource && ImageSource.prototype);
    CanvasSource.prototype.constructor = CanvasSource;
    CanvasSource.prototype.load = function load() {
        this._loaded = true;
        if (!this.canvas) {
            this.canvas = this.options.canvas instanceof performance.window.HTMLCanvasElement ? this.options.canvas : performance.window.document.getElementById(this.options.canvas);
        }
        this.width = this.canvas.width;
        this.height = this.canvas.height;
        if (this._hasInvalidDimensions()) {
            this.fire(new performance.ErrorEvent(new Error('Canvas dimensions cannot be less than or equal to zero.')));
            return;
        }
        this.play = function () {
            this._playing = true;
            this.map.triggerRepaint();
        };
        this.pause = function () {
            if (this._playing) {
                this.prepare();
                this._playing = false;
            }
        };
        this._finishLoading();
    };
    CanvasSource.prototype.getCanvas = function getCanvas() {
        return this.canvas;
    };
    CanvasSource.prototype.onAdd = function onAdd(map) {
        this.map = map;
        this.load();
        if (this.canvas) {
            if (this.animate) {
                this.play();
            }
        }
    };
    CanvasSource.prototype.onRemove = function onRemove() {
        this.pause();
    };
    CanvasSource.prototype.prepare = function prepare() {
        var resize = false;
        if (this.canvas.width !== this.width) {
            this.width = this.canvas.width;
            resize = true;
        }
        if (this.canvas.height !== this.height) {
            this.height = this.canvas.height;
            resize = true;
        }
        if (this._hasInvalidDimensions()) {
            return;
        }
        if (Object.keys(this.tiles).length === 0) {
            return;
        }
        var context = this.map.painter.context;
        var gl = context.gl;
        if (!this.boundsBuffer) {
            this.boundsBuffer = context.createVertexBuffer(this._boundsArray, rasterBoundsAttributes.members);
        }
        if (!this.boundsSegments) {
            this.boundsSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 2);
        }
        if (!this.texture) {
            this.texture = new performance.Texture(context, this.canvas, gl.RGBA, { premultiply: true });
        } else if (resize || this._playing) {
            this.texture.update(this.canvas, { premultiply: true });
        }
        for (var w in this.tiles) {
            var tile = this.tiles[w];
            if (tile.state !== 'loaded') {
                tile.state = 'loaded';
                tile.texture = this.texture;
            }
        }
    };
    CanvasSource.prototype.serialize = function serialize() {
        return {
            type: 'canvas',
            coordinates: this.coordinates
        };
    };
    CanvasSource.prototype.hasTransition = function hasTransition() {
        return this._playing;
    };
    CanvasSource.prototype._hasInvalidDimensions = function _hasInvalidDimensions() {
        for (var i = 0, list = [
                    this.canvas.width,
                    this.canvas.height
                ]; i < list.length; i += 1) {
            var x = list[i];
            if (isNaN(x) || x <= 0) {
                return true;
            }
        }
        return false;
    };
    return CanvasSource;
}(ImageSource);

var sourceTypes = {
    vector: VectorTileSource,
    raster: RasterTileSource,
    'raster-dem': RasterDEMTileSource,
    geojson: GeoJSONSource,
    video: VideoSource,
    image: ImageSource,
    canvas: CanvasSource
};
var create = function (id, specification, dispatcher, eventedParent) {
    var source = new sourceTypes[specification.type](id, specification, dispatcher, eventedParent);
    if (source.id !== id) {
        throw new Error('Expected Source id to be ' + id + ' instead of ' + source.id);
    }
    performance.bindAll([
        'load',
        'abort',
        'unload',
        'serialize',
        'prepare'
    ], source);
    return source;
};
var getType = function (name) {
    return sourceTypes[name];
};
var setType = function (name, type) {
    sourceTypes[name] = type;
};

function getPixelPosMatrix(transform, tileID) {
    var t = performance.identity([]);
    performance.translate(t, t, [
        1,
        1,
        0
    ]);
    performance.scale(t, t, [
        transform.width * 0.5,
        transform.height * 0.5,
        1
    ]);
    return performance.multiply(t, t, transform.calculatePosMatrix(tileID.toUnwrapped()));
}
function queryIncludes3DLayer(layers, styleLayers, sourceID) {
    if (layers) {
        for (var i = 0, list = layers; i < list.length; i += 1) {
            var layerID = list[i];
            var layer = styleLayers[layerID];
            if (layer && layer.source === sourceID && layer.type === 'fill-extrusion') {
                return true;
            }
        }
    } else {
        for (var key in styleLayers) {
            var layer$1 = styleLayers[key];
            if (layer$1.source === sourceID && layer$1.type === 'fill-extrusion') {
                return true;
            }
        }
    }
    return false;
}
function queryRenderedFeatures(sourceCache, styleLayers, serializedLayers, queryGeometry, params, transform) {
    var has3DLayer = queryIncludes3DLayer(params && params.layers, styleLayers, sourceCache.id);
    var maxPitchScaleFactor = transform.maxPitchScaleFactor();
    var tilesIn = sourceCache.tilesIn(queryGeometry, maxPitchScaleFactor, has3DLayer);
    tilesIn.sort(sortTilesIn);
    var renderedFeatureLayers = [];
    for (var i = 0, list = tilesIn; i < list.length; i += 1) {
        var tileIn = list[i];
        renderedFeatureLayers.push({
            wrappedTileID: tileIn.tileID.wrapped().key,
            queryResults: tileIn.tile.queryRenderedFeatures(styleLayers, serializedLayers, sourceCache._state, tileIn.queryGeometry, tileIn.cameraQueryGeometry, tileIn.scale, params, transform, maxPitchScaleFactor, getPixelPosMatrix(sourceCache.transform, tileIn.tileID))
        });
    }
    var result = mergeRenderedFeatureLayers(renderedFeatureLayers);
    for (var layerID in result) {
        result[layerID].forEach(function (featureWrapper) {
            var feature = featureWrapper.feature;
            var state = sourceCache.getFeatureState(feature.layer['source-layer'], feature.id);
            feature.source = feature.layer.source;
            if (feature.layer['source-layer']) {
                feature.sourceLayer = feature.layer['source-layer'];
            }
            feature.state = state;
        });
    }
    return result;
}
function queryRenderedSymbols(styleLayers, serializedLayers, sourceCaches, queryGeometry, params, collisionIndex, retainedQueryData) {
    var result = {};
    var renderedSymbols = collisionIndex.queryRenderedSymbols(queryGeometry);
    var bucketQueryData = [];
    for (var i = 0, list = Object.keys(renderedSymbols).map(Number); i < list.length; i += 1) {
        var bucketInstanceId = list[i];
        bucketQueryData.push(retainedQueryData[bucketInstanceId]);
    }
    bucketQueryData.sort(sortTilesIn);
    var loop = function () {
        var queryData = list$2[i$2];
        var bucketSymbols = queryData.featureIndex.lookupSymbolFeatures(renderedSymbols[queryData.bucketInstanceId], serializedLayers, queryData.bucketIndex, queryData.sourceLayerIndex, params.filter, params.layers, params.availableImages, styleLayers);
        for (var layerID in bucketSymbols) {
            var resultFeatures = result[layerID] = result[layerID] || [];
            var layerSymbols = bucketSymbols[layerID];
            layerSymbols.sort(function (a, b) {
                var featureSortOrder = queryData.featureSortOrder;
                if (featureSortOrder) {
                    var sortedA = featureSortOrder.indexOf(a.featureIndex);
                    var sortedB = featureSortOrder.indexOf(b.featureIndex);
                    return sortedB - sortedA;
                } else {
                    return b.featureIndex - a.featureIndex;
                }
            });
            for (var i$1 = 0, list$1 = layerSymbols; i$1 < list$1.length; i$1 += 1) {
                var symbolFeature = list$1[i$1];
                resultFeatures.push(symbolFeature);
            }
        }
    };
    for (var i$2 = 0, list$2 = bucketQueryData; i$2 < list$2.length; i$2 += 1)
        loop();
    var loop$1 = function (layerName) {
        result[layerName].forEach(function (featureWrapper) {
            var feature = featureWrapper.feature;
            var layer = styleLayers[layerName];
            var sourceCache = sourceCaches[layer.source];
            var state = sourceCache.getFeatureState(feature.layer['source-layer'], feature.id);
            feature.source = feature.layer.source;
            if (feature.layer['source-layer']) {
                feature.sourceLayer = feature.layer['source-layer'];
            }
            feature.state = state;
        });
    };
    for (var layerName in result)
        loop$1(layerName);
    return result;
}
function querySourceFeatures(sourceCache, params) {
    var tiles = sourceCache.getRenderableIds().map(function (id) {
        return sourceCache.getTileByID(id);
    });
    var result = [];
    var dataTiles = {};
    for (var i = 0; i < tiles.length; i++) {
        var tile = tiles[i];
        var dataID = tile.tileID.canonical.key;
        if (!dataTiles[dataID]) {
            dataTiles[dataID] = true;
            tile.querySourceFeatures(result, params);
        }
    }
    return result;
}
function sortTilesIn(a, b) {
    var idA = a.tileID;
    var idB = b.tileID;
    return idA.overscaledZ - idB.overscaledZ || idA.canonical.y - idB.canonical.y || idA.wrap - idB.wrap || idA.canonical.x - idB.canonical.x;
}
function mergeRenderedFeatureLayers(tiles) {
    var result = {};
    var wrappedIDLayerMap = {};
    for (var i$1 = 0, list$1 = tiles; i$1 < list$1.length; i$1 += 1) {
        var tile = list$1[i$1];
        var queryResults = tile.queryResults;
        var wrappedID = tile.wrappedTileID;
        var wrappedIDLayers = wrappedIDLayerMap[wrappedID] = wrappedIDLayerMap[wrappedID] || {};
        for (var layerID in queryResults) {
            var tileFeatures = queryResults[layerID];
            var wrappedIDFeatures = wrappedIDLayers[layerID] = wrappedIDLayers[layerID] || {};
            var resultFeatures = result[layerID] = result[layerID] || [];
            for (var i = 0, list = tileFeatures; i < list.length; i += 1) {
                var tileFeature = list[i];
                if (!wrappedIDFeatures[tileFeature.featureIndex]) {
                    wrappedIDFeatures[tileFeature.featureIndex] = true;
                    resultFeatures.push(tileFeature);
                }
            }
        }
    }
    return result;
}

var TileCache = function TileCache(max, onRemove) {
    this.max = max;
    this.onRemove = onRemove;
    this.reset();
};
TileCache.prototype.reset = function reset() {
    for (var key in this.data) {
        for (var i = 0, list = this.data[key]; i < list.length; i += 1) {
            var removedData = list[i];
            if (removedData.timeout) {
                clearTimeout(removedData.timeout);
            }
            this.onRemove(removedData.value);
        }
    }
    this.data = {};
    this.order = [];
    return this;
};
TileCache.prototype.add = function add(tileID, data, expiryTimeout) {
    var this$1 = this;
    var key = tileID.wrapped().key;
    if (this.data[key] === undefined) {
        this.data[key] = [];
    }
    var dataWrapper = {
        value: data,
        timeout: undefined
    };
    if (expiryTimeout !== undefined) {
        dataWrapper.timeout = setTimeout(function () {
            this$1.remove(tileID, dataWrapper);
        }, expiryTimeout);
    }
    this.data[key].push(dataWrapper);
    this.order.push(key);
    if (this.order.length > this.max) {
        var removedData = this._getAndRemoveByKey(this.order[0]);
        if (removedData) {
            this.onRemove(removedData);
        }
    }
    return this;
};
TileCache.prototype.has = function has(tileID) {
    return tileID.wrapped().key in this.data;
};
TileCache.prototype.getAndRemove = function getAndRemove(tileID) {
    if (!this.has(tileID)) {
        return null;
    }
    return this._getAndRemoveByKey(tileID.wrapped().key);
};
TileCache.prototype._getAndRemoveByKey = function _getAndRemoveByKey(key) {
    var data = this.data[key].shift();
    if (data.timeout) {
        clearTimeout(data.timeout);
    }
    if (this.data[key].length === 0) {
        delete this.data[key];
    }
    this.order.splice(this.order.indexOf(key), 1);
    return data.value;
};
TileCache.prototype.getByKey = function getByKey(key) {
    var data = this.data[key];
    return data ? data[0].value : null;
};
TileCache.prototype.get = function get(tileID) {
    if (!this.has(tileID)) {
        return null;
    }
    var data = this.data[tileID.wrapped().key][0];
    return data.value;
};
TileCache.prototype.remove = function remove(tileID, value) {
    if (!this.has(tileID)) {
        return this;
    }
    var key = tileID.wrapped().key;
    var dataIndex = value === undefined ? 0 : this.data[key].indexOf(value);
    var data = this.data[key][dataIndex];
    this.data[key].splice(dataIndex, 1);
    if (data.timeout) {
        clearTimeout(data.timeout);
    }
    if (this.data[key].length === 0) {
        delete this.data[key];
    }
    this.onRemove(data.value);
    this.order.splice(this.order.indexOf(key), 1);
    return this;
};
TileCache.prototype.setMaxSize = function setMaxSize(max) {
    this.max = max;
    while (this.order.length > this.max) {
        var removedData = this._getAndRemoveByKey(this.order[0]);
        if (removedData) {
            this.onRemove(removedData);
        }
    }
    return this;
};
TileCache.prototype.filter = function filter(filterFn) {
    var removed = [];
    for (var key in this.data) {
        for (var i = 0, list = this.data[key]; i < list.length; i += 1) {
            var entry = list[i];
            if (!filterFn(entry.value)) {
                removed.push(entry);
            }
        }
    }
    for (var i$1 = 0, list$1 = removed; i$1 < list$1.length; i$1 += 1) {
        var r = list$1[i$1];
        this.remove(r.value.tileID, r);
    }
};

var IndexBuffer = function IndexBuffer(context, array, dynamicDraw) {
    this.context = context;
    var gl = context.gl;
    this.buffer = gl.createBuffer();
    this.dynamicDraw = Boolean(dynamicDraw);
    this.context.unbindVAO();
    context.bindElementBuffer.set(this.buffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, array.arrayBuffer, this.dynamicDraw ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW);
    if (!this.dynamicDraw) {
        delete array.arrayBuffer;
    }
};
IndexBuffer.prototype.bind = function bind() {
    this.context.bindElementBuffer.set(this.buffer);
};
IndexBuffer.prototype.updateData = function updateData(array) {
    var gl = this.context.gl;
    this.context.unbindVAO();
    this.bind();
    gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, array.arrayBuffer);
};
IndexBuffer.prototype.destroy = function destroy() {
    var gl = this.context.gl;
    if (this.buffer) {
        gl.deleteBuffer(this.buffer);
        delete this.buffer;
    }
};

var AttributeType = {
    Int8: 'BYTE',
    Uint8: 'UNSIGNED_BYTE',
    Int16: 'SHORT',
    Uint16: 'UNSIGNED_SHORT',
    Int32: 'INT',
    Uint32: 'UNSIGNED_INT',
    Float32: 'FLOAT'
};
var VertexBuffer = function VertexBuffer(context, array, attributes, dynamicDraw) {
    this.length = array.length;
    this.attributes = attributes;
    this.itemSize = array.bytesPerElement;
    this.dynamicDraw = dynamicDraw;
    this.context = context;
    var gl = context.gl;
    this.buffer = gl.createBuffer();
    context.bindVertexBuffer.set(this.buffer);
    gl.bufferData(gl.ARRAY_BUFFER, array.arrayBuffer, this.dynamicDraw ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW);
    if (!this.dynamicDraw) {
        delete array.arrayBuffer;
    }
};
VertexBuffer.prototype.bind = function bind() {
    this.context.bindVertexBuffer.set(this.buffer);
};
VertexBuffer.prototype.updateData = function updateData(array) {
    var gl = this.context.gl;
    this.bind();
    gl.bufferSubData(gl.ARRAY_BUFFER, 0, array.arrayBuffer);
};
VertexBuffer.prototype.enableAttributes = function enableAttributes(gl, program) {
    for (var j = 0; j < this.attributes.length; j++) {
        var member = this.attributes[j];
        var attribIndex = program.attributes[member.name];
        if (attribIndex !== undefined) {
            gl.enableVertexAttribArray(attribIndex);
        }
    }
};
VertexBuffer.prototype.setVertexAttribPointers = function setVertexAttribPointers(gl, program, vertexOffset) {
    for (var j = 0; j < this.attributes.length; j++) {
        var member = this.attributes[j];
        var attribIndex = program.attributes[member.name];
        if (attribIndex !== undefined) {
            gl.vertexAttribPointer(attribIndex, member.components, gl[AttributeType[member.type]], false, this.itemSize, member.offset + this.itemSize * (vertexOffset || 0));
        }
    }
};
VertexBuffer.prototype.destroy = function destroy() {
    var gl = this.context.gl;
    if (this.buffer) {
        gl.deleteBuffer(this.buffer);
        delete this.buffer;
    }
};

var BaseValue = function BaseValue(context) {
    this.gl = context.gl;
    this.default = this.getDefault();
    this.current = this.default;
    this.dirty = false;
};
BaseValue.prototype.get = function get() {
    return this.current;
};
BaseValue.prototype.set = function set(value) {
};
BaseValue.prototype.getDefault = function getDefault() {
    return this.default;
};
BaseValue.prototype.setDefault = function setDefault() {
    this.set(this.default);
};
var ClearColor = function (BaseValue) {
    function ClearColor() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        ClearColor.__proto__ = BaseValue;
    ClearColor.prototype = Object.create(BaseValue && BaseValue.prototype);
    ClearColor.prototype.constructor = ClearColor;
    ClearColor.prototype.getDefault = function getDefault() {
        return performance.Color.transparent;
    };
    ClearColor.prototype.set = function set(v) {
        var c = this.current;
        if (v.r === c.r && v.g === c.g && v.b === c.b && v.a === c.a && !this.dirty) {
            return;
        }
        this.gl.clearColor(v.r, v.g, v.b, v.a);
        this.current = v;
        this.dirty = false;
    };
    return ClearColor;
}(BaseValue);
var ClearDepth = function (BaseValue) {
    function ClearDepth() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        ClearDepth.__proto__ = BaseValue;
    ClearDepth.prototype = Object.create(BaseValue && BaseValue.prototype);
    ClearDepth.prototype.constructor = ClearDepth;
    ClearDepth.prototype.getDefault = function getDefault() {
        return 1;
    };
    ClearDepth.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.clearDepth(v);
        this.current = v;
        this.dirty = false;
    };
    return ClearDepth;
}(BaseValue);
var ClearStencil = function (BaseValue) {
    function ClearStencil() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        ClearStencil.__proto__ = BaseValue;
    ClearStencil.prototype = Object.create(BaseValue && BaseValue.prototype);
    ClearStencil.prototype.constructor = ClearStencil;
    ClearStencil.prototype.getDefault = function getDefault() {
        return 0;
    };
    ClearStencil.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.clearStencil(v);
        this.current = v;
        this.dirty = false;
    };
    return ClearStencil;
}(BaseValue);
var ColorMask = function (BaseValue) {
    function ColorMask() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        ColorMask.__proto__ = BaseValue;
    ColorMask.prototype = Object.create(BaseValue && BaseValue.prototype);
    ColorMask.prototype.constructor = ColorMask;
    ColorMask.prototype.getDefault = function getDefault() {
        return [
            true,
            true,
            true,
            true
        ];
    };
    ColorMask.prototype.set = function set(v) {
        var c = this.current;
        if (v[0] === c[0] && v[1] === c[1] && v[2] === c[2] && v[3] === c[3] && !this.dirty) {
            return;
        }
        this.gl.colorMask(v[0], v[1], v[2], v[3]);
        this.current = v;
        this.dirty = false;
    };
    return ColorMask;
}(BaseValue);
var DepthMask = function (BaseValue) {
    function DepthMask() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        DepthMask.__proto__ = BaseValue;
    DepthMask.prototype = Object.create(BaseValue && BaseValue.prototype);
    DepthMask.prototype.constructor = DepthMask;
    DepthMask.prototype.getDefault = function getDefault() {
        return true;
    };
    DepthMask.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.depthMask(v);
        this.current = v;
        this.dirty = false;
    };
    return DepthMask;
}(BaseValue);
var StencilMask = function (BaseValue) {
    function StencilMask() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        StencilMask.__proto__ = BaseValue;
    StencilMask.prototype = Object.create(BaseValue && BaseValue.prototype);
    StencilMask.prototype.constructor = StencilMask;
    StencilMask.prototype.getDefault = function getDefault() {
        return 255;
    };
    StencilMask.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.stencilMask(v);
        this.current = v;
        this.dirty = false;
    };
    return StencilMask;
}(BaseValue);
var StencilFunc = function (BaseValue) {
    function StencilFunc() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        StencilFunc.__proto__ = BaseValue;
    StencilFunc.prototype = Object.create(BaseValue && BaseValue.prototype);
    StencilFunc.prototype.constructor = StencilFunc;
    StencilFunc.prototype.getDefault = function getDefault() {
        return {
            func: this.gl.ALWAYS,
            ref: 0,
            mask: 255
        };
    };
    StencilFunc.prototype.set = function set(v) {
        var c = this.current;
        if (v.func === c.func && v.ref === c.ref && v.mask === c.mask && !this.dirty) {
            return;
        }
        this.gl.stencilFunc(v.func, v.ref, v.mask);
        this.current = v;
        this.dirty = false;
    };
    return StencilFunc;
}(BaseValue);
var StencilOp = function (BaseValue) {
    function StencilOp() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        StencilOp.__proto__ = BaseValue;
    StencilOp.prototype = Object.create(BaseValue && BaseValue.prototype);
    StencilOp.prototype.constructor = StencilOp;
    StencilOp.prototype.getDefault = function getDefault() {
        var gl = this.gl;
        return [
            gl.KEEP,
            gl.KEEP,
            gl.KEEP
        ];
    };
    StencilOp.prototype.set = function set(v) {
        var c = this.current;
        if (v[0] === c[0] && v[1] === c[1] && v[2] === c[2] && !this.dirty) {
            return;
        }
        this.gl.stencilOp(v[0], v[1], v[2]);
        this.current = v;
        this.dirty = false;
    };
    return StencilOp;
}(BaseValue);
var StencilTest = function (BaseValue) {
    function StencilTest() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        StencilTest.__proto__ = BaseValue;
    StencilTest.prototype = Object.create(BaseValue && BaseValue.prototype);
    StencilTest.prototype.constructor = StencilTest;
    StencilTest.prototype.getDefault = function getDefault() {
        return false;
    };
    StencilTest.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        if (v) {
            gl.enable(gl.STENCIL_TEST);
        } else {
            gl.disable(gl.STENCIL_TEST);
        }
        this.current = v;
        this.dirty = false;
    };
    return StencilTest;
}(BaseValue);
var DepthRange = function (BaseValue) {
    function DepthRange() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        DepthRange.__proto__ = BaseValue;
    DepthRange.prototype = Object.create(BaseValue && BaseValue.prototype);
    DepthRange.prototype.constructor = DepthRange;
    DepthRange.prototype.getDefault = function getDefault() {
        return [
            0,
            1
        ];
    };
    DepthRange.prototype.set = function set(v) {
        var c = this.current;
        if (v[0] === c[0] && v[1] === c[1] && !this.dirty) {
            return;
        }
        this.gl.depthRange(v[0], v[1]);
        this.current = v;
        this.dirty = false;
    };
    return DepthRange;
}(BaseValue);
var DepthTest = function (BaseValue) {
    function DepthTest() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        DepthTest.__proto__ = BaseValue;
    DepthTest.prototype = Object.create(BaseValue && BaseValue.prototype);
    DepthTest.prototype.constructor = DepthTest;
    DepthTest.prototype.getDefault = function getDefault() {
        return false;
    };
    DepthTest.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        if (v) {
            gl.enable(gl.DEPTH_TEST);
        } else {
            gl.disable(gl.DEPTH_TEST);
        }
        this.current = v;
        this.dirty = false;
    };
    return DepthTest;
}(BaseValue);
var DepthFunc = function (BaseValue) {
    function DepthFunc() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        DepthFunc.__proto__ = BaseValue;
    DepthFunc.prototype = Object.create(BaseValue && BaseValue.prototype);
    DepthFunc.prototype.constructor = DepthFunc;
    DepthFunc.prototype.getDefault = function getDefault() {
        return this.gl.LESS;
    };
    DepthFunc.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.depthFunc(v);
        this.current = v;
        this.dirty = false;
    };
    return DepthFunc;
}(BaseValue);
var Blend = function (BaseValue) {
    function Blend() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        Blend.__proto__ = BaseValue;
    Blend.prototype = Object.create(BaseValue && BaseValue.prototype);
    Blend.prototype.constructor = Blend;
    Blend.prototype.getDefault = function getDefault() {
        return false;
    };
    Blend.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        if (v) {
            gl.enable(gl.BLEND);
        } else {
            gl.disable(gl.BLEND);
        }
        this.current = v;
        this.dirty = false;
    };
    return Blend;
}(BaseValue);
var BlendFunc = function (BaseValue) {
    function BlendFunc() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BlendFunc.__proto__ = BaseValue;
    BlendFunc.prototype = Object.create(BaseValue && BaseValue.prototype);
    BlendFunc.prototype.constructor = BlendFunc;
    BlendFunc.prototype.getDefault = function getDefault() {
        var gl = this.gl;
        return [
            gl.ONE,
            gl.ZERO
        ];
    };
    BlendFunc.prototype.set = function set(v) {
        var c = this.current;
        if (v[0] === c[0] && v[1] === c[1] && !this.dirty) {
            return;
        }
        this.gl.blendFunc(v[0], v[1]);
        this.current = v;
        this.dirty = false;
    };
    return BlendFunc;
}(BaseValue);
var BlendColor = function (BaseValue) {
    function BlendColor() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BlendColor.__proto__ = BaseValue;
    BlendColor.prototype = Object.create(BaseValue && BaseValue.prototype);
    BlendColor.prototype.constructor = BlendColor;
    BlendColor.prototype.getDefault = function getDefault() {
        return performance.Color.transparent;
    };
    BlendColor.prototype.set = function set(v) {
        var c = this.current;
        if (v.r === c.r && v.g === c.g && v.b === c.b && v.a === c.a && !this.dirty) {
            return;
        }
        this.gl.blendColor(v.r, v.g, v.b, v.a);
        this.current = v;
        this.dirty = false;
    };
    return BlendColor;
}(BaseValue);
var BlendEquation = function (BaseValue) {
    function BlendEquation() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BlendEquation.__proto__ = BaseValue;
    BlendEquation.prototype = Object.create(BaseValue && BaseValue.prototype);
    BlendEquation.prototype.constructor = BlendEquation;
    BlendEquation.prototype.getDefault = function getDefault() {
        return this.gl.FUNC_ADD;
    };
    BlendEquation.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.blendEquation(v);
        this.current = v;
        this.dirty = false;
    };
    return BlendEquation;
}(BaseValue);
var CullFace = function (BaseValue) {
    function CullFace() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        CullFace.__proto__ = BaseValue;
    CullFace.prototype = Object.create(BaseValue && BaseValue.prototype);
    CullFace.prototype.constructor = CullFace;
    CullFace.prototype.getDefault = function getDefault() {
        return false;
    };
    CullFace.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        if (v) {
            gl.enable(gl.CULL_FACE);
        } else {
            gl.disable(gl.CULL_FACE);
        }
        this.current = v;
        this.dirty = false;
    };
    return CullFace;
}(BaseValue);
var CullFaceSide = function (BaseValue) {
    function CullFaceSide() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        CullFaceSide.__proto__ = BaseValue;
    CullFaceSide.prototype = Object.create(BaseValue && BaseValue.prototype);
    CullFaceSide.prototype.constructor = CullFaceSide;
    CullFaceSide.prototype.getDefault = function getDefault() {
        return this.gl.BACK;
    };
    CullFaceSide.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.cullFace(v);
        this.current = v;
        this.dirty = false;
    };
    return CullFaceSide;
}(BaseValue);
var FrontFace = function (BaseValue) {
    function FrontFace() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        FrontFace.__proto__ = BaseValue;
    FrontFace.prototype = Object.create(BaseValue && BaseValue.prototype);
    FrontFace.prototype.constructor = FrontFace;
    FrontFace.prototype.getDefault = function getDefault() {
        return this.gl.CCW;
    };
    FrontFace.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.frontFace(v);
        this.current = v;
        this.dirty = false;
    };
    return FrontFace;
}(BaseValue);
var Program = function (BaseValue) {
    function Program() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        Program.__proto__ = BaseValue;
    Program.prototype = Object.create(BaseValue && BaseValue.prototype);
    Program.prototype.constructor = Program;
    Program.prototype.getDefault = function getDefault() {
        return null;
    };
    Program.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.useProgram(v);
        this.current = v;
        this.dirty = false;
    };
    return Program;
}(BaseValue);
var ActiveTextureUnit = function (BaseValue) {
    function ActiveTextureUnit() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        ActiveTextureUnit.__proto__ = BaseValue;
    ActiveTextureUnit.prototype = Object.create(BaseValue && BaseValue.prototype);
    ActiveTextureUnit.prototype.constructor = ActiveTextureUnit;
    ActiveTextureUnit.prototype.getDefault = function getDefault() {
        return this.gl.TEXTURE0;
    };
    ActiveTextureUnit.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.gl.activeTexture(v);
        this.current = v;
        this.dirty = false;
    };
    return ActiveTextureUnit;
}(BaseValue);
var Viewport = function (BaseValue) {
    function Viewport() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        Viewport.__proto__ = BaseValue;
    Viewport.prototype = Object.create(BaseValue && BaseValue.prototype);
    Viewport.prototype.constructor = Viewport;
    Viewport.prototype.getDefault = function getDefault() {
        var gl = this.gl;
        return [
            0,
            0,
            gl.drawingBufferWidth,
            gl.drawingBufferHeight
        ];
    };
    Viewport.prototype.set = function set(v) {
        var c = this.current;
        if (v[0] === c[0] && v[1] === c[1] && v[2] === c[2] && v[3] === c[3] && !this.dirty) {
            return;
        }
        this.gl.viewport(v[0], v[1], v[2], v[3]);
        this.current = v;
        this.dirty = false;
    };
    return Viewport;
}(BaseValue);
var BindFramebuffer = function (BaseValue) {
    function BindFramebuffer() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BindFramebuffer.__proto__ = BaseValue;
    BindFramebuffer.prototype = Object.create(BaseValue && BaseValue.prototype);
    BindFramebuffer.prototype.constructor = BindFramebuffer;
    BindFramebuffer.prototype.getDefault = function getDefault() {
        return null;
    };
    BindFramebuffer.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.bindFramebuffer(gl.FRAMEBUFFER, v);
        this.current = v;
        this.dirty = false;
    };
    return BindFramebuffer;
}(BaseValue);
var BindRenderbuffer = function (BaseValue) {
    function BindRenderbuffer() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BindRenderbuffer.__proto__ = BaseValue;
    BindRenderbuffer.prototype = Object.create(BaseValue && BaseValue.prototype);
    BindRenderbuffer.prototype.constructor = BindRenderbuffer;
    BindRenderbuffer.prototype.getDefault = function getDefault() {
        return null;
    };
    BindRenderbuffer.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.bindRenderbuffer(gl.RENDERBUFFER, v);
        this.current = v;
        this.dirty = false;
    };
    return BindRenderbuffer;
}(BaseValue);
var BindTexture = function (BaseValue) {
    function BindTexture() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BindTexture.__proto__ = BaseValue;
    BindTexture.prototype = Object.create(BaseValue && BaseValue.prototype);
    BindTexture.prototype.constructor = BindTexture;
    BindTexture.prototype.getDefault = function getDefault() {
        return null;
    };
    BindTexture.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.bindTexture(gl.TEXTURE_2D, v);
        this.current = v;
        this.dirty = false;
    };
    return BindTexture;
}(BaseValue);
var BindVertexBuffer = function (BaseValue) {
    function BindVertexBuffer() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BindVertexBuffer.__proto__ = BaseValue;
    BindVertexBuffer.prototype = Object.create(BaseValue && BaseValue.prototype);
    BindVertexBuffer.prototype.constructor = BindVertexBuffer;
    BindVertexBuffer.prototype.getDefault = function getDefault() {
        return null;
    };
    BindVertexBuffer.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.bindBuffer(gl.ARRAY_BUFFER, v);
        this.current = v;
        this.dirty = false;
    };
    return BindVertexBuffer;
}(BaseValue);
var BindElementBuffer = function (BaseValue) {
    function BindElementBuffer() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        BindElementBuffer.__proto__ = BaseValue;
    BindElementBuffer.prototype = Object.create(BaseValue && BaseValue.prototype);
    BindElementBuffer.prototype.constructor = BindElementBuffer;
    BindElementBuffer.prototype.getDefault = function getDefault() {
        return null;
    };
    BindElementBuffer.prototype.set = function set(v) {
        var gl = this.gl;
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, v);
        this.current = v;
        this.dirty = false;
    };
    return BindElementBuffer;
}(BaseValue);
var BindVertexArrayOES = function (BaseValue) {
    function BindVertexArrayOES(context) {
        BaseValue.call(this, context);
        this.vao = context.extVertexArrayObject;
    }
    if (BaseValue)
        BindVertexArrayOES.__proto__ = BaseValue;
    BindVertexArrayOES.prototype = Object.create(BaseValue && BaseValue.prototype);
    BindVertexArrayOES.prototype.constructor = BindVertexArrayOES;
    BindVertexArrayOES.prototype.getDefault = function getDefault() {
        return null;
    };
    BindVertexArrayOES.prototype.set = function set(v) {
        if (!this.vao || v === this.current && !this.dirty) {
            return;
        }
        this.vao.bindVertexArrayOES(v);
        this.current = v;
        this.dirty = false;
    };
    return BindVertexArrayOES;
}(BaseValue);
var PixelStoreUnpack = function (BaseValue) {
    function PixelStoreUnpack() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        PixelStoreUnpack.__proto__ = BaseValue;
    PixelStoreUnpack.prototype = Object.create(BaseValue && BaseValue.prototype);
    PixelStoreUnpack.prototype.constructor = PixelStoreUnpack;
    PixelStoreUnpack.prototype.getDefault = function getDefault() {
        return 4;
    };
    PixelStoreUnpack.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.pixelStorei(gl.UNPACK_ALIGNMENT, v);
        this.current = v;
        this.dirty = false;
    };
    return PixelStoreUnpack;
}(BaseValue);
var PixelStoreUnpackPremultiplyAlpha = function (BaseValue) {
    function PixelStoreUnpackPremultiplyAlpha() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        PixelStoreUnpackPremultiplyAlpha.__proto__ = BaseValue;
    PixelStoreUnpackPremultiplyAlpha.prototype = Object.create(BaseValue && BaseValue.prototype);
    PixelStoreUnpackPremultiplyAlpha.prototype.constructor = PixelStoreUnpackPremultiplyAlpha;
    PixelStoreUnpackPremultiplyAlpha.prototype.getDefault = function getDefault() {
        return false;
    };
    PixelStoreUnpackPremultiplyAlpha.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, v);
        this.current = v;
        this.dirty = false;
    };
    return PixelStoreUnpackPremultiplyAlpha;
}(BaseValue);
var PixelStoreUnpackFlipY = function (BaseValue) {
    function PixelStoreUnpackFlipY() {
        BaseValue.apply(this, arguments);
    }
    if (BaseValue)
        PixelStoreUnpackFlipY.__proto__ = BaseValue;
    PixelStoreUnpackFlipY.prototype = Object.create(BaseValue && BaseValue.prototype);
    PixelStoreUnpackFlipY.prototype.constructor = PixelStoreUnpackFlipY;
    PixelStoreUnpackFlipY.prototype.getDefault = function getDefault() {
        return false;
    };
    PixelStoreUnpackFlipY.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        var gl = this.gl;
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, v);
        this.current = v;
        this.dirty = false;
    };
    return PixelStoreUnpackFlipY;
}(BaseValue);
var FramebufferAttachment = function (BaseValue) {
    function FramebufferAttachment(context, parent) {
        BaseValue.call(this, context);
        this.context = context;
        this.parent = parent;
    }
    if (BaseValue)
        FramebufferAttachment.__proto__ = BaseValue;
    FramebufferAttachment.prototype = Object.create(BaseValue && BaseValue.prototype);
    FramebufferAttachment.prototype.constructor = FramebufferAttachment;
    FramebufferAttachment.prototype.getDefault = function getDefault() {
        return null;
    };
    return FramebufferAttachment;
}(BaseValue);
var ColorAttachment = function (FramebufferAttachment) {
    function ColorAttachment() {
        FramebufferAttachment.apply(this, arguments);
    }
    if (FramebufferAttachment)
        ColorAttachment.__proto__ = FramebufferAttachment;
    ColorAttachment.prototype = Object.create(FramebufferAttachment && FramebufferAttachment.prototype);
    ColorAttachment.prototype.constructor = ColorAttachment;
    ColorAttachment.prototype.setDirty = function setDirty() {
        this.dirty = true;
    };
    ColorAttachment.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.context.bindFramebuffer.set(this.parent);
        var gl = this.gl;
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, v, 0);
        this.current = v;
        this.dirty = false;
    };
    return ColorAttachment;
}(FramebufferAttachment);
var DepthAttachment = function (FramebufferAttachment) {
    function DepthAttachment() {
        FramebufferAttachment.apply(this, arguments);
    }
    if (FramebufferAttachment)
        DepthAttachment.__proto__ = FramebufferAttachment;
    DepthAttachment.prototype = Object.create(FramebufferAttachment && FramebufferAttachment.prototype);
    DepthAttachment.prototype.constructor = DepthAttachment;
    DepthAttachment.prototype.set = function set(v) {
        if (v === this.current && !this.dirty) {
            return;
        }
        this.context.bindFramebuffer.set(this.parent);
        var gl = this.gl;
        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, v);
        this.current = v;
        this.dirty = false;
    };
    return DepthAttachment;
}(FramebufferAttachment);

var Framebuffer = function Framebuffer(context, width, height, hasDepth) {
    this.context = context;
    this.width = width;
    this.height = height;
    var gl = context.gl;
    var fbo = this.framebuffer = gl.createFramebuffer();
    this.colorAttachment = new ColorAttachment(context, fbo);
    if (hasDepth) {
        this.depthAttachment = new DepthAttachment(context, fbo);
    }
};
Framebuffer.prototype.destroy = function destroy() {
    var gl = this.context.gl;
    var texture = this.colorAttachment.get();
    if (texture) {
        gl.deleteTexture(texture);
    }
    if (this.depthAttachment) {
        var renderbuffer = this.depthAttachment.get();
        if (renderbuffer) {
            gl.deleteRenderbuffer(renderbuffer);
        }
    }
    gl.deleteFramebuffer(this.framebuffer);
};

var ALWAYS = 519;
var DepthMode = function DepthMode(depthFunc, depthMask, depthRange) {
    this.func = depthFunc;
    this.mask = depthMask;
    this.range = depthRange;
};
DepthMode.ReadOnly = false;
DepthMode.ReadWrite = true;
DepthMode.disabled = new DepthMode(ALWAYS, DepthMode.ReadOnly, [
    0,
    1
]);

var ALWAYS$1 = 519;
var KEEP = 7680;
var StencilMode = function StencilMode(test, ref, mask, fail, depthFail, pass) {
    this.test = test;
    this.ref = ref;
    this.mask = mask;
    this.fail = fail;
    this.depthFail = depthFail;
    this.pass = pass;
};
StencilMode.disabled = new StencilMode({
    func: ALWAYS$1,
    mask: 0
}, 0, 0, KEEP, KEEP, KEEP);

var ZERO = 0;
var ONE = 1;
var ONE_MINUS_SRC_ALPHA = 771;
var ColorMode = function ColorMode(blendFunction, blendColor, mask) {
    this.blendFunction = blendFunction;
    this.blendColor = blendColor;
    this.mask = mask;
};
ColorMode.Replace = [
    ONE,
    ZERO
];
ColorMode.disabled = new ColorMode(ColorMode.Replace, performance.Color.transparent, [
    false,
    false,
    false,
    false
]);
ColorMode.unblended = new ColorMode(ColorMode.Replace, performance.Color.transparent, [
    true,
    true,
    true,
    true
]);
ColorMode.alphaBlended = new ColorMode([
    ONE,
    ONE_MINUS_SRC_ALPHA
], performance.Color.transparent, [
    true,
    true,
    true,
    true
]);

var BACK = 1029;
var CCW = 2305;
var CullFaceMode = function CullFaceMode(enable, mode, frontFace) {
    this.enable = enable;
    this.mode = mode;
    this.frontFace = frontFace;
};
CullFaceMode.disabled = new CullFaceMode(false, BACK, CCW);
CullFaceMode.backCCW = new CullFaceMode(true, BACK, CCW);

var Context = function Context(gl) {
    this.gl = gl;
    this.extVertexArrayObject = this.gl.getExtension('OES_vertex_array_object');
    this.clearColor = new ClearColor(this);
    this.clearDepth = new ClearDepth(this);
    this.clearStencil = new ClearStencil(this);
    this.colorMask = new ColorMask(this);
    this.depthMask = new DepthMask(this);
    this.stencilMask = new StencilMask(this);
    this.stencilFunc = new StencilFunc(this);
    this.stencilOp = new StencilOp(this);
    this.stencilTest = new StencilTest(this);
    this.depthRange = new DepthRange(this);
    this.depthTest = new DepthTest(this);
    this.depthFunc = new DepthFunc(this);
    this.blend = new Blend(this);
    this.blendFunc = new BlendFunc(this);
    this.blendColor = new BlendColor(this);
    this.blendEquation = new BlendEquation(this);
    this.cullFace = new CullFace(this);
    this.cullFaceSide = new CullFaceSide(this);
    this.frontFace = new FrontFace(this);
    this.program = new Program(this);
    this.activeTexture = new ActiveTextureUnit(this);
    this.viewport = new Viewport(this);
    this.bindFramebuffer = new BindFramebuffer(this);
    this.bindRenderbuffer = new BindRenderbuffer(this);
    this.bindTexture = new BindTexture(this);
    this.bindVertexBuffer = new BindVertexBuffer(this);
    this.bindElementBuffer = new BindElementBuffer(this);
    this.bindVertexArrayOES = this.extVertexArrayObject && new BindVertexArrayOES(this);
    this.pixelStoreUnpack = new PixelStoreUnpack(this);
    this.pixelStoreUnpackPremultiplyAlpha = new PixelStoreUnpackPremultiplyAlpha(this);
    this.pixelStoreUnpackFlipY = new PixelStoreUnpackFlipY(this);
    this.extTextureFilterAnisotropic = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
    if (this.extTextureFilterAnisotropic) {
        this.extTextureFilterAnisotropicMax = gl.getParameter(this.extTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
    }
    this.extTextureHalfFloat = gl.getExtension('OES_texture_half_float');
    if (this.extTextureHalfFloat) {
        gl.getExtension('OES_texture_half_float_linear');
        this.extRenderToTextureHalfFloat = gl.getExtension('EXT_color_buffer_half_float');
    }
    this.extTimerQuery = gl.getExtension('EXT_disjoint_timer_query');
    this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
};
Context.prototype.setDefault = function setDefault() {
    this.unbindVAO();
    this.clearColor.setDefault();
    this.clearDepth.setDefault();
    this.clearStencil.setDefault();
    this.colorMask.setDefault();
    this.depthMask.setDefault();
    this.stencilMask.setDefault();
    this.stencilFunc.setDefault();
    this.stencilOp.setDefault();
    this.stencilTest.setDefault();
    this.depthRange.setDefault();
    this.depthTest.setDefault();
    this.depthFunc.setDefault();
    this.blend.setDefault();
    this.blendFunc.setDefault();
    this.blendColor.setDefault();
    this.blendEquation.setDefault();
    this.cullFace.setDefault();
    this.cullFaceSide.setDefault();
    this.frontFace.setDefault();
    this.program.setDefault();
    this.activeTexture.setDefault();
    this.bindFramebuffer.setDefault();
    this.pixelStoreUnpack.setDefault();
    this.pixelStoreUnpackPremultiplyAlpha.setDefault();
    this.pixelStoreUnpackFlipY.setDefault();
};
Context.prototype.setDirty = function setDirty() {
    this.clearColor.dirty = true;
    this.clearDepth.dirty = true;
    this.clearStencil.dirty = true;
    this.colorMask.dirty = true;
    this.depthMask.dirty = true;
    this.stencilMask.dirty = true;
    this.stencilFunc.dirty = true;
    this.stencilOp.dirty = true;
    this.stencilTest.dirty = true;
    this.depthRange.dirty = true;
    this.depthTest.dirty = true;
    this.depthFunc.dirty = true;
    this.blend.dirty = true;
    this.blendFunc.dirty = true;
    this.blendColor.dirty = true;
    this.blendEquation.dirty = true;
    this.cullFace.dirty = true;
    this.cullFaceSide.dirty = true;
    this.frontFace.dirty = true;
    this.program.dirty = true;
    this.activeTexture.dirty = true;
    this.viewport.dirty = true;
    this.bindFramebuffer.dirty = true;
    this.bindRenderbuffer.dirty = true;
    this.bindTexture.dirty = true;
    this.bindVertexBuffer.dirty = true;
    this.bindElementBuffer.dirty = true;
    if (this.extVertexArrayObject) {
        this.bindVertexArrayOES.dirty = true;
    }
    this.pixelStoreUnpack.dirty = true;
    this.pixelStoreUnpackPremultiplyAlpha.dirty = true;
    this.pixelStoreUnpackFlipY.dirty = true;
};
Context.prototype.createIndexBuffer = function createIndexBuffer(array, dynamicDraw) {
    return new IndexBuffer(this, array, dynamicDraw);
};
Context.prototype.createVertexBuffer = function createVertexBuffer(array, attributes, dynamicDraw) {
    return new VertexBuffer(this, array, attributes, dynamicDraw);
};
Context.prototype.createRenderbuffer = function createRenderbuffer(storageFormat, width, height) {
    var gl = this.gl;
    var rbo = gl.createRenderbuffer();
    this.bindRenderbuffer.set(rbo);
    gl.renderbufferStorage(gl.RENDERBUFFER, storageFormat, width, height);
    this.bindRenderbuffer.set(null);
    return rbo;
};
Context.prototype.createFramebuffer = function createFramebuffer(width, height, hasDepth) {
    return new Framebuffer(this, width, height, hasDepth);
};
Context.prototype.clear = function clear(ref) {
    var color = ref.color;
    var depth = ref.depth;
    var gl = this.gl;
    var mask = 0;
    if (color) {
        mask |= gl.COLOR_BUFFER_BIT;
        this.clearColor.set(color);
        this.colorMask.set([
            true,
            true,
            true,
            true
        ]);
    }
    if (typeof depth !== 'undefined') {
        mask |= gl.DEPTH_BUFFER_BIT;
        this.depthRange.set([
            0,
            1
        ]);
        this.clearDepth.set(depth);
        this.depthMask.set(true);
    }
    gl.clear(mask);
};
Context.prototype.setCullFace = function setCullFace(cullFaceMode) {
    if (cullFaceMode.enable === false) {
        this.cullFace.set(false);
    } else {
        this.cullFace.set(true);
        this.cullFaceSide.set(cullFaceMode.mode);
        this.frontFace.set(cullFaceMode.frontFace);
    }
};
Context.prototype.setDepthMode = function setDepthMode(depthMode) {
    if (depthMode.func === this.gl.ALWAYS && !depthMode.mask) {
        this.depthTest.set(false);
    } else {
        this.depthTest.set(true);
        this.depthFunc.set(depthMode.func);
        this.depthMask.set(depthMode.mask);
        this.depthRange.set(depthMode.range);
    }
};
Context.prototype.setStencilMode = function setStencilMode(stencilMode) {
    if (stencilMode.test.func === this.gl.ALWAYS && !stencilMode.mask) {
        this.stencilTest.set(false);
    } else {
        this.stencilTest.set(true);
        this.stencilMask.set(stencilMode.mask);
        this.stencilOp.set([
            stencilMode.fail,
            stencilMode.depthFail,
            stencilMode.pass
        ]);
        this.stencilFunc.set({
            func: stencilMode.test.func,
            ref: stencilMode.ref,
            mask: stencilMode.test.mask
        });
    }
};
Context.prototype.setColorMode = function setColorMode(colorMode) {
    if (performance.deepEqual(colorMode.blendFunction, ColorMode.Replace)) {
        this.blend.set(false);
    } else {
        this.blend.set(true);
        this.blendFunc.set(colorMode.blendFunction);
        this.blendColor.set(colorMode.blendColor);
    }
    this.colorMask.set(colorMode.mask);
};
Context.prototype.unbindVAO = function unbindVAO() {
    if (this.extVertexArrayObject) {
        this.bindVertexArrayOES.set(null);
    }
};

var SourceCache = function (Evented) {
    function SourceCache(id, options, dispatcher) {
        var this$1 = this;
        Evented.call(this);
        this.id = id;
        this.dispatcher = dispatcher;
        this.on('data', function (e) {
            if (e.dataType === 'source' && e.sourceDataType === 'metadata') {
                this$1._sourceLoaded = true;
            }
            if (this$1._sourceLoaded && !this$1._paused && e.dataType === 'source' && e.sourceDataType === 'content') {
                this$1.reload();
                if (this$1.transform) {
                    this$1.update(this$1.transform);
                }
            }
        });
        this.on('error', function () {
            this$1._sourceErrored = true;
        });
        this._source = create(id, options, dispatcher, this);
        this._tiles = {};
        this._cache = new TileCache(0, this._unloadTile.bind(this));
        this._timers = {};
        this._cacheTimers = {};
        this._maxTileCacheSize = null;
        this._loadedParentTiles = {};
        this._coveredTiles = {};
        this._state = new performance.SourceFeatureState();
    }
    if (Evented)
        SourceCache.__proto__ = Evented;
    SourceCache.prototype = Object.create(Evented && Evented.prototype);
    SourceCache.prototype.constructor = SourceCache;
    SourceCache.prototype.onAdd = function onAdd(map) {
        this.map = map;
        this._maxTileCacheSize = map ? map._maxTileCacheSize : null;
        if (this._source && this._source.onAdd) {
            this._source.onAdd(map);
        }
    };
    SourceCache.prototype.onRemove = function onRemove(map) {
        if (this._source && this._source.onRemove) {
            this._source.onRemove(map);
        }
    };
    SourceCache.prototype.loaded = function loaded() {
        if (this._sourceErrored) {
            return true;
        }
        if (!this._sourceLoaded) {
            return false;
        }
        if (!this._source.loaded()) {
            return false;
        }
        for (var t in this._tiles) {
            var tile = this._tiles[t];
            if (tile.state !== 'loaded' && tile.state !== 'errored') {
                return false;
            }
        }
        return true;
    };
    SourceCache.prototype.getSource = function getSource() {
        return this._source;
    };
    SourceCache.prototype.pause = function pause() {
        this._paused = true;
    };
    SourceCache.prototype.resume = function resume() {
        if (!this._paused) {
            return;
        }
        var shouldReload = this._shouldReloadOnResume;
        this._paused = false;
        this._shouldReloadOnResume = false;
        if (shouldReload) {
            this.reload();
        }
        if (this.transform) {
            this.update(this.transform);
        }
    };
    SourceCache.prototype._loadTile = function _loadTile(tile, callback) {
        return this._source.loadTile(tile, callback);
    };
    SourceCache.prototype._unloadTile = function _unloadTile(tile) {
        if (this._source.unloadTile) {
            return this._source.unloadTile(tile, function () {
            });
        }
    };
    SourceCache.prototype._abortTile = function _abortTile(tile) {
        if (this._source.abortTile) {
            return this._source.abortTile(tile, function () {
            });
        }
    };
    SourceCache.prototype.serialize = function serialize() {
        return this._source.serialize();
    };
    SourceCache.prototype.prepare = function prepare(context) {
        if (this._source.prepare) {
            this._source.prepare();
        }
        this._state.coalesceChanges(this._tiles, this.map ? this.map.painter : null);
        for (var i in this._tiles) {
            var tile = this._tiles[i];
            tile.upload(context);
            tile.prepare(this.map.style.imageManager);
        }
    };
    SourceCache.prototype.getIds = function getIds() {
        return performance.values(this._tiles).map(function (tile) {
            return tile.tileID;
        }).sort(compareTileId).map(function (id) {
            return id.key;
        });
    };
    SourceCache.prototype.getRenderableIds = function getRenderableIds(symbolLayer) {
        var this$1 = this;
        var renderables = [];
        for (var id in this._tiles) {
            if (this._isIdRenderable(id, symbolLayer)) {
                renderables.push(this._tiles[id]);
            }
        }
        if (symbolLayer) {
            return renderables.sort(function (a_, b_) {
                var a = a_.tileID;
                var b = b_.tileID;
                var rotatedA = new performance.Point(a.canonical.x, a.canonical.y)._rotate(this$1.transform.angle);
                var rotatedB = new performance.Point(b.canonical.x, b.canonical.y)._rotate(this$1.transform.angle);
                return a.overscaledZ - b.overscaledZ || rotatedB.y - rotatedA.y || rotatedB.x - rotatedA.x;
            }).map(function (tile) {
                return tile.tileID.key;
            });
        }
        return renderables.map(function (tile) {
            return tile.tileID;
        }).sort(compareTileId).map(function (id) {
            return id.key;
        });
    };
    SourceCache.prototype.hasRenderableParent = function hasRenderableParent(tileID) {
        var parentTile = this.findLoadedParent(tileID, 0);
        if (parentTile) {
            return this._isIdRenderable(parentTile.tileID.key);
        }
        return false;
    };
    SourceCache.prototype._isIdRenderable = function _isIdRenderable(id, symbolLayer) {
        return this._tiles[id] && this._tiles[id].hasData() && !this._coveredTiles[id] && (symbolLayer || !this._tiles[id].holdingForFade());
    };
    SourceCache.prototype.reload = function reload() {
        if (this._paused) {
            this._shouldReloadOnResume = true;
            return;
        }
        this._cache.reset();
        for (var i in this._tiles) {
            if (this._tiles[i].state !== 'errored') {
                this._reloadTile(i, 'reloading');
            }
        }
    };
    SourceCache.prototype._reloadTile = function _reloadTile(id, state) {
        var tile = this._tiles[id];
        if (!tile) {
            return;
        }
        if (tile.state !== 'loading') {
            tile.state = state;
        }
        this._loadTile(tile, this._tileLoaded.bind(this, tile, id, state));
    };
    SourceCache.prototype._tileLoaded = function _tileLoaded(tile, id, previousState, err) {
        if (err) {
            tile.state = 'errored';
            if (err.status !== 404) {
                this._source.fire(new performance.ErrorEvent(err, { tile: tile }));
            } else {
                this.update(this.transform);
            }
            return;
        }
        tile.timeAdded = performance.browser.now();
        if (previousState === 'expired') {
            tile.refreshedUponExpiration = true;
        }
        this._setTileReloadTimer(id, tile);
        if (this.getSource().type === 'raster-dem' && tile.dem) {
            this._backfillDEM(tile);
        }
        this._state.initializeTileState(tile, this.map ? this.map.painter : null);
        this._source.fire(new performance.Event('data', {
            dataType: 'source',
            tile: tile,
            coord: tile.tileID
        }));
    };
    SourceCache.prototype._backfillDEM = function _backfillDEM(tile) {
        var renderables = this.getRenderableIds();
        for (var i = 0; i < renderables.length; i++) {
            var borderId = renderables[i];
            if (tile.neighboringTiles && tile.neighboringTiles[borderId]) {
                var borderTile = this.getTileByID(borderId);
                fillBorder(tile, borderTile);
                fillBorder(borderTile, tile);
            }
        }
        function fillBorder(tile, borderTile) {
            tile.needsHillshadePrepare = true;
            var dx = borderTile.tileID.canonical.x - tile.tileID.canonical.x;
            var dy = borderTile.tileID.canonical.y - tile.tileID.canonical.y;
            var dim = Math.pow(2, tile.tileID.canonical.z);
            var borderId = borderTile.tileID.key;
            if (dx === 0 && dy === 0) {
                return;
            }
            if (Math.abs(dy) > 1) {
                return;
            }
            if (Math.abs(dx) > 1) {
                if (Math.abs(dx + dim) === 1) {
                    dx += dim;
                } else if (Math.abs(dx - dim) === 1) {
                    dx -= dim;
                }
            }
            if (!borderTile.dem || !tile.dem) {
                return;
            }
            tile.dem.backfillBorder(borderTile.dem, dx, dy);
            if (tile.neighboringTiles && tile.neighboringTiles[borderId]) {
                tile.neighboringTiles[borderId].backfilled = true;
            }
        }
    };
    SourceCache.prototype.getTile = function getTile(tileID) {
        return this.getTileByID(tileID.key);
    };
    SourceCache.prototype.getTileByID = function getTileByID(id) {
        return this._tiles[id];
    };
    SourceCache.prototype._retainLoadedChildren = function _retainLoadedChildren(idealTiles, zoom, maxCoveringZoom, retain) {
        for (var id in this._tiles) {
            var tile = this._tiles[id];
            if (retain[id] || !tile.hasData() || tile.tileID.overscaledZ <= zoom || tile.tileID.overscaledZ > maxCoveringZoom) {
                continue;
            }
            var topmostLoadedID = tile.tileID;
            while (tile && tile.tileID.overscaledZ > zoom + 1) {
                var parentID = tile.tileID.scaledTo(tile.tileID.overscaledZ - 1);
                tile = this._tiles[parentID.key];
                if (tile && tile.hasData()) {
                    topmostLoadedID = parentID;
                }
            }
            var tileID = topmostLoadedID;
            while (tileID.overscaledZ > zoom) {
                tileID = tileID.scaledTo(tileID.overscaledZ - 1);
                if (idealTiles[tileID.key]) {
                    retain[topmostLoadedID.key] = topmostLoadedID;
                    break;
                }
            }
        }
    };
    SourceCache.prototype.findLoadedParent = function findLoadedParent(tileID, minCoveringZoom) {
        if (tileID.key in this._loadedParentTiles) {
            var parent = this._loadedParentTiles[tileID.key];
            if (parent && parent.tileID.overscaledZ >= minCoveringZoom) {
                return parent;
            } else {
                return null;
            }
        }
        for (var z = tileID.overscaledZ - 1; z >= minCoveringZoom; z--) {
            var parentTileID = tileID.scaledTo(z);
            var tile = this._getLoadedTile(parentTileID);
            if (tile) {
                return tile;
            }
        }
    };
    SourceCache.prototype._getLoadedTile = function _getLoadedTile(tileID) {
        var tile = this._tiles[tileID.key];
        if (tile && tile.hasData()) {
            return tile;
        }
        var cachedTile = this._cache.getByKey(tileID.wrapped().key);
        return cachedTile;
    };
    SourceCache.prototype.updateCacheSize = function updateCacheSize(transform) {
        var widthInTiles = Math.ceil(transform.width / this._source.tileSize) + 1;
        var heightInTiles = Math.ceil(transform.height / this._source.tileSize) + 1;
        var approxTilesInView = widthInTiles * heightInTiles;
        var commonZoomRange = 5;
        var viewDependentMaxSize = Math.floor(approxTilesInView * commonZoomRange);
        var maxSize = typeof this._maxTileCacheSize === 'number' ? Math.min(this._maxTileCacheSize, viewDependentMaxSize) : viewDependentMaxSize;
        this._cache.setMaxSize(maxSize);
    };
    SourceCache.prototype.handleWrapJump = function handleWrapJump(lng) {
        var prevLng = this._prevLng === undefined ? lng : this._prevLng;
        var lngDifference = lng - prevLng;
        var worldDifference = lngDifference / 360;
        var wrapDelta = Math.round(worldDifference);
        this._prevLng = lng;
        if (wrapDelta) {
            var tiles = {};
            for (var key in this._tiles) {
                var tile = this._tiles[key];
                tile.tileID = tile.tileID.unwrapTo(tile.tileID.wrap + wrapDelta);
                tiles[tile.tileID.key] = tile;
            }
            this._tiles = tiles;
            for (var id in this._timers) {
                clearTimeout(this._timers[id]);
                delete this._timers[id];
            }
            for (var id$1 in this._tiles) {
                var tile$1 = this._tiles[id$1];
                this._setTileReloadTimer(id$1, tile$1);
            }
        }
    };
    SourceCache.prototype.update = function update(transform) {
        var this$1 = this;
        this.transform = transform;
        if (!this._sourceLoaded || this._paused) {
            return;
        }
        this.updateCacheSize(transform);
        this.handleWrapJump(this.transform.center.lng);
        this._coveredTiles = {};
        var idealTileIDs;
        if (!this.used) {
            idealTileIDs = [];
        } else if (this._source.tileID) {
            idealTileIDs = transform.getVisibleUnwrappedCoordinates(this._source.tileID).map(function (unwrapped) {
                return new performance.OverscaledTileID(unwrapped.canonical.z, unwrapped.wrap, unwrapped.canonical.z, unwrapped.canonical.x, unwrapped.canonical.y);
            });
        } else {
            idealTileIDs = transform.coveringTiles({
                tileSize: this._source.tileSize,
                minzoom: this._source.minzoom,
                maxzoom: this._source.maxzoom,
                roundZoom: this._source.roundZoom,
                reparseOverscaled: this._source.reparseOverscaled
            });
            if (this._source.hasTile) {
                idealTileIDs = idealTileIDs.filter(function (coord) {
                    return this$1._source.hasTile(coord);
                });
            }
        }
        var zoom = transform.coveringZoomLevel(this._source);
        var minCoveringZoom = Math.max(zoom - SourceCache.maxOverzooming, this._source.minzoom);
        var maxCoveringZoom = Math.max(zoom + SourceCache.maxUnderzooming, this._source.minzoom);
        var retain = this._updateRetainedTiles(idealTileIDs, zoom);
        if (isRasterType(this._source.type)) {
            var parentsForFading = {};
            var fadingTiles = {};
            var ids = Object.keys(retain);
            for (var i = 0, list = ids; i < list.length; i += 1) {
                var id = list[i];
                var tileID = retain[id];
                var tile = this._tiles[id];
                if (!tile || tile.fadeEndTime && tile.fadeEndTime <= performance.browser.now()) {
                    continue;
                }
                var parentTile = this.findLoadedParent(tileID, minCoveringZoom);
                if (parentTile) {
                    this._addTile(parentTile.tileID);
                    parentsForFading[parentTile.tileID.key] = parentTile.tileID;
                }
                fadingTiles[id] = tileID;
            }
            this._retainLoadedChildren(fadingTiles, zoom, maxCoveringZoom, retain);
            for (var id$1 in parentsForFading) {
                if (!retain[id$1]) {
                    this._coveredTiles[id$1] = true;
                    retain[id$1] = parentsForFading[id$1];
                }
            }
        }
        for (var retainedId in retain) {
            this._tiles[retainedId].clearFadeHold();
        }
        var remove = performance.keysDifference(this._tiles, retain);
        for (var i$1 = 0, list$1 = remove; i$1 < list$1.length; i$1 += 1) {
            var tileID$1 = list$1[i$1];
            var tile$1 = this._tiles[tileID$1];
            if (tile$1.hasSymbolBuckets && !tile$1.holdingForFade()) {
                tile$1.setHoldDuration(this.map._fadeDuration);
            } else if (!tile$1.hasSymbolBuckets || tile$1.symbolFadeFinished()) {
                this._removeTile(tileID$1);
            }
        }
        this._updateLoadedParentTileCache();
    };
    SourceCache.prototype.releaseSymbolFadeTiles = function releaseSymbolFadeTiles() {
        for (var id in this._tiles) {
            if (this._tiles[id].holdingForFade()) {
                this._removeTile(id);
            }
        }
    };
    SourceCache.prototype._updateRetainedTiles = function _updateRetainedTiles(idealTileIDs, zoom) {
        var retain = {};
        var checked = {};
        var minCoveringZoom = Math.max(zoom - SourceCache.maxOverzooming, this._source.minzoom);
        var maxCoveringZoom = Math.max(zoom + SourceCache.maxUnderzooming, this._source.minzoom);
        var missingTiles = {};
        for (var i = 0, list = idealTileIDs; i < list.length; i += 1) {
            var tileID = list[i];
            var tile = this._addTile(tileID);
            retain[tileID.key] = tileID;
            if (tile.hasData()) {
                continue;
            }
            if (zoom < this._source.maxzoom) {
                missingTiles[tileID.key] = tileID;
            }
        }
        this._retainLoadedChildren(missingTiles, zoom, maxCoveringZoom, retain);
        for (var i$1 = 0, list$1 = idealTileIDs; i$1 < list$1.length; i$1 += 1) {
            var tileID$1 = list$1[i$1];
            var tile$1 = this._tiles[tileID$1.key];
            if (tile$1.hasData()) {
                continue;
            }
            if (zoom + 1 > this._source.maxzoom) {
                var childCoord = tileID$1.children(this._source.maxzoom)[0];
                var childTile = this.getTile(childCoord);
                if (!!childTile && childTile.hasData()) {
                    retain[childCoord.key] = childCoord;
                    continue;
                }
            } else {
                var children = tileID$1.children(this._source.maxzoom);
                if (retain[children[0].key] && retain[children[1].key] && retain[children[2].key] && retain[children[3].key]) {
                    continue;
                }
            }
            var parentWasRequested = tile$1.wasRequested();
            for (var overscaledZ = tileID$1.overscaledZ - 1; overscaledZ >= minCoveringZoom; --overscaledZ) {
                var parentId = tileID$1.scaledTo(overscaledZ);
                if (checked[parentId.key]) {
                    break;
                }
                checked[parentId.key] = true;
                tile$1 = this.getTile(parentId);
                if (!tile$1 && parentWasRequested) {
                    tile$1 = this._addTile(parentId);
                }
                if (tile$1) {
                    retain[parentId.key] = parentId;
                    parentWasRequested = tile$1.wasRequested();
                    if (tile$1.hasData()) {
                        break;
                    }
                }
            }
        }
        return retain;
    };
    SourceCache.prototype._updateLoadedParentTileCache = function _updateLoadedParentTileCache() {
        this._loadedParentTiles = {};
        for (var tileKey in this._tiles) {
            var path = [];
            var parentTile = void 0;
            var currentId = this._tiles[tileKey].tileID;
            while (currentId.overscaledZ > 0) {
                if (currentId.key in this._loadedParentTiles) {
                    parentTile = this._loadedParentTiles[currentId.key];
                    break;
                }
                path.push(currentId.key);
                var parentId = currentId.scaledTo(currentId.overscaledZ - 1);
                parentTile = this._getLoadedTile(parentId);
                if (parentTile) {
                    break;
                }
                currentId = parentId;
            }
            for (var i = 0, list = path; i < list.length; i += 1) {
                var key = list[i];
                this._loadedParentTiles[key] = parentTile;
            }
        }
    };
    SourceCache.prototype._addTile = function _addTile(tileID) {
        var tile = this._tiles[tileID.key];
        if (tile) {
            return tile;
        }
        tile = this._cache.getAndRemove(tileID);
        if (tile) {
            this._setTileReloadTimer(tileID.key, tile);
            tile.tileID = tileID;
            this._state.initializeTileState(tile, this.map ? this.map.painter : null);
            if (this._cacheTimers[tileID.key]) {
                clearTimeout(this._cacheTimers[tileID.key]);
                delete this._cacheTimers[tileID.key];
                this._setTileReloadTimer(tileID.key, tile);
            }
        }
        var cached = Boolean(tile);
        if (!cached) {
            tile = new performance.Tile(tileID, this._source.tileSize * tileID.overscaleFactor());
            this._loadTile(tile, this._tileLoaded.bind(this, tile, tileID.key, tile.state));
        }
        if (!tile) {
            return null;
        }
        tile.uses++;
        this._tiles[tileID.key] = tile;
        if (!cached) {
            this._source.fire(new performance.Event('dataloading', {
                tile: tile,
                coord: tile.tileID,
                dataType: 'source'
            }));
        }
        return tile;
    };
    SourceCache.prototype._setTileReloadTimer = function _setTileReloadTimer(id, tile) {
        var this$1 = this;
        if (id in this._timers) {
            clearTimeout(this._timers[id]);
            delete this._timers[id];
        }
        var expiryTimeout = tile.getExpiryTimeout();
        if (expiryTimeout) {
            this._timers[id] = setTimeout(function () {
                this$1._reloadTile(id, 'expired');
                delete this$1._timers[id];
            }, expiryTimeout);
        }
    };
    SourceCache.prototype._removeTile = function _removeTile(id) {
        var tile = this._tiles[id];
        if (!tile) {
            return;
        }
        tile.uses--;
        delete this._tiles[id];
        if (this._timers[id]) {
            clearTimeout(this._timers[id]);
            delete this._timers[id];
        }
        if (tile.uses > 0) {
            return;
        }
        if (tile.hasData() && tile.state !== 'reloading') {
            this._cache.add(tile.tileID, tile, tile.getExpiryTimeout());
        } else {
            tile.aborted = true;
            this._abortTile(tile);
            this._unloadTile(tile);
        }
    };
    SourceCache.prototype.clearTiles = function clearTiles() {
        this._shouldReloadOnResume = false;
        this._paused = false;
        for (var id in this._tiles) {
            this._removeTile(id);
        }
        this._cache.reset();
    };
    SourceCache.prototype.tilesIn = function tilesIn(pointQueryGeometry, maxPitchScaleFactor, has3DLayer) {
        var this$1 = this;
        var tileResults = [];
        var transform = this.transform;
        if (!transform) {
            return tileResults;
        }
        var cameraPointQueryGeometry = has3DLayer ? transform.getCameraQueryGeometry(pointQueryGeometry) : pointQueryGeometry;
        var queryGeometry = pointQueryGeometry.map(function (p) {
            return transform.pointCoordinate(p);
        });
        var cameraQueryGeometry = cameraPointQueryGeometry.map(function (p) {
            return transform.pointCoordinate(p);
        });
        var ids = this.getIds();
        var minX = Infinity;
        var minY = Infinity;
        var maxX = -Infinity;
        var maxY = -Infinity;
        for (var i$1 = 0, list = cameraQueryGeometry; i$1 < list.length; i$1 += 1) {
            var p = list[i$1];
            minX = Math.min(minX, p.x);
            minY = Math.min(minY, p.y);
            maxX = Math.max(maxX, p.x);
            maxY = Math.max(maxY, p.y);
        }
        var loop = function (i) {
            var tile = this$1._tiles[ids[i]];
            if (tile.holdingForFade()) {
                return;
            }
            var tileID = tile.tileID;
            var scale = Math.pow(2, transform.zoom - tile.tileID.overscaledZ);
            var queryPadding = maxPitchScaleFactor * tile.queryPadding * performance.EXTENT / tile.tileSize / scale;
            var tileSpaceBounds = [
                tileID.getTilePoint(new performance.MercatorCoordinate(minX, minY)),
                tileID.getTilePoint(new performance.MercatorCoordinate(maxX, maxY))
            ];
            if (tileSpaceBounds[0].x - queryPadding < performance.EXTENT && tileSpaceBounds[0].y - queryPadding < performance.EXTENT && tileSpaceBounds[1].x + queryPadding >= 0 && tileSpaceBounds[1].y + queryPadding >= 0) {
                var tileSpaceQueryGeometry = queryGeometry.map(function (c) {
                    return tileID.getTilePoint(c);
                });
                var tileSpaceCameraQueryGeometry = cameraQueryGeometry.map(function (c) {
                    return tileID.getTilePoint(c);
                });
                tileResults.push({
                    tile: tile,
                    tileID: tileID,
                    queryGeometry: tileSpaceQueryGeometry,
                    cameraQueryGeometry: tileSpaceCameraQueryGeometry,
                    scale: scale
                });
            }
        };
        for (var i = 0; i < ids.length; i++)
            loop(i);
        return tileResults;
    };
    SourceCache.prototype.getVisibleCoordinates = function getVisibleCoordinates(symbolLayer) {
        var this$1 = this;
        var coords = this.getRenderableIds(symbolLayer).map(function (id) {
            return this$1._tiles[id].tileID;
        });
        for (var i = 0, list = coords; i < list.length; i += 1) {
            var coord = list[i];
            coord.posMatrix = this.transform.calculatePosMatrix(coord.toUnwrapped());
        }
        return coords;
    };
    SourceCache.prototype.hasTransition = function hasTransition() {
        if (this._source.hasTransition()) {
            return true;
        }
        if (isRasterType(this._source.type)) {
            for (var id in this._tiles) {
                var tile = this._tiles[id];
                if (tile.fadeEndTime !== undefined && tile.fadeEndTime >= performance.browser.now()) {
                    return true;
                }
            }
        }
        return false;
    };
    SourceCache.prototype.setFeatureState = function setFeatureState(sourceLayer, featureId, state) {
        sourceLayer = sourceLayer || '_geojsonTileLayer';
        this._state.updateState(sourceLayer, featureId, state);
    };
    SourceCache.prototype.removeFeatureState = function removeFeatureState(sourceLayer, featureId, key) {
        sourceLayer = sourceLayer || '_geojsonTileLayer';
        this._state.removeFeatureState(sourceLayer, featureId, key);
    };
    SourceCache.prototype.getFeatureState = function getFeatureState(sourceLayer, featureId) {
        sourceLayer = sourceLayer || '_geojsonTileLayer';
        return this._state.getState(sourceLayer, featureId);
    };
    SourceCache.prototype.setDependencies = function setDependencies(tileKey, namespace, dependencies) {
        var tile = this._tiles[tileKey];
        if (tile) {
            tile.setDependencies(namespace, dependencies);
        }
    };
    SourceCache.prototype.reloadTilesForDependencies = function reloadTilesForDependencies(namespaces, keys) {
        for (var id in this._tiles) {
            var tile = this._tiles[id];
            if (tile.hasDependency(namespaces, keys)) {
                this._reloadTile(id, 'reloading');
            }
        }
        this._cache.filter(function (tile) {
            return !tile.hasDependency(namespaces, keys);
        });
    };
    return SourceCache;
}(performance.Evented);
SourceCache.maxOverzooming = 10;
SourceCache.maxUnderzooming = 3;
function compareTileId(a, b) {
    var aWrap = Math.abs(a.wrap * 2) - +(a.wrap < 0);
    var bWrap = Math.abs(b.wrap * 2) - +(b.wrap < 0);
    return a.overscaledZ - b.overscaledZ || bWrap - aWrap || b.canonical.y - a.canonical.y || b.canonical.x - a.canonical.x;
}
function isRasterType(type) {
    return type === 'raster' || type === 'image' || type === 'video';
}

function WebWorker () {
    return new performance.window.Worker(exported.workerUrl);
}

var PRELOAD_POOL_ID = 'mapboxgl_preloaded_worker_pool';
var WorkerPool = function WorkerPool() {
    this.active = {};
};
WorkerPool.prototype.acquire = function acquire(mapId) {
    if (!this.workers) {
        this.workers = [];
        while (this.workers.length < WorkerPool.workerCount) {
            this.workers.push(new WebWorker());
        }
    }
    this.active[mapId] = true;
    return this.workers.slice();
};
WorkerPool.prototype.release = function release(mapId) {
    delete this.active[mapId];
    if (this.numActive() === 0) {
        this.workers.forEach(function (w) {
            w.terminate();
        });
        this.workers = null;
    }
};
WorkerPool.prototype.isPreloaded = function isPreloaded() {
    return !!this.active[PRELOAD_POOL_ID];
};
WorkerPool.prototype.numActive = function numActive() {
    return Object.keys(this.active).length;
};
var availableLogicalProcessors = Math.floor(performance.browser.hardwareConcurrency / 2);
WorkerPool.workerCount = Math.max(Math.min(availableLogicalProcessors, 6), 1);

var globalWorkerPool;
function getGlobalWorkerPool() {
    if (!globalWorkerPool) {
        globalWorkerPool = new WorkerPool();
    }
    return globalWorkerPool;
}
function prewarm() {
    var workerPool = getGlobalWorkerPool();
    workerPool.acquire(PRELOAD_POOL_ID);
}
function clearPrewarmedResources() {
    var pool = globalWorkerPool;
    if (pool) {
        if (pool.isPreloaded() && pool.numActive() === 1) {
            pool.release(PRELOAD_POOL_ID);
            globalWorkerPool = null;
        } else {
            console.warn('Could not clear WebWorkers since there are active Map instances that still reference it. The pre-warmed WebWorker pool can only be cleared when all map instances have been removed with map.remove()');
        }
    }
}

function deref(layer, parent) {
    var result = {};
    for (var k in layer) {
        if (k !== 'ref') {
            result[k] = layer[k];
        }
    }
    performance.refProperties.forEach(function (k) {
        if (k in parent) {
            result[k] = parent[k];
        }
    });
    return result;
}
function derefLayers(layers) {
    layers = layers.slice();
    var map = Object.create(null);
    for (var i = 0; i < layers.length; i++) {
        map[layers[i].id] = layers[i];
    }
    for (var i$1 = 0; i$1 < layers.length; i$1++) {
        if ('ref' in layers[i$1]) {
            layers[i$1] = deref(layers[i$1], map[layers[i$1].ref]);
        }
    }
    return layers;
}

function emptyStyle() {
    var style = {};
    var version = performance.styleSpec['$version'];
    for (var styleKey in performance.styleSpec['$root']) {
        var spec = performance.styleSpec['$root'][styleKey];
        if (spec.required) {
            var value = null;
            if (styleKey === 'version') {
                value = version;
            } else {
                if (spec.type === 'array') {
                    value = [];
                } else {
                    value = {};
                }
            }
            if (value != null) {
                style[styleKey] = value;
            }
        }
    }
    return style;
}

var operations = {
    setStyle: 'setStyle',
    addLayer: 'addLayer',
    removeLayer: 'removeLayer',
    setPaintProperty: 'setPaintProperty',
    setLayoutProperty: 'setLayoutProperty',
    setFilter: 'setFilter',
    addSource: 'addSource',
    removeSource: 'removeSource',
    setGeoJSONSourceData: 'setGeoJSONSourceData',
    setLayerZoomRange: 'setLayerZoomRange',
    setLayerProperty: 'setLayerProperty',
    setCenter: 'setCenter',
    setZoom: 'setZoom',
    setBearing: 'setBearing',
    setPitch: 'setPitch',
    setSprite: 'setSprite',
    setGlyphs: 'setGlyphs',
    setTransition: 'setTransition',
    setLight: 'setLight'
};
function addSource(sourceId, after, commands) {
    commands.push({
        command: operations.addSource,
        args: [
            sourceId,
            after[sourceId]
        ]
    });
}
function removeSource(sourceId, commands, sourcesRemoved) {
    commands.push({
        command: operations.removeSource,
        args: [sourceId]
    });
    sourcesRemoved[sourceId] = true;
}
function updateSource(sourceId, after, commands, sourcesRemoved) {
    removeSource(sourceId, commands, sourcesRemoved);
    addSource(sourceId, after, commands);
}
function canUpdateGeoJSON(before, after, sourceId) {
    var prop;
    for (prop in before[sourceId]) {
        if (!before[sourceId].hasOwnProperty(prop)) {
            continue;
        }
        if (prop !== 'data' && !performance.deepEqual(before[sourceId][prop], after[sourceId][prop])) {
            return false;
        }
    }
    for (prop in after[sourceId]) {
        if (!after[sourceId].hasOwnProperty(prop)) {
            continue;
        }
        if (prop !== 'data' && !performance.deepEqual(before[sourceId][prop], after[sourceId][prop])) {
            return false;
        }
    }
    return true;
}
function diffSources(before, after, commands, sourcesRemoved) {
    before = before || {};
    after = after || {};
    var sourceId;
    for (sourceId in before) {
        if (!before.hasOwnProperty(sourceId)) {
            continue;
        }
        if (!after.hasOwnProperty(sourceId)) {
            removeSource(sourceId, commands, sourcesRemoved);
        }
    }
    for (sourceId in after) {
        if (!after.hasOwnProperty(sourceId)) {
            continue;
        }
        if (!before.hasOwnProperty(sourceId)) {
            addSource(sourceId, after, commands);
        } else if (!performance.deepEqual(before[sourceId], after[sourceId])) {
            if (before[sourceId].type === 'geojson' && after[sourceId].type === 'geojson' && canUpdateGeoJSON(before, after, sourceId)) {
                commands.push({
                    command: operations.setGeoJSONSourceData,
                    args: [
                        sourceId,
                        after[sourceId].data
                    ]
                });
            } else {
                updateSource(sourceId, after, commands, sourcesRemoved);
            }
        }
    }
}
function diffLayerPropertyChanges(before, after, commands, layerId, klass, command) {
    before = before || {};
    after = after || {};
    var prop;
    for (prop in before) {
        if (!before.hasOwnProperty(prop)) {
            continue;
        }
        if (!performance.deepEqual(before[prop], after[prop])) {
            commands.push({
                command: command,
                args: [
                    layerId,
                    prop,
                    after[prop],
                    klass
                ]
            });
        }
    }
    for (prop in after) {
        if (!after.hasOwnProperty(prop) || before.hasOwnProperty(prop)) {
            continue;
        }
        if (!performance.deepEqual(before[prop], after[prop])) {
            commands.push({
                command: command,
                args: [
                    layerId,
                    prop,
                    after[prop],
                    klass
                ]
            });
        }
    }
}
function pluckId(layer) {
    return layer.id;
}
function indexById(group, layer) {
    group[layer.id] = layer;
    return group;
}
function diffLayers(before, after, commands) {
    before = before || [];
    after = after || [];
    var beforeOrder = before.map(pluckId);
    var afterOrder = after.map(pluckId);
    var beforeIndex = before.reduce(indexById, {});
    var afterIndex = after.reduce(indexById, {});
    var tracker = beforeOrder.slice();
    var clean = Object.create(null);
    var i, d, layerId, beforeLayer, afterLayer, insertBeforeLayerId, prop;
    for (i = 0, d = 0; i < beforeOrder.length; i++) {
        layerId = beforeOrder[i];
        if (!afterIndex.hasOwnProperty(layerId)) {
            commands.push({
                command: operations.removeLayer,
                args: [layerId]
            });
            tracker.splice(tracker.indexOf(layerId, d), 1);
        } else {
            d++;
        }
    }
    for (i = 0, d = 0; i < afterOrder.length; i++) {
        layerId = afterOrder[afterOrder.length - 1 - i];
        if (tracker[tracker.length - 1 - i] === layerId) {
            continue;
        }
        if (beforeIndex.hasOwnProperty(layerId)) {
            commands.push({
                command: operations.removeLayer,
                args: [layerId]
            });
            tracker.splice(tracker.lastIndexOf(layerId, tracker.length - d), 1);
        } else {
            d++;
        }
        insertBeforeLayerId = tracker[tracker.length - i];
        commands.push({
            command: operations.addLayer,
            args: [
                afterIndex[layerId],
                insertBeforeLayerId
            ]
        });
        tracker.splice(tracker.length - i, 0, layerId);
        clean[layerId] = true;
    }
    for (i = 0; i < afterOrder.length; i++) {
        layerId = afterOrder[i];
        beforeLayer = beforeIndex[layerId];
        afterLayer = afterIndex[layerId];
        if (clean[layerId] || performance.deepEqual(beforeLayer, afterLayer)) {
            continue;
        }
        if (!performance.deepEqual(beforeLayer.source, afterLayer.source) || !performance.deepEqual(beforeLayer['source-layer'], afterLayer['source-layer']) || !performance.deepEqual(beforeLayer.type, afterLayer.type)) {
            commands.push({
                command: operations.removeLayer,
                args: [layerId]
            });
            insertBeforeLayerId = tracker[tracker.lastIndexOf(layerId) + 1];
            commands.push({
                command: operations.addLayer,
                args: [
                    afterLayer,
                    insertBeforeLayerId
                ]
            });
            continue;
        }
        diffLayerPropertyChanges(beforeLayer.layout, afterLayer.layout, commands, layerId, null, operations.setLayoutProperty);
        diffLayerPropertyChanges(beforeLayer.paint, afterLayer.paint, commands, layerId, null, operations.setPaintProperty);
        if (!performance.deepEqual(beforeLayer.filter, afterLayer.filter)) {
            commands.push({
                command: operations.setFilter,
                args: [
                    layerId,
                    afterLayer.filter
                ]
            });
        }
        if (!performance.deepEqual(beforeLayer.minzoom, afterLayer.minzoom) || !performance.deepEqual(beforeLayer.maxzoom, afterLayer.maxzoom)) {
            commands.push({
                command: operations.setLayerZoomRange,
                args: [
                    layerId,
                    afterLayer.minzoom,
                    afterLayer.maxzoom
                ]
            });
        }
        for (prop in beforeLayer) {
            if (!beforeLayer.hasOwnProperty(prop)) {
                continue;
            }
            if (prop === 'layout' || prop === 'paint' || prop === 'filter' || prop === 'metadata' || prop === 'minzoom' || prop === 'maxzoom') {
                continue;
            }
            if (prop.indexOf('paint.') === 0) {
                diffLayerPropertyChanges(beforeLayer[prop], afterLayer[prop], commands, layerId, prop.slice(6), operations.setPaintProperty);
            } else if (!performance.deepEqual(beforeLayer[prop], afterLayer[prop])) {
                commands.push({
                    command: operations.setLayerProperty,
                    args: [
                        layerId,
                        prop,
                        afterLayer[prop]
                    ]
                });
            }
        }
        for (prop in afterLayer) {
            if (!afterLayer.hasOwnProperty(prop) || beforeLayer.hasOwnProperty(prop)) {
                continue;
            }
            if (prop === 'layout' || prop === 'paint' || prop === 'filter' || prop === 'metadata' || prop === 'minzoom' || prop === 'maxzoom') {
                continue;
            }
            if (prop.indexOf('paint.') === 0) {
                diffLayerPropertyChanges(beforeLayer[prop], afterLayer[prop], commands, layerId, prop.slice(6), operations.setPaintProperty);
            } else if (!performance.deepEqual(beforeLayer[prop], afterLayer[prop])) {
                commands.push({
                    command: operations.setLayerProperty,
                    args: [
                        layerId,
                        prop,
                        afterLayer[prop]
                    ]
                });
            }
        }
    }
}
function diffStyles(before, after) {
    if (!before) {
        return [{
                command: operations.setStyle,
                args: [after]
            }];
    }
    var commands = [];
    try {
        if (!performance.deepEqual(before.version, after.version)) {
            return [{
                    command: operations.setStyle,
                    args: [after]
                }];
        }
        if (!performance.deepEqual(before.center, after.center)) {
            commands.push({
                command: operations.setCenter,
                args: [after.center]
            });
        }
        if (!performance.deepEqual(before.zoom, after.zoom)) {
            commands.push({
                command: operations.setZoom,
                args: [after.zoom]
            });
        }
        if (!performance.deepEqual(before.bearing, after.bearing)) {
            commands.push({
                command: operations.setBearing,
                args: [after.bearing]
            });
        }
        if (!performance.deepEqual(before.pitch, after.pitch)) {
            commands.push({
                command: operations.setPitch,
                args: [after.pitch]
            });
        }
        if (!performance.deepEqual(before.sprite, after.sprite)) {
            commands.push({
                command: operations.setSprite,
                args: [after.sprite]
            });
        }
        if (!performance.deepEqual(before.glyphs, after.glyphs)) {
            commands.push({
                command: operations.setGlyphs,
                args: [after.glyphs]
            });
        }
        if (!performance.deepEqual(before.transition, after.transition)) {
            commands.push({
                command: operations.setTransition,
                args: [after.transition]
            });
        }
        if (!performance.deepEqual(before.light, after.light)) {
            commands.push({
                command: operations.setLight,
                args: [after.light]
            });
        }
        var sourcesRemoved = {};
        var removeOrAddSourceCommands = [];
        diffSources(before.sources, after.sources, removeOrAddSourceCommands, sourcesRemoved);
        var beforeLayers = [];
        if (before.layers) {
            before.layers.forEach(function (layer) {
                if (sourcesRemoved[layer.source]) {
                    commands.push({
                        command: operations.removeLayer,
                        args: [layer.id]
                    });
                } else {
                    beforeLayers.push(layer);
                }
            });
        }
        commands = commands.concat(removeOrAddSourceCommands);
        diffLayers(beforeLayers, after.layers, commands);
    } catch (e) {
        console.warn('Unable to compute style diff:', e);
        commands = [{
                command: operations.setStyle,
                args: [after]
            }];
    }
    return commands;
}

var PathInterpolator = function PathInterpolator(points_, padding_) {
    this.reset(points_, padding_);
};
PathInterpolator.prototype.reset = function reset(points_, padding_) {
    this.points = points_ || [];
    this._distances = [0];
    for (var i = 1; i < this.points.length; i++) {
        this._distances[i] = this._distances[i - 1] + this.points[i].dist(this.points[i - 1]);
    }
    this.length = this._distances[this._distances.length - 1];
    this.padding = Math.min(padding_ || 0, this.length * 0.5);
    this.paddedLength = this.length - this.padding * 2;
};
PathInterpolator.prototype.lerp = function lerp(t) {
    if (this.points.length === 1) {
        return this.points[0];
    }
    t = performance.clamp(t, 0, 1);
    var currentIndex = 1;
    var distOfCurrentIdx = this._distances[currentIndex];
    var distToTarget = t * this.paddedLength + this.padding;
    while (distOfCurrentIdx < distToTarget && currentIndex < this._distances.length) {
        distOfCurrentIdx = this._distances[++currentIndex];
    }
    var idxOfPrevPoint = currentIndex - 1;
    var distOfPrevIdx = this._distances[idxOfPrevPoint];
    var segmentLength = distOfCurrentIdx - distOfPrevIdx;
    var segmentT = segmentLength > 0 ? (distToTarget - distOfPrevIdx) / segmentLength : 0;
    return this.points[idxOfPrevPoint].mult(1 - segmentT).add(this.points[currentIndex].mult(segmentT));
};

var GridIndex = function GridIndex(width, height, cellSize) {
    var boxCells = this.boxCells = [];
    var circleCells = this.circleCells = [];
    this.xCellCount = Math.ceil(width / cellSize);
    this.yCellCount = Math.ceil(height / cellSize);
    for (var i = 0; i < this.xCellCount * this.yCellCount; i++) {
        boxCells.push([]);
        circleCells.push([]);
    }
    this.circleKeys = [];
    this.boxKeys = [];
    this.bboxes = [];
    this.circles = [];
    this.width = width;
    this.height = height;
    this.xScale = this.xCellCount / width;
    this.yScale = this.yCellCount / height;
    this.boxUid = 0;
    this.circleUid = 0;
};
GridIndex.prototype.keysLength = function keysLength() {
    return this.boxKeys.length + this.circleKeys.length;
};
GridIndex.prototype.insert = function insert(key, x1, y1, x2, y2) {
    this._forEachCell(x1, y1, x2, y2, this._insertBoxCell, this.boxUid++);
    this.boxKeys.push(key);
    this.bboxes.push(x1);
    this.bboxes.push(y1);
    this.bboxes.push(x2);
    this.bboxes.push(y2);
};
GridIndex.prototype.insertCircle = function insertCircle(key, x, y, radius) {
    this._forEachCell(x - radius, y - radius, x + radius, y + radius, this._insertCircleCell, this.circleUid++);
    this.circleKeys.push(key);
    this.circles.push(x);
    this.circles.push(y);
    this.circles.push(radius);
};
GridIndex.prototype._insertBoxCell = function _insertBoxCell(x1, y1, x2, y2, cellIndex, uid) {
    this.boxCells[cellIndex].push(uid);
};
GridIndex.prototype._insertCircleCell = function _insertCircleCell(x1, y1, x2, y2, cellIndex, uid) {
    this.circleCells[cellIndex].push(uid);
};
GridIndex.prototype._query = function _query(x1, y1, x2, y2, hitTest, predicate) {
    if (x2 < 0 || x1 > this.width || y2 < 0 || y1 > this.height) {
        return hitTest ? false : [];
    }
    var result = [];
    if (x1 <= 0 && y1 <= 0 && this.width <= x2 && this.height <= y2) {
        if (hitTest) {
            return true;
        }
        for (var boxUid = 0; boxUid < this.boxKeys.length; boxUid++) {
            result.push({
                key: this.boxKeys[boxUid],
                x1: this.bboxes[boxUid * 4],
                y1: this.bboxes[boxUid * 4 + 1],
                x2: this.bboxes[boxUid * 4 + 2],
                y2: this.bboxes[boxUid * 4 + 3]
            });
        }
        for (var circleUid = 0; circleUid < this.circleKeys.length; circleUid++) {
            var x = this.circles[circleUid * 3];
            var y = this.circles[circleUid * 3 + 1];
            var radius = this.circles[circleUid * 3 + 2];
            result.push({
                key: this.circleKeys[circleUid],
                x1: x - radius,
                y1: y - radius,
                x2: x + radius,
                y2: y + radius
            });
        }
        return predicate ? result.filter(predicate) : result;
    } else {
        var queryArgs = {
            hitTest: hitTest,
            seenUids: {
                box: {},
                circle: {}
            }
        };
        this._forEachCell(x1, y1, x2, y2, this._queryCell, result, queryArgs, predicate);
        return hitTest ? result.length > 0 : result;
    }
};
GridIndex.prototype._queryCircle = function _queryCircle(x, y, radius, hitTest, predicate) {
    var x1 = x - radius;
    var x2 = x + radius;
    var y1 = y - radius;
    var y2 = y + radius;
    if (x2 < 0 || x1 > this.width || y2 < 0 || y1 > this.height) {
        return hitTest ? false : [];
    }
    var result = [];
    var queryArgs = {
        hitTest: hitTest,
        circle: {
            x: x,
            y: y,
            radius: radius
        },
        seenUids: {
            box: {},
            circle: {}
        }
    };
    this._forEachCell(x1, y1, x2, y2, this._queryCellCircle, result, queryArgs, predicate);
    return hitTest ? result.length > 0 : result;
};
GridIndex.prototype.query = function query(x1, y1, x2, y2, predicate) {
    return this._query(x1, y1, x2, y2, false, predicate);
};
GridIndex.prototype.hitTest = function hitTest(x1, y1, x2, y2, predicate) {
    return this._query(x1, y1, x2, y2, true, predicate);
};
GridIndex.prototype.hitTestCircle = function hitTestCircle(x, y, radius, predicate) {
    return this._queryCircle(x, y, radius, true, predicate);
};
GridIndex.prototype._queryCell = function _queryCell(x1, y1, x2, y2, cellIndex, result, queryArgs, predicate) {
    var seenUids = queryArgs.seenUids;
    var boxCell = this.boxCells[cellIndex];
    if (boxCell !== null) {
        var bboxes = this.bboxes;
        for (var i = 0, list = boxCell; i < list.length; i += 1) {
            var boxUid = list[i];
            if (!seenUids.box[boxUid]) {
                seenUids.box[boxUid] = true;
                var offset = boxUid * 4;
                if (x1 <= bboxes[offset + 2] && y1 <= bboxes[offset + 3] && x2 >= bboxes[offset + 0] && y2 >= bboxes[offset + 1] && (!predicate || predicate(this.boxKeys[boxUid]))) {
                    if (queryArgs.hitTest) {
                        result.push(true);
                        return true;
                    } else {
                        result.push({
                            key: this.boxKeys[boxUid],
                            x1: bboxes[offset],
                            y1: bboxes[offset + 1],
                            x2: bboxes[offset + 2],
                            y2: bboxes[offset + 3]
                        });
                    }
                }
            }
        }
    }
    var circleCell = this.circleCells[cellIndex];
    if (circleCell !== null) {
        var circles = this.circles;
        for (var i$1 = 0, list$1 = circleCell; i$1 < list$1.length; i$1 += 1) {
            var circleUid = list$1[i$1];
            if (!seenUids.circle[circleUid]) {
                seenUids.circle[circleUid] = true;
                var offset$1 = circleUid * 3;
                if (this._circleAndRectCollide(circles[offset$1], circles[offset$1 + 1], circles[offset$1 + 2], x1, y1, x2, y2) && (!predicate || predicate(this.circleKeys[circleUid]))) {
                    if (queryArgs.hitTest) {
                        result.push(true);
                        return true;
                    } else {
                        var x = circles[offset$1];
                        var y = circles[offset$1 + 1];
                        var radius = circles[offset$1 + 2];
                        result.push({
                            key: this.circleKeys[circleUid],
                            x1: x - radius,
                            y1: y - radius,
                            x2: x + radius,
                            y2: y + radius
                        });
                    }
                }
            }
        }
    }
};
GridIndex.prototype._queryCellCircle = function _queryCellCircle(x1, y1, x2, y2, cellIndex, result, queryArgs, predicate) {
    var circle = queryArgs.circle;
    var seenUids = queryArgs.seenUids;
    var boxCell = this.boxCells[cellIndex];
    if (boxCell !== null) {
        var bboxes = this.bboxes;
        for (var i = 0, list = boxCell; i < list.length; i += 1) {
            var boxUid = list[i];
            if (!seenUids.box[boxUid]) {
                seenUids.box[boxUid] = true;
                var offset = boxUid * 4;
                if (this._circleAndRectCollide(circle.x, circle.y, circle.radius, bboxes[offset + 0], bboxes[offset + 1], bboxes[offset + 2], bboxes[offset + 3]) && (!predicate || predicate(this.boxKeys[boxUid]))) {
                    result.push(true);
                    return true;
                }
            }
        }
    }
    var circleCell = this.circleCells[cellIndex];
    if (circleCell !== null) {
        var circles = this.circles;
        for (var i$1 = 0, list$1 = circleCell; i$1 < list$1.length; i$1 += 1) {
            var circleUid = list$1[i$1];
            if (!seenUids.circle[circleUid]) {
                seenUids.circle[circleUid] = true;
                var offset$1 = circleUid * 3;
                if (this._circlesCollide(circles[offset$1], circles[offset$1 + 1], circles[offset$1 + 2], circle.x, circle.y, circle.radius) && (!predicate || predicate(this.circleKeys[circleUid]))) {
                    result.push(true);
                    return true;
                }
            }
        }
    }
};
GridIndex.prototype._forEachCell = function _forEachCell(x1, y1, x2, y2, fn, arg1, arg2, predicate) {
    var cx1 = this._convertToXCellCoord(x1);
    var cy1 = this._convertToYCellCoord(y1);
    var cx2 = this._convertToXCellCoord(x2);
    var cy2 = this._convertToYCellCoord(y2);
    for (var x = cx1; x <= cx2; x++) {
        for (var y = cy1; y <= cy2; y++) {
            var cellIndex = this.xCellCount * y + x;
            if (fn.call(this, x1, y1, x2, y2, cellIndex, arg1, arg2, predicate)) {
                return;
            }
        }
    }
};
GridIndex.prototype._convertToXCellCoord = function _convertToXCellCoord(x) {
    return Math.max(0, Math.min(this.xCellCount - 1, Math.floor(x * this.xScale)));
};
GridIndex.prototype._convertToYCellCoord = function _convertToYCellCoord(y) {
    return Math.max(0, Math.min(this.yCellCount - 1, Math.floor(y * this.yScale)));
};
GridIndex.prototype._circlesCollide = function _circlesCollide(x1, y1, r1, x2, y2, r2) {
    var dx = x2 - x1;
    var dy = y2 - y1;
    var bothRadii = r1 + r2;
    return bothRadii * bothRadii > dx * dx + dy * dy;
};
GridIndex.prototype._circleAndRectCollide = function _circleAndRectCollide(circleX, circleY, radius, x1, y1, x2, y2) {
    var halfRectWidth = (x2 - x1) / 2;
    var distX = Math.abs(circleX - (x1 + halfRectWidth));
    if (distX > halfRectWidth + radius) {
        return false;
    }
    var halfRectHeight = (y2 - y1) / 2;
    var distY = Math.abs(circleY - (y1 + halfRectHeight));
    if (distY > halfRectHeight + radius) {
        return false;
    }
    if (distX <= halfRectWidth || distY <= halfRectHeight) {
        return true;
    }
    var dx = distX - halfRectWidth;
    var dy = distY - halfRectHeight;
    return dx * dx + dy * dy <= radius * radius;
};

function getLabelPlaneMatrix(posMatrix, pitchWithMap, rotateWithMap, transform, pixelsToTileUnits) {
    var m = performance.create();
    if (pitchWithMap) {
        performance.scale(m, m, [
            1 / pixelsToTileUnits,
            1 / pixelsToTileUnits,
            1
        ]);
        if (!rotateWithMap) {
            performance.rotateZ(m, m, transform.angle);
        }
    } else {
        performance.multiply(m, transform.labelPlaneMatrix, posMatrix);
    }
    return m;
}
function getGlCoordMatrix(posMatrix, pitchWithMap, rotateWithMap, transform, pixelsToTileUnits) {
    if (pitchWithMap) {
        var m = performance.clone(posMatrix);
        performance.scale(m, m, [
            pixelsToTileUnits,
            pixelsToTileUnits,
            1
        ]);
        if (!rotateWithMap) {
            performance.rotateZ(m, m, -transform.angle);
        }
        return m;
    } else {
        return transform.glCoordMatrix;
    }
}
function project(point, matrix) {
    var pos = [
        point.x,
        point.y,
        0,
        1
    ];
    xyTransformMat4(pos, pos, matrix);
    var w = pos[3];
    return {
        point: new performance.Point(pos[0] / w, pos[1] / w),
        signedDistanceFromCamera: w
    };
}
function getPerspectiveRatio(cameraToCenterDistance, signedDistanceFromCamera) {
    return 0.5 + 0.5 * (cameraToCenterDistance / signedDistanceFromCamera);
}
function isVisible(anchorPos, clippingBuffer) {
    var x = anchorPos[0] / anchorPos[3];
    var y = anchorPos[1] / anchorPos[3];
    var inPaddedViewport = x >= -clippingBuffer[0] && x <= clippingBuffer[0] && y >= -clippingBuffer[1] && y <= clippingBuffer[1];
    return inPaddedViewport;
}
function updateLineLabels(bucket, posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright) {
    var sizeData = isText ? bucket.textSizeData : bucket.iconSizeData;
    var partiallyEvaluatedSize = performance.evaluateSizeForZoom(sizeData, painter.transform.zoom);
    var clippingBuffer = [
        256 / painter.width * 2 + 1,
        256 / painter.height * 2 + 1
    ];
    var dynamicLayoutVertexArray = isText ? bucket.text.dynamicLayoutVertexArray : bucket.icon.dynamicLayoutVertexArray;
    dynamicLayoutVertexArray.clear();
    var lineVertexArray = bucket.lineVertexArray;
    var placedSymbols = isText ? bucket.text.placedSymbolArray : bucket.icon.placedSymbolArray;
    var aspectRatio = painter.transform.width / painter.transform.height;
    var useVertical = false;
    for (var s = 0; s < placedSymbols.length; s++) {
        var symbol = placedSymbols.get(s);
        if (symbol.hidden || symbol.writingMode === performance.WritingMode.vertical && !useVertical) {
            hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
            continue;
        }
        useVertical = false;
        var anchorPos = [
            symbol.anchorX,
            symbol.anchorY,
            0,
            1
        ];
        performance.transformMat4(anchorPos, anchorPos, posMatrix);
        if (!isVisible(anchorPos, clippingBuffer)) {
            hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
            continue;
        }
        var cameraToAnchorDistance = anchorPos[3];
        var perspectiveRatio = getPerspectiveRatio(painter.transform.cameraToCenterDistance, cameraToAnchorDistance);
        var fontSize = performance.evaluateSizeForFeature(sizeData, partiallyEvaluatedSize, symbol);
        var pitchScaledFontSize = pitchWithMap ? fontSize / perspectiveRatio : fontSize * perspectiveRatio;
        var tileAnchorPoint = new performance.Point(symbol.anchorX, symbol.anchorY);
        var anchorPoint = project(tileAnchorPoint, labelPlaneMatrix).point;
        var projectionCache = {};
        var placeUnflipped = placeGlyphsAlongLine(symbol, pitchScaledFontSize, false, keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, bucket.glyphOffsetArray, lineVertexArray, dynamicLayoutVertexArray, anchorPoint, tileAnchorPoint, projectionCache, aspectRatio);
        useVertical = placeUnflipped.useVertical;
        if (placeUnflipped.notEnoughRoom || useVertical || placeUnflipped.needsFlipping && placeGlyphsAlongLine(symbol, pitchScaledFontSize, true, keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, bucket.glyphOffsetArray, lineVertexArray, dynamicLayoutVertexArray, anchorPoint, tileAnchorPoint, projectionCache, aspectRatio).notEnoughRoom) {
            hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
        }
    }
    if (isText) {
        bucket.text.dynamicLayoutVertexBuffer.updateData(dynamicLayoutVertexArray);
    } else {
        bucket.icon.dynamicLayoutVertexBuffer.updateData(dynamicLayoutVertexArray);
    }
}
function placeFirstAndLastGlyph(fontScale, glyphOffsetArray, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol, lineVertexArray, labelPlaneMatrix, projectionCache) {
    var glyphEndIndex = symbol.glyphStartIndex + symbol.numGlyphs;
    var lineStartIndex = symbol.lineStartIndex;
    var lineEndIndex = symbol.lineStartIndex + symbol.lineLength;
    var firstGlyphOffset = glyphOffsetArray.getoffsetX(symbol.glyphStartIndex);
    var lastGlyphOffset = glyphOffsetArray.getoffsetX(glyphEndIndex - 1);
    var firstPlacedGlyph = placeGlyphAlongLine(fontScale * firstGlyphOffset, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol.segment, lineStartIndex, lineEndIndex, lineVertexArray, labelPlaneMatrix, projectionCache);
    if (!firstPlacedGlyph) {
        return null;
    }
    var lastPlacedGlyph = placeGlyphAlongLine(fontScale * lastGlyphOffset, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol.segment, lineStartIndex, lineEndIndex, lineVertexArray, labelPlaneMatrix, projectionCache);
    if (!lastPlacedGlyph) {
        return null;
    }
    return {
        first: firstPlacedGlyph,
        last: lastPlacedGlyph
    };
}
function requiresOrientationChange(writingMode, firstPoint, lastPoint, aspectRatio) {
    if (writingMode === performance.WritingMode.horizontal) {
        var rise = Math.abs(lastPoint.y - firstPoint.y);
        var run = Math.abs(lastPoint.x - firstPoint.x) * aspectRatio;
        if (rise > run) {
            return { useVertical: true };
        }
    }
    if (writingMode === performance.WritingMode.vertical ? firstPoint.y < lastPoint.y : firstPoint.x > lastPoint.x) {
        return { needsFlipping: true };
    }
    return null;
}
function placeGlyphsAlongLine(symbol, fontSize, flip, keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, glyphOffsetArray, lineVertexArray, dynamicLayoutVertexArray, anchorPoint, tileAnchorPoint, projectionCache, aspectRatio) {
    var fontScale = fontSize / 24;
    var lineOffsetX = symbol.lineOffsetX * fontScale;
    var lineOffsetY = symbol.lineOffsetY * fontScale;
    var placedGlyphs;
    if (symbol.numGlyphs > 1) {
        var glyphEndIndex = symbol.glyphStartIndex + symbol.numGlyphs;
        var lineStartIndex = symbol.lineStartIndex;
        var lineEndIndex = symbol.lineStartIndex + symbol.lineLength;
        var firstAndLastGlyph = placeFirstAndLastGlyph(fontScale, glyphOffsetArray, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol, lineVertexArray, labelPlaneMatrix, projectionCache);
        if (!firstAndLastGlyph) {
            return { notEnoughRoom: true };
        }
        var firstPoint = project(firstAndLastGlyph.first.point, glCoordMatrix).point;
        var lastPoint = project(firstAndLastGlyph.last.point, glCoordMatrix).point;
        if (keepUpright && !flip) {
            var orientationChange = requiresOrientationChange(symbol.writingMode, firstPoint, lastPoint, aspectRatio);
            if (orientationChange) {
                return orientationChange;
            }
        }
        placedGlyphs = [firstAndLastGlyph.first];
        for (var glyphIndex = symbol.glyphStartIndex + 1; glyphIndex < glyphEndIndex - 1; glyphIndex++) {
            placedGlyphs.push(placeGlyphAlongLine(fontScale * glyphOffsetArray.getoffsetX(glyphIndex), lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol.segment, lineStartIndex, lineEndIndex, lineVertexArray, labelPlaneMatrix, projectionCache));
        }
        placedGlyphs.push(firstAndLastGlyph.last);
    } else {
        if (keepUpright && !flip) {
            var a = project(tileAnchorPoint, posMatrix).point;
            var tileVertexIndex = symbol.lineStartIndex + symbol.segment + 1;
            var tileSegmentEnd = new performance.Point(lineVertexArray.getx(tileVertexIndex), lineVertexArray.gety(tileVertexIndex));
            var projectedVertex = project(tileSegmentEnd, posMatrix);
            var b = projectedVertex.signedDistanceFromCamera > 0 ? projectedVertex.point : projectTruncatedLineSegment(tileAnchorPoint, tileSegmentEnd, a, 1, posMatrix);
            var orientationChange$1 = requiresOrientationChange(symbol.writingMode, a, b, aspectRatio);
            if (orientationChange$1) {
                return orientationChange$1;
            }
        }
        var singleGlyph = placeGlyphAlongLine(fontScale * glyphOffsetArray.getoffsetX(symbol.glyphStartIndex), lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol.segment, symbol.lineStartIndex, symbol.lineStartIndex + symbol.lineLength, lineVertexArray, labelPlaneMatrix, projectionCache);
        if (!singleGlyph) {
            return { notEnoughRoom: true };
        }
        placedGlyphs = [singleGlyph];
    }
    for (var i = 0, list = placedGlyphs; i < list.length; i += 1) {
        var glyph = list[i];
        performance.addDynamicAttributes(dynamicLayoutVertexArray, glyph.point, glyph.angle);
    }
    return {};
}
function projectTruncatedLineSegment(previousTilePoint, currentTilePoint, previousProjectedPoint, minimumLength, projectionMatrix) {
    var projectedUnitVertex = project(previousTilePoint.add(previousTilePoint.sub(currentTilePoint)._unit()), projectionMatrix).point;
    var projectedUnitSegment = previousProjectedPoint.sub(projectedUnitVertex);
    return previousProjectedPoint.add(projectedUnitSegment._mult(minimumLength / projectedUnitSegment.mag()));
}
function placeGlyphAlongLine(offsetX, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, anchorSegment, lineStartIndex, lineEndIndex, lineVertexArray, labelPlaneMatrix, projectionCache) {
    var combinedOffsetX = flip ? offsetX - lineOffsetX : offsetX + lineOffsetX;
    var dir = combinedOffsetX > 0 ? 1 : -1;
    var angle = 0;
    if (flip) {
        dir *= -1;
        angle = Math.PI;
    }
    if (dir < 0) {
        angle += Math.PI;
    }
    var currentIndex = dir > 0 ? lineStartIndex + anchorSegment : lineStartIndex + anchorSegment + 1;
    var current = anchorPoint;
    var prev = anchorPoint;
    var distanceToPrev = 0;
    var currentSegmentDistance = 0;
    var absOffsetX = Math.abs(combinedOffsetX);
    var pathVertices = [];
    while (distanceToPrev + currentSegmentDistance <= absOffsetX) {
        currentIndex += dir;
        if (currentIndex < lineStartIndex || currentIndex >= lineEndIndex) {
            return null;
        }
        prev = current;
        pathVertices.push(current);
        current = projectionCache[currentIndex];
        if (current === undefined) {
            var currentVertex = new performance.Point(lineVertexArray.getx(currentIndex), lineVertexArray.gety(currentIndex));
            var projection = project(currentVertex, labelPlaneMatrix);
            if (projection.signedDistanceFromCamera > 0) {
                current = projectionCache[currentIndex] = projection.point;
            } else {
                var previousLineVertexIndex = currentIndex - dir;
                var previousTilePoint = distanceToPrev === 0 ? tileAnchorPoint : new performance.Point(lineVertexArray.getx(previousLineVertexIndex), lineVertexArray.gety(previousLineVertexIndex));
                current = projectTruncatedLineSegment(previousTilePoint, currentVertex, prev, absOffsetX - distanceToPrev + 1, labelPlaneMatrix);
            }
        }
        distanceToPrev += currentSegmentDistance;
        currentSegmentDistance = prev.dist(current);
    }
    var segmentInterpolationT = (absOffsetX - distanceToPrev) / currentSegmentDistance;
    var prevToCurrent = current.sub(prev);
    var p = prevToCurrent.mult(segmentInterpolationT)._add(prev);
    p._add(prevToCurrent._unit()._perp()._mult(lineOffsetY * dir));
    var segmentAngle = angle + Math.atan2(current.y - prev.y, current.x - prev.x);
    pathVertices.push(p);
    return {
        point: p,
        angle: segmentAngle,
        path: pathVertices
    };
}
var hiddenGlyphAttributes = new Float32Array([
    -Infinity,
    -Infinity,
    0,
    -Infinity,
    -Infinity,
    0,
    -Infinity,
    -Infinity,
    0,
    -Infinity,
    -Infinity,
    0
]);
function hideGlyphs(num, dynamicLayoutVertexArray) {
    for (var i = 0; i < num; i++) {
        var offset = dynamicLayoutVertexArray.length;
        dynamicLayoutVertexArray.resize(offset + 4);
        dynamicLayoutVertexArray.float32.set(hiddenGlyphAttributes, offset * 3);
    }
}
function xyTransformMat4(out, a, m) {
    var x = a[0], y = a[1];
    out[0] = m[0] * x + m[4] * y + m[12];
    out[1] = m[1] * x + m[5] * y + m[13];
    out[3] = m[3] * x + m[7] * y + m[15];
    return out;
}

var viewportPadding = 100;
var CollisionIndex = function CollisionIndex(transform, grid, ignoredGrid) {
    if (grid === void 0)
        grid = new GridIndex(transform.width + 2 * viewportPadding, transform.height + 2 * viewportPadding, 25);
    if (ignoredGrid === void 0)
        ignoredGrid = new GridIndex(transform.width + 2 * viewportPadding, transform.height + 2 * viewportPadding, 25);
    this.transform = transform;
    this.grid = grid;
    this.ignoredGrid = ignoredGrid;
    this.pitchfactor = Math.cos(transform._pitch) * transform.cameraToCenterDistance;
    this.screenRightBoundary = transform.width + viewportPadding;
    this.screenBottomBoundary = transform.height + viewportPadding;
    this.gridRightBoundary = transform.width + 2 * viewportPadding;
    this.gridBottomBoundary = transform.height + 2 * viewportPadding;
};
CollisionIndex.prototype.placeCollisionBox = function placeCollisionBox(collisionBox, allowOverlap, textPixelRatio, posMatrix, collisionGroupPredicate) {
    var projectedPoint = this.projectAndGetPerspectiveRatio(posMatrix, collisionBox.anchorPointX, collisionBox.anchorPointY);
    var tileToViewport = textPixelRatio * projectedPoint.perspectiveRatio;
    var tlX = collisionBox.x1 * tileToViewport + projectedPoint.point.x;
    var tlY = collisionBox.y1 * tileToViewport + projectedPoint.point.y;
    var brX = collisionBox.x2 * tileToViewport + projectedPoint.point.x;
    var brY = collisionBox.y2 * tileToViewport + projectedPoint.point.y;
    if (!this.isInsideGrid(tlX, tlY, brX, brY) || !allowOverlap && this.grid.hitTest(tlX, tlY, brX, brY, collisionGroupPredicate)) {
        return {
            box: [],
            offscreen: false
        };
    }
    return {
        box: [
            tlX,
            tlY,
            brX,
            brY
        ],
        offscreen: this.isOffscreen(tlX, tlY, brX, brY)
    };
};
CollisionIndex.prototype.placeCollisionCircles = function placeCollisionCircles(allowOverlap, symbol, lineVertexArray, glyphOffsetArray, fontSize, posMatrix, labelPlaneMatrix, labelToScreenMatrix, showCollisionCircles, pitchWithMap, collisionGroupPredicate, circlePixelDiameter, textPixelPadding) {
    var placedCollisionCircles = [];
    var tileUnitAnchorPoint = new performance.Point(symbol.anchorX, symbol.anchorY);
    var screenAnchorPoint = project(tileUnitAnchorPoint, posMatrix);
    var perspectiveRatio = getPerspectiveRatio(this.transform.cameraToCenterDistance, screenAnchorPoint.signedDistanceFromCamera);
    var labelPlaneFontSize = pitchWithMap ? fontSize / perspectiveRatio : fontSize * perspectiveRatio;
    var labelPlaneFontScale = labelPlaneFontSize / performance.ONE_EM;
    var labelPlaneAnchorPoint = project(tileUnitAnchorPoint, labelPlaneMatrix).point;
    var projectionCache = {};
    var lineOffsetX = symbol.lineOffsetX * labelPlaneFontScale;
    var lineOffsetY = symbol.lineOffsetY * labelPlaneFontScale;
    var firstAndLastGlyph = placeFirstAndLastGlyph(labelPlaneFontScale, glyphOffsetArray, lineOffsetX, lineOffsetY, false, labelPlaneAnchorPoint, tileUnitAnchorPoint, symbol, lineVertexArray, labelPlaneMatrix, projectionCache);
    var collisionDetected = false;
    var inGrid = false;
    var entirelyOffscreen = true;
    if (firstAndLastGlyph) {
        var radius = circlePixelDiameter * 0.5 * perspectiveRatio + textPixelPadding;
        var screenPlaneMin = new performance.Point(-viewportPadding, -viewportPadding);
        var screenPlaneMax = new performance.Point(this.screenRightBoundary, this.screenBottomBoundary);
        var interpolator = new PathInterpolator();
        var first = firstAndLastGlyph.first;
        var last = firstAndLastGlyph.last;
        var projectedPath = [];
        for (var i = first.path.length - 1; i >= 1; i--) {
            projectedPath.push(first.path[i]);
        }
        for (var i$1 = 1; i$1 < last.path.length; i$1++) {
            projectedPath.push(last.path[i$1]);
        }
        var circleDist = radius * 2.5;
        if (labelToScreenMatrix) {
            var screenSpacePath = projectedPath.map(function (p) {
                return project(p, labelToScreenMatrix);
            });
            if (screenSpacePath.some(function (point) {
                    return point.signedDistanceFromCamera <= 0;
                })) {
                projectedPath = [];
            } else {
                projectedPath = screenSpacePath.map(function (p) {
                    return p.point;
                });
            }
        }
        var segments = [];
        if (projectedPath.length > 0) {
            var minPoint = projectedPath[0].clone();
            var maxPoint = projectedPath[0].clone();
            for (var i$2 = 1; i$2 < projectedPath.length; i$2++) {
                minPoint.x = Math.min(minPoint.x, projectedPath[i$2].x);
                minPoint.y = Math.min(minPoint.y, projectedPath[i$2].y);
                maxPoint.x = Math.max(maxPoint.x, projectedPath[i$2].x);
                maxPoint.y = Math.max(maxPoint.y, projectedPath[i$2].y);
            }
            if (minPoint.x >= screenPlaneMin.x && maxPoint.x <= screenPlaneMax.x && minPoint.y >= screenPlaneMin.y && maxPoint.y <= screenPlaneMax.y) {
                segments = [projectedPath];
            } else if (maxPoint.x < screenPlaneMin.x || minPoint.x > screenPlaneMax.x || maxPoint.y < screenPlaneMin.y || minPoint.y > screenPlaneMax.y) {
                segments = [];
            } else {
                segments = performance.clipLine([projectedPath], screenPlaneMin.x, screenPlaneMin.y, screenPlaneMax.x, screenPlaneMax.y);
            }
        }
        for (var i$4 = 0, list = segments; i$4 < list.length; i$4 += 1) {
            var seg = list[i$4];
            interpolator.reset(seg, radius * 0.25);
            var numCircles = 0;
            if (interpolator.length <= 0.5 * radius) {
                numCircles = 1;
            } else {
                numCircles = Math.ceil(interpolator.paddedLength / circleDist) + 1;
            }
            for (var i$3 = 0; i$3 < numCircles; i$3++) {
                var t = i$3 / Math.max(numCircles - 1, 1);
                var circlePosition = interpolator.lerp(t);
                var centerX = circlePosition.x + viewportPadding;
                var centerY = circlePosition.y + viewportPadding;
                placedCollisionCircles.push(centerX, centerY, radius, 0);
                var x1 = centerX - radius;
                var y1 = centerY - radius;
                var x2 = centerX + radius;
                var y2 = centerY + radius;
                entirelyOffscreen = entirelyOffscreen && this.isOffscreen(x1, y1, x2, y2);
                inGrid = inGrid || this.isInsideGrid(x1, y1, x2, y2);
                if (!allowOverlap) {
                    if (this.grid.hitTestCircle(centerX, centerY, radius, collisionGroupPredicate)) {
                        collisionDetected = true;
                        if (!showCollisionCircles) {
                            return {
                                circles: [],
                                offscreen: false,
                                collisionDetected: collisionDetected
                            };
                        }
                    }
                }
            }
        }
    }
    return {
        circles: !showCollisionCircles && collisionDetected || !inGrid ? [] : placedCollisionCircles,
        offscreen: entirelyOffscreen,
        collisionDetected: collisionDetected
    };
};
CollisionIndex.prototype.queryRenderedSymbols = function queryRenderedSymbols(viewportQueryGeometry) {
    if (viewportQueryGeometry.length === 0 || this.grid.keysLength() === 0 && this.ignoredGrid.keysLength() === 0) {
        return {};
    }
    var query = [];
    var minX = Infinity;
    var minY = Infinity;
    var maxX = -Infinity;
    var maxY = -Infinity;
    for (var i = 0, list = viewportQueryGeometry; i < list.length; i += 1) {
        var point = list[i];
        var gridPoint = new performance.Point(point.x + viewportPadding, point.y + viewportPadding);
        minX = Math.min(minX, gridPoint.x);
        minY = Math.min(minY, gridPoint.y);
        maxX = Math.max(maxX, gridPoint.x);
        maxY = Math.max(maxY, gridPoint.y);
        query.push(gridPoint);
    }
    var features = this.grid.query(minX, minY, maxX, maxY).concat(this.ignoredGrid.query(minX, minY, maxX, maxY));
    var seenFeatures = {};
    var result = {};
    for (var i$1 = 0, list$1 = features; i$1 < list$1.length; i$1 += 1) {
        var feature = list$1[i$1];
        var featureKey = feature.key;
        if (seenFeatures[featureKey.bucketInstanceId] === undefined) {
            seenFeatures[featureKey.bucketInstanceId] = {};
        }
        if (seenFeatures[featureKey.bucketInstanceId][featureKey.featureIndex]) {
            continue;
        }
        var bbox = [
            new performance.Point(feature.x1, feature.y1),
            new performance.Point(feature.x2, feature.y1),
            new performance.Point(feature.x2, feature.y2),
            new performance.Point(feature.x1, feature.y2)
        ];
        if (!performance.polygonIntersectsPolygon(query, bbox)) {
            continue;
        }
        seenFeatures[featureKey.bucketInstanceId][featureKey.featureIndex] = true;
        if (result[featureKey.bucketInstanceId] === undefined) {
            result[featureKey.bucketInstanceId] = [];
        }
        result[featureKey.bucketInstanceId].push(featureKey.featureIndex);
    }
    return result;
};
CollisionIndex.prototype.insertCollisionBox = function insertCollisionBox(collisionBox, ignorePlacement, bucketInstanceId, featureIndex, collisionGroupID) {
    var grid = ignorePlacement ? this.ignoredGrid : this.grid;
    var key = {
        bucketInstanceId: bucketInstanceId,
        featureIndex: featureIndex,
        collisionGroupID: collisionGroupID
    };
    grid.insert(key, collisionBox[0], collisionBox[1], collisionBox[2], collisionBox[3]);
};
CollisionIndex.prototype.insertCollisionCircles = function insertCollisionCircles(collisionCircles, ignorePlacement, bucketInstanceId, featureIndex, collisionGroupID) {
    var grid = ignorePlacement ? this.ignoredGrid : this.grid;
    var key = {
        bucketInstanceId: bucketInstanceId,
        featureIndex: featureIndex,
        collisionGroupID: collisionGroupID
    };
    for (var k = 0; k < collisionCircles.length; k += 4) {
        grid.insertCircle(key, collisionCircles[k], collisionCircles[k + 1], collisionCircles[k + 2]);
    }
};
CollisionIndex.prototype.projectAndGetPerspectiveRatio = function projectAndGetPerspectiveRatio(posMatrix, x, y) {
    var p = [
        x,
        y,
        0,
        1
    ];
    xyTransformMat4(p, p, posMatrix);
    var a = new performance.Point((p[0] / p[3] + 1) / 2 * this.transform.width + viewportPadding, (-p[1] / p[3] + 1) / 2 * this.transform.height + viewportPadding);
    return {
        point: a,
        perspectiveRatio: 0.5 + 0.5 * (this.transform.cameraToCenterDistance / p[3])
    };
};
CollisionIndex.prototype.isOffscreen = function isOffscreen(x1, y1, x2, y2) {
    return x2 < viewportPadding || x1 >= this.screenRightBoundary || y2 < viewportPadding || y1 > this.screenBottomBoundary;
};
CollisionIndex.prototype.isInsideGrid = function isInsideGrid(x1, y1, x2, y2) {
    return x2 >= 0 && x1 < this.gridRightBoundary && y2 >= 0 && y1 < this.gridBottomBoundary;
};
CollisionIndex.prototype.getViewportMatrix = function getViewportMatrix() {
    var m = performance.identity([]);
    performance.translate(m, m, [
        -viewportPadding,
        -viewportPadding,
        0
    ]);
    return m;
};

function pixelsToTileUnits (tile, pixelValue, z) {
    return pixelValue * (performance.EXTENT / (tile.tileSize * Math.pow(2, z - tile.tileID.overscaledZ)));
}

var OpacityState = function OpacityState(prevState, increment, placed, skipFade) {
    if (prevState) {
        this.opacity = Math.max(0, Math.min(1, prevState.opacity + (prevState.placed ? increment : -increment)));
    } else {
        this.opacity = skipFade && placed ? 1 : 0;
    }
    this.placed = placed;
};
OpacityState.prototype.isHidden = function isHidden() {
    return this.opacity === 0 && !this.placed;
};
var JointOpacityState = function JointOpacityState(prevState, increment, placedText, placedIcon, skipFade) {
    this.text = new OpacityState(prevState ? prevState.text : null, increment, placedText, skipFade);
    this.icon = new OpacityState(prevState ? prevState.icon : null, increment, placedIcon, skipFade);
};
JointOpacityState.prototype.isHidden = function isHidden() {
    return this.text.isHidden() && this.icon.isHidden();
};
var JointPlacement = function JointPlacement(text, icon, skipFade) {
    this.text = text;
    this.icon = icon;
    this.skipFade = skipFade;
};
var CollisionCircleArray = function CollisionCircleArray() {
    this.invProjMatrix = performance.create();
    this.viewportMatrix = performance.create();
    this.circles = [];
};
var RetainedQueryData = function RetainedQueryData(bucketInstanceId, featureIndex, sourceLayerIndex, bucketIndex, tileID) {
    this.bucketInstanceId = bucketInstanceId;
    this.featureIndex = featureIndex;
    this.sourceLayerIndex = sourceLayerIndex;
    this.bucketIndex = bucketIndex;
    this.tileID = tileID;
};
var CollisionGroups = function CollisionGroups(crossSourceCollisions) {
    this.crossSourceCollisions = crossSourceCollisions;
    this.maxGroupID = 0;
    this.collisionGroups = {};
};
CollisionGroups.prototype.get = function get(sourceID) {
    if (!this.crossSourceCollisions) {
        if (!this.collisionGroups[sourceID]) {
            var nextGroupID = ++this.maxGroupID;
            this.collisionGroups[sourceID] = {
                ID: nextGroupID,
                predicate: function (key) {
                    return key.collisionGroupID === nextGroupID;
                }
            };
        }
        return this.collisionGroups[sourceID];
    } else {
        return {
            ID: 0,
            predicate: null
        };
    }
};
function calculateVariableLayoutShift(anchor, width, height, textOffset, textBoxScale) {
    var ref = performance.getAnchorAlignment(anchor);
    var horizontalAlign = ref.horizontalAlign;
    var verticalAlign = ref.verticalAlign;
    var shiftX = -(horizontalAlign - 0.5) * width;
    var shiftY = -(verticalAlign - 0.5) * height;
    var offset = performance.evaluateVariableOffset(anchor, textOffset);
    return new performance.Point(shiftX + offset[0] * textBoxScale, shiftY + offset[1] * textBoxScale);
}
function shiftVariableCollisionBox(collisionBox, shiftX, shiftY, rotateWithMap, pitchWithMap, angle) {
    var x1 = collisionBox.x1;
    var x2 = collisionBox.x2;
    var y1 = collisionBox.y1;
    var y2 = collisionBox.y2;
    var anchorPointX = collisionBox.anchorPointX;
    var anchorPointY = collisionBox.anchorPointY;
    var rotatedOffset = new performance.Point(shiftX, shiftY);
    if (rotateWithMap) {
        rotatedOffset._rotate(pitchWithMap ? angle : -angle);
    }
    return {
        x1: x1 + rotatedOffset.x,
        y1: y1 + rotatedOffset.y,
        x2: x2 + rotatedOffset.x,
        y2: y2 + rotatedOffset.y,
        anchorPointX: anchorPointX,
        anchorPointY: anchorPointY
    };
}
var Placement = function Placement(transform, fadeDuration, crossSourceCollisions, prevPlacement) {
    this.transform = transform.clone();
    this.collisionIndex = new CollisionIndex(this.transform);
    this.placements = {};
    this.opacities = {};
    this.variableOffsets = {};
    this.stale = false;
    this.commitTime = 0;
    this.fadeDuration = fadeDuration;
    this.retainedQueryData = {};
    this.collisionGroups = new CollisionGroups(crossSourceCollisions);
    this.collisionCircleArrays = {};
    this.prevPlacement = prevPlacement;
    if (prevPlacement) {
        prevPlacement.prevPlacement = undefined;
    }
    this.placedOrientations = {};
};
Placement.prototype.getBucketParts = function getBucketParts(results, styleLayer, tile, sortAcrossTiles) {
    var symbolBucket = tile.getBucket(styleLayer);
    var bucketFeatureIndex = tile.latestFeatureIndex;
    if (!symbolBucket || !bucketFeatureIndex || styleLayer.id !== symbolBucket.layerIds[0]) {
        return;
    }
    var collisionBoxArray = tile.collisionBoxArray;
    var layout = symbolBucket.layers[0].layout;
    var scale = Math.pow(2, this.transform.zoom - tile.tileID.overscaledZ);
    var textPixelRatio = tile.tileSize / performance.EXTENT;
    var posMatrix = this.transform.calculatePosMatrix(tile.tileID.toUnwrapped());
    var pitchWithMap = layout.get('text-pitch-alignment') === 'map';
    var rotateWithMap = layout.get('text-rotation-alignment') === 'map';
    var pixelsToTiles = pixelsToTileUnits(tile, 1, this.transform.zoom);
    var textLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, pitchWithMap, rotateWithMap, this.transform, pixelsToTiles);
    var labelToScreenMatrix = null;
    if (pitchWithMap) {
        var glMatrix = getGlCoordMatrix(posMatrix, pitchWithMap, rotateWithMap, this.transform, pixelsToTiles);
        labelToScreenMatrix = performance.multiply([], this.transform.labelPlaneMatrix, glMatrix);
    }
    this.retainedQueryData[symbolBucket.bucketInstanceId] = new RetainedQueryData(symbolBucket.bucketInstanceId, bucketFeatureIndex, symbolBucket.sourceLayerIndex, symbolBucket.index, tile.tileID);
    var parameters = {
        bucket: symbolBucket,
        layout: layout,
        posMatrix: posMatrix,
        textLabelPlaneMatrix: textLabelPlaneMatrix,
        labelToScreenMatrix: labelToScreenMatrix,
        scale: scale,
        textPixelRatio: textPixelRatio,
        holdingForFade: tile.holdingForFade(),
        collisionBoxArray: collisionBoxArray,
        partiallyEvaluatedTextSize: performance.evaluateSizeForZoom(symbolBucket.textSizeData, this.transform.zoom),
        collisionGroup: this.collisionGroups.get(symbolBucket.sourceID)
    };
    if (sortAcrossTiles) {
        for (var i = 0, list = symbolBucket.sortKeyRanges; i < list.length; i += 1) {
            var range = list[i];
            var sortKey = range.sortKey;
            var symbolInstanceStart = range.symbolInstanceStart;
            var symbolInstanceEnd = range.symbolInstanceEnd;
            results.push({
                sortKey: sortKey,
                symbolInstanceStart: symbolInstanceStart,
                symbolInstanceEnd: symbolInstanceEnd,
                parameters: parameters
            });
        }
    } else {
        results.push({
            symbolInstanceStart: 0,
            symbolInstanceEnd: symbolBucket.symbolInstances.length,
            parameters: parameters
        });
    }
};
Placement.prototype.attemptAnchorPlacement = function attemptAnchorPlacement(anchor, textBox, width, height, textBoxScale, rotateWithMap, pitchWithMap, textPixelRatio, posMatrix, collisionGroup, textAllowOverlap, symbolInstance, bucket, orientation, iconBox) {
    var textOffset = [
        symbolInstance.textOffset0,
        symbolInstance.textOffset1
    ];
    var shift = calculateVariableLayoutShift(anchor, width, height, textOffset, textBoxScale);
    var placedGlyphBoxes = this.collisionIndex.placeCollisionBox(shiftVariableCollisionBox(textBox, shift.x, shift.y, rotateWithMap, pitchWithMap, this.transform.angle), textAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
    if (iconBox) {
        var placedIconBoxes = this.collisionIndex.placeCollisionBox(shiftVariableCollisionBox(iconBox, shift.x, shift.y, rotateWithMap, pitchWithMap, this.transform.angle), textAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
        if (placedIconBoxes.box.length === 0) {
            return;
        }
    }
    if (placedGlyphBoxes.box.length > 0) {
        var prevAnchor;
        if (this.prevPlacement && this.prevPlacement.variableOffsets[symbolInstance.crossTileID] && this.prevPlacement.placements[symbolInstance.crossTileID] && this.prevPlacement.placements[symbolInstance.crossTileID].text) {
            prevAnchor = this.prevPlacement.variableOffsets[symbolInstance.crossTileID].anchor;
        }
        this.variableOffsets[symbolInstance.crossTileID] = {
            textOffset: textOffset,
            width: width,
            height: height,
            anchor: anchor,
            textBoxScale: textBoxScale,
            prevAnchor: prevAnchor
        };
        this.markUsedJustification(bucket, anchor, symbolInstance, orientation);
        if (bucket.allowVerticalPlacement) {
            this.markUsedOrientation(bucket, orientation, symbolInstance);
            this.placedOrientations[symbolInstance.crossTileID] = orientation;
        }
        return {
            shift: shift,
            placedGlyphBoxes: placedGlyphBoxes
        };
    }
};
Placement.prototype.placeLayerBucketPart = function placeLayerBucketPart(bucketPart, seenCrossTileIDs, showCollisionBoxes) {
    var this$1 = this;
    var ref = bucketPart.parameters;
    var bucket = ref.bucket;
    var layout = ref.layout;
    var posMatrix = ref.posMatrix;
    var textLabelPlaneMatrix = ref.textLabelPlaneMatrix;
    var labelToScreenMatrix = ref.labelToScreenMatrix;
    var textPixelRatio = ref.textPixelRatio;
    var holdingForFade = ref.holdingForFade;
    var collisionBoxArray = ref.collisionBoxArray;
    var partiallyEvaluatedTextSize = ref.partiallyEvaluatedTextSize;
    var collisionGroup = ref.collisionGroup;
    var textOptional = layout.get('text-optional');
    var iconOptional = layout.get('icon-optional');
    var textAllowOverlap = layout.get('text-allow-overlap');
    var iconAllowOverlap = layout.get('icon-allow-overlap');
    var rotateWithMap = layout.get('text-rotation-alignment') === 'map';
    var pitchWithMap = layout.get('text-pitch-alignment') === 'map';
    var hasIconTextFit = layout.get('icon-text-fit') !== 'none';
    var zOrderByViewportY = layout.get('symbol-z-order') === 'viewport-y';
    var alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || iconOptional);
    var alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || textOptional);
    if (!bucket.collisionArrays && collisionBoxArray) {
        bucket.deserializeCollisionBoxes(collisionBoxArray);
    }
    var placeSymbol = function (symbolInstance, collisionArrays) {
        if (seenCrossTileIDs[symbolInstance.crossTileID]) {
            return;
        }
        if (holdingForFade) {
            this$1.placements[symbolInstance.crossTileID] = new JointPlacement(false, false, false);
            return;
        }
        var placeText = false;
        var placeIcon = false;
        var offscreen = true;
        var shift = null;
        var placed = {
            box: null,
            offscreen: null
        };
        var placedVerticalText = {
            box: null,
            offscreen: null
        };
        var placedGlyphBoxes = null;
        var placedGlyphCircles = null;
        var placedIconBoxes = null;
        var textFeatureIndex = 0;
        var verticalTextFeatureIndex = 0;
        var iconFeatureIndex = 0;
        if (collisionArrays.textFeatureIndex) {
            textFeatureIndex = collisionArrays.textFeatureIndex;
        } else if (symbolInstance.useRuntimeCollisionCircles) {
            textFeatureIndex = symbolInstance.featureIndex;
        }
        if (collisionArrays.verticalTextFeatureIndex) {
            verticalTextFeatureIndex = collisionArrays.verticalTextFeatureIndex;
        }
        var textBox = collisionArrays.textBox;
        if (textBox) {
            var updatePreviousOrientationIfNotPlaced = function (isPlaced) {
                var previousOrientation = performance.WritingMode.horizontal;
                if (bucket.allowVerticalPlacement && !isPlaced && this$1.prevPlacement) {
                    var prevPlacedOrientation = this$1.prevPlacement.placedOrientations[symbolInstance.crossTileID];
                    if (prevPlacedOrientation) {
                        this$1.placedOrientations[symbolInstance.crossTileID] = prevPlacedOrientation;
                        previousOrientation = prevPlacedOrientation;
                        this$1.markUsedOrientation(bucket, previousOrientation, symbolInstance);
                    }
                }
                return previousOrientation;
            };
            var placeTextForPlacementModes = function (placeHorizontalFn, placeVerticalFn) {
                if (bucket.allowVerticalPlacement && symbolInstance.numVerticalGlyphVertices > 0 && collisionArrays.verticalTextBox) {
                    for (var i = 0, list = bucket.writingModes; i < list.length; i += 1) {
                        var placementMode = list[i];
                        if (placementMode === performance.WritingMode.vertical) {
                            placed = placeVerticalFn();
                            placedVerticalText = placed;
                        } else {
                            placed = placeHorizontalFn();
                        }
                        if (placed && placed.box && placed.box.length) {
                            break;
                        }
                    }
                } else {
                    placed = placeHorizontalFn();
                }
            };
            if (!layout.get('text-variable-anchor')) {
                var placeBox = function (collisionTextBox, orientation) {
                    var placedFeature = this$1.collisionIndex.placeCollisionBox(collisionTextBox, textAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
                    if (placedFeature && placedFeature.box && placedFeature.box.length) {
                        this$1.markUsedOrientation(bucket, orientation, symbolInstance);
                        this$1.placedOrientations[symbolInstance.crossTileID] = orientation;
                    }
                    return placedFeature;
                };
                var placeHorizontal = function () {
                    return placeBox(textBox, performance.WritingMode.horizontal);
                };
                var placeVertical = function () {
                    var verticalTextBox = collisionArrays.verticalTextBox;
                    if (bucket.allowVerticalPlacement && symbolInstance.numVerticalGlyphVertices > 0 && verticalTextBox) {
                        return placeBox(verticalTextBox, performance.WritingMode.vertical);
                    }
                    return {
                        box: null,
                        offscreen: null
                    };
                };
                placeTextForPlacementModes(placeHorizontal, placeVertical);
                updatePreviousOrientationIfNotPlaced(placed && placed.box && placed.box.length);
            } else {
                var anchors = layout.get('text-variable-anchor');
                if (this$1.prevPlacement && this$1.prevPlacement.variableOffsets[symbolInstance.crossTileID]) {
                    var prevOffsets = this$1.prevPlacement.variableOffsets[symbolInstance.crossTileID];
                    if (anchors.indexOf(prevOffsets.anchor) > 0) {
                        anchors = anchors.filter(function (anchor) {
                            return anchor !== prevOffsets.anchor;
                        });
                        anchors.unshift(prevOffsets.anchor);
                    }
                }
                var placeBoxForVariableAnchors = function (collisionTextBox, collisionIconBox, orientation) {
                    var width = collisionTextBox.x2 - collisionTextBox.x1;
                    var height = collisionTextBox.y2 - collisionTextBox.y1;
                    var textBoxScale = symbolInstance.textBoxScale;
                    var variableIconBox = hasIconTextFit && !iconAllowOverlap ? collisionIconBox : null;
                    var placedBox = {
                        box: [],
                        offscreen: false
                    };
                    var placementAttempts = textAllowOverlap ? anchors.length * 2 : anchors.length;
                    for (var i = 0; i < placementAttempts; ++i) {
                        var anchor = anchors[i % anchors.length];
                        var allowOverlap = i >= anchors.length;
                        var result = this$1.attemptAnchorPlacement(anchor, collisionTextBox, width, height, textBoxScale, rotateWithMap, pitchWithMap, textPixelRatio, posMatrix, collisionGroup, allowOverlap, symbolInstance, bucket, orientation, variableIconBox);
                        if (result) {
                            placedBox = result.placedGlyphBoxes;
                            if (placedBox && placedBox.box && placedBox.box.length) {
                                placeText = true;
                                shift = result.shift;
                                break;
                            }
                        }
                    }
                    return placedBox;
                };
                var placeHorizontal$1 = function () {
                    return placeBoxForVariableAnchors(textBox, collisionArrays.iconBox, performance.WritingMode.horizontal);
                };
                var placeVertical$1 = function () {
                    var verticalTextBox = collisionArrays.verticalTextBox;
                    var wasPlaced = placed && placed.box && placed.box.length;
                    if (bucket.allowVerticalPlacement && !wasPlaced && symbolInstance.numVerticalGlyphVertices > 0 && verticalTextBox) {
                        return placeBoxForVariableAnchors(verticalTextBox, collisionArrays.verticalIconBox, performance.WritingMode.vertical);
                    }
                    return {
                        box: null,
                        offscreen: null
                    };
                };
                placeTextForPlacementModes(placeHorizontal$1, placeVertical$1);
                if (placed) {
                    placeText = placed.box;
                    offscreen = placed.offscreen;
                }
                var prevOrientation = updatePreviousOrientationIfNotPlaced(placed && placed.box);
                if (!placeText && this$1.prevPlacement) {
                    var prevOffset = this$1.prevPlacement.variableOffsets[symbolInstance.crossTileID];
                    if (prevOffset) {
                        this$1.variableOffsets[symbolInstance.crossTileID] = prevOffset;
                        this$1.markUsedJustification(bucket, prevOffset.anchor, symbolInstance, prevOrientation);
                    }
                }
            }
        }
        placedGlyphBoxes = placed;
        placeText = placedGlyphBoxes && placedGlyphBoxes.box && placedGlyphBoxes.box.length > 0;
        offscreen = placedGlyphBoxes && placedGlyphBoxes.offscreen;
        if (symbolInstance.useRuntimeCollisionCircles) {
            var placedSymbol = bucket.text.placedSymbolArray.get(symbolInstance.centerJustifiedTextSymbolIndex);
            var fontSize = performance.evaluateSizeForFeature(bucket.textSizeData, partiallyEvaluatedTextSize, placedSymbol);
            var textPixelPadding = layout.get('text-padding');
            var circlePixelDiameter = symbolInstance.collisionCircleDiameter;
            placedGlyphCircles = this$1.collisionIndex.placeCollisionCircles(textAllowOverlap, placedSymbol, bucket.lineVertexArray, bucket.glyphOffsetArray, fontSize, posMatrix, textLabelPlaneMatrix, labelToScreenMatrix, showCollisionBoxes, pitchWithMap, collisionGroup.predicate, circlePixelDiameter, textPixelPadding);
            placeText = textAllowOverlap || placedGlyphCircles.circles.length > 0 && !placedGlyphCircles.collisionDetected;
            offscreen = offscreen && placedGlyphCircles.offscreen;
        }
        if (collisionArrays.iconFeatureIndex) {
            iconFeatureIndex = collisionArrays.iconFeatureIndex;
        }
        if (collisionArrays.iconBox) {
            var placeIconFeature = function (iconBox) {
                var shiftedIconBox = hasIconTextFit && shift ? shiftVariableCollisionBox(iconBox, shift.x, shift.y, rotateWithMap, pitchWithMap, this$1.transform.angle) : iconBox;
                return this$1.collisionIndex.placeCollisionBox(shiftedIconBox, iconAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate);
            };
            if (placedVerticalText && placedVerticalText.box && placedVerticalText.box.length && collisionArrays.verticalIconBox) {
                placedIconBoxes = placeIconFeature(collisionArrays.verticalIconBox);
                placeIcon = placedIconBoxes.box.length > 0;
            } else {
                placedIconBoxes = placeIconFeature(collisionArrays.iconBox);
                placeIcon = placedIconBoxes.box.length > 0;
            }
            offscreen = offscreen && placedIconBoxes.offscreen;
        }
        var iconWithoutText = textOptional || symbolInstance.numHorizontalGlyphVertices === 0 && symbolInstance.numVerticalGlyphVertices === 0;
        var textWithoutIcon = iconOptional || symbolInstance.numIconVertices === 0;
        if (!iconWithoutText && !textWithoutIcon) {
            placeIcon = placeText = placeIcon && placeText;
        } else if (!textWithoutIcon) {
            placeText = placeIcon && placeText;
        } else if (!iconWithoutText) {
            placeIcon = placeIcon && placeText;
        }
        if (placeText && placedGlyphBoxes && placedGlyphBoxes.box) {
            if (placedVerticalText && placedVerticalText.box && verticalTextFeatureIndex) {
                this$1.collisionIndex.insertCollisionBox(placedGlyphBoxes.box, layout.get('text-ignore-placement'), bucket.bucketInstanceId, verticalTextFeatureIndex, collisionGroup.ID);
            } else {
                this$1.collisionIndex.insertCollisionBox(placedGlyphBoxes.box, layout.get('text-ignore-placement'), bucket.bucketInstanceId, textFeatureIndex, collisionGroup.ID);
            }
        }
        if (placeIcon && placedIconBoxes) {
            this$1.collisionIndex.insertCollisionBox(placedIconBoxes.box, layout.get('icon-ignore-placement'), bucket.bucketInstanceId, iconFeatureIndex, collisionGroup.ID);
        }
        if (placedGlyphCircles) {
            if (placeText) {
                this$1.collisionIndex.insertCollisionCircles(placedGlyphCircles.circles, layout.get('text-ignore-placement'), bucket.bucketInstanceId, textFeatureIndex, collisionGroup.ID);
            }
            if (showCollisionBoxes) {
                var id = bucket.bucketInstanceId;
                var circleArray = this$1.collisionCircleArrays[id];
                if (circleArray === undefined) {
                    circleArray = this$1.collisionCircleArrays[id] = new CollisionCircleArray();
                }
                for (var i = 0; i < placedGlyphCircles.circles.length; i += 4) {
                    circleArray.circles.push(placedGlyphCircles.circles[i + 0]);
                    circleArray.circles.push(placedGlyphCircles.circles[i + 1]);
                    circleArray.circles.push(placedGlyphCircles.circles[i + 2]);
                    circleArray.circles.push(placedGlyphCircles.collisionDetected ? 1 : 0);
                }
            }
        }
        this$1.placements[symbolInstance.crossTileID] = new JointPlacement(placeText || alwaysShowText, placeIcon || alwaysShowIcon, offscreen || bucket.justReloaded);
        seenCrossTileIDs[symbolInstance.crossTileID] = true;
    };
    if (zOrderByViewportY) {
        var symbolIndexes = bucket.getSortedSymbolIndexes(this.transform.angle);
        for (var i = symbolIndexes.length - 1; i >= 0; --i) {
            var symbolIndex = symbolIndexes[i];
            placeSymbol(bucket.symbolInstances.get(symbolIndex), bucket.collisionArrays[symbolIndex]);
        }
    } else {
        for (var i$1 = bucketPart.symbolInstanceStart; i$1 < bucketPart.symbolInstanceEnd; i$1++) {
            placeSymbol(bucket.symbolInstances.get(i$1), bucket.collisionArrays[i$1]);
        }
    }
    if (showCollisionBoxes && bucket.bucketInstanceId in this.collisionCircleArrays) {
        var circleArray = this.collisionCircleArrays[bucket.bucketInstanceId];
        performance.invert(circleArray.invProjMatrix, posMatrix);
        circleArray.viewportMatrix = this.collisionIndex.getViewportMatrix();
    }
    bucket.justReloaded = false;
};
Placement.prototype.markUsedJustification = function markUsedJustification(bucket, placedAnchor, symbolInstance, orientation) {
    var justifications = {
        'left': symbolInstance.leftJustifiedTextSymbolIndex,
        'center': symbolInstance.centerJustifiedTextSymbolIndex,
        'right': symbolInstance.rightJustifiedTextSymbolIndex
    };
    var autoIndex;
    if (orientation === performance.WritingMode.vertical) {
        autoIndex = symbolInstance.verticalPlacedTextSymbolIndex;
    } else {
        autoIndex = justifications[performance.getAnchorJustification(placedAnchor)];
    }
    var indexes = [
        symbolInstance.leftJustifiedTextSymbolIndex,
        symbolInstance.centerJustifiedTextSymbolIndex,
        symbolInstance.rightJustifiedTextSymbolIndex,
        symbolInstance.verticalPlacedTextSymbolIndex
    ];
    for (var i = 0, list = indexes; i < list.length; i += 1) {
        var index = list[i];
        if (index >= 0) {
            if (autoIndex >= 0 && index !== autoIndex) {
                bucket.text.placedSymbolArray.get(index).crossTileID = 0;
            } else {
                bucket.text.placedSymbolArray.get(index).crossTileID = symbolInstance.crossTileID;
            }
        }
    }
};
Placement.prototype.markUsedOrientation = function markUsedOrientation(bucket, orientation, symbolInstance) {
    var horizontal = orientation === performance.WritingMode.horizontal || orientation === performance.WritingMode.horizontalOnly ? orientation : 0;
    var vertical = orientation === performance.WritingMode.vertical ? orientation : 0;
    var horizontalIndexes = [
        symbolInstance.leftJustifiedTextSymbolIndex,
        symbolInstance.centerJustifiedTextSymbolIndex,
        symbolInstance.rightJustifiedTextSymbolIndex
    ];
    for (var i = 0, list = horizontalIndexes; i < list.length; i += 1) {
        var index = list[i];
        bucket.text.placedSymbolArray.get(index).placedOrientation = horizontal;
    }
    if (symbolInstance.verticalPlacedTextSymbolIndex) {
        bucket.text.placedSymbolArray.get(symbolInstance.verticalPlacedTextSymbolIndex).placedOrientation = vertical;
    }
};
Placement.prototype.commit = function commit(now) {
    this.commitTime = now;
    this.zoomAtLastRecencyCheck = this.transform.zoom;
    var prevPlacement = this.prevPlacement;
    var placementChanged = false;
    this.prevZoomAdjustment = prevPlacement ? prevPlacement.zoomAdjustment(this.transform.zoom) : 0;
    var increment = prevPlacement ? prevPlacement.symbolFadeChange(now) : 1;
    var prevOpacities = prevPlacement ? prevPlacement.opacities : {};
    var prevOffsets = prevPlacement ? prevPlacement.variableOffsets : {};
    var prevOrientations = prevPlacement ? prevPlacement.placedOrientations : {};
    for (var crossTileID in this.placements) {
        var jointPlacement = this.placements[crossTileID];
        var prevOpacity = prevOpacities[crossTileID];
        if (prevOpacity) {
            this.opacities[crossTileID] = new JointOpacityState(prevOpacity, increment, jointPlacement.text, jointPlacement.icon);
            placementChanged = placementChanged || jointPlacement.text !== prevOpacity.text.placed || jointPlacement.icon !== prevOpacity.icon.placed;
        } else {
            this.opacities[crossTileID] = new JointOpacityState(null, increment, jointPlacement.text, jointPlacement.icon, jointPlacement.skipFade);
            placementChanged = placementChanged || jointPlacement.text || jointPlacement.icon;
        }
    }
    for (var crossTileID$1 in prevOpacities) {
        var prevOpacity$1 = prevOpacities[crossTileID$1];
        if (!this.opacities[crossTileID$1]) {
            var jointOpacity = new JointOpacityState(prevOpacity$1, increment, false, false);
            if (!jointOpacity.isHidden()) {
                this.opacities[crossTileID$1] = jointOpacity;
                placementChanged = placementChanged || prevOpacity$1.text.placed || prevOpacity$1.icon.placed;
            }
        }
    }
    for (var crossTileID$2 in prevOffsets) {
        if (!this.variableOffsets[crossTileID$2] && this.opacities[crossTileID$2] && !this.opacities[crossTileID$2].isHidden()) {
            this.variableOffsets[crossTileID$2] = prevOffsets[crossTileID$2];
        }
    }
    for (var crossTileID$3 in prevOrientations) {
        if (!this.placedOrientations[crossTileID$3] && this.opacities[crossTileID$3] && !this.opacities[crossTileID$3].isHidden()) {
            this.placedOrientations[crossTileID$3] = prevOrientations[crossTileID$3];
        }
    }
    if (placementChanged) {
        this.lastPlacementChangeTime = now;
    } else if (typeof this.lastPlacementChangeTime !== 'number') {
        this.lastPlacementChangeTime = prevPlacement ? prevPlacement.lastPlacementChangeTime : now;
    }
};
Placement.prototype.updateLayerOpacities = function updateLayerOpacities(styleLayer, tiles) {
    var seenCrossTileIDs = {};
    for (var i = 0, list = tiles; i < list.length; i += 1) {
        var tile = list[i];
        var symbolBucket = tile.getBucket(styleLayer);
        if (symbolBucket && tile.latestFeatureIndex && styleLayer.id === symbolBucket.layerIds[0]) {
            this.updateBucketOpacities(symbolBucket, seenCrossTileIDs, tile.collisionBoxArray);
        }
    }
};
Placement.prototype.updateBucketOpacities = function updateBucketOpacities(bucket, seenCrossTileIDs, collisionBoxArray) {
    var this$1 = this;
    if (bucket.hasTextData()) {
        bucket.text.opacityVertexArray.clear();
    }
    if (bucket.hasIconData()) {
        bucket.icon.opacityVertexArray.clear();
    }
    if (bucket.hasIconCollisionBoxData()) {
        bucket.iconCollisionBox.collisionVertexArray.clear();
    }
    if (bucket.hasTextCollisionBoxData()) {
        bucket.textCollisionBox.collisionVertexArray.clear();
    }
    var layout = bucket.layers[0].layout;
    var duplicateOpacityState = new JointOpacityState(null, 0, false, false, true);
    var textAllowOverlap = layout.get('text-allow-overlap');
    var iconAllowOverlap = layout.get('icon-allow-overlap');
    var variablePlacement = layout.get('text-variable-anchor');
    var rotateWithMap = layout.get('text-rotation-alignment') === 'map';
    var pitchWithMap = layout.get('text-pitch-alignment') === 'map';
    var hasIconTextFit = layout.get('icon-text-fit') !== 'none';
    var defaultOpacityState = new JointOpacityState(null, 0, textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || layout.get('icon-optional')), iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || layout.get('text-optional')), true);
    if (!bucket.collisionArrays && collisionBoxArray && (bucket.hasIconCollisionBoxData() || bucket.hasTextCollisionBoxData())) {
        bucket.deserializeCollisionBoxes(collisionBoxArray);
    }
    var addOpacities = function (iconOrText, numVertices, opacity) {
        for (var i = 0; i < numVertices / 4; i++) {
            iconOrText.opacityVertexArray.emplaceBack(opacity);
        }
    };
    var loop = function (s) {
        var symbolInstance = bucket.symbolInstances.get(s);
        var numHorizontalGlyphVertices = symbolInstance.numHorizontalGlyphVertices;
        var numVerticalGlyphVertices = symbolInstance.numVerticalGlyphVertices;
        var crossTileID = symbolInstance.crossTileID;
        var isDuplicate = seenCrossTileIDs[crossTileID];
        var opacityState = this$1.opacities[crossTileID];
        if (isDuplicate) {
            opacityState = duplicateOpacityState;
        } else if (!opacityState) {
            opacityState = defaultOpacityState;
            this$1.opacities[crossTileID] = opacityState;
        }
        seenCrossTileIDs[crossTileID] = true;
        var hasText = numHorizontalGlyphVertices > 0 || numVerticalGlyphVertices > 0;
        var hasIcon = symbolInstance.numIconVertices > 0;
        var placedOrientation = this$1.placedOrientations[symbolInstance.crossTileID];
        var horizontalHidden = placedOrientation === performance.WritingMode.vertical;
        var verticalHidden = placedOrientation === performance.WritingMode.horizontal || placedOrientation === performance.WritingMode.horizontalOnly;
        if (hasText) {
            var packedOpacity = packOpacity(opacityState.text);
            var horizontalOpacity = horizontalHidden ? PACKED_HIDDEN_OPACITY : packedOpacity;
            addOpacities(bucket.text, numHorizontalGlyphVertices, horizontalOpacity);
            var verticalOpacity = verticalHidden ? PACKED_HIDDEN_OPACITY : packedOpacity;
            addOpacities(bucket.text, numVerticalGlyphVertices, verticalOpacity);
            var symbolHidden = opacityState.text.isHidden();
            [
                symbolInstance.rightJustifiedTextSymbolIndex,
                symbolInstance.centerJustifiedTextSymbolIndex,
                symbolInstance.leftJustifiedTextSymbolIndex
            ].forEach(function (index) {
                if (index >= 0) {
                    bucket.text.placedSymbolArray.get(index).hidden = symbolHidden || horizontalHidden ? 1 : 0;
                }
            });
            if (symbolInstance.verticalPlacedTextSymbolIndex >= 0) {
                bucket.text.placedSymbolArray.get(symbolInstance.verticalPlacedTextSymbolIndex).hidden = symbolHidden || verticalHidden ? 1 : 0;
            }
            var prevOffset = this$1.variableOffsets[symbolInstance.crossTileID];
            if (prevOffset) {
                this$1.markUsedJustification(bucket, prevOffset.anchor, symbolInstance, placedOrientation);
            }
            var prevOrientation = this$1.placedOrientations[symbolInstance.crossTileID];
            if (prevOrientation) {
                this$1.markUsedJustification(bucket, 'left', symbolInstance, prevOrientation);
                this$1.markUsedOrientation(bucket, prevOrientation, symbolInstance);
            }
        }
        if (hasIcon) {
            var packedOpacity$1 = packOpacity(opacityState.icon);
            var useHorizontal = !(hasIconTextFit && symbolInstance.verticalPlacedIconSymbolIndex && horizontalHidden);
            if (symbolInstance.placedIconSymbolIndex >= 0) {
                var horizontalOpacity$1 = useHorizontal ? packedOpacity$1 : PACKED_HIDDEN_OPACITY;
                addOpacities(bucket.icon, symbolInstance.numIconVertices, horizontalOpacity$1);
                bucket.icon.placedSymbolArray.get(symbolInstance.placedIconSymbolIndex).hidden = opacityState.icon.isHidden();
            }
            if (symbolInstance.verticalPlacedIconSymbolIndex >= 0) {
                var verticalOpacity$1 = !useHorizontal ? packedOpacity$1 : PACKED_HIDDEN_OPACITY;
                addOpacities(bucket.icon, symbolInstance.numVerticalIconVertices, verticalOpacity$1);
                bucket.icon.placedSymbolArray.get(symbolInstance.verticalPlacedIconSymbolIndex).hidden = opacityState.icon.isHidden();
            }
        }
        if (bucket.hasIconCollisionBoxData() || bucket.hasTextCollisionBoxData()) {
            var collisionArrays = bucket.collisionArrays[s];
            if (collisionArrays) {
                var shift = new performance.Point(0, 0);
                if (collisionArrays.textBox || collisionArrays.verticalTextBox) {
                    var used = true;
                    if (variablePlacement) {
                        var variableOffset = this$1.variableOffsets[crossTileID];
                        if (variableOffset) {
                            shift = calculateVariableLayoutShift(variableOffset.anchor, variableOffset.width, variableOffset.height, variableOffset.textOffset, variableOffset.textBoxScale);
                            if (rotateWithMap) {
                                shift._rotate(pitchWithMap ? this$1.transform.angle : -this$1.transform.angle);
                            }
                        } else {
                            used = false;
                        }
                    }
                    if (collisionArrays.textBox) {
                        updateCollisionVertices(bucket.textCollisionBox.collisionVertexArray, opacityState.text.placed, !used || horizontalHidden, shift.x, shift.y);
                    }
                    if (collisionArrays.verticalTextBox) {
                        updateCollisionVertices(bucket.textCollisionBox.collisionVertexArray, opacityState.text.placed, !used || verticalHidden, shift.x, shift.y);
                    }
                }
                var verticalIconUsed = Boolean(!verticalHidden && collisionArrays.verticalIconBox);
                if (collisionArrays.iconBox) {
                    updateCollisionVertices(bucket.iconCollisionBox.collisionVertexArray, opacityState.icon.placed, verticalIconUsed, hasIconTextFit ? shift.x : 0, hasIconTextFit ? shift.y : 0);
                }
                if (collisionArrays.verticalIconBox) {
                    updateCollisionVertices(bucket.iconCollisionBox.collisionVertexArray, opacityState.icon.placed, !verticalIconUsed, hasIconTextFit ? shift.x : 0, hasIconTextFit ? shift.y : 0);
                }
            }
        }
    };
    for (var s = 0; s < bucket.symbolInstances.length; s++)
        loop(s);
    bucket.sortFeatures(this.transform.angle);
    if (this.retainedQueryData[bucket.bucketInstanceId]) {
        this.retainedQueryData[bucket.bucketInstanceId].featureSortOrder = bucket.featureSortOrder;
    }
    if (bucket.hasTextData() && bucket.text.opacityVertexBuffer) {
        bucket.text.opacityVertexBuffer.updateData(bucket.text.opacityVertexArray);
    }
    if (bucket.hasIconData() && bucket.icon.opacityVertexBuffer) {
        bucket.icon.opacityVertexBuffer.updateData(bucket.icon.opacityVertexArray);
    }
    if (bucket.hasIconCollisionBoxData() && bucket.iconCollisionBox.collisionVertexBuffer) {
        bucket.iconCollisionBox.collisionVertexBuffer.updateData(bucket.iconCollisionBox.collisionVertexArray);
    }
    if (bucket.hasTextCollisionBoxData() && bucket.textCollisionBox.collisionVertexBuffer) {
        bucket.textCollisionBox.collisionVertexBuffer.updateData(bucket.textCollisionBox.collisionVertexArray);
    }
    if (bucket.bucketInstanceId in this.collisionCircleArrays) {
        var instance = this.collisionCircleArrays[bucket.bucketInstanceId];
        bucket.placementInvProjMatrix = instance.invProjMatrix;
        bucket.placementViewportMatrix = instance.viewportMatrix;
        bucket.collisionCircleArray = instance.circles;
        delete this.collisionCircleArrays[bucket.bucketInstanceId];
    }
};
Placement.prototype.symbolFadeChange = function symbolFadeChange(now) {
    return this.fadeDuration === 0 ? 1 : (now - this.commitTime) / this.fadeDuration + this.prevZoomAdjustment;
};
Placement.prototype.zoomAdjustment = function zoomAdjustment(zoom) {
    return Math.max(0, (this.transform.zoom - zoom) / 1.5);
};
Placement.prototype.hasTransitions = function hasTransitions(now) {
    return this.stale || now - this.lastPlacementChangeTime < this.fadeDuration;
};
Placement.prototype.stillRecent = function stillRecent(now, zoom) {
    var durationAdjustment = this.zoomAtLastRecencyCheck === zoom ? 1 - this.zoomAdjustment(zoom) : 1;
    this.zoomAtLastRecencyCheck = zoom;
    return this.commitTime + this.fadeDuration * durationAdjustment > now;
};
Placement.prototype.setStale = function setStale() {
    this.stale = true;
};
function updateCollisionVertices(collisionVertexArray, placed, notUsed, shiftX, shiftY) {
    collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0);
    collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0);
    collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0);
    collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0);
}
var shift25 = Math.pow(2, 25);
var shift24 = Math.pow(2, 24);
var shift17 = Math.pow(2, 17);
var shift16 = Math.pow(2, 16);
var shift9 = Math.pow(2, 9);
var shift8 = Math.pow(2, 8);
var shift1 = Math.pow(2, 1);
function packOpacity(opacityState) {
    if (opacityState.opacity === 0 && !opacityState.placed) {
        return 0;
    } else if (opacityState.opacity === 1 && opacityState.placed) {
        return 4294967295;
    }
    var targetBit = opacityState.placed ? 1 : 0;
    var opacityBits = Math.floor(opacityState.opacity * 127);
    return opacityBits * shift25 + targetBit * shift24 + opacityBits * shift17 + targetBit * shift16 + opacityBits * shift9 + targetBit * shift8 + opacityBits * shift1 + targetBit;
}
var PACKED_HIDDEN_OPACITY = 0;

var LayerPlacement = function LayerPlacement(styleLayer) {
    this._sortAcrossTiles = styleLayer.layout.get('symbol-z-order') !== 'viewport-y' && styleLayer.layout.get('symbol-sort-key').constantOr(1) !== undefined;
    this._currentTileIndex = 0;
    this._currentPartIndex = 0;
    this._seenCrossTileIDs = {};
    this._bucketParts = [];
};
LayerPlacement.prototype.continuePlacement = function continuePlacement(tiles, placement, showCollisionBoxes, styleLayer, shouldPausePlacement) {
    var bucketParts = this._bucketParts;
    while (this._currentTileIndex < tiles.length) {
        var tile = tiles[this._currentTileIndex];
        placement.getBucketParts(bucketParts, styleLayer, tile, this._sortAcrossTiles);
        this._currentTileIndex++;
        if (shouldPausePlacement()) {
            return true;
        }
    }
    if (this._sortAcrossTiles) {
        this._sortAcrossTiles = false;
        bucketParts.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
    while (this._currentPartIndex < bucketParts.length) {
        var bucketPart = bucketParts[this._currentPartIndex];
        placement.placeLayerBucketPart(bucketPart, this._seenCrossTileIDs, showCollisionBoxes);
        this._currentPartIndex++;
        if (shouldPausePlacement()) {
            return true;
        }
    }
    return false;
};
var PauseablePlacement = function PauseablePlacement(transform, order, forceFullPlacement, showCollisionBoxes, fadeDuration, crossSourceCollisions, prevPlacement) {
    this.placement = new Placement(transform, fadeDuration, crossSourceCollisions, prevPlacement);
    this._currentPlacementIndex = order.length - 1;
    this._forceFullPlacement = forceFullPlacement;
    this._showCollisionBoxes = showCollisionBoxes;
    this._done = false;
};
PauseablePlacement.prototype.isDone = function isDone() {
    return this._done;
};
PauseablePlacement.prototype.continuePlacement = function continuePlacement(order, layers, layerTiles) {
    var this$1 = this;
    var startTime = performance.browser.now();
    var shouldPausePlacement = function () {
        var elapsedTime = performance.browser.now() - startTime;
        return this$1._forceFullPlacement ? false : elapsedTime > 2;
    };
    while (this._currentPlacementIndex >= 0) {
        var layerId = order[this._currentPlacementIndex];
        var layer = layers[layerId];
        var placementZoom = this.placement.collisionIndex.transform.zoom;
        if (layer.type === 'symbol' && (!layer.minzoom || layer.minzoom <= placementZoom) && (!layer.maxzoom || layer.maxzoom > placementZoom)) {
            if (!this._inProgressLayer) {
                this._inProgressLayer = new LayerPlacement(layer);
            }
            var pausePlacement = this._inProgressLayer.continuePlacement(layerTiles[layer.source], this.placement, this._showCollisionBoxes, layer, shouldPausePlacement);
            if (pausePlacement) {
                return;
            }
            delete this._inProgressLayer;
        }
        this._currentPlacementIndex--;
    }
    this._done = true;
};
PauseablePlacement.prototype.commit = function commit(now) {
    this.placement.commit(now);
    return this.placement;
};

var roundingFactor = 512 / performance.EXTENT / 2;
var TileLayerIndex = function TileLayerIndex(tileID, symbolInstances, bucketInstanceId) {
    this.tileID = tileID;
    this.indexedSymbolInstances = {};
    this.bucketInstanceId = bucketInstanceId;
    for (var i = 0; i < symbolInstances.length; i++) {
        var symbolInstance = symbolInstances.get(i);
        var key = symbolInstance.key;
        if (!this.indexedSymbolInstances[key]) {
            this.indexedSymbolInstances[key] = [];
        }
        this.indexedSymbolInstances[key].push({
            crossTileID: symbolInstance.crossTileID,
            coord: this.getScaledCoordinates(symbolInstance, tileID)
        });
    }
};
TileLayerIndex.prototype.getScaledCoordinates = function getScaledCoordinates(symbolInstance, childTileID) {
    var zDifference = childTileID.canonical.z - this.tileID.canonical.z;
    var scale = roundingFactor / Math.pow(2, zDifference);
    return {
        x: Math.floor((childTileID.canonical.x * performance.EXTENT + symbolInstance.anchorX) * scale),
        y: Math.floor((childTileID.canonical.y * performance.EXTENT + symbolInstance.anchorY) * scale)
    };
};
TileLayerIndex.prototype.findMatches = function findMatches(symbolInstances, newTileID, zoomCrossTileIDs) {
    var tolerance = this.tileID.canonical.z < newTileID.canonical.z ? 1 : Math.pow(2, this.tileID.canonical.z - newTileID.canonical.z);
    for (var i = 0; i < symbolInstances.length; i++) {
        var symbolInstance = symbolInstances.get(i);
        if (symbolInstance.crossTileID) {
            continue;
        }
        var indexedInstances = this.indexedSymbolInstances[symbolInstance.key];
        if (!indexedInstances) {
            continue;
        }
        var scaledSymbolCoord = this.getScaledCoordinates(symbolInstance, newTileID);
        for (var i$1 = 0, list = indexedInstances; i$1 < list.length; i$1 += 1) {
            var thisTileSymbol = list[i$1];
            if (Math.abs(thisTileSymbol.coord.x - scaledSymbolCoord.x) <= tolerance && Math.abs(thisTileSymbol.coord.y - scaledSymbolCoord.y) <= tolerance && !zoomCrossTileIDs[thisTileSymbol.crossTileID]) {
                zoomCrossTileIDs[thisTileSymbol.crossTileID] = true;
                symbolInstance.crossTileID = thisTileSymbol.crossTileID;
                break;
            }
        }
    }
};
var CrossTileIDs = function CrossTileIDs() {
    this.maxCrossTileID = 0;
};
CrossTileIDs.prototype.generate = function generate() {
    return ++this.maxCrossTileID;
};
var CrossTileSymbolLayerIndex = function CrossTileSymbolLayerIndex() {
    this.indexes = {};
    this.usedCrossTileIDs = {};
    this.lng = 0;
};
CrossTileSymbolLayerIndex.prototype.handleWrapJump = function handleWrapJump(lng) {
    var wrapDelta = Math.round((lng - this.lng) / 360);
    if (wrapDelta !== 0) {
        for (var zoom in this.indexes) {
            var zoomIndexes = this.indexes[zoom];
            var newZoomIndex = {};
            for (var key in zoomIndexes) {
                var index = zoomIndexes[key];
                index.tileID = index.tileID.unwrapTo(index.tileID.wrap + wrapDelta);
                newZoomIndex[index.tileID.key] = index;
            }
            this.indexes[zoom] = newZoomIndex;
        }
    }
    this.lng = lng;
};
CrossTileSymbolLayerIndex.prototype.addBucket = function addBucket(tileID, bucket, crossTileIDs) {
    if (this.indexes[tileID.overscaledZ] && this.indexes[tileID.overscaledZ][tileID.key]) {
        if (this.indexes[tileID.overscaledZ][tileID.key].bucketInstanceId === bucket.bucketInstanceId) {
            return false;
        } else {
            this.removeBucketCrossTileIDs(tileID.overscaledZ, this.indexes[tileID.overscaledZ][tileID.key]);
        }
    }
    for (var i = 0; i < bucket.symbolInstances.length; i++) {
        var symbolInstance = bucket.symbolInstances.get(i);
        symbolInstance.crossTileID = 0;
    }
    if (!this.usedCrossTileIDs[tileID.overscaledZ]) {
        this.usedCrossTileIDs[tileID.overscaledZ] = {};
    }
    var zoomCrossTileIDs = this.usedCrossTileIDs[tileID.overscaledZ];
    for (var zoom in this.indexes) {
        var zoomIndexes = this.indexes[zoom];
        if (Number(zoom) > tileID.overscaledZ) {
            for (var id in zoomIndexes) {
                var childIndex = zoomIndexes[id];
                if (childIndex.tileID.isChildOf(tileID)) {
                    childIndex.findMatches(bucket.symbolInstances, tileID, zoomCrossTileIDs);
                }
            }
        } else {
            var parentCoord = tileID.scaledTo(Number(zoom));
            var parentIndex = zoomIndexes[parentCoord.key];
            if (parentIndex) {
                parentIndex.findMatches(bucket.symbolInstances, tileID, zoomCrossTileIDs);
            }
        }
    }
    for (var i$1 = 0; i$1 < bucket.symbolInstances.length; i$1++) {
        var symbolInstance$1 = bucket.symbolInstances.get(i$1);
        if (!symbolInstance$1.crossTileID) {
            symbolInstance$1.crossTileID = crossTileIDs.generate();
            zoomCrossTileIDs[symbolInstance$1.crossTileID] = true;
        }
    }
    if (this.indexes[tileID.overscaledZ] === undefined) {
        this.indexes[tileID.overscaledZ] = {};
    }
    this.indexes[tileID.overscaledZ][tileID.key] = new TileLayerIndex(tileID, bucket.symbolInstances, bucket.bucketInstanceId);
    return true;
};
CrossTileSymbolLayerIndex.prototype.removeBucketCrossTileIDs = function removeBucketCrossTileIDs(zoom, removedBucket) {
    for (var key in removedBucket.indexedSymbolInstances) {
        for (var i = 0, list = removedBucket.indexedSymbolInstances[key]; i < list.length; i += 1) {
            var symbolInstance = list[i];
            delete this.usedCrossTileIDs[zoom][symbolInstance.crossTileID];
        }
    }
};
CrossTileSymbolLayerIndex.prototype.removeStaleBuckets = function removeStaleBuckets(currentIDs) {
    var tilesChanged = false;
    for (var z in this.indexes) {
        var zoomIndexes = this.indexes[z];
        for (var tileKey in zoomIndexes) {
            if (!currentIDs[zoomIndexes[tileKey].bucketInstanceId]) {
                this.removeBucketCrossTileIDs(z, zoomIndexes[tileKey]);
                delete zoomIndexes[tileKey];
                tilesChanged = true;
            }
        }
    }
    return tilesChanged;
};
var CrossTileSymbolIndex = function CrossTileSymbolIndex() {
    this.layerIndexes = {};
    this.crossTileIDs = new CrossTileIDs();
    this.maxBucketInstanceId = 0;
    this.bucketsInCurrentPlacement = {};
};
CrossTileSymbolIndex.prototype.addLayer = function addLayer(styleLayer, tiles, lng) {
    var layerIndex = this.layerIndexes[styleLayer.id];
    if (layerIndex === undefined) {
        layerIndex = this.layerIndexes[styleLayer.id] = new CrossTileSymbolLayerIndex();
    }
    var symbolBucketsChanged = false;
    var currentBucketIDs = {};
    layerIndex.handleWrapJump(lng);
    for (var i = 0, list = tiles; i < list.length; i += 1) {
        var tile = list[i];
        var symbolBucket = tile.getBucket(styleLayer);
        if (!symbolBucket || styleLayer.id !== symbolBucket.layerIds[0]) {
            continue;
        }
        if (!symbolBucket.bucketInstanceId) {
            symbolBucket.bucketInstanceId = ++this.maxBucketInstanceId;
        }
        if (layerIndex.addBucket(tile.tileID, symbolBucket, this.crossTileIDs)) {
            symbolBucketsChanged = true;
        }
        currentBucketIDs[symbolBucket.bucketInstanceId] = true;
    }
    if (layerIndex.removeStaleBuckets(currentBucketIDs)) {
        symbolBucketsChanged = true;
    }
    return symbolBucketsChanged;
};
CrossTileSymbolIndex.prototype.pruneUnusedLayers = function pruneUnusedLayers(usedLayers) {
    var usedLayerMap = {};
    usedLayers.forEach(function (usedLayer) {
        usedLayerMap[usedLayer] = true;
    });
    for (var layerId in this.layerIndexes) {
        if (!usedLayerMap[layerId]) {
            delete this.layerIndexes[layerId];
        }
    }
};

var emitValidationErrors = function (evented, errors) {
    return performance.emitValidationErrors(evented, errors && errors.filter(function (error) {
        return error.identifier !== 'source.canvas';
    }));
};
var supportedDiffOperations = performance.pick(operations, [
    'addLayer',
    'removeLayer',
    'setPaintProperty',
    'setLayoutProperty',
    'setFilter',
    'addSource',
    'removeSource',
    'setLayerZoomRange',
    'setLight',
    'setTransition',
    'setGeoJSONSourceData'
]);
var ignoredDiffOperations = performance.pick(operations, [
    'setCenter',
    'setZoom',
    'setBearing',
    'setPitch'
]);
var empty = emptyStyle();
var Style = function (Evented) {
    function Style(map, options) {
        var this$1 = this;
        if (options === void 0)
            options = {};
        Evented.call(this);
        this.map = map;
        this.dispatcher = new Dispatcher(getGlobalWorkerPool(), this);
        this.imageManager = new ImageManager();
        this.imageManager.setEventedParent(this);
        this.glyphManager = new GlyphManager(map._requestManager, options.localIdeographFontFamily);
        this.lineAtlas = new LineAtlas(256, 512);
        this.crossTileSymbolIndex = new CrossTileSymbolIndex();
        this._layers = {};
        this._serializedLayers = {};
        this._order = [];
        this.sourceCaches = {};
        this.zoomHistory = new performance.ZoomHistory();
        this._loaded = false;
        this._availableImages = [];
        this._resetUpdates();
        this.dispatcher.broadcast('setReferrer', performance.getReferrer());
        var self = this;
        this._rtlTextPluginCallback = Style.registerForPluginStateChange(function (event) {
            var state = {
                pluginStatus: event.pluginStatus,
                pluginURL: event.pluginURL
            };
            self.dispatcher.broadcast('syncRTLPluginState', state, function (err, results) {
                performance.triggerPluginCompletionEvent(err);
                if (results) {
                    var allComplete = results.every(function (elem) {
                        return elem;
                    });
                    if (allComplete) {
                        for (var id in self.sourceCaches) {
                            self.sourceCaches[id].reload();
                        }
                    }
                }
            });
        });
        this.on('data', function (event) {
            if (event.dataType !== 'source' || event.sourceDataType !== 'metadata') {
                return;
            }
            var sourceCache = this$1.sourceCaches[event.sourceId];
            if (!sourceCache) {
                return;
            }
            var source = sourceCache.getSource();
            if (!source || !source.vectorLayerIds) {
                return;
            }
            for (var layerId in this$1._layers) {
                var layer = this$1._layers[layerId];
                if (layer.source === source.id) {
                    this$1._validateLayer(layer);
                }
            }
        });
    }
    if (Evented)
        Style.__proto__ = Evented;
    Style.prototype = Object.create(Evented && Evented.prototype);
    Style.prototype.constructor = Style;
    Style.prototype.loadURL = function loadURL(url, options) {
        var this$1 = this;
        if (options === void 0)
            options = {};
        this.fire(new performance.Event('dataloading', { dataType: 'style' }));
        var validate = typeof options.validate === 'boolean' ? options.validate : !performance.isMapboxURL(url);
        url = this.map._requestManager.normalizeStyleURL(url, options.accessToken);
        var request = this.map._requestManager.transformRequest(url, performance.ResourceType.Style);
        this._request = performance.getJSON(request, function (error, json) {
            this$1._request = null;
            if (error) {
                this$1.fire(new performance.ErrorEvent(error));
            } else if (json) {
                this$1._load(json, validate);
            }
        });
    };
    Style.prototype.loadJSON = function loadJSON(json, options) {
        var this$1 = this;
        if (options === void 0)
            options = {};
        this.fire(new performance.Event('dataloading', { dataType: 'style' }));
        this._request = performance.browser.frame(function () {
            this$1._request = null;
            this$1._load(json, options.validate !== false);
        });
    };
    Style.prototype.loadEmpty = function loadEmpty() {
        this.fire(new performance.Event('dataloading', { dataType: 'style' }));
        this._load(empty, false);
    };
    Style.prototype._load = function _load(json, validate) {
        if (validate && emitValidationErrors(this, performance.validateStyle(json))) {
            return;
        }
        this._loaded = true;
        this.stylesheet = json;
        for (var id in json.sources) {
            this.addSource(id, json.sources[id], { validate: false });
        }
        if (json.sprite) {
            this._loadSprite(json.sprite);
        } else {
            this.imageManager.setLoaded(true);
        }
        this.glyphManager.setURL(json.glyphs);
        var layers = derefLayers(this.stylesheet.layers);
        this._order = layers.map(function (layer) {
            return layer.id;
        });
        this._layers = {};
        this._serializedLayers = {};
        for (var i = 0, list = layers; i < list.length; i += 1) {
            var layer = list[i];
            layer = performance.createStyleLayer(layer);
            layer.setEventedParent(this, { layer: { id: layer.id } });
            this._layers[layer.id] = layer;
            this._serializedLayers[layer.id] = layer.serialize();
        }
        this.dispatcher.broadcast('setLayers', this._serializeLayers(this._order));
        this.light = new Light(this.stylesheet.light);
        this.fire(new performance.Event('data', { dataType: 'style' }));
        this.fire(new performance.Event('style.load'));
    };
    Style.prototype._loadSprite = function _loadSprite(url) {
        var this$1 = this;
        this._spriteRequest = loadSprite(url, this.map._requestManager, function (err, images) {
            this$1._spriteRequest = null;
            if (err) {
                this$1.fire(new performance.ErrorEvent(err));
            } else if (images) {
                for (var id in images) {
                    this$1.imageManager.addImage(id, images[id]);
                }
            }
            this$1.imageManager.setLoaded(true);
            this$1._availableImages = this$1.imageManager.listImages();
            this$1.dispatcher.broadcast('setImages', this$1._availableImages);
            this$1.fire(new performance.Event('data', { dataType: 'style' }));
        });
    };
    Style.prototype._validateLayer = function _validateLayer(layer) {
        var sourceCache = this.sourceCaches[layer.source];
        if (!sourceCache) {
            return;
        }
        var sourceLayer = layer.sourceLayer;
        if (!sourceLayer) {
            return;
        }
        var source = sourceCache.getSource();
        if (source.type === 'geojson' || source.vectorLayerIds && source.vectorLayerIds.indexOf(sourceLayer) === -1) {
            this.fire(new performance.ErrorEvent(new Error('Source layer "' + sourceLayer + '" ' + 'does not exist on source "' + source.id + '" ' + 'as specified by style layer "' + layer.id + '"')));
        }
    };
    Style.prototype.loaded = function loaded() {
        if (!this._loaded) {
            return false;
        }
        if (Object.keys(this._updatedSources).length) {
            return false;
        }
        for (var id in this.sourceCaches) {
            if (!this.sourceCaches[id].loaded()) {
                return false;
            }
        }
        if (!this.imageManager.isLoaded()) {
            return false;
        }
        return true;
    };
    Style.prototype._serializeLayers = function _serializeLayers(ids) {
        var serializedLayers = [];
        for (var i = 0, list = ids; i < list.length; i += 1) {
            var id = list[i];
            var layer = this._layers[id];
            if (layer.type !== 'custom') {
                serializedLayers.push(layer.serialize());
            }
        }
        return serializedLayers;
    };
    Style.prototype.hasTransitions = function hasTransitions() {
        if (this.light && this.light.hasTransition()) {
            return true;
        }
        for (var id in this.sourceCaches) {
            if (this.sourceCaches[id].hasTransition()) {
                return true;
            }
        }
        for (var id$1 in this._layers) {
            if (this._layers[id$1].hasTransition()) {
                return true;
            }
        }
        return false;
    };
    Style.prototype._checkLoaded = function _checkLoaded() {
        if (!this._loaded) {
            throw new Error('Style is not done loading');
        }
    };
    Style.prototype.update = function update(parameters) {
        if (!this._loaded) {
            return;
        }
        var changed = this._changed;
        if (this._changed) {
            var updatedIds = Object.keys(this._updatedLayers);
            var removedIds = Object.keys(this._removedLayers);
            if (updatedIds.length || removedIds.length) {
                this._updateWorkerLayers(updatedIds, removedIds);
            }
            for (var id in this._updatedSources) {
                var action = this._updatedSources[id];
                if (action === 'reload') {
                    this._reloadSource(id);
                } else if (action === 'clear') {
                    this._clearSource(id);
                }
            }
            this._updateTilesForChangedImages();
            for (var id$1 in this._updatedPaintProps) {
                this._layers[id$1].updateTransitions(parameters);
            }
            this.light.updateTransitions(parameters);
            this._resetUpdates();
        }
        var sourcesUsedBefore = {};
        for (var sourceId in this.sourceCaches) {
            var sourceCache = this.sourceCaches[sourceId];
            sourcesUsedBefore[sourceId] = sourceCache.used;
            sourceCache.used = false;
        }
        for (var i = 0, list = this._order; i < list.length; i += 1) {
            var layerId = list[i];
            var layer = this._layers[layerId];
            layer.recalculate(parameters, this._availableImages);
            if (!layer.isHidden(parameters.zoom) && layer.source) {
                this.sourceCaches[layer.source].used = true;
            }
        }
        for (var sourceId$1 in sourcesUsedBefore) {
            var sourceCache$1 = this.sourceCaches[sourceId$1];
            if (sourcesUsedBefore[sourceId$1] !== sourceCache$1.used) {
                sourceCache$1.fire(new performance.Event('data', {
                    sourceDataType: 'visibility',
                    dataType: 'source',
                    sourceId: sourceId$1
                }));
            }
        }
        this.light.recalculate(parameters);
        this.z = parameters.zoom;
        if (changed) {
            this.fire(new performance.Event('data', { dataType: 'style' }));
        }
    };
    Style.prototype._updateTilesForChangedImages = function _updateTilesForChangedImages() {
        var changedImages = Object.keys(this._changedImages);
        if (changedImages.length) {
            for (var name in this.sourceCaches) {
                this.sourceCaches[name].reloadTilesForDependencies([
                    'icons',
                    'patterns'
                ], changedImages);
            }
            this._changedImages = {};
        }
    };
    Style.prototype._updateWorkerLayers = function _updateWorkerLayers(updatedIds, removedIds) {
        this.dispatcher.broadcast('updateLayers', {
            layers: this._serializeLayers(updatedIds),
            removedIds: removedIds
        });
    };
    Style.prototype._resetUpdates = function _resetUpdates() {
        this._changed = false;
        this._updatedLayers = {};
        this._removedLayers = {};
        this._updatedSources = {};
        this._updatedPaintProps = {};
        this._changedImages = {};
    };
    Style.prototype.setState = function setState(nextState) {
        var this$1 = this;
        this._checkLoaded();
        if (emitValidationErrors(this, performance.validateStyle(nextState))) {
            return false;
        }
        nextState = performance.clone$1(nextState);
        nextState.layers = derefLayers(nextState.layers);
        var changes = diffStyles(this.serialize(), nextState).filter(function (op) {
            return !(op.command in ignoredDiffOperations);
        });
        if (changes.length === 0) {
            return false;
        }
        var unimplementedOps = changes.filter(function (op) {
            return !(op.command in supportedDiffOperations);
        });
        if (unimplementedOps.length > 0) {
            throw new Error('Unimplemented: ' + unimplementedOps.map(function (op) {
                return op.command;
            }).join(', ') + '.');
        }
        changes.forEach(function (op) {
            if (op.command === 'setTransition') {
                return;
            }
            this$1[op.command].apply(this$1, op.args);
        });
        this.stylesheet = nextState;
        return true;
    };
    Style.prototype.addImage = function addImage(id, image) {
        if (this.getImage(id)) {
            return this.fire(new performance.ErrorEvent(new Error('An image with this name already exists.')));
        }
        this.imageManager.addImage(id, image);
        this._afterImageUpdated(id);
    };
    Style.prototype.updateImage = function updateImage(id, image) {
        this.imageManager.updateImage(id, image);
    };
    Style.prototype.getImage = function getImage(id) {
        return this.imageManager.getImage(id);
    };
    Style.prototype.removeImage = function removeImage(id) {
        if (!this.getImage(id)) {
            return this.fire(new performance.ErrorEvent(new Error('No image with this name exists.')));
        }
        this.imageManager.removeImage(id);
        this._afterImageUpdated(id);
    };
    Style.prototype._afterImageUpdated = function _afterImageUpdated(id) {
        this._availableImages = this.imageManager.listImages();
        this._changedImages[id] = true;
        this._changed = true;
        this.dispatcher.broadcast('setImages', this._availableImages);
        this.fire(new performance.Event('data', { dataType: 'style' }));
    };
    Style.prototype.listImages = function listImages() {
        this._checkLoaded();
        return this.imageManager.listImages();
    };
    Style.prototype.addSource = function addSource(id, source, options) {
        var this$1 = this;
        if (options === void 0)
            options = {};
        this._checkLoaded();
        if (this.sourceCaches[id] !== undefined) {
            throw new Error('There is already a source with this ID');
        }
        if (!source.type) {
            throw new Error('The type property must be defined, but only the following properties were given: ' + Object.keys(source).join(', ') + '.');
        }
        var builtIns = [
            'vector',
            'raster',
            'geojson',
            'video',
            'image'
        ];
        var shouldValidate = builtIns.indexOf(source.type) >= 0;
        if (shouldValidate && this._validate(performance.validateStyle.source, 'sources.' + id, source, null, options)) {
            return;
        }
        if (this.map && this.map._collectResourceTiming) {
            source.collectResourceTiming = true;
        }
        var sourceCache = this.sourceCaches[id] = new SourceCache(id, source, this.dispatcher);
        sourceCache.style = this;
        sourceCache.setEventedParent(this, function () {
            return {
                isSourceLoaded: this$1.loaded(),
                source: sourceCache.serialize(),
                sourceId: id
            };
        });
        sourceCache.onAdd(this.map);
        this._changed = true;
    };
    Style.prototype.removeSource = function removeSource(id) {
        this._checkLoaded();
        if (this.sourceCaches[id] === undefined) {
            throw new Error('There is no source with this ID');
        }
        for (var layerId in this._layers) {
            if (this._layers[layerId].source === id) {
                return this.fire(new performance.ErrorEvent(new Error('Source "' + id + '" cannot be removed while layer "' + layerId + '" is using it.')));
            }
        }
        var sourceCache = this.sourceCaches[id];
        delete this.sourceCaches[id];
        delete this._updatedSources[id];
        sourceCache.fire(new performance.Event('data', {
            sourceDataType: 'metadata',
            dataType: 'source',
            sourceId: id
        }));
        sourceCache.setEventedParent(null);
        sourceCache.clearTiles();
        if (sourceCache.onRemove) {
            sourceCache.onRemove(this.map);
        }
        this._changed = true;
    };
    Style.prototype.setGeoJSONSourceData = function setGeoJSONSourceData(id, data) {
        this._checkLoaded();
        var geojsonSource = this.sourceCaches[id].getSource();
        geojsonSource.setData(data);
        this._changed = true;
    };
    Style.prototype.getSource = function getSource(id) {
        return this.sourceCaches[id] && this.sourceCaches[id].getSource();
    };
    Style.prototype.addLayer = function addLayer(layerObject, before, options) {
        if (options === void 0)
            options = {};
        this._checkLoaded();
        var id = layerObject.id;
        if (this.getLayer(id)) {
            this.fire(new performance.ErrorEvent(new Error('Layer with id "' + id + '" already exists on this map')));
            return;
        }
        var layer;
        if (layerObject.type === 'custom') {
            if (emitValidationErrors(this, performance.validateCustomStyleLayer(layerObject))) {
                return;
            }
            layer = performance.createStyleLayer(layerObject);
        } else {
            if (typeof layerObject.source === 'object') {
                this.addSource(id, layerObject.source);
                layerObject = performance.clone$1(layerObject);
                layerObject = performance.extend(layerObject, { source: id });
            }
            if (this._validate(performance.validateStyle.layer, 'layers.' + id, layerObject, { arrayIndex: -1 }, options)) {
                return;
            }
            layer = performance.createStyleLayer(layerObject);
            this._validateLayer(layer);
            layer.setEventedParent(this, { layer: { id: id } });
            this._serializedLayers[layer.id] = layer.serialize();
        }
        var index = before ? this._order.indexOf(before) : this._order.length;
        if (before && index === -1) {
            this.fire(new performance.ErrorEvent(new Error('Layer with id "' + before + '" does not exist on this map.')));
            return;
        }
        this._order.splice(index, 0, id);
        this._layerOrderChanged = true;
        this._layers[id] = layer;
        if (this._removedLayers[id] && layer.source && layer.type !== 'custom') {
            var removed = this._removedLayers[id];
            delete this._removedLayers[id];
            if (removed.type !== layer.type) {
                this._updatedSources[layer.source] = 'clear';
            } else {
                this._updatedSources[layer.source] = 'reload';
                this.sourceCaches[layer.source].pause();
            }
        }
        this._updateLayer(layer);
        if (layer.onAdd) {
            layer.onAdd(this.map);
        }
    };
    Style.prototype.moveLayer = function moveLayer(id, before) {
        this._checkLoaded();
        this._changed = true;
        var layer = this._layers[id];
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + id + '\' does not exist in the map\'s style and cannot be moved.')));
            return;
        }
        if (id === before) {
            return;
        }
        var index = this._order.indexOf(id);
        this._order.splice(index, 1);
        var newIndex = before ? this._order.indexOf(before) : this._order.length;
        if (before && newIndex === -1) {
            this.fire(new performance.ErrorEvent(new Error('Layer with id "' + before + '" does not exist on this map.')));
            return;
        }
        this._order.splice(newIndex, 0, id);
        this._layerOrderChanged = true;
    };
    Style.prototype.removeLayer = function removeLayer(id) {
        this._checkLoaded();
        var layer = this._layers[id];
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + id + '\' does not exist in the map\'s style and cannot be removed.')));
            return;
        }
        layer.setEventedParent(null);
        var index = this._order.indexOf(id);
        this._order.splice(index, 1);
        this._layerOrderChanged = true;
        this._changed = true;
        this._removedLayers[id] = layer;
        delete this._layers[id];
        delete this._serializedLayers[id];
        delete this._updatedLayers[id];
        delete this._updatedPaintProps[id];
        if (layer.onRemove) {
            layer.onRemove(this.map);
        }
    };
    Style.prototype.getLayer = function getLayer(id) {
        return this._layers[id];
    };
    Style.prototype.hasLayer = function hasLayer(id) {
        return id in this._layers;
    };
    Style.prototype.setLayerZoomRange = function setLayerZoomRange(layerId, minzoom, maxzoom) {
        this._checkLoaded();
        var layer = this.getLayer(layerId);
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + layerId + '\' does not exist in the map\'s style and cannot have zoom extent.')));
            return;
        }
        if (layer.minzoom === minzoom && layer.maxzoom === maxzoom) {
            return;
        }
        if (minzoom != null) {
            layer.minzoom = minzoom;
        }
        if (maxzoom != null) {
            layer.maxzoom = maxzoom;
        }
        this._updateLayer(layer);
    };
    Style.prototype.setFilter = function setFilter(layerId, filter, options) {
        if (options === void 0)
            options = {};
        this._checkLoaded();
        var layer = this.getLayer(layerId);
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + layerId + '\' does not exist in the map\'s style and cannot be filtered.')));
            return;
        }
        if (performance.deepEqual(layer.filter, filter)) {
            return;
        }
        if (filter === null || filter === undefined) {
            layer.filter = undefined;
            this._updateLayer(layer);
            return;
        }
        if (this._validate(performance.validateStyle.filter, 'layers.' + layer.id + '.filter', filter, null, options)) {
            return;
        }
        layer.filter = performance.clone$1(filter);
        this._updateLayer(layer);
    };
    Style.prototype.getFilter = function getFilter(layer) {
        return performance.clone$1(this.getLayer(layer).filter);
    };
    Style.prototype.setLayoutProperty = function setLayoutProperty(layerId, name, value, options) {
        if (options === void 0)
            options = {};
        this._checkLoaded();
        var layer = this.getLayer(layerId);
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + layerId + '\' does not exist in the map\'s style and cannot be styled.')));
            return;
        }
        if (performance.deepEqual(layer.getLayoutProperty(name), value)) {
            return;
        }
        layer.setLayoutProperty(name, value, options);
        this._updateLayer(layer);
    };
    Style.prototype.getLayoutProperty = function getLayoutProperty(layerId, name) {
        var layer = this.getLayer(layerId);
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + layerId + '\' does not exist in the map\'s style.')));
            return;
        }
        return layer.getLayoutProperty(name);
    };
    Style.prototype.setPaintProperty = function setPaintProperty(layerId, name, value, options) {
        if (options === void 0)
            options = {};
        this._checkLoaded();
        var layer = this.getLayer(layerId);
        if (!layer) {
            this.fire(new performance.ErrorEvent(new Error('The layer \'' + layerId + '\' does not exist in the map\'s style and cannot be styled.')));
            return;
        }
        if (performance.deepEqual(layer.getPaintProperty(name), value)) {
            return;
        }
        var requiresRelayout = layer.setPaintProperty(name, value, options);
        if (requiresRelayout) {
            this._updateLayer(layer);
        }
        this._changed = true;
        this._updatedPaintProps[layerId] = true;
    };
    Style.prototype.getPaintProperty = function getPaintProperty(layer, name) {
        return this.getLayer(layer).getPaintProperty(name);
    };
    Style.prototype.setFeatureState = function setFeatureState(target, state) {
        this._checkLoaded();
        var sourceId = target.source;
        var sourceLayer = target.sourceLayer;
        var sourceCache = this.sourceCaches[sourceId];
        if (sourceCache === undefined) {
            this.fire(new performance.ErrorEvent(new Error('The source \'' + sourceId + '\' does not exist in the map\'s style.')));
            return;
        }
        var sourceType = sourceCache.getSource().type;
        if (sourceType === 'geojson' && sourceLayer) {
            this.fire(new performance.ErrorEvent(new Error('GeoJSON sources cannot have a sourceLayer parameter.')));
            return;
        }
        if (sourceType === 'vector' && !sourceLayer) {
            this.fire(new performance.ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
            return;
        }
        if (target.id === undefined) {
            this.fire(new performance.ErrorEvent(new Error('The feature id parameter must be provided.')));
        }
        sourceCache.setFeatureState(sourceLayer, target.id, state);
    };
    Style.prototype.removeFeatureState = function removeFeatureState(target, key) {
        this._checkLoaded();
        var sourceId = target.source;
        var sourceCache = this.sourceCaches[sourceId];
        if (sourceCache === undefined) {
            this.fire(new performance.ErrorEvent(new Error('The source \'' + sourceId + '\' does not exist in the map\'s style.')));
            return;
        }
        var sourceType = sourceCache.getSource().type;
        var sourceLayer = sourceType === 'vector' ? target.sourceLayer : undefined;
        if (sourceType === 'vector' && !sourceLayer) {
            this.fire(new performance.ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
            return;
        }
        if (key && (typeof target.id !== 'string' && typeof target.id !== 'number')) {
            this.fire(new performance.ErrorEvent(new Error('A feature id is required to remove its specific state property.')));
            return;
        }
        sourceCache.removeFeatureState(sourceLayer, target.id, key);
    };
    Style.prototype.getFeatureState = function getFeatureState(target) {
        this._checkLoaded();
        var sourceId = target.source;
        var sourceLayer = target.sourceLayer;
        var sourceCache = this.sourceCaches[sourceId];
        if (sourceCache === undefined) {
            this.fire(new performance.ErrorEvent(new Error('The source \'' + sourceId + '\' does not exist in the map\'s style.')));
            return;
        }
        var sourceType = sourceCache.getSource().type;
        if (sourceType === 'vector' && !sourceLayer) {
            this.fire(new performance.ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
            return;
        }
        if (target.id === undefined) {
            this.fire(new performance.ErrorEvent(new Error('The feature id parameter must be provided.')));
        }
        return sourceCache.getFeatureState(sourceLayer, target.id);
    };
    Style.prototype.getTransition = function getTransition() {
        return performance.extend({
            duration: 300,
            delay: 0
        }, this.stylesheet && this.stylesheet.transition);
    };
    Style.prototype.serialize = function serialize() {
        return performance.filterObject({
            version: this.stylesheet.version,
            name: this.stylesheet.name,
            metadata: this.stylesheet.metadata,
            light: this.stylesheet.light,
            center: this.stylesheet.center,
            zoom: this.stylesheet.zoom,
            bearing: this.stylesheet.bearing,
            pitch: this.stylesheet.pitch,
            sprite: this.stylesheet.sprite,
            glyphs: this.stylesheet.glyphs,
            transition: this.stylesheet.transition,
            sources: performance.mapObject(this.sourceCaches, function (source) {
                return source.serialize();
            }),
            layers: this._serializeLayers(this._order)
        }, function (value) {
            return value !== undefined;
        });
    };
    Style.prototype._updateLayer = function _updateLayer(layer) {
        this._updatedLayers[layer.id] = true;
        if (layer.source && !this._updatedSources[layer.source] && this.sourceCaches[layer.source].getSource().type !== 'raster') {
            this._updatedSources[layer.source] = 'reload';
            this.sourceCaches[layer.source].pause();
        }
        this._changed = true;
    };
    Style.prototype._flattenAndSortRenderedFeatures = function _flattenAndSortRenderedFeatures(sourceResults) {
        var this$1 = this;
        var isLayer3D = function (layerId) {
            return this$1._layers[layerId].type === 'fill-extrusion';
        };
        var layerIndex = {};
        var features3D = [];
        for (var l = this._order.length - 1; l >= 0; l--) {
            var layerId = this._order[l];
            if (isLayer3D(layerId)) {
                layerIndex[layerId] = l;
                for (var i$2 = 0, list$1 = sourceResults; i$2 < list$1.length; i$2 += 1) {
                    var sourceResult = list$1[i$2];
                    var layerFeatures = sourceResult[layerId];
                    if (layerFeatures) {
                        for (var i$1 = 0, list = layerFeatures; i$1 < list.length; i$1 += 1) {
                            var featureWrapper = list[i$1];
                            features3D.push(featureWrapper);
                        }
                    }
                }
            }
        }
        features3D.sort(function (a, b) {
            return b.intersectionZ - a.intersectionZ;
        });
        var features = [];
        for (var l$1 = this._order.length - 1; l$1 >= 0; l$1--) {
            var layerId$1 = this._order[l$1];
            if (isLayer3D(layerId$1)) {
                for (var i = features3D.length - 1; i >= 0; i--) {
                    var topmost3D = features3D[i].feature;
                    if (layerIndex[topmost3D.layer.id] < l$1) {
                        break;
                    }
                    features.push(topmost3D);
                    features3D.pop();
                }
            } else {
                for (var i$4 = 0, list$3 = sourceResults; i$4 < list$3.length; i$4 += 1) {
                    var sourceResult$1 = list$3[i$4];
                    var layerFeatures$1 = sourceResult$1[layerId$1];
                    if (layerFeatures$1) {
                        for (var i$3 = 0, list$2 = layerFeatures$1; i$3 < list$2.length; i$3 += 1) {
                            var featureWrapper$1 = list$2[i$3];
                            features.push(featureWrapper$1.feature);
                        }
                    }
                }
            }
        }
        return features;
    };
    Style.prototype.queryRenderedFeatures = function queryRenderedFeatures$1(queryGeometry, params, transform) {
        if (params && params.filter) {
            this._validate(performance.validateStyle.filter, 'queryRenderedFeatures.filter', params.filter, null, params);
        }
        var includedSources = {};
        if (params && params.layers) {
            if (!Array.isArray(params.layers)) {
                this.fire(new performance.ErrorEvent(new Error('parameters.layers must be an Array.')));
                return [];
            }
            for (var i = 0, list = params.layers; i < list.length; i += 1) {
                var layerId = list[i];
                var layer = this._layers[layerId];
                if (!layer) {
                    this.fire(new performance.ErrorEvent(new Error('The layer \'' + layerId + '\' does not exist in the map\'s style and cannot be queried for features.')));
                    return [];
                }
                includedSources[layer.source] = true;
            }
        }
        var sourceResults = [];
        params.availableImages = this._availableImages;
        for (var id in this.sourceCaches) {
            if (params.layers && !includedSources[id]) {
                continue;
            }
            sourceResults.push(queryRenderedFeatures(this.sourceCaches[id], this._layers, this._serializedLayers, queryGeometry, params, transform));
        }
        if (this.placement) {
            sourceResults.push(queryRenderedSymbols(this._layers, this._serializedLayers, this.sourceCaches, queryGeometry, params, this.placement.collisionIndex, this.placement.retainedQueryData));
        }
        return this._flattenAndSortRenderedFeatures(sourceResults);
    };
    Style.prototype.querySourceFeatures = function querySourceFeatures$1(sourceID, params) {
        if (params && params.filter) {
            this._validate(performance.validateStyle.filter, 'querySourceFeatures.filter', params.filter, null, params);
        }
        var sourceCache = this.sourceCaches[sourceID];
        return sourceCache ? querySourceFeatures(sourceCache, params) : [];
    };
    Style.prototype.addSourceType = function addSourceType(name, SourceType, callback) {
        if (Style.getSourceType(name)) {
            return callback(new Error('A source type called "' + name + '" already exists.'));
        }
        Style.setSourceType(name, SourceType);
        if (!SourceType.workerSourceURL) {
            return callback(null, null);
        }
        this.dispatcher.broadcast('loadWorkerSource', {
            name: name,
            url: SourceType.workerSourceURL
        }, callback);
    };
    Style.prototype.getLight = function getLight() {
        return this.light.getLight();
    };
    Style.prototype.setLight = function setLight(lightOptions, options) {
        if (options === void 0)
            options = {};
        this._checkLoaded();
        var light = this.light.getLight();
        var _update = false;
        for (var key in lightOptions) {
            if (!performance.deepEqual(lightOptions[key], light[key])) {
                _update = true;
                break;
            }
        }
        if (!_update) {
            return;
        }
        var parameters = {
            now: performance.browser.now(),
            transition: performance.extend({
                duration: 300,
                delay: 0
            }, this.stylesheet.transition)
        };
        this.light.setLight(lightOptions, options);
        this.light.updateTransitions(parameters);
    };
    Style.prototype._validate = function _validate(validate, key, value, props, options) {
        if (options === void 0)
            options = {};
        if (options && options.validate === false) {
            return false;
        }
        return emitValidationErrors(this, validate.call(performance.validateStyle, performance.extend({
            key: key,
            style: this.serialize(),
            value: value,
            styleSpec: performance.styleSpec
        }, props)));
    };
    Style.prototype._remove = function _remove() {
        if (this._request) {
            this._request.cancel();
            this._request = null;
        }
        if (this._spriteRequest) {
            this._spriteRequest.cancel();
            this._spriteRequest = null;
        }
        performance.evented.off('pluginStateChange', this._rtlTextPluginCallback);
        for (var layerId in this._layers) {
            var layer = this._layers[layerId];
            layer.setEventedParent(null);
        }
        for (var id in this.sourceCaches) {
            this.sourceCaches[id].clearTiles();
            this.sourceCaches[id].setEventedParent(null);
        }
        this.imageManager.setEventedParent(null);
        this.setEventedParent(null);
        this.dispatcher.remove();
    };
    Style.prototype._clearSource = function _clearSource(id) {
        this.sourceCaches[id].clearTiles();
    };
    Style.prototype._reloadSource = function _reloadSource(id) {
        this.sourceCaches[id].resume();
        this.sourceCaches[id].reload();
    };
    Style.prototype._updateSources = function _updateSources(transform) {
        for (var id in this.sourceCaches) {
            this.sourceCaches[id].update(transform);
        }
    };
    Style.prototype._generateCollisionBoxes = function _generateCollisionBoxes() {
        for (var id in this.sourceCaches) {
            this._reloadSource(id);
        }
    };
    Style.prototype._updatePlacement = function _updatePlacement(transform, showCollisionBoxes, fadeDuration, crossSourceCollisions, forceFullPlacement) {
        if (forceFullPlacement === void 0)
            forceFullPlacement = false;
        var symbolBucketsChanged = false;
        var placementCommitted = false;
        var layerTiles = {};
        for (var i = 0, list = this._order; i < list.length; i += 1) {
            var layerID = list[i];
            var styleLayer = this._layers[layerID];
            if (styleLayer.type !== 'symbol') {
                continue;
            }
            if (!layerTiles[styleLayer.source]) {
                var sourceCache = this.sourceCaches[styleLayer.source];
                layerTiles[styleLayer.source] = sourceCache.getRenderableIds(true).map(function (id) {
                    return sourceCache.getTileByID(id);
                }).sort(function (a, b) {
                    return b.tileID.overscaledZ - a.tileID.overscaledZ || (a.tileID.isLessThan(b.tileID) ? -1 : 1);
                });
            }
            var layerBucketsChanged = this.crossTileSymbolIndex.addLayer(styleLayer, layerTiles[styleLayer.source], transform.center.lng);
            symbolBucketsChanged = symbolBucketsChanged || layerBucketsChanged;
        }
        this.crossTileSymbolIndex.pruneUnusedLayers(this._order);
        forceFullPlacement = forceFullPlacement || this._layerOrderChanged || fadeDuration === 0;
        if (forceFullPlacement || !this.pauseablePlacement || this.pauseablePlacement.isDone() && !this.placement.stillRecent(performance.browser.now(), transform.zoom)) {
            this.pauseablePlacement = new PauseablePlacement(transform, this._order, forceFullPlacement, showCollisionBoxes, fadeDuration, crossSourceCollisions, this.placement);
            this._layerOrderChanged = false;
        }
        if (this.pauseablePlacement.isDone()) {
            this.placement.setStale();
        } else {
            this.pauseablePlacement.continuePlacement(this._order, this._layers, layerTiles);
            if (this.pauseablePlacement.isDone()) {
                this.placement = this.pauseablePlacement.commit(performance.browser.now());
                placementCommitted = true;
            }
            if (symbolBucketsChanged) {
                this.pauseablePlacement.placement.setStale();
            }
        }
        if (placementCommitted || symbolBucketsChanged) {
            for (var i$1 = 0, list$1 = this._order; i$1 < list$1.length; i$1 += 1) {
                var layerID$1 = list$1[i$1];
                var styleLayer$1 = this._layers[layerID$1];
                if (styleLayer$1.type !== 'symbol') {
                    continue;
                }
                this.placement.updateLayerOpacities(styleLayer$1, layerTiles[styleLayer$1.source]);
            }
        }
        var needsRerender = !this.pauseablePlacement.isDone() || this.placement.hasTransitions(performance.browser.now());
        return needsRerender;
    };
    Style.prototype._releaseSymbolFadeTiles = function _releaseSymbolFadeTiles() {
        for (var id in this.sourceCaches) {
            this.sourceCaches[id].releaseSymbolFadeTiles();
        }
    };
    Style.prototype.getImages = function getImages(mapId, params, callback) {
        this.imageManager.getImages(params.icons, callback);
        this._updateTilesForChangedImages();
        var sourceCache = this.sourceCaches[params.source];
        if (sourceCache) {
            sourceCache.setDependencies(params.tileID.key, params.type, params.icons);
        }
    };
    Style.prototype.getGlyphs = function getGlyphs(mapId, params, callback) {
        this.glyphManager.getGlyphs(params.stacks, callback);
    };
    Style.prototype.getResource = function getResource(mapId, params, callback) {
        return performance.makeRequest(params, callback);
    };
    return Style;
}(performance.Evented);
Style.getSourceType = getType;
Style.setSourceType = setType;
Style.registerForPluginStateChange = performance.registerForPluginStateChange;

var posAttributes = performance.createLayout([{
        name: 'a_pos',
        type: 'Int16',
        components: 2
    }]);

var preludeFrag = "#ifdef GL_ES\nprecision mediump float;\n#else\n#if !defined(lowp)\n#define lowp\n#endif\n#if !defined(mediump)\n#define mediump\n#endif\n#if !defined(highp)\n#define highp\n#endif\n#endif";

var preludeVert = "#ifdef GL_ES\nprecision highp float;\n#else\n#if !defined(lowp)\n#define lowp\n#endif\n#if !defined(mediump)\n#define mediump\n#endif\n#if !defined(highp)\n#define highp\n#endif\n#endif\nvec2 unpack_float(const float packedValue) {int packedIntValue=int(packedValue);int v0=packedIntValue/256;return vec2(v0,packedIntValue-v0*256);}vec2 unpack_opacity(const float packedOpacity) {int intOpacity=int(packedOpacity)/2;return vec2(float(intOpacity)/127.0,mod(packedOpacity,2.0));}vec4 decode_color(const vec2 encodedColor) {return vec4(unpack_float(encodedColor[0])/255.0,unpack_float(encodedColor[1])/255.0\n);}float unpack_mix_vec2(const vec2 packedValue,const float t) {return mix(packedValue[0],packedValue[1],t);}vec4 unpack_mix_color(const vec4 packedColors,const float t) {vec4 minColor=decode_color(vec2(packedColors[0],packedColors[1]));vec4 maxColor=decode_color(vec2(packedColors[2],packedColors[3]));return mix(minColor,maxColor,t);}vec2 get_pattern_pos(const vec2 pixel_coord_upper,const vec2 pixel_coord_lower,const vec2 pattern_size,const float tile_units_to_pixels,const vec2 pos) {vec2 offset=mod(mod(mod(pixel_coord_upper,pattern_size)*256.0,pattern_size)*256.0+pixel_coord_lower,pattern_size);return (tile_units_to_pixels*pos+offset)/pattern_size;}";

var backgroundFrag = "uniform vec4 u_color;uniform float u_opacity;void main() {gl_FragColor=u_color*u_opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var backgroundVert = "attribute vec2 a_pos;uniform mat4 u_matrix;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);}";

var backgroundPatternFrag = "uniform vec2 u_pattern_tl_a;uniform vec2 u_pattern_br_a;uniform vec2 u_pattern_tl_b;uniform vec2 u_pattern_br_b;uniform vec2 u_texsize;uniform float u_mix;uniform float u_opacity;uniform sampler2D u_image;varying vec2 v_pos_a;varying vec2 v_pos_b;void main() {vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(u_pattern_tl_a/u_texsize,u_pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(u_pattern_tl_b/u_texsize,u_pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);gl_FragColor=mix(color1,color2,u_mix)*u_opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var backgroundPatternVert = "uniform mat4 u_matrix;uniform vec2 u_pattern_size_a;uniform vec2 u_pattern_size_b;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform float u_scale_a;uniform float u_scale_b;uniform float u_tile_units_to_pixels;attribute vec2 a_pos;varying vec2 v_pos_a;varying vec2 v_pos_b;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,u_scale_a*u_pattern_size_a,u_tile_units_to_pixels,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,u_scale_b*u_pattern_size_b,u_tile_units_to_pixels,a_pos);}";

var circleFrag = "varying vec3 v_data;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define mediump float radius\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define highp vec4 stroke_color\n#pragma mapbox: define mediump float stroke_width\n#pragma mapbox: define lowp float stroke_opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize mediump float radius\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize highp vec4 stroke_color\n#pragma mapbox: initialize mediump float stroke_width\n#pragma mapbox: initialize lowp float stroke_opacity\nvec2 extrude=v_data.xy;float extrude_length=length(extrude);lowp float antialiasblur=v_data.z;float antialiased_blur=-max(blur,antialiasblur);float opacity_t=smoothstep(0.0,antialiased_blur,extrude_length-1.0);float color_t=stroke_width < 0.01 ? 0.0 : smoothstep(antialiased_blur,0.0,extrude_length-radius/(radius+stroke_width));gl_FragColor=opacity_t*mix(color*opacity,stroke_color*stroke_opacity,color_t);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var circleVert = "uniform mat4 u_matrix;uniform bool u_scale_with_map;uniform bool u_pitch_with_map;uniform vec2 u_extrude_scale;uniform lowp float u_device_pixel_ratio;uniform highp float u_camera_to_center_distance;attribute vec2 a_pos;varying vec3 v_data;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define mediump float radius\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define highp vec4 stroke_color\n#pragma mapbox: define mediump float stroke_width\n#pragma mapbox: define lowp float stroke_opacity\nvoid main(void) {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize mediump float radius\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize highp vec4 stroke_color\n#pragma mapbox: initialize mediump float stroke_width\n#pragma mapbox: initialize lowp float stroke_opacity\nvec2 extrude=vec2(mod(a_pos,2.0)*2.0-1.0);vec2 circle_center=floor(a_pos*0.5);if (u_pitch_with_map) {vec2 corner_position=circle_center;if (u_scale_with_map) {corner_position+=extrude*(radius+stroke_width)*u_extrude_scale;} else {vec4 projected_center=u_matrix*vec4(circle_center,0,1);corner_position+=extrude*(radius+stroke_width)*u_extrude_scale*(projected_center.w/u_camera_to_center_distance);}gl_Position=u_matrix*vec4(corner_position,0,1);} else {gl_Position=u_matrix*vec4(circle_center,0,1);if (u_scale_with_map) {gl_Position.xy+=extrude*(radius+stroke_width)*u_extrude_scale*u_camera_to_center_distance;} else {gl_Position.xy+=extrude*(radius+stroke_width)*u_extrude_scale*gl_Position.w;}}lowp float antialiasblur=1.0/u_device_pixel_ratio/(radius+stroke_width);v_data=vec3(extrude.x,extrude.y,antialiasblur);}";

var clippingMaskFrag = "void main() {gl_FragColor=vec4(1.0);}";

var clippingMaskVert = "attribute vec2 a_pos;uniform mat4 u_matrix;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);}";

var heatmapFrag = "uniform highp float u_intensity;varying vec2 v_extrude;\n#pragma mapbox: define highp float weight\n#define GAUSS_COEF 0.3989422804014327\nvoid main() {\n#pragma mapbox: initialize highp float weight\nfloat d=-0.5*3.0*3.0*dot(v_extrude,v_extrude);float val=weight*u_intensity*GAUSS_COEF*exp(d);gl_FragColor=vec4(val,1.0,1.0,1.0);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var heatmapVert = "uniform mat4 u_matrix;uniform float u_extrude_scale;uniform float u_opacity;uniform float u_intensity;attribute vec2 a_pos;varying vec2 v_extrude;\n#pragma mapbox: define highp float weight\n#pragma mapbox: define mediump float radius\nconst highp float ZERO=1.0/255.0/16.0;\n#define GAUSS_COEF 0.3989422804014327\nvoid main(void) {\n#pragma mapbox: initialize highp float weight\n#pragma mapbox: initialize mediump float radius\nvec2 unscaled_extrude=vec2(mod(a_pos,2.0)*2.0-1.0);float S=sqrt(-2.0*log(ZERO/weight/u_intensity/GAUSS_COEF))/3.0;v_extrude=S*unscaled_extrude;vec2 extrude=v_extrude*radius*u_extrude_scale;vec4 pos=vec4(floor(a_pos*0.5)+extrude,0,1);gl_Position=u_matrix*pos;}";

var heatmapTextureFrag = "uniform sampler2D u_image;uniform sampler2D u_color_ramp;uniform float u_opacity;varying vec2 v_pos;void main() {float t=texture2D(u_image,v_pos).r;vec4 color=texture2D(u_color_ramp,vec2(t,0.5));gl_FragColor=color*u_opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(0.0);\n#endif\n}";

var heatmapTextureVert = "uniform mat4 u_matrix;uniform vec2 u_world;attribute vec2 a_pos;varying vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos*u_world,0,1);v_pos.x=a_pos.x;v_pos.y=1.0-a_pos.y;}";

var collisionBoxFrag = "varying float v_placed;varying float v_notUsed;void main() {float alpha=0.5;gl_FragColor=vec4(1.0,0.0,0.0,1.0)*alpha;if (v_placed > 0.5) {gl_FragColor=vec4(0.0,0.0,1.0,0.5)*alpha;}if (v_notUsed > 0.5) {gl_FragColor*=.1;}}";

var collisionBoxVert = "attribute vec2 a_pos;attribute vec2 a_anchor_pos;attribute vec2 a_extrude;attribute vec2 a_placed;attribute vec2 a_shift;uniform mat4 u_matrix;uniform vec2 u_extrude_scale;uniform float u_camera_to_center_distance;varying float v_placed;varying float v_notUsed;void main() {vec4 projectedPoint=u_matrix*vec4(a_anchor_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float collision_perspective_ratio=clamp(0.5+0.5*(u_camera_to_center_distance/camera_to_anchor_distance),0.0,4.0);gl_Position=u_matrix*vec4(a_pos,0.0,1.0);gl_Position.xy+=(a_extrude+a_shift)*u_extrude_scale*gl_Position.w*collision_perspective_ratio;v_placed=a_placed.x;v_notUsed=a_placed.y;}";

var collisionCircleFrag = "varying float v_radius;varying vec2 v_extrude;varying float v_perspective_ratio;varying float v_collision;void main() {float alpha=0.5*min(v_perspective_ratio,1.0);float stroke_radius=0.9*max(v_perspective_ratio,1.0);float distance_to_center=length(v_extrude);float distance_to_edge=abs(distance_to_center-v_radius);float opacity_t=smoothstep(-stroke_radius,0.0,-distance_to_edge);vec4 color=mix(vec4(0.0,0.0,1.0,0.5),vec4(1.0,0.0,0.0,1.0),v_collision);gl_FragColor=color*alpha*opacity_t;}";

var collisionCircleVert = "attribute vec2 a_pos;attribute float a_radius;attribute vec2 a_flags;uniform mat4 u_matrix;uniform mat4 u_inv_matrix;uniform vec2 u_viewport_size;uniform float u_camera_to_center_distance;varying float v_radius;varying vec2 v_extrude;varying float v_perspective_ratio;varying float v_collision;vec3 toTilePosition(vec2 screenPos) {vec4 rayStart=u_inv_matrix*vec4(screenPos,-1.0,1.0);vec4 rayEnd  =u_inv_matrix*vec4(screenPos, 1.0,1.0);rayStart.xyz/=rayStart.w;rayEnd.xyz  /=rayEnd.w;highp float t=(0.0-rayStart.z)/(rayEnd.z-rayStart.z);return mix(rayStart.xyz,rayEnd.xyz,t);}void main() {vec2 quadCenterPos=a_pos;float radius=a_radius;float collision=a_flags.x;float vertexIdx=a_flags.y;vec2 quadVertexOffset=vec2(mix(-1.0,1.0,float(vertexIdx >=2.0)),mix(-1.0,1.0,float(vertexIdx >=1.0 && vertexIdx <=2.0)));vec2 quadVertexExtent=quadVertexOffset*radius;vec3 tilePos=toTilePosition(quadCenterPos);vec4 clipPos=u_matrix*vec4(tilePos,1.0);highp float camera_to_anchor_distance=clipPos.w;highp float collision_perspective_ratio=clamp(0.5+0.5*(u_camera_to_center_distance/camera_to_anchor_distance),0.0,4.0);float padding_factor=1.2;v_radius=radius;v_extrude=quadVertexExtent*padding_factor;v_perspective_ratio=collision_perspective_ratio;v_collision=collision;gl_Position=vec4(clipPos.xyz/clipPos.w,1.0)+vec4(quadVertexExtent*padding_factor/u_viewport_size*2.0,0.0,0.0);}";

var debugFrag = "uniform highp vec4 u_color;uniform sampler2D u_overlay;varying vec2 v_uv;void main() {vec4 overlay_color=texture2D(u_overlay,v_uv);gl_FragColor=mix(u_color,overlay_color,overlay_color.a);}";

var debugVert = "attribute vec2 a_pos;varying vec2 v_uv;uniform mat4 u_matrix;uniform float u_overlay_scale;void main() {v_uv=a_pos/8192.0;gl_Position=u_matrix*vec4(a_pos*u_overlay_scale,0,1);}";

var fillFrag = "#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float opacity\ngl_FragColor=color*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var fillVert = "attribute vec2 a_pos;uniform mat4 u_matrix;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float opacity\ngl_Position=u_matrix*vec4(a_pos,0,1);}";

var fillOutlineFrag = "varying vec2 v_pos;\n#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 outline_color\n#pragma mapbox: initialize lowp float opacity\nfloat dist=length(v_pos-gl_FragCoord.xy);float alpha=1.0-smoothstep(0.0,1.0,dist);gl_FragColor=outline_color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var fillOutlineVert = "attribute vec2 a_pos;uniform mat4 u_matrix;uniform vec2 u_world;varying vec2 v_pos;\n#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 outline_color\n#pragma mapbox: initialize lowp float opacity\ngl_Position=u_matrix*vec4(a_pos,0,1);v_pos=(gl_Position.xy/gl_Position.w+1.0)/2.0*u_world;}";

var fillOutlinePatternFrag = "uniform vec2 u_texsize;uniform sampler2D u_image;uniform float u_fade;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec2 v_pos;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);float dist=length(v_pos-gl_FragCoord.xy);float alpha=1.0-smoothstep(0.0,1.0,dist);gl_FragColor=mix(color1,color2,u_fade)*alpha*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var fillOutlinePatternVert = "uniform mat4 u_matrix;uniform vec2 u_world;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec3 u_scale;attribute vec2 a_pos;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec2 v_pos;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float pixel_ratio_from\n#pragma mapbox: define lowp float pixel_ratio_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float pixel_ratio_from\n#pragma mapbox: initialize lowp float pixel_ratio_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;gl_Position=u_matrix*vec4(a_pos,0,1);vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,a_pos);v_pos=(gl_Position.xy/gl_Position.w+1.0)/2.0*u_world;}";

var fillPatternFrag = "uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;varying vec2 v_pos_a;varying vec2 v_pos_b;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);gl_FragColor=mix(color1,color2,u_fade)*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var fillPatternVert = "uniform mat4 u_matrix;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec3 u_scale;attribute vec2 a_pos;varying vec2 v_pos_a;varying vec2 v_pos_b;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float pixel_ratio_from\n#pragma mapbox: define lowp float pixel_ratio_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float pixel_ratio_from\n#pragma mapbox: initialize lowp float pixel_ratio_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileZoomRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;gl_Position=u_matrix*vec4(a_pos,0,1);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileZoomRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileZoomRatio,a_pos);}";

var fillExtrusionFrag = "varying vec4 v_color;void main() {gl_FragColor=v_color;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var fillExtrusionVert = "uniform mat4 u_matrix;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp float u_lightintensity;uniform float u_vertical_gradient;uniform lowp float u_opacity;attribute vec2 a_pos;attribute vec4 a_normal_ed;varying vec4 v_color;\n#pragma mapbox: define highp float base\n#pragma mapbox: define highp float height\n#pragma mapbox: define highp vec4 color\nvoid main() {\n#pragma mapbox: initialize highp float base\n#pragma mapbox: initialize highp float height\n#pragma mapbox: initialize highp vec4 color\nvec3 normal=a_normal_ed.xyz;base=max(0.0,base);height=max(0.0,height);float t=mod(normal.x,2.0);gl_Position=u_matrix*vec4(a_pos,t > 0.0 ? height : base,1);float colorvalue=color.r*0.2126+color.g*0.7152+color.b*0.0722;v_color=vec4(0.0,0.0,0.0,1.0);vec4 ambientlight=vec4(0.03,0.03,0.03,1.0);color+=ambientlight;float directional=clamp(dot(normal/16384.0,u_lightpos),0.0,1.0);directional=mix((1.0-u_lightintensity),max((1.0-colorvalue+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_color.r+=clamp(color.r*directional*u_lightcolor.r,mix(0.0,0.3,1.0-u_lightcolor.r),1.0);v_color.g+=clamp(color.g*directional*u_lightcolor.g,mix(0.0,0.3,1.0-u_lightcolor.g),1.0);v_color.b+=clamp(color.b*directional*u_lightcolor.b,mix(0.0,0.3,1.0-u_lightcolor.b),1.0);v_color*=u_opacity;}";

var fillExtrusionPatternFrag = "uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec4 v_lighting;\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float pixel_ratio_from\n#pragma mapbox: define lowp float pixel_ratio_to\nvoid main() {\n#pragma mapbox: initialize lowp float base\n#pragma mapbox: initialize lowp float height\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float pixel_ratio_from\n#pragma mapbox: initialize lowp float pixel_ratio_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);vec4 mixedColor=mix(color1,color2,u_fade);gl_FragColor=mixedColor*v_lighting;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var fillExtrusionPatternVert = "uniform mat4 u_matrix;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform float u_height_factor;uniform vec3 u_scale;uniform float u_vertical_gradient;uniform lowp float u_opacity;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp float u_lightintensity;attribute vec2 a_pos;attribute vec4 a_normal_ed;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec4 v_lighting;\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float pixel_ratio_from\n#pragma mapbox: define lowp float pixel_ratio_to\nvoid main() {\n#pragma mapbox: initialize lowp float base\n#pragma mapbox: initialize lowp float height\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float pixel_ratio_from\n#pragma mapbox: initialize lowp float pixel_ratio_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec3 normal=a_normal_ed.xyz;float edgedistance=a_normal_ed.w;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;base=max(0.0,base);height=max(0.0,height);float t=mod(normal.x,2.0);float z=t > 0.0 ? height : base;gl_Position=u_matrix*vec4(a_pos,z,1);vec2 pos=normal.x==1.0 && normal.y==0.0 && normal.z==16384.0\n? a_pos\n: vec2(edgedistance,z*u_height_factor);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,pos);v_lighting=vec4(0.0,0.0,0.0,1.0);float directional=clamp(dot(normal/16383.0,u_lightpos),0.0,1.0);directional=mix((1.0-u_lightintensity),max((0.5+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_lighting.rgb+=clamp(directional*u_lightcolor,mix(vec3(0.0),vec3(0.3),1.0-u_lightcolor),vec3(1.0));v_lighting*=u_opacity;}";

var hillshadePrepareFrag = "#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D u_image;varying vec2 v_pos;uniform vec2 u_dimension;uniform float u_zoom;uniform vec4 u_unpack;float getElevation(vec2 coord,float bias) {vec4 data=texture2D(u_image,coord)*255.0;data.a=-1.0;return dot(data,u_unpack)/4.0;}void main() {vec2 epsilon=1.0/u_dimension;float a=getElevation(v_pos+vec2(-epsilon.x,-epsilon.y),0.0);float b=getElevation(v_pos+vec2(0,-epsilon.y),0.0);float c=getElevation(v_pos+vec2(epsilon.x,-epsilon.y),0.0);float d=getElevation(v_pos+vec2(-epsilon.x,0),0.0);float e=getElevation(v_pos,0.0);float f=getElevation(v_pos+vec2(epsilon.x,0),0.0);float g=getElevation(v_pos+vec2(-epsilon.x,epsilon.y),0.0);float h=getElevation(v_pos+vec2(0,epsilon.y),0.0);float i=getElevation(v_pos+vec2(epsilon.x,epsilon.y),0.0);float exaggerationFactor=u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;float exaggeration=u_zoom < 15.0 ? (u_zoom-15.0)*exaggerationFactor : 0.0;vec2 deriv=vec2((c+f+f+i)-(a+d+d+g),(g+h+h+i)-(a+b+b+c))/pow(2.0,exaggeration+(19.2562-u_zoom));gl_FragColor=clamp(vec4(deriv.x/2.0+0.5,deriv.y/2.0+0.5,1.0,1.0),0.0,1.0);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var hillshadePrepareVert = "uniform mat4 u_matrix;uniform vec2 u_dimension;attribute vec2 a_pos;attribute vec2 a_texture_pos;varying vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);highp vec2 epsilon=1.0/u_dimension;float scale=(u_dimension.x-2.0)/u_dimension.x;v_pos=(a_texture_pos/8192.0)*scale+epsilon;}";

var hillshadeFrag = "uniform sampler2D u_image;varying vec2 v_pos;uniform vec2 u_latrange;uniform vec2 u_light;uniform vec4 u_shadow;uniform vec4 u_highlight;uniform vec4 u_accent;\n#define PI 3.141592653589793\nvoid main() {vec4 pixel=texture2D(u_image,v_pos);vec2 deriv=((pixel.rg*2.0)-1.0);float scaleFactor=cos(radians((u_latrange[0]-u_latrange[1])*(1.0-v_pos.y)+u_latrange[1]));float slope=atan(1.25*length(deriv)/scaleFactor);float aspect=deriv.x !=0.0 ? atan(deriv.y,-deriv.x) : PI/2.0*(deriv.y > 0.0 ? 1.0 :-1.0);float intensity=u_light.x;float azimuth=u_light.y+PI;float base=1.875-intensity*1.75;float maxValue=0.5*PI;float scaledSlope=intensity !=0.5 ? ((pow(base,slope)-1.0)/(pow(base,maxValue)-1.0))*maxValue : slope;float accent=cos(scaledSlope);vec4 accent_color=(1.0-accent)*u_accent*clamp(intensity*2.0,0.0,1.0);float shade=abs(mod((aspect+azimuth)/PI+0.5,2.0)-1.0);vec4 shade_color=mix(u_shadow,u_highlight,shade)*sin(scaledSlope)*clamp(intensity*2.0,0.0,1.0);gl_FragColor=accent_color*(1.0-shade_color.a)+shade_color;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var hillshadeVert = "uniform mat4 u_matrix;attribute vec2 a_pos;attribute vec2 a_texture_pos;varying vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);v_pos=a_texture_pos/8192.0;}";

var lineFrag = "uniform lowp float u_device_pixel_ratio;varying vec2 v_width2;varying vec2 v_normal;varying float v_gamma_scale;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\nfloat dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);gl_FragColor=color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var lineVert = "\n#define scale 0.015873016\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform mediump float u_ratio;uniform vec2 u_units_to_pixels;uniform lowp float u_device_pixel_ratio;varying vec2 v_normal;varying vec2 v_width2;varying float v_gamma_scale;varying highp float v_linesofar;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float width\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;v_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*2.0;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_width2=vec2(outset,inset);}";

var lineGradientFrag = "uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;varying vec2 v_width2;varying vec2 v_normal;varying float v_gamma_scale;varying highp vec2 v_uv;\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\nfloat dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);vec4 color=texture2D(u_image,v_uv);gl_FragColor=color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var lineGradientVert = "\n#define scale 0.015873016\nattribute vec2 a_pos_normal;attribute vec4 a_data;attribute float a_uv_x;attribute float a_split_index;uniform mat4 u_matrix;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_units_to_pixels;uniform float u_image_height;varying vec2 v_normal;varying vec2 v_width2;varying float v_gamma_scale;varying highp vec2 v_uv;\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\nvoid main() {\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float width\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;highp float texel_height=1.0/u_image_height;highp float half_texel_height=0.5*texel_height;v_uv=vec2(a_uv_x,a_split_index*texel_height-half_texel_height);vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_width2=vec2(outset,inset);}";

var linePatternFrag = "uniform lowp float u_device_pixel_ratio;uniform vec2 u_texsize;uniform float u_fade;uniform mediump vec3 u_scale;uniform sampler2D u_image;varying vec2 v_normal;varying vec2 v_width2;varying float v_linesofar;varying float v_gamma_scale;varying float v_width;\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float pixel_ratio_from\n#pragma mapbox: define lowp float pixel_ratio_to\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float pixel_ratio_from\n#pragma mapbox: initialize lowp float pixel_ratio_to\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileZoomRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;vec2 pattern_size_a=vec2(display_size_a.x*fromScale/tileZoomRatio,display_size_a.y);vec2 pattern_size_b=vec2(display_size_b.x*toScale/tileZoomRatio,display_size_b.y);float aspect_a=display_size_a.y/v_width;float aspect_b=display_size_b.y/v_width;float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);float x_a=mod(v_linesofar/pattern_size_a.x*aspect_a,1.0);float x_b=mod(v_linesofar/pattern_size_b.x*aspect_b,1.0);float y=0.5*v_normal.y+0.5;vec2 texel_size=1.0/u_texsize;vec2 pos_a=mix(pattern_tl_a*texel_size-texel_size,pattern_br_a*texel_size+texel_size,vec2(x_a,y));vec2 pos_b=mix(pattern_tl_b*texel_size-texel_size,pattern_br_b*texel_size+texel_size,vec2(x_b,y));vec4 color=mix(texture2D(u_image,pos_a),texture2D(u_image,pos_b),u_fade);gl_FragColor=color*alpha*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var linePatternVert = "\n#define scale 0.015873016\n#define LINE_DISTANCE_SCALE 2.0\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform vec2 u_units_to_pixels;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;varying vec2 v_normal;varying vec2 v_width2;varying float v_linesofar;varying float v_gamma_scale;varying float v_width;\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float pixel_ratio_from\n#pragma mapbox: define lowp float pixel_ratio_to\nvoid main() {\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize mediump float width\n#pragma mapbox: initialize lowp float floorwidth\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float pixel_ratio_from\n#pragma mapbox: initialize lowp float pixel_ratio_to\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_linesofar=a_linesofar;v_width2=vec2(outset,inset);v_width=floorwidth;}";

var lineSDFFrag = "uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;uniform float u_sdfgamma;uniform float u_mix;varying vec2 v_normal;varying vec2 v_width2;varying vec2 v_tex_a;varying vec2 v_tex_b;varying float v_gamma_scale;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float width\n#pragma mapbox: initialize lowp float floorwidth\nfloat dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);float sdfdist_a=texture2D(u_image,v_tex_a).a;float sdfdist_b=texture2D(u_image,v_tex_b).a;float sdfdist=mix(sdfdist_a,sdfdist_b,u_mix);alpha*=smoothstep(0.5-u_sdfgamma/floorwidth,0.5+u_sdfgamma/floorwidth,sdfdist);gl_FragColor=color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var lineSDFVert = "\n#define scale 0.015873016\n#define LINE_DISTANCE_SCALE 2.0\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_patternscale_a;uniform float u_tex_y_a;uniform vec2 u_patternscale_b;uniform float u_tex_y_b;uniform vec2 u_units_to_pixels;varying vec2 v_normal;varying vec2 v_width2;varying vec2 v_tex_a;varying vec2 v_tex_b;varying float v_gamma_scale;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float width\n#pragma mapbox: initialize lowp float floorwidth\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_tex_a=vec2(a_linesofar*u_patternscale_a.x/floorwidth,normal.y*u_patternscale_a.y+u_tex_y_a);v_tex_b=vec2(a_linesofar*u_patternscale_b.x/floorwidth,normal.y*u_patternscale_b.y+u_tex_y_b);v_width2=vec2(outset,inset);}";

var rasterFrag = "uniform float u_fade_t;uniform float u_opacity;uniform sampler2D u_image0;uniform sampler2D u_image1;varying vec2 v_pos0;varying vec2 v_pos1;uniform float u_brightness_low;uniform float u_brightness_high;uniform float u_saturation_factor;uniform float u_contrast_factor;uniform vec3 u_spin_weights;void main() {vec4 color0=texture2D(u_image0,v_pos0);vec4 color1=texture2D(u_image1,v_pos1);if (color0.a > 0.0) {color0.rgb=color0.rgb/color0.a;}if (color1.a > 0.0) {color1.rgb=color1.rgb/color1.a;}vec4 color=mix(color0,color1,u_fade_t);color.a*=u_opacity;vec3 rgb=color.rgb;rgb=vec3(dot(rgb,u_spin_weights.xyz),dot(rgb,u_spin_weights.zxy),dot(rgb,u_spin_weights.yzx));float average=(color.r+color.g+color.b)/3.0;rgb+=(average-rgb)*u_saturation_factor;rgb=(rgb-0.5)*u_contrast_factor+0.5;vec3 u_high_vec=vec3(u_brightness_low,u_brightness_low,u_brightness_low);vec3 u_low_vec=vec3(u_brightness_high,u_brightness_high,u_brightness_high);gl_FragColor=vec4(mix(u_high_vec,u_low_vec,rgb)*color.a,color.a);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var rasterVert = "uniform mat4 u_matrix;uniform vec2 u_tl_parent;uniform float u_scale_parent;uniform float u_buffer_scale;attribute vec2 a_pos;attribute vec2 a_texture_pos;varying vec2 v_pos0;varying vec2 v_pos1;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);v_pos0=(((a_texture_pos/8192.0)-0.5)/u_buffer_scale )+0.5;v_pos1=(v_pos0*u_scale_parent)+u_tl_parent;}";

var symbolIconFrag = "uniform sampler2D u_texture;varying vec2 v_tex;varying float v_fade_opacity;\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\nlowp float alpha=opacity*v_fade_opacity;gl_FragColor=texture2D(u_texture,v_tex)*alpha;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var symbolIconVert = "const float PI=3.141592653589793;attribute vec4 a_pos_offset;attribute vec4 a_data;attribute vec4 a_pixeloffset;attribute vec3 a_projected_pos;attribute float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform highp float u_camera_to_center_distance;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform float u_fade_change;uniform mat4 u_matrix;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform vec2 u_texsize;varying vec2 v_tex;varying float v_fade_opacity;\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\nvec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;float a_size_min=floor(a_size[0]*0.5);vec2 a_pxoffset=a_pixeloffset.xy;vec2 a_minFontScale=a_pixeloffset.zw/256.0;highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size_min,a_size[1],u_size_t)/128.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size_min/128.0;} else {size=u_size;}vec4 projectedPoint=u_matrix*vec4(a_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?\ncamera_to_anchor_distance/u_camera_to_center_distance :\nu_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);size*=perspective_ratio;float fontScale=u_is_text ? size/24.0 : size;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=u_matrix*vec4(a_pos+vec2(1,0),0,1);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy,0.0,1.0);gl_Position=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*max(a_minFontScale,fontScale)+a_pxoffset/16.0),0.0,1.0);v_tex=a_tex/u_texsize;vec2 fade_opacity=unpack_opacity(a_fade_opacity);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;v_fade_opacity=max(0.0,min(1.0,fade_opacity[0]+fade_change));}";

var symbolSDFFrag = "#define SDF_PX 8.0\nuniform bool u_is_halo;uniform sampler2D u_texture;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;uniform bool u_is_text;varying vec2 v_data0;varying vec3 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nfloat EDGE_GAMMA=0.105/u_device_pixel_ratio;vec2 tex=v_data0.xy;float gamma_scale=v_data1.x;float size=v_data1.y;float fade_opacity=v_data1[2];float fontScale=u_is_text ? size/24.0 : size;lowp vec4 color=fill_color;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float buff=(256.0-64.0)/256.0;if (u_is_halo) {color=halo_color;gamma=(halo_blur*1.19/SDF_PX+EDGE_GAMMA)/(fontScale*u_gamma_scale);buff=(6.0-halo_width/fontScale)/SDF_PX;}lowp float dist=texture2D(u_texture,tex).a;highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(buff-gamma_scaled,buff+gamma_scaled,dist);gl_FragColor=color*(alpha*opacity*fade_opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var symbolSDFVert = "const float PI=3.141592653589793;attribute vec4 a_pos_offset;attribute vec4 a_data;attribute vec4 a_pixeloffset;attribute vec3 a_projected_pos;attribute float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform mat4 u_matrix;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform highp float u_camera_to_center_distance;uniform float u_fade_change;uniform vec2 u_texsize;varying vec2 v_data0;varying vec3 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nvec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;float a_size_min=floor(a_size[0]*0.5);vec2 a_pxoffset=a_pixeloffset.xy;highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size_min,a_size[1],u_size_t)/128.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size_min/128.0;} else {size=u_size;}vec4 projectedPoint=u_matrix*vec4(a_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?\ncamera_to_anchor_distance/u_camera_to_center_distance :\nu_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);size*=perspective_ratio;float fontScale=u_is_text ? size/24.0 : size;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=u_matrix*vec4(a_pos+vec2(1,0),0,1);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy,0.0,1.0);gl_Position=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*fontScale+a_pxoffset),0.0,1.0);float gamma_scale=gl_Position.w;vec2 fade_opacity=unpack_opacity(a_fade_opacity);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;float interpolated_fade_opacity=max(0.0,min(1.0,fade_opacity[0]+fade_change));v_data0=a_tex/u_texsize;v_data1=vec3(gamma_scale,size,interpolated_fade_opacity);}";

var symbolTextAndIconFrag = "#define SDF_PX 8.0\n#define SDF 1.0\n#define ICON 0.0\nuniform bool u_is_halo;uniform sampler2D u_texture;uniform sampler2D u_texture_icon;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;varying vec4 v_data0;varying vec4 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nfloat fade_opacity=v_data1[2];if (v_data1.w==ICON) {vec2 tex_icon=v_data0.zw;lowp float alpha=opacity*fade_opacity;gl_FragColor=texture2D(u_texture_icon,tex_icon)*alpha;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\nreturn;}vec2 tex=v_data0.xy;float EDGE_GAMMA=0.105/u_device_pixel_ratio;float gamma_scale=v_data1.x;float size=v_data1.y;float fontScale=size/24.0;lowp vec4 color=fill_color;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float buff=(256.0-64.0)/256.0;if (u_is_halo) {color=halo_color;gamma=(halo_blur*1.19/SDF_PX+EDGE_GAMMA)/(fontScale*u_gamma_scale);buff=(6.0-halo_width/fontScale)/SDF_PX;}lowp float dist=texture2D(u_texture,tex).a;highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(buff-gamma_scaled,buff+gamma_scaled,dist);gl_FragColor=color*(alpha*opacity*fade_opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}";

var symbolTextAndIconVert = "const float PI=3.141592653589793;attribute vec4 a_pos_offset;attribute vec4 a_data;attribute vec3 a_projected_pos;attribute float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform mat4 u_matrix;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform highp float u_camera_to_center_distance;uniform float u_fade_change;uniform vec2 u_texsize;uniform vec2 u_texsize_icon;varying vec4 v_data0;varying vec4 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nvec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;float a_size_min=floor(a_size[0]*0.5);float is_sdf=a_size[0]-2.0*a_size_min;highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size_min,a_size[1],u_size_t)/128.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size_min/128.0;} else {size=u_size;}vec4 projectedPoint=u_matrix*vec4(a_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?\ncamera_to_anchor_distance/u_camera_to_center_distance :\nu_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);size*=perspective_ratio;float fontScale=size/24.0;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=u_matrix*vec4(a_pos+vec2(1,0),0,1);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy,0.0,1.0);gl_Position=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*fontScale),0.0,1.0);float gamma_scale=gl_Position.w;vec2 fade_opacity=unpack_opacity(a_fade_opacity);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;float interpolated_fade_opacity=max(0.0,min(1.0,fade_opacity[0]+fade_change));v_data0.xy=a_tex/u_texsize;v_data0.zw=a_tex/u_texsize_icon;v_data1=vec4(gamma_scale,size,interpolated_fade_opacity,is_sdf);}";

var prelude = compile(preludeFrag, preludeVert);
var background = compile(backgroundFrag, backgroundVert);
var backgroundPattern = compile(backgroundPatternFrag, backgroundPatternVert);
var circle = compile(circleFrag, circleVert);
var clippingMask = compile(clippingMaskFrag, clippingMaskVert);
var heatmap = compile(heatmapFrag, heatmapVert);
var heatmapTexture = compile(heatmapTextureFrag, heatmapTextureVert);
var collisionBox = compile(collisionBoxFrag, collisionBoxVert);
var collisionCircle = compile(collisionCircleFrag, collisionCircleVert);
var debug = compile(debugFrag, debugVert);
var fill = compile(fillFrag, fillVert);
var fillOutline = compile(fillOutlineFrag, fillOutlineVert);
var fillOutlinePattern = compile(fillOutlinePatternFrag, fillOutlinePatternVert);
var fillPattern = compile(fillPatternFrag, fillPatternVert);
var fillExtrusion = compile(fillExtrusionFrag, fillExtrusionVert);
var fillExtrusionPattern = compile(fillExtrusionPatternFrag, fillExtrusionPatternVert);
var hillshadePrepare = compile(hillshadePrepareFrag, hillshadePrepareVert);
var hillshade = compile(hillshadeFrag, hillshadeVert);
var line = compile(lineFrag, lineVert);
var lineGradient = compile(lineGradientFrag, lineGradientVert);
var linePattern = compile(linePatternFrag, linePatternVert);
var lineSDF = compile(lineSDFFrag, lineSDFVert);
var raster = compile(rasterFrag, rasterVert);
var symbolIcon = compile(symbolIconFrag, symbolIconVert);
var symbolSDF = compile(symbolSDFFrag, symbolSDFVert);
var symbolTextAndIcon = compile(symbolTextAndIconFrag, symbolTextAndIconVert);
function compile(fragmentSource, vertexSource) {
    var re = /#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g;
    var staticAttributes = vertexSource.match(/attribute ([\w]+) ([\w]+)/g);
    var fragmentUniforms = fragmentSource.match(/uniform ([\w]+) ([\w]+)([\s]*)([\w]*)/g);
    var vertexUniforms = vertexSource.match(/uniform ([\w]+) ([\w]+)([\s]*)([\w]*)/g);
    var staticUniforms = vertexUniforms ? vertexUniforms.concat(fragmentUniforms) : fragmentUniforms;
    var fragmentPragmas = {};
    fragmentSource = fragmentSource.replace(re, function (match, operation, precision, type, name) {
        fragmentPragmas[name] = true;
        if (operation === 'define') {
            return '\n#ifndef HAS_UNIFORM_u_' + name + '\nvarying ' + precision + ' ' + type + ' ' + name + ';\n#else\nuniform ' + precision + ' ' + type + ' u_' + name + ';\n#endif\n';
        } else {
            return '\n#ifdef HAS_UNIFORM_u_' + name + '\n    ' + precision + ' ' + type + ' ' + name + ' = u_' + name + ';\n#endif\n';
        }
    });
    vertexSource = vertexSource.replace(re, function (match, operation, precision, type, name) {
        var attrType = type === 'float' ? 'vec2' : 'vec4';
        var unpackType = name.match(/color/) ? 'color' : attrType;
        if (fragmentPragmas[name]) {
            if (operation === 'define') {
                return '\n#ifndef HAS_UNIFORM_u_' + name + '\nuniform lowp float u_' + name + '_t;\nattribute ' + precision + ' ' + attrType + ' a_' + name + ';\nvarying ' + precision + ' ' + type + ' ' + name + ';\n#else\nuniform ' + precision + ' ' + type + ' u_' + name + ';\n#endif\n';
            } else {
                if (unpackType === 'vec4') {
                    return '\n#ifndef HAS_UNIFORM_u_' + name + '\n    ' + name + ' = a_' + name + ';\n#else\n    ' + precision + ' ' + type + ' ' + name + ' = u_' + name + ';\n#endif\n';
                } else {
                    return '\n#ifndef HAS_UNIFORM_u_' + name + '\n    ' + name + ' = unpack_mix_' + unpackType + '(a_' + name + ', u_' + name + '_t);\n#else\n    ' + precision + ' ' + type + ' ' + name + ' = u_' + name + ';\n#endif\n';
                }
            }
        } else {
            if (operation === 'define') {
                return '\n#ifndef HAS_UNIFORM_u_' + name + '\nuniform lowp float u_' + name + '_t;\nattribute ' + precision + ' ' + attrType + ' a_' + name + ';\n#else\nuniform ' + precision + ' ' + type + ' u_' + name + ';\n#endif\n';
            } else {
                if (unpackType === 'vec4') {
                    return '\n#ifndef HAS_UNIFORM_u_' + name + '\n    ' + precision + ' ' + type + ' ' + name + ' = a_' + name + ';\n#else\n    ' + precision + ' ' + type + ' ' + name + ' = u_' + name + ';\n#endif\n';
                } else {
                    return '\n#ifndef HAS_UNIFORM_u_' + name + '\n    ' + precision + ' ' + type + ' ' + name + ' = unpack_mix_' + unpackType + '(a_' + name + ', u_' + name + '_t);\n#else\n    ' + precision + ' ' + type + ' ' + name + ' = u_' + name + ';\n#endif\n';
                }
            }
        }
    });
    return {
        fragmentSource: fragmentSource,
        vertexSource: vertexSource,
        staticAttributes: staticAttributes,
        staticUniforms: staticUniforms
    };
}

var shaders = /*#__PURE__*/Object.freeze({
__proto__: null,
prelude: prelude,
background: background,
backgroundPattern: backgroundPattern,
circle: circle,
clippingMask: clippingMask,
heatmap: heatmap,
heatmapTexture: heatmapTexture,
collisionBox: collisionBox,
collisionCircle: collisionCircle,
debug: debug,
fill: fill,
fillOutline: fillOutline,
fillOutlinePattern: fillOutlinePattern,
fillPattern: fillPattern,
fillExtrusion: fillExtrusion,
fillExtrusionPattern: fillExtrusionPattern,
hillshadePrepare: hillshadePrepare,
hillshade: hillshade,
line: line,
lineGradient: lineGradient,
linePattern: linePattern,
lineSDF: lineSDF,
raster: raster,
symbolIcon: symbolIcon,
symbolSDF: symbolSDF,
symbolTextAndIcon: symbolTextAndIcon
});

var VertexArrayObject = function VertexArrayObject() {
    this.boundProgram = null;
    this.boundLayoutVertexBuffer = null;
    this.boundPaintVertexBuffers = [];
    this.boundIndexBuffer = null;
    this.boundVertexOffset = null;
    this.boundDynamicVertexBuffer = null;
    this.vao = null;
};
VertexArrayObject.prototype.bind = function bind(context, program, layoutVertexBuffer, paintVertexBuffers, indexBuffer, vertexOffset, dynamicVertexBuffer, dynamicVertexBuffer2) {
    this.context = context;
    var paintBuffersDiffer = this.boundPaintVertexBuffers.length !== paintVertexBuffers.length;
    for (var i = 0; !paintBuffersDiffer && i < paintVertexBuffers.length; i++) {
        if (this.boundPaintVertexBuffers[i] !== paintVertexBuffers[i]) {
            paintBuffersDiffer = true;
        }
    }
    var isFreshBindRequired = !this.vao || this.boundProgram !== program || this.boundLayoutVertexBuffer !== layoutVertexBuffer || paintBuffersDiffer || this.boundIndexBuffer !== indexBuffer || this.boundVertexOffset !== vertexOffset || this.boundDynamicVertexBuffer !== dynamicVertexBuffer || this.boundDynamicVertexBuffer2 !== dynamicVertexBuffer2;
    if (!context.extVertexArrayObject || isFreshBindRequired) {
        this.freshBind(program, layoutVertexBuffer, paintVertexBuffers, indexBuffer, vertexOffset, dynamicVertexBuffer, dynamicVertexBuffer2);
    } else {
        context.bindVertexArrayOES.set(this.vao);
        if (dynamicVertexBuffer) {
            dynamicVertexBuffer.bind();
        }
        if (indexBuffer && indexBuffer.dynamicDraw) {
            indexBuffer.bind();
        }
        if (dynamicVertexBuffer2) {
            dynamicVertexBuffer2.bind();
        }
    }
};
VertexArrayObject.prototype.freshBind = function freshBind(program, layoutVertexBuffer, paintVertexBuffers, indexBuffer, vertexOffset, dynamicVertexBuffer, dynamicVertexBuffer2) {
    var numPrevAttributes;
    var numNextAttributes = program.numAttributes;
    var context = this.context;
    var gl = context.gl;
    if (context.extVertexArrayObject) {
        if (this.vao) {
            this.destroy();
        }
        this.vao = context.extVertexArrayObject.createVertexArrayOES();
        context.bindVertexArrayOES.set(this.vao);
        numPrevAttributes = 0;
        this.boundProgram = program;
        this.boundLayoutVertexBuffer = layoutVertexBuffer;
        this.boundPaintVertexBuffers = paintVertexBuffers;
        this.boundIndexBuffer = indexBuffer;
        this.boundVertexOffset = vertexOffset;
        this.boundDynamicVertexBuffer = dynamicVertexBuffer;
        this.boundDynamicVertexBuffer2 = dynamicVertexBuffer2;
    } else {
        numPrevAttributes = context.currentNumAttributes || 0;
        for (var i = numNextAttributes; i < numPrevAttributes; i++) {
            gl.disableVertexAttribArray(i);
        }
    }
    layoutVertexBuffer.enableAttributes(gl, program);
    for (var i$1 = 0, list = paintVertexBuffers; i$1 < list.length; i$1 += 1) {
        var vertexBuffer = list[i$1];
        vertexBuffer.enableAttributes(gl, program);
    }
    if (dynamicVertexBuffer) {
        dynamicVertexBuffer.enableAttributes(gl, program);
    }
    if (dynamicVertexBuffer2) {
        dynamicVertexBuffer2.enableAttributes(gl, program);
    }
    layoutVertexBuffer.bind();
    layoutVertexBuffer.setVertexAttribPointers(gl, program, vertexOffset);
    for (var i$2 = 0, list$1 = paintVertexBuffers; i$2 < list$1.length; i$2 += 1) {
        var vertexBuffer$1 = list$1[i$2];
        vertexBuffer$1.bind();
        vertexBuffer$1.setVertexAttribPointers(gl, program, vertexOffset);
    }
    if (dynamicVertexBuffer) {
        dynamicVertexBuffer.bind();
        dynamicVertexBuffer.setVertexAttribPointers(gl, program, vertexOffset);
    }
    if (indexBuffer) {
        indexBuffer.bind();
    }
    if (dynamicVertexBuffer2) {
        dynamicVertexBuffer2.bind();
        dynamicVertexBuffer2.setVertexAttribPointers(gl, program, vertexOffset);
    }
    context.currentNumAttributes = numNextAttributes;
};
VertexArrayObject.prototype.destroy = function destroy() {
    if (this.vao) {
        this.context.extVertexArrayObject.deleteVertexArrayOES(this.vao);
        this.vao = null;
    }
};

function getTokenizedAttributesAndUniforms(array) {
    var result = [];
    for (var i = 0; i < array.length; i++) {
        if (array[i] === null) {
            continue;
        }
        var token = array[i].split(' ');
        result.push(token.pop());
    }
    return result;
}
var Program$1 = function Program(context, name, source, configuration, fixedUniforms, showOverdrawInspector) {
    var gl = context.gl;
    this.program = gl.createProgram();
    var staticAttrInfo = getTokenizedAttributesAndUniforms(source.staticAttributes);
    var dynamicAttrInfo = configuration ? configuration.getBinderAttributes() : [];
    var allAttrInfo = staticAttrInfo.concat(dynamicAttrInfo);
    var staticUniformsInfo = source.staticUniforms ? getTokenizedAttributesAndUniforms(source.staticUniforms) : [];
    var dynamicUniformsInfo = configuration ? configuration.getBinderUniforms() : [];
    var uniformList = staticUniformsInfo.concat(dynamicUniformsInfo);
    var allUniformsInfo = [];
    for (var i$1 = 0, list = uniformList; i$1 < list.length; i$1 += 1) {
        var uniform = list[i$1];
        if (allUniformsInfo.indexOf(uniform) < 0) {
            allUniformsInfo.push(uniform);
        }
    }
    var defines = configuration ? configuration.defines() : [];
    if (showOverdrawInspector) {
        defines.push('#define OVERDRAW_INSPECTOR;');
    }
    var fragmentSource = defines.concat(prelude.fragmentSource, source.fragmentSource).join('\n');
    var vertexSource = defines.concat(prelude.vertexSource, source.vertexSource).join('\n');
    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    if (gl.isContextLost()) {
        this.failedToCreate = true;
        return;
    }
    gl.shaderSource(fragmentShader, fragmentSource);
    gl.compileShader(fragmentShader);
    gl.attachShader(this.program, fragmentShader);
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    if (gl.isContextLost()) {
        this.failedToCreate = true;
        return;
    }
    gl.shaderSource(vertexShader, vertexSource);
    gl.compileShader(vertexShader);
    gl.attachShader(this.program, vertexShader);
    this.attributes = {};
    var uniformLocations = {};
    this.numAttributes = allAttrInfo.length;
    for (var i = 0; i < this.numAttributes; i++) {
        if (allAttrInfo[i]) {
            gl.bindAttribLocation(this.program, i, allAttrInfo[i]);
            this.attributes[allAttrInfo[i]] = i;
        }
    }
    gl.linkProgram(this.program);
    gl.deleteShader(vertexShader);
    gl.deleteShader(fragmentShader);
    for (var it = 0; it < allUniformsInfo.length; it++) {
        var uniform$1 = allUniformsInfo[it];
        if (uniform$1 && !uniformLocations[uniform$1]) {
            var uniformLocation = gl.getUniformLocation(this.program, uniform$1);
            if (uniformLocation) {
                uniformLocations[uniform$1] = uniformLocation;
            }
        }
    }
    this.fixedUniforms = fixedUniforms(context, uniformLocations);
    this.binderUniforms = configuration ? configuration.getUniforms(context, uniformLocations) : [];
};
Program$1.prototype.draw = function draw(context, drawMode, depthMode, stencilMode, colorMode, cullFaceMode, uniformValues, layerID, layoutVertexBuffer, indexBuffer, segments, currentProperties, zoom, configuration, dynamicLayoutBuffer, dynamicLayoutBuffer2) {
    var obj;
    var gl = context.gl;
    if (this.failedToCreate) {
        return;
    }
    context.program.set(this.program);
    context.setDepthMode(depthMode);
    context.setStencilMode(stencilMode);
    context.setColorMode(colorMode);
    context.setCullFace(cullFaceMode);
    for (var name in this.fixedUniforms) {
        this.fixedUniforms[name].set(uniformValues[name]);
    }
    if (configuration) {
        configuration.setUniforms(context, this.binderUniforms, currentProperties, { zoom: zoom });
    }
    var primitiveSize = (obj = {}, obj[gl.LINES] = 2, obj[gl.TRIANGLES] = 3, obj[gl.LINE_STRIP] = 1, obj)[drawMode];
    for (var i = 0, list = segments.get(); i < list.length; i += 1) {
        var segment = list[i];
        var vaos = segment.vaos || (segment.vaos = {});
        var vao = vaos[layerID] || (vaos[layerID] = new VertexArrayObject());
        vao.bind(context, this, layoutVertexBuffer, configuration ? configuration.getPaintVertexBuffers() : [], indexBuffer, segment.vertexOffset, dynamicLayoutBuffer, dynamicLayoutBuffer2);
        gl.drawElements(drawMode, segment.primitiveLength * primitiveSize, gl.UNSIGNED_SHORT, segment.primitiveOffset * primitiveSize * 2);
    }
};

function patternUniformValues(crossfade, painter, tile) {
    var tileRatio = 1 / pixelsToTileUnits(tile, 1, painter.transform.tileZoom);
    var numTiles = Math.pow(2, tile.tileID.overscaledZ);
    var tileSizeAtNearestZoom = tile.tileSize * Math.pow(2, painter.transform.tileZoom) / numTiles;
    var pixelX = tileSizeAtNearestZoom * (tile.tileID.canonical.x + tile.tileID.wrap * numTiles);
    var pixelY = tileSizeAtNearestZoom * tile.tileID.canonical.y;
    return {
        'u_image': 0,
        'u_texsize': tile.imageAtlasTexture.size,
        'u_scale': [
            tileRatio,
            crossfade.fromScale,
            crossfade.toScale
        ],
        'u_fade': crossfade.t,
        'u_pixel_coord_upper': [
            pixelX >> 16,
            pixelY >> 16
        ],
        'u_pixel_coord_lower': [
            pixelX & 65535,
            pixelY & 65535
        ]
    };
}
function bgPatternUniformValues(image, crossfade, painter, tile) {
    var imagePosA = painter.imageManager.getPattern(image.from.toString());
    var imagePosB = painter.imageManager.getPattern(image.to.toString());
    var ref = painter.imageManager.getPixelSize();
    var width = ref.width;
    var height = ref.height;
    var numTiles = Math.pow(2, tile.tileID.overscaledZ);
    var tileSizeAtNearestZoom = tile.tileSize * Math.pow(2, painter.transform.tileZoom) / numTiles;
    var pixelX = tileSizeAtNearestZoom * (tile.tileID.canonical.x + tile.tileID.wrap * numTiles);
    var pixelY = tileSizeAtNearestZoom * tile.tileID.canonical.y;
    return {
        'u_image': 0,
        'u_pattern_tl_a': imagePosA.tl,
        'u_pattern_br_a': imagePosA.br,
        'u_pattern_tl_b': imagePosB.tl,
        'u_pattern_br_b': imagePosB.br,
        'u_texsize': [
            width,
            height
        ],
        'u_mix': crossfade.t,
        'u_pattern_size_a': imagePosA.displaySize,
        'u_pattern_size_b': imagePosB.displaySize,
        'u_scale_a': crossfade.fromScale,
        'u_scale_b': crossfade.toScale,
        'u_tile_units_to_pixels': 1 / pixelsToTileUnits(tile, 1, painter.transform.tileZoom),
        'u_pixel_coord_upper': [
            pixelX >> 16,
            pixelY >> 16
        ],
        'u_pixel_coord_lower': [
            pixelX & 65535,
            pixelY & 65535
        ]
    };
}

var fillExtrusionUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_lightpos': new performance.Uniform3f(context, locations.u_lightpos),
        'u_lightintensity': new performance.Uniform1f(context, locations.u_lightintensity),
        'u_lightcolor': new performance.Uniform3f(context, locations.u_lightcolor),
        'u_vertical_gradient': new performance.Uniform1f(context, locations.u_vertical_gradient),
        'u_opacity': new performance.Uniform1f(context, locations.u_opacity)
    };
};
var fillExtrusionPatternUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_lightpos': new performance.Uniform3f(context, locations.u_lightpos),
        'u_lightintensity': new performance.Uniform1f(context, locations.u_lightintensity),
        'u_lightcolor': new performance.Uniform3f(context, locations.u_lightcolor),
        'u_vertical_gradient': new performance.Uniform1f(context, locations.u_vertical_gradient),
        'u_height_factor': new performance.Uniform1f(context, locations.u_height_factor),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_pixel_coord_upper': new performance.Uniform2f(context, locations.u_pixel_coord_upper),
        'u_pixel_coord_lower': new performance.Uniform2f(context, locations.u_pixel_coord_lower),
        'u_scale': new performance.Uniform3f(context, locations.u_scale),
        'u_fade': new performance.Uniform1f(context, locations.u_fade),
        'u_opacity': new performance.Uniform1f(context, locations.u_opacity)
    };
};
var fillExtrusionUniformValues = function (matrix, painter, shouldUseVerticalGradient, opacity) {
    var light = painter.style.light;
    var _lp = light.properties.get('position');
    var lightPos = [
        _lp.x,
        _lp.y,
        _lp.z
    ];
    var lightMat = performance.create$1();
    if (light.properties.get('anchor') === 'viewport') {
        performance.fromRotation(lightMat, -painter.transform.angle);
    }
    performance.transformMat3(lightPos, lightPos, lightMat);
    var lightColor = light.properties.get('color');
    return {
        'u_matrix': matrix,
        'u_lightpos': lightPos,
        'u_lightintensity': light.properties.get('intensity'),
        'u_lightcolor': [
            lightColor.r,
            lightColor.g,
            lightColor.b
        ],
        'u_vertical_gradient': +shouldUseVerticalGradient,
        'u_opacity': opacity
    };
};
var fillExtrusionPatternUniformValues = function (matrix, painter, shouldUseVerticalGradient, opacity, coord, crossfade, tile) {
    return performance.extend(fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity), patternUniformValues(crossfade, painter, tile), { 'u_height_factor': -Math.pow(2, coord.overscaledZ) / tile.tileSize / 8 });
};

var fillUniforms = function (context, locations) {
    return { 'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix) };
};
var fillPatternUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_pixel_coord_upper': new performance.Uniform2f(context, locations.u_pixel_coord_upper),
        'u_pixel_coord_lower': new performance.Uniform2f(context, locations.u_pixel_coord_lower),
        'u_scale': new performance.Uniform3f(context, locations.u_scale),
        'u_fade': new performance.Uniform1f(context, locations.u_fade)
    };
};
var fillOutlineUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_world': new performance.Uniform2f(context, locations.u_world)
    };
};
var fillOutlinePatternUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_world': new performance.Uniform2f(context, locations.u_world),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_pixel_coord_upper': new performance.Uniform2f(context, locations.u_pixel_coord_upper),
        'u_pixel_coord_lower': new performance.Uniform2f(context, locations.u_pixel_coord_lower),
        'u_scale': new performance.Uniform3f(context, locations.u_scale),
        'u_fade': new performance.Uniform1f(context, locations.u_fade)
    };
};
var fillUniformValues = function (matrix) {
    return { 'u_matrix': matrix };
};
var fillPatternUniformValues = function (matrix, painter, crossfade, tile) {
    return performance.extend(fillUniformValues(matrix), patternUniformValues(crossfade, painter, tile));
};
var fillOutlineUniformValues = function (matrix, drawingBufferSize) {
    return {
        'u_matrix': matrix,
        'u_world': drawingBufferSize
    };
};
var fillOutlinePatternUniformValues = function (matrix, painter, crossfade, tile, drawingBufferSize) {
    return performance.extend(fillPatternUniformValues(matrix, painter, crossfade, tile), { 'u_world': drawingBufferSize });
};

var circleUniforms = function (context, locations) {
    return {
        'u_camera_to_center_distance': new performance.Uniform1f(context, locations.u_camera_to_center_distance),
        'u_scale_with_map': new performance.Uniform1i(context, locations.u_scale_with_map),
        'u_pitch_with_map': new performance.Uniform1i(context, locations.u_pitch_with_map),
        'u_extrude_scale': new performance.Uniform2f(context, locations.u_extrude_scale),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix)
    };
};
var circleUniformValues = function (painter, coord, tile, layer) {
    var transform = painter.transform;
    var pitchWithMap, extrudeScale;
    if (layer.paint.get('circle-pitch-alignment') === 'map') {
        var pixelRatio = pixelsToTileUnits(tile, 1, transform.zoom);
        pitchWithMap = true;
        extrudeScale = [
            pixelRatio,
            pixelRatio
        ];
    } else {
        pitchWithMap = false;
        extrudeScale = transform.pixelsToGLUnits;
    }
    return {
        'u_camera_to_center_distance': transform.cameraToCenterDistance,
        'u_scale_with_map': +(layer.paint.get('circle-pitch-scale') === 'map'),
        'u_matrix': painter.translatePosMatrix(coord.posMatrix, tile, layer.paint.get('circle-translate'), layer.paint.get('circle-translate-anchor')),
        'u_pitch_with_map': +pitchWithMap,
        'u_device_pixel_ratio': performance.browser.devicePixelRatio,
        'u_extrude_scale': extrudeScale
    };
};

var collisionUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_camera_to_center_distance': new performance.Uniform1f(context, locations.u_camera_to_center_distance),
        'u_pixels_to_tile_units': new performance.Uniform1f(context, locations.u_pixels_to_tile_units),
        'u_extrude_scale': new performance.Uniform2f(context, locations.u_extrude_scale),
        'u_overscale_factor': new performance.Uniform1f(context, locations.u_overscale_factor)
    };
};
var collisionCircleUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_inv_matrix': new performance.UniformMatrix4f(context, locations.u_inv_matrix),
        'u_camera_to_center_distance': new performance.Uniform1f(context, locations.u_camera_to_center_distance),
        'u_viewport_size': new performance.Uniform2f(context, locations.u_viewport_size)
    };
};
var collisionUniformValues = function (matrix, transform, tile) {
    var pixelRatio = pixelsToTileUnits(tile, 1, transform.zoom);
    var scale = Math.pow(2, transform.zoom - tile.tileID.overscaledZ);
    var overscaleFactor = tile.tileID.overscaleFactor();
    return {
        'u_matrix': matrix,
        'u_camera_to_center_distance': transform.cameraToCenterDistance,
        'u_pixels_to_tile_units': pixelRatio,
        'u_extrude_scale': [
            transform.pixelsToGLUnits[0] / (pixelRatio * scale),
            transform.pixelsToGLUnits[1] / (pixelRatio * scale)
        ],
        'u_overscale_factor': overscaleFactor
    };
};
var collisionCircleUniformValues = function (matrix, invMatrix, transform) {
    return {
        'u_matrix': matrix,
        'u_inv_matrix': invMatrix,
        'u_camera_to_center_distance': transform.cameraToCenterDistance,
        'u_viewport_size': [
            transform.width,
            transform.height
        ]
    };
};

var debugUniforms = function (context, locations) {
    return {
        'u_color': new performance.UniformColor(context, locations.u_color),
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_overlay': new performance.Uniform1i(context, locations.u_overlay),
        'u_overlay_scale': new performance.Uniform1f(context, locations.u_overlay_scale)
    };
};
var debugUniformValues = function (matrix, color, scaleRatio) {
    if (scaleRatio === void 0)
        scaleRatio = 1;
    return {
        'u_matrix': matrix,
        'u_color': color,
        'u_overlay': 0,
        'u_overlay_scale': scaleRatio
    };
};

var clippingMaskUniforms = function (context, locations) {
    return { 'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix) };
};
var clippingMaskUniformValues = function (matrix) {
    return { 'u_matrix': matrix };
};

var heatmapUniforms = function (context, locations) {
    return {
        'u_extrude_scale': new performance.Uniform1f(context, locations.u_extrude_scale),
        'u_intensity': new performance.Uniform1f(context, locations.u_intensity),
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix)
    };
};
var heatmapTextureUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_world': new performance.Uniform2f(context, locations.u_world),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_color_ramp': new performance.Uniform1i(context, locations.u_color_ramp),
        'u_opacity': new performance.Uniform1f(context, locations.u_opacity)
    };
};
var heatmapUniformValues = function (matrix, tile, zoom, intensity) {
    return {
        'u_matrix': matrix,
        'u_extrude_scale': pixelsToTileUnits(tile, 1, zoom),
        'u_intensity': intensity
    };
};
var heatmapTextureUniformValues = function (painter, layer, textureUnit, colorRampUnit) {
    var matrix = performance.create();
    performance.ortho(matrix, 0, painter.width, painter.height, 0, 0, 1);
    var gl = painter.context.gl;
    return {
        'u_matrix': matrix,
        'u_world': [
            gl.drawingBufferWidth,
            gl.drawingBufferHeight
        ],
        'u_image': textureUnit,
        'u_color_ramp': colorRampUnit,
        'u_opacity': layer.paint.get('heatmap-opacity')
    };
};

var hillshadeUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_latrange': new performance.Uniform2f(context, locations.u_latrange),
        'u_light': new performance.Uniform2f(context, locations.u_light),
        'u_shadow': new performance.UniformColor(context, locations.u_shadow),
        'u_highlight': new performance.UniformColor(context, locations.u_highlight),
        'u_accent': new performance.UniformColor(context, locations.u_accent)
    };
};
var hillshadePrepareUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_dimension': new performance.Uniform2f(context, locations.u_dimension),
        'u_zoom': new performance.Uniform1f(context, locations.u_zoom),
        'u_unpack': new performance.Uniform4f(context, locations.u_unpack)
    };
};
var hillshadeUniformValues = function (painter, tile, layer) {
    var shadow = layer.paint.get('hillshade-shadow-color');
    var highlight = layer.paint.get('hillshade-highlight-color');
    var accent = layer.paint.get('hillshade-accent-color');
    var azimuthal = layer.paint.get('hillshade-illumination-direction') * (Math.PI / 180);
    if (layer.paint.get('hillshade-illumination-anchor') === 'viewport') {
        azimuthal -= painter.transform.angle;
    }
    var align = !painter.options.moving;
    return {
        'u_matrix': painter.transform.calculatePosMatrix(tile.tileID.toUnwrapped(), align),
        'u_image': 0,
        'u_latrange': getTileLatRange(painter, tile.tileID),
        'u_light': [
            layer.paint.get('hillshade-exaggeration'),
            azimuthal
        ],
        'u_shadow': shadow,
        'u_highlight': highlight,
        'u_accent': accent
    };
};
var hillshadeUniformPrepareValues = function (tileID, dem) {
    var stride = dem.stride;
    var matrix = performance.create();
    performance.ortho(matrix, 0, performance.EXTENT, -performance.EXTENT, 0, 0, 1);
    performance.translate(matrix, matrix, [
        0,
        -performance.EXTENT,
        0
    ]);
    return {
        'u_matrix': matrix,
        'u_image': 1,
        'u_dimension': [
            stride,
            stride
        ],
        'u_zoom': tileID.overscaledZ,
        'u_unpack': dem.getUnpackVector()
    };
};
function getTileLatRange(painter, tileID) {
    var tilesAtZoom = Math.pow(2, tileID.canonical.z);
    var y = tileID.canonical.y;
    return [
        new performance.MercatorCoordinate(0, y / tilesAtZoom).toLngLat().lat,
        new performance.MercatorCoordinate(0, (y + 1) / tilesAtZoom).toLngLat().lat
    ];
}

var lineUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_ratio': new performance.Uniform1f(context, locations.u_ratio),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_units_to_pixels': new performance.Uniform2f(context, locations.u_units_to_pixels)
    };
};
var lineGradientUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_ratio': new performance.Uniform1f(context, locations.u_ratio),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_units_to_pixels': new performance.Uniform2f(context, locations.u_units_to_pixels),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_image_height': new performance.Uniform1f(context, locations.u_image_height)
    };
};
var linePatternUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_ratio': new performance.Uniform1f(context, locations.u_ratio),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_units_to_pixels': new performance.Uniform2f(context, locations.u_units_to_pixels),
        'u_scale': new performance.Uniform3f(context, locations.u_scale),
        'u_fade': new performance.Uniform1f(context, locations.u_fade)
    };
};
var lineSDFUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_ratio': new performance.Uniform1f(context, locations.u_ratio),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_units_to_pixels': new performance.Uniform2f(context, locations.u_units_to_pixels),
        'u_patternscale_a': new performance.Uniform2f(context, locations.u_patternscale_a),
        'u_patternscale_b': new performance.Uniform2f(context, locations.u_patternscale_b),
        'u_sdfgamma': new performance.Uniform1f(context, locations.u_sdfgamma),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_tex_y_a': new performance.Uniform1f(context, locations.u_tex_y_a),
        'u_tex_y_b': new performance.Uniform1f(context, locations.u_tex_y_b),
        'u_mix': new performance.Uniform1f(context, locations.u_mix)
    };
};
var lineUniformValues = function (painter, tile, layer) {
    var transform = painter.transform;
    return {
        'u_matrix': calculateMatrix(painter, tile, layer),
        'u_ratio': 1 / pixelsToTileUnits(tile, 1, transform.zoom),
        'u_device_pixel_ratio': performance.browser.devicePixelRatio,
        'u_units_to_pixels': [
            1 / transform.pixelsToGLUnits[0],
            1 / transform.pixelsToGLUnits[1]
        ]
    };
};
var lineGradientUniformValues = function (painter, tile, layer, imageHeight) {
    return performance.extend(lineUniformValues(painter, tile, layer), {
        'u_image': 0,
        'u_image_height': imageHeight
    });
};
var linePatternUniformValues = function (painter, tile, layer, crossfade) {
    var transform = painter.transform;
    var tileZoomRatio = calculateTileRatio(tile, transform);
    return {
        'u_matrix': calculateMatrix(painter, tile, layer),
        'u_texsize': tile.imageAtlasTexture.size,
        'u_ratio': 1 / pixelsToTileUnits(tile, 1, transform.zoom),
        'u_device_pixel_ratio': performance.browser.devicePixelRatio,
        'u_image': 0,
        'u_scale': [
            tileZoomRatio,
            crossfade.fromScale,
            crossfade.toScale
        ],
        'u_fade': crossfade.t,
        'u_units_to_pixels': [
            1 / transform.pixelsToGLUnits[0],
            1 / transform.pixelsToGLUnits[1]
        ]
    };
};
var lineSDFUniformValues = function (painter, tile, layer, dasharray, crossfade) {
    var transform = painter.transform;
    var lineAtlas = painter.lineAtlas;
    var tileRatio = calculateTileRatio(tile, transform);
    var round = layer.layout.get('line-cap') === 'round';
    var posA = lineAtlas.getDash(dasharray.from, round);
    var posB = lineAtlas.getDash(dasharray.to, round);
    var widthA = posA.width * crossfade.fromScale;
    var widthB = posB.width * crossfade.toScale;
    return performance.extend(lineUniformValues(painter, tile, layer), {
        'u_patternscale_a': [
            tileRatio / widthA,
            -posA.height / 2
        ],
        'u_patternscale_b': [
            tileRatio / widthB,
            -posB.height / 2
        ],
        'u_sdfgamma': lineAtlas.width / (Math.min(widthA, widthB) * 256 * performance.browser.devicePixelRatio) / 2,
        'u_image': 0,
        'u_tex_y_a': posA.y,
        'u_tex_y_b': posB.y,
        'u_mix': crossfade.t
    });
};
function calculateTileRatio(tile, transform) {
    return 1 / pixelsToTileUnits(tile, 1, transform.tileZoom);
}
function calculateMatrix(painter, tile, layer) {
    return painter.translatePosMatrix(tile.tileID.posMatrix, tile, layer.paint.get('line-translate'), layer.paint.get('line-translate-anchor'));
}

var rasterUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_tl_parent': new performance.Uniform2f(context, locations.u_tl_parent),
        'u_scale_parent': new performance.Uniform1f(context, locations.u_scale_parent),
        'u_buffer_scale': new performance.Uniform1f(context, locations.u_buffer_scale),
        'u_fade_t': new performance.Uniform1f(context, locations.u_fade_t),
        'u_opacity': new performance.Uniform1f(context, locations.u_opacity),
        'u_image0': new performance.Uniform1i(context, locations.u_image0),
        'u_image1': new performance.Uniform1i(context, locations.u_image1),
        'u_brightness_low': new performance.Uniform1f(context, locations.u_brightness_low),
        'u_brightness_high': new performance.Uniform1f(context, locations.u_brightness_high),
        'u_saturation_factor': new performance.Uniform1f(context, locations.u_saturation_factor),
        'u_contrast_factor': new performance.Uniform1f(context, locations.u_contrast_factor),
        'u_spin_weights': new performance.Uniform3f(context, locations.u_spin_weights)
    };
};
var rasterUniformValues = function (matrix, parentTL, parentScaleBy, fade, layer) {
    return {
        'u_matrix': matrix,
        'u_tl_parent': parentTL,
        'u_scale_parent': parentScaleBy,
        'u_buffer_scale': 1,
        'u_fade_t': fade.mix,
        'u_opacity': fade.opacity * layer.paint.get('raster-opacity'),
        'u_image0': 0,
        'u_image1': 1,
        'u_brightness_low': layer.paint.get('raster-brightness-min'),
        'u_brightness_high': layer.paint.get('raster-brightness-max'),
        'u_saturation_factor': saturationFactor(layer.paint.get('raster-saturation')),
        'u_contrast_factor': contrastFactor(layer.paint.get('raster-contrast')),
        'u_spin_weights': spinWeights(layer.paint.get('raster-hue-rotate'))
    };
};
function spinWeights(angle) {
    angle *= Math.PI / 180;
    var s = Math.sin(angle);
    var c = Math.cos(angle);
    return [
        (2 * c + 1) / 3,
        (-Math.sqrt(3) * s - c + 1) / 3,
        (Math.sqrt(3) * s - c + 1) / 3
    ];
}
function contrastFactor(contrast) {
    return contrast > 0 ? 1 / (1 - contrast) : 1 + contrast;
}
function saturationFactor(saturation) {
    return saturation > 0 ? 1 - 1 / (1.001 - saturation) : -saturation;
}

var symbolIconUniforms = function (context, locations) {
    return {
        'u_is_size_zoom_constant': new performance.Uniform1i(context, locations.u_is_size_zoom_constant),
        'u_is_size_feature_constant': new performance.Uniform1i(context, locations.u_is_size_feature_constant),
        'u_size_t': new performance.Uniform1f(context, locations.u_size_t),
        'u_size': new performance.Uniform1f(context, locations.u_size),
        'u_camera_to_center_distance': new performance.Uniform1f(context, locations.u_camera_to_center_distance),
        'u_pitch': new performance.Uniform1f(context, locations.u_pitch),
        'u_rotate_symbol': new performance.Uniform1i(context, locations.u_rotate_symbol),
        'u_aspect_ratio': new performance.Uniform1f(context, locations.u_aspect_ratio),
        'u_fade_change': new performance.Uniform1f(context, locations.u_fade_change),
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_label_plane_matrix': new performance.UniformMatrix4f(context, locations.u_label_plane_matrix),
        'u_coord_matrix': new performance.UniformMatrix4f(context, locations.u_coord_matrix),
        'u_is_text': new performance.Uniform1i(context, locations.u_is_text),
        'u_pitch_with_map': new performance.Uniform1i(context, locations.u_pitch_with_map),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_texture': new performance.Uniform1i(context, locations.u_texture)
    };
};
var symbolSDFUniforms = function (context, locations) {
    return {
        'u_is_size_zoom_constant': new performance.Uniform1i(context, locations.u_is_size_zoom_constant),
        'u_is_size_feature_constant': new performance.Uniform1i(context, locations.u_is_size_feature_constant),
        'u_size_t': new performance.Uniform1f(context, locations.u_size_t),
        'u_size': new performance.Uniform1f(context, locations.u_size),
        'u_camera_to_center_distance': new performance.Uniform1f(context, locations.u_camera_to_center_distance),
        'u_pitch': new performance.Uniform1f(context, locations.u_pitch),
        'u_rotate_symbol': new performance.Uniform1i(context, locations.u_rotate_symbol),
        'u_aspect_ratio': new performance.Uniform1f(context, locations.u_aspect_ratio),
        'u_fade_change': new performance.Uniform1f(context, locations.u_fade_change),
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_label_plane_matrix': new performance.UniformMatrix4f(context, locations.u_label_plane_matrix),
        'u_coord_matrix': new performance.UniformMatrix4f(context, locations.u_coord_matrix),
        'u_is_text': new performance.Uniform1i(context, locations.u_is_text),
        'u_pitch_with_map': new performance.Uniform1i(context, locations.u_pitch_with_map),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_texture': new performance.Uniform1i(context, locations.u_texture),
        'u_gamma_scale': new performance.Uniform1f(context, locations.u_gamma_scale),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_is_halo': new performance.Uniform1i(context, locations.u_is_halo)
    };
};
var symbolTextAndIconUniforms = function (context, locations) {
    return {
        'u_is_size_zoom_constant': new performance.Uniform1i(context, locations.u_is_size_zoom_constant),
        'u_is_size_feature_constant': new performance.Uniform1i(context, locations.u_is_size_feature_constant),
        'u_size_t': new performance.Uniform1f(context, locations.u_size_t),
        'u_size': new performance.Uniform1f(context, locations.u_size),
        'u_camera_to_center_distance': new performance.Uniform1f(context, locations.u_camera_to_center_distance),
        'u_pitch': new performance.Uniform1f(context, locations.u_pitch),
        'u_rotate_symbol': new performance.Uniform1i(context, locations.u_rotate_symbol),
        'u_aspect_ratio': new performance.Uniform1f(context, locations.u_aspect_ratio),
        'u_fade_change': new performance.Uniform1f(context, locations.u_fade_change),
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_label_plane_matrix': new performance.UniformMatrix4f(context, locations.u_label_plane_matrix),
        'u_coord_matrix': new performance.UniformMatrix4f(context, locations.u_coord_matrix),
        'u_is_text': new performance.Uniform1i(context, locations.u_is_text),
        'u_pitch_with_map': new performance.Uniform1i(context, locations.u_pitch_with_map),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_texsize_icon': new performance.Uniform2f(context, locations.u_texsize_icon),
        'u_texture': new performance.Uniform1i(context, locations.u_texture),
        'u_texture_icon': new performance.Uniform1i(context, locations.u_texture_icon),
        'u_gamma_scale': new performance.Uniform1f(context, locations.u_gamma_scale),
        'u_device_pixel_ratio': new performance.Uniform1f(context, locations.u_device_pixel_ratio),
        'u_is_halo': new performance.Uniform1i(context, locations.u_is_halo)
    };
};
var symbolIconUniformValues = function (functionType, size, rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix, glCoordMatrix, isText, texSize) {
    var transform = painter.transform;
    return {
        'u_is_size_zoom_constant': +(functionType === 'constant' || functionType === 'source'),
        'u_is_size_feature_constant': +(functionType === 'constant' || functionType === 'camera'),
        'u_size_t': size ? size.uSizeT : 0,
        'u_size': size ? size.uSize : 0,
        'u_camera_to_center_distance': transform.cameraToCenterDistance,
        'u_pitch': transform.pitch / 360 * 2 * Math.PI,
        'u_rotate_symbol': +rotateInShader,
        'u_aspect_ratio': transform.width / transform.height,
        'u_fade_change': painter.options.fadeDuration ? painter.symbolFadeChange : 1,
        'u_matrix': matrix,
        'u_label_plane_matrix': labelPlaneMatrix,
        'u_coord_matrix': glCoordMatrix,
        'u_is_text': +isText,
        'u_pitch_with_map': +pitchWithMap,
        'u_texsize': texSize,
        'u_texture': 0
    };
};
var symbolSDFUniformValues = function (functionType, size, rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix, glCoordMatrix, isText, texSize, isHalo) {
    var transform = painter.transform;
    return performance.extend(symbolIconUniformValues(functionType, size, rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix, glCoordMatrix, isText, texSize), {
        'u_gamma_scale': pitchWithMap ? Math.cos(transform._pitch) * transform.cameraToCenterDistance : 1,
        'u_device_pixel_ratio': performance.browser.devicePixelRatio,
        'u_is_halo': +isHalo
    });
};
var symbolTextAndIconUniformValues = function (functionType, size, rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix, glCoordMatrix, texSizeSDF, texSizeIcon) {
    return performance.extend(symbolSDFUniformValues(functionType, size, rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix, glCoordMatrix, true, texSizeSDF, true), {
        'u_texsize_icon': texSizeIcon,
        'u_texture_icon': 1
    });
};

var backgroundUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_opacity': new performance.Uniform1f(context, locations.u_opacity),
        'u_color': new performance.UniformColor(context, locations.u_color)
    };
};
var backgroundPatternUniforms = function (context, locations) {
    return {
        'u_matrix': new performance.UniformMatrix4f(context, locations.u_matrix),
        'u_opacity': new performance.Uniform1f(context, locations.u_opacity),
        'u_image': new performance.Uniform1i(context, locations.u_image),
        'u_pattern_tl_a': new performance.Uniform2f(context, locations.u_pattern_tl_a),
        'u_pattern_br_a': new performance.Uniform2f(context, locations.u_pattern_br_a),
        'u_pattern_tl_b': new performance.Uniform2f(context, locations.u_pattern_tl_b),
        'u_pattern_br_b': new performance.Uniform2f(context, locations.u_pattern_br_b),
        'u_texsize': new performance.Uniform2f(context, locations.u_texsize),
        'u_mix': new performance.Uniform1f(context, locations.u_mix),
        'u_pattern_size_a': new performance.Uniform2f(context, locations.u_pattern_size_a),
        'u_pattern_size_b': new performance.Uniform2f(context, locations.u_pattern_size_b),
        'u_scale_a': new performance.Uniform1f(context, locations.u_scale_a),
        'u_scale_b': new performance.Uniform1f(context, locations.u_scale_b),
        'u_pixel_coord_upper': new performance.Uniform2f(context, locations.u_pixel_coord_upper),
        'u_pixel_coord_lower': new performance.Uniform2f(context, locations.u_pixel_coord_lower),
        'u_tile_units_to_pixels': new performance.Uniform1f(context, locations.u_tile_units_to_pixels)
    };
};
var backgroundUniformValues = function (matrix, opacity, color) {
    return {
        'u_matrix': matrix,
        'u_opacity': opacity,
        'u_color': color
    };
};
var backgroundPatternUniformValues = function (matrix, opacity, painter, image, tile, crossfade) {
    return performance.extend(bgPatternUniformValues(image, crossfade, painter, tile), {
        'u_matrix': matrix,
        'u_opacity': opacity
    });
};

var programUniforms = {
    fillExtrusion: fillExtrusionUniforms,
    fillExtrusionPattern: fillExtrusionPatternUniforms,
    fill: fillUniforms,
    fillPattern: fillPatternUniforms,
    fillOutline: fillOutlineUniforms,
    fillOutlinePattern: fillOutlinePatternUniforms,
    circle: circleUniforms,
    collisionBox: collisionUniforms,
    collisionCircle: collisionCircleUniforms,
    debug: debugUniforms,
    clippingMask: clippingMaskUniforms,
    heatmap: heatmapUniforms,
    heatmapTexture: heatmapTextureUniforms,
    hillshade: hillshadeUniforms,
    hillshadePrepare: hillshadePrepareUniforms,
    line: lineUniforms,
    lineGradient: lineGradientUniforms,
    linePattern: linePatternUniforms,
    lineSDF: lineSDFUniforms,
    raster: rasterUniforms,
    symbolIcon: symbolIconUniforms,
    symbolSDF: symbolSDFUniforms,
    symbolTextAndIcon: symbolTextAndIconUniforms,
    background: backgroundUniforms,
    backgroundPattern: backgroundPatternUniforms
};

var quadTriangles;
function drawCollisionDebug(painter, sourceCache, layer, coords, translate, translateAnchor, isText) {
    var context = painter.context;
    var gl = context.gl;
    var program = painter.useProgram('collisionBox');
    var tileBatches = [];
    var circleCount = 0;
    var circleOffset = 0;
    for (var i = 0; i < coords.length; i++) {
        var coord = coords[i];
        var tile = sourceCache.getTile(coord);
        var bucket = tile.getBucket(layer);
        if (!bucket) {
            continue;
        }
        var posMatrix = coord.posMatrix;
        if (translate[0] !== 0 || translate[1] !== 0) {
            posMatrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor);
        }
        var buffers = isText ? bucket.textCollisionBox : bucket.iconCollisionBox;
        var circleArray = bucket.collisionCircleArray;
        if (circleArray.length > 0) {
            var invTransform = performance.create();
            var transform = posMatrix;
            performance.mul(invTransform, bucket.placementInvProjMatrix, painter.transform.glCoordMatrix);
            performance.mul(invTransform, invTransform, bucket.placementViewportMatrix);
            tileBatches.push({
                circleArray: circleArray,
                circleOffset: circleOffset,
                transform: transform,
                invTransform: invTransform
            });
            circleCount += circleArray.length / 4;
            circleOffset = circleCount;
        }
        if (!buffers) {
            continue;
        }
        program.draw(context, gl.LINES, DepthMode.disabled, StencilMode.disabled, painter.colorModeForRenderPass(), CullFaceMode.disabled, collisionUniformValues(posMatrix, painter.transform, tile), layer.id, buffers.layoutVertexBuffer, buffers.indexBuffer, buffers.segments, null, painter.transform.zoom, null, null, buffers.collisionVertexBuffer);
    }
    if (!isText || !tileBatches.length) {
        return;
    }
    var circleProgram = painter.useProgram('collisionCircle');
    var vertexData = new performance.StructArrayLayout2f1f2i16();
    vertexData.resize(circleCount * 4);
    vertexData._trim();
    var vertexOffset = 0;
    for (var i$2 = 0, list = tileBatches; i$2 < list.length; i$2 += 1) {
        var batch = list[i$2];
        for (var i$1 = 0; i$1 < batch.circleArray.length / 4; i$1++) {
            var circleIdx = i$1 * 4;
            var x = batch.circleArray[circleIdx + 0];
            var y = batch.circleArray[circleIdx + 1];
            var radius = batch.circleArray[circleIdx + 2];
            var collision = batch.circleArray[circleIdx + 3];
            vertexData.emplace(vertexOffset++, x, y, radius, collision, 0);
            vertexData.emplace(vertexOffset++, x, y, radius, collision, 1);
            vertexData.emplace(vertexOffset++, x, y, radius, collision, 2);
            vertexData.emplace(vertexOffset++, x, y, radius, collision, 3);
        }
    }
    if (!quadTriangles || quadTriangles.length < circleCount * 2) {
        quadTriangles = createQuadTriangles(circleCount);
    }
    var indexBuffer = context.createIndexBuffer(quadTriangles, true);
    var vertexBuffer = context.createVertexBuffer(vertexData, performance.collisionCircleLayout.members, true);
    for (var i$3 = 0, list$1 = tileBatches; i$3 < list$1.length; i$3 += 1) {
        var batch$1 = list$1[i$3];
        var uniforms = collisionCircleUniformValues(batch$1.transform, batch$1.invTransform, painter.transform);
        circleProgram.draw(context, gl.TRIANGLES, DepthMode.disabled, StencilMode.disabled, painter.colorModeForRenderPass(), CullFaceMode.disabled, uniforms, layer.id, vertexBuffer, indexBuffer, performance.SegmentVector.simpleSegment(0, batch$1.circleOffset * 2, batch$1.circleArray.length, batch$1.circleArray.length / 2), null, painter.transform.zoom, null, null, null);
    }
    vertexBuffer.destroy();
    indexBuffer.destroy();
}
function createQuadTriangles(quadCount) {
    var triCount = quadCount * 2;
    var array = new performance.StructArrayLayout3ui6();
    array.resize(triCount);
    array._trim();
    for (var i = 0; i < triCount; i++) {
        var idx = i * 6;
        array.uint16[idx + 0] = i * 4 + 0;
        array.uint16[idx + 1] = i * 4 + 1;
        array.uint16[idx + 2] = i * 4 + 2;
        array.uint16[idx + 3] = i * 4 + 2;
        array.uint16[idx + 4] = i * 4 + 3;
        array.uint16[idx + 5] = i * 4 + 0;
    }
    return array;
}

var identityMat4 = performance.identity(new Float32Array(16));
function drawSymbols(painter, sourceCache, layer, coords, variableOffsets) {
    if (painter.renderPass !== 'translucent') {
        return;
    }
    var stencilMode = StencilMode.disabled;
    var colorMode = painter.colorModeForRenderPass();
    var variablePlacement = layer.layout.get('text-variable-anchor');
    if (variablePlacement) {
        updateVariableAnchors(coords, painter, layer, sourceCache, layer.layout.get('text-rotation-alignment'), layer.layout.get('text-pitch-alignment'), variableOffsets);
    }
    if (layer.paint.get('icon-opacity').constantOr(1) !== 0) {
        drawLayerSymbols(painter, sourceCache, layer, coords, false, layer.paint.get('icon-translate'), layer.paint.get('icon-translate-anchor'), layer.layout.get('icon-rotation-alignment'), layer.layout.get('icon-pitch-alignment'), layer.layout.get('icon-keep-upright'), stencilMode, colorMode);
    }
    if (layer.paint.get('text-opacity').constantOr(1) !== 0) {
        drawLayerSymbols(painter, sourceCache, layer, coords, true, layer.paint.get('text-translate'), layer.paint.get('text-translate-anchor'), layer.layout.get('text-rotation-alignment'), layer.layout.get('text-pitch-alignment'), layer.layout.get('text-keep-upright'), stencilMode, colorMode);
    }
    if (sourceCache.map.showCollisionBoxes) {
        drawCollisionDebug(painter, sourceCache, layer, coords, layer.paint.get('text-translate'), layer.paint.get('text-translate-anchor'), true);
        drawCollisionDebug(painter, sourceCache, layer, coords, layer.paint.get('icon-translate'), layer.paint.get('icon-translate-anchor'), false);
    }
}
function calculateVariableRenderShift(anchor, width, height, textOffset, textBoxScale, renderTextSize) {
    var ref = performance.getAnchorAlignment(anchor);
    var horizontalAlign = ref.horizontalAlign;
    var verticalAlign = ref.verticalAlign;
    var shiftX = -(horizontalAlign - 0.5) * width;
    var shiftY = -(verticalAlign - 0.5) * height;
    var variableOffset = performance.evaluateVariableOffset(anchor, textOffset);
    return new performance.Point((shiftX / textBoxScale + variableOffset[0]) * renderTextSize, (shiftY / textBoxScale + variableOffset[1]) * renderTextSize);
}
function updateVariableAnchors(coords, painter, layer, sourceCache, rotationAlignment, pitchAlignment, variableOffsets) {
    var tr = painter.transform;
    var rotateWithMap = rotationAlignment === 'map';
    var pitchWithMap = pitchAlignment === 'map';
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        var tile = sourceCache.getTile(coord);
        var bucket = tile.getBucket(layer);
        if (!bucket || !bucket.text || !bucket.text.segments.get().length) {
            continue;
        }
        var sizeData = bucket.textSizeData;
        var size = performance.evaluateSizeForZoom(sizeData, tr.zoom);
        var pixelToTileScale = pixelsToTileUnits(tile, 1, painter.transform.zoom);
        var labelPlaneMatrix = getLabelPlaneMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, pixelToTileScale);
        var updateTextFitIcon = layer.layout.get('icon-text-fit') !== 'none' && bucket.hasIconData();
        if (size) {
            var tileScale = Math.pow(2, tr.zoom - tile.tileID.overscaledZ);
            updateVariableAnchorsForBucket(bucket, rotateWithMap, pitchWithMap, variableOffsets, performance.symbolSize, tr, labelPlaneMatrix, coord.posMatrix, tileScale, size, updateTextFitIcon);
        }
    }
}
function updateVariableAnchorsForBucket(bucket, rotateWithMap, pitchWithMap, variableOffsets, symbolSize, transform, labelPlaneMatrix, posMatrix, tileScale, size, updateTextFitIcon) {
    var placedSymbols = bucket.text.placedSymbolArray;
    var dynamicTextLayoutVertexArray = bucket.text.dynamicLayoutVertexArray;
    var dynamicIconLayoutVertexArray = bucket.icon.dynamicLayoutVertexArray;
    var placedTextShifts = {};
    dynamicTextLayoutVertexArray.clear();
    for (var s = 0; s < placedSymbols.length; s++) {
        var symbol = placedSymbols.get(s);
        var skipOrientation = bucket.allowVerticalPlacement && !symbol.placedOrientation;
        var variableOffset = !symbol.hidden && symbol.crossTileID && !skipOrientation ? variableOffsets[symbol.crossTileID] : null;
        if (!variableOffset) {
            hideGlyphs(symbol.numGlyphs, dynamicTextLayoutVertexArray);
        } else {
            var tileAnchor = new performance.Point(symbol.anchorX, symbol.anchorY);
            var projectedAnchor = project(tileAnchor, pitchWithMap ? posMatrix : labelPlaneMatrix);
            var perspectiveRatio = getPerspectiveRatio(transform.cameraToCenterDistance, projectedAnchor.signedDistanceFromCamera);
            var renderTextSize = symbolSize.evaluateSizeForFeature(bucket.textSizeData, size, symbol) * perspectiveRatio / performance.ONE_EM;
            if (pitchWithMap) {
                renderTextSize *= bucket.tilePixelRatio / tileScale;
            }
            var width = variableOffset.width;
            var height = variableOffset.height;
            var anchor = variableOffset.anchor;
            var textOffset = variableOffset.textOffset;
            var textBoxScale = variableOffset.textBoxScale;
            var shift = calculateVariableRenderShift(anchor, width, height, textOffset, textBoxScale, renderTextSize);
            var shiftedAnchor = pitchWithMap ? project(tileAnchor.add(shift), labelPlaneMatrix).point : projectedAnchor.point.add(rotateWithMap ? shift.rotate(-transform.angle) : shift);
            var angle = bucket.allowVerticalPlacement && symbol.placedOrientation === performance.WritingMode.vertical ? Math.PI / 2 : 0;
            for (var g = 0; g < symbol.numGlyphs; g++) {
                performance.addDynamicAttributes(dynamicTextLayoutVertexArray, shiftedAnchor, angle);
            }
            if (updateTextFitIcon && symbol.associatedIconIndex >= 0) {
                placedTextShifts[symbol.associatedIconIndex] = {
                    shiftedAnchor: shiftedAnchor,
                    angle: angle
                };
            }
        }
    }
    if (updateTextFitIcon) {
        dynamicIconLayoutVertexArray.clear();
        var placedIcons = bucket.icon.placedSymbolArray;
        for (var i = 0; i < placedIcons.length; i++) {
            var placedIcon = placedIcons.get(i);
            if (placedIcon.hidden) {
                hideGlyphs(placedIcon.numGlyphs, dynamicIconLayoutVertexArray);
            } else {
                var shift$1 = placedTextShifts[i];
                if (!shift$1) {
                    hideGlyphs(placedIcon.numGlyphs, dynamicIconLayoutVertexArray);
                } else {
                    for (var g$1 = 0; g$1 < placedIcon.numGlyphs; g$1++) {
                        performance.addDynamicAttributes(dynamicIconLayoutVertexArray, shift$1.shiftedAnchor, shift$1.angle);
                    }
                }
            }
        }
        bucket.icon.dynamicLayoutVertexBuffer.updateData(dynamicIconLayoutVertexArray);
    }
    bucket.text.dynamicLayoutVertexBuffer.updateData(dynamicTextLayoutVertexArray);
}
function getSymbolProgramName(isSDF, isText, bucket) {
    if (bucket.iconsInText && isText) {
        return 'symbolTextAndIcon';
    } else if (isSDF) {
        return 'symbolSDF';
    } else {
        return 'symbolIcon';
    }
}
function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate, translateAnchor, rotationAlignment, pitchAlignment, keepUpright, stencilMode, colorMode) {
    var context = painter.context;
    var gl = context.gl;
    var tr = painter.transform;
    var rotateWithMap = rotationAlignment === 'map';
    var pitchWithMap = pitchAlignment === 'map';
    var alongLine = rotateWithMap && layer.layout.get('symbol-placement') !== 'point';
    var rotateInShader = rotateWithMap && !pitchWithMap && !alongLine;
    var hasSortKey = layer.layout.get('symbol-sort-key').constantOr(1) !== undefined;
    var sortFeaturesByKey = false;
    var depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
    var variablePlacement = layer.layout.get('text-variable-anchor');
    var tileRenderState = [];
    for (var i$1 = 0, list$1 = coords; i$1 < list$1.length; i$1 += 1) {
        var coord = list$1[i$1];
        var tile = sourceCache.getTile(coord);
        var bucket = tile.getBucket(layer);
        if (!bucket) {
            continue;
        }
        var buffers = isText ? bucket.text : bucket.icon;
        if (!buffers || !buffers.segments.get().length) {
            continue;
        }
        var programConfiguration = buffers.programConfigurations.get(layer.id);
        var isSDF = isText || bucket.sdfIcons;
        var sizeData = isText ? bucket.textSizeData : bucket.iconSizeData;
        var transformed = pitchWithMap || tr.pitch !== 0;
        var program = painter.useProgram(getSymbolProgramName(isSDF, isText, bucket), programConfiguration);
        var size = performance.evaluateSizeForZoom(sizeData, tr.zoom);
        var texSize = void 0;
        var texSizeIcon = [
            0,
            0
        ];
        var atlasTexture = void 0;
        var atlasInterpolation = void 0;
        var atlasTextureIcon = null;
        var atlasInterpolationIcon = void 0;
        if (isText) {
            atlasTexture = tile.glyphAtlasTexture;
            atlasInterpolation = gl.LINEAR;
            texSize = tile.glyphAtlasTexture.size;
            if (bucket.iconsInText) {
                texSizeIcon = tile.imageAtlasTexture.size;
                atlasTextureIcon = tile.imageAtlasTexture;
                var zoomDependentSize = sizeData.kind === 'composite' || sizeData.kind === 'camera';
                atlasInterpolationIcon = transformed || painter.options.rotating || painter.options.zooming || zoomDependentSize ? gl.LINEAR : gl.NEAREST;
            }
        } else {
            var iconScaled = layer.layout.get('icon-size').constantOr(0) !== 1 || bucket.iconsNeedLinear;
            atlasTexture = tile.imageAtlasTexture;
            atlasInterpolation = isSDF || painter.options.rotating || painter.options.zooming || iconScaled || transformed ? gl.LINEAR : gl.NEAREST;
            texSize = tile.imageAtlasTexture.size;
        }
        var s = pixelsToTileUnits(tile, 1, painter.transform.zoom);
        var labelPlaneMatrix = getLabelPlaneMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, s);
        var glCoordMatrix = getGlCoordMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, s);
        var hasVariableAnchors = variablePlacement && bucket.hasTextData();
        var updateTextFitIcon = layer.layout.get('icon-text-fit') !== 'none' && hasVariableAnchors && bucket.hasIconData();
        if (alongLine) {
            updateLineLabels(bucket, coord.posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright);
        }
        var matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor), uLabelPlaneMatrix = alongLine || isText && variablePlacement || updateTextFitIcon ? identityMat4 : labelPlaneMatrix, uglCoordMatrix = painter.translatePosMatrix(glCoordMatrix, tile, translate, translateAnchor, true);
        var hasHalo = isSDF && layer.paint.get(isText ? 'text-halo-width' : 'icon-halo-width').constantOr(1) !== 0;
        var uniformValues = void 0;
        if (isSDF) {
            if (!bucket.iconsInText) {
                uniformValues = symbolSDFUniformValues(sizeData.kind, size, rotateInShader, pitchWithMap, painter, matrix, uLabelPlaneMatrix, uglCoordMatrix, isText, texSize, true);
            } else {
                uniformValues = symbolTextAndIconUniformValues(sizeData.kind, size, rotateInShader, pitchWithMap, painter, matrix, uLabelPlaneMatrix, uglCoordMatrix, texSize, texSizeIcon);
            }
        } else {
            uniformValues = symbolIconUniformValues(sizeData.kind, size, rotateInShader, pitchWithMap, painter, matrix, uLabelPlaneMatrix, uglCoordMatrix, isText, texSize);
        }
        var state = {
            program: program,
            buffers: buffers,
            uniformValues: uniformValues,
            atlasTexture: atlasTexture,
            atlasTextureIcon: atlasTextureIcon,
            atlasInterpolation: atlasInterpolation,
            atlasInterpolationIcon: atlasInterpolationIcon,
            isSDF: isSDF,
            hasHalo: hasHalo
        };
        if (hasSortKey && bucket.canOverlap) {
            sortFeaturesByKey = true;
            var oldSegments = buffers.segments.get();
            for (var i = 0, list = oldSegments; i < list.length; i += 1) {
                var segment = list[i];
                tileRenderState.push({
                    segments: new performance.SegmentVector([segment]),
                    sortKey: segment.sortKey,
                    state: state
                });
            }
        } else {
            tileRenderState.push({
                segments: buffers.segments,
                sortKey: 0,
                state: state
            });
        }
    }
    if (sortFeaturesByKey) {
        tileRenderState.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
    for (var i$2 = 0, list$2 = tileRenderState; i$2 < list$2.length; i$2 += 1) {
        var segmentState = list$2[i$2];
        var state$1 = segmentState.state;
        context.activeTexture.set(gl.TEXTURE0);
        state$1.atlasTexture.bind(state$1.atlasInterpolation, gl.CLAMP_TO_EDGE);
        if (state$1.atlasTextureIcon) {
            context.activeTexture.set(gl.TEXTURE1);
            if (state$1.atlasTextureIcon) {
                state$1.atlasTextureIcon.bind(state$1.atlasInterpolationIcon, gl.CLAMP_TO_EDGE);
            }
        }
        if (state$1.isSDF) {
            var uniformValues$1 = state$1.uniformValues;
            if (state$1.hasHalo) {
                uniformValues$1['u_is_halo'] = 1;
                drawSymbolElements(state$1.buffers, segmentState.segments, layer, painter, state$1.program, depthMode, stencilMode, colorMode, uniformValues$1);
            }
            uniformValues$1['u_is_halo'] = 0;
        }
        drawSymbolElements(state$1.buffers, segmentState.segments, layer, painter, state$1.program, depthMode, stencilMode, colorMode, state$1.uniformValues);
    }
}
function drawSymbolElements(buffers, segments, layer, painter, program, depthMode, stencilMode, colorMode, uniformValues) {
    var context = painter.context;
    var gl = context.gl;
    program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled, uniformValues, layer.id, buffers.layoutVertexBuffer, buffers.indexBuffer, segments, layer.paint, painter.transform.zoom, buffers.programConfigurations.get(layer.id), buffers.dynamicLayoutVertexBuffer, buffers.opacityVertexBuffer);
}

function drawCircles(painter, sourceCache, layer, coords) {
    if (painter.renderPass !== 'translucent') {
        return;
    }
    var opacity = layer.paint.get('circle-opacity');
    var strokeWidth = layer.paint.get('circle-stroke-width');
    var strokeOpacity = layer.paint.get('circle-stroke-opacity');
    var sortFeaturesByKey = layer.layout.get('circle-sort-key').constantOr(1) !== undefined;
    if (opacity.constantOr(1) === 0 && (strokeWidth.constantOr(1) === 0 || strokeOpacity.constantOr(1) === 0)) {
        return;
    }
    var context = painter.context;
    var gl = context.gl;
    var depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
    var stencilMode = StencilMode.disabled;
    var colorMode = painter.colorModeForRenderPass();
    var segmentsRenderStates = [];
    for (var i = 0; i < coords.length; i++) {
        var coord = coords[i];
        var tile = sourceCache.getTile(coord);
        var bucket = tile.getBucket(layer);
        if (!bucket) {
            continue;
        }
        var programConfiguration = bucket.programConfigurations.get(layer.id);
        var program = painter.useProgram('circle', programConfiguration);
        var layoutVertexBuffer = bucket.layoutVertexBuffer;
        var indexBuffer = bucket.indexBuffer;
        var uniformValues = circleUniformValues(painter, coord, tile, layer);
        var state = {
            programConfiguration: programConfiguration,
            program: program,
            layoutVertexBuffer: layoutVertexBuffer,
            indexBuffer: indexBuffer,
            uniformValues: uniformValues
        };
        if (sortFeaturesByKey) {
            var oldSegments = bucket.segments.get();
            for (var i$1 = 0, list = oldSegments; i$1 < list.length; i$1 += 1) {
                var segment = list[i$1];
                segmentsRenderStates.push({
                    segments: new performance.SegmentVector([segment]),
                    sortKey: segment.sortKey,
                    state: state
                });
            }
        } else {
            segmentsRenderStates.push({
                segments: bucket.segments,
                sortKey: 0,
                state: state
            });
        }
    }
    if (sortFeaturesByKey) {
        segmentsRenderStates.sort(function (a, b) {
            return a.sortKey - b.sortKey;
        });
    }
    for (var i$2 = 0, list$1 = segmentsRenderStates; i$2 < list$1.length; i$2 += 1) {
        var segmentsState = list$1[i$2];
        var ref = segmentsState.state;
        var programConfiguration$1 = ref.programConfiguration;
        var program$1 = ref.program;
        var layoutVertexBuffer$1 = ref.layoutVertexBuffer;
        var indexBuffer$1 = ref.indexBuffer;
        var uniformValues$1 = ref.uniformValues;
        var segments = segmentsState.segments;
        program$1.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled, uniformValues$1, layer.id, layoutVertexBuffer$1, indexBuffer$1, segments, layer.paint, painter.transform.zoom, programConfiguration$1);
    }
}

function drawHeatmap(painter, sourceCache, layer, coords) {
    if (layer.paint.get('heatmap-opacity') === 0) {
        return;
    }
    if (painter.renderPass === 'offscreen') {
        var context = painter.context;
        var gl = context.gl;
        var stencilMode = StencilMode.disabled;
        var colorMode = new ColorMode([
            gl.ONE,
            gl.ONE
        ], performance.Color.transparent, [
            true,
            true,
            true,
            true
        ]);
        bindFramebuffer(context, painter, layer);
        context.clear({ color: performance.Color.transparent });
        for (var i = 0; i < coords.length; i++) {
            var coord = coords[i];
            if (sourceCache.hasRenderableParent(coord)) {
                continue;
            }
            var tile = sourceCache.getTile(coord);
            var bucket = tile.getBucket(layer);
            if (!bucket) {
                continue;
            }
            var programConfiguration = bucket.programConfigurations.get(layer.id);
            var program = painter.useProgram('heatmap', programConfiguration);
            var ref = painter.transform;
            var zoom = ref.zoom;
            program.draw(context, gl.TRIANGLES, DepthMode.disabled, stencilMode, colorMode, CullFaceMode.disabled, heatmapUniformValues(coord.posMatrix, tile, zoom, layer.paint.get('heatmap-intensity')), layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer, bucket.segments, layer.paint, painter.transform.zoom, programConfiguration);
        }
        context.viewport.set([
            0,
            0,
            painter.width,
            painter.height
        ]);
    } else if (painter.renderPass === 'translucent') {
        painter.context.setColorMode(painter.colorModeForRenderPass());
        renderTextureToMap(painter, layer);
    }
}
function bindFramebuffer(context, painter, layer) {
    var gl = context.gl;
    context.activeTexture.set(gl.TEXTURE1);
    context.viewport.set([
        0,
        0,
        painter.width / 4,
        painter.height / 4
    ]);
    var fbo = layer.heatmapFbo;
    if (!fbo) {
        var texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        fbo = layer.heatmapFbo = context.createFramebuffer(painter.width / 4, painter.height / 4, false);
        bindTextureToFramebuffer(context, painter, texture, fbo);
    } else {
        gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
        context.bindFramebuffer.set(fbo.framebuffer);
    }
}
function bindTextureToFramebuffer(context, painter, texture, fbo) {
    var gl = context.gl;
    var internalFormat = context.extRenderToTextureHalfFloat ? context.extTextureHalfFloat.HALF_FLOAT_OES : gl.UNSIGNED_BYTE;
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, painter.width / 4, painter.height / 4, 0, gl.RGBA, internalFormat, null);
    fbo.colorAttachment.set(texture);
}
function renderTextureToMap(painter, layer) {
    var context = painter.context;
    var gl = context.gl;
    var fbo = layer.heatmapFbo;
    if (!fbo) {
        return;
    }
    context.activeTexture.set(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
    context.activeTexture.set(gl.TEXTURE1);
    var colorRampTexture = layer.colorRampTexture;
    if (!colorRampTexture) {
        colorRampTexture = layer.colorRampTexture = new performance.Texture(context, layer.colorRamp, gl.RGBA);
    }
    colorRampTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
    painter.useProgram('heatmapTexture').draw(context, gl.TRIANGLES, DepthMode.disabled, StencilMode.disabled, painter.colorModeForRenderPass(), CullFaceMode.disabled, heatmapTextureUniformValues(painter, layer, 0, 1), layer.id, painter.viewportBuffer, painter.quadTriangleIndexBuffer, painter.viewportSegments, layer.paint, painter.transform.zoom);
}

function drawLine(painter, sourceCache, layer, coords) {
    if (painter.renderPass !== 'translucent') {
        return;
    }
    var opacity = layer.paint.get('line-opacity');
    var width = layer.paint.get('line-width');
    if (opacity.constantOr(1) === 0 || width.constantOr(1) === 0) {
        return;
    }
    var depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
    var colorMode = painter.colorModeForRenderPass();
    var dasharray = layer.paint.get('line-dasharray');
    var patternProperty = layer.paint.get('line-pattern');
    var image = patternProperty.constantOr(1);
    var gradient = layer.paint.get('line-gradient');
    var crossfade = layer.getCrossfadeParameters();
    var programId = image ? 'linePattern' : dasharray ? 'lineSDF' : gradient ? 'lineGradient' : 'line';
    var context = painter.context;
    var gl = context.gl;
    var firstTile = true;
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        var tile = sourceCache.getTile(coord);
        if (image && !tile.patternsLoaded()) {
            continue;
        }
        var bucket = tile.getBucket(layer);
        if (!bucket) {
            continue;
        }
        var programConfiguration = bucket.programConfigurations.get(layer.id);
        var prevProgram = painter.context.program.get();
        var program = painter.useProgram(programId, programConfiguration);
        var programChanged = firstTile || program.program !== prevProgram;
        var constantPattern = patternProperty.constantOr(null);
        if (constantPattern && tile.imageAtlas) {
            var atlas = tile.imageAtlas;
            var posTo = atlas.patternPositions[constantPattern.to.toString()];
            var posFrom = atlas.patternPositions[constantPattern.from.toString()];
            if (posTo && posFrom) {
                programConfiguration.setConstantPatternPositions(posTo, posFrom);
            }
        }
        var uniformValues = image ? linePatternUniformValues(painter, tile, layer, crossfade) : dasharray ? lineSDFUniformValues(painter, tile, layer, dasharray, crossfade) : gradient ? lineGradientUniformValues(painter, tile, layer, bucket.lineClipsArray.length) : lineUniformValues(painter, tile, layer);
        if (image) {
            context.activeTexture.set(gl.TEXTURE0);
            tile.imageAtlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
            programConfiguration.updatePaintBuffers(crossfade);
        } else if (dasharray && (programChanged || painter.lineAtlas.dirty)) {
            context.activeTexture.set(gl.TEXTURE0);
            painter.lineAtlas.bind(context);
        } else if (gradient) {
            var layerGradient = bucket.gradients[layer.id];
            var gradientTexture = layerGradient.texture;
            if (layer.gradientVersion !== layerGradient.version) {
                var textureResolution = 256;
                if (layer.stepInterpolant) {
                    var sourceMaxZoom = sourceCache.getSource().maxzoom;
                    var potentialOverzoom = coord.canonical.z === sourceMaxZoom ? Math.ceil(1 << painter.transform.maxZoom - coord.canonical.z) : 1;
                    var lineLength = bucket.maxLineLength / performance.EXTENT;
                    var maxTilePixelSize = 1024;
                    var maxTextureCoverage = lineLength * maxTilePixelSize * potentialOverzoom;
                    textureResolution = performance.clamp(performance.nextPowerOfTwo(maxTextureCoverage), 256, context.maxTextureSize);
                }
                layerGradient.gradient = performance.renderColorRamp({
                    expression: layer.gradientExpression(),
                    evaluationKey: 'lineProgress',
                    resolution: textureResolution,
                    image: layerGradient.gradient || undefined,
                    clips: bucket.lineClipsArray
                });
                if (layerGradient.texture) {
                    layerGradient.texture.update(layerGradient.gradient);
                } else {
                    layerGradient.texture = new performance.Texture(context, layerGradient.gradient, gl.RGBA);
                }
                layerGradient.version = layer.gradientVersion;
                gradientTexture = layerGradient.texture;
            }
            context.activeTexture.set(gl.TEXTURE0);
            gradientTexture.bind(layer.stepInterpolant ? gl.NEAREST : gl.LINEAR, gl.CLAMP_TO_EDGE);
        }
        program.draw(context, gl.TRIANGLES, depthMode, painter.stencilModeForClipping(coord), colorMode, CullFaceMode.disabled, uniformValues, layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer, bucket.segments, layer.paint, painter.transform.zoom, programConfiguration, bucket.layoutVertexBuffer2);
        firstTile = false;
    }
}

function drawFill(painter, sourceCache, layer, coords) {
    var color = layer.paint.get('fill-color');
    var opacity = layer.paint.get('fill-opacity');
    if (opacity.constantOr(1) === 0) {
        return;
    }
    var colorMode = painter.colorModeForRenderPass();
    var pattern = layer.paint.get('fill-pattern');
    var pass = painter.opaquePassEnabledForLayer() && (!pattern.constantOr(1) && color.constantOr(performance.Color.transparent).a === 1 && opacity.constantOr(0) === 1) ? 'opaque' : 'translucent';
    if (painter.renderPass === pass) {
        var depthMode = painter.depthModeForSublayer(1, painter.renderPass === 'opaque' ? DepthMode.ReadWrite : DepthMode.ReadOnly);
        drawFillTiles(painter, sourceCache, layer, coords, depthMode, colorMode, false);
    }
    if (painter.renderPass === 'translucent' && layer.paint.get('fill-antialias')) {
        var depthMode$1 = painter.depthModeForSublayer(layer.getPaintProperty('fill-outline-color') ? 2 : 0, DepthMode.ReadOnly);
        drawFillTiles(painter, sourceCache, layer, coords, depthMode$1, colorMode, true);
    }
}
function drawFillTiles(painter, sourceCache, layer, coords, depthMode, colorMode, isOutline) {
    var gl = painter.context.gl;
    var patternProperty = layer.paint.get('fill-pattern');
    var image = patternProperty && patternProperty.constantOr(1);
    var crossfade = layer.getCrossfadeParameters();
    var drawMode, programName, uniformValues, indexBuffer, segments;
    if (!isOutline) {
        programName = image ? 'fillPattern' : 'fill';
        drawMode = gl.TRIANGLES;
    } else {
        programName = image && !layer.getPaintProperty('fill-outline-color') ? 'fillOutlinePattern' : 'fillOutline';
        drawMode = gl.LINES;
    }
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        var tile = sourceCache.getTile(coord);
        if (image && !tile.patternsLoaded()) {
            continue;
        }
        var bucket = tile.getBucket(layer);
        if (!bucket) {
            continue;
        }
        var programConfiguration = bucket.programConfigurations.get(layer.id);
        var program = painter.useProgram(programName, programConfiguration);
        if (image) {
            painter.context.activeTexture.set(gl.TEXTURE0);
            tile.imageAtlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
            programConfiguration.updatePaintBuffers(crossfade);
        }
        var constantPattern = patternProperty.constantOr(null);
        if (constantPattern && tile.imageAtlas) {
            var atlas = tile.imageAtlas;
            var posTo = atlas.patternPositions[constantPattern.to.toString()];
            var posFrom = atlas.patternPositions[constantPattern.from.toString()];
            if (posTo && posFrom) {
                programConfiguration.setConstantPatternPositions(posTo, posFrom);
            }
        }
        var tileMatrix = painter.translatePosMatrix(coord.posMatrix, tile, layer.paint.get('fill-translate'), layer.paint.get('fill-translate-anchor'));
        if (!isOutline) {
            indexBuffer = bucket.indexBuffer;
            segments = bucket.segments;
            uniformValues = image ? fillPatternUniformValues(tileMatrix, painter, crossfade, tile) : fillUniformValues(tileMatrix);
        } else {
            indexBuffer = bucket.indexBuffer2;
            segments = bucket.segments2;
            var drawingBufferSize = [
                gl.drawingBufferWidth,
                gl.drawingBufferHeight
            ];
            uniformValues = programName === 'fillOutlinePattern' && image ? fillOutlinePatternUniformValues(tileMatrix, painter, crossfade, tile, drawingBufferSize) : fillOutlineUniformValues(tileMatrix, drawingBufferSize);
        }
        program.draw(painter.context, drawMode, depthMode, painter.stencilModeForClipping(coord), colorMode, CullFaceMode.disabled, uniformValues, layer.id, bucket.layoutVertexBuffer, indexBuffer, segments, layer.paint, painter.transform.zoom, programConfiguration);
    }
}

function draw(painter, source, layer, coords) {
    var opacity = layer.paint.get('fill-extrusion-opacity');
    if (opacity === 0) {
        return;
    }
    if (painter.renderPass === 'translucent') {
        var depthMode = new DepthMode(painter.context.gl.LEQUAL, DepthMode.ReadWrite, painter.depthRangeFor3D);
        if (opacity === 1 && !layer.paint.get('fill-extrusion-pattern').constantOr(1)) {
            var colorMode = painter.colorModeForRenderPass();
            drawExtrusionTiles(painter, source, layer, coords, depthMode, StencilMode.disabled, colorMode);
        } else {
            drawExtrusionTiles(painter, source, layer, coords, depthMode, StencilMode.disabled, ColorMode.disabled);
            drawExtrusionTiles(painter, source, layer, coords, depthMode, painter.stencilModeFor3D(), painter.colorModeForRenderPass());
        }
    }
}
function drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMode, colorMode) {
    var context = painter.context;
    var gl = context.gl;
    var patternProperty = layer.paint.get('fill-extrusion-pattern');
    var image = patternProperty.constantOr(1);
    var crossfade = layer.getCrossfadeParameters();
    var opacity = layer.paint.get('fill-extrusion-opacity');
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        var tile = source.getTile(coord);
        var bucket = tile.getBucket(layer);
        if (!bucket) {
            continue;
        }
        var programConfiguration = bucket.programConfigurations.get(layer.id);
        var program = painter.useProgram(image ? 'fillExtrusionPattern' : 'fillExtrusion', programConfiguration);
        if (image) {
            painter.context.activeTexture.set(gl.TEXTURE0);
            tile.imageAtlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
            programConfiguration.updatePaintBuffers(crossfade);
        }
        var constantPattern = patternProperty.constantOr(null);
        if (constantPattern && tile.imageAtlas) {
            var atlas = tile.imageAtlas;
            var posTo = atlas.patternPositions[constantPattern.to.toString()];
            var posFrom = atlas.patternPositions[constantPattern.from.toString()];
            if (posTo && posFrom) {
                programConfiguration.setConstantPatternPositions(posTo, posFrom);
            }
        }
        var matrix = painter.translatePosMatrix(coord.posMatrix, tile, layer.paint.get('fill-extrusion-translate'), layer.paint.get('fill-extrusion-translate-anchor'));
        var shouldUseVerticalGradient = layer.paint.get('fill-extrusion-vertical-gradient');
        var uniformValues = image ? fillExtrusionPatternUniformValues(matrix, painter, shouldUseVerticalGradient, opacity, coord, crossfade, tile) : fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity);
        program.draw(context, context.gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.backCCW, uniformValues, layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer, bucket.segments, layer.paint, painter.transform.zoom, programConfiguration);
    }
}

function drawHillshade(painter, sourceCache, layer, tileIDs) {
    if (painter.renderPass !== 'offscreen' && painter.renderPass !== 'translucent') {
        return;
    }
    var context = painter.context;
    var depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
    var colorMode = painter.colorModeForRenderPass();
    var ref = painter.renderPass === 'translucent' ? painter.stencilConfigForOverlap(tileIDs) : [
        {},
        tileIDs
    ];
    var stencilModes = ref[0];
    var coords = ref[1];
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        var tile = sourceCache.getTile(coord);
        if (tile.needsHillshadePrepare && painter.renderPass === 'offscreen') {
            prepareHillshade(painter, tile, layer, depthMode, StencilMode.disabled, colorMode);
        } else if (painter.renderPass === 'translucent') {
            renderHillshade(painter, tile, layer, depthMode, stencilModes[coord.overscaledZ], colorMode);
        }
    }
    context.viewport.set([
        0,
        0,
        painter.width,
        painter.height
    ]);
}
function renderHillshade(painter, tile, layer, depthMode, stencilMode, colorMode) {
    var context = painter.context;
    var gl = context.gl;
    var fbo = tile.fbo;
    if (!fbo) {
        return;
    }
    var program = painter.useProgram('hillshade');
    context.activeTexture.set(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
    var uniformValues = hillshadeUniformValues(painter, tile, layer);
    program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled, uniformValues, layer.id, painter.rasterBoundsBuffer, painter.quadTriangleIndexBuffer, painter.rasterBoundsSegments);
}
function prepareHillshade(painter, tile, layer, depthMode, stencilMode, colorMode) {
    var context = painter.context;
    var gl = context.gl;
    var dem = tile.dem;
    if (dem && dem.data) {
        var tileSize = dem.dim;
        var textureStride = dem.stride;
        var pixelData = dem.getPixels();
        context.activeTexture.set(gl.TEXTURE1);
        context.pixelStoreUnpackPremultiplyAlpha.set(false);
        tile.demTexture = tile.demTexture || painter.getTileTexture(textureStride);
        if (tile.demTexture) {
            var demTexture = tile.demTexture;
            demTexture.update(pixelData, { premultiply: false });
            demTexture.bind(gl.NEAREST, gl.CLAMP_TO_EDGE);
        } else {
            tile.demTexture = new performance.Texture(context, pixelData, gl.RGBA, { premultiply: false });
            tile.demTexture.bind(gl.NEAREST, gl.CLAMP_TO_EDGE);
        }
        context.activeTexture.set(gl.TEXTURE0);
        var fbo = tile.fbo;
        if (!fbo) {
            var renderTexture = new performance.Texture(context, {
                width: tileSize,
                height: tileSize,
                data: null
            }, gl.RGBA);
            renderTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
            fbo = tile.fbo = context.createFramebuffer(tileSize, tileSize, true);
            fbo.colorAttachment.set(renderTexture.texture);
        }
        context.bindFramebuffer.set(fbo.framebuffer);
        context.viewport.set([
            0,
            0,
            tileSize,
            tileSize
        ]);
        painter.useProgram('hillshadePrepare').draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled, hillshadeUniformPrepareValues(tile.tileID, dem), layer.id, painter.rasterBoundsBuffer, painter.quadTriangleIndexBuffer, painter.rasterBoundsSegments);
        tile.needsHillshadePrepare = false;
    }
}

function drawRaster(painter, sourceCache, layer, tileIDs) {
    if (painter.renderPass !== 'translucent') {
        return;
    }
    if (layer.paint.get('raster-opacity') === 0) {
        return;
    }
    if (!tileIDs.length) {
        return;
    }
    var context = painter.context;
    var gl = context.gl;
    var source = sourceCache.getSource();
    var program = painter.useProgram('raster');
    var colorMode = painter.colorModeForRenderPass();
    var ref = source instanceof ImageSource ? [
        {},
        tileIDs
    ] : painter.stencilConfigForOverlap(tileIDs);
    var stencilModes = ref[0];
    var coords = ref[1];
    var minTileZ = coords[coords.length - 1].overscaledZ;
    var align = !painter.options.moving;
    for (var i = 0, list = coords; i < list.length; i += 1) {
        var coord = list[i];
        var depthMode = painter.depthModeForSublayer(coord.overscaledZ - minTileZ, layer.paint.get('raster-opacity') === 1 ? DepthMode.ReadWrite : DepthMode.ReadOnly, gl.LESS);
        var tile = sourceCache.getTile(coord);
        var posMatrix = painter.transform.calculatePosMatrix(coord.toUnwrapped(), align);
        tile.registerFadeDuration(layer.paint.get('raster-fade-duration'));
        var parentTile = sourceCache.findLoadedParent(coord, 0), fade = getFadeValues(tile, parentTile, sourceCache, layer, painter.transform);
        var parentScaleBy = void 0, parentTL = void 0;
        var textureFilter = layer.paint.get('raster-resampling') === 'nearest' ? gl.NEAREST : gl.LINEAR;
        context.activeTexture.set(gl.TEXTURE0);
        tile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
        context.activeTexture.set(gl.TEXTURE1);
        if (parentTile) {
            parentTile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
            parentScaleBy = Math.pow(2, parentTile.tileID.overscaledZ - tile.tileID.overscaledZ);
            parentTL = [
                tile.tileID.canonical.x * parentScaleBy % 1,
                tile.tileID.canonical.y * parentScaleBy % 1
            ];
        } else {
            tile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
        }
        var uniformValues = rasterUniformValues(posMatrix, parentTL || [
            0,
            0
        ], parentScaleBy || 1, fade, layer);
        if (source instanceof ImageSource) {
            program.draw(context, gl.TRIANGLES, depthMode, StencilMode.disabled, colorMode, CullFaceMode.disabled, uniformValues, layer.id, source.boundsBuffer, painter.quadTriangleIndexBuffer, source.boundsSegments);
        } else {
            program.draw(context, gl.TRIANGLES, depthMode, stencilModes[coord.overscaledZ], colorMode, CullFaceMode.disabled, uniformValues, layer.id, painter.rasterBoundsBuffer, painter.quadTriangleIndexBuffer, painter.rasterBoundsSegments);
        }
    }
}
function getFadeValues(tile, parentTile, sourceCache, layer, transform) {
    var fadeDuration = layer.paint.get('raster-fade-duration');
    if (fadeDuration > 0) {
        var now = performance.browser.now();
        var sinceTile = (now - tile.timeAdded) / fadeDuration;
        var sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1;
        var source = sourceCache.getSource();
        var idealZ = transform.coveringZoomLevel({
            tileSize: source.tileSize,
            roundZoom: source.roundZoom
        });
        var fadeIn = !parentTile || Math.abs(parentTile.tileID.overscaledZ - idealZ) > Math.abs(tile.tileID.overscaledZ - idealZ);
        var childOpacity = fadeIn && tile.refreshedUponExpiration ? 1 : performance.clamp(fadeIn ? sinceTile : 1 - sinceParent, 0, 1);
        if (tile.refreshedUponExpiration && sinceTile >= 1) {
            tile.refreshedUponExpiration = false;
        }
        if (parentTile) {
            return {
                opacity: 1,
                mix: 1 - childOpacity
            };
        } else {
            return {
                opacity: childOpacity,
                mix: 0
            };
        }
    } else {
        return {
            opacity: 1,
            mix: 0
        };
    }
}

function drawBackground(painter, sourceCache, layer) {
    var color = layer.paint.get('background-color');
    var opacity = layer.paint.get('background-opacity');
    if (opacity === 0) {
        return;
    }
    var context = painter.context;
    var gl = context.gl;
    var transform = painter.transform;
    var tileSize = transform.tileSize;
    var image = layer.paint.get('background-pattern');
    if (painter.isPatternMissing(image)) {
        return;
    }
    var pass = !image && color.a === 1 && opacity === 1 && painter.opaquePassEnabledForLayer() ? 'opaque' : 'translucent';
    if (painter.renderPass !== pass) {
        return;
    }
    var stencilMode = StencilMode.disabled;
    var depthMode = painter.depthModeForSublayer(0, pass === 'opaque' ? DepthMode.ReadWrite : DepthMode.ReadOnly);
    var colorMode = painter.colorModeForRenderPass();
    var program = painter.useProgram(image ? 'backgroundPattern' : 'background');
    var tileIDs = transform.coveringTiles({ tileSize: tileSize });
    if (image) {
        context.activeTexture.set(gl.TEXTURE0);
        painter.imageManager.bind(painter.context);
    }
    var crossfade = layer.getCrossfadeParameters();
    for (var i = 0, list = tileIDs; i < list.length; i += 1) {
        var tileID = list[i];
        var matrix = painter.transform.calculatePosMatrix(tileID.toUnwrapped());
        var uniformValues = image ? backgroundPatternUniformValues(matrix, opacity, painter, image, {
            tileID: tileID,
            tileSize: tileSize
        }, crossfade) : backgroundUniformValues(matrix, opacity, color);
        program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled, uniformValues, layer.id, painter.tileExtentBuffer, painter.quadTriangleIndexBuffer, painter.tileExtentSegments);
    }
}

var topColor = new performance.Color(1, 0, 0, 1);
var btmColor = new performance.Color(0, 1, 0, 1);
var leftColor = new performance.Color(0, 0, 1, 1);
var rightColor = new performance.Color(1, 0, 1, 1);
var centerColor = new performance.Color(0, 1, 1, 1);
function drawDebugPadding(painter) {
    var padding = painter.transform.padding;
    var lineWidth = 3;
    drawHorizontalLine(painter, painter.transform.height - (padding.top || 0), lineWidth, topColor);
    drawHorizontalLine(painter, padding.bottom || 0, lineWidth, btmColor);
    drawVerticalLine(painter, padding.left || 0, lineWidth, leftColor);
    drawVerticalLine(painter, painter.transform.width - (padding.right || 0), lineWidth, rightColor);
    var center = painter.transform.centerPoint;
    drawCrosshair(painter, center.x, painter.transform.height - center.y, centerColor);
}
function drawCrosshair(painter, x, y, color) {
    var size = 20;
    var lineWidth = 2;
    drawDebugSSRect(painter, x - lineWidth / 2, y - size / 2, lineWidth, size, color);
    drawDebugSSRect(painter, x - size / 2, y - lineWidth / 2, size, lineWidth, color);
}
function drawHorizontalLine(painter, y, lineWidth, color) {
    drawDebugSSRect(painter, 0, y + lineWidth / 2, painter.transform.width, lineWidth, color);
}
function drawVerticalLine(painter, x, lineWidth, color) {
    drawDebugSSRect(painter, x - lineWidth / 2, 0, lineWidth, painter.transform.height, color);
}
function drawDebugSSRect(painter, x, y, width, height, color) {
    var context = painter.context;
    var gl = context.gl;
    gl.enable(gl.SCISSOR_TEST);
    gl.scissor(x * performance.browser.devicePixelRatio, y * performance.browser.devicePixelRatio, width * performance.browser.devicePixelRatio, height * performance.browser.devicePixelRatio);
    context.clear({ color: color });
    gl.disable(gl.SCISSOR_TEST);
}
function drawDebug(painter, sourceCache, coords) {
    for (var i = 0; i < coords.length; i++) {
        drawDebugTile(painter, sourceCache, coords[i]);
    }
}
function drawDebugTile(painter, sourceCache, coord) {
    var context = painter.context;
    var gl = context.gl;
    var posMatrix = coord.posMatrix;
    var program = painter.useProgram('debug');
    var depthMode = DepthMode.disabled;
    var stencilMode = StencilMode.disabled;
    var colorMode = painter.colorModeForRenderPass();
    var id = '$debug';
    context.activeTexture.set(gl.TEXTURE0);
    painter.emptyTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
    program.draw(context, gl.LINE_STRIP, depthMode, stencilMode, colorMode, CullFaceMode.disabled, debugUniformValues(posMatrix, performance.Color.red), id, painter.debugBuffer, painter.tileBorderIndexBuffer, painter.debugSegments);
    var tileRawData = sourceCache.getTileByID(coord.key).latestRawTileData;
    var tileByteLength = tileRawData && tileRawData.byteLength || 0;
    var tileSizeKb = Math.floor(tileByteLength / 1024);
    var tileSize = sourceCache.getTile(coord).tileSize;
    var scaleRatio = 512 / Math.min(tileSize, 512) * (coord.overscaledZ / painter.transform.zoom) * 0.5;
    var tileIdText = coord.canonical.toString();
    if (coord.overscaledZ !== coord.canonical.z) {
        tileIdText += ' => ' + coord.overscaledZ;
    }
    var tileLabel = tileIdText + ' ' + tileSizeKb + 'kb';
    drawTextToOverlay(painter, tileLabel);
    program.draw(context, gl.TRIANGLES, depthMode, stencilMode, ColorMode.alphaBlended, CullFaceMode.disabled, debugUniformValues(posMatrix, performance.Color.transparent, scaleRatio), id, painter.debugBuffer, painter.quadTriangleIndexBuffer, painter.debugSegments);
}
function drawTextToOverlay(painter, text) {
    painter.initDebugOverlayCanvas();
    var canvas = painter.debugOverlayCanvas;
    var gl = painter.context.gl;
    var ctx2d = painter.debugOverlayCanvas.getContext('2d');
    ctx2d.clearRect(0, 0, canvas.width, canvas.height);
    ctx2d.shadowColor = 'white';
    ctx2d.shadowBlur = 2;
    ctx2d.lineWidth = 1.5;
    ctx2d.strokeStyle = 'white';
    ctx2d.textBaseline = 'top';
    ctx2d.font = 'bold ' + 36 + 'px Open Sans, sans-serif';
    ctx2d.fillText(text, 5, 5);
    ctx2d.strokeText(text, 5, 5);
    painter.debugOverlayTexture.update(canvas);
    painter.debugOverlayTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
}

function drawCustom(painter, sourceCache, layer) {
    var context = painter.context;
    var implementation = layer.implementation;
    if (painter.renderPass === 'offscreen') {
        var prerender = implementation.prerender;
        if (prerender) {
            painter.setCustomLayerDefaults();
            context.setColorMode(painter.colorModeForRenderPass());
            prerender.call(implementation, context.gl, painter.transform.customLayerMatrix());
            context.setDirty();
            painter.setBaseState();
        }
    } else if (painter.renderPass === 'translucent') {
        painter.setCustomLayerDefaults();
        context.setColorMode(painter.colorModeForRenderPass());
        context.setStencilMode(StencilMode.disabled);
        var depthMode = implementation.renderingMode === '3d' ? new DepthMode(painter.context.gl.LEQUAL, DepthMode.ReadWrite, painter.depthRangeFor3D) : painter.depthModeForSublayer(0, DepthMode.ReadOnly);
        context.setDepthMode(depthMode);
        implementation.render(context.gl, painter.transform.customLayerMatrix());
        context.setDirty();
        painter.setBaseState();
        context.bindFramebuffer.set(null);
    }
}

var draw$1 = {
    symbol: drawSymbols,
    circle: drawCircles,
    heatmap: drawHeatmap,
    line: drawLine,
    fill: drawFill,
    'fill-extrusion': draw,
    hillshade: drawHillshade,
    raster: drawRaster,
    background: drawBackground,
    debug: drawDebug,
    custom: drawCustom
};
var Painter = function Painter(gl, transform) {
    this.context = new Context(gl);
    this.transform = transform;
    this._tileTextures = {};
    this.setup();
    this.numSublayers = SourceCache.maxUnderzooming + SourceCache.maxOverzooming + 1;
    this.depthEpsilon = 1 / Math.pow(2, 16);
    this.crossTileSymbolIndex = new CrossTileSymbolIndex();
    this.gpuTimers = {};
};
Painter.prototype.resize = function resize(width, height) {
    this.width = width * performance.browser.devicePixelRatio;
    this.height = height * performance.browser.devicePixelRatio;
    this.context.viewport.set([
        0,
        0,
        this.width,
        this.height
    ]);
    if (this.style) {
        for (var i = 0, list = this.style._order; i < list.length; i += 1) {
            var layerId = list[i];
            this.style._layers[layerId].resize();
        }
    }
};
Painter.prototype.setup = function setup() {
    var context = this.context;
    var tileExtentArray = new performance.StructArrayLayout2i4();
    tileExtentArray.emplaceBack(0, 0);
    tileExtentArray.emplaceBack(performance.EXTENT, 0);
    tileExtentArray.emplaceBack(0, performance.EXTENT);
    tileExtentArray.emplaceBack(performance.EXTENT, performance.EXTENT);
    this.tileExtentBuffer = context.createVertexBuffer(tileExtentArray, posAttributes.members);
    this.tileExtentSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 2);
    var debugArray = new performance.StructArrayLayout2i4();
    debugArray.emplaceBack(0, 0);
    debugArray.emplaceBack(performance.EXTENT, 0);
    debugArray.emplaceBack(0, performance.EXTENT);
    debugArray.emplaceBack(performance.EXTENT, performance.EXTENT);
    this.debugBuffer = context.createVertexBuffer(debugArray, posAttributes.members);
    this.debugSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 5);
    var rasterBoundsArray = new performance.StructArrayLayout4i8();
    rasterBoundsArray.emplaceBack(0, 0, 0, 0);
    rasterBoundsArray.emplaceBack(performance.EXTENT, 0, performance.EXTENT, 0);
    rasterBoundsArray.emplaceBack(0, performance.EXTENT, 0, performance.EXTENT);
    rasterBoundsArray.emplaceBack(performance.EXTENT, performance.EXTENT, performance.EXTENT, performance.EXTENT);
    this.rasterBoundsBuffer = context.createVertexBuffer(rasterBoundsArray, rasterBoundsAttributes.members);
    this.rasterBoundsSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 2);
    var viewportArray = new performance.StructArrayLayout2i4();
    viewportArray.emplaceBack(0, 0);
    viewportArray.emplaceBack(1, 0);
    viewportArray.emplaceBack(0, 1);
    viewportArray.emplaceBack(1, 1);
    this.viewportBuffer = context.createVertexBuffer(viewportArray, posAttributes.members);
    this.viewportSegments = performance.SegmentVector.simpleSegment(0, 0, 4, 2);
    var tileLineStripIndices = new performance.StructArrayLayout1ui2();
    tileLineStripIndices.emplaceBack(0);
    tileLineStripIndices.emplaceBack(1);
    tileLineStripIndices.emplaceBack(3);
    tileLineStripIndices.emplaceBack(2);
    tileLineStripIndices.emplaceBack(0);
    this.tileBorderIndexBuffer = context.createIndexBuffer(tileLineStripIndices);
    var quadTriangleIndices = new performance.StructArrayLayout3ui6();
    quadTriangleIndices.emplaceBack(0, 1, 2);
    quadTriangleIndices.emplaceBack(2, 1, 3);
    this.quadTriangleIndexBuffer = context.createIndexBuffer(quadTriangleIndices);
    this.emptyTexture = new performance.Texture(context, {
        width: 1,
        height: 1,
        data: new Uint8Array([
            0,
            0,
            0,
            0
        ])
    }, context.gl.RGBA);
    var gl = this.context.gl;
    this.stencilClearMode = new StencilMode({
        func: gl.ALWAYS,
        mask: 0
    }, 0, 255, gl.ZERO, gl.ZERO, gl.ZERO);
};
Painter.prototype.clearStencil = function clearStencil() {
    var context = this.context;
    var gl = context.gl;
    this.nextStencilID = 1;
    this.currentStencilSource = undefined;
    var matrix = performance.create();
    performance.ortho(matrix, 0, this.width, this.height, 0, 0, 1);
    performance.scale(matrix, matrix, [
        gl.drawingBufferWidth,
        gl.drawingBufferHeight,
        0
    ]);
    this.useProgram('clippingMask').draw(context, gl.TRIANGLES, DepthMode.disabled, this.stencilClearMode, ColorMode.disabled, CullFaceMode.disabled, clippingMaskUniformValues(matrix), '$clipping', this.viewportBuffer, this.quadTriangleIndexBuffer, this.viewportSegments);
};
Painter.prototype._renderTileClippingMasks = function _renderTileClippingMasks(layer, tileIDs) {
    if (this.currentStencilSource === layer.source || !layer.isTileClipped() || !tileIDs || !tileIDs.length) {
        return;
    }
    this.currentStencilSource = layer.source;
    var context = this.context;
    var gl = context.gl;
    if (this.nextStencilID + tileIDs.length > 256) {
        this.clearStencil();
    }
    context.setColorMode(ColorMode.disabled);
    context.setDepthMode(DepthMode.disabled);
    var program = this.useProgram('clippingMask');
    this._tileClippingMaskIDs = {};
    for (var i = 0, list = tileIDs; i < list.length; i += 1) {
        var tileID = list[i];
        var id = this._tileClippingMaskIDs[tileID.key] = this.nextStencilID++;
        program.draw(context, gl.TRIANGLES, DepthMode.disabled, new StencilMode({
            func: gl.ALWAYS,
            mask: 0
        }, id, 255, gl.KEEP, gl.KEEP, gl.REPLACE), ColorMode.disabled, CullFaceMode.disabled, clippingMaskUniformValues(tileID.posMatrix), '$clipping', this.tileExtentBuffer, this.quadTriangleIndexBuffer, this.tileExtentSegments);
    }
};
Painter.prototype.stencilModeFor3D = function stencilModeFor3D() {
    this.currentStencilSource = undefined;
    if (this.nextStencilID + 1 > 256) {
        this.clearStencil();
    }
    var id = this.nextStencilID++;
    var gl = this.context.gl;
    return new StencilMode({
        func: gl.NOTEQUAL,
        mask: 255
    }, id, 255, gl.KEEP, gl.KEEP, gl.REPLACE);
};
Painter.prototype.stencilModeForClipping = function stencilModeForClipping(tileID) {
    var gl = this.context.gl;
    return new StencilMode({
        func: gl.EQUAL,
        mask: 255
    }, this._tileClippingMaskIDs[tileID.key], 0, gl.KEEP, gl.KEEP, gl.REPLACE);
};
Painter.prototype.stencilConfigForOverlap = function stencilConfigForOverlap(tileIDs) {
    var obj;
    var gl = this.context.gl;
    var coords = tileIDs.sort(function (a, b) {
        return b.overscaledZ - a.overscaledZ;
    });
    var minTileZ = coords[coords.length - 1].overscaledZ;
    var stencilValues = coords[0].overscaledZ - minTileZ + 1;
    if (stencilValues > 1) {
        this.currentStencilSource = undefined;
        if (this.nextStencilID + stencilValues > 256) {
            this.clearStencil();
        }
        var zToStencilMode = {};
        for (var i = 0; i < stencilValues; i++) {
            zToStencilMode[i + minTileZ] = new StencilMode({
                func: gl.GEQUAL,
                mask: 255
            }, i + this.nextStencilID, 255, gl.KEEP, gl.KEEP, gl.REPLACE);
        }
        this.nextStencilID += stencilValues;
        return [
            zToStencilMode,
            coords
        ];
    }
    return [
        (obj = {}, obj[minTileZ] = StencilMode.disabled, obj),
        coords
    ];
};
Painter.prototype.colorModeForRenderPass = function colorModeForRenderPass() {
    var gl = this.context.gl;
    if (this._showOverdrawInspector) {
        var numOverdrawSteps = 8;
        var a = 1 / numOverdrawSteps;
        return new ColorMode([
            gl.CONSTANT_COLOR,
            gl.ONE
        ], new performance.Color(a, a, a, 0), [
            true,
            true,
            true,
            true
        ]);
    } else if (this.renderPass === 'opaque') {
        return ColorMode.unblended;
    } else {
        return ColorMode.alphaBlended;
    }
};
Painter.prototype.depthModeForSublayer = function depthModeForSublayer(n, mask, func) {
    if (!this.opaquePassEnabledForLayer()) {
        return DepthMode.disabled;
    }
    var depth = 1 - ((1 + this.currentLayer) * this.numSublayers + n) * this.depthEpsilon;
    return new DepthMode(func || this.context.gl.LEQUAL, mask, [
        depth,
        depth
    ]);
};
Painter.prototype.opaquePassEnabledForLayer = function opaquePassEnabledForLayer() {
    return this.currentLayer < this.opaquePassCutoff;
};
Painter.prototype.render = function render(style, options) {
    var this$1 = this;
    this.style = style;
    this.options = options;
    this.lineAtlas = style.lineAtlas;
    this.imageManager = style.imageManager;
    this.glyphManager = style.glyphManager;
    this.symbolFadeChange = style.placement.symbolFadeChange(performance.browser.now());
    this.imageManager.beginFrame();
    var layerIds = this.style._order;
    var sourceCaches = this.style.sourceCaches;
    for (var id in sourceCaches) {
        var sourceCache = sourceCaches[id];
        if (sourceCache.used) {
            sourceCache.prepare(this.context);
        }
    }
    var coordsAscending = {};
    var coordsDescending = {};
    var coordsDescendingSymbol = {};
    for (var id$1 in sourceCaches) {
        var sourceCache$1 = sourceCaches[id$1];
        coordsAscending[id$1] = sourceCache$1.getVisibleCoordinates();
        coordsDescending[id$1] = coordsAscending[id$1].slice().reverse();
        coordsDescendingSymbol[id$1] = sourceCache$1.getVisibleCoordinates(true).reverse();
    }
    this.opaquePassCutoff = Infinity;
    for (var i = 0; i < layerIds.length; i++) {
        var layerId = layerIds[i];
        if (this.style._layers[layerId].is3D()) {
            this.opaquePassCutoff = i;
            break;
        }
    }
    this.renderPass = 'offscreen';
    for (var i$1 = 0, list = layerIds; i$1 < list.length; i$1 += 1) {
        var layerId$1 = list[i$1];
        var layer = this.style._layers[layerId$1];
        if (!layer.hasOffscreenPass() || layer.isHidden(this.transform.zoom)) {
            continue;
        }
        var coords = coordsDescending[layer.source];
        if (layer.type !== 'custom' && !coords.length) {
            continue;
        }
        this.renderLayer(this, sourceCaches[layer.source], layer, coords);
    }
    this.context.bindFramebuffer.set(null);
    this.context.clear({
        color: options.showOverdrawInspector ? performance.Color.black : performance.Color.transparent,
        depth: 1
    });
    this.clearStencil();
    this._showOverdrawInspector = options.showOverdrawInspector;
    this.depthRangeFor3D = [
        0,
        1 - (style._order.length + 2) * this.numSublayers * this.depthEpsilon
    ];
    this.renderPass = 'opaque';
    for (this.currentLayer = layerIds.length - 1; this.currentLayer >= 0; this.currentLayer--) {
        var layer$1 = this.style._layers[layerIds[this.currentLayer]];
        var sourceCache$2 = sourceCaches[layer$1.source];
        var coords$1 = coordsAscending[layer$1.source];
        this._renderTileClippingMasks(layer$1, coords$1);
        this.renderLayer(this, sourceCache$2, layer$1, coords$1);
    }
    this.renderPass = 'translucent';
    for (this.currentLayer = 0; this.currentLayer < layerIds.length; this.currentLayer++) {
        var layer$2 = this.style._layers[layerIds[this.currentLayer]];
        var sourceCache$3 = sourceCaches[layer$2.source];
        var coords$2 = (layer$2.type === 'symbol' ? coordsDescendingSymbol : coordsDescending)[layer$2.source];
        this._renderTileClippingMasks(layer$2, coordsAscending[layer$2.source]);
        this.renderLayer(this, sourceCache$3, layer$2, coords$2);
    }
    if (this.options.showTileBoundaries) {
        var selectedSource;
        var sourceCache$4;
        var layers = performance.values(this.style._layers);
        layers.forEach(function (layer) {
            if (layer.source && !layer.isHidden(this$1.transform.zoom)) {
                if (layer.source !== (sourceCache$4 && sourceCache$4.id)) {
                    sourceCache$4 = this$1.style.sourceCaches[layer.source];
                }
                if (!selectedSource || selectedSource.getSource().maxzoom < sourceCache$4.getSource().maxzoom) {
                    selectedSource = sourceCache$4;
                }
            }
        });
        if (selectedSource) {
            draw$1.debug(this, selectedSource, selectedSource.getVisibleCoordinates());
        }
    }
    if (this.options.showPadding) {
        drawDebugPadding(this);
    }
    this.context.setDefault();
};
Painter.prototype.renderLayer = function renderLayer(painter, sourceCache, layer, coords) {
    if (layer.isHidden(this.transform.zoom)) {
        return;
    }
    if (layer.type !== 'background' && layer.type !== 'custom' && !coords.length) {
        return;
    }
    this.id = layer.id;
    this.gpuTimingStart(layer);
    draw$1[layer.type](painter, sourceCache, layer, coords, this.style.placement.variableOffsets);
    this.gpuTimingEnd();
};
Painter.prototype.gpuTimingStart = function gpuTimingStart(layer) {
    if (!this.options.gpuTiming) {
        return;
    }
    var ext = this.context.extTimerQuery;
    var layerTimer = this.gpuTimers[layer.id];
    if (!layerTimer) {
        layerTimer = this.gpuTimers[layer.id] = {
            calls: 0,
            cpuTime: 0,
            query: ext.createQueryEXT()
        };
    }
    layerTimer.calls++;
    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, layerTimer.query);
};
Painter.prototype.gpuTimingEnd = function gpuTimingEnd() {
    if (!this.options.gpuTiming) {
        return;
    }
    var ext = this.context.extTimerQuery;
    ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
};
Painter.prototype.collectGpuTimers = function collectGpuTimers() {
    var currentLayerTimers = this.gpuTimers;
    this.gpuTimers = {};
    return currentLayerTimers;
};
Painter.prototype.queryGpuTimers = function queryGpuTimers(gpuTimers) {
    var layers = {};
    for (var layerId in gpuTimers) {
        var gpuTimer = gpuTimers[layerId];
        var ext = this.context.extTimerQuery;
        var gpuTime = ext.getQueryObjectEXT(gpuTimer.query, ext.QUERY_RESULT_EXT) / (1000 * 1000);
        ext.deleteQueryEXT(gpuTimer.query);
        layers[layerId] = gpuTime;
    }
    return layers;
};
Painter.prototype.translatePosMatrix = function translatePosMatrix(matrix, tile, translate, translateAnchor, inViewportPixelUnitsUnits) {
    if (!translate[0] && !translate[1]) {
        return matrix;
    }
    var angle = inViewportPixelUnitsUnits ? translateAnchor === 'map' ? this.transform.angle : 0 : translateAnchor === 'viewport' ? -this.transform.angle : 0;
    if (angle) {
        var sinA = Math.sin(angle);
        var cosA = Math.cos(angle);
        translate = [
            translate[0] * cosA - translate[1] * sinA,
            translate[0] * sinA + translate[1] * cosA
        ];
    }
    var translation = [
        inViewportPixelUnitsUnits ? translate[0] : pixelsToTileUnits(tile, translate[0], this.transform.zoom),
        inViewportPixelUnitsUnits ? translate[1] : pixelsToTileUnits(tile, translate[1], this.transform.zoom),
        0
    ];
    var translatedMatrix = new Float32Array(16);
    performance.translate(translatedMatrix, matrix, translation);
    return translatedMatrix;
};
Painter.prototype.saveTileTexture = function saveTileTexture(texture) {
    var textures = this._tileTextures[texture.size[0]];
    if (!textures) {
        this._tileTextures[texture.size[0]] = [texture];
    } else {
        textures.push(texture);
    }
};
Painter.prototype.getTileTexture = function getTileTexture(size) {
    var textures = this._tileTextures[size];
    return textures && textures.length > 0 ? textures.pop() : null;
};
Painter.prototype.isPatternMissing = function isPatternMissing(image) {
    if (!image) {
        return false;
    }
    if (!image.from || !image.to) {
        return true;
    }
    var imagePosA = this.imageManager.getPattern(image.from.toString());
    var imagePosB = this.imageManager.getPattern(image.to.toString());
    return !imagePosA || !imagePosB;
};
Painter.prototype.useProgram = function useProgram(name, programConfiguration) {
    this.cache = this.cache || {};
    var key = '' + name + (programConfiguration ? programConfiguration.cacheKey : '') + (this._showOverdrawInspector ? '/overdraw' : '');
    if (!this.cache[key]) {
        this.cache[key] = new Program$1(this.context, name, shaders[name], programConfiguration, programUniforms[name], this._showOverdrawInspector);
    }
    return this.cache[key];
};
Painter.prototype.setCustomLayerDefaults = function setCustomLayerDefaults() {
    this.context.unbindVAO();
    this.context.cullFace.setDefault();
    this.context.activeTexture.setDefault();
    this.context.pixelStoreUnpack.setDefault();
    this.context.pixelStoreUnpackPremultiplyAlpha.setDefault();
    this.context.pixelStoreUnpackFlipY.setDefault();
};
Painter.prototype.setBaseState = function setBaseState() {
    var gl = this.context.gl;
    this.context.cullFace.set(false);
    this.context.viewport.set([
        0,
        0,
        this.width,
        this.height
    ]);
    this.context.blendEquation.set(gl.FUNC_ADD);
};
Painter.prototype.initDebugOverlayCanvas = function initDebugOverlayCanvas() {
    if (this.debugOverlayCanvas == null) {
        this.debugOverlayCanvas = performance.window.document.createElement('canvas');
        this.debugOverlayCanvas.width = 512;
        this.debugOverlayCanvas.height = 512;
        var gl = this.context.gl;
        this.debugOverlayTexture = new performance.Texture(this.context, this.debugOverlayCanvas, gl.RGBA);
    }
};
Painter.prototype.destroy = function destroy() {
    this.emptyTexture.destroy();
    if (this.debugOverlayTexture) {
        this.debugOverlayTexture.destroy();
    }
};

var Frustum = function Frustum(points_, planes_) {
    this.points = points_;
    this.planes = planes_;
};
Frustum.fromInvProjectionMatrix = function fromInvProjectionMatrix(invProj, worldSize, zoom) {
    var clipSpaceCorners = [
        [
            -1,
            1,
            -1,
            1
        ],
        [
            1,
            1,
            -1,
            1
        ],
        [
            1,
            -1,
            -1,
            1
        ],
        [
            -1,
            -1,
            -1,
            1
        ],
        [
            -1,
            1,
            1,
            1
        ],
        [
            1,
            1,
            1,
            1
        ],
        [
            1,
            -1,
            1,
            1
        ],
        [
            -1,
            -1,
            1,
            1
        ]
    ];
    var scale = Math.pow(2, zoom);
    var frustumCoords = clipSpaceCorners.map(function (v) {
        return performance.transformMat4([], v, invProj);
    }).map(function (v) {
        return performance.scale$1([], v, 1 / v[3] / worldSize * scale);
    });
    var frustumPlanePointIndices = [
        [
            0,
            1,
            2
        ],
        [
            6,
            5,
            4
        ],
        [
            0,
            3,
            7
        ],
        [
            2,
            1,
            5
        ],
        [
            3,
            2,
            6
        ],
        [
            0,
            4,
            5
        ]
    ];
    var frustumPlanes = frustumPlanePointIndices.map(function (p) {
        var a = performance.sub([], frustumCoords[p[0]], frustumCoords[p[1]]);
        var b = performance.sub([], frustumCoords[p[2]], frustumCoords[p[1]]);
        var n = performance.normalize([], performance.cross([], a, b));
        var d = -performance.dot(n, frustumCoords[p[1]]);
        return n.concat(d);
    });
    return new Frustum(frustumCoords, frustumPlanes);
};
var Aabb = function Aabb(min_, max_) {
    this.min = min_;
    this.max = max_;
    this.center = performance.scale$2([], performance.add([], this.min, this.max), 0.5);
};
Aabb.prototype.quadrant = function quadrant(index) {
    var split = [
        index % 2 === 0,
        index < 2
    ];
    var qMin = performance.clone$2(this.min);
    var qMax = performance.clone$2(this.max);
    for (var axis = 0; axis < split.length; axis++) {
        qMin[axis] = split[axis] ? this.min[axis] : this.center[axis];
        qMax[axis] = split[axis] ? this.center[axis] : this.max[axis];
    }
    qMax[2] = this.max[2];
    return new Aabb(qMin, qMax);
};
Aabb.prototype.distanceX = function distanceX(point) {
    var pointOnAabb = Math.max(Math.min(this.max[0], point[0]), this.min[0]);
    return pointOnAabb - point[0];
};
Aabb.prototype.distanceY = function distanceY(point) {
    var pointOnAabb = Math.max(Math.min(this.max[1], point[1]), this.min[1]);
    return pointOnAabb - point[1];
};
Aabb.prototype.intersects = function intersects(frustum) {
    var aabbPoints = [
        [
            this.min[0],
            this.min[1],
            0,
            1
        ],
        [
            this.max[0],
            this.min[1],
            0,
            1
        ],
        [
            this.max[0],
            this.max[1],
            0,
            1
        ],
        [
            this.min[0],
            this.max[1],
            0,
            1
        ]
    ];
    var fullyInside = true;
    for (var p = 0; p < frustum.planes.length; p++) {
        var plane = frustum.planes[p];
        var pointsInside = 0;
        for (var i = 0; i < aabbPoints.length; i++) {
            pointsInside += performance.dot$1(plane, aabbPoints[i]) >= 0;
        }
        if (pointsInside === 0) {
            return 0;
        }
        if (pointsInside !== aabbPoints.length) {
            fullyInside = false;
        }
    }
    if (fullyInside) {
        return 2;
    }
    for (var axis = 0; axis < 3; axis++) {
        var projMin = Number.MAX_VALUE;
        var projMax = -Number.MAX_VALUE;
        for (var p$1 = 0; p$1 < frustum.points.length; p$1++) {
            var projectedPoint = frustum.points[p$1][axis] - this.min[axis];
            projMin = Math.min(projMin, projectedPoint);
            projMax = Math.max(projMax, projectedPoint);
        }
        if (projMax < 0 || projMin > this.max[axis] - this.min[axis]) {
            return 0;
        }
    }
    return 1;
};

var EdgeInsets = function EdgeInsets(top, bottom, left, right) {
    if (top === void 0)
        top = 0;
    if (bottom === void 0)
        bottom = 0;
    if (left === void 0)
        left = 0;
    if (right === void 0)
        right = 0;
    if (isNaN(top) || top < 0 || isNaN(bottom) || bottom < 0 || isNaN(left) || left < 0 || isNaN(right) || right < 0) {
        throw new Error('Invalid value for edge-insets, top, bottom, left and right must all be numbers');
    }
    this.top = top;
    this.bottom = bottom;
    this.left = left;
    this.right = right;
};
EdgeInsets.prototype.interpolate = function interpolate(start, target, t) {
    if (target.top != null && start.top != null) {
        this.top = performance.number(start.top, target.top, t);
    }
    if (target.bottom != null && start.bottom != null) {
        this.bottom = performance.number(start.bottom, target.bottom, t);
    }
    if (target.left != null && start.left != null) {
        this.left = performance.number(start.left, target.left, t);
    }
    if (target.right != null && start.right != null) {
        this.right = performance.number(start.right, target.right, t);
    }
    return this;
};
EdgeInsets.prototype.getCenter = function getCenter(width, height) {
    var x = performance.clamp((this.left + width - this.right) / 2, 0, width);
    var y = performance.clamp((this.top + height - this.bottom) / 2, 0, height);
    return new performance.Point(x, y);
};
EdgeInsets.prototype.equals = function equals(other) {
    return this.top === other.top && this.bottom === other.bottom && this.left === other.left && this.right === other.right;
};
EdgeInsets.prototype.clone = function clone() {
    return new EdgeInsets(this.top, this.bottom, this.left, this.right);
};
EdgeInsets.prototype.toJSON = function toJSON() {
    return {
        top: this.top,
        bottom: this.bottom,
        left: this.left,
        right: this.right
    };
};

var Transform = function Transform(minZoom, maxZoom, minPitch, maxPitch, renderWorldCopies) {
    this.tileSize = 512;
    this.maxValidLatitude = 85.051129;
    this._renderWorldCopies = renderWorldCopies === undefined ? true : renderWorldCopies;
    this._minZoom = minZoom || 0;
    this._maxZoom = maxZoom || 22;
    this._minPitch = minPitch === undefined || minPitch === null ? 0 : minPitch;
    this._maxPitch = maxPitch === undefined || maxPitch === null ? 60 : maxPitch;
    this.setMaxBounds();
    this.width = 0;
    this.height = 0;
    this._center = new performance.LngLat(0, 0);
    this.zoom = 0;
    this.angle = 0;
    this._fov = 0.6435011087932844;
    this._pitch = 0;
    this._unmodified = true;
    this._edgeInsets = new EdgeInsets();
    this._posMatrixCache = {};
    this._alignedPosMatrixCache = {};
};
var prototypeAccessors = {
    minZoom: { configurable: true },
    maxZoom: { configurable: true },
    minPitch: { configurable: true },
    maxPitch: { configurable: true },
    renderWorldCopies: { configurable: true },
    worldSize: { configurable: true },
    centerOffset: { configurable: true },
    size: { configurable: true },
    bearing: { configurable: true },
    pitch: { configurable: true },
    fov: { configurable: true },
    zoom: { configurable: true },
    center: { configurable: true },
    padding: { configurable: true },
    centerPoint: { configurable: true },
    unmodified: { configurable: true },
    point: { configurable: true }
};
Transform.prototype.clone = function clone() {
    var clone = new Transform(this._minZoom, this._maxZoom, this._minPitch, this.maxPitch, this._renderWorldCopies);
    clone.tileSize = this.tileSize;
    clone.latRange = this.latRange;
    clone.width = this.width;
    clone.height = this.height;
    clone._center = this._center;
    clone.zoom = this.zoom;
    clone.angle = this.angle;
    clone._fov = this._fov;
    clone._pitch = this._pitch;
    clone._unmodified = this._unmodified;
    clone._edgeInsets = this._edgeInsets.clone();
    clone._calcMatrices();
    return clone;
};
prototypeAccessors.minZoom.get = function () {
    return this._minZoom;
};
prototypeAccessors.minZoom.set = function (zoom) {
    if (this._minZoom === zoom) {
        return;
    }
    this._minZoom = zoom;
    this.zoom = Math.max(this.zoom, zoom);
};
prototypeAccessors.maxZoom.get = function () {
    return this._maxZoom;
};
prototypeAccessors.maxZoom.set = function (zoom) {
    if (this._maxZoom === zoom) {
        return;
    }
    this._maxZoom = zoom;
    this.zoom = Math.min(this.zoom, zoom);
};
prototypeAccessors.minPitch.get = function () {
    return this._minPitch;
};
prototypeAccessors.minPitch.set = function (pitch) {
    if (this._minPitch === pitch) {
        return;
    }
    this._minPitch = pitch;
    this.pitch = Math.max(this.pitch, pitch);
};
prototypeAccessors.maxPitch.get = function () {
    return this._maxPitch;
};
prototypeAccessors.maxPitch.set = function (pitch) {
    if (this._maxPitch === pitch) {
        return;
    }
    this._maxPitch = pitch;
    this.pitch = Math.min(this.pitch, pitch);
};
prototypeAccessors.renderWorldCopies.get = function () {
    return this._renderWorldCopies;
};
prototypeAccessors.renderWorldCopies.set = function (renderWorldCopies) {
    if (renderWorldCopies === undefined) {
        renderWorldCopies = true;
    } else if (renderWorldCopies === null) {
        renderWorldCopies = false;
    }
    this._renderWorldCopies = renderWorldCopies;
};
prototypeAccessors.worldSize.get = function () {
    return this.tileSize * this.scale;
};
prototypeAccessors.centerOffset.get = function () {
    return this.centerPoint._sub(this.size._div(2));
};
prototypeAccessors.size.get = function () {
    return new performance.Point(this.width, this.height);
};
prototypeAccessors.bearing.get = function () {
    return -this.angle / Math.PI * 180;
};
prototypeAccessors.bearing.set = function (bearing) {
    var b = -performance.wrap(bearing, -180, 180) * Math.PI / 180;
    if (this.angle === b) {
        return;
    }
    this._unmodified = false;
    this.angle = b;
    this._calcMatrices();
    this.rotationMatrix = performance.create$2();
    performance.rotate(this.rotationMatrix, this.rotationMatrix, this.angle);
};
prototypeAccessors.pitch.get = function () {
    return this._pitch / Math.PI * 180;
};
prototypeAccessors.pitch.set = function (pitch) {
    var p = performance.clamp(pitch, this.minPitch, this.maxPitch) / 180 * Math.PI;
    if (this._pitch === p) {
        return;
    }
    this._unmodified = false;
    this._pitch = p;
    this._calcMatrices();
};
prototypeAccessors.fov.get = function () {
    return this._fov / Math.PI * 180;
};
prototypeAccessors.fov.set = function (fov) {
    fov = Math.max(0.01, Math.min(60, fov));
    if (this._fov === fov) {
        return;
    }
    this._unmodified = false;
    this._fov = fov / 180 * Math.PI;
    this._calcMatrices();
};
prototypeAccessors.zoom.get = function () {
    return this._zoom;
};
prototypeAccessors.zoom.set = function (zoom) {
    var z = Math.min(Math.max(zoom, this.minZoom), this.maxZoom);
    if (this._zoom === z) {
        return;
    }
    this._unmodified = false;
    this._zoom = z;
    this.scale = this.zoomScale(z);
    this.tileZoom = Math.floor(z);
    this.zoomFraction = z - this.tileZoom;
    this._constrain();
    this._calcMatrices();
};
prototypeAccessors.center.get = function () {
    return this._center;
};
prototypeAccessors.center.set = function (center) {
    if (center.lat === this._center.lat && center.lng === this._center.lng) {
        return;
    }
    this._unmodified = false;
    this._center = center;
    this._constrain();
    this._calcMatrices();
};
prototypeAccessors.padding.get = function () {
    return this._edgeInsets.toJSON();
};
prototypeAccessors.padding.set = function (padding) {
    if (this._edgeInsets.equals(padding)) {
        return;
    }
    this._unmodified = false;
    this._edgeInsets.interpolate(this._edgeInsets, padding, 1);
    this._calcMatrices();
};
prototypeAccessors.centerPoint.get = function () {
    return this._edgeInsets.getCenter(this.width, this.height);
};
Transform.prototype.isPaddingEqual = function isPaddingEqual(padding) {
    return this._edgeInsets.equals(padding);
};
Transform.prototype.interpolatePadding = function interpolatePadding(start, target, t) {
    this._unmodified = false;
    this._edgeInsets.interpolate(start, target, t);
    this._constrain();
    this._calcMatrices();
};
Transform.prototype.coveringZoomLevel = function coveringZoomLevel(options) {
    var z = (options.roundZoom ? Math.round : Math.floor)(this.zoom + this.scaleZoom(this.tileSize / options.tileSize));
    return Math.max(0, z);
};
Transform.prototype.getVisibleUnwrappedCoordinates = function getVisibleUnwrappedCoordinates(tileID) {
    var result = [new performance.UnwrappedTileID(0, tileID)];
    if (this._renderWorldCopies) {
        var utl = this.pointCoordinate(new performance.Point(0, 0));
        var utr = this.pointCoordinate(new performance.Point(this.width, 0));
        var ubl = this.pointCoordinate(new performance.Point(this.width, this.height));
        var ubr = this.pointCoordinate(new performance.Point(0, this.height));
        var w0 = Math.floor(Math.min(utl.x, utr.x, ubl.x, ubr.x));
        var w1 = Math.floor(Math.max(utl.x, utr.x, ubl.x, ubr.x));
        var extraWorldCopy = 1;
        for (var w = w0 - extraWorldCopy; w <= w1 + extraWorldCopy; w++) {
            if (w === 0) {
                continue;
            }
            result.push(new performance.UnwrappedTileID(w, tileID));
        }
    }
    return result;
};
Transform.prototype.coveringTiles = function coveringTiles(options) {
    var z = this.coveringZoomLevel(options);
    var actualZ = z;
    if (options.minzoom !== undefined && z < options.minzoom) {
        return [];
    }
    if (options.maxzoom !== undefined && z > options.maxzoom) {
        z = options.maxzoom;
    }
    var centerCoord = performance.MercatorCoordinate.fromLngLat(this.center);
    var numTiles = Math.pow(2, z);
    var centerPoint = [
        numTiles * centerCoord.x,
        numTiles * centerCoord.y,
        0
    ];
    var cameraFrustum = Frustum.fromInvProjectionMatrix(this.invProjMatrix, this.worldSize, z);
    var minZoom = options.minzoom || 0;
    if (this.pitch <= 60 && this._edgeInsets.top < 0.1) {
        minZoom = z;
    }
    var radiusOfMaxLvlLodInTiles = 3;
    var newRootTile = function (wrap) {
        return {
            aabb: new Aabb([
                wrap * numTiles,
                0,
                0
            ], [
                (wrap + 1) * numTiles,
                numTiles,
                0
            ]),
            zoom: 0,
            x: 0,
            y: 0,
            wrap: wrap,
            fullyVisible: false
        };
    };
    var stack = [];
    var result = [];
    var maxZoom = z;
    var overscaledZ = options.reparseOverscaled ? actualZ : z;
    if (this._renderWorldCopies) {
        for (var i = 1; i <= 3; i++) {
            stack.push(newRootTile(-i));
            stack.push(newRootTile(i));
        }
    }
    stack.push(newRootTile(0));
    while (stack.length > 0) {
        var it = stack.pop();
        var x = it.x;
        var y = it.y;
        var fullyVisible = it.fullyVisible;
        if (!fullyVisible) {
            var intersectResult = it.aabb.intersects(cameraFrustum);
            if (intersectResult === 0) {
                continue;
            }
            fullyVisible = intersectResult === 2;
        }
        var distanceX = it.aabb.distanceX(centerPoint);
        var distanceY = it.aabb.distanceY(centerPoint);
        var longestDim = Math.max(Math.abs(distanceX), Math.abs(distanceY));
        var distToSplit = radiusOfMaxLvlLodInTiles + (1 << maxZoom - it.zoom) - 2;
        if (it.zoom === maxZoom || longestDim > distToSplit && it.zoom >= minZoom) {
            result.push({
                tileID: new performance.OverscaledTileID(it.zoom === maxZoom ? overscaledZ : it.zoom, it.wrap, it.zoom, x, y),
                distanceSq: performance.sqrLen([
                    centerPoint[0] - 0.5 - x,
                    centerPoint[1] - 0.5 - y
                ])
            });
            continue;
        }
        for (var i$1 = 0; i$1 < 4; i$1++) {
            var childX = (x << 1) + i$1 % 2;
            var childY = (y << 1) + (i$1 >> 1);
            stack.push({
                aabb: it.aabb.quadrant(i$1),
                zoom: it.zoom + 1,
                x: childX,
                y: childY,
                wrap: it.wrap,
                fullyVisible: fullyVisible
            });
        }
    }
    return result.sort(function (a, b) {
        return a.distanceSq - b.distanceSq;
    }).map(function (a) {
        return a.tileID;
    });
};
Transform.prototype.resize = function resize(width, height) {
    this.width = width;
    this.height = height;
    this.pixelsToGLUnits = [
        2 / width,
        -2 / height
    ];
    this._constrain();
    this._calcMatrices();
};
prototypeAccessors.unmodified.get = function () {
    return this._unmodified;
};
Transform.prototype.zoomScale = function zoomScale(zoom) {
    return Math.pow(2, zoom);
};
Transform.prototype.scaleZoom = function scaleZoom(scale) {
    return Math.log(scale) / Math.LN2;
};
Transform.prototype.project = function project(lnglat) {
    var lat = performance.clamp(lnglat.lat, -this.maxValidLatitude, this.maxValidLatitude);
    return new performance.Point(performance.mercatorXfromLng(lnglat.lng) * this.worldSize, performance.mercatorYfromLat(lat) * this.worldSize);
};
Transform.prototype.unproject = function unproject(point) {
    return new performance.MercatorCoordinate(point.x / this.worldSize, point.y / this.worldSize).toLngLat();
};
prototypeAccessors.point.get = function () {
    return this.project(this.center);
};
Transform.prototype.setLocationAtPoint = function setLocationAtPoint(lnglat, point) {
    var a = this.pointCoordinate(point);
    var b = this.pointCoordinate(this.centerPoint);
    var loc = this.locationCoordinate(lnglat);
    var newCenter = new performance.MercatorCoordinate(loc.x - (a.x - b.x), loc.y - (a.y - b.y));
    this.center = this.coordinateLocation(newCenter);
    if (this._renderWorldCopies) {
        this.center = this.center.wrap();
    }
};
Transform.prototype.locationPoint = function locationPoint(lnglat) {
    return this.coordinatePoint(this.locationCoordinate(lnglat));
};
Transform.prototype.pointLocation = function pointLocation(p) {
    return this.coordinateLocation(this.pointCoordinate(p));
};
Transform.prototype.locationCoordinate = function locationCoordinate(lnglat) {
    return performance.MercatorCoordinate.fromLngLat(lnglat);
};
Transform.prototype.coordinateLocation = function coordinateLocation(coord) {
    return coord.toLngLat();
};
Transform.prototype.pointCoordinate = function pointCoordinate(p) {
    var targetZ = 0;
    var coord0 = [
        p.x,
        p.y,
        0,
        1
    ];
    var coord1 = [
        p.x,
        p.y,
        1,
        1
    ];
    performance.transformMat4(coord0, coord0, this.pixelMatrixInverse);
    performance.transformMat4(coord1, coord1, this.pixelMatrixInverse);
    var w0 = coord0[3];
    var w1 = coord1[3];
    var x0 = coord0[0] / w0;
    var x1 = coord1[0] / w1;
    var y0 = coord0[1] / w0;
    var y1 = coord1[1] / w1;
    var z0 = coord0[2] / w0;
    var z1 = coord1[2] / w1;
    var t = z0 === z1 ? 0 : (targetZ - z0) / (z1 - z0);
    return new performance.MercatorCoordinate(performance.number(x0, x1, t) / this.worldSize, performance.number(y0, y1, t) / this.worldSize);
};
Transform.prototype.coordinatePoint = function coordinatePoint(coord) {
    var p = [
        coord.x * this.worldSize,
        coord.y * this.worldSize,
        0,
        1
    ];
    performance.transformMat4(p, p, this.pixelMatrix);
    return new performance.Point(p[0] / p[3], p[1] / p[3]);
};
Transform.prototype.getBounds = function getBounds() {
    return new performance.LngLatBounds().extend(this.pointLocation(new performance.Point(0, 0))).extend(this.pointLocation(new performance.Point(this.width, 0))).extend(this.pointLocation(new performance.Point(this.width, this.height))).extend(this.pointLocation(new performance.Point(0, this.height)));
};
Transform.prototype.getMaxBounds = function getMaxBounds() {
    if (!this.latRange || this.latRange.length !== 2 || !this.lngRange || this.lngRange.length !== 2) {
        return null;
    }
    return new performance.LngLatBounds([
        this.lngRange[0],
        this.latRange[0]
    ], [
        this.lngRange[1],
        this.latRange[1]
    ]);
};
Transform.prototype.setMaxBounds = function setMaxBounds(bounds) {
    if (bounds) {
        this.lngRange = [
            bounds.getWest(),
            bounds.getEast()
        ];
        this.latRange = [
            bounds.getSouth(),
            bounds.getNorth()
        ];
        this._constrain();
    } else {
        this.lngRange = null;
        this.latRange = [
            -this.maxValidLatitude,
            this.maxValidLatitude
        ];
    }
};
Transform.prototype.calculatePosMatrix = function calculatePosMatrix(unwrappedTileID, aligned) {
    if (aligned === void 0)
        aligned = false;
    var posMatrixKey = unwrappedTileID.key;
    var cache = aligned ? this._alignedPosMatrixCache : this._posMatrixCache;
    if (cache[posMatrixKey]) {
        return cache[posMatrixKey];
    }
    var canonical = unwrappedTileID.canonical;
    var scale = this.worldSize / this.zoomScale(canonical.z);
    var unwrappedX = canonical.x + Math.pow(2, canonical.z) * unwrappedTileID.wrap;
    var posMatrix = performance.identity(new Float64Array(16));
    performance.translate(posMatrix, posMatrix, [
        unwrappedX * scale,
        canonical.y * scale,
        0
    ]);
    performance.scale(posMatrix, posMatrix, [
        scale / performance.EXTENT,
        scale / performance.EXTENT,
        1
    ]);
    performance.multiply(posMatrix, aligned ? this.alignedProjMatrix : this.projMatrix, posMatrix);
    cache[posMatrixKey] = new Float32Array(posMatrix);
    return cache[posMatrixKey];
};
Transform.prototype.customLayerMatrix = function customLayerMatrix() {
    return this.mercatorMatrix.slice();
};
Transform.prototype._constrain = function _constrain() {
    if (!this.center || !this.width || !this.height || this._constraining) {
        return;
    }
    this._constraining = true;
    var minY = -90;
    var maxY = 90;
    var minX = -180;
    var maxX = 180;
    var sy, sx, x2, y2;
    var size = this.size, unmodified = this._unmodified;
    if (this.latRange) {
        var latRange = this.latRange;
        minY = performance.mercatorYfromLat(latRange[1]) * this.worldSize;
        maxY = performance.mercatorYfromLat(latRange[0]) * this.worldSize;
        sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0;
    }
    if (this.lngRange) {
        var lngRange = this.lngRange;
        minX = performance.mercatorXfromLng(lngRange[0]) * this.worldSize;
        maxX = performance.mercatorXfromLng(lngRange[1]) * this.worldSize;
        sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0;
    }
    var point = this.point;
    var s = Math.max(sx || 0, sy || 0);
    if (s) {
        this.center = this.unproject(new performance.Point(sx ? (maxX + minX) / 2 : point.x, sy ? (maxY + minY) / 2 : point.y));
        this.zoom += this.scaleZoom(s);
        this._unmodified = unmodified;
        this._constraining = false;
        return;
    }
    if (this.latRange) {
        var y = point.y, h2 = size.y / 2;
        if (y - h2 < minY) {
            y2 = minY + h2;
        }
        if (y + h2 > maxY) {
            y2 = maxY - h2;
        }
    }
    if (this.lngRange) {
        var x = point.x, w2 = size.x / 2;
        if (x - w2 < minX) {
            x2 = minX + w2;
        }
        if (x + w2 > maxX) {
            x2 = maxX - w2;
        }
    }
    if (x2 !== undefined || y2 !== undefined) {
        this.center = this.unproject(new performance.Point(x2 !== undefined ? x2 : point.x, y2 !== undefined ? y2 : point.y));
    }
    this._unmodified = unmodified;
    this._constraining = false;
};
Transform.prototype._calcMatrices = function _calcMatrices() {
    if (!this.height) {
        return;
    }
    var halfFov = this._fov / 2;
    var offset = this.centerOffset;
    this.cameraToCenterDistance = 0.5 / Math.tan(halfFov) * this.height;
    var groundAngle = Math.PI / 2 + this._pitch;
    var fovAboveCenter = this._fov * (0.5 + offset.y / this.height);
    var topHalfSurfaceDistance = Math.sin(fovAboveCenter) * this.cameraToCenterDistance / Math.sin(performance.clamp(Math.PI - groundAngle - fovAboveCenter, 0.01, Math.PI - 0.01));
    var point = this.point;
    var x = point.x, y = point.y;
    var furthestDistance = Math.cos(Math.PI / 2 - this._pitch) * topHalfSurfaceDistance + this.cameraToCenterDistance;
    var farZ = furthestDistance * 1.01;
    var nearZ = this.height / 50;
    var m = new Float64Array(16);
    performance.perspective(m, this._fov, this.width / this.height, nearZ, farZ);
    m[8] = -offset.x * 2 / this.width;
    m[9] = offset.y * 2 / this.height;
    performance.scale(m, m, [
        1,
        -1,
        1
    ]);
    performance.translate(m, m, [
        0,
        0,
        -this.cameraToCenterDistance
    ]);
    performance.rotateX(m, m, this._pitch);
    performance.rotateZ(m, m, this.angle);
    performance.translate(m, m, [
        -x,
        -y,
        0
    ]);
    this.mercatorMatrix = performance.scale([], m, [
        this.worldSize,
        this.worldSize,
        this.worldSize
    ]);
    performance.scale(m, m, [
        1,
        1,
        performance.mercatorZfromAltitude(1, this.center.lat) * this.worldSize,
        1
    ]);
    this.projMatrix = m;
    this.invProjMatrix = performance.invert([], this.projMatrix);
    var xShift = this.width % 2 / 2, yShift = this.height % 2 / 2, angleCos = Math.cos(this.angle), angleSin = Math.sin(this.angle), dx = x - Math.round(x) + angleCos * xShift + angleSin * yShift, dy = y - Math.round(y) + angleCos * yShift + angleSin * xShift;
    var alignedM = new Float64Array(m);
    performance.translate(alignedM, alignedM, [
        dx > 0.5 ? dx - 1 : dx,
        dy > 0.5 ? dy - 1 : dy,
        0
    ]);
    this.alignedProjMatrix = alignedM;
    m = performance.create();
    performance.scale(m, m, [
        this.width / 2,
        -this.height / 2,
        1
    ]);
    performance.translate(m, m, [
        1,
        -1,
        0
    ]);
    this.labelPlaneMatrix = m;
    m = performance.create();
    performance.scale(m, m, [
        1,
        -1,
        1
    ]);
    performance.translate(m, m, [
        -1,
        -1,
        0
    ]);
    performance.scale(m, m, [
        2 / this.width,
        2 / this.height,
        1
    ]);
    this.glCoordMatrix = m;
    this.pixelMatrix = performance.multiply(new Float64Array(16), this.labelPlaneMatrix, this.projMatrix);
    m = performance.invert(new Float64Array(16), this.pixelMatrix);
    if (!m) {
        throw new Error('failed to invert matrix');
    }
    this.pixelMatrixInverse = m;
    this._posMatrixCache = {};
    this._alignedPosMatrixCache = {};
};
Transform.prototype.maxPitchScaleFactor = function maxPitchScaleFactor() {
    if (!this.pixelMatrixInverse) {
        return 1;
    }
    var coord = this.pointCoordinate(new performance.Point(0, 0));
    var p = [
        coord.x * this.worldSize,
        coord.y * this.worldSize,
        0,
        1
    ];
    var topPoint = performance.transformMat4(p, p, this.pixelMatrix);
    return topPoint[3] / this.cameraToCenterDistance;
};
Transform.prototype.getCameraPoint = function getCameraPoint() {
    var pitch = this._pitch;
    var yOffset = Math.tan(pitch) * (this.cameraToCenterDistance || 1);
    return this.centerPoint.add(new performance.Point(0, yOffset));
};
Transform.prototype.getCameraQueryGeometry = function getCameraQueryGeometry(queryGeometry) {
    var c = this.getCameraPoint();
    if (queryGeometry.length === 1) {
        return [
            queryGeometry[0],
            c
        ];
    } else {
        var minX = c.x;
        var minY = c.y;
        var maxX = c.x;
        var maxY = c.y;
        for (var i = 0, list = queryGeometry; i < list.length; i += 1) {
            var p = list[i];
            minX = Math.min(minX, p.x);
            minY = Math.min(minY, p.y);
            maxX = Math.max(maxX, p.x);
            maxY = Math.max(maxY, p.y);
        }
        return [
            new performance.Point(minX, minY),
            new performance.Point(maxX, minY),
            new performance.Point(maxX, maxY),
            new performance.Point(minX, maxY),
            new performance.Point(minX, minY)
        ];
    }
};
Object.defineProperties(Transform.prototype, prototypeAccessors);

function throttle(fn, time) {
    var pending = false;
    var timerId = null;
    var later = function () {
        timerId = null;
        if (pending) {
            fn();
            timerId = setTimeout(later, time);
            pending = false;
        }
    };
    return function () {
        pending = true;
        if (!timerId) {
            later();
        }
        return timerId;
    };
}

var Hash = function Hash(hashName) {
    this._hashName = hashName && encodeURIComponent(hashName);
    performance.bindAll([
        '_getCurrentHash',
        '_onHashChange',
        '_updateHash'
    ], this);
    this._updateHash = throttle(this._updateHashUnthrottled.bind(this), 30 * 1000 / 100);
};
Hash.prototype.addTo = function addTo(map) {
    this._map = map;
    performance.window.addEventListener('hashchange', this._onHashChange, false);
    this._map.on('moveend', this._updateHash);
    return this;
};
Hash.prototype.remove = function remove() {
    performance.window.removeEventListener('hashchange', this._onHashChange, false);
    this._map.off('moveend', this._updateHash);
    clearTimeout(this._updateHash());
    delete this._map;
    return this;
};
Hash.prototype.getHashString = function getHashString(mapFeedback) {
    var center = this._map.getCenter(), zoom = Math.round(this._map.getZoom() * 100) / 100, precision = Math.ceil((zoom * Math.LN2 + Math.log(512 / 360 / 0.5)) / Math.LN10), m = Math.pow(10, precision), lng = Math.round(center.lng * m) / m, lat = Math.round(center.lat * m) / m, bearing = this._map.getBearing(), pitch = this._map.getPitch();
    var hash = '';
    if (mapFeedback) {
        hash += '/' + lng + '/' + lat + '/' + zoom;
    } else {
        hash += zoom + '/' + lat + '/' + lng;
    }
    if (bearing || pitch) {
        hash += '/' + Math.round(bearing * 10) / 10;
    }
    if (pitch) {
        hash += '/' + Math.round(pitch);
    }
    if (this._hashName) {
        var hashName = this._hashName;
        var found = false;
        var parts = performance.window.location.hash.slice(1).split('&').map(function (part) {
            var key = part.split('=')[0];
            if (key === hashName) {
                found = true;
                return key + '=' + hash;
            }
            return part;
        }).filter(function (a) {
            return a;
        });
        if (!found) {
            parts.push(hashName + '=' + hash);
        }
        return '#' + parts.join('&');
    }
    return '#' + hash;
};
Hash.prototype._getCurrentHash = function _getCurrentHash() {
    var this$1 = this;
    var hash = performance.window.location.hash.replace('#', '');
    if (this._hashName) {
        var keyval;
        hash.split('&').map(function (part) {
            return part.split('=');
        }).forEach(function (part) {
            if (part[0] === this$1._hashName) {
                keyval = part;
            }
        });
        return (keyval ? keyval[1] || '' : '').split('/');
    }
    return hash.split('/');
};
Hash.prototype._onHashChange = function _onHashChange() {
    var loc = this._getCurrentHash();
    if (loc.length >= 3 && !loc.some(function (v) {
            return isNaN(v);
        })) {
        var bearing = this._map.dragRotate.isEnabled() && this._map.touchZoomRotate.isEnabled() ? +(loc[3] || 0) : this._map.getBearing();
        this._map.jumpTo({
            center: [
                +loc[2],
                +loc[1]
            ],
            zoom: +loc[0],
            bearing: bearing,
            pitch: +(loc[4] || 0)
        });
        return true;
    }
    return false;
};
Hash.prototype._updateHashUnthrottled = function _updateHashUnthrottled() {
    var location = performance.window.location.href.replace(/(#.+)?$/, this.getHashString());
    try {
        performance.window.history.replaceState(performance.window.history.state, null, location);
    } catch (SecurityError) {
    }
};

var defaultInertiaOptions = {
    linearity: 0.3,
    easing: performance.bezier(0, 0, 0.3, 1)
};
var defaultPanInertiaOptions = performance.extend({
    deceleration: 2500,
    maxSpeed: 1400
}, defaultInertiaOptions);
var defaultZoomInertiaOptions = performance.extend({
    deceleration: 20,
    maxSpeed: 1400
}, defaultInertiaOptions);
var defaultBearingInertiaOptions = performance.extend({
    deceleration: 1000,
    maxSpeed: 360
}, defaultInertiaOptions);
var defaultPitchInertiaOptions = performance.extend({
    deceleration: 1000,
    maxSpeed: 90
}, defaultInertiaOptions);
var HandlerInertia = function HandlerInertia(map) {
    this._map = map;
    this.clear();
};
HandlerInertia.prototype.clear = function clear() {
    this._inertiaBuffer = [];
};
HandlerInertia.prototype.record = function record(settings) {
    this._drainInertiaBuffer();
    this._inertiaBuffer.push({
        time: performance.browser.now(),
        settings: settings
    });
};
HandlerInertia.prototype._drainInertiaBuffer = function _drainInertiaBuffer() {
    var inertia = this._inertiaBuffer, now = performance.browser.now(), cutoff = 160;
    while (inertia.length > 0 && now - inertia[0].time > cutoff) {
        inertia.shift();
    }
};
HandlerInertia.prototype._onMoveEnd = function _onMoveEnd(panInertiaOptions) {
    this._drainInertiaBuffer();
    if (this._inertiaBuffer.length < 2) {
        return;
    }
    var deltas = {
        zoom: 0,
        bearing: 0,
        pitch: 0,
        pan: new performance.Point(0, 0),
        pinchAround: undefined,
        around: undefined
    };
    for (var i = 0, list = this._inertiaBuffer; i < list.length; i += 1) {
        var ref = list[i];
        var settings = ref.settings;
        deltas.zoom += settings.zoomDelta || 0;
        deltas.bearing += settings.bearingDelta || 0;
        deltas.pitch += settings.pitchDelta || 0;
        if (settings.panDelta) {
            deltas.pan._add(settings.panDelta);
        }
        if (settings.around) {
            deltas.around = settings.around;
        }
        if (settings.pinchAround) {
            deltas.pinchAround = settings.pinchAround;
        }
    }
    var lastEntry = this._inertiaBuffer[this._inertiaBuffer.length - 1];
    var duration = lastEntry.time - this._inertiaBuffer[0].time;
    var easeOptions = {};
    if (deltas.pan.mag()) {
        var result = calculateEasing(deltas.pan.mag(), duration, performance.extend({}, defaultPanInertiaOptions, panInertiaOptions || {}));
        easeOptions.offset = deltas.pan.mult(result.amount / deltas.pan.mag());
        easeOptions.center = this._map.transform.center;
        extendDuration(easeOptions, result);
    }
    if (deltas.zoom) {
        var result$1 = calculateEasing(deltas.zoom, duration, defaultZoomInertiaOptions);
        easeOptions.zoom = this._map.transform.zoom + result$1.amount;
        extendDuration(easeOptions, result$1);
    }
    if (deltas.bearing) {
        var result$2 = calculateEasing(deltas.bearing, duration, defaultBearingInertiaOptions);
        easeOptions.bearing = this._map.transform.bearing + performance.clamp(result$2.amount, -179, 179);
        extendDuration(easeOptions, result$2);
    }
    if (deltas.pitch) {
        var result$3 = calculateEasing(deltas.pitch, duration, defaultPitchInertiaOptions);
        easeOptions.pitch = this._map.transform.pitch + result$3.amount;
        extendDuration(easeOptions, result$3);
    }
    if (easeOptions.zoom || easeOptions.bearing) {
        var last = deltas.pinchAround === undefined ? deltas.around : deltas.pinchAround;
        easeOptions.around = last ? this._map.unproject(last) : this._map.getCenter();
    }
    this.clear();
    return performance.extend(easeOptions, { noMoveStart: true });
};
function extendDuration(easeOptions, result) {
    if (!easeOptions.duration || easeOptions.duration < result.duration) {
        easeOptions.duration = result.duration;
        easeOptions.easing = result.easing;
    }
}
function calculateEasing(amount, inertiaDuration, inertiaOptions) {
    var maxSpeed = inertiaOptions.maxSpeed;
    var linearity = inertiaOptions.linearity;
    var deceleration = inertiaOptions.deceleration;
    var speed = performance.clamp(amount * linearity / (inertiaDuration / 1000), -maxSpeed, maxSpeed);
    var duration = Math.abs(speed) / (deceleration * linearity);
    return {
        easing: inertiaOptions.easing,
        duration: duration * 1000,
        amount: speed * (duration / 2)
    };
}

var MapMouseEvent = function (Event) {
    function MapMouseEvent(type, map, originalEvent, data) {
        if (data === void 0)
            data = {};
        var point = DOM.mousePos(map.getCanvasContainer(), originalEvent);
        var lngLat = map.unproject(point);
        Event.call(this, type, performance.extend({
            point: point,
            lngLat: lngLat,
            originalEvent: originalEvent
        }, data));
        this._defaultPrevented = false;
        this.target = map;
    }
    if (Event)
        MapMouseEvent.__proto__ = Event;
    MapMouseEvent.prototype = Object.create(Event && Event.prototype);
    MapMouseEvent.prototype.constructor = MapMouseEvent;
    var prototypeAccessors = { defaultPrevented: { configurable: true } };
    MapMouseEvent.prototype.preventDefault = function preventDefault() {
        this._defaultPrevented = true;
    };
    prototypeAccessors.defaultPrevented.get = function () {
        return this._defaultPrevented;
    };
    Object.defineProperties(MapMouseEvent.prototype, prototypeAccessors);
    return MapMouseEvent;
}(performance.Event);
var MapTouchEvent = function (Event) {
    function MapTouchEvent(type, map, originalEvent) {
        var touches = type === 'touchend' ? originalEvent.changedTouches : originalEvent.touches;
        var points = DOM.touchPos(map.getCanvasContainer(), touches);
        var lngLats = points.map(function (t) {
            return map.unproject(t);
        });
        var point = points.reduce(function (prev, curr, i, arr) {
            return prev.add(curr.div(arr.length));
        }, new performance.Point(0, 0));
        var lngLat = map.unproject(point);
        Event.call(this, type, {
            points: points,
            point: point,
            lngLats: lngLats,
            lngLat: lngLat,
            originalEvent: originalEvent
        });
        this._defaultPrevented = false;
    }
    if (Event)
        MapTouchEvent.__proto__ = Event;
    MapTouchEvent.prototype = Object.create(Event && Event.prototype);
    MapTouchEvent.prototype.constructor = MapTouchEvent;
    var prototypeAccessors$1 = { defaultPrevented: { configurable: true } };
    MapTouchEvent.prototype.preventDefault = function preventDefault() {
        this._defaultPrevented = true;
    };
    prototypeAccessors$1.defaultPrevented.get = function () {
        return this._defaultPrevented;
    };
    Object.defineProperties(MapTouchEvent.prototype, prototypeAccessors$1);
    return MapTouchEvent;
}(performance.Event);
var MapWheelEvent = function (Event) {
    function MapWheelEvent(type, map, originalEvent) {
        Event.call(this, type, { originalEvent: originalEvent });
        this._defaultPrevented = false;
    }
    if (Event)
        MapWheelEvent.__proto__ = Event;
    MapWheelEvent.prototype = Object.create(Event && Event.prototype);
    MapWheelEvent.prototype.constructor = MapWheelEvent;
    var prototypeAccessors$2 = { defaultPrevented: { configurable: true } };
    MapWheelEvent.prototype.preventDefault = function preventDefault() {
        this._defaultPrevented = true;
    };
    prototypeAccessors$2.defaultPrevented.get = function () {
        return this._defaultPrevented;
    };
    Object.defineProperties(MapWheelEvent.prototype, prototypeAccessors$2);
    return MapWheelEvent;
}(performance.Event);

var MapEventHandler = function MapEventHandler(map, options) {
    this._map = map;
    this._clickTolerance = options.clickTolerance;
};
MapEventHandler.prototype.reset = function reset() {
    delete this._mousedownPos;
};
MapEventHandler.prototype.wheel = function wheel(e) {
    return this._firePreventable(new MapWheelEvent(e.type, this._map, e));
};
MapEventHandler.prototype.mousedown = function mousedown(e, point) {
    this._mousedownPos = point;
    return this._firePreventable(new MapMouseEvent(e.type, this._map, e));
};
MapEventHandler.prototype.mouseup = function mouseup(e) {
    this._map.fire(new MapMouseEvent(e.type, this._map, e));
};
MapEventHandler.prototype.click = function click(e, point) {
    if (this._mousedownPos && this._mousedownPos.dist(point) >= this._clickTolerance) {
        return;
    }
    this._map.fire(new MapMouseEvent(e.type, this._map, e));
};
MapEventHandler.prototype.dblclick = function dblclick(e) {
    return this._firePreventable(new MapMouseEvent(e.type, this._map, e));
};
MapEventHandler.prototype.mouseover = function mouseover(e) {
    this._map.fire(new MapMouseEvent(e.type, this._map, e));
};
MapEventHandler.prototype.mouseout = function mouseout(e) {
    this._map.fire(new MapMouseEvent(e.type, this._map, e));
};
MapEventHandler.prototype.touchstart = function touchstart(e) {
    return this._firePreventable(new MapTouchEvent(e.type, this._map, e));
};
MapEventHandler.prototype.touchmove = function touchmove(e) {
    this._map.fire(new MapTouchEvent(e.type, this._map, e));
};
MapEventHandler.prototype.touchend = function touchend(e) {
    this._map.fire(new MapTouchEvent(e.type, this._map, e));
};
MapEventHandler.prototype.touchcancel = function touchcancel(e) {
    this._map.fire(new MapTouchEvent(e.type, this._map, e));
};
MapEventHandler.prototype._firePreventable = function _firePreventable(mapEvent) {
    this._map.fire(mapEvent);
    if (mapEvent.defaultPrevented) {
        return {};
    }
};
MapEventHandler.prototype.isEnabled = function isEnabled() {
    return true;
};
MapEventHandler.prototype.isActive = function isActive() {
    return false;
};
MapEventHandler.prototype.enable = function enable() {
};
MapEventHandler.prototype.disable = function disable() {
};
var BlockableMapEventHandler = function BlockableMapEventHandler(map) {
    this._map = map;
};
BlockableMapEventHandler.prototype.reset = function reset() {
    this._delayContextMenu = false;
    delete this._contextMenuEvent;
};
BlockableMapEventHandler.prototype.mousemove = function mousemove(e) {
    this._map.fire(new MapMouseEvent(e.type, this._map, e));
};
BlockableMapEventHandler.prototype.mousedown = function mousedown() {
    this._delayContextMenu = true;
};
BlockableMapEventHandler.prototype.mouseup = function mouseup() {
    this._delayContextMenu = false;
    if (this._contextMenuEvent) {
        this._map.fire(new MapMouseEvent('contextmenu', this._map, this._contextMenuEvent));
        delete this._contextMenuEvent;
    }
};
BlockableMapEventHandler.prototype.contextmenu = function contextmenu(e) {
    if (this._delayContextMenu) {
        this._contextMenuEvent = e;
    } else {
        this._map.fire(new MapMouseEvent(e.type, this._map, e));
    }
    if (this._map.listens('contextmenu')) {
        e.preventDefault();
    }
};
BlockableMapEventHandler.prototype.isEnabled = function isEnabled() {
    return true;
};
BlockableMapEventHandler.prototype.isActive = function isActive() {
    return false;
};
BlockableMapEventHandler.prototype.enable = function enable() {
};
BlockableMapEventHandler.prototype.disable = function disable() {
};

var BoxZoomHandler = function BoxZoomHandler(map, options) {
    this._map = map;
    this._el = map.getCanvasContainer();
    this._container = map.getContainer();
    this._clickTolerance = options.clickTolerance || 1;
};
BoxZoomHandler.prototype.isEnabled = function isEnabled() {
    return !!this._enabled;
};
BoxZoomHandler.prototype.isActive = function isActive() {
    return !!this._active;
};
BoxZoomHandler.prototype.enable = function enable() {
    if (this.isEnabled()) {
        return;
    }
    this._enabled = true;
};
BoxZoomHandler.prototype.disable = function disable() {
    if (!this.isEnabled()) {
        return;
    }
    this._enabled = false;
};
BoxZoomHandler.prototype.mousedown = function mousedown(e, point) {
    if (!this.isEnabled()) {
        return;
    }
    if (!(e.shiftKey && e.button === 0)) {
        return;
    }
    DOM.disableDrag();
    this._startPos = this._lastPos = point;
    this._active = true;
};
BoxZoomHandler.prototype.mousemoveWindow = function mousemoveWindow(e, point) {
    if (!this._active) {
        return;
    }
    var pos = point;
    if (this._lastPos.equals(pos) || !this._box && pos.dist(this._startPos) < this._clickTolerance) {
        return;
    }
    var p0 = this._startPos;
    this._lastPos = pos;
    if (!this._box) {
        this._box = DOM.create('div', 'mapboxgl-boxzoom', this._container);
        this._container.classList.add('mapboxgl-crosshair');
        this._fireEvent('boxzoomstart', e);
    }
    var minX = Math.min(p0.x, pos.x), maxX = Math.max(p0.x, pos.x), minY = Math.min(p0.y, pos.y), maxY = Math.max(p0.y, pos.y);
    DOM.setTransform(this._box, 'translate(' + minX + 'px,' + minY + 'px)');
    this._box.style.width = maxX - minX + 'px';
    this._box.style.height = maxY - minY + 'px';
};
BoxZoomHandler.prototype.mouseupWindow = function mouseupWindow(e, point) {
    var this$1 = this;
    if (!this._active) {
        return;
    }
    if (e.button !== 0) {
        return;
    }
    var p0 = this._startPos, p1 = point;
    this.reset();
    DOM.suppressClick();
    if (p0.x === p1.x && p0.y === p1.y) {
        this._fireEvent('boxzoomcancel', e);
    } else {
        this._map.fire(new performance.Event('boxzoomend', { originalEvent: e }));
        return {
            cameraAnimation: function (map) {
                return map.fitScreenCoordinates(p0, p1, this$1._map.getBearing(), { linear: true });
            }
        };
    }
};
BoxZoomHandler.prototype.keydown = function keydown(e) {
    if (!this._active) {
        return;
    }
    if (e.keyCode === 27) {
        this.reset();
        this._fireEvent('boxzoomcancel', e);
    }
};
BoxZoomHandler.prototype.blur = function blur() {
    this.reset();
};
BoxZoomHandler.prototype.reset = function reset() {
    this._active = false;
    this._container.classList.remove('mapboxgl-crosshair');
    if (this._box) {
        DOM.remove(this._box);
        this._box = null;
    }
    DOM.enableDrag();
    delete this._startPos;
    delete this._lastPos;
};
BoxZoomHandler.prototype._fireEvent = function _fireEvent(type, e) {
    return this._map.fire(new performance.Event(type, { originalEvent: e }));
};

function indexTouches(touches, points) {
    var obj = {};
    for (var i = 0; i < touches.length; i++) {
        obj[touches[i].identifier] = points[i];
    }
    return obj;
}

function getCentroid(points) {
    var sum = new performance.Point(0, 0);
    for (var i = 0, list = points; i < list.length; i += 1) {
        var point = list[i];
        sum._add(point);
    }
    return sum.div(points.length);
}
var MAX_TAP_INTERVAL = 500;
var MAX_TOUCH_TIME = 500;
var MAX_DIST = 30;
var SingleTapRecognizer = function SingleTapRecognizer(options) {
    this.reset();
    this.numTouches = options.numTouches;
};
SingleTapRecognizer.prototype.reset = function reset() {
    delete this.centroid;
    delete this.startTime;
    delete this.touches;
    this.aborted = false;
};
SingleTapRecognizer.prototype.touchstart = function touchstart(e, points, mapTouches) {
    if (this.centroid || mapTouches.length > this.numTouches) {
        this.aborted = true;
    }
    if (this.aborted) {
        return;
    }
    if (this.startTime === undefined) {
        this.startTime = e.timeStamp;
    }
    if (mapTouches.length === this.numTouches) {
        this.centroid = getCentroid(points);
        this.touches = indexTouches(mapTouches, points);
    }
};
SingleTapRecognizer.prototype.touchmove = function touchmove(e, points, mapTouches) {
    if (this.aborted || !this.centroid) {
        return;
    }
    var newTouches = indexTouches(mapTouches, points);
    for (var id in this.touches) {
        var prevPos = this.touches[id];
        var pos = newTouches[id];
        if (!pos || pos.dist(prevPos) > MAX_DIST) {
            this.aborted = true;
        }
    }
};
SingleTapRecognizer.prototype.touchend = function touchend(e, points, mapTouches) {
    if (!this.centroid || e.timeStamp - this.startTime > MAX_TOUCH_TIME) {
        this.aborted = true;
    }
    if (mapTouches.length === 0) {
        var centroid = !this.aborted && this.centroid;
        this.reset();
        if (centroid) {
            return centroid;
        }
    }
};
var TapRecognizer = function TapRecognizer(options) {
    this.singleTap = new SingleTapRecognizer(options);
    this.numTaps = options.numTaps;
    this.reset();
};
TapRecognizer.prototype.reset = function reset() {
    this.lastTime = Infinity;
    delete this.lastTap;
    this.count = 0;
    this.singleTap.reset();
};
TapRecognizer.prototype.touchstart = function touchstart(e, points, mapTouches) {
    this.singleTap.touchstart(e, points, mapTouches);
};
TapRecognizer.prototype.touchmove = function touchmove(e, points, mapTouches) {
    this.singleTap.touchmove(e, points, mapTouches);
};
TapRecognizer.prototype.touchend = function touchend(e, points, mapTouches) {
    var tap = this.singleTap.touchend(e, points, mapTouches);
    if (tap) {
        var soonEnough = e.timeStamp - this.lastTime < MAX_TAP_INTERVAL;
        var closeEnough = !this.lastTap || this.lastTap.dist(tap) < MAX_DIST;
        if (!soonEnough || !closeEnough) {
            this.reset();
        }
        this.count++;
        this.lastTime = e.timeStamp;
        this.lastTap = tap;
        if (this.count === this.numTaps) {
            this.reset();
            return tap;
        }
    }
};

var TapZoomHandler = function TapZoomHandler() {
    this._zoomIn = new TapRecognizer({
        numTouches: 1,
        numTaps: 2
    });
    this._zoomOut = new TapRecognizer({
        numTouches: 2,
        numTaps: 1
    });
    this.reset();
};
TapZoomHandler.prototype.reset = function reset() {
    this._active = false;
    this._zoomIn.reset();
    this._zoomOut.reset();
};
TapZoomHandler.prototype.touchstart = function touchstart(e, points, mapTouches) {
    this._zoomIn.touchstart(e, points, mapTouches);
    this._zoomOut.touchstart(e, points, mapTouches);
};
TapZoomHandler.prototype.touchmove = function touchmove(e, points, mapTouches) {
    this._zoomIn.touchmove(e, points, mapTouches);
    this._zoomOut.touchmove(e, points, mapTouches);
};
TapZoomHandler.prototype.touchend = function touchend(e, points, mapTouches) {
    var this$1 = this;
    var zoomInPoint = this._zoomIn.touchend(e, points, mapTouches);
    var zoomOutPoint = this._zoomOut.touchend(e, points, mapTouches);
    if (zoomInPoint) {
        this._active = true;
        e.preventDefault();
        setTimeout(function () {
            return this$1.reset();
        }, 0);
        return {
            cameraAnimation: function (map) {
                return map.easeTo({
                    duration: 300,
                    zoom: map.getZoom() + 1,
                    around: map.unproject(zoomInPoint)
                }, { originalEvent: e });
            }
        };
    } else if (zoomOutPoint) {
        this._active = true;
        e.preventDefault();
        setTimeout(function () {
            return this$1.reset();
        }, 0);
        return {
            cameraAnimation: function (map) {
                return map.easeTo({
                    duration: 300,
                    zoom: map.getZoom() - 1,
                    around: map.unproject(zoomOutPoint)
                }, { originalEvent: e });
            }
        };
    }
};
TapZoomHandler.prototype.touchcancel = function touchcancel() {
    this.reset();
};
TapZoomHandler.prototype.enable = function enable() {
    this._enabled = true;
};
TapZoomHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
TapZoomHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
TapZoomHandler.prototype.isActive = function isActive() {
    return this._active;
};

var LEFT_BUTTON = 0;
var RIGHT_BUTTON = 2;
var BUTTONS_FLAGS = {};
BUTTONS_FLAGS[LEFT_BUTTON] = 1;
BUTTONS_FLAGS[RIGHT_BUTTON] = 2;
function buttonStillPressed(e, button) {
    var flag = BUTTONS_FLAGS[button];
    return e.buttons === undefined || (e.buttons & flag) !== flag;
}
var MouseHandler = function MouseHandler(options) {
    this.reset();
    this._clickTolerance = options.clickTolerance || 1;
};
MouseHandler.prototype.blur = function blur() {
    this.reset();
};
MouseHandler.prototype.reset = function reset() {
    this._active = false;
    this._moved = false;
    delete this._lastPoint;
    delete this._eventButton;
};
MouseHandler.prototype._correctButton = function _correctButton(e, button) {
    return false;
};
MouseHandler.prototype._move = function _move(lastPoint, point) {
    return {};
};
MouseHandler.prototype.mousedown = function mousedown(e, point) {
    if (this._lastPoint) {
        return;
    }
    var eventButton = DOM.mouseButton(e);
    if (!this._correctButton(e, eventButton)) {
        return;
    }
    this._lastPoint = point;
    this._eventButton = eventButton;
};
MouseHandler.prototype.mousemoveWindow = function mousemoveWindow(e, point) {
    var lastPoint = this._lastPoint;
    if (!lastPoint) {
        return;
    }
    e.preventDefault();
    if (buttonStillPressed(e, this._eventButton)) {
        this.reset();
        return;
    }
    if (!this._moved && point.dist(lastPoint) < this._clickTolerance) {
        return;
    }
    this._moved = true;
    this._lastPoint = point;
    return this._move(lastPoint, point);
};
MouseHandler.prototype.mouseupWindow = function mouseupWindow(e) {
    if (!this._lastPoint) {
        return;
    }
    var eventButton = DOM.mouseButton(e);
    if (eventButton !== this._eventButton) {
        return;
    }
    if (this._moved) {
        DOM.suppressClick();
    }
    this.reset();
};
MouseHandler.prototype.enable = function enable() {
    this._enabled = true;
};
MouseHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
MouseHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
MouseHandler.prototype.isActive = function isActive() {
    return this._active;
};
var MousePanHandler = function (MouseHandler) {
    function MousePanHandler() {
        MouseHandler.apply(this, arguments);
    }
    if (MouseHandler)
        MousePanHandler.__proto__ = MouseHandler;
    MousePanHandler.prototype = Object.create(MouseHandler && MouseHandler.prototype);
    MousePanHandler.prototype.constructor = MousePanHandler;
    MousePanHandler.prototype.mousedown = function mousedown(e, point) {
        MouseHandler.prototype.mousedown.call(this, e, point);
        if (this._lastPoint) {
            this._active = true;
        }
    };
    MousePanHandler.prototype._correctButton = function _correctButton(e, button) {
        return button === LEFT_BUTTON && !e.ctrlKey;
    };
    MousePanHandler.prototype._move = function _move(lastPoint, point) {
        return {
            around: point,
            panDelta: point.sub(lastPoint)
        };
    };
    return MousePanHandler;
}(MouseHandler);
var MouseRotateHandler = function (MouseHandler) {
    function MouseRotateHandler() {
        MouseHandler.apply(this, arguments);
    }
    if (MouseHandler)
        MouseRotateHandler.__proto__ = MouseHandler;
    MouseRotateHandler.prototype = Object.create(MouseHandler && MouseHandler.prototype);
    MouseRotateHandler.prototype.constructor = MouseRotateHandler;
    MouseRotateHandler.prototype._correctButton = function _correctButton(e, button) {
        return button === LEFT_BUTTON && e.ctrlKey || button === RIGHT_BUTTON;
    };
    MouseRotateHandler.prototype._move = function _move(lastPoint, point) {
        var degreesPerPixelMoved = 0.8;
        var bearingDelta = (point.x - lastPoint.x) * degreesPerPixelMoved;
        if (bearingDelta) {
            this._active = true;
            return { bearingDelta: bearingDelta };
        }
    };
    MouseRotateHandler.prototype.contextmenu = function contextmenu(e) {
        e.preventDefault();
    };
    return MouseRotateHandler;
}(MouseHandler);
var MousePitchHandler = function (MouseHandler) {
    function MousePitchHandler() {
        MouseHandler.apply(this, arguments);
    }
    if (MouseHandler)
        MousePitchHandler.__proto__ = MouseHandler;
    MousePitchHandler.prototype = Object.create(MouseHandler && MouseHandler.prototype);
    MousePitchHandler.prototype.constructor = MousePitchHandler;
    MousePitchHandler.prototype._correctButton = function _correctButton(e, button) {
        return button === LEFT_BUTTON && e.ctrlKey || button === RIGHT_BUTTON;
    };
    MousePitchHandler.prototype._move = function _move(lastPoint, point) {
        var degreesPerPixelMoved = -0.5;
        var pitchDelta = (point.y - lastPoint.y) * degreesPerPixelMoved;
        if (pitchDelta) {
            this._active = true;
            return { pitchDelta: pitchDelta };
        }
    };
    MousePitchHandler.prototype.contextmenu = function contextmenu(e) {
        e.preventDefault();
    };
    return MousePitchHandler;
}(MouseHandler);

var TouchPanHandler = function TouchPanHandler(options) {
    this._minTouches = 1;
    this._clickTolerance = options.clickTolerance || 1;
    this.reset();
};
TouchPanHandler.prototype.reset = function reset() {
    this._active = false;
    this._touches = {};
    this._sum = new performance.Point(0, 0);
};
TouchPanHandler.prototype.touchstart = function touchstart(e, points, mapTouches) {
    return this._calculateTransform(e, points, mapTouches);
};
TouchPanHandler.prototype.touchmove = function touchmove(e, points, mapTouches) {
    if (!this._active || mapTouches.length < this._minTouches) {
        return;
    }
    e.preventDefault();
    return this._calculateTransform(e, points, mapTouches);
};
TouchPanHandler.prototype.touchend = function touchend(e, points, mapTouches) {
    this._calculateTransform(e, points, mapTouches);
    if (this._active && mapTouches.length < this._minTouches) {
        this.reset();
    }
};
TouchPanHandler.prototype.touchcancel = function touchcancel() {
    this.reset();
};
TouchPanHandler.prototype._calculateTransform = function _calculateTransform(e, points, mapTouches) {
    if (mapTouches.length > 0) {
        this._active = true;
    }
    var touches = indexTouches(mapTouches, points);
    var touchPointSum = new performance.Point(0, 0);
    var touchDeltaSum = new performance.Point(0, 0);
    var touchDeltaCount = 0;
    for (var identifier in touches) {
        var point = touches[identifier];
        var prevPoint = this._touches[identifier];
        if (prevPoint) {
            touchPointSum._add(point);
            touchDeltaSum._add(point.sub(prevPoint));
            touchDeltaCount++;
            touches[identifier] = point;
        }
    }
    this._touches = touches;
    if (touchDeltaCount < this._minTouches || !touchDeltaSum.mag()) {
        return;
    }
    var panDelta = touchDeltaSum.div(touchDeltaCount);
    this._sum._add(panDelta);
    if (this._sum.mag() < this._clickTolerance) {
        return;
    }
    var around = touchPointSum.div(touchDeltaCount);
    return {
        around: around,
        panDelta: panDelta
    };
};
TouchPanHandler.prototype.enable = function enable() {
    this._enabled = true;
};
TouchPanHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
TouchPanHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
TouchPanHandler.prototype.isActive = function isActive() {
    return this._active;
};

var TwoTouchHandler = function TwoTouchHandler() {
    this.reset();
};
TwoTouchHandler.prototype.reset = function reset() {
    this._active = false;
    delete this._firstTwoTouches;
};
TwoTouchHandler.prototype._start = function _start(points) {
};
TwoTouchHandler.prototype._move = function _move(points, pinchAround, e) {
    return {};
};
TwoTouchHandler.prototype.touchstart = function touchstart(e, points, mapTouches) {
    if (this._firstTwoTouches || mapTouches.length < 2) {
        return;
    }
    this._firstTwoTouches = [
        mapTouches[0].identifier,
        mapTouches[1].identifier
    ];
    this._start([
        points[0],
        points[1]
    ]);
};
TwoTouchHandler.prototype.touchmove = function touchmove(e, points, mapTouches) {
    if (!this._firstTwoTouches) {
        return;
    }
    e.preventDefault();
    var ref = this._firstTwoTouches;
    var idA = ref[0];
    var idB = ref[1];
    var a = getTouchById(mapTouches, points, idA);
    var b = getTouchById(mapTouches, points, idB);
    if (!a || !b) {
        return;
    }
    var pinchAround = this._aroundCenter ? null : a.add(b).div(2);
    return this._move([
        a,
        b
    ], pinchAround, e);
};
TwoTouchHandler.prototype.touchend = function touchend(e, points, mapTouches) {
    if (!this._firstTwoTouches) {
        return;
    }
    var ref = this._firstTwoTouches;
    var idA = ref[0];
    var idB = ref[1];
    var a = getTouchById(mapTouches, points, idA);
    var b = getTouchById(mapTouches, points, idB);
    if (a && b) {
        return;
    }
    if (this._active) {
        DOM.suppressClick();
    }
    this.reset();
};
TwoTouchHandler.prototype.touchcancel = function touchcancel() {
    this.reset();
};
TwoTouchHandler.prototype.enable = function enable(options) {
    this._enabled = true;
    this._aroundCenter = !!options && options.around === 'center';
};
TwoTouchHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
TwoTouchHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
TwoTouchHandler.prototype.isActive = function isActive() {
    return this._active;
};
function getTouchById(mapTouches, points, identifier) {
    for (var i = 0; i < mapTouches.length; i++) {
        if (mapTouches[i].identifier === identifier) {
            return points[i];
        }
    }
}
var ZOOM_THRESHOLD = 0.1;
function getZoomDelta(distance, lastDistance) {
    return Math.log(distance / lastDistance) / Math.LN2;
}
var TouchZoomHandler = function (TwoTouchHandler) {
    function TouchZoomHandler() {
        TwoTouchHandler.apply(this, arguments);
    }
    if (TwoTouchHandler)
        TouchZoomHandler.__proto__ = TwoTouchHandler;
    TouchZoomHandler.prototype = Object.create(TwoTouchHandler && TwoTouchHandler.prototype);
    TouchZoomHandler.prototype.constructor = TouchZoomHandler;
    TouchZoomHandler.prototype.reset = function reset() {
        TwoTouchHandler.prototype.reset.call(this);
        delete this._distance;
        delete this._startDistance;
    };
    TouchZoomHandler.prototype._start = function _start(points) {
        this._startDistance = this._distance = points[0].dist(points[1]);
    };
    TouchZoomHandler.prototype._move = function _move(points, pinchAround) {
        var lastDistance = this._distance;
        this._distance = points[0].dist(points[1]);
        if (!this._active && Math.abs(getZoomDelta(this._distance, this._startDistance)) < ZOOM_THRESHOLD) {
            return;
        }
        this._active = true;
        return {
            zoomDelta: getZoomDelta(this._distance, lastDistance),
            pinchAround: pinchAround
        };
    };
    return TouchZoomHandler;
}(TwoTouchHandler);
var ROTATION_THRESHOLD = 25;
function getBearingDelta(a, b) {
    return a.angleWith(b) * 180 / Math.PI;
}
var TouchRotateHandler = function (TwoTouchHandler) {
    function TouchRotateHandler() {
        TwoTouchHandler.apply(this, arguments);
    }
    if (TwoTouchHandler)
        TouchRotateHandler.__proto__ = TwoTouchHandler;
    TouchRotateHandler.prototype = Object.create(TwoTouchHandler && TwoTouchHandler.prototype);
    TouchRotateHandler.prototype.constructor = TouchRotateHandler;
    TouchRotateHandler.prototype.reset = function reset() {
        TwoTouchHandler.prototype.reset.call(this);
        delete this._minDiameter;
        delete this._startVector;
        delete this._vector;
    };
    TouchRotateHandler.prototype._start = function _start(points) {
        this._startVector = this._vector = points[0].sub(points[1]);
        this._minDiameter = points[0].dist(points[1]);
    };
    TouchRotateHandler.prototype._move = function _move(points, pinchAround) {
        var lastVector = this._vector;
        this._vector = points[0].sub(points[1]);
        if (!this._active && this._isBelowThreshold(this._vector)) {
            return;
        }
        this._active = true;
        return {
            bearingDelta: getBearingDelta(this._vector, lastVector),
            pinchAround: pinchAround
        };
    };
    TouchRotateHandler.prototype._isBelowThreshold = function _isBelowThreshold(vector) {
        this._minDiameter = Math.min(this._minDiameter, vector.mag());
        var circumference = Math.PI * this._minDiameter;
        var threshold = ROTATION_THRESHOLD / circumference * 360;
        var bearingDeltaSinceStart = getBearingDelta(vector, this._startVector);
        return Math.abs(bearingDeltaSinceStart) < threshold;
    };
    return TouchRotateHandler;
}(TwoTouchHandler);
function isVertical(vector) {
    return Math.abs(vector.y) > Math.abs(vector.x);
}
var ALLOWED_SINGLE_TOUCH_TIME = 100;
var TouchPitchHandler = function (TwoTouchHandler) {
    function TouchPitchHandler() {
        TwoTouchHandler.apply(this, arguments);
    }
    if (TwoTouchHandler)
        TouchPitchHandler.__proto__ = TwoTouchHandler;
    TouchPitchHandler.prototype = Object.create(TwoTouchHandler && TwoTouchHandler.prototype);
    TouchPitchHandler.prototype.constructor = TouchPitchHandler;
    TouchPitchHandler.prototype.reset = function reset() {
        TwoTouchHandler.prototype.reset.call(this);
        this._valid = undefined;
        delete this._firstMove;
        delete this._lastPoints;
    };
    TouchPitchHandler.prototype._start = function _start(points) {
        this._lastPoints = points;
        if (isVertical(points[0].sub(points[1]))) {
            this._valid = false;
        }
    };
    TouchPitchHandler.prototype._move = function _move(points, center, e) {
        var vectorA = points[0].sub(this._lastPoints[0]);
        var vectorB = points[1].sub(this._lastPoints[1]);
        this._valid = this.gestureBeginsVertically(vectorA, vectorB, e.timeStamp);
        if (!this._valid) {
            return;
        }
        this._lastPoints = points;
        this._active = true;
        var yDeltaAverage = (vectorA.y + vectorB.y) / 2;
        var degreesPerPixelMoved = -0.5;
        return { pitchDelta: yDeltaAverage * degreesPerPixelMoved };
    };
    TouchPitchHandler.prototype.gestureBeginsVertically = function gestureBeginsVertically(vectorA, vectorB, timeStamp) {
        if (this._valid !== undefined) {
            return this._valid;
        }
        var threshold = 2;
        var movedA = vectorA.mag() >= threshold;
        var movedB = vectorB.mag() >= threshold;
        if (!movedA && !movedB) {
            return;
        }
        if (!movedA || !movedB) {
            if (this._firstMove === undefined) {
                this._firstMove = timeStamp;
            }
            if (timeStamp - this._firstMove < ALLOWED_SINGLE_TOUCH_TIME) {
                return undefined;
            } else {
                return false;
            }
        }
        var isSameDirection = vectorA.y > 0 === vectorB.y > 0;
        return isVertical(vectorA) && isVertical(vectorB) && isSameDirection;
    };
    return TouchPitchHandler;
}(TwoTouchHandler);

var defaultOptions = {
    panStep: 100,
    bearingStep: 15,
    pitchStep: 10
};
var KeyboardHandler = function KeyboardHandler() {
    var stepOptions = defaultOptions;
    this._panStep = stepOptions.panStep;
    this._bearingStep = stepOptions.bearingStep;
    this._pitchStep = stepOptions.pitchStep;
    this._rotationDisabled = false;
};
KeyboardHandler.prototype.blur = function blur() {
    this.reset();
};
KeyboardHandler.prototype.reset = function reset() {
    this._active = false;
};
KeyboardHandler.prototype.keydown = function keydown(e) {
    var this$1 = this;
    if (e.altKey || e.ctrlKey || e.metaKey) {
        return;
    }
    var zoomDir = 0;
    var bearingDir = 0;
    var pitchDir = 0;
    var xDir = 0;
    var yDir = 0;
    switch (e.keyCode) {
    case 61:
    case 107:
    case 171:
    case 187:
        zoomDir = 1;
        break;
    case 189:
    case 109:
    case 173:
        zoomDir = -1;
        break;
    case 37:
        if (e.shiftKey) {
            bearingDir = -1;
        } else {
            e.preventDefault();
            xDir = -1;
        }
        break;
    case 39:
        if (e.shiftKey) {
            bearingDir = 1;
        } else {
            e.preventDefault();
            xDir = 1;
        }
        break;
    case 38:
        if (e.shiftKey) {
            pitchDir = 1;
        } else {
            e.preventDefault();
            yDir = -1;
        }
        break;
    case 40:
        if (e.shiftKey) {
            pitchDir = -1;
        } else {
            e.preventDefault();
            yDir = 1;
        }
        break;
    default:
        return;
    }
    if (this._rotationDisabled) {
        bearingDir = 0;
        pitchDir = 0;
    }
    return {
        cameraAnimation: function (map) {
            var zoom = map.getZoom();
            map.easeTo({
                duration: 300,
                easeId: 'keyboardHandler',
                easing: easeOut,
                zoom: zoomDir ? Math.round(zoom) + zoomDir * (e.shiftKey ? 2 : 1) : zoom,
                bearing: map.getBearing() + bearingDir * this$1._bearingStep,
                pitch: map.getPitch() + pitchDir * this$1._pitchStep,
                offset: [
                    -xDir * this$1._panStep,
                    -yDir * this$1._panStep
                ],
                center: map.getCenter()
            }, { originalEvent: e });
        }
    };
};
KeyboardHandler.prototype.enable = function enable() {
    this._enabled = true;
};
KeyboardHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
KeyboardHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
KeyboardHandler.prototype.isActive = function isActive() {
    return this._active;
};
KeyboardHandler.prototype.disableRotation = function disableRotation() {
    this._rotationDisabled = true;
};
KeyboardHandler.prototype.enableRotation = function enableRotation() {
    this._rotationDisabled = false;
};
function easeOut(t) {
    return t * (2 - t);
}

var wheelZoomDelta = 4.000244140625;
var defaultZoomRate = 1 / 100;
var wheelZoomRate = 1 / 450;
var maxScalePerFrame = 2;
var ScrollZoomHandler = function ScrollZoomHandler(map, handler) {
    this._map = map;
    this._el = map.getCanvasContainer();
    this._handler = handler;
    this._delta = 0;
    this._defaultZoomRate = defaultZoomRate;
    this._wheelZoomRate = wheelZoomRate;
    performance.bindAll(['_onTimeout'], this);
};
ScrollZoomHandler.prototype.setZoomRate = function setZoomRate(zoomRate) {
    this._defaultZoomRate = zoomRate;
};
ScrollZoomHandler.prototype.setWheelZoomRate = function setWheelZoomRate(wheelZoomRate) {
    this._wheelZoomRate = wheelZoomRate;
};
ScrollZoomHandler.prototype.isEnabled = function isEnabled() {
    return !!this._enabled;
};
ScrollZoomHandler.prototype.isActive = function isActive() {
    return !!this._active || this._finishTimeout !== undefined;
};
ScrollZoomHandler.prototype.isZooming = function isZooming() {
    return !!this._zooming;
};
ScrollZoomHandler.prototype.enable = function enable(options) {
    if (this.isEnabled()) {
        return;
    }
    this._enabled = true;
    this._aroundCenter = options && options.around === 'center';
};
ScrollZoomHandler.prototype.disable = function disable() {
    if (!this.isEnabled()) {
        return;
    }
    this._enabled = false;
};
ScrollZoomHandler.prototype.wheel = function wheel(e) {
    if (!this.isEnabled()) {
        return;
    }
    var value = e.deltaMode === performance.window.WheelEvent.DOM_DELTA_LINE ? e.deltaY * 40 : e.deltaY;
    var now = performance.browser.now(), timeDelta = now - (this._lastWheelEventTime || 0);
    this._lastWheelEventTime = now;
    if (value !== 0 && value % wheelZoomDelta === 0) {
        this._type = 'wheel';
    } else if (value !== 0 && Math.abs(value) < 4) {
        this._type = 'trackpad';
    } else if (timeDelta > 400) {
        this._type = null;
        this._lastValue = value;
        this._timeout = setTimeout(this._onTimeout, 40, e);
    } else if (!this._type) {
        this._type = Math.abs(timeDelta * value) < 200 ? 'trackpad' : 'wheel';
        if (this._timeout) {
            clearTimeout(this._timeout);
            this._timeout = null;
            value += this._lastValue;
        }
    }
    if (e.shiftKey && value) {
        value = value / 4;
    }
    if (this._type) {
        this._lastWheelEvent = e;
        this._delta -= value;
        if (!this._active) {
            this._start(e);
        }
    }
    e.preventDefault();
};
ScrollZoomHandler.prototype._onTimeout = function _onTimeout(initialEvent) {
    this._type = 'wheel';
    this._delta -= this._lastValue;
    if (!this._active) {
        this._start(initialEvent);
    }
};
ScrollZoomHandler.prototype._start = function _start(e) {
    if (!this._delta) {
        return;
    }
    if (this._frameId) {
        this._frameId = null;
    }
    this._active = true;
    if (!this.isZooming()) {
        this._zooming = true;
    }
    if (this._finishTimeout) {
        clearTimeout(this._finishTimeout);
        delete this._finishTimeout;
    }
    var pos = DOM.mousePos(this._el, e);
    this._around = performance.LngLat.convert(this._aroundCenter ? this._map.getCenter() : this._map.unproject(pos));
    this._aroundPoint = this._map.transform.locationPoint(this._around);
    if (!this._frameId) {
        this._frameId = true;
        this._handler._triggerRenderFrame();
    }
};
ScrollZoomHandler.prototype.renderFrame = function renderFrame() {
    var this$1 = this;
    if (!this._frameId) {
        return;
    }
    this._frameId = null;
    if (!this.isActive()) {
        return;
    }
    var tr = this._map.transform;
    if (this._delta !== 0) {
        var zoomRate = this._type === 'wheel' && Math.abs(this._delta) > wheelZoomDelta ? this._wheelZoomRate : this._defaultZoomRate;
        var scale = maxScalePerFrame / (1 + Math.exp(-Math.abs(this._delta * zoomRate)));
        if (this._delta < 0 && scale !== 0) {
            scale = 1 / scale;
        }
        var fromScale = typeof this._targetZoom === 'number' ? tr.zoomScale(this._targetZoom) : tr.scale;
        this._targetZoom = Math.min(tr.maxZoom, Math.max(tr.minZoom, tr.scaleZoom(fromScale * scale)));
        if (this._type === 'wheel') {
            this._startZoom = tr.zoom;
            this._easing = this._smoothOutEasing(200);
        }
        this._delta = 0;
    }
    var targetZoom = typeof this._targetZoom === 'number' ? this._targetZoom : tr.zoom;
    var startZoom = this._startZoom;
    var easing = this._easing;
    var finished = false;
    var zoom;
    if (this._type === 'wheel' && startZoom && easing) {
        var t = Math.min((performance.browser.now() - this._lastWheelEventTime) / 200, 1);
        var k = easing(t);
        zoom = performance.number(startZoom, targetZoom, k);
        if (t < 1) {
            if (!this._frameId) {
                this._frameId = true;
            }
        } else {
            finished = true;
        }
    } else {
        zoom = targetZoom;
        finished = true;
    }
    this._active = true;
    if (finished) {
        this._active = false;
        this._finishTimeout = setTimeout(function () {
            this$1._zooming = false;
            this$1._handler._triggerRenderFrame();
            delete this$1._targetZoom;
            delete this$1._finishTimeout;
        }, 200);
    }
    return {
        noInertia: true,
        needsRenderFrame: !finished,
        zoomDelta: zoom - tr.zoom,
        around: this._aroundPoint,
        originalEvent: this._lastWheelEvent
    };
};
ScrollZoomHandler.prototype._smoothOutEasing = function _smoothOutEasing(duration) {
    var easing = performance.ease;
    if (this._prevEase) {
        var ease = this._prevEase, t = (performance.browser.now() - ease.start) / ease.duration, speed = ease.easing(t + 0.01) - ease.easing(t), x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01, y = Math.sqrt(0.27 * 0.27 - x * x);
        easing = performance.bezier(x, y, 0.25, 1);
    }
    this._prevEase = {
        start: performance.browser.now(),
        duration: duration,
        easing: easing
    };
    return easing;
};
ScrollZoomHandler.prototype.blur = function blur() {
    this.reset();
};
ScrollZoomHandler.prototype.reset = function reset() {
    this._active = false;
};

var DoubleClickZoomHandler = function DoubleClickZoomHandler(clickZoom, TapZoom) {
    this._clickZoom = clickZoom;
    this._tapZoom = TapZoom;
};
DoubleClickZoomHandler.prototype.enable = function enable() {
    this._clickZoom.enable();
    this._tapZoom.enable();
};
DoubleClickZoomHandler.prototype.disable = function disable() {
    this._clickZoom.disable();
    this._tapZoom.disable();
};
DoubleClickZoomHandler.prototype.isEnabled = function isEnabled() {
    return this._clickZoom.isEnabled() && this._tapZoom.isEnabled();
};
DoubleClickZoomHandler.prototype.isActive = function isActive() {
    return this._clickZoom.isActive() || this._tapZoom.isActive();
};

var ClickZoomHandler = function ClickZoomHandler() {
    this.reset();
};
ClickZoomHandler.prototype.reset = function reset() {
    this._active = false;
};
ClickZoomHandler.prototype.blur = function blur() {
    this.reset();
};
ClickZoomHandler.prototype.dblclick = function dblclick(e, point) {
    e.preventDefault();
    return {
        cameraAnimation: function (map) {
            map.easeTo({
                duration: 300,
                zoom: map.getZoom() + (e.shiftKey ? -1 : 1),
                around: map.unproject(point)
            }, { originalEvent: e });
        }
    };
};
ClickZoomHandler.prototype.enable = function enable() {
    this._enabled = true;
};
ClickZoomHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
ClickZoomHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
ClickZoomHandler.prototype.isActive = function isActive() {
    return this._active;
};

var TapDragZoomHandler = function TapDragZoomHandler() {
    this._tap = new TapRecognizer({
        numTouches: 1,
        numTaps: 1
    });
    this.reset();
};
TapDragZoomHandler.prototype.reset = function reset() {
    this._active = false;
    delete this._swipePoint;
    delete this._swipeTouch;
    delete this._tapTime;
    this._tap.reset();
};
TapDragZoomHandler.prototype.touchstart = function touchstart(e, points, mapTouches) {
    if (this._swipePoint) {
        return;
    }
    if (this._tapTime && e.timeStamp - this._tapTime > MAX_TAP_INTERVAL) {
        this.reset();
    }
    if (!this._tapTime) {
        this._tap.touchstart(e, points, mapTouches);
    } else if (mapTouches.length > 0) {
        this._swipePoint = points[0];
        this._swipeTouch = mapTouches[0].identifier;
    }
};
TapDragZoomHandler.prototype.touchmove = function touchmove(e, points, mapTouches) {
    if (!this._tapTime) {
        this._tap.touchmove(e, points, mapTouches);
    } else if (this._swipePoint) {
        if (mapTouches[0].identifier !== this._swipeTouch) {
            return;
        }
        var newSwipePoint = points[0];
        var dist = newSwipePoint.y - this._swipePoint.y;
        this._swipePoint = newSwipePoint;
        e.preventDefault();
        this._active = true;
        return { zoomDelta: dist / 128 };
    }
};
TapDragZoomHandler.prototype.touchend = function touchend(e, points, mapTouches) {
    if (!this._tapTime) {
        var point = this._tap.touchend(e, points, mapTouches);
        if (point) {
            this._tapTime = e.timeStamp;
        }
    } else if (this._swipePoint) {
        if (mapTouches.length === 0) {
            this.reset();
        }
    }
};
TapDragZoomHandler.prototype.touchcancel = function touchcancel() {
    this.reset();
};
TapDragZoomHandler.prototype.enable = function enable() {
    this._enabled = true;
};
TapDragZoomHandler.prototype.disable = function disable() {
    this._enabled = false;
    this.reset();
};
TapDragZoomHandler.prototype.isEnabled = function isEnabled() {
    return this._enabled;
};
TapDragZoomHandler.prototype.isActive = function isActive() {
    return this._active;
};

var DragPanHandler = function DragPanHandler(el, mousePan, touchPan) {
    this._el = el;
    this._mousePan = mousePan;
    this._touchPan = touchPan;
};
DragPanHandler.prototype.enable = function enable(options) {
    this._inertiaOptions = options || {};
    this._mousePan.enable();
    this._touchPan.enable();
    this._el.classList.add('mapboxgl-touch-drag-pan');
};
DragPanHandler.prototype.disable = function disable() {
    this._mousePan.disable();
    this._touchPan.disable();
    this._el.classList.remove('mapboxgl-touch-drag-pan');
};
DragPanHandler.prototype.isEnabled = function isEnabled() {
    return this._mousePan.isEnabled() && this._touchPan.isEnabled();
};
DragPanHandler.prototype.isActive = function isActive() {
    return this._mousePan.isActive() || this._touchPan.isActive();
};

var DragRotateHandler = function DragRotateHandler(options, mouseRotate, mousePitch) {
    this._pitchWithRotate = options.pitchWithRotate;
    this._mouseRotate = mouseRotate;
    this._mousePitch = mousePitch;
};
DragRotateHandler.prototype.enable = function enable() {
    this._mouseRotate.enable();
    if (this._pitchWithRotate) {
        this._mousePitch.enable();
    }
};
DragRotateHandler.prototype.disable = function disable() {
    this._mouseRotate.disable();
    this._mousePitch.disable();
};
DragRotateHandler.prototype.isEnabled = function isEnabled() {
    return this._mouseRotate.isEnabled() && (!this._pitchWithRotate || this._mousePitch.isEnabled());
};
DragRotateHandler.prototype.isActive = function isActive() {
    return this._mouseRotate.isActive() || this._mousePitch.isActive();
};

var TouchZoomRotateHandler = function TouchZoomRotateHandler(el, touchZoom, touchRotate, tapDragZoom) {
    this._el = el;
    this._touchZoom = touchZoom;
    this._touchRotate = touchRotate;
    this._tapDragZoom = tapDragZoom;
    this._rotationDisabled = false;
    this._enabled = true;
};
TouchZoomRotateHandler.prototype.enable = function enable(options) {
    this._touchZoom.enable(options);
    if (!this._rotationDisabled) {
        this._touchRotate.enable(options);
    }
    this._tapDragZoom.enable();
    this._el.classList.add('mapboxgl-touch-zoom-rotate');
};
TouchZoomRotateHandler.prototype.disable = function disable() {
    this._touchZoom.disable();
    this._touchRotate.disable();
    this._tapDragZoom.disable();
    this._el.classList.remove('mapboxgl-touch-zoom-rotate');
};
TouchZoomRotateHandler.prototype.isEnabled = function isEnabled() {
    return this._touchZoom.isEnabled() && (this._rotationDisabled || this._touchRotate.isEnabled()) && this._tapDragZoom.isEnabled();
};
TouchZoomRotateHandler.prototype.isActive = function isActive() {
    return this._touchZoom.isActive() || this._touchRotate.isActive() || this._tapDragZoom.isActive();
};
TouchZoomRotateHandler.prototype.disableRotation = function disableRotation() {
    this._rotationDisabled = true;
    this._touchRotate.disable();
};
TouchZoomRotateHandler.prototype.enableRotation = function enableRotation() {
    this._rotationDisabled = false;
    if (this._touchZoom.isEnabled()) {
        this._touchRotate.enable();
    }
};

var isMoving = function (p) {
    return p.zoom || p.drag || p.pitch || p.rotate;
};
var RenderFrameEvent = function (Event) {
    function RenderFrameEvent() {
        Event.apply(this, arguments);
    }
    if (Event)
        RenderFrameEvent.__proto__ = Event;
    RenderFrameEvent.prototype = Object.create(Event && Event.prototype);
    RenderFrameEvent.prototype.constructor = RenderFrameEvent;
    return RenderFrameEvent;
}(performance.Event);
function hasChange(result) {
    return result.panDelta && result.panDelta.mag() || result.zoomDelta || result.bearingDelta || result.pitchDelta;
}
var HandlerManager = function HandlerManager(map, options) {
    this._map = map;
    this._el = this._map.getCanvasContainer();
    this._handlers = [];
    this._handlersById = {};
    this._changes = [];
    this._inertia = new HandlerInertia(map);
    this._bearingSnap = options.bearingSnap;
    this._previousActiveHandlers = {};
    this._eventsInProgress = {};
    this._addDefaultHandlers(options);
    performance.bindAll([
        'handleEvent',
        'handleWindowEvent'
    ], this);
    var el = this._el;
    this._listeners = [
        [
            el,
            'touchstart',
            { passive: true }
        ],
        [
            el,
            'touchmove',
            { passive: false }
        ],
        [
            el,
            'touchend',
            undefined
        ],
        [
            el,
            'touchcancel',
            undefined
        ],
        [
            el,
            'mousedown',
            undefined
        ],
        [
            el,
            'mousemove',
            undefined
        ],
        [
            el,
            'mouseup',
            undefined
        ],
        [
            performance.window.document,
            'mousemove',
            { capture: true }
        ],
        [
            performance.window.document,
            'mouseup',
            undefined
        ],
        [
            el,
            'mouseover',
            undefined
        ],
        [
            el,
            'mouseout',
            undefined
        ],
        [
            el,
            'dblclick',
            undefined
        ],
        [
            el,
            'click',
            undefined
        ],
        [
            el,
            'keydown',
            { capture: false }
        ],
        [
            el,
            'keyup',
            undefined
        ],
        [
            el,
            'wheel',
            { passive: false }
        ],
        [
            el,
            'contextmenu',
            undefined
        ],
        [
            performance.window,
            'blur',
            undefined
        ]
    ];
    for (var i = 0, list = this._listeners; i < list.length; i += 1) {
        var ref = list[i];
        var target = ref[0];
        var type = ref[1];
        var listenerOptions = ref[2];
        DOM.addEventListener(target, type, target === performance.window.document ? this.handleWindowEvent : this.handleEvent, listenerOptions);
    }
};
HandlerManager.prototype.destroy = function destroy() {
    for (var i = 0, list = this._listeners; i < list.length; i += 1) {
        var ref = list[i];
        var target = ref[0];
        var type = ref[1];
        var listenerOptions = ref[2];
        DOM.removeEventListener(target, type, target === performance.window.document ? this.handleWindowEvent : this.handleEvent, listenerOptions);
    }
};
HandlerManager.prototype._addDefaultHandlers = function _addDefaultHandlers(options) {
    var map = this._map;
    var el = map.getCanvasContainer();
    this._add('mapEvent', new MapEventHandler(map, options));
    var boxZoom = map.boxZoom = new BoxZoomHandler(map, options);
    this._add('boxZoom', boxZoom);
    var tapZoom = new TapZoomHandler();
    var clickZoom = new ClickZoomHandler();
    map.doubleClickZoom = new DoubleClickZoomHandler(clickZoom, tapZoom);
    this._add('tapZoom', tapZoom);
    this._add('clickZoom', clickZoom);
    var tapDragZoom = new TapDragZoomHandler();
    this._add('tapDragZoom', tapDragZoom);
    var touchPitch = map.touchPitch = new TouchPitchHandler();
    this._add('touchPitch', touchPitch);
    var mouseRotate = new MouseRotateHandler(options);
    var mousePitch = new MousePitchHandler(options);
    map.dragRotate = new DragRotateHandler(options, mouseRotate, mousePitch);
    this._add('mouseRotate', mouseRotate, ['mousePitch']);
    this._add('mousePitch', mousePitch, ['mouseRotate']);
    var mousePan = new MousePanHandler(options);
    var touchPan = new TouchPanHandler(options);
    map.dragPan = new DragPanHandler(el, mousePan, touchPan);
    this._add('mousePan', mousePan);
    this._add('touchPan', touchPan, [
        'touchZoom',
        'touchRotate'
    ]);
    var touchRotate = new TouchRotateHandler();
    var touchZoom = new TouchZoomHandler();
    map.touchZoomRotate = new TouchZoomRotateHandler(el, touchZoom, touchRotate, tapDragZoom);
    this._add('touchRotate', touchRotate, [
        'touchPan',
        'touchZoom'
    ]);
    this._add('touchZoom', touchZoom, [
        'touchPan',
        'touchRotate'
    ]);
    var scrollZoom = map.scrollZoom = new ScrollZoomHandler(map, this);
    this._add('scrollZoom', scrollZoom, ['mousePan']);
    var keyboard = map.keyboard = new KeyboardHandler();
    this._add('keyboard', keyboard);
    this._add('blockableMapEvent', new BlockableMapEventHandler(map));
    for (var i = 0, list = [
                'boxZoom',
                'doubleClickZoom',
                'tapDragZoom',
                'touchPitch',
                'dragRotate',
                'dragPan',
                'touchZoomRotate',
                'scrollZoom',
                'keyboard'
            ]; i < list.length; i += 1) {
        var name = list[i];
        if (options.interactive && options[name]) {
            map[name].enable(options[name]);
        }
    }
};
HandlerManager.prototype._add = function _add(handlerName, handler, allowed) {
    this._handlers.push({
        handlerName: handlerName,
        handler: handler,
        allowed: allowed
    });
    this._handlersById[handlerName] = handler;
};
HandlerManager.prototype.stop = function stop(allowEndAnimation) {
    if (this._updatingCamera) {
        return;
    }
    for (var i = 0, list = this._handlers; i < list.length; i += 1) {
        var ref = list[i];
        var handler = ref.handler;
        handler.reset();
    }
    this._inertia.clear();
    this._fireEvents({}, {}, allowEndAnimation);
    this._changes = [];
};
HandlerManager.prototype.isActive = function isActive() {
    for (var i = 0, list = this._handlers; i < list.length; i += 1) {
        var ref = list[i];
        var handler = ref.handler;
        if (handler.isActive()) {
            return true;
        }
    }
    return false;
};
HandlerManager.prototype.isZooming = function isZooming() {
    return !!this._eventsInProgress.zoom || this._map.scrollZoom.isZooming();
};
HandlerManager.prototype.isRotating = function isRotating() {
    return !!this._eventsInProgress.rotate;
};
HandlerManager.prototype.isMoving = function isMoving$1() {
    return Boolean(isMoving(this._eventsInProgress)) || this.isZooming();
};
HandlerManager.prototype._blockedByActive = function _blockedByActive(activeHandlers, allowed, myName) {
    for (var name in activeHandlers) {
        if (name === myName) {
            continue;
        }
        if (!allowed || allowed.indexOf(name) < 0) {
            return true;
        }
    }
    return false;
};
HandlerManager.prototype.handleWindowEvent = function handleWindowEvent(e) {
    this.handleEvent(e, e.type + 'Window');
};
HandlerManager.prototype._getMapTouches = function _getMapTouches(touches) {
    var mapTouches = [];
    for (var i = 0, list = touches; i < list.length; i += 1) {
        var t = list[i];
        var target = t.target;
        if (this._el.contains(target)) {
            mapTouches.push(t);
        }
    }
    return mapTouches;
};
HandlerManager.prototype.handleEvent = function handleEvent(e, eventName) {
    this._updatingCamera = true;
    var inputEvent = e.type === 'renderFrame' ? undefined : e;
    var mergedHandlerResult = { needsRenderFrame: false };
    var eventsInProgress = {};
    var activeHandlers = {};
    var mapTouches = e.touches ? this._getMapTouches(e.touches) : undefined;
    var points = mapTouches ? DOM.touchPos(this._el, mapTouches) : DOM.mousePos(this._el, e);
    for (var i = 0, list = this._handlers; i < list.length; i += 1) {
        var ref = list[i];
        var handlerName = ref.handlerName;
        var handler = ref.handler;
        var allowed = ref.allowed;
        if (!handler.isEnabled()) {
            continue;
        }
        var data = void 0;
        if (this._blockedByActive(activeHandlers, allowed, handlerName)) {
            handler.reset();
        } else {
            if (handler[eventName || e.type]) {
                data = handler[eventName || e.type](e, points, mapTouches);
                this.mergeHandlerResult(mergedHandlerResult, eventsInProgress, data, handlerName, inputEvent);
                if (data && data.needsRenderFrame) {
                    this._triggerRenderFrame();
                }
            }
        }
        if (data || handler.isActive()) {
            activeHandlers[handlerName] = handler;
        }
    }
    var deactivatedHandlers = {};
    for (var name in this._previousActiveHandlers) {
        if (!activeHandlers[name]) {
            deactivatedHandlers[name] = inputEvent;
        }
    }
    this._previousActiveHandlers = activeHandlers;
    if (Object.keys(deactivatedHandlers).length || hasChange(mergedHandlerResult)) {
        this._changes.push([
            mergedHandlerResult,
            eventsInProgress,
            deactivatedHandlers
        ]);
        this._triggerRenderFrame();
    }
    if (Object.keys(activeHandlers).length || hasChange(mergedHandlerResult)) {
        this._map._stop(true);
    }
    this._updatingCamera = false;
    var cameraAnimation = mergedHandlerResult.cameraAnimation;
    if (cameraAnimation) {
        this._inertia.clear();
        this._fireEvents({}, {}, true);
        this._changes = [];
        cameraAnimation(this._map);
    }
};
HandlerManager.prototype.mergeHandlerResult = function mergeHandlerResult(mergedHandlerResult, eventsInProgress, handlerResult, name, e) {
    if (!handlerResult) {
        return;
    }
    performance.extend(mergedHandlerResult, handlerResult);
    var eventData = {
        handlerName: name,
        originalEvent: handlerResult.originalEvent || e
    };
    if (handlerResult.zoomDelta !== undefined) {
        eventsInProgress.zoom = eventData;
    }
    if (handlerResult.panDelta !== undefined) {
        eventsInProgress.drag = eventData;
    }
    if (handlerResult.pitchDelta !== undefined) {
        eventsInProgress.pitch = eventData;
    }
    if (handlerResult.bearingDelta !== undefined) {
        eventsInProgress.rotate = eventData;
    }
};
HandlerManager.prototype._applyChanges = function _applyChanges() {
    var combined = {};
    var combinedEventsInProgress = {};
    var combinedDeactivatedHandlers = {};
    for (var i = 0, list = this._changes; i < list.length; i += 1) {
        var ref = list[i];
        var change = ref[0];
        var eventsInProgress = ref[1];
        var deactivatedHandlers = ref[2];
        if (change.panDelta) {
            combined.panDelta = (combined.panDelta || new performance.Point(0, 0))._add(change.panDelta);
        }
        if (change.zoomDelta) {
            combined.zoomDelta = (combined.zoomDelta || 0) + change.zoomDelta;
        }
        if (change.bearingDelta) {
            combined.bearingDelta = (combined.bearingDelta || 0) + change.bearingDelta;
        }
        if (change.pitchDelta) {
            combined.pitchDelta = (combined.pitchDelta || 0) + change.pitchDelta;
        }
        if (change.around !== undefined) {
            combined.around = change.around;
        }
        if (change.pinchAround !== undefined) {
            combined.pinchAround = change.pinchAround;
        }
        if (change.noInertia) {
            combined.noInertia = change.noInertia;
        }
        performance.extend(combinedEventsInProgress, eventsInProgress);
        performance.extend(combinedDeactivatedHandlers, deactivatedHandlers);
    }
    this._updateMapTransform(combined, combinedEventsInProgress, combinedDeactivatedHandlers);
    this._changes = [];
};
HandlerManager.prototype._updateMapTransform = function _updateMapTransform(combinedResult, combinedEventsInProgress, deactivatedHandlers) {
    var map = this._map;
    var tr = map.transform;
    if (!hasChange(combinedResult)) {
        return this._fireEvents(combinedEventsInProgress, deactivatedHandlers, true);
    }
    var panDelta = combinedResult.panDelta;
    var zoomDelta = combinedResult.zoomDelta;
    var bearingDelta = combinedResult.bearingDelta;
    var pitchDelta = combinedResult.pitchDelta;
    var around = combinedResult.around;
    var pinchAround = combinedResult.pinchAround;
    if (pinchAround !== undefined) {
        around = pinchAround;
    }
    map._stop(true);
    around = around || map.transform.centerPoint;
    var loc = tr.pointLocation(panDelta ? around.sub(panDelta) : around);
    if (bearingDelta) {
        tr.bearing += bearingDelta;
    }
    if (pitchDelta) {
        tr.pitch += pitchDelta;
    }
    if (zoomDelta) {
        tr.zoom += zoomDelta;
    }
    tr.setLocationAtPoint(loc, around);
    this._map._update();
    if (!combinedResult.noInertia) {
        this._inertia.record(combinedResult);
    }
    this._fireEvents(combinedEventsInProgress, deactivatedHandlers, true);
};
HandlerManager.prototype._fireEvents = function _fireEvents(newEventsInProgress, deactivatedHandlers, allowEndAnimation) {
    var this$1 = this;
    var wasMoving = isMoving(this._eventsInProgress);
    var nowMoving = isMoving(newEventsInProgress);
    var startEvents = {};
    for (var eventName in newEventsInProgress) {
        var ref = newEventsInProgress[eventName];
        var originalEvent = ref.originalEvent;
        if (!this._eventsInProgress[eventName]) {
            startEvents[eventName + 'start'] = originalEvent;
        }
        this._eventsInProgress[eventName] = newEventsInProgress[eventName];
    }
    if (!wasMoving && nowMoving) {
        this._fireEvent('movestart', nowMoving.originalEvent);
    }
    for (var name in startEvents) {
        this._fireEvent(name, startEvents[name]);
    }
    if (nowMoving) {
        this._fireEvent('move', nowMoving.originalEvent);
    }
    for (var eventName$1 in newEventsInProgress) {
        var ref$1 = newEventsInProgress[eventName$1];
        var originalEvent$1 = ref$1.originalEvent;
        this._fireEvent(eventName$1, originalEvent$1);
    }
    var endEvents = {};
    var originalEndEvent;
    for (var eventName$2 in this._eventsInProgress) {
        var ref$2 = this._eventsInProgress[eventName$2];
        var handlerName = ref$2.handlerName;
        var originalEvent$2 = ref$2.originalEvent;
        if (!this._handlersById[handlerName].isActive()) {
            delete this._eventsInProgress[eventName$2];
            originalEndEvent = deactivatedHandlers[handlerName] || originalEvent$2;
            endEvents[eventName$2 + 'end'] = originalEndEvent;
        }
    }
    for (var name$1 in endEvents) {
        this._fireEvent(name$1, endEvents[name$1]);
    }
    var stillMoving = isMoving(this._eventsInProgress);
    if (allowEndAnimation && (wasMoving || nowMoving) && !stillMoving) {
        this._updatingCamera = true;
        var inertialEase = this._inertia._onMoveEnd(this._map.dragPan._inertiaOptions);
        var shouldSnapToNorth = function (bearing) {
            return bearing !== 0 && -this$1._bearingSnap < bearing && bearing < this$1._bearingSnap;
        };
        if (inertialEase) {
            if (shouldSnapToNorth(inertialEase.bearing || this._map.getBearing())) {
                inertialEase.bearing = 0;
            }
            this._map.easeTo(inertialEase, { originalEvent: originalEndEvent });
        } else {
            this._map.fire(new performance.Event('moveend', { originalEvent: originalEndEvent }));
            if (shouldSnapToNorth(this._map.getBearing())) {
                this._map.resetNorth();
            }
        }
        this._updatingCamera = false;
    }
};
HandlerManager.prototype._fireEvent = function _fireEvent(type, e) {
    this._map.fire(new performance.Event(type, e ? { originalEvent: e } : {}));
};
HandlerManager.prototype._requestFrame = function _requestFrame() {
    var this$1 = this;
    this._map.triggerRepaint();
    return this._map._renderTaskQueue.add(function (timeStamp) {
        delete this$1._frameId;
        this$1.handleEvent(new RenderFrameEvent('renderFrame', { timeStamp: timeStamp }));
        this$1._applyChanges();
    });
};
HandlerManager.prototype._triggerRenderFrame = function _triggerRenderFrame() {
    if (this._frameId === undefined) {
        this._frameId = this._requestFrame();
    }
};

var Camera = function (Evented) {
    function Camera(transform, options) {
        Evented.call(this);
        this._moving = false;
        this._zooming = false;
        this.transform = transform;
        this._bearingSnap = options.bearingSnap;
        performance.bindAll(['_renderFrameCallback'], this);
    }
    if (Evented)
        Camera.__proto__ = Evented;
    Camera.prototype = Object.create(Evented && Evented.prototype);
    Camera.prototype.constructor = Camera;
    Camera.prototype.getCenter = function getCenter() {
        return new performance.LngLat(this.transform.center.lng, this.transform.center.lat);
    };
    Camera.prototype.setCenter = function setCenter(center, eventData) {
        return this.jumpTo({ center: center }, eventData);
    };
    Camera.prototype.panBy = function panBy(offset, options, eventData) {
        offset = performance.Point.convert(offset).mult(-1);
        return this.panTo(this.transform.center, performance.extend({ offset: offset }, options), eventData);
    };
    Camera.prototype.panTo = function panTo(lnglat, options, eventData) {
        return this.easeTo(performance.extend({ center: lnglat }, options), eventData);
    };
    Camera.prototype.getZoom = function getZoom() {
        return this.transform.zoom;
    };
    Camera.prototype.setZoom = function setZoom(zoom, eventData) {
        this.jumpTo({ zoom: zoom }, eventData);
        return this;
    };
    Camera.prototype.zoomTo = function zoomTo(zoom, options, eventData) {
        return this.easeTo(performance.extend({ zoom: zoom }, options), eventData);
    };
    Camera.prototype.zoomIn = function zoomIn(options, eventData) {
        this.zoomTo(this.getZoom() + 1, options, eventData);
        return this;
    };
    Camera.prototype.zoomOut = function zoomOut(options, eventData) {
        this.zoomTo(this.getZoom() - 1, options, eventData);
        return this;
    };
    Camera.prototype.getBearing = function getBearing() {
        return this.transform.bearing;
    };
    Camera.prototype.setBearing = function setBearing(bearing, eventData) {
        this.jumpTo({ bearing: bearing }, eventData);
        return this;
    };
    Camera.prototype.getPadding = function getPadding() {
        return this.transform.padding;
    };
    Camera.prototype.setPadding = function setPadding(padding, eventData) {
        this.jumpTo({ padding: padding }, eventData);
        return this;
    };
    Camera.prototype.rotateTo = function rotateTo(bearing, options, eventData) {
        return this.easeTo(performance.extend({ bearing: bearing }, options), eventData);
    };
    Camera.prototype.resetNorth = function resetNorth(options, eventData) {
        this.rotateTo(0, performance.extend({ duration: 1000 }, options), eventData);
        return this;
    };
    Camera.prototype.resetNorthPitch = function resetNorthPitch(options, eventData) {
        this.easeTo(performance.extend({
            bearing: 0,
            pitch: 0,
            duration: 1000
        }, options), eventData);
        return this;
    };
    Camera.prototype.snapToNorth = function snapToNorth(options, eventData) {
        if (Math.abs(this.getBearing()) < this._bearingSnap) {
            return this.resetNorth(options, eventData);
        }
        return this;
    };
    Camera.prototype.getPitch = function getPitch() {
        return this.transform.pitch;
    };
    Camera.prototype.setPitch = function setPitch(pitch, eventData) {
        this.jumpTo({ pitch: pitch }, eventData);
        return this;
    };
    Camera.prototype.cameraForBounds = function cameraForBounds(bounds, options) {
        bounds = performance.LngLatBounds.convert(bounds);
        var bearing = options && options.bearing || 0;
        return this._cameraForBoxAndBearing(bounds.getNorthWest(), bounds.getSouthEast(), bearing, options);
    };
    Camera.prototype._cameraForBoxAndBearing = function _cameraForBoxAndBearing(p0, p1, bearing, options) {
        var defaultPadding = {
            top: 0,
            bottom: 0,
            right: 0,
            left: 0
        };
        options = performance.extend({
            padding: defaultPadding,
            offset: [
                0,
                0
            ],
            maxZoom: this.transform.maxZoom
        }, options);
        if (typeof options.padding === 'number') {
            var p = options.padding;
            options.padding = {
                top: p,
                bottom: p,
                right: p,
                left: p
            };
        }
        options.padding = performance.extend(defaultPadding, options.padding);
        var tr = this.transform;
        var edgePadding = tr.padding;
        var p0world = tr.project(performance.LngLat.convert(p0));
        var p1world = tr.project(performance.LngLat.convert(p1));
        var p0rotated = p0world.rotate(-bearing * Math.PI / 180);
        var p1rotated = p1world.rotate(-bearing * Math.PI / 180);
        var upperRight = new performance.Point(Math.max(p0rotated.x, p1rotated.x), Math.max(p0rotated.y, p1rotated.y));
        var lowerLeft = new performance.Point(Math.min(p0rotated.x, p1rotated.x), Math.min(p0rotated.y, p1rotated.y));
        var size = upperRight.sub(lowerLeft);
        var scaleX = (tr.width - (edgePadding.left + edgePadding.right + options.padding.left + options.padding.right)) / size.x;
        var scaleY = (tr.height - (edgePadding.top + edgePadding.bottom + options.padding.top + options.padding.bottom)) / size.y;
        if (scaleY < 0 || scaleX < 0) {
            performance.warnOnce('Map cannot fit within canvas with the given bounds, padding, and/or offset.');
            return;
        }
        var zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);
        var offset = typeof options.offset.x === 'number' ? new performance.Point(options.offset.x, options.offset.y) : performance.Point.convert(options.offset);
        var paddingOffsetX = (options.padding.left - options.padding.right) / 2;
        var paddingOffsetY = (options.padding.top - options.padding.bottom) / 2;
        var paddingOffset = new performance.Point(paddingOffsetX, paddingOffsetY);
        var rotatedPaddingOffset = paddingOffset.rotate(bearing * Math.PI / 180);
        var offsetAtInitialZoom = offset.add(rotatedPaddingOffset);
        var offsetAtFinalZoom = offsetAtInitialZoom.mult(tr.scale / tr.zoomScale(zoom));
        var center = tr.unproject(p0world.add(p1world).div(2).sub(offsetAtFinalZoom));
        return {
            center: center,
            zoom: zoom,
            bearing: bearing
        };
    };
    Camera.prototype.fitBounds = function fitBounds(bounds, options, eventData) {
        return this._fitInternal(this.cameraForBounds(bounds, options), options, eventData);
    };
    Camera.prototype.fitScreenCoordinates = function fitScreenCoordinates(p0, p1, bearing, options, eventData) {
        return this._fitInternal(this._cameraForBoxAndBearing(this.transform.pointLocation(performance.Point.convert(p0)), this.transform.pointLocation(performance.Point.convert(p1)), bearing, options), options, eventData);
    };
    Camera.prototype._fitInternal = function _fitInternal(calculatedOptions, options, eventData) {
        if (!calculatedOptions) {
            return this;
        }
        options = performance.extend(calculatedOptions, options);
        delete options.padding;
        return options.linear ? this.easeTo(options, eventData) : this.flyTo(options, eventData);
    };
    Camera.prototype.jumpTo = function jumpTo(options, eventData) {
        this.stop();
        var tr = this.transform;
        var zoomChanged = false, bearingChanged = false, pitchChanged = false;
        if ('zoom' in options && tr.zoom !== +options.zoom) {
            zoomChanged = true;
            tr.zoom = +options.zoom;
        }
        if (options.center !== undefined) {
            tr.center = performance.LngLat.convert(options.center);
        }
        if ('bearing' in options && tr.bearing !== +options.bearing) {
            bearingChanged = true;
            tr.bearing = +options.bearing;
        }
        if ('pitch' in options && tr.pitch !== +options.pitch) {
            pitchChanged = true;
            tr.pitch = +options.pitch;
        }
        if (options.padding != null && !tr.isPaddingEqual(options.padding)) {
            tr.padding = options.padding;
        }
        this.fire(new performance.Event('movestart', eventData)).fire(new performance.Event('move', eventData));
        if (zoomChanged) {
            this.fire(new performance.Event('zoomstart', eventData)).fire(new performance.Event('zoom', eventData)).fire(new performance.Event('zoomend', eventData));
        }
        if (bearingChanged) {
            this.fire(new performance.Event('rotatestart', eventData)).fire(new performance.Event('rotate', eventData)).fire(new performance.Event('rotateend', eventData));
        }
        if (pitchChanged) {
            this.fire(new performance.Event('pitchstart', eventData)).fire(new performance.Event('pitch', eventData)).fire(new performance.Event('pitchend', eventData));
        }
        return this.fire(new performance.Event('moveend', eventData));
    };
    Camera.prototype.easeTo = function easeTo(options, eventData) {
        var this$1 = this;
        this._stop(false, options.easeId);
        options = performance.extend({
            offset: [
                0,
                0
            ],
            duration: 500,
            easing: performance.ease
        }, options);
        if (options.animate === false || !options.essential && performance.browser.prefersReducedMotion) {
            options.duration = 0;
        }
        var tr = this.transform, startZoom = this.getZoom(), startBearing = this.getBearing(), startPitch = this.getPitch(), startPadding = this.getPadding(), zoom = 'zoom' in options ? +options.zoom : startZoom, bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing, pitch = 'pitch' in options ? +options.pitch : startPitch, padding = 'padding' in options ? options.padding : tr.padding;
        var offsetAsPoint = performance.Point.convert(options.offset);
        var pointAtOffset = tr.centerPoint.add(offsetAsPoint);
        var locationAtOffset = tr.pointLocation(pointAtOffset);
        var center = performance.LngLat.convert(options.center || locationAtOffset);
        this._normalizeCenter(center);
        var from = tr.project(locationAtOffset);
        var delta = tr.project(center).sub(from);
        var finalScale = tr.zoomScale(zoom - startZoom);
        var around, aroundPoint;
        if (options.around) {
            around = performance.LngLat.convert(options.around);
            aroundPoint = tr.locationPoint(around);
        }
        var currently = {
            moving: this._moving,
            zooming: this._zooming,
            rotating: this._rotating,
            pitching: this._pitching
        };
        this._zooming = this._zooming || zoom !== startZoom;
        this._rotating = this._rotating || startBearing !== bearing;
        this._pitching = this._pitching || pitch !== startPitch;
        this._padding = !tr.isPaddingEqual(padding);
        this._easeId = options.easeId;
        this._prepareEase(eventData, options.noMoveStart, currently);
        this._ease(function (k) {
            if (this$1._zooming) {
                tr.zoom = performance.number(startZoom, zoom, k);
            }
            if (this$1._rotating) {
                tr.bearing = performance.number(startBearing, bearing, k);
            }
            if (this$1._pitching) {
                tr.pitch = performance.number(startPitch, pitch, k);
            }
            if (this$1._padding) {
                tr.interpolatePadding(startPadding, padding, k);
                pointAtOffset = tr.centerPoint.add(offsetAsPoint);
            }
            if (around) {
                tr.setLocationAtPoint(around, aroundPoint);
            } else {
                var scale = tr.zoomScale(tr.zoom - startZoom);
                var base = zoom > startZoom ? Math.min(2, finalScale) : Math.max(0.5, finalScale);
                var speedup = Math.pow(base, 1 - k);
                var newCenter = tr.unproject(from.add(delta.mult(k * speedup)).mult(scale));
                tr.setLocationAtPoint(tr.renderWorldCopies ? newCenter.wrap() : newCenter, pointAtOffset);
            }
            this$1._fireMoveEvents(eventData);
        }, function (interruptingEaseId) {
            this$1._afterEase(eventData, interruptingEaseId);
        }, options);
        return this;
    };
    Camera.prototype._prepareEase = function _prepareEase(eventData, noMoveStart, currently) {
        if (currently === void 0)
            currently = {};
        this._moving = true;
        if (!noMoveStart && !currently.moving) {
            this.fire(new performance.Event('movestart', eventData));
        }
        if (this._zooming && !currently.zooming) {
            this.fire(new performance.Event('zoomstart', eventData));
        }
        if (this._rotating && !currently.rotating) {
            this.fire(new performance.Event('rotatestart', eventData));
        }
        if (this._pitching && !currently.pitching) {
            this.fire(new performance.Event('pitchstart', eventData));
        }
    };
    Camera.prototype._fireMoveEvents = function _fireMoveEvents(eventData) {
        this.fire(new performance.Event('move', eventData));
        if (this._zooming) {
            this.fire(new performance.Event('zoom', eventData));
        }
        if (this._rotating) {
            this.fire(new performance.Event('rotate', eventData));
        }
        if (this._pitching) {
            this.fire(new performance.Event('pitch', eventData));
        }
    };
    Camera.prototype._afterEase = function _afterEase(eventData, easeId) {
        if (this._easeId && easeId && this._easeId === easeId) {
            return;
        }
        delete this._easeId;
        var wasZooming = this._zooming;
        var wasRotating = this._rotating;
        var wasPitching = this._pitching;
        this._moving = false;
        this._zooming = false;
        this._rotating = false;
        this._pitching = false;
        this._padding = false;
        if (wasZooming) {
            this.fire(new performance.Event('zoomend', eventData));
        }
        if (wasRotating) {
            this.fire(new performance.Event('rotateend', eventData));
        }
        if (wasPitching) {
            this.fire(new performance.Event('pitchend', eventData));
        }
        this.fire(new performance.Event('moveend', eventData));
    };
    Camera.prototype.flyTo = function flyTo(options, eventData) {
        var this$1 = this;
        if (!options.essential && performance.browser.prefersReducedMotion) {
            var coercedOptions = performance.pick(options, [
                'center',
                'zoom',
                'bearing',
                'pitch',
                'around'
            ]);
            return this.jumpTo(coercedOptions, eventData);
        }
        this.stop();
        options = performance.extend({
            offset: [
                0,
                0
            ],
            speed: 1.2,
            curve: 1.42,
            easing: performance.ease
        }, options);
        var tr = this.transform, startZoom = this.getZoom(), startBearing = this.getBearing(), startPitch = this.getPitch(), startPadding = this.getPadding();
        var zoom = 'zoom' in options ? performance.clamp(+options.zoom, tr.minZoom, tr.maxZoom) : startZoom;
        var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing;
        var pitch = 'pitch' in options ? +options.pitch : startPitch;
        var padding = 'padding' in options ? options.padding : tr.padding;
        var scale = tr.zoomScale(zoom - startZoom);
        var offsetAsPoint = performance.Point.convert(options.offset);
        var pointAtOffset = tr.centerPoint.add(offsetAsPoint);
        var locationAtOffset = tr.pointLocation(pointAtOffset);
        var center = performance.LngLat.convert(options.center || locationAtOffset);
        this._normalizeCenter(center);
        var from = tr.project(locationAtOffset);
        var delta = tr.project(center).sub(from);
        var rho = options.curve;
        var w0 = Math.max(tr.width, tr.height), w1 = w0 / scale, u1 = delta.mag();
        if ('minZoom' in options) {
            var minZoom = performance.clamp(Math.min(options.minZoom, startZoom, zoom), tr.minZoom, tr.maxZoom);
            var wMax = w0 / tr.zoomScale(minZoom - startZoom);
            rho = Math.sqrt(wMax / u1 * 2);
        }
        var rho2 = rho * rho;
        function r(i) {
            var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);
            return Math.log(Math.sqrt(b * b + 1) - b);
        }
        function sinh(n) {
            return (Math.exp(n) - Math.exp(-n)) / 2;
        }
        function cosh(n) {
            return (Math.exp(n) + Math.exp(-n)) / 2;
        }
        function tanh(n) {
            return sinh(n) / cosh(n);
        }
        var r0 = r(0);
        var w = function (s) {
            return cosh(r0) / cosh(r0 + rho * s);
        };
        var u = function (s) {
            return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1;
        };
        var S = (r(1) - r0) / rho;
        if (Math.abs(u1) < 0.000001 || !isFinite(S)) {
            if (Math.abs(w0 - w1) < 0.000001) {
                return this.easeTo(options, eventData);
            }
            var k = w1 < w0 ? -1 : 1;
            S = Math.abs(Math.log(w1 / w0)) / rho;
            u = function () {
                return 0;
            };
            w = function (s) {
                return Math.exp(k * rho * s);
            };
        }
        if ('duration' in options) {
            options.duration = +options.duration;
        } else {
            var V = 'screenSpeed' in options ? +options.screenSpeed / rho : +options.speed;
            options.duration = 1000 * S / V;
        }
        if (options.maxDuration && options.duration > options.maxDuration) {
            options.duration = 0;
        }
        this._zooming = true;
        this._rotating = startBearing !== bearing;
        this._pitching = pitch !== startPitch;
        this._padding = !tr.isPaddingEqual(padding);
        this._prepareEase(eventData, false);
        this._ease(function (k) {
            var s = k * S;
            var scale = 1 / w(s);
            tr.zoom = k === 1 ? zoom : startZoom + tr.scaleZoom(scale);
            if (this$1._rotating) {
                tr.bearing = performance.number(startBearing, bearing, k);
            }
            if (this$1._pitching) {
                tr.pitch = performance.number(startPitch, pitch, k);
            }
            if (this$1._padding) {
                tr.interpolatePadding(startPadding, padding, k);
                pointAtOffset = tr.centerPoint.add(offsetAsPoint);
            }
            var newCenter = k === 1 ? center : tr.unproject(from.add(delta.mult(u(s))).mult(scale));
            tr.setLocationAtPoint(tr.renderWorldCopies ? newCenter.wrap() : newCenter, pointAtOffset);
            this$1._fireMoveEvents(eventData);
        }, function () {
            return this$1._afterEase(eventData);
        }, options);
        return this;
    };
    Camera.prototype.isEasing = function isEasing() {
        return !!this._easeFrameId;
    };
    Camera.prototype.stop = function stop() {
        return this._stop();
    };
    Camera.prototype._stop = function _stop(allowGestures, easeId) {
        if (this._easeFrameId) {
            this._cancelRenderFrame(this._easeFrameId);
            delete this._easeFrameId;
            delete this._onEaseFrame;
        }
        if (this._onEaseEnd) {
            var onEaseEnd = this._onEaseEnd;
            delete this._onEaseEnd;
            onEaseEnd.call(this, easeId);
        }
        if (!allowGestures) {
            var handlers = this.handlers;
            if (handlers) {
                handlers.stop(false);
            }
        }
        return this;
    };
    Camera.prototype._ease = function _ease(frame, finish, options) {
        if (options.animate === false || options.duration === 0) {
            frame(1);
            finish();
        } else {
            this._easeStart = performance.browser.now();
            this._easeOptions = options;
            this._onEaseFrame = frame;
            this._onEaseEnd = finish;
            this._easeFrameId = this._requestRenderFrame(this._renderFrameCallback);
        }
    };
    Camera.prototype._renderFrameCallback = function _renderFrameCallback() {
        var t = Math.min((performance.browser.now() - this._easeStart) / this._easeOptions.duration, 1);
        this._onEaseFrame(this._easeOptions.easing(t));
        if (t < 1) {
            this._easeFrameId = this._requestRenderFrame(this._renderFrameCallback);
        } else {
            this.stop();
        }
    };
    Camera.prototype._normalizeBearing = function _normalizeBearing(bearing, currentBearing) {
        bearing = performance.wrap(bearing, -180, 180);
        var diff = Math.abs(bearing - currentBearing);
        if (Math.abs(bearing - 360 - currentBearing) < diff) {
            bearing -= 360;
        }
        if (Math.abs(bearing + 360 - currentBearing) < diff) {
            bearing += 360;
        }
        return bearing;
    };
    Camera.prototype._normalizeCenter = function _normalizeCenter(center) {
        var tr = this.transform;
        if (!tr.renderWorldCopies || tr.lngRange) {
            return;
        }
        var delta = center.lng - tr.center.lng;
        center.lng += delta > 180 ? -360 : delta < -180 ? 360 : 0;
    };
    return Camera;
}(performance.Evented);

var AttributionControl = function AttributionControl(options) {
    if (options === void 0)
        options = {};
    this.options = options;
    performance.bindAll([
        '_toggleAttribution',
        '_updateEditLink',
        '_updateData',
        '_updateCompact'
    ], this);
};
AttributionControl.prototype.getDefaultPosition = function getDefaultPosition() {
    return 'bottom-right';
};
AttributionControl.prototype.onAdd = function onAdd(map) {
    var compact = this.options && this.options.compact;
    this._map = map;
    this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-attrib');
    this._compactButton = DOM.create('button', 'mapboxgl-ctrl-attrib-button', this._container);
    this._compactButton.addEventListener('click', this._toggleAttribution);
    this._setElementTitle(this._compactButton, 'ToggleAttribution');
    this._innerContainer = DOM.create('div', 'mapboxgl-ctrl-attrib-inner', this._container);
    this._innerContainer.setAttribute('role', 'list');
    if (compact) {
        this._container.classList.add('mapboxgl-compact');
    }
    this._updateAttributions();
    this._updateEditLink();
    this._map.on('styledata', this._updateData);
    this._map.on('sourcedata', this._updateData);
    this._map.on('moveend', this._updateEditLink);
    if (compact === undefined) {
        this._map.on('resize', this._updateCompact);
        this._updateCompact();
    }
    return this._container;
};
AttributionControl.prototype.onRemove = function onRemove() {
    DOM.remove(this._container);
    this._map.off('styledata', this._updateData);
    this._map.off('sourcedata', this._updateData);
    this._map.off('moveend', this._updateEditLink);
    this._map.off('resize', this._updateCompact);
    this._map = undefined;
    this._attribHTML = undefined;
};
AttributionControl.prototype._setElementTitle = function _setElementTitle(element, title) {
    var str = this._map._getUIString('AttributionControl.' + title);
    element.title = str;
    element.setAttribute('aria-label', str);
};
AttributionControl.prototype._toggleAttribution = function _toggleAttribution() {
    if (this._container.classList.contains('mapboxgl-compact-show')) {
        this._container.classList.remove('mapboxgl-compact-show');
        this._compactButton.setAttribute('aria-pressed', 'false');
    } else {
        this._container.classList.add('mapboxgl-compact-show');
        this._compactButton.setAttribute('aria-pressed', 'true');
    }
};
AttributionControl.prototype._updateEditLink = function _updateEditLink() {
    var editLink = this._editLink;
    if (!editLink) {
        editLink = this._editLink = this._container.querySelector('.mapbox-improve-map');
    }
    var params = [
        {
            key: 'owner',
            value: this.styleOwner
        },
        {
            key: 'id',
            value: this.styleId
        },
        {
            key: 'access_token',
            value: this._map._requestManager._customAccessToken || performance.config.ACCESS_TOKEN
        }
    ];
    if (editLink) {
        var paramString = params.reduce(function (acc, next, i) {
            if (next.value) {
                acc += next.key + '=' + next.value + (i < params.length - 1 ? '&' : '');
            }
            return acc;
        }, '?');
        editLink.href = performance.config.FEEDBACK_URL + '/' + paramString + (this._map._hash ? this._map._hash.getHashString(true) : '');
        editLink.rel = 'noopener nofollow';
        this._setElementTitle(editLink, 'MapFeedback');
    }
};
AttributionControl.prototype._updateData = function _updateData(e) {
    if (e && (e.sourceDataType === 'metadata' || e.sourceDataType === 'visibility' || e.dataType === 'style')) {
        this._updateAttributions();
        this._updateEditLink();
    }
};
AttributionControl.prototype._updateAttributions = function _updateAttributions() {
    if (!this._map.style) {
        return;
    }
    var attributions = [];
    if (this.options.customAttribution) {
        if (Array.isArray(this.options.customAttribution)) {
            attributions = attributions.concat(this.options.customAttribution.map(function (attribution) {
                if (typeof attribution !== 'string') {
                    return '';
                }
                return attribution;
            }));
        } else if (typeof this.options.customAttribution === 'string') {
            attributions.push(this.options.customAttribution);
        }
    }
    if (this._map.style.stylesheet) {
        var stylesheet = this._map.style.stylesheet;
        this.styleOwner = stylesheet.owner;
        this.styleId = stylesheet.id;
    }
    var sourceCaches = this._map.style.sourceCaches;
    for (var id in sourceCaches) {
        var sourceCache = sourceCaches[id];
        if (sourceCache.used) {
            var source = sourceCache.getSource();
            if (source.attribution && attributions.indexOf(source.attribution) < 0) {
                attributions.push(source.attribution);
            }
        }
    }
    attributions.sort(function (a, b) {
        return a.length - b.length;
    });
    attributions = attributions.filter(function (attrib, i) {
        for (var j = i + 1; j < attributions.length; j++) {
            if (attributions[j].indexOf(attrib) >= 0) {
                return false;
            }
        }
        return true;
    });
    var attribHTML = attributions.join(' | ');
    if (attribHTML === this._attribHTML) {
        return;
    }
    this._attribHTML = attribHTML;
    if (attributions.length) {
        this._innerContainer.innerHTML = attribHTML;
        this._container.classList.remove('mapboxgl-attrib-empty');
    } else {
        this._container.classList.add('mapboxgl-attrib-empty');
    }
    this._editLink = null;
};
AttributionControl.prototype._updateCompact = function _updateCompact() {
    if (this._map.getCanvasContainer().offsetWidth <= 640) {
        this._container.classList.add('mapboxgl-compact');
    } else {
        this._container.classList.remove('mapboxgl-compact', 'mapboxgl-compact-show');
    }
};

var LogoControl = function LogoControl() {
    performance.bindAll(['_updateLogo'], this);
    performance.bindAll(['_updateCompact'], this);
};
LogoControl.prototype.onAdd = function onAdd(map) {
    this._map = map;
    this._container = DOM.create('div', 'mapboxgl-ctrl');
    var anchor = DOM.create('a', 'mapboxgl-ctrl-logo');
    anchor.target = '_blank';
    anchor.rel = 'noopener nofollow';
    anchor.href = 'https://www.mapbox.com/';
    anchor.setAttribute('aria-label', this._map._getUIString('LogoControl.Title'));
    anchor.setAttribute('rel', 'noopener nofollow');
    this._container.appendChild(anchor);
    this._container.style.display = 'none';
    this._map.on('sourcedata', this._updateLogo);
    this._updateLogo();
    this._map.on('resize', this._updateCompact);
    this._updateCompact();
    return this._container;
};
LogoControl.prototype.onRemove = function onRemove() {
    DOM.remove(this._container);
    this._map.off('sourcedata', this._updateLogo);
    this._map.off('resize', this._updateCompact);
};
LogoControl.prototype.getDefaultPosition = function getDefaultPosition() {
    return 'bottom-left';
};
LogoControl.prototype._updateLogo = function _updateLogo(e) {
    if (!e || e.sourceDataType === 'metadata') {
        this._container.style.display = this._logoRequired() ? 'block' : 'none';
    }
};
LogoControl.prototype._logoRequired = function _logoRequired() {
    if (!this._map.style) {
        return;
    }
    var sourceCaches = this._map.style.sourceCaches;
    for (var id in sourceCaches) {
        var source = sourceCaches[id].getSource();
        if (source.mapbox_logo) {
            return true;
        }
    }
    return false;
};
LogoControl.prototype._updateCompact = function _updateCompact() {
    var containerChildren = this._container.children;
    if (containerChildren.length) {
        var anchor = containerChildren[0];
        if (this._map.getCanvasContainer().offsetWidth < 250) {
            anchor.classList.add('mapboxgl-compact');
        } else {
            anchor.classList.remove('mapboxgl-compact');
        }
    }
};

var TaskQueue = function TaskQueue() {
    this._queue = [];
    this._id = 0;
    this._cleared = false;
    this._currentlyRunning = false;
};
TaskQueue.prototype.add = function add(callback) {
    var id = ++this._id;
    var queue = this._queue;
    queue.push({
        callback: callback,
        id: id,
        cancelled: false
    });
    return id;
};
TaskQueue.prototype.remove = function remove(id) {
    var running = this._currentlyRunning;
    var queue = running ? this._queue.concat(running) : this._queue;
    for (var i = 0, list = queue; i < list.length; i += 1) {
        var task = list[i];
        if (task.id === id) {
            task.cancelled = true;
            return;
        }
    }
};
TaskQueue.prototype.run = function run(timeStamp) {
    if (timeStamp === void 0)
        timeStamp = 0;
    var queue = this._currentlyRunning = this._queue;
    this._queue = [];
    for (var i = 0, list = queue; i < list.length; i += 1) {
        var task = list[i];
        if (task.cancelled) {
            continue;
        }
        task.callback(timeStamp);
        if (this._cleared) {
            break;
        }
    }
    this._cleared = false;
    this._currentlyRunning = false;
};
TaskQueue.prototype.clear = function clear() {
    if (this._currentlyRunning) {
        this._cleared = true;
    }
    this._queue = [];
};

var defaultLocale = {
    'AttributionControl.ToggleAttribution': 'Toggle attribution',
    'AttributionControl.MapFeedback': 'Map feedback',
    'FullscreenControl.Enter': 'Enter fullscreen',
    'FullscreenControl.Exit': 'Exit fullscreen',
    'GeolocateControl.FindMyLocation': 'Find my location',
    'GeolocateControl.LocationNotAvailable': 'Location not available',
    'LogoControl.Title': 'Mapbox logo',
    'NavigationControl.ResetBearing': 'Reset bearing to north',
    'NavigationControl.ZoomIn': 'Zoom in',
    'NavigationControl.ZoomOut': 'Zoom out',
    'ScaleControl.Feet': 'ft',
    'ScaleControl.Meters': 'm',
    'ScaleControl.Kilometers': 'km',
    'ScaleControl.Miles': 'mi',
    'ScaleControl.NauticalMiles': 'nm'
};

var HTMLImageElement = performance.window.HTMLImageElement;
var HTMLElement = performance.window.HTMLElement;
var ImageBitmap = performance.window.ImageBitmap;
var defaultMinZoom = -2;
var defaultMaxZoom = 22;
var defaultMinPitch = 0;
var defaultMaxPitch = 60;
var defaultOptions$1 = {
    center: [
        0,
        0
    ],
    zoom: 0,
    bearing: 0,
    pitch: 0,
    minZoom: defaultMinZoom,
    maxZoom: defaultMaxZoom,
    minPitch: defaultMinPitch,
    maxPitch: defaultMaxPitch,
    interactive: true,
    scrollZoom: true,
    boxZoom: true,
    dragRotate: true,
    dragPan: true,
    keyboard: true,
    doubleClickZoom: true,
    touchZoomRotate: true,
    touchPitch: true,
    bearingSnap: 7,
    clickTolerance: 3,
    pitchWithRotate: true,
    hash: false,
    attributionControl: true,
    failIfMajorPerformanceCaveat: false,
    preserveDrawingBuffer: false,
    trackResize: true,
    renderWorldCopies: true,
    refreshExpiredTiles: true,
    maxTileCacheSize: null,
    localIdeographFontFamily: 'sans-serif',
    transformRequest: null,
    accessToken: null,
    fadeDuration: 300,
    crossSourceCollisions: true
};
var Map = function (Camera) {
    function Map(options) {
        var this$1 = this;
        options = performance.extend({}, defaultOptions$1, options);
        if (options.minZoom != null && options.maxZoom != null && options.minZoom > options.maxZoom) {
            throw new Error('maxZoom must be greater than or equal to minZoom');
        }
        if (options.minPitch != null && options.maxPitch != null && options.minPitch > options.maxPitch) {
            throw new Error('maxPitch must be greater than or equal to minPitch');
        }
        if (options.minPitch != null && options.minPitch < defaultMinPitch) {
            throw new Error('minPitch must be greater than or equal to ' + defaultMinPitch);
        }
        if (options.maxPitch != null && options.maxPitch > defaultMaxPitch) {
            throw new Error('maxPitch must be less than or equal to ' + defaultMaxPitch);
        }
        var transform = new Transform(options.minZoom, options.maxZoom, options.minPitch, options.maxPitch, options.renderWorldCopies);
        Camera.call(this, transform, options);
        this._interactive = options.interactive;
        this._maxTileCacheSize = options.maxTileCacheSize;
        this._failIfMajorPerformanceCaveat = options.failIfMajorPerformanceCaveat;
        this._preserveDrawingBuffer = options.preserveDrawingBuffer;
        this._antialias = options.antialias;
        this._trackResize = options.trackResize;
        this._bearingSnap = options.bearingSnap;
        this._refreshExpiredTiles = options.refreshExpiredTiles;
        this._fadeDuration = options.fadeDuration;
        this._crossSourceCollisions = options.crossSourceCollisions;
        this._crossFadingFactor = 1;
        this._collectResourceTiming = options.collectResourceTiming;
        this._renderTaskQueue = new TaskQueue();
        this._controls = [];
        this._mapId = performance.uniqueId();
        this._locale = performance.extend({}, defaultLocale, options.locale);
        this._clickTolerance = options.clickTolerance;
        this._requestManager = new performance.RequestManager(options.transformRequest, options.accessToken);
        if (typeof options.container === 'string') {
            this._container = performance.window.document.getElementById(options.container);
            if (!this._container) {
                throw new Error('Container \'' + options.container + '\' not found.');
            }
        } else if (options.container instanceof HTMLElement) {
            this._container = options.container;
        } else {
            throw new Error('Invalid type: \'container\' must be a String or HTMLElement.');
        }
        if (options.maxBounds) {
            this.setMaxBounds(options.maxBounds);
        }
        performance.bindAll([
            '_onWindowOnline',
            '_onWindowResize',
            '_onMapScroll',
            '_contextLost',
            '_contextRestored'
        ], this);
        this._setupContainer();
        this._setupPainter();
        if (this.painter === undefined) {
            throw new Error('Failed to initialize WebGL.');
        }
        this.on('move', function () {
            return this$1._update(false);
        });
        this.on('moveend', function () {
            return this$1._update(false);
        });
        this.on('zoom', function () {
            return this$1._update(true);
        });
        if (typeof performance.window !== 'undefined') {
            performance.window.addEventListener('online', this._onWindowOnline, false);
            performance.window.addEventListener('resize', this._onWindowResize, false);
            performance.window.addEventListener('orientationchange', this._onWindowResize, false);
        }
        this.handlers = new HandlerManager(this, options);
        var hashName = typeof options.hash === 'string' && options.hash || undefined;
        this._hash = options.hash && new Hash(hashName).addTo(this);
        if (!this._hash || !this._hash._onHashChange()) {
            this.jumpTo({
                center: options.center,
                zoom: options.zoom,
                bearing: options.bearing,
                pitch: options.pitch
            });
            if (options.bounds) {
                this.resize();
                this.fitBounds(options.bounds, performance.extend({}, options.fitBoundsOptions, { duration: 0 }));
            }
        }
        this.resize();
        this._localIdeographFontFamily = options.localIdeographFontFamily;
        if (options.style) {
            this.setStyle(options.style, { localIdeographFontFamily: options.localIdeographFontFamily });
        }
        if (options.attributionControl) {
            this.addControl(new AttributionControl({ customAttribution: options.customAttribution }));
        }
        this.addControl(new LogoControl(), options.logoPosition);
        this.on('style.load', function () {
            if (this$1.transform.unmodified) {
                this$1.jumpTo(this$1.style.stylesheet);
            }
        });
        this.on('data', function (event) {
            this$1._update(event.dataType === 'style');
            this$1.fire(new performance.Event(event.dataType + 'data', event));
        });
        this.on('dataloading', function (event) {
            this$1.fire(new performance.Event(event.dataType + 'dataloading', event));
        });
    }
    if (Camera)
        Map.__proto__ = Camera;
    Map.prototype = Object.create(Camera && Camera.prototype);
    Map.prototype.constructor = Map;
    var prototypeAccessors = {
        showTileBoundaries: { configurable: true },
        showPadding: { configurable: true },
        showCollisionBoxes: { configurable: true },
        showOverdrawInspector: { configurable: true },
        repaint: { configurable: true },
        vertices: { configurable: true },
        version: { configurable: true }
    };
    Map.prototype._getMapId = function _getMapId() {
        return this._mapId;
    };
    Map.prototype.addControl = function addControl(control, position) {
        if (position === undefined) {
            if (control.getDefaultPosition) {
                position = control.getDefaultPosition();
            } else {
                position = 'top-right';
            }
        }
        if (!control || !control.onAdd) {
            return this.fire(new performance.ErrorEvent(new Error('Invalid argument to map.addControl(). Argument must be a control with onAdd and onRemove methods.')));
        }
        var controlElement = control.onAdd(this);
        this._controls.push(control);
        var positionContainer = this._controlPositions[position];
        if (position.indexOf('bottom') !== -1) {
            positionContainer.insertBefore(controlElement, positionContainer.firstChild);
        } else {
            positionContainer.appendChild(controlElement);
        }
        return this;
    };
    Map.prototype.removeControl = function removeControl(control) {
        if (!control || !control.onRemove) {
            return this.fire(new performance.ErrorEvent(new Error('Invalid argument to map.removeControl(). Argument must be a control with onAdd and onRemove methods.')));
        }
        var ci = this._controls.indexOf(control);
        if (ci > -1) {
            this._controls.splice(ci, 1);
        }
        control.onRemove(this);
        return this;
    };
    Map.prototype.hasControl = function hasControl(control) {
        return this._controls.indexOf(control) > -1;
    };
    Map.prototype.resize = function resize(eventData) {
        var ref = this._containerDimensions();
        var width = ref[0];
        var height = ref[1];
        if (width === this.transform.width && height === this.transform.height) {
            return this;
        }
        this._resizeCanvas(width, height);
        this.transform.resize(width, height);
        this.painter.resize(width, height);
        var fireMoving = !this._moving;
        if (fireMoving) {
            this.fire(new performance.Event('movestart', eventData)).fire(new performance.Event('move', eventData));
        }
        this.fire(new performance.Event('resize', eventData));
        if (fireMoving) {
            this.fire(new performance.Event('moveend', eventData));
        }
        return this;
    };
    Map.prototype.getBounds = function getBounds() {
        return this.transform.getBounds();
    };
    Map.prototype.getMaxBounds = function getMaxBounds() {
        return this.transform.getMaxBounds();
    };
    Map.prototype.setMaxBounds = function setMaxBounds(bounds) {
        this.transform.setMaxBounds(performance.LngLatBounds.convert(bounds));
        return this._update();
    };
    Map.prototype.setMinZoom = function setMinZoom(minZoom) {
        minZoom = minZoom === null || minZoom === undefined ? defaultMinZoom : minZoom;
        if (minZoom >= defaultMinZoom && minZoom <= this.transform.maxZoom) {
            this.transform.minZoom = minZoom;
            this._update();
            if (this.getZoom() < minZoom) {
                this.setZoom(minZoom);
            }
            return this;
        } else {
            throw new Error('minZoom must be between ' + defaultMinZoom + ' and the current maxZoom, inclusive');
        }
    };
    Map.prototype.getMinZoom = function getMinZoom() {
        return this.transform.minZoom;
    };
    Map.prototype.setMaxZoom = function setMaxZoom(maxZoom) {
        maxZoom = maxZoom === null || maxZoom === undefined ? defaultMaxZoom : maxZoom;
        if (maxZoom >= this.transform.minZoom) {
            this.transform.maxZoom = maxZoom;
            this._update();
            if (this.getZoom() > maxZoom) {
                this.setZoom(maxZoom);
            }
            return this;
        } else {
            throw new Error('maxZoom must be greater than the current minZoom');
        }
    };
    Map.prototype.getMaxZoom = function getMaxZoom() {
        return this.transform.maxZoom;
    };
    Map.prototype.setMinPitch = function setMinPitch(minPitch) {
        minPitch = minPitch === null || minPitch === undefined ? defaultMinPitch : minPitch;
        if (minPitch < defaultMinPitch) {
            throw new Error('minPitch must be greater than or equal to ' + defaultMinPitch);
        }
        if (minPitch >= defaultMinPitch && minPitch <= this.transform.maxPitch) {
            this.transform.minPitch = minPitch;
            this._update();
            if (this.getPitch() < minPitch) {
                this.setPitch(minPitch);
            }
            return this;
        } else {
            throw new Error('minPitch must be between ' + defaultMinPitch + ' and the current maxPitch, inclusive');
        }
    };
    Map.prototype.getMinPitch = function getMinPitch() {
        return this.transform.minPitch;
    };
    Map.prototype.setMaxPitch = function setMaxPitch(maxPitch) {
        maxPitch = maxPitch === null || maxPitch === undefined ? defaultMaxPitch : maxPitch;
        if (maxPitch > defaultMaxPitch) {
            throw new Error('maxPitch must be less than or equal to ' + defaultMaxPitch);
        }
        if (maxPitch >= this.transform.minPitch) {
            this.transform.maxPitch = maxPitch;
            this._update();
            if (this.getPitch() > maxPitch) {
                this.setPitch(maxPitch);
            }
            return this;
        } else {
            throw new Error('maxPitch must be greater than the current minPitch');
        }
    };
    Map.prototype.getMaxPitch = function getMaxPitch() {
        return this.transform.maxPitch;
    };
    Map.prototype.getRenderWorldCopies = function getRenderWorldCopies() {
        return this.transform.renderWorldCopies;
    };
    Map.prototype.setRenderWorldCopies = function setRenderWorldCopies(renderWorldCopies) {
        this.transform.renderWorldCopies = renderWorldCopies;
        return this._update();
    };
    Map.prototype.project = function project(lnglat) {
        return this.transform.locationPoint(performance.LngLat.convert(lnglat));
    };
    Map.prototype.unproject = function unproject(point) {
        return this.transform.pointLocation(performance.Point.convert(point));
    };
    Map.prototype.isMoving = function isMoving() {
        return this._moving || this.handlers.isMoving();
    };
    Map.prototype.isZooming = function isZooming() {
        return this._zooming || this.handlers.isZooming();
    };
    Map.prototype.isRotating = function isRotating() {
        return this._rotating || this.handlers.isRotating();
    };
    Map.prototype._createDelegatedListener = function _createDelegatedListener(type, layerId, listener) {
        var this$1 = this;
        var obj;
        if (type === 'mouseenter' || type === 'mouseover') {
            var mousein = false;
            var mousemove = function (e) {
                var features = this$1.getLayer(layerId) ? this$1.queryRenderedFeatures(e.point, { layers: [layerId] }) : [];
                if (!features.length) {
                    mousein = false;
                } else if (!mousein) {
                    mousein = true;
                    listener.call(this$1, new MapMouseEvent(type, this$1, e.originalEvent, { features: features }));
                }
            };
            var mouseout = function () {
                mousein = false;
            };
            return {
                layer: layerId,
                listener: listener,
                delegates: {
                    mousemove: mousemove,
                    mouseout: mouseout
                }
            };
        } else if (type === 'mouseleave' || type === 'mouseout') {
            var mousein$1 = false;
            var mousemove$1 = function (e) {
                var features = this$1.getLayer(layerId) ? this$1.queryRenderedFeatures(e.point, { layers: [layerId] }) : [];
                if (features.length) {
                    mousein$1 = true;
                } else if (mousein$1) {
                    mousein$1 = false;
                    listener.call(this$1, new MapMouseEvent(type, this$1, e.originalEvent));
                }
            };
            var mouseout$1 = function (e) {
                if (mousein$1) {
                    mousein$1 = false;
                    listener.call(this$1, new MapMouseEvent(type, this$1, e.originalEvent));
                }
            };
            return {
                layer: layerId,
                listener: listener,
                delegates: {
                    mousemove: mousemove$1,
                    mouseout: mouseout$1
                }
            };
        } else {
            var delegate = function (e) {
                var features = this$1.getLayer(layerId) ? this$1.queryRenderedFeatures(e.point, { layers: [layerId] }) : [];
                if (features.length) {
                    e.features = features;
                    listener.call(this$1, e);
                    delete e.features;
                }
            };
            return {
                layer: layerId,
                listener: listener,
                delegates: (obj = {}, obj[type] = delegate, obj)
            };
        }
    };
    Map.prototype.on = function on(type, layerId, listener) {
        if (listener === undefined) {
            return Camera.prototype.on.call(this, type, layerId);
        }
        var delegatedListener = this._createDelegatedListener(type, layerId, listener);
        this._delegatedListeners = this._delegatedListeners || {};
        this._delegatedListeners[type] = this._delegatedListeners[type] || [];
        this._delegatedListeners[type].push(delegatedListener);
        for (var event in delegatedListener.delegates) {
            this.on(event, delegatedListener.delegates[event]);
        }
        return this;
    };
    Map.prototype.once = function once(type, layerId, listener) {
        if (listener === undefined) {
            return Camera.prototype.once.call(this, type, layerId);
        }
        var delegatedListener = this._createDelegatedListener(type, layerId, listener);
        for (var event in delegatedListener.delegates) {
            this.once(event, delegatedListener.delegates[event]);
        }
        return this;
    };
    Map.prototype.off = function off(type, layerId, listener) {
        var this$1 = this;
        if (listener === undefined) {
            return Camera.prototype.off.call(this, type, layerId);
        }
        var removeDelegatedListener = function (delegatedListeners) {
            var listeners = delegatedListeners[type];
            for (var i = 0; i < listeners.length; i++) {
                var delegatedListener = listeners[i];
                if (delegatedListener.layer === layerId && delegatedListener.listener === listener) {
                    for (var event in delegatedListener.delegates) {
                        this$1.off(event, delegatedListener.delegates[event]);
                    }
                    listeners.splice(i, 1);
                    return this$1;
                }
            }
        };
        if (this._delegatedListeners && this._delegatedListeners[type]) {
            removeDelegatedListener(this._delegatedListeners);
        }
        return this;
    };
    Map.prototype.queryRenderedFeatures = function queryRenderedFeatures(geometry, options) {
        if (!this.style) {
            return [];
        }
        if (options === undefined && geometry !== undefined && !(geometry instanceof performance.Point) && !Array.isArray(geometry)) {
            options = geometry;
            geometry = undefined;
        }
        options = options || {};
        geometry = geometry || [
            [
                0,
                0
            ],
            [
                this.transform.width,
                this.transform.height
            ]
        ];
        var queryGeometry;
        if (geometry instanceof performance.Point || typeof geometry[0] === 'number') {
            queryGeometry = [performance.Point.convert(geometry)];
        } else {
            var tl = performance.Point.convert(geometry[0]);
            var br = performance.Point.convert(geometry[1]);
            queryGeometry = [
                tl,
                new performance.Point(br.x, tl.y),
                br,
                new performance.Point(tl.x, br.y),
                tl
            ];
        }
        return this.style.queryRenderedFeatures(queryGeometry, options, this.transform);
    };
    Map.prototype.querySourceFeatures = function querySourceFeatures(sourceId, parameters) {
        return this.style.querySourceFeatures(sourceId, parameters);
    };
    Map.prototype.setStyle = function setStyle(style, options) {
        options = performance.extend({}, { localIdeographFontFamily: this._localIdeographFontFamily }, options);
        if (options.diff !== false && options.localIdeographFontFamily === this._localIdeographFontFamily && this.style && style) {
            this._diffStyle(style, options);
            return this;
        } else {
            this._localIdeographFontFamily = options.localIdeographFontFamily;
            return this._updateStyle(style, options);
        }
    };
    Map.prototype._getUIString = function _getUIString(key) {
        var str = this._locale[key];
        if (str == null) {
            throw new Error('Missing UI string \'' + key + '\'');
        }
        return str;
    };
    Map.prototype._updateStyle = function _updateStyle(style, options) {
        if (this.style) {
            this.style.setEventedParent(null);
            this.style._remove();
        }
        if (!style) {
            delete this.style;
            return this;
        } else {
            this.style = new Style(this, options || {});
        }
        this.style.setEventedParent(this, { style: this.style });
        if (typeof style === 'string') {
            this.style.loadURL(style);
        } else {
            this.style.loadJSON(style);
        }
        return this;
    };
    Map.prototype._lazyInitEmptyStyle = function _lazyInitEmptyStyle() {
        if (!this.style) {
            this.style = new Style(this, {});
            this.style.setEventedParent(this, { style: this.style });
            this.style.loadEmpty();
        }
    };
    Map.prototype._diffStyle = function _diffStyle(style, options) {
        var this$1 = this;
        if (typeof style === 'string') {
            var url = this._requestManager.normalizeStyleURL(style);
            var request = this._requestManager.transformRequest(url, performance.ResourceType.Style);
            performance.getJSON(request, function (error, json) {
                if (error) {
                    this$1.fire(new performance.ErrorEvent(error));
                } else if (json) {
                    this$1._updateDiff(json, options);
                }
            });
        } else if (typeof style === 'object') {
            this._updateDiff(style, options);
        }
    };
    Map.prototype._updateDiff = function _updateDiff(style, options) {
        try {
            if (this.style.setState(style)) {
                this._update(true);
            }
        } catch (e) {
            performance.warnOnce('Unable to perform style diff: ' + (e.message || e.error || e) + '.  Rebuilding the style from scratch.');
            this._updateStyle(style, options);
        }
    };
    Map.prototype.getStyle = function getStyle() {
        if (this.style) {
            return this.style.serialize();
        }
    };
    Map.prototype.isStyleLoaded = function isStyleLoaded() {
        if (!this.style) {
            return performance.warnOnce('There is no style added to the map.');
        }
        return this.style.loaded();
    };
    Map.prototype.addSource = function addSource(id, source) {
        this._lazyInitEmptyStyle();
        this.style.addSource(id, source);
        return this._update(true);
    };
    Map.prototype.isSourceLoaded = function isSourceLoaded(id) {
        var source = this.style && this.style.sourceCaches[id];
        if (source === undefined) {
            this.fire(new performance.ErrorEvent(new Error('There is no source with ID \'' + id + '\'')));
            return;
        }
        return source.loaded();
    };
    Map.prototype.areTilesLoaded = function areTilesLoaded() {
        var sources = this.style && this.style.sourceCaches;
        for (var id in sources) {
            var source = sources[id];
            var tiles = source._tiles;
            for (var t in tiles) {
                var tile = tiles[t];
                if (!(tile.state === 'loaded' || tile.state === 'errored')) {
                    return false;
                }
            }
        }
        return true;
    };
    Map.prototype.addSourceType = function addSourceType(name, SourceType, callback) {
        this._lazyInitEmptyStyle();
        return this.style.addSourceType(name, SourceType, callback);
    };
    Map.prototype.removeSource = function removeSource(id) {
        this.style.removeSource(id);
        return this._update(true);
    };
    Map.prototype.getSource = function getSource(id) {
        return this.style.getSource(id);
    };
    Map.prototype.addImage = function addImage(id, image, ref) {
        if (ref === void 0)
            ref = {};
        var pixelRatio = ref.pixelRatio;
        if (pixelRatio === void 0)
            pixelRatio = 1;
        var sdf = ref.sdf;
        if (sdf === void 0)
            sdf = false;
        var stretchX = ref.stretchX;
        var stretchY = ref.stretchY;
        var content = ref.content;
        this._lazyInitEmptyStyle();
        var version = 0;
        if (image instanceof HTMLImageElement || ImageBitmap && image instanceof ImageBitmap) {
            var ref$1 = performance.browser.getImageData(image);
            var width = ref$1.width;
            var height = ref$1.height;
            var data = ref$1.data;
            this.style.addImage(id, {
                data: new performance.RGBAImage({
                    width: width,
                    height: height
                }, data),
                pixelRatio: pixelRatio,
                stretchX: stretchX,
                stretchY: stretchY,
                content: content,
                sdf: sdf,
                version: version
            });
        } else if (image.width === undefined || image.height === undefined) {
            return this.fire(new performance.ErrorEvent(new Error('Invalid arguments to map.addImage(). The second argument must be an `HTMLImageElement`, `ImageData`, `ImageBitmap`, ' + 'or object with `width`, `height`, and `data` properties with the same format as `ImageData`')));
        } else {
            var width$1 = image.width;
            var height$1 = image.height;
            var data$1 = image.data;
            var userImage = image;
            this.style.addImage(id, {
                data: new performance.RGBAImage({
                    width: width$1,
                    height: height$1
                }, new Uint8Array(data$1)),
                pixelRatio: pixelRatio,
                stretchX: stretchX,
                stretchY: stretchY,
                content: content,
                sdf: sdf,
                version: version,
                userImage: userImage
            });
            if (userImage.onAdd) {
                userImage.onAdd(this, id);
            }
        }
    };
    Map.prototype.updateImage = function updateImage(id, image) {
        var existingImage = this.style.getImage(id);
        if (!existingImage) {
            return this.fire(new performance.ErrorEvent(new Error('The map has no image with that id. If you are adding a new image use `map.addImage(...)` instead.')));
        }
        var imageData = image instanceof HTMLImageElement || ImageBitmap && image instanceof ImageBitmap ? performance.browser.getImageData(image) : image;
        var width = imageData.width;
        var height = imageData.height;
        var data = imageData.data;
        if (width === undefined || height === undefined) {
            return this.fire(new performance.ErrorEvent(new Error('Invalid arguments to map.updateImage(). The second argument must be an `HTMLImageElement`, `ImageData`, `ImageBitmap`, ' + 'or object with `width`, `height`, and `data` properties with the same format as `ImageData`')));
        }
        if (width !== existingImage.data.width || height !== existingImage.data.height) {
            return this.fire(new performance.ErrorEvent(new Error('The width and height of the updated image must be that same as the previous version of the image')));
        }
        var copy = !(image instanceof HTMLImageElement || ImageBitmap && image instanceof ImageBitmap);
        existingImage.data.replace(data, copy);
        this.style.updateImage(id, existingImage);
    };
    Map.prototype.hasImage = function hasImage(id) {
        if (!id) {
            this.fire(new performance.ErrorEvent(new Error('Missing required image id')));
            return false;
        }
        return !!this.style.getImage(id);
    };
    Map.prototype.removeImage = function removeImage(id) {
        this.style.removeImage(id);
    };
    Map.prototype.loadImage = function loadImage(url, callback) {
        performance.getImage(this._requestManager.transformRequest(url, performance.ResourceType.Image), callback);
    };
    Map.prototype.listImages = function listImages() {
        return this.style.listImages();
    };
    Map.prototype.addLayer = function addLayer(layer, beforeId) {
        this._lazyInitEmptyStyle();
        this.style.addLayer(layer, beforeId);
        return this._update(true);
    };
    Map.prototype.moveLayer = function moveLayer(id, beforeId) {
        this.style.moveLayer(id, beforeId);
        return this._update(true);
    };
    Map.prototype.removeLayer = function removeLayer(id) {
        this.style.removeLayer(id);
        return this._update(true);
    };
    Map.prototype.getLayer = function getLayer(id) {
        return this.style.getLayer(id);
    };
    Map.prototype.setLayerZoomRange = function setLayerZoomRange(layerId, minzoom, maxzoom) {
        this.style.setLayerZoomRange(layerId, minzoom, maxzoom);
        return this._update(true);
    };
    Map.prototype.setFilter = function setFilter(layerId, filter, options) {
        if (options === void 0)
            options = {};
        this.style.setFilter(layerId, filter, options);
        return this._update(true);
    };
    Map.prototype.getFilter = function getFilter(layerId) {
        return this.style.getFilter(layerId);
    };
    Map.prototype.setPaintProperty = function setPaintProperty(layerId, name, value, options) {
        if (options === void 0)
            options = {};
        this.style.setPaintProperty(layerId, name, value, options);
        return this._update(true);
    };
    Map.prototype.getPaintProperty = function getPaintProperty(layerId, name) {
        return this.style.getPaintProperty(layerId, name);
    };
    Map.prototype.setLayoutProperty = function setLayoutProperty(layerId, name, value, options) {
        if (options === void 0)
            options = {};
        this.style.setLayoutProperty(layerId, name, value, options);
        return this._update(true);
    };
    Map.prototype.getLayoutProperty = function getLayoutProperty(layerId, name) {
        return this.style.getLayoutProperty(layerId, name);
    };
    Map.prototype.setLight = function setLight(light, options) {
        if (options === void 0)
            options = {};
        this._lazyInitEmptyStyle();
        this.style.setLight(light, options);
        return this._update(true);
    };
    Map.prototype.getLight = function getLight() {
        return this.style.getLight();
    };
    Map.prototype.setFeatureState = function setFeatureState(feature, state) {
        this.style.setFeatureState(feature, state);
        return this._update();
    };
    Map.prototype.removeFeatureState = function removeFeatureState(target, key) {
        this.style.removeFeatureState(target, key);
        return this._update();
    };
    Map.prototype.getFeatureState = function getFeatureState(feature) {
        return this.style.getFeatureState(feature);
    };
    Map.prototype.getContainer = function getContainer() {
        return this._container;
    };
    Map.prototype.getCanvasContainer = function getCanvasContainer() {
        return this._canvasContainer;
    };
    Map.prototype.getCanvas = function getCanvas() {
        return this._canvas;
    };
    Map.prototype._containerDimensions = function _containerDimensions() {
        var width = 0;
        var height = 0;
        if (this._container) {
            width = this._container.clientWidth || 400;
            height = this._container.clientHeight || 300;
        }
        return [
            width,
            height
        ];
    };
    Map.prototype._detectMissingCSS = function _detectMissingCSS() {
        var computedColor = performance.window.getComputedStyle(this._missingCSSCanary).getPropertyValue('background-color');
        if (computedColor !== 'rgb(250, 128, 114)') {
            performance.warnOnce('This page appears to be missing CSS declarations for ' + 'Mapbox GL JS, which may cause the map to display incorrectly. ' + 'Please ensure your page includes mapbox-gl.css, as described ' + 'in https://www.mapbox.com/mapbox-gl-js/api/.');
        }
    };
    Map.prototype._setupContainer = function _setupContainer() {
        var container = this._container;
        container.classList.add('mapboxgl-map');
        var missingCSSCanary = this._missingCSSCanary = DOM.create('div', 'mapboxgl-canary', container);
        missingCSSCanary.style.visibility = 'hidden';
        this._detectMissingCSS();
        var canvasContainer = this._canvasContainer = DOM.create('div', 'mapboxgl-canvas-container', container);
        if (this._interactive) {
            canvasContainer.classList.add('mapboxgl-interactive');
        }
        this._canvas = DOM.create('canvas', 'mapboxgl-canvas', canvasContainer);
        this._canvas.addEventListener('webglcontextlost', this._contextLost, false);
        this._canvas.addEventListener('webglcontextrestored', this._contextRestored, false);
        this._canvas.setAttribute('tabindex', '0');
        this._canvas.setAttribute('aria-label', 'Map');
        this._canvas.setAttribute('role', 'region');
        var dimensions = this._containerDimensions();
        this._resizeCanvas(dimensions[0], dimensions[1]);
        var controlContainer = this._controlContainer = DOM.create('div', 'mapboxgl-control-container', container);
        var positions = this._controlPositions = {};
        [
            'top-left',
            'top-right',
            'bottom-left',
            'bottom-right'
        ].forEach(function (positionName) {
            positions[positionName] = DOM.create('div', 'mapboxgl-ctrl-' + positionName, controlContainer);
        });
        this._container.addEventListener('scroll', this._onMapScroll, false);
    };
    Map.prototype._resizeCanvas = function _resizeCanvas(width, height) {
        var pixelRatio = performance.browser.devicePixelRatio || 1;
        this._canvas.width = pixelRatio * width;
        this._canvas.height = pixelRatio * height;
        this._canvas.style.width = width + 'px';
        this._canvas.style.height = height + 'px';
    };
    Map.prototype._setupPainter = function _setupPainter() {
        var attributes = performance.extend({}, mapboxGlSupported.webGLContextAttributes, {
            failIfMajorPerformanceCaveat: this._failIfMajorPerformanceCaveat,
            preserveDrawingBuffer: this._preserveDrawingBuffer,
            antialias: this._antialias || false
        });
        var gl = this._canvas.getContext('webgl', attributes) || this._canvas.getContext('experimental-webgl', attributes);
        if (!gl) {
            this.fire(new performance.ErrorEvent(new Error('Failed to initialize WebGL')));
            return;
        }
        this.painter = new Painter(gl, this.transform);
        performance.webpSupported.testSupport(gl);
    };
    Map.prototype._contextLost = function _contextLost(event) {
        event.preventDefault();
        if (this._frame) {
            this._frame.cancel();
            this._frame = null;
        }
        this.fire(new performance.Event('webglcontextlost', { originalEvent: event }));
    };
    Map.prototype._contextRestored = function _contextRestored(event) {
        this._setupPainter();
        this.resize();
        this._update();
        this.fire(new performance.Event('webglcontextrestored', { originalEvent: event }));
    };
    Map.prototype._onMapScroll = function _onMapScroll(event) {
        if (event.target !== this._container) {
            return;
        }
        this._container.scrollTop = 0;
        this._container.scrollLeft = 0;
        return false;
    };
    Map.prototype.loaded = function loaded() {
        return !this._styleDirty && !this._sourcesDirty && !!this.style && this.style.loaded();
    };
    Map.prototype._update = function _update(updateStyle) {
        if (!this.style) {
            return this;
        }
        this._styleDirty = this._styleDirty || updateStyle;
        this._sourcesDirty = true;
        this.triggerRepaint();
        return this;
    };
    Map.prototype._requestRenderFrame = function _requestRenderFrame(callback) {
        this._update();
        return this._renderTaskQueue.add(callback);
    };
    Map.prototype._cancelRenderFrame = function _cancelRenderFrame(id) {
        this._renderTaskQueue.remove(id);
    };
    Map.prototype._render = function _render(paintStartTimeStamp) {
        var this$1 = this;
        var gpuTimer, frameStartTime = 0;
        var extTimerQuery = this.painter.context.extTimerQuery;
        if (this.listens('gpu-timing-frame')) {
            gpuTimer = extTimerQuery.createQueryEXT();
            extTimerQuery.beginQueryEXT(extTimerQuery.TIME_ELAPSED_EXT, gpuTimer);
            frameStartTime = performance.browser.now();
        }
        this.painter.context.setDirty();
        this.painter.setBaseState();
        this._renderTaskQueue.run(paintStartTimeStamp);
        if (this._removed) {
            return;
        }
        var crossFading = false;
        if (this.style && this._styleDirty) {
            this._styleDirty = false;
            var zoom = this.transform.zoom;
            var now = performance.browser.now();
            this.style.zoomHistory.update(zoom, now);
            var parameters = new performance.EvaluationParameters(zoom, {
                now: now,
                fadeDuration: this._fadeDuration,
                zoomHistory: this.style.zoomHistory,
                transition: this.style.getTransition()
            });
            var factor = parameters.crossFadingFactor();
            if (factor !== 1 || factor !== this._crossFadingFactor) {
                crossFading = true;
                this._crossFadingFactor = factor;
            }
            this.style.update(parameters);
        }
        if (this.style && this._sourcesDirty) {
            this._sourcesDirty = false;
            this.style._updateSources(this.transform);
        }
        this._placementDirty = this.style && this.style._updatePlacement(this.painter.transform, this.showCollisionBoxes, this._fadeDuration, this._crossSourceCollisions);
        this.painter.render(this.style, {
            showTileBoundaries: this.showTileBoundaries,
            showOverdrawInspector: this._showOverdrawInspector,
            rotating: this.isRotating(),
            zooming: this.isZooming(),
            moving: this.isMoving(),
            fadeDuration: this._fadeDuration,
            showPadding: this.showPadding,
            gpuTiming: !!this.listens('gpu-timing-layer')
        });
        this.fire(new performance.Event('render'));
        if (this.loaded() && !this._loaded) {
            this._loaded = true;
            this.fire(new performance.Event('load'));
        }
        if (this.style && (this.style.hasTransitions() || crossFading)) {
            this._styleDirty = true;
        }
        if (this.style && !this._placementDirty) {
            this.style._releaseSymbolFadeTiles();
        }
        if (this.listens('gpu-timing-frame')) {
            var renderCPUTime = performance.browser.now() - frameStartTime;
            extTimerQuery.endQueryEXT(extTimerQuery.TIME_ELAPSED_EXT, gpuTimer);
            setTimeout(function () {
                var renderGPUTime = extTimerQuery.getQueryObjectEXT(gpuTimer, extTimerQuery.QUERY_RESULT_EXT) / (1000 * 1000);
                extTimerQuery.deleteQueryEXT(gpuTimer);
                this$1.fire(new performance.Event('gpu-timing-frame', {
                    cpuTime: renderCPUTime,
                    gpuTime: renderGPUTime
                }));
            }, 50);
        }
        if (this.listens('gpu-timing-layer')) {
            var frameLayerQueries = this.painter.collectGpuTimers();
            setTimeout(function () {
                var renderedLayerTimes = this$1.painter.queryGpuTimers(frameLayerQueries);
                this$1.fire(new performance.Event('gpu-timing-layer', { layerTimes: renderedLayerTimes }));
            }, 50);
        }
        var somethingDirty = this._sourcesDirty || this._styleDirty || this._placementDirty;
        if (somethingDirty || this._repaint) {
            this.triggerRepaint();
        } else if (!this.isMoving() && this.loaded()) {
            this.fire(new performance.Event('idle'));
        }
        if (this._loaded && !this._fullyLoaded && !somethingDirty) {
            this._fullyLoaded = true;
        }
        return this;
    };
    Map.prototype.remove = function remove() {
        if (this._hash) {
            this._hash.remove();
        }
        for (var i = 0, list = this._controls; i < list.length; i += 1) {
            var control = list[i];
            control.onRemove(this);
        }
        this._controls = [];
        if (this._frame) {
            this._frame.cancel();
            this._frame = null;
        }
        this._renderTaskQueue.clear();
        this.painter.destroy();
        this.handlers.destroy();
        delete this.handlers;
        this.setStyle(null);
        if (typeof performance.window !== 'undefined') {
            performance.window.removeEventListener('resize', this._onWindowResize, false);
            performance.window.removeEventListener('orientationchange', this._onWindowResize, false);
            performance.window.removeEventListener('online', this._onWindowOnline, false);
        }
        var extension = this.painter.context.gl.getExtension('WEBGL_lose_context');
        if (extension) {
            extension.loseContext();
        }
        removeNode(this._canvasContainer);
        removeNode(this._controlContainer);
        removeNode(this._missingCSSCanary);
        this._container.classList.remove('mapboxgl-map');
        this._removed = true;
        this.fire(new performance.Event('remove'));
    };
    Map.prototype.triggerRepaint = function triggerRepaint() {
        var this$1 = this;
        if (this.style && !this._frame) {
            this._frame = performance.browser.frame(function (paintStartTimeStamp) {
                this$1._frame = null;
                this$1._render(paintStartTimeStamp);
            });
        }
    };
    Map.prototype._onWindowOnline = function _onWindowOnline() {
        this._update();
    };
    Map.prototype._onWindowResize = function _onWindowResize(event) {
        if (this._trackResize) {
            this.resize({ originalEvent: event })._update();
        }
    };
    prototypeAccessors.showTileBoundaries.get = function () {
        return !!this._showTileBoundaries;
    };
    prototypeAccessors.showTileBoundaries.set = function (value) {
        if (this._showTileBoundaries === value) {
            return;
        }
        this._showTileBoundaries = value;
        this._update();
    };
    prototypeAccessors.showPadding.get = function () {
        return !!this._showPadding;
    };
    prototypeAccessors.showPadding.set = function (value) {
        if (this._showPadding === value) {
            return;
        }
        this._showPadding = value;
        this._update();
    };
    prototypeAccessors.showCollisionBoxes.get = function () {
        return !!this._showCollisionBoxes;
    };
    prototypeAccessors.showCollisionBoxes.set = function (value) {
        if (this._showCollisionBoxes === value) {
            return;
        }
        this._showCollisionBoxes = value;
        if (value) {
            this.style._generateCollisionBoxes();
        } else {
            this._update();
        }
    };
    prototypeAccessors.showOverdrawInspector.get = function () {
        return !!this._showOverdrawInspector;
    };
    prototypeAccessors.showOverdrawInspector.set = function (value) {
        if (this._showOverdrawInspector === value) {
            return;
        }
        this._showOverdrawInspector = value;
        this._update();
    };
    prototypeAccessors.repaint.get = function () {
        return !!this._repaint;
    };
    prototypeAccessors.repaint.set = function (value) {
        if (this._repaint !== value) {
            this._repaint = value;
            this.triggerRepaint();
        }
    };
    prototypeAccessors.vertices.get = function () {
        return !!this._vertices;
    };
    prototypeAccessors.vertices.set = function (value) {
        this._vertices = value;
        this._update();
    };
    Map.prototype._setCacheLimits = function _setCacheLimits(limit, checkThreshold) {
        performance.setCacheLimits(limit, checkThreshold);
    };
    prototypeAccessors.version.get = function () {
        return performance.version;
    };
    Object.defineProperties(Map.prototype, prototypeAccessors);
    return Map;
}(Camera);
function removeNode(node) {
    if (node.parentNode) {
        node.parentNode.removeChild(node);
    }
}

var defaultOptions$2 = {
    showCompass: true,
    showZoom: true,
    visualizePitch: false
};
var NavigationControl = function NavigationControl(options) {
    var this$1 = this;
    this.options = performance.extend({}, defaultOptions$2, options);
    this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-group');
    this._container.addEventListener('contextmenu', function (e) {
        return e.preventDefault();
    });
    if (this.options.showZoom) {
        performance.bindAll([
            '_setButtonTitle',
            '_updateZoomButtons'
        ], this);
        this._zoomInButton = this._createButton('mapboxgl-ctrl-zoom-in', function (e) {
            return this$1._map.zoomIn({}, { originalEvent: e });
        });
        DOM.create('span', 'mapboxgl-ctrl-icon', this._zoomInButton).setAttribute('aria-hidden', true);
        this._zoomOutButton = this._createButton('mapboxgl-ctrl-zoom-out', function (e) {
            return this$1._map.zoomOut({}, { originalEvent: e });
        });
        DOM.create('span', 'mapboxgl-ctrl-icon', this._zoomOutButton).setAttribute('aria-hidden', true);
    }
    if (this.options.showCompass) {
        performance.bindAll(['_rotateCompassArrow'], this);
        this._compass = this._createButton('mapboxgl-ctrl-compass', function (e) {
            if (this$1.options.visualizePitch) {
                this$1._map.resetNorthPitch({}, { originalEvent: e });
            } else {
                this$1._map.resetNorth({}, { originalEvent: e });
            }
        });
        this._compassIcon = DOM.create('span', 'mapboxgl-ctrl-icon', this._compass);
        this._compassIcon.setAttribute('aria-hidden', true);
    }
};
NavigationControl.prototype._updateZoomButtons = function _updateZoomButtons() {
    var zoom = this._map.getZoom();
    var isMax = zoom === this._map.getMaxZoom();
    var isMin = zoom === this._map.getMinZoom();
    this._zoomInButton.disabled = isMax;
    this._zoomOutButton.disabled = isMin;
    this._zoomInButton.setAttribute('aria-disabled', isMax.toString());
    this._zoomOutButton.setAttribute('aria-disabled', isMin.toString());
};
NavigationControl.prototype._rotateCompassArrow = function _rotateCompassArrow() {
    var rotate = this.options.visualizePitch ? 'scale(' + 1 / Math.pow(Math.cos(this._map.transform.pitch * (Math.PI / 180)), 0.5) + ') rotateX(' + this._map.transform.pitch + 'deg) rotateZ(' + this._map.transform.angle * (180 / Math.PI) + 'deg)' : 'rotate(' + this._map.transform.angle * (180 / Math.PI) + 'deg)';
    this._compassIcon.style.transform = rotate;
};
NavigationControl.prototype.onAdd = function onAdd(map) {
    this._map = map;
    if (this.options.showZoom) {
        this._setButtonTitle(this._zoomInButton, 'ZoomIn');
        this._setButtonTitle(this._zoomOutButton, 'ZoomOut');
        this._map.on('zoom', this._updateZoomButtons);
        this._updateZoomButtons();
    }
    if (this.options.showCompass) {
        this._setButtonTitle(this._compass, 'ResetBearing');
        if (this.options.visualizePitch) {
            this._map.on('pitch', this._rotateCompassArrow);
        }
        this._map.on('rotate', this._rotateCompassArrow);
        this._rotateCompassArrow();
        this._handler = new MouseRotateWrapper(this._map, this._compass, this.options.visualizePitch);
    }
    return this._container;
};
NavigationControl.prototype.onRemove = function onRemove() {
    DOM.remove(this._container);
    if (this.options.showZoom) {
        this._map.off('zoom', this._updateZoomButtons);
    }
    if (this.options.showCompass) {
        if (this.options.visualizePitch) {
            this._map.off('pitch', this._rotateCompassArrow);
        }
        this._map.off('rotate', this._rotateCompassArrow);
        this._handler.off();
        delete this._handler;
    }
    delete this._map;
};
NavigationControl.prototype._createButton = function _createButton(className, fn) {
    var a = DOM.create('button', className, this._container);
    a.type = 'button';
    a.addEventListener('click', fn);
    return a;
};
NavigationControl.prototype._setButtonTitle = function _setButtonTitle(button, title) {
    var str = this._map._getUIString('NavigationControl.' + title);
    button.title = str;
    button.setAttribute('aria-label', str);
};
var MouseRotateWrapper = function MouseRotateWrapper(map, element, pitch) {
    if (pitch === void 0)
        pitch = false;
    this._clickTolerance = 10;
    this.element = element;
    this.mouseRotate = new MouseRotateHandler({ clickTolerance: map.dragRotate._mouseRotate._clickTolerance });
    this.map = map;
    if (pitch) {
        this.mousePitch = new MousePitchHandler({ clickTolerance: map.dragRotate._mousePitch._clickTolerance });
    }
    performance.bindAll([
        'mousedown',
        'mousemove',
        'mouseup',
        'touchstart',
        'touchmove',
        'touchend',
        'reset'
    ], this);
    DOM.addEventListener(element, 'mousedown', this.mousedown);
    DOM.addEventListener(element, 'touchstart', this.touchstart, { passive: false });
    DOM.addEventListener(element, 'touchmove', this.touchmove);
    DOM.addEventListener(element, 'touchend', this.touchend);
    DOM.addEventListener(element, 'touchcancel', this.reset);
};
MouseRotateWrapper.prototype.down = function down(e, point) {
    this.mouseRotate.mousedown(e, point);
    if (this.mousePitch) {
        this.mousePitch.mousedown(e, point);
    }
    DOM.disableDrag();
};
MouseRotateWrapper.prototype.move = function move(e, point) {
    var map = this.map;
    var r = this.mouseRotate.mousemoveWindow(e, point);
    if (r && r.bearingDelta) {
        map.setBearing(map.getBearing() + r.bearingDelta);
    }
    if (this.mousePitch) {
        var p = this.mousePitch.mousemoveWindow(e, point);
        if (p && p.pitchDelta) {
            map.setPitch(map.getPitch() + p.pitchDelta);
        }
    }
};
MouseRotateWrapper.prototype.off = function off() {
    var element = this.element;
    DOM.removeEventListener(element, 'mousedown', this.mousedown);
    DOM.removeEventListener(element, 'touchstart', this.touchstart, { passive: false });
    DOM.removeEventListener(element, 'touchmove', this.touchmove);
    DOM.removeEventListener(element, 'touchend', this.touchend);
    DOM.removeEventListener(element, 'touchcancel', this.reset);
    this.offTemp();
};
MouseRotateWrapper.prototype.offTemp = function offTemp() {
    DOM.enableDrag();
    DOM.removeEventListener(performance.window, 'mousemove', this.mousemove);
    DOM.removeEventListener(performance.window, 'mouseup', this.mouseup);
};
MouseRotateWrapper.prototype.mousedown = function mousedown(e) {
    this.down(performance.extend({}, e, {
        ctrlKey: true,
        preventDefault: function () {
            return e.preventDefault();
        }
    }), DOM.mousePos(this.element, e));
    DOM.addEventListener(performance.window, 'mousemove', this.mousemove);
    DOM.addEventListener(performance.window, 'mouseup', this.mouseup);
};
MouseRotateWrapper.prototype.mousemove = function mousemove(e) {
    this.move(e, DOM.mousePos(this.element, e));
};
MouseRotateWrapper.prototype.mouseup = function mouseup(e) {
    this.mouseRotate.mouseupWindow(e);
    if (this.mousePitch) {
        this.mousePitch.mouseupWindow(e);
    }
    this.offTemp();
};
MouseRotateWrapper.prototype.touchstart = function touchstart(e) {
    if (e.targetTouches.length !== 1) {
        this.reset();
    } else {
        this._startPos = this._lastPos = DOM.touchPos(this.element, e.targetTouches)[0];
        this.down({
            type: 'mousedown',
            button: 0,
            ctrlKey: true,
            preventDefault: function () {
                return e.preventDefault();
            }
        }, this._startPos);
    }
};
MouseRotateWrapper.prototype.touchmove = function touchmove(e) {
    if (e.targetTouches.length !== 1) {
        this.reset();
    } else {
        this._lastPos = DOM.touchPos(this.element, e.targetTouches)[0];
        this.move({
            preventDefault: function () {
                return e.preventDefault();
            }
        }, this._lastPos);
    }
};
MouseRotateWrapper.prototype.touchend = function touchend(e) {
    if (e.targetTouches.length === 0 && this._startPos && this._lastPos && this._startPos.dist(this._lastPos) < this._clickTolerance) {
        this.element.click();
    }
    this.reset();
};
MouseRotateWrapper.prototype.reset = function reset() {
    this.mouseRotate.reset();
    if (this.mousePitch) {
        this.mousePitch.reset();
    }
    delete this._startPos;
    delete this._lastPos;
    this.offTemp();
};

function smartWrap (lngLat, priorPos, transform) {
    lngLat = new performance.LngLat(lngLat.lng, lngLat.lat);
    if (priorPos) {
        var left = new performance.LngLat(lngLat.lng - 360, lngLat.lat);
        var right = new performance.LngLat(lngLat.lng + 360, lngLat.lat);
        var delta = transform.locationPoint(lngLat).distSqr(priorPos);
        if (transform.locationPoint(left).distSqr(priorPos) < delta) {
            lngLat = left;
        } else if (transform.locationPoint(right).distSqr(priorPos) < delta) {
            lngLat = right;
        }
    }
    while (Math.abs(lngLat.lng - transform.center.lng) > 180) {
        var pos = transform.locationPoint(lngLat);
        if (pos.x >= 0 && pos.y >= 0 && pos.x <= transform.width && pos.y <= transform.height) {
            break;
        }
        if (lngLat.lng > transform.center.lng) {
            lngLat.lng -= 360;
        } else {
            lngLat.lng += 360;
        }
    }
    return lngLat;
}

var anchorTranslate = {
    'center': 'translate(-50%,-50%)',
    'top': 'translate(-50%,0)',
    'top-left': 'translate(0,0)',
    'top-right': 'translate(-100%,0)',
    'bottom': 'translate(-50%,-100%)',
    'bottom-left': 'translate(0,-100%)',
    'bottom-right': 'translate(-100%,-100%)',
    'left': 'translate(0,-50%)',
    'right': 'translate(-100%,-50%)'
};
function applyAnchorClass(element, anchor, prefix) {
    var classList = element.classList;
    for (var key in anchorTranslate) {
        classList.remove('mapboxgl-' + prefix + '-anchor-' + key);
    }
    classList.add('mapboxgl-' + prefix + '-anchor-' + anchor);
}

var Marker = function (Evented) {
    function Marker(options, legacyOptions) {
        Evented.call(this);
        if (options instanceof performance.window.HTMLElement || legacyOptions) {
            options = performance.extend({ element: options }, legacyOptions);
        }
        performance.bindAll([
            '_update',
            '_onMove',
            '_onUp',
            '_addDragHandler',
            '_onMapClick',
            '_onKeyPress'
        ], this);
        this._anchor = options && options.anchor || 'center';
        this._color = options && options.color || '#3FB1CE';
        this._scale = options && options.scale || 1;
        this._draggable = options && options.draggable || false;
        this._clickTolerance = options && options.clickTolerance || 0;
        this._isDragging = false;
        this._state = 'inactive';
        this._rotation = options && options.rotation || 0;
        this._rotationAlignment = options && options.rotationAlignment || 'auto';
        this._pitchAlignment = options && options.pitchAlignment && options.pitchAlignment !== 'auto' ? options.pitchAlignment : this._rotationAlignment;
        if (!options || !options.element) {
            this._defaultMarker = true;
            this._element = DOM.create('div');
            this._element.setAttribute('aria-label', 'Map marker');
            var svg = DOM.createNS('http://www.w3.org/2000/svg', 'svg');
            var defaultHeight = 41;
            var defaultWidth = 27;
            svg.setAttributeNS(null, 'display', 'block');
            svg.setAttributeNS(null, 'height', defaultHeight + 'px');
            svg.setAttributeNS(null, 'width', defaultWidth + 'px');
            svg.setAttributeNS(null, 'viewBox', '0 0 ' + defaultWidth + ' ' + defaultHeight);
            var markerLarge = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            markerLarge.setAttributeNS(null, 'stroke', 'none');
            markerLarge.setAttributeNS(null, 'stroke-width', '1');
            markerLarge.setAttributeNS(null, 'fill', 'none');
            markerLarge.setAttributeNS(null, 'fill-rule', 'evenodd');
            var page1 = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            page1.setAttributeNS(null, 'fill-rule', 'nonzero');
            var shadow = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            shadow.setAttributeNS(null, 'transform', 'translate(3.0, 29.0)');
            shadow.setAttributeNS(null, 'fill', '#000000');
            var ellipses = [
                {
                    'rx': '10.5',
                    'ry': '5.25002273'
                },
                {
                    'rx': '10.5',
                    'ry': '5.25002273'
                },
                {
                    'rx': '9.5',
                    'ry': '4.77275007'
                },
                {
                    'rx': '8.5',
                    'ry': '4.29549936'
                },
                {
                    'rx': '7.5',
                    'ry': '3.81822308'
                },
                {
                    'rx': '6.5',
                    'ry': '3.34094679'
                },
                {
                    'rx': '5.5',
                    'ry': '2.86367051'
                },
                {
                    'rx': '4.5',
                    'ry': '2.38636864'
                }
            ];
            for (var i = 0, list = ellipses; i < list.length; i += 1) {
                var data = list[i];
                var ellipse = DOM.createNS('http://www.w3.org/2000/svg', 'ellipse');
                ellipse.setAttributeNS(null, 'opacity', '0.04');
                ellipse.setAttributeNS(null, 'cx', '10.5');
                ellipse.setAttributeNS(null, 'cy', '5.80029008');
                ellipse.setAttributeNS(null, 'rx', data['rx']);
                ellipse.setAttributeNS(null, 'ry', data['ry']);
                shadow.appendChild(ellipse);
            }
            var background = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            background.setAttributeNS(null, 'fill', this._color);
            var bgPath = DOM.createNS('http://www.w3.org/2000/svg', 'path');
            bgPath.setAttributeNS(null, 'd', 'M27,13.5 C27,19.074644 20.250001,27.000002 14.75,34.500002 C14.016665,35.500004 12.983335,35.500004 12.25,34.500002 C6.7499993,27.000002 0,19.222562 0,13.5 C0,6.0441559 6.0441559,0 13.5,0 C20.955844,0 27,6.0441559 27,13.5 Z');
            background.appendChild(bgPath);
            var border = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            border.setAttributeNS(null, 'opacity', '0.25');
            border.setAttributeNS(null, 'fill', '#000000');
            var borderPath = DOM.createNS('http://www.w3.org/2000/svg', 'path');
            borderPath.setAttributeNS(null, 'd', 'M13.5,0 C6.0441559,0 0,6.0441559 0,13.5 C0,19.222562 6.7499993,27 12.25,34.5 C13,35.522727 14.016664,35.500004 14.75,34.5 C20.250001,27 27,19.074644 27,13.5 C27,6.0441559 20.955844,0 13.5,0 Z M13.5,1 C20.415404,1 26,6.584596 26,13.5 C26,15.898657 24.495584,19.181431 22.220703,22.738281 C19.945823,26.295132 16.705119,30.142167 13.943359,33.908203 C13.743445,34.180814 13.612715,34.322738 13.5,34.441406 C13.387285,34.322738 13.256555,34.180814 13.056641,33.908203 C10.284481,30.127985 7.4148684,26.314159 5.015625,22.773438 C2.6163816,19.232715 1,15.953538 1,13.5 C1,6.584596 6.584596,1 13.5,1 Z');
            border.appendChild(borderPath);
            var maki = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            maki.setAttributeNS(null, 'transform', 'translate(6.0, 7.0)');
            maki.setAttributeNS(null, 'fill', '#FFFFFF');
            var circleContainer = DOM.createNS('http://www.w3.org/2000/svg', 'g');
            circleContainer.setAttributeNS(null, 'transform', 'translate(8.0, 8.0)');
            var circle1 = DOM.createNS('http://www.w3.org/2000/svg', 'circle');
            circle1.setAttributeNS(null, 'fill', '#000000');
            circle1.setAttributeNS(null, 'opacity', '0.25');
            circle1.setAttributeNS(null, 'cx', '5.5');
            circle1.setAttributeNS(null, 'cy', '5.5');
            circle1.setAttributeNS(null, 'r', '5.4999962');
            var circle2 = DOM.createNS('http://www.w3.org/2000/svg', 'circle');
            circle2.setAttributeNS(null, 'fill', '#FFFFFF');
            circle2.setAttributeNS(null, 'cx', '5.5');
            circle2.setAttributeNS(null, 'cy', '5.5');
            circle2.setAttributeNS(null, 'r', '5.4999962');
            circleContainer.appendChild(circle1);
            circleContainer.appendChild(circle2);
            page1.appendChild(shadow);
            page1.appendChild(background);
            page1.appendChild(border);
            page1.appendChild(maki);
            page1.appendChild(circleContainer);
            svg.appendChild(page1);
            svg.setAttributeNS(null, 'height', defaultHeight * this._scale + 'px');
            svg.setAttributeNS(null, 'width', defaultWidth * this._scale + 'px');
            this._element.appendChild(svg);
            this._offset = performance.Point.convert(options && options.offset || [
                0,
                -14
            ]);
        } else {
            this._element = options.element;
            this._offset = performance.Point.convert(options && options.offset || [
                0,
                0
            ]);
        }
        this._element.classList.add('mapboxgl-marker');
        this._element.addEventListener('dragstart', function (e) {
            e.preventDefault();
        });
        this._element.addEventListener('mousedown', function (e) {
            e.preventDefault();
        });
        applyAnchorClass(this._element, this._anchor, 'marker');
        this._popup = null;
    }
    if (Evented)
        Marker.__proto__ = Evented;
    Marker.prototype = Object.create(Evented && Evented.prototype);
    Marker.prototype.constructor = Marker;
    Marker.prototype.addTo = function addTo(map) {
        this.remove();
        this._map = map;
        map.getCanvasContainer().appendChild(this._element);
        map.on('move', this._update);
        map.on('moveend', this._update);
        this.setDraggable(this._draggable);
        this._update();
        this._map.on('click', this._onMapClick);
        return this;
    };
    Marker.prototype.remove = function remove() {
        if (this._map) {
            this._map.off('click', this._onMapClick);
            this._map.off('move', this._update);
            this._map.off('moveend', this._update);
            this._map.off('mousedown', this._addDragHandler);
            this._map.off('touchstart', this._addDragHandler);
            this._map.off('mouseup', this._onUp);
            this._map.off('touchend', this._onUp);
            this._map.off('mousemove', this._onMove);
            this._map.off('touchmove', this._onMove);
            delete this._map;
        }
        DOM.remove(this._element);
        if (this._popup) {
            this._popup.remove();
        }
        return this;
    };
    Marker.prototype.getLngLat = function getLngLat() {
        return this._lngLat;
    };
    Marker.prototype.setLngLat = function setLngLat(lnglat) {
        this._lngLat = performance.LngLat.convert(lnglat);
        this._pos = null;
        if (this._popup) {
            this._popup.setLngLat(this._lngLat);
        }
        this._update();
        return this;
    };
    Marker.prototype.getElement = function getElement() {
        return this._element;
    };
    Marker.prototype.setPopup = function setPopup(popup) {
        if (this._popup) {
            this._popup.remove();
            this._popup = null;
            this._element.removeEventListener('keypress', this._onKeyPress);
            if (!this._originalTabIndex) {
                this._element.removeAttribute('tabindex');
            }
        }
        if (popup) {
            if (!('offset' in popup.options)) {
                var markerHeight = 41 - 5.8 / 2;
                var markerRadius = 13.5;
                var linearOffset = Math.sqrt(Math.pow(markerRadius, 2) / 2);
                popup.options.offset = this._defaultMarker ? {
                    'top': [
                        0,
                        0
                    ],
                    'top-left': [
                        0,
                        0
                    ],
                    'top-right': [
                        0,
                        0
                    ],
                    'bottom': [
                        0,
                        -markerHeight
                    ],
                    'bottom-left': [
                        linearOffset,
                        (markerHeight - markerRadius + linearOffset) * -1
                    ],
                    'bottom-right': [
                        -linearOffset,
                        (markerHeight - markerRadius + linearOffset) * -1
                    ],
                    'left': [
                        markerRadius,
                        (markerHeight - markerRadius) * -1
                    ],
                    'right': [
                        -markerRadius,
                        (markerHeight - markerRadius) * -1
                    ]
                } : this._offset;
            }
            this._popup = popup;
            if (this._lngLat) {
                this._popup.setLngLat(this._lngLat);
            }
            this._originalTabIndex = this._element.getAttribute('tabindex');
            if (!this._originalTabIndex) {
                this._element.setAttribute('tabindex', '0');
            }
            this._element.addEventListener('keypress', this._onKeyPress);
        }
        return this;
    };
    Marker.prototype._onKeyPress = function _onKeyPress(e) {
        var code = e.code;
        var legacyCode = e.charCode || e.keyCode;
        if (code === 'Space' || code === 'Enter' || legacyCode === 32 || legacyCode === 13) {
            this.togglePopup();
        }
    };
    Marker.prototype._onMapClick = function _onMapClick(e) {
        var targetElement = e.originalEvent.target;
        var element = this._element;
        if (this._popup && (targetElement === element || element.contains(targetElement))) {
            this.togglePopup();
        }
    };
    Marker.prototype.getPopup = function getPopup() {
        return this._popup;
    };
    Marker.prototype.togglePopup = function togglePopup() {
        var popup = this._popup;
        if (!popup) {
            return this;
        } else if (popup.isOpen()) {
            popup.remove();
        } else {
            popup.addTo(this._map);
        }
        return this;
    };
    Marker.prototype._update = function _update(e) {
        if (!this._map) {
            return;
        }
        if (this._map.transform.renderWorldCopies) {
            this._lngLat = smartWrap(this._lngLat, this._pos, this._map.transform);
        }
        this._pos = this._map.project(this._lngLat)._add(this._offset);
        var rotation = '';
        if (this._rotationAlignment === 'viewport' || this._rotationAlignment === 'auto') {
            rotation = 'rotateZ(' + this._rotation + 'deg)';
        } else if (this._rotationAlignment === 'map') {
            rotation = 'rotateZ(' + (this._rotation - this._map.getBearing()) + 'deg)';
        }
        var pitch = '';
        if (this._pitchAlignment === 'viewport' || this._pitchAlignment === 'auto') {
            pitch = 'rotateX(0deg)';
        } else if (this._pitchAlignment === 'map') {
            pitch = 'rotateX(' + this._map.getPitch() + 'deg)';
        }
        if (!e || e.type === 'moveend') {
            this._pos = this._pos.round();
        }
        DOM.setTransform(this._element, anchorTranslate[this._anchor] + ' translate(' + this._pos.x + 'px, ' + this._pos.y + 'px) ' + pitch + ' ' + rotation);
    };
    Marker.prototype.getOffset = function getOffset() {
        return this._offset;
    };
    Marker.prototype.setOffset = function setOffset(offset) {
        this._offset = performance.Point.convert(offset);
        this._update();
        return this;
    };
    Marker.prototype._onMove = function _onMove(e) {
        if (!this._isDragging) {
            var clickTolerance = this._clickTolerance || this._map._clickTolerance;
            this._isDragging = e.point.dist(this._pointerdownPos) >= clickTolerance;
        }
        if (!this._isDragging) {
            return;
        }
        this._pos = e.point.sub(this._positionDelta);
        this._lngLat = this._map.unproject(this._pos);
        this.setLngLat(this._lngLat);
        this._element.style.pointerEvents = 'none';
        if (this._state === 'pending') {
            this._state = 'active';
            this.fire(new performance.Event('dragstart'));
        }
        this.fire(new performance.Event('drag'));
    };
    Marker.prototype._onUp = function _onUp() {
        this._element.style.pointerEvents = 'auto';
        this._positionDelta = null;
        this._pointerdownPos = null;
        this._isDragging = false;
        this._map.off('mousemove', this._onMove);
        this._map.off('touchmove', this._onMove);
        if (this._state === 'active') {
            this.fire(new performance.Event('dragend'));
        }
        this._state = 'inactive';
    };
    Marker.prototype._addDragHandler = function _addDragHandler(e) {
        if (this._element.contains(e.originalEvent.target)) {
            e.preventDefault();
            this._positionDelta = e.point.sub(this._pos).add(this._offset);
            this._pointerdownPos = e.point;
            this._state = 'pending';
            this._map.on('mousemove', this._onMove);
            this._map.on('touchmove', this._onMove);
            this._map.once('mouseup', this._onUp);
            this._map.once('touchend', this._onUp);
        }
    };
    Marker.prototype.setDraggable = function setDraggable(shouldBeDraggable) {
        this._draggable = !!shouldBeDraggable;
        if (this._map) {
            if (shouldBeDraggable) {
                this._map.on('mousedown', this._addDragHandler);
                this._map.on('touchstart', this._addDragHandler);
            } else {
                this._map.off('mousedown', this._addDragHandler);
                this._map.off('touchstart', this._addDragHandler);
            }
        }
        return this;
    };
    Marker.prototype.isDraggable = function isDraggable() {
        return this._draggable;
    };
    Marker.prototype.setRotation = function setRotation(rotation) {
        this._rotation = rotation || 0;
        this._update();
        return this;
    };
    Marker.prototype.getRotation = function getRotation() {
        return this._rotation;
    };
    Marker.prototype.setRotationAlignment = function setRotationAlignment(alignment) {
        this._rotationAlignment = alignment || 'auto';
        this._update();
        return this;
    };
    Marker.prototype.getRotationAlignment = function getRotationAlignment() {
        return this._rotationAlignment;
    };
    Marker.prototype.setPitchAlignment = function setPitchAlignment(alignment) {
        this._pitchAlignment = alignment && alignment !== 'auto' ? alignment : this._rotationAlignment;
        this._update();
        return this;
    };
    Marker.prototype.getPitchAlignment = function getPitchAlignment() {
        return this._pitchAlignment;
    };
    return Marker;
}(performance.Evented);

var defaultOptions$3 = {
    positionOptions: {
        enableHighAccuracy: false,
        maximumAge: 0,
        timeout: 6000
    },
    fitBoundsOptions: { maxZoom: 15 },
    trackUserLocation: false,
    showAccuracyCircle: true,
    showUserLocation: true
};
var supportsGeolocation;
function checkGeolocationSupport(callback) {
    if (supportsGeolocation !== undefined) {
        callback(supportsGeolocation);
    } else if (performance.window.navigator.permissions !== undefined) {
        performance.window.navigator.permissions.query({ name: 'geolocation' }).then(function (p) {
            supportsGeolocation = p.state !== 'denied';
            callback(supportsGeolocation);
        });
    } else {
        supportsGeolocation = !!performance.window.navigator.geolocation;
        callback(supportsGeolocation);
    }
}
var numberOfWatches = 0;
var noTimeout = false;
var GeolocateControl = function (Evented) {
    function GeolocateControl(options) {
        Evented.call(this);
        this.options = performance.extend({}, defaultOptions$3, options);
        performance.bindAll([
            '_onSuccess',
            '_onError',
            '_onZoom',
            '_finish',
            '_setupUI',
            '_updateCamera',
            '_updateMarker'
        ], this);
    }
    if (Evented)
        GeolocateControl.__proto__ = Evented;
    GeolocateControl.prototype = Object.create(Evented && Evented.prototype);
    GeolocateControl.prototype.constructor = GeolocateControl;
    GeolocateControl.prototype.onAdd = function onAdd(map) {
        this._map = map;
        this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-group');
        checkGeolocationSupport(this._setupUI);
        return this._container;
    };
    GeolocateControl.prototype.onRemove = function onRemove() {
        if (this._geolocationWatchID !== undefined) {
            performance.window.navigator.geolocation.clearWatch(this._geolocationWatchID);
            this._geolocationWatchID = undefined;
        }
        if (this.options.showUserLocation && this._userLocationDotMarker) {
            this._userLocationDotMarker.remove();
        }
        if (this.options.showAccuracyCircle && this._accuracyCircleMarker) {
            this._accuracyCircleMarker.remove();
        }
        DOM.remove(this._container);
        this._map.off('zoom', this._onZoom);
        this._map = undefined;
        numberOfWatches = 0;
        noTimeout = false;
    };
    GeolocateControl.prototype._isOutOfMapMaxBounds = function _isOutOfMapMaxBounds(position) {
        var bounds = this._map.getMaxBounds();
        var coordinates = position.coords;
        return bounds && (coordinates.longitude < bounds.getWest() || coordinates.longitude > bounds.getEast() || coordinates.latitude < bounds.getSouth() || coordinates.latitude > bounds.getNorth());
    };
    GeolocateControl.prototype._setErrorState = function _setErrorState() {
        switch (this._watchState) {
        case 'WAITING_ACTIVE':
            this._watchState = 'ACTIVE_ERROR';
            this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active');
            this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-active-error');
            break;
        case 'ACTIVE_LOCK':
            this._watchState = 'ACTIVE_ERROR';
            this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active');
            this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-active-error');
            this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-waiting');
            break;
        case 'BACKGROUND':
            this._watchState = 'BACKGROUND_ERROR';
            this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background');
            this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-background-error');
            this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-waiting');
            break;
        }
    };
    GeolocateControl.prototype._onSuccess = function _onSuccess(position) {
        if (!this._map) {
            return;
        }
        if (this._isOutOfMapMaxBounds(position)) {
            this._setErrorState();
            this.fire(new performance.Event('outofmaxbounds', position));
            this._updateMarker();
            this._finish();
            return;
        }
        if (this.options.trackUserLocation) {
            this._lastKnownPosition = position;
            switch (this._watchState) {
            case 'WAITING_ACTIVE':
            case 'ACTIVE_LOCK':
            case 'ACTIVE_ERROR':
                this._watchState = 'ACTIVE_LOCK';
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active-error');
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-active');
                break;
            case 'BACKGROUND':
            case 'BACKGROUND_ERROR':
                this._watchState = 'BACKGROUND';
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background-error');
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-background');
                break;
            }
        }
        if (this.options.showUserLocation && this._watchState !== 'OFF') {
            this._updateMarker(position);
        }
        if (!this.options.trackUserLocation || this._watchState === 'ACTIVE_LOCK') {
            this._updateCamera(position);
        }
        if (this.options.showUserLocation) {
            this._dotElement.classList.remove('mapboxgl-user-location-dot-stale');
        }
        this.fire(new performance.Event('geolocate', position));
        this._finish();
    };
    GeolocateControl.prototype._updateCamera = function _updateCamera(position) {
        var center = new performance.LngLat(position.coords.longitude, position.coords.latitude);
        var radius = position.coords.accuracy;
        var bearing = this._map.getBearing();
        var options = performance.extend({ bearing: bearing }, this.options.fitBoundsOptions);
        this._map.fitBounds(center.toBounds(radius), options, { geolocateSource: true });
    };
    GeolocateControl.prototype._updateMarker = function _updateMarker(position) {
        if (position) {
            var center = new performance.LngLat(position.coords.longitude, position.coords.latitude);
            this._accuracyCircleMarker.setLngLat(center).addTo(this._map);
            this._userLocationDotMarker.setLngLat(center).addTo(this._map);
            this._accuracy = position.coords.accuracy;
            if (this.options.showUserLocation && this.options.showAccuracyCircle) {
                this._updateCircleRadius();
            }
        } else {
            this._userLocationDotMarker.remove();
            this._accuracyCircleMarker.remove();
        }
    };
    GeolocateControl.prototype._updateCircleRadius = function _updateCircleRadius() {
        var y = this._map._container.clientHeight / 2;
        var a = this._map.unproject([
            0,
            y
        ]);
        var b = this._map.unproject([
            1,
            y
        ]);
        var metersPerPixel = a.distanceTo(b);
        var circleDiameter = Math.ceil(2 * this._accuracy / metersPerPixel);
        this._circleElement.style.width = circleDiameter + 'px';
        this._circleElement.style.height = circleDiameter + 'px';
    };
    GeolocateControl.prototype._onZoom = function _onZoom() {
        if (this.options.showUserLocation && this.options.showAccuracyCircle) {
            this._updateCircleRadius();
        }
    };
    GeolocateControl.prototype._onError = function _onError(error) {
        if (!this._map) {
            return;
        }
        if (this.options.trackUserLocation) {
            if (error.code === 1) {
                this._watchState = 'OFF';
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active-error');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background-error');
                this._geolocateButton.disabled = true;
                var title = this._map._getUIString('GeolocateControl.LocationNotAvailable');
                this._geolocateButton.title = title;
                this._geolocateButton.setAttribute('aria-label', title);
                if (this._geolocationWatchID !== undefined) {
                    this._clearWatch();
                }
            } else if (error.code === 3 && noTimeout) {
                return;
            } else {
                this._setErrorState();
            }
        }
        if (this._watchState !== 'OFF' && this.options.showUserLocation) {
            this._dotElement.classList.add('mapboxgl-user-location-dot-stale');
        }
        this.fire(new performance.Event('error', error));
        this._finish();
    };
    GeolocateControl.prototype._finish = function _finish() {
        if (this._timeoutId) {
            clearTimeout(this._timeoutId);
        }
        this._timeoutId = undefined;
    };
    GeolocateControl.prototype._setupUI = function _setupUI(supported) {
        var this$1 = this;
        this._container.addEventListener('contextmenu', function (e) {
            return e.preventDefault();
        });
        this._geolocateButton = DOM.create('button', 'mapboxgl-ctrl-geolocate', this._container);
        DOM.create('span', 'mapboxgl-ctrl-icon', this._geolocateButton).setAttribute('aria-hidden', true);
        this._geolocateButton.type = 'button';
        if (supported === false) {
            performance.warnOnce('Geolocation support is not available so the GeolocateControl will be disabled.');
            var title = this._map._getUIString('GeolocateControl.LocationNotAvailable');
            this._geolocateButton.disabled = true;
            this._geolocateButton.title = title;
            this._geolocateButton.setAttribute('aria-label', title);
        } else {
            var title$1 = this._map._getUIString('GeolocateControl.FindMyLocation');
            this._geolocateButton.title = title$1;
            this._geolocateButton.setAttribute('aria-label', title$1);
        }
        if (this.options.trackUserLocation) {
            this._geolocateButton.setAttribute('aria-pressed', 'false');
            this._watchState = 'OFF';
        }
        if (this.options.showUserLocation) {
            this._dotElement = DOM.create('div', 'mapboxgl-user-location-dot');
            this._userLocationDotMarker = new Marker(this._dotElement);
            this._circleElement = DOM.create('div', 'mapboxgl-user-location-accuracy-circle');
            this._accuracyCircleMarker = new Marker({
                element: this._circleElement,
                pitchAlignment: 'map'
            });
            if (this.options.trackUserLocation) {
                this._watchState = 'OFF';
            }
            this._map.on('zoom', this._onZoom);
        }
        this._geolocateButton.addEventListener('click', this.trigger.bind(this));
        this._setup = true;
        if (this.options.trackUserLocation) {
            this._map.on('movestart', function (event) {
                var fromResize = event.originalEvent && event.originalEvent.type === 'resize';
                if (!event.geolocateSource && this$1._watchState === 'ACTIVE_LOCK' && !fromResize) {
                    this$1._watchState = 'BACKGROUND';
                    this$1._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-background');
                    this$1._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active');
                    this$1.fire(new performance.Event('trackuserlocationend'));
                }
            });
        }
    };
    GeolocateControl.prototype.trigger = function trigger() {
        if (!this._setup) {
            performance.warnOnce('Geolocate control triggered before added to a map');
            return false;
        }
        if (this.options.trackUserLocation) {
            switch (this._watchState) {
            case 'OFF':
                this._watchState = 'WAITING_ACTIVE';
                this.fire(new performance.Event('trackuserlocationstart'));
                break;
            case 'WAITING_ACTIVE':
            case 'ACTIVE_LOCK':
            case 'ACTIVE_ERROR':
            case 'BACKGROUND_ERROR':
                numberOfWatches--;
                noTimeout = false;
                this._watchState = 'OFF';
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-active-error');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background');
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background-error');
                this.fire(new performance.Event('trackuserlocationend'));
                break;
            case 'BACKGROUND':
                this._watchState = 'ACTIVE_LOCK';
                this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-background');
                if (this._lastKnownPosition) {
                    this._updateCamera(this._lastKnownPosition);
                }
                this.fire(new performance.Event('trackuserlocationstart'));
                break;
            }
            switch (this._watchState) {
            case 'WAITING_ACTIVE':
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-active');
                break;
            case 'ACTIVE_LOCK':
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-active');
                break;
            case 'ACTIVE_ERROR':
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-active-error');
                break;
            case 'BACKGROUND':
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-background');
                break;
            case 'BACKGROUND_ERROR':
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-background-error');
                break;
            }
            if (this._watchState === 'OFF' && this._geolocationWatchID !== undefined) {
                this._clearWatch();
            } else if (this._geolocationWatchID === undefined) {
                this._geolocateButton.classList.add('mapboxgl-ctrl-geolocate-waiting');
                this._geolocateButton.setAttribute('aria-pressed', 'true');
                numberOfWatches++;
                var positionOptions;
                if (numberOfWatches > 1) {
                    positionOptions = {
                        maximumAge: 600000,
                        timeout: 0
                    };
                    noTimeout = true;
                } else {
                    positionOptions = this.options.positionOptions;
                    noTimeout = false;
                }
                this._geolocationWatchID = performance.window.navigator.geolocation.watchPosition(this._onSuccess, this._onError, positionOptions);
            }
        } else {
            performance.window.navigator.geolocation.getCurrentPosition(this._onSuccess, this._onError, this.options.positionOptions);
            this._timeoutId = setTimeout(this._finish, 10000);
        }
        return true;
    };
    GeolocateControl.prototype._clearWatch = function _clearWatch() {
        performance.window.navigator.geolocation.clearWatch(this._geolocationWatchID);
        this._geolocationWatchID = undefined;
        this._geolocateButton.classList.remove('mapboxgl-ctrl-geolocate-waiting');
        this._geolocateButton.setAttribute('aria-pressed', 'false');
        if (this.options.showUserLocation) {
            this._updateMarker(null);
        }
    };
    return GeolocateControl;
}(performance.Evented);

var defaultOptions$4 = {
    maxWidth: 100,
    unit: 'metric'
};
var ScaleControl = function ScaleControl(options) {
    this.options = performance.extend({}, defaultOptions$4, options);
    performance.bindAll([
        '_onMove',
        'setUnit'
    ], this);
};
ScaleControl.prototype.getDefaultPosition = function getDefaultPosition() {
    return 'bottom-left';
};
ScaleControl.prototype._onMove = function _onMove() {
    updateScale(this._map, this._container, this.options);
};
ScaleControl.prototype.onAdd = function onAdd(map) {
    this._map = map;
    this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-scale', map.getContainer());
    this._map.on('move', this._onMove);
    this._onMove();
    return this._container;
};
ScaleControl.prototype.onRemove = function onRemove() {
    DOM.remove(this._container);
    this._map.off('move', this._onMove);
    this._map = undefined;
};
ScaleControl.prototype.setUnit = function setUnit(unit) {
    this.options.unit = unit;
    updateScale(this._map, this._container, this.options);
};
function updateScale(map, container, options) {
    var maxWidth = options && options.maxWidth || 100;
    var y = map._container.clientHeight / 2;
    var left = map.unproject([
        0,
        y
    ]);
    var right = map.unproject([
        maxWidth,
        y
    ]);
    var maxMeters = left.distanceTo(right);
    if (options && options.unit === 'imperial') {
        var maxFeet = 3.2808 * maxMeters;
        if (maxFeet > 5280) {
            var maxMiles = maxFeet / 5280;
            setScale(container, maxWidth, maxMiles, map._getUIString('ScaleControl.Miles'));
        } else {
            setScale(container, maxWidth, maxFeet, map._getUIString('ScaleControl.Feet'));
        }
    } else if (options && options.unit === 'nautical') {
        var maxNauticals = maxMeters / 1852;
        setScale(container, maxWidth, maxNauticals, map._getUIString('ScaleControl.NauticalMiles'));
    } else if (maxMeters >= 1000) {
        setScale(container, maxWidth, maxMeters / 1000, map._getUIString('ScaleControl.Kilometers'));
    } else {
        setScale(container, maxWidth, maxMeters, map._getUIString('ScaleControl.Meters'));
    }
}
function setScale(container, maxWidth, maxDistance, unit) {
    var distance = getRoundNum(maxDistance);
    var ratio = distance / maxDistance;
    container.style.width = maxWidth * ratio + 'px';
    container.innerHTML = distance + '&nbsp;' + unit;
}
function getDecimalRoundNum(d) {
    var multiplier = Math.pow(10, Math.ceil(-Math.log(d) / Math.LN10));
    return Math.round(d * multiplier) / multiplier;
}
function getRoundNum(num) {
    var pow10 = Math.pow(10, ('' + Math.floor(num)).length - 1);
    var d = num / pow10;
    d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : d >= 1 ? 1 : getDecimalRoundNum(d);
    return pow10 * d;
}

var FullscreenControl = function FullscreenControl(options) {
    this._fullscreen = false;
    if (options && options.container) {
        if (options.container instanceof performance.window.HTMLElement) {
            this._container = options.container;
        } else {
            performance.warnOnce('Full screen control \'container\' must be a DOM element.');
        }
    }
    performance.bindAll([
        '_onClickFullscreen',
        '_changeIcon'
    ], this);
    if ('onfullscreenchange' in performance.window.document) {
        this._fullscreenchange = 'fullscreenchange';
    } else if ('onmozfullscreenchange' in performance.window.document) {
        this._fullscreenchange = 'mozfullscreenchange';
    } else if ('onwebkitfullscreenchange' in performance.window.document) {
        this._fullscreenchange = 'webkitfullscreenchange';
    } else if ('onmsfullscreenchange' in performance.window.document) {
        this._fullscreenchange = 'MSFullscreenChange';
    }
};
FullscreenControl.prototype.onAdd = function onAdd(map) {
    this._map = map;
    if (!this._container) {
        this._container = this._map.getContainer();
    }
    this._controlContainer = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-group');
    if (this._checkFullscreenSupport()) {
        this._setupUI();
    } else {
        this._controlContainer.style.display = 'none';
        performance.warnOnce('This device does not support fullscreen mode.');
    }
    return this._controlContainer;
};
FullscreenControl.prototype.onRemove = function onRemove() {
    DOM.remove(this._controlContainer);
    this._map = null;
    performance.window.document.removeEventListener(this._fullscreenchange, this._changeIcon);
};
FullscreenControl.prototype._checkFullscreenSupport = function _checkFullscreenSupport() {
    return !!(performance.window.document.fullscreenEnabled || performance.window.document.mozFullScreenEnabled || performance.window.document.msFullscreenEnabled || performance.window.document.webkitFullscreenEnabled);
};
FullscreenControl.prototype._setupUI = function _setupUI() {
    var button = this._fullscreenButton = DOM.create('button', 'mapboxgl-ctrl-fullscreen', this._controlContainer);
    DOM.create('span', 'mapboxgl-ctrl-icon', button).setAttribute('aria-hidden', true);
    button.type = 'button';
    this._updateTitle();
    this._fullscreenButton.addEventListener('click', this._onClickFullscreen);
    performance.window.document.addEventListener(this._fullscreenchange, this._changeIcon);
};
FullscreenControl.prototype._updateTitle = function _updateTitle() {
    var title = this._getTitle();
    this._fullscreenButton.setAttribute('aria-label', title);
    this._fullscreenButton.title = title;
};
FullscreenControl.prototype._getTitle = function _getTitle() {
    return this._map._getUIString(this._isFullscreen() ? 'FullscreenControl.Exit' : 'FullscreenControl.Enter');
};
FullscreenControl.prototype._isFullscreen = function _isFullscreen() {
    return this._fullscreen;
};
FullscreenControl.prototype._changeIcon = function _changeIcon() {
    var fullscreenElement = performance.window.document.fullscreenElement || performance.window.document.mozFullScreenElement || performance.window.document.webkitFullscreenElement || performance.window.document.msFullscreenElement;
    if (fullscreenElement === this._container !== this._fullscreen) {
        this._fullscreen = !this._fullscreen;
        this._fullscreenButton.classList.toggle('mapboxgl-ctrl-shrink');
        this._fullscreenButton.classList.toggle('mapboxgl-ctrl-fullscreen');
        this._updateTitle();
    }
};
FullscreenControl.prototype._onClickFullscreen = function _onClickFullscreen() {
    if (this._isFullscreen()) {
        if (performance.window.document.exitFullscreen) {
            performance.window.document.exitFullscreen();
        } else if (performance.window.document.mozCancelFullScreen) {
            performance.window.document.mozCancelFullScreen();
        } else if (performance.window.document.msExitFullscreen) {
            performance.window.document.msExitFullscreen();
        } else if (performance.window.document.webkitCancelFullScreen) {
            performance.window.document.webkitCancelFullScreen();
        }
    } else if (this._container.requestFullscreen) {
        this._container.requestFullscreen();
    } else if (this._container.mozRequestFullScreen) {
        this._container.mozRequestFullScreen();
    } else if (this._container.msRequestFullscreen) {
        this._container.msRequestFullscreen();
    } else if (this._container.webkitRequestFullscreen) {
        this._container.webkitRequestFullscreen();
    }
};

var defaultOptions$5 = {
    closeButton: true,
    closeOnClick: true,
    focusAfterOpen: true,
    className: '',
    maxWidth: '240px'
};
var focusQuerySelector = [
    'a[href]',
    '[tabindex]:not([tabindex=\'-1\'])',
    '[contenteditable]:not([contenteditable=\'false\'])',
    'button:not([disabled])',
    'input:not([disabled])',
    'select:not([disabled])',
    'textarea:not([disabled])'
].join(', ');
var Popup = function (Evented) {
    function Popup(options) {
        Evented.call(this);
        this.options = performance.extend(Object.create(defaultOptions$5), options);
        performance.bindAll([
            '_update',
            '_onClose',
            'remove',
            '_onMouseMove',
            '_onMouseUp',
            '_onDrag'
        ], this);
    }
    if (Evented)
        Popup.__proto__ = Evented;
    Popup.prototype = Object.create(Evented && Evented.prototype);
    Popup.prototype.constructor = Popup;
    Popup.prototype.addTo = function addTo(map) {
        if (this._map) {
            this.remove();
        }
        this._map = map;
        if (this.options.closeOnClick) {
            this._map.on('click', this._onClose);
        }
        if (this.options.closeOnMove) {
            this._map.on('move', this._onClose);
        }
        this._map.on('remove', this.remove);
        this._update();
        this._focusFirstElement();
        if (this._trackPointer) {
            this._map.on('mousemove', this._onMouseMove);
            this._map.on('mouseup', this._onMouseUp);
            if (this._container) {
                this._container.classList.add('mapboxgl-popup-track-pointer');
            }
            this._map._canvasContainer.classList.add('mapboxgl-track-pointer');
        } else {
            this._map.on('move', this._update);
        }
        this.fire(new performance.Event('open'));
        return this;
    };
    Popup.prototype.isOpen = function isOpen() {
        return !!this._map;
    };
    Popup.prototype.remove = function remove() {
        if (this._content) {
            DOM.remove(this._content);
        }
        if (this._container) {
            DOM.remove(this._container);
            delete this._container;
        }
        if (this._map) {
            this._map.off('move', this._update);
            this._map.off('move', this._onClose);
            this._map.off('click', this._onClose);
            this._map.off('remove', this.remove);
            this._map.off('mousemove', this._onMouseMove);
            this._map.off('mouseup', this._onMouseUp);
            this._map.off('drag', this._onDrag);
            delete this._map;
        }
        this.fire(new performance.Event('close'));
        return this;
    };
    Popup.prototype.getLngLat = function getLngLat() {
        return this._lngLat;
    };
    Popup.prototype.setLngLat = function setLngLat(lnglat) {
        this._lngLat = performance.LngLat.convert(lnglat);
        this._pos = null;
        this._trackPointer = false;
        this._update();
        if (this._map) {
            this._map.on('move', this._update);
            this._map.off('mousemove', this._onMouseMove);
            if (this._container) {
                this._container.classList.remove('mapboxgl-popup-track-pointer');
            }
            this._map._canvasContainer.classList.remove('mapboxgl-track-pointer');
        }
        return this;
    };
    Popup.prototype.trackPointer = function trackPointer() {
        this._trackPointer = true;
        this._pos = null;
        this._update();
        if (this._map) {
            this._map.off('move', this._update);
            this._map.on('mousemove', this._onMouseMove);
            this._map.on('drag', this._onDrag);
            if (this._container) {
                this._container.classList.add('mapboxgl-popup-track-pointer');
            }
            this._map._canvasContainer.classList.add('mapboxgl-track-pointer');
        }
        return this;
    };
    Popup.prototype.getElement = function getElement() {
        return this._container;
    };
    Popup.prototype.setText = function setText(text) {
        return this.setDOMContent(performance.window.document.createTextNode(text));
    };
    Popup.prototype.setHTML = function setHTML(html) {
        var frag = performance.window.document.createDocumentFragment();
        var temp = performance.window.document.createElement('body');
        var child;
        temp.innerHTML = html;
        while (true) {
            child = temp.firstChild;
            if (!child) {
                break;
            }
            frag.appendChild(child);
        }
        return this.setDOMContent(frag);
    };
    Popup.prototype.getMaxWidth = function getMaxWidth() {
        return this._container && this._container.style.maxWidth;
    };
    Popup.prototype.setMaxWidth = function setMaxWidth(maxWidth) {
        this.options.maxWidth = maxWidth;
        this._update();
        return this;
    };
    Popup.prototype.setDOMContent = function setDOMContent(htmlNode) {
        if (this._content) {
            while (this._content.hasChildNodes()) {
                if (this._content.firstChild) {
                    this._content.removeChild(this._content.firstChild);
                }
            }
        } else {
            this._content = DOM.create('div', 'mapboxgl-popup-content', this._container);
        }
        this._content.appendChild(htmlNode);
        this._createCloseButton();
        this._update();
        this._focusFirstElement();
        return this;
    };
    Popup.prototype.addClassName = function addClassName(className) {
        if (this._container) {
            this._container.classList.add(className);
        }
    };
    Popup.prototype.removeClassName = function removeClassName(className) {
        if (this._container) {
            this._container.classList.remove(className);
        }
    };
    Popup.prototype.setOffset = function setOffset(offset) {
        this.options.offset = offset;
        this._update();
        return this;
    };
    Popup.prototype.toggleClassName = function toggleClassName(className) {
        if (this._container) {
            return this._container.classList.toggle(className);
        }
    };
    Popup.prototype._createCloseButton = function _createCloseButton() {
        if (this.options.closeButton) {
            this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._content);
            this._closeButton.type = 'button';
            this._closeButton.setAttribute('aria-label', 'Close popup');
            this._closeButton.innerHTML = '&#215;';
            this._closeButton.addEventListener('click', this._onClose);
        }
    };
    Popup.prototype._onMouseUp = function _onMouseUp(event) {
        this._update(event.point);
    };
    Popup.prototype._onMouseMove = function _onMouseMove(event) {
        this._update(event.point);
    };
    Popup.prototype._onDrag = function _onDrag(event) {
        this._update(event.point);
    };
    Popup.prototype._update = function _update(cursor) {
        var this$1 = this;
        var hasPosition = this._lngLat || this._trackPointer;
        if (!this._map || !hasPosition || !this._content) {
            return;
        }
        if (!this._container) {
            this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());
            this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);
            this._container.appendChild(this._content);
            if (this.options.className) {
                this.options.className.split(' ').forEach(function (name) {
                    return this$1._container.classList.add(name);
                });
            }
            if (this._trackPointer) {
                this._container.classList.add('mapboxgl-popup-track-pointer');
            }
        }
        if (this.options.maxWidth && this._container.style.maxWidth !== this.options.maxWidth) {
            this._container.style.maxWidth = this.options.maxWidth;
        }
        if (this._map.transform.renderWorldCopies && !this._trackPointer) {
            this._lngLat = smartWrap(this._lngLat, this._pos, this._map.transform);
        }
        if (this._trackPointer && !cursor) {
            return;
        }
        var pos = this._pos = this._trackPointer && cursor ? cursor : this._map.project(this._lngLat);
        var anchor = this.options.anchor;
        var offset = normalizeOffset(this.options.offset);
        if (!anchor) {
            var width = this._container.offsetWidth;
            var height = this._container.offsetHeight;
            var anchorComponents;
            if (pos.y + offset.bottom.y < height) {
                anchorComponents = ['top'];
            } else if (pos.y > this._map.transform.height - height) {
                anchorComponents = ['bottom'];
            } else {
                anchorComponents = [];
            }
            if (pos.x < width / 2) {
                anchorComponents.push('left');
            } else if (pos.x > this._map.transform.width - width / 2) {
                anchorComponents.push('right');
            }
            if (anchorComponents.length === 0) {
                anchor = 'bottom';
            } else {
                anchor = anchorComponents.join('-');
            }
        }
        var offsetedPos = pos.add(offset[anchor]).round();
        DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + offsetedPos.x + 'px,' + offsetedPos.y + 'px)');
        applyAnchorClass(this._container, anchor, 'popup');
    };
    Popup.prototype._focusFirstElement = function _focusFirstElement() {
        if (!this.options.focusAfterOpen || !this._container) {
            return;
        }
        var firstFocusable = this._container.querySelector(focusQuerySelector);
        if (firstFocusable) {
            firstFocusable.focus();
        }
    };
    Popup.prototype._onClose = function _onClose() {
        this.remove();
    };
    return Popup;
}(performance.Evented);
function normalizeOffset(offset) {
    if (!offset) {
        return normalizeOffset(new performance.Point(0, 0));
    } else if (typeof offset === 'number') {
        var cornerOffset = Math.round(Math.sqrt(0.5 * Math.pow(offset, 2)));
        return {
            'center': new performance.Point(0, 0),
            'top': new performance.Point(0, offset),
            'top-left': new performance.Point(cornerOffset, cornerOffset),
            'top-right': new performance.Point(-cornerOffset, cornerOffset),
            'bottom': new performance.Point(0, -offset),
            'bottom-left': new performance.Point(cornerOffset, -cornerOffset),
            'bottom-right': new performance.Point(-cornerOffset, -cornerOffset),
            'left': new performance.Point(offset, 0),
            'right': new performance.Point(-offset, 0)
        };
    } else if (offset instanceof performance.Point || Array.isArray(offset)) {
        var convertedOffset = performance.Point.convert(offset);
        return {
            'center': convertedOffset,
            'top': convertedOffset,
            'top-left': convertedOffset,
            'top-right': convertedOffset,
            'bottom': convertedOffset,
            'bottom-left': convertedOffset,
            'bottom-right': convertedOffset,
            'left': convertedOffset,
            'right': convertedOffset
        };
    } else {
        return {
            'center': performance.Point.convert(offset['center'] || [
                0,
                0
            ]),
            'top': performance.Point.convert(offset['top'] || [
                0,
                0
            ]),
            'top-left': performance.Point.convert(offset['top-left'] || [
                0,
                0
            ]),
            'top-right': performance.Point.convert(offset['top-right'] || [
                0,
                0
            ]),
            'bottom': performance.Point.convert(offset['bottom'] || [
                0,
                0
            ]),
            'bottom-left': performance.Point.convert(offset['bottom-left'] || [
                0,
                0
            ]),
            'bottom-right': performance.Point.convert(offset['bottom-right'] || [
                0,
                0
            ]),
            'left': performance.Point.convert(offset['left'] || [
                0,
                0
            ]),
            'right': performance.Point.convert(offset['right'] || [
                0,
                0
            ])
        };
    }
}

var exported = {
    version: performance.version,
    supported: mapboxGlSupported,
    setRTLTextPlugin: performance.setRTLTextPlugin,
    getRTLTextPluginStatus: performance.getRTLTextPluginStatus,
    Map: Map,
    NavigationControl: NavigationControl,
    GeolocateControl: GeolocateControl,
    AttributionControl: AttributionControl,
    ScaleControl: ScaleControl,
    FullscreenControl: FullscreenControl,
    Popup: Popup,
    Marker: Marker,
    Style: Style,
    LngLat: performance.LngLat,
    LngLatBounds: performance.LngLatBounds,
    Point: performance.Point,
    MercatorCoordinate: performance.MercatorCoordinate,
    Evented: performance.Evented,
    config: performance.config,
    prewarm: prewarm,
    clearPrewarmedResources: clearPrewarmedResources,
    get accessToken() {
        return performance.config.ACCESS_TOKEN;
    },
    set accessToken(token) {
        performance.config.ACCESS_TOKEN = token;
    },
    get baseApiUrl() {
        return performance.config.API_URL;
    },
    set baseApiUrl(url) {
        performance.config.API_URL = url;
    },
    get workerCount() {
        return WorkerPool.workerCount;
    },
    set workerCount(count) {
        WorkerPool.workerCount = count;
    },
    get maxParallelImageRequests() {
        return performance.config.MAX_PARALLEL_IMAGE_REQUESTS;
    },
    set maxParallelImageRequests(numRequests) {
        performance.config.MAX_PARALLEL_IMAGE_REQUESTS = numRequests;
    },
    clearStorage: function clearStorage(callback) {
        performance.clearTileCache(callback);
    },
    workerUrl: ''
};

return exported;

});

//

return mapboxgl;

})));
//# sourceMappingURL=mapbox-gl-unminified.js.map
