@mapbox/mapbox-gl-style-spec 13.28.0 → 14.0.0-beta.1

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 (62) hide show
  1. package/bin/gl-style-composite.js +2 -2
  2. package/bin/gl-style-format.js +2 -2
  3. package/bin/gl-style-migrate.js +2 -2
  4. package/bin/gl-style-validate.js +2 -2
  5. package/data/extent.js +18 -0
  6. package/deref.js +1 -1
  7. package/diff.js +36 -15
  8. package/dist/index.cjs +5810 -1995
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.es.js +5808 -1991
  11. package/dist/index.es.js.map +1 -1
  12. package/expression/compound_expression.js +2 -1
  13. package/expression/definitions/assertion.js +2 -2
  14. package/expression/definitions/coercion.js +54 -15
  15. package/expression/definitions/comparison.js +2 -0
  16. package/expression/definitions/distance.js +597 -0
  17. package/expression/definitions/format.js +2 -2
  18. package/expression/definitions/image.js +34 -14
  19. package/expression/definitions/index.js +122 -8
  20. package/expression/definitions/interpolate.js +1 -1
  21. package/expression/definitions/match.js +2 -2
  22. package/expression/definitions/within.js +21 -92
  23. package/expression/evaluation_context.js +12 -1
  24. package/expression/index.js +74 -43
  25. package/expression/is_constant.js +19 -1
  26. package/expression/parsing_context.js +20 -16
  27. package/expression/types/formatted.js +2 -2
  28. package/expression/types/resolved_image.js +19 -8
  29. package/expression/types.js +2 -1
  30. package/expression/values.js +25 -0
  31. package/feature_filter/convert.js +1 -1
  32. package/feature_filter/index.js +4 -4
  33. package/flow-typed/cheap-ruler.js +25 -0
  34. package/flow-typed/geojson.js +8 -7
  35. package/flow-typed/gl-matrix.js +4 -2
  36. package/flow-typed/kdbush.js +9 -0
  37. package/function/convert.js +23 -12
  38. package/group_by_layout.js +2 -2
  39. package/migrate/expressions.js +3 -0
  40. package/package.json +5 -2
  41. package/reference/v8.json +1772 -112
  42. package/style-spec.js +4 -3
  43. package/types.js +190 -24
  44. package/util/color.js +31 -0
  45. package/util/geometry_util.js +145 -0
  46. package/util/properties.js +10 -2
  47. package/util/random.js +12 -0
  48. package/validate/validate.js +17 -7
  49. package/validate/validate_array.js +1 -1
  50. package/validate/validate_filter.js +4 -12
  51. package/validate/validate_function.js +2 -2
  52. package/validate/validate_import.js +31 -0
  53. package/validate/validate_layer.js +3 -2
  54. package/validate/validate_lights.js +84 -0
  55. package/validate/validate_model.js +38 -0
  56. package/validate/validate_property.js +17 -3
  57. package/validate/validate_source.js +3 -2
  58. package/validate/validate_style.js +29 -0
  59. package/validate_mapbox_api_supported.js +55 -11
  60. package/validate_style.js +4 -0
  61. package/validate_style.min.js +11 -19
  62. package/visit.js +3 -2
@@ -14,7 +14,7 @@ import {
14
14
  toString as typeToString
15
15
  } from '../types.js';
16
16
 
17
- import {typeOf, Color, validateRGBA, toString as valueToString} from '../values.js';
17
+ import {typeOf, Color, validateRGBA, validateHSLA, toString as valueToString} from '../values.js';
18
18
  import CompoundExpression from '../compound_expression.js';
19
19
  import RuntimeError from '../runtime_error.js';
20
20
  import Let from './let.js';
@@ -45,9 +45,12 @@ import FormatExpression from './format.js';
45
45
  import ImageExpression from './image.js';
46
46
  import Length from './length.js';
47
47
  import Within from './within.js';
48
+ import Distance from './distance.js';
48
49
 
50
+ import type EvaluationContext from '../evaluation_context.js';
49
51
  import type {Varargs} from '../compound_expression.js';
