@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.
- package/dist/index.cjs +2998 -114
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/layers/animation-layer/animation-layer.d.ts +30 -0
- package/dist/layers/animation-layer/animation-layer.d.ts.map +1 -0
- package/dist/layers/animation-layer/animation-layer.js +53 -0
- package/dist/layers/animation-layer/animation-layer.js.map +1 -0
- package/dist/layers/animation-layer/animation.d.ts +86 -0
- package/dist/layers/animation-layer/animation.d.ts.map +1 -0
- package/dist/layers/animation-layer/animation.js +214 -0
- package/dist/layers/animation-layer/animation.js.map +1 -0
- package/dist/layers/block-layer/block-layer-fragment.glsl.d.ts +3 -0
- package/dist/layers/block-layer/block-layer-fragment.glsl.d.ts.map +1 -0
- package/dist/layers/block-layer/block-layer-fragment.glsl.js +41 -0
- package/dist/layers/block-layer/block-layer-fragment.glsl.js.map +1 -0
- package/dist/layers/block-layer/block-layer-uniforms.d.ts +27 -0
- package/dist/layers/block-layer/block-layer-uniforms.d.ts.map +1 -0
- package/dist/layers/block-layer/block-layer-uniforms.js +26 -0
- package/dist/layers/block-layer/block-layer-uniforms.js.map +1 -0
- package/dist/layers/block-layer/block-layer-vertex.glsl.d.ts +3 -0
- package/dist/layers/block-layer/block-layer-vertex.glsl.d.ts.map +1 -0
- package/dist/layers/block-layer/block-layer-vertex.glsl.js +67 -0
- package/dist/layers/block-layer/block-layer-vertex.glsl.js.map +1 -0
- package/dist/layers/block-layer/block-layer.d.ts +71 -0
- package/dist/layers/block-layer/block-layer.d.ts.map +1 -0
- package/dist/layers/block-layer/block-layer.js +108 -0
- package/dist/layers/block-layer/block-layer.js.map +1 -0
- package/dist/layers/fast-text-layer/fast-text-layer.d.ts +148 -0
- package/dist/layers/fast-text-layer/fast-text-layer.d.ts.map +1 -0
- package/dist/layers/fast-text-layer/fast-text-layer.js +862 -0
- package/dist/layers/fast-text-layer/fast-text-layer.js.map +1 -0
- package/dist/layers/fast-text-layer/fast-text-layer.test.d.ts +2 -0
- package/dist/layers/fast-text-layer/fast-text-layer.test.d.ts.map +1 -0
- package/dist/layers/fast-text-layer/fast-text-layer.test.js +300 -0
- package/dist/layers/fast-text-layer/fast-text-layer.test.js.map +1 -0
- package/dist/layers/fast-text-layer/fast-text-layout.d.ts +179 -0
- package/dist/layers/fast-text-layer/fast-text-layout.d.ts.map +1 -0
- package/dist/layers/fast-text-layer/fast-text-layout.js +665 -0
- package/dist/layers/fast-text-layer/fast-text-layout.js.map +1 -0
- package/dist/layers/fast-text-layer/font-atlas.d.ts +98 -0
- package/dist/layers/fast-text-layer/font-atlas.d.ts.map +1 -0
- package/dist/layers/fast-text-layer/font-atlas.js +337 -0
- package/dist/layers/fast-text-layer/font-atlas.js.map +1 -0
- package/dist/layers/fast-text-layer/index.d.ts +4 -0
- package/dist/layers/fast-text-layer/index.d.ts.map +1 -0
- package/dist/layers/fast-text-layer/index.js +4 -0
- package/dist/layers/fast-text-layer/index.js.map +1 -0
- package/dist/layers/time-delta-layer.d.ts +22 -60
- package/dist/layers/time-delta-layer.d.ts.map +1 -1
- package/dist/layers/time-delta-layer.js +31 -53
- package/dist/layers/time-delta-layer.js.map +1 -1
- package/dist/synchronized-views/synchronized-views.js +1 -1
- package/dist/synchronized-views/synchronized-views.js.map +1 -1
- package/dist/utils/format-utils.d.ts +27 -3
- package/dist/utils/format-utils.d.ts.map +1 -1
- package/dist/utils/format-utils.js +72 -40
- package/dist/utils/format-utils.js.map +1 -1
- package/dist/utils/utf8-string-view.d.ts +53 -0
- package/dist/utils/utf8-string-view.d.ts.map +1 -0
- package/dist/utils/utf8-string-view.js +169 -0
- package/dist/utils/utf8-string-view.js.map +1 -0
- package/dist/utils/utf8-string-view.test.d.ts +2 -0
- package/dist/utils/utf8-string-view.test.d.ts.map +1 -0
- package/dist/utils/utf8-string-view.test.js +88 -0
- package/dist/utils/utf8-string-view.test.js.map +1 -0
- package/dist/views/bounds-utils.d.ts +23 -0
- package/dist/views/bounds-utils.d.ts.map +1 -0
- package/dist/views/bounds-utils.js +65 -0
- package/dist/views/bounds-utils.js.map +1 -0
- package/dist/views/layer-bounds-filter.d.ts +48 -0
- package/dist/views/layer-bounds-filter.d.ts.map +1 -0
- package/dist/views/layer-bounds-filter.js +99 -0
- package/dist/views/layer-bounds-filter.js.map +1 -0
- package/dist/views/layer-filter.js +4 -4
- package/dist/views/layer-filter.js.map +1 -1
- package/dist/views/orthographic-utils.d.ts +30 -2
- package/dist/views/orthographic-utils.d.ts.map +1 -1
- package/dist/views/orthographic-utils.js +33 -14
- package/dist/views/orthographic-utils.js.map +1 -1
- package/dist/views/view-layout/build-views-from-view-layout.d.ts +37 -0
- package/dist/views/view-layout/build-views-from-view-layout.d.ts.map +1 -0
- package/dist/views/view-layout/build-views-from-view-layout.js +413 -0
- package/dist/views/view-layout/build-views-from-view-layout.js.map +1 -0
- package/dist/views/view-layout/index.d.ts +3 -0
- package/dist/views/view-layout/index.d.ts.map +1 -0
- package/dist/views/view-layout/index.js +3 -0
- package/dist/views/view-layout/index.js.map +1 -0
- package/dist/views/view-layout/view-layout-item.d.ts +74 -0
- package/dist/views/view-layout/view-layout-item.d.ts.map +1 -0
- package/dist/views/view-layout/view-layout-item.js +48 -0
- package/dist/views/view-layout/view-layout-item.js.map +1 -0
- package/dist/views/view-layout/view-layout.test.d.ts +2 -0
- package/dist/views/view-layout/view-layout.test.d.ts.map +1 -0
- package/dist/views/view-layout/view-layout.test.js +112 -0
- package/dist/views/view-layout/view-layout.test.js.map +1 -0
- package/dist/views/viewport-bounds-utils.d.ts +55 -0
- package/dist/views/viewport-bounds-utils.d.ts.map +1 -0
- package/dist/views/viewport-bounds-utils.js +70 -0
- package/dist/views/viewport-bounds-utils.js.map +1 -0
- package/package.json +15 -5
- package/src/index.ts +91 -2
- package/src/layers/animation-layer/animation-layer.ts +92 -0
- package/src/layers/animation-layer/animation.ts +328 -0
- package/src/layers/block-layer/block-layer-fragment.glsl.ts +41 -0
- package/src/layers/block-layer/block-layer-uniforms.ts +43 -0
- package/src/layers/block-layer/block-layer-vertex.glsl.ts +67 -0
- package/src/layers/block-layer/block-layer.ts +199 -0
- package/src/layers/fast-text-layer/fast-text-layer.test.ts +359 -0
- package/src/layers/fast-text-layer/fast-text-layer.ts +1208 -0
- package/src/layers/fast-text-layer/fast-text-layout.ts +1124 -0
- package/src/layers/fast-text-layer/font-atlas.ts +574 -0
- package/src/layers/fast-text-layer/index.ts +37 -0
- package/src/layers/time-delta-layer.ts +55 -70
- package/src/synchronized-views/synchronized-views.ts +1 -1
- package/src/utils/format-utils.ts +90 -40
- package/src/utils/utf8-string-view.test.ts +119 -0
- package/src/utils/utf8-string-view.ts +273 -0
- package/src/views/bounds-utils.ts +88 -0
- package/src/views/layer-bounds-filter.ts +160 -0
- package/src/views/layer-filter.ts +4 -4
- package/src/views/orthographic-utils.ts +65 -18
- package/src/views/view-layout/build-views-from-view-layout.ts +547 -0
- package/src/views/view-layout/index.ts +18 -0
- package/src/views/view-layout/view-layout-item.ts +125 -0
- package/src/views/view-layout/view-layout.test.ts +129 -0
- 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,
|
|
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}
|
|
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}
|
|
93
|
+
return `${floatToStr(s, roundDigits)}${sep}s`;
|
|
64
94
|
}
|
|
65
95
|
const m = s / 60;
|
|
66
96
|
if (Math.abs(m) < 60) {
|
|
67
|
-
return
|
|
97
|
+
return formatMinuteDuration(s);
|
|
68
98
|
}
|
|
69
99
|
const h = m / 60;
|
|
70
100
|
if (Math.abs(h) < 24) {
|
|
71
|
-
return
|
|
101
|
+
return formatHourDuration(s);
|
|
72
102
|
}
|
|
73
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
|
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:
|
|
168
|
+
getColor: color3,
|
|
118
169
|
getWidth: 4,
|
|
119
170
|
widthUnits: "pixels"
|
|
120
171
|
})
|
|
121
172
|
];
|
|
122
173
|
}
|
|
123
|
-
const
|
|
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,
|
|
127
|
-
targetPosition: [startTimeMs,
|
|
180
|
+
sourcePosition: [startTimeMs, y],
|
|
181
|
+
targetPosition: [startTimeMs, y - 7]
|
|
128
182
|
},
|
|
129
183
|
{
|
|
130
|
-
sourcePosition: [endTimeMs,
|
|
131
|
-
targetPosition: [endTimeMs,
|
|
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:
|
|
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,
|
|
151
|
-
targetPosition: [endTimeMs,
|
|
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:
|
|
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
|
-
|
|
167
|
-
|
|
220
|
+
characterSet: "-0123456789.dhms\xB5",
|
|
221
|
+
getSize: fontSize,
|
|
222
|
+
fontFamily,
|
|
223
|
+
fontSettings,
|
|
224
|
+
fontWeight,
|
|
225
|
+
getColor: color3,
|
|
168
226
|
getTextAnchor: "middle",
|
|
169
|
-
getAlignmentBaseline: "
|
|
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/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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/
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
|
|
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/
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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
|
-
|
|
255
|
-
exclude: value.exclude.map((v) => new RegExp(v))
|
|
256
|
-
};
|
|
951
|
+
writeSingleLineStringLabelGlyphs(props, object, objectInfo, writeState, writeTimings);
|
|
257
952
|
}
|
|
258
953
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
-
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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:
|
|
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
|
|
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
|
|
3192
|
+
new import_core8.OrthographicView({
|
|
309
3193
|
id: "legend",
|
|
310
3194
|
flipY: false,
|
|
311
3195
|
clear: true,
|