@deck.gl-community/infovis-layers 9.3.2 → 9.3.7

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 (129) hide show
  1. package/dist/index.cjs +2998 -114
  2. package/dist/index.cjs.map +4 -4
  3. package/dist/index.d.ts +11 -2
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +9 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/layers/animation-layer/animation-layer.d.ts +30 -0
  8. package/dist/layers/animation-layer/animation-layer.d.ts.map +1 -0
  9. package/dist/layers/animation-layer/animation-layer.js +53 -0
  10. package/dist/layers/animation-layer/animation-layer.js.map +1 -0
  11. package/dist/layers/animation-layer/animation.d.ts +86 -0
  12. package/dist/layers/animation-layer/animation.d.ts.map +1 -0
  13. package/dist/layers/animation-layer/animation.js +214 -0
  14. package/dist/layers/animation-layer/animation.js.map +1 -0
  15. package/dist/layers/block-layer/block-layer-fragment.glsl.d.ts +3 -0
  16. package/dist/layers/block-layer/block-layer-fragment.glsl.d.ts.map +1 -0
  17. package/dist/layers/block-layer/block-layer-fragment.glsl.js +41 -0
  18. package/dist/layers/block-layer/block-layer-fragment.glsl.js.map +1 -0
  19. package/dist/layers/block-layer/block-layer-uniforms.d.ts +27 -0
  20. package/dist/layers/block-layer/block-layer-uniforms.d.ts.map +1 -0
  21. package/dist/layers/block-layer/block-layer-uniforms.js +26 -0
  22. package/dist/layers/block-layer/block-layer-uniforms.js.map +1 -0
  23. package/dist/layers/block-layer/block-layer-vertex.glsl.d.ts +3 -0
  24. package/dist/layers/block-layer/block-layer-vertex.glsl.d.ts.map +1 -0
  25. package/dist/layers/block-layer/block-layer-vertex.glsl.js +67 -0
  26. package/dist/layers/block-layer/block-layer-vertex.glsl.js.map +1 -0
  27. package/dist/layers/block-layer/block-layer.d.ts +71 -0
  28. package/dist/layers/block-layer/block-layer.d.ts.map +1 -0
  29. package/dist/layers/block-layer/block-layer.js +108 -0
  30. package/dist/layers/block-layer/block-layer.js.map +1 -0
  31. package/dist/layers/fast-text-layer/fast-text-layer.d.ts +148 -0
  32. package/dist/layers/fast-text-layer/fast-text-layer.d.ts.map +1 -0
  33. package/dist/layers/fast-text-layer/fast-text-layer.js +862 -0
  34. package/dist/layers/fast-text-layer/fast-text-layer.js.map +1 -0
  35. package/dist/layers/fast-text-layer/fast-text-layer.test.d.ts +2 -0
  36. package/dist/layers/fast-text-layer/fast-text-layer.test.d.ts.map +1 -0
  37. package/dist/layers/fast-text-layer/fast-text-layer.test.js +300 -0
  38. package/dist/layers/fast-text-layer/fast-text-layer.test.js.map +1 -0
  39. package/dist/layers/fast-text-layer/fast-text-layout.d.ts +179 -0
  40. package/dist/layers/fast-text-layer/fast-text-layout.d.ts.map +1 -0
  41. package/dist/layers/fast-text-layer/fast-text-layout.js +665 -0
  42. package/dist/layers/fast-text-layer/fast-text-layout.js.map +1 -0
  43. package/dist/layers/fast-text-layer/font-atlas.d.ts +98 -0
  44. package/dist/layers/fast-text-layer/font-atlas.d.ts.map +1 -0
  45. package/dist/layers/fast-text-layer/font-atlas.js +337 -0
  46. package/dist/layers/fast-text-layer/font-atlas.js.map +1 -0
  47. package/dist/layers/fast-text-layer/index.d.ts +4 -0
  48. package/dist/layers/fast-text-layer/index.d.ts.map +1 -0
  49. package/dist/layers/fast-text-layer/index.js +4 -0
  50. package/dist/layers/fast-text-layer/index.js.map +1 -0
  51. package/dist/layers/time-delta-layer.d.ts +22 -60
  52. package/dist/layers/time-delta-layer.d.ts.map +1 -1
  53. package/dist/layers/time-delta-layer.js +31 -53
  54. package/dist/layers/time-delta-layer.js.map +1 -1
  55. package/dist/synchronized-views/synchronized-views.js +1 -1
  56. package/dist/synchronized-views/synchronized-views.js.map +1 -1
  57. package/dist/utils/format-utils.d.ts +27 -3
  58. package/dist/utils/format-utils.d.ts.map +1 -1
  59. package/dist/utils/format-utils.js +72 -40
  60. package/dist/utils/format-utils.js.map +1 -1
  61. package/dist/utils/utf8-string-view.d.ts +53 -0
  62. package/dist/utils/utf8-string-view.d.ts.map +1 -0
  63. package/dist/utils/utf8-string-view.js +169 -0
  64. package/dist/utils/utf8-string-view.js.map +1 -0
  65. package/dist/utils/utf8-string-view.test.d.ts +2 -0
  66. package/dist/utils/utf8-string-view.test.d.ts.map +1 -0
  67. package/dist/utils/utf8-string-view.test.js +88 -0
  68. package/dist/utils/utf8-string-view.test.js.map +1 -0
  69. package/dist/views/bounds-utils.d.ts +23 -0
  70. package/dist/views/bounds-utils.d.ts.map +1 -0
  71. package/dist/views/bounds-utils.js +65 -0
  72. package/dist/views/bounds-utils.js.map +1 -0
  73. package/dist/views/layer-bounds-filter.d.ts +48 -0
  74. package/dist/views/layer-bounds-filter.d.ts.map +1 -0
  75. package/dist/views/layer-bounds-filter.js +99 -0
  76. package/dist/views/layer-bounds-filter.js.map +1 -0
  77. package/dist/views/layer-filter.js +4 -4
  78. package/dist/views/layer-filter.js.map +1 -1
  79. package/dist/views/orthographic-utils.d.ts +30 -2
  80. package/dist/views/orthographic-utils.d.ts.map +1 -1
  81. package/dist/views/orthographic-utils.js +33 -14
  82. package/dist/views/orthographic-utils.js.map +1 -1
  83. package/dist/views/view-layout/build-views-from-view-layout.d.ts +37 -0
  84. package/dist/views/view-layout/build-views-from-view-layout.d.ts.map +1 -0
  85. package/dist/views/view-layout/build-views-from-view-layout.js +413 -0
  86. package/dist/views/view-layout/build-views-from-view-layout.js.map +1 -0
  87. package/dist/views/view-layout/index.d.ts +3 -0
  88. package/dist/views/view-layout/index.d.ts.map +1 -0
  89. package/dist/views/view-layout/index.js +3 -0
  90. package/dist/views/view-layout/index.js.map +1 -0
  91. package/dist/views/view-layout/view-layout-item.d.ts +74 -0
  92. package/dist/views/view-layout/view-layout-item.d.ts.map +1 -0
  93. package/dist/views/view-layout/view-layout-item.js +48 -0
  94. package/dist/views/view-layout/view-layout-item.js.map +1 -0
  95. package/dist/views/view-layout/view-layout.test.d.ts +2 -0
  96. package/dist/views/view-layout/view-layout.test.d.ts.map +1 -0
  97. package/dist/views/view-layout/view-layout.test.js +112 -0
  98. package/dist/views/view-layout/view-layout.test.js.map +1 -0
  99. package/dist/views/viewport-bounds-utils.d.ts +55 -0
  100. package/dist/views/viewport-bounds-utils.d.ts.map +1 -0
  101. package/dist/views/viewport-bounds-utils.js +70 -0
  102. package/dist/views/viewport-bounds-utils.js.map +1 -0
  103. package/package.json +15 -5
  104. package/src/index.ts +91 -2
  105. package/src/layers/animation-layer/animation-layer.ts +92 -0
  106. package/src/layers/animation-layer/animation.ts +328 -0
  107. package/src/layers/block-layer/block-layer-fragment.glsl.ts +41 -0
  108. package/src/layers/block-layer/block-layer-uniforms.ts +43 -0
  109. package/src/layers/block-layer/block-layer-vertex.glsl.ts +67 -0
  110. package/src/layers/block-layer/block-layer.ts +199 -0
  111. package/src/layers/fast-text-layer/fast-text-layer.test.ts +359 -0
  112. package/src/layers/fast-text-layer/fast-text-layer.ts +1208 -0
  113. package/src/layers/fast-text-layer/fast-text-layout.ts +1124 -0
  114. package/src/layers/fast-text-layer/font-atlas.ts +574 -0
  115. package/src/layers/fast-text-layer/index.ts +37 -0
  116. package/src/layers/time-delta-layer.ts +55 -70
  117. package/src/synchronized-views/synchronized-views.ts +1 -1
  118. package/src/utils/format-utils.ts +90 -40
  119. package/src/utils/utf8-string-view.test.ts +119 -0
  120. package/src/utils/utf8-string-view.ts +273 -0
  121. package/src/views/bounds-utils.ts +88 -0
  122. package/src/views/layer-bounds-filter.ts +160 -0
  123. package/src/views/layer-filter.ts +4 -4
  124. package/src/views/orthographic-utils.ts +65 -18
  125. package/src/views/view-layout/build-views-from-view-layout.ts +547 -0
  126. package/src/views/view-layout/index.ts +18 -0
  127. package/src/views/view-layout/view-layout-item.ts +125 -0
  128. package/src/views/view-layout/view-layout.test.ts +129 -0
  129. package/src/views/viewport-bounds-utils.ts +104 -0
