@vectojs/core 1.21.0 → 1.22.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-GKSCJ6AF.js → chunk-LHONR3GO.js} +150 -44
- package/dist/{chunk-RTENOAYT.mjs → chunk-UPULSLKA.mjs} +106 -0
- package/dist/index.js +82 -61
- package/dist/index.mjs +22 -1
- package/dist/renderer/CanvasRenderer.d.ts +18 -1
- package/dist/renderer/IRenderer.d.ts +63 -0
- package/dist/renderer/SVGRenderer.d.ts +2 -0
- package/dist/renderer/WebGLPointRenderer.d.ts +33 -0
- package/dist/renderer.js +2 -2
- package/dist/renderer.mjs +1 -1
- package/dist/tree/Entity.d.ts +6 -4
- package/dist/tree/Scene.d.ts +18 -0
- package/package.json +2 -2
|
@@ -1,6 +1,21 @@
|
|
|
1
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; var _class5;const __vecto_cjs_url=require("url").pathToFileURL(__filename).href;
|
|
2
2
|
|
|
3
3
|
// src/renderer/CanvasRenderer.ts
|
|
4
|
+
function emptyDrawCounters() {
|
|
5
|
+
return {
|
|
6
|
+
fills: 0,
|
|
7
|
+
strokes: 0,
|
|
8
|
+
texts: 0,
|
|
9
|
+
images: 0,
|
|
10
|
+
circles: 0,
|
|
11
|
+
flushes: 0,
|
|
12
|
+
saves: 0,
|
|
13
|
+
restores: 0,
|
|
14
|
+
clips: 0,
|
|
15
|
+
stateSwitches: 0,
|
|
16
|
+
overdrawRatio: 0
|
|
17
|
+
};
|
|
18
|
+
}
|
|
4
19
|
var TWO_PI = Math.PI * 2;
|
|
5
20
|
function getDevicePixelRatio() {
|
|
6
21
|
return typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
@@ -41,6 +56,17 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
41
56
|
__init6() {this.batchCount = 0}
|
|
42
57
|
__init7() {this._cachedFont = ""}
|
|
43
58
|
__init8() {this._cachedFill = ""}
|
|
59
|
+
/** Backend discriminator; see {@link IRenderer.kind}. */
|
|
60
|
+
__init9() {this.kind = "canvas2d"}
|
|
61
|
+
/**
|
|
62
|
+
* Draw counters, allocated only once counting is enabled.
|
|
63
|
+
*
|
|
64
|
+
* Null when off, so the guard on every op is a single null test and an inactive
|
|
65
|
+
* renderer carries no counter object at all.
|
|
66
|
+
*/
|
|
67
|
+
__init10() {this.counters = null}
|
|
68
|
+
/** Accumulated primitive area, kept separately so the ratio is derived on read. */
|
|
69
|
+
__init11() {this.drawnArea = 0}
|
|
44
70
|
/**
|
|
45
71
|
* @param canvas - The target canvas. Its backing store is resized to the
|
|
46
72
|
* logical size × devicePixelRatio.
|
|
@@ -50,7 +76,7 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
50
76
|
* set) so the canvas's own dimensions aren't clobbered by the window's.
|
|
51
77
|
* @param maxDPR - See {@link maxDPR}.
|
|
52
78
|
*/
|
|
53
|
-
constructor(canvas, size, maxDPR) {;_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);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);
|
|
79
|
+
constructor(canvas, size, maxDPR) {;_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);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);
|
|
54
80
|
this.maxDPR = maxDPR;
|
|
55
81
|
const dpr = this.effectiveDPR();
|
|
56
82
|
this.width = _nullishCoalesce(_optionalChain([size, 'optionalAccess', _ => _.width]), () => ( (typeof window !== "undefined" ? window.innerWidth : canvas.width || 0)));
|
|
@@ -137,19 +163,47 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
137
163
|
return this.contextLost;
|
|
138
164
|
}
|
|
139
165
|
/** @inheritdoc */
|
|
166
|
+
/** @inheritdoc */
|
|
167
|
+
setDrawCounters(enabled) {
|
|
168
|
+
if (!enabled) {
|
|
169
|
+
this.counters = null;
|
|
170
|
+
this.drawnArea = 0;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (!this.counters) this.counters = emptyDrawCounters();
|
|
174
|
+
}
|
|
175
|
+
/** @inheritdoc */
|
|
176
|
+
getDrawCounters() {
|
|
177
|
+
if (!this.counters) return null;
|
|
178
|
+
const area = this.width * this.height;
|
|
179
|
+
return {
|
|
180
|
+
...this.counters,
|
|
181
|
+
// Derived on read rather than maintained: the ratio is only meaningful
|
|
182
|
+
// against the current surface size, which can change under resize.
|
|
183
|
+
overdrawRatio: area > 0 ? Math.round(this.drawnArea / area * 100) / 100 : 0
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/** @inheritdoc */
|
|
187
|
+
clearDrawCounters() {
|
|
188
|
+
if (this.counters) this.counters = emptyDrawCounters();
|
|
189
|
+
this.drawnArea = 0;
|
|
190
|
+
}
|
|
140
191
|
clear() {
|
|
141
192
|
if (this.contextLost) return;
|
|
142
193
|
this.flush();
|
|
194
|
+
if (this.counters) this.drawnArea = 0;
|
|
143
195
|
this.ctx.clearRect(0, 0, this.width, this.height);
|
|
144
196
|
}
|
|
145
197
|
/** @inheritdoc */
|
|
146
198
|
save() {
|
|
147
199
|
this.flush();
|
|
200
|
+
if (this.counters) this.counters.saves++;
|
|
148
201
|
this.ctx.save();
|
|
149
202
|
}
|
|
150
203
|
/** @inheritdoc */
|
|
151
204
|
restore() {
|
|
152
205
|
this.flush();
|
|
206
|
+
if (this.counters) this.counters.restores++;
|
|
153
207
|
this.ctx.restore();
|
|
154
208
|
this._cachedFont = "";
|
|
155
209
|
this._cachedFill = "";
|
|
@@ -173,6 +227,7 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
173
227
|
/** @inheritdoc */
|
|
174
228
|
clip(x, y, width, height) {
|
|
175
229
|
this.flush();
|
|
230
|
+
if (this.counters) this.counters.clips++;
|
|
176
231
|
this.ctx.beginPath();
|
|
177
232
|
this.ctx.rect(x, y, width, height);
|
|
178
233
|
this.ctx.clip();
|
|
@@ -209,11 +264,19 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
209
264
|
/** @inheritdoc */
|
|
210
265
|
drawImage(source, dx, dy, dw, dh) {
|
|
211
266
|
this.flush();
|
|
267
|
+
if (this.counters) {
|
|
268
|
+
this.counters.images++;
|
|
269
|
+
this.drawnArea += Math.abs(dw * dh);
|
|
270
|
+
}
|
|
212
271
|
this.ctx.drawImage(source, dx, dy, dw, dh);
|
|
213
272
|
}
|
|
214
273
|
/** @inheritdoc */
|
|
215
274
|
drawImageRect(source, sx, sy, sw, sh, dx, dy, dw, dh) {
|
|
216
275
|
this.flush();
|
|
276
|
+
if (this.counters) {
|
|
277
|
+
this.counters.images++;
|
|
278
|
+
this.drawnArea += Math.abs(dw * dh);
|
|
279
|
+
}
|
|
217
280
|
this.ctx.drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
218
281
|
}
|
|
219
282
|
/** @inheritdoc */
|
|
@@ -227,6 +290,10 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
227
290
|
this.batchColor = color;
|
|
228
291
|
this.batchAlpha = alpha;
|
|
229
292
|
}
|
|
293
|
+
if (this.counters) {
|
|
294
|
+
this.counters.circles++;
|
|
295
|
+
this.drawnArea += Math.PI * radius * radius;
|
|
296
|
+
}
|
|
230
297
|
this.ctx.moveTo(cx + radius, cy);
|
|
231
298
|
this.ctx.arc(cx, cy, radius, 0, TWO_PI);
|
|
232
299
|
this.batchCount++;
|
|
@@ -235,6 +302,7 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
235
302
|
/** @inheritdoc */
|
|
236
303
|
flush() {
|
|
237
304
|
if (!this.batchActive) return;
|
|
305
|
+
if (this.counters) this.counters.flushes++;
|
|
238
306
|
this.ctx.globalAlpha = this.batchAlpha;
|
|
239
307
|
this.ctx.fillStyle = this.batchColor;
|
|
240
308
|
this.ctx.fill();
|
|
@@ -245,7 +313,9 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
245
313
|
/** @inheritdoc */
|
|
246
314
|
fill(color) {
|
|
247
315
|
this.flush();
|
|
316
|
+
if (this.counters) this.counters.fills++;
|
|
248
317
|
if (this._cachedFill !== color) {
|
|
318
|
+
if (this.counters) this.counters.stateSwitches++;
|
|
249
319
|
this.ctx.fillStyle = color;
|
|
250
320
|
this._cachedFill = color;
|
|
251
321
|
}
|
|
@@ -254,6 +324,7 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
254
324
|
/** @inheritdoc */
|
|
255
325
|
stroke(color, lineWidth = 1) {
|
|
256
326
|
this.flush();
|
|
327
|
+
if (this.counters) this.counters.strokes++;
|
|
257
328
|
this.ctx.strokeStyle = color;
|
|
258
329
|
this.ctx.lineWidth = lineWidth;
|
|
259
330
|
this.ctx.lineCap = "round";
|
|
@@ -263,11 +334,14 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
263
334
|
/** @inheritdoc */
|
|
264
335
|
fillText(text, x, y, font, color) {
|
|
265
336
|
this.flush();
|
|
337
|
+
if (this.counters) this.counters.texts++;
|
|
266
338
|
if (this._cachedFont !== font) {
|
|
339
|
+
if (this.counters) this.counters.stateSwitches++;
|
|
267
340
|
this.ctx.font = font;
|
|
268
341
|
this._cachedFont = font;
|
|
269
342
|
}
|
|
270
343
|
if (this._cachedFill !== color) {
|
|
344
|
+
if (this.counters) this.counters.stateSwitches++;
|
|
271
345
|
this.ctx.fillStyle = color;
|
|
272
346
|
this._cachedFill = color;
|
|
273
347
|
}
|
|
@@ -378,41 +452,43 @@ function fontFamilyFromShorthand(font, sizeToken) {
|
|
|
378
452
|
return family || "sans-serif";
|
|
379
453
|
}
|
|
380
454
|
var SVGRenderer = (_class2 = class {
|
|
455
|
+
/** Backend discriminator; see {@link IRenderer.kind}. */
|
|
456
|
+
__init12() {this.kind = "svg"}
|
|
381
457
|
|
|
382
458
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
459
|
+
__init13() {this.buffer = []}
|
|
460
|
+
__init14() {this.defsBuffer = []}
|
|
461
|
+
__init15() {this.currentPath = []}
|
|
386
462
|
// Inline matrix states (3x3 representation)
|
|
387
463
|
// [a, b, c, d, e, f] corresponding to:
|
|
388
464
|
// | a c e |
|
|
389
465
|
// | b d f |
|
|
390
466
|
// | 0 0 1 |
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
467
|
+
__init16() {this.mStack = []}
|
|
468
|
+
__init17() {this.ma = 1}
|
|
469
|
+
__init18() {this.mb = 0}
|
|
470
|
+
__init19() {this.mc = 0}
|
|
471
|
+
__init20() {this.md = 1}
|
|
472
|
+
__init21() {this.me = 0}
|
|
473
|
+
__init22() {this.mf = 0}
|
|
398
474
|
// Alpha stack
|
|
399
|
-
|
|
400
|
-
|
|
475
|
+
__init23() {this.alphaStack = []}
|
|
476
|
+
__init24() {this.globalAlpha = 1}
|
|
401
477
|
// Clipping stack
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
478
|
+
__init25() {this.clipDepthStack = []}
|
|
479
|
+
__init26() {this.clipDepth = 0}
|
|
480
|
+
__init27() {this.clipCounter = 0}
|
|
405
481
|
// uniquely identifies clipPaths
|
|
406
482
|
// Batch circles states (local coordinates)
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
483
|
+
__init28() {this.batchCircles = []}
|
|
484
|
+
__init29() {this.batchMatrix = [1, 0, 0, 1, 0, 0]}
|
|
485
|
+
__init30() {this.batchColor = ""}
|
|
486
|
+
__init31() {this.batchAlpha = 1}
|
|
487
|
+
__init32() {this.batchActive = false}
|
|
412
488
|
// Cache for generated gradient defs
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
constructor(width, height) {;_class2.prototype.
|
|
489
|
+
__init33() {this.gradientCounter = 0}
|
|
490
|
+
__init34() {this.gradientCache = /* @__PURE__ */ new Map()}
|
|
491
|
+
constructor(width, height) {;_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);
|
|
416
492
|
this.width = width;
|
|
417
493
|
this.height = height;
|
|
418
494
|
}
|
|
@@ -1230,6 +1306,12 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1230
1306
|
let spriteCount = 0;
|
|
1231
1307
|
let glyphData = new Float32Array(FLOATS_PER_SPRITE_VERT * VERTS_PER_QUAD * 1024);
|
|
1232
1308
|
let glyphCount = 0;
|
|
1309
|
+
let frameDrawCalls = 0;
|
|
1310
|
+
let lastFrameDrawCalls = 0;
|
|
1311
|
+
let totalDrawCalls = 0;
|
|
1312
|
+
let atlasSwitches = 0;
|
|
1313
|
+
let circleQuadFallbacks = 0;
|
|
1314
|
+
let circlePoints = 0;
|
|
1233
1315
|
let circleQuadData = new Float32Array(FLOATS_PER_SPRITE_VERT * VERTS_PER_QUAD * 64);
|
|
1234
1316
|
let circleQuadCount = 0;
|
|
1235
1317
|
let logicalW = 0;
|
|
@@ -1252,6 +1334,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1252
1334
|
gl.uniform1f(gURange, distanceRange);
|
|
1253
1335
|
ensureQuadIndices(glyphCount);
|
|
1254
1336
|
gl.drawElements(gl.TRIANGLES, glyphCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1337
|
+
frameDrawCalls++;
|
|
1255
1338
|
gl.bindVertexArray(null);
|
|
1256
1339
|
glyphCount = 0;
|
|
1257
1340
|
};
|
|
@@ -1268,7 +1351,23 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1268
1351
|
canvas.style.height = `${height}px`;
|
|
1269
1352
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
1270
1353
|
},
|
|
1354
|
+
stats() {
|
|
1355
|
+
return {
|
|
1356
|
+
drawCalls: lastFrameDrawCalls,
|
|
1357
|
+
totalDrawCalls,
|
|
1358
|
+
atlasSwitches,
|
|
1359
|
+
// Fixed at creation: five programs compiled once, never per frame, so
|
|
1360
|
+
// these are capability facts rather than counters.
|
|
1361
|
+
programs: 5,
|
|
1362
|
+
textures: (texture ? 1 : 0) + (msdfTexture ? 1 : 0),
|
|
1363
|
+
circleQuadFallbacks,
|
|
1364
|
+
circlePoints
|
|
1365
|
+
};
|
|
1366
|
+
},
|
|
1271
1367
|
begin() {
|
|
1368
|
+
lastFrameDrawCalls = frameDrawCalls;
|
|
1369
|
+
totalDrawCalls += frameDrawCalls;
|
|
1370
|
+
frameDrawCalls = 0;
|
|
1272
1371
|
pointCount = 0;
|
|
1273
1372
|
rectCount = 0;
|
|
1274
1373
|
spriteCount = 0;
|
|
@@ -1321,6 +1420,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1321
1420
|
distanceRange = range;
|
|
1322
1421
|
return;
|
|
1323
1422
|
}
|
|
1423
|
+
atlasSwitches++;
|
|
1324
1424
|
drawGlyphs();
|
|
1325
1425
|
distanceRange = range;
|
|
1326
1426
|
if (!msdfTexture) {
|
|
@@ -1363,6 +1463,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1363
1463
|
addCircle(x, y, radius, color, alpha = 1) {
|
|
1364
1464
|
const needsQuad = logicalW > 0 && (x < radius || y < radius || x > logicalW - radius || y > logicalH - radius) || radius * 2 * dpr > maxPointSize;
|
|
1365
1465
|
if (needsQuad) {
|
|
1466
|
+
circleQuadFallbacks++;
|
|
1366
1467
|
const stride = FLOATS_PER_SPRITE_VERT * VERTS_PER_QUAD;
|
|
1367
1468
|
circleQuadData = grow(circleQuadData, (circleQuadCount + 1) * stride);
|
|
1368
1469
|
const rgba = parseColorToRGBA(color);
|
|
@@ -1387,6 +1488,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1387
1488
|
circleQuadCount++;
|
|
1388
1489
|
return;
|
|
1389
1490
|
}
|
|
1491
|
+
circlePoints++;
|
|
1390
1492
|
pointData = grow(pointData, (pointCount + 1) * FLOATS_PER_POINT);
|
|
1391
1493
|
const [r, g, b, a] = parseColorToRGBA(color);
|
|
1392
1494
|
const o = pointCount * FLOATS_PER_POINT;
|
|
@@ -1428,6 +1530,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1428
1530
|
gl.uniform2f(rURes, logicalW, logicalH);
|
|
1429
1531
|
ensureQuadIndices(rectCount);
|
|
1430
1532
|
gl.drawElements(gl.TRIANGLES, rectCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1533
|
+
frameDrawCalls++;
|
|
1431
1534
|
}
|
|
1432
1535
|
if (pointCount > 0) {
|
|
1433
1536
|
gl.useProgram(pointProgram);
|
|
@@ -1441,6 +1544,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1441
1544
|
gl.uniform2f(pURes, logicalW, logicalH);
|
|
1442
1545
|
gl.uniform1f(pUDpr, dpr);
|
|
1443
1546
|
gl.drawArrays(gl.POINTS, 0, pointCount);
|
|
1547
|
+
frameDrawCalls++;
|
|
1444
1548
|
}
|
|
1445
1549
|
if (circleQuadCount > 0) {
|
|
1446
1550
|
const floats = circleQuadCount * VERTS_PER_QUAD * FLOATS_PER_SPRITE_VERT;
|
|
@@ -1451,6 +1555,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1451
1555
|
gl.uniform2f(cURes, logicalW, logicalH);
|
|
1452
1556
|
ensureQuadIndices(circleQuadCount);
|
|
1453
1557
|
gl.drawElements(gl.TRIANGLES, circleQuadCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1558
|
+
frameDrawCalls++;
|
|
1454
1559
|
}
|
|
1455
1560
|
if (spriteCount > 0 && texture) {
|
|
1456
1561
|
const floats = spriteCount * VERTS_PER_QUAD * FLOATS_PER_SPRITE_VERT;
|
|
@@ -1464,6 +1569,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1464
1569
|
gl.uniform2f(sURes, logicalW, logicalH);
|
|
1465
1570
|
ensureQuadIndices(spriteCount);
|
|
1466
1571
|
gl.drawElements(gl.TRIANGLES, spriteCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1572
|
+
frameDrawCalls++;
|
|
1467
1573
|
}
|
|
1468
1574
|
gl.bindVertexArray(null);
|
|
1469
1575
|
drawGlyphs();
|
|
@@ -1669,11 +1775,11 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
1669
1775
|
`;
|
|
1670
1776
|
var WebGPUParticleSystemManager = (_class3 = class {
|
|
1671
1777
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
constructor(device) {;_class3.prototype.
|
|
1778
|
+
__init35() {this.computePipeline = null}
|
|
1779
|
+
__init36() {this.renderPipeline = null}
|
|
1780
|
+
__init37() {this.computeBindGroupLayout = null}
|
|
1781
|
+
__init38() {this.renderBindGroupLayout = null}
|
|
1782
|
+
constructor(device) {;_class3.prototype.__init35.call(this);_class3.prototype.__init36.call(this);_class3.prototype.__init37.call(this);_class3.prototype.__init38.call(this);
|
|
1677
1783
|
this.device = device;
|
|
1678
1784
|
}
|
|
1679
1785
|
initPipelines(format) {
|
|
@@ -1818,23 +1924,23 @@ var WebGPUParticleSystemManager = (_class3 = class {
|
|
|
1818
1924
|
var HARD_MAX_SIZE = 8192;
|
|
1819
1925
|
var PAD = 2;
|
|
1820
1926
|
var GlyphRasterAtlas = (_class4 = class {
|
|
1821
|
-
|
|
1927
|
+
__init39() {this.slots = /* @__PURE__ */ new Map()}
|
|
1822
1928
|
|
|
1823
1929
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1930
|
+
__init40() {this.canvas = null}
|
|
1931
|
+
__init41() {this.ctx = null}
|
|
1826
1932
|
/**
|
|
1827
1933
|
* Shelf packing: glyphs land left-to-right on a row, then a new row starts.
|
|
1828
1934
|
* A monospace grid produces near-uniform widths, so shelves waste very little
|
|
1829
1935
|
* and cost one comparison per insert — a real 2D packer would buy nothing here.
|
|
1830
1936
|
*/
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
constructor(options = {}) {;_class4.prototype.
|
|
1937
|
+
__init42() {this.penX = PAD}
|
|
1938
|
+
__init43() {this.penY = PAD}
|
|
1939
|
+
__init44() {this.rowHeight = 0}
|
|
1940
|
+
__init45() {this._hits = 0}
|
|
1941
|
+
__init46() {this._misses = 0}
|
|
1942
|
+
__init47() {this._resets = 0}
|
|
1943
|
+
constructor(options = {}) {;_class4.prototype.__init39.call(this);_class4.prototype.__init40.call(this);_class4.prototype.__init41.call(this);_class4.prototype.__init42.call(this);_class4.prototype.__init43.call(this);_class4.prototype.__init44.call(this);_class4.prototype.__init45.call(this);_class4.prototype.__init46.call(this);_class4.prototype.__init47.call(this);
|
|
1838
1944
|
this.dpr = Math.max(1, _nullishCoalesce(options.dpr, () => ( 1)));
|
|
1839
1945
|
this.maxSize = Math.min(HARD_MAX_SIZE, Math.max(256, _nullishCoalesce(options.maxSize, () => ( 2048))));
|
|
1840
1946
|
}
|
|
@@ -2002,13 +2108,13 @@ var GlyphRasterAtlas = (_class4 = class {
|
|
|
2002
2108
|
|
|
2003
2109
|
// src/renderer/TextRasterCache.ts
|
|
2004
2110
|
var TextRasterCache = (_class5 = class {
|
|
2005
|
-
|
|
2111
|
+
__init48() {this.cache = /* @__PURE__ */ new Map()}
|
|
2006
2112
|
|
|
2007
2113
|
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
constructor(options = {}) {;_class5.prototype.
|
|
2114
|
+
__init49() {this.scratchCtx = null}
|
|
2115
|
+
__init50() {this._hits = 0}
|
|
2116
|
+
__init51() {this._misses = 0}
|
|
2117
|
+
constructor(options = {}) {;_class5.prototype.__init48.call(this);_class5.prototype.__init49.call(this);_class5.prototype.__init50.call(this);_class5.prototype.__init51.call(this);
|
|
2012
2118
|
this.maxEntries = Math.max(1, _nullishCoalesce(options.maxEntries, () => ( 4096)));
|
|
2013
2119
|
this.dpr = Math.max(1, _nullishCoalesce(options.dpr, () => ( 1)));
|
|
2014
2120
|
}
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
// src/renderer/CanvasRenderer.ts
|
|
2
|
+
function emptyDrawCounters() {
|
|
3
|
+
return {
|
|
4
|
+
fills: 0,
|
|
5
|
+
strokes: 0,
|
|
6
|
+
texts: 0,
|
|
7
|
+
images: 0,
|
|
8
|
+
circles: 0,
|
|
9
|
+
flushes: 0,
|
|
10
|
+
saves: 0,
|
|
11
|
+
restores: 0,
|
|
12
|
+
clips: 0,
|
|
13
|
+
stateSwitches: 0,
|
|
14
|
+
overdrawRatio: 0
|
|
15
|
+
};
|
|
16
|
+
}
|
|
2
17
|
var TWO_PI = Math.PI * 2;
|
|
3
18
|
function getDevicePixelRatio() {
|
|
4
19
|
return typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
@@ -39,6 +54,17 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
39
54
|
batchCount = 0;
|
|
40
55
|
_cachedFont = "";
|
|
41
56
|
_cachedFill = "";
|
|
57
|
+
/** Backend discriminator; see {@link IRenderer.kind}. */
|
|
58
|
+
kind = "canvas2d";
|
|
59
|
+
/**
|
|
60
|
+
* Draw counters, allocated only once counting is enabled.
|
|
61
|
+
*
|
|
62
|
+
* Null when off, so the guard on every op is a single null test and an inactive
|
|
63
|
+
* renderer carries no counter object at all.
|
|
64
|
+
*/
|
|
65
|
+
counters = null;
|
|
66
|
+
/** Accumulated primitive area, kept separately so the ratio is derived on read. */
|
|
67
|
+
drawnArea = 0;
|
|
42
68
|
/**
|
|
43
69
|
* @param canvas - The target canvas. Its backing store is resized to the
|
|
44
70
|
* logical size × devicePixelRatio.
|
|
@@ -135,19 +161,47 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
135
161
|
return this.contextLost;
|
|
136
162
|
}
|
|
137
163
|
/** @inheritdoc */
|
|
164
|
+
/** @inheritdoc */
|
|
165
|
+
setDrawCounters(enabled) {
|
|
166
|
+
if (!enabled) {
|
|
167
|
+
this.counters = null;
|
|
168
|
+
this.drawnArea = 0;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (!this.counters) this.counters = emptyDrawCounters();
|
|
172
|
+
}
|
|
173
|
+
/** @inheritdoc */
|
|
174
|
+
getDrawCounters() {
|
|
175
|
+
if (!this.counters) return null;
|
|
176
|
+
const area = this.width * this.height;
|
|
177
|
+
return {
|
|
178
|
+
...this.counters,
|
|
179
|
+
// Derived on read rather than maintained: the ratio is only meaningful
|
|
180
|
+
// against the current surface size, which can change under resize.
|
|
181
|
+
overdrawRatio: area > 0 ? Math.round(this.drawnArea / area * 100) / 100 : 0
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/** @inheritdoc */
|
|
185
|
+
clearDrawCounters() {
|
|
186
|
+
if (this.counters) this.counters = emptyDrawCounters();
|
|
187
|
+
this.drawnArea = 0;
|
|
188
|
+
}
|
|
138
189
|
clear() {
|
|
139
190
|
if (this.contextLost) return;
|
|
140
191
|
this.flush();
|
|
192
|
+
if (this.counters) this.drawnArea = 0;
|
|
141
193
|
this.ctx.clearRect(0, 0, this.width, this.height);
|
|
142
194
|
}
|
|
143
195
|
/** @inheritdoc */
|
|
144
196
|
save() {
|
|
145
197
|
this.flush();
|
|
198
|
+
if (this.counters) this.counters.saves++;
|
|
146
199
|
this.ctx.save();
|
|
147
200
|
}
|
|
148
201
|
/** @inheritdoc */
|
|
149
202
|
restore() {
|
|
150
203
|
this.flush();
|
|
204
|
+
if (this.counters) this.counters.restores++;
|
|
151
205
|
this.ctx.restore();
|
|
152
206
|
this._cachedFont = "";
|
|
153
207
|
this._cachedFill = "";
|
|
@@ -171,6 +225,7 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
171
225
|
/** @inheritdoc */
|
|
172
226
|
clip(x, y, width, height) {
|
|
173
227
|
this.flush();
|
|
228
|
+
if (this.counters) this.counters.clips++;
|
|
174
229
|
this.ctx.beginPath();
|
|
175
230
|
this.ctx.rect(x, y, width, height);
|
|
176
231
|
this.ctx.clip();
|
|
@@ -207,11 +262,19 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
207
262
|
/** @inheritdoc */
|
|
208
263
|
drawImage(source, dx, dy, dw, dh) {
|
|
209
264
|
this.flush();
|
|
265
|
+
if (this.counters) {
|
|
266
|
+
this.counters.images++;
|
|
267
|
+
this.drawnArea += Math.abs(dw * dh);
|
|
268
|
+
}
|
|
210
269
|
this.ctx.drawImage(source, dx, dy, dw, dh);
|
|
211
270
|
}
|
|
212
271
|
/** @inheritdoc */
|
|
213
272
|
drawImageRect(source, sx, sy, sw, sh, dx, dy, dw, dh) {
|
|
214
273
|
this.flush();
|
|
274
|
+
if (this.counters) {
|
|
275
|
+
this.counters.images++;
|
|
276
|
+
this.drawnArea += Math.abs(dw * dh);
|
|
277
|
+
}
|
|
215
278
|
this.ctx.drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
216
279
|
}
|
|
217
280
|
/** @inheritdoc */
|
|
@@ -225,6 +288,10 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
225
288
|
this.batchColor = color;
|
|
226
289
|
this.batchAlpha = alpha;
|
|
227
290
|
}
|
|
291
|
+
if (this.counters) {
|
|
292
|
+
this.counters.circles++;
|
|
293
|
+
this.drawnArea += Math.PI * radius * radius;
|
|
294
|
+
}
|
|
228
295
|
this.ctx.moveTo(cx + radius, cy);
|
|
229
296
|
this.ctx.arc(cx, cy, radius, 0, TWO_PI);
|
|
230
297
|
this.batchCount++;
|
|
@@ -233,6 +300,7 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
233
300
|
/** @inheritdoc */
|
|
234
301
|
flush() {
|
|
235
302
|
if (!this.batchActive) return;
|
|
303
|
+
if (this.counters) this.counters.flushes++;
|
|
236
304
|
this.ctx.globalAlpha = this.batchAlpha;
|
|
237
305
|
this.ctx.fillStyle = this.batchColor;
|
|
238
306
|
this.ctx.fill();
|
|
@@ -243,7 +311,9 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
243
311
|
/** @inheritdoc */
|
|
244
312
|
fill(color) {
|
|
245
313
|
this.flush();
|
|
314
|
+
if (this.counters) this.counters.fills++;
|
|
246
315
|
if (this._cachedFill !== color) {
|
|
316
|
+
if (this.counters) this.counters.stateSwitches++;
|
|
247
317
|
this.ctx.fillStyle = color;
|
|
248
318
|
this._cachedFill = color;
|
|
249
319
|
}
|
|
@@ -252,6 +322,7 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
252
322
|
/** @inheritdoc */
|
|
253
323
|
stroke(color, lineWidth = 1) {
|
|
254
324
|
this.flush();
|
|
325
|
+
if (this.counters) this.counters.strokes++;
|
|
255
326
|
this.ctx.strokeStyle = color;
|
|
256
327
|
this.ctx.lineWidth = lineWidth;
|
|
257
328
|
this.ctx.lineCap = "round";
|
|
@@ -261,11 +332,14 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
261
332
|
/** @inheritdoc */
|
|
262
333
|
fillText(text, x, y, font, color) {
|
|
263
334
|
this.flush();
|
|
335
|
+
if (this.counters) this.counters.texts++;
|
|
264
336
|
if (this._cachedFont !== font) {
|
|
337
|
+
if (this.counters) this.counters.stateSwitches++;
|
|
265
338
|
this.ctx.font = font;
|
|
266
339
|
this._cachedFont = font;
|
|
267
340
|
}
|
|
268
341
|
if (this._cachedFill !== color) {
|
|
342
|
+
if (this.counters) this.counters.stateSwitches++;
|
|
269
343
|
this.ctx.fillStyle = color;
|
|
270
344
|
this._cachedFill = color;
|
|
271
345
|
}
|
|
@@ -376,6 +450,8 @@ function fontFamilyFromShorthand(font, sizeToken) {
|
|
|
376
450
|
return family || "sans-serif";
|
|
377
451
|
}
|
|
378
452
|
var SVGRenderer = class {
|
|
453
|
+
/** Backend discriminator; see {@link IRenderer.kind}. */
|
|
454
|
+
kind = "svg";
|
|
379
455
|
width;
|
|
380
456
|
height;
|
|
381
457
|
buffer = [];
|
|
@@ -1228,6 +1304,12 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1228
1304
|
let spriteCount = 0;
|
|
1229
1305
|
let glyphData = new Float32Array(FLOATS_PER_SPRITE_VERT * VERTS_PER_QUAD * 1024);
|
|
1230
1306
|
let glyphCount = 0;
|
|
1307
|
+
let frameDrawCalls = 0;
|
|
1308
|
+
let lastFrameDrawCalls = 0;
|
|
1309
|
+
let totalDrawCalls = 0;
|
|
1310
|
+
let atlasSwitches = 0;
|
|
1311
|
+
let circleQuadFallbacks = 0;
|
|
1312
|
+
let circlePoints = 0;
|
|
1231
1313
|
let circleQuadData = new Float32Array(FLOATS_PER_SPRITE_VERT * VERTS_PER_QUAD * 64);
|
|
1232
1314
|
let circleQuadCount = 0;
|
|
1233
1315
|
let logicalW = 0;
|
|
@@ -1250,6 +1332,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1250
1332
|
gl.uniform1f(gURange, distanceRange);
|
|
1251
1333
|
ensureQuadIndices(glyphCount);
|
|
1252
1334
|
gl.drawElements(gl.TRIANGLES, glyphCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1335
|
+
frameDrawCalls++;
|
|
1253
1336
|
gl.bindVertexArray(null);
|
|
1254
1337
|
glyphCount = 0;
|
|
1255
1338
|
};
|
|
@@ -1266,7 +1349,23 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1266
1349
|
canvas.style.height = `${height}px`;
|
|
1267
1350
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
1268
1351
|
},
|
|
1352
|
+
stats() {
|
|
1353
|
+
return {
|
|
1354
|
+
drawCalls: lastFrameDrawCalls,
|
|
1355
|
+
totalDrawCalls,
|
|
1356
|
+
atlasSwitches,
|
|
1357
|
+
// Fixed at creation: five programs compiled once, never per frame, so
|
|
1358
|
+
// these are capability facts rather than counters.
|
|
1359
|
+
programs: 5,
|
|
1360
|
+
textures: (texture ? 1 : 0) + (msdfTexture ? 1 : 0),
|
|
1361
|
+
circleQuadFallbacks,
|
|
1362
|
+
circlePoints
|
|
1363
|
+
};
|
|
1364
|
+
},
|
|
1269
1365
|
begin() {
|
|
1366
|
+
lastFrameDrawCalls = frameDrawCalls;
|
|
1367
|
+
totalDrawCalls += frameDrawCalls;
|
|
1368
|
+
frameDrawCalls = 0;
|
|
1270
1369
|
pointCount = 0;
|
|
1271
1370
|
rectCount = 0;
|
|
1272
1371
|
spriteCount = 0;
|
|
@@ -1319,6 +1418,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1319
1418
|
distanceRange = range;
|
|
1320
1419
|
return;
|
|
1321
1420
|
}
|
|
1421
|
+
atlasSwitches++;
|
|
1322
1422
|
drawGlyphs();
|
|
1323
1423
|
distanceRange = range;
|
|
1324
1424
|
if (!msdfTexture) {
|
|
@@ -1361,6 +1461,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1361
1461
|
addCircle(x, y, radius, color, alpha = 1) {
|
|
1362
1462
|
const needsQuad = logicalW > 0 && (x < radius || y < radius || x > logicalW - radius || y > logicalH - radius) || radius * 2 * dpr > maxPointSize;
|
|
1363
1463
|
if (needsQuad) {
|
|
1464
|
+
circleQuadFallbacks++;
|
|
1364
1465
|
const stride = FLOATS_PER_SPRITE_VERT * VERTS_PER_QUAD;
|
|
1365
1466
|
circleQuadData = grow(circleQuadData, (circleQuadCount + 1) * stride);
|
|
1366
1467
|
const rgba = parseColorToRGBA(color);
|
|
@@ -1385,6 +1486,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1385
1486
|
circleQuadCount++;
|
|
1386
1487
|
return;
|
|
1387
1488
|
}
|
|
1489
|
+
circlePoints++;
|
|
1388
1490
|
pointData = grow(pointData, (pointCount + 1) * FLOATS_PER_POINT);
|
|
1389
1491
|
const [r, g, b, a] = parseColorToRGBA(color);
|
|
1390
1492
|
const o = pointCount * FLOATS_PER_POINT;
|
|
@@ -1426,6 +1528,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1426
1528
|
gl.uniform2f(rURes, logicalW, logicalH);
|
|
1427
1529
|
ensureQuadIndices(rectCount);
|
|
1428
1530
|
gl.drawElements(gl.TRIANGLES, rectCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1531
|
+
frameDrawCalls++;
|
|
1429
1532
|
}
|
|
1430
1533
|
if (pointCount > 0) {
|
|
1431
1534
|
gl.useProgram(pointProgram);
|
|
@@ -1439,6 +1542,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1439
1542
|
gl.uniform2f(pURes, logicalW, logicalH);
|
|
1440
1543
|
gl.uniform1f(pUDpr, dpr);
|
|
1441
1544
|
gl.drawArrays(gl.POINTS, 0, pointCount);
|
|
1545
|
+
frameDrawCalls++;
|
|
1442
1546
|
}
|
|
1443
1547
|
if (circleQuadCount > 0) {
|
|
1444
1548
|
const floats = circleQuadCount * VERTS_PER_QUAD * FLOATS_PER_SPRITE_VERT;
|
|
@@ -1449,6 +1553,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1449
1553
|
gl.uniform2f(cURes, logicalW, logicalH);
|
|
1450
1554
|
ensureQuadIndices(circleQuadCount);
|
|
1451
1555
|
gl.drawElements(gl.TRIANGLES, circleQuadCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1556
|
+
frameDrawCalls++;
|
|
1452
1557
|
}
|
|
1453
1558
|
if (spriteCount > 0 && texture) {
|
|
1454
1559
|
const floats = spriteCount * VERTS_PER_QUAD * FLOATS_PER_SPRITE_VERT;
|
|
@@ -1462,6 +1567,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1462
1567
|
gl.uniform2f(sURes, logicalW, logicalH);
|
|
1463
1568
|
ensureQuadIndices(spriteCount);
|
|
1464
1569
|
gl.drawElements(gl.TRIANGLES, spriteCount * INDICES_PER_QUAD, gl.UNSIGNED_INT, 0);
|
|
1570
|
+
frameDrawCalls++;
|
|
1465
1571
|
}
|
|
1466
1572
|
gl.bindVertexArray(null);
|
|
1467
1573
|
drawGlyphs();
|