50
- import type {ExpressionRegistry} from '../expression.js';
52
+ import type {Expression, ExpressionRegistry} from '../expression.js';
53
+ import {mulberry32} from '../../util/random.js';
51
54
 
52
55
  const expressions: ExpressionRegistry = {
53
56
  // special forms
@@ -57,38 +60,60 @@ const expressions: ExpressionRegistry = {
57
60
  '<': LessThan,
58
61
  '>=': GreaterThanOrEqual,
59
62
  '<=': LessThanOrEqual,
63
+ // $FlowFixMe[method-unbinding]
60
64
  'array': Assertion,
65
+ // $FlowFixMe[method-unbinding]
61
66
  'at': At,
62
67
  'boolean': Assertion,
68
+ // $FlowFixMe[method-unbinding]
63
69
  'case': Case,
70
+ // $FlowFixMe[method-unbinding]
64
71
  'coalesce': Coalesce,
72
+ // $FlowFixMe[method-unbinding]
65
73
  'collator': CollatorExpression,
74
+ // $FlowFixMe[method-unbinding]
66
75
  'format': FormatExpression,
76
+ // $FlowFixMe[method-unbinding]
67
77
  'image': ImageExpression,
78
+ // $FlowFixMe[method-unbinding]
68
79
  'in': In,
80
+ // $FlowFixMe[method-unbinding]
69
81
  'index-of': IndexOf,
82
+ // $FlowFixMe[method-unbinding]
70
83
  'interpolate': Interpolate,
71
84
  'interpolate-hcl': Interpolate,
72
85
  'interpolate-lab': Interpolate,
86
+ // $FlowFixMe[method-unbinding]
73
87
  'length': Length,
88
+ // $FlowFixMe[method-unbinding]
74
89
  'let': Let,
90
+ // $FlowFixMe[method-unbinding]
75
91
  'literal': Literal,
92
+ // $FlowFixMe[method-unbinding]
76
93
  'match': Match,
77
94
  'number': Assertion,
95
+ // $FlowFixMe[method-unbinding]
78
96
  'number-format': NumberFormat,
79
97
  'object': Assertion,
98
+ // $FlowFixMe[method-unbinding]
80
99
  'slice': Slice,
100
+ // $FlowFixMe[method-unbinding]
81
101
  'step': Step,
82
102
  'string': Assertion,
103
+ // $FlowFixMe[method-unbinding]
83
104
  'to-boolean': Coercion,
84
105
  'to-color': Coercion,
85
106
  'to-number': Coercion,
86
107
  'to-string': Coercion,
108
+ // $FlowFixMe[method-unbinding]
87
109
  'var': Var,
88
- 'within': Within
110
+ // $FlowFixMe[method-unbinding]
111
+ 'within': Within,
112
+ // $FlowFixMe[method-unbinding]
113
+ 'distance': Distance
89
114
  };
90
115
 
91
- function rgba(ctx, [r, g, b, a]) {
116
+ function rgba(ctx: EvaluationContext, [r, g, b, a]: Array<Expression>) {
92
117
  r = r.evaluate(ctx);
93
118
  g = g.evaluate(ctx);
94
119
  b = b.evaluate(ctx);
@@ -98,16 +123,37 @@ function rgba(ctx, [r, g, b, a]) {
98
123
  return new Color(r / 255 * alpha, g / 255 * alpha, b / 255 * alpha, alpha);
99
124
  }
100
125
 
101
- function has(key, obj) {
126
+ function hsla(ctx: EvaluationContext, [h, s, l, a]: Array<Expression>) {
127
+ h = h.evaluate(ctx);
128
+ s = s.evaluate(ctx);
129
+ l = l.evaluate(ctx);
130
+ const alpha = a ? a.evaluate(ctx) : 1;
131
+ const error = validateHSLA(h, s, l, alpha);
132
+ if (error) throw new RuntimeError(error);
133
+ const colorFunction = `hsla(${h}, ${s}%, ${l}%, ${alpha})`;
134
+ const color = Color.parse(colorFunction);
135
+ if (!color) throw new RuntimeError(`Failed to parse HSLA color: ${colorFunction}`);
136
+ return color;
137
+ }
138
+
139
+ function has(key: string, obj: {[string]: any}): boolean {
102
140
  return key in obj;
103
141
  }
104
142
 
105
- function get(key, obj) {
143
+ function get(key: string, obj: {[string]: any}) {
106
144
  const v = obj[key];
107
145
  return typeof v === 'undefined' ? null : v;
108
146
  }
109
147
 
110
- function binarySearch(v, a, i, j) {
148
+ function getConfig(ctx: EvaluationContext, key: string, scope: string) {
149
+ if (scope.length) {
150
+ key += `\u{1f}${scope}`;
151
+ }
152
+ const v = ctx.getConfig(key);
153
+ return v ? v.evaluate(ctx) : null;
154
+ }
155
+
156
+ function binarySearch(v: any, a: {[number]: any}, i: number, j: number) {
111
157
  while (i <= j) {
112
158
  const m = (i + j) >> 1;
113
159
  if (a[m] === v)
@@ -124,6 +170,19 @@ function varargs(type: Type): Varargs {
124
170
  return {type};
125
171
  }
126
172
 
173
+ function hashString(str: string) {
174
+ let hash = 0;
175
+ if (str.length === 0) {
176
+ return hash;
177
+ }
178
+ for (let i = 0; i < str.length; i++) {
179
+ const char = str.charCodeAt(i);
180
+ hash = ((hash << 5) - hash) + char;
181
+ hash = hash & hash;
182
+ }
183
+ return hash;
184
+ }
185
+
127
186
  CompoundExpression.register(expressions, {
128
187
  'error': [
129
188
  ErrorType,
@@ -152,6 +211,16 @@ CompoundExpression.register(expressions, {
152
211
  [NumberType, NumberType, NumberType, NumberType],
153
212
  rgba
154
213
  ],
214
+ 'hsl': [
215
+ ColorType,
216
+ [NumberType, NumberType, NumberType],
217
+ hsla
218
+ ],
219
+ 'hsla': [
220
+ ColorType,
221
+ [NumberType, NumberType, NumberType, NumberType],
222
+ hsla
223
+ ],
155
224
  'has': {
156
225
  type: BooleanType,
157
226
  overloads: [
@@ -176,6 +245,18 @@ CompoundExpression.register(expressions, {
176
245
  ]
177
246
  ]
178
247
  },
248
+ 'config': {
249
+ type: ValueType,
250
+ overloads: [
251
+ [
252
+ [StringType],
253
+ (ctx, [key]) => getConfig(ctx, key.evaluate(ctx), '')
254
+ ], [
255
+ [StringType, StringType],
256
+ (ctx, [key, scope]) => getConfig(ctx, key.evaluate(ctx), scope.evaluate(ctx))
257
+ ]
258
+ ]
259
+ },
179
260
  'feature-state': [
180
261
  ValueType,
181
262
  [StringType],
@@ -211,6 +292,11 @@ CompoundExpression.register(expressions, {
211
292
  [],
212
293
  (ctx) => ctx.distanceFromCenter()
213
294
  ],
295
+ 'measure-light': [
296
+ NumberType,
297
+ [StringType],
298
+ (ctx, [s]) => ctx.measureLight(s.evaluate(ctx))
299
+ ],
214
300
  'heatmap-density': [
215
301
  NumberType,
216
302
  [],
@@ -221,6 +307,11 @@ CompoundExpression.register(expressions, {
221
307
  [],
222
308
  (ctx) => ctx.globals.lineProgress || 0
223
309
  ],
310
+ 'raster-value': [
311
+ NumberType,
312
+ [],
313
+ (ctx) => ctx.globals.rasterValue || 0
314
+ ],
224
315
  'sky-radial-progress': [
225
316
  NumberType,
226
317
  [],
@@ -574,7 +665,30 @@ CompoundExpression.register(expressions, {
574
665
  StringType,
575
666
  [CollatorType],
576
667
  (ctx, [collator]) => collator.evaluate(ctx).resolvedLocale()
577
- ]
668
+ ],
669
+ 'random': [
670
+ NumberType,
671
+ [NumberType, NumberType, ValueType],
672
+ (ctx, args) => {
673
+ const [min, max, seed] = args.map(arg => arg.evaluate(ctx));
674
+ if (min > max) {
675
+ return min;
676
+ }
677
+ if (min === max) {
678
+ return min;
679
+ }
680
+ let seedVal;
681
+ if (typeof seed === 'string') {
682
+ seedVal = hashString(seed);
683
+ } else if (typeof seed === 'number') {
684
+ seedVal = seed;
685
+ } else {
686
+ throw new RuntimeError(`Invalid seed input: ${seed}`);
687
+ }
688
+ const random = mulberry32(seedVal)();
689
+ return min + random * (max - min);
690
+ }
691
+ ],
578
692
  });
579
693
 
580
694
  export default expressions;
@@ -252,7 +252,7 @@ class Interpolate implements Expression {
252
252
  *
253
253
  * @private
254
254
  */
255
- function exponentialInterpolation(input, base, lowerValue, upperValue) {
255
+ function exponentialInterpolation(input: number, base: number, lowerValue: number, upperValue: number) {
256
256
  const difference = upperValue - lowerValue;
257
257
  const progress = input - lowerValue;
258
258
 
@@ -37,7 +37,7 @@ class Match implements Expression {
37
37
  return context.error(`Expected an even number of arguments.`);
38
38
 
39
39
  let inputType;
40
- let outputType;
40
+ let outputType: ?Type;
41
41
  if (context.expectedType && context.expectedType.kind !== 'value') {
42
42
  outputType = context.expectedType;
43
43
  }
@@ -138,7 +138,7 @@ class Match implements Expression {
138
138
  }
139
139
  }
140
140
 
141
- const coerceLabel = (label) => this.inputType.kind === 'number' ? Number(label) : label;
141
+ const coerceLabel = (label: number | string) => this.inputType.kind === 'number' ? Number(label) : label;
142
142
 
143
143
  for (const [outputIndex, labels] of groupedByOutput) {
144
144
  if (labels.length === 1) {
@@ -6,22 +6,16 @@ import {BooleanType} from '../types.js';
6
6
  import type {Expression, SerializedExpression} from '../expression.js';
7
7
  import type ParsingContext from '../parsing_context.js';
8
8
  import type EvaluationContext from '../evaluation_context.js';
9
- import type {GeoJSON, GeoJSONPolygon, GeoJSONMultiPolygon} from '@mapbox/geojson-types';
9
+ import type Point from '@mapbox/point-geometry';
10
+ import type {GeoJSON, GeoJSONPosition, GeoJSONPolygon, GeoJSONMultiPolygon} from '@mapbox/geojson-types';
10
11
  import type {CanonicalTileID} from '../../../source/tile_id.js';
12
+ import {updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment} from '../../util/geometry_util.js';
13
+ import type {BBox} from '../../util/geometry_util.js';
11
14
 
12
15
  type GeoJSONPolygons =| GeoJSONPolygon | GeoJSONMultiPolygon;
13
16
 
14
- // minX, minY, maxX, maxY
15
- type BBox = [number, number, number, number];
16
17
  const EXTENT = 8192;
17
18
 
18
- function updateBBox(bbox: BBox, coord: [number, number]) {
19
- bbox[0] = Math.min(bbox[0], coord[0]);
20
- bbox[1] = Math.min(bbox[1], coord[1]);
21
- bbox[2] = Math.max(bbox[2], coord[0]);
22
- bbox[3] = Math.max(bbox[3], coord[1]);
23
- }
24
-
25
19
  function mercatorXfromLng(lng: number) {
26
20
  return (180 + lng) / 360;
27
21
  }
@@ -30,92 +24,27 @@ function mercatorYfromLat(lat: number) {
30
24
  return (180 - (180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360)))) / 360;
31
25
  }
32
26
 
33
- function boxWithinBox(bbox1: BBox, bbox2: BBox) {
34
- if (bbox1[0] <= bbox2[0]) return false;
35
- if (bbox1[2] >= bbox2[2]) return false;
36
- if (bbox1[1] <= bbox2[1]) return false;
37
- if (bbox1[3] >= bbox2[3]) return false;
38
- return true;
39
- }
40
-
41
- function getTileCoordinates(p, canonical: CanonicalTileID) {
27
+ function getTileCoordinates(p: GeoJSONPosition, canonical: CanonicalTileID) {
42
28
  const x = mercatorXfromLng(p[0]);
43
29
  const y = mercatorYfromLat(p[1]);
44
30
  const tilesAtZoom = Math.pow(2, canonical.z);
45
31
  return [Math.round(x * tilesAtZoom * EXTENT), Math.round(y * tilesAtZoom * EXTENT)];
46
32
  }
47
33
 
48
- function onBoundary(p, p1, p2) {
49
- const x1 = p[0] - p1[0];
50
- const y1 = p[1] - p1[1];
51
- const x2 = p[0] - p2[0];
52
- const y2 = p[1] - p2[1];
53
- return (x1 * y2 - x2 * y1 === 0) && (x1 * x2 <= 0) && (y1 * y2 <= 0);
54
- }
55
-
56
- function rayIntersect(p, p1, p2) {
57
- return ((p1[1] > p[1]) !== (p2[1] > p[1])) && (p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0]);
58
- }
59
-
60
- // ray casting algorithm for detecting if point is in polygon
61
- function pointWithinPolygon(point, rings) {
62
- let inside = false;
63
- for (let i = 0, len = rings.length; i < len; i++) {
64
- const ring = rings[i];
65
- for (let j = 0, len2 = ring.length; j < len2 - 1; j++) {
66
- if (onBoundary(point, ring[j], ring[j + 1])) return false;
67
- if (rayIntersect(point, ring[j], ring[j + 1])) inside = !inside;
68
- }
69
- }
70
- return inside;
71
- }
72
-
73
- function pointWithinPolygons(point, polygons) {
34
+ function pointWithinPolygons(point: GeoJSONPosition, polygons: Array<Array<Array<GeoJSONPosition>>>) {
74
35
  for (let i = 0; i < polygons.length; i++) {
75
36
  if (pointWithinPolygon(point, polygons[i])) return true;
76
37
  }
77
38
  return false;
78
39
  }
79
40
 
80
- function perp(v1, v2) {
81
- return (v1[0] * v2[1] - v1[1] * v2[0]);
82
- }
83
-
84
- // check if p1 and p2 are in different sides of line segment q1->q2
85
- function twoSided(p1, p2, q1, q2) {
86
- // q1->p1 (x1, y1), q1->p2 (x2, y2), q1->q2 (x3, y3)
87
- const x1 = p1[0] - q1[0];
88
- const y1 = p1[1] - q1[1];
89
- const x2 = p2[0] - q1[0];
90
- const y2 = p2[1] - q1[1];
91
- const x3 = q2[0] - q1[0];
92
- const y3 = q2[1] - q1[1];
93
- const det1 = (x1 * y3 - x3 * y1);
94
- const det2 = (x2 * y3 - x3 * y2);
95
- if ((det1 > 0 && det2 < 0) || (det1 < 0 && det2 > 0)) return true;
96
- return false;
97
- }
98
- // a, b are end points for line segment1, c and d are end points for line segment2
99
- function lineIntersectLine(a, b, c, d) {
100
- // check if two segments are parallel or not
101
- // precondition is end point a, b is inside polygon, if line a->b is
102
- // parallel to polygon edge c->d, then a->b won't intersect with c->d
103
- const vectorP = [b[0] - a[0], b[1] - a[1]];
104
- const vectorQ = [d[0] - c[0], d[1] - c[1]];
105
- if (perp(vectorQ, vectorP) === 0) return false;
106
-
107
- // If lines are intersecting with each other, the relative location should be:
108
- // a and b lie in different sides of segment c->d
109
- // c and d lie in different sides of segment a->b
110
- if (twoSided(a, b, c, d) && twoSided(c, d, a, b)) return true;
111
- return false;
112
- }
113
-
114
- function lineIntersectPolygon(p1, p2, polygon) {
41
+ function lineIntersectPolygon(p1: GeoJSONPosition, p2: GeoJSONPosition, polygon: Array<Array<GeoJSONPosition>>) {
115
42
  for (const ring of polygon) {
116
43
  // loop through every edge of the ring
117
- for (let j = 0; j < ring.length - 1; ++j) {
118
- if (lineIntersectLine(p1, p2, ring[j], ring[j + 1])) {
44
+ for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
45
+ const q1 = ring[k];
46
+ const q2 = ring[j];
47
+ if (segmentIntersectSegment(p1, p2, q1, q2)) {
119
48
  return true;
120
49
  }
121
50
  }
@@ -123,7 +52,7 @@ function lineIntersectPolygon(p1, p2, polygon) {
123
52
  return false;
124
53
  }
125
54
 
126
- function lineStringWithinPolygon(line, polygon) {
55
+ function lineStringWithinPolygon(line: Array<GeoJSONPosition>, polygon: Array<Array<GeoJSONPosition>>) {
127
56
  // First, check if geometry points of line segments are all inside polygon
128
57
  for (let i = 0; i < line.length; ++i) {
129
58
  if (!pointWithinPolygon(line[i], polygon)) {
@@ -140,14 +69,14 @@ function lineStringWithinPolygon(line, polygon) {
140
69
  return true;
141
70
  }
142
71
 
143
- function lineStringWithinPolygons(line, polygons) {
72
+ function lineStringWithinPolygons(line: Array<GeoJSONPosition>, polygons: Array<Array<Array<GeoJSONPosition>>>) {
144
73
  for (let i = 0; i < polygons.length; i++) {
145
74
  if (lineStringWithinPolygon(line, polygons[i])) return true;
146
75
  }
147
76
  return false;
148
77
  }
149
78
 
150
- function getTilePolygon(coordinates, bbox: BBox, canonical: CanonicalTileID) {
79
+ function getTilePolygon(coordinates: Array<Array<GeoJSONPosition>>, bbox: BBox, canonical: CanonicalTileID) {
151
80
  const polygon = [];
152
81
  for (let i = 0; i < coordinates.length; i++) {
153
82
  const ring = [];
@@ -161,7 +90,7 @@ function getTilePolygon(coordinates, bbox: BBox, canonical: CanonicalTileID) {
161
90
  return polygon;
162
91
  }
163
92
 
164
- function getTilePolygons(coordinates, bbox, canonical: CanonicalTileID) {
93
+ function getTilePolygons(coordinates: Array<Array<Array<GeoJSONPosition>>>, bbox: BBox, canonical: CanonicalTileID) {
165
94
  const polygons = [];
166
95
  for (let i = 0; i < coordinates.length; i++) {
167
96
  const polygon = getTilePolygon(coordinates[i], bbox, canonical);
@@ -170,7 +99,7 @@ function getTilePolygons(coordinates, bbox, canonical: CanonicalTileID) {
170
99
  return polygons;
171
100
  }
172
101
 
173
- function updatePoint(p, bbox, polyBBox, worldSize) {
102
+ function updatePoint(p: GeoJSONPosition, bbox: BBox, polyBBox: Array<number>, worldSize: number) {
174
103
  if (p[0] < polyBBox[0] || p[0] > polyBBox[2]) {
175
104
  const halfWorldSize = worldSize * 0.5;
176
105
  let shift = (p[0] - polyBBox[0] > halfWorldSize) ? -worldSize : (polyBBox[0] - p[0] > halfWorldSize) ? worldSize : 0;
@@ -182,12 +111,12 @@ function updatePoint(p, bbox, polyBBox, worldSize) {
182
111
  updateBBox(bbox, p);
183
112
  }
184
113
 
185
- function resetBBox(bbox) {
114
+ function resetBBox(bbox: BBox) {
186
115
  bbox[0] = bbox[1] = Infinity;
187
116
  bbox[2] = bbox[3] = -Infinity;
188
117
  }
189
118
 
190
- function getTilePoints(geometry, pointBBox, polyBBox, canonical: CanonicalTileID) {
119
+ function getTilePoints(geometry: ?Array<Array<Point>>, pointBBox: BBox, polyBBox: Array<number>, canonical: CanonicalTileID) {
191
120
  const worldSize = Math.pow(2, canonical.z) * EXTENT;
192
121
  const shifts = [canonical.x * EXTENT, canonical.y * EXTENT];
193
122
  const tilePoints = [];
@@ -202,15 +131,15 @@ function getTilePoints(geometry, pointBBox, polyBBox, canonical: CanonicalTileID
202
131
  return tilePoints;
203
132
  }
204
133
 
205
- function getTileLines(geometry, lineBBox, polyBBox, canonical: CanonicalTileID) {
134
+ function getTileLines(geometry: ?Array<Array<Point>>, lineBBox: BBox, polyBBox: Array<number>, canonical: CanonicalTileID) {
206
135
  const worldSize = Math.pow(2, canonical.z) * EXTENT;
207
136
  const shifts = [canonical.x * EXTENT, canonical.y * EXTENT];
208
- const tileLines = [];
137
+ const tileLines: Array<Array<GeoJSONPosition>> = [];
209
138
  if (!geometry) return tileLines;
210
139
  for (const line of geometry) {
211
140
  const tileLine = [];
212
141
  for (const point of line) {
213
- const p = [point.x + shifts[0], point.y + shifts[1]];
142
+ const p: GeoJSONPosition = [point.x + shifts[0], point.y + shifts[1]];
214
143
  updateBBox(lineBBox, p);
215
144
  tileLine.push(p);
216
145
  }
@@ -1,6 +1,7 @@
1
1
  // @flow
2
2
 
3
3
  import {Color} from './values.js';
4
+ import type {Expression} from './expression.js';
4
5
 
5
6
  import type Point from '@mapbox/point-geometry';
6
7
  import type {FormattedSection} from './types/formatted.js';
@@ -19,10 +20,11 @@ class EvaluationContext {
19
20
  canonical: null | CanonicalTileID;
20
21
  featureTileCoord: ?Point;
21
22
  featureDistanceData: ?FeatureDistanceData;
23
+ options: ?Map<string, Expression>;
22
24
 
23
25
  _parseColorCache: {[_: string]: ?Color};
24
26
 
25
- constructor() {
27
+ constructor(options?: ?Map<string, Expression>) {
26
28
  this.globals = (null: any);
27
29
  this.feature = null;
28
30
  this.featureState = null;
@@ -32,6 +34,7 @@ class EvaluationContext {
32
34
  this.canonical = null;
33
35
  this.featureTileCoord = null;
34
36
  this.featureDistanceData = null;
37
+ this.options = options;
35
38
  }
36
39
 
37
40
  id(): number | null {
@@ -54,6 +57,10 @@ class EvaluationContext {
54
57
  return (this.feature && this.feature.properties) || {};
55
58
  }
56
59
 
60
+ measureLight(_: string): number {
61
+ return this.globals.brightness || 0;
62
+ }
63
+
57
64
  distanceFromCenter(): number {
58
65
  if (this.featureTileCoord && this.featureDistanceData) {
59
66
 
@@ -84,6 +91,10 @@ class EvaluationContext {
84
91
  }
85
92
  return cached;
86
93
  }
94
+
95
+ getConfig(id: string): ?Expression {
96
+ return this.options ? this.options.get(id) : null;
97
+ }
87
98
  }
88
99
 
89
100
  export default EvaluationContext;