@vectojs/core 0.2.4 → 0.2.6
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-TQ4H357Q.js → chunk-4BO5XBJL.js} +57 -13
- package/dist/{chunk-IKLYTHAL.js → chunk-BWLNEJJW.js} +24 -28
- package/dist/{chunk-76NMTLYL.js → chunk-CTZQOM5Z.js} +1 -1
- package/dist/{chunk-TPNADFNN.js → chunk-GADBN53Z.js} +52 -26
- package/dist/{chunk-WEQRBXT2.mjs → chunk-PK5EYWIT.mjs} +50 -24
- package/dist/{chunk-P6MDWIEX.mjs → chunk-SL654OMF.mjs} +55 -11
- package/dist/{chunk-MCULB5VC.mjs → chunk-SSOP3F5F.mjs} +17 -21
- package/dist/{chunk-B3Z3JEJH.mjs → chunk-STWPTWO4.mjs} +1 -1
- package/dist/components/SplineEntity.d.ts +5 -0
- package/dist/index.js +178 -98
- package/dist/index.mjs +101 -21
- package/dist/layout/LayoutEngine.d.ts +1 -0
- package/dist/layout/LayoutWorkerSource.d.ts +1 -1
- package/dist/layout.js +3 -3
- package/dist/layout.mjs +2 -2
- package/dist/renderer/CanvasRenderer.d.ts +12 -1
- package/dist/renderer/IRenderer.d.ts +7 -0
- package/dist/renderer/url.d.ts +1 -1
- package/dist/renderer.js +2 -2
- package/dist/renderer.mjs +1 -1
- package/dist/text/MSDFTextEntity.d.ts +9 -0
- package/dist/text.js +3 -3
- package/dist/text.mjs +2 -2
- package/dist/tree/Scene.d.ts +7 -3
- package/package.json +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
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; var _class6; var _class7;
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkCTZQOM5Zjs = require('./chunk-CTZQOM5Z.js');
|
|
4
4
|
|
|
5
5
|
// src/math/SpringPhysics.ts
|
|
6
|
+
var MAX_FRAME_DT = 0.25;
|
|
7
|
+
var MAX_STEP_DT = 1 / 120;
|
|
6
8
|
var SpringPhysics = (_class = class {
|
|
7
9
|
|
|
8
10
|
|
|
@@ -22,11 +24,22 @@ var SpringPhysics = (_class = class {
|
|
|
22
24
|
this.velocity = 0;
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
if (!(dt > 0)) return;
|
|
28
|
+
let remaining = dt < MAX_FRAME_DT ? dt : MAX_FRAME_DT;
|
|
29
|
+
while (remaining > 0) {
|
|
30
|
+
const step = remaining < MAX_STEP_DT ? remaining : MAX_STEP_DT;
|
|
31
|
+
const forceSpring = -this.stiffness * (this.value - this.target);
|
|
32
|
+
const forceDamping = -this.damping * this.velocity;
|
|
33
|
+
const acceleration = (forceSpring + forceDamping) / this.mass;
|
|
34
|
+
this.velocity += acceleration * step;
|
|
35
|
+
this.value += this.velocity * step;
|
|
36
|
+
remaining -= step;
|
|
37
|
+
if (this.isAtRest()) {
|
|
38
|
+
this.value = this.target;
|
|
39
|
+
this.velocity = 0;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
30
43
|
}
|
|
31
44
|
isAtRest() {
|
|
32
45
|
return Math.abs(this.value - this.target) < this.valEpsilon && Math.abs(this.velocity) < this.velEpsilon;
|
|
@@ -117,6 +130,14 @@ var SpringDriver = class {
|
|
|
117
130
|
};
|
|
118
131
|
|
|
119
132
|
// src/tree/Entity.ts
|
|
133
|
+
var ANIMATABLE_PROPS = /* @__PURE__ */ new Set([
|
|
134
|
+
"x",
|
|
135
|
+
"y",
|
|
136
|
+
"scaleX",
|
|
137
|
+
"scaleY",
|
|
138
|
+
"rotation",
|
|
139
|
+
"opacity"
|
|
140
|
+
]);
|
|
120
141
|
var VectoJSEvent = (_class3 = class {
|
|
121
142
|
/** The event name. */
|
|
122
143
|
|
|
@@ -568,7 +589,12 @@ var Entity = (_class4 = class {
|
|
|
568
589
|
const end = anim.target[key];
|
|
569
590
|
if (typeof start === "number" && typeof end === "number") {
|
|
570
591
|
const easeOut = progress * (2 - progress);
|
|
571
|
-
|
|
592
|
+
const value = start + (end - start) * easeOut;
|
|
593
|
+
if (ANIMATABLE_PROPS.has(key)) {
|
|
594
|
+
this._applyAnimated(key, value);
|
|
595
|
+
} else {
|
|
596
|
+
this[key] = value;
|
|
597
|
+
}
|
|
572
598
|
}
|
|
573
599
|
}
|
|
574
600
|
if (progress >= 1) {
|
|
@@ -619,6 +645,10 @@ var Entity = (_class4 = class {
|
|
|
619
645
|
*/
|
|
620
646
|
destroy() {
|
|
621
647
|
this.animations = [];
|
|
648
|
+
for (const driver of this._drivers.values()) {
|
|
649
|
+
this._settleDriver(driver);
|
|
650
|
+
}
|
|
651
|
+
this._drivers.clear();
|
|
622
652
|
this.listeners.clear();
|
|
623
653
|
this.captureListeners.clear();
|
|
624
654
|
if (this.parent) {
|
|
@@ -989,6 +1019,8 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
989
1019
|
|
|
990
1020
|
|
|
991
1021
|
|
|
1022
|
+
|
|
1023
|
+
|
|
992
1024
|
__init35() {this.text = ""}
|
|
993
1025
|
__init36() {this.lastRenderedSeqId = 0}
|
|
994
1026
|
__init37() {this.rgbColorCache = /* @__PURE__ */ new Map()}
|
|
@@ -1003,17 +1035,27 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1003
1035
|
this.color = _nullishCoalesce(options.color, () => ( "#ffffff"));
|
|
1004
1036
|
this.letterSpacing = _nullishCoalesce(options.letterSpacing, () => ( 0));
|
|
1005
1037
|
this.lineHeight = options.lineHeight;
|
|
1038
|
+
this.maxWidth = _nullishCoalesce(options.maxWidth, () => ( 1e3));
|
|
1039
|
+
this.maxHeight = _nullishCoalesce(options.maxHeight, () => ( 1e3));
|
|
1006
1040
|
this.setText(text);
|
|
1007
1041
|
}
|
|
1042
|
+
/** Change the wrap boundary and re-run layout for the current text. */
|
|
1043
|
+
setMaxWidth(maxWidth) {
|
|
1044
|
+
if (this.maxWidth === maxWidth) return;
|
|
1045
|
+
this.maxWidth = maxWidth;
|
|
1046
|
+
this.queueLayout();
|
|
1047
|
+
}
|
|
1008
1048
|
setText(text) {
|
|
1009
1049
|
if (this.text === text && this.layoutResult) return;
|
|
1010
1050
|
this.text = text;
|
|
1011
|
-
|
|
1051
|
+
this.queueLayout();
|
|
1052
|
+
}
|
|
1053
|
+
queueLayout() {
|
|
1054
|
+
_chunkCTZQOM5Zjs.LayoutWorkerManager.getInstance().queueLayout(this.id, this.text, {
|
|
1012
1055
|
fontId: this.font.id,
|
|
1013
1056
|
fontSize: this.fontSize,
|
|
1014
|
-
maxWidth:
|
|
1015
|
-
|
|
1016
|
-
maxHeight: 1e3,
|
|
1057
|
+
maxWidth: this.maxWidth,
|
|
1058
|
+
maxHeight: this.maxHeight,
|
|
1017
1059
|
fontData: this.font.data,
|
|
1018
1060
|
letterSpacing: this.letterSpacing,
|
|
1019
1061
|
lineHeight: this.lineHeight,
|
|
@@ -1042,6 +1084,8 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1042
1084
|
if (scene && scene.pointRenderer && scene.glCanvas && canUsePointGlyphs) {
|
|
1043
1085
|
scene.pointRenderer.setMSDFTexture(this.texture, this.font.distanceRange);
|
|
1044
1086
|
const worldRot = Math.atan2(world.b, world.a);
|
|
1087
|
+
let worldOpacity = this.opacity;
|
|
1088
|
+
for (let p = this.parent; p; p = p.parent) worldOpacity *= p.opacity;
|
|
1045
1089
|
const len2 = this.layoutResult.codePoints.length;
|
|
1046
1090
|
for (let i = 0; i < len2; i++) {
|
|
1047
1091
|
const code = this.layoutResult.codePoints[i];
|
|
@@ -1080,7 +1124,7 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1080
1124
|
ab.right / aw,
|
|
1081
1125
|
v1,
|
|
1082
1126
|
runColor,
|
|
1083
|
-
|
|
1127
|
+
worldOpacity,
|
|
1084
1128
|
worldRot
|
|
1085
1129
|
);
|
|
1086
1130
|
}
|
|
@@ -1112,7 +1156,7 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1112
1156
|
}
|
|
1113
1157
|
}
|
|
1114
1158
|
destroy() {
|
|
1115
|
-
|
|
1159
|
+
_chunkCTZQOM5Zjs.LayoutWorkerManager.getInstance().cancelLayout(this.id);
|
|
1116
1160
|
super.destroy();
|
|
1117
1161
|
}
|
|
1118
1162
|
}, _class6);
|
|
@@ -1,7 +1,7 @@
|
|
|
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;
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkCTZQOM5Zjs = require('./chunk-CTZQOM5Z.js');
|
|
5
5
|
|
|
6
6
|
// src/layout/LayoutEngine.ts
|
|
7
7
|
function computeLineSegments(top, bottom, maxWidth, exclusions) {
|
|
@@ -79,6 +79,12 @@ var LayoutEngine = (_class = class {
|
|
|
79
79
|
if (this.measurer) return this.measurer.measure(char, fontSize);
|
|
80
80
|
return fontSize * 0.5;
|
|
81
81
|
}
|
|
82
|
+
glyphKeyFor(grapheme, fontAtlas) {
|
|
83
|
+
if (fontAtlas[grapheme]) return grapheme;
|
|
84
|
+
const firstCodePoint = Array.from(grapheme)[0];
|
|
85
|
+
if (firstCodePoint && fontAtlas[firstCodePoint]) return firstCodePoint;
|
|
86
|
+
return grapheme;
|
|
87
|
+
}
|
|
82
88
|
getGraphemes(word) {
|
|
83
89
|
const cached = this.graphemeCache.get(word);
|
|
84
90
|
if (cached) return cached;
|
|
@@ -142,8 +148,8 @@ var LayoutEngine = (_class = class {
|
|
|
142
148
|
offset += paragraph.length + 1;
|
|
143
149
|
continue;
|
|
144
150
|
}
|
|
145
|
-
const { shapedText, indexMap } =
|
|
146
|
-
const levels =
|
|
151
|
+
const { shapedText, indexMap } = _chunkCTZQOM5Zjs.ArabicShaper.shapeArabic(paragraph);
|
|
152
|
+
const levels = _chunkCTZQOM5Zjs.BidiResolver.resolveLevels(shapedText);
|
|
147
153
|
const words = [];
|
|
148
154
|
let shapedCharIdx = 0;
|
|
149
155
|
let pFallback = false;
|
|
@@ -158,25 +164,20 @@ var LayoutEngine = (_class = class {
|
|
|
158
164
|
const rawEnd = visualEnd === shapedText.length ? paragraph.length : indexMap[visualEnd];
|
|
159
165
|
const sourceIndex = offset + rawStart;
|
|
160
166
|
const sourceLength = rawEnd - rawStart;
|
|
161
|
-
const
|
|
167
|
+
const glyphKey = this.glyphKeyFor(char, fontAtlas);
|
|
162
168
|
const level = levels[visualStart];
|
|
163
|
-
const hasGlyph = !!fontAtlas[
|
|
169
|
+
const hasGlyph = !!fontAtlas[glyphKey];
|
|
164
170
|
if (char.trim().length > 0 && !hasGlyph) {
|
|
165
171
|
pFallback = true;
|
|
166
172
|
fallbackToCanvas = true;
|
|
167
173
|
}
|
|
168
|
-
const w = this.glyphWidth(
|
|
169
|
-
const combining = [];
|
|
170
|
-
for (let cIdx = 1; cIdx < char.length; cIdx++) {
|
|
171
|
-
combining.push(char[cIdx]);
|
|
172
|
-
}
|
|
174
|
+
const w = this.glyphWidth(glyphKey, fontAtlas, fontSize);
|
|
173
175
|
glyphs.push({
|
|
174
|
-
char
|
|
176
|
+
char,
|
|
175
177
|
width: w,
|
|
176
178
|
level,
|
|
177
179
|
sourceIndex,
|
|
178
|
-
sourceLength
|
|
179
|
-
combining: combining.length > 0 ? combining : void 0
|
|
180
|
+
sourceLength
|
|
180
181
|
});
|
|
181
182
|
width += w;
|
|
182
183
|
shapedCharIdx += char.length;
|
|
@@ -192,7 +193,7 @@ var LayoutEngine = (_class = class {
|
|
|
192
193
|
words,
|
|
193
194
|
isEmpty: false,
|
|
194
195
|
fallbackToCanvas: pFallback || void 0,
|
|
195
|
-
baseLevel:
|
|
196
|
+
baseLevel: _chunkCTZQOM5Zjs.BidiResolver.getBaseLevel(shapedText)
|
|
196
197
|
};
|
|
197
198
|
if (this.paragraphCache.size > 1e3) this.paragraphCache.clear();
|
|
198
199
|
this.paragraphCache.set(key, prepared);
|
|
@@ -264,8 +265,8 @@ var LayoutEngine = (_class = class {
|
|
|
264
265
|
offset += paragraph.length + 1;
|
|
265
266
|
continue;
|
|
266
267
|
}
|
|
267
|
-
const { shapedText, indexMap } =
|
|
268
|
-
const levels =
|
|
268
|
+
const { shapedText, indexMap } = _chunkCTZQOM5Zjs.ArabicShaper.shapeArabic(paragraph);
|
|
269
|
+
const levels = _chunkCTZQOM5Zjs.BidiResolver.resolveLevels(shapedText);
|
|
269
270
|
const words = [];
|
|
270
271
|
let shapedCharIdx = 0;
|
|
271
272
|
let pFallback = false;
|
|
@@ -280,28 +281,23 @@ var LayoutEngine = (_class = class {
|
|
|
280
281
|
const rawEnd = visualEnd === shapedText.length ? paragraph.length : indexMap[visualEnd];
|
|
281
282
|
const sourceIndex = offset + rawStart;
|
|
282
283
|
const sourceLength = rawEnd - rawStart;
|
|
283
|
-
const
|
|
284
|
+
const glyphKey = this.glyphKeyFor(char, fontAtlas);
|
|
284
285
|
const level = levels[visualStart];
|
|
285
286
|
const style = styleAt[offset + rawStart];
|
|
286
287
|
const gfs = _nullishCoalesce(_optionalChain([style, 'optionalAccess', _ => _.fontSize]), () => ( baseFontSize));
|
|
287
|
-
const hasGlyph = !!fontAtlas[
|
|
288
|
+
const hasGlyph = !!fontAtlas[glyphKey];
|
|
288
289
|
if (char.trim().length > 0 && !hasGlyph) {
|
|
289
290
|
pFallback = true;
|
|
290
291
|
fallbackToCanvas = true;
|
|
291
292
|
}
|
|
292
|
-
const w = this.glyphWidth(
|
|
293
|
-
const combining = [];
|
|
294
|
-
for (let cIdx = 1; cIdx < char.length; cIdx++) {
|
|
295
|
-
combining.push(char[cIdx]);
|
|
296
|
-
}
|
|
293
|
+
const w = this.glyphWidth(glyphKey, fontAtlas, gfs);
|
|
297
294
|
glyphs.push({
|
|
298
|
-
char
|
|
295
|
+
char,
|
|
299
296
|
width: w,
|
|
300
297
|
style,
|
|
301
298
|
level,
|
|
302
299
|
sourceIndex,
|
|
303
|
-
sourceLength
|
|
304
|
-
combining: combining.length > 0 ? combining : void 0
|
|
300
|
+
sourceLength
|
|
305
301
|
});
|
|
306
302
|
width += w;
|
|
307
303
|
shapedCharIdx += char.length;
|
|
@@ -317,7 +313,7 @@ var LayoutEngine = (_class = class {
|
|
|
317
313
|
words,
|
|
318
314
|
isEmpty: false,
|
|
319
315
|
fallbackToCanvas: pFallback || void 0,
|
|
320
|
-
baseLevel:
|
|
316
|
+
baseLevel: _chunkCTZQOM5Zjs.BidiResolver.getBaseLevel(shapedText)
|
|
321
317
|
};
|
|
322
318
|
if (this.richParagraphCache.size > 1e3) this.richParagraphCache.clear();
|
|
323
319
|
this.richParagraphCache.set(key, prepared);
|
|
@@ -372,7 +368,7 @@ var LayoutEngine = (_class = class {
|
|
|
372
368
|
}
|
|
373
369
|
for (const run of runs) {
|
|
374
370
|
const runStartX = run[0].x;
|
|
375
|
-
|
|
371
|
+
_chunkCTZQOM5Zjs.BidiResolver.reorderVisual(run, paragraphBaseLevel);
|
|
376
372
|
let x = runStartX;
|
|
377
373
|
for (const node of run) {
|
|
378
374
|
node.x = x;
|
|
@@ -296,7 +296,7 @@ var BidiResolver = class _BidiResolver {
|
|
|
296
296
|
};
|
|
297
297
|
|
|
298
298
|
// src/layout/LayoutWorkerSource.ts
|
|
299
|
-
var WORKER_SOURCE_STRING = '"use strict";(()=>{var
|
|
299
|
+
var WORKER_SOURCE_STRING = '"use strict";(()=>{var C=new Map;function f(t){return typeof t=="number"&&Number.isFinite(t)}function U(t){return t.origin?t.origin===self.location.origin:!0}function j(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="string"&&f(e.seqId)&&typeof e.text=="string"&&typeof e.fontId=="string"&&(e.fontData===void 0||typeof e.fontData=="object")&&f(e.maxWidth)&&f(e.maxHeight)&&f(e.fontSize)&&(e.lineHeight===void 0||f(e.lineHeight))&&(e.letterSpacing===void 0||f(e.letterSpacing))}self.onmessage=t=>{if(!U(t)||!j(t.data))return;let{id:e,seqId:D,text:L,fontId:k,fontData:S,maxWidth:H,maxHeight:z,fontSize:d,lineHeight:I,letterSpacing:M}=t.data;S&&C.set(k,S);let g=C.get(k);if(!g)return;let m=[],i=[],h=[],w=[],n=0,c=0,r=0,o=-1,p=g.metrics?.ascender??.8,R=g.metrics?.descender??-.2,b=I??d*(p-R),P=M??0,F=new Map;for(let s of g.glyphs??[])F.set(s.unicode,s.advance);let x=()=>{n>r&&(r=n),n=0,c++,o=-1},A=Array.from(L);for(let s=0;s<A.length;s++){let a=A[s].codePointAt(0);if(a===10){x();continue}let W=(F.get(a)??1)*d,q=a>=11904;if(q&&(o=-1),n+W>H&&n>0){if(a===32){x();continue}if(o>=0&&i[o]>0){let l=i[o];l>r&&(r=l),c++;let v=c*b+p*d;for(let y=o;y<i.length;y++)i[y]-=l,h[y]=v;n-=l}else x()}a===32?o=-1:o===-1&&!q&&(o=m.length),m.push(a),i.push(n),h.push(c*b+p*d),w.push(-256),n+=W+P}n>r&&(r=n);let u={id:e,seqId:D,width:r,height:(c+1)*b,codePoints:new Uint32Array(m),xCoords:new Float32Array(i),yCoords:new Float32Array(h),packedStyles:new Uint32Array(w)};self.postMessage(u,[u.codePoints.buffer,u.xCoords.buffer,u.yCoords.buffer,u.packedStyles.buffer])};})();\n';
|
|
300
300
|
|
|
301
301
|
// src/layout/LayoutWorkerManager.ts
|
|
302
302
|
var LayoutWorkerManager = (_class2 = class _LayoutWorkerManager {
|
|
@@ -20,10 +20,18 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
|
|
|
20
20
|
__init2() {this.batchColor = ""}
|
|
21
21
|
__init3() {this.batchAlpha = 1}
|
|
22
22
|
__init4() {this.batchCount = 0}
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @param canvas - The target canvas. Its backing store is resized to the
|
|
25
|
+
* logical size × devicePixelRatio.
|
|
26
|
+
* @param size - Explicit logical size. Without it the renderer assumes a
|
|
27
|
+
* fullscreen canvas and sizes to the window — pass this for embedded /
|
|
28
|
+
* custom-container canvases (the Scene does when `disableWindowResize` is
|
|
29
|
+
* set) so the canvas's own dimensions aren't clobbered by the window's.
|
|
30
|
+
*/
|
|
31
|
+
constructor(canvas, size) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
|
|
24
32
|
const dpr = getDevicePixelRatio();
|
|
25
|
-
this.width = typeof window !== "undefined" ? window.innerWidth : canvas.width || 0;
|
|
26
|
-
this.height = typeof window !== "undefined" ? window.innerHeight : canvas.height || 0;
|
|
33
|
+
this.width = _nullishCoalesce(_optionalChain([size, 'optionalAccess', _ => _.width]), () => ( (typeof window !== "undefined" ? window.innerWidth : canvas.width || 0)));
|
|
34
|
+
this.height = _nullishCoalesce(_optionalChain([size, 'optionalAccess', _2 => _2.height]), () => ( (typeof window !== "undefined" ? window.innerHeight : canvas.height || 0)));
|
|
27
35
|
canvas.width = this.width * dpr;
|
|
28
36
|
canvas.height = this.height * dpr;
|
|
29
37
|
const ctx = canvas.getContext("2d");
|
|
@@ -414,18 +422,19 @@ var SVGRenderer = (_class2 = class {
|
|
|
414
422
|
} else {
|
|
415
423
|
this.currentPath.push(`L ${xs} ${ys}`);
|
|
416
424
|
}
|
|
417
|
-
const
|
|
418
|
-
|
|
425
|
+
const TWO_PI2 = Math.PI * 2;
|
|
426
|
+
const directedDelta = ccw ? startAngle - endAngle : endAngle - startAngle;
|
|
427
|
+
const sweepAngle = directedDelta >= TWO_PI2 ? TWO_PI2 : (directedDelta % TWO_PI2 + TWO_PI2) % TWO_PI2;
|
|
428
|
+
const sweep = ccw ? 0 : 1;
|
|
429
|
+
if (sweepAngle >= TWO_PI2 - 1e-4) {
|
|
419
430
|
const xm = x - r * Math.cos(startAngle);
|
|
420
431
|
const ym = y - r * Math.sin(startAngle);
|
|
421
|
-
const sweep = ccw ? 0 : 1;
|
|
422
432
|
this.currentPath.push(`A ${r} ${r} 0 0 ${sweep} ${xm} ${ym}`);
|
|
423
433
|
this.currentPath.push(`A ${r} ${r} 0 0 ${sweep} ${xs} ${ys}`);
|
|
424
434
|
} else {
|
|
425
435
|
const xe = x + r * Math.cos(endAngle);
|
|
426
436
|
const ye = y + r * Math.sin(endAngle);
|
|
427
|
-
const largeArc =
|
|
428
|
-
const sweep = ccw ? 0 : 1;
|
|
437
|
+
const largeArc = sweepAngle > Math.PI ? 1 : 0;
|
|
429
438
|
this.currentPath.push(`A ${r} ${r} 0 ${largeArc} ${sweep} ${xe} ${ye}`);
|
|
430
439
|
}
|
|
431
440
|
}
|
|
@@ -537,8 +546,8 @@ var SVGRenderer = (_class2 = class {
|
|
|
537
546
|
}
|
|
538
547
|
drawImage(source, dx, dy, dw, dh) {
|
|
539
548
|
this.flush();
|
|
540
|
-
const fromCanvas2 = typeof _optionalChain([source, 'optionalAccess',
|
|
541
|
-
const rawHref = fromCanvas2 ? source.toDataURL() : _optionalChain([source, 'optionalAccess',
|
|
549
|
+
const fromCanvas2 = typeof _optionalChain([source, 'optionalAccess', _3 => _3.toDataURL]) === "function";
|
|
550
|
+
const rawHref = fromCanvas2 ? source.toDataURL() : _optionalChain([source, 'optionalAccess', _4 => _4.src]) || "";
|
|
542
551
|
const href = fromCanvas2 && this.isSafeRasterDataUrl(rawHref) ? rawHref : sanitizeUrl(String(rawHref));
|
|
543
552
|
const transformStr = `matrix(${this.ma},${this.mb},${this.mc},${this.md},${this.me},${this.mf})`;
|
|
544
553
|
if (href) {
|
|
@@ -723,6 +732,7 @@ function fromCanvas(css) {
|
|
|
723
732
|
if (typeof document === "undefined") return null;
|
|
724
733
|
if (!fallbackCtx) fallbackCtx = document.createElement("canvas").getContext("2d");
|
|
725
734
|
if (!fallbackCtx) return null;
|
|
735
|
+
fallbackCtx.clearRect(0, 0, 1, 1);
|
|
726
736
|
fallbackCtx.fillStyle = css;
|
|
727
737
|
fallbackCtx.fillRect(0, 0, 1, 1);
|
|
728
738
|
const d = fallbackCtx.getImageData(0, 0, 1, 1).data;
|
|
@@ -869,7 +879,9 @@ function grow(data, needed) {
|
|
|
869
879
|
return grown;
|
|
870
880
|
}
|
|
871
881
|
function createWebGLPointRenderer(canvas) {
|
|
872
|
-
const gl = canvas.getContext("webgl2"
|
|
882
|
+
const gl = canvas.getContext("webgl2", {
|
|
883
|
+
premultipliedAlpha: false
|
|
884
|
+
});
|
|
873
885
|
if (!gl) return null;
|
|
874
886
|
const pointProgram = link(gl, POINT_VERT, POINT_FRAG);
|
|
875
887
|
const rectProgram = link(gl, RECT_VERT, RECT_FRAG);
|
|
@@ -937,7 +949,9 @@ function createWebGLPointRenderer(canvas) {
|
|
|
937
949
|
gl.vertexAttribPointer(gATint, 4, gl.FLOAT, false, SPRITE_VERT_STRIDE, 16);
|
|
938
950
|
gl.bindVertexArray(null);
|
|
939
951
|
let texture = null;
|
|
952
|
+
let textureSource = null;
|
|
940
953
|
let msdfTexture = null;
|
|
954
|
+
let msdfSource = null;
|
|
941
955
|
let distanceRange = 4;
|
|
942
956
|
let pointData = new Float32Array(FLOATS_PER_POINT * 1024);
|
|
943
957
|
let pointCount = 0;
|
|
@@ -951,6 +965,22 @@ function createWebGLPointRenderer(canvas) {
|
|
|
951
965
|
let logicalH = 0;
|
|
952
966
|
let dpr = 1;
|
|
953
967
|
let destroyed = false;
|
|
968
|
+
const drawGlyphs = () => {
|
|
969
|
+
if (glyphCount === 0 || !msdfTexture) return;
|
|
970
|
+
const floats = glyphCount * VERTS_PER_SPRITE * FLOATS_PER_SPRITE_VERT;
|
|
971
|
+
gl.useProgram(msdfProgram);
|
|
972
|
+
gl.bindVertexArray(glyphVAO);
|
|
973
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, glyphBuffer);
|
|
974
|
+
gl.bufferData(gl.ARRAY_BUFFER, glyphData.subarray(0, floats), gl.DYNAMIC_DRAW);
|
|
975
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
976
|
+
gl.bindTexture(gl.TEXTURE_2D, msdfTexture);
|
|
977
|
+
gl.uniform1i(gUTex, 0);
|
|
978
|
+
gl.uniform2f(gURes, logicalW, logicalH);
|
|
979
|
+
gl.uniform1f(gURange, distanceRange);
|
|
980
|
+
gl.drawArrays(gl.TRIANGLES, 0, glyphCount * VERTS_PER_SPRITE);
|
|
981
|
+
gl.bindVertexArray(null);
|
|
982
|
+
glyphCount = 0;
|
|
983
|
+
};
|
|
954
984
|
return {
|
|
955
985
|
resize(width, height) {
|
|
956
986
|
logicalW = width;
|
|
@@ -967,8 +997,11 @@ function createWebGLPointRenderer(canvas) {
|
|
|
967
997
|
rectCount = 0;
|
|
968
998
|
spriteCount = 0;
|
|
969
999
|
glyphCount = 0;
|
|
1000
|
+
gl.clearColor(0, 0, 0, 0);
|
|
1001
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
970
1002
|
},
|
|
971
1003
|
setTexture(source) {
|
|
1004
|
+
if (source === textureSource && texture) return;
|
|
972
1005
|
if (!texture) {
|
|
973
1006
|
texture = gl.createTexture();
|
|
974
1007
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
@@ -980,6 +1013,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
980
1013
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
981
1014
|
}
|
|
982
1015
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
1016
|
+
textureSource = source;
|
|
983
1017
|
},
|
|
984
1018
|
addSprite(x, y, width, height, u0, v0, u1, v1, color = "#ffffff", alpha = 1, rotation = 0) {
|
|
985
1019
|
if (!texture) return;
|
|
@@ -1016,6 +1050,11 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1016
1050
|
spriteCount++;
|
|
1017
1051
|
},
|
|
1018
1052
|
setMSDFTexture(source, range) {
|
|
1053
|
+
if (source === msdfSource && msdfTexture) {
|
|
1054
|
+
distanceRange = range;
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
drawGlyphs();
|
|
1019
1058
|
distanceRange = range;
|
|
1020
1059
|
if (!msdfTexture) {
|
|
1021
1060
|
msdfTexture = gl.createTexture();
|
|
@@ -1028,6 +1067,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1028
1067
|
gl.bindTexture(gl.TEXTURE_2D, msdfTexture);
|
|
1029
1068
|
}
|
|
1030
1069
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
1070
|
+
msdfSource = source;
|
|
1031
1071
|
},
|
|
1032
1072
|
addGlyph(x, y, width, height, u0, v0, u1, v1, color = "#ffffff", alpha = 1, rotation = 0) {
|
|
1033
1073
|
if (!msdfTexture) return;
|
|
@@ -1105,8 +1145,6 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1105
1145
|
rectCount++;
|
|
1106
1146
|
},
|
|
1107
1147
|
flush() {
|
|
1108
|
-
gl.clearColor(0, 0, 0, 0);
|
|
1109
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1110
1148
|
if (rectCount > 0) {
|
|
1111
1149
|
const floats = rectCount * VERTS_PER_RECT * FLOATS_PER_RECT_VERT;
|
|
1112
1150
|
gl.useProgram(rectProgram);
|
|
@@ -1141,20 +1179,8 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1141
1179
|
gl.uniform2f(sURes, logicalW, logicalH);
|
|
1142
1180
|
gl.drawArrays(gl.TRIANGLES, 0, spriteCount * VERTS_PER_SPRITE);
|
|
1143
1181
|
}
|
|
1144
|
-
if (glyphCount > 0 && msdfTexture) {
|
|
1145
|
-
const floats = glyphCount * VERTS_PER_SPRITE * FLOATS_PER_SPRITE_VERT;
|
|
1146
|
-
gl.useProgram(msdfProgram);
|
|
1147
|
-
gl.bindVertexArray(glyphVAO);
|
|
1148
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, glyphBuffer);
|
|
1149
|
-
gl.bufferData(gl.ARRAY_BUFFER, glyphData.subarray(0, floats), gl.DYNAMIC_DRAW);
|
|
1150
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
1151
|
-
gl.bindTexture(gl.TEXTURE_2D, msdfTexture);
|
|
1152
|
-
gl.uniform1i(gUTex, 0);
|
|
1153
|
-
gl.uniform2f(gURes, logicalW, logicalH);
|
|
1154
|
-
gl.uniform1f(gURange, distanceRange);
|
|
1155
|
-
gl.drawArrays(gl.TRIANGLES, 0, glyphCount * VERTS_PER_SPRITE);
|
|
1156
|
-
}
|
|
1157
1182
|
gl.bindVertexArray(null);
|
|
1183
|
+
drawGlyphs();
|
|
1158
1184
|
},
|
|
1159
1185
|
destroy() {
|
|
1160
1186
|
if (destroyed) return;
|
|
@@ -20,10 +20,18 @@ var CanvasRenderer = class _CanvasRenderer {
|
|
|
20
20
|
batchColor = "";
|
|
21
21
|
batchAlpha = 1;
|
|
22
22
|
batchCount = 0;
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @param canvas - The target canvas. Its backing store is resized to the
|
|
25
|
+
* logical size × devicePixelRatio.
|
|
26
|
+
* @param size - Explicit logical size. Without it the renderer assumes a
|
|
27
|
+
* fullscreen canvas and sizes to the window — pass this for embedded /
|
|
28
|
+
* custom-container canvases (the Scene does when `disableWindowResize` is
|
|
29
|
+
* set) so the canvas's own dimensions aren't clobbered by the window's.
|
|
30
|
+
*/
|
|
31
|
+
constructor(canvas, size) {
|
|
24
32
|
const dpr = getDevicePixelRatio();
|
|
25
|
-
this.width = typeof window !== "undefined" ? window.innerWidth : canvas.width || 0;
|
|
26
|
-
this.height = typeof window !== "undefined" ? window.innerHeight : canvas.height || 0;
|
|
33
|
+
this.width = size?.width ?? (typeof window !== "undefined" ? window.innerWidth : canvas.width || 0);
|
|
34
|
+
this.height = size?.height ?? (typeof window !== "undefined" ? window.innerHeight : canvas.height || 0);
|
|
27
35
|
canvas.width = this.width * dpr;
|
|
28
36
|
canvas.height = this.height * dpr;
|
|
29
37
|
const ctx = canvas.getContext("2d");
|
|
@@ -414,18 +422,19 @@ var SVGRenderer = class {
|
|
|
414
422
|
} else {
|
|
415
423
|
this.currentPath.push(`L ${xs} ${ys}`);
|
|
416
424
|
}
|
|
417
|
-
const
|
|
418
|
-
|
|
425
|
+
const TWO_PI2 = Math.PI * 2;
|
|
426
|
+
const directedDelta = ccw ? startAngle - endAngle : endAngle - startAngle;
|
|
427
|
+
const sweepAngle = directedDelta >= TWO_PI2 ? TWO_PI2 : (directedDelta % TWO_PI2 + TWO_PI2) % TWO_PI2;
|
|
428
|
+
const sweep = ccw ? 0 : 1;
|
|
429
|
+
if (sweepAngle >= TWO_PI2 - 1e-4) {
|
|
419
430
|
const xm = x - r * Math.cos(startAngle);
|
|
420
431
|
const ym = y - r * Math.sin(startAngle);
|
|
421
|
-
const sweep = ccw ? 0 : 1;
|
|
422
432
|
this.currentPath.push(`A ${r} ${r} 0 0 ${sweep} ${xm} ${ym}`);
|
|
423
433
|
this.currentPath.push(`A ${r} ${r} 0 0 ${sweep} ${xs} ${ys}`);
|
|
424
434
|
} else {
|
|
425
435
|
const xe = x + r * Math.cos(endAngle);
|
|
426
436
|
const ye = y + r * Math.sin(endAngle);
|
|
427
|
-
const largeArc =
|
|
428
|
-
const sweep = ccw ? 0 : 1;
|
|
437
|
+
const largeArc = sweepAngle > Math.PI ? 1 : 0;
|
|
429
438
|
this.currentPath.push(`A ${r} ${r} 0 ${largeArc} ${sweep} ${xe} ${ye}`);
|
|
430
439
|
}
|
|
431
440
|
}
|
|
@@ -723,6 +732,7 @@ function fromCanvas(css) {
|
|
|
723
732
|
if (typeof document === "undefined") return null;
|
|
724
733
|
if (!fallbackCtx) fallbackCtx = document.createElement("canvas").getContext("2d");
|
|
725
734
|
if (!fallbackCtx) return null;
|
|
735
|
+
fallbackCtx.clearRect(0, 0, 1, 1);
|
|
726
736
|
fallbackCtx.fillStyle = css;
|
|
727
737
|
fallbackCtx.fillRect(0, 0, 1, 1);
|
|
728
738
|
const d = fallbackCtx.getImageData(0, 0, 1, 1).data;
|
|
@@ -869,7 +879,9 @@ function grow(data, needed) {
|
|
|
869
879
|
return grown;
|
|
870
880
|
}
|
|
871
881
|
function createWebGLPointRenderer(canvas) {
|
|
872
|
-
const gl = canvas.getContext("webgl2"
|
|
882
|
+
const gl = canvas.getContext("webgl2", {
|
|
883
|
+
premultipliedAlpha: false
|
|
884
|
+
});
|
|
873
885
|
if (!gl) return null;
|
|
874
886
|
const pointProgram = link(gl, POINT_VERT, POINT_FRAG);
|
|
875
887
|
const rectProgram = link(gl, RECT_VERT, RECT_FRAG);
|
|
@@ -937,7 +949,9 @@ function createWebGLPointRenderer(canvas) {
|
|
|
937
949
|
gl.vertexAttribPointer(gATint, 4, gl.FLOAT, false, SPRITE_VERT_STRIDE, 16);
|
|
938
950
|
gl.bindVertexArray(null);
|
|
939
951
|
let texture = null;
|
|
952
|
+
let textureSource = null;
|
|
940
953
|
let msdfTexture = null;
|
|
954
|
+
let msdfSource = null;
|
|
941
955
|
let distanceRange = 4;
|
|
942
956
|
let pointData = new Float32Array(FLOATS_PER_POINT * 1024);
|
|
943
957
|
let pointCount = 0;
|
|
@@ -951,6 +965,22 @@ function createWebGLPointRenderer(canvas) {
|
|
|
951
965
|
let logicalH = 0;
|
|
952
966
|
let dpr = 1;
|
|
953
967
|
let destroyed = false;
|
|
968
|
+
const drawGlyphs = () => {
|
|
969
|
+
if (glyphCount === 0 || !msdfTexture) return;
|
|
970
|
+
const floats = glyphCount * VERTS_PER_SPRITE * FLOATS_PER_SPRITE_VERT;
|
|
971
|
+
gl.useProgram(msdfProgram);
|
|
972
|
+
gl.bindVertexArray(glyphVAO);
|
|
973
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, glyphBuffer);
|
|
974
|
+
gl.bufferData(gl.ARRAY_BUFFER, glyphData.subarray(0, floats), gl.DYNAMIC_DRAW);
|
|
975
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
976
|
+
gl.bindTexture(gl.TEXTURE_2D, msdfTexture);
|
|
977
|
+
gl.uniform1i(gUTex, 0);
|
|
978
|
+
gl.uniform2f(gURes, logicalW, logicalH);
|
|
979
|
+
gl.uniform1f(gURange, distanceRange);
|
|
980
|
+
gl.drawArrays(gl.TRIANGLES, 0, glyphCount * VERTS_PER_SPRITE);
|
|
981
|
+
gl.bindVertexArray(null);
|
|
982
|
+
glyphCount = 0;
|
|
983
|
+
};
|
|
954
984
|
return {
|
|
955
985
|
resize(width, height) {
|
|
956
986
|
logicalW = width;
|
|
@@ -967,8 +997,11 @@ function createWebGLPointRenderer(canvas) {
|
|
|
967
997
|
rectCount = 0;
|
|
968
998
|
spriteCount = 0;
|
|
969
999
|
glyphCount = 0;
|
|
1000
|
+
gl.clearColor(0, 0, 0, 0);
|
|
1001
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
970
1002
|
},
|
|
971
1003
|
setTexture(source) {
|
|
1004
|
+
if (source === textureSource && texture) return;
|
|
972
1005
|
if (!texture) {
|
|
973
1006
|
texture = gl.createTexture();
|
|
974
1007
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
@@ -980,6 +1013,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
980
1013
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
981
1014
|
}
|
|
982
1015
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
1016
|
+
textureSource = source;
|
|
983
1017
|
},
|
|
984
1018
|
addSprite(x, y, width, height, u0, v0, u1, v1, color = "#ffffff", alpha = 1, rotation = 0) {
|
|
985
1019
|
if (!texture) return;
|
|
@@ -1016,6 +1050,11 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1016
1050
|
spriteCount++;
|
|
1017
1051
|
},
|
|
1018
1052
|
setMSDFTexture(source, range) {
|
|
1053
|
+
if (source === msdfSource && msdfTexture) {
|
|
1054
|
+
distanceRange = range;
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
drawGlyphs();
|
|
1019
1058
|
distanceRange = range;
|
|
1020
1059
|
if (!msdfTexture) {
|
|
1021
1060
|
msdfTexture = gl.createTexture();
|
|
@@ -1028,6 +1067,7 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1028
1067
|
gl.bindTexture(gl.TEXTURE_2D, msdfTexture);
|
|
1029
1068
|
}
|
|
1030
1069
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
1070
|
+
msdfSource = source;
|
|
1031
1071
|
},
|
|
1032
1072
|
addGlyph(x, y, width, height, u0, v0, u1, v1, color = "#ffffff", alpha = 1, rotation = 0) {
|
|
1033
1073
|
if (!msdfTexture) return;
|
|
@@ -1105,8 +1145,6 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1105
1145
|
rectCount++;
|
|
1106
1146
|
},
|
|
1107
1147
|
flush() {
|
|
1108
|
-
gl.clearColor(0, 0, 0, 0);
|
|
1109
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1110
1148
|
if (rectCount > 0) {
|
|
1111
1149
|
const floats = rectCount * VERTS_PER_RECT * FLOATS_PER_RECT_VERT;
|
|
1112
1150
|
gl.useProgram(rectProgram);
|
|
@@ -1141,20 +1179,8 @@ function createWebGLPointRenderer(canvas) {
|
|
|
1141
1179
|
gl.uniform2f(sURes, logicalW, logicalH);
|
|
1142
1180
|
gl.drawArrays(gl.TRIANGLES, 0, spriteCount * VERTS_PER_SPRITE);
|
|
1143
1181
|
}
|
|
1144
|
-
if (glyphCount > 0 && msdfTexture) {
|
|
1145
|
-
const floats = glyphCount * VERTS_PER_SPRITE * FLOATS_PER_SPRITE_VERT;
|
|
1146
|
-
gl.useProgram(msdfProgram);
|
|
1147
|
-
gl.bindVertexArray(glyphVAO);
|
|
1148
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, glyphBuffer);
|
|
1149
|
-
gl.bufferData(gl.ARRAY_BUFFER, glyphData.subarray(0, floats), gl.DYNAMIC_DRAW);
|
|
1150
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
1151
|
-
gl.bindTexture(gl.TEXTURE_2D, msdfTexture);
|
|
1152
|
-
gl.uniform1i(gUTex, 0);
|
|
1153
|
-
gl.uniform2f(gURes, logicalW, logicalH);
|
|
1154
|
-
gl.uniform1f(gURange, distanceRange);
|
|
1155
|
-
gl.drawArrays(gl.TRIANGLES, 0, glyphCount * VERTS_PER_SPRITE);
|
|
1156
|
-
}
|
|
1157
1182
|
gl.bindVertexArray(null);
|
|
1183
|
+
drawGlyphs();
|
|
1158
1184
|
},
|
|
1159
1185
|
destroy() {
|
|
1160
1186
|
if (destroyed) return;
|