ts-maps 0.3.1 → 0.3.3
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/dist/core-map/control/FullscreenControl.d.ts +39 -0
- package/dist/core-map/control/GeocoderControl.d.ts +61 -0
- package/dist/core-map/control/LocateControl.d.ts +56 -0
- package/dist/core-map/control/NavigationControl.d.ts +39 -0
- package/dist/core-map/control/index.d.ts +8 -0
- package/dist/core-map/game/TerritoryLog.d.ts +66 -0
- package/dist/core-map/game/TerritoryStore.d.ts +59 -0
- package/dist/core-map/game/index.d.ts +11 -0
- package/dist/core-map/game/loop.d.ts +61 -0
- package/dist/core-map/geo/area.d.ts +52 -0
- package/dist/core-map/geo/index.d.ts +30 -0
- package/dist/core-map/geo/index.js +856 -31
- package/dist/core-map/geo/polygonClip.d.ts +75 -0
- package/dist/core-map/geo/validate.d.ts +54 -0
- package/dist/core-map/geometry/index.js +28 -28
- package/dist/core-map/index.d.ts +8 -2
- package/dist/core-map/layer/GeoJSONTileSource.d.ts +50 -0
- package/dist/core-map/layer/RunTrailLayer.d.ts +35 -0
- package/dist/core-map/layer/TerritoryLayer.d.ts +62 -0
- package/dist/core-map/layer/index.d.ts +6 -0
- package/dist/core-map/layer/tile/RasterDEMLayer.d.ts +4 -0
- package/dist/core-map/layer/tile/VectorTileMapLayer.d.ts +59 -11
- package/dist/core-map/layer/tile/urlTemplate.d.ts +1 -2
- package/dist/core-map/map/Map.d.ts +32 -1
- package/dist/core-map/mvt/DecodedTile.d.ts +20 -0
- package/dist/core-map/mvt/FlatTile.d.ts +25 -0
- package/dist/core-map/mvt/VectorTileFeature.d.ts +8 -0
- package/dist/core-map/services/index.js +48 -48
- package/dist/core-map/storage/index.js +5 -5
- package/dist/core-map/style-spec/expressions/formatted.d.ts +36 -0
- package/dist/core-map/style-spec/expressions/operators/binding.d.ts +1 -0
- package/dist/core-map/style-spec/expressions/operators/geometry.d.ts +19 -0
- package/dist/core-map/style-spec/expressions/types.d.ts +3 -0
- package/dist/core-map/style-spec/index.js +460 -60
- package/dist/core-map/style-spec/schema.d.ts +43 -3
- package/dist/core-map/style-spec/types.d.ts +47 -7
- package/dist/core-map/styles/basemap.d.ts +41 -0
- package/dist/core-map/styles/index.d.ts +5 -0
- package/dist/core-map/styles/palette.d.ts +31 -0
- package/dist/core-map/symbols/CollisionIndex.d.ts +22 -5
- package/dist/core-map/symbols/GlyphAtlas.d.ts +6 -1
- package/dist/core-map/symbols/GlyphProvider.d.ts +21 -0
- package/dist/core-map/symbols/GlyphRenderer.d.ts +48 -0
- package/dist/core-map/symbols/IconAtlas.d.ts +10 -1
- package/dist/core-map/symbols/SymbolOverlay.d.ts +47 -0
- package/dist/core-map/symbols/index.d.ts +4 -0
- package/dist/core-map/symbols/index.js +1072 -68
- package/dist/core-map/symbols/loadGlyphs.d.ts +53 -0
- package/dist/core-map/symbols/loadSprite.d.ts +57 -0
- package/dist/core-map/symbols/placement.d.ts +67 -0
- package/dist/core-map/symbols/sdf.d.ts +37 -0
- package/dist/core-map/symbols/sections.d.ts +32 -0
- package/dist/core-map/workers/WorkerPool.d.ts +40 -0
- package/dist/core-map/workers/decodeMvtFlat.d.ts +52 -0
- package/dist/index.js +11783 -6100
- package/package.json +2 -2
- package/src/core-map/ts-maps.css +576 -79
|
@@ -40,24 +40,39 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
40
40
|
// src/core-map/symbols/CollisionIndex.ts
|
|
41
41
|
class CollisionIndex {
|
|
42
42
|
_cellSize;
|
|
43
|
-
_cols;
|
|
44
|
-
_rows;
|
|
45
43
|
_cells;
|
|
44
|
+
_ownerCells;
|
|
46
45
|
constructor(opts) {
|
|
47
46
|
this._cellSize = opts?.cellSize ?? 64;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for (let
|
|
54
|
-
|
|
47
|
+
this._cells = new Map;
|
|
48
|
+
this._ownerCells = new Map;
|
|
49
|
+
}
|
|
50
|
+
hits(box) {
|
|
51
|
+
const range = this._cellRange(box);
|
|
52
|
+
for (let cy = range.y0;cy <= range.y1; cy++) {
|
|
53
|
+
for (let cx = range.x0;cx <= range.x1; cx++) {
|
|
54
|
+
const bucket = this._cells.get(cellKey(cx, cy));
|
|
55
|
+
if (!bucket)
|
|
56
|
+
continue;
|
|
57
|
+
for (const other of bucket) {
|
|
58
|
+
if (!overlaps(box, other))
|
|
59
|
+
continue;
|
|
60
|
+
if (other.priority === undefined || box.priority === undefined)
|
|
61
|
+
return true;
|
|
62
|
+
if (other.priority >= box.priority)
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
55
68
|
}
|
|
56
69
|
tryInsert(box) {
|
|
57
70
|
const range = this._cellRange(box);
|
|
58
71
|
for (let cy = range.y0;cy <= range.y1; cy++) {
|
|
59
72
|
for (let cx = range.x0;cx <= range.x1; cx++) {
|
|
60
|
-
const bucket = this._cells
|
|
73
|
+
const bucket = this._cells.get(cellKey(cx, cy));
|
|
74
|
+
if (!bucket)
|
|
75
|
+
continue;
|
|
61
76
|
for (const other of bucket) {
|
|
62
77
|
if (!overlaps(box, other))
|
|
63
78
|
continue;
|
|
@@ -74,38 +89,68 @@ class CollisionIndex {
|
|
|
74
89
|
insert(box) {
|
|
75
90
|
this._insertBucketed(box, this._cellRange(box));
|
|
76
91
|
}
|
|
92
|
+
removeOwner(owner) {
|
|
93
|
+
const cells = this._ownerCells.get(owner);
|
|
94
|
+
if (!cells)
|
|
95
|
+
return;
|
|
96
|
+
for (const key of cells) {
|
|
97
|
+
const bucket = this._cells.get(key);
|
|
98
|
+
if (!bucket)
|
|
99
|
+
continue;
|
|
100
|
+
const kept = bucket.filter((box) => box.owner !== owner);
|
|
101
|
+
if (kept.length)
|
|
102
|
+
this._cells.set(key, kept);
|
|
103
|
+
else
|
|
104
|
+
this._cells.delete(key);
|
|
105
|
+
}
|
|
106
|
+
this._ownerCells.delete(owner);
|
|
107
|
+
}
|
|
77
108
|
clear() {
|
|
78
|
-
|
|
79
|
-
|
|
109
|
+
this._cells.clear();
|
|
110
|
+
this._ownerCells.clear();
|
|
111
|
+
}
|
|
112
|
+
get size() {
|
|
113
|
+
const seen = new Set;
|
|
114
|
+
for (const bucket of this._cells.values()) {
|
|
115
|
+
for (const box of bucket)
|
|
116
|
+
seen.add(box);
|
|
117
|
+
}
|
|
118
|
+
return seen.size;
|
|
80
119
|
}
|
|
81
120
|
_cellRange(box) {
|
|
82
121
|
const cs = this._cellSize;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (y0 < 0)
|
|
90
|
-
y0 = 0;
|
|
91
|
-
if (x1 > this._cols - 1)
|
|
92
|
-
x1 = this._cols - 1;
|
|
93
|
-
if (y1 > this._rows - 1)
|
|
94
|
-
y1 = this._rows - 1;
|
|
95
|
-
if (x1 < x0)
|
|
96
|
-
x1 = x0;
|
|
97
|
-
if (y1 < y0)
|
|
98
|
-
y1 = y0;
|
|
99
|
-
return { x0, y0, x1, y1 };
|
|
122
|
+
return {
|
|
123
|
+
x0: Math.floor(box.minX / cs),
|
|
124
|
+
y0: Math.floor(box.minY / cs),
|
|
125
|
+
x1: Math.floor(box.maxX / cs),
|
|
126
|
+
y1: Math.floor(box.maxY / cs)
|
|
127
|
+
};
|
|
100
128
|
}
|
|
101
129
|
_insertBucketed(box, range) {
|
|
130
|
+
let ownerCells;
|
|
131
|
+
if (box.owner !== undefined) {
|
|
132
|
+
ownerCells = this._ownerCells.get(box.owner);
|
|
133
|
+
if (!ownerCells) {
|
|
134
|
+
ownerCells = new Set;
|
|
135
|
+
this._ownerCells.set(box.owner, ownerCells);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
102
138
|
for (let cy = range.y0;cy <= range.y1; cy++) {
|
|
103
139
|
for (let cx = range.x0;cx <= range.x1; cx++) {
|
|
104
|
-
|
|
140
|
+
const key = cellKey(cx, cy);
|
|
141
|
+
const bucket = this._cells.get(key);
|
|
142
|
+
if (bucket)
|
|
143
|
+
bucket.push(box);
|
|
144
|
+
else
|
|
145
|
+
this._cells.set(key, [box]);
|
|
146
|
+
ownerCells?.add(key);
|
|
105
147
|
}
|
|
106
148
|
}
|
|
107
149
|
}
|
|
108
150
|
}
|
|
151
|
+
function cellKey(x, y) {
|
|
152
|
+
return `${x}:${y}`;
|
|
153
|
+
}
|
|
109
154
|
function overlaps(a, b) {
|
|
110
155
|
if (a.maxX < b.minX)
|
|
111
156
|
return false;
|
|
@@ -119,6 +164,10 @@ function overlaps(a, b) {
|
|
|
119
164
|
}
|
|
120
165
|
|
|
121
166
|
// src/core-map/symbols/GlyphAtlas.ts
|
|
167
|
+
var exports_GlyphAtlas = {};
|
|
168
|
+
__export(exports_GlyphAtlas, {
|
|
169
|
+
GlyphAtlas: () => GlyphAtlas
|
|
170
|
+
});
|
|
122
171
|
function styleKey(k) {
|
|
123
172
|
if (!k)
|
|
124
173
|
return "r";
|
|
@@ -141,7 +190,7 @@ class GlyphAtlas {
|
|
|
141
190
|
constructor(opts) {
|
|
142
191
|
this._fontFamily = opts?.fontFamily ?? "system-ui, -apple-system, Segoe UI, Roboto";
|
|
143
192
|
this._fontSize = opts?.fontSize ?? 24;
|
|
144
|
-
this._padding = opts?.padding ??
|
|
193
|
+
this._padding = opts?.padding ?? 8;
|
|
145
194
|
const bucketSize = opts?.bucketSize ?? 512;
|
|
146
195
|
this.canvas = document.createElement("canvas");
|
|
147
196
|
this.canvas.width = bucketSize;
|
|
@@ -175,19 +224,105 @@ class GlyphAtlas {
|
|
|
175
224
|
}
|
|
176
225
|
return { width, height };
|
|
177
226
|
}
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
if (
|
|
227
|
+
advances(text, size, style) {
|
|
228
|
+
const ctx = this._ctx;
|
|
229
|
+
const out = [];
|
|
230
|
+
if (ctx) {
|
|
182
231
|
ctx.save();
|
|
183
|
-
ctx.
|
|
184
|
-
|
|
185
|
-
|
|
232
|
+
ctx.font = this.fontString(size, style);
|
|
233
|
+
for (const ch of text)
|
|
234
|
+
out.push({ char: ch, advance: ctx.measureText(ch).width });
|
|
186
235
|
ctx.restore();
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
const scale = size / this._fontSize;
|
|
239
|
+
for (const ch of text) {
|
|
240
|
+
const cp = ch.codePointAt(0) ?? 0;
|
|
241
|
+
const g = this.getOrAddGlyph(cp, style);
|
|
242
|
+
out.push({ char: ch, advance: g.advance * scale });
|
|
243
|
+
}
|
|
244
|
+
return out;
|
|
245
|
+
}
|
|
246
|
+
measureText(text, size, style) {
|
|
247
|
+
const ctx = this._ctx;
|
|
248
|
+
if (!ctx) {
|
|
249
|
+
const atlas = this.measure(text, style);
|
|
250
|
+
const scale = size / this._fontSize;
|
|
251
|
+
const height = atlas.height * scale;
|
|
252
|
+
return { width: atlas.width * scale, height, ascent: height * 0.8, descent: height * 0.2 };
|
|
187
253
|
}
|
|
188
254
|
ctx.save();
|
|
255
|
+
ctx.font = this.fontString(size, style);
|
|
256
|
+
const m = ctx.measureText(text);
|
|
257
|
+
ctx.restore();
|
|
258
|
+
const ascent = m.fontBoundingBoxAscent || m.actualBoundingBoxAscent || size * 0.8;
|
|
259
|
+
const descent = m.fontBoundingBoxDescent || m.actualBoundingBoxDescent || size * 0.2;
|
|
260
|
+
return { width: m.width, height: ascent + descent, ascent, descent };
|
|
261
|
+
}
|
|
262
|
+
fontString(size, style) {
|
|
263
|
+
const parts = [];
|
|
264
|
+
if (style?.italic)
|
|
265
|
+
parts.push("italic");
|
|
266
|
+
if (style?.bold)
|
|
267
|
+
parts.push("700");
|
|
268
|
+
parts.push(`${size}px`, style?.family || this._fontFamily);
|
|
269
|
+
return parts.join(" ");
|
|
270
|
+
}
|
|
271
|
+
resolveFont(textFont) {
|
|
272
|
+
const names = Array.isArray(textFont) ? textFont : textFont ? [textFont] : [];
|
|
273
|
+
if (!names.length)
|
|
274
|
+
return { family: this._fontFamily, bold: false, italic: false };
|
|
275
|
+
let bold = false;
|
|
276
|
+
let italic = false;
|
|
277
|
+
const families = [];
|
|
278
|
+
for (const raw of names) {
|
|
279
|
+
if (typeof raw !== "string" || !raw)
|
|
280
|
+
continue;
|
|
281
|
+
let name = raw;
|
|
282
|
+
for (const [token, apply] of [
|
|
283
|
+
["Semibold", () => {
|
|
284
|
+
bold = true;
|
|
285
|
+
}],
|
|
286
|
+
["Bold", () => {
|
|
287
|
+
bold = true;
|
|
288
|
+
}],
|
|
289
|
+
["Italic", () => {
|
|
290
|
+
italic = true;
|
|
291
|
+
}],
|
|
292
|
+
["Oblique", () => {
|
|
293
|
+
italic = true;
|
|
294
|
+
}],
|
|
295
|
+
["Regular", () => {}],
|
|
296
|
+
["Medium", () => {}],
|
|
297
|
+
["Light", () => {}]
|
|
298
|
+
]) {
|
|
299
|
+
if (name.includes(token)) {
|
|
300
|
+
apply();
|
|
301
|
+
name = name.replace(token, "");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const cleaned = name.replace(/\s+/g, " ").trim();
|
|
305
|
+
if (cleaned)
|
|
306
|
+
families.push(cleaned.includes(" ") ? `"${cleaned}"` : cleaned);
|
|
307
|
+
}
|
|
308
|
+
families.push(this._fontFamily);
|
|
309
|
+
return { family: families.join(", "), bold, italic };
|
|
310
|
+
}
|
|
311
|
+
drawText(ctx, text, x, y, options) {
|
|
312
|
+
const style = { italic: !!options.italic, bold: !!options.bold, family: options.family };
|
|
313
|
+
ctx.save();
|
|
314
|
+
ctx.font = this.fontString(options.size, style);
|
|
315
|
+
ctx.textAlign = "left";
|
|
316
|
+
ctx.textBaseline = "alphabetic";
|
|
317
|
+
if (options.haloColor && options.haloWidth && options.haloWidth > 0) {
|
|
318
|
+
ctx.strokeStyle = options.haloColor;
|
|
319
|
+
ctx.lineWidth = options.haloWidth * 2;
|
|
320
|
+
ctx.lineJoin = "round";
|
|
321
|
+
ctx.miterLimit = 2;
|
|
322
|
+
ctx.strokeText(text, x, y);
|
|
323
|
+
}
|
|
189
324
|
ctx.fillStyle = options.color;
|
|
190
|
-
|
|
325
|
+
ctx.fillText(text, x, y);
|
|
191
326
|
ctx.restore();
|
|
192
327
|
}
|
|
193
328
|
_buildSDF(imageData) {
|
|
@@ -195,23 +330,23 @@ class GlyphAtlas {
|
|
|
195
330
|
const h = imageData.height;
|
|
196
331
|
const radius = this._padding;
|
|
197
332
|
const INF = 1 << 20;
|
|
198
|
-
const
|
|
199
|
-
const
|
|
333
|
+
const depthInside = new Int32Array(w * h);
|
|
334
|
+
const distanceToInk = new Int32Array(w * h);
|
|
200
335
|
for (let i = 0;i < w * h; i++) {
|
|
201
336
|
const a = imageData.data[i * 4 + 3];
|
|
202
337
|
if (a >= 128) {
|
|
203
|
-
|
|
204
|
-
|
|
338
|
+
depthInside[i] = INF;
|
|
339
|
+
distanceToInk[i] = 0;
|
|
205
340
|
} else {
|
|
206
|
-
|
|
207
|
-
|
|
341
|
+
depthInside[i] = 0;
|
|
342
|
+
distanceToInk[i] = INF;
|
|
208
343
|
}
|
|
209
344
|
}
|
|
210
|
-
chamfer34(
|
|
211
|
-
chamfer34(
|
|
345
|
+
chamfer34(depthInside, w, h);
|
|
346
|
+
chamfer34(distanceToInk, w, h);
|
|
212
347
|
const out = createImageData(w, h);
|
|
213
348
|
for (let i = 0;i < w * h; i++) {
|
|
214
|
-
const d = (
|
|
349
|
+
const d = (distanceToInk[i] - depthInside[i]) / 3;
|
|
215
350
|
let v = 128 - d / radius * 128;
|
|
216
351
|
if (v < 0)
|
|
217
352
|
v = 0;
|
|
@@ -224,21 +359,6 @@ class GlyphAtlas {
|
|
|
224
359
|
}
|
|
225
360
|
return out;
|
|
226
361
|
}
|
|
227
|
-
_drawRun(ctx, text, x, y, scale, style, haloInflate) {
|
|
228
|
-
let pen = x;
|
|
229
|
-
for (const ch of text) {
|
|
230
|
-
const cp = ch.codePointAt(0) ?? 0;
|
|
231
|
-
const g = this.getOrAddGlyph(cp, style);
|
|
232
|
-
if (g.width > 0 && g.height > 0) {
|
|
233
|
-
const dx = pen + g.bearingX * scale - haloInflate;
|
|
234
|
-
const dy = y - g.bearingY * scale - haloInflate;
|
|
235
|
-
const dw = g.width * scale + haloInflate * 2;
|
|
236
|
-
const dh = g.height * scale + haloInflate * 2;
|
|
237
|
-
ctx.drawImage(this.canvas, g.x, g.y, g.width, g.height, dx, dy, dw, dh);
|
|
238
|
-
}
|
|
239
|
-
pen += g.advance * scale;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
362
|
_rasterize(key) {
|
|
243
363
|
const ctx = this._ctx;
|
|
244
364
|
if (!ctx) {
|
|
@@ -397,6 +517,81 @@ function chamfer34(buf, w, h) {
|
|
|
397
517
|
}
|
|
398
518
|
}
|
|
399
519
|
|
|
520
|
+
// src/core-map/symbols/sdf.ts
|
|
521
|
+
function renderSdfPixels(field, width, height, options) {
|
|
522
|
+
const out = new Uint8ClampedArray(width * height * 4);
|
|
523
|
+
const fill = parseColor(options.color);
|
|
524
|
+
const haloWidth = options.haloWidth ?? 0;
|
|
525
|
+
const halo = options.haloColor && haloWidth > 0 ? parseColor(options.haloColor) : null;
|
|
526
|
+
const haloEdge = halo ? Math.max(0.02, 0.5 - haloWidth / 16) : 0;
|
|
527
|
+
const band = 0.06;
|
|
528
|
+
for (let i = 0;i < width * height; i++) {
|
|
529
|
+
const distance = field[i * 4 + 3] / 255;
|
|
530
|
+
const inside = smoothstep(0.5 - band, 0.5 + band, distance);
|
|
531
|
+
const outline = halo ? smoothstep(haloEdge - band, haloEdge + band, distance) : 0;
|
|
532
|
+
const alpha = inside + outline * (1 - inside);
|
|
533
|
+
if (alpha <= 0)
|
|
534
|
+
continue;
|
|
535
|
+
const weight = outline * (1 - inside);
|
|
536
|
+
out[i * 4] = halo ? (fill[0] * inside + halo[0] * weight) / alpha : fill[0];
|
|
537
|
+
out[i * 4 + 1] = halo ? (fill[1] * inside + halo[1] * weight) / alpha : fill[1];
|
|
538
|
+
out[i * 4 + 2] = halo ? (fill[2] * inside + halo[2] * weight) / alpha : fill[2];
|
|
539
|
+
out[i * 4 + 3] = Math.round(alpha * 255);
|
|
540
|
+
}
|
|
541
|
+
return out;
|
|
542
|
+
}
|
|
543
|
+
function smoothstep(edge0, edge1, x) {
|
|
544
|
+
if (edge1 <= edge0)
|
|
545
|
+
return x < edge0 ? 0 : 1;
|
|
546
|
+
const t = Math.min(1, Math.max(0, (x - edge0) / (edge1 - edge0)));
|
|
547
|
+
return t * t * (3 - 2 * t);
|
|
548
|
+
}
|
|
549
|
+
function parseColor(color) {
|
|
550
|
+
const text = color.trim();
|
|
551
|
+
const hex = /^#([0-9a-f]{3,8})$/i.exec(text);
|
|
552
|
+
if (hex) {
|
|
553
|
+
let body = hex[1];
|
|
554
|
+
if (body.length === 3 || body.length === 4)
|
|
555
|
+
body = body.slice(0, 3).split("").map((c) => c + c).join("");
|
|
556
|
+
if (body.length < 6)
|
|
557
|
+
return [0, 0, 0];
|
|
558
|
+
const n = Number.parseInt(body.slice(0, 6), 16);
|
|
559
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
560
|
+
}
|
|
561
|
+
const rgb = /^rgba?\(([^)]+)\)$/i.exec(text);
|
|
562
|
+
if (rgb) {
|
|
563
|
+
const parts = rgb[1].split(/[,/\s]+/).filter(Boolean);
|
|
564
|
+
if (parts.length >= 3) {
|
|
565
|
+
const channel = (value) => {
|
|
566
|
+
const n = Number.parseFloat(value);
|
|
567
|
+
if (Number.isNaN(n))
|
|
568
|
+
return 0;
|
|
569
|
+
return Math.max(0, Math.min(255, Math.round(value.includes("%") ? n / 100 * 255 : n)));
|
|
570
|
+
};
|
|
571
|
+
return [channel(parts[0]), channel(parts[1]), channel(parts[2])];
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return probeColor(text);
|
|
575
|
+
}
|
|
576
|
+
function probeColor(color) {
|
|
577
|
+
if (typeof document === "undefined")
|
|
578
|
+
return [0, 0, 0];
|
|
579
|
+
const probe = document.createElement("canvas");
|
|
580
|
+
probe.width = 1;
|
|
581
|
+
probe.height = 1;
|
|
582
|
+
const ctx = probe.getContext("2d");
|
|
583
|
+
if (!ctx)
|
|
584
|
+
return [0, 0, 0];
|
|
585
|
+
ctx.fillStyle = color;
|
|
586
|
+
ctx.fillRect(0, 0, 1, 1);
|
|
587
|
+
try {
|
|
588
|
+
const data = ctx.getImageData(0, 0, 1, 1).data;
|
|
589
|
+
return [data[0], data[1], data[2]];
|
|
590
|
+
} catch {
|
|
591
|
+
return [0, 0, 0];
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
400
595
|
// src/core-map/symbols/IconAtlas.ts
|
|
401
596
|
class IconAtlas {
|
|
402
597
|
canvas;
|
|
@@ -405,6 +600,7 @@ class IconAtlas {
|
|
|
405
600
|
_cursorX;
|
|
406
601
|
_cursorY;
|
|
407
602
|
_rowH;
|
|
603
|
+
_sdfCache;
|
|
408
604
|
constructor() {
|
|
409
605
|
this.canvas = document.createElement("canvas");
|
|
410
606
|
this.canvas.width = 512;
|
|
@@ -414,6 +610,7 @@ class IconAtlas {
|
|
|
414
610
|
this._cursorX = 0;
|
|
415
611
|
this._cursorY = 0;
|
|
416
612
|
this._rowH = 0;
|
|
613
|
+
this._sdfCache = new Map;
|
|
417
614
|
}
|
|
418
615
|
addSprite(entry, source) {
|
|
419
616
|
const w = entry.width;
|
|
@@ -448,7 +645,8 @@ class IconAtlas {
|
|
|
448
645
|
y: dy,
|
|
449
646
|
width: w,
|
|
450
647
|
height: h,
|
|
451
|
-
pixelRatio: entry.pixelRatio ?? 1
|
|
648
|
+
pixelRatio: entry.pixelRatio ?? 1,
|
|
649
|
+
sdf: entry.sdf
|
|
452
650
|
};
|
|
453
651
|
this._sprites.set(entry.id, packed);
|
|
454
652
|
this._cursorX += w;
|
|
@@ -466,15 +664,54 @@ class IconAtlas {
|
|
|
466
664
|
const scale = target / s.width;
|
|
467
665
|
const w = s.width * scale;
|
|
468
666
|
const h = s.height * scale;
|
|
667
|
+
const source = s.sdf ? this._renderSdf(s, opts) : this.canvas;
|
|
668
|
+
const sx = source === this.canvas ? s.x : 0;
|
|
669
|
+
const sy = source === this.canvas ? s.y : 0;
|
|
670
|
+
const previousAlpha = ctx.globalAlpha;
|
|
671
|
+
const opacity = opts?.opacity;
|
|
672
|
+
if (opacity !== undefined && opacity < 1)
|
|
673
|
+
ctx.globalAlpha = previousAlpha * Math.max(0, opacity);
|
|
469
674
|
if (opts?.rotation) {
|
|
470
675
|
ctx.save();
|
|
471
676
|
ctx.translate(dx, dy);
|
|
472
677
|
ctx.rotate(opts.rotation);
|
|
473
|
-
ctx.drawImage(
|
|
678
|
+
ctx.drawImage(source, sx, sy, s.width, s.height, -w / 2, -h / 2, w, h);
|
|
474
679
|
ctx.restore();
|
|
475
680
|
} else {
|
|
476
|
-
ctx.drawImage(
|
|
681
|
+
ctx.drawImage(source, sx, sy, s.width, s.height, dx - w / 2, dy - h / 2, w, h);
|
|
477
682
|
}
|
|
683
|
+
ctx.globalAlpha = previousAlpha;
|
|
684
|
+
}
|
|
685
|
+
_renderSdf(entry, opts) {
|
|
686
|
+
const color = opts?.color ?? "#000000";
|
|
687
|
+
const haloColor = opts?.haloColor;
|
|
688
|
+
const haloWidth = opts?.haloWidth ?? 0;
|
|
689
|
+
const key = `${entry.id}|${color}|${haloColor ?? ""}|${haloWidth}`;
|
|
690
|
+
const cached = this._sdfCache.get(key);
|
|
691
|
+
if (cached)
|
|
692
|
+
return cached;
|
|
693
|
+
const w = entry.width;
|
|
694
|
+
const h = entry.height;
|
|
695
|
+
const out = document.createElement("canvas");
|
|
696
|
+
out.width = w;
|
|
697
|
+
out.height = h;
|
|
698
|
+
const octx = out.getContext("2d");
|
|
699
|
+
const src = this._ctx;
|
|
700
|
+
if (!octx || !src)
|
|
701
|
+
return out;
|
|
702
|
+
let field;
|
|
703
|
+
try {
|
|
704
|
+
field = src.getImageData(entry.x, entry.y, w, h);
|
|
705
|
+
} catch {
|
|
706
|
+
return out;
|
|
707
|
+
}
|
|
708
|
+
const pixels = octx.createImageData(w, h);
|
|
709
|
+
pixels.data.set(renderSdfPixels(field.data, w, h, { color, haloColor, haloWidth }));
|
|
710
|
+
octx.putImageData(pixels, 0, 0);
|
|
711
|
+
if (this._sdfCache.size > 128)
|
|
712
|
+
this._sdfCache.clear();
|
|
713
|
+
this._sdfCache.set(key, out);
|
|
714
|
+
return out;
|
|
478
715
|
}
|
|
479
716
|
_grow(newSide) {
|
|
480
717
|
const old = this.canvas;
|
|
@@ -494,8 +731,775 @@ function isImageData(v) {
|
|
|
494
731
|
const anyV = v;
|
|
495
732
|
return typeof anyV.width === "number" && typeof anyV.height === "number" && (anyV.data instanceof Uint8ClampedArray || anyV.data instanceof Uint8Array);
|
|
496
733
|
}
|
|
734
|
+
var init_IconAtlas = () => {};
|
|
735
|
+
|
|
736
|
+
// src/core-map/proto/Pbf.ts
|
|
737
|
+
class Pbf {
|
|
738
|
+
buf;
|
|
739
|
+
pos;
|
|
740
|
+
type;
|
|
741
|
+
length;
|
|
742
|
+
_view;
|
|
743
|
+
constructor(buf) {
|
|
744
|
+
if (buf instanceof Uint8Array) {
|
|
745
|
+
this.buf = buf;
|
|
746
|
+
} else if (buf instanceof ArrayBuffer) {
|
|
747
|
+
this.buf = new Uint8Array(buf);
|
|
748
|
+
} else {
|
|
749
|
+
this.buf = new Uint8Array(0);
|
|
750
|
+
}
|
|
751
|
+
this.pos = 0;
|
|
752
|
+
this.type = 0;
|
|
753
|
+
this.length = this.buf.length;
|
|
754
|
+
this._view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength);
|
|
755
|
+
}
|
|
756
|
+
readFields(readField, result, end) {
|
|
757
|
+
const endPos = end === undefined ? this.length : end;
|
|
758
|
+
while (this.pos < endPos) {
|
|
759
|
+
const val = this.readVarint();
|
|
760
|
+
const tag = val >> 3;
|
|
761
|
+
const startPos = this.pos;
|
|
762
|
+
this.type = val & 7;
|
|
763
|
+
readField(tag, result, this);
|
|
764
|
+
if (this.pos === startPos)
|
|
765
|
+
this.skip(val);
|
|
766
|
+
}
|
|
767
|
+
return result;
|
|
768
|
+
}
|
|
769
|
+
readMessage(readField, result) {
|
|
770
|
+
return this.readFields(readField, result, this.readVarint() + this.pos);
|
|
771
|
+
}
|
|
772
|
+
readFixed32() {
|
|
773
|
+
const val = this._view.getUint32(this.pos, true);
|
|
774
|
+
this.pos += 4;
|
|
775
|
+
return val;
|
|
776
|
+
}
|
|
777
|
+
readSFixed32() {
|
|
778
|
+
const val = this._view.getInt32(this.pos, true);
|
|
779
|
+
this.pos += 4;
|
|
780
|
+
return val;
|
|
781
|
+
}
|
|
782
|
+
readFixed64() {
|
|
783
|
+
const lo = this._view.getUint32(this.pos, true);
|
|
784
|
+
const hi = this._view.getUint32(this.pos + 4, true);
|
|
785
|
+
this.pos += 8;
|
|
786
|
+
return hi * SHIFT_LEFT_32 + lo;
|
|
787
|
+
}
|
|
788
|
+
readSFixed64() {
|
|
789
|
+
const lo = this._view.getUint32(this.pos, true);
|
|
790
|
+
const hi = this._view.getInt32(this.pos + 4, true);
|
|
791
|
+
this.pos += 8;
|
|
792
|
+
return hi * SHIFT_LEFT_32 + lo;
|
|
793
|
+
}
|
|
794
|
+
readFloat() {
|
|
795
|
+
const val = this._view.getFloat32(this.pos, true);
|
|
796
|
+
this.pos += 4;
|
|
797
|
+
return val;
|
|
798
|
+
}
|
|
799
|
+
readDouble() {
|
|
800
|
+
const val = this._view.getFloat64(this.pos, true);
|
|
801
|
+
this.pos += 8;
|
|
802
|
+
return val;
|
|
803
|
+
}
|
|
804
|
+
readVarint(isSigned) {
|
|
805
|
+
const buf = this.buf;
|
|
806
|
+
let val;
|
|
807
|
+
let b;
|
|
808
|
+
b = buf[this.pos++];
|
|
809
|
+
val = b & 127;
|
|
810
|
+
if (b < 128)
|
|
811
|
+
return val;
|
|
812
|
+
b = buf[this.pos++];
|
|
813
|
+
val |= (b & 127) << 7;
|
|
814
|
+
if (b < 128)
|
|
815
|
+
return val;
|
|
816
|
+
b = buf[this.pos++];
|
|
817
|
+
val |= (b & 127) << 14;
|
|
818
|
+
if (b < 128)
|
|
819
|
+
return val;
|
|
820
|
+
b = buf[this.pos++];
|
|
821
|
+
val |= (b & 127) << 21;
|
|
822
|
+
if (b < 128)
|
|
823
|
+
return val >>> 0;
|
|
824
|
+
b = buf[this.pos];
|
|
825
|
+
return readVarintRemainder(val >>> 0, isSigned === true, this);
|
|
826
|
+
}
|
|
827
|
+
readVarint64() {
|
|
828
|
+
return this.readVarint(true);
|
|
829
|
+
}
|
|
830
|
+
readSVarint() {
|
|
831
|
+
const n = this.readVarint();
|
|
832
|
+
return n % 2 === 1 ? (n + 1) / -2 : n / 2;
|
|
833
|
+
}
|
|
834
|
+
readBoolean() {
|
|
835
|
+
return Boolean(this.readVarint());
|
|
836
|
+
}
|
|
837
|
+
readString() {
|
|
838
|
+
const end = this.readVarint() + this.pos;
|
|
839
|
+
const start = this.pos;
|
|
840
|
+
this.pos = end;
|
|
841
|
+
if (utf8Decoder !== null) {
|
|
842
|
+
return utf8Decoder.decode(this.buf.subarray(start, end));
|
|
843
|
+
}
|
|
844
|
+
return manualUtf8Decode(this.buf, start, end);
|
|
845
|
+
}
|
|
846
|
+
readBytes() {
|
|
847
|
+
const end = this.readVarint() + this.pos;
|
|
848
|
+
const bytes = this.buf.subarray(this.pos, end);
|
|
849
|
+
this.pos = end;
|
|
850
|
+
return new Uint8Array(bytes);
|
|
851
|
+
}
|
|
852
|
+
readPackedVarint(arr, isSigned) {
|
|
853
|
+
return readPacked(this, arr, (p) => p.readVarint(isSigned));
|
|
854
|
+
}
|
|
855
|
+
readPackedSVarint(arr) {
|
|
856
|
+
return readPacked(this, arr, (p) => p.readSVarint());
|
|
857
|
+
}
|
|
858
|
+
readPackedBoolean(arr) {
|
|
859
|
+
return readPacked(this, arr, (p) => p.readBoolean());
|
|
860
|
+
}
|
|
861
|
+
readPackedFloat(arr) {
|
|
862
|
+
return readPacked(this, arr, (p) => p.readFloat());
|
|
863
|
+
}
|
|
864
|
+
readPackedDouble(arr) {
|
|
865
|
+
return readPacked(this, arr, (p) => p.readDouble());
|
|
866
|
+
}
|
|
867
|
+
readPackedFixed32(arr) {
|
|
868
|
+
return readPacked(this, arr, (p) => p.readFixed32());
|
|
869
|
+
}
|
|
870
|
+
readPackedSFixed32(arr) {
|
|
871
|
+
return readPacked(this, arr, (p) => p.readSFixed32());
|
|
872
|
+
}
|
|
873
|
+
readPackedFixed64(arr) {
|
|
874
|
+
return readPacked(this, arr, (p) => p.readFixed64());
|
|
875
|
+
}
|
|
876
|
+
readPackedSFixed64(arr) {
|
|
877
|
+
return readPacked(this, arr, (p) => p.readSFixed64());
|
|
878
|
+
}
|
|
879
|
+
skip(val) {
|
|
880
|
+
const type = val & 7;
|
|
881
|
+
if (type === PBF_VARINT) {
|
|
882
|
+
while (this.buf[this.pos++] >= 128) {}
|
|
883
|
+
} else if (type === PBF_BYTES) {
|
|
884
|
+
this.pos = this.readVarint() + this.pos;
|
|
885
|
+
} else if (type === PBF_FIXED32) {
|
|
886
|
+
this.pos += 4;
|
|
887
|
+
} else if (type === PBF_FIXED64) {
|
|
888
|
+
this.pos += 8;
|
|
889
|
+
} else {
|
|
890
|
+
throw new Error(`Unimplemented wire type: ${type}`);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
writeTag(tag, type) {
|
|
894
|
+
this.writeVarint(tag << 3 | type);
|
|
895
|
+
}
|
|
896
|
+
realloc(min) {
|
|
897
|
+
let length = Math.max(this.length, 16);
|
|
898
|
+
while (length < this.pos + min)
|
|
899
|
+
length *= 2;
|
|
900
|
+
if (length !== this.buf.length) {
|
|
901
|
+
const next = new Uint8Array(length);
|
|
902
|
+
next.set(this.buf);
|
|
903
|
+
this.buf = next;
|
|
904
|
+
this._view = new DataView(next.buffer);
|
|
905
|
+
this.length = length;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
finish() {
|
|
909
|
+
this.length = this.pos;
|
|
910
|
+
this.pos = 0;
|
|
911
|
+
return this.buf.subarray(0, this.length);
|
|
912
|
+
}
|
|
913
|
+
destroy() {
|
|
914
|
+
this.buf = new Uint8Array(0);
|
|
915
|
+
this._view = new DataView(this.buf.buffer);
|
|
916
|
+
this.pos = 0;
|
|
917
|
+
this.length = 0;
|
|
918
|
+
this.type = 0;
|
|
919
|
+
}
|
|
920
|
+
writeVarint(val) {
|
|
921
|
+
if (val > 268435455 || val < 0) {
|
|
922
|
+
writeBigVarint(val, this);
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
this.realloc(4);
|
|
926
|
+
const v = val | 0;
|
|
927
|
+
this.buf[this.pos++] = v & 127 | (v > 127 ? 128 : 0);
|
|
928
|
+
if (v <= 127)
|
|
929
|
+
return;
|
|
930
|
+
this.buf[this.pos++] = v >>> 7 & 127 | (v > 16383 ? 128 : 0);
|
|
931
|
+
if (v <= 16383)
|
|
932
|
+
return;
|
|
933
|
+
this.buf[this.pos++] = v >>> 14 & 127 | (v > 2097151 ? 128 : 0);
|
|
934
|
+
if (v <= 2097151)
|
|
935
|
+
return;
|
|
936
|
+
this.buf[this.pos++] = v >>> 21 & 127 | (v > 268435455 ? 128 : 0);
|
|
937
|
+
if (v <= 268435455)
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
writeSVarint(val) {
|
|
941
|
+
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
|
|
942
|
+
}
|
|
943
|
+
writeBoolean(val) {
|
|
944
|
+
this.writeVarint(val ? 1 : 0);
|
|
945
|
+
}
|
|
946
|
+
writeString(str) {
|
|
947
|
+
const bytes = utf8Encoder !== null ? utf8Encoder.encode(str) : manualUtf8Encode(str);
|
|
948
|
+
this.writeVarint(bytes.length);
|
|
949
|
+
this.realloc(bytes.length);
|
|
950
|
+
this.buf.set(bytes, this.pos);
|
|
951
|
+
this.pos += bytes.length;
|
|
952
|
+
}
|
|
953
|
+
writeFloat(val) {
|
|
954
|
+
this.realloc(4);
|
|
955
|
+
this._view.setFloat32(this.pos, val, true);
|
|
956
|
+
this.pos += 4;
|
|
957
|
+
}
|
|
958
|
+
writeDouble(val) {
|
|
959
|
+
this.realloc(8);
|
|
960
|
+
this._view.setFloat64(this.pos, val, true);
|
|
961
|
+
this.pos += 8;
|
|
962
|
+
}
|
|
963
|
+
writeBytes(bytes) {
|
|
964
|
+
this.writeVarint(bytes.length);
|
|
965
|
+
this.realloc(bytes.length);
|
|
966
|
+
this.buf.set(bytes, this.pos);
|
|
967
|
+
this.pos += bytes.length;
|
|
968
|
+
}
|
|
969
|
+
writeRawFixed32(val) {
|
|
970
|
+
this.realloc(4);
|
|
971
|
+
this._view.setUint32(this.pos, val >>> 0, true);
|
|
972
|
+
this.pos += 4;
|
|
973
|
+
}
|
|
974
|
+
writeRawSFixed32(val) {
|
|
975
|
+
this.realloc(4);
|
|
976
|
+
this._view.setInt32(this.pos, val | 0, true);
|
|
977
|
+
this.pos += 4;
|
|
978
|
+
}
|
|
979
|
+
writeRawFixed64(val) {
|
|
980
|
+
this.realloc(8);
|
|
981
|
+
const lo = val >>> 0;
|
|
982
|
+
const hi = Math.floor(val * SHIFT_RIGHT_32) >>> 0;
|
|
983
|
+
this._view.setUint32(this.pos, lo, true);
|
|
984
|
+
this._view.setUint32(this.pos + 4, hi, true);
|
|
985
|
+
this.pos += 8;
|
|
986
|
+
}
|
|
987
|
+
writeRawSFixed64(val) {
|
|
988
|
+
this.realloc(8);
|
|
989
|
+
const lo = val >>> 0;
|
|
990
|
+
const hi = Math.floor(val * SHIFT_RIGHT_32) | 0;
|
|
991
|
+
this._view.setUint32(this.pos, lo, true);
|
|
992
|
+
this._view.setInt32(this.pos + 4, hi, true);
|
|
993
|
+
this.pos += 8;
|
|
994
|
+
}
|
|
995
|
+
writeMessage(tag, fn, value) {
|
|
996
|
+
this.writeTag(tag, PBF_BYTES);
|
|
997
|
+
const headPos = this.pos;
|
|
998
|
+
this.pos++;
|
|
999
|
+
const startMessage = this.pos;
|
|
1000
|
+
fn(value, this);
|
|
1001
|
+
const len = this.pos - startMessage;
|
|
1002
|
+
if (len >= 128) {
|
|
1003
|
+
const varintLen = varintLength(len);
|
|
1004
|
+
this.realloc(varintLen - 1);
|
|
1005
|
+
this.buf.copyWithin(startMessage + varintLen - 1, startMessage, startMessage + len);
|
|
1006
|
+
this.pos = headPos;
|
|
1007
|
+
this.writeVarint(len);
|
|
1008
|
+
this.pos = startMessage + varintLen - 1 + len;
|
|
1009
|
+
} else {
|
|
1010
|
+
this.buf[headPos] = len;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
writePackedVarint(tag, arr) {
|
|
1014
|
+
if (arr.length > 0)
|
|
1015
|
+
this.writeMessage(tag, writePackedVarintFn, arr);
|
|
1016
|
+
}
|
|
1017
|
+
writePackedSVarint(tag, arr) {
|
|
1018
|
+
if (arr.length > 0)
|
|
1019
|
+
this.writeMessage(tag, writePackedSVarintFn, arr);
|
|
1020
|
+
}
|
|
1021
|
+
writePackedBoolean(tag, arr) {
|
|
1022
|
+
if (arr.length > 0)
|
|
1023
|
+
this.writeMessage(tag, writePackedBooleanFn, arr);
|
|
1024
|
+
}
|
|
1025
|
+
writePackedFloat(tag, arr) {
|
|
1026
|
+
if (arr.length > 0)
|
|
1027
|
+
this.writeMessage(tag, writePackedFloatFn, arr);
|
|
1028
|
+
}
|
|
1029
|
+
writePackedDouble(tag, arr) {
|
|
1030
|
+
if (arr.length > 0)
|
|
1031
|
+
this.writeMessage(tag, writePackedDoubleFn, arr);
|
|
1032
|
+
}
|
|
1033
|
+
writePackedFixed32(tag, arr) {
|
|
1034
|
+
if (arr.length > 0)
|
|
1035
|
+
this.writeMessage(tag, writePackedFixed32Fn, arr);
|
|
1036
|
+
}
|
|
1037
|
+
writePackedSFixed32(tag, arr) {
|
|
1038
|
+
if (arr.length > 0)
|
|
1039
|
+
this.writeMessage(tag, writePackedSFixed32Fn, arr);
|
|
1040
|
+
}
|
|
1041
|
+
writePackedFixed64(tag, arr) {
|
|
1042
|
+
if (arr.length > 0)
|
|
1043
|
+
this.writeMessage(tag, writePackedFixed64Fn, arr);
|
|
1044
|
+
}
|
|
1045
|
+
writePackedSFixed64(tag, arr) {
|
|
1046
|
+
if (arr.length > 0)
|
|
1047
|
+
this.writeMessage(tag, writePackedSFixed64Fn, arr);
|
|
1048
|
+
}
|
|
1049
|
+
writeBytesField(tag, buffer) {
|
|
1050
|
+
this.writeTag(tag, PBF_BYTES);
|
|
1051
|
+
this.writeBytes(buffer);
|
|
1052
|
+
}
|
|
1053
|
+
writeFixed32(tag, val) {
|
|
1054
|
+
this.writeTag(tag, PBF_FIXED32);
|
|
1055
|
+
this.writeRawFixed32(val);
|
|
1056
|
+
}
|
|
1057
|
+
writeSFixed32(tag, val) {
|
|
1058
|
+
this.writeTag(tag, PBF_FIXED32);
|
|
1059
|
+
this.writeRawSFixed32(val);
|
|
1060
|
+
}
|
|
1061
|
+
writeFixed64(tag, val) {
|
|
1062
|
+
this.writeTag(tag, PBF_FIXED64);
|
|
1063
|
+
this.writeRawFixed64(val);
|
|
1064
|
+
}
|
|
1065
|
+
writeSFixed64(tag, val) {
|
|
1066
|
+
this.writeTag(tag, PBF_FIXED64);
|
|
1067
|
+
this.writeRawSFixed64(val);
|
|
1068
|
+
}
|
|
1069
|
+
writeVarintField(tag, val) {
|
|
1070
|
+
this.writeTag(tag, PBF_VARINT);
|
|
1071
|
+
this.writeVarint(val);
|
|
1072
|
+
}
|
|
1073
|
+
writeSVarintField(tag, val) {
|
|
1074
|
+
this.writeTag(tag, PBF_VARINT);
|
|
1075
|
+
this.writeSVarint(val);
|
|
1076
|
+
}
|
|
1077
|
+
writeStringField(tag, str) {
|
|
1078
|
+
this.writeTag(tag, PBF_BYTES);
|
|
1079
|
+
this.writeString(str);
|
|
1080
|
+
}
|
|
1081
|
+
writeFloatField(tag, val) {
|
|
1082
|
+
this.writeTag(tag, PBF_FIXED32);
|
|
1083
|
+
this.writeFloat(val);
|
|
1084
|
+
}
|
|
1085
|
+
writeDoubleField(tag, val) {
|
|
1086
|
+
this.writeTag(tag, PBF_FIXED64);
|
|
1087
|
+
this.writeDouble(val);
|
|
1088
|
+
}
|
|
1089
|
+
writeBooleanField(tag, val) {
|
|
1090
|
+
this.writeVarintField(tag, val ? 1 : 0);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function readVarintRemainder(low, isSigned, pbf) {
|
|
1094
|
+
const buf = pbf.buf;
|
|
1095
|
+
let b;
|
|
1096
|
+
let high = 0;
|
|
1097
|
+
b = buf[pbf.pos++];
|
|
1098
|
+
low |= (b & 15) << 28;
|
|
1099
|
+
high = (b & 112) >> 4;
|
|
1100
|
+
if (b < 128)
|
|
1101
|
+
return toNum(low, high, isSigned);
|
|
1102
|
+
b = buf[pbf.pos++];
|
|
1103
|
+
high |= (b & 127) << 3;
|
|
1104
|
+
if (b < 128)
|
|
1105
|
+
return toNum(low, high, isSigned);
|
|
1106
|
+
b = buf[pbf.pos++];
|
|
1107
|
+
high |= (b & 127) << 10;
|
|
1108
|
+
if (b < 128)
|
|
1109
|
+
return toNum(low, high, isSigned);
|
|
1110
|
+
b = buf[pbf.pos++];
|
|
1111
|
+
high |= (b & 127) << 17;
|
|
1112
|
+
if (b < 128)
|
|
1113
|
+
return toNum(low, high, isSigned);
|
|
1114
|
+
b = buf[pbf.pos++];
|
|
1115
|
+
high |= (b & 127) << 24;
|
|
1116
|
+
if (b < 128)
|
|
1117
|
+
return toNum(low, high, isSigned);
|
|
1118
|
+
b = buf[pbf.pos++];
|
|
1119
|
+
high |= (b & 1) << 31;
|
|
1120
|
+
if (b < 128)
|
|
1121
|
+
return toNum(low, high, isSigned);
|
|
1122
|
+
throw new Error("Expected varint not more than 10 bytes");
|
|
1123
|
+
}
|
|
1124
|
+
function toNum(low, high, isSigned) {
|
|
1125
|
+
if (isSigned && (high & 2147483648) !== 0) {
|
|
1126
|
+
const negLow = ~low + 1 >>> 0;
|
|
1127
|
+
let negHigh = ~high >>> 0;
|
|
1128
|
+
if (negLow === 0)
|
|
1129
|
+
negHigh = negHigh + 1 >>> 0;
|
|
1130
|
+
const mag = negHigh * SHIFT_LEFT_32 + negLow;
|
|
1131
|
+
if (mag > MAX_SAFE)
|
|
1132
|
+
throw new Error("Varint exceeds safe integer range");
|
|
1133
|
+
return -mag;
|
|
1134
|
+
}
|
|
1135
|
+
const val = (high >>> 0) * SHIFT_LEFT_32 + (low >>> 0);
|
|
1136
|
+
if (val > MAX_SAFE)
|
|
1137
|
+
throw new Error("Varint exceeds safe integer range");
|
|
1138
|
+
return val;
|
|
1139
|
+
}
|
|
1140
|
+
function readPackedEnd(pbf) {
|
|
1141
|
+
return pbf.readVarint() + pbf.pos;
|
|
1142
|
+
}
|
|
1143
|
+
function readPacked(pbf, arr, readOne) {
|
|
1144
|
+
if (pbf.type !== PBF_BYTES) {
|
|
1145
|
+
if (arr === undefined)
|
|
1146
|
+
return [readOne(pbf)];
|
|
1147
|
+
arr.push(readOne(pbf));
|
|
1148
|
+
return arr;
|
|
1149
|
+
}
|
|
1150
|
+
const out = arr === undefined ? [] : arr;
|
|
1151
|
+
const end = readPackedEnd(pbf);
|
|
1152
|
+
while (pbf.pos < end)
|
|
1153
|
+
out.push(readOne(pbf));
|
|
1154
|
+
return out;
|
|
1155
|
+
}
|
|
1156
|
+
function varintLength(val) {
|
|
1157
|
+
let n = 1;
|
|
1158
|
+
while (val >= 128) {
|
|
1159
|
+
val = Math.floor(val / 128);
|
|
1160
|
+
n++;
|
|
1161
|
+
}
|
|
1162
|
+
return n;
|
|
1163
|
+
}
|
|
1164
|
+
function writeBigVarint(val, pbf) {
|
|
1165
|
+
let low;
|
|
1166
|
+
let high;
|
|
1167
|
+
if (val < 0) {
|
|
1168
|
+
const mag = -val;
|
|
1169
|
+
low = ~(mag >>> 0) + 1 >>> 0;
|
|
1170
|
+
high = ~Math.floor(mag / SHIFT_LEFT_32) >>> 0;
|
|
1171
|
+
if (low === 0)
|
|
1172
|
+
high = high + 1 >>> 0;
|
|
1173
|
+
} else {
|
|
1174
|
+
low = val >>> 0;
|
|
1175
|
+
high = Math.floor(val / SHIFT_LEFT_32) >>> 0;
|
|
1176
|
+
}
|
|
1177
|
+
pbf.realloc(10);
|
|
1178
|
+
for (let i = 0;i < 10; i++) {
|
|
1179
|
+
const bit = i * 7;
|
|
1180
|
+
const chunk = readBits7(low, high, bit);
|
|
1181
|
+
const more = bit + 7 < 64 ? readBitsAbove(low, high, bit + 7) : false;
|
|
1182
|
+
pbf.buf[pbf.pos++] = more ? chunk | 128 : chunk;
|
|
1183
|
+
if (!more)
|
|
1184
|
+
break;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
function readBits7(low, high, bit) {
|
|
1188
|
+
if (bit >= 32)
|
|
1189
|
+
return high >>> bit - 32 & 127;
|
|
1190
|
+
if (bit + 7 <= 32)
|
|
1191
|
+
return low >>> bit & 127;
|
|
1192
|
+
return (low >>> bit | high << 32 - bit) & 127;
|
|
1193
|
+
}
|
|
1194
|
+
function readBitsAbove(low, high, startBit) {
|
|
1195
|
+
if (startBit >= 64)
|
|
1196
|
+
return false;
|
|
1197
|
+
if (startBit >= 32)
|
|
1198
|
+
return high >>> startBit - 32 !== 0;
|
|
1199
|
+
return low >>> startBit !== 0 || high !== 0;
|
|
1200
|
+
}
|
|
1201
|
+
function writePackedVarintFn(arr, pbf) {
|
|
1202
|
+
for (let i = 0;i < arr.length; i++)
|
|
1203
|
+
pbf.writeVarint(arr[i]);
|
|
1204
|
+
}
|
|
1205
|
+
function writePackedSVarintFn(arr, pbf) {
|
|
1206
|
+
for (let i = 0;i < arr.length; i++)
|
|
1207
|
+
pbf.writeSVarint(arr[i]);
|
|
1208
|
+
}
|
|
1209
|
+
function writePackedBooleanFn(arr, pbf) {
|
|
1210
|
+
for (let i = 0;i < arr.length; i++)
|
|
1211
|
+
pbf.writeBoolean(arr[i]);
|
|
1212
|
+
}
|
|
1213
|
+
function writePackedFloatFn(arr, pbf) {
|
|
1214
|
+
for (let i = 0;i < arr.length; i++)
|
|
1215
|
+
pbf.writeFloat(arr[i]);
|
|
1216
|
+
}
|
|
1217
|
+
function writePackedDoubleFn(arr, pbf) {
|
|
1218
|
+
for (let i = 0;i < arr.length; i++)
|
|
1219
|
+
pbf.writeDouble(arr[i]);
|
|
1220
|
+
}
|
|
1221
|
+
function writePackedFixed32Fn(arr, pbf) {
|
|
1222
|
+
for (let i = 0;i < arr.length; i++)
|
|
1223
|
+
pbf.writeRawFixed32(arr[i]);
|
|
1224
|
+
}
|
|
1225
|
+
function writePackedSFixed32Fn(arr, pbf) {
|
|
1226
|
+
for (let i = 0;i < arr.length; i++)
|
|
1227
|
+
pbf.writeRawSFixed32(arr[i]);
|
|
1228
|
+
}
|
|
1229
|
+
function writePackedFixed64Fn(arr, pbf) {
|
|
1230
|
+
for (let i = 0;i < arr.length; i++)
|
|
1231
|
+
pbf.writeRawFixed64(arr[i]);
|
|
1232
|
+
}
|
|
1233
|
+
function writePackedSFixed64Fn(arr, pbf) {
|
|
1234
|
+
for (let i = 0;i < arr.length; i++)
|
|
1235
|
+
pbf.writeRawSFixed64(arr[i]);
|
|
1236
|
+
}
|
|
1237
|
+
function manualUtf8Decode(buf, start, end) {
|
|
1238
|
+
let out = "";
|
|
1239
|
+
let i = start;
|
|
1240
|
+
while (i < end) {
|
|
1241
|
+
const b0 = buf[i++];
|
|
1242
|
+
if (b0 < 128) {
|
|
1243
|
+
out += String.fromCharCode(b0);
|
|
1244
|
+
} else if (b0 < 224) {
|
|
1245
|
+
const b1 = buf[i++] & 63;
|
|
1246
|
+
out += String.fromCharCode((b0 & 31) << 6 | b1);
|
|
1247
|
+
} else if (b0 < 240) {
|
|
1248
|
+
const b1 = buf[i++] & 63;
|
|
1249
|
+
const b2 = buf[i++] & 63;
|
|
1250
|
+
out += String.fromCharCode((b0 & 15) << 12 | b1 << 6 | b2);
|
|
1251
|
+
} else {
|
|
1252
|
+
const b1 = buf[i++] & 63;
|
|
1253
|
+
const b2 = buf[i++] & 63;
|
|
1254
|
+
const b3 = buf[i++] & 63;
|
|
1255
|
+
let cp = (b0 & 7) << 18 | b1 << 12 | b2 << 6 | b3;
|
|
1256
|
+
cp -= 65536;
|
|
1257
|
+
out += String.fromCharCode(55296 | cp >> 10);
|
|
1258
|
+
out += String.fromCharCode(56320 | cp & 1023);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
return out;
|
|
1262
|
+
}
|
|
1263
|
+
function manualUtf8Encode(str) {
|
|
1264
|
+
const out = [];
|
|
1265
|
+
for (let i = 0;i < str.length; i++) {
|
|
1266
|
+
let cp = str.charCodeAt(i);
|
|
1267
|
+
if (cp >= 55296 && cp <= 56319 && i + 1 < str.length) {
|
|
1268
|
+
const low = str.charCodeAt(i + 1);
|
|
1269
|
+
if (low >= 56320 && low <= 57343) {
|
|
1270
|
+
cp = 65536 + ((cp & 1023) << 10 | low & 1023);
|
|
1271
|
+
i++;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
if (cp < 128) {
|
|
1275
|
+
out.push(cp);
|
|
1276
|
+
} else if (cp < 2048) {
|
|
1277
|
+
out.push(192 | cp >> 6, 128 | cp & 63);
|
|
1278
|
+
} else if (cp < 65536) {
|
|
1279
|
+
out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
|
|
1280
|
+
} else {
|
|
1281
|
+
out.push(240 | cp >> 18, 128 | cp >> 12 & 63, 128 | cp >> 6 & 63, 128 | cp & 63);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
return new Uint8Array(out);
|
|
1285
|
+
}
|
|
1286
|
+
var PBF_VARINT = 0, PBF_FIXED64 = 1, PBF_BYTES = 2, PBF_FIXED32 = 5, SHIFT_LEFT_32, SHIFT_RIGHT_32, MAX_SAFE, utf8Decoder, utf8Encoder;
|
|
1287
|
+
var init_Pbf = __esm(() => {
|
|
1288
|
+
SHIFT_LEFT_32 = (1 << 16) * (1 << 16);
|
|
1289
|
+
SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
|
|
1290
|
+
MAX_SAFE = Number.MAX_SAFE_INTEGER;
|
|
1291
|
+
utf8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8") : null;
|
|
1292
|
+
utf8Encoder = typeof TextEncoder !== "undefined" ? new TextEncoder : null;
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
// src/core-map/symbols/loadGlyphs.ts
|
|
1296
|
+
var exports_loadGlyphs = {};
|
|
1297
|
+
__export(exports_loadGlyphs, {
|
|
1298
|
+
GLYPH_BORDER: () => GLYPH_BORDER,
|
|
1299
|
+
GlyphSource: () => GlyphSource,
|
|
1300
|
+
decodeGlyphPbf: () => decodeGlyphPbf,
|
|
1301
|
+
glyphUrl: () => glyphUrl,
|
|
1302
|
+
rangeStartFor: () => rangeStartFor
|
|
1303
|
+
});
|
|
1304
|
+
function glyphUrl(template, fontstack, rangeStart) {
|
|
1305
|
+
const range = `${rangeStart}-${rangeStart + 255}`;
|
|
1306
|
+
return template.replace("{fontstack}", encodeURIComponent(fontstack)).replace("{range}", range);
|
|
1307
|
+
}
|
|
1308
|
+
function rangeStartFor(codePoint) {
|
|
1309
|
+
return Math.floor(codePoint / 256) * 256;
|
|
1310
|
+
}
|
|
1311
|
+
function decodeGlyphPbf(bytes) {
|
|
1312
|
+
const glyphs = new Map;
|
|
1313
|
+
const pbf = new Pbf(bytes);
|
|
1314
|
+
while (pbf.pos < pbf.length) {
|
|
1315
|
+
const tag = pbf.readVarint() >> 3;
|
|
1316
|
+
if (tag !== 1) {
|
|
1317
|
+
pbf.skip(tag << 3);
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
1320
|
+
const stackEnd = pbf.readVarint() + pbf.pos;
|
|
1321
|
+
while (pbf.pos < stackEnd) {
|
|
1322
|
+
const value = pbf.readVarint();
|
|
1323
|
+
const stackTag = value >> 3;
|
|
1324
|
+
pbf.type = value & 7;
|
|
1325
|
+
if (stackTag !== 3) {
|
|
1326
|
+
pbf.skip(value);
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
const glyphEnd = pbf.readVarint() + pbf.pos;
|
|
1330
|
+
const glyph = { id: 0, width: 0, height: 0, left: 0, top: 0, advance: 0 };
|
|
1331
|
+
while (pbf.pos < glyphEnd) {
|
|
1332
|
+
const gv = pbf.readVarint();
|
|
1333
|
+
const gTag = gv >> 3;
|
|
1334
|
+
pbf.type = gv & 7;
|
|
1335
|
+
switch (gTag) {
|
|
1336
|
+
case 1:
|
|
1337
|
+
glyph.id = pbf.readVarint();
|
|
1338
|
+
break;
|
|
1339
|
+
case 2:
|
|
1340
|
+
glyph.bitmap = pbf.readBytes();
|
|
1341
|
+
break;
|
|
1342
|
+
case 3:
|
|
1343
|
+
glyph.width = pbf.readVarint();
|
|
1344
|
+
break;
|
|
1345
|
+
case 4:
|
|
1346
|
+
glyph.height = pbf.readVarint();
|
|
1347
|
+
break;
|
|
1348
|
+
case 5:
|
|
1349
|
+
glyph.left = pbf.readSVarint();
|
|
1350
|
+
break;
|
|
1351
|
+
case 6:
|
|
1352
|
+
glyph.top = pbf.readSVarint();
|
|
1353
|
+
break;
|
|
1354
|
+
case 7:
|
|
1355
|
+
glyph.advance = pbf.readVarint();
|
|
1356
|
+
break;
|
|
1357
|
+
default:
|
|
1358
|
+
pbf.skip(gv);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
pbf.pos = glyphEnd;
|
|
1362
|
+
glyphs.set(glyph.id, glyph);
|
|
1363
|
+
}
|
|
1364
|
+
pbf.pos = stackEnd;
|
|
1365
|
+
}
|
|
1366
|
+
return glyphs;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
class GlyphSource {
|
|
1370
|
+
_template;
|
|
1371
|
+
_fetch;
|
|
1372
|
+
_ranges;
|
|
1373
|
+
_pending;
|
|
1374
|
+
constructor(template, options = {}) {
|
|
1375
|
+
this._template = template;
|
|
1376
|
+
this._fetch = options.fetch ?? globalThis.fetch;
|
|
1377
|
+
this._ranges = new Map;
|
|
1378
|
+
this._pending = new Map;
|
|
1379
|
+
}
|
|
1380
|
+
get(fontstack, codePoint) {
|
|
1381
|
+
const key = `${fontstack}/${rangeStartFor(codePoint)}`;
|
|
1382
|
+
return this._ranges.get(key)?.get(codePoint);
|
|
1383
|
+
}
|
|
1384
|
+
has(fontstack, codePoint) {
|
|
1385
|
+
return this._ranges.has(`${fontstack}/${rangeStartFor(codePoint)}`);
|
|
1386
|
+
}
|
|
1387
|
+
async load(fontstack, codePoint, signal) {
|
|
1388
|
+
const start = rangeStartFor(codePoint);
|
|
1389
|
+
const key = `${fontstack}/${start}`;
|
|
1390
|
+
const cached = this._ranges.get(key);
|
|
1391
|
+
if (cached)
|
|
1392
|
+
return cached;
|
|
1393
|
+
const inFlight = this._pending.get(key);
|
|
1394
|
+
if (inFlight)
|
|
1395
|
+
return inFlight;
|
|
1396
|
+
const request = (async () => {
|
|
1397
|
+
const url = glyphUrl(this._template, fontstack, start);
|
|
1398
|
+
const response = await this._fetch(url, { signal });
|
|
1399
|
+
if (!response.ok)
|
|
1400
|
+
throw new Error(`HTTP ${response.status} fetching glyphs ${url}`);
|
|
1401
|
+
const range = decodeGlyphPbf(new Uint8Array(await response.arrayBuffer()));
|
|
1402
|
+
this._ranges.set(key, range);
|
|
1403
|
+
this._pending.delete(key);
|
|
1404
|
+
return range;
|
|
1405
|
+
})();
|
|
1406
|
+
this._pending.set(key, request);
|
|
1407
|
+
request.catch(() => this._pending.delete(key));
|
|
1408
|
+
return request;
|
|
1409
|
+
}
|
|
1410
|
+
async loadForText(fontstack, text, signal) {
|
|
1411
|
+
const starts = new Set;
|
|
1412
|
+
for (const ch of text)
|
|
1413
|
+
starts.add(rangeStartFor(ch.codePointAt(0) ?? 0));
|
|
1414
|
+
await Promise.all([...starts].map((start) => this.load(fontstack, start, signal)));
|
|
1415
|
+
}
|
|
1416
|
+
get size() {
|
|
1417
|
+
return this._ranges.size;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
var GLYPH_BORDER = 3;
|
|
1421
|
+
var init_loadGlyphs = __esm(() => {
|
|
1422
|
+
init_Pbf();
|
|
1423
|
+
});
|
|
1424
|
+
|
|
1425
|
+
// src/core-map/symbols/loadSprite.ts
|
|
1426
|
+
var exports_loadSprite = {};
|
|
1427
|
+
__export(exports_loadSprite, {
|
|
1428
|
+
addSpriteToAtlas: () => addSpriteToAtlas,
|
|
1429
|
+
loadSprite: () => loadSprite,
|
|
1430
|
+
spriteUrl: () => spriteUrl
|
|
1431
|
+
});
|
|
1432
|
+
function spriteUrl(base, extension, pixelRatio) {
|
|
1433
|
+
const suffix = pixelRatio > 1 ? "@2x" : "";
|
|
1434
|
+
const queryAt = base.indexOf("?");
|
|
1435
|
+
if (queryAt === -1)
|
|
1436
|
+
return `${base}${suffix}.${extension}`;
|
|
1437
|
+
return `${base.slice(0, queryAt)}${suffix}.${extension}${base.slice(queryAt)}`;
|
|
1438
|
+
}
|
|
1439
|
+
function defaultLoadImage(url) {
|
|
1440
|
+
return new Promise((resolve, reject) => {
|
|
1441
|
+
const image = new Image;
|
|
1442
|
+
image.crossOrigin = "anonymous";
|
|
1443
|
+
image.onload = () => resolve(image);
|
|
1444
|
+
image.onerror = () => reject(new Error(`failed to load sprite image ${url}`));
|
|
1445
|
+
image.src = url;
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
async function loadSprite(base, options = {}) {
|
|
1449
|
+
const doFetch = options.fetch ?? globalThis.fetch;
|
|
1450
|
+
const loadImage = options.loadImage ?? defaultLoadImage;
|
|
1451
|
+
const wanted = (options.pixelRatio ?? 1) > 1 ? 2 : 1;
|
|
1452
|
+
const attempt = async (ratio) => {
|
|
1453
|
+
const response = await doFetch(spriteUrl(base, "json", ratio), { signal: options.signal });
|
|
1454
|
+
if (!response.ok)
|
|
1455
|
+
throw new Error(`HTTP ${response.status} fetching sprite index for ${base}`);
|
|
1456
|
+
const index = await response.json();
|
|
1457
|
+
const image = await loadImage(spriteUrl(base, "png", ratio));
|
|
1458
|
+
return { index, image, pixelRatio: ratio };
|
|
1459
|
+
};
|
|
1460
|
+
if (wanted === 2) {
|
|
1461
|
+
try {
|
|
1462
|
+
return await attempt(2);
|
|
1463
|
+
} catch {}
|
|
1464
|
+
}
|
|
1465
|
+
return attempt(1);
|
|
1466
|
+
}
|
|
1467
|
+
function addSpriteToAtlas(atlas, sprite, prefix) {
|
|
1468
|
+
let added = 0;
|
|
1469
|
+
for (const [name, entry] of Object.entries(sprite.index)) {
|
|
1470
|
+
const id = prefix ? `${prefix}:${name}` : name;
|
|
1471
|
+
if (!entry || typeof entry.width !== "number" || typeof entry.height !== "number")
|
|
1472
|
+
continue;
|
|
1473
|
+
if (entry.width <= 0 || entry.height <= 0)
|
|
1474
|
+
continue;
|
|
1475
|
+
const packed = {
|
|
1476
|
+
id,
|
|
1477
|
+
x: entry.x,
|
|
1478
|
+
y: entry.y,
|
|
1479
|
+
width: entry.width,
|
|
1480
|
+
height: entry.height,
|
|
1481
|
+
pixelRatio: entry.pixelRatio ?? sprite.pixelRatio,
|
|
1482
|
+
sdf: entry.sdf === true
|
|
1483
|
+
};
|
|
1484
|
+
atlas.addSprite(packed, sprite.image);
|
|
1485
|
+
added += 1;
|
|
1486
|
+
}
|
|
1487
|
+
return added;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// src/core-map/symbols/index.ts
|
|
1491
|
+
init_IconAtlas();
|
|
1492
|
+
init_loadGlyphs();
|
|
497
1493
|
export {
|
|
498
|
-
|
|
1494
|
+
CollisionIndex,
|
|
1495
|
+
GLYPH_BORDER,
|
|
499
1496
|
GlyphAtlas,
|
|
500
|
-
|
|
1497
|
+
GlyphSource,
|
|
1498
|
+
IconAtlas,
|
|
1499
|
+
addSpriteToAtlas,
|
|
1500
|
+
decodeGlyphPbf,
|
|
1501
|
+
glyphUrl,
|
|
1502
|
+
loadSprite,
|
|
1503
|
+
rangeStartFor,
|
|
1504
|
+
spriteUrl
|
|
501
1505
|
};
|