@vectojs/core 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-XIEQHSBB.mjs → chunk-AQTO7OSU.mjs} +253 -496
- package/dist/{chunk-2Z23LTH3.js → chunk-DUYB4GX4.js} +310 -551
- package/dist/{chunk-BEUIB3U7.js → chunk-IYPLG4Z4.js} +93 -43
- package/dist/{chunk-L5BCKFQE.mjs → chunk-JFU56BX4.mjs} +48 -0
- package/dist/index.d.ts +4 -12
- package/dist/index.js +2155 -456
- package/dist/index.mjs +1977 -279
- package/dist/layout/index.d.ts +1 -3
- package/dist/layout.js +3 -15
- package/dist/layout.mjs +2 -16
- package/dist/renderer/CanvasRenderer.d.ts +22 -0
- package/dist/renderer/IRenderer.d.ts +13 -0
- package/dist/renderer.js +4 -3
- package/dist/renderer.mjs +1 -1
- package/dist/text/MSDFTextEntity.d.ts +30 -1
- package/dist/text/index.d.ts +1 -5
- package/dist/text.js +5 -15
- package/dist/text.mjs +6 -17
- package/dist/tree/ComputeParticleEntity.d.ts +18 -0
- package/dist/tree/DOMPortalEntity.d.ts +18 -0
- package/dist/tree/Entity.d.ts +122 -6
- package/dist/tree/Scene.d.ts +380 -0
- package/dist/wasm/anim-backend.d.ts +86 -0
- package/dist/wasm/asset.d.ts +25 -0
- package/dist/wasm/asset.js +7 -0
- package/dist/wasm/asset.mjs +5 -0
- package/dist/wasm/backend.d.ts +154 -0
- package/dist/wasm/hit-backend.d.ts +92 -0
- package/dist/wasm/hit-store.d.ts +48 -0
- package/dist/wasm/particle-backend.d.ts +104 -0
- package/dist/wasm/scene-store.d.ts +28 -0
- package/dist/wasm/soa.d.ts +146 -0
- package/dist/wasm/vectojs_core.wasm +0 -0
- package/package.json +17 -8
- package/dist/animation/drivers.d.ts +0 -48
- package/dist/animation/easing.d.ts +0 -16
- package/dist/chunk-4AR425AR.js +0 -1121
- package/dist/chunk-BA5HUUDF.js +0 -760
- package/dist/chunk-IESDTEJ4.mjs +0 -1121
- package/dist/chunk-X7I465AQ.mjs +0 -760
- package/dist/layout/LayoutEngine.d.ts +0 -289
- package/dist/layout/LayoutWorker.d.ts +0 -23
- package/dist/layout/LayoutWorkerManager.d.ts +0 -26
- package/dist/layout/LayoutWorkerSource.d.ts +0 -1
- package/dist/layout/measure.d.ts +0 -20
- package/dist/math/SpatialHashGrid.d.ts +0 -53
- package/dist/math/SpringPhysics.d.ts +0 -13
- package/dist/text/ArabicShaper.d.ts +0 -10
- package/dist/text/BidiResolver.d.ts +0 -5
- package/dist/text/MSDFFont.d.ts +0 -129
- package/dist/text/PreparedContentGrid.d.ts +0 -60
- package/dist/text/Typography.d.ts +0 -11
|
@@ -1,137 +1,11 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4;
|
|
2
|
-
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4;const __vecto_cjs_url=require("url").pathToFileURL(__filename).href;
|
|
3
2
|
|
|
3
|
+
// src/tree/Entity.ts
|
|
4
4
|
|
|
5
|
-
var _chunk4AR425ARjs = require('./chunk-4AR425AR.js');
|
|
6
5
|
|
|
7
|
-
// src/math/SpringPhysics.ts
|
|
8
|
-
var MAX_FRAME_DT = 0.25;
|
|
9
|
-
var MAX_STEP_DT = 1 / 120;
|
|
10
|
-
var SpringPhysics = (_class = class {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
__init() {this.velocity = 0}
|
|
14
|
-
__init2() {this.stiffness = 180}
|
|
15
|
-
__init3() {this.damping = 12}
|
|
16
|
-
__init4() {this.mass = 1}
|
|
17
|
-
__init5() {this.valEpsilon = 5e-3}
|
|
18
|
-
__init6() {this.velEpsilon = 5e-3}
|
|
19
|
-
constructor(initial) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);
|
|
20
|
-
this.value = initial;
|
|
21
|
-
this.target = initial;
|
|
22
|
-
}
|
|
23
|
-
update(dt) {
|
|
24
|
-
if (this.isAtRest()) {
|
|
25
|
-
this.value = this.target;
|
|
26
|
-
this.velocity = 0;
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (!(dt > 0)) return;
|
|
30
|
-
let remaining = dt < MAX_FRAME_DT ? dt : MAX_FRAME_DT;
|
|
31
|
-
while (remaining > 0) {
|
|
32
|
-
const step = remaining < MAX_STEP_DT ? remaining : MAX_STEP_DT;
|
|
33
|
-
const forceSpring = -this.stiffness * (this.value - this.target);
|
|
34
|
-
const forceDamping = -this.damping * this.velocity;
|
|
35
|
-
const acceleration = (forceSpring + forceDamping) / this.mass;
|
|
36
|
-
this.velocity += acceleration * step;
|
|
37
|
-
this.value += this.velocity * step;
|
|
38
|
-
remaining -= step;
|
|
39
|
-
if (this.isAtRest()) {
|
|
40
|
-
this.value = this.target;
|
|
41
|
-
this.velocity = 0;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
isAtRest() {
|
|
47
|
-
return Math.abs(this.value - this.target) < this.valEpsilon && Math.abs(this.velocity) < this.velEpsilon;
|
|
48
|
-
}
|
|
49
|
-
}, _class);
|
|
50
6
|
|
|
51
|
-
// src/animation/easing.ts
|
|
52
|
-
var c1 = 1.70158;
|
|
53
|
-
var c3 = c1 + 1;
|
|
54
|
-
var Easing = {
|
|
55
|
-
linear: (t) => t,
|
|
56
|
-
easeInQuad: (t) => t * t,
|
|
57
|
-
easeOutQuad: (t) => t * (2 - t),
|
|
58
|
-
easeInOutQuad: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
|
|
59
|
-
easeInCubic: (t) => t * t * t,
|
|
60
|
-
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
|
61
|
-
easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,
|
|
62
|
-
easeOutBack: (t) => 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2),
|
|
63
|
-
easeInOutBack: (t) => {
|
|
64
|
-
const c2 = c1 * 1.525;
|
|
65
|
-
return t < 0.5 ? Math.pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2) / 2 : (Math.pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
7
|
|
|
69
|
-
|
|
70
|
-
function isTweenConfig(c) {
|
|
71
|
-
return typeof c === "object" && "duration" in c;
|
|
72
|
-
}
|
|
73
|
-
var TweenDriver = (_class2 = class {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
__init7() {this.elapsed = 0}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
constructor(from, to, cfg) {;_class2.prototype.__init7.call(this);
|
|
82
|
-
this.value = from;
|
|
83
|
-
this.from = from;
|
|
84
|
-
this.to = to;
|
|
85
|
-
this.duration = Math.max(1, cfg.duration);
|
|
86
|
-
this.delay = _nullishCoalesce(cfg.delay, () => ( 0));
|
|
87
|
-
this.ease = typeof cfg.easing === "function" ? cfg.easing : Easing[_nullishCoalesce(cfg.easing, () => ( "easeOutQuad"))];
|
|
88
|
-
}
|
|
89
|
-
get target() {
|
|
90
|
-
return this.to;
|
|
91
|
-
}
|
|
92
|
-
retarget(to) {
|
|
93
|
-
this.from = this.value;
|
|
94
|
-
this.to = to;
|
|
95
|
-
this.elapsed = 0;
|
|
96
|
-
}
|
|
97
|
-
tick(dtMs) {
|
|
98
|
-
this.elapsed += dtMs;
|
|
99
|
-
const active = this.elapsed - this.delay;
|
|
100
|
-
if (active <= 0) return;
|
|
101
|
-
const p = Math.min(active / this.duration, 1);
|
|
102
|
-
this.value = this.from + (this.to - this.from) * this.ease(p);
|
|
103
|
-
}
|
|
104
|
-
isDone() {
|
|
105
|
-
return this.elapsed - this.delay >= this.duration;
|
|
106
|
-
}
|
|
107
|
-
}, _class2);
|
|
108
|
-
var SpringDriver = class {
|
|
109
|
-
|
|
110
|
-
constructor(from, to, cfg) {
|
|
111
|
-
this.spring = new SpringPhysics(from);
|
|
112
|
-
if (cfg.stiffness !== void 0) this.spring.stiffness = cfg.stiffness;
|
|
113
|
-
if (cfg.damping !== void 0) this.spring.damping = cfg.damping;
|
|
114
|
-
if (cfg.mass !== void 0) this.spring.mass = cfg.mass;
|
|
115
|
-
this.spring.target = to;
|
|
116
|
-
}
|
|
117
|
-
get value() {
|
|
118
|
-
return this.spring.value;
|
|
119
|
-
}
|
|
120
|
-
get target() {
|
|
121
|
-
return this.spring.target;
|
|
122
|
-
}
|
|
123
|
-
retarget(to) {
|
|
124
|
-
this.spring.target = to;
|
|
125
|
-
}
|
|
126
|
-
tick(dtMs) {
|
|
127
|
-
this.spring.update(dtMs / 1e3);
|
|
128
|
-
}
|
|
129
|
-
isDone() {
|
|
130
|
-
return this.spring.isAtRest();
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// src/tree/Entity.ts
|
|
8
|
+
var _animation = require('@vectojs/animation');
|
|
135
9
|
var ANIMATABLE_PROPS = /* @__PURE__ */ new Set([
|
|
136
10
|
"x",
|
|
137
11
|
"y",
|
|
@@ -140,7 +14,7 @@ var ANIMATABLE_PROPS = /* @__PURE__ */ new Set([
|
|
|
140
14
|
"rotation",
|
|
141
15
|
"opacity"
|
|
142
16
|
]);
|
|
143
|
-
var VectoJSEvent = (
|
|
17
|
+
var VectoJSEvent = (_class = class {
|
|
144
18
|
/** The event name. */
|
|
145
19
|
|
|
146
20
|
/** The entity the event originated on. */
|
|
@@ -152,9 +26,9 @@ var VectoJSEvent = (_class3 = class {
|
|
|
152
26
|
/** Whether the event bubbles past its target (capture always runs). */
|
|
153
27
|
|
|
154
28
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
constructor(type, target, nativeEvent, bubbles = true, scenePoint) {;
|
|
29
|
+
__init() {this.stopped = false}
|
|
30
|
+
__init2() {this.stoppedImmediate = false}
|
|
31
|
+
constructor(type, target, nativeEvent, bubbles = true, scenePoint) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
|
|
158
32
|
this.type = type;
|
|
159
33
|
this.target = target;
|
|
160
34
|
this.currentTarget = target;
|
|
@@ -252,11 +126,11 @@ var VectoJSEvent = (_class3 = class {
|
|
|
252
126
|
get key() {
|
|
253
127
|
return _optionalChain([this, 'access', _38 => _38.nativeEvent, 'optionalAccess', _39 => _39.key]);
|
|
254
128
|
}
|
|
255
|
-
},
|
|
256
|
-
var Entity = (
|
|
129
|
+
}, _class);
|
|
130
|
+
var Entity = (_class2 = class {
|
|
257
131
|
|
|
258
|
-
|
|
259
|
-
|
|
132
|
+
__init3() {this.children = []}
|
|
133
|
+
__init4() {this.parent = null}
|
|
260
134
|
/**
|
|
261
135
|
* Walk up the parent chain to find the scene this entity is currently attached to.
|
|
262
136
|
*/
|
|
@@ -264,18 +138,52 @@ var Entity = (_class4 = class {
|
|
|
264
138
|
if (this._scene) return this._scene;
|
|
265
139
|
return this.parent ? this.parent.scene : null;
|
|
266
140
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
141
|
+
__init5() {this._x = 0}
|
|
142
|
+
__init6() {this._y = 0}
|
|
143
|
+
__init7() {this._scaleX = 1}
|
|
144
|
+
__init8() {this._scaleY = 1}
|
|
145
|
+
__init9() {this._rotation = 0}
|
|
146
|
+
__init10() {this._opacity = 1}
|
|
273
147
|
// Fast-path flag: false for the overwhelming majority of entities (incl. the
|
|
274
148
|
// Danmaku hot loop), so a bare `entity.x = v` is one boolean check + field write.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
149
|
+
__init11() {this._hasTransitions = false}
|
|
150
|
+
__init12() {this._transitions = null}
|
|
151
|
+
// Lazily allocated: null until first use. A scene of many passive entities
|
|
152
|
+
// (particles, data points) never touches these, so paying an empty-Map/array
|
|
153
|
+
// allocation per entity in the constructor is pure waste at scale.
|
|
154
|
+
__init13() {this._drivers = null}
|
|
155
|
+
__init14() {this._mounted = false}
|
|
156
|
+
__init15() {this._destroyed = false}
|
|
157
|
+
// Frame this entity's active drivers were last advanced by Scene's batched
|
|
158
|
+
// WASM animation pass (see Scene._tickBatchedDrivers), or -1 if never. When
|
|
159
|
+
// it equals the current frame, tickDrivers() must skip its own tick loop —
|
|
160
|
+
// otherwise a driver already advanced by the batch pass would be ticked a
|
|
161
|
+
// second time by the normal per-entity update() walk in the same frame.
|
|
162
|
+
// Irrelevant (and harmless) for entities never touched by WASM batching.
|
|
163
|
+
__init16() {this._driversTickedFrame = -1}
|
|
164
|
+
// Cached cos/sin, recomputed only when rotation actually changes. renderNode
|
|
165
|
+
// and getWorldTransform() both read this instead of calling Math.cos/sin per
|
|
166
|
+
// entity per frame (V8's are ~2.5x slower than other engines).
|
|
167
|
+
__init17() {this._trig = { cos: 1, sin: 0 }}
|
|
168
|
+
__init18() {this._trigRotation = Number.NaN}
|
|
169
|
+
// NaN !== any rotation -> first read computes
|
|
170
|
+
// Per-frame world-matrix cache. Written by Scene during the render walk;
|
|
171
|
+
// getWorldTransform() returns it only while `_worldFrame === scene.currentFrame`
|
|
172
|
+
// and otherwise falls back to the full ancestor walk, so it can never return a
|
|
173
|
+
// stale/wrong transform — only sometimes miss the fast path.
|
|
174
|
+
__init19() {this._wa = 1}
|
|
175
|
+
__init20() {this._wb = 0}
|
|
176
|
+
__init21() {this._wc = 0}
|
|
177
|
+
__init22() {this._wd = 1}
|
|
178
|
+
__init23() {this._we = 0}
|
|
179
|
+
__init24() {this._wf = 0}
|
|
180
|
+
__init25() {this._worldFrame = -1}
|
|
181
|
+
// Slot in the Scene's resident WASM transform store, or -1 when this entity is
|
|
182
|
+
// not in that store (JS transform path, overlay/detached, or before the first
|
|
183
|
+
// structural rebuild). Assigned by Scene on a structural rebuild; the Scene
|
|
184
|
+
// validates it against its slot table before trusting it, so a stale value can
|
|
185
|
+
// only cost a JS-path fallback, never a wrong read.
|
|
186
|
+
__init26() {this._storeSlot = -1}
|
|
279
187
|
get x() {
|
|
280
188
|
return this._x;
|
|
281
189
|
}
|
|
@@ -318,8 +226,8 @@ var Entity = (_class4 = class {
|
|
|
318
226
|
if (this._hasTransitions) this._animateProp("opacity", v);
|
|
319
227
|
else this._opacity = v;
|
|
320
228
|
}
|
|
321
|
-
|
|
322
|
-
|
|
229
|
+
__init27() {this.isDOMPortal = false}
|
|
230
|
+
__init28() {this._interactive = false}
|
|
323
231
|
get interactive() {
|
|
324
232
|
return this._interactive;
|
|
325
233
|
}
|
|
@@ -333,10 +241,10 @@ var Entity = (_class4 = class {
|
|
|
333
241
|
}
|
|
334
242
|
}
|
|
335
243
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
244
|
+
__init29() {this.width = 0}
|
|
245
|
+
__init30() {this.height = 0}
|
|
246
|
+
__init31() {this.a11yOffsetX = 0}
|
|
247
|
+
__init32() {this.a11yOffsetY = 0}
|
|
340
248
|
/**
|
|
341
249
|
* Opt in to a viewport-filling accessibility/automation shadow node even when
|
|
342
250
|
* this entity has no intrinsic box (`width`/`height` of `0`). Use for
|
|
@@ -344,19 +252,21 @@ var Entity = (_class4 = class {
|
|
|
344
252
|
* that need global pointer events. The node is mounted behind all other shadow
|
|
345
253
|
* nodes, so on-top components stay clickable.
|
|
346
254
|
*/
|
|
347
|
-
|
|
255
|
+
__init33() {this.a11yFullViewport = false}
|
|
348
256
|
/**
|
|
349
257
|
* Clip this node's children to its local box (`[0,0]–[width,height]`) while
|
|
350
258
|
* rendering. Combined with translating a content child, this is how
|
|
351
259
|
* scroll/overflow containers (e.g. `ScrollView`) keep their content inside a
|
|
352
260
|
* fixed viewport. Off by default (children render unclipped). Canvas2D only.
|
|
353
261
|
*/
|
|
354
|
-
|
|
355
|
-
|
|
262
|
+
__init34() {this.clipChildren = false}
|
|
263
|
+
// Lazily allocated (see _drivers above). Most entities never register a
|
|
264
|
+
// listener or an imperative animate() tween.
|
|
265
|
+
__init35() {this.listeners = null}
|
|
356
266
|
/** Capture-phase listeners (fired root→target before bubble). */
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
constructor(id) {;
|
|
267
|
+
__init36() {this.captureListeners = null}
|
|
268
|
+
__init37() {this.animations = null}
|
|
269
|
+
constructor(id) {;_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);_class2.prototype.__init29.call(this);_class2.prototype.__init30.call(this);_class2.prototype.__init31.call(this);_class2.prototype.__init32.call(this);_class2.prototype.__init33.call(this);_class2.prototype.__init34.call(this);_class2.prototype.__init35.call(this);_class2.prototype.__init36.call(this);_class2.prototype.__init37.call(this);
|
|
360
270
|
this.id = id || `entity_${Math.random().toString(36).substring(2, 9)}`;
|
|
361
271
|
}
|
|
362
272
|
/**
|
|
@@ -390,6 +300,7 @@ var Entity = (_class4 = class {
|
|
|
390
300
|
const s = this.scene;
|
|
391
301
|
if (s) {
|
|
392
302
|
s.a11yNeedsReorder = true;
|
|
303
|
+
_optionalChain([s, 'access', _40 => _40.markStructureChanged, 'optionalCall', _41 => _41()]);
|
|
393
304
|
s.markDirty();
|
|
394
305
|
child._notifyMounted();
|
|
395
306
|
}
|
|
@@ -419,6 +330,7 @@ var Entity = (_class4 = class {
|
|
|
419
330
|
if (s) {
|
|
420
331
|
s.detachA11y(child);
|
|
421
332
|
s.a11yNeedsReorder = true;
|
|
333
|
+
_optionalChain([s, 'access', _42 => _42.markStructureChanged, 'optionalCall', _43 => _43()]);
|
|
422
334
|
s.markDirty();
|
|
423
335
|
}
|
|
424
336
|
}
|
|
@@ -467,13 +379,13 @@ var Entity = (_class4 = class {
|
|
|
467
379
|
* @example entity.animate({ x: 400, opacity: 0 }, 500);
|
|
468
380
|
*/
|
|
469
381
|
animate(targetProps, durationMs) {
|
|
470
|
-
this.animations.push({
|
|
382
|
+
(this.animations ??= []).push({
|
|
471
383
|
target: targetProps,
|
|
472
384
|
duration: durationMs,
|
|
473
385
|
startTime: -1,
|
|
474
386
|
startProps: {}
|
|
475
387
|
});
|
|
476
|
-
_optionalChain([this, 'access',
|
|
388
|
+
_optionalChain([this, 'access', _44 => _44.scene, 'optionalAccess', _45 => _45.markDirty, 'call', _46 => _46()]);
|
|
477
389
|
return this;
|
|
478
390
|
}
|
|
479
391
|
/** Write a driver-computed value to a backing field without re-triggering the setter. */
|
|
@@ -520,39 +432,40 @@ var Entity = (_class4 = class {
|
|
|
520
432
|
* that need to seed a starting state (e.g. the presence helper's enter `from`).
|
|
521
433
|
*/
|
|
522
434
|
setImmediate(prop, v) {
|
|
523
|
-
const existing = this._drivers.get(prop);
|
|
435
|
+
const existing = _optionalChain([this, 'access', _47 => _47._drivers, 'optionalAccess', _48 => _48.get, 'call', _49 => _49(prop)]);
|
|
524
436
|
if (existing) this._settleDriver(existing);
|
|
525
|
-
this._drivers.delete(prop);
|
|
437
|
+
_optionalChain([this, 'access', _50 => _50._drivers, 'optionalAccess', _51 => _51.delete, 'call', _52 => _52(prop)]);
|
|
526
438
|
this._applyAnimated(prop, v);
|
|
527
439
|
}
|
|
528
440
|
_settleDriver(driver) {
|
|
529
441
|
const active = driver;
|
|
530
442
|
const onDone = active.onDone;
|
|
531
443
|
active.onDone = void 0;
|
|
532
|
-
_optionalChain([onDone, 'optionalCall',
|
|
444
|
+
_optionalChain([onDone, 'optionalCall', _53 => _53()]);
|
|
533
445
|
}
|
|
534
446
|
_spawnDriver(prop, to, cfg) {
|
|
535
|
-
if (prop !== "opacity" && _optionalChain([this, 'access',
|
|
536
|
-
const existing2 = this._drivers.get(prop);
|
|
447
|
+
if (prop !== "opacity" && _optionalChain([this, 'access', _54 => _54.scene, 'optionalAccess', _55 => _55.prefersReducedMotion])) {
|
|
448
|
+
const existing2 = _optionalChain([this, 'access', _56 => _56._drivers, 'optionalAccess', _57 => _57.get, 'call', _58 => _58(prop)]);
|
|
537
449
|
if (existing2) this._settleDriver(existing2);
|
|
538
|
-
this._drivers.delete(prop);
|
|
450
|
+
_optionalChain([this, 'access', _59 => _59._drivers, 'optionalAccess', _60 => _60.delete, 'call', _61 => _61(prop)]);
|
|
539
451
|
this._applyAnimated(prop, to);
|
|
540
452
|
return;
|
|
541
453
|
}
|
|
542
|
-
const existing = this._drivers.get(prop);
|
|
454
|
+
const existing = _optionalChain([this, 'access', _62 => _62._drivers, 'optionalAccess', _63 => _63.get, 'call', _64 => _64(prop)]);
|
|
543
455
|
if (existing) {
|
|
544
456
|
this._settleDriver(existing);
|
|
545
457
|
existing.retarget(to);
|
|
546
458
|
return;
|
|
547
459
|
}
|
|
548
460
|
const from = this._currentOf(prop);
|
|
549
|
-
const driver = isTweenConfig(cfg) ? new TweenDriver(from, to, cfg) : new SpringDriver(from, to, cfg === "spring" ? {} : cfg);
|
|
550
|
-
this._drivers.set(prop, driver);
|
|
551
|
-
_optionalChain([this, 'access',
|
|
461
|
+
const driver = _animation.isTweenConfig.call(void 0, cfg) ? new (0, _animation.TweenDriver)(from, to, cfg) : new (0, _animation.SpringDriver)(from, to, cfg === "spring" ? {} : cfg);
|
|
462
|
+
(this._drivers ??= /* @__PURE__ */ new Map()).set(prop, driver);
|
|
463
|
+
_optionalChain([this, 'access', _65 => _65.scene, 'optionalAccess', _66 => _66.markDirty, 'call', _67 => _67()]);
|
|
464
|
+
_optionalChain([this, 'access', _68 => _68.scene, 'optionalAccess', _69 => _69._registerActiveDriverEntity, 'call', _70 => _70(this)]);
|
|
552
465
|
}
|
|
553
466
|
/** Assignment path when a declarative transition is configured for `prop`. */
|
|
554
467
|
_animateProp(prop, to) {
|
|
555
|
-
const cfg = _optionalChain([this, 'access',
|
|
468
|
+
const cfg = _optionalChain([this, 'access', _71 => _71._transitions, 'optionalAccess', _72 => _72.get, 'call', _73 => _73(prop)]);
|
|
556
469
|
if (!cfg) {
|
|
557
470
|
this._applyAnimated(prop, to);
|
|
558
471
|
return;
|
|
@@ -581,7 +494,7 @@ var Entity = (_class4 = class {
|
|
|
581
494
|
entries.map(
|
|
582
495
|
(e) => new Promise((resolve) => {
|
|
583
496
|
this._spawnDriver(e[0], e[1], cfg);
|
|
584
|
-
const d = this._drivers.get(e[0]);
|
|
497
|
+
const d = _optionalChain([this, 'access', _74 => _74._drivers, 'optionalAccess', _75 => _75.get, 'call', _76 => _76(e[0])]);
|
|
585
498
|
if (!d)
|
|
586
499
|
resolve();
|
|
587
500
|
else d.onDone = resolve;
|
|
@@ -591,7 +504,8 @@ var Entity = (_class4 = class {
|
|
|
591
504
|
}
|
|
592
505
|
/** Advance active property drivers one frame. Call from update(). */
|
|
593
506
|
tickDrivers(dt) {
|
|
594
|
-
if (this._drivers.size === 0) return;
|
|
507
|
+
if (!this._drivers || this._drivers.size === 0) return;
|
|
508
|
+
if (this.scene && this._driversTickedFrame === this.scene.currentFrame) return;
|
|
595
509
|
for (const [prop, driver] of this._drivers) {
|
|
596
510
|
driver.tick(dt);
|
|
597
511
|
if (driver.isDone()) {
|
|
@@ -602,7 +516,39 @@ var Entity = (_class4 = class {
|
|
|
602
516
|
this._applyAnimated(prop, driver.value);
|
|
603
517
|
}
|
|
604
518
|
}
|
|
605
|
-
_optionalChain([this, 'access',
|
|
519
|
+
_optionalChain([this, 'access', _77 => _77.scene, 'optionalAccess', _78 => _78.markDirty, 'call', _79 => _79()]);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Internal: this entity's active-driver map (read-only view), or `null` if
|
|
523
|
+
* it has none. Called only by Scene's batched WASM animation pass, never
|
|
524
|
+
* application code. Returns the Map directly (not a callback iteration) so
|
|
525
|
+
* a caller can `for...of` it with zero per-entity closure allocation — the
|
|
526
|
+
* integrated benchmark (benchmarks/anim-wasm-scene) found a fresh callback
|
|
527
|
+
* per entity per frame was a real cost, not a negligible one.
|
|
528
|
+
*/
|
|
529
|
+
_driverEntries() {
|
|
530
|
+
return this._drivers;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Internal: finalize one driver that was ALREADY advanced externally this
|
|
534
|
+
* frame (e.g. by Scene's batched WASM tick via `driver.syncExternal`, or a
|
|
535
|
+
* direct `driver.tick()` call for a driver the batch can't offload) —
|
|
536
|
+
* exactly mirrors tickDrivers()'s own per-driver completion logic, so a
|
|
537
|
+
* driver behaves identically regardless of which path ticked it. Called
|
|
538
|
+
* only by Scene, never application code.
|
|
539
|
+
*/
|
|
540
|
+
_applyDriverTick(prop, driver) {
|
|
541
|
+
if (driver.isDone()) {
|
|
542
|
+
this._applyAnimated(prop, driver.target);
|
|
543
|
+
this._settleDriver(driver);
|
|
544
|
+
_optionalChain([this, 'access', _80 => _80._drivers, 'optionalAccess', _81 => _81.delete, 'call', _82 => _82(prop)]);
|
|
545
|
+
} else {
|
|
546
|
+
this._applyAnimated(prop, driver.value);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
/** Internal: true if this entity currently has any active property driver. */
|
|
550
|
+
_hasActiveDrivers() {
|
|
551
|
+
return !!this._drivers && this._drivers.size > 0;
|
|
606
552
|
}
|
|
607
553
|
/**
|
|
608
554
|
* Advance the entity's internal state for one frame.
|
|
@@ -615,7 +561,7 @@ var Entity = (_class4 = class {
|
|
|
615
561
|
*/
|
|
616
562
|
update(dt, time) {
|
|
617
563
|
this.tickDrivers(dt);
|
|
618
|
-
if (this.animations.length > 0) {
|
|
564
|
+
if (this.animations && this.animations.length > 0) {
|
|
619
565
|
const anim = this.animations[0];
|
|
620
566
|
if (anim.startTime === -1) {
|
|
621
567
|
anim.startTime = time;
|
|
@@ -656,7 +602,7 @@ var Entity = (_class4 = class {
|
|
|
656
602
|
* @example entity.on('click', (e) => console.log('clicked', e));
|
|
657
603
|
*/
|
|
658
604
|
on(event, callback, options) {
|
|
659
|
-
const map = _optionalChain([options, 'optionalAccess',
|
|
605
|
+
const map = _optionalChain([options, 'optionalAccess', _83 => _83.capture]) ? this.captureListeners ??= /* @__PURE__ */ new Map() : this.listeners ??= /* @__PURE__ */ new Map();
|
|
660
606
|
if (!map.has(event)) {
|
|
661
607
|
map.set(event, []);
|
|
662
608
|
}
|
|
@@ -672,7 +618,7 @@ var Entity = (_class4 = class {
|
|
|
672
618
|
* @returns `this` for method chaining.
|
|
673
619
|
*/
|
|
674
620
|
off(event, callback, options) {
|
|
675
|
-
const handlers = (_optionalChain([options, 'optionalAccess',
|
|
621
|
+
const handlers = _optionalChain([(_optionalChain([options, 'optionalAccess', _84 => _84.capture]) ? this.captureListeners : this.listeners), 'optionalAccess', _85 => _85.get, 'call', _86 => _86(event)]);
|
|
676
622
|
if (handlers) {
|
|
677
623
|
const idx = handlers.indexOf(callback);
|
|
678
624
|
if (idx !== -1) handlers.splice(idx, 1);
|
|
@@ -680,17 +626,37 @@ var Entity = (_class4 = class {
|
|
|
680
626
|
return this;
|
|
681
627
|
}
|
|
682
628
|
/**
|
|
683
|
-
* Tear down this entity
|
|
684
|
-
*
|
|
629
|
+
* Tear down this entity **and its entire subtree**: recursively destroy every
|
|
630
|
+
* descendant (leaf-first), clear all animations, event listeners, and property
|
|
631
|
+
* drivers, then detach from the parent. Call before discarding an entity to
|
|
632
|
+
* prevent memory leaks.
|
|
633
|
+
*
|
|
634
|
+
* Recursing here is what frees a subtree's GPU buffers, layout workers, and DOM
|
|
635
|
+
* observers when an app does `entity.destroy()` or `scene.remove(subtree)` on a
|
|
636
|
+
* route change — without it, only the root's own state was released and every
|
|
637
|
+
* descendant (and its subclass resources) was stranded. Subclasses that own
|
|
638
|
+
* external resources override `destroy()`, free their resource, then call
|
|
639
|
+
* `super.destroy()`; because children don't depend on a parent's resource, the
|
|
640
|
+
* order (parent resource first, then descendants) is safe.
|
|
641
|
+
*
|
|
642
|
+
* Idempotent and re-entrancy safe: a second call is a no-op, and because each
|
|
643
|
+
* child is detached as it is destroyed, destroying a subtree never double-frees.
|
|
685
644
|
*/
|
|
686
645
|
destroy() {
|
|
687
|
-
this.
|
|
688
|
-
|
|
689
|
-
|
|
646
|
+
if (this._destroyed) return;
|
|
647
|
+
this._destroyed = true;
|
|
648
|
+
while (this.children.length > 0) {
|
|
649
|
+
this.children.at(-1).destroy();
|
|
690
650
|
}
|
|
691
|
-
this.
|
|
692
|
-
this.
|
|
693
|
-
|
|
651
|
+
this.animations = null;
|
|
652
|
+
if (this._drivers) {
|
|
653
|
+
for (const driver of this._drivers.values()) {
|
|
654
|
+
this._settleDriver(driver);
|
|
655
|
+
}
|
|
656
|
+
this._drivers.clear();
|
|
657
|
+
}
|
|
658
|
+
_optionalChain([this, 'access', _87 => _87.listeners, 'optionalAccess', _88 => _88.clear, 'call', _89 => _89()]);
|
|
659
|
+
_optionalChain([this, 'access', _90 => _90.captureListeners, 'optionalAccess', _91 => _91.clear, 'call', _92 => _92()]);
|
|
694
660
|
if (this.parent) {
|
|
695
661
|
this.parent.remove(this);
|
|
696
662
|
}
|
|
@@ -705,7 +671,7 @@ var Entity = (_class4 = class {
|
|
|
705
671
|
* @param payload - Arbitrary data forwarded to each listener.
|
|
706
672
|
*/
|
|
707
673
|
emit(event, payload) {
|
|
708
|
-
const handlers = this.listeners.get(event);
|
|
674
|
+
const handlers = _optionalChain([this, 'access', _93 => _93.listeners, 'optionalAccess', _94 => _94.get, 'call', _95 => _95(event)]);
|
|
709
675
|
if (handlers) {
|
|
710
676
|
handlers.forEach((h) => h(payload));
|
|
711
677
|
}
|
|
@@ -719,19 +685,19 @@ var Entity = (_class4 = class {
|
|
|
719
685
|
* with `requestAnimationFrame(() => document.getElementById(id)?.focus())`.
|
|
720
686
|
*/
|
|
721
687
|
focus() {
|
|
722
|
-
const el = _optionalChain([this, 'access',
|
|
688
|
+
const el = _optionalChain([this, 'access', _96 => _96.scene, 'optionalAccess', _97 => _97.getA11yElement, 'call', _98 => _98(this.id)]);
|
|
723
689
|
if (el) {
|
|
724
690
|
el.focus();
|
|
725
691
|
return;
|
|
726
692
|
}
|
|
727
693
|
requestAnimationFrame(() => {
|
|
728
|
-
const retry = _optionalChain([this, 'access',
|
|
694
|
+
const retry = _optionalChain([this, 'access', _99 => _99.scene, 'optionalAccess', _100 => _100.getA11yElement, 'call', _101 => _101(this.id)]);
|
|
729
695
|
if (retry) retry.focus();
|
|
730
696
|
});
|
|
731
697
|
}
|
|
732
698
|
/** Run one node's listeners for the event, honoring stopImmediatePropagation. */
|
|
733
699
|
fireListeners(node, map, event) {
|
|
734
|
-
const handlers = map.get(event.type);
|
|
700
|
+
const handlers = _optionalChain([map, 'optionalAccess', _102 => _102.get, 'call', _103 => _103(event.type)]);
|
|
735
701
|
if (!handlers) return;
|
|
736
702
|
event.currentTarget = node;
|
|
737
703
|
for (const h of handlers.slice()) {
|
|
@@ -770,10 +736,45 @@ var Entity = (_class4 = class {
|
|
|
770
736
|
getGlobalPosition() {
|
|
771
737
|
return this.localToWorld(0, 0);
|
|
772
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* Internal: read this entity's cached world matrix into `out` — the SAME
|
|
741
|
+
* cache {@link getWorldTransform} reads — without allocating a wrapper
|
|
742
|
+
* object. Returns `false` (leaving `out` untouched) when the cache isn't
|
|
743
|
+
* valid for `frame` (typically the caller's `scene.currentFrame`), exactly
|
|
744
|
+
* mirroring {@link getWorldTransform}'s own validity check; the caller
|
|
745
|
+
* falls back to {@link getWorldTransform}'s full walk in that case. Exists
|
|
746
|
+
* so a per-entity gather that runs every entity through this (e.g. G3's
|
|
747
|
+
* `gatherHitAABBs`) pays for six scalar reads instead of one object
|
|
748
|
+
* allocation per entity per call — the exact class of per-frame garbage
|
|
749
|
+
* the G2 integrated benchmark found dominating its own gather cost.
|
|
750
|
+
*/
|
|
751
|
+
_readWorldCache(frame, out) {
|
|
752
|
+
if (this._worldFrame < 0 || this._worldFrame !== frame) return false;
|
|
753
|
+
out.a = this._wa;
|
|
754
|
+
out.b = this._wb;
|
|
755
|
+
out.c = this._wc;
|
|
756
|
+
out.d = this._wd;
|
|
757
|
+
out.e = this._we;
|
|
758
|
+
out.f = this._wf;
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
773
761
|
/**
|
|
774
762
|
* Return the exact accumulated Canvas `T * S * R` transform for this entity.
|
|
775
763
|
*/
|
|
776
764
|
getWorldTransform() {
|
|
765
|
+
if (this._worldFrame >= 0) {
|
|
766
|
+
const s = this.scene;
|
|
767
|
+
if (s && this._worldFrame === s.currentFrame) {
|
|
768
|
+
return {
|
|
769
|
+
a: this._wa,
|
|
770
|
+
b: this._wb,
|
|
771
|
+
c: this._wc,
|
|
772
|
+
d: this._wd,
|
|
773
|
+
e: this._we,
|
|
774
|
+
f: this._wf
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
}
|
|
777
778
|
const path = [this];
|
|
778
779
|
let ancestor = this.parent;
|
|
779
780
|
while (ancestor) {
|
|
@@ -788,8 +789,9 @@ var Entity = (_class4 = class {
|
|
|
788
789
|
let f = 0;
|
|
789
790
|
for (let i = path.length - 1; i >= 0; i--) {
|
|
790
791
|
const node = path[i];
|
|
791
|
-
const
|
|
792
|
-
const
|
|
792
|
+
const trig = node._getTrig();
|
|
793
|
+
const cos = trig.cos;
|
|
794
|
+
const sin = trig.sin;
|
|
793
795
|
const la = node.scaleX * cos;
|
|
794
796
|
const lb = node.scaleY * sin;
|
|
795
797
|
const lc = -node.scaleX * sin;
|
|
@@ -811,6 +813,37 @@ var Entity = (_class4 = class {
|
|
|
811
813
|
}
|
|
812
814
|
return { a, b, c, d, e, f };
|
|
813
815
|
}
|
|
816
|
+
/**
|
|
817
|
+
* Return this entity's cached `{ cos, sin }` of its current rotation,
|
|
818
|
+
* recomputing only when `rotation` has actually changed since the last call.
|
|
819
|
+
* The same object identity is returned across calls with an unchanged
|
|
820
|
+
* rotation, so callers must treat it as read-only. Used by the render walk
|
|
821
|
+
* and {@link getWorldTransform} to avoid V8's comparatively slow Math.cos/sin
|
|
822
|
+
* (a software libm call, ~2.5x slower than other engines) per entity/frame.
|
|
823
|
+
*/
|
|
824
|
+
_getTrig() {
|
|
825
|
+
if (this._trigRotation !== this._rotation) {
|
|
826
|
+
this._trig.cos = Math.cos(this._rotation);
|
|
827
|
+
this._trig.sin = Math.sin(this._rotation);
|
|
828
|
+
this._trigRotation = this._rotation;
|
|
829
|
+
}
|
|
830
|
+
return this._trig;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Store the world matrix Scene computed for this entity during the render
|
|
834
|
+
* walk, stamped with the frame it belongs to. {@link getWorldTransform}
|
|
835
|
+
* returns it verbatim while `frame === scene.currentFrame`. Internal: called
|
|
836
|
+
* only by Scene's renderer, never by application code.
|
|
837
|
+
*/
|
|
838
|
+
_setWorldCache(a, b, c, d, e, f, frame) {
|
|
839
|
+
this._wa = a;
|
|
840
|
+
this._wb = b;
|
|
841
|
+
this._wc = c;
|
|
842
|
+
this._wd = d;
|
|
843
|
+
this._we = e;
|
|
844
|
+
this._wf = f;
|
|
845
|
+
this._worldFrame = frame;
|
|
846
|
+
}
|
|
814
847
|
/** Convert a point from this entity's local space to Scene/world space. */
|
|
815
848
|
localToWorld(localX, localY) {
|
|
816
849
|
const { a, b, c, d, e, f } = this.getWorldTransform();
|
|
@@ -840,7 +873,12 @@ var Entity = (_class4 = class {
|
|
|
840
873
|
* does not provide a render-specific box.
|
|
841
874
|
*/
|
|
842
875
|
getWorldBounds() {
|
|
843
|
-
const bounds = _nullishCoalesce(this.getBounds(), () => ( {
|
|
876
|
+
const bounds = _nullishCoalesce(this.getBounds(), () => ( {
|
|
877
|
+
x: 0,
|
|
878
|
+
y: 0,
|
|
879
|
+
width: this.width,
|
|
880
|
+
height: this.height
|
|
881
|
+
}));
|
|
844
882
|
const { a, b, c, d, e, f } = this.getWorldTransform();
|
|
845
883
|
let minX = Infinity;
|
|
846
884
|
let minY = Infinity;
|
|
@@ -981,134 +1019,13 @@ var Entity = (_class4 = class {
|
|
|
981
1019
|
* @returns `true` if at least one animation or property driver remains.
|
|
982
1020
|
*/
|
|
983
1021
|
hasPendingAnimations() {
|
|
984
|
-
return this.animations.length > 0 || this._drivers.size > 0;
|
|
985
|
-
}
|
|
986
|
-
}, _class4);
|
|
987
|
-
|
|
988
|
-
// src/text/Typography.ts
|
|
989
|
-
var typographyContext;
|
|
990
|
-
var baselineCache = /* @__PURE__ */ new Map();
|
|
991
|
-
function cssLineBoxBaseline(font, lineHeight) {
|
|
992
|
-
if (typeof document === "undefined") return lineHeight * 0.8;
|
|
993
|
-
const key = `${font}\0${lineHeight}`;
|
|
994
|
-
const cached = baselineCache.get(key);
|
|
995
|
-
if (cached !== void 0) return cached;
|
|
996
|
-
if (typographyContext === void 0) {
|
|
997
|
-
typographyContext = document.createElement("canvas").getContext("2d");
|
|
998
|
-
}
|
|
999
|
-
if (!typographyContext) return lineHeight * 0.8;
|
|
1000
|
-
typographyContext.font = font;
|
|
1001
|
-
const metrics = typographyContext.measureText("Mg");
|
|
1002
|
-
const ascent = metrics.fontBoundingBoxAscent || metrics.actualBoundingBoxAscent;
|
|
1003
|
-
const descent = metrics.fontBoundingBoxDescent || metrics.actualBoundingBoxDescent;
|
|
1004
|
-
if (!(ascent > 0) || !(descent >= 0)) return lineHeight * 0.8;
|
|
1005
|
-
const baseline = (lineHeight - ascent - descent) / 2 + ascent;
|
|
1006
|
-
baselineCache.set(key, baseline);
|
|
1007
|
-
return baseline;
|
|
1008
|
-
}
|
|
1009
|
-
function clearCssLineBoxMetrics() {
|
|
1010
|
-
baselineCache.clear();
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
// src/text/MSDFFont.ts
|
|
1014
|
-
function kernKey(a, b) {
|
|
1015
|
-
return a * 1114112 + b;
|
|
1016
|
-
}
|
|
1017
|
-
var MSDFFont = (_class5 = class _MSDFFont {
|
|
1018
|
-
static __initStatic() {this.idCounter = 0}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
__init33() {this.byCode = /* @__PURE__ */ new Map()}
|
|
1022
|
-
__init34() {this.kern = /* @__PURE__ */ new Map()}
|
|
1023
|
-
constructor(data) {;_class5.prototype.__init33.call(this);_class5.prototype.__init34.call(this);
|
|
1024
|
-
this.id = `font-${_MSDFFont.idCounter++}`;
|
|
1025
|
-
this.data = data;
|
|
1026
|
-
for (const g of data.glyphs) this.byCode.set(g.unicode, g);
|
|
1027
|
-
for (const k of _nullishCoalesce(data.kerning, () => ( []))) this.kern.set(kernKey(k.unicode1, k.unicode2), k.advance);
|
|
1028
|
-
}
|
|
1029
|
-
/** Parse the `msdf-atlas-gen` JSON (string or already-parsed object). */
|
|
1030
|
-
static parse(json) {
|
|
1031
|
-
return new _MSDFFont(typeof json === "string" ? JSON.parse(json) : json);
|
|
1032
|
-
}
|
|
1033
|
-
/** Get a glyph's definition by its unicode value in O(1) time. */
|
|
1034
|
-
getGlyph(unicode) {
|
|
1035
|
-
return this.byCode.get(unicode);
|
|
1036
|
-
}
|
|
1037
|
-
/** Distance field range in atlas pixels (for the shader's `u_distanceRange`). */
|
|
1038
|
-
get distanceRange() {
|
|
1039
|
-
return this.data.atlas.distanceRange;
|
|
1040
|
-
}
|
|
1041
|
-
get atlasWidth() {
|
|
1042
|
-
return this.data.atlas.width;
|
|
1043
|
-
}
|
|
1044
|
-
get atlasHeight() {
|
|
1045
|
-
return this.data.atlas.height;
|
|
1046
|
-
}
|
|
1047
|
-
/**
|
|
1048
|
-
* Lay `text` out at `fontSizePx`. Returns positioned quads (skipping glyphs the
|
|
1049
|
-
* font doesn't contain), the widest line's advance, and the total block height.
|
|
1050
|
-
* Honors `\n`, kerning pairs, and `letterSpacing`.
|
|
1051
|
-
*/
|
|
1052
|
-
layout(text, fontSizePx, opts = {}) {
|
|
1053
|
-
const { x = 0, y = 0, letterSpacing = 0 } = opts;
|
|
1054
|
-
const { width: aw, height: ah, yOrigin } = this.data.atlas;
|
|
1055
|
-
const { lineHeight, ascender } = this.data.metrics;
|
|
1056
|
-
const glyphs = [];
|
|
1057
|
-
let penX = x;
|
|
1058
|
-
let line = 0;
|
|
1059
|
-
let maxAdvance = 0;
|
|
1060
|
-
let prevCode = -1;
|
|
1061
|
-
const chars = Array.from(text);
|
|
1062
|
-
for (const char of chars) {
|
|
1063
|
-
if (char === "\n") {
|
|
1064
|
-
maxAdvance = Math.max(maxAdvance, penX - x);
|
|
1065
|
-
penX = x;
|
|
1066
|
-
line++;
|
|
1067
|
-
prevCode = -1;
|
|
1068
|
-
continue;
|
|
1069
|
-
}
|
|
1070
|
-
const code = char.codePointAt(0);
|
|
1071
|
-
const def = this.byCode.get(code);
|
|
1072
|
-
if (!def) {
|
|
1073
|
-
prevCode = -1;
|
|
1074
|
-
continue;
|
|
1075
|
-
}
|
|
1076
|
-
if (prevCode >= 0) {
|
|
1077
|
-
const k = this.kern.get(kernKey(prevCode, code));
|
|
1078
|
-
if (k) penX += k * fontSizePx;
|
|
1079
|
-
}
|
|
1080
|
-
const baseline = y + (ascender + line * lineHeight) * fontSizePx;
|
|
1081
|
-
const pb = def.planeBounds;
|
|
1082
|
-
const ab = def.atlasBounds;
|
|
1083
|
-
if (pb && ab) {
|
|
1084
|
-
const v0 = yOrigin === "bottom" ? 1 - ab.top / ah : ab.top / ah;
|
|
1085
|
-
const v1 = yOrigin === "bottom" ? 1 - ab.bottom / ah : ab.bottom / ah;
|
|
1086
|
-
glyphs.push({
|
|
1087
|
-
char,
|
|
1088
|
-
x: penX + pb.left * fontSizePx,
|
|
1089
|
-
y: baseline - pb.top * fontSizePx,
|
|
1090
|
-
w: (pb.right - pb.left) * fontSizePx,
|
|
1091
|
-
h: (pb.top - pb.bottom) * fontSizePx,
|
|
1092
|
-
u0: ab.left / aw,
|
|
1093
|
-
v0,
|
|
1094
|
-
u1: ab.right / aw,
|
|
1095
|
-
v1
|
|
1096
|
-
});
|
|
1097
|
-
}
|
|
1098
|
-
penX += def.advance * fontSizePx + letterSpacing;
|
|
1099
|
-
prevCode = code;
|
|
1100
|
-
}
|
|
1101
|
-
maxAdvance = Math.max(maxAdvance, penX - x);
|
|
1102
|
-
return {
|
|
1103
|
-
glyphs,
|
|
1104
|
-
width: maxAdvance,
|
|
1105
|
-
height: (line + 1) * lineHeight * fontSizePx
|
|
1106
|
-
};
|
|
1022
|
+
return (_nullishCoalesce(_optionalChain([this, 'access', _104 => _104.animations, 'optionalAccess', _105 => _105.length]), () => ( 0))) > 0 || (_nullishCoalesce(_optionalChain([this, 'access', _106 => _106._drivers, 'optionalAccess', _107 => _107.size]), () => ( 0))) > 0;
|
|
1107
1023
|
}
|
|
1108
|
-
},
|
|
1024
|
+
}, _class2);
|
|
1109
1025
|
|
|
1110
1026
|
// src/text/MSDFTextEntity.ts
|
|
1111
|
-
var
|
|
1027
|
+
var _layout = require('@vectojs/layout');
|
|
1028
|
+
var MSDFTextEntity = (_class3 = class extends Entity {
|
|
1112
1029
|
|
|
1113
1030
|
|
|
1114
1031
|
|
|
@@ -1118,13 +1035,21 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1118
1035
|
|
|
1119
1036
|
|
|
1120
1037
|
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1038
|
+
|
|
1039
|
+
// Optional hyphenator. Runs on the MAIN thread (a function can't be
|
|
1040
|
+
// structure-cloned into the layout worker), turning each word into parts
|
|
1041
|
+
// joined by soft hyphens (U+00AD); the worker then treats those as break
|
|
1042
|
+
// opportunities. `text` keeps the original string for a11y/content
|
|
1043
|
+
// projection; `layoutText` is the soft-hyphen-annotated string sent to layout.
|
|
1044
|
+
__init38() {this.hyphenator = null}
|
|
1045
|
+
__init39() {this.layoutText = ""}
|
|
1046
|
+
__init40() {this.text = ""}
|
|
1047
|
+
__init41() {this.lastRenderedSeqId = 0}
|
|
1048
|
+
__init42() {this.rgbColorCache = /* @__PURE__ */ new Map()}
|
|
1049
|
+
__init43() {this.fontStringCache = []}
|
|
1050
|
+
__init44() {this.layoutResult = null}
|
|
1126
1051
|
constructor(text, options) {
|
|
1127
|
-
super();
|
|
1052
|
+
super();_class3.prototype.__init38.call(this);_class3.prototype.__init39.call(this);_class3.prototype.__init40.call(this);_class3.prototype.__init41.call(this);_class3.prototype.__init42.call(this);_class3.prototype.__init43.call(this);_class3.prototype.__init44.call(this);;
|
|
1128
1053
|
this.font = options.font;
|
|
1129
1054
|
this.texture = options.texture;
|
|
1130
1055
|
this.fallbackFont = _nullishCoalesce(options.fallbackFont, () => ( "sans-serif"));
|
|
@@ -1134,6 +1059,7 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1134
1059
|
this.lineHeight = options.lineHeight;
|
|
1135
1060
|
this.maxWidth = _nullishCoalesce(options.maxWidth, () => ( 1e3));
|
|
1136
1061
|
this.maxHeight = _nullishCoalesce(options.maxHeight, () => ( 1e3));
|
|
1062
|
+
this.textAlign = _nullishCoalesce(options.textAlign, () => ( "left"));
|
|
1137
1063
|
this.setText(text);
|
|
1138
1064
|
}
|
|
1139
1065
|
/** Change the wrap boundary and re-run layout for the current text. */
|
|
@@ -1142,13 +1068,53 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1142
1068
|
this.maxWidth = maxWidth;
|
|
1143
1069
|
this.queueLayout();
|
|
1144
1070
|
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Set horizontal alignment (`'justify'` stretches wrapped lines flush to
|
|
1073
|
+
* {@link setMaxWidth}'s width; the last line stays ragged) and re-run layout.
|
|
1074
|
+
*/
|
|
1075
|
+
setTextAlign(align) {
|
|
1076
|
+
if (this.textAlign === align) return;
|
|
1077
|
+
this.textAlign = align;
|
|
1078
|
+
this.queueLayout();
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* Plug a hyphenator (word → parts). Break opportunities are inserted as soft
|
|
1082
|
+
* hyphens (U+00AD) into the string sent to layout, so a word that doesn't fit
|
|
1083
|
+
* can break with a visible hyphen. Soft hyphens already present in the text
|
|
1084
|
+
* work without one. Pass `null` to disable. The original text is preserved
|
|
1085
|
+
* for accessibility — only the layout string carries the hyphens.
|
|
1086
|
+
*/
|
|
1087
|
+
setHyphenator(fn) {
|
|
1088
|
+
this.hyphenator = fn;
|
|
1089
|
+
this.rebuildLayoutText();
|
|
1090
|
+
this.queueLayout();
|
|
1091
|
+
}
|
|
1145
1092
|
setText(text) {
|
|
1146
1093
|
if (this.text === text && this.layoutResult) return;
|
|
1147
1094
|
this.text = text;
|
|
1095
|
+
this.rebuildLayoutText();
|
|
1148
1096
|
this.queueLayout();
|
|
1149
1097
|
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Recompute {@link layoutText} from {@link text}: with a hyphenator active,
|
|
1100
|
+
* split each whitespace-delimited word and rejoin its parts with U+00AD so
|
|
1101
|
+
* the worker sees the break opportunities. Without one, the layout string is
|
|
1102
|
+
* the text unchanged.
|
|
1103
|
+
*/
|
|
1104
|
+
rebuildLayoutText() {
|
|
1105
|
+
if (!this.hyphenator) {
|
|
1106
|
+
this.layoutText = this.text;
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
const SHY = "\xAD";
|
|
1110
|
+
this.layoutText = this.text.replace(/[^\s]+/g, (word) => {
|
|
1111
|
+
if (word.length <= 3 || word.includes(SHY)) return word;
|
|
1112
|
+
const parts = this.hyphenator(word);
|
|
1113
|
+
return parts.length > 1 ? parts.join(SHY) : word;
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1150
1116
|
queueLayout() {
|
|
1151
|
-
|
|
1117
|
+
_layout.LayoutWorkerManager.getInstance().queueLayout(this.id, this.layoutText, {
|
|
1152
1118
|
fontId: this.font.id,
|
|
1153
1119
|
fontSize: this.fontSize,
|
|
1154
1120
|
maxWidth: this.maxWidth,
|
|
@@ -1156,11 +1122,12 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1156
1122
|
fontData: this.font.data,
|
|
1157
1123
|
letterSpacing: this.letterSpacing,
|
|
1158
1124
|
lineHeight: this.lineHeight,
|
|
1125
|
+
textAlign: this.textAlign,
|
|
1159
1126
|
callback: (res) => {
|
|
1160
1127
|
if (res.seqId < this.lastRenderedSeqId) return;
|
|
1161
1128
|
this.lastRenderedSeqId = res.seqId;
|
|
1162
1129
|
this.layoutResult = res;
|
|
1163
|
-
_optionalChain([this, 'access',
|
|
1130
|
+
_optionalChain([this, 'access', _108 => _108.scene, 'optionalAccess', _109 => _109.markDirty, 'call', _110 => _110()]);
|
|
1164
1131
|
}
|
|
1165
1132
|
});
|
|
1166
1133
|
}
|
|
@@ -1265,10 +1232,10 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1265
1232
|
}
|
|
1266
1233
|
}
|
|
1267
1234
|
destroy() {
|
|
1268
|
-
|
|
1235
|
+
_layout.LayoutWorkerManager.cancelLayoutForEntity(this.id);
|
|
1269
1236
|
super.destroy();
|
|
1270
1237
|
}
|
|
1271
|
-
},
|
|
1238
|
+
}, _class3);
|
|
1272
1239
|
|
|
1273
1240
|
// src/text/SVGEntity.ts
|
|
1274
1241
|
function isSvgWhitespace(ch) {
|
|
@@ -1301,20 +1268,20 @@ function readSvgAttribute(source, name) {
|
|
|
1301
1268
|
}
|
|
1302
1269
|
return null;
|
|
1303
1270
|
}
|
|
1304
|
-
var SVGEntity = (
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1271
|
+
var SVGEntity = (_class4 = class extends Entity {
|
|
1272
|
+
__init45() {this.svgSource = ""}
|
|
1273
|
+
__init46() {this.imageBitmap = null}
|
|
1274
|
+
__init47() {this.imageElement = null}
|
|
1275
|
+
__init48() {this.blobURL = null}
|
|
1276
|
+
__init49() {this.currentImg = null}
|
|
1277
|
+
__init50() {this.lodTimeout = null}
|
|
1278
|
+
__init51() {this.cachedDoc = null}
|
|
1279
|
+
__init52() {this.baseWidth = 100}
|
|
1280
|
+
__init53() {this.baseHeight = 100}
|
|
1281
|
+
__init54() {this.lastRasterizedScale = 1}
|
|
1282
|
+
__init55() {this.targetScale = 1}
|
|
1316
1283
|
constructor(svgSource, id) {
|
|
1317
|
-
super(id);
|
|
1284
|
+
super(id);_class4.prototype.__init45.call(this);_class4.prototype.__init46.call(this);_class4.prototype.__init47.call(this);_class4.prototype.__init48.call(this);_class4.prototype.__init49.call(this);_class4.prototype.__init50.call(this);_class4.prototype.__init51.call(this);_class4.prototype.__init52.call(this);_class4.prototype.__init53.call(this);_class4.prototype.__init54.call(this);_class4.prototype.__init55.call(this);;
|
|
1318
1285
|
this.setSVGSource(svgSource);
|
|
1319
1286
|
}
|
|
1320
1287
|
setSVGSource(svgSource) {
|
|
@@ -1503,219 +1470,11 @@ var SVGEntity = (_class7 = class extends Entity {
|
|
|
1503
1470
|
this.cachedDoc = null;
|
|
1504
1471
|
super.destroy();
|
|
1505
1472
|
}
|
|
1506
|
-
},
|
|
1507
|
-
|
|
1508
|
-
// src/text/PreparedContentGrid.ts
|
|
1509
|
-
var nextRevision = 1;
|
|
1510
|
-
var graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
1511
|
-
var MARK = /\p{Mark}/u;
|
|
1512
|
-
var EXTENDED_PICTOGRAPHIC = /\p{Extended_Pictographic}/u;
|
|
1513
|
-
var REGIONAL_INDICATOR = /\p{Regional_Indicator}/u;
|
|
1514
|
-
var BIDI_CONTROL = /\p{Bidi_Control}/u;
|
|
1515
|
-
var EAST_ASIAN_WIDE = /[ᄀ-ᅟ⌚-⌛⏩-⏬⏰⏳◽-◾⺀-〾ぁ-㏿㐀-䶿一-鿿ꀀ-가-힣豈-︰-﹏-⦆¢-₩]/u;
|
|
1516
|
-
function codePointAt(text, index) {
|
|
1517
|
-
const point = text.codePointAt(index);
|
|
1518
|
-
if (point === void 0) return { value: "", next: index };
|
|
1519
|
-
const value = String.fromCodePoint(point);
|
|
1520
|
-
return { value, next: index + value.length };
|
|
1521
|
-
}
|
|
1522
|
-
function fallbackGraphemes(text) {
|
|
1523
|
-
const parts = [];
|
|
1524
|
-
let index = 0;
|
|
1525
|
-
while (index < text.length) {
|
|
1526
|
-
const start = index;
|
|
1527
|
-
let current = codePointAt(text, index);
|
|
1528
|
-
let segment = current.value;
|
|
1529
|
-
index = current.next;
|
|
1530
|
-
let regionalCount = REGIONAL_INDICATOR.test(segment) ? 1 : 0;
|
|
1531
|
-
while (index < text.length) {
|
|
1532
|
-
current = codePointAt(text, index);
|
|
1533
|
-
const point = _nullishCoalesce(current.value.codePointAt(0), () => ( 0));
|
|
1534
|
-
const isVariation = point >= 65024 && point <= 65039;
|
|
1535
|
-
const isEmojiModifier = point >= 127995 && point <= 127999;
|
|
1536
|
-
const isKeycap = point === 8419;
|
|
1537
|
-
if (MARK.test(current.value) || isVariation || isEmojiModifier || isKeycap) {
|
|
1538
|
-
segment += current.value;
|
|
1539
|
-
index = current.next;
|
|
1540
|
-
continue;
|
|
1541
|
-
}
|
|
1542
|
-
if (REGIONAL_INDICATOR.test(current.value) && regionalCount === 1) {
|
|
1543
|
-
segment += current.value;
|
|
1544
|
-
index = current.next;
|
|
1545
|
-
regionalCount++;
|
|
1546
|
-
continue;
|
|
1547
|
-
}
|
|
1548
|
-
if (point === 8205) {
|
|
1549
|
-
segment += current.value;
|
|
1550
|
-
index = current.next;
|
|
1551
|
-
if (index < text.length) {
|
|
1552
|
-
current = codePointAt(text, index);
|
|
1553
|
-
segment += current.value;
|
|
1554
|
-
index = current.next;
|
|
1555
|
-
}
|
|
1556
|
-
continue;
|
|
1557
|
-
}
|
|
1558
|
-
break;
|
|
1559
|
-
}
|
|
1560
|
-
parts.push({ segment, index: start });
|
|
1561
|
-
}
|
|
1562
|
-
return parts;
|
|
1563
|
-
}
|
|
1564
|
-
function graphemes(text) {
|
|
1565
|
-
if (!graphemeSegmenter) return fallbackGraphemes(text);
|
|
1566
|
-
return Array.from(graphemeSegmenter.segment(text), (part) => ({
|
|
1567
|
-
segment: part.segment,
|
|
1568
|
-
index: part.index
|
|
1569
|
-
}));
|
|
1570
|
-
}
|
|
1571
|
-
function lowerBound(values, target) {
|
|
1572
|
-
let low = 0;
|
|
1573
|
-
let high = values.length;
|
|
1574
|
-
while (low < high) {
|
|
1575
|
-
const middle = low + high >>> 1;
|
|
1576
|
-
if (values[middle] < target) low = middle + 1;
|
|
1577
|
-
else high = middle;
|
|
1578
|
-
}
|
|
1579
|
-
return low;
|
|
1580
|
-
}
|
|
1581
|
-
function isWideCluster(cluster) {
|
|
1582
|
-
if (EXTENDED_PICTOGRAPHIC.test(cluster) || REGIONAL_INDICATOR.test(cluster)) return true;
|
|
1583
|
-
if (cluster.includes("\u20E3")) return true;
|
|
1584
|
-
if (EAST_ASIAN_WIDE.test(cluster)) return true;
|
|
1585
|
-
const point = _nullishCoalesce(cluster.codePointAt(0), () => ( 0));
|
|
1586
|
-
return point >= 131072 && point <= 262141;
|
|
1587
|
-
}
|
|
1588
|
-
function sourceLines(source) {
|
|
1589
|
-
const lines = [];
|
|
1590
|
-
let start = 0;
|
|
1591
|
-
while (true) {
|
|
1592
|
-
let end = start;
|
|
1593
|
-
while (end < source.length && source[end] !== "\r" && source[end] !== "\n") end++;
|
|
1594
|
-
if (end === source.length) {
|
|
1595
|
-
lines.push({
|
|
1596
|
-
sourceStart: start,
|
|
1597
|
-
sourceEnd: end,
|
|
1598
|
-
nextSourceStart: end,
|
|
1599
|
-
text: source.slice(start)
|
|
1600
|
-
});
|
|
1601
|
-
break;
|
|
1602
|
-
}
|
|
1603
|
-
const next = source[end] === "\r" && source[end + 1] === "\n" ? end + 2 : end + 1;
|
|
1604
|
-
lines.push({
|
|
1605
|
-
sourceStart: start,
|
|
1606
|
-
sourceEnd: end,
|
|
1607
|
-
nextSourceStart: next,
|
|
1608
|
-
text: source.slice(start, end)
|
|
1609
|
-
});
|
|
1610
|
-
start = next;
|
|
1611
|
-
if (start === source.length) {
|
|
1612
|
-
lines.push({ sourceStart: start, sourceEnd: start, nextSourceStart: start, text: "" });
|
|
1613
|
-
break;
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
return lines;
|
|
1617
|
-
}
|
|
1618
|
-
function assertPositiveFinite(value, name) {
|
|
1619
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
1620
|
-
throw new RangeError(`${name} must be a positive finite number`);
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
function prepareContentGrid(source, options) {
|
|
1624
|
-
assertPositiveFinite(options.cellWidth, "cellWidth");
|
|
1625
|
-
assertPositiveFinite(options.lineHeight, "lineHeight");
|
|
1626
|
-
if (!Number.isFinite(options.baseline)) throw new RangeError("baseline must be finite");
|
|
1627
|
-
const tabSize = _nullishCoalesce(options.tabSize, () => ( 4));
|
|
1628
|
-
if (!Number.isInteger(tabSize) || tabSize <= 0) {
|
|
1629
|
-
throw new RangeError("tabSize must be a positive integer");
|
|
1630
|
-
}
|
|
1631
|
-
const rawLines = sourceLines(source);
|
|
1632
|
-
const lines = [];
|
|
1633
|
-
for (let lineIndex = 0; lineIndex < rawLines.length; lineIndex++) {
|
|
1634
|
-
const sourceLine = rawLines[lineIndex];
|
|
1635
|
-
const rawLine = sourceLine.text;
|
|
1636
|
-
const { sourceStart: lineStart, sourceEnd, nextSourceStart } = sourceLine;
|
|
1637
|
-
const rawCaretBoundaries = [
|
|
1638
|
-
0,
|
|
1639
|
-
...graphemes(rawLine).map((grapheme) => grapheme.index + grapheme.segment.length)
|
|
1640
|
-
];
|
|
1641
|
-
const shaped = _chunk4AR425ARjs.ArabicShaper.shapeArabic(rawLine);
|
|
1642
|
-
const shapedParts = graphemes(shaped.shapedText);
|
|
1643
|
-
const levels = _chunk4AR425ARjs.BidiResolver.resolveLevels(shaped.shapedText);
|
|
1644
|
-
const cells = [];
|
|
1645
|
-
let column = 0;
|
|
1646
|
-
for (let index = 0; index < shapedParts.length; index++) {
|
|
1647
|
-
const part = shapedParts[index];
|
|
1648
|
-
const sourceOffset = _nullishCoalesce(shaped.indexMap[part.index], () => ( part.index));
|
|
1649
|
-
const nextPart = shapedParts[index + 1];
|
|
1650
|
-
const sourceOffsetEnd = nextPart ? _nullishCoalesce(shaped.indexMap[nextPart.index], () => ( nextPart.index)) : rawLine.length;
|
|
1651
|
-
const raw = rawLine.slice(sourceOffset, sourceOffsetEnd);
|
|
1652
|
-
const sourceCaretOffsets = [0];
|
|
1653
|
-
for (let caretIndex = lowerBound(rawCaretBoundaries, sourceOffset + 1); caretIndex < rawCaretBoundaries.length && rawCaretBoundaries[caretIndex] < sourceOffsetEnd; caretIndex++) {
|
|
1654
|
-
sourceCaretOffsets.push(rawCaretBoundaries[caretIndex] - sourceOffset);
|
|
1655
|
-
}
|
|
1656
|
-
if (sourceCaretOffsets.at(-1) !== sourceOffsetEnd - sourceOffset) {
|
|
1657
|
-
sourceCaretOffsets.push(sourceOffsetEnd - sourceOffset);
|
|
1658
|
-
}
|
|
1659
|
-
let columns;
|
|
1660
|
-
if (BIDI_CONTROL.test(raw)) columns = 0;
|
|
1661
|
-
else if (raw === " ") columns = tabSize - column % tabSize;
|
|
1662
|
-
else columns = isWideCluster(raw) ? 2 : 1;
|
|
1663
|
-
const advance = columns * options.cellWidth;
|
|
1664
|
-
cells.push({
|
|
1665
|
-
sourceStart: lineStart + sourceOffset,
|
|
1666
|
-
sourceEnd: lineStart + sourceOffsetEnd,
|
|
1667
|
-
sourceCaretOffsets: Object.freeze(sourceCaretOffsets),
|
|
1668
|
-
glyph: part.segment,
|
|
1669
|
-
x: 0,
|
|
1670
|
-
advance,
|
|
1671
|
-
level: _nullishCoalesce(levels[part.index], () => ( 0)),
|
|
1672
|
-
char: part.segment
|
|
1673
|
-
});
|
|
1674
|
-
column += columns;
|
|
1675
|
-
}
|
|
1676
|
-
const visualCells = [...cells];
|
|
1677
|
-
_chunk4AR425ARjs.BidiResolver.reorderVisual(visualCells, _chunk4AR425ARjs.BidiResolver.getBaseLevel(shaped.shapedText));
|
|
1678
|
-
let visualX = 0;
|
|
1679
|
-
for (const cell of visualCells) {
|
|
1680
|
-
cell.x = visualX;
|
|
1681
|
-
visualX += cell.advance;
|
|
1682
|
-
}
|
|
1683
|
-
const frozenCells = cells.map(({ char: _char, ...cell }) => Object.freeze(cell));
|
|
1684
|
-
lines.push(
|
|
1685
|
-
Object.freeze({
|
|
1686
|
-
sourceStart: lineStart,
|
|
1687
|
-
sourceEnd,
|
|
1688
|
-
nextSourceStart,
|
|
1689
|
-
width: visualX,
|
|
1690
|
-
cells: Object.freeze(frozenCells)
|
|
1691
|
-
})
|
|
1692
|
-
);
|
|
1693
|
-
}
|
|
1694
|
-
return Object.freeze({
|
|
1695
|
-
kind: "content-grid",
|
|
1696
|
-
revision: nextRevision++,
|
|
1697
|
-
source,
|
|
1698
|
-
font: options.font,
|
|
1699
|
-
cellWidth: options.cellWidth,
|
|
1700
|
-
lineHeight: options.lineHeight,
|
|
1701
|
-
baseline: options.baseline,
|
|
1702
|
-
tabSize,
|
|
1703
|
-
lines: Object.freeze(lines)
|
|
1704
|
-
});
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1473
|
+
}, _class4);
|
|
1715
1474
|
|
|
1716
1475
|
|
|
1717
1476
|
|
|
1718
1477
|
|
|
1719
1478
|
|
|
1720
1479
|
|
|
1721
|
-
exports.
|
|
1480
|
+
exports.VectoJSEvent = VectoJSEvent; exports.Entity = Entity; exports.MSDFTextEntity = MSDFTextEntity; exports.SVGEntity = SVGEntity;
|