maplibre-gl 3.2.2 → 3.3.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/generate-struct-arrays.ts +3 -1
- package/build/generate-style-code.ts +7 -8
- package/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp-worker.js.map +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-csp.js.map +1 -1
- package/dist/maplibre-gl-dev.js +424 -168
- package/dist/maplibre-gl-dev.js.map +1 -1
- package/dist/maplibre-gl.d.ts +44 -7
- package/dist/maplibre-gl.js +3 -3
- package/dist/maplibre-gl.js.map +1 -1
- package/package.json +10 -10
- package/src/data/array_types.g.ts +78 -14
- package/src/data/bucket/symbol_attributes.ts +7 -1
- package/src/data/bucket/symbol_bucket.ts +4 -1
- package/src/render/draw_symbol.ts +8 -9
- package/src/style/properties.ts +4 -0
- package/src/style/style_layer/background_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/circle_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/fill_extrusion_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/fill_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/heatmap_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/hillshade_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/line_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/raster_style_layer_properties.g.ts +1 -6
- package/src/style/style_layer/symbol_style_layer_properties.g.ts +4 -6
- package/src/style/style_layer/variable_text_anchor.test.ts +117 -0
- package/src/style/style_layer/variable_text_anchor.ts +163 -0
- package/src/symbol/placement.ts +52 -40
- package/src/symbol/symbol_layout.ts +42 -116
package/dist/maplibre-gl-dev.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* MapLibre GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v3.
|
|
1
|
+
/* MapLibre GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v3.3.0/LICENSE.txt */
|
|
2
2
|
(function (global, factory) {
|
|
3
3
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
4
4
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
@@ -2549,6 +2549,25 @@ var layout_symbol = {
|
|
|
2549
2549
|
},
|
|
2550
2550
|
"property-type": "data-constant"
|
|
2551
2551
|
},
|
|
2552
|
+
"text-variable-anchor-offset": {
|
|
2553
|
+
type: "variableAnchorOffsetCollection",
|
|
2554
|
+
requires: [
|
|
2555
|
+
"text-field",
|
|
2556
|
+
{
|
|
2557
|
+
"symbol-placement": [
|
|
2558
|
+
"point"
|
|
2559
|
+
]
|
|
2560
|
+
}
|
|
2561
|
+
],
|
|
2562
|
+
expression: {
|
|
2563
|
+
interpolated: true,
|
|
2564
|
+
parameters: [
|
|
2565
|
+
"zoom",
|
|
2566
|
+
"feature"
|
|
2567
|
+
]
|
|
2568
|
+
},
|
|
2569
|
+
"property-type": "data-driven"
|
|
2570
|
+
},
|
|
2552
2571
|
"text-anchor": {
|
|
2553
2572
|
type: "enum",
|
|
2554
2573
|
values: {
|
|
@@ -4868,6 +4887,7 @@ const CollatorType = { kind: 'collator' };
|
|
|
4868
4887
|
const FormattedType = { kind: 'formatted' };
|
|
4869
4888
|
const PaddingType = { kind: 'padding' };
|
|
4870
4889
|
const ResolvedImageType = { kind: 'resolvedImage' };
|
|
4890
|
+
const VariableAnchorOffsetCollectionType = { kind: 'variableAnchorOffsetCollection' };
|
|
4871
4891
|
function array$1(itemType, N) {
|
|
4872
4892
|
return {
|
|
4873
4893
|
kind: 'array',
|
|
@@ -4896,7 +4916,8 @@ const valueMemberTypes = [
|
|
|
4896
4916
|
ObjectType,
|
|
4897
4917
|
array$1(ValueType),
|
|
4898
4918
|
PaddingType,
|
|
4899
|
-
ResolvedImageType
|
|
4919
|
+
ResolvedImageType,
|
|
4920
|
+
VariableAnchorOffsetCollectionType
|
|
4900
4921
|
];
|
|
4901
4922
|
/**
|
|
4902
4923
|
* Returns null if `t` is a subtype of `expected`; otherwise returns an
|
|
@@ -5592,6 +5613,44 @@ class Padding {
|
|
|
5592
5613
|
}
|
|
5593
5614
|
}
|
|
5594
5615
|
|
|
5616
|
+
/** Set of valid anchor positions, as a set for validation */
|
|
5617
|
+
const anchors = new Set(['center', 'left', 'right', 'top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right']);
|
|
5618
|
+
/**
|
|
5619
|
+
* Utility class to assist managing values for text-variable-anchor-offset property. Create instances from
|
|
5620
|
+
* bare arrays using the static method `VariableAnchorOffsetCollection.parse`.
|
|
5621
|
+
* @private
|
|
5622
|
+
*/
|
|
5623
|
+
class VariableAnchorOffsetCollection {
|
|
5624
|
+
constructor(values) {
|
|
5625
|
+
this.values = values.slice();
|
|
5626
|
+
}
|
|
5627
|
+
static parse(input) {
|
|
5628
|
+
if (input instanceof VariableAnchorOffsetCollection) {
|
|
5629
|
+
return input;
|
|
5630
|
+
}
|
|
5631
|
+
if (!Array.isArray(input) ||
|
|
5632
|
+
input.length < 1 ||
|
|
5633
|
+
input.length % 2 !== 0) {
|
|
5634
|
+
return undefined;
|
|
5635
|
+
}
|
|
5636
|
+
for (let i = 0; i < input.length; i += 2) {
|
|
5637
|
+
// Elements in even positions should be anchor positions; Elements in odd positions should be offset values
|
|
5638
|
+
const anchorValue = input[i];
|
|
5639
|
+
const offsetValue = input[i + 1];
|
|
5640
|
+
if (typeof anchorValue !== 'string' || !anchors.has(anchorValue)) {
|
|
5641
|
+
return undefined;
|
|
5642
|
+
}
|
|
5643
|
+
if (!Array.isArray(offsetValue) || offsetValue.length !== 2 || typeof offsetValue[0] !== 'number' || typeof offsetValue[1] !== 'number') {
|
|
5644
|
+
return undefined;
|
|
5645
|
+
}
|
|
5646
|
+
}
|
|
5647
|
+
return new VariableAnchorOffsetCollection(input);
|
|
5648
|
+
}
|
|
5649
|
+
toString() {
|
|
5650
|
+
return JSON.stringify(this.values);
|
|
5651
|
+
}
|
|
5652
|
+
}
|
|
5653
|
+
|
|
5595
5654
|
class ResolvedImage {
|
|
5596
5655
|
constructor(options) {
|
|
5597
5656
|
this.name = options.name;
|
|
@@ -5620,31 +5679,16 @@ function validateRGBA(r, g, b, a) {
|
|
|
5620
5679
|
return null;
|
|
5621
5680
|
}
|
|
5622
5681
|
function isValue(mixed) {
|
|
5623
|
-
if (mixed === null
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
return true;
|
|
5634
|
-
}
|
|
5635
|
-
else if (mixed instanceof Color) {
|
|
5636
|
-
return true;
|
|
5637
|
-
}
|
|
5638
|
-
else if (mixed instanceof Collator) {
|
|
5639
|
-
return true;
|
|
5640
|
-
}
|
|
5641
|
-
else if (mixed instanceof Formatted) {
|
|
5642
|
-
return true;
|
|
5643
|
-
}
|
|
5644
|
-
else if (mixed instanceof Padding) {
|
|
5645
|
-
return true;
|
|
5646
|
-
}
|
|
5647
|
-
else if (mixed instanceof ResolvedImage) {
|
|
5682
|
+
if (mixed === null ||
|
|
5683
|
+
typeof mixed === 'string' ||
|
|
5684
|
+
typeof mixed === 'boolean' ||
|
|
5685
|
+
typeof mixed === 'number' ||
|
|
5686
|
+
mixed instanceof Color ||
|
|
5687
|
+
mixed instanceof Collator ||
|
|
5688
|
+
mixed instanceof Formatted ||
|
|
5689
|
+
mixed instanceof Padding ||
|
|
5690
|
+
mixed instanceof VariableAnchorOffsetCollection ||
|
|
5691
|
+
mixed instanceof ResolvedImage) {
|
|
5648
5692
|
return true;
|
|
5649
5693
|
}
|
|
5650
5694
|
else if (Array.isArray(mixed)) {
|
|
@@ -5692,6 +5736,9 @@ function typeOf(value) {
|
|
|
5692
5736
|
else if (value instanceof Padding) {
|
|
5693
5737
|
return PaddingType;
|
|
5694
5738
|
}
|
|
5739
|
+
else if (value instanceof VariableAnchorOffsetCollection) {
|
|
5740
|
+
return VariableAnchorOffsetCollectionType;
|
|
5741
|
+
}
|
|
5695
5742
|
else if (value instanceof ResolvedImage) {
|
|
5696
5743
|
return ResolvedImageType;
|
|
5697
5744
|
}
|
|
@@ -5725,7 +5772,7 @@ function toString(value) {
|
|
|
5725
5772
|
else if (type === 'string' || type === 'number' || type === 'boolean') {
|
|
5726
5773
|
return String(value);
|
|
5727
5774
|
}
|
|
5728
|
-
else if (value instanceof Color || value instanceof Formatted || value instanceof Padding || value instanceof ResolvedImage) {
|
|
5775
|
+
else if (value instanceof Color || value instanceof Formatted || value instanceof Padding || value instanceof VariableAnchorOffsetCollection || value instanceof ResolvedImage) {
|
|
5729
5776
|
return value.toString();
|
|
5730
5777
|
}
|
|
5731
5778
|
else {
|
|
@@ -5889,71 +5936,80 @@ class Coercion {
|
|
|
5889
5936
|
return new Coercion(type, parsed);
|
|
5890
5937
|
}
|
|
5891
5938
|
evaluate(ctx) {
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
}
|
|
5904
|
-
else if (typeof input === 'string') {
|
|
5905
|
-
const c = ctx.parseColor(input);
|
|
5906
|
-
if (c)
|
|
5907
|
-
return c;
|
|
5908
|
-
}
|
|
5909
|
-
else if (Array.isArray(input)) {
|
|
5910
|
-
if (input.length < 3 || input.length > 4) {
|
|
5911
|
-
error = `Invalid rbga value ${JSON.stringify(input)}: expected an array containing either three or four numeric values.`;
|
|
5939
|
+
switch (this.type.kind) {
|
|
5940
|
+
case 'boolean':
|
|
5941
|
+
return Boolean(this.args[0].evaluate(ctx));
|
|
5942
|
+
case 'color': {
|
|
5943
|
+
let input;
|
|
5944
|
+
let error;
|
|
5945
|
+
for (const arg of this.args) {
|
|
5946
|
+
input = arg.evaluate(ctx);
|
|
5947
|
+
error = null;
|
|
5948
|
+
if (input instanceof Color) {
|
|
5949
|
+
return input;
|
|
5912
5950
|
}
|
|
5913
|
-
else {
|
|
5914
|
-
|
|
5951
|
+
else if (typeof input === 'string') {
|
|
5952
|
+
const c = ctx.parseColor(input);
|
|
5953
|
+
if (c)
|
|
5954
|
+
return c;
|
|
5915
5955
|
}
|
|
5916
|
-
if (
|
|
5917
|
-
|
|
5956
|
+
else if (Array.isArray(input)) {
|
|
5957
|
+
if (input.length < 3 || input.length > 4) {
|
|
5958
|
+
error = `Invalid rbga value ${JSON.stringify(input)}: expected an array containing either three or four numeric values.`;
|
|
5959
|
+
}
|
|
5960
|
+
else {
|
|
5961
|
+
error = validateRGBA(input[0], input[1], input[2], input[3]);
|
|
5962
|
+
}
|
|
5963
|
+
if (!error) {
|
|
5964
|
+
return new Color(input[0] / 255, input[1] / 255, input[2] / 255, input[3]);
|
|
5965
|
+
}
|
|
5918
5966
|
}
|
|
5919
5967
|
}
|
|
5968
|
+
throw new RuntimeError(error || `Could not parse color from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`);
|
|
5920
5969
|
}
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
return pad;
|
|
5970
|
+
case 'padding': {
|
|
5971
|
+
let input;
|
|
5972
|
+
for (const arg of this.args) {
|
|
5973
|
+
input = arg.evaluate(ctx);
|
|
5974
|
+
const pad = Padding.parse(input);
|
|
5975
|
+
if (pad) {
|
|
5976
|
+
return pad;
|
|
5977
|
+
}
|
|
5930
5978
|
}
|
|
5979
|
+
throw new RuntimeError(`Could not parse padding from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`);
|
|
5931
5980
|
}
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
continue;
|
|
5943
|
-
return num;
|
|
5981
|
+
case 'variableAnchorOffsetCollection': {
|
|
5982
|
+
let input;
|
|
5983
|
+
for (const arg of this.args) {
|
|
5984
|
+
input = arg.evaluate(ctx);
|
|
5985
|
+
const coll = VariableAnchorOffsetCollection.parse(input);
|
|
5986
|
+
if (coll) {
|
|
5987
|
+
return coll;
|
|
5988
|
+
}
|
|
5989
|
+
}
|
|
5990
|
+
throw new RuntimeError(`Could not parse variableAnchorOffsetCollection from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`);
|
|
5944
5991
|
}
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5992
|
+
case 'number': {
|
|
5993
|
+
let value = null;
|
|
5994
|
+
for (const arg of this.args) {
|
|
5995
|
+
value = arg.evaluate(ctx);
|
|
5996
|
+
if (value === null)
|
|
5997
|
+
return 0;
|
|
5998
|
+
const num = Number(value);
|
|
5999
|
+
if (isNaN(num))
|
|
6000
|
+
continue;
|
|
6001
|
+
return num;
|
|
6002
|
+
}
|
|
6003
|
+
throw new RuntimeError(`Could not convert ${JSON.stringify(value)} to number.`);
|
|
6004
|
+
}
|
|
6005
|
+
case 'formatted':
|
|
6006
|
+
// There is no explicit 'to-formatted' but this coercion can be implicitly
|
|
6007
|
+
// created by properties that expect the 'formatted' type.
|
|
6008
|
+
return Formatted.fromString(toString(this.args[0].evaluate(ctx)));
|
|
6009
|
+
case 'resolvedImage':
|
|
6010
|
+
return ResolvedImage.fromString(toString(this.args[0].evaluate(ctx)));
|
|
6011
|
+
default:
|
|
6012
|
+
return toString(this.args[0].evaluate(ctx));
|
|
5957
6013
|
}
|
|
5958
6014
|
}
|
|
5959
6015
|
eachChild(fn) {
|
|
@@ -6075,6 +6131,9 @@ class ParsingContext {
|
|
|
6075
6131
|
else if (expected.kind === 'padding' && (actual.kind === 'value' || actual.kind === 'number' || actual.kind === 'array')) {
|
|
6076
6132
|
parsed = annotate(parsed, expected, options.typeAnnotation || 'coerce');
|
|
6077
6133
|
}
|
|
6134
|
+
else if (expected.kind === 'variableAnchorOffsetCollection' && (actual.kind === 'value' || actual.kind === 'array')) {
|
|
6135
|
+
parsed = annotate(parsed, expected, options.typeAnnotation || 'coerce');
|
|
6136
|
+
}
|
|
6078
6137
|
else if (this.checkSubtype(expected, actual)) {
|
|
6079
6138
|
return null;
|
|
6080
6139
|
}
|
|
@@ -6845,6 +6904,7 @@ const interpolateFactory = (interpolationType) => {
|
|
|
6845
6904
|
case 'color': return color;
|
|
6846
6905
|
case 'array': return array;
|
|
6847
6906
|
case 'padding': return padding;
|
|
6907
|
+
case 'variableAnchorOffsetCollection': return variableAnchorOffsetCollection;
|
|
6848
6908
|
}
|
|
6849
6909
|
};
|
|
6850
6910
|
function number(from, to, t) {
|
|
@@ -6906,11 +6966,32 @@ function array(from, to, t) {
|
|
|
6906
6966
|
function padding(from, to, t) {
|
|
6907
6967
|
return new Padding(array(from.values, to.values, t));
|
|
6908
6968
|
}
|
|
6969
|
+
function variableAnchorOffsetCollection(from, to, t) {
|
|
6970
|
+
const fromValues = from.values;
|
|
6971
|
+
const toValues = to.values;
|
|
6972
|
+
if (fromValues.length !== toValues.length) {
|
|
6973
|
+
throw new RuntimeError(`Cannot interpolate values of different length. from: ${from.toString()}, to: ${to.toString()}`);
|
|
6974
|
+
}
|
|
6975
|
+
const output = [];
|
|
6976
|
+
for (let i = 0; i < fromValues.length; i += 2) {
|
|
6977
|
+
// Anchor entries must match
|
|
6978
|
+
if (fromValues[i] !== toValues[i]) {
|
|
6979
|
+
throw new RuntimeError(`Cannot interpolate values containing mismatched anchors. from[${i}]: ${fromValues[i]}, to[${i}]: ${toValues[i]}`);
|
|
6980
|
+
}
|
|
6981
|
+
output.push(fromValues[i]);
|
|
6982
|
+
// Interpolate the offset values for each anchor
|
|
6983
|
+
const [fx, fy] = fromValues[i + 1];
|
|
6984
|
+
const [tx, ty] = toValues[i + 1];
|
|
6985
|
+
output.push([number(fx, tx, t), number(fy, ty, t)]);
|
|
6986
|
+
}
|
|
6987
|
+
return new VariableAnchorOffsetCollection(output);
|
|
6988
|
+
}
|
|
6909
6989
|
const interpolate = {
|
|
6910
6990
|
number,
|
|
6911
6991
|
color,
|
|
6912
6992
|
array,
|
|
6913
6993
|
padding,
|
|
6994
|
+
variableAnchorOffsetCollection
|
|
6914
6995
|
};
|
|
6915
6996
|
|
|
6916
6997
|
class Interpolate {
|
|
@@ -7009,6 +7090,7 @@ class Interpolate {
|
|
|
7009
7090
|
if (!verifyType(outputType, NumberType) &&
|
|
7010
7091
|
!verifyType(outputType, ColorType) &&
|
|
7011
7092
|
!verifyType(outputType, PaddingType) &&
|
|
7093
|
+
!verifyType(outputType, VariableAnchorOffsetCollectionType) &&
|
|
7012
7094
|
!verifyType(outputType, array$1(NumberType))) {
|
|
7013
7095
|
return context.error(`Type ${toString$1(outputType)} is not interpolatable.`);
|
|
7014
7096
|
}
|
|
@@ -8868,6 +8950,9 @@ function normalizePropertyExpression(value, specification) {
|
|
|
8868
8950
|
else if (specification.type === 'padding' && (typeof value === 'number' || Array.isArray(value))) {
|
|
8869
8951
|
constant = Padding.parse(value);
|
|
8870
8952
|
}
|
|
8953
|
+
else if (specification.type === 'variableAnchorOffsetCollection' && Array.isArray(value)) {
|
|
8954
|
+
constant = VariableAnchorOffsetCollection.parse(value);
|
|
8955
|
+
}
|
|
8871
8956
|
return {
|
|
8872
8957
|
kind: 'constant',
|
|
8873
8958
|
evaluate: () => constant
|
|
@@ -8921,7 +9006,8 @@ function getExpectedType(spec) {
|
|
|
8921
9006
|
boolean: BooleanType,
|
|
8922
9007
|
formatted: FormattedType,
|
|
8923
9008
|
padding: PaddingType,
|
|
8924
|
-
resolvedImage: ResolvedImageType
|
|
9009
|
+
resolvedImage: ResolvedImageType,
|
|
9010
|
+
variableAnchorOffsetCollection: VariableAnchorOffsetCollectionType
|
|
8925
9011
|
};
|
|
8926
9012
|
if (spec.type === 'array') {
|
|
8927
9013
|
return array$1(types[spec.value] || ValueType, spec.length);
|
|
@@ -8941,6 +9027,9 @@ function getDefaultValue(spec) {
|
|
|
8941
9027
|
else if (spec.type === 'padding') {
|
|
8942
9028
|
return Padding.parse(spec.default) || null;
|
|
8943
9029
|
}
|
|
9030
|
+
else if (spec.type === 'variableAnchorOffsetCollection') {
|
|
9031
|
+
return VariableAnchorOffsetCollection.parse(spec.default) || null;
|
|
9032
|
+
}
|
|
8944
9033
|
else if (spec.default === undefined) {
|
|
8945
9034
|
return null;
|
|
8946
9035
|
}
|
|
@@ -10610,6 +10699,38 @@ function validatePadding(options) {
|
|
|
10610
10699
|
}
|
|
10611
10700
|
}
|
|
10612
10701
|
|
|
10702
|
+
function validateVariableAnchorOffsetCollection(options) {
|
|
10703
|
+
const key = options.key;
|
|
10704
|
+
const value = options.value;
|
|
10705
|
+
const type = getType(value);
|
|
10706
|
+
const styleSpec = options.styleSpec;
|
|
10707
|
+
if (type !== 'array' || value.length < 1 || value.length % 2 !== 0) {
|
|
10708
|
+
return [new ValidationError(key, value, 'variableAnchorOffsetCollection requires a non-empty array of even length')];
|
|
10709
|
+
}
|
|
10710
|
+
let errors = [];
|
|
10711
|
+
for (let i = 0; i < value.length; i += 2) {
|
|
10712
|
+
// Elements in even positions should be values from text-anchor enum
|
|
10713
|
+
errors = errors.concat(validateEnum({
|
|
10714
|
+
key: `${key}[${i}]`,
|
|
10715
|
+
value: value[i],
|
|
10716
|
+
valueSpec: styleSpec['layout_symbol']['text-anchor']
|
|
10717
|
+
}));
|
|
10718
|
+
// Elements in odd positions should be points (2-element numeric arrays)
|
|
10719
|
+
errors = errors.concat(validateArray({
|
|
10720
|
+
key: `${key}[${i + 1}]`,
|
|
10721
|
+
value: value[i + 1],
|
|
10722
|
+
valueSpec: {
|
|
10723
|
+
length: 2,
|
|
10724
|
+
value: 'number'
|
|
10725
|
+
},
|
|
10726
|
+
validateSpec: options.validateSpec,
|
|
10727
|
+
style: options.style,
|
|
10728
|
+
styleSpec
|
|
10729
|
+
}));
|
|
10730
|
+
}
|
|
10731
|
+
return errors;
|
|
10732
|
+
}
|
|
10733
|
+
|
|
10613
10734
|
function validateSprite(options) {
|
|
10614
10735
|
let errors = [];
|
|
10615
10736
|
const sprite = options.value;
|
|
@@ -10672,6 +10793,7 @@ const VALIDATORS = {
|
|
|
10672
10793
|
'formatted': validateFormatted,
|
|
10673
10794
|
'resolvedImage': validateImage,
|
|
10674
10795
|
'padding': validatePadding,
|
|
10796
|
+
'variableAnchorOffsetCollection': validateVariableAnchorOffsetCollection,
|
|
10675
10797
|
'sprite': validateSprite,
|
|
10676
10798
|
};
|
|
10677
10799
|
// Main recursive validation function. Tracks:
|
|
@@ -12246,6 +12368,9 @@ class Layout {
|
|
|
12246
12368
|
this._properties = properties;
|
|
12247
12369
|
this._values = Object.create(properties.defaultPropertyValues);
|
|
12248
12370
|
}
|
|
12371
|
+
hasValue(name) {
|
|
12372
|
+
return this._values[name].value !== undefined;
|
|
12373
|
+
}
|
|
12249
12374
|
getValue(name) {
|
|
12250
12375
|
return clone$9(this._values[name].value);
|
|
12251
12376
|
}
|
|
@@ -13371,10 +13496,11 @@ register('StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48', StructArrayLayout2i2ui3ul3u
|
|
|
13371
13496
|
* [0]: Int16[8]
|
|
13372
13497
|
* [16]: Uint16[15]
|
|
13373
13498
|
* [48]: Uint32[1]
|
|
13374
|
-
* [52]: Float32[
|
|
13499
|
+
* [52]: Float32[2]
|
|
13500
|
+
* [60]: Uint16[2]
|
|
13375
13501
|
*
|
|
13376
13502
|
*/
|
|
13377
|
-
class
|
|
13503
|
+
class StructArrayLayout8i15ui1ul2f2ui64 extends StructArray {
|
|
13378
13504
|
_refreshViews() {
|
|
13379
13505
|
this.uint8 = new Uint8Array(this.arrayBuffer);
|
|
13380
13506
|
this.int16 = new Int16Array(this.arrayBuffer);
|
|
@@ -13388,8 +13514,8 @@ class StructArrayLayout8i15ui1ul4f68 extends StructArray {
|
|
|
13388
13514
|
return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
|
|
13389
13515
|
}
|
|
13390
13516
|
emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) {
|
|
13391
|
-
const o2 = i *
|
|
13392
|
-
const o4 = i *
|
|
13517
|
+
const o2 = i * 32;
|
|
13518
|
+
const o4 = i * 16;
|
|
13393
13519
|
this.int16[o2 + 0] = v0;
|
|
13394
13520
|
this.int16[o2 + 1] = v1;
|
|
13395
13521
|
this.int16[o2 + 2] = v2;
|
|
@@ -13416,13 +13542,13 @@ class StructArrayLayout8i15ui1ul4f68 extends StructArray {
|
|
|
13416
13542
|
this.uint32[o4 + 12] = v23;
|
|
13417
13543
|
this.float32[o4 + 13] = v24;
|
|
13418
13544
|
this.float32[o4 + 14] = v25;
|
|
13419
|
-
this.
|
|
13420
|
-
this.
|
|
13545
|
+
this.uint16[o2 + 30] = v26;
|
|
13546
|
+
this.uint16[o2 + 31] = v27;
|
|
13421
13547
|
return i;
|
|
13422
13548
|
}
|
|
13423
13549
|
}
|
|
13424
|
-
|
|
13425
|
-
register('
|
|
13550
|
+
StructArrayLayout8i15ui1ul2f2ui64.prototype.bytesPerElement = 64;
|
|
13551
|
+
register('StructArrayLayout8i15ui1ul2f2ui64', StructArrayLayout8i15ui1ul2f2ui64);
|
|
13426
13552
|
/**
|
|
13427
13553
|
* @internal
|
|
13428
13554
|
* Implementation of the StructArray layout:
|
|
@@ -13447,6 +13573,35 @@ class StructArrayLayout1f4 extends StructArray {
|
|
|
13447
13573
|
}
|
|
13448
13574
|
StructArrayLayout1f4.prototype.bytesPerElement = 4;
|
|
13449
13575
|
register('StructArrayLayout1f4', StructArrayLayout1f4);
|
|
13576
|
+
/**
|
|
13577
|
+
* @internal
|
|
13578
|
+
* Implementation of the StructArray layout:
|
|
13579
|
+
* [0]: Uint16[1]
|
|
13580
|
+
* [4]: Float32[2]
|
|
13581
|
+
*
|
|
13582
|
+
*/
|
|
13583
|
+
class StructArrayLayout1ui2f12 extends StructArray {
|
|
13584
|
+
_refreshViews() {
|
|
13585
|
+
this.uint8 = new Uint8Array(this.arrayBuffer);
|
|
13586
|
+
this.uint16 = new Uint16Array(this.arrayBuffer);
|
|
13587
|
+
this.float32 = new Float32Array(this.arrayBuffer);
|
|
13588
|
+
}
|
|
13589
|
+
emplaceBack(v0, v1, v2) {
|
|
13590
|
+
const i = this.length;
|
|
13591
|
+
this.resize(i + 1);
|
|
13592
|
+
return this.emplace(i, v0, v1, v2);
|
|
13593
|
+
}
|
|
13594
|
+
emplace(i, v0, v1, v2) {
|
|
13595
|
+
const o2 = i * 6;
|
|
13596
|
+
const o4 = i * 3;
|
|
13597
|
+
this.uint16[o2 + 0] = v0;
|
|
13598
|
+
this.float32[o4 + 1] = v1;
|
|
13599
|
+
this.float32[o4 + 2] = v2;
|
|
13600
|
+
return i;
|
|
13601
|
+
}
|
|
13602
|
+
}
|
|
13603
|
+
StructArrayLayout1ui2f12.prototype.bytesPerElement = 12;
|
|
13604
|
+
register('StructArrayLayout1ui2f12', StructArrayLayout1ui2f12);
|
|
13450
13605
|
/**
|
|
13451
13606
|
* @internal
|
|
13452
13607
|
* Implementation of the StructArray layout:
|
|
@@ -13640,13 +13795,13 @@ class SymbolInstanceStruct extends Struct {
|
|
|
13640
13795
|
get crossTileID() { return this._structArray.uint32[this._pos4 + 12]; }
|
|
13641
13796
|
set crossTileID(x) { this._structArray.uint32[this._pos4 + 12] = x; }
|
|
13642
13797
|
get textBoxScale() { return this._structArray.float32[this._pos4 + 13]; }
|
|
13643
|
-
get
|
|
13644
|
-
get
|
|
13645
|
-
get
|
|
13798
|
+
get collisionCircleDiameter() { return this._structArray.float32[this._pos4 + 14]; }
|
|
13799
|
+
get textAnchorOffsetStartIndex() { return this._structArray.uint16[this._pos2 + 30]; }
|
|
13800
|
+
get textAnchorOffsetEndIndex() { return this._structArray.uint16[this._pos2 + 31]; }
|
|
13646
13801
|
}
|
|
13647
|
-
SymbolInstanceStruct.prototype.size =
|
|
13802
|
+
SymbolInstanceStruct.prototype.size = 64;
|
|
13648
13803
|
/** @internal */
|
|
13649
|
-
class SymbolInstanceArray extends
|
|
13804
|
+
class SymbolInstanceArray extends StructArrayLayout8i15ui1ul2f2ui64 {
|
|
13650
13805
|
/**
|
|
13651
13806
|
* Return the SymbolInstanceStruct at the given location in the array.
|
|
13652
13807
|
* @param index The index of the element.
|
|
@@ -13669,6 +13824,24 @@ class SymbolLineVertexArray extends StructArrayLayout3i6 {
|
|
|
13669
13824
|
}
|
|
13670
13825
|
register('SymbolLineVertexArray', SymbolLineVertexArray);
|
|
13671
13826
|
/** @internal */
|
|
13827
|
+
class TextAnchorOffsetStruct extends Struct {
|
|
13828
|
+
get textAnchor() { return this._structArray.uint16[this._pos2 + 0]; }
|
|
13829
|
+
get textOffset0() { return this._structArray.float32[this._pos4 + 1]; }
|
|
13830
|
+
get textOffset1() { return this._structArray.float32[this._pos4 + 2]; }
|
|
13831
|
+
}
|
|
13832
|
+
TextAnchorOffsetStruct.prototype.size = 12;
|
|
13833
|
+
/** @internal */
|
|
13834
|
+
class TextAnchorOffsetArray extends StructArrayLayout1ui2f12 {
|
|
13835
|
+
/**
|
|
13836
|
+
* Return the TextAnchorOffsetStruct at the given location in the array.
|
|
13837
|
+
* @param index The index of the element.
|
|
13838
|
+
*/
|
|
13839
|
+
get(index) {
|
|
13840
|
+
return new TextAnchorOffsetStruct(this, index);
|
|
13841
|
+
}
|
|
13842
|
+
}
|
|
13843
|
+
register('TextAnchorOffsetArray', TextAnchorOffsetArray);
|
|
13844
|
+
/** @internal */
|
|
13672
13845
|
class FeatureIndexStruct extends Struct {
|
|
13673
13846
|
get featureIndex() { return this._structArray.uint32[this._pos4 + 0]; }
|
|
13674
13847
|
get sourceLayerIndex() { return this._structArray.uint16[this._pos2 + 2]; }
|
|
@@ -25433,8 +25606,9 @@ const symbolInstance = createLayout([
|
|
|
25433
25606
|
{ type: 'Uint16', name: 'useRuntimeCollisionCircles' },
|
|
25434
25607
|
{ type: 'Uint32', name: 'crossTileID' },
|
|
25435
25608
|
{ type: 'Float32', name: 'textBoxScale' },
|
|
25436
|
-
{ type: 'Float32', components: 2, name: 'textOffset' },
|
|
25437
25609
|
{ type: 'Float32', name: 'collisionCircleDiameter' },
|
|
25610
|
+
{ type: 'Uint16', name: 'textAnchorOffsetStartIndex' },
|
|
25611
|
+
{ type: 'Uint16', name: 'textAnchorOffsetEndIndex' }
|
|
25438
25612
|
]);
|
|
25439
25613
|
const glyphOffset = createLayout([
|
|
25440
25614
|
{ type: 'Float32', name: 'offsetX' }
|
|
@@ -25444,6 +25618,10 @@ const lineVertex = createLayout([
|
|
|
25444
25618
|
{ type: 'Int16', name: 'y' },
|
|
25445
25619
|
{ type: 'Int16', name: 'tileUnitDistanceFromAnchor' }
|
|
25446
25620
|
]);
|
|
25621
|
+
const textAnchorOffset = createLayout([
|
|
25622
|
+
{ type: 'Uint16', name: 'textAnchor' },
|
|
25623
|
+
{ type: 'Float32', components: 2, name: 'textOffset' }
|
|
25624
|
+
]);
|
|
25447
25625
|
|
|
25448
25626
|
function transformTextInternal(text, layer, feature) {
|
|
25449
25627
|
const transform = layer.layout.get('text-transform').evaluate(feature, {});
|
|
@@ -27436,6 +27614,7 @@ class SymbolBucket {
|
|
|
27436
27614
|
this.glyphOffsetArray = new GlyphOffsetArray();
|
|
27437
27615
|
this.lineVertexArray = new SymbolLineVertexArray();
|
|
27438
27616
|
this.symbolInstances = new SymbolInstanceArray();
|
|
27617
|
+
this.textAnchorOffsets = new TextAnchorOffsetArray();
|
|
27439
27618
|
}
|
|
27440
27619
|
calculateGlyphDependencies(text, stack, textAlongLine, allowVerticalPlacement, doesAllowVerticalWritingMode) {
|
|
27441
27620
|
for (let i = 0; i < text.length; i++) {
|
|
@@ -27913,6 +28092,7 @@ const getLayout = () => layout = layout || new Properties({
|
|
|
27913
28092
|
"text-justify": new DataDrivenProperty(v8Spec["layout_symbol"]["text-justify"]),
|
|
27914
28093
|
"text-radial-offset": new DataDrivenProperty(v8Spec["layout_symbol"]["text-radial-offset"]),
|
|
27915
28094
|
"text-variable-anchor": new DataConstantProperty(v8Spec["layout_symbol"]["text-variable-anchor"]),
|
|
28095
|
+
"text-variable-anchor-offset": new DataDrivenProperty(v8Spec["layout_symbol"]["text-variable-anchor-offset"]),
|
|
27916
28096
|
"text-anchor": new DataDrivenProperty(v8Spec["layout_symbol"]["text-anchor"]),
|
|
27917
28097
|
"text-max-angle": new DataConstantProperty(v8Spec["layout_symbol"]["text-max-angle"]),
|
|
27918
28098
|
"text-writing-mode": new DataConstantProperty(v8Spec["layout_symbol"]["text-writing-mode"]),
|
|
@@ -30044,6 +30224,18 @@ function getCentroidCell(polygon) {
|
|
|
30044
30224
|
return new Cell(x / area, y / area, 0, polygon);
|
|
30045
30225
|
}
|
|
30046
30226
|
|
|
30227
|
+
exports.TextAnchorEnum = void 0;
|
|
30228
|
+
(function (TextAnchorEnum) {
|
|
30229
|
+
TextAnchorEnum[TextAnchorEnum["center"] = 1] = "center";
|
|
30230
|
+
TextAnchorEnum[TextAnchorEnum["left"] = 2] = "left";
|
|
30231
|
+
TextAnchorEnum[TextAnchorEnum["right"] = 3] = "right";
|
|
30232
|
+
TextAnchorEnum[TextAnchorEnum["top"] = 4] = "top";
|
|
30233
|
+
TextAnchorEnum[TextAnchorEnum["bottom"] = 5] = "bottom";
|
|
30234
|
+
TextAnchorEnum[TextAnchorEnum["top-left"] = 6] = "top-left";
|
|
30235
|
+
TextAnchorEnum[TextAnchorEnum["top-right"] = 7] = "top-right";
|
|
30236
|
+
TextAnchorEnum[TextAnchorEnum["bottom-left"] = 8] = "bottom-left";
|
|
30237
|
+
TextAnchorEnum[TextAnchorEnum["bottom-right"] = 9] = "bottom-right";
|
|
30238
|
+
})(exports.TextAnchorEnum || (exports.TextAnchorEnum = {}));
|
|
30047
30239
|
// The radial offset is to the edge of the text box
|
|
30048
30240
|
// In the horizontal direction, the edge of the text box is where glyphs start
|
|
30049
30241
|
// But in the vertical direction, the glyphs appear to "start" at the baseline
|
|
@@ -30125,14 +30317,60 @@ function evaluateVariableOffset(anchor, offset) {
|
|
|
30125
30317
|
}
|
|
30126
30318
|
return (offset[1] !== INVALID_TEXT_OFFSET) ? fromTextOffset(anchor, offset[0], offset[1]) : fromRadialOffset(anchor, offset[0]);
|
|
30127
30319
|
}
|
|
30320
|
+
// Helper to support both text-variable-anchor and text-variable-anchor-offset. Offset values converted from EMs to PXs
|
|
30321
|
+
function getTextVariableAnchorOffset(layer, feature, canonical) {
|
|
30322
|
+
var _a;
|
|
30323
|
+
const layout = layer.layout;
|
|
30324
|
+
// If style specifies text-variable-anchor-offset, just return it
|
|
30325
|
+
const variableAnchorOffset = (_a = layout.get('text-variable-anchor-offset')) === null || _a === void 0 ? void 0 : _a.evaluate(feature, {}, canonical);
|
|
30326
|
+
if (variableAnchorOffset) {
|
|
30327
|
+
const sourceValues = variableAnchorOffset.values;
|
|
30328
|
+
const destValues = [];
|
|
30329
|
+
// Convert offsets from EM to PX, and apply baseline shift
|
|
30330
|
+
for (let i = 0; i < sourceValues.length; i += 2) {
|
|
30331
|
+
const anchor = destValues[i] = sourceValues[i];
|
|
30332
|
+
const offset = sourceValues[i + 1].map(t => t * ONE_EM);
|
|
30333
|
+
if (anchor.startsWith('top')) {
|
|
30334
|
+
offset[1] -= baselineOffset;
|
|
30335
|
+
}
|
|
30336
|
+
else if (anchor.startsWith('bottom')) {
|
|
30337
|
+
offset[1] += baselineOffset;
|
|
30338
|
+
}
|
|
30339
|
+
destValues[i + 1] = offset;
|
|
30340
|
+
}
|
|
30341
|
+
return new VariableAnchorOffsetCollection(destValues);
|
|
30342
|
+
}
|
|
30343
|
+
// If style specifies text-variable-anchor, convert to the new format
|
|
30344
|
+
const variableAnchor = layout.get('text-variable-anchor');
|
|
30345
|
+
if (variableAnchor) {
|
|
30346
|
+
let textOffset;
|
|
30347
|
+
const unevaluatedLayout = layer._unevaluatedLayout;
|
|
30348
|
+
// The style spec says don't use `text-offset` and `text-radial-offset` together
|
|
30349
|
+
// but doesn't actually specify what happens if you use both. We go with the radial offset.
|
|
30350
|
+
if (unevaluatedLayout.getValue('text-radial-offset') !== undefined) {
|
|
30351
|
+
textOffset = [layout.get('text-radial-offset').evaluate(feature, {}, canonical) * ONE_EM, INVALID_TEXT_OFFSET];
|
|
30352
|
+
}
|
|
30353
|
+
else {
|
|
30354
|
+
textOffset = layout.get('text-offset').evaluate(feature, {}, canonical).map(t => t * ONE_EM);
|
|
30355
|
+
}
|
|
30356
|
+
const anchorOffsets = [];
|
|
30357
|
+
for (const anchor of variableAnchor) {
|
|
30358
|
+
anchorOffsets.push(anchor, evaluateVariableOffset(anchor, textOffset));
|
|
30359
|
+
}
|
|
30360
|
+
return new VariableAnchorOffsetCollection(anchorOffsets);
|
|
30361
|
+
}
|
|
30362
|
+
return null;
|
|
30363
|
+
}
|
|
30364
|
+
|
|
30128
30365
|
function performSymbolLayout(args) {
|
|
30129
30366
|
args.bucket.createArrays();
|
|
30130
30367
|
const tileSize = 512 * args.bucket.overscaling;
|
|
30131
30368
|
args.bucket.tilePixelRatio = EXTENT / tileSize;
|
|
30132
30369
|
args.bucket.compareText = {};
|
|
30133
30370
|
args.bucket.iconsNeedLinear = false;
|
|
30134
|
-
const
|
|
30135
|
-
const
|
|
30371
|
+
const layer = args.bucket.layers[0];
|
|
30372
|
+
const layout = layer.layout;
|
|
30373
|
+
const unevaluatedLayoutValues = layer._unevaluatedLayout._values;
|
|
30136
30374
|
const sizes = {
|
|
30137
30375
|
// Filled in below, if *SizeData.kind is 'composite'
|
|
30138
30376
|
// compositeIconSizes: undefined,
|
|
@@ -30175,8 +30413,8 @@ function performSymbolLayout(args) {
|
|
|
30175
30413
|
const spacing = layout.get('text-letter-spacing').evaluate(feature, {}, args.canonical) * ONE_EM;
|
|
30176
30414
|
const spacingIfAllowed = allowsLetterSpacing(unformattedText) ? spacing : 0;
|
|
30177
30415
|
const textAnchor = layout.get('text-anchor').evaluate(feature, {}, args.canonical);
|
|
30178
|
-
const
|
|
30179
|
-
if (!
|
|
30416
|
+
const variableAnchorOffset = getTextVariableAnchorOffset(layer, feature, args.canonical);
|
|
30417
|
+
if (!variableAnchorOffset) {
|
|
30180
30418
|
const radialOffset = layout.get('text-radial-offset').evaluate(feature, {}, args.canonical);
|
|
30181
30419
|
// Layers with variable anchors use the `text-radial-offset` property and the [x, y] offset vector
|
|
30182
30420
|
// is calculated at placement time instead of layout time
|
|
@@ -30205,13 +30443,18 @@ function performSymbolLayout(args) {
|
|
|
30205
30443
|
}
|
|
30206
30444
|
};
|
|
30207
30445
|
// If this layer uses text-variable-anchor, generate shapings for all justification possibilities.
|
|
30208
|
-
if (!textAlongLine &&
|
|
30209
|
-
const justifications =
|
|
30210
|
-
|
|
30211
|
-
|
|
30446
|
+
if (!textAlongLine && variableAnchorOffset) {
|
|
30447
|
+
const justifications = new Set();
|
|
30448
|
+
if (textJustify === 'auto') {
|
|
30449
|
+
for (let i = 0; i < variableAnchorOffset.values.length; i += 2) {
|
|
30450
|
+
justifications.add(getAnchorJustification(variableAnchorOffset.values[i]));
|
|
30451
|
+
}
|
|
30452
|
+
}
|
|
30453
|
+
else {
|
|
30454
|
+
justifications.add(textJustify);
|
|
30455
|
+
}
|
|
30212
30456
|
let singleLine = false;
|
|
30213
|
-
for (
|
|
30214
|
-
const justification = justifications[i];
|
|
30457
|
+
for (const justification of justifications) {
|
|
30215
30458
|
if (shapedTextOrientations.horizontal[justification])
|
|
30216
30459
|
continue;
|
|
30217
30460
|
if (singleLine) {
|
|
@@ -30376,6 +30619,18 @@ function addFeature(bucket, feature, shapedTextOrientations, shapedIcon, imageMa
|
|
|
30376
30619
|
}
|
|
30377
30620
|
}
|
|
30378
30621
|
}
|
|
30622
|
+
function addTextVariableAnchorOffsets(textAnchorOffsets, variableAnchorOffset) {
|
|
30623
|
+
const startIndex = textAnchorOffsets.length;
|
|
30624
|
+
const values = variableAnchorOffset === null || variableAnchorOffset === void 0 ? void 0 : variableAnchorOffset.values;
|
|
30625
|
+
if ((values === null || values === void 0 ? void 0 : values.length) > 0) {
|
|
30626
|
+
for (let i = 0; i < values.length; i += 2) {
|
|
30627
|
+
const anchor = exports.TextAnchorEnum[values[i]];
|
|
30628
|
+
const offset = values[i + 1];
|
|
30629
|
+
textAnchorOffsets.emplaceBack(anchor, offset[0], offset[1]);
|
|
30630
|
+
}
|
|
30631
|
+
}
|
|
30632
|
+
return [startIndex, textAnchorOffsets.length];
|
|
30633
|
+
}
|
|
30379
30634
|
function addTextVertices(bucket, anchor, shapedText, imageMap, layer, textAlongLine, feature, textOffset, lineArray, writingMode, placementTypes, placedTextSymbolIndices, placedIconIndex, sizes, canonical) {
|
|
30380
30635
|
const glyphQuads = getGlyphQuads(anchor, shapedText, textOffset, layer, textAlongLine, feature, imageMap, bucket.allowVerticalPlacement);
|
|
30381
30636
|
const sizeData = bucket.textSizeData;
|
|
@@ -30427,15 +30682,6 @@ function addSymbol(bucket, anchor, line, shapedTextOrientations, shapedIcon, ima
|
|
|
30427
30682
|
let verticalPlacedIconSymbolIndex = -1;
|
|
30428
30683
|
const placedTextSymbolIndices = {};
|
|
30429
30684
|
let key = murmur3$1('');
|
|
30430
|
-
let textOffset0 = 0;
|
|
30431
|
-
let textOffset1 = 0;
|
|
30432
|
-
if (layer._unevaluatedLayout.getValue('text-radial-offset') === undefined) {
|
|
30433
|
-
[textOffset0, textOffset1] = layer.layout.get('text-offset').evaluate(feature, {}, canonical).map(t => t * ONE_EM);
|
|
30434
|
-
}
|
|
30435
|
-
else {
|
|
30436
|
-
textOffset0 = layer.layout.get('text-radial-offset').evaluate(feature, {}, canonical) * ONE_EM;
|
|
30437
|
-
textOffset1 = INVALID_TEXT_OFFSET;
|
|
30438
|
-
}
|
|
30439
30685
|
if (bucket.allowVerticalPlacement && shapedTextOrientations.vertical) {
|
|
30440
30686
|
const textRotation = layer.layout.get('text-rotate').evaluate(feature, {}, canonical);
|
|
30441
30687
|
const verticalTextRotation = textRotation + 90.0;
|
|
@@ -30536,7 +30782,9 @@ function addSymbol(bucket, anchor, line, shapedTextOrientations, shapedIcon, ima
|
|
|
30536
30782
|
if (feature.sortKey !== undefined) {
|
|
30537
30783
|
bucket.addToSortKeyRanges(bucket.symbolInstances.length, feature.sortKey);
|
|
30538
30784
|
}
|
|
30539
|
-
|
|
30785
|
+
const variableAnchorOffset = getTextVariableAnchorOffset(layer, feature, canonical);
|
|
30786
|
+
const [textAnchorOffsetStartIndex, textAnchorOffsetEndIndex] = addTextVariableAnchorOffsets(bucket.textAnchorOffsets, variableAnchorOffset);
|
|
30787
|
+
bucket.symbolInstances.emplaceBack(anchor.x, anchor.y, placedTextSymbolIndices.right >= 0 ? placedTextSymbolIndices.right : -1, placedTextSymbolIndices.center >= 0 ? placedTextSymbolIndices.center : -1, placedTextSymbolIndices.left >= 0 ? placedTextSymbolIndices.left : -1, placedTextSymbolIndices.vertical || -1, placedIconSymbolIndex, verticalPlacedIconSymbolIndex, key, textBoxStartIndex, textBoxEndIndex, verticalTextBoxStartIndex, verticalTextBoxEndIndex, iconBoxStartIndex, iconBoxEndIndex, verticalIconBoxStartIndex, verticalIconBoxEndIndex, featureIndex, numHorizontalGlyphVertices, numVerticalGlyphVertices, numIconVertices, numVerticalIconVertices, useRuntimeCollisionCircles, 0, textBoxScale, collisionCircleDiameter, textAnchorOffsetStartIndex, textAnchorOffsetEndIndex);
|
|
30540
30788
|
}
|
|
30541
30789
|
function anchorIsTooClose(bucket, text, repeatDistance, anchor) {
|
|
30542
30790
|
const compareText = bucket.compareText;
|
|
@@ -31058,7 +31306,6 @@ exports.emptyStyle = emptyStyle;
|
|
|
31058
31306
|
exports.equals = equals$6;
|
|
31059
31307
|
exports.evaluateSizeForFeature = evaluateSizeForFeature;
|
|
31060
31308
|
exports.evaluateSizeForZoom = evaluateSizeForZoom;
|
|
31061
|
-
exports.evaluateVariableOffset = evaluateVariableOffset;
|
|
31062
31309
|
exports.evented = evented;
|
|
31063
31310
|
exports.extend = extend;
|
|
31064
31311
|
exports.filterObject = filterObject;
|
|
@@ -33782,7 +34029,7 @@ define(['./shared'], (function (performance) { 'use strict';
|
|
|
33782
34029
|
|
|
33783
34030
|
var name = "maplibre-gl";
|
|
33784
34031
|
var description = "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library";
|
|
33785
|
-
var version$2 = "3.
|
|
34032
|
+
var version$2 = "3.3.0";
|
|
33786
34033
|
var main = "dist/maplibre-gl.js";
|
|
33787
34034
|
var style = "dist/maplibre-gl.css";
|
|
33788
34035
|
var license = "BSD-3-Clause";
|
|
@@ -33801,7 +34048,7 @@ var dependencies = {
|
|
|
33801
34048
|
"@mapbox/unitbezier": "^0.0.1",
|
|
33802
34049
|
"@mapbox/vector-tile": "^1.3.1",
|
|
33803
34050
|
"@mapbox/whoots-js": "^3.1.0",
|
|
33804
|
-
"@maplibre/maplibre-gl-style-spec": "^19.
|
|
34051
|
+
"@maplibre/maplibre-gl-style-spec": "^19.3.0",
|
|
33805
34052
|
"@types/geojson": "^7946.0.10",
|
|
33806
34053
|
"@types/mapbox__point-geometry": "^0.1.2",
|
|
33807
34054
|
"@types/mapbox__vector-tile": "^1.3.0",
|
|
@@ -33835,7 +34082,7 @@ var devDependencies = {
|
|
|
33835
34082
|
"@types/d3": "^7.4.0",
|
|
33836
34083
|
"@types/diff": "^5.0.3",
|
|
33837
34084
|
"@types/earcut": "^2.1.1",
|
|
33838
|
-
"@types/eslint": "^8.44.
|
|
34085
|
+
"@types/eslint": "^8.44.2",
|
|
33839
34086
|
"@types/gl": "^6.0.2",
|
|
33840
34087
|
"@types/glob": "^8.1.0",
|
|
33841
34088
|
"@types/jest": "^29.5.3",
|
|
@@ -33843,24 +34090,24 @@ var devDependencies = {
|
|
|
33843
34090
|
"@types/minimist": "^1.2.2",
|
|
33844
34091
|
"@types/murmurhash-js": "^1.0.4",
|
|
33845
34092
|
"@types/nise": "^1.4.1",
|
|
33846
|
-
"@types/node": "^20.4.
|
|
34093
|
+
"@types/node": "^20.4.8",
|
|
33847
34094
|
"@types/offscreencanvas": "^2019.7.0",
|
|
33848
34095
|
"@types/pixelmatch": "^5.2.4",
|
|
33849
34096
|
"@types/pngjs": "^6.0.1",
|
|
33850
|
-
"@types/react": "^18.2.
|
|
34097
|
+
"@types/react": "^18.2.18",
|
|
33851
34098
|
"@types/react-dom": "^18.2.7",
|
|
33852
34099
|
"@types/request": "^2.48.8",
|
|
33853
34100
|
"@types/shuffle-seed": "^1.1.0",
|
|
33854
34101
|
"@types/window-or-global": "^1.0.4",
|
|
33855
|
-
"@typescript-eslint/eslint-plugin": "^6.2.
|
|
33856
|
-
"@typescript-eslint/parser": "^6.2.
|
|
34102
|
+
"@typescript-eslint/eslint-plugin": "^6.2.1",
|
|
34103
|
+
"@typescript-eslint/parser": "^6.2.1",
|
|
33857
34104
|
address: "^1.2.2",
|
|
33858
34105
|
benchmark: "^2.1.4",
|
|
33859
34106
|
canvas: "^2.11.2",
|
|
33860
34107
|
cssnano: "^6.0.1",
|
|
33861
34108
|
d3: "^7.8.5",
|
|
33862
34109
|
"d3-queue": "^3.0.7",
|
|
33863
|
-
"devtools-protocol": "^0.0.
|
|
34110
|
+
"devtools-protocol": "^0.0.1179426",
|
|
33864
34111
|
diff: "^5.1.0",
|
|
33865
34112
|
"dts-bundle-generator": "^8.0.1",
|
|
33866
34113
|
eslint: "^8.46.0",
|
|
@@ -33892,10 +34139,10 @@ var devDependencies = {
|
|
|
33892
34139
|
"postcss-cli": "^10.1.0",
|
|
33893
34140
|
"postcss-inline-svg": "^6.0.0",
|
|
33894
34141
|
"pretty-bytes": "^6.1.1",
|
|
33895
|
-
puppeteer: "^
|
|
34142
|
+
puppeteer: "^21.0.1",
|
|
33896
34143
|
react: "^18.2.0",
|
|
33897
34144
|
"react-dom": "^18.2.0",
|
|
33898
|
-
rollup: "^3.27.
|
|
34145
|
+
rollup: "^3.27.2",
|
|
33899
34146
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
33900
34147
|
rw: "^1.3.3",
|
|
33901
34148
|
semver: "^7.5.4",
|
|
@@ -40127,8 +40374,7 @@ function calculateVariableLayoutShift(anchor, width, height, textOffset, textBox
|
|
|
40127
40374
|
const { horizontalAlign, verticalAlign } = performance.getAnchorAlignment(anchor);
|
|
40128
40375
|
const shiftX = -(horizontalAlign - 0.5) * width;
|
|
40129
40376
|
const shiftY = -(verticalAlign - 0.5) * height;
|
|
40130
|
-
|
|
40131
|
-
return new performance.Point(shiftX + offset[0] * textBoxScale, shiftY + offset[1] * textBoxScale);
|
|
40377
|
+
return new performance.Point(shiftX + textOffset[0] * textBoxScale, shiftY + textOffset[1] * textBoxScale);
|
|
40132
40378
|
}
|
|
40133
40379
|
function shiftVariableCollisionBox(collisionBox, shiftX, shiftY, rotateWithMap, pitchWithMap, angle) {
|
|
40134
40380
|
const { x1, x2, y1, y2, anchorPointX, anchorPointY } = collisionBox;
|
|
@@ -40215,8 +40461,9 @@ class Placement {
|
|
|
40215
40461
|
});
|
|
40216
40462
|
}
|
|
40217
40463
|
}
|
|
40218
|
-
attemptAnchorPlacement(
|
|
40219
|
-
const
|
|
40464
|
+
attemptAnchorPlacement(textAnchorOffset, textBox, width, height, textBoxScale, rotateWithMap, pitchWithMap, textPixelRatio, posMatrix, collisionGroup, textOverlapMode, symbolInstance, bucket, orientation, iconBox, getElevation) {
|
|
40465
|
+
const anchor = performance.TextAnchorEnum[textAnchorOffset.textAnchor];
|
|
40466
|
+
const textOffset = [textAnchorOffset.textOffset0, textAnchorOffset.textOffset1];
|
|
40220
40467
|
const shift = calculateVariableLayoutShift(anchor, width, height, textOffset, textBoxScale);
|
|
40221
40468
|
const placedGlyphBoxes = this.collisionIndex.placeCollisionBox(shiftVariableCollisionBox(textBox, shift.x, shift.y, rotateWithMap, pitchWithMap, this.transform.angle), textOverlapMode, textPixelRatio, posMatrix, collisionGroup.predicate, getElevation);
|
|
40222
40469
|
if (iconBox) {
|
|
@@ -40286,6 +40533,7 @@ class Placement {
|
|
|
40286
40533
|
const tileID = this.retainedQueryData[bucket.bucketInstanceId].tileID;
|
|
40287
40534
|
const getElevation = this.terrain ? (x, y) => this.terrain.getElevation(tileID, x, y) : null;
|
|
40288
40535
|
const placeSymbol = (symbolInstance, collisionArrays) => {
|
|
40536
|
+
var _a, _b;
|
|
40289
40537
|
if (seenCrossTileIDs[symbolInstance.crossTileID])
|
|
40290
40538
|
return;
|
|
40291
40539
|
if (holdingForFade) {
|
|
@@ -40347,7 +40595,10 @@ class Placement {
|
|
|
40347
40595
|
placed = placeHorizontalFn();
|
|
40348
40596
|
}
|
|
40349
40597
|
};
|
|
40350
|
-
|
|
40598
|
+
const textAnchorOffsetStart = symbolInstance.textAnchorOffsetStartIndex;
|
|
40599
|
+
const textAnchorOffsetEnd = symbolInstance.textAnchorOffsetEndIndex;
|
|
40600
|
+
// If start+end indices match, text-variable-anchor is not in play.
|
|
40601
|
+
if (textAnchorOffsetEnd === textAnchorOffsetStart) {
|
|
40351
40602
|
const placeBox = (collisionTextBox, orientation) => {
|
|
40352
40603
|
const placedFeature = this.collisionIndex.placeCollisionBox(collisionTextBox, textOverlapMode, textPixelRatio, posMatrix, collisionGroup.predicate, getElevation);
|
|
40353
40604
|
if (placedFeature && placedFeature.box && placedFeature.box.length) {
|
|
@@ -40370,35 +40621,40 @@ class Placement {
|
|
|
40370
40621
|
updatePreviousOrientationIfNotPlaced(placed && placed.box && placed.box.length);
|
|
40371
40622
|
}
|
|
40372
40623
|
else {
|
|
40373
|
-
|
|
40374
|
-
|
|
40375
|
-
// anchor to the front of the anchor list, only if the previous anchor
|
|
40376
|
-
// is still in the anchor list
|
|
40377
|
-
if (this.prevPlacement && this.prevPlacement.variableOffsets[symbolInstance.crossTileID]) {
|
|
40378
|
-
const prevOffsets = this.prevPlacement.variableOffsets[symbolInstance.crossTileID];
|
|
40379
|
-
if (anchors.indexOf(prevOffsets.anchor) > 0) {
|
|
40380
|
-
anchors = anchors.filter(anchor => anchor !== prevOffsets.anchor);
|
|
40381
|
-
anchors.unshift(prevOffsets.anchor);
|
|
40382
|
-
}
|
|
40383
|
-
}
|
|
40624
|
+
// If this symbol was in the last placement, prefer placement using same anchor, if it's still available
|
|
40625
|
+
let prevAnchor = performance.TextAnchorEnum[(_b = (_a = this.prevPlacement) === null || _a === void 0 ? void 0 : _a.variableOffsets[symbolInstance.crossTileID]) === null || _b === void 0 ? void 0 : _b.anchor];
|
|
40384
40626
|
const placeBoxForVariableAnchors = (collisionTextBox, collisionIconBox, orientation) => {
|
|
40385
40627
|
const width = collisionTextBox.x2 - collisionTextBox.x1;
|
|
40386
40628
|
const height = collisionTextBox.y2 - collisionTextBox.y1;
|
|
40387
40629
|
const textBoxScale = symbolInstance.textBoxScale;
|
|
40388
40630
|
const variableIconBox = hasIconTextFit && (iconOverlapMode === 'never') ? collisionIconBox : null;
|
|
40389
40631
|
let placedBox = { box: [], offscreen: false };
|
|
40390
|
-
|
|
40391
|
-
|
|
40392
|
-
|
|
40393
|
-
|
|
40394
|
-
|
|
40395
|
-
|
|
40396
|
-
|
|
40397
|
-
|
|
40398
|
-
|
|
40399
|
-
|
|
40400
|
-
break;
|
|
40632
|
+
let placementPasses = (textOverlapMode === 'never') ? 1 : 2;
|
|
40633
|
+
let overlapMode = 'never';
|
|
40634
|
+
if (prevAnchor) {
|
|
40635
|
+
placementPasses++;
|
|
40636
|
+
}
|
|
40637
|
+
for (let pass = 0; pass < placementPasses; pass++) {
|
|
40638
|
+
for (let i = textAnchorOffsetStart; i < textAnchorOffsetEnd; i++) {
|
|
40639
|
+
const textAnchorOffset = bucket.textAnchorOffsets.get(i);
|
|
40640
|
+
if (prevAnchor && textAnchorOffset.textAnchor !== prevAnchor) {
|
|
40641
|
+
continue;
|
|
40401
40642
|
}
|
|
40643
|
+
const result = this.attemptAnchorPlacement(textAnchorOffset, collisionTextBox, width, height, textBoxScale, rotateWithMap, pitchWithMap, textPixelRatio, posMatrix, collisionGroup, overlapMode, symbolInstance, bucket, orientation, variableIconBox, getElevation);
|
|
40644
|
+
if (result) {
|
|
40645
|
+
placedBox = result.placedGlyphBoxes;
|
|
40646
|
+
if (placedBox && placedBox.box && placedBox.box.length) {
|
|
40647
|
+
placeText = true;
|
|
40648
|
+
shift = result.shift;
|
|
40649
|
+
return placedBox;
|
|
40650
|
+
}
|
|
40651
|
+
}
|
|
40652
|
+
}
|
|
40653
|
+
if (prevAnchor) {
|
|
40654
|
+
prevAnchor = null;
|
|
40655
|
+
}
|
|
40656
|
+
else {
|
|
40657
|
+
overlapMode = textOverlapMode;
|
|
40402
40658
|
}
|
|
40403
40659
|
}
|
|
40404
40660
|
return placedBox;
|
|
@@ -40670,11 +40926,12 @@ class Placement {
|
|
|
40670
40926
|
bucket.iconCollisionBox.collisionVertexArray.clear();
|
|
40671
40927
|
if (bucket.hasTextCollisionBoxData())
|
|
40672
40928
|
bucket.textCollisionBox.collisionVertexArray.clear();
|
|
40673
|
-
const
|
|
40929
|
+
const layer = bucket.layers[0];
|
|
40930
|
+
const layout = layer.layout;
|
|
40674
40931
|
const duplicateOpacityState = new JointOpacityState(null, 0, false, false, true);
|
|
40675
40932
|
const textAllowOverlap = layout.get('text-allow-overlap');
|
|
40676
40933
|
const iconAllowOverlap = layout.get('icon-allow-overlap');
|
|
40677
|
-
const
|
|
40934
|
+
const hasVariablePlacement = layer._unevaluatedLayout.hasValue('text-variable-anchor') || layer._unevaluatedLayout.hasValue('text-variable-anchor-offset');
|
|
40678
40935
|
const rotateWithMap = layout.get('text-rotation-alignment') === 'map';
|
|
40679
40936
|
const pitchWithMap = layout.get('text-pitch-alignment') === 'map';
|
|
40680
40937
|
const hasIconTextFit = layout.get('icon-text-fit') !== 'none';
|
|
@@ -40768,7 +41025,7 @@ class Placement {
|
|
|
40768
41025
|
let shift = new performance.Point(0, 0);
|
|
40769
41026
|
if (collisionArrays.textBox || collisionArrays.verticalTextBox) {
|
|
40770
41027
|
let used = true;
|
|
40771
|
-
if (
|
|
41028
|
+
if (hasVariablePlacement) {
|
|
40772
41029
|
const variableOffset = this.variableOffsets[crossTileID];
|
|
40773
41030
|
if (variableOffset) {
|
|
40774
41031
|
// This will show either the currently placed position or the last
|
|
@@ -44771,10 +45028,10 @@ function drawSymbols(painter, sourceCache, layer, coords, variableOffsets) {
|
|
|
44771
45028
|
// Disable the stencil test so that labels aren't clipped to tile boundaries.
|
|
44772
45029
|
const stencilMode = StencilMode.disabled;
|
|
44773
45030
|
const colorMode = painter.colorModeForRenderPass();
|
|
44774
|
-
const
|
|
45031
|
+
const hasVariablePlacement = layer._unevaluatedLayout.hasValue('text-variable-anchor') || layer._unevaluatedLayout.hasValue('text-variable-anchor-offset');
|
|
44775
45032
|
//Compute variable-offsets before painting since icons and text data positioning
|
|
44776
45033
|
//depend on each other in this case.
|
|
44777
|
-
if (
|
|
45034
|
+
if (hasVariablePlacement) {
|
|
44778
45035
|
updateVariableAnchors(coords, painter, layer, sourceCache, layer.layout.get('text-rotation-alignment'), layer.layout.get('text-pitch-alignment'), variableOffsets);
|
|
44779
45036
|
}
|
|
44780
45037
|
if (layer.paint.get('icon-opacity').constantOr(1) !== 0) {
|
|
@@ -44792,8 +45049,7 @@ function calculateVariableRenderShift(anchor, width, height, textOffset, textBox
|
|
|
44792
45049
|
const { horizontalAlign, verticalAlign } = performance.getAnchorAlignment(anchor);
|
|
44793
45050
|
const shiftX = -(horizontalAlign - 0.5) * width;
|
|
44794
45051
|
const shiftY = -(verticalAlign - 0.5) * height;
|
|
44795
|
-
|
|
44796
|
-
return new performance.Point((shiftX / textBoxScale + variableOffset[0]) * renderTextSize, (shiftY / textBoxScale + variableOffset[1]) * renderTextSize);
|
|
45052
|
+
return new performance.Point((shiftX / textBoxScale + textOffset[0]) * renderTextSize, (shiftY / textBoxScale + textOffset[1]) * renderTextSize);
|
|
44797
45053
|
}
|
|
44798
45054
|
function updateVariableAnchors(coords, painter, layer, sourceCache, rotationAlignment, pitchAlignment, variableOffsets) {
|
|
44799
45055
|
const tr = painter.transform;
|
|
@@ -44909,7 +45165,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
|
|
|
44909
45165
|
const hasSortKey = !layer.layout.get('symbol-sort-key').isConstant();
|
|
44910
45166
|
let sortFeaturesByKey = false;
|
|
44911
45167
|
const depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
|
|
44912
|
-
const
|
|
45168
|
+
const hasVariablePlacement = layer._unevaluatedLayout.hasValue('text-variable-anchor') || layer._unevaluatedLayout.hasValue('text-variable-anchor-offset');
|
|
44913
45169
|
const tileRenderState = [];
|
|
44914
45170
|
for (const coord of coords) {
|
|
44915
45171
|
const tile = sourceCache.getTile(coord);
|
|
@@ -44954,7 +45210,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
|
|
|
44954
45210
|
const s = pixelsToTileUnits(tile, 1, painter.transform.zoom);
|
|
44955
45211
|
const labelPlaneMatrix = getLabelPlaneMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, s);
|
|
44956
45212
|
const glCoordMatrix = getGlCoordMatrix(coord.posMatrix, pitchWithMap, rotateWithMap, painter.transform, s);
|
|
44957
|
-
const hasVariableAnchors =
|
|
45213
|
+
const hasVariableAnchors = hasVariablePlacement && bucket.hasTextData();
|
|
44958
45214
|
const updateTextFitIcon = layer.layout.get('icon-text-fit') !== 'none' &&
|
|
44959
45215
|
hasVariableAnchors &&
|
|
44960
45216
|
bucket.hasIconData();
|
|
@@ -44963,7 +45219,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
|
|
|
44963
45219
|
const rotateToLine = layer.layout.get('text-rotation-alignment') === 'map';
|
|
44964
45220
|
updateLineLabels(bucket, coord.posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright, rotateToLine, getElevation);
|
|
44965
45221
|
}
|
|
44966
|
-
const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor), uLabelPlaneMatrix = (alongLine || (isText &&
|
|
45222
|
+
const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor), uLabelPlaneMatrix = (alongLine || (isText && hasVariablePlacement) || updateTextFitIcon) ? identityMat4 : labelPlaneMatrix, uglCoordMatrix = painter.translatePosMatrix(glCoordMatrix, tile, translate, translateAnchor, true);
|
|
44967
45223
|
const hasHalo = isSDF && layer.paint.get(isText ? 'text-halo-width' : 'icon-halo-width').constantOr(1) !== 0;
|
|
44968
45224
|
let uniformValues;
|
|
44969
45225
|
if (isSDF) {
|