dicom-microscopy-viewer-changed
Version:
Interactive web-based viewer for DICOM Microscopy Images
2,104 lines (2,068 loc) • 354 kB
JavaScript
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