isard 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +44 -39
  3. package/dist/basemap/basemaps.d.ts +1 -1
  4. package/dist/basemap/basemaps.js +2 -2
  5. package/dist/basemap/basemaps.js.map +1 -1
  6. package/dist/basemap/grid.d.ts +5 -5
  7. package/dist/basemap/grid.js +59 -65
  8. package/dist/basemap/grid.js.map +1 -1
  9. package/dist/basemap/mvt.d.ts +1 -1
  10. package/dist/basemap/mvt.js +6 -6
  11. package/dist/basemap/mvt.js.map +1 -1
  12. package/dist/basemap/pmtiles.d.ts +10 -10
  13. package/dist/basemap/pmtiles.js +39 -31
  14. package/dist/basemap/pmtiles.js.map +1 -1
  15. package/dist/basemap/pmtileslayer.d.ts +33 -0
  16. package/dist/basemap/pmtileslayer.js +97 -0
  17. package/dist/basemap/pmtileslayer.js.map +1 -0
  18. package/dist/basemap/resample.d.ts +2 -2
  19. package/dist/basemap/resample.js +16 -14
  20. package/dist/basemap/resample.js.map +1 -1
  21. package/dist/basemap/terrain.d.ts +3 -3
  22. package/dist/basemap/terrain.js +6 -6
  23. package/dist/basemap/terrain.js.map +1 -1
  24. package/dist/basemap/trees.d.ts +26 -0
  25. package/dist/basemap/trees.js +141 -0
  26. package/dist/basemap/trees.js.map +1 -0
  27. package/dist/basemap/vectorstyle.d.ts +22 -10
  28. package/dist/basemap/vectorstyle.js +163 -110
  29. package/dist/basemap/vectorstyle.js.map +1 -1
  30. package/dist/basemap/vectortiles.d.ts +70 -47
  31. package/dist/basemap/vectortiles.js +480 -358
  32. package/dist/basemap/vectortiles.js.map +1 -1
  33. package/dist/basemap/wmts.d.ts +3 -3
  34. package/dist/basemap/wmts.js +16 -11
  35. package/dist/basemap/wmts.js.map +1 -1
  36. package/dist/basemap/workerpool.d.ts +17 -0
  37. package/dist/basemap/workerpool.js +194 -0
  38. package/dist/basemap/workerpool.js.map +1 -0
  39. package/dist/basemap.worker.js +2 -2
  40. package/dist/basemap.worker.js.map +21 -13
  41. package/dist/bind/layers.d.ts +13 -4
  42. package/dist/bind/layers.js +64 -40
  43. package/dist/bind/layers.js.map +1 -1
  44. package/dist/data/crs.d.ts +10 -10
  45. package/dist/data/crs.js +38 -34
  46. package/dist/data/crs.js.map +1 -1
  47. package/dist/data/gpx.d.ts +1 -1
  48. package/dist/data/gpx.js +20 -20
  49. package/dist/data/gpx.js.map +1 -1
  50. package/dist/data/kml.d.ts +1 -1
  51. package/dist/data/kml.js +42 -39
  52. package/dist/data/kml.js.map +1 -1
  53. package/dist/data/topojson.d.ts +1 -1
  54. package/dist/data/topojson.js +15 -10
  55. package/dist/data/topojson.js.map +1 -1
  56. package/dist/data/xml.d.ts +5 -5
  57. package/dist/data/xml.js +19 -18
  58. package/dist/data/xml.js.map +1 -1
  59. package/dist/decoder.worker.js +4 -4
  60. package/dist/decoder.worker.js.map +6 -6
  61. package/dist/engine/decoders.d.ts +2 -2
  62. package/dist/engine/decoders.js +28 -25
  63. package/dist/engine/decoders.js.map +1 -1
  64. package/dist/engine/loader.js +13 -14
  65. package/dist/engine/loader.js.map +1 -1
  66. package/dist/engine/requests.d.ts +1 -1
  67. package/dist/engine/requests.js +19 -16
  68. package/dist/engine/requests.js.map +1 -1
  69. package/dist/engine-loader.d.ts +13 -9
  70. package/dist/engine-loader.js +38 -28
  71. package/dist/engine-loader.js.map +1 -1
  72. package/dist/geoplateforme.d.ts +26 -10
  73. package/dist/geoplateforme.js +45 -20
  74. package/dist/geoplateforme.js.map +1 -1
  75. package/dist/index.d.ts +12 -4
  76. package/dist/index.js +9 -2
  77. package/dist/index.js.map +1 -1
  78. package/dist/isard_bg.wasm +0 -0
  79. package/dist/isard_core_bg.wasm +0 -0
  80. package/dist/isard_points_bg.wasm +0 -0
  81. package/dist/isard_tess_bg.wasm +0 -0
  82. package/dist/layers/extrusions.d.ts +1 -1
  83. package/dist/layers/extrusions.js +10 -5
  84. package/dist/layers/extrusions.js.map +1 -1
  85. package/dist/layers/features.d.ts +10 -10
  86. package/dist/layers/features.js +41 -42
  87. package/dist/layers/features.js.map +1 -1
  88. package/dist/layers/glyphs.d.ts +3 -3
  89. package/dist/layers/glyphs.js +34 -40
  90. package/dist/layers/glyphs.js.map +1 -1
  91. package/dist/layers/icons.d.ts +8 -8
  92. package/dist/layers/icons.js +76 -68
  93. package/dist/layers/icons.js.map +1 -1
  94. package/dist/layers/layers.d.ts +1 -1
  95. package/dist/layers/layers.js +42 -29
  96. package/dist/layers/layers.js.map +1 -1
  97. package/dist/layers/panoramas.d.ts +2 -2
  98. package/dist/layers/panoramas.js +52 -41
  99. package/dist/layers/panoramas.js.map +1 -1
  100. package/dist/layers/pointclouds.d.ts +3 -3
  101. package/dist/layers/pointclouds.js +25 -33
  102. package/dist/layers/pointclouds.js.map +1 -1
  103. package/dist/layers/symbols.d.ts +1 -1
  104. package/dist/layers/symbols.js +68 -71
  105. package/dist/layers/symbols.js.map +1 -1
  106. package/dist/layers/vectors.d.ts +60 -0
  107. package/dist/layers/vectors.js +130 -0
  108. package/dist/layers/vectors.js.map +1 -0
  109. package/dist/map/basemap-layers.d.ts +26 -0
  110. package/dist/map/basemap-layers.js +61 -0
  111. package/dist/map/basemap-layers.js.map +1 -0
  112. package/dist/map/canvas.d.ts +17 -0
  113. package/dist/map/canvas.js +56 -0
  114. package/dist/map/canvas.js.map +1 -0
  115. package/dist/map/checks.d.ts +11 -0
  116. package/dist/map/checks.js +39 -0
  117. package/dist/map/checks.js.map +1 -0
  118. package/dist/map/credits.d.ts +17 -0
  119. package/dist/map/credits.js +34 -0
  120. package/dist/map/credits.js.map +1 -0
  121. package/dist/map/engine-settings.d.ts +15 -0
  122. package/dist/map/engine-settings.js +45 -0
  123. package/dist/map/engine-settings.js.map +1 -0
  124. package/dist/map/engines.d.ts +41 -0
  125. package/dist/map/engines.js +77 -0
  126. package/dist/map/engines.js.map +1 -0
  127. package/dist/map/events.d.ts +14 -0
  128. package/dist/map/events.js +46 -0
  129. package/dist/map/events.js.map +1 -0
  130. package/dist/map/frame-loop.d.ts +64 -0
  131. package/dist/map/frame-loop.js +145 -0
  132. package/dist/map/frame-loop.js.map +1 -0
  133. package/dist/map/hover-pick.d.ts +30 -0
  134. package/dist/map/hover-pick.js +56 -0
  135. package/dist/map/hover-pick.js.map +1 -0
  136. package/dist/map/layer-spec.d.ts +42 -0
  137. package/dist/map/layer-spec.js +34 -0
  138. package/dist/map/layer-spec.js.map +1 -0
  139. package/dist/map/layer-stack.d.ts +36 -0
  140. package/dist/map/layer-stack.js +101 -0
  141. package/dist/map/layer-stack.js.map +1 -0
  142. package/dist/map/overlay-host.d.ts +36 -0
  143. package/dist/map/overlay-host.js +101 -0
  144. package/dist/map/overlay-host.js.map +1 -0
  145. package/dist/map/panorama-host.d.ts +5 -0
  146. package/dist/map/panorama-host.js +32 -0
  147. package/dist/map/panorama-host.js.map +1 -0
  148. package/dist/map/raster-source.d.ts +11 -0
  149. package/dist/map/raster-source.js +26 -0
  150. package/dist/map/raster-source.js.map +1 -0
  151. package/dist/map/symbol-atlases.d.ts +26 -0
  152. package/dist/map/symbol-atlases.js +59 -0
  153. package/dist/map/symbol-atlases.js.map +1 -0
  154. package/dist/map/viewshed.d.ts +5 -0
  155. package/dist/map/viewshed.js +28 -0
  156. package/dist/map/viewshed.js.map +1 -0
  157. package/dist/map/workers.d.ts +46 -0
  158. package/dist/map/workers.js +73 -0
  159. package/dist/map/workers.js.map +1 -0
  160. package/dist/map.d.ts +54 -126
  161. package/dist/map.js +227 -698
  162. package/dist/map.js.map +1 -1
  163. package/dist/react/Control.d.ts +11 -0
  164. package/dist/react/Control.js +18 -0
  165. package/dist/react/Control.js.map +1 -0
  166. package/dist/react/CustomLayer.d.ts +11 -0
  167. package/dist/react/CustomLayer.js +30 -0
  168. package/dist/react/CustomLayer.js.map +1 -0
  169. package/dist/react/IsardMap.d.ts +43 -0
  170. package/dist/react/IsardMap.js +147 -0
  171. package/dist/react/IsardMap.js.map +1 -0
  172. package/dist/react/Layer.d.ts +42 -0
  173. package/dist/react/Layer.js +74 -0
  174. package/dist/react/Layer.js.map +1 -0
  175. package/dist/react/Marker.d.ts +24 -0
  176. package/dist/react/Marker.js +53 -0
  177. package/dist/react/Marker.js.map +1 -0
  178. package/dist/react/Panel.d.ts +11 -0
  179. package/dist/react/Panel.js +37 -0
  180. package/dist/react/Panel.js.map +1 -0
  181. package/dist/react/Popup.d.ts +18 -0
  182. package/dist/react/Popup.js +60 -0
  183. package/dist/react/Popup.js.map +1 -0
  184. package/dist/react/Swipe.d.ts +16 -0
  185. package/dist/react/Swipe.js +52 -0
  186. package/dist/react/Swipe.js.map +1 -0
  187. package/dist/react/VectorGeometry.d.ts +35 -0
  188. package/dist/react/VectorGeometry.js +82 -0
  189. package/dist/react/VectorGeometry.js.map +1 -0
  190. package/dist/react/Viewshed.d.ts +5 -0
  191. package/dist/react/Viewshed.js +28 -0
  192. package/dist/react/Viewshed.js.map +1 -0
  193. package/dist/react/context.d.ts +33 -0
  194. package/dist/react/context.js +20 -0
  195. package/dist/react/context.js.map +1 -0
  196. package/dist/react/index.d.ts +16 -108
  197. package/dist/react/index.js +11 -397
  198. package/dist/react/index.js.map +1 -1
  199. package/dist/settings.d.ts +5 -9
  200. package/dist/settings.js +17 -15
  201. package/dist/settings.js.map +1 -1
  202. package/dist/types.d.ts +27 -4
  203. package/dist/types.js.map +1 -1
  204. package/dist/ui/controls.js +6 -4
  205. package/dist/ui/controls.js.map +1 -1
  206. package/dist/ui/interaction.d.ts +2 -2
  207. package/dist/ui/interaction.js +8 -7
  208. package/dist/ui/interaction.js.map +1 -1
  209. package/dist/ui/minimap.d.ts +25 -0
  210. package/dist/ui/minimap.js +90 -0
  211. package/dist/ui/minimap.js.map +1 -0
  212. package/dist/ui/overlay.js +18 -20
  213. package/dist/ui/overlay.js.map +1 -1
  214. package/dist/ui/scale.d.ts +19 -0
  215. package/dist/ui/scale.js +44 -0
  216. package/dist/ui/scale.js.map +1 -0
  217. package/dist/ui/search.d.ts +25 -0
  218. package/dist/ui/search.js +119 -0
  219. package/dist/ui/search.js.map +1 -0
  220. package/dist/ui/style.d.ts +1 -1
  221. package/dist/ui/style.js +19 -2
  222. package/dist/ui/style.js.map +1 -1
  223. package/dist/util/animation.d.ts +3 -3
  224. package/dist/util/animation.js +6 -6
  225. package/dist/util/animation.js.map +1 -1
  226. package/dist/util/color.d.ts +1 -1
  227. package/dist/util/color.js +14 -16
  228. package/dist/util/color.js.map +1 -1
  229. package/dist/util/geo.d.ts +6 -6
  230. package/dist/util/geo.js +12 -12
  231. package/dist/util/geo.js.map +1 -1
  232. package/dist/util/guards.d.ts +7 -0
  233. package/dist/util/guards.js +8 -0
  234. package/dist/util/guards.js.map +1 -0
  235. package/dist/util/lru.js.map +1 -1
  236. package/dist/util/sun.d.ts +11 -0
  237. package/dist/util/sun.js +26 -0
  238. package/dist/util/sun.js.map +1 -0
  239. package/dist/wasm/isard.d.ts +250 -7
  240. package/dist/wasm/isard.js +375 -8
  241. package/dist/wasm/isard_core.d.ts +226 -7
  242. package/dist/wasm/isard_core.js +351 -8
  243. package/dist/wasm/isard_tess.d.ts +109 -0
  244. package/dist/wasm/isard_tess.js +398 -0
  245. package/dist/workers/basemap/geometry.d.ts +72 -0
  246. package/dist/workers/basemap/labels.d.ts +8 -0
  247. package/dist/workers/basemap/raster.d.ts +10 -0
  248. package/dist/workers/basemap/tiles.d.ts +65 -0
  249. package/dist/workers/basemap/trees.d.ts +19 -0
  250. package/dist/workers/basemap.worker.d.ts +126 -22
  251. package/dist/workers/basemap.worker.js +76 -544
  252. package/dist/workers/basemap.worker.js.map +1 -1
  253. package/package.json +5 -4
  254. package/vite.js +10 -2
