@mapwhit/tilerenderer 0.49.0 → 0.50.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.
- package/build/min/package.json +1 -1
- package/build/min/src/shaders/fill_extrusion.fragment.glsl.txt +1 -9
- package/build/min/src/shaders/fill_extrusion.vertex.glsl.txt +4 -4
- package/package.json +1 -1
- package/src/data/bucket/symbol_bucket.js +15 -14
- package/src/shaders/fill_extrusion.fragment.glsl +0 -7
- package/src/shaders/fill_extrusion.vertex.glsl +4 -4
- package/src/style-spec/expression/definitions/coalesce.js +1 -3
- package/src/style-spec/expression/definitions/coercion.js +32 -21
- package/src/style-spec/expression/definitions/collator.js +1 -23
- package/src/style-spec/expression/definitions/{formatted.js → format.js} +3 -29
- package/src/style-spec/expression/definitions/index.js +7 -24
- package/src/style-spec/expression/definitions/let.js +1 -1
- package/src/style-spec/expression/definitions/literal.js +1 -1
- package/src/style-spec/expression/evaluation_context.js +3 -0
- package/src/style-spec/expression/index.js +18 -17
- package/src/style-spec/expression/parsing_context.js +25 -16
- package/src/style-spec/expression/types/collator.js +24 -0
- package/src/style-spec/expression/types/formatted.js +39 -0
- package/src/style-spec/expression/types.js +1 -1
- package/src/style-spec/expression/values.js +24 -1
- package/src/style-spec/function/convert.js +15 -9
- package/src/style-spec/function/index.js +4 -0
- package/src/style-spec/reference/v8.json +1 -1
- package/src/symbol/mergelines.js +2 -2
- package/src/symbol/placement.js +21 -2
- package/src/symbol/shaping.js +9 -18
- package/src/symbol/symbol_layout.js +2 -2
- package/src/symbol/transform_text.js +5 -8
package/build/min/package.json
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
varying vec4 v_color;
|
|
2
|
-
#pragma mapbox: define lowp float base
|
|
3
|
-
#pragma mapbox: define lowp float height
|
|
4
|
-
#pragma mapbox: define highp vec4 color
|
|
5
|
-
void main(){
|
|
6
|
-
#pragma mapbox: initialize lowp float base
|
|
7
|
-
#pragma mapbox: initialize lowp float height
|
|
8
|
-
#pragma mapbox: initialize highp vec4 color
|
|
9
|
-
gl_FragColor=v_color;
|
|
1
|
+
varying vec4 v_color;void main(){gl_FragColor=v_color;
|
|
10
2
|
#ifdef OVERDRAW_INSPECTOR
|
|
11
3
|
gl_FragColor=vec4(1.);
|
|
12
4
|
#endif
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
uniform mat4 u_matrix;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp float u_lightintensity;uniform float u_vertical_gradient;uniform lowp float u_opacity;attribute vec2 a_pos;attribute vec4 a_normal_ed;varying vec4 v_color;
|
|
2
|
-
#pragma mapbox: define
|
|
3
|
-
#pragma mapbox: define
|
|
2
|
+
#pragma mapbox: define highp float base
|
|
3
|
+
#pragma mapbox: define highp float height
|
|
4
4
|
#pragma mapbox: define highp vec4 color
|
|
5
5
|
void main(){
|
|
6
|
-
#pragma mapbox: initialize
|
|
7
|
-
#pragma mapbox: initialize
|
|
6
|
+
#pragma mapbox: initialize highp float base
|
|
7
|
+
#pragma mapbox: initialize highp float height
|
|
8
8
|
#pragma mapbox: initialize highp vec4 color
|
|
9
9
|
vec3 normal=a_normal_ed.xyz;base=max(0.,base);height=max(0.,height);float t=mod(normal.x,2.);gl_Position=u_matrix*vec4(a_pos,t>0.?height:base,1);float colorvalue=color.r*0.2126+color.g*0.7152+color.b*0.0722;v_color=vec4(0.,0.,0.,1.);vec4 ambientlight=vec4(0.03,0.03,0.03,1.);color+=ambientlight;float directional=clamp(dot(normal/16384.,u_lightpos),0.,1.);directional=mix((1.-u_lightintensity),max((1.-colorvalue+u_lightintensity),1.),directional);if(normal.y!=0.){directional*=((1.-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.,0.5),mix(0.7,0.98,1.-u_lightintensity),1.)));}v_color.r+=clamp(color.r*directional*u_lightcolor.r,mix(0.,0.3,1.-u_lightcolor.r),1.);v_color.g+=clamp(color.g*directional*u_lightcolor.g,mix(0.,0.3,1.-u_lightcolor.g),1.);v_color.b+=clamp(color.b*directional*u_lightcolor.b,mix(0.,0.3,1.-u_lightcolor.b),1.);v_color*=u_opacity;}
|
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@ const { verticalizedCharacterMap } = require('../../util/verticalize_punctuation
|
|
|
32
32
|
const { getSizeData } = require('../../symbol/symbol_size');
|
|
33
33
|
const { register } = require('../../util/transfer_registry');
|
|
34
34
|
const EvaluationParameters = require('../../style/evaluation_parameters');
|
|
35
|
-
const { Formatted } = require('../../style-spec/expression/
|
|
35
|
+
const { Formatted } = require('../../style-spec/expression/types/formatted');
|
|
36
36
|
|
|
37
37
|
// Opacity arrays are frequently updated but don't contain a lot of information, so we pack them
|
|
38
38
|
// tight. Each Uint32 is actually four duplicate Uint8s for the four corners of a glyph
|
|
@@ -267,8 +267,15 @@ class SymbolBucket {
|
|
|
267
267
|
|
|
268
268
|
let text;
|
|
269
269
|
if (hasText) {
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
// Expression evaluation will automatically coerce to Formatted
|
|
271
|
+
// but plain string token evaluation skips that pathway so do the
|
|
272
|
+
// conversion here.
|
|
273
|
+
const resolvedTokens = layer.getValueAndResolveTokens('text-field', feature);
|
|
274
|
+
text = transformText(
|
|
275
|
+
resolvedTokens instanceof Formatted ? resolvedTokens : Formatted.fromString(resolvedTokens),
|
|
276
|
+
layer,
|
|
277
|
+
feature
|
|
278
|
+
);
|
|
272
279
|
}
|
|
273
280
|
|
|
274
281
|
let icon;
|
|
@@ -300,19 +307,13 @@ class SymbolBucket {
|
|
|
300
307
|
|
|
301
308
|
if (text) {
|
|
302
309
|
const fontStack = textFont.evaluate(feature, {}).join(',');
|
|
303
|
-
const stack = (stacks[fontStack] = stacks[fontStack] || {});
|
|
304
310
|
const textAlongLine =
|
|
305
311
|
layout.get('text-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point';
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this.calculateGlyphDependencies(section.text, sectionStack, textAlongLine, doesAllowVerticalWritingMode);
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
const doesAllowVerticalWritingMode = allowsVerticalWritingMode(text);
|
|
315
|
-
this.calculateGlyphDependencies(text, stack, textAlongLine, doesAllowVerticalWritingMode);
|
|
312
|
+
for (const section of text.sections) {
|
|
313
|
+
const doesAllowVerticalWritingMode = allowsVerticalWritingMode(text.toString());
|
|
314
|
+
const sectionFont = section.fontStack || fontStack;
|
|
315
|
+
const sectionStack = (stacks[sectionFont] = stacks[sectionFont] || {});
|
|
316
|
+
this.calculateGlyphDependencies(section.text, sectionStack, textAlongLine, doesAllowVerticalWritingMode);
|
|
316
317
|
}
|
|
317
318
|
}
|
|
318
319
|
}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
varying vec4 v_color;
|
|
2
|
-
#pragma mapbox: define lowp float base
|
|
3
|
-
#pragma mapbox: define lowp float height
|
|
4
|
-
#pragma mapbox: define highp vec4 color
|
|
5
2
|
|
|
6
3
|
void main() {
|
|
7
|
-
#pragma mapbox: initialize lowp float base
|
|
8
|
-
#pragma mapbox: initialize lowp float height
|
|
9
|
-
#pragma mapbox: initialize highp vec4 color
|
|
10
|
-
|
|
11
4
|
gl_FragColor = v_color;
|
|
12
5
|
|
|
13
6
|
#ifdef OVERDRAW_INSPECTOR
|
|
@@ -10,14 +10,14 @@ attribute vec4 a_normal_ed;
|
|
|
10
10
|
|
|
11
11
|
varying vec4 v_color;
|
|
12
12
|
|
|
13
|
-
#pragma mapbox: define
|
|
14
|
-
#pragma mapbox: define
|
|
13
|
+
#pragma mapbox: define highp float base
|
|
14
|
+
#pragma mapbox: define highp float height
|
|
15
15
|
|
|
16
16
|
#pragma mapbox: define highp vec4 color
|
|
17
17
|
|
|
18
18
|
void main() {
|
|
19
|
-
#pragma mapbox: initialize
|
|
20
|
-
#pragma mapbox: initialize
|
|
19
|
+
#pragma mapbox: initialize highp float base
|
|
20
|
+
#pragma mapbox: initialize highp float height
|
|
21
21
|
#pragma mapbox: initialize highp vec4 color
|
|
22
22
|
|
|
23
23
|
vec3 normal = a_normal_ed.xyz;
|
|
@@ -20,9 +20,7 @@ class Coalesce {
|
|
|
20
20
|
const parsedArgs = [];
|
|
21
21
|
|
|
22
22
|
for (const arg of args.slice(1)) {
|
|
23
|
-
const parsed = context.parse(arg, 1 + parsedArgs.length, outputType, undefined, {
|
|
24
|
-
omitTypeAnnotations: true
|
|
25
|
-
});
|
|
23
|
+
const parsed = context.parse(arg, 1 + parsedArgs.length, outputType, undefined, { typeAnnotation: 'omit' });
|
|
26
24
|
if (!parsed) return null;
|
|
27
25
|
outputType = outputType || parsed.type;
|
|
28
26
|
parsedArgs.push(parsed);
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
const { Color, validateRGBA } = require('../values');
|
|
3
|
+
const { BooleanType, ColorType, NumberType, StringType, ValueType } = require('../types');
|
|
4
|
+
const { Color, toString: valueToString, validateRGBA } = require('../values');
|
|
5
5
|
const RuntimeError = require('../runtime_error');
|
|
6
|
-
const {
|
|
6
|
+
const { FormatExpression } = require('../definitions/format');
|
|
7
|
+
const { Formatted } = require('../types/formatted');
|
|
7
8
|
|
|
8
9
|
const types = {
|
|
10
|
+
'to-boolean': BooleanType,
|
|
11
|
+
'to-color': ColorType,
|
|
9
12
|
'to-number': NumberType,
|
|
10
|
-
'to-
|
|
13
|
+
'to-string': StringType
|
|
11
14
|
};
|
|
12
15
|
|
|
13
16
|
/**
|
|
@@ -29,6 +32,9 @@ class Coercion {
|
|
|
29
32
|
const name = args[0];
|
|
30
33
|
assert(types[name], name);
|
|
31
34
|
|
|
35
|
+
if ((name === 'to-boolean' || name === 'to-string') && args.length !== 2)
|
|
36
|
+
return context.error('Expected one argument.');
|
|
37
|
+
|
|
32
38
|
const type = types[name];
|
|
33
39
|
|
|
34
40
|
const parsed = [];
|
|
@@ -42,12 +48,18 @@ class Coercion {
|
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
evaluate(ctx) {
|
|
51
|
+
if (this.type.kind === 'boolean') {
|
|
52
|
+
return Boolean(this.args[0].evaluate(ctx));
|
|
53
|
+
}
|
|
45
54
|
if (this.type.kind === 'color') {
|
|
46
55
|
let input;
|
|
47
56
|
let error;
|
|
48
57
|
for (const arg of this.args) {
|
|
49
58
|
input = arg.evaluate(ctx);
|
|
50
59
|
error = null;
|
|
60
|
+
if (input instanceof Color) {
|
|
61
|
+
return input;
|
|
62
|
+
}
|
|
51
63
|
if (typeof input === 'string') {
|
|
52
64
|
const c = ctx.parseColor(input);
|
|
53
65
|
if (c) return c;
|
|
@@ -66,27 +78,23 @@ class Coercion {
|
|
|
66
78
|
error || `Could not parse color from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`
|
|
67
79
|
);
|
|
68
80
|
}
|
|
69
|
-
if (this.type.kind === '
|
|
70
|
-
let
|
|
81
|
+
if (this.type.kind === 'number') {
|
|
82
|
+
let value = null;
|
|
71
83
|
for (const arg of this.args) {
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
value = arg.evaluate(ctx);
|
|
85
|
+
if (value === null) return 0;
|
|
86
|
+
const num = Number(value);
|
|
87
|
+
if (isNaN(num)) continue;
|
|
88
|
+
return num;
|
|
76
89
|
}
|
|
77
|
-
throw new RuntimeError(
|
|
78
|
-
`Could not parse formatted text from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`
|
|
79
|
-
);
|
|
90
|
+
throw new RuntimeError(`Could not convert ${JSON.stringify(value)} to number.`);
|
|
80
91
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const num = Number(value);
|
|
86
|
-
if (isNaN(num)) continue;
|
|
87
|
-
return num;
|
|
92
|
+
if (this.type.kind === 'formatted') {
|
|
93
|
+
// There is no explicit 'to-formatted' but this coercion can be implicitly
|
|
94
|
+
// created by properties that expect the 'formatted' type.
|
|
95
|
+
return Formatted.fromString(valueToString(this.args[0].evaluate(ctx)));
|
|
88
96
|
}
|
|
89
|
-
|
|
97
|
+
return valueToString(this.args[0].evaluate(ctx));
|
|
90
98
|
}
|
|
91
99
|
|
|
92
100
|
eachChild(fn) {
|
|
@@ -98,6 +106,9 @@ class Coercion {
|
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
serialize() {
|
|
109
|
+
if (this.type.kind === 'formatted') {
|
|
110
|
+
return new FormatExpression([{ text: this.args[0], scale: null, font: null }]).serialize();
|
|
111
|
+
}
|
|
101
112
|
const serialized = [`to-${this.type.kind}`];
|
|
102
113
|
this.eachChild(child => {
|
|
103
114
|
serialized.push(child.serialize());
|
|
@@ -1,27 +1,5 @@
|
|
|
1
1
|
const { StringType, BooleanType, CollatorType } = require('../types');
|
|
2
|
-
|
|
3
|
-
class Collator {
|
|
4
|
-
constructor(caseSensitive, diacriticSensitive, locale) {
|
|
5
|
-
if (caseSensitive) this.sensitivity = diacriticSensitive ? 'variant' : 'case';
|
|
6
|
-
else this.sensitivity = diacriticSensitive ? 'accent' : 'base';
|
|
7
|
-
|
|
8
|
-
this.locale = locale;
|
|
9
|
-
this.collator = new Intl.Collator(this.locale ? this.locale : [], {
|
|
10
|
-
sensitivity: this.sensitivity,
|
|
11
|
-
usage: 'search'
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
compare(lhs, rhs) {
|
|
16
|
-
return this.collator.compare(lhs, rhs);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
resolvedLocale() {
|
|
20
|
-
// We create a Collator without "usage: search" because we don't want
|
|
21
|
-
// the search options encoded in our result (e.g. "en-u-co-search")
|
|
22
|
-
return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
2
|
+
const { Collator } = require('../types/collator');
|
|
25
3
|
|
|
26
4
|
class CollatorExpression {
|
|
27
5
|
constructor(caseSensitive, diacriticSensitive, locale) {
|
|
@@ -1,32 +1,6 @@
|
|
|
1
1
|
const { NumberType, ValueType, FormattedType, array, StringType } = require('../types');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
constructor(text, scale, fontStack) {
|
|
5
|
-
this.text = text;
|
|
6
|
-
this.scale = scale;
|
|
7
|
-
this.fontStack = fontStack;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class Formatted {
|
|
12
|
-
constructor(sections) {
|
|
13
|
-
this.sections = sections;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
toString() {
|
|
17
|
-
return this.sections.map(section => section.text).join('');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
serialize() {
|
|
21
|
-
const serialized = ['format'];
|
|
22
|
-
for (const section of this.sections) {
|
|
23
|
-
serialized.push(section.text);
|
|
24
|
-
const fontStack = section.fontStack ? ['literal', section.fontStack.split(',')] : null;
|
|
25
|
-
serialized.push({ 'text-font': fontStack, 'font-scale': section.scale });
|
|
26
|
-
}
|
|
27
|
-
return serialized;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
2
|
+
const { Formatted, FormattedSection } = require('../types/formatted');
|
|
3
|
+
const { toString } = require('../values');
|
|
30
4
|
|
|
31
5
|
class FormatExpression {
|
|
32
6
|
constructor(sections) {
|
|
@@ -77,7 +51,7 @@ class FormatExpression {
|
|
|
77
51
|
this.sections.map(
|
|
78
52
|
section =>
|
|
79
53
|
new FormattedSection(
|
|
80
|
-
section.text.evaluate(ctx)
|
|
54
|
+
toString(section.text.evaluate(ctx)),
|
|
81
55
|
section.scale ? section.scale.evaluate(ctx) : null,
|
|
82
56
|
section.font ? section.font.evaluate(ctx).join(',') : null
|
|
83
57
|
)
|
|
@@ -8,10 +8,10 @@ const {
|
|
|
8
8
|
ErrorType,
|
|
9
9
|
CollatorType,
|
|
10
10
|
array,
|
|
11
|
-
toString
|
|
11
|
+
toString: typeToString
|
|
12
12
|
} = require('../types');
|
|
13
13
|
|
|
14
|
-
const { typeOf, Color, validateRGBA } = require('../values');
|
|
14
|
+
const { typeOf, Color, validateRGBA, toString: valueToString } = require('../values');
|
|
15
15
|
const CompoundExpression = require('../compound_expression');
|
|
16
16
|
const RuntimeError = require('../runtime_error');
|
|
17
17
|
const Let = require('./let');
|
|
@@ -27,7 +27,7 @@ const Interpolate = require('./interpolate');
|
|
|
27
27
|
const Coalesce = require('./coalesce');
|
|
28
28
|
const { Equals, NotEquals, LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual } = require('./comparison');
|
|
29
29
|
const { CollatorExpression } = require('./collator');
|
|
30
|
-
const {
|
|
30
|
+
const { FormatExpression } = require('./format');
|
|
31
31
|
const Length = require('./length');
|
|
32
32
|
|
|
33
33
|
const expressions = {
|
|
@@ -56,8 +56,10 @@ const expressions = {
|
|
|
56
56
|
object: Assertion,
|
|
57
57
|
step: Step,
|
|
58
58
|
string: Assertion,
|
|
59
|
+
'to-boolean': Coercion,
|
|
59
60
|
'to-color': Coercion,
|
|
60
61
|
'to-number': Coercion,
|
|
62
|
+
'to-string': Coercion,
|
|
61
63
|
var: Var
|
|
62
64
|
};
|
|
63
65
|
|
|
@@ -102,26 +104,7 @@ CompoundExpression.register(expressions, {
|
|
|
102
104
|
throw new RuntimeError(v.evaluate(ctx));
|
|
103
105
|
}
|
|
104
106
|
],
|
|
105
|
-
typeof: [StringType, [ValueType], (ctx, [v]) =>
|
|
106
|
-
'to-string': [
|
|
107
|
-
StringType,
|
|
108
|
-
[ValueType],
|
|
109
|
-
(ctx, [v]) => {
|
|
110
|
-
v = v.evaluate(ctx);
|
|
111
|
-
const type = typeof v;
|
|
112
|
-
if (v === null) {
|
|
113
|
-
return '';
|
|
114
|
-
}
|
|
115
|
-
if (type === 'string' || type === 'number' || type === 'boolean') {
|
|
116
|
-
return String(v);
|
|
117
|
-
}
|
|
118
|
-
if (v instanceof Color || v instanceof Formatted) {
|
|
119
|
-
return v.toString();
|
|
120
|
-
}
|
|
121
|
-
return JSON.stringify(v);
|
|
122
|
-
}
|
|
123
|
-
],
|
|
124
|
-
'to-boolean': [BooleanType, [ValueType], (ctx, [v]) => Boolean(v.evaluate(ctx))],
|
|
107
|
+
typeof: [StringType, [ValueType], (ctx, [v]) => typeToString(typeOf(v.evaluate(ctx)))],
|
|
125
108
|
'to-rgba': [
|
|
126
109
|
array(NumberType, 4),
|
|
127
110
|
[ColorType],
|
|
@@ -349,7 +332,7 @@ CompoundExpression.register(expressions, {
|
|
|
349
332
|
],
|
|
350
333
|
upcase: [StringType, [StringType], (ctx, [s]) => s.evaluate(ctx).toUpperCase()],
|
|
351
334
|
downcase: [StringType, [StringType], (ctx, [s]) => s.evaluate(ctx).toLowerCase()],
|
|
352
|
-
concat: [StringType, varargs(
|
|
335
|
+
concat: [StringType, varargs(ValueType), (ctx, args) => args.map(arg => valueToString(arg.evaluate(ctx))).join('')],
|
|
353
336
|
'resolved-locale': [StringType, [CollatorType], (ctx, [collator]) => collator.evaluate(ctx).resolvedLocale()]
|
|
354
337
|
});
|
|
355
338
|
|
|
@@ -37,7 +37,7 @@ class Let {
|
|
|
37
37
|
bindings.push([name, value]);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const result = context.parse(args[args.length - 1], args.length - 1,
|
|
40
|
+
const result = context.parse(args[args.length - 1], args.length - 1, context.expectedType, bindings);
|
|
41
41
|
if (!result) return null;
|
|
42
42
|
|
|
43
43
|
return new Let(bindings, result);
|
|
@@ -18,17 +18,12 @@ class StyleExpression {
|
|
|
18
18
|
constructor(expression, propertySpec) {
|
|
19
19
|
this.expression = expression;
|
|
20
20
|
this._warningHistory = {};
|
|
21
|
+
this._evaluator = new EvaluationContext();
|
|
21
22
|
this._defaultValue = getDefaultValue(propertySpec);
|
|
22
|
-
|
|
23
|
-
this._enumValues = propertySpec.values;
|
|
24
|
-
}
|
|
23
|
+
this._enumValues = propertySpec.type === 'enum' ? propertySpec.values : null;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
evaluateWithoutErrorHandling(globals, feature, featureState) {
|
|
28
|
-
if (!this._evaluator) {
|
|
29
|
-
this._evaluator = new EvaluationContext();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
27
|
this._evaluator.globals = globals;
|
|
33
28
|
this._evaluator.feature = feature;
|
|
34
29
|
this._evaluator.featureState = featureState;
|
|
@@ -37,13 +32,9 @@ class StyleExpression {
|
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
evaluate(globals, feature, featureState) {
|
|
40
|
-
if (!this._evaluator) {
|
|
41
|
-
this._evaluator = new EvaluationContext();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
35
|
this._evaluator.globals = globals;
|
|
45
|
-
this._evaluator.feature = feature;
|
|
46
|
-
this._evaluator.featureState = featureState;
|
|
36
|
+
this._evaluator.feature = feature || null;
|
|
37
|
+
this._evaluator.featureState = featureState || null;
|
|
47
38
|
|
|
48
39
|
try {
|
|
49
40
|
const val = this.expression.evaluate(this._evaluator);
|
|
@@ -90,7 +81,16 @@ function isExpression(expression) {
|
|
|
90
81
|
*/
|
|
91
82
|
function createExpression(expression, propertySpec) {
|
|
92
83
|
const parser = new ParsingContext(definitions, [], getExpectedType(propertySpec));
|
|
93
|
-
|
|
84
|
+
|
|
85
|
+
// For string-valued properties, coerce to string at the top level rather than asserting.
|
|
86
|
+
const parsed = parser.parse(
|
|
87
|
+
expression,
|
|
88
|
+
undefined,
|
|
89
|
+
undefined,
|
|
90
|
+
undefined,
|
|
91
|
+
propertySpec.type === 'string' ? { typeAnnotation: 'coerce' } : undefined
|
|
92
|
+
);
|
|
93
|
+
|
|
94
94
|
if (!parsed) {
|
|
95
95
|
assert(parser.errors.length > 0);
|
|
96
96
|
return error(parser.errors);
|
|
@@ -283,7 +283,7 @@ function findZoomCurve(expression) {
|
|
|
283
283
|
return result;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
const { ColorType, StringType, NumberType, BooleanType, ValueType, array } = require('./types');
|
|
286
|
+
const { ColorType, StringType, NumberType, BooleanType, ValueType, FormattedType, array } = require('./types');
|
|
287
287
|
|
|
288
288
|
function getExpectedType(spec) {
|
|
289
289
|
const types = {
|
|
@@ -291,14 +291,15 @@ function getExpectedType(spec) {
|
|
|
291
291
|
string: StringType,
|
|
292
292
|
number: NumberType,
|
|
293
293
|
enum: StringType,
|
|
294
|
-
boolean: BooleanType
|
|
294
|
+
boolean: BooleanType,
|
|
295
|
+
formatted: FormattedType
|
|
295
296
|
};
|
|
296
297
|
|
|
297
298
|
if (spec.type === 'array') {
|
|
298
299
|
return array(types[spec.value] || ValueType, spec.length);
|
|
299
300
|
}
|
|
300
301
|
|
|
301
|
-
return types[spec.type]
|
|
302
|
+
return types[spec.type];
|
|
302
303
|
}
|
|
303
304
|
|
|
304
305
|
function getDefaultValue(spec) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
1
2
|
const Scope = require('./scope');
|
|
2
3
|
|
|
3
4
|
const { checkSubtype } = require('./types');
|
|
@@ -48,6 +49,16 @@ class ParsingContext {
|
|
|
48
49
|
expr = ['literal', expr];
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
function annotate(parsed, type, typeAnnotation) {
|
|
53
|
+
if (typeAnnotation === 'assert') {
|
|
54
|
+
return new Assertion(type, [parsed]);
|
|
55
|
+
}
|
|
56
|
+
if (typeAnnotation === 'coerce') {
|
|
57
|
+
return new Coercion(type, [parsed]);
|
|
58
|
+
}
|
|
59
|
+
return parsed;
|
|
60
|
+
}
|
|
61
|
+
|
|
51
62
|
if (Array.isArray(expr)) {
|
|
52
63
|
if (expr.length === 0) {
|
|
53
64
|
return this.error(
|
|
@@ -73,11 +84,14 @@ class ParsingContext {
|
|
|
73
84
|
const expected = this.expectedType;
|
|
74
85
|
const actual = parsed.type;
|
|
75
86
|
|
|
76
|
-
// When we expect a number, string, boolean, or array but
|
|
77
|
-
//
|
|
78
|
-
// When we expect a Color but have a String or Value, we
|
|
79
|
-
// can wrap it in "to-color" coercion.
|
|
87
|
+
// When we expect a number, string, boolean, or array but have a value, wrap it in an assertion.
|
|
88
|
+
// When we expect a color or formatted string, but have a string or value, wrap it in a coercion.
|
|
80
89
|
// Otherwise, we do static type-checking.
|
|
90
|
+
//
|
|
91
|
+
// These behaviors are overridable for:
|
|
92
|
+
// * The "coalesce" operator, which needs to omit type annotations.
|
|
93
|
+
// * String-valued properties (e.g. `text-field`), where coercion is more convenient than assertion.
|
|
94
|
+
//
|
|
81
95
|
if (
|
|
82
96
|
(expected.kind === 'string' ||
|
|
83
97
|
expected.kind === 'number' ||
|
|
@@ -86,18 +100,13 @@ class ParsingContext {
|
|
|
86
100
|
expected.kind === 'array') &&
|
|
87
101
|
actual.kind === 'value'
|
|
88
102
|
) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
} else if (expected.kind === 'formatted' && (actual.kind === 'value' || actual.kind === 'string')) {
|
|
97
|
-
if (!options.omitTypeAnnotations) {
|
|
98
|
-
parsed = new Coercion(expected, [parsed]);
|
|
99
|
-
}
|
|
100
|
-
} else if (this.checkSubtype(this.expectedType, parsed.type)) {
|
|
103
|
+
parsed = annotate(parsed, expected, options.typeAnnotation || 'assert');
|
|
104
|
+
} else if (
|
|
105
|
+
(expected.kind === 'color' || expected.kind === 'formatted') &&
|
|
106
|
+
(actual.kind === 'value' || actual.kind === 'string')
|
|
107
|
+
) {
|
|
108
|
+
parsed = annotate(parsed, expected, options.typeAnnotation || 'coerce');
|
|
109
|
+
} else if (this.checkSubtype(expected, actual)) {
|
|
101
110
|
return null;
|
|
102
111
|
}
|
|
103
112
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
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 };
|
|
@@ -0,0 +1,39 @@
|
|
|
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 };
|
|
@@ -53,7 +53,7 @@ function checkSubtype(expected, t) {
|
|
|
53
53
|
if (expected.kind === 'array') {
|
|
54
54
|
if (
|
|
55
55
|
t.kind === 'array' &&
|
|
56
|
-
!checkSubtype(expected.itemType, t.itemType) &&
|
|
56
|
+
((t.N === 0 && t.itemType.kind === 'value') || !checkSubtype(expected.itemType, t.itemType)) &&
|
|
57
57
|
(typeof expected.N !== 'number' || expected.N === t.N)
|
|
58
58
|
) {
|
|
59
59
|
return null;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
2
|
|
|
3
3
|
const Color = require('../util/color');
|
|
4
|
-
const { Collator } = require('./
|
|
4
|
+
const { Collator } = require('./types/collator');
|
|
5
|
+
const { Formatted } = require('./types/formatted');
|
|
5
6
|
const {
|
|
6
7
|
NullType,
|
|
7
8
|
NumberType,
|
|
@@ -11,6 +12,7 @@ const {
|
|
|
11
12
|
ObjectType,
|
|
12
13
|
ValueType,
|
|
13
14
|
CollatorType,
|
|
15
|
+
FormattedType,
|
|
14
16
|
array
|
|
15
17
|
} = require('./types');
|
|
16
18
|
|
|
@@ -58,6 +60,9 @@ function isValue(mixed) {
|
|
|
58
60
|
if (mixed instanceof Collator) {
|
|
59
61
|
return true;
|
|
60
62
|
}
|
|
63
|
+
if (mixed instanceof Formatted) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
61
66
|
if (Array.isArray(mixed)) {
|
|
62
67
|
for (const item of mixed) {
|
|
63
68
|
if (!isValue(item)) {
|
|
@@ -96,6 +101,9 @@ function typeOf(value) {
|
|
|
96
101
|
if (value instanceof Collator) {
|
|
97
102
|
return CollatorType;
|
|
98
103
|
}
|
|
104
|
+
if (value instanceof Formatted) {
|
|
105
|
+
return FormattedType;
|
|
106
|
+
}
|
|
99
107
|
if (Array.isArray(value)) {
|
|
100
108
|
const length = value.length;
|
|
101
109
|
let itemType;
|
|
@@ -117,7 +125,22 @@ function typeOf(value) {
|
|
|
117
125
|
return ObjectType;
|
|
118
126
|
}
|
|
119
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
|
+
|
|
120
142
|
module.exports = {
|
|
143
|
+
toString,
|
|
121
144
|
Color,
|
|
122
145
|
Collator,
|
|
123
146
|
validateRGBA,
|
|
@@ -2,6 +2,10 @@ const assert = require('assert');
|
|
|
2
2
|
|
|
3
3
|
module.exports = convertFunction;
|
|
4
4
|
|
|
5
|
+
function convertLiteral(value) {
|
|
6
|
+
return typeof value === 'object' ? ['literal', value] : value;
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
function convertFunction(parameters, propertySpec) {
|
|
6
10
|
let stops = parameters.stops;
|
|
7
11
|
if (!stops) {
|
|
@@ -17,7 +21,7 @@ function convertFunction(parameters, propertySpec) {
|
|
|
17
21
|
if (!featureDependent && propertySpec.tokens && typeof stop[1] === 'string') {
|
|
18
22
|
return [stop[0], convertTokenString(stop[1])];
|
|
19
23
|
}
|
|
20
|
-
return [stop[0],
|
|
24
|
+
return [stop[0], convertLiteral(stop[1])];
|
|
21
25
|
});
|
|
22
26
|
|
|
23
27
|
if (zoomAndFeatureDependent) {
|
|
@@ -33,7 +37,9 @@ function convertIdentityFunction(parameters, propertySpec) {
|
|
|
33
37
|
const get = ['get', parameters.property];
|
|
34
38
|
|
|
35
39
|
if (parameters.default === undefined) {
|
|
36
|
-
|
|
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;
|
|
37
43
|
}
|
|
38
44
|
if (propertySpec.type === 'enum') {
|
|
39
45
|
return ['match', get, Object.keys(propertySpec.values), get, parameters.default];
|
|
@@ -41,7 +47,7 @@ function convertIdentityFunction(parameters, propertySpec) {
|
|
|
41
47
|
const expression = [
|
|
42
48
|
propertySpec.type === 'color' ? 'to-color' : propertySpec.type,
|
|
43
49
|
get,
|
|
44
|
-
|
|
50
|
+
convertLiteral(parameters.default)
|
|
45
51
|
];
|
|
46
52
|
if (propertySpec.type === 'array') {
|
|
47
53
|
expression.splice(1, 0, propertySpec.value, propertySpec.length || null);
|
|
@@ -121,7 +127,7 @@ function convertPropertyFunction(parameters, propertySpec, stops) {
|
|
|
121
127
|
for (const stop of stops) {
|
|
122
128
|
expression.push(['==', get, stop[0]], stop[1]);
|
|
123
129
|
}
|
|
124
|
-
expression.push(
|
|
130
|
+
expression.push(convertLiteral(coalesce(parameters.default, propertySpec.default)));
|
|
125
131
|
return expression;
|
|
126
132
|
}
|
|
127
133
|
if (type === 'categorical') {
|
|
@@ -129,7 +135,7 @@ function convertPropertyFunction(parameters, propertySpec, stops) {
|
|
|
129
135
|
for (const stop of stops) {
|
|
130
136
|
appendStopPair(expression, stop[0], stop[1], false);
|
|
131
137
|
}
|
|
132
|
-
expression.push(
|
|
138
|
+
expression.push(convertLiteral(coalesce(parameters.default, propertySpec.default)));
|
|
133
139
|
return expression;
|
|
134
140
|
}
|
|
135
141
|
if (type === 'interval') {
|
|
@@ -140,7 +146,7 @@ function convertPropertyFunction(parameters, propertySpec, stops) {
|
|
|
140
146
|
fixupDegenerateStepCurve(expression);
|
|
141
147
|
return parameters.default === undefined
|
|
142
148
|
? expression
|
|
143
|
-
: ['case', ['==', ['typeof', get], 'number'], expression,
|
|
149
|
+
: ['case', ['==', ['typeof', get], 'number'], expression, convertLiteral(parameters.default)];
|
|
144
150
|
}
|
|
145
151
|
if (type === 'exponential') {
|
|
146
152
|
const base = parameters.base !== undefined ? parameters.base : 1;
|
|
@@ -150,7 +156,7 @@ function convertPropertyFunction(parameters, propertySpec, stops) {
|
|
|
150
156
|
}
|
|
151
157
|
return parameters.default === undefined
|
|
152
158
|
? expression
|
|
153
|
-
: ['case', ['==', ['typeof', get], 'number'], expression,
|
|
159
|
+
: ['case', ['==', ['typeof', get], 'number'], expression, convertLiteral(parameters.default)];
|
|
154
160
|
}
|
|
155
161
|
throw new Error(`Unknown property function type ${type}`);
|
|
156
162
|
}
|
|
@@ -217,7 +223,7 @@ function convertTokenString(s) {
|
|
|
217
223
|
const literal = s.slice(pos, re.lastIndex - match[0].length);
|
|
218
224
|
pos = re.lastIndex;
|
|
219
225
|
if (literal.length > 0) result.push(literal);
|
|
220
|
-
result.push(['
|
|
226
|
+
result.push(['get', match[1]]);
|
|
221
227
|
}
|
|
222
228
|
|
|
223
229
|
if (result.length === 1) {
|
|
@@ -227,7 +233,7 @@ function convertTokenString(s) {
|
|
|
227
233
|
if (pos < s.length) {
|
|
228
234
|
result.push(s.slice(pos));
|
|
229
235
|
} else if (result.length === 2) {
|
|
230
|
-
return result[1];
|
|
236
|
+
return ['to-string', result[1]];
|
|
231
237
|
}
|
|
232
238
|
|
|
233
239
|
return result;
|
|
@@ -3,6 +3,7 @@ const Color = require('../util/color');
|
|
|
3
3
|
const getType = require('../util/get_type');
|
|
4
4
|
const interpolate = require('../util/interpolate');
|
|
5
5
|
const Interpolate = require('../expression/definitions/interpolate');
|
|
6
|
+
const { Formatted } = require('../expression/types/formatted');
|
|
6
7
|
const { supportsInterpolation } = require('../util/properties');
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
@@ -203,6 +204,9 @@ function evaluateIdentityFunction(parameters, propertySpec, input) {
|
|
|
203
204
|
case 'color':
|
|
204
205
|
input = Color.parse(input);
|
|
205
206
|
break;
|
|
207
|
+
case 'formatted':
|
|
208
|
+
input = Formatted.fromString(input.toString());
|
|
209
|
+
break;
|
|
206
210
|
case 'enum':
|
|
207
211
|
if (!propertySpec.values.includes(input)) {
|
|
208
212
|
input = undefined;
|
|
@@ -3148,7 +3148,7 @@
|
|
|
3148
3148
|
}
|
|
3149
3149
|
},
|
|
3150
3150
|
"concat": {
|
|
3151
|
-
"doc": "Returns a `string` consisting of the concatenation of the inputs.
|
|
3151
|
+
"doc": "Returns a `string` consisting of the concatenation of the inputs. Each input is converted to a string as if by `to-string`.",
|
|
3152
3152
|
"group": "String",
|
|
3153
3153
|
"sdk-support": {
|
|
3154
3154
|
"basic functionality": {
|
package/src/symbol/mergelines.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { Formatted } = require('../style-spec/expression/
|
|
1
|
+
const { Formatted } = require('../style-spec/expression/types/formatted');
|
|
2
2
|
|
|
3
3
|
module.exports = function (features) {
|
|
4
4
|
const leftIndex = new Map();
|
|
@@ -8,7 +8,7 @@ module.exports = function (features) {
|
|
|
8
8
|
|
|
9
9
|
for (let k = 0; k < features.length; k++) {
|
|
10
10
|
const { geometry, text: featureText } = features[k];
|
|
11
|
-
const text = featureText
|
|
11
|
+
const text = featureText ? featureText.toString() : null;
|
|
12
12
|
|
|
13
13
|
if (!text) {
|
|
14
14
|
add(k);
|
package/src/symbol/placement.js
CHANGED
|
@@ -170,6 +170,25 @@ class Placement {
|
|
|
170
170
|
const textOptional = layout.get('text-optional');
|
|
171
171
|
const iconOptional = layout.get('icon-optional');
|
|
172
172
|
|
|
173
|
+
const textAllowOverlap = layout.get('text-allow-overlap');
|
|
174
|
+
const iconAllowOverlap = layout.get('icon-allow-overlap');
|
|
175
|
+
// This logic is similar to the "defaultOpacityState" logic below in updateBucketOpacities
|
|
176
|
+
// If we know a symbol is always supposed to show, force it to be marked visible even if
|
|
177
|
+
// it wasn't placed into the collision index (because some or all of it was outside the range
|
|
178
|
+
// of the collision grid).
|
|
179
|
+
// There is a subtle edge case here we're accepting:
|
|
180
|
+
// Symbol A has text-allow-overlap: true, icon-allow-overlap: true, icon-optional: false
|
|
181
|
+
// A's icon is outside the grid, so doesn't get placed
|
|
182
|
+
// A's text would be inside grid, but doesn't get placed because of icon-optional: false
|
|
183
|
+
// We still show A because of the allow-overlap settings.
|
|
184
|
+
// Symbol B has allow-overlap: false, and gets placed where A's text would be
|
|
185
|
+
// On panning in, there is a short period when Symbol B and Symbol A will overlap
|
|
186
|
+
// This is the reverse of our normal policy of "fade in on pan", but should look like any other
|
|
187
|
+
// collision and hopefully not be too noticeable.
|
|
188
|
+
// See https://github.com/mapbox/mapbox-gl-js/issues/7172
|
|
189
|
+
const alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || iconOptional);
|
|
190
|
+
const alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || textOptional);
|
|
191
|
+
|
|
173
192
|
const collisionGroup = this.collisionGroups.get(bucket.sourceID);
|
|
174
193
|
|
|
175
194
|
if (!bucket.collisionArrays && collisionBoxArray) {
|
|
@@ -304,8 +323,8 @@ class Placement {
|
|
|
304
323
|
assert(bucket.bucketInstanceId !== 0);
|
|
305
324
|
|
|
306
325
|
this.placements[symbolInstance.crossTileID] = new JointPlacement(
|
|
307
|
-
placeText,
|
|
308
|
-
placeIcon,
|
|
326
|
+
placeText || (alwaysShowText && placedGlyphBoxes),
|
|
327
|
+
placeIcon || alwaysShowIcon,
|
|
309
328
|
offscreen || bucket.justReloaded
|
|
310
329
|
);
|
|
311
330
|
seenCrossTileIDs[symbolInstance.crossTileID] = true;
|
package/src/symbol/shaping.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { charHasUprightVerticalOrientation, charAllowsIdeographicBreaking } = require('../util/script_detection');
|
|
2
2
|
const verticalizePunctuation = require('../util/verticalize_punctuation');
|
|
3
3
|
const { plugin: rtlTextPlugin } = require('../source/rtl_text_plugin');
|
|
4
|
-
const { Formatted } = require('../style-spec/expression/definitions/formatted');
|
|
5
4
|
|
|
6
5
|
const WritingMode = {
|
|
7
6
|
horizontal: 1,
|
|
@@ -24,23 +23,15 @@ class TaggedString {
|
|
|
24
23
|
|
|
25
24
|
static fromFeature(text, defaultFontStack) {
|
|
26
25
|
const result = new TaggedString();
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
result.sectionIndex.push(i);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
result.text = text;
|
|
41
|
-
result.sections.push({ scale: 1, fontStack: defaultFontStack });
|
|
42
|
-
for (let i = 0; i < text.length; i++) {
|
|
43
|
-
result.sectionIndex.push(0);
|
|
26
|
+
for (let i = 0; i < text.sections.length; i++) {
|
|
27
|
+
const section = text.sections[i];
|
|
28
|
+
result.sections.push({
|
|
29
|
+
scale: section.scale || 1,
|
|
30
|
+
fontStack: section.fontStack || defaultFontStack
|
|
31
|
+
});
|
|
32
|
+
result.text += section.text;
|
|
33
|
+
for (let j = 0; j < section.text.length; j++) {
|
|
34
|
+
result.sectionIndex.push(i);
|
|
44
35
|
}
|
|
45
36
|
}
|
|
46
37
|
return result;
|
|
@@ -12,7 +12,7 @@ const classifyRings = require('../util/classify_rings');
|
|
|
12
12
|
const EXTENT = require('../data/extent');
|
|
13
13
|
const SymbolBucket = require('../data/bucket/symbol_bucket');
|
|
14
14
|
const EvaluationParameters = require('../style/evaluation_parameters');
|
|
15
|
-
const { Formatted } = require('../style-spec/expression/
|
|
15
|
+
const { Formatted } = require('../style-spec/expression/types/formatted');
|
|
16
16
|
const murmur3 = require('murmurhash-js');
|
|
17
17
|
|
|
18
18
|
// The symbol layout process needs `text-size` evaluated at up to five different zoom levels, and
|
|
@@ -79,7 +79,7 @@ function performSymbolLayout(bucket, glyphMap, glyphPositions, imageMap, imagePo
|
|
|
79
79
|
const shapedTextOrientations = {};
|
|
80
80
|
const text = feature.text;
|
|
81
81
|
if (text) {
|
|
82
|
-
const unformattedText = text
|
|
82
|
+
const unformattedText = text.toString();
|
|
83
83
|
const textOffset = layout
|
|
84
84
|
.get('text-offset')
|
|
85
85
|
.evaluate(feature, {})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { plugin: rtlTextPlugin } = require('../source/rtl_text_plugin');
|
|
2
|
-
const { Formatted } = require('../style-spec/expression/
|
|
2
|
+
const { Formatted } = require('../style-spec/expression/types/formatted');
|
|
3
3
|
|
|
4
4
|
function transformText(text, layer, feature) {
|
|
5
5
|
const transform = layer.layout.get('text-transform').evaluate(feature, {});
|
|
@@ -17,11 +17,8 @@ function transformText(text, layer, feature) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
module.exports = function (text, layer, feature) {
|
|
20
|
-
|
|
21
|
-
text
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return text;
|
|
25
|
-
}
|
|
26
|
-
return transformText(text, layer, feature);
|
|
20
|
+
text.sections.forEach(section => {
|
|
21
|
+
section.text = transformText(section.text, layer, feature);
|
|
22
|
+
});
|
|
23
|
+
return text;
|
|
27
24
|
};
|