package/dist/index.cjs CHANGED
@@ -24,18 +24,46 @@ var __publicField = (obj, key, value) => {
24
24
  // dist/index.js
25
25
  var dist_exports = {};
26
26
  __export(dist_exports, {
27
+ AnimationLayer: () => AnimationLayer,
28
+ BlockLayer: () => BlockLayer,
29
+ DEFAULT_BOUNDS_EPSILON: () => DEFAULT_BOUNDS_EPSILON,
30
+ DEFAULT_FAST_TEXT_FONT_SETTINGS: () => DEFAULT_FAST_TEXT_FONT_SETTINGS,
31
+ FastTextFontAtlasManager: () => FastTextFontAtlasManager,
32
+ FastTextLayer: () => FastTextLayer,
27
33
  HEADER_VIEW_HEIGHT: () => HEADER_VIEW_HEIGHT,
28
34
  LEGEND_VIEW_WIDTH: () => LEGEND_VIEW_WIDTH,
29
35
  SYNCHRONIZED_VIEWS: () => SYNCHRONIZED_VIEWS,
30
36
  SYNCHRONIZED_VIEW_STATE_CONSTRAINTS: () => SYNCHRONIZED_VIEW_STATE_CONSTRAINTS,
31
37
  TimeDeltaLayer: () => TimeDeltaLayer,
38
+ ViewLayoutItem: () => ViewLayoutItem,
39
+ arrowFindUtf8: () => arrowFindUtf8,
40
+ boundsAreEqual: () => boundsAreEqual,
41
+ buildFastTextCharacterMapping: () => buildFastTextCharacterMapping,
42
+ buildFastTextGlyphData: () => buildFastTextGlyphData,
43
+ buildFastTextUtf8ColumnSource: () => buildFastTextUtf8ColumnSource,
44
+ buildMultiLineGlyphData: () => buildMultiLineGlyphData,
45
+ buildSingleLineGlyphData: () => buildSingleLineGlyphData,
46
+ buildViewsFromViewLayout: () => buildViewsFromViewLayout,
47
+ collectFastTextCharacterSet: () => collectFastTextCharacterSet,
48
+ combineLayerFilters: () => combineLayerFilters,
49
+ createFastTextFontAtlas: () => createFastTextFontAtlas,
50
+ createViewportBoundsFilter: () => createViewportBoundsFilter,
32
51
  fitBoundsOrthographic: () => fitBoundsOrthographic,
33
52
  fitSynchronizedViewStatesToBounds: () => fitSynchronizedViewStatesToBounds,
34
53
  formatTimeMs: () => formatTimeMs,
35
54
  formatTimeRangeMs: () => formatTimeRangeMs,
55
+ getArrowUtf8ColumnSource: () => getArrowUtf8ColumnSource,
56
+ getArrowUtf8RowView: () => getArrowUtf8RowView,
57
+ getBoundsOrthographic: () => getBoundsOrthographic,
58
+ getPaddedBlockBounds: () => getPaddedBlockBounds,
36
59
  getSynchronizedViewStates: () => getSynchronizedViewStates,
60
+ getUtf8ColumnSourceRowView: () => getUtf8ColumnSourceRowView,
61
+ getViewportBoundsForViewState: () => getViewportBoundsForViewState,
62
+ isBoundsCompletelyOutside: () => isBoundsCompletelyOutside,
37
63
  makeLayerFilter: () => makeLayerFilter,
64
+ makeUtf8StringView: () => makeUtf8StringView,
38
65
  mergeViewStates: () => mergeViewStates,
66
+ updateFastTextDynamicGlyphAttributes: () => updateFastTextDynamicGlyphAttributes,
39
67
  validateViewState: () => validateViewState
40
68
  });
41
69
  module.exports = __toCommonJS(dist_exports);
@@ -45,57 +73,80 @@ var import_core = require("@deck.gl/core");
45
73
  var import_layers = require("@deck.gl/layers");
46
74
 
47
75
  // dist/utils/format-utils.js
48
- function formatTimeMs(timeMs, space = true) {
76
+ function formatTimeMs(timeMs, options = {}) {
77
+ const normalizedOptions = typeof options === "boolean" ? { space: options } : options;
78
+ const { space = true, roundDigits = 5 } = normalizedOptions;
49
79
  const sep = space ? " " : "";
50
80
  const us = timeMs * 1e3;
51
81
  if (us === 0) {
52
82
  return "0s";
53
83
  }
54
84
  if (Math.abs(us) < 1e3) {
55
- return `${floatToStr(us)}${sep}\xB5s`;
85
+ return `${floatToStr(us, roundDigits)}${sep}\xB5s`;
56
86
  }
57
87
  const ms = us / 1e3;
58
88
  if (Math.abs(ms) < 1e3) {
59
- return `${floatToStr(ms)}${sep} ms`;
89
+ return `${floatToStr(ms, roundDigits)}${sep}ms`;
60
90
  }
61
91
  const s = ms / 1e3;
62
92
  if (Math.abs(s) < 60) {
63
- return `${floatToStr(s)}${sep} s`;
93
+ return `${floatToStr(s, roundDigits)}${sep}s`;
64
94
  }
65
95
  const m = s / 60;
66
96
  if (Math.abs(m) < 60) {
67
- return `${floatToStr(m)}${sep} min`;
97
+ return formatMinuteDuration(s);
68
98
  }
69
99
  const h = m / 60;
70
100
  if (Math.abs(h) < 24) {
71
- return `${floatToStr(h)}${sep} hrs`;
101
+ return formatHourDuration(s);
72
102
  }
73
- const d = h / 24;
74
- return `${floatToStr(d)}${sep} days`;
103
+ return formatDayDuration(s);
75
104
  }
76
105
  function formatTimeRangeMs(startMs, endMs) {
77
106
  return `${formatTimeMs(startMs)} - ${formatTimeMs(endMs)}`;
78
107
  }
79
108
  function floatToStr(f, roundDigits = 5) {
80
- if (Number.isInteger(f)) {
109
+ if (roundDigits < 1 || Number.isInteger(f)) {
81
110
  return f.toString();
82
111
  }
83
- for (let i = 1; i < roundDigits - 1; i++) {
84
- const rounded = parseFloat(f.toPrecision(i));
85
- if (rounded === f) {
86
- return rounded.toPrecision(i);
87
- }
112
+ const precision = f.toPrecision(roundDigits);
113
+ return parseFloat(precision).toString();
114
+ }
115
+ function formatMinuteDuration(seconds) {
116
+ const sign = seconds < 0 ? "-" : "";
117
+ const totalSeconds = Math.floor(Math.abs(seconds));
118
+ const minutes = Math.floor(totalSeconds / 60);
119
+ const remainingSeconds = totalSeconds % 60;
120
+ if (remainingSeconds === 0) {
121
+ return `${sign}${minutes}m`;
122
+ }
123
+ return `${sign}${minutes}m${remainingSeconds}s`;
124
+ }
125
+ function formatHourDuration(seconds) {
126
+ const sign = seconds < 0 ? "-" : "";
127
+ const totalMinutes = Math.floor(Math.abs(seconds) / 60);
128
+ const hours = Math.floor(totalMinutes / 60);
129
+ const remainingMinutes = totalMinutes % 60;
130
+ if (remainingMinutes === 0) {
131
+ return `${sign}${hours}h`;
88
132
  }
89
- return f.toPrecision(roundDigits);
133
+ return `${sign}${hours}h${remainingMinutes}m`;
134
+ }
135
+ function formatDayDuration(seconds) {
136
+ const sign = seconds < 0 ? "-" : "";
137
+ const totalHours = Math.floor(Math.abs(seconds) / 3600);
138
+ const days = Math.floor(totalHours / 24);
139
+ const remainingHours = totalHours % 24;
140
+ if (remainingHours === 0) {
141
+ return `${sign}${days}d`;
142
+ }
143
+ return `${sign}${days}d${remainingHours}h`;
90
144
  }
91
145
 
92
146
  // dist/layers/time-delta-layer.js
93
147
  var TimeDeltaLayer = class extends import_core.CompositeLayer {
94
148
  renderLayers() {
95
- const { startTimeMs, endTimeMs, color = [0, 0, 0, 255], yMin, yMax } = this.props;
96
- const timeDeltaPosition = [(startTimeMs + endTimeMs) / 2, 10];
97
- const timeDeltaMs = Math.abs(endTimeMs - startTimeMs);
98
- const timeDeltaLabel = formatTimeMs(timeDeltaMs, false);
149
+ const { startTimeMs, endTimeMs, color: color3 = [0, 0, 0, 255], yMin, yMax } = this.props;
99
150
  if (!this.props.header) {
100
151
  const timeLines2 = [
101
152
  {
@@ -114,21 +165,24 @@ var TimeDeltaLayer = class extends import_core.CompositeLayer {
114
165
  data: timeLines2,
115
166
  getSourcePosition: (d) => d.sourcePosition,
116
167
  getTargetPosition: (d) => d.targetPosition,
117
- getColor: color,
168
+ getColor: color3,
118
169
  getWidth: 4,
119
170
  widthUnits: "pixels"
120
171
  })
121
172
  ];
122
173
  }
123
- const HEADER_Y = 12;
174
+ const { y, fontSize, fontFamily, fontSettings, fontWeight } = this.props;
175
+ const timeDeltaPosition = [(startTimeMs + endTimeMs) / 2, y - 10];
176
+ const timeDeltaMs = Math.abs(endTimeMs - startTimeMs);
177
+ const timeDeltaLabel = formatTimeMs(timeDeltaMs, { space: false });
124
178
  const timeLines = [
125
179
  {
126
- sourcePosition: [startTimeMs, -100],
127
- targetPosition: [startTimeMs, HEADER_Y]
180
+ sourcePosition: [startTimeMs, y],
181
+ targetPosition: [startTimeMs, y - 7]
128
182
  },
129
183
  {
130
- sourcePosition: [endTimeMs, -100],
131
- targetPosition: [endTimeMs, HEADER_Y]
184
+ sourcePosition: [endTimeMs, y],
185
+ targetPosition: [endTimeMs, y - 7]
132
186
  }
133
187
  ];
134
188
  return [
@@ -138,7 +192,7 @@ var TimeDeltaLayer = class extends import_core.CompositeLayer {
138
192
  data: timeLines,
139
193
  getSourcePosition: (d) => d.sourcePosition,
140
194
  getTargetPosition: (d) => d.targetPosition,
141
- getColor: color,
195
+ getColor: color3,
142
196
  getWidth: 4,
143
197
  widthUnits: "pixels"
144
198
  }),
@@ -147,13 +201,13 @@ var TimeDeltaLayer = class extends import_core.CompositeLayer {
147
201
  id: "header-time-delta-dotted-line",
148
202
  data: [
149
203
  {
150
- sourcePosition: [startTimeMs, HEADER_Y - 7],
151
- targetPosition: [endTimeMs, HEADER_Y - 7]
204
+ sourcePosition: [startTimeMs, y - 7],
205
+ targetPosition: [endTimeMs, y - 7]
152
206
  }
153
207
  ],
154
208
  getSourcePosition: (d) => d.sourcePosition,
155
209
  getTargetPosition: (d) => d.targetPosition,
156
- getColor: color,
210
+ getColor: color3,
157
211
  getWidth: 1,
158
212
  widthUnits: "pixels"
159
213
  }),
@@ -163,13 +217,16 @@ var TimeDeltaLayer = class extends import_core.CompositeLayer {
163
217
  data: [{ position: timeDeltaPosition, text: timeDeltaLabel }],
164
218
  getPosition: (d) => d.position,
165
219
  getText: (d) => d.text,
166
- getSize: 12,
167
- getColor: color,
220
+ characterSet: "-0123456789.dhms\xB5",
221
+ getSize: fontSize,
222
+ fontFamily,
223
+ fontSettings,
224
+ fontWeight,
225
+ getColor: color3,
168
226
  getTextAnchor: "middle",
169
- getAlignmentBaseline: "top",
227
+ getAlignmentBaseline: "center",
170
228
  background: true,
171
- getBackgroundColor: [255, 255, 255, 255],
172
- // Solid green background
229
+ getBackgroundColor: [255 - color3[0], 255 - color3[1], 255 - color3[2], 255],
173
230
  backgroundPadding: [4, 2]
174
231
  // Horizontal and vertical padding
175
232
  })
@@ -188,114 +245,2941 @@ __publicField(TimeDeltaLayer, "defaultProps", {
188
245
  unit: "timestamp",
189
246
  yMin: -1e6,
190
247
  // Should cover full viewport height in most cases
191
- yMax: 1e6
248
+ yMax: 1e6,
192
249
  // Should cover full viewport height in most cases
250
+ fontSize: 12,
251
+ fontFamily: import_layers.TextLayer.defaultProps.fontFamily,
252
+ fontSettings: import_layers.TextLayer.defaultProps.fontSettings,
253
+ fontWeight: import_layers.TextLayer.defaultProps.fontWeight
193
254
  });
194
255
 
195
- // dist/views/orthographic-utils.js
196
- function fitBoundsOrthographic(width, height, bounds, zoomMode = "per-axis") {
197
- const [[minX, minY], [maxX, maxY]] = bounds;
198
- const centerX = (minX + maxX) / 2;
199
- const centerY = (minY + maxY) / 2;
200
- const boxW = maxX - minX;
201
- const boxH = maxY - minY;
202
- const scaleX = width / boxW;
203
- const scaleY = height / boxH;
204
- const scale = Math.min(scaleX, scaleY);
205
- const zoom = Math.log2(scale);
206
- const zoomX = Math.log2(scaleX);
207
- const zoomY = Math.log2(scaleY);
208
- if (Number.isNaN(zoom) || Number.isNaN(zoomX) || Number.isNaN(zoom)) {
209
- console.warn("Invalid zoom values:", { zoom, zoomX, zoomY });
256
+ // dist/layers/animation-layer/animation-layer.js
257
+ var import_core2 = require("@deck.gl/core");
258
+
259
+ // dist/layers/animation-layer/animation.js
260
+ var LINEAR_EASING = (t) => t;
261
+ function resolveFramesGroup(group, baseStart) {
262
+ if ("props" in group) {
263
+ const delay2 = group.delay ?? 0;
264
+ const start = baseStart + delay2;
265
+ const end = start + group.duration;
266
+ return {
267
+ frames: [
268
+ {
269
+ from: void 0,
270
+ to: group.props,
271
+ start,
272
+ end,
273
+ easing: group.easing ?? LINEAR_EASING
274
+ }
275
+ ],
276
+ duration: delay2 + group.duration
277
+ };
210
278
  }
211
- return {
212
- target: [centerX, centerY],
213
- zoom: zoomMode === "single" ? zoom : [zoomX, zoomY]
214
- };
279
+ const delay = group.delay ?? 0;
280
+ const frames = [];
281
+ if (group.type === "sequence") {
282
+ let current = baseStart;
283
+ for (let i = 0; i < group.frames.length; i += 1) {
284
+ const child = group.frames[i];
285
+ const childResult = resolveFramesGroup(child, current);
286
+ frames.push(...childResult.frames);
287
+ current += childResult.duration;
288
+ if (i < group.frames.length - 1)
289
+ current += delay;
290
+ }
291
+ return { frames, duration: Math.max(0, current - baseStart) };
292
+ }
293
+ if (group.type === "concurrence") {
294
+ const start = baseStart + delay;
295
+ let maxDuration = 0;
296
+ for (const child of group.frames) {
297
+ const childResult = resolveFramesGroup(child, start);
298
+ frames.push(...childResult.frames);
299
+ if (childResult.duration > maxDuration)
300
+ maxDuration = childResult.duration;
301
+ }
302
+ return { frames, duration: delay + maxDuration };
303
+ }
304
+ let maxEnd = baseStart;
305
+ for (let i = 0; i < group.frames.length; i += 1) {
306
+ const child = group.frames[i];
307
+ const childResult = resolveFramesGroup(child, baseStart + i * delay);
308
+ frames.push(...childResult.frames);
309
+ const childEnd = baseStart + i * delay + childResult.duration;
310
+ if (childEnd > maxEnd)
311
+ maxEnd = childEnd;
312
+ }
313
+ frames.sort((f1, f2) => f1.end - f2.end);
314
+ return { frames, duration: Math.max(0, maxEnd - baseStart) };
315
+ }
316
+ function getFramesDuration(frames) {
317
+ let maxEnd = 0;
318
+ for (const frame of frames) {
319
+ if (frame.end > maxEnd)
320
+ maxEnd = frame.end;
321
+ }
322
+ return maxEnd;
323
+ }
324
+ function reverseResolvedFrames(frames) {
325
+ const duration = getFramesDuration(frames);
326
+ const reversed = [];
327
+ for (let i = frames.length - 1; i >= 0; i -= 1) {
328
+ const frame = frames[i];
329
+ reversed.push({
330
+ from: void 0,
331
+ to: frame.from ?? frame.to,
332
+ start: duration - frame.end,
333
+ end: duration - frame.start,
334
+ easing: frame.easing
335
+ });
336
+ }
337
+ return reversed;
338
+ }
339
+ function resolveAnimationFrames(time, opts, prevState) {
340
+ const { frames, repeat = 0, repeatType = "loop", repeatDelay = 0 } = opts;
341
+ if (!prevState) {
342
+ const resolved = resolveFramesGroup(frames, 0);
343
+ return {
344
+ start: time,
345
+ end: time + resolved.duration,
346
+ inProgress: true,
347
+ iterations: 0,
348
+ frames: resolved.frames
349
+ };
350
+ }
351
+ const state = prevState;
352
+ if (time < state.end) {
353
+ return state;
354
+ }
355
+ const iterationEnd = state.end;
356
+ const iterations = state.iterations + 1;
357
+ if (iterations > repeat) {
358
+ return state;
359
+ }
360
+ const start = iterationEnd + repeatDelay;
361
+ if (repeatType === "reverse" && iterations % 2 === 1) {
362
+ const duration = state.end - state.start;
363
+ return {
364
+ start,
365
+ end: start + duration,
366
+ iterations,
367
+ frames: reverseResolvedFrames(state.frames),
368
+ inProgress: true
369
+ };
370
+ } else {
371
+ const resolved = resolveFramesGroup(frames, 0);
372
+ return {
373
+ start,
374
+ end: start + resolved.duration,
375
+ inProgress: true,
376
+ iterations,
377
+ frames: resolved.frames
378
+ };
379
+ }
380
+ }
381
+ function interpolateProp(from, to, ratio) {
382
+ if (from === void 0 || to === void 0)
383
+ return to;
384
+ if (typeof to === "string" || typeof to === "function")
385
+ return to;
386
+ if (typeof to === "number" && typeof from === "number") {
387
+ return from + (to - from) * ratio;
388
+ }
389
+ if (Array.isArray(to) && Array.isArray(from)) {
390
+ const len = to.length;
391
+ const out = new Array(len);
392
+ for (let i = 0; i < len; i += 1) {
393
+ const toValue = to[i];
394
+ const fromValue = from[i];
395
+ out[i] = typeof toValue === "number" && typeof fromValue === "number" ? fromValue + (toValue - fromValue) * ratio : toValue;
396
+ }
397
+ return out;
398
+ }
399
+ return to;
400
+ }
401
+ function resolveProps(layer, frames, timeSinceStart) {
402
+ if (timeSinceStart < 0 || frames.length === 0)
403
+ return {};
404
+ const baseProps = layer.props;
405
+ const nextProps = {};
406
+ let transitions = baseProps.transitions ? { ...baseProps.transitions } : void 0;
407
+ const updateTriggers = { ...baseProps.updateTriggers };
408
+ const getPropValue = (key) => Object.prototype.hasOwnProperty.call(nextProps, key) ? nextProps[key] : baseProps[key];
409
+ for (const frame of frames) {
410
+ if (timeSinceStart < frame.start)
411
+ continue;
412
+ const duration = frame.end - frame.start;
413
+ if (duration <= 0) {
414
+ Object.assign(nextProps, frame.to);
415
+ continue;
416
+ }
417
+ if (frame.from === void 0) {
418
+ const from = {};
419
+ for (const key of Object.keys(frame.to)) {
420
+ from[key] = getPropValue(key);
421
+ }
422
+ frame.from = from;
423
+ }
424
+ if (timeSinceStart >= frame.end) {
425
+ Object.assign(nextProps, frame.to);
426
+ continue;
427
+ }
428
+ const t = frame.easing((timeSinceStart - frame.start) / duration);
429
+ for (const key of Object.keys(frame.to)) {
430
+ const toValue = frame.to[key];
431
+ const fromValue = frame.from[key];
432
+ if (String(key).startsWith("get") && (typeof fromValue === "function" || typeof toValue === "function")) {
433
+ nextProps[key] = toValue;
434
+ updateTriggers[key] = { ...updateTriggers[key], animation: toValue };
435
+ transitions ??= {};
436
+ transitions[key] = {
437
+ duration: frame.end - frame.start,
438
+ easing: frame.easing
439
+ };
440
+ } else {
441
+ const value = interpolateProp(fromValue, toValue, t);
442
+ if (value !== void 0) {
443
+ nextProps[key] = value;
444
+ }
445
+ }
446
+ }
447
+ }
448
+ return nextProps;
215
449
  }
216
450
 
217
- // dist/views/view-state-utils.js
218
- function mergeViewStates(viewState1, viewState2) {
219
- var _a, _b, _c, _d;
220
- const target1 = viewState1.target ?? [0, 0];
221
- const zoom1 = viewState1.zoom ?? [1, 1];
222
- const mergedViewState = {
223
- ...viewState1,
224
- ...viewState2,
225
- target: [((_a = viewState2.target) == null ? void 0 : _a[0]) ?? target1[0], ((_b = viewState2.target) == null ? void 0 : _b[1]) ?? target1[1]],
226
- zoom: [
227
- // ts-expect-error view state typing is awfully optional
228
- ((_c = viewState2.zoom) == null ? void 0 : _c[0]) ?? zoom1[0],
229
- // ts-expect-error view state typing is awfully optional
230
- ((_d = viewState2.zoom) == null ? void 0 : _d[1]) ?? zoom1[1]
231
- ]
451
+ // dist/layers/animation-layer/animation-layer.js
452
+ var AnimationLayer = class extends import_core2.CompositeLayer {
453
+ state = {};
454
+ // Hack - hijacking another flag to force updates
455
+ hasUniformTransition() {
456
+ if (!this.props.visible)
457
+ return false;
458
+ const { animationState } = this.state;
459
+ return !animationState || animationState.inProgress;
460
+ }
461
+ updateState() {
462
+ if (!this.props.visible) {
463
+ this.state.animationState = void 0;
464
+ this.state.layer = void 0;
465
+ return;
466
+ }
467
+ const time = this.context.timeline.getTime();
468
+ const baseLayer = this.props.layer.clone({
469
+ parameters: {
470
+ ...this.props.layer.props.parameters,
471
+ ...this.props.parameters
472
+ }
473
+ });
474
+ let { animationState } = this.state;
475
+ let layer = baseLayer;
476
+ while (true) {
477
+ if (animationState == null ? void 0 : animationState.inProgress) {
478
+ const nextProps = resolveProps(layer, animationState.frames, time - animationState.start);
479
+ nextProps["id"] = `${this.id}-animation-layer`;
480
+ layer = baseLayer.clone(nextProps);
481
+ animationState.inProgress = time < animationState.end;
482
+ this.setNeedsRedraw();
483
+ }
484
+ const nextState = resolveAnimationFrames(time, this.props, animationState);
485
+ if (nextState === animationState)
486
+ break;
487
+ animationState = nextState;
488
+ }
489
+ this.state.animationState = animationState;
490
+ this.state.layer = layer;
491
+ }
492
+ renderLayers() {
493
+ return this.state.layer;
494
+ }
495
+ };
496
+ __publicField(AnimationLayer, "layerName", "AnimationLayer");
497
+
498
+ // dist/layers/block-layer/block-layer.js
499
+ var import_core3 = require("@deck.gl/core");
500
+ var import_engine = require("@luma.gl/engine");
501
+
502
+ // dist/layers/block-layer/block-layer-fragment.glsl.js
503
+ var block_layer_fragment_glsl_default = `#version 300 es
504
+ #define SHADER_NAME block-layer-fragment-shader
505
+
506
+ precision highp float;
507
+
508
+ in vec2 unitPosition;
509
+ flat in vec4 vFillColor;
510
+ flat in vec4 vLineColor;
511
+ flat in float lineWidth;
512
+ flat in vec2 size;
513
+
514
+ out vec4 fragColor;
515
+
516
+ void main(void) {
517
+ if (lineWidth > 0.0) {
518
+ vec2 relPosition = unitPosition * size;
519
+ float distToBorder =
520
+ min(
521
+ min(
522
+ min(relPosition.x, relPosition.y),
523
+ size.x - relPosition.x
524
+ ),
525
+ size.y - relPosition.y
526
+ );
527
+ if (distToBorder <= lineWidth) {
528
+ fragColor = vLineColor;
529
+ } else {
530
+ fragColor = vFillColor;
531
+ }
532
+ } else {
533
+ fragColor = vFillColor;
534
+ }
535
+
536
+ DECKGL_FILTER_COLOR(fragColor, geometry);
537
+ }
538
+ `;
539
+
540
+ // dist/layers/block-layer/block-layer-uniforms.js
541
+ var glslUniformBlock = `uniform blockUniforms {
542
+ highp int sizeUnits;
543
+ highp float widthMinPixels;
544
+ highp float heightMinPixels;
545
+ highp float sizeMaxPixels;
546
+ highp int lineWidthUnits;
547
+ } block;
548
+ `;
549
+ var blockUniforms = {
550
+ name: "block",
551
+ vs: glslUniformBlock,
552
+ fs: glslUniformBlock,
553
+ uniformTypes: {
554
+ sizeUnits: "i32",
555
+ widthMinPixels: "f32",
556
+ heightMinPixels: "f32",
557
+ sizeMaxPixels: "f32",
558
+ lineWidthUnits: "i32"
559
+ }
560
+ };
561
+
562
+ // dist/layers/block-layer/block-layer-vertex.glsl.js
563
+ var block_layer_vertex_glsl_default = `#version 300 es
564
+ #define SHADER_NAME block-layer-vertex-shader
565
+
566
+ in vec3 positions;
567
+ in vec3 instancePositions;
568
+ in vec3 instancePositions64Low;
569
+ in vec2 instanceSizes;
570
+ in float instanceLineWidths;
571
+ in vec4 instanceFillColors;
572
+ in vec4 instanceLineColors;
573
+ in vec3 instancePickingColors;
574
+
575
+ out vec2 unitPosition;
576
+ flat out vec4 vFillColor;
577
+ flat out vec4 vLineColor;
578
+ flat out float lineWidth;
579
+ flat out vec2 size;
580
+
581
+ // This needs to be added back to the project module
582
+ vec2 project_size_to_pixel(vec2 size, int unit) {
583
+ if (unit == UNIT_PIXELS) return size;
584
+ if (unit == UNIT_COMMON && project.projectionMode != PROJECTION_MODE_IDENTITY) {
585
+ return size * project.scale;
586
+ }
587
+ return project_size(size) * project.scale;
588
+ }
589
+
590
+ float clamp_signed_size(float size, float minPixels, float maxPixels) {
591
+ float clampedMagnitude = clamp(abs(size), minPixels, maxPixels);
592
+ if (size < 0.0) {
593
+ return -clampedMagnitude;
594
+ }
595
+ return clampedMagnitude;
596
+ }
597
+
598
+ void main(void) {
599
+ geometry.worldPosition = instancePositions;
600
+ geometry.pickingColor = instancePickingColors;
601
+ geometry.uv = positions.xy;
602
+
603
+ vec2 pixelSize = project_size_to_pixel(instanceSizes, block.sizeUnits);
604
+ pixelSize.x = clamp_signed_size(pixelSize.x, block.widthMinPixels, block.sizeMaxPixels);
605
+ pixelSize.y = clamp_signed_size(pixelSize.y, block.heightMinPixels, block.sizeMaxPixels);
606
+ unitPosition = positions.xy;
607
+ size = pixelSize;
608
+ lineWidth = project_size_to_pixel(vec2(instanceLineWidths, 0.0), block.lineWidthUnits).x;
609
+
610
+ // Find the center of the point and add the current vertex
611
+ vec3 offset = vec3(unitPosition * project_pixel_size(pixelSize), 0.0);
612
+ DECKGL_FILTER_SIZE(offset, geometry);
613
+
614
+ gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, offset, geometry.position);
615
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
616
+
617
+ // Apply opacity to instance color, or return instance picking color
618
+ vFillColor = vec4(instanceFillColors.rgb, instanceFillColors.a * layer.opacity);
619
+ DECKGL_FILTER_COLOR(vFillColor, geometry);
620
+
621
+ vLineColor = vec4(instanceLineColors.rgb, instanceLineColors.a * layer.opacity);
622
+ DECKGL_FILTER_COLOR(vLineColor, geometry);
623
+ }
624
+ `;
625
+
626
+ // dist/layers/block-layer/block-layer.js
627
+ var DEFAULT_COLOR = [0, 0, 0, 255];
628
+ var defaultProps = {
629
+ sizeUnits: "meters",
630
+ widthMinPixels: { type: "number", min: 0, value: 0 },
631
+ heightMinPixels: { type: "number", min: 0, value: 0 },
632
+ sizeMaxPixels: { type: "number", min: 0, value: Number.MAX_SAFE_INTEGER },
633
+ lineWidthUnits: "pixels",
634
+ getPosition: { type: "accessor", value: (x) => x.position },
635
+ getSize: { type: "accessor", value: [10, 10] },
636
+ getLineWidth: { type: "accessor", value: 1 },
637
+ getFillColor: { type: "accessor", value: DEFAULT_COLOR },
638
+ getLineColor: { type: "accessor", value: DEFAULT_COLOR }
639
+ };
640
+ var BlockLayer = class extends import_core3.Layer {
641
+ state = {};
642
+ getShaders() {
643
+ return super.getShaders({
644
+ vs: block_layer_vertex_glsl_default,
645
+ fs: block_layer_fragment_glsl_default,
646
+ modules: [import_core3.project32, import_core3.color, import_core3.picking, blockUniforms]
647
+ });
648
+ }
649
+ initializeState() {
650
+ this.getAttributeManager().addInstanced({
651
+ instancePositions: {
652
+ size: 3,
653
+ type: "float64",
654
+ fp64: this.use64bitPositions(),
655
+ transition: true,
656
+ accessor: "getPosition"
657
+ },
658
+ instanceSizes: {
659
+ size: 2,
660
+ transition: true,
661
+ accessor: "getSize"
662
+ },
663
+ instanceLineWidths: {
664
+ size: 1,
665
+ transition: true,
666
+ accessor: "getLineWidth"
667
+ },
668
+ instanceLineColors: {
669
+ size: this.props.colorFormat.length,
670
+ type: "unorm8",
671
+ transition: true,
672
+ accessor: "getLineColor",
673
+ defaultValue: DEFAULT_COLOR
674
+ },
675
+ instanceFillColors: {
676
+ size: this.props.colorFormat.length,
677
+ type: "unorm8",
678
+ transition: true,
679
+ accessor: "getFillColor",
680
+ defaultValue: DEFAULT_COLOR
681
+ }
682
+ });
683
+ }
684
+ updateState(params) {
685
+ var _a;
686
+ const { changeFlags } = params;
687
+ super.updateState(params);
688
+ if (changeFlags.extensionsChanged) {
689
+ (_a = this.state.model) == null ? void 0 : _a.destroy();
690
+ this.state.model = this._getModel();
691
+ this.getAttributeManager().invalidateAll();
692
+ }
693
+ }
694
+ draw() {
695
+ const { sizeUnits, widthMinPixels, heightMinPixels, sizeMaxPixels, lineWidthUnits } = this.props;
696
+ const model = this.state.model;
697
+ const blockProps = {
698
+ sizeUnits: import_core3.UNIT[sizeUnits],
699
+ widthMinPixels,
700
+ heightMinPixels,
701
+ sizeMaxPixels,
702
+ lineWidthUnits: import_core3.UNIT[lineWidthUnits]
703
+ };
704
+ model.shaderInputs.setProps({ block: blockProps });
705
+ model.draw(this.context.renderPass);
706
+ }
707
+ _getModel() {
708
+ const positions = [0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0];
709
+ return new import_engine.Model(this.context.device, {
710
+ ...this.getShaders(),
711
+ id: this.props.id,
712
+ bufferLayout: this.getAttributeManager().getBufferLayouts(),
713
+ geometry: new import_engine.Geometry({
714
+ topology: "triangle-strip",
715
+ attributes: {
716
+ positions: new Float32Array(positions)
717
+ }
718
+ }),
719
+ isInstanced: true
720
+ });
721
+ }
722
+ };
723
+ __publicField(BlockLayer, "layerName", "BlockLayer");
724
+ __publicField(BlockLayer, "defaultProps", defaultProps);
725
+
726
+ // dist/layers/fast-text-layer/fast-text-layer.js
727
+ var import_core5 = require("@deck.gl/core");
728
+ var import_core6 = require("@luma.gl/core");
729
+ var import_engine2 = require("@luma.gl/engine");
730
+ var import_log = require("@probe.gl/log");
731
+
732
+ // dist/layers/fast-text-layer/fast-text-layout.js
733
+ var import_core4 = require("@deck.gl/core");
734
+
735
+ // dist/utils/utf8-string-view.js
736
+ var textEncoder = new TextEncoder();
737
+ var textDecoder = new TextDecoder();
738
+ function makeUtf8StringView(value) {
739
+ const data = textEncoder.encode(value);
740
+ return { data, start: 0, end: data.length };
741
+ }
742
+ function getArrowUtf8ColumnSource(utf8Column) {
743
+ const chunks = getArrowUtf8DataChunks(utf8Column);
744
+ if (!chunks || chunks.length === 0) {
745
+ return null;
746
+ }
747
+ const sourceChunks = [];
748
+ let rowOffset = 0;
749
+ for (const chunk of chunks) {
750
+ const valueOffsets = chunk.valueOffsets;
751
+ const values = chunk.values;
752
+ if (!valueOffsets || !values) {
753
+ return null;
754
+ }
755
+ sourceChunks.push({
756
+ rowOffset,
757
+ rowCount: chunk.length,
758
+ valueOffsetIndex: 0,
759
+ valueOffsets,
760
+ values
761
+ });
762
+ rowOffset += chunk.length;
763
+ }
764
+ return {
765
+ rowCount: utf8Column.length,
766
+ chunks: sourceChunks,
767
+ isValid: (rowIndex) => utf8Column.isValid(rowIndex)
232
768
  };
233
- validateViewState(mergedViewState);
234
- return mergedViewState;
235
769
  }
236
- function validateViewState(viewState) {
237
- const isTargetValid = Array.isArray(viewState.target) && viewState.target[0] !== void 0 && !Number.isNaN(viewState.target[0]) && viewState.target[1] !== void 0 && !Number.isNaN(viewState.target[1]);
238
- const isZoomValid = Array.isArray(viewState.zoom) && viewState.zoom[0] !== void 0 && !Number.isNaN(viewState.zoom[0]) && viewState.zoom[1] !== void 0 && !Number.isNaN(viewState.zoom[1]);
239
- if (!isTargetValid || !isZoomValid) {
240
- console.warn("Invalid viewState:", viewState);
770
+ function getArrowUtf8RowView(utf8Column, rowIndex, out) {
771
+ if (!Number.isInteger(rowIndex) || rowIndex < 0 || rowIndex >= utf8Column.length) {
772
+ return false;
241
773
  }
242
- return isTargetValid && isZoomValid;
774
+ if (!utf8Column.isValid(rowIndex)) {
775
+ return false;
776
+ }
777
+ const chunks = getArrowUtf8DataChunks(utf8Column);
778
+ if (!chunks || chunks.length === 0) {
779
+ return false;
780
+ }
781
+ let rowOffset = 0;
782
+ for (const chunk of chunks) {
783
+ const chunkEnd = rowOffset + chunk.length;
784
+ if (rowIndex >= rowOffset && rowIndex < chunkEnd) {
785
+ const valueOffsets = chunk.valueOffsets;
786
+ const values = chunk.values;
787
+ if (!valueOffsets || !values) {
788
+ return false;
789
+ }
790
+ return fillUtf8StringView(valueOffsets, values, rowIndex - rowOffset, out);
791
+ }
792
+ rowOffset = chunkEnd;
793
+ }
794
+ return false;
795
+ }
796
+ function getUtf8ColumnSourceRowView(source, rowIndex, out) {
797
+ if (!Number.isInteger(rowIndex) || rowIndex < 0 || rowIndex >= source.rowCount) {
798
+ return false;
799
+ }
800
+ if (!source.isValid(rowIndex)) {
801
+ return false;
802
+ }
803
+ for (const chunk of source.chunks) {
804
+ const chunkEnd = chunk.rowOffset + chunk.rowCount;
805
+ if (rowIndex < chunk.rowOffset || rowIndex >= chunkEnd) {
806
+ continue;
807
+ }
808
+ return fillUtf8StringView(chunk.valueOffsets, chunk.values, chunk.valueOffsetIndex + rowIndex - chunk.rowOffset, out);
809
+ }
810
+ return false;
811
+ }
812
+ function arrowFindUtf8(utf8Column, value, startRow = 0) {
813
+ const normalizedStartRow = Math.max(0, startRow);
814
+ const fastResult = arrowFindUtf8InDataChunks(utf8Column, value, normalizedStartRow);
815
+ if (fastResult !== null) {
816
+ return fastResult;
817
+ }
818
+ const expected = decodeUtf8StringView(value);
819
+ for (let rowIndex = normalizedStartRow; rowIndex < utf8Column.length; rowIndex += 1) {
820
+ if (utf8Column.get(rowIndex) === expected) {
821
+ return rowIndex;
822
+ }
823
+ }
824
+ return -1;
825
+ }
826
+ function arrowFindUtf8InDataChunks(utf8Column, value, startRow) {
827
+ const chunks = getArrowUtf8DataChunks(utf8Column);
828
+ if (!chunks || chunks.length === 0) {
829
+ return null;
830
+ }
831
+ let globalRowOffset = 0;
832
+ for (const chunk of chunks) {
833
+ const valueOffsets = chunk.valueOffsets;
834
+ const values = chunk.values;
835
+ if (!valueOffsets || !values) {
836
+ return null;
837
+ }
838
+ const chunkStartRow = Math.max(0, startRow - globalRowOffset);
839
+ for (let chunkRow = chunkStartRow; chunkRow < chunk.length; chunkRow += 1) {
840
+ const globalRow = globalRowOffset + chunkRow;
841
+ if (!utf8Column.isValid(globalRow)) {
842
+ continue;
843
+ }
844
+ const start = valueOffsets[chunkRow];
845
+ const end = valueOffsets[chunkRow + 1];
846
+ if (start !== void 0 && end !== void 0 && utf8BytesEqual(values, start, end, value)) {
847
+ return globalRow;
848
+ }
849
+ }
850
+ globalRowOffset += chunk.length;
851
+ }
852
+ return -1;
853
+ }
854
+ function getArrowUtf8DataChunks(utf8Column) {
855
+ return utf8Column.data;
856
+ }
857
+ function fillUtf8StringView(valueOffsets, values, offsetIndex, out) {
858
+ const start = valueOffsets[offsetIndex];
859
+ const end = valueOffsets[offsetIndex + 1];
860
+ if (start === void 0 || end === void 0) {
861
+ return false;
862
+ }
863
+ out.data = values;
864
+ out.start = start;
865
+ out.end = end;
866
+ return true;
867
+ }
868
+ function utf8BytesEqual(data, start, end, value) {
869
+ const valueLength = value.end - value.start;
870
+ if (end - start !== valueLength) {
871
+ return false;
872
+ }
873
+ for (let index = 0; index < valueLength; index += 1) {
874
+ if (data[start + index] !== value.data[value.start + index]) {
875
+ return false;
876
+ }
877
+ }
878
+ return true;
879
+ }
880
+ function decodeUtf8StringView(value) {
881
+ return textDecoder.decode(value.data.subarray(value.start, value.end));
243
882
  }
244
883
 
245
- // dist/views/layer-filter.js
246
- function makeLayerFilter(filters) {
247
- const regexpFilters = {};
248
- for (const [key, value] of Object.entries(filters)) {
249
- if ("include" in value) {
250
- regexpFilters[key] = {
251
- include: value.include.map((v) => new RegExp(v))
252
- };
884
+ // dist/layers/fast-text-layer/fast-text-layout.js
885
+ var FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE = Int16Array.BYTES_PER_ELEMENT * 10 + Uint8Array.BYTES_PER_ELEMENT * 4;
886
+ function buildFastTextUtf8ColumnSource(utf8Column) {
887
+ return getArrowUtf8ColumnSource(utf8Column);
888
+ }
889
+ function collectFastTextCharacterSet(props) {
890
+ const characterSet = /* @__PURE__ */ new Set();
891
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
892
+ for (const object of iterable) {
893
+ objectInfo.index++;
894
+ const text = resolveAccessor(props.getText, object, objectInfo) ?? "";
895
+ for (const character of Array.from(text)) {
896
+ if (character !== "\n") {
897
+ characterSet.add(character);
898
+ }
899
+ }
900
+ }
901
+ return characterSet;
902
+ }
903
+ function buildFastTextGlyphData(props) {
904
+ const buildStartTime = performance.now();
905
+ const columnNormalizeStartTime = performance.now();
906
+ const textUtf8Column = resolveFastTextUtf8ColumnSource(props.textUtf8Column);
907
+ const columnNormalizeDurationMs = performance.now() - columnNormalizeStartTime;
908
+ if (props.textUtf8Column && !textUtf8Column) {
909
+ throw new Error("FastTextLayer textUtf8Column must expose Arrow Utf8 buffers");
910
+ }
911
+ if ((textUtf8Column || props.getTextUtf8) && !props.singleLine) {
912
+ throw new Error("FastTextLayer UTF-8 text sources require singleLine text layout");
913
+ }
914
+ const glyphData = props.singleLine ? buildSingleLineGlyphData({
915
+ ...props,
916
+ textUtf8Column
917
+ }) : buildMultiLineGlyphData(props);
918
+ return withFastTextGlyphBuildStats(glyphData, {
919
+ columnNormalizeDurationMs,
920
+ totalDurationMs: performance.now() - buildStartTime
921
+ });
922
+ }
923
+ function buildSingleLineGlyphData(props) {
924
+ const buildStartTime = performance.now();
925
+ const countStartTime = performance.now();
926
+ const countResult = countSingleLineFastTextGlyphs(props);
927
+ const countDurationMs = performance.now() - countStartTime;
928
+ const allocateStartTime = performance.now();
929
+ const attributes = allocateFastTextGlyphAttributes(countResult.glyphCount);
930
+ const startIndices = new Uint32Array(countResult.rowCount + 1);
931
+ const allocateDurationMs = performance.now() - allocateStartTime;
932
+ const writeState = {
933
+ glyphIndex: 0,
934
+ startIndices,
935
+ attributes,
936
+ glyphRecordViews: createFastTextGlyphRecordViews(attributes.instanceGlyphData)
937
+ };
938
+ const writeTimings = createFastTextGlyphWriteTimings();
939
+ const byteLookup = props.textUtf8Column || props.getTextUtf8 ? buildFastTextByteGlyphLookup(props.mapping) : null;
940
+ const scratchUtf8View = { data: EMPTY_BYTES, start: 0, end: 0 };
941
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
942
+ const writeStartTime = performance.now();
943
+ for (const object of iterable) {
944
+ objectInfo.index++;
945
+ startIndices[objectInfo.index] = writeState.glyphIndex;
946
+ if (props.textUtf8Column && byteLookup) {
947
+ writeSingleLineUtf8LabelGlyphs(props, props.textUtf8Column, byteLookup, scratchUtf8View, object, objectInfo, writeState, writeTimings);
948
+ } else if (props.getTextUtf8 && byteLookup) {
949
+ writeSingleLineUtf8ViewLabelGlyphs(props, props.getTextUtf8, byteLookup, scratchUtf8View, object, objectInfo, writeState, writeTimings);
253
950
  } else {
254
- regexpFilters[key] = {
255
- exclude: value.exclude.map((v) => new RegExp(v))
256
- };
951
+ writeSingleLineStringLabelGlyphs(props, object, objectInfo, writeState, writeTimings);
257
952
  }
258
953
  }
259
- return ({ viewport, layer }) => {
260
- let visible = true;
261
- const viewFilters = regexpFilters[viewport.id] || {};
262
- if ("include" in viewFilters) {
263
- if (!viewFilters.include.some((regexp) => regexp.test(layer.id))) {
264
- visible = false;
954
+ startIndices[countResult.rowCount] = writeState.glyphIndex;
955
+ const writeDurationMs = performance.now() - writeStartTime;
956
+ return createFastTextGlyphData(countResult, startIndices, attributes, {
957
+ sourceMode: props.textUtf8Column ? "utf8-column" : props.getTextUtf8 ? "utf8-view" : "string",
958
+ layoutMode: "single-line",
959
+ columnNormalizeDurationMs: 0,
960
+ countDurationMs,
961
+ allocateDurationMs,
962
+ writeDurationMs,
963
+ ...writeTimings,
964
+ totalDurationMs: performance.now() - buildStartTime
965
+ });
966
+ }
967
+ function buildMultiLineGlyphData(props) {
968
+ const buildStartTime = performance.now();
969
+ const countStartTime = performance.now();
970
+ const countResult = countMultiLineFastTextGlyphs(props);
971
+ const countDurationMs = performance.now() - countStartTime;
972
+ const allocateStartTime = performance.now();
973
+ const attributes = allocateFastTextGlyphAttributes(countResult.glyphCount);
974
+ const startIndices = new Uint32Array(countResult.rowCount + 1);
975
+ const allocateDurationMs = performance.now() - allocateStartTime;
976
+ const writeState = {
977
+ glyphIndex: 0,
978
+ startIndices,
979
+ attributes,
980
+ glyphRecordViews: createFastTextGlyphRecordViews(attributes.instanceGlyphData)
981
+ };
982
+ const writeTimings = createFastTextGlyphWriteTimings();
983
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
984
+ const writeStartTime = performance.now();
985
+ for (const object of iterable) {
986
+ objectInfo.index++;
987
+ startIndices[objectInfo.index] = writeState.glyphIndex;
988
+ writeMultiLineLabelGlyphs(props, object, objectInfo, writeState, writeTimings);
989
+ }
990
+ startIndices[countResult.rowCount] = writeState.glyphIndex;
991
+ const writeDurationMs = performance.now() - writeStartTime;
992
+ return createFastTextGlyphData(countResult, startIndices, attributes, {
993
+ sourceMode: "string",
994
+ layoutMode: "multi-line",
995
+ columnNormalizeDurationMs: 0,
996
+ countDurationMs,
997
+ allocateDurationMs,
998
+ writeDurationMs,
999
+ ...writeTimings,
1000
+ totalDurationMs: performance.now() - buildStartTime
1001
+ });
1002
+ }
1003
+ function updateFastTextDynamicGlyphAttributes(props) {
1004
+ const updateStartTime = performance.now();
1005
+ const glyphRecordViews = createFastTextGlyphRecordViews(props.glyphData.attributes.instanceGlyphData);
1006
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
1007
+ let rowCount = 0;
1008
+ let glyphCount = 0;
1009
+ let positionAccessorDurationMs = 0;
1010
+ let colorAccessorDurationMs = 0;
1011
+ let clipRectAccessorDurationMs = 0;
1012
+ let writeDurationMs = 0;
1013
+ for (const object of iterable) {
1014
+ objectInfo.index++;
1015
+ rowCount++;
1016
+ const rowGlyphStart = props.glyphData.startIndices[objectInfo.index] ?? 0;
1017
+ const rowGlyphEnd = props.glyphData.startIndices[objectInfo.index + 1] ?? rowGlyphStart;
1018
+ if (rowGlyphEnd <= rowGlyphStart) {
1019
+ continue;
1020
+ }
1021
+ let position = DEFAULT_POSITION;
1022
+ let color3 = DEFAULT_COLOR2;
1023
+ let clipRect = DEFAULT_CLIP_RECT;
1024
+ if (props.updatePositions) {
1025
+ const accessorStartTime = performance.now();
1026
+ position = resolveAccessor(props.getPosition, object, objectInfo) ?? DEFAULT_POSITION;
1027
+ positionAccessorDurationMs += performance.now() - accessorStartTime;
1028
+ }
1029
+ if (props.updateColors) {
1030
+ const accessorStartTime = performance.now();
1031
+ color3 = resolveAccessor(props.getColor, object, objectInfo) ?? DEFAULT_COLOR2;
1032
+ colorAccessorDurationMs += performance.now() - accessorStartTime;
1033
+ }
1034
+ if (props.updateClipRects) {
1035
+ const accessorStartTime = performance.now();
1036
+ clipRect = resolveAccessor(props.getClipRect, object, objectInfo) ?? DEFAULT_CLIP_RECT;
1037
+ clipRectAccessorDurationMs += performance.now() - accessorStartTime;
1038
+ }
1039
+ const writeStartTime = performance.now();
1040
+ for (let glyphIndex = rowGlyphStart; glyphIndex < rowGlyphEnd; glyphIndex += 1) {
1041
+ if (props.updatePositions) {
1042
+ writeFastTextGlyphPosition(props.glyphData.attributes, glyphIndex, position);
1043
+ }
1044
+ if (props.updateClipRects) {
1045
+ writeFastTextGlyphClipRect(glyphRecordViews, glyphIndex, clipRect);
1046
+ }
1047
+ if (props.updateColors) {
1048
+ writeFastTextGlyphColor(glyphRecordViews, glyphIndex, color3);
265
1049
  }
266
1050
  }
267
- if ("exclude" in viewFilters) {
268
- if (viewFilters.exclude.some((regexp) => regexp.test(layer.id))) {
269
- visible = false;
1051
+ writeDurationMs += performance.now() - writeStartTime;
1052
+ glyphCount += rowGlyphEnd - rowGlyphStart;
1053
+ }
1054
+ return {
1055
+ rowCount,
1056
+ glyphCount,
1057
+ attributeByteLength: props.glyphData.byteLength,
1058
+ positionAccessorDurationMs,
1059
+ colorAccessorDurationMs,
1060
+ clipRectAccessorDurationMs,
1061
+ writeDurationMs,
1062
+ totalDurationMs: performance.now() - updateStartTime
1063
+ };
1064
+ }
1065
+ var MISSING_CHARACTER_ADVANCE = 32;
1066
+ var FAST_TEXT_BYTE_LOOKUP_SIZE = 256;
1067
+ var EMPTY_BYTES = new Uint8Array();
1068
+ var DEFAULT_COLOR2 = [0, 0, 0, 255];
1069
+ var DEFAULT_POSITION = [0, 0, 0];
1070
+ var DEFAULT_CLIP_RECT = [0, 0, -1, -1];
1071
+ var ANCHOR_OFFSET_MULTIPLIER = {
1072
+ start: 0,
1073
+ middle: -0.5,
1074
+ end: -1
1075
+ };
1076
+ var BASELINE_OFFSET_MULTIPLIER = {
1077
+ top: 0,
1078
+ center: -0.5,
1079
+ bottom: -1
1080
+ };
1081
+ function countSingleLineFastTextGlyphs(props) {
1082
+ if (props.textUtf8Column) {
1083
+ return countSingleLineUtf8FastTextGlyphs(props, props.textUtf8Column);
1084
+ }
1085
+ if (props.getTextUtf8) {
1086
+ return countSingleLineUtf8ViewFastTextGlyphs(props, props.getTextUtf8);
1087
+ }
1088
+ return countSingleLineStringFastTextGlyphs(props);
1089
+ }
1090
+ function countSingleLineUtf8FastTextGlyphs(props, textUtf8Column) {
1091
+ let glyphCount = 0;
1092
+ let rowCount = 0;
1093
+ const characterSet = /* @__PURE__ */ new Set();
1094
+ const textView = { data: EMPTY_BYTES, start: 0, end: 0 };
1095
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
1096
+ for (const object of iterable) {
1097
+ objectInfo.index++;
1098
+ rowCount++;
1099
+ const rowIndex = resolveTextUtf8Row(props.getTextUtf8Row, object, objectInfo);
1100
+ if (rowIndex == null || !getUtf8ColumnSourceRowView(textUtf8Column, rowIndex, textView)) {
1101
+ continue;
1102
+ }
1103
+ glyphCount += textView.end - textView.start;
1104
+ }
1105
+ return { glyphCount, rowCount, characterSet };
1106
+ }
1107
+ function countSingleLineUtf8ViewFastTextGlyphs(props, getTextUtf8) {
1108
+ let glyphCount = 0;
1109
+ let rowCount = 0;
1110
+ const characterSet = /* @__PURE__ */ new Set();
1111
+ const textView = { data: EMPTY_BYTES, start: 0, end: 0 };
1112
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
1113
+ for (const object of iterable) {
1114
+ objectInfo.index++;
1115
+ rowCount++;
1116
+ if (getTextUtf8(object, textView, objectInfo)) {
1117
+ glyphCount += Math.max(0, textView.end - textView.start);
1118
+ }
1119
+ }
1120
+ return { glyphCount, rowCount, characterSet };
1121
+ }
1122
+ function countSingleLineStringFastTextGlyphs(props) {
1123
+ let glyphCount = 0;
1124
+ let rowCount = 0;
1125
+ const characterSet = /* @__PURE__ */ new Set();
1126
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
1127
+ for (const object of iterable) {
1128
+ objectInfo.index++;
1129
+ rowCount++;
1130
+ const text = resolveAccessor(props.getText, object, objectInfo) ?? "";
1131
+ glyphCount += text.length;
1132
+ for (let index = 0; index < text.length; index += 1) {
1133
+ characterSet.add(text[index]);
1134
+ }
1135
+ }
1136
+ return { glyphCount, rowCount, characterSet };
1137
+ }
1138
+ function countMultiLineFastTextGlyphs(props) {
1139
+ let glyphCount = 0;
1140
+ let rowCount = 0;
1141
+ const characterSet = /* @__PURE__ */ new Set();
1142
+ const { iterable, objectInfo } = (0, import_core4.createIterable)(props.data);
1143
+ for (const object of iterable) {
1144
+ objectInfo.index++;
1145
+ rowCount++;
1146
+ const text = resolveAccessor(props.getText, object, objectInfo) ?? "";
1147
+ for (const character of Array.from(text)) {
1148
+ if (character === "\n") {
1149
+ continue;
270
1150
  }
1151
+ characterSet.add(character);
1152
+ glyphCount++;
271
1153
  }
272
- return visible;
1154
+ }
1155
+ return { glyphCount, rowCount, characterSet };
1156
+ }
1157
+ function allocateFastTextGlyphAttributes(glyphCount) {
1158
+ return {
1159
+ instanceGlyphData: new Uint8Array(glyphCount * FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE),
1160
+ instancePositions: new Float32Array(glyphCount * 2)
273
1161
  };
274
1162
  }
275
-
276
- // dist/synchronized-views/synchronized-views.js
277
- var import_core2 = require("@deck.gl/core");
278
- var HEADER_VIEW_HEIGHT = 50;
279
- var LEGEND_VIEW_WIDTH = 150;
280
- var SYNCHRONIZED_VIEWS = [
281
- new import_core2.OrthographicView({
282
- id: "main",
283
- flipY: false,
284
- clear: true,
285
- // [1, 1, 1, 1],
286
- x: LEGEND_VIEW_WIDTH,
287
- width: `calc(100% - ${LEGEND_VIEW_WIDTH}px`,
1163
+ function createFastTextGlyphRecordViews(instanceGlyphData) {
1164
+ return {
1165
+ int16Values: new Int16Array(instanceGlyphData.buffer),
1166
+ uint16Values: new Uint16Array(instanceGlyphData.buffer),
1167
+ uint8Values: instanceGlyphData
1168
+ };
1169
+ }
1170
+ function createFastTextGlyphData(countResult, startIndices, attributes, stats) {
1171
+ const byteLength = startIndices.byteLength + attributes.instanceGlyphData.byteLength + attributes.instancePositions.byteLength;
1172
+ return {
1173
+ length: countResult.glyphCount,
1174
+ startIndices,
1175
+ attributes,
1176
+ characterSet: countResult.characterSet,
1177
+ byteLength,
1178
+ buildStats: {
1179
+ ...stats,
1180
+ rowCount: countResult.rowCount,
1181
+ glyphCount: countResult.glyphCount,
1182
+ attributeByteLength: byteLength
1183
+ }
1184
+ };
1185
+ }
1186
+ function createFastTextGlyphWriteTimings() {
1187
+ return {
1188
+ textResolveDurationMs: 0,
1189
+ styleAccessorDurationMs: 0,
1190
+ layoutDurationMs: 0,
1191
+ glyphWriteDurationMs: 0
1192
+ };
1193
+ }
1194
+ function withFastTextGlyphBuildStats(glyphData, stats) {
1195
+ return {
1196
+ ...glyphData,
1197
+ buildStats: {
1198
+ ...glyphData.buildStats,
1199
+ ...stats
1200
+ }
1201
+ };
1202
+ }
1203
+ function writeSingleLineStringLabelGlyphs(props, object, objectInfo, writeState, timings) {
1204
+ const textResolveStartTime = performance.now();
1205
+ const text = resolveAccessor(props.getText, object, objectInfo) ?? "";
1206
+ timings.textResolveDurationMs += performance.now() - textResolveStartTime;
1207
+ if (!text) {
1208
+ return;
1209
+ }
1210
+ const styleAccessorStartTime = performance.now();
1211
+ const position = resolveAccessor(props.getPosition, object, objectInfo) ?? DEFAULT_POSITION;
1212
+ const color3 = resolveAccessor(props.getColor, object, objectInfo) ?? DEFAULT_COLOR2;
1213
+ const clipRect = resolveAccessor(props.getClipRect, object, objectInfo) ?? DEFAULT_CLIP_RECT;
1214
+ timings.styleAccessorDurationMs += performance.now() - styleAccessorStartTime;
1215
+ const layoutStartTime = performance.now();
1216
+ const width = getSingleLineStringWidth(text, props.mapping);
1217
+ const lineOffsetX = ANCHOR_OFFSET_MULTIPLIER[props.textAnchor] * width;
1218
+ const rowBaselineY = getSingleLineBaselineY(props);
1219
+ timings.layoutDurationMs += performance.now() - layoutStartTime;
1220
+ let cursorX = 0;
1221
+ const glyphWriteStartTime = performance.now();
1222
+ for (let index = 0; index < text.length; index += 1) {
1223
+ const character = text[index];
1224
+ const frame = props.mapping[character];
1225
+ writeFastTextGlyphRecord({
1226
+ frame,
1227
+ lineOffsetX,
1228
+ cursorX,
1229
+ rowBaselineY,
1230
+ position,
1231
+ color: color3,
1232
+ clipRect,
1233
+ writeState
1234
+ });
1235
+ cursorX += (frame == null ? void 0 : frame.advance) ?? MISSING_CHARACTER_ADVANCE;
1236
+ }
1237
+ timings.glyphWriteDurationMs += performance.now() - glyphWriteStartTime;
1238
+ }
1239
+ function writeSingleLineUtf8LabelGlyphs(props, textUtf8Column, byteLookup, textView, object, objectInfo, writeState, timings) {
1240
+ const textResolveStartTime = performance.now();
1241
+ const rowIndex = resolveTextUtf8Row(props.getTextUtf8Row, object, objectInfo);
1242
+ const hasTextView = rowIndex != null && getUtf8ColumnSourceRowView(textUtf8Column, rowIndex, textView);
1243
+ timings.textResolveDurationMs += performance.now() - textResolveStartTime;
1244
+ if (!hasTextView) {
1245
+ return;
1246
+ }
1247
+ if (textView.end <= textView.start) {
1248
+ return;
1249
+ }
1250
+ const styleAccessorStartTime = performance.now();
1251
+ const position = resolveAccessor(props.getPosition, object, objectInfo) ?? DEFAULT_POSITION;
1252
+ const color3 = resolveAccessor(props.getColor, object, objectInfo) ?? DEFAULT_COLOR2;
1253
+ const clipRect = resolveAccessor(props.getClipRect, object, objectInfo) ?? DEFAULT_CLIP_RECT;
1254
+ timings.styleAccessorDurationMs += performance.now() - styleAccessorStartTime;
1255
+ const layoutStartTime = performance.now();
1256
+ const width = getSingleLineUtf8Width(textView, byteLookup);
1257
+ const lineOffsetX = ANCHOR_OFFSET_MULTIPLIER[props.textAnchor] * width;
1258
+ const rowBaselineY = getSingleLineBaselineY(props);
1259
+ timings.layoutDurationMs += performance.now() - layoutStartTime;
1260
+ let cursorX = 0;
1261
+ const glyphWriteStartTime = performance.now();
1262
+ for (let byteIndex = textView.start; byteIndex < textView.end; byteIndex += 1) {
1263
+ const frame = byteLookup[textView.data[byteIndex] ?? -1];
1264
+ writeFastTextGlyphRecord({
1265
+ frame,
1266
+ lineOffsetX,
1267
+ cursorX,
1268
+ rowBaselineY,
1269
+ position,
1270
+ color: color3,
1271
+ clipRect,
1272
+ writeState
1273
+ });
1274
+ cursorX += (frame == null ? void 0 : frame.advance) ?? MISSING_CHARACTER_ADVANCE;
1275
+ }
1276
+ timings.glyphWriteDurationMs += performance.now() - glyphWriteStartTime;
1277
+ }
1278
+ function writeSingleLineUtf8ViewLabelGlyphs(props, getTextUtf8, byteLookup, textView, object, objectInfo, writeState, timings) {
1279
+ const textResolveStartTime = performance.now();
1280
+ const hasTextView = getTextUtf8(object, textView, objectInfo);
1281
+ timings.textResolveDurationMs += performance.now() - textResolveStartTime;
1282
+ if (!hasTextView || textView.end <= textView.start) {
1283
+ return;
1284
+ }
1285
+ const styleAccessorStartTime = performance.now();
1286
+ const position = resolveAccessor(props.getPosition, object, objectInfo) ?? DEFAULT_POSITION;
1287
+ const color3 = resolveAccessor(props.getColor, object, objectInfo) ?? DEFAULT_COLOR2;
1288
+ const clipRect = resolveAccessor(props.getClipRect, object, objectInfo) ?? DEFAULT_CLIP_RECT;
1289
+ timings.styleAccessorDurationMs += performance.now() - styleAccessorStartTime;
1290
+ const layoutStartTime = performance.now();
1291
+ const width = getSingleLineUtf8Width(textView, byteLookup);
1292
+ const lineOffsetX = ANCHOR_OFFSET_MULTIPLIER[props.textAnchor] * width;
1293
+ const rowBaselineY = getSingleLineBaselineY(props);
1294
+ timings.layoutDurationMs += performance.now() - layoutStartTime;
1295
+ let cursorX = 0;
1296
+ const glyphWriteStartTime = performance.now();
1297
+ for (let byteIndex = textView.start; byteIndex < textView.end; byteIndex += 1) {
1298
+ const frame = byteLookup[textView.data[byteIndex] ?? -1];
1299
+ writeFastTextGlyphRecord({
1300
+ frame,
1301
+ lineOffsetX,
1302
+ cursorX,
1303
+ rowBaselineY,
1304
+ position,
1305
+ color: color3,
1306
+ clipRect,
1307
+ writeState
1308
+ });
1309
+ cursorX += (frame == null ? void 0 : frame.advance) ?? MISSING_CHARACTER_ADVANCE;
1310
+ }
1311
+ timings.glyphWriteDurationMs += performance.now() - glyphWriteStartTime;
1312
+ }
1313
+ function writeMultiLineLabelGlyphs(props, object, objectInfo, writeState, timings) {
1314
+ const textResolveStartTime = performance.now();
1315
+ const text = resolveAccessor(props.getText, object, objectInfo) ?? "";
1316
+ timings.textResolveDurationMs += performance.now() - textResolveStartTime;
1317
+ if (!text) {
1318
+ return;
1319
+ }
1320
+ const styleAccessorStartTime = performance.now();
1321
+ const position = resolveAccessor(props.getPosition, object, objectInfo) ?? DEFAULT_POSITION;
1322
+ const color3 = resolveAccessor(props.getColor, object, objectInfo) ?? DEFAULT_COLOR2;
1323
+ const clipRect = resolveAccessor(props.getClipRect, object, objectInfo) ?? DEFAULT_CLIP_RECT;
1324
+ timings.styleAccessorDurationMs += performance.now() - styleAccessorStartTime;
1325
+ const layoutStartTime = performance.now();
1326
+ const lines = buildFastTextLineLayouts(text, props.mapping);
1327
+ const lineHeightPixels = props.lineHeight * props.fontSize;
1328
+ const labelHeight = lines.length * lineHeightPixels;
1329
+ const blockOffsetY = BASELINE_OFFSET_MULTIPLIER[props.alignmentBaseline] * labelHeight;
1330
+ timings.layoutDurationMs += performance.now() - layoutStartTime;
1331
+ const glyphWriteStartTime = performance.now();
1332
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
1333
+ const line = lines[lineIndex];
1334
+ const lineOffsetX = ANCHOR_OFFSET_MULTIPLIER[props.textAnchor] * line.width;
1335
+ const rowBaselineY = blockOffsetY + props.baselineOffset + lineHeightPixels / 2 + lineIndex * lineHeightPixels;
1336
+ let cursorX = 0;
1337
+ for (const character of line.characters) {
1338
+ const frame = props.mapping[character];
1339
+ writeFastTextGlyphRecord({
1340
+ frame,
1341
+ lineOffsetX,
1342
+ cursorX,
1343
+ rowBaselineY,
1344
+ position,
1345
+ color: color3,
1346
+ clipRect,
1347
+ writeState
1348
+ });
1349
+ cursorX += (frame == null ? void 0 : frame.advance) ?? MISSING_CHARACTER_ADVANCE;
1350
+ }
1351
+ }
1352
+ timings.glyphWriteDurationMs += performance.now() - glyphWriteStartTime;
1353
+ }
1354
+ function buildFastTextLineLayouts(text, mapping) {
1355
+ const lines = [];
1356
+ let currentCharacters = [];
1357
+ let currentWidth = 0;
1358
+ let currentGlyphCount = 0;
1359
+ for (const character of Array.from(text)) {
1360
+ if (character === "\n") {
1361
+ lines.push({
1362
+ characters: currentCharacters,
1363
+ width: currentWidth,
1364
+ glyphCount: currentGlyphCount
1365
+ });
1366
+ currentCharacters = [];
1367
+ currentWidth = 0;
1368
+ currentGlyphCount = 0;
1369
+ continue;
1370
+ }
1371
+ const frame = mapping[character];
1372
+ currentCharacters.push(character);
1373
+ currentWidth += (frame == null ? void 0 : frame.advance) ?? MISSING_CHARACTER_ADVANCE;
1374
+ if (frame) {
1375
+ currentGlyphCount++;
1376
+ }
1377
+ }
1378
+ lines.push({
1379
+ characters: currentCharacters,
1380
+ width: currentWidth,
1381
+ glyphCount: currentGlyphCount
1382
+ });
1383
+ return lines;
1384
+ }
1385
+ function resolveFastTextUtf8ColumnSource(textUtf8Column) {
1386
+ if (!textUtf8Column) {
1387
+ return null;
1388
+ }
1389
+ return isFastTextUtf8ColumnSource(textUtf8Column) ? textUtf8Column : buildFastTextUtf8ColumnSource(textUtf8Column);
1390
+ }
1391
+ function isFastTextUtf8ColumnSource(textUtf8Column) {
1392
+ return "rowCount" in textUtf8Column && "chunks" in textUtf8Column;
1393
+ }
1394
+ function buildFastTextByteGlyphLookup(mapping) {
1395
+ const lookup = new Array(FAST_TEXT_BYTE_LOOKUP_SIZE);
1396
+ for (let byte = 0; byte < 128; byte += 1) {
1397
+ lookup[byte] = mapping[String.fromCharCode(byte)];
1398
+ }
1399
+ return lookup;
1400
+ }
1401
+ function resolveTextUtf8Row(getTextUtf8Row, object, objectInfo) {
1402
+ return getTextUtf8Row === void 0 ? objectInfo.index : resolveAccessor(getTextUtf8Row, object, objectInfo);
1403
+ }
1404
+ function getSingleLineStringWidth(text, mapping) {
1405
+ var _a;
1406
+ let width = 0;
1407
+ for (let index = 0; index < text.length; index += 1) {
1408
+ width += ((_a = mapping[text[index]]) == null ? void 0 : _a.advance) ?? MISSING_CHARACTER_ADVANCE;
1409
+ }
1410
+ return width;
1411
+ }
1412
+ function getSingleLineUtf8Width(textView, byteLookup) {
1413
+ var _a;
1414
+ let width = 0;
1415
+ for (let byteIndex = textView.start; byteIndex < textView.end; byteIndex += 1) {
1416
+ width += ((_a = byteLookup[textView.data[byteIndex] ?? -1]) == null ? void 0 : _a.advance) ?? MISSING_CHARACTER_ADVANCE;
1417
+ }
1418
+ return width;
1419
+ }
1420
+ function getSingleLineBaselineY(props) {
1421
+ const lineHeightPixels = props.lineHeight * props.fontSize;
1422
+ const blockOffsetY = BASELINE_OFFSET_MULTIPLIER[props.alignmentBaseline] * lineHeightPixels;
1423
+ return blockOffsetY + props.baselineOffset + lineHeightPixels / 2;
1424
+ }
1425
+ function writeFastTextGlyphRecord(params) {
1426
+ const frame = params.frame;
1427
+ const glyphIndex = params.writeState.glyphIndex;
1428
+ const recordInt16Index = glyphIndex * FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE / Int16Array.BYTES_PER_ELEMENT;
1429
+ const glyphX = params.lineOffsetX + params.cursorX + ((frame == null ? void 0 : frame.anchorX) ?? 0) - ((frame == null ? void 0 : frame.width) ?? 0) / 2;
1430
+ const glyphY = params.rowBaselineY - ((frame == null ? void 0 : frame.anchorY) ?? 0);
1431
+ const writeState = params.writeState;
1432
+ writeFastTextGlyphPosition(writeState.attributes, glyphIndex, params.position);
1433
+ writeState.glyphRecordViews.int16Values[recordInt16Index] = toInt16(glyphX);
1434
+ writeState.glyphRecordViews.int16Values[recordInt16Index + 1] = toInt16(glyphY);
1435
+ writeState.glyphRecordViews.uint16Values[recordInt16Index + 2] = toUint16((frame == null ? void 0 : frame.x) ?? 0);
1436
+ writeState.glyphRecordViews.uint16Values[recordInt16Index + 3] = toUint16((frame == null ? void 0 : frame.y) ?? 0);
1437
+ writeState.glyphRecordViews.uint16Values[recordInt16Index + 4] = toUint16((frame == null ? void 0 : frame.width) ?? 0);
1438
+ writeState.glyphRecordViews.uint16Values[recordInt16Index + 5] = toUint16((frame == null ? void 0 : frame.height) ?? 0);
1439
+ writeFastTextGlyphClipRect(writeState.glyphRecordViews, glyphIndex, params.clipRect);
1440
+ writeFastTextGlyphColor(writeState.glyphRecordViews, glyphIndex, params.color);
1441
+ writeState.glyphIndex++;
1442
+ }
1443
+ function writeFastTextGlyphPosition(attributes, glyphIndex, position) {
1444
+ const positionOffset = glyphIndex * 2;
1445
+ attributes.instancePositions[positionOffset] = position[0] ?? 0;
1446
+ attributes.instancePositions[positionOffset + 1] = position[1] ?? 0;
1447
+ }
1448
+ function writeFastTextGlyphClipRect(glyphRecordViews, glyphIndex, clipRect) {
1449
+ const recordInt16Index = glyphIndex * FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE / Int16Array.BYTES_PER_ELEMENT;
1450
+ glyphRecordViews.int16Values[recordInt16Index + 6] = toInt16(clipRect[0] ?? 0);
1451
+ glyphRecordViews.int16Values[recordInt16Index + 7] = toInt16(clipRect[1] ?? 0);
1452
+ glyphRecordViews.int16Values[recordInt16Index + 8] = toInt16ClipDimension(clipRect[2] ?? -1);
1453
+ glyphRecordViews.int16Values[recordInt16Index + 9] = toInt16ClipDimension(clipRect[3] ?? -1);
1454
+ }
1455
+ function writeFastTextGlyphColor(glyphRecordViews, glyphIndex, color3) {
1456
+ const recordByteIndex = glyphIndex * FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE;
1457
+ writeColor(glyphRecordViews.uint8Values, recordByteIndex + Int16Array.BYTES_PER_ELEMENT * 10, color3);
1458
+ }
1459
+ function resolveAccessor(accessor, object, objectInfo) {
1460
+ return typeof accessor === "function" ? accessor(object, objectInfo) : accessor;
1461
+ }
1462
+ function writeColor(target, offset, color3) {
1463
+ target[offset] = clampByte(color3[0] ?? DEFAULT_COLOR2[0]);
1464
+ target[offset + 1] = clampByte(color3[1] ?? DEFAULT_COLOR2[1]);
1465
+ target[offset + 2] = clampByte(color3[2] ?? DEFAULT_COLOR2[2]);
1466
+ target[offset + 3] = clampByte(color3[3] ?? DEFAULT_COLOR2[3]);
1467
+ }
1468
+ function clampByte(value) {
1469
+ return Math.max(0, Math.min(255, Math.round(value)));
1470
+ }
1471
+ function toInt16(value) {
1472
+ const integerValue = Math.round(value);
1473
+ if (integerValue < -32768 || integerValue > 32767) {
1474
+ throw new Error(`FastTextLayer value ${value} is outside the signed 16-bit range`);
1475
+ }
1476
+ return integerValue;
1477
+ }
1478
+ function toInt16ClipDimension(value) {
1479
+ const integerValue = value > 0 ? Math.max(1, Math.round(value)) : Math.round(value);
1480
+ if (integerValue < -32768 || integerValue > 32767) {
1481
+ throw new Error(`FastTextLayer value ${value} is outside the signed 16-bit range`);
1482
+ }
1483
+ return integerValue;
1484
+ }
1485
+ function toUint16(value) {
1486
+ const integerValue = Math.round(value);
1487
+ if (integerValue < 0 || integerValue > 65535) {
1488
+ throw new Error(`FastTextLayer glyph frame value ${value} is outside the unsigned 16-bit range`);
1489
+ }
1490
+ return integerValue;
1491
+ }
1492
+
1493
+ // dist/layers/fast-text-layer/font-atlas.js
1494
+ var DEFAULT_FAST_TEXT_FONT_SETTINGS = {
1495
+ fontFamily: "Monaco, monospace",
1496
+ fontWeight: "normal",
1497
+ characterSet: getDefaultCharacterSet(),
1498
+ fontSize: 64,
1499
+ buffer: 4,
1500
+ sdf: true,
1501
+ cutoff: 0.25,
1502
+ radius: 12,
1503
+ smoothing: 0.1
1504
+ };
1505
+ function createFastTextFontAtlas(settings = {}) {
1506
+ if (typeof document === "undefined") {
1507
+ throw new Error("FastTextLayer font atlas generation requires document.createElement");
1508
+ }
1509
+ const resolvedSettings = {
1510
+ ...DEFAULT_FAST_TEXT_FONT_SETTINGS,
1511
+ ...settings,
1512
+ characterSet: normalizeCharacterSet(settings.characterSet ?? DEFAULT_FAST_TEXT_FONT_SETTINGS.characterSet)
1513
+ };
1514
+ const canvas = document.createElement("canvas");
1515
+ canvas.width = MAX_CANVAS_WIDTH;
1516
+ const context = canvas.getContext("2d", { willReadFrequently: true });
1517
+ if (!context) {
1518
+ throw new Error("FastTextLayer font atlas generation requires a 2D canvas context");
1519
+ }
1520
+ setTextStyle(context, resolvedSettings);
1521
+ const sdfRenderer = resolvedSettings.sdf ? createFastTextSdfRenderer(resolvedSettings) : void 0;
1522
+ const mappingResult = buildFastTextCharacterMapping({
1523
+ characterSet: resolvedSettings.characterSet,
1524
+ measureText: (character) => measureFastText(context, resolvedSettings.fontSize, character),
1525
+ buffer: resolvedSettings.buffer,
1526
+ maxCanvasWidth: MAX_CANVAS_WIDTH
1527
+ });
1528
+ canvas.height = mappingResult.canvasHeight;
1529
+ setTextStyle(context, resolvedSettings);
1530
+ for (const character of resolvedSettings.characterSet) {
1531
+ const frame = mappingResult.mapping[character];
1532
+ if (frame) {
1533
+ if (sdfRenderer) {
1534
+ drawFastTextSdfCharacter(context, sdfRenderer, character, frame, resolvedSettings.buffer);
1535
+ } else {
1536
+ context.fillText(character, frame.x, frame.y + frame.anchorY);
1537
+ }
1538
+ }
1539
+ }
1540
+ const fontMetrics = measureFastText(context, resolvedSettings.fontSize);
1541
+ return {
1542
+ baselineOffset: (fontMetrics.ascent - fontMetrics.descent) / 2,
1543
+ mapping: mappingResult.mapping,
1544
+ data: canvas,
1545
+ width: canvas.width,
1546
+ height: canvas.height
1547
+ };
1548
+ }
1549
+ function buildFastTextCharacterMapping({ characterSet, measureText, buffer, maxCanvasWidth }) {
1550
+ const mapping = {};
1551
+ let x = 0;
1552
+ let yMin = 0;
1553
+ let yMax = 0;
1554
+ for (const character of characterSet) {
1555
+ const { advance, width, ascent, descent } = measureText(character);
1556
+ const height = ascent + descent;
1557
+ if (x + width + buffer * 2 > maxCanvasWidth) {
1558
+ x = 0;
1559
+ yMin = yMax;
1560
+ }
1561
+ mapping[character] = {
1562
+ x: x + buffer,
1563
+ y: yMin + buffer,
1564
+ width,
1565
+ height,
1566
+ advance,
1567
+ anchorX: width / 2,
1568
+ anchorY: ascent
1569
+ };
1570
+ x += width + buffer * 2;
1571
+ yMax = Math.max(yMax, yMin + height + buffer * 2);
1572
+ }
1573
+ return {
1574
+ mapping,
1575
+ canvasHeight: Math.max(1, nextPowerOfTwo(yMax))
1576
+ };
1577
+ }
1578
+ var FastTextFontAtlasManager = class {
1579
+ /** Current resolved font settings. */
1580
+ props = { ...DEFAULT_FAST_TEXT_FONT_SETTINGS };
1581
+ currentAtlas;
1582
+ currentKey;
1583
+ /** Current atlas, if one has been built. */
1584
+ get atlas() {
1585
+ return this.currentAtlas;
1586
+ }
1587
+ /** Current character mapping, if an atlas has been built. */
1588
+ get mapping() {
1589
+ var _a;
1590
+ return (_a = this.currentAtlas) == null ? void 0 : _a.mapping;
1591
+ }
1592
+ /** Update font settings and return whether the atlas was rebuilt. */
1593
+ setProps(props = {}) {
1594
+ this.props = {
1595
+ ...this.props,
1596
+ ...props,
1597
+ characterSet: normalizeCharacterSet(props.characterSet ?? this.props.characterSet)
1598
+ };
1599
+ const nextKey = getFontAtlasKey(this.props);
1600
+ if (this.currentAtlas && this.currentKey === nextKey) {
1601
+ return false;
1602
+ }
1603
+ this.currentAtlas = createFastTextFontAtlas(this.props);
1604
+ this.currentKey = nextKey;
1605
+ return true;
1606
+ }
1607
+ };
1608
+ var MAX_CANVAS_WIDTH = 1024;
1609
+ var DEFAULT_ASCENT = 0.9;
1610
+ var DEFAULT_DESCENT = 0.3;
1611
+ function getDefaultCharacterSet() {
1612
+ const characterSet = [];
1613
+ for (let code = 32; code < 128; code++) {
1614
+ characterSet.push(String.fromCharCode(code));
1615
+ }
1616
+ return characterSet;
1617
+ }
1618
+ function normalizeCharacterSet(characterSet) {
1619
+ return typeof characterSet === "string" ? new Set(Array.from(characterSet)) : new Set(characterSet);
1620
+ }
1621
+ function getFontAtlasKey(settings) {
1622
+ const characters = Array.from(settings.characterSet).sort().join("");
1623
+ return [
1624
+ settings.fontFamily,
1625
+ settings.fontWeight,
1626
+ settings.fontSize,
1627
+ settings.buffer,
1628
+ settings.sdf,
1629
+ settings.cutoff,
1630
+ settings.radius,
1631
+ characters
1632
+ ].join("\n");
1633
+ }
1634
+ function setTextStyle(context, settings) {
1635
+ context.font = `${settings.fontWeight} ${settings.fontSize}px ${settings.fontFamily}`;
1636
+ context.fillStyle = "#000";
1637
+ context.textBaseline = "alphabetic";
1638
+ context.textAlign = "left";
1639
+ }
1640
+ function measureFastText(context, fontSize, character) {
1641
+ if (character === void 0) {
1642
+ const fontMetrics = context.measureText("A");
1643
+ if (fontMetrics.fontBoundingBoxAscent) {
1644
+ return {
1645
+ advance: 0,
1646
+ width: 0,
1647
+ ascent: Math.ceil(fontMetrics.fontBoundingBoxAscent),
1648
+ descent: Math.ceil(fontMetrics.fontBoundingBoxDescent)
1649
+ };
1650
+ }
1651
+ return {
1652
+ advance: 0,
1653
+ width: 0,
1654
+ ascent: fontSize * DEFAULT_ASCENT,
1655
+ descent: fontSize * DEFAULT_DESCENT
1656
+ };
1657
+ }
1658
+ const metrics = context.measureText(character);
1659
+ if (!metrics.actualBoundingBoxAscent) {
1660
+ return {
1661
+ advance: metrics.width,
1662
+ width: metrics.width,
1663
+ ascent: fontSize * DEFAULT_ASCENT,
1664
+ descent: fontSize * DEFAULT_DESCENT
1665
+ };
1666
+ }
1667
+ return {
1668
+ advance: metrics.width,
1669
+ width: Math.ceil(metrics.actualBoundingBoxRight - metrics.actualBoundingBoxLeft),
1670
+ ascent: Math.ceil(metrics.actualBoundingBoxAscent),
1671
+ descent: Math.ceil(metrics.actualBoundingBoxDescent)
1672
+ };
1673
+ }
1674
+ function createFastTextSdfRenderer(settings) {
1675
+ const buffer = Math.ceil(settings.buffer);
1676
+ const size = Math.ceil(settings.fontSize + buffer * 4);
1677
+ const scratchSize = size + buffer;
1678
+ const canvas = document.createElement("canvas");
1679
+ canvas.width = size;
1680
+ canvas.height = size;
1681
+ const context = canvas.getContext("2d", { willReadFrequently: true });
1682
+ if (!context) {
1683
+ throw new Error("FastTextLayer SDF generation requires a 2D canvas context");
1684
+ }
1685
+ setTextStyle(context, settings);
1686
+ const gridOuter = new Float64Array(scratchSize * scratchSize);
1687
+ const gridInner = new Float64Array(scratchSize * scratchSize);
1688
+ const f = new Float64Array(scratchSize);
1689
+ const z = new Float64Array(scratchSize + 1);
1690
+ const v = new Uint16Array(scratchSize);
1691
+ return {
1692
+ draw: (character) => drawFastTextSdfGlyph({
1693
+ character,
1694
+ context,
1695
+ fontSize: settings.fontSize,
1696
+ buffer,
1697
+ cutoff: settings.cutoff,
1698
+ radius: settings.radius,
1699
+ size,
1700
+ gridOuter,
1701
+ gridInner,
1702
+ f,
1703
+ z,
1704
+ v
1705
+ })
1706
+ };
1707
+ }
1708
+ function drawFastTextSdfCharacter(context, sdfRenderer, character, frame, buffer) {
1709
+ const { data, width, height } = sdfRenderer.draw(character);
1710
+ const imageData = context.createImageData(width, height);
1711
+ populateAlphaChannel(data, imageData);
1712
+ const x = frame.x - buffer;
1713
+ const y = frame.y - buffer;
1714
+ const x0 = Math.max(0, Math.round(x));
1715
+ const y0 = Math.max(0, Math.round(y));
1716
+ const w = Math.min(width, context.canvas.width - x0);
1717
+ const h = Math.min(height, context.canvas.height - y0);
1718
+ context.putImageData(imageData, x0, y0, 0, 0, w, h);
1719
+ frame.x += x0 - x;
1720
+ frame.y += y0 - y;
1721
+ }
1722
+ function populateAlphaChannel(alphaChannel, imageData) {
1723
+ for (let index = 0; index < alphaChannel.length; index++) {
1724
+ imageData.data[4 * index + 3] = alphaChannel[index];
1725
+ }
1726
+ }
1727
+ var FAST_TEXT_SDF_INF = 1e20;
1728
+ function drawFastTextSdfGlyph({ character, context, fontSize, buffer, cutoff, radius, size, gridOuter, gridInner, f, z, v }) {
1729
+ const metrics = context.measureText(character);
1730
+ const glyphTop = Math.ceil(metrics.actualBoundingBoxAscent ?? fontSize * DEFAULT_ASCENT);
1731
+ const glyphWidth = Math.max(0, Math.min(size - buffer, Math.ceil((metrics.actualBoundingBoxRight ?? metrics.width) - (metrics.actualBoundingBoxLeft ?? 0))));
1732
+ const glyphHeight = Math.min(size - buffer, glyphTop + Math.ceil(metrics.actualBoundingBoxDescent ?? fontSize * DEFAULT_DESCENT));
1733
+ const width = glyphWidth + 2 * buffer;
1734
+ const height = glyphHeight + 2 * buffer;
1735
+ const data = new Uint8ClampedArray(Math.max(width * height, 0));
1736
+ if (glyphWidth === 0 || glyphHeight === 0) {
1737
+ return { data, width, height };
1738
+ }
1739
+ context.clearRect(buffer, buffer, glyphWidth, glyphHeight);
1740
+ context.fillText(character, buffer, buffer + glyphTop);
1741
+ const imageData = context.getImageData(buffer, buffer, glyphWidth, glyphHeight);
1742
+ gridOuter.fill(FAST_TEXT_SDF_INF, 0, data.length);
1743
+ gridInner.fill(0, 0, data.length);
1744
+ for (let y = 0; y < glyphHeight; y++) {
1745
+ for (let x = 0; x < glyphWidth; x++) {
1746
+ const alpha = imageData.data[4 * (y * glyphWidth + x) + 3] / 255;
1747
+ if (alpha === 0) {
1748
+ continue;
1749
+ }
1750
+ const gridIndex = (y + buffer) * width + x + buffer;
1751
+ if (alpha === 1) {
1752
+ gridOuter[gridIndex] = 0;
1753
+ gridInner[gridIndex] = FAST_TEXT_SDF_INF;
1754
+ } else {
1755
+ const distance = 0.5 - alpha;
1756
+ gridOuter[gridIndex] = distance > 0 ? distance * distance : 0;
1757
+ gridInner[gridIndex] = distance < 0 ? distance * distance : 0;
1758
+ }
1759
+ }
1760
+ }
1761
+ transformFastTextSdfGrid(gridOuter, 0, 0, width, height, width, f, v, z);
1762
+ transformFastTextSdfGrid(gridInner, buffer, buffer, glyphWidth, glyphHeight, width, f, v, z);
1763
+ for (let index = 0; index < data.length; index++) {
1764
+ const distance = Math.sqrt(gridOuter[index]) - Math.sqrt(gridInner[index]);
1765
+ data[index] = Math.round(255 - 255 * (distance / radius + cutoff));
1766
+ }
1767
+ return { data, width, height };
1768
+ }
1769
+ function transformFastTextSdfGrid(data, x0, y0, width, height, gridSize, f, v, z) {
1770
+ for (let x = x0; x < x0 + width; x++) {
1771
+ transformFastTextSdfGrid1d(data, y0 * gridSize + x, gridSize, height, f, v, z);
1772
+ }
1773
+ for (let y = y0; y < y0 + height; y++) {
1774
+ transformFastTextSdfGrid1d(data, y * gridSize + x0, 1, width, f, v, z);
1775
+ }
1776
+ }
1777
+ function transformFastTextSdfGrid1d(grid, offset, stride, length, f, v, z) {
1778
+ v[0] = 0;
1779
+ z[0] = -FAST_TEXT_SDF_INF;
1780
+ z[1] = FAST_TEXT_SDF_INF;
1781
+ f[0] = grid[offset];
1782
+ for (let q = 1, k = 0; q < length; q++) {
1783
+ f[q] = grid[offset + q * stride];
1784
+ const q2 = q * q;
1785
+ let s = 0;
1786
+ do {
1787
+ const r = v[k];
1788
+ s = (f[q] - f[r] + q2 - r * r) / (q - r) / 2;
1789
+ } while (s <= z[k] && --k > -1);
1790
+ k++;
1791
+ v[k] = q;
1792
+ z[k] = s;
1793
+ z[k + 1] = FAST_TEXT_SDF_INF;
1794
+ }
1795
+ for (let q = 0, k = 0; q < length; q++) {
1796
+ while (z[k + 1] < q) {
1797
+ k++;
1798
+ }
1799
+ const r = v[k];
1800
+ const qr = q - r;
1801
+ grid[offset + q * stride] = f[r] + qr * qr;
1802
+ }
1803
+ }
1804
+ function nextPowerOfTwo(value) {
1805
+ return Math.pow(2, Math.ceil(Math.log2(Math.max(1, value))));
1806
+ }
1807
+
1808
+ // dist/layers/fast-text-layer/fast-text-layer.js
1809
+ var defaultProps2 = {
1810
+ billboard: true,
1811
+ sizeScale: { type: "number", value: 1, min: 0 },
1812
+ sizeUnits: "pixels",
1813
+ sizeMinPixels: { type: "number", value: 0, min: 0 },
1814
+ sizeMaxPixels: { type: "number", value: Number.MAX_SAFE_INTEGER, min: 0 },
1815
+ alphaCutoff: { type: "number", value: 1e-3, min: 0, max: 1 },
1816
+ characterSet: { type: "object", value: DEFAULT_FAST_TEXT_FONT_SETTINGS.characterSet },
1817
+ fontFamily: DEFAULT_FAST_TEXT_FONT_SETTINGS.fontFamily,
1818
+ fontWeight: DEFAULT_FAST_TEXT_FONT_SETTINGS.fontWeight,
1819
+ lineHeight: { type: "number", value: 1, min: 0 },
1820
+ size: { type: "number", value: 32, min: 0 },
1821
+ pixelOffset: { type: "array", value: [0, 0] },
1822
+ getPixelOffset: { type: "array", value: [0, 0] },
1823
+ fontSettings: { type: "object", value: {}, compare: 1 },
1824
+ characterMapping: { type: "object", value: null, optional: true },
1825
+ fontAtlas: { type: "object", value: null, optional: true },
1826
+ getText: { type: "accessor", value: (datum) => datum.text },
1827
+ textUtf8Column: { type: "object", value: null, optional: true },
1828
+ getTextUtf8Row: {
1829
+ type: "accessor",
1830
+ value: (_datum, objectInfo) => objectInfo.index
1831
+ },
1832
+ getTextUtf8: { type: "accessor", value: null },
1833
+ singleLine: true,
1834
+ getPosition: { type: "accessor", value: (datum) => datum.position },
1835
+ getColor: { type: "accessor", value: [0, 0, 0, 255] },
1836
+ textAnchor: "middle",
1837
+ alignmentBaseline: "center",
1838
+ getClipRect: { type: "accessor", value: [0, 0, -1, -1] },
1839
+ getContentBox: { type: "accessor", value: [0, 0, -1, -1] },
1840
+ contentCutoffPixels: { type: "array", value: [0, 0] },
1841
+ contentAlignHorizontal: "none",
1842
+ contentAlignVertical: "none"
1843
+ };
1844
+ var FastTextLayer = class extends import_core5.Layer {
1845
+ /** Return the shader set used by the direct glyph instance model. */
1846
+ getShaders() {
1847
+ return super.getShaders({
1848
+ vs: FAST_TEXT_VS,
1849
+ fs: FAST_TEXT_FS,
1850
+ modules: [import_core5.project32, import_core5.color, fastTextUniforms]
1851
+ });
1852
+ }
1853
+ /** Initialize the model and atlas manager. */
1854
+ initializeState() {
1855
+ this.state = {
1856
+ fontAtlasManager: new FastTextFontAtlasManager()
1857
+ };
1858
+ this.state.model = this.getModel();
1859
+ }
1860
+ /** Rebuild text layout or update dynamic glyph attributes when inputs change. */
1861
+ updateState(params) {
1862
+ var _a, _b;
1863
+ super.updateState(params);
1864
+ if (params.changeFlags.extensionsChanged) {
1865
+ (_a = this.state.model) == null ? void 0 : _a.destroy();
1866
+ this.state.model = this.getModel();
1867
+ if (this.state.buffers) {
1868
+ this.state.model.setAttributes(this.state.buffers);
1869
+ this.state.model.setInstanceCount(((_b = this.state.glyphData) == null ? void 0 : _b.length) ?? 0);
1870
+ }
1871
+ }
1872
+ if (shouldRebuildFastText(params) || this.hasMutableLayoutSourceChanged()) {
1873
+ this.rebuildGlyphState();
1874
+ } else {
1875
+ const dynamicUpdate = getFastTextDynamicUpdate(params);
1876
+ if (dynamicUpdate) {
1877
+ this.updateDynamicGlyphState(dynamicUpdate);
1878
+ }
1879
+ }
1880
+ }
1881
+ /** Draw the glyph model when atlas texture and glyph buffers are ready. */
1882
+ draw() {
1883
+ const { atlasTexture, glyphData, model, fontSize } = this.state;
1884
+ if (!model || !atlasTexture || !glyphData || glyphData.length === 0 || !fontSize) {
1885
+ return;
1886
+ }
1887
+ model.shaderInputs.setProps({
1888
+ fastText: {
1889
+ fontAtlasTexture: atlasTexture,
1890
+ fontAtlasSize: [atlasTexture.width, atlasTexture.height],
1891
+ fontSize,
1892
+ size: this.props.size,
1893
+ sizeScale: this.props.sizeScale,
1894
+ sizeMinPixels: this.props.sizeMinPixels,
1895
+ sizeMaxPixels: this.props.sizeMaxPixels,
1896
+ pixelOffset: this.props.pixelOffset,
1897
+ billboard: this.props.billboard,
1898
+ sizeUnits: import_core5.UNIT[this.props.sizeUnits],
1899
+ alphaCutoff: this.props.alphaCutoff,
1900
+ sdfEnabled: this.resolveSdfEnabled(),
1901
+ sdfBuffer: FAST_TEXT_SDF_BUFFER,
1902
+ sdfGamma: this.resolveSdfSmoothing(),
1903
+ contentCutoffPixels: this.props.contentCutoffPixels,
1904
+ contentAlign: [
1905
+ getFastTextContentAlignUniform(this.props.contentAlignHorizontal),
1906
+ getFastTextContentAlignUniform(this.props.contentAlignVertical)
1907
+ ],
1908
+ flipY: Boolean(this.context.viewport.flipY)
1909
+ }
1910
+ });
1911
+ model.draw(this.context.renderPass);
1912
+ }
1913
+ /** Release GPU buffers, atlas texture, and the luma model. */
1914
+ finalizeState(context) {
1915
+ var _a, _b;
1916
+ destroyFastTextBuffers(this.state.buffers);
1917
+ (_a = this.state.atlasTexture) == null ? void 0 : _a.destroy();
1918
+ (_b = this.state.model) == null ? void 0 : _b.destroy();
1919
+ super.finalizeState(context);
1920
+ }
1921
+ /** Build a luma model for instanced glyph quads. */
1922
+ getModel() {
1923
+ return new import_engine2.Model(this.context.device, {
1924
+ ...this.getShaders(),
1925
+ id: this.props.id,
1926
+ bufferLayout: FAST_TEXT_BUFFER_LAYOUT,
1927
+ geometry: new import_engine2.Geometry({
1928
+ topology: "triangle-list",
1929
+ attributes: {
1930
+ positions: {
1931
+ size: 2,
1932
+ value: new Float32Array([0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1])
1933
+ }
1934
+ }
1935
+ }),
1936
+ isInstanced: true
1937
+ });
1938
+ }
1939
+ /** Rebuild CPU glyph data, GPU vertex buffers, and the font atlas texture. */
1940
+ rebuildGlyphState() {
1941
+ var _a, _b;
1942
+ const rebuildStartTime = performance.now();
1943
+ const atlasStartTime = performance.now();
1944
+ const atlas = this.resolveFontAtlas();
1945
+ const atlasDurationMs = performance.now() - atlasStartTime;
1946
+ const mapping = this.props.characterMapping ?? atlas.mapping;
1947
+ const glyphDataStartTime = performance.now();
1948
+ const glyphData = buildFastTextGlyphData({
1949
+ data: this.props.data,
1950
+ getText: this.props.getText,
1951
+ textUtf8Column: this.props.textUtf8Column,
1952
+ getTextUtf8Row: this.props.getTextUtf8Row,
1953
+ getTextUtf8: this.props.getTextUtf8,
1954
+ singleLine: this.props.singleLine,
1955
+ getPosition: this.props.getPosition,
1956
+ getColor: this.props.getColor,
1957
+ textAnchor: this.props.textAnchor,
1958
+ alignmentBaseline: this.props.alignmentBaseline,
1959
+ getClipRect: this.props.getClipRect,
1960
+ mapping,
1961
+ baselineOffset: atlas.baselineOffset,
1962
+ fontSize: this.resolveFontSize(),
1963
+ lineHeight: this.props.lineHeight
1964
+ });
1965
+ const glyphDataDurationMs = performance.now() - glyphDataStartTime;
1966
+ const bufferStartTime = performance.now();
1967
+ const buffers = createFastTextBuffers(this.context.device, glyphData);
1968
+ const bufferCreateDurationMs = performance.now() - bufferStartTime;
1969
+ destroyFastTextBuffers(this.state.buffers);
1970
+ (_a = this.state.model) == null ? void 0 : _a.setAttributes(buffers);
1971
+ (_b = this.state.model) == null ? void 0 : _b.setInstanceCount(glyphData.length);
1972
+ this.setState({
1973
+ glyphData,
1974
+ buffers,
1975
+ layoutSourceSignature: getFastTextLayoutSourceSignature(this.props)
1976
+ });
1977
+ logFastTextAttributeBuildProbe({
1978
+ atlasDurationMs,
1979
+ bufferCreateDurationMs,
1980
+ glyphDataDurationMs,
1981
+ glyphStats: glyphData.buildStats,
1982
+ layerId: this.props.id,
1983
+ totalDurationMs: performance.now() - rebuildStartTime
1984
+ });
1985
+ this.setNeedsRedraw();
1986
+ }
1987
+ /** Rewrite dynamic glyph attributes in place without rebuilding text layout. */
1988
+ updateDynamicGlyphState(update) {
1989
+ const { glyphData, buffers } = this.state;
1990
+ if (!glyphData || !buffers) {
1991
+ this.rebuildGlyphState();
1992
+ return;
1993
+ }
1994
+ const updateStartTime = performance.now();
1995
+ const dynamicStats = updateFastTextDynamicGlyphAttributes({
1996
+ data: this.props.data,
1997
+ glyphData,
1998
+ getPosition: this.props.getPosition,
1999
+ getColor: this.props.getColor,
2000
+ getClipRect: this.props.getClipRect,
2001
+ updatePositions: update.positions,
2002
+ updateColors: update.colors,
2003
+ updateClipRects: update.clipRects
2004
+ });
2005
+ if (dynamicStats.rowCount !== glyphData.startIndices.length - 1) {
2006
+ this.rebuildGlyphState();
2007
+ return;
2008
+ }
2009
+ const bufferUploadStartTime = performance.now();
2010
+ if (update.positions) {
2011
+ buffers.instancePositions.write(glyphData.attributes.instancePositions);
2012
+ }
2013
+ if (update.colors || update.clipRects) {
2014
+ buffers.instanceGlyphData.write(glyphData.attributes.instanceGlyphData);
2015
+ }
2016
+ const bufferUploadDurationMs = performance.now() - bufferUploadStartTime;
2017
+ logFastTextDynamicAttributeUpdateProbe({
2018
+ bufferUploadDurationMs,
2019
+ dynamicStats,
2020
+ layerId: this.props.id,
2021
+ totalDurationMs: performance.now() - updateStartTime,
2022
+ update
2023
+ });
2024
+ this.setNeedsRedraw();
2025
+ }
2026
+ /** Return whether source data or UTF-8 column growth invalidated the current glyph layout. */
2027
+ hasMutableLayoutSourceChanged() {
2028
+ const { glyphData, layoutSourceSignature } = this.state;
2029
+ if (!glyphData || !layoutSourceSignature) {
2030
+ return true;
2031
+ }
2032
+ return !areFastTextLayoutSourceSignaturesEqual(getFastTextLayoutSourceSignature(this.props), layoutSourceSignature);
2033
+ }
2034
+ /** Resolve a caller-supplied atlas or rebuild the local generated atlas. */
2035
+ resolveFontAtlas() {
2036
+ const { characterMapping, fontAtlas } = this.props;
2037
+ if ((this.props.textUtf8Column || this.props.getTextUtf8) && this.props.characterSet === "auto") {
2038
+ throw new Error('FastTextLayer characterSet="auto" is not supported with UTF-8 text sources');
2039
+ }
2040
+ if (characterMapping || fontAtlas) {
2041
+ if (!characterMapping || !fontAtlas) {
2042
+ throw new Error("FastTextLayer requires characterMapping and fontAtlas to be supplied together");
2043
+ }
2044
+ this.syncAtlasTexture(fontAtlas);
2045
+ return fontAtlas;
2046
+ }
2047
+ const characterSet = this.props.characterSet === "auto" ? collectFastTextCharacterSet({
2048
+ data: this.props.data,
2049
+ getText: this.props.getText
2050
+ }) : this.props.characterSet;
2051
+ this.state.fontAtlasManager.setProps({
2052
+ ...this.props.fontSettings,
2053
+ fontFamily: this.props.fontFamily,
2054
+ fontWeight: this.props.fontWeight,
2055
+ characterSet
2056
+ });
2057
+ const atlas = this.state.fontAtlasManager.atlas;
2058
+ if (!atlas) {
2059
+ throw new Error("FastTextLayer failed to build a font atlas");
2060
+ }
2061
+ this.syncAtlasTexture(atlas);
2062
+ return atlas;
2063
+ }
2064
+ /** Resolve the atlas pixel size used by glyph offsets. */
2065
+ resolveFontSize() {
2066
+ return this.props.fontAtlas ? this.props.fontSettings.fontSize ?? DEFAULT_FAST_TEXT_FONT_SETTINGS.fontSize : this.state.fontAtlasManager.props.fontSize;
2067
+ }
2068
+ /** Resolve whether the current atlas should be sampled as SDF data. */
2069
+ resolveSdfEnabled() {
2070
+ return this.props.fontAtlas ? this.props.fontSettings.sdf ?? DEFAULT_FAST_TEXT_FONT_SETTINGS.sdf : this.state.fontAtlasManager.props.sdf;
2071
+ }
2072
+ /** Resolve the SDF smoothing width for the current atlas. */
2073
+ resolveSdfSmoothing() {
2074
+ return this.props.fontAtlas ? this.props.fontSettings.smoothing ?? DEFAULT_FAST_TEXT_FONT_SETTINGS.smoothing : this.state.fontAtlasManager.props.smoothing;
2075
+ }
2076
+ /** Upload a new atlas texture when the atlas object changes. */
2077
+ syncAtlasTexture(atlas) {
2078
+ var _a;
2079
+ if (this.state.textureAtlas === atlas && this.state.atlasTexture) {
2080
+ return;
2081
+ }
2082
+ (_a = this.state.atlasTexture) == null ? void 0 : _a.destroy();
2083
+ const texture = createFastTextAtlasTexture(this.context.device, atlas);
2084
+ this.setState({
2085
+ textureAtlas: atlas,
2086
+ atlasTexture: texture,
2087
+ fontSize: this.resolveFontSize()
2088
+ });
2089
+ }
2090
+ };
2091
+ __publicField(FastTextLayer, "defaultProps", defaultProps2);
2092
+ __publicField(FastTextLayer, "layerName", "FastTextLayer");
2093
+ var FAST_TEXT_CONTENT_ALIGN = {
2094
+ none: 0,
2095
+ start: 1,
2096
+ center: 2,
2097
+ end: 3
2098
+ };
2099
+ var FAST_TEXT_ALIGN_START = FAST_TEXT_CONTENT_ALIGN.start;
2100
+ var FAST_TEXT_ALIGN_CENTER = FAST_TEXT_CONTENT_ALIGN.center;
2101
+ var FAST_TEXT_ALIGN_END = FAST_TEXT_CONTENT_ALIGN.end;
2102
+ var FAST_TEXT_SDF_BUFFER = 192 / 256;
2103
+ var fastTextLog = new import_log.Log({ id: "trace-layers" });
2104
+ var FAST_TEXT_PROBE_LABEL_STYLE = "background:#f59e0b;color:#111827;font-weight:700;padding:2px 8px;border-radius:6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;";
2105
+ var fastTextUniforms = {
2106
+ name: "fastText",
2107
+ vs: `layout(std140) uniform fastTextUniforms {
2108
+ vec2 fontAtlasSize;
2109
+ float fontSize;
2110
+ float size;
2111
+ float sizeScale;
2112
+ float sizeMinPixels;
2113
+ float sizeMaxPixels;
2114
+ vec2 pixelOffset;
2115
+ bool billboard;
2116
+ highp int sizeUnits;
2117
+ float alphaCutoff;
2118
+ bool sdfEnabled;
2119
+ float sdfBuffer;
2120
+ float sdfGamma;
2121
+ vec2 contentCutoffPixels;
2122
+ highp ivec2 contentAlign;
2123
+ bool flipY;
2124
+ } fastText;
2125
+
2126
+ #define FAST_TEXT_ALIGN_MODE_START ${FAST_TEXT_ALIGN_START}
2127
+ #define FAST_TEXT_ALIGN_MODE_CENTER ${FAST_TEXT_ALIGN_CENTER}
2128
+ #define FAST_TEXT_ALIGN_MODE_END ${FAST_TEXT_ALIGN_END}
2129
+ `,
2130
+ fs: `layout(std140) uniform fastTextUniforms {
2131
+ vec2 fontAtlasSize;
2132
+ float fontSize;
2133
+ float size;
2134
+ float sizeScale;
2135
+ float sizeMinPixels;
2136
+ float sizeMaxPixels;
2137
+ vec2 pixelOffset;
2138
+ bool billboard;
2139
+ highp int sizeUnits;
2140
+ float alphaCutoff;
2141
+ bool sdfEnabled;
2142
+ float sdfBuffer;
2143
+ float sdfGamma;
2144
+ vec2 contentCutoffPixels;
2145
+ highp ivec2 contentAlign;
2146
+ bool flipY;
2147
+ } fastText;
2148
+ `,
2149
+ uniformTypes: {
2150
+ fontAtlasSize: "vec2<f32>",
2151
+ fontSize: "f32",
2152
+ size: "f32",
2153
+ sizeScale: "f32",
2154
+ sizeMinPixels: "f32",
2155
+ sizeMaxPixels: "f32",
2156
+ pixelOffset: "vec2<f32>",
2157
+ billboard: "f32",
2158
+ sizeUnits: "i32",
2159
+ alphaCutoff: "f32",
2160
+ sdfEnabled: "f32",
2161
+ sdfBuffer: "f32",
2162
+ sdfGamma: "f32",
2163
+ contentCutoffPixels: "vec2<f32>",
2164
+ contentAlign: "vec2<i32>",
2165
+ flipY: "f32"
2166
+ }
2167
+ };
2168
+ var FAST_TEXT_BUFFER_LAYOUT = [
2169
+ { name: "instancePositions", stepMode: "instance", format: "float32x2" },
2170
+ {
2171
+ name: "instanceGlyphData",
2172
+ stepMode: "instance",
2173
+ byteStride: FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE,
2174
+ attributes: [
2175
+ { attribute: "instanceGlyphOffsets", format: "sint16x2", byteOffset: 0 },
2176
+ {
2177
+ attribute: "instanceGlyphFrames",
2178
+ format: "uint16x4",
2179
+ byteOffset: Int16Array.BYTES_PER_ELEMENT * 2
2180
+ },
2181
+ {
2182
+ attribute: "instanceClipRects",
2183
+ format: "sint16x4",
2184
+ byteOffset: Int16Array.BYTES_PER_ELEMENT * 6
2185
+ },
2186
+ {
2187
+ attribute: "instanceColors",
2188
+ format: "unorm8x4",
2189
+ byteOffset: Int16Array.BYTES_PER_ELEMENT * 10
2190
+ }
2191
+ ]
2192
+ }
2193
+ ];
2194
+ var DEFAULT_SAMPLER_PARAMETERS = {
2195
+ minFilter: "linear",
2196
+ mipmapFilter: "linear",
2197
+ magFilter: "linear",
2198
+ addressModeU: "clamp-to-edge",
2199
+ addressModeV: "clamp-to-edge"
2200
+ };
2201
+ var FAST_TEXT_VS = `#version 300 es
2202
+ #define SHADER_NAME fast-text-layer-vertex-shader
2203
+
2204
+ in vec2 positions;
2205
+ in vec2 instancePositions;
2206
+ in ivec2 instanceGlyphOffsets;
2207
+ in uvec4 instanceGlyphFrames;
2208
+ in ivec4 instanceClipRects;
2209
+ in vec4 instanceColors;
2210
+
2211
+ out vec4 vColor;
2212
+ out vec2 vTextureCoords;
2213
+ out vec2 uv;
2214
+
2215
+ float fastTextGetAlignmentPixelOffset(float anchor, float extent, float clipStart, float clipEnd, int mode) {
2216
+ if (clipEnd < clipStart) {
2217
+ return 0.0;
2218
+ }
2219
+ if (mode == FAST_TEXT_ALIGN_MODE_START) {
2220
+ return max(-(anchor + clipStart), 0.0);
2221
+ }
2222
+ if (mode == FAST_TEXT_ALIGN_MODE_CENTER) {
2223
+ float visibleMin = max(0.0, anchor + clipStart);
2224
+ float visibleMax = min(extent, anchor + clipEnd);
2225
+ return visibleMin < visibleMax ? (visibleMin + visibleMax) / 2.0 - anchor : 0.0;
2226
+ }
2227
+ if (mode == FAST_TEXT_ALIGN_MODE_END) {
2228
+ return min(extent - (anchor + clipEnd), 0.0);
2229
+ }
2230
+ return 0.0;
2231
+ }
2232
+
2233
+ void fastTextClipGlyphVertex(vec2 pixelOffset, vec2 anchorPosScreen) {
2234
+ vec4 clipRect = vec4(instanceClipRects);
2235
+ vec2 clipXY = project_size_to_pixel(clipRect.xy);
2236
+ vec2 clipWH = project_size_to_pixel(clipRect.zw);
2237
+ if (fastText.flipY) {
2238
+ clipXY.y = -clipXY.y - clipWH.y;
2239
+ }
2240
+
2241
+ if (fastText.contentAlign.x > 0 || fastText.contentAlign.y > 0) {
2242
+ vec2 viewportPixels = project.viewportSize / project.devicePixelRatio;
2243
+ vec2 scrollPixels = vec2(
2244
+ fastTextGetAlignmentPixelOffset(
2245
+ anchorPosScreen.x,
2246
+ viewportPixels.x,
2247
+ clipXY.x,
2248
+ clipXY.x + clipWH.x,
2249
+ fastText.contentAlign.x
2250
+ ),
2251
+ -fastTextGetAlignmentPixelOffset(
2252
+ anchorPosScreen.y,
2253
+ viewportPixels.y,
2254
+ -clipXY.y - clipWH.y,
2255
+ -clipXY.y,
2256
+ fastText.contentAlign.y
2257
+ )
2258
+ );
2259
+ pixelOffset += scrollPixels;
2260
+ gl_Position.xy += project_pixel_size_to_clipspace(scrollPixels);
2261
+ }
2262
+
2263
+ if (clipRect.z >= 0.0) {
2264
+ if (pixelOffset.x < clipXY.x || pixelOffset.x > clipXY.x + clipWH.x) {
2265
+ gl_Position = vec4(0.0);
2266
+ } else if (fastText.contentCutoffPixels.x > 0.0) {
2267
+ float viewportWidth = project.viewportSize.x / project.devicePixelRatio;
2268
+ float left = max(anchorPosScreen.x + clipXY.x, 0.0);
2269
+ float right = min(anchorPosScreen.x + clipXY.x + clipWH.x, viewportWidth);
2270
+ if (right - left < fastText.contentCutoffPixels.x) {
2271
+ gl_Position = vec4(0.0);
2272
+ }
2273
+ }
2274
+ }
2275
+ if (clipRect.w >= 0.0) {
2276
+ if (pixelOffset.y < clipXY.y || pixelOffset.y > clipXY.y + clipWH.y) {
2277
+ gl_Position = vec4(0.0);
2278
+ } else if (fastText.contentCutoffPixels.y > 0.0) {
2279
+ float viewportHeight = project.viewportSize.y / project.devicePixelRatio;
2280
+ float top = max(anchorPosScreen.y - clipXY.y - clipWH.y, 0.0);
2281
+ float bottom = min(anchorPosScreen.y - clipXY.y, viewportHeight);
2282
+ if (bottom - top < fastText.contentCutoffPixels.y) {
2283
+ gl_Position = vec4(0.0);
2284
+ }
2285
+ }
2286
+ }
2287
+ }
2288
+
2289
+ void main(void) {
2290
+ vec3 worldPosition = vec3(instancePositions, 0.0);
2291
+ geometry.worldPosition = worldPosition;
2292
+ geometry.uv = positions;
2293
+ uv = positions;
2294
+
2295
+ vec4 glyphFrame = vec4(instanceGlyphFrames);
2296
+ vec2 glyphSize = glyphFrame.zw;
2297
+ float sizePixels = clamp(
2298
+ project_size_to_pixel(fastText.size * fastText.sizeScale, fastText.sizeUnits),
2299
+ fastText.sizeMinPixels,
2300
+ fastText.sizeMaxPixels
2301
+ );
2302
+ float instanceScale = fastText.fontSize == 0.0 ? 0.0 : sizePixels / fastText.fontSize;
2303
+ vec2 pixelOffset = vec2(instanceGlyphOffsets) + positions * glyphSize;
2304
+ pixelOffset = pixelOffset * instanceScale + fastText.pixelOffset;
2305
+ pixelOffset.y *= -1.0;
2306
+
2307
+ vec2 anchorPosScreen;
2308
+ if (fastText.billboard) {
2309
+ gl_Position = project_position_to_clipspace(
2310
+ worldPosition,
2311
+ vec3(0.0),
2312
+ vec3(0.0),
2313
+ geometry.position
2314
+ );
2315
+ anchorPosScreen = gl_Position.xy / gl_Position.w;
2316
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
2317
+ vec3 offset = vec3(pixelOffset, 0.0);
2318
+ DECKGL_FILTER_SIZE(offset, geometry);
2319
+ gl_Position.xy += project_pixel_size_to_clipspace(offset.xy);
2320
+ } else {
2321
+ vec3 offsetCommon = vec3(project_pixel_size(pixelOffset), 0.0);
2322
+ if (fastText.flipY) {
2323
+ offsetCommon.y *= -1.0;
2324
+ }
2325
+ DECKGL_FILTER_SIZE(offsetCommon, geometry);
2326
+ vec4 anchorPosition = project_position_to_clipspace(worldPosition, vec3(0.0), vec3(0.0));
2327
+ anchorPosScreen = anchorPosition.xy / anchorPosition.w;
2328
+ gl_Position = project_position_to_clipspace(
2329
+ worldPosition,
2330
+ vec3(0.0),
2331
+ offsetCommon,
2332
+ geometry.position
2333
+ );
2334
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
2335
+ }
2336
+
2337
+ anchorPosScreen = vec2(anchorPosScreen.x + 1.0, 1.0 - anchorPosScreen.y) / 2.0 *
2338
+ project.viewportSize / project.devicePixelRatio;
2339
+ fastTextClipGlyphVertex(pixelOffset, anchorPosScreen);
2340
+
2341
+ vTextureCoords = (glyphFrame.xy + positions * glyphSize) / fastText.fontAtlasSize;
2342
+ vColor = instanceColors;
2343
+ DECKGL_FILTER_COLOR(vColor, geometry);
2344
+ }
2345
+ `;
2346
+ var FAST_TEXT_FS = `#version 300 es
2347
+ #define SHADER_NAME fast-text-layer-fragment-shader
2348
+
2349
+ precision highp float;
2350
+
2351
+ uniform sampler2D fontAtlasTexture;
2352
+
2353
+ in vec4 vColor;
2354
+ in vec2 vTextureCoords;
2355
+ in vec2 uv;
2356
+
2357
+ out vec4 fragColor;
2358
+
2359
+ void main(void) {
2360
+ geometry.uv = uv;
2361
+
2362
+ float alpha = texture(fontAtlasTexture, vTextureCoords).a;
2363
+ if (fastText.sdfEnabled) {
2364
+ alpha = smoothstep(fastText.sdfBuffer - fastText.sdfGamma, fastText.sdfBuffer + fastText.sdfGamma, alpha);
2365
+ }
2366
+ float outputAlpha = alpha * vColor.a;
2367
+
2368
+ if (outputAlpha < fastText.alphaCutoff) {
2369
+ discard;
2370
+ }
2371
+
2372
+ fragColor = vec4(vColor.rgb, outputAlpha * layer.opacity);
2373
+
2374
+ DECKGL_FILTER_COLOR(fragColor, geometry);
2375
+ }
2376
+ `;
2377
+ function getFastTextLayoutSourceSignature(props) {
2378
+ const textUtf8ColumnSignature = getFastTextUtf8ColumnSourceSignature(props.textUtf8Column);
2379
+ return {
2380
+ dataRowCount: getFastTextDataRowCount(props.data),
2381
+ hasTextUtf8Accessor: Boolean(props.getTextUtf8),
2382
+ textUtf8ColumnRowCount: textUtf8ColumnSignature.rowCount,
2383
+ textUtf8ColumnChunkCount: textUtf8ColumnSignature.chunkCount,
2384
+ textUtf8ColumnOffsetCount: textUtf8ColumnSignature.offsetCount,
2385
+ textUtf8ColumnValueByteLength: textUtf8ColumnSignature.valueByteLength
2386
+ };
2387
+ }
2388
+ function areFastTextLayoutSourceSignaturesEqual(signature, oldSignature) {
2389
+ return signature.dataRowCount === oldSignature.dataRowCount && signature.hasTextUtf8Accessor === oldSignature.hasTextUtf8Accessor && signature.textUtf8ColumnRowCount === oldSignature.textUtf8ColumnRowCount && signature.textUtf8ColumnChunkCount === oldSignature.textUtf8ColumnChunkCount && signature.textUtf8ColumnOffsetCount === oldSignature.textUtf8ColumnOffsetCount && signature.textUtf8ColumnValueByteLength === oldSignature.textUtf8ColumnValueByteLength;
2390
+ }
2391
+ function getFastTextDataRowCount(data) {
2392
+ const arrayLikeLength = data.length;
2393
+ if (typeof arrayLikeLength === "number") {
2394
+ return arrayLikeLength;
2395
+ }
2396
+ const tableLikeNumRows = data.numRows;
2397
+ if (typeof tableLikeNumRows === "number") {
2398
+ return tableLikeNumRows;
2399
+ }
2400
+ const { iterable } = (0, import_core5.createIterable)(data);
2401
+ let rowCount = 0;
2402
+ for (const _object of iterable) {
2403
+ rowCount++;
2404
+ }
2405
+ return rowCount;
2406
+ }
2407
+ function getFastTextUtf8ColumnSourceSignature(textUtf8Column) {
2408
+ if (!textUtf8Column) {
2409
+ return { rowCount: 0, chunkCount: 0, offsetCount: 0, valueByteLength: 0 };
2410
+ }
2411
+ const source = normalizeFastTextUtf8ColumnForComparison(textUtf8Column);
2412
+ if (!source) {
2413
+ return { rowCount: -1, chunkCount: -1, offsetCount: -1, valueByteLength: -1 };
2414
+ }
2415
+ let offsetCount = 0;
2416
+ let valueByteLength = 0;
2417
+ for (const chunk of source.chunks) {
2418
+ offsetCount += chunk.valueOffsets.length;
2419
+ valueByteLength += chunk.values.byteLength;
2420
+ }
2421
+ return {
2422
+ rowCount: source.rowCount,
2423
+ chunkCount: source.chunks.length,
2424
+ offsetCount,
2425
+ valueByteLength
2426
+ };
2427
+ }
2428
+ function shouldRebuildFastText(layerParams) {
2429
+ const { props, oldProps, changeFlags } = layerParams;
2430
+ const updateTriggersChanged = changeFlags.updateTriggersChanged;
2431
+ return Boolean(changeFlags.dataChanged) || didFastTextAccessorPropChange(props.getText, oldProps.getText) || !areFastTextUtf8ColumnsEqual(props.textUtf8Column, oldProps.textUtf8Column) || didFastTextAccessorPropChange(props.getTextUtf8Row, oldProps.getTextUtf8Row) || didFastTextAccessorPropChange(props.getTextUtf8, oldProps.getTextUtf8) || props.singleLine !== oldProps.singleLine || props.textAnchor !== oldProps.textAnchor || props.alignmentBaseline !== oldProps.alignmentBaseline || props.characterSet !== oldProps.characterSet || props.fontFamily !== oldProps.fontFamily || props.fontWeight !== oldProps.fontWeight || props.lineHeight !== oldProps.lineHeight || props.fontSettings !== oldProps.fontSettings || props.characterMapping !== oldProps.characterMapping || props.fontAtlas !== oldProps.fontAtlas || Boolean(updateTriggersChanged && (updateTriggersChanged.all || updateTriggersChanged.getText || updateTriggersChanged.getTextUtf8 || updateTriggersChanged.getTextUtf8Row));
2432
+ }
2433
+ function getFastTextDynamicUpdate(layerParams) {
2434
+ const { props, oldProps, changeFlags } = layerParams;
2435
+ const updateTriggersChanged = changeFlags.updateTriggersChanged;
2436
+ const positions = didFastTextAccessorPropChange(props.getPosition, oldProps.getPosition) || Boolean(updateTriggersChanged && updateTriggersChanged.getPosition);
2437
+ const colors = didFastTextAccessorPropChange(props.getColor, oldProps.getColor) || Boolean(updateTriggersChanged && updateTriggersChanged.getColor);
2438
+ const clipRects = didFastTextAccessorPropChange(props.getClipRect, oldProps.getClipRect) || Boolean(updateTriggersChanged && updateTriggersChanged.getClipRect);
2439
+ if (!positions && !colors && !clipRects) {
2440
+ return null;
2441
+ }
2442
+ return { positions, colors, clipRects };
2443
+ }
2444
+ function areFastTextUtf8ColumnsEqual(textUtf8Column, oldTextUtf8Column) {
2445
+ if (textUtf8Column === oldTextUtf8Column) {
2446
+ return true;
2447
+ }
2448
+ if (!textUtf8Column || !oldTextUtf8Column) {
2449
+ return false;
2450
+ }
2451
+ const source = normalizeFastTextUtf8ColumnForComparison(textUtf8Column);
2452
+ const oldSource = normalizeFastTextUtf8ColumnForComparison(oldTextUtf8Column);
2453
+ if (!source || !oldSource || source.rowCount !== oldSource.rowCount) {
2454
+ return false;
2455
+ }
2456
+ if (source.chunks.length !== oldSource.chunks.length) {
2457
+ return false;
2458
+ }
2459
+ for (let index = 0; index < source.chunks.length; index += 1) {
2460
+ const chunk = source.chunks[index];
2461
+ const oldChunk = oldSource.chunks[index];
2462
+ if (chunk.rowOffset !== oldChunk.rowOffset || chunk.rowCount !== oldChunk.rowCount || chunk.valueOffsetIndex !== oldChunk.valueOffsetIndex || chunk.valueOffsets !== oldChunk.valueOffsets || chunk.values !== oldChunk.values) {
2463
+ return false;
2464
+ }
2465
+ }
2466
+ return true;
2467
+ }
2468
+ function normalizeFastTextUtf8ColumnForComparison(textUtf8Column) {
2469
+ return isFastTextUtf8ColumnSource2(textUtf8Column) ? textUtf8Column : buildFastTextUtf8ColumnSource(textUtf8Column);
2470
+ }
2471
+ function isFastTextUtf8ColumnSource2(textUtf8Column) {
2472
+ return "rowCount" in textUtf8Column && "chunks" in textUtf8Column;
2473
+ }
2474
+ function didFastTextAccessorPropChange(accessor, oldAccessor) {
2475
+ if (typeof oldAccessor === "function") {
2476
+ return false;
2477
+ }
2478
+ if (typeof accessor === "function") {
2479
+ return true;
2480
+ }
2481
+ return !areFastTextAccessorConstantsEqual(accessor, oldAccessor);
2482
+ }
2483
+ function areFastTextAccessorConstantsEqual(accessor, oldAccessor) {
2484
+ if (accessor === oldAccessor) {
2485
+ return true;
2486
+ }
2487
+ if (!Array.isArray(accessor) || !Array.isArray(oldAccessor)) {
2488
+ return false;
2489
+ }
2490
+ if (accessor.length !== oldAccessor.length) {
2491
+ return false;
2492
+ }
2493
+ for (let index = 0; index < accessor.length; index += 1) {
2494
+ if (accessor[index] !== oldAccessor[index]) {
2495
+ return false;
2496
+ }
2497
+ }
2498
+ return true;
2499
+ }
2500
+ function logFastTextAttributeBuildProbe(params) {
2501
+ getFastTextProbeLog().probe(0, `%cFastTextLayer%c ${params.glyphStats.rowCount} rows in ${formatFastTextDurationMs(params.totalDurationMs)} ${params.layerId}`, FAST_TEXT_PROBE_LABEL_STYLE, "", {
2502
+ layerId: params.layerId,
2503
+ updateMode: "full",
2504
+ sourceMode: params.glyphStats.sourceMode,
2505
+ layoutMode: params.glyphStats.layoutMode,
2506
+ rowCount: params.glyphStats.rowCount,
2507
+ glyphCount: params.glyphStats.glyphCount,
2508
+ attributeByteLength: params.glyphStats.attributeByteLength,
2509
+ atlasDurationMs: params.atlasDurationMs,
2510
+ glyphDataDurationMs: params.glyphDataDurationMs,
2511
+ columnNormalizeDurationMs: params.glyphStats.columnNormalizeDurationMs,
2512
+ countDurationMs: params.glyphStats.countDurationMs,
2513
+ allocateDurationMs: params.glyphStats.allocateDurationMs,
2514
+ writeDurationMs: params.glyphStats.writeDurationMs,
2515
+ textResolveDurationMs: params.glyphStats.textResolveDurationMs,
2516
+ styleAccessorDurationMs: params.glyphStats.styleAccessorDurationMs,
2517
+ layoutDurationMs: params.glyphStats.layoutDurationMs,
2518
+ glyphWriteDurationMs: params.glyphStats.glyphWriteDurationMs,
2519
+ bufferCreateDurationMs: params.bufferCreateDurationMs,
2520
+ totalDurationMs: params.totalDurationMs
2521
+ })();
2522
+ }
2523
+ function logFastTextDynamicAttributeUpdateProbe(params) {
2524
+ getFastTextProbeLog().probe(0, `%cFastTextLayer%c dynamic ${params.dynamicStats.rowCount} rows in ${formatFastTextDurationMs(params.totalDurationMs)} ${params.layerId}`, FAST_TEXT_PROBE_LABEL_STYLE, "", {
2525
+ layerId: params.layerId,
2526
+ updateMode: "dynamic",
2527
+ updatePositions: params.update.positions,
2528
+ updateColors: params.update.colors,
2529
+ updateClipRects: params.update.clipRects,
2530
+ rowCount: params.dynamicStats.rowCount,
2531
+ glyphCount: params.dynamicStats.glyphCount,
2532
+ attributeByteLength: params.dynamicStats.attributeByteLength,
2533
+ positionAccessorDurationMs: params.dynamicStats.positionAccessorDurationMs,
2534
+ colorAccessorDurationMs: params.dynamicStats.colorAccessorDurationMs,
2535
+ clipRectAccessorDurationMs: params.dynamicStats.clipRectAccessorDurationMs,
2536
+ writeDurationMs: params.dynamicStats.writeDurationMs,
2537
+ bufferUploadDurationMs: params.bufferUploadDurationMs,
2538
+ totalDurationMs: params.totalDurationMs
2539
+ })();
2540
+ }
2541
+ function formatFastTextDurationMs(durationMs) {
2542
+ return `${durationMs.toFixed(durationMs < 10 ? 2 : 1)}ms`;
2543
+ }
2544
+ function getFastTextProbeLog() {
2545
+ var _a;
2546
+ const globalLog = (_a = globalThis.traceLayers) == null ? void 0 : _a.log;
2547
+ return globalLog ?? fastTextLog;
2548
+ }
2549
+ function createFastTextBuffers(device, glyphData) {
2550
+ const { attributes } = glyphData;
2551
+ return {
2552
+ instanceGlyphData: createVertexBuffer(device, attributes.instanceGlyphData, new Uint8Array(FAST_TEXT_GLYPH_VERTEX_BYTE_STRIDE)),
2553
+ instancePositions: createVertexBuffer(device, attributes.instancePositions, new Float32Array(2))
2554
+ };
2555
+ }
2556
+ function createVertexBuffer(device, data, fallback) {
2557
+ return device.createBuffer({
2558
+ data: data.byteLength > 0 ? data : fallback,
2559
+ usage: import_core6.Buffer.VERTEX | import_core6.Buffer.COPY_DST
2560
+ });
2561
+ }
2562
+ function destroyFastTextBuffers(buffers) {
2563
+ if (!buffers) {
2564
+ return;
2565
+ }
2566
+ for (const buffer of Object.values(buffers)) {
2567
+ buffer.destroy();
2568
+ }
2569
+ }
2570
+ function createFastTextAtlasTexture(device, atlas) {
2571
+ const texture = device.createTexture({
2572
+ format: "rgba8unorm",
2573
+ data: null,
2574
+ width: atlas.width,
2575
+ height: atlas.height,
2576
+ sampler: DEFAULT_SAMPLER_PARAMETERS,
2577
+ mipLevels: device.getMipLevelCount(atlas.width, atlas.height)
2578
+ });
2579
+ texture.copyExternalImage({
2580
+ image: atlas.data,
2581
+ width: atlas.width,
2582
+ height: atlas.height
2583
+ });
2584
+ regenerateMipmaps(texture);
2585
+ return texture;
2586
+ }
2587
+ function regenerateMipmaps(texture) {
2588
+ if (texture.device.type === "webgl") {
2589
+ texture.generateMipmapsWebGL();
2590
+ } else if (texture.device.type === "webgpu") {
2591
+ texture.device.generateMipmapsWebGPU(texture);
2592
+ }
2593
+ }
2594
+ function getFastTextContentAlignUniform(mode) {
2595
+ return FAST_TEXT_CONTENT_ALIGN[mode];
2596
+ }
2597
+
2598
+ // dist/views/orthographic-utils.js
2599
+ function fitBoundsOrthographic(width, height, bounds, zoomMode = "per-axis") {
2600
+ const [[minX, minY], [maxX, maxY]] = bounds;
2601
+ const centerX = (minX + maxX) / 2;
2602
+ const centerY = (minY + maxY) / 2;
2603
+ const boxW = Math.max(0, maxX - minX);
2604
+ const boxH = Math.max(0, maxY - minY);
2605
+ const scaleX = boxW ? Math.max(1, width) / boxW : 1;
2606
+ const scaleY = boxH ? Math.max(1, height) / boxH : 1;
2607
+ const scale = Math.min(scaleX, scaleY);
2608
+ const zoom = Math.log2(scale);
2609
+ const zoomX = Math.log2(scaleX);
2610
+ const zoomY = Math.log2(scaleY);
2611
+ if (Number.isNaN(zoom) || Number.isNaN(zoomX) || Number.isNaN(zoomY)) {
2612
+ console.warn("Invalid zoom values:", { zoom, zoomX, zoomY });
2613
+ }
2614
+ return {
2615
+ target: [centerX, centerY],
2616
+ zoom: zoomMode === "single" ? zoom : [zoomX, zoomY],
2617
+ zoomX: zoomMode === "single" ? zoom : zoomX,
2618
+ zoomY: zoomMode === "single" ? zoom : zoomY
2619
+ };
2620
+ }
2621
+ function getBoundsOrthographic(width, height, zoom, target) {
2622
+ const [centerX, centerY] = target;
2623
+ const scaleX = Array.isArray(zoom) ? 2 ** zoom[0] : 2 ** zoom;
2624
+ const scaleY = Array.isArray(zoom) ? 2 ** zoom[1] : 2 ** zoom;
2625
+ const worldW = width / scaleX;
2626
+ const worldH = height / scaleY;
2627
+ return [
2628
+ [centerX - worldW / 2, centerY - worldH / 2],
2629
+ [centerX + worldW / 2, centerY + worldH / 2]
2630
+ ];
2631
+ }
2632
+
2633
+ // dist/views/view-layout/view-layout-item.js
2634
+ var import_core7 = require("@deck.gl/core");
2635
+ var ViewLayoutItem = class {
2636
+ /** Validated props backing this layout node. */
2637
+ props;
2638
+ /**
2639
+ * Creates one validated layout item from discriminated-union props.
2640
+ *
2641
+ * @param props - Layout item props keyed by `type`.
2642
+ */
2643
+ constructor(props) {
2644
+ assertViewLayoutItemProps(props);
2645
+ this.props = props;
2646
+ }
2647
+ };
2648
+ function assertViewLayoutItemProps(props) {
2649
+ if (!props || typeof props !== "object") {
2650
+ throw new Error("ViewLayoutItem props must be an object.");
2651
+ }
2652
+ switch (props.type) {
2653
+ case "row":
2654
+ case "column":
2655
+ case "overlay":
2656
+ if (!Array.isArray(props.children)) {
2657
+ throw new Error(`ViewLayoutItem "${props.type}" requires a children array.`);
2658
+ }
2659
+ break;
2660
+ case "view":
2661
+ if (!(props.view instanceof import_core7.View)) {
2662
+ throw new Error('ViewLayoutItem "view" requires a deck.gl View instance.');
2663
+ }
2664
+ break;
2665
+ case "spacer":
2666
+ break;
2667
+ default: {
2668
+ const exhaustiveCheck = props;
2669
+ throw new Error(`Unsupported view layout item: ${String(exhaustiveCheck)}`);
2670
+ }
2671
+ }
2672
+ }
2673
+
2674
+ // dist/views/view-layout/build-views-from-view-layout.js
2675
+ function buildViewsFromViewLayout(args) {
2676
+ var _a;
2677
+ const rootRect = {
2678
+ x: 0,
2679
+ y: 0,
2680
+ width: Math.max(1, args.width),
2681
+ height: Math.max(1, args.height)
2682
+ };
2683
+ const previousViewsById = new Map((((_a = args.previous) == null ? void 0 : _a.views) ?? []).map((view) => [getViewId(view), view]).filter((entry) => Boolean(entry[0])));
2684
+ const outputViews = [];
2685
+ const rectsById = {};
2686
+ compileLayoutItem({
2687
+ item: args.layout,
2688
+ rect: rootRect,
2689
+ outputViews,
2690
+ rectsById,
2691
+ previousViewsById
2692
+ });
2693
+ return {
2694
+ views: outputViews,
2695
+ rectsById
2696
+ };
2697
+ }
2698
+ function compileLayoutItem(args) {
2699
+ const { item } = args;
2700
+ switch (item.props.type) {
2701
+ case "row":
2702
+ compileStackLayout({ ...args, orientation: "row", children: item.props.children });
2703
+ return;
2704
+ case "column":
2705
+ compileStackLayout({ ...args, orientation: "column", children: item.props.children });
2706
+ return;
2707
+ case "overlay":
2708
+ compileOverlayLayout({ ...args, children: item.props.children });
2709
+ return;
2710
+ case "view":
2711
+ compileResolvedView({
2712
+ view: item.props.view,
2713
+ rect: applyInsets(args.rect, item.props.inset),
2714
+ outputViews: args.outputViews,
2715
+ rectsById: args.rectsById,
2716
+ previousViewsById: args.previousViewsById
2717
+ });
2718
+ return;
2719
+ case "spacer":
2720
+ return;
2721
+ }
2722
+ }
2723
+ function compileStackLayout(args) {
2724
+ const containerRect = applyInsets(args.rect, args.item.props.inset);
2725
+ const children = args.children.filter(isPresentChild);
2726
+ if (children.length === 0) {
2727
+ return;
2728
+ }
2729
+ const containerAxisLength = args.orientation === "row" ? containerRect.width : containerRect.height;
2730
+ const explicitLengths = children.map((child) => resolveStackChildAxisLength(child, args.orientation, containerAxisLength));
2731
+ const fixedLength = explicitLengths.reduce((sum, length) => sum + (length ?? 0), 0);
2732
+ const flexibleChildCount = explicitLengths.filter((length) => length === void 0).length;
2733
+ const flexibleLength = flexibleChildCount > 0 ? Math.max(containerAxisLength - fixedLength, 0) / flexibleChildCount : 0;
2734
+ let cursor = args.orientation === "row" ? containerRect.x : containerRect.y;
2735
+ children.forEach((child, index) => {
2736
+ const childAxisLength = explicitLengths[index] ?? flexibleLength;
2737
+ const childRect = args.orientation === "row" ? {
2738
+ x: cursor,
2739
+ y: containerRect.y,
2740
+ width: childAxisLength,
2741
+ height: containerRect.height
2742
+ } : {
2743
+ x: containerRect.x,
2744
+ y: cursor,
2745
+ width: containerRect.width,
2746
+ height: childAxisLength
2747
+ };
2748
+ cursor += childAxisLength;
2749
+ compileLayoutChild({
2750
+ child,
2751
+ rect: childRect,
2752
+ outputViews: args.outputViews,
2753
+ rectsById: args.rectsById,
2754
+ previousViewsById: args.previousViewsById
2755
+ });
2756
+ });
2757
+ }
2758
+ function compileOverlayLayout(args) {
2759
+ const containerRect = applyInsets(args.rect, args.item.props.inset);
2760
+ args.children.filter(isPresentChild).forEach((child) => compileLayoutChild({
2761
+ child,
2762
+ rect: containerRect,
2763
+ outputViews: args.outputViews,
2764
+ rectsById: args.rectsById,
2765
+ previousViewsById: args.previousViewsById
2766
+ }));
2767
+ }
2768
+ function compileLayoutChild(args) {
2769
+ if (args.child instanceof ViewLayoutItem) {
2770
+ compileLayoutItem({
2771
+ item: args.child,
2772
+ rect: args.rect,
2773
+ outputViews: args.outputViews,
2774
+ rectsById: args.rectsById,
2775
+ previousViewsById: args.previousViewsById
2776
+ });
2777
+ return;
2778
+ }
2779
+ compileResolvedView({
2780
+ view: args.child,
2781
+ rect: args.rect,
2782
+ outputViews: args.outputViews,
2783
+ rectsById: args.rectsById,
2784
+ previousViewsById: args.previousViewsById
2785
+ });
2786
+ }
2787
+ function compileResolvedView(args) {
2788
+ const resolvedRect = resolveViewRectWithinParent(args.view, args.rect);
2789
+ const viewId = getRequiredViewId(args.view);
2790
+ args.rectsById[viewId] = resolvedRect;
2791
+ const nextProps = {
2792
+ ...args.view.props,
2793
+ x: resolvedRect.x,
2794
+ y: resolvedRect.y,
2795
+ width: resolvedRect.width,
2796
+ height: resolvedRect.height
2797
+ };
2798
+ const previousView = args.previousViewsById.get(viewId);
2799
+ const nextView = previousView && previousView.constructor === args.view.constructor && arePropsEqual(previousView.props, nextProps) ? previousView : instantiateView(args.view, nextProps);
2800
+ args.outputViews.push(nextView);
2801
+ }
2802
+ function resolveStackChildAxisLength(child, orientation, parentAxisLength) {
2803
+ const axisValue = getAxisLengthValue(child, orientation);
2804
+ if (axisValue === void 0) {
2805
+ return void 0;
2806
+ }
2807
+ return resolveLength(axisValue, parentAxisLength);
2808
+ }
2809
+ function resolveViewRectWithinParent(view, parentRect) {
2810
+ const props = view.props;
2811
+ const x = parentRect.x + resolveOffset(props.x, parentRect.width);
2812
+ const y = parentRect.y + resolveOffset(props.y, parentRect.height);
2813
+ const width = resolveDimension(props.width, parentRect.width, parentRect.width);
2814
+ const height = resolveDimension(props.height, parentRect.height, parentRect.height);
2815
+ return {
2816
+ x,
2817
+ y,
2818
+ width,
2819
+ height
2820
+ };
2821
+ }
2822
+ function instantiateView(view, props) {
2823
+ const ViewConstructor = view.constructor;
2824
+ return new ViewConstructor(props);
2825
+ }
2826
+ function getAxisLengthValue(child, orientation) {
2827
+ if (child instanceof ViewLayoutItem) {
2828
+ return orientation === "row" ? child.props.width : child.props.height;
2829
+ }
2830
+ const props = child.props;
2831
+ return orientation === "row" ? props.width : props.height;
2832
+ }
2833
+ function applyInsets(rect, inset) {
2834
+ if (!inset) {
2835
+ return rect;
2836
+ }
2837
+ const top = inset.top ?? 0;
2838
+ const right = inset.right ?? 0;
2839
+ const bottom = inset.bottom ?? 0;
2840
+ const left = inset.left ?? 0;
2841
+ return {
2842
+ x: rect.x + left,
2843
+ y: rect.y + top,
2844
+ width: Math.max(0, rect.width - left - right),
2845
+ height: Math.max(0, rect.height - top - bottom)
2846
+ };
2847
+ }
2848
+ function resolveOffset(value, parentLength) {
2849
+ if (value === void 0 || value === null) {
2850
+ return 0;
2851
+ }
2852
+ return resolveLength(value, parentLength);
2853
+ }
2854
+ function resolveDimension(value, parentLength, fallback) {
2855
+ if (value === void 0 || value === null) {
2856
+ return fallback;
2857
+ }
2858
+ return resolveLength(value, parentLength);
2859
+ }
2860
+ function resolveLength(value, parentLength) {
2861
+ if (typeof value === "number") {
2862
+ return value;
2863
+ }
2864
+ const normalized = value.trim();
2865
+ if (normalized.length === 0) {
2866
+ throw new Error("View layout length must not be empty.");
2867
+ }
2868
+ if (normalized.startsWith("calc(") && normalized.endsWith(")")) {
2869
+ return resolveCalcExpression(normalized.slice(5, -1), parentLength);
2870
+ }
2871
+ return resolveLengthTerm(normalized, parentLength);
2872
+ }
2873
+ function resolveCalcExpression(expression, parentLength) {
2874
+ const sanitized = expression.replace(/\s+/g, "");
2875
+ const terms = sanitized.match(/[+-]?[^+-]+/g);
2876
+ if (!terms) {
2877
+ throw new Error(`Unsupported calc expression: calc(${expression})`);
2878
+ }
2879
+ return terms.reduce((sum, term) => sum + resolveLengthTerm(term, parentLength), 0);
2880
+ }
2881
+ function resolveLengthTerm(term, parentLength) {
2882
+ if (term.endsWith("%")) {
2883
+ return Number.parseFloat(term.slice(0, -1)) / 100 * parentLength;
2884
+ }
2885
+ if (term.endsWith("px")) {
2886
+ return Number.parseFloat(term.slice(0, -2));
2887
+ }
2888
+ return Number.parseFloat(term);
2889
+ }
2890
+ function getViewId(view) {
2891
+ const viewId = view.props.id;
2892
+ return typeof viewId === "string" && viewId.length > 0 ? viewId : null;
2893
+ }
2894
+ function getRequiredViewId(view) {
2895
+ const viewId = getViewId(view);
2896
+ if (!viewId) {
2897
+ throw new Error("Every compiled deck view must have a string id.");
2898
+ }
2899
+ return viewId;
2900
+ }
2901
+ function arePropsEqual(left, right) {
2902
+ if (left === right) {
2903
+ return true;
2904
+ }
2905
+ const leftKeys = Object.keys(left);
2906
+ const rightKeys = Object.keys(right);
2907
+ if (leftKeys.length !== rightKeys.length) {
2908
+ return false;
2909
+ }
2910
+ return leftKeys.every((key) => areValuesEqual(left[key], right[key]));
2911
+ }
2912
+ function areValuesEqual(left, right) {
2913
+ if (Object.is(left, right)) {
2914
+ return true;
2915
+ }
2916
+ if (Array.isArray(left) && Array.isArray(right)) {
2917
+ return left.length === right.length && left.every((value, index) => areValuesEqual(value, right[index]));
2918
+ }
2919
+ if (isPlainObject(left) && isPlainObject(right)) {
2920
+ const leftEntries = Object.keys(left);
2921
+ const rightEntries = Object.keys(right);
2922
+ return leftEntries.length === rightEntries.length && leftEntries.every((key) => areValuesEqual(left[key], right[key]));
2923
+ }
2924
+ return false;
2925
+ }
2926
+ function isPlainObject(value) {
2927
+ return Boolean(value) && typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype;
2928
+ }
2929
+ function isPresentChild(child) {
2930
+ return Boolean(child);
2931
+ }
2932
+
2933
+ // dist/views/bounds-utils.js
2934
+ function getPaddedBlockBounds(geometry, options) {
2935
+ const bounds = getGeometryBounds(geometry);
2936
+ if (!bounds) {
2937
+ return null;
2938
+ }
2939
+ const paddingFraction = (options == null ? void 0 : options.paddingFraction) ?? 0.1;
2940
+ const minimumPadding = (options == null ? void 0 : options.minimumPadding) ?? 1;
2941
+ return padBounds(bounds, paddingFraction, minimumPadding);
2942
+ }
2943
+ function getGeometryBounds(geometry) {
2944
+ if (!geometry || geometry.length < 2) {
2945
+ return null;
2946
+ }
2947
+ let minX = Infinity;
2948
+ let minY = Infinity;
2949
+ let maxX = -Infinity;
2950
+ let maxY = -Infinity;
2951
+ for (let index = 0; index < geometry.length; index += 2) {
2952
+ const x = geometry[index];
2953
+ const y = geometry[index + 1];
2954
+ if (x < minX)
2955
+ minX = x;
2956
+ if (y < minY)
2957
+ minY = y;
2958
+ if (x > maxX)
2959
+ maxX = x;
2960
+ if (y > maxY)
2961
+ maxY = y;
2962
+ }
2963
+ if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {
2964
+ return null;
2965
+ }
2966
+ return [
2967
+ [minX, minY],
2968
+ [maxX, maxY]
2969
+ ];
2970
+ }
2971
+ function padBounds(bounds, paddingFraction, minimumPadding) {
2972
+ const [[minX, minY], [maxX, maxY]] = bounds;
2973
+ const width = maxX - minX;
2974
+ const height = maxY - minY;
2975
+ const paddingX = Math.max(width * paddingFraction, minimumPadding);
2976
+ const paddingY = Math.max(height * paddingFraction, minimumPadding);
2977
+ return [
2978
+ [minX - paddingX, minY - paddingY],
2979
+ [maxX + paddingX, maxY + paddingY]
2980
+ ];
2981
+ }
2982
+
2983
+ // dist/views/view-state-utils.js
2984
+ function mergeViewStates(viewState1, viewState2) {
2985
+ var _a, _b, _c, _d;
2986
+ const target1 = viewState1.target ?? [0, 0];
2987
+ const zoom1 = viewState1.zoom ?? [1, 1];
2988
+ const mergedViewState = {
2989
+ ...viewState1,
2990
+ ...viewState2,
2991
+ target: [((_a = viewState2.target) == null ? void 0 : _a[0]) ?? target1[0], ((_b = viewState2.target) == null ? void 0 : _b[1]) ?? target1[1]],
2992
+ zoom: [
2993
+ // ts-expect-error view state typing is awfully optional
2994
+ ((_c = viewState2.zoom) == null ? void 0 : _c[0]) ?? zoom1[0],
2995
+ // ts-expect-error view state typing is awfully optional
2996
+ ((_d = viewState2.zoom) == null ? void 0 : _d[1]) ?? zoom1[1]
2997
+ ]
2998
+ };
2999
+ validateViewState(mergedViewState);
3000
+ return mergedViewState;
3001
+ }
3002
+ function validateViewState(viewState) {
3003
+ const isTargetValid = Array.isArray(viewState.target) && viewState.target[0] !== void 0 && !Number.isNaN(viewState.target[0]) && viewState.target[1] !== void 0 && !Number.isNaN(viewState.target[1]);
3004
+ const isZoomValid = Array.isArray(viewState.zoom) && viewState.zoom[0] !== void 0 && !Number.isNaN(viewState.zoom[0]) && viewState.zoom[1] !== void 0 && !Number.isNaN(viewState.zoom[1]);
3005
+ if (!isTargetValid || !isZoomValid) {
3006
+ console.warn("Invalid viewState:", viewState);
3007
+ }
3008
+ return isTargetValid && isZoomValid;
3009
+ }
3010
+
3011
+ // dist/views/layer-filter.js
3012
+ function makeLayerFilter(filters) {
3013
+ const regexpFilters = {};
3014
+ for (const [key, value] of Object.entries(filters)) {
3015
+ if ("include" in value) {
3016
+ regexpFilters[key] = {
3017
+ include: value.include.map((v) => new RegExp(v))
3018
+ };
3019
+ } else {
3020
+ regexpFilters[key] = {
3021
+ exclude: value.exclude.map((v) => new RegExp(v))
3022
+ };
3023
+ }
3024
+ }
3025
+ return ({ viewport, layer }) => {
3026
+ let visible = true;
3027
+ const viewFilters = regexpFilters[viewport.id] || {};
3028
+ if ("include" in viewFilters) {
3029
+ if (!viewFilters.include.some((regexp) => regexp.test(layer.id))) {
3030
+ visible = false;
3031
+ }
3032
+ }
3033
+ if ("exclude" in viewFilters) {
3034
+ if (viewFilters.exclude.some((regexp) => regexp.test(layer.id))) {
3035
+ visible = false;
3036
+ }
3037
+ }
3038
+ return visible;
3039
+ };
3040
+ }
3041
+
3042
+ // dist/views/viewport-bounds-utils.js
3043
+ var DEFAULT_BOUNDS_EPSILON = 1e-6;
3044
+ function boundsAreEqual(a, b, options) {
3045
+ const epsilon = (options == null ? void 0 : options.epsilon) ?? DEFAULT_BOUNDS_EPSILON;
3046
+ let [ax, ay] = a[0];
3047
+ let [bx, by] = b[0];
3048
+ if (Math.abs(ax - bx) > epsilon || Math.abs(ay - by) > epsilon) {
3049
+ return false;
3050
+ }
3051
+ [ax, ay] = a[1];
3052
+ [bx, by] = b[1];
3053
+ if (Math.abs(ax - bx) > epsilon || Math.abs(ay - by) > epsilon) {
3054
+ return false;
3055
+ }
3056
+ return true;
3057
+ }
3058
+ function getViewportBoundsForViewState(view, deckDimensions) {
3059
+ const target = view.target ?? [0, 0];
3060
+ const zoomValue = view.zoom;
3061
+ const zoomArray = Array.isArray(zoomValue) ? zoomValue : typeof zoomValue === "number" ? [zoomValue, zoomValue] : [0, 0];
3062
+ const zoomX = zoomArray[0] ?? 0;
3063
+ const zoomY = zoomArray[1] ?? zoomArray[0] ?? 0;
3064
+ const scaleX = 2 ** zoomX || 1;
3065
+ const scaleY = 2 ** zoomY || 1;
3066
+ const halfWidth = deckDimensions.width / scaleX / 2;
3067
+ const halfHeight = deckDimensions.height / scaleY / 2;
3068
+ return {
3069
+ minX: target[0] - halfWidth,
3070
+ maxX: target[0] + halfWidth,
3071
+ minY: target[1] - halfHeight,
3072
+ maxY: target[1] + halfHeight
3073
+ };
3074
+ }
3075
+ function isBoundsCompletelyOutside(bounds, viewport) {
3076
+ const [[minX, minY], [maxX, maxY]] = bounds;
3077
+ return maxX < viewport.minX || minX > viewport.maxX || maxY < viewport.minY || minY > viewport.maxY;
3078
+ }
3079
+
3080
+ // dist/views/layer-bounds-filter.js
3081
+ function combineLayerFilters(filters) {
3082
+ const definedFilters = filters.filter(Boolean);
3083
+ if (!definedFilters.length) {
3084
+ return null;
3085
+ }
3086
+ if (definedFilters.length === 1) {
3087
+ return definedFilters[0];
3088
+ }
3089
+ return (context) => definedFilters.every((filter) => filter(context));
3090
+ }
3091
+ function createViewportBoundsFilter(options) {
3092
+ const layerBoundsCache = /* @__PURE__ */ new WeakMap();
3093
+ const viewportBoundsCache = /* @__PURE__ */ new WeakMap();
3094
+ return (context) => {
3095
+ var _a, _b, _c;
3096
+ const { layer, viewport } = context;
3097
+ let layerBounds = layerBoundsCache.get(layer);
3098
+ if (layerBounds === void 0) {
3099
+ layerBounds = getLayerBounds(layer);
3100
+ layerBoundsCache.set(layer, layerBounds);
3101
+ }
3102
+ if (!layerBounds) {
3103
+ (_a = options == null ? void 0 : options.onDecision) == null ? void 0 : _a.call(options, { decision: "missing-layer-bounds", context });
3104
+ return true;
3105
+ }
3106
+ let viewportBounds = viewportBoundsCache.get(viewport);
3107
+ if (viewportBounds === void 0) {
3108
+ viewportBounds = getViewportBounds(viewport);
3109
+ viewportBoundsCache.set(viewport, viewportBounds);
3110
+ }
3111
+ if (!viewportBounds) {
3112
+ (_b = options == null ? void 0 : options.onDecision) == null ? void 0 : _b.call(options, { decision: "missing-viewport-bounds", context, layerBounds });
3113
+ return true;
3114
+ }
3115
+ const shouldRender = boundsOverlap(layerBounds, viewportBounds);
3116
+ if (!shouldRender) {
3117
+ (_c = options == null ? void 0 : options.onDecision) == null ? void 0 : _c.call(options, { decision: "filter", context, layerBounds, viewportBounds });
3118
+ }
3119
+ return shouldRender;
3120
+ };
3121
+ }
3122
+ function getLayerBounds(layer) {
3123
+ const bounds = layer.getBounds();
3124
+ if (!bounds || bounds.length < 2) {
3125
+ return null;
3126
+ }
3127
+ return normalizeBounds(bounds[0], bounds[1]);
3128
+ }
3129
+ function getViewportBounds(viewport) {
3130
+ const bounds = viewport.getBounds();
3131
+ if (!bounds || bounds.length < 4) {
3132
+ return null;
3133
+ }
3134
+ const [minX, minY, maxX, maxY] = bounds;
3135
+ if (!isFiniteNumber(minX) || !isFiniteNumber(minY) || !isFiniteNumber(maxX) || !isFiniteNumber(maxY)) {
3136
+ return null;
3137
+ }
3138
+ return normalizeBounds([minX, minY], [maxX, maxY]);
3139
+ }
3140
+ function normalizeBounds(min, max) {
3141
+ if (!min || !max || min.length < 2 || max.length < 2) {
3142
+ return null;
3143
+ }
3144
+ const minX = Math.min(min[0], max[0]);
3145
+ const minY = Math.min(min[1], max[1]);
3146
+ const maxX = Math.max(min[0], max[0]);
3147
+ const maxY = Math.max(min[1], max[1]);
3148
+ if (!isFiniteNumber(minX) || !isFiniteNumber(minY) || !isFiniteNumber(maxX) || !isFiniteNumber(maxY)) {
3149
+ return null;
3150
+ }
3151
+ return [minX, minY, maxX, maxY];
3152
+ }
3153
+ function boundsOverlap(a, b) {
3154
+ return !(a[2] < b[0] || b[2] < a[0] || a[3] < b[1] || b[3] < a[1]);
3155
+ }
3156
+ function isFiniteNumber(value) {
3157
+ return Number.isFinite(value);
3158
+ }
3159
+
3160
+ // dist/synchronized-views/synchronized-views.js
3161
+ var import_core8 = require("@deck.gl/core");
3162
+ var HEADER_VIEW_HEIGHT = 50;
3163
+ var LEGEND_VIEW_WIDTH = 150;
3164
+ var SYNCHRONIZED_VIEWS = [
3165
+ new import_core8.OrthographicView({
3166
+ id: "main",
3167
+ flipY: false,
3168
+ clear: true,
3169
+ // [1, 1, 1, 1],
3170
+ x: LEGEND_VIEW_WIDTH,
3171
+ width: `calc(100% - ${LEGEND_VIEW_WIDTH}px)`,
288
3172
  y: HEADER_VIEW_HEIGHT,
289
3173
  height: `calc(100% - ${HEADER_VIEW_HEIGHT}px)`,
290
3174
  controller: {
291
- type: import_core2.OrthographicController,
3175
+ type: import_core8.OrthographicController,
292
3176
  // @ts-expect-error Specific to OrthographicController
293
3177
  zoomAxis: "X",
294
3178
  inertia: false,
295
3179
  scrollZoom: true
296
3180
  }
297
3181
  }),
298
- new import_core2.OrthographicView({
3182
+ new import_core8.OrthographicView({
299
3183
  id: "header",
300
3184
  flipY: false,
301
3185
  clear: true,
@@ -305,7 +3189,7 @@ var SYNCHRONIZED_VIEWS = [
305
3189
  height: 50,
306
3190
  controller: false
307
3191
  }),
308
- new import_core2.OrthographicView({
3192
+ new import_core8.OrthographicView({
309
3193
  id: "legend",
310
3194
  flipY: false,
311
3195
  clear: true,