UNPKG

dicom-microscopy-viewer-changed

Version:
2,104 lines (2,068 loc) 354 kB
import Circle from 'ol/style/Circle.js'; import Fill from 'ol/style/Fill.js'; import Icon from 'ol/style/Icon.js'; import RenderFeature from 'ol/render/Feature.js'; import Stroke from 'ol/style/Stroke.js'; import Style from 'ol/style/Style.js'; import Text from 'ol/style/Text.js'; import { registerFont, checkedFonts } from 'ol/render/canvas.js'; import { expandUrl } from 'ol/tileurlfunction.js'; import GeoJSON from 'ol/format/GeoJSON.js'; import ImageLayer from 'ol/layer/Image.js'; import Layer from 'ol/layer/Layer.js'; import LayerGroup from 'ol/layer/Group.js'; import MVT from 'ol/format/MVT.js'; import Map from 'ol/Map.js'; import Raster from 'ol/source/Raster.js'; import Source from 'ol/source/Source.js'; import TileGrid from 'ol/tilegrid/TileGrid.js'; import TileJSON from 'ol/source/TileJSON.js'; import TileLayer from 'ol/layer/Tile.js'; import VectorLayer from 'ol/layer/Vector.js'; import VectorSource from 'ol/source/Vector.js'; import VectorTileLayer from 'ol/layer/VectorTile.js'; import VectorTileSource, { defaultLoadFunction } from 'ol/source/VectorTile.js'; import View from 'ol/View.js'; import { get as get$1, METERS_PER_UNIT, fromLonLat, equivalent, getUserProjection } from 'ol/proj.js'; import { bbox } from 'ol/loadingstrategy.js'; import { createXYZ } from 'ol/tilegrid.js'; import { getTopLeft } from 'ol/extent.js'; import { getUid } from 'ol/util.js'; function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var csscolorparser = {}; var parseCSSColor_1; // (c) Dean McNamee <dean@gmail.com>, 2012. // // https://github.com/deanm/css-color-parser-js // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // http://www.w3.org/TR/css3-color/ 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) { // Clamp to integer 0 .. 255. i = Math.round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 255 ? 255 : i; } function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0. return f < 0 ? 0 : f > 1 ? 1 : f; } function parse_css_int(str) { // int or percentage. if (str[str.length - 1] === '%') { return clamp_css_byte(parseFloat(str) / 100 * 255); } return clamp_css_byte(parseInt(str)); } function parse_css_float(str) { // float or percentage. 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) { // Remove all whitespace, not compliant, but should just be more accepting. var str = css_str.replace(/ /g, '').toLowerCase(); // Color keywords (and transparent) lookup. if (str in kCSSColorTable) { return kCSSColorTable[str].slice(); } // dup. // #abc and #abc123 syntax. if (str[0] === '#') { if (str.length === 4) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 4095)) { return null; } // Covers NaN. 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); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 16777215)) { return null; } // Covers NaN. 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; // To allow case fallthrough. switch (fname) { case 'rgba': if (params.length !== 4) { return null; } alpha = parse_css_float(params.pop()); // Fall through. 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()); // Fall through. case 'hsl': if (params.length !== 3) { return null; } var h = (parseFloat(params[0]) % 360 + 360) % 360 / 360; // 0 .. 1 // NOTE(deanm): According to the CSS spec s/l should only be // percentages, but we don't bother and let float or percentage. 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 { parseCSSColor_1 = csscolorparser.parseCSSColor = parseCSSColor; } catch (e) { } // /** * An RGBA color value. Create instances from color strings using the static * method `Color.parse`. The constructor accepts RGB channel values in the range * `[0, 1]`, premultiplied by A. * * @param {number} r The red channel. * @param {number} g The green channel. * @param {number} b The blue channel. * @param {number} a The alpha channel. * @private */ 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; }; /** * Parses valid CSS color strings and returns a `Color` instance. * @returns A `Color` instance, or `undefined` if the input is not a valid color string. */ Color.parse = function parse (input) { if (!input) { return undefined; } if (input instanceof Color) { return input; } if (typeof input !== 'string') { return undefined; } var rgba = parseCSSColor_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]); }; /** * Returns an RGBA string representing the color value. * * @returns An RGBA string. * @example * var purple = new Color.parse('purple'); * purple.toString; // = "rgba(128,0,128,1)" * var translucentGreen = new Color.parse('rgba(26, 207, 26, .73)'); * translucentGreen.toString(); // = "rgba(26,207,26,0.73)" */ 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 + ")"); }; /** * Returns an RGBA array of values representing the color, unpremultiplied by A. * * @returns An array of RGBA color values in the range [0, 255]. */ 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 ]; }; /** * Returns a RGBA array of float values representing the color, unpremultiplied by A. * * @returns An array of RGBA color values in the range [0, 1]. */ Color.prototype.toArray01 = function toArray01 () { 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 / a, g / a, b / a, a ]; }; /** * Returns an RGBA array of values representing the color, premultiplied by A. * * @returns An array of RGBA color values in the range [0, 1]. */ Color.prototype.toArray01PremultipliedAlpha = function toArray01PremultipliedAlpha () { var ref = this; var r = ref.r; var g = ref.g; var b = ref.b; var a = ref.a; return [ r, g, b, 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); Color.blue = new Color(0, 0, 1, 1); var Color$1 = Color; function convertLiteral(value) { return typeof value === 'object' ? [ 'literal', value ] : value; } function convertFunction(parameters, propertySpec) { var stops = parameters.stops; if (!stops) { // identity function return convertIdentityFunction(parameters, propertySpec); } var zoomAndFeatureDependent = stops && typeof stops[0][0] === 'object'; var featureDependent = zoomAndFeatureDependent || parameters.property !== undefined; var zoomDependent = zoomAndFeatureDependent || !featureDependent; stops = stops.map(function (stop) { if (!featureDependent && propertySpec.tokens && typeof stop[1] === 'string') { return [ stop[0], convertTokenString(stop[1]) ]; } return [ stop[0], convertLiteral(stop[1]) ]; }); if (zoomAndFeatureDependent) { return convertZoomAndPropertyFunction(parameters, propertySpec, stops); } else if (zoomDependent) { return convertZoomFunction(parameters, propertySpec, stops); } else { return convertPropertyFunction(parameters, propertySpec, stops); } } function convertIdentityFunction(parameters, propertySpec) { var get = [ 'get', parameters.property ]; if (parameters.default === undefined) { // By default, expressions for string-valued properties get coerced. To preserve // legacy function semantics, insert an explicit assertion instead. return propertySpec.type === 'string' ? [ 'string', get ] : get; } else if (propertySpec.type === 'enum') { return [ 'match', get, Object.keys(propertySpec.values), get, parameters.default ]; } else { var expression = [ propertySpec.type === 'color' ? 'to-color' : propertySpec.type, get, convertLiteral(parameters.default) ]; if (propertySpec.type === 'array') { expression.splice(1, 0, propertySpec.value, propertySpec.length || null); } return expression; } } function getInterpolateOperator(parameters) { switch (parameters.colorSpace) { case 'hcl': return 'interpolate-hcl'; case 'lab': return 'interpolate-lab'; default: return 'interpolate'; } } function convertZoomAndPropertyFunction(parameters, propertySpec, stops) { var featureFunctionParameters = {}; var featureFunctionStops = {}; var zoomStops = []; for (var s = 0; s < stops.length; s++) { var stop = stops[s]; var zoom = stop[0].zoom; if (featureFunctionParameters[zoom] === undefined) { featureFunctionParameters[zoom] = { zoom: zoom, type: parameters.type, property: parameters.property, default: parameters.default }; featureFunctionStops[zoom] = []; zoomStops.push(zoom); } featureFunctionStops[zoom].push([ stop[0].value, stop[1] ]); } // the interpolation type for the zoom dimension of a zoom-and-property // function is determined directly from the style property specification // for which it's being used: linear for interpolatable properties, step // otherwise. var functionType = getFunctionType({}, propertySpec); if (functionType === 'exponential') { var expression = [ getInterpolateOperator(parameters), ['linear'], ['zoom'] ]; for (var i = 0, list = zoomStops; i < list.length; i += 1) { var z = list[i]; var output = convertPropertyFunction(featureFunctionParameters[z], propertySpec, featureFunctionStops[z]); appendStopPair(expression, z, output, false); } return expression; } else { var expression$1 = [ 'step', ['zoom'] ]; for (var i$1 = 0, list$1 = zoomStops; i$1 < list$1.length; i$1 += 1) { var z$1 = list$1[i$1]; var output$1 = convertPropertyFunction(featureFunctionParameters[z$1], propertySpec, featureFunctionStops[z$1]); appendStopPair(expression$1, z$1, output$1, true); } fixupDegenerateStepCurve(expression$1); return expression$1; } } function coalesce(a, b) { if (a !== undefined) { return a; } if (b !== undefined) { return b; } } function getFallback(parameters, propertySpec) { var defaultValue = convertLiteral(coalesce(parameters.default, propertySpec.default)); /* * Some fields with type: resolvedImage have an undefined default. * Because undefined is an invalid value for resolvedImage, set fallback to * an empty string instead of undefined to ensure output * passes validation. */ if (defaultValue === undefined && propertySpec.type === 'resolvedImage') { return ''; } return defaultValue; } function convertPropertyFunction(parameters, propertySpec, stops) { var type = getFunctionType(parameters, propertySpec); var get = [ 'get', parameters.property ]; if (type === 'categorical' && typeof stops[0][0] === 'boolean') { var expression = ['case']; for (var i = 0, list = stops; i < list.length; i += 1) { var stop = list[i]; expression.push([ '==', get, stop[0] ], stop[1]); } expression.push(getFallback(parameters, propertySpec)); return expression; } else if (type === 'categorical') { var expression$1 = [ 'match', get ]; for (var i$1 = 0, list$1 = stops; i$1 < list$1.length; i$1 += 1) { var stop$1 = list$1[i$1]; appendStopPair(expression$1, stop$1[0], stop$1[1], false); } expression$1.push(getFallback(parameters, propertySpec)); return expression$1; } else if (type === 'interval') { var expression$2 = [ 'step', [ 'number', get ] ]; for (var i$2 = 0, list$2 = stops; i$2 < list$2.length; i$2 += 1) { var stop$2 = list$2[i$2]; appendStopPair(expression$2, stop$2[0], stop$2[1], true); } fixupDegenerateStepCurve(expression$2); return parameters.default === undefined ? expression$2 : [ 'case', [ '==', [ 'typeof', get ], 'number' ], expression$2, convertLiteral(parameters.default) ]; } else if (type === 'exponential') { var base = parameters.base !== undefined ? parameters.base : 1; var expression$3 = [ getInterpolateOperator(parameters), base === 1 ? ['linear'] : [ 'exponential', base ], [ 'number', get ] ]; for (var i$3 = 0, list$3 = stops; i$3 < list$3.length; i$3 += 1) { var stop$3 = list$3[i$3]; appendStopPair(expression$3, stop$3[0], stop$3[1], false); } return parameters.default === undefined ? expression$3 : [ 'case', [ '==', [ 'typeof', get ], 'number' ], expression$3, convertLiteral(parameters.default) ]; } else { throw new Error(("Unknown property function type " + type)); } } function convertZoomFunction(parameters, propertySpec, stops, input) { if ( input === void 0 ) input = ['zoom']; var type = getFunctionType(parameters, propertySpec); var expression; var isStep = false; if (type === 'interval') { expression = [ 'step', input ]; isStep = true; } else if (type === 'exponential') { var base = parameters.base !== undefined ? parameters.base : 1; expression = [ getInterpolateOperator(parameters), base === 1 ? ['linear'] : [ 'exponential', base ], input ]; } else { throw new Error(("Unknown zoom function type \"" + type + "\"")); } for (var i = 0, list = stops; i < list.length; i += 1) { var stop = list[i]; appendStopPair(expression, stop[0], stop[1], isStep); } fixupDegenerateStepCurve(expression); return expression; } function fixupDegenerateStepCurve(expression) { // degenerate step curve (i.e. a constant function): add a noop stop if (expression[0] === 'step' && expression.length === 3) { expression.push(0); expression.push(expression[3]); } } function appendStopPair(curve, input, output, isStep) { // Skip duplicate stop values. They were not validated for functions, but they are for expressions. // https://github.com/mapbox/mapbox-gl-js/issues/4107 if (curve.length > 3 && input === curve[curve.length - 2]) { return; } // step curves don't get the first input value, as it is redundant. if (!(isStep && curve.length === 2)) { curve.push(input); } curve.push(output); } function getFunctionType(parameters, propertySpec) { if (parameters.type) { return parameters.type; } else { return propertySpec.expression.interpolated ? 'exponential' : 'interval'; } } // "String with {name} token" => ["concat", "String with ", ["get", "name"], " token"] function convertTokenString(s) { var result = ['concat']; var re = /{([^{}]+)}/g; var pos = 0; for (var match = re.exec(s); match !== null; match = re.exec(s)) { var literal = s.slice(pos, re.lastIndex - match[0].length); pos = re.lastIndex; if (literal.length > 0) { result.push(literal); } result.push([ 'get', match[1] ]); } if (result.length === 1) { return s; } if (pos < s.length) { result.push(s.slice(pos)); } else if (result.length === 2) { return [ 'to-string', result[1] ]; } return result; } // var ParsingError = /*@__PURE__*/(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 ParsingError$1 = ParsingError; // /** * Tracks `let` bindings during expression parsing. * @private */ 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 Scope$1 = Scope; // 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$1(itemType, N) { return { kind: 'array', itemType: itemType, N: N }; } function toString$1(type) { if (type.kind === 'array') { var itemType = toString$1(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$1(ValueType), ResolvedImageType ]; /** * Returns null if `t` is a subtype of `expected`; otherwise returns an * error message. * @private */ function checkSubtype(expected, t) { if (t.kind === 'error') { // Error is a subtype of every type 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$1(expected)) + " but found " + (toString$1(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; } }); } // // Flow type declarations for Intl cribbed from // https://github.com/facebook/flow/issues/1270 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 () { // We create a Collator without "usage: search" because we don't want // the search options encoded in our result (e.g. "en-u-co-search") return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale; }; var Collator$1 = Collator; // var FormattedSection = function FormattedSection(text, image, scale, fontStack, textColor) { // combine characters so that diacritic marks are not separate code points this.text = text.normalize ? text.normalize() : 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 Formatted$1 = Formatted; // 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; } // treat empty values as no image return new ResolvedImage({ name: name, available: false }); }; ResolvedImage.prototype.serialize = function serialize () { return [ 'image', this.name ]; }; var ResolvedImage$1 = ResolvedImage; 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$1) { return true; } else if (mixed instanceof Collator$1) { return true; } else if (mixed instanceof Formatted$1) { return true; } else if (mixed instanceof ResolvedImage$1) { 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$1) { return ColorType; } else if (value instanceof Collator$1) { return CollatorType; } else if (value instanceof Formatted$1) { return FormattedType; } else if (value instanceof ResolvedImage$1) { 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$1(itemType || ValueType, length); } else { return ObjectType; } } function toString(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$1 || value instanceof Formatted$1 || value instanceof ResolvedImage$1) { 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); // special case: infer the item type if possible for zero-length arrays 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$1) { // Constant-folding can generate Literal expressions that you // couldn't actually generate with a "literal" expression, // so we have to implement an equivalent serialization here return ['rgba'].concat(this.value.toArray()); } else if (this.value instanceof Formatted$1) { // Same as Color return this.value.serialize(); } else { return this.value; } }; var Literal$1 = Literal; // var RuntimeError = function RuntimeError(message) { this.name = 'ExpressionEvaluationError'; this.message = message; }; RuntimeError.prototype.toJSON = function toJSON () { return this.message; }; var RuntimeError$1 = RuntimeError; var types$2 = { 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$2) || type$1 === 'object') { return context.error('The item type argument of "array" must be one of string, number, boolean', 1); } itemType = types$2[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$1(itemType, N); } else { type = types$2[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$1(("Expected value to be of type " + (toString$1(this.type)) + ", but found " + (toString$1(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 Assertion$1 = Assertion; // 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$1(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 (sectio