@mapwhit/tilerenderer 0.50.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/build/min/package.json +1 -1
  2. package/build/min/src/shaders/.dir +0 -0
  3. package/build/min/src/shaders/_prelude.fragment.glsl.js +14 -0
  4. package/build/min/src/shaders/_prelude.vertex.glsl.js +14 -0
  5. package/build/min/src/shaders/background.fragment.glsl.js +5 -0
  6. package/build/min/src/shaders/background.vertex.glsl.js +1 -0
  7. package/build/min/src/shaders/background_pattern.fragment.glsl.js +5 -0
  8. package/build/min/src/shaders/background_pattern.vertex.glsl.js +1 -0
  9. package/build/min/src/shaders/circle.fragment.glsl.js +20 -0
  10. package/build/min/src/shaders/circle.vertex.glsl.js +17 -0
  11. package/build/min/src/shaders/clipping_mask.fragment.glsl.js +1 -0
  12. package/build/min/src/shaders/clipping_mask.vertex.glsl.js +1 -0
  13. package/build/min/src/shaders/collision_box.fragment.glsl.js +1 -0
  14. package/build/min/src/shaders/collision_box.vertex.glsl.js +1 -0
  15. package/build/min/src/shaders/collision_circle.fragment.glsl.js +1 -0
  16. package/build/min/src/shaders/collision_circle.vertex.glsl.js +1 -0
  17. package/build/min/src/shaders/debug.fragment.glsl.js +1 -0
  18. package/build/min/src/shaders/debug.vertex.glsl.js +1 -0
  19. package/build/min/src/shaders/fill.fragment.glsl.js +10 -0
  20. package/build/min/src/shaders/fill.vertex.glsl.js +7 -0
  21. package/build/min/src/shaders/fill_extrusion.fragment.glsl.js +5 -0
  22. package/build/min/src/shaders/fill_extrusion.vertex.glsl.js +9 -0
  23. package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.js +15 -0
  24. package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.js +11 -0
  25. package/build/min/src/shaders/fill_outline.fragment.glsl.js +10 -0
  26. package/build/min/src/shaders/fill_outline.vertex.glsl.js +7 -0
  27. package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.js +13 -0
  28. package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.js +9 -0
  29. package/build/min/src/shaders/fill_pattern.fragment.glsl.js +13 -0
  30. package/build/min/src/shaders/fill_pattern.vertex.glsl.js +9 -0
  31. package/build/min/src/shaders/heatmap.fragment.glsl.js +10 -0
  32. package/build/min/src/shaders/heatmap.vertex.glsl.js +8 -0
  33. package/build/min/src/shaders/heatmap_texture.fragment.glsl.js +5 -0
  34. package/build/min/src/shaders/heatmap_texture.vertex.glsl.js +1 -0
  35. package/build/min/src/shaders/hillshade.fragment.glsl.js +7 -0
  36. package/build/min/src/shaders/hillshade.vertex.glsl.js +1 -0
  37. package/build/min/src/shaders/hillshade_prepare.fragment.glsl.js +8 -0
  38. package/build/min/src/shaders/hillshade_prepare.vertex.glsl.js +1 -0
  39. package/build/min/src/shaders/line.fragment.glsl.js +12 -0
  40. package/build/min/src/shaders/line.vertex.glsl.js +17 -0
  41. package/build/min/src/shaders/line_gradient.fragment.glsl.js +10 -0
  42. package/build/min/src/shaders/line_gradient.vertex.glsl.js +16 -0
  43. package/build/min/src/shaders/line_pattern.fragment.glsl.js +15 -0
  44. package/build/min/src/shaders/line_pattern.vertex.glsl.js +20 -0
  45. package/build/min/src/shaders/line_sdf.fragment.glsl.js +17 -0
  46. package/build/min/src/shaders/line_sdf.vertex.glsl.js +20 -0
  47. package/build/min/src/shaders/raster.fragment.glsl.js +5 -0
  48. package/build/min/src/shaders/raster.vertex.glsl.js +1 -0
  49. package/build/min/src/shaders/symbol_icon.fragment.glsl.js +9 -0
  50. package/build/min/src/shaders/symbol_icon.vertex.glsl.js +5 -0
  51. package/build/min/src/shaders/symbol_sdf.fragment.glsl.js +19 -0
  52. package/build/min/src/shaders/symbol_sdf.vertex.glsl.js +13 -0
  53. package/package.json +7 -7
  54. package/src/data/bucket/fill_bucket.js +1 -1
  55. package/src/data/bucket/fill_extrusion_bucket.js +2 -2
  56. package/src/data/bucket/line_bucket.js +1 -1
  57. package/src/data/bucket/symbol_bucket.js +2 -2
  58. package/src/data/feature_index.js +1 -1
  59. package/src/data/program_configuration.js +1 -1
  60. package/src/gl/color_mode.js +1 -1
  61. package/src/gl/value.js +1 -1
  62. package/src/render/draw_debug.js +1 -1
  63. package/src/render/draw_fill.js +1 -1
  64. package/src/render/draw_heatmap.js +1 -1
  65. package/src/render/glyph_manager.js +6 -130
  66. package/src/render/painter.js +1 -1
  67. package/src/render/uniform_binding.js +1 -1
  68. package/src/shaders/index.js +50 -50
  69. package/src/source/geojson_worker_source.js +4 -4
  70. package/src/source/geojson_wrapper.js +34 -26
  71. package/src/source/resources/glyphs.js +73 -0
  72. package/src/source/resources/images.js +68 -0
  73. package/src/source/resources/index.js +22 -0
  74. package/src/source/vector_tile_worker_source.js +5 -5
  75. package/src/source/worker.js +6 -5
  76. package/src/source/worker_tile.js +4 -4
  77. package/src/style/properties.js +1 -2
  78. package/src/style/style.js +3 -3
  79. package/src/style/style_layer/symbol_style_layer.js +1 -1
  80. package/src/style/style_layer.js +1 -1
  81. package/src/style-spec/feature_filter/index.js +43 -34
  82. package/src/style-spec/group_by_layout.js +10 -32
  83. package/src/symbol/mergelines.js +0 -2
  84. package/src/symbol/symbol_layout.js +0 -1
  85. package/src/symbol/symbol_size.js +1 -1
  86. package/src/symbol/transform_text.js +0 -1
  87. package/src/ui/map.js +11 -39
  88. package/src/util/browser.js +3 -18
  89. package/src/util/classify_rings.js +1 -1
  90. package/src/util/dom.js +0 -88
  91. package/src/util/find_pole_of_inaccessibility.js +2 -2
  92. package/src/util/web_worker_transfer.js +4 -4
  93. package/src/style/load_glyph_range.js +0 -17
  94. package/src/style-spec/expression/compound_expression.js +0 -132
  95. package/src/style-spec/expression/definitions/assertion.js +0 -116
  96. package/src/style-spec/expression/definitions/at.js +0 -57
  97. package/src/style-spec/expression/definitions/case.js +0 -73
  98. package/src/style-spec/expression/definitions/coalesce.js +0 -66
  99. package/src/style-spec/expression/definitions/coercion.js +0 -120
  100. package/src/style-spec/expression/definitions/collator.js +0 -80
  101. package/src/style-spec/expression/definitions/comparison.js +0 -193
  102. package/src/style-spec/expression/definitions/format.js +0 -97
  103. package/src/style-spec/expression/definitions/index.js +0 -339
  104. package/src/style-spec/expression/definitions/interpolate.js +0 -245
  105. package/src/style-spec/expression/definitions/length.js +0 -54
  106. package/src/style-spec/expression/definitions/let.js +0 -60
  107. package/src/style-spec/expression/definitions/literal.js +0 -69
  108. package/src/style-spec/expression/definitions/match.js +0 -142
  109. package/src/style-spec/expression/definitions/step.js +0 -116
  110. package/src/style-spec/expression/definitions/var.js +0 -38
  111. package/src/style-spec/expression/evaluation_context.js +0 -38
  112. package/src/style-spec/expression/index.js +0 -330
  113. package/src/style-spec/expression/is_constant.js +0 -63
  114. package/src/style-spec/expression/parsing_context.js +0 -221
  115. package/src/style-spec/expression/parsing_error.js +0 -9
  116. package/src/style-spec/expression/runtime_error.js +0 -12
  117. package/src/style-spec/expression/scope.js +0 -34
  118. package/src/style-spec/expression/stops.js +0 -37
  119. package/src/style-spec/expression/types/collator.js +0 -24
  120. package/src/style-spec/expression/types/formatted.js +0 -39
  121. package/src/style-spec/expression/types.js +0 -88
  122. package/src/style-spec/expression/values.js +0 -149
  123. package/src/style-spec/function/convert.js +0 -240
  124. package/src/style-spec/function/index.js +0 -303
  125. package/src/style-spec/util/color.js +0 -73
  126. package/src/style-spec/util/color_spaces.js +0 -128
  127. package/src/style-spec/util/get_type.js +0 -18
  128. package/src/style-spec/util/interpolate.js +0 -21
  129. package/src/style-spec/util/properties.js +0 -17
  130. package/src/style-spec/util/result.js +0 -19
  131. package/src/ui/anchor.js +0 -24
  132. package/src/ui/bind_handlers.js +0 -199
  133. package/src/ui/events.js +0 -210
  134. package/src/ui/handler/box_zoom.js +0 -151
  135. package/src/ui/handler/dblclick_zoom.js +0 -91
  136. package/src/ui/handler/drag_pan.js +0 -285
  137. package/src/ui/handler/drag_rotate.js +0 -290
  138. package/src/ui/handler/frame.js +0 -28
  139. package/src/ui/handler/inertia.js +0 -45
  140. package/src/ui/handler/keyboard.js +0 -148
  141. package/src/ui/handler/scroll_zoom.js +0 -284
  142. package/src/ui/handler/touch_zoom_rotate.js +0 -263
