@tangram.gl/tangram-renderer 0.0.0-stage → 0.0.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 (321) hide show
  1. package/README.md +59 -2
  2. package/dist/core.js +36923 -0
  3. package/dist/core.js.map +6 -0
  4. package/dist/index.js +32 -0
  5. package/dist/loaders-gl-worker.js +82 -0
  6. package/dist/loaders-gl-worker.js.map +6 -0
  7. package/dist/map-logic.js +2 -0
  8. package/dist/map-logic.js.map +6 -0
  9. package/dist/projected-basemaps-worker.js +3 -0
  10. package/dist/projected-basemaps-worker.js.map +6 -0
  11. package/dist/shader-modules.js +141 -0
  12. package/dist/shader-modules.js.map +6 -0
  13. package/dist/style-schema.js +126 -0
  14. package/dist/style-schema.js.map +6 -0
  15. package/dist/tangram-style.schema.json +882 -0
  16. package/dist/tangram.debug.mjs +37139 -0
  17. package/dist/tangram.debug.mjs.map +6 -0
  18. package/dist/tangram.min.mjs +4950 -0
  19. package/dist/types/builders/earcut.d.ts +15 -0
  20. package/dist/types/core.d.ts +29 -0
  21. package/dist/types/gl/constants.d.ts +2 -0
  22. package/dist/types/gl/globe_mesh.d.ts +48 -0
  23. package/dist/types/gl/glsl.d.ts +17 -0
  24. package/dist/types/gl/vertex-constants.d.ts +4 -0
  25. package/dist/types/gl/vertex-types.d.ts +34 -0
  26. package/dist/types/gl/vertex_data.d.ts +32 -0
  27. package/dist/types/gl/vertex_elements.d.ts +8 -0
  28. package/dist/types/gl/vertex_layout.d.ts +32 -0
  29. package/dist/types/glsl.d.ts +14 -0
  30. package/dist/types/gpu/luma_device_renderer.d.ts +66 -0
  31. package/dist/types/gpu/resource_lifecycle.d.ts +4 -0
  32. package/dist/types/gpu/tangram_gpu_backend.d.ts +151 -0
  33. package/dist/types/index.d.ts +155 -0
  34. package/dist/types/lights/light-definitions.d.ts +121 -0
  35. package/dist/types/map-logic/draped-terrain-bounds.d.ts +41 -0
  36. package/dist/types/map-logic/globe-terrain-preparation.d.ts +85 -0
  37. package/dist/types/map-logic/globe-terrain.d.ts +54 -0
  38. package/dist/types/map-logic/index.d.ts +33 -0
  39. package/dist/types/map-logic/label-identity.d.ts +22 -0
  40. package/dist/types/map-logic/label-placement.d.ts +32 -0
  41. package/dist/types/map-logic/screen-bounds.d.ts +15 -0
  42. package/dist/types/map-logic/terrain-data.d.ts +55 -0
  43. package/dist/types/map-logic/terrain-error.d.ts +51 -0
  44. package/dist/types/map-logic/terrain-ground-topology.d.ts +26 -0
  45. package/dist/types/map-logic/terrain-height-field.d.ts +59 -0
  46. package/dist/types/map-logic/terrain-navigation.d.ts +27 -0
  47. package/dist/types/map-logic/terrain-neighborhood.d.ts +5 -0
  48. package/dist/types/map-logic/terrain-query.d.ts +33 -0
  49. package/dist/types/map-logic/terrain-resource-budget.d.ts +51 -0
  50. package/dist/types/map-logic/terrain-transition-topology.d.ts +23 -0
  51. package/dist/types/map-logic/tile-build-queue.d.ts +51 -0
  52. package/dist/types/map-logic/tile-cache-policy.d.ts +46 -0
  53. package/dist/types/map-logic/tile-residency.d.ts +17 -0
  54. package/dist/types/map-logic/triangle-query-index.d.ts +87 -0
  55. package/dist/types/procedures/js-yaml.d.ts +15 -0
  56. package/dist/types/procedures/mesh-projector.d.ts +107 -0
  57. package/dist/types/procedures/mvt-dependencies.d.ts +20 -0
  58. package/dist/types/procedures/projected-coordinate-transform.d.ts +27 -0
  59. package/dist/types/procedures/projection-batch-executor.d.ts +53 -0
  60. package/dist/types/procedures/scene-yaml-legacy.d.ts +6 -0
  61. package/dist/types/procedures/terrain-draping.d.ts +165 -0
  62. package/dist/types/procedures/terrain-globe.d.ts +6 -0
  63. package/dist/types/procedures/terrain-styled-topology.d.ts +34 -0
  64. package/dist/types/procedures/web-mercator-legacy.d.ts +4 -0
  65. package/dist/types/procedures/web-mercator-math.d.ts +4 -0
  66. package/dist/types/scene/globals.d.ts +11 -0
  67. package/dist/types/scene/ground_footprint.d.ts +16 -0
  68. package/dist/types/scene/host_frame.d.ts +54 -0
  69. package/dist/types/scene/projection_math.d.ts +52 -0
  70. package/dist/types/scene/scene-resource-types.d.ts +177 -0
  71. package/dist/types/scene/scene_bundle.d.ts +69 -0
  72. package/dist/types/scene/visibility_adapter.d.ts +106 -0
  73. package/dist/types/selection/draped-terrain-surface.d.ts +78 -0
  74. package/dist/types/selection/terrain_surface.d.ts +149 -0
  75. package/dist/types/shader-modules/globe-horizon.d.ts +15 -0
  76. package/dist/types/shader-modules/height-decode.d.ts +13 -0
  77. package/dist/types/shader-modules/hillshade.d.ts +13 -0
  78. package/dist/types/shader-modules/index.d.ts +6 -0
  79. package/dist/types/shader-modules/planar.d.ts +12 -0
  80. package/dist/types/shader-modules/sphere-map.d.ts +13 -0
  81. package/dist/types/shader-modules/triplanar.d.ts +15 -0
  82. package/dist/types/sources/decoded_tile_store.d.ts +95 -0
  83. package/dist/types/sources/tile_source_metadata.d.ts +32 -0
  84. package/dist/types/styles/text/fontfaceobserver.d.ts +10 -0
  85. package/dist/types/tile/tile_id.d.ts +37 -0
  86. package/dist/types/tile/tile_traversal_adapter.d.ts +63 -0
  87. package/dist/types/types.d.ts +293 -0
  88. package/dist/types/utils/geo.d.ts +57 -0
  89. package/dist/types/utils/hash.d.ts +1 -0
  90. package/dist/types/utils/log.d.ts +27 -0
  91. package/dist/types/utils/props.d.ts +6 -0
  92. package/dist/types/utils/subscribe.d.ts +10 -0
  93. package/dist/types/utils/thread.d.ts +6 -0
  94. package/dist/types/utils/urls.d.ts +26 -0
  95. package/dist/types/utils/utils.d.ts +26 -0
  96. package/dist/types/utils/version.d.ts +2 -0
  97. package/dist/types/utils/worker-types.d.ts +68 -0
  98. package/dist/types/utils/worker_broker.d.ts +3 -0
  99. package/package.json +103 -3
  100. package/src/builders/common.ts +41 -0
  101. package/src/builders/earcut.d.ts +15 -0
  102. package/src/builders/geometry-types.ts +60 -0
  103. package/src/builders/points.ts +115 -0
  104. package/src/builders/polygons.ts +225 -0
  105. package/src/builders/polylines.ts +682 -0
  106. package/src/builders/wireframe.ts +31 -0
  107. package/src/core.d.ts +29 -0
  108. package/src/core.ts +33 -0
  109. package/src/experimental/loaders-gl-worker.ts +19 -0
  110. package/src/experimental/projected-basemaps-worker.ts +13 -0
  111. package/src/experimental/projected-mesh-cache.ts +137 -0
  112. package/src/experimental/projected-mesh-domain.ts +110 -0
  113. package/src/experimental/projected-mesh-refinement.ts +193 -0
  114. package/src/experimental/projected-mesh.ts +399 -0
  115. package/src/experimental/projected-normal.ts +26 -0
  116. package/src/experimental/projected-symbol-mesh.ts +74 -0
  117. package/src/gl/constants.ts +18 -0
  118. package/src/gl/context.ts +103 -0
  119. package/src/gl/extensions.ts +30 -0
  120. package/src/gl/globe_mesh.ts +285 -0
  121. package/src/gl/glsl.ts +257 -0
  122. package/src/gl/mesh-types.ts +56 -0
  123. package/src/gl/render_state.ts +111 -0
  124. package/src/gl/shader_program.ts +1310 -0
  125. package/src/gl/texture.ts +814 -0
  126. package/src/gl/uniform_buffer.ts +340 -0
  127. package/src/gl/vao.ts +154 -0
  128. package/src/gl/vbo_mesh.ts +349 -0
  129. package/src/gl/vertex-constants.ts +19 -0
  130. package/src/gl/vertex-types.ts +35 -0
  131. package/src/gl/vertex_data.ts +126 -0
  132. package/src/gl/vertex_elements.ts +54 -0
  133. package/src/gl/vertex_layout.ts +241 -0
  134. package/src/glsl.d.ts +14 -0
  135. package/src/gpu/luma_device_renderer.ts +579 -0
  136. package/src/gpu/pixel_readback.ts +51 -0
  137. package/src/gpu/resource_lifecycle.ts +32 -0
  138. package/src/gpu/tangram_gpu_backend.ts +195 -0
  139. package/src/index.d.ts +155 -0
  140. package/src/index.ts +105 -0
  141. package/src/labels/collision-types.ts +94 -0
  142. package/src/labels/collision.ts +273 -0
  143. package/src/labels/collision_grid.ts +61 -0
  144. package/src/labels/intersect.ts +30 -0
  145. package/src/labels/label-types.ts +91 -0
  146. package/src/labels/label.ts +207 -0
  147. package/src/labels/label_line.ts +801 -0
  148. package/src/labels/label_point.ts +131 -0
  149. package/src/labels/main-pass-types.ts +73 -0
  150. package/src/labels/main_pass.ts +221 -0
  151. package/src/labels/point_anchor.ts +100 -0
  152. package/src/labels/point_placement.ts +150 -0
  153. package/src/labels/projected-pass.ts +259 -0
  154. package/src/labels/repeat_group.ts +72 -0
  155. package/src/lights/ambient_light.glsl +18 -0
  156. package/src/lights/directional_light.glsl +39 -0
  157. package/src/lights/geographic-lights.ts +21 -0
  158. package/src/lights/light-definitions.ts +285 -0
  159. package/src/lights/light.ts +590 -0
  160. package/src/lights/lighting-uniforms.ts +80 -0
  161. package/src/lights/lighting-wgsl.ts +116 -0
  162. package/src/lights/material.glsl +237 -0
  163. package/src/lights/material.ts +145 -0
  164. package/src/lights/native-falloff.ts +37 -0
  165. package/src/lights/point_light.glsl +96 -0
  166. package/src/lights/spot_light.glsl +111 -0
  167. package/src/map-logic/draped-terrain-bounds.ts +71 -0
  168. package/src/map-logic/globe-terrain-preparation.ts +217 -0
  169. package/src/map-logic/globe-terrain.ts +296 -0
  170. package/src/map-logic/index.ts +37 -0
  171. package/src/map-logic/label-identity.ts +36 -0
  172. package/src/map-logic/label-placement.ts +117 -0
  173. package/src/map-logic/screen-bounds.ts +34 -0
  174. package/src/map-logic/terrain-data.ts +107 -0
  175. package/src/map-logic/terrain-error.ts +134 -0
  176. package/src/map-logic/terrain-ground-topology.ts +164 -0
  177. package/src/map-logic/terrain-height-field.ts +254 -0
  178. package/src/map-logic/terrain-navigation.ts +50 -0
  179. package/src/map-logic/terrain-neighborhood.ts +43 -0
  180. package/src/map-logic/terrain-query.ts +51 -0
  181. package/src/map-logic/terrain-resource-budget.ts +124 -0
  182. package/src/map-logic/terrain-transition-topology.ts +164 -0
  183. package/src/map-logic/tile-build-queue.ts +110 -0
  184. package/src/map-logic/tile-cache-policy.ts +89 -0
  185. package/src/map-logic/tile-residency.ts +50 -0
  186. package/src/map-logic/triangle-query-index.ts +265 -0
  187. package/src/procedures/js-yaml.d.ts +15 -0
  188. package/src/procedures/mesh-projector.ts +191 -0
  189. package/src/procedures/mlt-loaders.ts +55 -0
  190. package/src/procedures/mvt-dependencies.d.ts +20 -0
  191. package/src/procedures/mvt-legacy.ts +150 -0
  192. package/src/procedures/mvt-loaders.ts +53 -0
  193. package/src/procedures/mvt-parser.ts +48 -0
  194. package/src/procedures/mvt-properties.ts +36 -0
  195. package/src/procedures/mvt-tile-provider.ts +72 -0
  196. package/src/procedures/pmtiles-loader.ts +75 -0
  197. package/src/procedures/projected-coordinate-transform.ts +79 -0
  198. package/src/procedures/projection-batch-executor.ts +140 -0
  199. package/src/procedures/scene-yaml-legacy.ts +16 -0
  200. package/src/procedures/scene-yaml-loaders.ts +10 -0
  201. package/src/procedures/terrain-draping.ts +713 -0
  202. package/src/procedures/terrain-globe.ts +32 -0
  203. package/src/procedures/terrain-styled-topology.ts +184 -0
  204. package/src/procedures/web-mercator-legacy.ts +24 -0
  205. package/src/procedures/web-mercator-math.ts +50 -0
  206. package/src/scene/camera.ts +298 -0
  207. package/src/scene/camera_base.ts +116 -0
  208. package/src/scene/classic_scene.ts +20 -0
  209. package/src/scene/external_camera.ts +101 -0
  210. package/src/scene/globals.ts +120 -0
  211. package/src/scene/ground_footprint.ts +139 -0
  212. package/src/scene/host_frame.ts +326 -0
  213. package/src/scene/projected_tile_lod.ts +125 -0
  214. package/src/scene/projection_math.ts +142 -0
  215. package/src/scene/projection_shaders.ts +183 -0
  216. package/src/scene/renderer.ts +516 -0
  217. package/src/scene/scene-resource-types.ts +174 -0
  218. package/src/scene/scene.ts +2378 -0
  219. package/src/scene/scene_bundle.ts +304 -0
  220. package/src/scene/scene_debug.ts +129 -0
  221. package/src/scene/scene_loader.ts +402 -0
  222. package/src/scene/scene_worker.ts +528 -0
  223. package/src/scene/view.ts +683 -0
  224. package/src/scene/visibility_adapter.ts +319 -0
  225. package/src/scene/worker_url.ts +15 -0
  226. package/src/selection/draped-terrain-surface.ts +377 -0
  227. package/src/selection/selection-types.ts +79 -0
  228. package/src/selection/selection.ts +542 -0
  229. package/src/selection/selection_fragment.glsl +18 -0
  230. package/src/selection/selection_globals.glsl +9 -0
  231. package/src/selection/selection_pixels.ts +59 -0
  232. package/src/selection/selection_vertex.glsl +15 -0
  233. package/src/selection/terrain_surface.ts +298 -0
  234. package/src/shader-modules/globe-horizon.ts +52 -0
  235. package/src/shader-modules/height-decode.ts +41 -0
  236. package/src/shader-modules/hillshade.ts +70 -0
  237. package/src/shader-modules/index.ts +10 -0
  238. package/src/shader-modules/planar.ts +24 -0
  239. package/src/shader-modules/sphere-map.ts +38 -0
  240. package/src/shader-modules/triplanar.ts +45 -0
  241. package/src/sources/aligned_tile_source.ts +122 -0
  242. package/src/sources/data_source.ts +655 -0
  243. package/src/sources/decoded_tile_store.ts +245 -0
  244. package/src/sources/geojson.ts +300 -0
  245. package/src/sources/mvt.ts +247 -0
  246. package/src/sources/raster.ts +341 -0
  247. package/src/sources/shared_tile_source_adapter.ts +117 -0
  248. package/src/sources/sources.ts +10 -0
  249. package/src/sources/tile_source_adapter.ts +84 -0
  250. package/src/sources/tile_source_metadata.ts +65 -0
  251. package/src/sources/tile_source_state.ts +112 -0
  252. package/src/sources/topojson.ts +90 -0
  253. package/src/styles/feature_annotations.ts +16 -0
  254. package/src/styles/filter.ts +190 -0
  255. package/src/styles/geometry-style-types.ts +209 -0
  256. package/src/styles/globe_visibility_wgsl.ts +22 -0
  257. package/src/styles/layer-types.ts +45 -0
  258. package/src/styles/layer.ts +586 -0
  259. package/src/styles/lines/dasharray.ts +49 -0
  260. package/src/styles/lines/lines.ts +707 -0
  261. package/src/styles/lines/lines_wgsl.ts +224 -0
  262. package/src/styles/points/point-runtime-types.ts +125 -0
  263. package/src/styles/points/points.ts +1079 -0
  264. package/src/styles/points/points_fragment.glsl +126 -0
  265. package/src/styles/points/points_vertex.glsl +230 -0
  266. package/src/styles/points/points_wgsl.ts +189 -0
  267. package/src/styles/polygons/polygons.ts +268 -0
  268. package/src/styles/polygons/polygons_fragment.glsl +173 -0
  269. package/src/styles/polygons/polygons_vertex.glsl +213 -0
  270. package/src/styles/polygons/polygons_wgsl.ts +127 -0
  271. package/src/styles/property-types.ts +125 -0
  272. package/src/styles/raster/raster.ts +33 -0
  273. package/src/styles/raster/raster_globals.glsl +46 -0
  274. package/src/styles/style-mixing-types.ts +101 -0
  275. package/src/styles/style-runtime-types.ts +220 -0
  276. package/src/styles/style-schema.ts +133 -0
  277. package/src/styles/style.ts +1033 -0
  278. package/src/styles/style_globals.glsl +69 -0
  279. package/src/styles/style_manager.ts +464 -0
  280. package/src/styles/style_parser.ts +620 -0
  281. package/src/styles/text/font_manager.ts +180 -0
  282. package/src/styles/text/fontfaceobserver.d.ts +10 -0
  283. package/src/styles/text/text-types.ts +220 -0
  284. package/src/styles/text/text.ts +378 -0
  285. package/src/styles/text/text_canvas.ts +773 -0
  286. package/src/styles/text/text_labels.ts +436 -0
  287. package/src/styles/text/text_segments.ts +142 -0
  288. package/src/styles/text/text_settings.ts +228 -0
  289. package/src/styles/text/text_wgsl.ts +159 -0
  290. package/src/styles/text/text_wrap.ts +194 -0
  291. package/src/tile/globe_tile_preload.ts +40 -0
  292. package/src/tile/tangram_tileset_2d.ts +108 -0
  293. package/src/tile/tile-build-types.ts +155 -0
  294. package/src/tile/tile.ts +807 -0
  295. package/src/tile/tile_id.ts +172 -0
  296. package/src/tile/tile_manager.ts +889 -0
  297. package/src/tile/tile_pyramid.ts +119 -0
  298. package/src/tile/tile_resource_cache.ts +91 -0
  299. package/src/tile/tile_traversal_adapter.ts +132 -0
  300. package/src/types.ts +332 -0
  301. package/src/utils/debounce.ts +17 -0
  302. package/src/utils/debug_settings.ts +43 -0
  303. package/src/utils/errors.ts +12 -0
  304. package/src/utils/functions.ts +95 -0
  305. package/src/utils/geo.ts +364 -0
  306. package/src/utils/hash.ts +14 -0
  307. package/src/utils/log.ts +108 -0
  308. package/src/utils/media_capture.ts +193 -0
  309. package/src/utils/merge.ts +44 -0
  310. package/src/utils/obb.ts +134 -0
  311. package/src/utils/props.ts +43 -0
  312. package/src/utils/slice.ts +14 -0
  313. package/src/utils/subscribe.ts +58 -0
  314. package/src/utils/task.ts +154 -0
  315. package/src/utils/thread.ts +26 -0
  316. package/src/utils/urls.ts +223 -0
  317. package/src/utils/utils.ts +310 -0
  318. package/src/utils/vector.ts +197 -0
  319. package/src/utils/version.ts +8 -0
  320. package/src/utils/worker-types.ts +79 -0
  321. package/src/utils/worker_broker.ts +523 -0
