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.
Files changed (57) hide show
  1. package/dist/core-map/control/FullscreenControl.d.ts +39 -0
  2. package/dist/core-map/control/GeocoderControl.d.ts +61 -0
  3. package/dist/core-map/control/LocateControl.d.ts +56 -0
  4. package/dist/core-map/control/NavigationControl.d.ts +39 -0
  5. package/dist/core-map/control/index.d.ts +8 -0
  6. package/dist/core-map/game/TerritoryLog.d.ts +66 -0
  7. package/dist/core-map/game/TerritoryStore.d.ts +59 -0
  8. package/dist/core-map/game/index.d.ts +11 -0
  9. package/dist/core-map/game/loop.d.ts +61 -0
  10. package/dist/core-map/geo/area.d.ts +52 -0
  11. package/dist/core-map/geo/index.d.ts +30 -0
  12. package/dist/core-map/geo/index.js +856 -31
  13. package/dist/core-map/geo/polygonClip.d.ts +75 -0
  14. package/dist/core-map/geo/validate.d.ts +54 -0
  15. package/dist/core-map/geometry/index.js +28 -28
  16. package/dist/core-map/index.d.ts +8 -2
  17. package/dist/core-map/layer/GeoJSONTileSource.d.ts +50 -0
  18. package/dist/core-map/layer/RunTrailLayer.d.ts +35 -0
  19. package/dist/core-map/layer/TerritoryLayer.d.ts +62 -0
  20. package/dist/core-map/layer/index.d.ts +6 -0
  21. package/dist/core-map/layer/tile/RasterDEMLayer.d.ts +4 -0
  22. package/dist/core-map/layer/tile/VectorTileMapLayer.d.ts +59 -11
  23. package/dist/core-map/layer/tile/urlTemplate.d.ts +1 -2
  24. package/dist/core-map/map/Map.d.ts +32 -1
  25. package/dist/core-map/mvt/DecodedTile.d.ts +20 -0
  26. package/dist/core-map/mvt/FlatTile.d.ts +25 -0
  27. package/dist/core-map/mvt/VectorTileFeature.d.ts +8 -0
  28. package/dist/core-map/services/index.js +48 -48
  29. package/dist/core-map/storage/index.js +5 -5
  30. package/dist/core-map/style-spec/expressions/formatted.d.ts +36 -0
  31. package/dist/core-map/style-spec/expressions/operators/binding.d.ts +1 -0
  32. package/dist/core-map/style-spec/expressions/operators/geometry.d.ts +19 -0
  33. package/dist/core-map/style-spec/expressions/types.d.ts +3 -0
  34. package/dist/core-map/style-spec/index.js +460 -60
  35. package/dist/core-map/style-spec/schema.d.ts +43 -3
  36. package/dist/core-map/style-spec/types.d.ts +47 -7
  37. package/dist/core-map/styles/basemap.d.ts +41 -0
  38. package/dist/core-map/styles/index.d.ts +5 -0
  39. package/dist/core-map/styles/palette.d.ts +31 -0
  40. package/dist/core-map/symbols/CollisionIndex.d.ts +22 -5
  41. package/dist/core-map/symbols/GlyphAtlas.d.ts +6 -1
  42. package/dist/core-map/symbols/GlyphProvider.d.ts +21 -0
  43. package/dist/core-map/symbols/GlyphRenderer.d.ts +48 -0
  44. package/dist/core-map/symbols/IconAtlas.d.ts +10 -1
  45. package/dist/core-map/symbols/SymbolOverlay.d.ts +47 -0
  46. package/dist/core-map/symbols/index.d.ts +4 -0
  47. package/dist/core-map/symbols/index.js +1072 -68
  48. package/dist/core-map/symbols/loadGlyphs.d.ts +53 -0
  49. package/dist/core-map/symbols/loadSprite.d.ts +57 -0
  50. package/dist/core-map/symbols/placement.d.ts +67 -0
  51. package/dist/core-map/symbols/sdf.d.ts +37 -0
  52. package/dist/core-map/symbols/sections.d.ts +32 -0
  53. package/dist/core-map/workers/WorkerPool.d.ts +40 -0
  54. package/dist/core-map/workers/decodeMvtFlat.d.ts +52 -0
  55. package/dist/index.js +11783 -6100
  56. package/package.json +2 -2
  57. 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
- const width = opts?.width ?? 1;
49
- const height = opts?.height ?? 1;
50
- this._cols = Math.max(1, Math.ceil(width / this._cellSize));
51
- this._rows = Math.max(1, Math.ceil(height / this._cellSize));
52
- this._cells = [];
53
- for (let i = 0;i < this._cols * this._rows; i++)
54
- this._cells.push([]);
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[cy * this._cols + cx];
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
- for (let i = 0;i < this._cells.length; i++)
79
- this._cells[i] = [];
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
- let x0 = Math.floor(box.minX / cs);
84
- let y0 = Math.floor(box.minY / cs);
85
- let x1 = Math.floor(box.maxX / cs);
86
- let y1 = Math.floor(box.maxY / cs);
87
- if (x0 < 0)
88
- x0 = 0;
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
- this._cells[cy * this._cols + cx].push(box);
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 ?? 4;
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
- drawText(ctx, text, x, y, options) {
179
- const style = { italic: !!options.italic, bold: !!options.bold };
180
- const scale = options.size / this._fontSize;
181
- if (options.haloColor && options.haloWidth && options.haloWidth > 0) {
227
+ advances(text, size, style) {
228
+ const ctx = this._ctx;
229
+ const out = [];
230
+ if (ctx) {
182
231
  ctx.save();
183
- ctx.globalCompositeOperation = "destination-over";
184
- ctx.fillStyle = options.haloColor;
185
- this._drawRun(ctx, text, x, y, scale, style, options.haloWidth);
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
- this._drawRun(ctx, text, x, y, scale, style, 0);
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 inside = new Int32Array(w * h);
199
- const outside = new Int32Array(w * h);
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
- outside[i] = INF;
204
- inside[i] = 0;
338
+ depthInside[i] = INF;
339
+ distanceToInk[i] = 0;
205
340
  } else {
206
- outside[i] = 0;
207
- inside[i] = INF;
341
+ depthInside[i] = 0;
342
+ distanceToInk[i] = INF;
208
343
  }
209
344
  }
210
- chamfer34(outside, w, h);
211
- chamfer34(inside, w, h);
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 = (outside[i] - inside[i]) / 3;
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(this.canvas, s.x, s.y, s.width, s.height, -w / 2, -h / 2, w, h);
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(this.canvas, s.x, s.y, s.width, s.height, dx - w / 2, dy - h / 2, w, h);
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
- IconAtlas,
1494
+ CollisionIndex,
1495
+ GLYPH_BORDER,
499
1496
  GlyphAtlas,
500
- CollisionIndex
1497
+ GlyphSource,
1498
+ IconAtlas,
1499
+ addSpriteToAtlas,
1500
+ decodeGlyphPbf,
1501
+ glyphUrl,
1502
+ loadSprite,
1503
+ rangeStartFor,
1504
+ spriteUrl
501
1505
  };