@@ -1,37 +0,0 @@
1
- const RuntimeError = require('./runtime_error');
2
-
3
- /**
4
- * Returns the index of the last stop <= input, or 0 if it doesn't exist.
5
- * @private
6
- */
7
- function findStopLessThanOrEqualTo(stops, input) {
8
- const n = stops.length;
9
- let lowerIndex = 0;
10
- let upperIndex = n - 1;
11
- let currentIndex = 0;
12
- let currentValue;
13
- let upperValue;
14
-
15
- while (lowerIndex <= upperIndex) {
16
- currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
17
- currentValue = stops[currentIndex];
18
- upperValue = stops[currentIndex + 1];
19
- if (input === currentValue || (input > currentValue && input < upperValue)) {
20
- // Search complete
21
- return currentIndex;
22
- }
23
- if (currentValue < input) {
24
- lowerIndex = currentIndex + 1;
25
- } else if (currentValue > input) {
26
- upperIndex = currentIndex - 1;
27
- } else {
28
- throw new RuntimeError('Input is not a number.');
29
- }
30
- }
31
-
32
- return Math.max(currentIndex - 1, 0);
33
- }
34
-
35
- module.exports = {
36
- findStopLessThanOrEqualTo
37
- };
@@ -1,24 +0,0 @@
1
- class Collator {
2
- constructor(caseSensitive, diacriticSensitive, locale) {
3
- if (caseSensitive) this.sensitivity = diacriticSensitive ? 'variant' : 'case';
4
- else this.sensitivity = diacriticSensitive ? 'accent' : 'base';
5
-
6
- this.locale = locale;
7
- this.collator = new Intl.Collator(this.locale ? this.locale : [], {
8
- sensitivity: this.sensitivity,
9
- usage: 'search'
10
- });
11
- }
12
-
13
- compare(lhs, rhs) {
14
- return this.collator.compare(lhs, rhs);
15
- }
16
-
17
- resolvedLocale() {
18
- // We create a Collator without "usage: search" because we don't want
19
- // the search options encoded in our result (e.g. "en-u-co-search")
20
- return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale;
21
- }
22
- }
23
-
24
- module.exports = { Collator };
@@ -1,39 +0,0 @@
1
- class FormattedSection {
2
- constructor(text, scale, fontStack = null) {
3
- this.text = text;
4
- this.scale = scale;
5
- this.fontStack = fontStack;
6
- }
7
- }
8
-
9
- class Formatted {
10
- constructor(sections) {
11
- this.sections = sections;
12
- }
13
-
14
- static fromString(unformatted) {
15
- return new Formatted([new FormattedSection(unformatted, null, null)]);
16
- }
17
-
18
- toString() {
19
- return this.sections.map(section => section.text).join('');
20
- }
21
-
22
- serialize() {
23
- const serialized = ['format'];
24
- for (const section of this.sections) {
25
- serialized.push(section.text);
26
- const options = {};
27
- if (section.fontStack) {
28
- options['text-font'] = ['literal', section.fontStack.split(',')];
29
- }
30
- if (section.scale) {
31
- options['font-scale'] = section.scale;
32
- }
33
- serialized.push(options);
34
- }
35
- return serialized;
36
- }
37
- }
38
-
39
- module.exports = { Formatted, FormattedSection };
@@ -1,88 +0,0 @@
1
- const NullType = { kind: 'null' };
2
- const NumberType = { kind: 'number' };
3
- const StringType = { kind: 'string' };
4
- const BooleanType = { kind: 'boolean' };
5
- const ColorType = { kind: 'color' };
6
- const ObjectType = { kind: 'object' };
7
- const ValueType = { kind: 'value' };
8
- const ErrorType = { kind: 'error' };
9
- const CollatorType = { kind: 'collator' };
10
- const FormattedType = { kind: 'formatted' };
11
-
12
- function array(itemType, N) {
13
- return {
14
- kind: 'array',
15
- itemType,
16
- N
17
- };
18
- }
19
-
20
- function toString(type) {
21
- if (type.kind === 'array') {
22
- const itemType = toString(type.itemType);
23
- return typeof type.N === 'number'
24
- ? `array<${itemType}, ${type.N}>`
25
- : type.itemType.kind === 'value'
26
- ? 'array'
27
- : `array<${itemType}>`;
28
- }
29
- return type.kind;
30
- }
31
-
32
- const valueMemberTypes = [
33
- NullType,
34
- NumberType,
35
- StringType,
36
- BooleanType,
37
- ColorType,
38
- FormattedType,
39
- ObjectType,
40
- array(ValueType)
41
- ];
42
-
43
- /**
44
- * Returns null if `t` is a subtype of `expected`; otherwise returns an
45
- * error message.
46
- * @private
47
- */
48
- function checkSubtype(expected, t) {
49
- if (t.kind === 'error') {
50
- // Error is a subtype of every type
51
- return null;
52
- }
53
- if (expected.kind === 'array') {
54
- if (
55
- t.kind === 'array' &&
56
- ((t.N === 0 && t.itemType.kind === 'value') || !checkSubtype(expected.itemType, t.itemType)) &&
57
- (typeof expected.N !== 'number' || expected.N === t.N)
58
- ) {
59
- return null;
60
- }
61
- } else if (expected.kind === t.kind) {
62
- return null;
63
- } else if (expected.kind === 'value') {
64
- for (const memberType of valueMemberTypes) {
65
- if (!checkSubtype(memberType, t)) {
66
- return null;
67
- }
68
- }
69
- }
70
-
71
- return `Expected ${toString(expected)} but found ${toString(t)} instead.`;
72
- }
73
-
74
- module.exports = {
75
- NullType,
76
- NumberType,
77
- StringType,
78
- BooleanType,
79
- ColorType,
80
- FormattedType,
81
- ObjectType,
82
- ValueType,
83
- ErrorType,
84
- CollatorType,
85
- array,
86
- toString,
87
- checkSubtype
88
- };
@@ -1,149 +0,0 @@
1
- const assert = require('assert');
2
-
3
- const Color = require('../util/color');
4
- const { Collator } = require('./types/collator');
5
- const { Formatted } = require('./types/formatted');
6
- const {
7
- NullType,
8
- NumberType,
9
- StringType,
10
- BooleanType,
11
- ColorType,
12
- ObjectType,
13
- ValueType,
14
- CollatorType,
15
- FormattedType,
16
- array
17
- } = require('./types');
18
-
19
- function validateRGBA(r, g, b, a) {
20
- if (
21
- !(
22
- typeof r === 'number' &&
23
- r >= 0 &&
24
- r <= 255 &&
25
- typeof g === 'number' &&
26
- g >= 0 &&
27
- g <= 255 &&
28
- typeof b === 'number' &&
29
- b >= 0 &&
30
- b <= 255
31
- )
32
- ) {
33
- const value = typeof a === 'number' ? [r, g, b, a] : [r, g, b];
34
- return `Invalid rgba value [${value.join(', ')}]: 'r', 'g', and 'b' must be between 0 and 255.`;
35
- }
36
-
37
- if (!(typeof a === 'undefined' || (typeof a === 'number' && a >= 0 && a <= 1))) {
38
- return `Invalid rgba value [${[r, g, b, a].join(', ')}]: 'a' must be between 0 and 1.`;
39
- }
40
-
41
- return null;
42
- }
43
-
44
- function isValue(mixed) {
45
- if (mixed === null) {
46
- return true;
47
- }
48
- if (typeof mixed === 'string') {
49
- return true;
50
- }
51
- if (typeof mixed === 'boolean') {
52
- return true;
53
- }
54
- if (typeof mixed === 'number') {
55
- return true;
56
- }
57
- if (mixed instanceof Color) {
58
- return true;
59
- }
60
- if (mixed instanceof Collator) {
61
- return true;
62
- }
63
- if (mixed instanceof Formatted) {
64
- return true;
65
- }
66
- if (Array.isArray(mixed)) {
67
- for (const item of mixed) {
68
- if (!isValue(item)) {
69
- return false;
70
- }
71
- }
72
- return true;
73
- }
74
- if (typeof mixed === 'object') {
75
- for (const key in mixed) {
76
- if (!isValue(mixed[key])) {
77
- return false;
78
- }
79
- }
80
- return true;
81
- }
82
- return false;
83
- }
84
-
85
- function typeOf(value) {
86
- if (value === null) {
87
- return NullType;
88
- }
89
- if (typeof value === 'string') {
90
- return StringType;
91
- }
92
- if (typeof value === 'boolean') {
93
- return BooleanType;
94
- }
95
- if (typeof value === 'number') {
96
- return NumberType;
97
- }
98
- if (value instanceof Color) {
99
- return ColorType;
100
- }
101
- if (value instanceof Collator) {
102
- return CollatorType;
103
- }
104
- if (value instanceof Formatted) {
105
- return FormattedType;
106
- }
107
- if (Array.isArray(value)) {
108
- const length = value.length;
109
- let itemType;
110
-
111
- for (const item of value) {
112
- const t = typeOf(item);
113
- if (!itemType) {
114
- itemType = t;
115
- } else if (itemType === t) {
116
- } else {
117
- itemType = ValueType;
118
- break;
119
- }
120
- }
121
-
122
- return array(itemType || ValueType, length);
123
- }
124
- assert(typeof value === 'object');
125
- return ObjectType;
126
- }
127
-
128
- function toString(value) {
129
- const type = typeof value;
130
- if (value === null) {
131
- return '';
132
- }
133
- if (type === 'string' || type === 'number' || type === 'boolean') {
134
- return String(value);
135
- }
136
- if (value instanceof Color || value instanceof Formatted) {
137
- return value.toString();
138
- }
139
- return JSON.stringify(value);
140
- }
141
-
142
- module.exports = {
143
- toString,
144
- Color,
145
- Collator,
146
- validateRGBA,
147
- isValue,
148
- typeOf
149
- };
@@ -1,240 +0,0 @@
1
- const assert = require('assert');
2
-
3
- module.exports = convertFunction;
4
-
5
- function convertLiteral(value) {
6
- return typeof value === 'object' ? ['literal', value] : value;
7
- }
8
-
9
- function convertFunction(parameters, propertySpec) {
10
- let stops = parameters.stops;
11
- if (!stops) {
12
- // identity function
13
- return convertIdentityFunction(parameters, propertySpec);
14
- }
15
-
16
- const zoomAndFeatureDependent = stops && typeof stops[0][0] === 'object';
17
- const featureDependent = zoomAndFeatureDependent || parameters.property !== undefined;
18
- const zoomDependent = zoomAndFeatureDependent || !featureDependent;
19
-
20
- stops = stops.map(stop => {
21
- if (!featureDependent && propertySpec.tokens && typeof stop[1] === 'string') {
22
- return [stop[0], convertTokenString(stop[1])];
23
- }
24
- return [stop[0], convertLiteral(stop[1])];
25
- });
26
-
27
- if (zoomAndFeatureDependent) {
28
- return convertZoomAndPropertyFunction(parameters, propertySpec, stops);
29
- }
30
- if (zoomDependent) {
31
- return convertZoomFunction(parameters, propertySpec, stops);
32
- }
33
- return convertPropertyFunction(parameters, propertySpec, stops);
34
- }
35
-
36
- function convertIdentityFunction(parameters, propertySpec) {
37
- const get = ['get', parameters.property];
38
-
39
- if (parameters.default === undefined) {
40
- // By default, expressions for string-valued properties get coerced. To preserve
41
- // legacy function semantics, insert an explicit assertion instead.
42
- return propertySpec.type === 'string' ? ['string', get] : get;
43
- }
44
- if (propertySpec.type === 'enum') {
45
- return ['match', get, Object.keys(propertySpec.values), get, parameters.default];
46
- }
47
- const expression = [
48
- propertySpec.type === 'color' ? 'to-color' : propertySpec.type,
49
- get,
50
- convertLiteral(parameters.default)
51
- ];
52
- if (propertySpec.type === 'array') {
53
- expression.splice(1, 0, propertySpec.value, propertySpec.length || null);
54
- }
55
- return expression;
56
- }
57
-
58
- function getInterpolateOperator(parameters) {
59
- switch (parameters.colorSpace) {
60
- case 'hcl':
61
- return 'interpolate-hcl';
62
- case 'lab':
63
- return 'interpolate-lab';
64
- default:
65
- return 'interpolate';
66
- }
67
- }
68
-
69
- function convertZoomAndPropertyFunction(parameters, propertySpec, stops) {
70
- const featureFunctionParameters = {};
71
- const featureFunctionStops = {};
72
- const zoomStops = [];
73
- for (let s = 0; s < stops.length; s++) {
74
- const stop = stops[s];
75
- const zoom = stop[0].zoom;
76
- if (featureFunctionParameters[zoom] === undefined) {
77
- featureFunctionParameters[zoom] = {
78
- zoom: zoom,
79
- type: parameters.type,
80
- property: parameters.property,
81
- default: parameters.default
82
- };
83
- featureFunctionStops[zoom] = [];
84
- zoomStops.push(zoom);
85
- }
86
- featureFunctionStops[zoom].push([stop[0].value, stop[1]]);
87
- }
88
-
89
- // the interpolation type for the zoom dimension of a zoom-and-property
90
- // function is determined directly from the style property specification
91
- // for which it's being used: linear for interpolatable properties, step
92
- // otherwise.
93
- const functionType = getFunctionType({}, propertySpec);
94
- if (functionType === 'exponential') {
95
- const expression = [getInterpolateOperator(parameters), ['linear'], ['zoom']];
96
-
97
- for (const z of zoomStops) {
98
- const output = convertPropertyFunction(featureFunctionParameters[z], propertySpec, featureFunctionStops[z]);
99
- appendStopPair(expression, z, output, false);
100
- }
101
-
102
- return expression;
103
- }
104
- const expression = ['step', ['zoom']];
105
-
106
- for (const z of zoomStops) {
107
- const output = convertPropertyFunction(featureFunctionParameters[z], propertySpec, featureFunctionStops[z]);
108
- appendStopPair(expression, z, output, true);
109
- }
110
-
111
- fixupDegenerateStepCurve(expression);
112
-
113
- return expression;
114
- }
115
-
116
- function coalesce(a, b) {
117
- if (a !== undefined) return a;
118
- if (b !== undefined) return b;
119
- }
120
-
121
- function convertPropertyFunction(parameters, propertySpec, stops) {
122
- const type = getFunctionType(parameters, propertySpec);
123
- const get = ['get', parameters.property];
124
- if (type === 'categorical' && typeof stops[0][0] === 'boolean') {
125
- assert(parameters.stops.length > 0 && parameters.stops.length <= 2);
126
- const expression = ['case'];
127
- for (const stop of stops) {
128
- expression.push(['==', get, stop[0]], stop[1]);
129
- }
130
- expression.push(convertLiteral(coalesce(parameters.default, propertySpec.default)));
131
- return expression;
132
- }
133
- if (type === 'categorical') {
134
- const expression = ['match', get];
135
- for (const stop of stops) {
136
- appendStopPair(expression, stop[0], stop[1], false);
137
- }
138
- expression.push(convertLiteral(coalesce(parameters.default, propertySpec.default)));
139
- return expression;
140
- }
141
- if (type === 'interval') {
142
- const expression = ['step', ['number', get]];
143
- for (const stop of stops) {
144
- appendStopPair(expression, stop[0], stop[1], true);
145
- }
146
- fixupDegenerateStepCurve(expression);
147
- return parameters.default === undefined
148
- ? expression
149
- : ['case', ['==', ['typeof', get], 'number'], expression, convertLiteral(parameters.default)];
150
- }
151
- if (type === 'exponential') {
152
- const base = parameters.base !== undefined ? parameters.base : 1;
153
- const expression = [getInterpolateOperator(parameters), ['exponential', base], ['number', get]];
154
- for (const stop of stops) {
155
- appendStopPair(expression, stop[0], stop[1], false);
156
- }
157
- return parameters.default === undefined
158
- ? expression
159
- : ['case', ['==', ['typeof', get], 'number'], expression, convertLiteral(parameters.default)];
160
- }
161
- throw new Error(`Unknown property function type ${type}`);
162
- }
163
-
164
- function convertZoomFunction(parameters, propertySpec, stops, input = ['zoom']) {
165
- const type = getFunctionType(parameters, propertySpec);
166
- let expression;
167
- let isStep = false;
168
- if (type === 'interval') {
169
- expression = ['step', input];
170
- isStep = true;
171
- } else if (type === 'exponential') {
172
- const base = parameters.base !== undefined ? parameters.base : 1;
173
- expression = [getInterpolateOperator(parameters), ['exponential', base], input];
174
- } else {
175
- throw new Error(`Unknown zoom function type "${type}"`);
176
- }
177
-
178
- for (const stop of stops) {
179
- appendStopPair(expression, stop[0], stop[1], isStep);
180
- }
181
-
182
- fixupDegenerateStepCurve(expression);
183
-
184
- return expression;
185
- }
186
-
187
- function fixupDegenerateStepCurve(expression) {
188
- // degenerate step curve (i.e. a constant function): add a noop stop
189
- if (expression[0] === 'step' && expression.length === 3) {
190
- expression.push(0);
191
- expression.push(expression[3]);
192
- }
193
- }
194
-
195
- function appendStopPair(curve, input, output, isStep) {
196
- // Skip duplicate stop values. They were not validated for functions, but they are for expressions.
197
- // https://github.com/mapbox/mapbox-gl-js/issues/4107
198
- if (curve.length > 3 && input === curve[curve.length - 2]) {
199
- return;
200
- }
201
- // step curves don't get the first input value, as it is redundant.
202
- if (!(isStep && curve.length === 2)) {
203
- curve.push(input);
204
- }
205
- curve.push(output);
206
- }
207
-
208
- function getFunctionType(parameters, propertySpec) {
209
- if (parameters.type) {
210
- return parameters.type;
211
- }
212
- assert(propertySpec.expression);
213
- return propertySpec.expression.interpolated ? 'exponential' : 'interval';
214
- }
215
-
216
- // "String with {name} token" => ["concat", "String with ", ["get", "name"], " token"]
217
- function convertTokenString(s) {
218
- const result = ['concat'];
219
- const re = /{([^{}]+)}/g;
220
- let pos = 0;
221
- let match;
222
- while ((match = re.exec(s)) !== null) {
223
- const literal = s.slice(pos, re.lastIndex - match[0].length);
224
- pos = re.lastIndex;
225
- if (literal.length > 0) result.push(literal);
226
- result.push(['get', match[1]]);
227
- }
228
-
229
- if (result.length === 1) {
230
- return s;
231
- }
232
-
233
- if (pos < s.length) {
234
- result.push(s.slice(pos));
235
- } else if (result.length === 2) {
236
- return ['to-string', result[1]];
237
- }
238
-
239
- return result;
240
- }