@@ -62,7 +62,7 @@ class Reader {
62
62
  }
63
63
  }
64
64
  /** Glyphs of a range file: id → metrics and bitmap */
65
- function parse(buffer) {
65
+ const parse = (buffer) => {
66
66
  const out = new Map();
67
67
  const root = new Reader(new Uint8Array(buffer));
68
68
  while (!root.done) {
@@ -115,7 +115,7 @@ function parse(buffer) {
115
115
  }
116
116
  }
117
117
  return out;
118
- }
118
+ };
119
119
  /** The glyphs of a map and their atlas */
120
120
  export class Glyphs {
121
121
  url;
@@ -160,47 +160,45 @@ export class Glyphs {
160
160
  }
161
161
  /** Loads these fonts from another glyph URL (a style's `glyphs`); a font keeps the first URL given for it */
162
162
  register(url, fonts) {
163
- for (const font of fonts)
163
+ [...fonts].forEach((font) => {
164
164
  if (!this.sources.has(font))
165
165
  this.sources.set(font, url);
166
+ });
166
167
  }
167
168
  /** Loads the glyphs of these code points in a font */
168
169
  async load(font, codes) {
169
170
  const glyphs = this.fonts.get(font) ?? new Map();
170
171
  this.fonts.set(font, glyphs);
171
- const starts = new Set();
172
- for (const code of codes)
173
- if (!glyphs.has(code))
174
- starts.add(Math.floor(code / 256) * 256);
172
+ const starts = new Set([...codes].filter((code) => !glyphs.has(code)).map((code) => Math.floor(code / 256) * 256));
175
173
  await Promise.all([...starts].map((start) => this.range(font, start, glyphs)));
176
174
  return glyphs;
177
175
  }
178
176
  range(font, start, glyphs) {
179
177
  const key = `${font}/${start}`;
180
- let pending = this.ranges.get(key);
181
- if (!pending) {
182
- const url = (this.sources.get(font) ?? this.url)
183
- .replace('{fontstack}', encodeURIComponent(font))
184
- .replace('{range}', `${start}-${start + 255}`);
185
- pending = fetch(url, withHeaders(url))
186
- .then((r) => (r.ok ? r.arrayBuffer() : Promise.reject(new Error(`${url}: ${r.status}`))))
187
- .then((buffer) => {
188
- for (const [id, { glyph, bitmap }] of parse(buffer)) {
189
- if (glyph.width > 0 && bitmap.length >= (glyph.width + 2 * BUFFER) * (glyph.height + 2 * BUFFER)) {
190
- this.pack(glyph, bitmap);
191
- }
192
- glyphs.set(id, glyph);
178
+ const cached = this.ranges.get(key);
179
+ if (cached)
180
+ return cached;
181
+ const url = (this.sources.get(font) ?? this.url)
182
+ .replace('{fontstack}', encodeURIComponent(font))
183
+ .replace('{range}', `${start}-${start + 255}`);
184
+ const pending = fetch(url, withHeaders(url))
185
+ .then((r) => (r.ok ? r.arrayBuffer() : Promise.reject(new Error(`${url}: ${r.status}`))))
186
+ .then((buffer) => {
187
+ parse(buffer).forEach(({ glyph, bitmap }, id) => {
188
+ if (glyph.width > 0 && bitmap.length >= (glyph.width + 2 * BUFFER) * (glyph.height + 2 * BUFFER)) {
189
+ this.pack(glyph, bitmap);
193
190
  }
194
- this.version += 1;
195
- // One upload for the range
196
- this.flush();
197
- })
198
- .catch((error) => {
199
- // A missing range is not retried this session; its characters stay blank
200
- console.warn('isard: glyphs', error);
191
+ glyphs.set(id, glyph);
201
192
  });
202
- this.ranges.set(key, pending);
203
- }
193
+ this.version += 1;
194
+ // One upload for the range
195
+ this.flush();
196
+ })
197
+ .catch((error) => {
198
+ // A missing range is not retried this session; its characters stay blank
199
+ console.warn('isard: glyphs', error);
200
+ });
201
+ this.ranges.set(key, pending);
204
202
  return pending;
205
203
  }
206
204
  /**
@@ -220,11 +218,11 @@ export class Glyphs {
220
218
  }
221
219
  /** Sends the rows changed since the last upload to the engine */
222
220
  flush() {
223
- for (const [page, [y0, y1]] of this.dirty) {
221
+ this.dirty.forEach(([y0, y1], page) => {
224
222
  const data = this.pages[page];
225
223
  if (data)
226
224
  this.engine?.updateGlyphPage(page, 0, y0, this.size, y1 - y0, data.subarray(y0 * this.size, y1 * this.size));
227
- }
225
+ });
228
226
  this.dirty.clear();
229
227
  }
230
228
  /**
@@ -300,18 +298,14 @@ export class Glyphs {
300
298
  }
301
299
  }
302
300
  /** Code points of a text, for loading */
303
- export function codes(parts) {
304
- const out = new Set();
305
- for (const p of parts)
306
- for (const ch of p.text)
307
- out.add(ch.codePointAt(0) ?? 32);
308
- return out;
309
- }
301
+ export const codes = (parts) => {
302
+ return new Set(parts.flatMap((p) => [...p.text].map((ch) => ch.codePointAt(0) ?? 32)));
303
+ };
310
304
  /**
311
305
  * Lays out a label: lines split at `\n` and wrapped at `maxWidth` ems, centered, the block placed by `anchor` around
312
306
  * the anchor point and moved by `offset` (ems); `size` in CSS pixels. Glyphs not loaded take no room.
313
307
  */
314
- export function shape(parts, glyphsOf, options) {
308
+ export const shape = (parts, glyphsOf, options) => {
315
309
  const { size, maxWidth, lineHeight, anchor, offset } = options;
316
310
  const k = size / EM;
317
311
  const lines = [[]];
@@ -412,5 +406,5 @@ export function shape(parts, glyphsOf, options) {
412
406
  box: [(x0 + dx) * k, (y0 + dy) * k, (x1 + dx) * k, (y1 + dy) * k],
413
407
  layout: [(dx - widest / 2) * k, (middle - height / 2) * k, (dx + widest / 2) * k, (middle + height / 2) * k],
414
408
  };
415
- }
409
+ };
416
410
  //# sourceMappingURL=glyphs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"glyphs.js","sourceRoot":"","sources":["../../src/layers/glyphs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Glyphs for the symbol layers: signed distance fields in MapLibre's glyph format (ranges of 256 code points per\n * protobuf file, 24 px glyphs with a 3 px buffer), loaded on first use (from OpenFreeMap's fonts by default, a vector\n * basemap's labels from the glyphs of its style), packed into an atlas the engine samples; and the shaping of a label:\n * its lines (explicit and wrapped), their glyphs placed around the anchor.\n *\n * The atlas has pages of one size: the first one grows up to the page size limit, then pages are added, so it never\n * runs out. A glyph's atlas row counts the rows of the pages before its own (`y + page × size`, the pages stacked):\n * the coordinates of the glyphs placed so far stay valid as the atlas grows.\n */\n\nimport { withHeaders } from '../engine/requests.ts';\nimport type { Anchor } from '../ui/overlay.ts';\nimport type { Engine } from '../wasm/isard.js';\n\n/** OpenFreeMap's fonts, those of its styles (Noto Sans Regular, Bold, Italic) */\nexport const GLYPHS_URL = 'https://tiles.openfreemap.org/fonts/{fontstack}/{range}.pbf';\n\n/** The font of labels that name none */\nexport const DEFAULT_FONT = 'Noto Sans Regular';\n\n/** Size the glyphs are drawn at in the files, and their buffer */\nconst EM = 24;\nconst BUFFER = 3;\n\nexport interface Glyph {\n width: number;\n height: number;\n left: number;\n top: number;\n advance: number;\n /**\n * Place of its bitmap ((width + 6) × (height + 6)) in the atlas, `y` counting the rows of the pages before its\n * own; undefined for an empty one (a space)\n */\n x?: number;\n y?: number;\n /** Its page of the atlas */\n page?: number;\n}\n\n/** Largest side of a page of the atlas, and most pages (WebGL2 guarantees 256 layers of a texture array) */\nconst PAGE_MAX = 2048;\nconst MAX_PAGES = 256;\n\n/** A protobuf reader, enough for the glyph files */\nclass Reader {\n pos = 0;\n constructor(private readonly buf: Uint8Array) {}\n get done(): boolean {\n return this.pos >= this.buf.length;\n }\n varint(): number {\n let value = 0;\n let shift = 0;\n for (;;) {\n const b = this.buf[this.pos++] ?? 0;\n value += (b & 0x7f) * 2 ** shift;\n if (b < 0x80) return value;\n shift += 7;\n }\n }\n sint(): number {\n const v = this.varint();\n return v % 2 === 1 ? -(v + 1) / 2 : v / 2;\n }\n bytes(): Uint8Array {\n const n = this.varint();\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n skip(wire: number): void {\n if (wire === 0) this.varint();\n else if (wire === 2) this.pos += this.varint();\n else if (wire === 5) this.pos += 4;\n else if (wire === 1) this.pos += 8;\n }\n}\n\n/** Glyphs of a range file: id → metrics and bitmap */\nfunction parse(buffer: ArrayBuffer): Map<number, { glyph: Glyph; bitmap: Uint8Array }> {\n const out = new Map<number, { glyph: Glyph; bitmap: Uint8Array }>();\n const root = new Reader(new Uint8Array(buffer));\n while (!root.done) {\n const tag = root.varint();\n if (tag >> 3 !== 1) {\n root.skip(tag & 7);\n continue;\n }\n // A fontstack\n const stack = new Reader(root.bytes());\n while (!stack.done) {\n const t = stack.varint();\n if (t >> 3 !== 3) {\n stack.skip(t & 7);\n continue;\n }\n const g = new Reader(stack.bytes());\n let id = 0;\n let bitmap: Uint8Array = new Uint8Array(0);\n const glyph: Glyph = { width: 0, height: 0, left: 0, top: 0, advance: 0 };\n while (!g.done) {\n const f = g.varint();\n switch (f >> 3) {\n case 1:\n id = g.varint();\n break;\n case 2:\n bitmap = g.bytes();\n break;\n case 3:\n glyph.width = g.varint();\n break;\n case 4:\n glyph.height = g.varint();\n break;\n case 5:\n glyph.left = g.sint();\n break;\n case 6:\n glyph.top = g.sint();\n break;\n case 7:\n glyph.advance = g.varint();\n break;\n default:\n g.skip(f & 7);\n }\n }\n out.set(id, { glyph, bitmap });\n }\n }\n return out;\n}\n\n/** A shelf of the packer: its page, y, height, and the x of the next free place */\ninterface Shelf {\n page: number;\n y: number;\n height: number;\n x: number;\n}\n\n/** The glyphs of a map and their atlas */\nexport class Glyphs {\n /** Side of the pages */\n private size = 512;\n private pages: Uint8Array[] = [new Uint8Array(512 * 512)];\n /** Pages allocated in the engine (doubled when more are needed: fewer reallocations) */\n private capacity = 1;\n private shelves: Shelf[] = [];\n /** Rows of each page holding glyphs (from its top): the rest is blank, never sent */\n private readonly used: number[] = [0];\n private readonly fonts = new Map<string, Map<number, Glyph>>();\n private readonly ranges = new Map<string, Promise<void>>();\n /** Glyph URLs of fonts other than the map's (those of a vector basemap's style) */\n private readonly sources = new Map<string, string>();\n private engine: Engine | undefined;\n /** Rows of each page changed since the last upload: first, end */\n private readonly dirty = new Map<number, [number, number]>();\n /** The atlas has its most pages: new glyphs stay blank */\n private full = false;\n /** Largest side of a page */\n private readonly maxSize: number;\n /** Bumped each time glyphs are added: labels shaped while some of theirs were missing are shaped again */\n version = 0;\n\n /** `maxSize`: the GPU's texture size limit if known (the pages are at most 2048 × 2048) */\n constructor(\n private readonly url = GLYPHS_URL,\n maxSize = 4096,\n ) {\n this.maxSize = Math.max(512, Math.min(PAGE_MAX, maxSize));\n }\n\n /** Sends the whole atlas to an engine (a new one after a context loss) */\n attach(engine: Engine): void {\n this.engine = engine;\n this.dirty.clear();\n this.upload();\n }\n\n /** Side of the pages of the atlas */\n get atlasSize(): number {\n return this.size;\n }\n\n get pageCount(): number {\n return this.pages.length;\n }\n\n /** Loads these fonts from another glyph URL (a style's `glyphs`); a font keeps the first URL given for it */\n register(url: string, fonts: Iterable<string>): void {\n for (const font of fonts) if (!this.sources.has(font)) this.sources.set(font, url);\n }\n\n /** Loads the glyphs of these code points in a font */\n async load(font: string, codes: Iterable<number>): Promise<Map<number, Glyph>> {\n const glyphs = this.fonts.get(font) ?? new Map<number, Glyph>();\n this.fonts.set(font, glyphs);\n const starts = new Set<number>();\n for (const code of codes) if (!glyphs.has(code)) starts.add(Math.floor(code / 256) * 256);\n await Promise.all([...starts].map((start) => this.range(font, start, glyphs)));\n return glyphs;\n }\n\n private range(font: string, start: number, glyphs: Map<number, Glyph>): Promise<void> {\n const key = `${font}/${start}`;\n let pending = this.ranges.get(key);\n if (!pending) {\n const url = (this.sources.get(font) ?? this.url)\n .replace('{fontstack}', encodeURIComponent(font))\n .replace('{range}', `${start}-${start + 255}`);\n pending = fetch(url, withHeaders(url))\n .then((r) => (r.ok ? r.arrayBuffer() : Promise.reject(new Error(`${url}: ${r.status}`))))\n .then((buffer) => {\n for (const [id, { glyph, bitmap }] of parse(buffer)) {\n if (glyph.width > 0 && bitmap.length >= (glyph.width + 2 * BUFFER) * (glyph.height + 2 * BUFFER)) {\n this.pack(glyph, bitmap);\n }\n glyphs.set(id, glyph);\n }\n this.version += 1;\n // One upload for the range\n this.flush();\n })\n .catch((error: unknown) => {\n // A missing range is not retried this session; its characters stay blank\n console.warn('isard: glyphs', error);\n });\n this.ranges.set(key, pending);\n }\n return pending;\n }\n\n /**\n * Allocates the pages in the engine and sends what they hold (their rows with glyphs). The engine allocates its\n * pages again empty: everything is sent each time, the pages doubled to make it rare\n */\n private upload(): void {\n const engine = this.engine;\n if (!engine) return;\n engine.setGlyphPages(this.size, this.size, this.capacity);\n this.pages.forEach((page, i) => {\n const rows = this.used[i] ?? 0;\n if (rows > 0) engine.updateGlyphPage(i, 0, 0, this.size, rows, page.subarray(0, rows * this.size));\n });\n }\n\n /** Sends the rows changed since the last upload to the engine */\n private flush(): void {\n for (const [page, [y0, y1]] of this.dirty) {\n const data = this.pages[page];\n if (data)\n this.engine?.updateGlyphPage(page, 0, y0, this.size, y1 - y0, data.subarray(y0 * this.size, y1 * this.size));\n }\n this.dirty.clear();\n }\n\n /**\n * Places a bitmap in the atlas (growing the first page, then adding pages when full); `flush` sends it to the\n * engine\n */\n private pack(glyph: Glyph, bitmap: Uint8Array): void {\n const w = glyph.width + 2 * BUFFER;\n const h = glyph.height + 2 * BUFFER;\n // One texel of padding between bitmaps: linear filtering never reads a neighbour\n let shelf = this.shelves.find((s) => s.height >= h && s.height <= h + 4 && s.x + w + 1 <= this.size);\n if (!shelf) {\n const page = this.pages.length - 1;\n // New shelves go on the last page only: the last shelf is on it, unless the page is new\n const last = this.shelves.at(-1);\n const y = last && last.page === page ? last.y + last.height + 1 : 0;\n if (y + h > this.size) {\n if (this.pages.length === 1 && this.size * 2 <= this.maxSize) this.grow();\n else if (this.pages.length < MAX_PAGES) this.addPage();\n else {\n // Full: the glyph takes its room in the text but is not drawn\n if (!this.full) console.warn(`isard: the glyph atlas is full (${MAX_PAGES} pages)`);\n this.full = true;\n return;\n }\n this.pack(glyph, bitmap);\n return;\n }\n shelf = { page, y, height: h, x: 0 };\n this.shelves.push(shelf);\n }\n const data = this.pages[shelf.page];\n if (!data) return;\n glyph.x = shelf.x;\n glyph.y = shelf.page * this.size + shelf.y;\n glyph.page = shelf.page;\n shelf.x += w + 1;\n for (let row = 0; row < h; row += 1) {\n data.set(bitmap.subarray(row * w, row * w + w), (shelf.y + row) * this.size + glyph.x);\n }\n this.used[shelf.page] = Math.max(this.used[shelf.page] ?? 0, shelf.y + h);\n const dirty = this.dirty.get(shelf.page);\n this.dirty.set(shelf.page, [Math.min(dirty?.[0] ?? shelf.y, shelf.y), Math.max(dirty?.[1] ?? 0, shelf.y + h)]);\n }\n\n /** Doubles the only page; the glyphs keep their places (texel coordinates) */\n private grow(): void {\n const size = this.size * 2;\n const old = this.pages[0] ?? new Uint8Array(this.size * this.size);\n const page = new Uint8Array(size * size);\n for (let row = 0; row < this.size; row += 1) {\n page.set(old.subarray(row * this.size, (row + 1) * this.size), row * size);\n }\n this.size = size;\n this.pages = [page];\n // The whole atlas is sent with what it holds so far\n this.dirty.clear();\n this.upload();\n }\n\n /** A new empty page, after the others; the engine's pages are allocated again only past its capacity */\n private addPage(): void {\n this.pages.push(new Uint8Array(this.size * this.size));\n this.used.push(0);\n if (this.pages.length > this.capacity) {\n this.capacity = Math.min(MAX_PAGES, this.capacity * 2);\n // The pages are allocated again: everything is sent, pending changes included\n this.dirty.clear();\n this.upload();\n }\n }\n}\n\n/** A run of text with its own scale (MapLibre's `format` with `font-scale`) and font */\nexport interface TextPart {\n text: string;\n scale?: number;\n font?: string;\n}\n\nexport type { Anchor } from '../ui/overlay.ts';\n\nexport interface Shaping {\n /** Glyph quads: x, y, width, height (CSS pixels from the anchor), atlas u0, v0, u1, v1, font scale */\n quads: number[][];\n /** Ink box from the anchor: min x, min y, max x, max y */\n box: [number, number, number, number];\n /** Layout box from the anchor, what an icon fitted to the text frames: the advances of its widest line across, its\n * lines' height (`lineHeight` each) down, centered on the ink */\n layout: [number, number, number, number];\n}\n\n/** Code points of a text, for loading */\nexport function codes(parts: readonly TextPart[]): Set<number> {\n const out = new Set<number>();\n for (const p of parts) for (const ch of p.text) out.add(ch.codePointAt(0) ?? 32);\n return out;\n}\n\n/**\n * Lays out a label: lines split at `\\n` and wrapped at `maxWidth` ems, centered, the block placed by `anchor` around\n * the anchor point and moved by `offset` (ems); `size` in CSS pixels. Glyphs not loaded take no room.\n */\nexport function shape(\n parts: readonly TextPart[],\n glyphsOf: (font: string) => Map<number, Glyph> | undefined,\n options: {\n font: string;\n size: number;\n maxWidth: number;\n lineHeight: number;\n anchor: Anchor;\n offset: [number, number];\n },\n): Shaping {\n const { size, maxWidth, lineHeight, anchor, offset } = options;\n const k = size / EM;\n // Characters with their glyph and scale, split into lines\n type Char = { glyph: Glyph | undefined; scale: number; space: boolean };\n const lines: Char[][] = [[]];\n for (const part of parts) {\n const glyphs = glyphsOf(part.font ?? options.font);\n for (const ch of part.text) {\n if (ch === '\\n') {\n lines.push([]);\n continue;\n }\n const code = ch.codePointAt(0) ?? 32;\n lines.at(-1)?.push({ glyph: glyphs?.get(code), scale: part.scale ?? 1, space: /\\s/.test(ch) });\n }\n }\n const advance = (c: Char) => (c.glyph?.advance ?? (c.space ? EM / 4 : 0)) * c.scale;\n // Wrapping at spaces, greedy\n const limit = maxWidth * EM;\n const wrapped: Char[][] = [];\n for (const line of lines) {\n let current: Char[] = [];\n let width = 0;\n let lastSpace = -1;\n for (const c of line) {\n current.push(c);\n width += advance(c);\n if (c.space) lastSpace = current.length - 1;\n if (width > limit && lastSpace > 0) {\n wrapped.push(current.slice(0, lastSpace));\n current = current.slice(lastSpace + 1);\n width = current.reduce((s, x) => s + advance(x), 0);\n lastSpace = -1;\n }\n }\n wrapped.push(current);\n }\n // Glyphs on their lines, each line centered on x = 0, in units of the 24 px font\n const quads: number[][] = [];\n let [x0, y0, x1, y1] = [\n Number.POSITIVE_INFINITY,\n Number.POSITIVE_INFINITY,\n Number.NEGATIVE_INFINITY,\n Number.NEGATIVE_INFINITY,\n ];\n let baseline = 0;\n let widest = 0;\n let height = 0;\n wrapped.forEach((line, i) => {\n const scale = Math.max(1, ...line.map((c) => c.scale));\n if (i > 0) baseline += lineHeight * EM * scale;\n height += lineHeight * EM * scale;\n const width = line.reduce((s, c) => s + advance(c), 0);\n widest = Math.max(widest, width);\n let pen = -width / 2;\n for (const c of line) {\n const g = c.glyph;\n if (g && g.x !== undefined && g.y !== undefined && g.width > 0) {\n const qx = pen + (g.left - BUFFER) * c.scale;\n const qy = baseline - (g.top + BUFFER) * c.scale;\n const qw = (g.width + 2 * BUFFER) * c.scale;\n const qh = (g.height + 2 * BUFFER) * c.scale;\n quads.push([qx, qy, qw, qh, g.x, g.y, g.x + g.width + 2 * BUFFER, g.y + g.height + 2 * BUFFER, c.scale]);\n x0 = Math.min(x0, qx + BUFFER * c.scale);\n y0 = Math.min(y0, qy + BUFFER * c.scale);\n x1 = Math.max(x1, qx + qw - BUFFER * c.scale);\n y1 = Math.max(y1, qy + qh - BUFFER * c.scale);\n }\n pen += advance(c);\n }\n });\n if (!quads.length) return { quads, box: [0, 0, 0, 0], layout: [0, 0, 0, 0] };\n // The block placed around the anchor by its ink box\n // The side of the box at the anchor: its start, its end, or its middle\n const side = (start: boolean, end: boolean, lo: number, hi: number) => {\n if (start) return -lo;\n if (end) return -hi;\n return -(lo + hi) / 2;\n };\n const horizontal = side(anchor.includes('left'), anchor.includes('right'), x0, x1);\n const vertical = side(anchor.startsWith('top'), anchor.startsWith('bottom'), y0, y1);\n const dx = horizontal + offset[0] * EM;\n const dy = vertical + offset[1] * EM;\n for (const q of quads) {\n q[0] = ((q[0] ?? 0) + dx) * k;\n q[1] = ((q[1] ?? 0) + dy) * k;\n q[2] = (q[2] ?? 0) * k;\n q[3] = (q[3] ?? 0) * k;\n q[8] = (q[8] ?? 1) * k;\n }\n const middle = (y0 + y1) / 2 + dy;\n height = Math.max(height, y1 - y0);\n return {\n quads,\n box: [(x0 + dx) * k, (y0 + dy) * k, (x1 + dx) * k, (y1 + dy) * k],\n layout: [(dx - widest / 2) * k, (middle - height / 2) * k, (dx + widest / 2) * k, (middle + height / 2) * k],\n };\n}\n"]}
1
+ {"version":3,"file":"glyphs.js","sourceRoot":"","sources":["../../src/layers/glyphs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Glyphs for the symbol layers: signed distance fields in MapLibre's glyph format (ranges of 256 code points per\n * protobuf file, 24 px glyphs with a 3 px buffer), loaded on first use (from OpenFreeMap's fonts by default, a vector\n * basemap's labels from the glyphs of its style), packed into an atlas the engine samples; and the shaping of a label:\n * its lines (explicit and wrapped), their glyphs placed around the anchor.\n *\n * The atlas has pages of one size: the first one grows up to the page size limit, then pages are added, so it never\n * runs out. A glyph's atlas row counts the rows of the pages before its own (`y + page × size`, the pages stacked):\n * the coordinates of the glyphs placed so far stay valid as the atlas grows.\n */\n\nimport { withHeaders } from '../engine/requests.ts';\nimport type { Anchor } from '../ui/overlay.ts';\nimport type { Engine } from '../wasm/isard.js';\n\n/** OpenFreeMap's fonts, those of its styles (Noto Sans Regular, Bold, Italic) */\nexport const GLYPHS_URL = 'https://tiles.openfreemap.org/fonts/{fontstack}/{range}.pbf';\n\n/** The font of labels that name none */\nexport const DEFAULT_FONT = 'Noto Sans Regular';\n\n/** Size the glyphs are drawn at in the files, and their buffer */\nconst EM = 24;\nconst BUFFER = 3;\n\nexport interface Glyph {\n width: number;\n height: number;\n left: number;\n top: number;\n advance: number;\n /**\n * Place of its bitmap ((width + 6) × (height + 6)) in the atlas, `y` counting the rows of the pages before its\n * own; undefined for an empty one (a space)\n */\n x?: number;\n y?: number;\n /** Its page of the atlas */\n page?: number;\n}\n\n/** Largest side of a page of the atlas, and most pages (WebGL2 guarantees 256 layers of a texture array) */\nconst PAGE_MAX = 2048;\nconst MAX_PAGES = 256;\n\n/** A protobuf reader, enough for the glyph files */\nclass Reader {\n pos = 0;\n constructor(private readonly buf: Uint8Array) {}\n get done(): boolean {\n return this.pos >= this.buf.length;\n }\n varint(): number {\n let value = 0;\n let shift = 0;\n\n for (;;) {\n const b = this.buf[this.pos++] ?? 0;\n\n value += (b & 0x7f) * 2 ** shift;\n if (b < 0x80) return value;\n shift += 7;\n }\n }\n sint(): number {\n const v = this.varint();\n\n return v % 2 === 1 ? -(v + 1) / 2 : v / 2;\n }\n bytes(): Uint8Array {\n const n = this.varint();\n const out = this.buf.subarray(this.pos, this.pos + n);\n\n this.pos += n;\n\n return out;\n }\n skip(wire: number): void {\n if (wire === 0) this.varint();\n else if (wire === 2) this.pos += this.varint();\n else if (wire === 5) this.pos += 4;\n else if (wire === 1) this.pos += 8;\n }\n}\n\n/** Glyphs of a range file: id → metrics and bitmap */\nconst parse = (buffer: ArrayBuffer): Map<number, { glyph: Glyph; bitmap: Uint8Array }> => {\n const out = new Map<number, { glyph: Glyph; bitmap: Uint8Array }>();\n const root = new Reader(new Uint8Array(buffer));\n\n while (!root.done) {\n const tag = root.varint();\n\n if (tag >> 3 !== 1) {\n root.skip(tag & 7);\n continue;\n }\n\n // A fontstack\n const stack = new Reader(root.bytes());\n\n while (!stack.done) {\n const t = stack.varint();\n\n if (t >> 3 !== 3) {\n stack.skip(t & 7);\n continue;\n }\n\n const g = new Reader(stack.bytes());\n let id = 0;\n let bitmap: Uint8Array = new Uint8Array(0);\n const glyph: Glyph = { width: 0, height: 0, left: 0, top: 0, advance: 0 };\n\n while (!g.done) {\n const f = g.varint();\n\n switch (f >> 3) {\n case 1:\n id = g.varint();\n break;\n case 2:\n bitmap = g.bytes();\n break;\n case 3:\n glyph.width = g.varint();\n break;\n case 4:\n glyph.height = g.varint();\n break;\n case 5:\n glyph.left = g.sint();\n break;\n case 6:\n glyph.top = g.sint();\n break;\n case 7:\n glyph.advance = g.varint();\n break;\n default:\n g.skip(f & 7);\n }\n }\n out.set(id, { glyph, bitmap });\n }\n }\n\n return out;\n};\n\n/** A shelf of the packer: its page, y, height, and the x of the next free place */\ninterface Shelf {\n page: number;\n y: number;\n height: number;\n x: number;\n}\n\n/** The glyphs of a map and their atlas */\nexport class Glyphs {\n /** Side of the pages */\n private size = 512;\n private pages: Uint8Array[] = [new Uint8Array(512 * 512)];\n /** Pages allocated in the engine (doubled when more are needed: fewer reallocations) */\n private capacity = 1;\n private shelves: Shelf[] = [];\n /** Rows of each page holding glyphs (from its top): the rest is blank, never sent */\n private readonly used: number[] = [0];\n private readonly fonts = new Map<string, Map<number, Glyph>>();\n private readonly ranges = new Map<string, Promise<void>>();\n /** Glyph URLs of fonts other than the map's (those of a vector basemap's style) */\n private readonly sources = new Map<string, string>();\n private engine: Engine | undefined;\n /** Rows of each page changed since the last upload: first, end */\n private readonly dirty = new Map<number, [number, number]>();\n /** The atlas has its most pages: new glyphs stay blank */\n private full = false;\n /** Largest side of a page */\n private readonly maxSize: number;\n /** Bumped each time glyphs are added: labels shaped while some of theirs were missing are shaped again */\n version = 0;\n\n /** `maxSize`: the GPU's texture size limit if known (the pages are at most 2048 × 2048) */\n constructor(\n private readonly url = GLYPHS_URL,\n maxSize = 4096,\n ) {\n this.maxSize = Math.max(512, Math.min(PAGE_MAX, maxSize));\n }\n\n /** Sends the whole atlas to an engine (a new one after a context loss) */\n attach(engine: Engine): void {\n this.engine = engine;\n this.dirty.clear();\n this.upload();\n }\n\n /** Side of the pages of the atlas */\n get atlasSize(): number {\n return this.size;\n }\n\n get pageCount(): number {\n return this.pages.length;\n }\n\n /** Loads these fonts from another glyph URL (a style's `glyphs`); a font keeps the first URL given for it */\n register(url: string, fonts: Iterable<string>): void {\n [...fonts].forEach((font) => {\n if (!this.sources.has(font)) this.sources.set(font, url);\n });\n }\n\n /** Loads the glyphs of these code points in a font */\n async load(font: string, codes: Iterable<number>): Promise<Map<number, Glyph>> {\n const glyphs = this.fonts.get(font) ?? new Map<number, Glyph>();\n\n this.fonts.set(font, glyphs);\n\n const starts = new Set([...codes].filter((code) => !glyphs.has(code)).map((code) => Math.floor(code / 256) * 256));\n\n await Promise.all([...starts].map((start) => this.range(font, start, glyphs)));\n\n return glyphs;\n }\n\n private range(font: string, start: number, glyphs: Map<number, Glyph>): Promise<void> {\n const key = `${font}/${start}`;\n const cached = this.ranges.get(key);\n\n if (cached) return cached;\n\n const url = (this.sources.get(font) ?? this.url)\n .replace('{fontstack}', encodeURIComponent(font))\n .replace('{range}', `${start}-${start + 255}`);\n const pending = fetch(url, withHeaders(url))\n .then((r) => (r.ok ? r.arrayBuffer() : Promise.reject(new Error(`${url}: ${r.status}`))))\n .then((buffer) => {\n parse(buffer).forEach(({ glyph, bitmap }, id) => {\n if (glyph.width > 0 && bitmap.length >= (glyph.width + 2 * BUFFER) * (glyph.height + 2 * BUFFER)) {\n this.pack(glyph, bitmap);\n }\n glyphs.set(id, glyph);\n });\n this.version += 1;\n // One upload for the range\n this.flush();\n })\n .catch((error: unknown) => {\n // A missing range is not retried this session; its characters stay blank\n console.warn('isard: glyphs', error);\n });\n\n this.ranges.set(key, pending);\n\n return pending;\n }\n\n /**\n * Allocates the pages in the engine and sends what they hold (their rows with glyphs). The engine allocates its\n * pages again empty: everything is sent each time, the pages doubled to make it rare\n */\n private upload(): void {\n const engine = this.engine;\n\n if (!engine) return;\n engine.setGlyphPages(this.size, this.size, this.capacity);\n this.pages.forEach((page, i) => {\n const rows = this.used[i] ?? 0;\n\n if (rows > 0) engine.updateGlyphPage(i, 0, 0, this.size, rows, page.subarray(0, rows * this.size));\n });\n }\n\n /** Sends the rows changed since the last upload to the engine */\n private flush(): void {\n this.dirty.forEach(([y0, y1], page) => {\n const data = this.pages[page];\n\n if (data)\n this.engine?.updateGlyphPage(page, 0, y0, this.size, y1 - y0, data.subarray(y0 * this.size, y1 * this.size));\n });\n this.dirty.clear();\n }\n\n /**\n * Places a bitmap in the atlas (growing the first page, then adding pages when full); `flush` sends it to the\n * engine\n */\n private pack(glyph: Glyph, bitmap: Uint8Array): void {\n const w = glyph.width + 2 * BUFFER;\n const h = glyph.height + 2 * BUFFER;\n // One texel of padding between bitmaps: linear filtering never reads a neighbour\n let shelf = this.shelves.find((s) => s.height >= h && s.height <= h + 4 && s.x + w + 1 <= this.size);\n\n if (!shelf) {\n const page = this.pages.length - 1;\n // New shelves go on the last page only: the last shelf is on it, unless the page is new\n const last = this.shelves.at(-1);\n const y = last && last.page === page ? last.y + last.height + 1 : 0;\n\n if (y + h > this.size) {\n if (this.pages.length === 1 && this.size * 2 <= this.maxSize) this.grow();\n else if (this.pages.length < MAX_PAGES) this.addPage();\n else {\n // Full: the glyph takes its room in the text but is not drawn\n if (!this.full) console.warn(`isard: the glyph atlas is full (${MAX_PAGES} pages)`);\n this.full = true;\n\n return;\n }\n this.pack(glyph, bitmap);\n\n return;\n }\n shelf = { page, y, height: h, x: 0 };\n this.shelves.push(shelf);\n }\n\n const data = this.pages[shelf.page];\n\n if (!data) return;\n glyph.x = shelf.x;\n glyph.y = shelf.page * this.size + shelf.y;\n glyph.page = shelf.page;\n shelf.x += w + 1;\n for (let row = 0; row < h; row += 1) {\n data.set(bitmap.subarray(row * w, row * w + w), (shelf.y + row) * this.size + glyph.x);\n }\n this.used[shelf.page] = Math.max(this.used[shelf.page] ?? 0, shelf.y + h);\n\n const dirty = this.dirty.get(shelf.page);\n\n this.dirty.set(shelf.page, [Math.min(dirty?.[0] ?? shelf.y, shelf.y), Math.max(dirty?.[1] ?? 0, shelf.y + h)]);\n }\n\n /** Doubles the only page; the glyphs keep their places (texel coordinates) */\n private grow(): void {\n const size = this.size * 2;\n const old = this.pages[0] ?? new Uint8Array(this.size * this.size);\n const page = new Uint8Array(size * size);\n\n for (let row = 0; row < this.size; row += 1) {\n page.set(old.subarray(row * this.size, (row + 1) * this.size), row * size);\n }\n this.size = size;\n this.pages = [page];\n // The whole atlas is sent with what it holds so far\n this.dirty.clear();\n this.upload();\n }\n\n /** A new empty page, after the others; the engine's pages are allocated again only past its capacity */\n private addPage(): void {\n this.pages.push(new Uint8Array(this.size * this.size));\n this.used.push(0);\n if (this.pages.length > this.capacity) {\n this.capacity = Math.min(MAX_PAGES, this.capacity * 2);\n // The pages are allocated again: everything is sent, pending changes included\n this.dirty.clear();\n this.upload();\n }\n }\n}\n\n/** A run of text with its own scale (MapLibre's `format` with `font-scale`) and font */\nexport interface TextPart {\n text: string;\n scale?: number;\n font?: string;\n}\n\nexport type { Anchor } from '../ui/overlay.ts';\n\nexport interface Shaping {\n /** Glyph quads: x, y, width, height (CSS pixels from the anchor), atlas u0, v0, u1, v1, font scale */\n quads: number[][];\n /** Ink box from the anchor: min x, min y, max x, max y */\n box: [number, number, number, number];\n /** Layout box from the anchor, what an icon fitted to the text frames: the advances of its widest line across, its\n * lines' height (`lineHeight` each) down, centered on the ink */\n layout: [number, number, number, number];\n}\n\n/** Code points of a text, for loading */\nexport const codes = (parts: readonly TextPart[]): Set<number> => {\n return new Set(parts.flatMap((p) => [...p.text].map((ch) => ch.codePointAt(0) ?? 32)));\n};\n\n/**\n * Lays out a label: lines split at `\\n` and wrapped at `maxWidth` ems, centered, the block placed by `anchor` around\n * the anchor point and moved by `offset` (ems); `size` in CSS pixels. Glyphs not loaded take no room.\n */\nexport const shape = (\n parts: readonly TextPart[],\n glyphsOf: (font: string) => Map<number, Glyph> | undefined,\n options: {\n font: string;\n size: number;\n maxWidth: number;\n lineHeight: number;\n anchor: Anchor;\n offset: [number, number];\n },\n): Shaping => {\n const { size, maxWidth, lineHeight, anchor, offset } = options;\n const k = size / EM;\n\n // Characters with their glyph and scale, split into lines\n type Char = { glyph: Glyph | undefined; scale: number; space: boolean };\n\n const lines: Char[][] = [[]];\n\n for (const part of parts) {\n const glyphs = glyphsOf(part.font ?? options.font);\n\n for (const ch of part.text) {\n if (ch === '\\n') {\n lines.push([]);\n continue;\n }\n\n const code = ch.codePointAt(0) ?? 32;\n\n lines.at(-1)?.push({ glyph: glyphs?.get(code), scale: part.scale ?? 1, space: /\\s/.test(ch) });\n }\n }\n\n const advance = (c: Char) => (c.glyph?.advance ?? (c.space ? EM / 4 : 0)) * c.scale;\n // Wrapping at spaces, greedy\n const limit = maxWidth * EM;\n const wrapped: Char[][] = [];\n\n for (const line of lines) {\n let current: Char[] = [];\n let width = 0;\n let lastSpace = -1;\n\n for (const c of line) {\n current.push(c);\n width += advance(c);\n if (c.space) lastSpace = current.length - 1;\n if (width > limit && lastSpace > 0) {\n wrapped.push(current.slice(0, lastSpace));\n current = current.slice(lastSpace + 1);\n width = current.reduce((s, x) => s + advance(x), 0);\n lastSpace = -1;\n }\n }\n wrapped.push(current);\n }\n\n // Glyphs on their lines, each line centered on x = 0, in units of the 24 px font\n const quads: number[][] = [];\n let [x0, y0, x1, y1] = [\n Number.POSITIVE_INFINITY,\n Number.POSITIVE_INFINITY,\n Number.NEGATIVE_INFINITY,\n Number.NEGATIVE_INFINITY,\n ];\n let baseline = 0;\n let widest = 0;\n let height = 0;\n\n wrapped.forEach((line, i) => {\n const scale = Math.max(1, ...line.map((c) => c.scale));\n\n if (i > 0) baseline += lineHeight * EM * scale;\n height += lineHeight * EM * scale;\n\n const width = line.reduce((s, c) => s + advance(c), 0);\n\n widest = Math.max(widest, width);\n\n let pen = -width / 2;\n\n for (const c of line) {\n const g = c.glyph;\n\n if (g && g.x !== undefined && g.y !== undefined && g.width > 0) {\n const qx = pen + (g.left - BUFFER) * c.scale;\n const qy = baseline - (g.top + BUFFER) * c.scale;\n const qw = (g.width + 2 * BUFFER) * c.scale;\n const qh = (g.height + 2 * BUFFER) * c.scale;\n\n quads.push([qx, qy, qw, qh, g.x, g.y, g.x + g.width + 2 * BUFFER, g.y + g.height + 2 * BUFFER, c.scale]);\n x0 = Math.min(x0, qx + BUFFER * c.scale);\n y0 = Math.min(y0, qy + BUFFER * c.scale);\n x1 = Math.max(x1, qx + qw - BUFFER * c.scale);\n y1 = Math.max(y1, qy + qh - BUFFER * c.scale);\n }\n pen += advance(c);\n }\n });\n if (!quads.length) return { quads, box: [0, 0, 0, 0], layout: [0, 0, 0, 0] };\n\n // The block placed around the anchor by its ink box\n // The side of the box at the anchor: its start, its end, or its middle\n const side = (start: boolean, end: boolean, lo: number, hi: number) => {\n if (start) return -lo;\n if (end) return -hi;\n\n return -(lo + hi) / 2;\n };\n const horizontal = side(anchor.includes('left'), anchor.includes('right'), x0, x1);\n const vertical = side(anchor.startsWith('top'), anchor.startsWith('bottom'), y0, y1);\n const dx = horizontal + offset[0] * EM;\n const dy = vertical + offset[1] * EM;\n\n for (const q of quads) {\n q[0] = ((q[0] ?? 0) + dx) * k;\n q[1] = ((q[1] ?? 0) + dy) * k;\n q[2] = (q[2] ?? 0) * k;\n q[3] = (q[3] ?? 0) * k;\n q[8] = (q[8] ?? 1) * k;\n }\n\n const middle = (y0 + y1) / 2 + dy;\n\n height = Math.max(height, y1 - y0);\n\n return {\n quads,\n box: [(x0 + dx) * k, (y0 + dy) * k, (x1 + dx) * k, (y1 + dy) * k],\n layout: [(dx - widest / 2) * k, (middle - height / 2) * k, (dx + widest / 2) * k, (middle + height / 2) * k],\n };\n};\n"]}
@@ -51,12 +51,12 @@ export interface SpriteSource {
51
51
  url: string;
52
52
  }
53
53
  /** The sprites of a style's `sprite`: one URL, or several with their ids (MapLibre's style specification) */
54
- export declare function spriteSources(sprite: string | readonly SpriteSource[] | undefined): SpriteSource[];
54
+ export declare const spriteSources: (sprite: string | readonly SpriteSource[] | undefined) => SpriteSource[];
55
55
  /** The name of an image of a sprite in the style: its own in the `default` sprite, `id:name` in another */
56
- export declare function spriteName(id: string, name: string): string;
56
+ export declare const spriteName: (id: string, name: string) => string;
57
57
  /** The URL of a sprite's index or sheet: `.json` or `.png`, `@2x` before it for high-density screens, before the
58
58
  * query of the URL if it has one */
59
- export declare function spriteFile(url: string, extension: 'json' | 'png', ratio: number): string;
59
+ export declare const spriteFile: (url: string, extension: "json" | "png", ratio: number) => string;
60
60
  /** A sprite loaded: its images by name (with the sprite's prefix) and its sheet */
61
61
  export interface LoadedSprite {
62
62
  icons: SpriteIndex;
@@ -64,12 +64,12 @@ export interface LoadedSprite {
64
64
  }
65
65
  /** Loads a style's sprites (`@2x` above a device pixel ratio of 1, the 1x ones if a server has none); the sprites
66
66
  * that fail are left out */
67
- export declare function loadSprites(sprite: string | readonly SpriteSource[] | undefined, ratio?: number): Promise<LoadedSprite[]>;
67
+ export declare const loadSprites: (sprite: string | readonly SpriteSource[] | undefined, ratio?: number) => Promise<LoadedSprite[]>;
68
68
  /** The pixels of an image (read back through a canvas) */
69
- export declare function readPixels(image: CanvasImageSource & {
69
+ export declare const readPixels: (image: CanvasImageSource & {
70
70
  width: number;
71
71
  height: number;
72
- }): Pixels | undefined;
72
+ }) => Pixels | undefined;
73
73
  /** The icons of a map and their atlas: a square that doubles as it fills, up to the texture size limit */
74
74
  export declare class Icons {
75
75
  private size;
@@ -140,7 +140,7 @@ type Pieces = [number, number, number, number][];
140
140
  * stretchable zones (the whole image by default) taking the room the fixed parts (at `scale` CSS pixels per image
141
141
  * pixel) leave
142
142
  */
143
- export declare function stretch(length: number, zones: readonly [number, number][] | undefined, content: [number, number] | undefined, lo: number, hi: number, scale: number): Pieces;
143
+ export declare const stretch: (length: number, zones: readonly [number, number][] | undefined, content: [number, number] | undefined, lo: number, hi: number, scale: number) => Pieces;
144
144
  /** Lays an icon out around its anchor: placed by its anchor and offset, or fitted to its text */
145
- export declare function layoutIcon(icon: Icon, options: IconLayoutOptions): IconLayout;
145
+ export declare const layoutIcon: (icon: Icon, options: IconLayoutOptions) => IconLayout;
146
146
  export {};
@@ -6,26 +6,36 @@
6
6
  * the stretchable zones and the content box of its image when it has them (`stretchX`, `stretchY`, `content`).
7
7
  */
8
8
  import { withHeaders } from "../engine/requests.js";
9
+ import { isNumbers, isRecord } from "../util/guards.js";
10
+ const isPairs = (value) => Array.isArray(value) && value.every((pair) => isNumbers(pair) && pair.length === 2);
11
+ /** An icon of a sprite index: its place, and what is drawn from the rest */
12
+ const isSpriteIcon = (value) => isRecord(value) &&
13
+ [value.x, value.y, value.width, value.height].every((v) => typeof v === 'number') &&
14
+ (value.pixelRatio === undefined || typeof value.pixelRatio === 'number') &&
15
+ (value.sdf === undefined || typeof value.sdf === 'boolean') &&
16
+ (value.stretchX === undefined || isPairs(value.stretchX)) &&
17
+ (value.stretchY === undefined || isPairs(value.stretchY)) &&
18
+ (value.content === undefined || (isNumbers(value.content) && value.content.length === 4));
9
19
  /** The sprites of a style's `sprite`: one URL, or several with their ids (MapLibre's style specification) */
10
- export function spriteSources(sprite) {
20
+ export const spriteSources = (sprite) => {
11
21
  if (typeof sprite === 'string')
12
22
  return sprite ? [{ id: 'default', url: sprite }] : [];
13
23
  return Array.isArray(sprite) ? sprite.filter((s) => typeof s?.url === 'string' && typeof s.id === 'string') : [];
14
- }
24
+ };
15
25
  /** The name of an image of a sprite in the style: its own in the `default` sprite, `id:name` in another */
16
- export function spriteName(id, name) {
26
+ export const spriteName = (id, name) => {
17
27
  return id === 'default' ? name : `${id}:${name}`;
18
- }
28
+ };
19
29
  /** The URL of a sprite's index or sheet: `.json` or `.png`, `@2x` before it for high-density screens, before the
20
30
  * query of the URL if it has one */
21
- export function spriteFile(url, extension, ratio) {
31
+ export const spriteFile = (url, extension, ratio) => {
22
32
  const suffix = `${ratio > 1 ? '@2x' : ''}.${extension}`;
23
33
  const query = url.search(/[?#]/);
24
34
  return query < 0 ? `${url}${suffix}` : `${url.slice(0, query)}${suffix}${url.slice(query)}`;
25
- }
35
+ };
26
36
  /** Loads a style's sprites (`@2x` above a device pixel ratio of 1, the 1x ones if a server has none); the sprites
27
37
  * that fail are left out */
28
- export async function loadSprites(sprite, ratio = typeof devicePixelRatio === 'number' ? devicePixelRatio : 1) {
38
+ export const loadSprites = async (sprite, ratio = typeof devicePixelRatio === 'number' ? devicePixelRatio : 1) => {
29
39
  const one = async ({ id, url }, r) => {
30
40
  const [json, png] = await Promise.all([
31
41
  fetch(spriteFile(url, 'json', r), withHeaders(spriteFile(url, 'json', r))),
@@ -33,29 +43,28 @@ export async function loadSprites(sprite, ratio = typeof devicePixelRatio === 'n
33
43
  ]);
34
44
  if (!json.ok || !png.ok)
35
45
  return r > 1 ? one({ id, url }, 1) : undefined;
36
- const index = (await json.json());
37
- const icons = {};
38
- for (const [name, icon] of Object.entries(index))
39
- icons[spriteName(id, name)] = icon;
46
+ const index = await json.json();
47
+ if (!isRecord(index))
48
+ return r > 1 ? one({ id, url }, 1) : undefined;
49
+ const icons = Object.fromEntries(Object.entries(index).flatMap(([name, icon]) => (isSpriteIcon(icon) ? [[spriteName(id, name), icon]] : [])));
40
50
  return { icons, image: await createImageBitmap(await png.blob()) };
41
51
  };
42
52
  const loaded = await Promise.all(spriteSources(sprite).map((s) => one(s, ratio).catch(() => undefined)));
43
53
  return loaded.filter((s) => s !== undefined);
44
- }
54
+ };
45
55
  /** The pixels of an image (read back through a canvas) */
46
- export function readPixels(image) {
56
+ export const readPixels = (image) => {
47
57
  const { width, height } = image;
48
58
  if (!(width > 0 && height > 0))
49
59
  return undefined;
50
- const canvas = typeof OffscreenCanvas === 'function'
51
- ? new OffscreenCanvas(width, height)
52
- : Object.assign(document.createElement('canvas'), { width, height });
53
- const g = canvas.getContext('2d');
60
+ const g = typeof OffscreenCanvas === 'function'
61
+ ? new OffscreenCanvas(width, height).getContext('2d')
62
+ : Object.assign(document.createElement('canvas'), { width, height }).getContext('2d');
54
63
  if (!g)
55
64
  return undefined;
56
65
  g.drawImage(image, 0, 0);
57
66
  return g.getImageData(0, 0, width, height);
58
- }
67
+ };
59
68
  /** The icons of a map and their atlas: a square that doubles as it fills, up to the texture size limit */
60
69
  export class Icons {
61
70
  size = 256;
@@ -100,12 +109,12 @@ export class Icons {
100
109
  }
101
110
  return pixels;
102
111
  };
103
- for (const [name, icon] of Object.entries(index)) {
112
+ Object.entries(index).forEach(([name, icon]) => {
104
113
  if (!icon || typeof icon !== 'object')
105
- continue;
114
+ return;
106
115
  const { x, y, width, height, ...options } = icon;
107
116
  this.define(`${prefix}${name}`, { pixels: once, x, y, width, height, options }, false);
108
- }
117
+ });
109
118
  this.version += 1;
110
119
  }
111
120
  define(name, source, bump = true) {
@@ -120,12 +129,12 @@ export class Icons {
120
129
  }
121
130
  /** Forgets an image, or every image whose name starts with `prefix` (a sprite's) */
122
131
  remove(name, prefix = false) {
123
- for (const key of [...this.sources.keys()]) {
124
- if (prefix ? key.startsWith(name) : key === name) {
125
- this.sources.delete(key);
126
- this.packed.delete(key);
127
- }
128
- }
132
+ [...this.sources.keys()]
133
+ .filter((key) => (prefix ? key.startsWith(name) : key === name))
134
+ .forEach((key) => {
135
+ this.sources.delete(key);
136
+ this.packed.delete(key);
137
+ });
129
138
  this.version += 1;
130
139
  }
131
140
  /** The icon of this name, packed into the atlas on first use; undefined if there is none (`flush` uploads it) */
@@ -237,9 +246,10 @@ export class Icons {
237
246
  * stretchable zones (the whole image by default) taking the room the fixed parts (at `scale` CSS pixels per image
238
247
  * pixel) leave
239
248
  */
240
- export function stretch(length, zones, content, lo, hi, scale) {
249
+ export const stretch = (length, zones, content, lo, hi, scale) => {
241
250
  const clamp = (v) => Math.max(0, Math.min(length, Number(v) || 0));
242
- const spans = (zones?.length ? zones : [[0, length]])
251
+ const whole = [[0, length]];
252
+ const spans = (zones?.length ? zones : whole)
243
253
  .map(([a, b]) => [clamp(Math.min(a, b)), clamp(Math.max(a, b))])
244
254
  .filter(([a, b]) => b > a);
245
255
  const cuts = [...new Set([0, length, ...spans.flat()])].sort((a, b) => a - b);
@@ -257,47 +267,44 @@ export function stretch(length, zones, content, lo, hi, scale) {
257
267
  const at = (x) => pieces.reduce((n, [a, b, s]) => n + Math.max(0, Math.min(x, b) - a) * (s ? k : scale), 0);
258
268
  const origin = lo - at(c0);
259
269
  return pieces.map(([a, b]) => [a, b, origin + at(a), origin + at(b)]);
260
- }
270
+ };
261
271
  /** Where an anchor's side lies along an axis of the icon: at its start 0, at its end 1, else the middle */
262
- function align(start, end) {
272
+ const align = (start, end) => {
263
273
  if (start)
264
274
  return 0;
265
275
  return end ? 1 : 0.5;
266
- }
276
+ };
267
277
  /** Lays an icon out around its anchor: placed by its anchor and offset, or fitted to its text */
268
- export function layoutIcon(icon, options) {
278
+ export const layoutIcon = (icon, options) => {
269
279
  const { size, anchor, offset, rotate, fit, padding, text } = options;
270
280
  const { width: w, height: h, pixelRatio } = icon;
271
- let xs;
272
- let ys;
273
- if (fit !== 'none' && text) {
274
- const [top, right, bottom, left] = padding;
275
- const [x0, y0, x1, y1] = [text[0] - left, text[1] - top, text[2] + right, text[3] + bottom];
276
- // The fixed parts at the image's own size; an axis not fitted at the icon's size, centered on the text
277
- const own = 1 / pixelRatio;
278
- const scaled = size / pixelRatio;
279
- const centered = (length, lo, hi) => {
280
- const c = (lo + hi) / 2;
281
- return [[0, length, c - (length * scaled) / 2, c + (length * scaled) / 2]];
282
- };
283
- const content = icon.content;
284
- xs =
285
- fit === 'height'
286
- ? centered(w, x0, x1)
287
- : stretch(w, icon.stretchX, content && [content[0], content[2]], x0, x1, own);
288
- ys =
289
- fit === 'width'
290
- ? centered(h, y0, y1)
291
- : stretch(h, icon.stretchY, content && [content[1], content[3]], y0, y1, own);
292
- }
293
- else {
281
+ const [xs, ys] = (() => {
282
+ if (fit !== 'none' && text) {
283
+ const [top, right, bottom, left] = padding;
284
+ const [x0, y0, x1, y1] = [text[0] - left, text[1] - top, text[2] + right, text[3] + bottom];
285
+ // The fixed parts at the image's own size; an axis not fitted at the icon's size, centered on the text
286
+ const own = 1 / pixelRatio;
287
+ const scaled = size / pixelRatio;
288
+ const centered = (length, lo, hi) => {
289
+ const c = (lo + hi) / 2;
290
+ return [[0, length, c - (length * scaled) / 2, c + (length * scaled) / 2]];
291
+ };
292
+ const content = icon.content;
293
+ return [
294
+ fit === 'height'
295
+ ? centered(w, x0, x1)
296
+ : stretch(w, icon.stretchX, content && [content[0], content[2]], x0, x1, own),
297
+ fit === 'width'
298
+ ? centered(h, y0, y1)
299
+ : stretch(h, icon.stretchY, content && [content[1], content[3]], y0, y1, own),
300
+ ];
301
+ }
294
302
  const [dw, dh] = [(w / pixelRatio) * size, (h / pixelRatio) * size];
295
303
  const ax = align(anchor.includes('left'), anchor.includes('right'));
296
304
  const ay = align(anchor.startsWith('top'), anchor.startsWith('bottom'));
297
305
  const [left, top] = [offset[0] * size - dw * ax, offset[1] * size - dh * ay];
298
- xs = [[0, w, left, left + dw]];
299
- ys = [[0, h, top, top + dh]];
300
- }
306
+ return [[[0, w, left, left + dw]], [[0, h, top, top + dh]]];
307
+ })();
301
308
  const angle = ((Number(rotate) || 0) * Math.PI) / 180;
302
309
  const kind = icon.sdf ? -2 : -1;
303
310
  const quads = [];
@@ -308,10 +315,10 @@ export function layoutIcon(icon, options) {
308
315
  Number.NEGATIVE_INFINITY,
309
316
  Number.NEGATIVE_INFINITY,
310
317
  ];
311
- for (const [v0, v1, top, bottom] of ys) {
312
- for (const [u0, u1, left, right] of xs) {
318
+ ys.forEach(([v0, v1, top, bottom]) => {
319
+ xs.forEach(([u0, u1, left, right]) => {
313
320
  if (right <= left || bottom <= top)
314
- continue;
321
+ return;
315
322
  quads.push([
316
323
  left,
317
324
  top,
@@ -325,20 +332,21 @@ export function layoutIcon(icon, options) {
325
332
  angle,
326
333
  ]);
327
334
  // The box of the turned corners
328
- for (const [px, py] of [
335
+ const corners = [
329
336
  [left, top],
330
337
  [right, top],
331
338
  [left, bottom],
332
339
  [right, bottom],
333
- ]) {
340
+ ];
341
+ corners.forEach(([px, py]) => {
334
342
  const [rx, ry] = [px * cs - py * sn, px * sn + py * cs];
335
343
  box[0] = Math.min(box[0], rx);
336
344
  box[1] = Math.min(box[1], ry);
337
345
  box[2] = Math.max(box[2], rx);
338
346
  box[3] = Math.max(box[3], ry);
339
- }
340
- }
341
- }
347
+ });
348
+ });
349
+ });
342
350
  return { quads, box: quads.length ? box : [0, 0, 0, 0] };
343
- }
351
+ };
344
352
  //# sourceMappingURL=icons.js.map