@@ -0,0 +1,247 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+ // Copyright (c) 2026 vis.gl contributors
5
+
6
+ import DataSource, {NetworkTileSource} from './data_source';
7
+ import Geo from '../utils/geo';
8
+ import log from '../utils/log';
9
+ import {
10
+ convertMvtTileWithLegacy,
11
+ decodeMultiPolygon,
12
+ parseMvtWithLegacy,
13
+ type MvtTile
14
+ } from '../procedures/mvt-legacy';
15
+ import {parseMvt, registerMvtDecoder} from '../procedures/mvt-parser';
16
+ import {getMvtTileProvider} from '../procedures/mvt-tile-provider';
17
+ import type {MvtTileProviderSource} from '../procedures/mvt-tile-provider';
18
+ import {parseMvtJsonProperties} from '../procedures/mvt-properties';
19
+ import {createTileSourceMetadata} from './tile_source_metadata';
20
+ import type {TangramTileSourceMetadata} from './tile_source_metadata';
21
+ import {updateTileSourceRequest} from './tile_source_state';
22
+
23
+ const PARSE_JSON_TYPE = {
24
+ NONE: 0,
25
+ ALL: 1,
26
+ SOME: 2
27
+ };
28
+
29
+ type MvtSourceConfig = {
30
+ decoder?: string;
31
+ tile_provider?: string;
32
+ parse_json?: boolean | readonly string[];
33
+ name?: string;
34
+ [key: string]: unknown;
35
+ };
36
+
37
+ type TileData = {
38
+ /** Worker cancellation may precede deferred TileJSON URL resolution. */
39
+ canceled?: boolean;
40
+ min: Record<string, unknown>;
41
+ max: Record<string, unknown>;
42
+ coords: Record<string, unknown> & {x: number; y: number; z: number};
43
+ source_data?: SourceData;
44
+ debug?: Record<string, any>;
45
+ };
46
+
47
+ type SourceData = {
48
+ layers?: Record<string, unknown>;
49
+ url?: string;
50
+ error?: string | null;
51
+ };
52
+
53
+ /**
54
+ Mapbox Vector Tile format
55
+ @class MVTSource
56
+ */
57
+ export class MVTSource extends NetworkTileSource {
58
+
59
+ decoder!: string;
60
+ tile_provider?: string;
61
+ parse_json_type!: number;
62
+ parse_json_prop_list?: readonly string[];
63
+ /** Archive handles belong to this source instance, never a global URL cache. */
64
+ private providerSources = new Map<string, MvtTileProviderSource>();
65
+ /** Source replacement cancels every live tile request, including custom function providers. */
66
+ private providerRequests = new Set<AbortController>();
67
+ /** Additional archive credits are retained separately from scene-authored attribution. */
68
+ private providerAttributions: string[] = [];
69
+ /** Disposed instances cannot reopen an archive after asynchronous URL resolution. */
70
+ private disposed = false;
71
+
72
+ /** Resolve a factory once per effective URL; stateless registered functions stay unchanged. */
73
+ private getProviderSource(url: string): MvtTileProviderSource | undefined {
74
+ if (this.disposed) throw new Error('MVT source is disposed');
75
+ const provider = this.tile_provider && getMvtTileProvider(this.tile_provider);
76
+ if (!provider) throw new Error(`MVT tile provider '${this.tile_provider}' is not registered in this worker`);
77
+ if (typeof provider === 'function') return undefined;
78
+ let source = this.providerSources.get(url);
79
+ if (!source) {
80
+ source = provider.createSource(url, {headers: this.request_headers});
81
+ this.providerSources.set(url, source);
82
+ }
83
+ return source;
84
+ }
85
+
86
+ /** Include provider credits alongside authored and TileJSON attribution. */
87
+ getAttributions(): string[] { return [...new Set([...super.getAttributions(), ...this.providerAttributions])]; }
88
+
89
+ /** Normalize TileJSON and archive capabilities without changing authored layout or decoder choice. */
90
+ async getMetadata(): Promise<TangramTileSourceMetadata> {
91
+ if (!this.tile_provider) return super.getMetadata();
92
+ const url = await this.resolveURL();
93
+ const provider = this.getProviderSource(url);
94
+ const metadata = await provider?.getMetadata?.();
95
+ if (this.disposed) throw new Error('MVT source is disposed');
96
+ this.providerAttributions = (metadata?.attributions ?? []).filter(value => typeof value === 'string' && value.trim()).map(value => value.trim());
97
+ return createTileSourceMetadata(this, {...this.tile_metadata, ...metadata});
98
+ }
99
+
100
+ /** Dispose source-owned archive resources and cancel requests on replacement/removal/worker reset. */
101
+ dispose(): void {
102
+ super.dispose();
103
+ this.disposed = true;
104
+ for (const controller of this.providerRequests) controller.abort();
105
+ this.providerRequests.clear();
106
+ for (const provider of this.providerSources.values()) provider.dispose();
107
+ this.providerSources.clear();
108
+ }
109
+
110
+ constructor (source: MvtSourceConfig, sources?: Record<string, unknown>) {
111
+ super(source, sources);
112
+ this.response_type = 'arraybuffer'; // binary data
113
+ this.decoder = source.decoder || 'tangram';
114
+ this.tile_provider = source.tile_provider;
115
+
116
+ // Optionally parse some or all properties from JSON strings
117
+ if (source.parse_json === true) {
118
+ // try to parse all properties (least efficient)
119
+ this.parse_json_type = PARSE_JSON_TYPE.ALL;
120
+ }
121
+ else if (Array.isArray(source.parse_json)) {
122
+ // try to parse a specific list of property names (more efficient)
123
+ this.parse_json_type = PARSE_JSON_TYPE.SOME;
124
+ this.parse_json_prop_list = source.parse_json;
125
+ }
126
+ else {
127
+ if (source.parse_json != null) {
128
+ let msg = `Data source '${this.name}': 'parse_json' parameter should be 'true', or an array of ` +
129
+ `property names (was '${JSON.stringify(source.parse_json)}')`;
130
+ log({ level: 'warn', once: true }, msg);
131
+ }
132
+
133
+ // skip parsing entirely (default behavior)
134
+ this.parse_json_type = PARSE_JSON_TYPE.NONE;
135
+ }
136
+ }
137
+
138
+ loadURL (dest: TileData, url_template: string): Promise<any> {
139
+ if (!this.tile_provider) {
140
+ return super.loadURL(dest, url_template);
141
+ }
142
+
143
+ const tileProvider = getMvtTileProvider(this.tile_provider);
144
+ if (!tileProvider) {
145
+ return Promise.reject(new Error(`MVT tile provider '${this.tile_provider}' is not registered in this worker`));
146
+ }
147
+
148
+ const url = this.formatURL(url_template, dest);
149
+ const sourceData = dest.source_data as SourceData;
150
+ dest.debug = dest.debug || {};
151
+ const debug = dest.debug;
152
+ debug.network = +new Date();
153
+ sourceData.url = url;
154
+ sourceData.error = null;
155
+
156
+ const providerTileIndex = Geo.wrapTile(dest.coords, {x: true, y: false});
157
+ if (this.tms) {
158
+ providerTileIndex.y = Math.pow(2, providerTileIndex.z) - 1 - providerTileIndex.y;
159
+ }
160
+
161
+ const controller = new AbortController();
162
+ if (dest.canceled) controller.abort();
163
+ this.providerRequests.add(controller);
164
+ updateTileSourceRequest(dest, {cancel: () => controller.abort()});
165
+ const checkActive = (): void => {
166
+ if (controller.signal.aborted || this.disposed) {
167
+ const error = new Error('MVT provider request aborted');
168
+ error.name = 'AbortError';
169
+ throw error;
170
+ }
171
+ };
172
+ return Promise.resolve().then(() => {
173
+ checkActive();
174
+ return typeof tileProvider === 'function' ? tileProvider(url, providerTileIndex) :
175
+ this.getProviderSource(url)?.getTile(providerTileIndex, controller.signal);
176
+ }).then(response => {
177
+ checkActive();
178
+ debug.network = +new Date() - debug.network;
179
+ debug.parsing = +new Date();
180
+ const preprocessedResponse = response != null && typeof this.preprocess === 'function'
181
+ ? this.preprocess(response)
182
+ : response;
183
+ return Promise.resolve(preprocessedResponse).then(processedResponse => {
184
+ checkActive();
185
+ if (processedResponse != null) {
186
+ this.parseSourceData(dest, sourceData, processedResponse);
187
+ }
188
+ else {
189
+ sourceData.layers = {};
190
+ }
191
+ debug.parsing = +new Date() - debug.parsing;
192
+ return dest;
193
+ });
194
+ }).catch(error => {
195
+ sourceData.error = error instanceof Error ? error.stack || error.message : String(error);
196
+ return dest;
197
+ }).finally(() => {
198
+ this.providerRequests.delete(controller);
199
+ updateTileSourceRequest(dest, {cancel: undefined});
200
+ });
201
+ }
202
+
203
+ parseSourceData (tile?: TileData, source?: SourceData, response?: ArrayBuffer | Uint8Array): void {
204
+ if (!tile || !source || !response) {
205
+ throw new Error('MVT source parsing requires a tile, source data and response');
206
+ }
207
+ source.layers = parseMvt(this.decoder, response, {parseJson: this.parseJsonOption()});
208
+
209
+ // Apply optional data transform
210
+ if (typeof this.transform === 'function') {
211
+ const tile_data = {
212
+ min: Object.assign({}, tile.min),
213
+ max: Object.assign({}, tile.max),
214
+ coords: Object.assign({}, tile.coords)
215
+ };
216
+ source.layers = this.transform(source.layers, this.extra_data, tile_data);
217
+ }
218
+
219
+ }
220
+
221
+ // Loop through layers/features using Mapbox lib API, convert to GeoJSON features
222
+ // Returns an object with keys for each layer, e.g. { layer: geojson }
223
+ toGeoJSON (tile: MvtTile) {
224
+ return convertMvtTileWithLegacy(tile, {parseJson: this.parseJsonOption()});
225
+ }
226
+
227
+ // Optionally parse some or all feature properties from JSON strings
228
+ parseJSONProperties (feature: {properties: Record<string, unknown>}): void {
229
+ parseMvtJsonProperties(feature, this.parseJsonOption());
230
+ }
231
+
232
+ parseJsonOption (): boolean | readonly string[] | undefined {
233
+ if (this.parse_json_type === PARSE_JSON_TYPE.ALL) {
234
+ return true;
235
+ }
236
+ if (this.parse_json_type === PARSE_JSON_TYPE.SOME) {
237
+ return this.parse_json_prop_list;
238
+ }
239
+ return undefined;
240
+ }
241
+ }
242
+
243
+ export {decodeMultiPolygon};
244
+
245
+ DataSource.register('MVT', () => MVTSource);
246
+
247
+ registerMvtDecoder('tangram', parseMvtWithLegacy);
@@ -0,0 +1,341 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+ // Copyright (c) 2026 vis.gl contributors
5
+
6
+ import DataSource, {NetworkTileSource} from './data_source';
7
+ import {TileID} from '../tile/tile_id';
8
+ import Geo from '../utils/geo';
9
+ import Texture from '../gl/texture';
10
+ import Utils from '../utils/utils';
11
+ import hashString from '../utils/hash';
12
+ import log from '../utils/log';
13
+
14
+ type SourceConfig = Record<string, any>;
15
+ type Tile = any;
16
+ type RasterImage = {url: string | null; bounds: any; alpha: number | null};
17
+
18
+ export class RasterTileSource extends NetworkTileSource {
19
+
20
+ filtering: any;
21
+ textures!: Record<string, any>;
22
+
23
+ constructor (source: SourceConfig, sources?: Record<string, unknown>) {
24
+ super(source, sources);
25
+
26
+ if (this.rasters.indexOf(this.name) === -1) {
27
+ this.rasters.unshift(this.name); // add this raster as the first
28
+ }
29
+ this.filtering = source.filtering; // optional texture filtering (nearest, linear, mipmap)
30
+
31
+ // save texture objects by tile key, so URL remains stable if tile is built multiple times,
32
+ // e.g. avoid re-loading the same tile texture under a different subdomain when using tile hosts
33
+ this.textures = {};
34
+ }
35
+
36
+ async load (tile: Tile): Promise<Tile> {
37
+ tile.source_data = {};
38
+ tile.source_data.layers = {};
39
+ tile.pad_scale = this.pad_scale;
40
+ tile.rasters = [...this.rasters]; // copy list of rasters to load for tile
41
+
42
+ // Generate a single quad that fills the entire tile
43
+ let scale = Geo.tile_scale;
44
+ tile.source_data.layers = {
45
+ _default: {
46
+ type: 'FeatureCollection',
47
+ features: [{
48
+ geometry: {
49
+ type: 'Polygon',
50
+ coordinates: [[
51
+ [0, 0], [scale, 0],
52
+ [scale, -scale], [0, -scale], [0, 0]
53
+ ]]
54
+ },
55
+ properties: {}
56
+ }]
57
+ }
58
+ };
59
+
60
+ tile.default_winding = 'CW';
61
+ return tile;
62
+ }
63
+
64
+ // Return texture info for a raster tile
65
+ async tileTexture (tile: Tile, _options: {blend?: string; generation?: number} = {}): Promise<any> {
66
+ let coords = this.adjustRasterTileZoom(tile);
67
+ let key = coords.key;
68
+ // texture definitions are cached to avoid loading the same raster tile multiple times,
69
+ // e.g. due to slightly different URLs when subdomain pattern is used (a.tile.com vs. b.tile.com)
70
+ if (!this.textures[key]) {
71
+ let url = this.formatURL(this.url as string, { coords });
72
+ this.textures[key] = {
73
+ name: url,
74
+ url,
75
+ filtering: this.filtering,
76
+ coords
77
+ };
78
+ }
79
+ return this.textures[key];
80
+ }
81
+
82
+ // If the raster is attached to another source, we need to compare their levels of zoom detail
83
+ // to see if any adjustments are needed. Both the `tile_size` and `zoom_offset` data source params
84
+ // cause the zoom level to be downsampled relative to the "base" zoom level of the map view.
85
+ // The attaching source has already applied its own zoom downsampling. If this source has a lower
86
+ // level of detail, we apply the remaining differential here.
87
+ adjustRasterTileZoom (tile: Tile): any {
88
+ let coords = tile.coords;
89
+ const tile_source = this.sources[tile.source];
90
+ if (tile_source !== this) { // no-op if the raster source isn't being rendered as an attachment
91
+ let zdiff = this.zoom_bias - tile_source.zoom_bias; // difference in zoom detail between the sources
92
+ if (zdiff > 0) { // raster source is less detailed
93
+ // do extra zoom adjustment and apply this raster source's max zoom
94
+ coords = TileID.normalizedCoord(tile.coords, {
95
+ zoom_bias: zdiff,
96
+ zooms: this.zooms || []
97
+ } as any);
98
+ }
99
+ else {
100
+ // raster source supports higher detail, but was downsampled to match (the downsampling already
101
+ // happened upstream, when the attaching source calculated its own tile coordinate)
102
+ if (zdiff < 0) {
103
+ log({ level: 'warn', once: true},
104
+ `Raster source '${this.name}' supports higher zoom detail than source '${tile_source.name}' ` +
105
+ `it's attached to. Downsampling this source ${-zdiff} extra zoom levels to match.`
106
+ );
107
+ }
108
+
109
+ // no extra zoom adjustment needed, but still need to apply this raster source's max zoom
110
+ coords = TileID.coordForTileZooms(coords, this.zooms || []);
111
+ }
112
+ }
113
+ return coords;
114
+ }
115
+
116
+ }
117
+
118
+ // Data source for loading standalone, geo-referenced raster images
119
+ // The `bounds` parameter is used to position the raster image on the map
120
+ // Currently, only axis-aligned, rectangular North-up images are supported
121
+ // TODO: add support for arbitrarily rotated images and quadrangle control points
122
+ export class RasterSource extends RasterTileSource {
123
+
124
+ load_image!: Record<string, Promise<HTMLImageElement | null>>;
125
+ alpha: number | null;
126
+ mask_alpha!: boolean;
127
+ preserve_tiles_within_zoom!: number;
128
+ max_display_density?: number;
129
+ images!: RasterImage[];
130
+
131
+ constructor (source: SourceConfig, sources?: Record<string, unknown>) {
132
+ super(source, sources);
133
+
134
+ this.load_image = {}; // resolves to image, cached for life of data source
135
+
136
+ // alpha factor applied at time raster images are loaded and tiled (*not* at shader render-time)
137
+ this.alpha = (source.alpha != null) ? Math.max(Math.min(source.alpha, 1), 0) : null;
138
+
139
+ // non-full-alpha pixels should be discarded (for rendering rasters w/opaque blend)
140
+ this.mask_alpha = true;
141
+
142
+ // don't retain tiles for this source from nearby zooms (to improve memory usage)
143
+ this.preserve_tiles_within_zoom = 0;
144
+
145
+ // optionally set a max pixel density used for generated raster tiles (to improve memory usage)
146
+ this.max_display_density = source.max_display_density;
147
+
148
+ // Optionally composite multiple images into one raster layer
149
+ if (Array.isArray(source.composite)) {
150
+ // TODO: calculate enclosing bounding box to speed tile intersection checks
151
+ this.images = source.composite.map((s: SourceConfig) => {
152
+ return {
153
+ url: s.url,
154
+ bounds: this.parseBounds(s),
155
+ alpha: (s.alpha != null) ? Math.max(Math.min(s.alpha, 1), 0) : null
156
+ };
157
+ });
158
+ }
159
+ // Single image raster layer
160
+ else {
161
+ this.images = [{
162
+ url: this.url,
163
+ bounds: this.bounds,
164
+ alpha: this.alpha
165
+ }];
166
+ }
167
+ }
168
+
169
+ // Render the sub-rectangle of the source raster image for the given tile, to a texture.
170
+ // Clipping the source image to individual raster tiles naturally partitions images
171
+ // (which may be large or only have a small portion in current view), and maintains
172
+ // consistency with the raster tile pipeline allowing for sampling within the fragment shader,
173
+ // and clipping the raster against vector source data.
174
+ async tileTexture (tile: Tile, options: {blend?: string; generation?: number} = {}): Promise<any> {
175
+ const {blend, generation} = options;
176
+ let coords = this.adjustRasterTileZoom(tile);
177
+ const use_alpha = (blend !== 'opaque'); // ignore source alpha multiplier with opaque blending
178
+ const name = `raster-${this.name}-${coords.key}-${use_alpha ? 'alpha' : 'opaque'}-${generation}`; // unique texture name
179
+
180
+ // only render each raster tile once (per scene generation)
181
+ if ((Texture as any).textures[name]) {
182
+ return {
183
+ name,
184
+ coords,
185
+
186
+ // tell style to skip re-creating this texture
187
+ // we have an explicit flag for this because element-based (e.g. canvas) textures
188
+ // are usually considered dynamic and always re-created when a new tile needs them
189
+ // (because the user could have updated the canvas pixel contents outside of Tangram)
190
+ skip_create: true
191
+ };
192
+ }
193
+
194
+ // Display density, with extra 2x for better intra-zoom scaling, because raster tiles
195
+ // can be scaled up to 100% before next zoom level is loaded
196
+ let dpr = Utils.device_pixel_ratio || 1;
197
+ if (this.max_display_density) {
198
+ dpr = Math.min(dpr, this.max_display_density); // optionally cap pixel density
199
+ }
200
+ dpr *= 2;
201
+
202
+ const canvas = document.createElement('canvas');
203
+ const ctx = canvas.getContext('2d');
204
+ if (!ctx) {
205
+ throw new Error('Raster source requires a 2D canvas context');
206
+ }
207
+ canvas.width = this.tile_size * dpr; // adjusted for display density
208
+ canvas.height = this.tile_size * dpr;
209
+
210
+ // Applies nearest neighbor filtering to the canvas image rendering when data source requests it
211
+ // NB: does not work on IE11 (image will be blurry when scaled)
212
+ ctx.imageSmoothingEnabled = (this.filtering !== 'nearest');
213
+
214
+ // Draw one or more images
215
+ const images = this.images.filter((r: RasterImage) => this.checkBounds(tile.coords, r.bounds));
216
+ await Promise.all(images.map((i: RasterImage) => {
217
+ // TODO: log warning if alpha specified but will be ignored (in opaque mode)?
218
+ const alpha = (use_alpha ? (i.alpha != null ? i.alpha : this.alpha) : 1);
219
+ if (!i.url) {
220
+ return Promise.resolve();
221
+ }
222
+ return this.drawImage(i.url, i.bounds, alpha, tile, dpr, ctx);
223
+ }));
224
+
225
+ // texture config
226
+ return {
227
+ name,
228
+ element: canvas,
229
+ filtering: this.filtering,
230
+ coords
231
+ };
232
+ }
233
+
234
+ // Draw a single image to the tile canvas based on on its bounds
235
+ async drawImage (
236
+ url: string,
237
+ bounds: any,
238
+ alpha: number | null,
239
+ tile: Tile,
240
+ dpr: number,
241
+ ctx: CanvasRenderingContext2D
242
+ ): Promise<void> {
243
+ // Get source raster image
244
+ const key = hashString(url); // use hash of URL for shorter keys
245
+ this.load_image[key] = this.load_image[key] || this.loadImage(url);
246
+ const image = await this.load_image[key];
247
+
248
+ // Meters per pixel for this zoom, adjusted for display density and source tile size (e.g. 512px tiles)
249
+ const mpp = Geo.metersPerPixel(tile.coords.z) / dpr / (this.tile_size / Geo.tile_size);
250
+
251
+ // Raster origin relative to tile origin (get delta in meters, then convert to pixels)
252
+ const dx = (bounds.meters.min[0] - tile.min.x) / mpp;
253
+ const dy = -(bounds.meters.min[1] - tile.min.y) / mpp;
254
+
255
+ // Raster size in pixels for current zoom
256
+ const sx = (bounds.meters.max[0] - bounds.meters.min[0]) / mpp;
257
+ const sy = -(bounds.meters.max[1] - bounds.meters.min[1]) / mpp;
258
+
259
+ // Draw the raster, clipped to the current tile
260
+ // NB: this is drawing the *whole* raster, no matter how large, and relying on the native Canvas clipping.
261
+ // May want to benchmark with a pre-clipped draw area, though the native implementation is likely fast,
262
+ // and has to apply its own clipping check anyway.
263
+ ctx.globalAlpha = (alpha != null) ? alpha : 1;
264
+ if (image) {
265
+ ctx.drawImage(image, dx, dy, sx, sy);
266
+ }
267
+ }
268
+
269
+ // Load source raster image
270
+ loadImage (url: string): Promise<HTMLImageElement | null> {
271
+ return new Promise(resolve => {
272
+ let image = new Image();
273
+ image.onload = () => resolve(image);
274
+ image.onerror = e => {
275
+ // Warn and resolve on error
276
+ log('warn', `Raster source '${this.name}': failed to load url: '${url}'`, e);
277
+ resolve(null);
278
+ };
279
+
280
+ // Safari has a bug loading data-URL images with CORS enabled, so it must be disabled in that case
281
+ // https://bugs.webkit.org/show_bug.cgi?id=123978
282
+ if (!(Utils.isSafari() && url.slice(0, 5) === 'data:')) {
283
+ image.crossOrigin = 'anonymous';
284
+ }
285
+
286
+ image.src = url;
287
+ });
288
+ }
289
+
290
+ // Checks if tile interects any rasters in this source
291
+ includesTile (coords: any, style_z: number): boolean {
292
+ // Checks zoom range and dependent rasters
293
+ if (!DataSource.prototype.includesTile.call(this, coords, style_z)) {
294
+ return false;
295
+ }
296
+
297
+ return this.images.some((r: RasterImage) => this.checkBounds(coords, r.bounds)); // check if any images intersect
298
+ }
299
+
300
+ validate (source: SourceConfig): void {
301
+ const is_composite = Array.isArray(source.composite);
302
+
303
+ let url_msg = 'Raster data source must provide a string `url` parameter, or an array of `composite` raster ';
304
+ url_msg += 'image objects that each have a `url` parameter';
305
+
306
+ let bounds_msg = 'Raster data source must provide a `bounds` parameter, or an array of `composite` raster ';
307
+ bounds_msg += 'image objects that each have a `bounds` parameter';
308
+
309
+ let mutex_msg = 'Raster data source must have *either* a single image specified as `url` and `bounds `';
310
+ mutex_msg += 'parameters, or an array of `composite` raster image objects, each with `url` and `bounds`.';
311
+
312
+ if (is_composite) {
313
+ if (source.composite.some((s: SourceConfig) => typeof s.url !== 'string')) {
314
+ throw Error(url_msg);
315
+ }
316
+
317
+ if (source.composite.some((s: SourceConfig) => !(Array.isArray(s.bounds) && s.bounds.length === 4))) {
318
+ throw Error(bounds_msg);
319
+ }
320
+
321
+ if (source.url != null || source.bounds != null) {
322
+ throw Error(mutex_msg);
323
+ }
324
+ }
325
+ else {
326
+ if (typeof source.url !== 'string') {
327
+ throw Error(url_msg);
328
+ }
329
+
330
+ if (!(Array.isArray(source.bounds) && source.bounds.length === 4)) {
331
+ throw Error(bounds_msg);
332
+ }
333
+ }
334
+ }
335
+
336
+ }
337
+
338
+ // Check for URL tile pattern, if not found, treat as geo-referenced raster layer
339
+ DataSource.register('Raster', (source: SourceConfig) => {
340
+ return RasterTileSource.urlHasTilePattern(source.url) ? RasterTileSource : RasterSource;
341
+ });