@tangram.gl/tangram-renderer 0.0.0-stage → 0.0.1

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 +60 -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,620 @@
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 type {PropertyCache, PropertyContext, PropertyFunction, PropertyStop, PropertyTransform, PointSizeCache, PointSizeFlags, PointSizeImage, StyleParserRuntime, UnitValue} from './property-types';
7
+
8
+ import Utils from '../utils/utils';
9
+ import {compileFunctionString} from '../utils/functions';
10
+ import Geo from '../utils/geo';
11
+ import log from '../utils/log';
12
+
13
+ import parseCSSColor from 'csscolorparser';
14
+
15
+ // This macro is stringified and evaluated inside wrapFunction's feature scope.
16
+ declare const feature: {id: string};
17
+
18
+ // Members are installed below before this object is exposed to callers.
19
+ const StyleParser = {} as StyleParserRuntime;
20
+ export default StyleParser;
21
+
22
+ // Helpers for string converstion / NaN handling
23
+ const clampPositive = (v: unknown) => Math.max(v as number, 0);
24
+ const noNaN = (v: number) => isNaN(v) ? 0 : v;
25
+ const parseNumber = ((v: unknown) => Array.isArray(v) ? v.map(parseFloat).map(noNaN) : noNaN(parseFloat(v as string))) as StyleParserRuntime['parseNumber'];
26
+ const parsePositiveNumber = ((v: unknown) => Array.isArray(v) ? v.map(parseNumber).map(clampPositive) : clampPositive(parseNumber(v) as number)) as StyleParserRuntime['parsePositiveNumber'];
27
+
28
+ Object.assign(StyleParser, {clampPositive, noNaN, parseNumber, parsePositiveNumber});
29
+
30
+ // Wraps style functions and provides a scope of commonly accessible data:
31
+ // - feature: the 'properties' of the feature, e.g. accessed as 'feature.name'
32
+ // - global: user-defined properties on the `global` object in the scene file
33
+ // - $zoom: the current map zoom level
34
+ // - $geometry: the type of geometry, 'point', 'line', or 'polygon'
35
+ // - $meters_per_pixel: conversion for meters/pixels at current map zoom
36
+ StyleParser.wrapFunction = function (func, preserveNaN = false) {
37
+ var f = `
38
+ var feature = context.feature.properties;
39
+ var global = context.global;
40
+ var $zoom = context.zoom;
41
+ var $layer = context.layer;
42
+ var $source = context.source;
43
+ var $geometry = context.geometry;
44
+ var $meters_per_pixel = context.meters_per_pixel;
45
+ var $id = context.id;
46
+
47
+ var val = (function(){ ${func} }());
48
+
49
+ ${preserveNaN ? '' : `if (typeof val === 'number' && isNaN(val)) {
50
+ val = null; // convert NaNs to nulls
51
+ }`}
52
+
53
+ return val;
54
+ `;
55
+ return f;
56
+ };
57
+
58
+
59
+ // Style parsing
60
+
61
+ StyleParser.zeroPair = Object.freeze([0, 0] as [number, number]); // single allocation for zero values that won't be modified
62
+
63
+ // Style defaults
64
+ StyleParser.defaults = {
65
+ color: [1, 1, 1, 1],
66
+ width: 1,
67
+ size: 1,
68
+ extrude: false,
69
+ height: 20,
70
+ min_height: 0,
71
+ order: 0,
72
+ z: 0,
73
+ outline: {
74
+ color: [0, 0, 0, 0],
75
+ width: 0
76
+ },
77
+ material: {
78
+ ambient: 1,
79
+ diffuse: 1
80
+ }
81
+ };
82
+
83
+ // Style macros
84
+ StyleParser.macros = {
85
+ // pseudo-random color by geometry id
86
+ 'Style.color.pseudoRandomColor': function() {
87
+ return [
88
+ 0.7 * (parseInt(feature.id, 16) / 100 % 1), // eslint-disable-line no-undef
89
+ 0.7 * (parseInt(feature.id, 16) / 10000 % 1), // eslint-disable-line no-undef
90
+ 0.7 * (parseInt(feature.id, 16) / 1000000 % 1), // eslint-disable-line no-undef
91
+ 1
92
+ ];
93
+ },
94
+
95
+ // random color
96
+ 'Style.color.randomColor': function() {
97
+ return [0.7 * Math.random(), 0.7 * Math.random(), 0.7 * Math.random(), 1];
98
+ }
99
+ };
100
+
101
+ // A context object that is passed to style parsing functions to provide a scope of commonly used values
102
+ StyleParser.getFeatureParseContext = function (feature, tile, global) {
103
+ return {
104
+ feature,
105
+ id: feature.id,
106
+ tile,
107
+ global,
108
+ zoom: tile.style_z,
109
+ geometry: Geo.geometryType(feature.geometry.type),
110
+ meters_per_pixel: tile.meters_per_pixel,
111
+ meters_per_pixel_sq: tile.meters_per_pixel_sq,
112
+ units_per_meter_overzoom: tile.units_per_meter_overzoom
113
+ };
114
+ };
115
+
116
+ // Build a style param cache object
117
+ // `value` is a raw value, cache methods will add other properties as needed
118
+ // `transform` is an optional, one-time transform function to run on values during setup
119
+ // `dynamic_transform` is an optional post-processing function applied to the result of function-based properties
120
+ const CACHE_TYPE = {
121
+ STATIC: 0,
122
+ DYNAMIC: 1,
123
+ ZOOM: 2
124
+ };
125
+ StyleParser.CACHE_TYPE = CACHE_TYPE;
126
+
127
+ StyleParser.createPropertyCache = function (obj, transform = null, dynamic_transform = null) {
128
+ if (obj == null) {
129
+ return;
130
+ }
131
+
132
+ if ((obj as PropertyCache).value) {
133
+ return { value: (obj as PropertyCache).value, zoom: ((obj as PropertyCache).zoom ? {} : null), type: (obj as PropertyCache).type }; // clone existing cache object
134
+ }
135
+
136
+ let c: PropertyCache = { value: obj, type: CACHE_TYPE.STATIC };
137
+
138
+ // does value contain zoom stops to be interpolated?
139
+ if (Array.isArray(c.value) && Array.isArray(c.value[0])) {
140
+ c.zoom = {}; // will hold values interpolated by zoom
141
+ c.type = CACHE_TYPE.ZOOM;
142
+ }
143
+ else if (typeof c.value === 'function') {
144
+ c.type = CACHE_TYPE.DYNAMIC;
145
+ c.dynamic_transform = (typeof dynamic_transform === 'function' ? dynamic_transform : null);
146
+ }
147
+
148
+ // apply optional transform function - usually a parsing function
149
+ if (typeof transform === 'function') {
150
+ if (c.zoom) { // apply to each zoom stop value
151
+ c.value = (c.value as PropertyStop[]).map((v, i) => [v[0], transform(v[1], i)]);
152
+ }
153
+ else if (typeof c.value !== 'function') { // don't transform functions
154
+ c.value = transform(c.value, 0); // single value, 0 = the first and only item in the array
155
+ }
156
+ }
157
+
158
+ return c;
159
+ };
160
+
161
+ // Convert old-style color macro into a function
162
+ // TODO: deprecate this macro syntax
163
+ StyleParser.createColorPropertyCache = function (obj) {
164
+ return StyleParser.createPropertyCache(obj, v => {
165
+ if (v === 'Style.color.pseudoRandomColor') {
166
+ return compileFunctionString(StyleParser.wrapFunction(StyleParser.macros['Style.color.pseudoRandomColor']));
167
+ }
168
+ else if (v === 'Style.color.randomColor') {
169
+ return StyleParser.macros['Style.color.randomColor'];
170
+ }
171
+
172
+ return v;
173
+ });
174
+ };
175
+
176
+ // Parse point sizes, which include optional %-based or aspect-ratio-constrained scaling from sprite size
177
+ // Returns a cache object if successful, otherwise throws error message
178
+ const isPercent = (v: unknown) => typeof v === 'string' && v[v.length-1] === '%'; // size computed by %
179
+ const isRatio = (v: unknown) => v === 'auto'; // size derived from aspect ratio of one dimension
180
+ const isComputed = (v: unknown) => isPercent(v) || isRatio(v);
181
+ const dualRatioError = '\'size\' can specify either width or height as derived from aspect ratio, but not both';
182
+ StyleParser.createPointSizePropertyCache = function (obj, texture) {
183
+ // obj is the value to be parsed eg "64px" "100%" "auto"
184
+ // mimics the structure of the size value (at each zoom stop if applicable),
185
+ // stores flags indicating if each element is a %-based size or not, or derived from aspect
186
+ let has_pct: PointSizeFlags | null = null;
187
+ let has_ratio: PointSizeFlags | null = null;
188
+ if (isPercent(obj)) { // 1D size
189
+ has_pct = [true];
190
+ }
191
+ else if (Array.isArray(obj)) {
192
+ // track which fields are % vals
193
+ if (Array.isArray(obj[0])) { // zoom stops
194
+ // could be a 1D value (that could be a %), or a 2D value (either width or height or both could be a %)
195
+ if (obj.some(v => Array.isArray(v[1]) ? v[1].some(w => isComputed(w)) : isPercent(v[1]))) {
196
+ has_pct = obj.map(v => Array.isArray(v[1]) ? v[1].map(w => isPercent(w)) : isPercent(v[1]));
197
+ has_ratio = obj.map(v => Array.isArray(v[1]) && v[1].map(w => isRatio(w)));
198
+ if (has_ratio.some(v => Array.isArray(v) && v.every(c => c))) {
199
+ throw dualRatioError; // invalid case where both dims are ratios
200
+ }
201
+ }
202
+ }
203
+ else if (obj.some(isComputed)) { // 2D size
204
+ has_pct = [obj.map(isPercent)];
205
+ has_ratio = [obj.map(isRatio)];
206
+ if ((has_ratio[0] as boolean[]).every(c => c)) {
207
+ throw dualRatioError; // invalid case where both dims are ratios
208
+ }
209
+ }
210
+ }
211
+ else if (isRatio(obj)) {
212
+ throw 'this value only allowed as half of an array, eg [16px, auto]:';
213
+ // TODO: add this error check for zoom stop parsing above
214
+ }
215
+
216
+ if (has_pct || has_ratio) {
217
+ // texture is required when % or ratio sizes are used
218
+ if (!texture) {
219
+ throw '% or \'auto\' keywords can only be used to specify point size when a texture is defined';
220
+ }
221
+
222
+ // per-sprite based evaluation
223
+ obj = { value: obj };
224
+ (obj as PointSizeCache).has_pct = has_pct;
225
+ (obj as PointSizeCache).has_ratio = has_ratio;
226
+ (obj as PointSizeCache).sprites = {}; // cache by sprite
227
+ }
228
+ else {
229
+ // no % or aspect ratio sizing, one cache for texture or all sprites
230
+ obj = StyleParser.createPropertyCache(obj, parsePositiveNumber);
231
+ }
232
+
233
+ return obj as PointSizeCache | undefined;
234
+ };
235
+
236
+ StyleParser.evalCachedPointSizeProperty = function (val, sprite_info, texture_info, context) {
237
+ if (val == null) {
238
+ return;
239
+ }
240
+
241
+ // no percentage-based calculation, one cache for all sprites
242
+ if (!val.has_pct && !val.has_ratio) {
243
+ return StyleParser.evalCachedProperty(val, context);
244
+ }
245
+
246
+ if (sprite_info) {
247
+ // per-sprite based evaluation, cache sizes per sprite
248
+ if (!val.sprites![sprite_info.sprite!]) {
249
+ val.sprites![sprite_info.sprite!] = createPointSizeCacheEntry(val, sprite_info);
250
+ }
251
+ return StyleParser.evalCachedProperty(val.sprites![sprite_info.sprite!], context);
252
+ }
253
+ else {
254
+ // texture-based evaluation
255
+ // apply percentage or ratio sizing to a texture
256
+ val.texture = val.texture || createPointSizeCacheEntry(val, texture_info!);
257
+ return StyleParser.evalCachedProperty(val.texture, context);
258
+ }
259
+ };
260
+
261
+ function createPointSizeCacheEntry (val: PointSizeCache, image_info: PointSizeImage): PropertyCache | undefined {
262
+ // the cache property transform function needs access to the image in `val`
263
+ // so it's accessed via a closure here
264
+ return StyleParser.createPropertyCache(val.value, (v, i) => {
265
+ if (Array.isArray(v)) { // 2D size
266
+ // either width or height or both could be a %
267
+ v = v.
268
+ map((c, j) => (val.has_ratio![i] as boolean[])[j] ? c : parsePositiveNumber(c)). // convert non-ratio values to px
269
+ map((c, j) => (val.has_pct![i] as boolean[])[j] ? image_info.css_size[j] * (c as number) / 100 : c); // apply % scaling as needed
270
+
271
+ // either width or height could be a ratio
272
+ if ((val.has_ratio![i] as boolean[])[0]) {
273
+ (v as number[])[0] = (v as number[])[1] * image_info.aspect;
274
+ }
275
+ else if ((val.has_ratio![i] as boolean[])[1]) {
276
+ (v as number[])[1] = (v as number[])[0] / image_info.aspect;
277
+ }
278
+ }
279
+ else { // 1D size
280
+ v = parsePositiveNumber(v);
281
+ if (val.has_pct![i]) {
282
+ v = image_info.css_size.map(c => c * (v as number) / 100); // set size as % of image
283
+ }
284
+ else {
285
+ v = [v, v]; // expand 1D size to 2D
286
+ }
287
+ }
288
+ return v;
289
+ });
290
+ }
291
+
292
+ // Interpolation and caching for a generic property (not a color or distance)
293
+ // { value: original, static: val, zoom: { 1: val1, 2: val2, ... }, dynamic: function(){...} }
294
+ StyleParser.evalCachedProperty = function(val, context) {
295
+ if (val == null) {
296
+ return;
297
+ }
298
+ else if (val.dynamic) { // function, compute each time (no caching)
299
+ return tryEval(val.dynamic, context);
300
+ }
301
+ else if (val.static) { // single static value
302
+ return val.static;
303
+ }
304
+ else if (val.zoom && val.zoom[context.zoom!]) { // interpolated, cached
305
+ return val.zoom[context.zoom!];
306
+ }
307
+ else { // not yet evaulated for cache
308
+ // Dynamic function-based
309
+ if (typeof val.value === 'function') {
310
+ if (val.dynamic_transform) {
311
+ // apply an optional post-eval transform function
312
+ // e.g. apply device pixel ratio to font sizes, unit conversions, etc.
313
+ val.dynamic = function(context) {
314
+ return val.dynamic_transform!((val.value as PropertyFunction)(context));
315
+ };
316
+ }
317
+ else {
318
+ val.dynamic = val.value as PropertyFunction;
319
+ }
320
+ return tryEval(val.dynamic, context);
321
+ }
322
+ // Array of zoom-interpolated stops, e.g. [zoom, value] pairs
323
+ else if (Array.isArray(val.value) && Array.isArray(val.value[0])) {
324
+ // Calculate value for current zoom
325
+ val.zoom = val.zoom || {};
326
+ val.zoom[context.zoom!] = Utils.interpolate(context.zoom!, val.value);
327
+ return val.zoom[context.zoom!];
328
+ }
329
+ // Single static value
330
+ else {
331
+ val.static = val.value;
332
+ return val.static;
333
+ }
334
+ }
335
+ };
336
+
337
+ StyleParser.convertUnits = function(val, context) {
338
+ // pre-parsed units
339
+ if ((val as UnitValue).value != null) {
340
+ if ((val as UnitValue).units === 'px') { // convert from pixels
341
+ return ((val as UnitValue).value as number) * Geo.metersPerPixel(context.zoom!);
342
+ }
343
+ return (val as UnitValue).value;
344
+ }
345
+ // un-parsed unit string
346
+ else if (typeof val === 'string') {
347
+ if (val.trim().slice(-2) === 'px') {
348
+ val = parseNumber(val);
349
+ (val as number) *= Geo.metersPerPixel(context.zoom!); // convert from pixels
350
+ }
351
+ else {
352
+ val = parseNumber(val);
353
+ }
354
+ }
355
+ // multiple values or stops
356
+ else if (Array.isArray(val)) {
357
+ // Array of arrays, e.g. zoom-interpolated stops
358
+ if (Array.isArray(val[0])) {
359
+ return val.map(v => [v[0], StyleParser.convertUnits(v[1], context)]);
360
+ }
361
+ // Array of values
362
+ else {
363
+ return val.map(v => StyleParser.convertUnits(v, context));
364
+ }
365
+ }
366
+ return val;
367
+ };
368
+
369
+ // Pre-parse units from string values
370
+ StyleParser.parseUnits = function (value) {
371
+ var obj: UnitValue = { value: parseNumber(value) };
372
+ if (obj.value !== 0 && typeof value === 'string' && value.trim().slice(-2) === 'px') {
373
+ obj.units = 'px';
374
+ }
375
+ return obj;
376
+ };
377
+
378
+ /** Keep invalid projected heights visible to validation, including wrapped scene functions. */
379
+ StyleParser.createProjectedHeightPropertyCache = function (value) {
380
+ if (typeof value === 'function' && 'source' in value && typeof value.source === 'string') {
381
+ // Recompile from the authored body, not the legacy NaN-to-null wrapper.
382
+ // Leave the shared compiled function untouched for other style properties.
383
+ value = compileFunctionString(`function(context) {${value.source}}`,
384
+ source => StyleParser.wrapFunction(source, true));
385
+ }
386
+ return StyleParser.createPropertyCache(value, height => {
387
+ const parsedHeight = typeof height === 'string' ? parseFloat(height) : height;
388
+ if (typeof parsedHeight !== 'number' || !Number.isFinite(parsedHeight)) {
389
+ throw new Error('Projected annotation height must be a finite number');
390
+ }
391
+ return StyleParser.parseUnits(height);
392
+ });
393
+ };
394
+
395
+ /** Dynamic projected heights must reach packing validation without legacy error fallback. */
396
+ StyleParser.evalProjectedHeightProperty = function (value, context) {
397
+ return typeof value?.value === 'function' ? value.value(context) :
398
+ StyleParser.evalCachedDistanceProperty(value, context);
399
+ };
400
+
401
+ // Takes a distance cache object and returns a distance value for this zoom
402
+ // (caching the result for future use)
403
+ // { value: original, zoom: { z: meters }, dynamic: function(){...} }
404
+ StyleParser.evalCachedDistanceProperty = function(val, context) {
405
+ if (val == null) {
406
+ return;
407
+ }
408
+ else if (val.dynamic) {
409
+ return tryEval(val.dynamic, context);
410
+ }
411
+ else if (val.zoom && val.zoom[context.zoom!]) {
412
+ return val.zoom[context.zoom!];
413
+ }
414
+ else {
415
+ // Dynamic function-based
416
+ if (typeof val.value === 'function') {
417
+ val.dynamic = val.value as PropertyFunction;
418
+ return tryEval(val.dynamic, context);
419
+ }
420
+ // Array of zoom-interpolated stops, e.g. [zoom, value] pairs
421
+ else if (val.zoom) {
422
+ // Calculate value for current zoom
423
+ // Do final unit conversion as late as possible, when interpolation values have been determined
424
+ val.zoom[context.zoom!] = Utils.interpolate(context.zoom!, val.value as PropertyStop[],
425
+ v => StyleParser.convertUnits(v, context) as number);
426
+
427
+ return val.zoom[context.zoom!];
428
+ }
429
+ else {
430
+ return StyleParser.convertUnits(val.value, context);
431
+ }
432
+ }
433
+ };
434
+
435
+ // Cache previously parsed color strings
436
+ StyleParser.string_colors = {};
437
+ StyleParser.colorForString = function(string) {
438
+ // Cached
439
+ if (StyleParser.string_colors[string]) {
440
+ return StyleParser.string_colors[string];
441
+ }
442
+
443
+ // Calculate and cache
444
+ let color: number[] | undefined = parseCSSColor.parseCSSColor(string);
445
+ if (color && color.length === 4) {
446
+ color[0] /= 255;
447
+ color[1] /= 255;
448
+ color[2] /= 255;
449
+ }
450
+ else {
451
+ color = StyleParser.defaults.color;
452
+ }
453
+ StyleParser.string_colors[string] = color;
454
+ return color;
455
+ };
456
+
457
+ // Takes a color cache object and returns a color value for this zoom
458
+ // (caching the result for future use)
459
+ // { value: original, static: [r,g,b,a], zoom: { z: [r,g,b,a] }, dynamic: function(){...} }
460
+ StyleParser.evalCachedColorProperty = function(val, context = {}) {
461
+ if (val == null) {
462
+ return;
463
+ }
464
+ else if (val.dynamic) {
465
+ let v = tryEval(val.dynamic, context) as number[] | string | undefined;
466
+
467
+ if (typeof v === 'string') {
468
+ v = StyleParser.colorForString(v);
469
+ }
470
+
471
+ if (v && v[3] == null) {
472
+ v[3] = 1; // default alpha
473
+ }
474
+ return v;
475
+ }
476
+ else if (val.static) {
477
+ return val.static as number[];
478
+ }
479
+ else if (val.zoom && val.zoom[context.zoom!]) {
480
+ return val.zoom[context.zoom!] as number[];
481
+ }
482
+ else {
483
+ // Dynamic function-based color
484
+ if (typeof val.value === 'function') {
485
+ val.dynamic = val.value as PropertyFunction;
486
+ let v = tryEval(val.dynamic, context) as number[] | string | undefined;
487
+
488
+ if (typeof v === 'string') {
489
+ v = StyleParser.colorForString(v);
490
+ }
491
+
492
+ if (v && v[3] == null) {
493
+ v[3] = 1; // default alpha
494
+ }
495
+ return v;
496
+ }
497
+ // Single string color
498
+ else if (typeof val.value === 'string') {
499
+ val.static = StyleParser.colorForString(val.value);
500
+ return val.static as number[];
501
+ }
502
+ // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
503
+ else if (val.zoom) {
504
+ // Parse any string colors inside stops, the first time we encounter this property
505
+ if (!val.zoom_preprocessed) {
506
+ for (let i=0; i < (val.value as PropertyStop[]).length; i++) {
507
+ let v = (val.value as PropertyStop[])[i];
508
+ if (v && typeof v[1] === 'string') {
509
+ v[1] = StyleParser.colorForString(v[1]);
510
+ }
511
+ }
512
+ val.zoom_preprocessed = true;
513
+ }
514
+
515
+ // Calculate color for current zoom
516
+ val.zoom[context.zoom!] = Utils.interpolate(context.zoom!, val.value as PropertyStop[]);
517
+ (val.zoom[context.zoom!] as number[])[3] = (val.zoom[context.zoom!] as number[])[3] || 1; // default alpha
518
+ return val.zoom[context.zoom!] as number[];
519
+ }
520
+ // Single array color
521
+ else {
522
+ val.static = (val.value as number[]).map(x => x); // copy to avoid modifying
523
+ if (val.static && (val.static as number[])[3] == null) {
524
+ (val.static as number[])[3] = 1; // default alpha
525
+ }
526
+ return val.static as number[];
527
+ }
528
+ }
529
+ };
530
+
531
+ // Evaluate color cache object and apply optional alpha override (alpha arg is a single value cache object)
532
+ StyleParser.evalCachedColorPropertyWithAlpha = function (val, alpha_prop, context) {
533
+ const color = StyleParser.evalCachedColorProperty(val, context);
534
+ if (color != null && alpha_prop != null) {
535
+ const alpha = StyleParser.evalCachedProperty(alpha_prop, context);
536
+ if (alpha != null) {
537
+ return [color[0], color[1], color[2], alpha];
538
+ }
539
+ }
540
+ return color;
541
+ };
542
+
543
+ StyleParser.parseColor = function(val, context = {}) {
544
+ if (typeof val === 'function') {
545
+ val = tryEval(val as PropertyFunction, context);
546
+ }
547
+
548
+ // Parse CSS-style colors
549
+ // TODO: change all colors to use 0-255 range internally to avoid dividing and then re-multiplying in geom builder
550
+ if (typeof val === 'string') {
551
+ val = StyleParser.colorForString(val);
552
+ }
553
+ else if (Array.isArray(val) && Array.isArray(val[0])) {
554
+ // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
555
+ for (let i=0; i < val.length; i++) {
556
+ let v = val[i];
557
+ if (typeof v[1] === 'string') {
558
+ v[1] = StyleParser.colorForString(v[1]);
559
+ }
560
+ }
561
+
562
+ if (context.zoom) {
563
+ val = Utils.interpolate(context.zoom, val);
564
+ }
565
+ }
566
+
567
+ // Defaults
568
+ if (Array.isArray(val)) {
569
+ val = val.map(x => x); // copy to avoid modifying
570
+ // alpha
571
+ if ((val as number[])[3] == null) {
572
+ (val as number[])[3] = 1;
573
+ }
574
+ }
575
+ else {
576
+ val = [0, 0, 0, 1];
577
+ }
578
+
579
+ return val as number[];
580
+ };
581
+
582
+ StyleParser.calculateOrder = function(order, context) {
583
+ // Computed order
584
+ if (typeof order === 'function') {
585
+ order = tryEval(order as PropertyFunction, context);
586
+ }
587
+ else if (typeof order === 'string') {
588
+ // Order tied to feature property
589
+ if (context.feature!.properties[order]) {
590
+ order = context.feature!.properties[order];
591
+ }
592
+ // Explicit order value
593
+ else {
594
+ order = parsePositiveNumber(order);
595
+ }
596
+ }
597
+
598
+ return order;
599
+ };
600
+
601
+ // Evaluate a function-based property, or pass-through static value
602
+ StyleParser.evalProperty = function(prop, context) {
603
+ if (typeof prop === 'function') {
604
+ return tryEval(prop as PropertyFunction, context);
605
+ }
606
+ return prop;
607
+ };
608
+
609
+ // eval property function with try/catch
610
+ function tryEval (func: PropertyFunction, context: PropertyContext): unknown {
611
+ try {
612
+ return func(context);
613
+ } catch(e) {
614
+ log('warn',
615
+ `Property function in layer '${context.layers![context.layers!.length-1]}' failed with\n`,
616
+ `error ${(e as Error).stack}\n`,
617
+ `function '${func.source}'\n`,
618
+ context.feature, context);
619
+ }
620
+ }