textmode.js 0.1.4-beta.1 → 0.1.4-beta.2
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/textmode.esm.js +351 -156
- package/dist/textmode.esm.min.js +382 -187
- package/dist/textmode.umd.js +6 -6
- package/dist/textmode.umd.min.js +6 -6
- package/dist/types/Textmode.d.ts +14 -0
- package/dist/types/rendering/webgl/Framebuffer.d.ts +9 -0
- package/dist/types/rendering/webgl/Renderer.d.ts +9 -0
- package/dist/types/rendering/webgl/Shader.d.ts +9 -0
- package/dist/types/textmode/Canvas.d.ts +9 -0
- package/dist/types/textmode/ConversionPipeline.d.ts +9 -0
- package/dist/types/textmode/Grid.d.ts +9 -0
- package/dist/types/textmode/Textmodifier.d.ts +32 -0
- package/dist/types/textmode/converters/Converter.d.ts +9 -0
- package/dist/types/textmode/font/TextmodeFont.d.ts +9 -0
- package/package.json +1 -1
package/dist/textmode.esm.min.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var se = Object.defineProperty;
|
|
2
|
-
var ae = (
|
|
3
|
-
var o = (
|
|
2
|
+
var ae = (h, e, t) => e in h ? se(h, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[e] = t;
|
|
3
|
+
var o = (h, e, t) => ae(h, typeof e != "symbol" ? e + "" : e, t);
|
|
4
4
|
class F extends Error {
|
|
5
5
|
constructor(t, r, i = {}) {
|
|
6
6
|
const s = F.createFormattedMessage(t, i);
|
|
@@ -46,7 +46,7 @@ class F extends Error {
|
|
|
46
46
|
return String(t);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
var ne = /* @__PURE__ */ ((
|
|
49
|
+
var ne = /* @__PURE__ */ ((h) => (h[h.SILENT = 0] = "SILENT", h[h.WARNING = 1] = "WARNING", h[h.ERROR = 2] = "ERROR", h[h.THROW = 3] = "THROW", h))(ne || {});
|
|
50
50
|
const E = class E {
|
|
51
51
|
constructor() {
|
|
52
52
|
o(this, "_options", {
|
|
@@ -104,8 +104,8 @@ const E = class E {
|
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
106
|
o(E, "_instance", null);
|
|
107
|
-
let
|
|
108
|
-
const x =
|
|
107
|
+
let $ = E;
|
|
108
|
+
const x = $.getInstance();
|
|
109
109
|
class oe {
|
|
110
110
|
constructor(e, t, r = t, i = {}) {
|
|
111
111
|
o(this, "gl");
|
|
@@ -201,6 +201,20 @@ class oe {
|
|
|
201
201
|
return s.bindFramebuffer(s.FRAMEBUFFER, this._framebuffer), s.readPixels(e, t, r, i, s.RGBA, s.UNSIGNED_BYTE, a), s.bindFramebuffer(s.FRAMEBUFFER, n), a;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Dispose of WebGL resources used by this framebuffer.
|
|
206
|
+
* This method is idempotent and safe to call multiple times.
|
|
207
|
+
*/
|
|
208
|
+
dispose() {
|
|
209
|
+
const { gl: e } = this;
|
|
210
|
+
this._framebuffer && (e.deleteFramebuffer(this._framebuffer), this._framebuffer = null), this._texture && (e.deleteTexture(this._texture), this._texture = null), this._pixels = null;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if this framebuffer has been disposed
|
|
214
|
+
*/
|
|
215
|
+
get isDisposed() {
|
|
216
|
+
return this._framebuffer === null || this._texture === null;
|
|
217
|
+
}
|
|
204
218
|
get framebuffer() {
|
|
205
219
|
return this._framebuffer;
|
|
206
220
|
}
|
|
@@ -225,7 +239,7 @@ class Q {
|
|
|
225
239
|
this.gl = e, this.x = t, this.y = r;
|
|
226
240
|
}
|
|
227
241
|
}
|
|
228
|
-
class
|
|
242
|
+
class A {
|
|
229
243
|
constructor(e, t, r, i, s) {
|
|
230
244
|
/** The WebGL rendering context */
|
|
231
245
|
o(this, "gl");
|
|
@@ -236,12 +250,12 @@ class M {
|
|
|
236
250
|
/** Bytes per vertex: depends on position format (vec2 vs vec3) */
|
|
237
251
|
o(this, "bytesPerVertex");
|
|
238
252
|
this.gl = e, this.bytesPerVertex = 16;
|
|
239
|
-
const a = e.getParameter(e.VIEWPORT), n = a[2],
|
|
253
|
+
const a = e.getParameter(e.VIEWPORT), n = a[2], l = a[3], c = e.getParameter(e.FRAMEBUFFER_BINDING) !== null, u = t / n * 2 - 1, d = (t + i) / n * 2 - 1;
|
|
240
254
|
let f, g;
|
|
241
|
-
c ? (f = r /
|
|
242
|
-
let _,
|
|
243
|
-
|
|
244
|
-
const v = this.generateVertices(_,
|
|
255
|
+
c ? (f = r / l * 2 - 1, g = (r + s) / l * 2 - 1) : (f = 1 - r / l * 2, g = 1 - (r + s) / l * 2);
|
|
256
|
+
let p, _, b, C;
|
|
257
|
+
p = u, b = d, _ = f, C = g;
|
|
258
|
+
const v = this.generateVertices(p, _, b, C);
|
|
245
259
|
this.vertexBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer), e.bufferData(e.ARRAY_BUFFER, v, e.STATIC_DRAW);
|
|
246
260
|
}
|
|
247
261
|
/**
|
|
@@ -292,7 +306,7 @@ class M {
|
|
|
292
306
|
this.gl.enableVertexAttribArray(t), this.gl.vertexAttribPointer(t, 2, this.gl.FLOAT, !1, this.bytesPerVertex, 0), this.gl.enableVertexAttribArray(r), this.gl.vertexAttribPointer(r, 2, this.gl.FLOAT, !1, this.bytesPerVertex, 8), this.gl.drawArrays(this.gl.TRIANGLES, 0, this.vertexCount), this.gl.disableVertexAttribArray(t), this.gl.disableVertexAttribArray(r);
|
|
293
307
|
}
|
|
294
308
|
}
|
|
295
|
-
class
|
|
309
|
+
class he extends Q {
|
|
296
310
|
constructor(t, r, i, s, a) {
|
|
297
311
|
super(t, r, i);
|
|
298
312
|
o(this, "width");
|
|
@@ -303,7 +317,7 @@ class le extends Q {
|
|
|
303
317
|
* Render the filled rectangle using the existing Rectangle geometry.
|
|
304
318
|
*/
|
|
305
319
|
renderFill() {
|
|
306
|
-
new
|
|
320
|
+
new A(this.gl, this.x, this.y, this.width, this.height).render();
|
|
307
321
|
}
|
|
308
322
|
/**
|
|
309
323
|
* Render the stroke rectangle as four separate Rectangle instances for each edge.
|
|
@@ -312,11 +326,11 @@ class le extends Q {
|
|
|
312
326
|
*/
|
|
313
327
|
renderStroke(t) {
|
|
314
328
|
if (t <= 0) return;
|
|
315
|
-
const r = new
|
|
329
|
+
const r = new A(this.gl, this.x, this.y, this.width, t), i = new A(this.gl, this.x + this.width - t, this.y, t, this.height), s = new A(this.gl, this.x, this.y + this.height - t, this.width, t), a = new A(this.gl, this.x, this.y, t, this.height);
|
|
316
330
|
r.render(), i.render(), s.render(), a.render();
|
|
317
331
|
}
|
|
318
332
|
}
|
|
319
|
-
class
|
|
333
|
+
class le {
|
|
320
334
|
constructor(e, t, r, i, s, a) {
|
|
321
335
|
/** The WebGL rendering context */
|
|
322
336
|
o(this, "gl");
|
|
@@ -327,15 +341,15 @@ class he {
|
|
|
327
341
|
/** Bytes per vertex: vec2+vec2 = 16 bytes */
|
|
328
342
|
o(this, "bytesPerVertex");
|
|
329
343
|
this.gl = e, this.bytesPerVertex = 16;
|
|
330
|
-
const n = e.getParameter(e.VIEWPORT),
|
|
344
|
+
const n = e.getParameter(e.VIEWPORT), l = n[2], c = n[3], u = e.getParameter(e.FRAMEBUFFER_BINDING) !== null, d = i - t, f = s - r, g = Math.sqrt(d * d + f * f);
|
|
331
345
|
if (g === 0) {
|
|
332
346
|
const ie = this.generateVertices(0, 0, 0, 0);
|
|
333
347
|
this.vertexBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer), e.bufferData(e.ARRAY_BUFFER, ie, e.STATIC_DRAW);
|
|
334
348
|
return;
|
|
335
349
|
}
|
|
336
|
-
const
|
|
350
|
+
const p = d / g, b = -(f / g), C = p, v = a / 2, w = t + b * v, D = r + C * v, R = t - b * v, y = r - C * v, P = i + b * v, M = s + C * v, Z = i - b * v, W = s - C * v, J = w / l * 2 - 1, K = R / l * 2 - 1, ee = P / l * 2 - 1, te = Z / l * 2 - 1;
|
|
337
351
|
let B, G, V, k;
|
|
338
|
-
u ? (B =
|
|
352
|
+
u ? (B = D / c * 2 - 1, G = y / c * 2 - 1, V = M / c * 2 - 1, k = W / c * 2 - 1) : (B = 1 - D / c * 2, G = 1 - y / c * 2, V = 1 - M / c * 2, k = 1 - W / c * 2);
|
|
339
353
|
const re = this.generateLineVertices(
|
|
340
354
|
J,
|
|
341
355
|
B,
|
|
@@ -391,7 +405,7 @@ class he {
|
|
|
391
405
|
* Uses the four corners calculated based on line direction and thickness
|
|
392
406
|
* @private
|
|
393
407
|
*/
|
|
394
|
-
generateLineVertices(e, t, r, i, s, a, n,
|
|
408
|
+
generateLineVertices(e, t, r, i, s, a, n, l) {
|
|
395
409
|
return new Float32Array([
|
|
396
410
|
e,
|
|
397
411
|
t,
|
|
@@ -414,7 +428,7 @@ class he {
|
|
|
414
428
|
1,
|
|
415
429
|
// corner2 (start - perpendicular)
|
|
416
430
|
n,
|
|
417
|
-
|
|
431
|
+
l,
|
|
418
432
|
1,
|
|
419
433
|
1,
|
|
420
434
|
// corner4 (end - perpendicular)
|
|
@@ -454,7 +468,7 @@ class ce extends Q {
|
|
|
454
468
|
*/
|
|
455
469
|
renderStroke(t) {
|
|
456
470
|
if (t <= 0) return;
|
|
457
|
-
new
|
|
471
|
+
new le(this.gl, this.x, this.y, this.x2, this.y2, t).render();
|
|
458
472
|
}
|
|
459
473
|
}
|
|
460
474
|
class T {
|
|
@@ -590,6 +604,19 @@ class T {
|
|
|
590
604
|
get glProgram() {
|
|
591
605
|
return this.program;
|
|
592
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* Dispose of WebGL resources used by this shader.
|
|
609
|
+
* This method is idempotent and safe to call multiple times.
|
|
610
|
+
*/
|
|
611
|
+
dispose() {
|
|
612
|
+
this.program && (this.gl.deleteProgram(this.program), this.program = null), this.uniformLocations.clear(), this.attributeLocations.clear(), this.textureUnitCounter = 0;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Check if this shader has been disposed
|
|
616
|
+
*/
|
|
617
|
+
get isDisposed() {
|
|
618
|
+
return this.program === null;
|
|
619
|
+
}
|
|
593
620
|
/**
|
|
594
621
|
* Reset texture unit counter (useful when starting a new frame)
|
|
595
622
|
*/
|
|
@@ -729,18 +756,18 @@ class fe {
|
|
|
729
756
|
* Draw a rectangle with the current fill and/or stroke settings
|
|
730
757
|
*/
|
|
731
758
|
rect(e, t, r, i) {
|
|
732
|
-
const s = new
|
|
759
|
+
const s = new he(this.gl, e, t, r, i);
|
|
733
760
|
if (this.currentShader !== null) {
|
|
734
761
|
if (this.currentRotation !== 0) {
|
|
735
|
-
const { centerX: d, centerY: f, radians: g, aspectRatio:
|
|
736
|
-
this.setUniform("u_rotation", g), this.setUniform("u_center", [d, f]), this.setUniform("u_aspectRatio",
|
|
762
|
+
const { centerX: d, centerY: f, radians: g, aspectRatio: p } = this.calculateRotationParams(e, t, r, i);
|
|
763
|
+
this.setUniform("u_rotation", g), this.setUniform("u_center", [d, f]), this.setUniform("u_aspectRatio", p);
|
|
737
764
|
} else
|
|
738
765
|
this.setUniform("u_rotation", 0), this.setUniform("u_center", [0, 0]), this.setUniform("u_aspectRatio", 1);
|
|
739
766
|
s.renderFill(), this.currentShader = null;
|
|
740
767
|
return;
|
|
741
768
|
}
|
|
742
|
-
const a = this.solidColorShader, { centerX: n, centerY:
|
|
743
|
-
this.fillMode && (this.shader(a), this.setUniform("u_color", this.currentFillColor), this.setUniform("u_rotation", c), this.setUniform("u_center", [n,
|
|
769
|
+
const a = this.solidColorShader, { centerX: n, centerY: l, radians: c, aspectRatio: u } = this.calculateRotationParams(e, t, r, i);
|
|
770
|
+
this.fillMode && (this.shader(a), this.setUniform("u_color", this.currentFillColor), this.setUniform("u_rotation", c), this.setUniform("u_center", [n, l]), this.setUniform("u_aspectRatio", u), s.renderFill()), this.strokeMode && (this.shader(a), this.setUniform("u_color", this.currentStrokeColor), this.setUniform("u_rotation", c), this.setUniform("u_center", [n, l]), this.setUniform("u_aspectRatio", u), s.renderStroke(this.currentStrokeWeight)), this.currentShader = null;
|
|
744
771
|
}
|
|
745
772
|
/**
|
|
746
773
|
* Draw a line from (x1, y1) to (x2, y2) with the current stroke settings.
|
|
@@ -755,25 +782,25 @@ class fe {
|
|
|
755
782
|
const s = new ce(this.gl, e, t, r, i);
|
|
756
783
|
if (this.currentShader !== null) {
|
|
757
784
|
if (this.currentRotation !== 0) {
|
|
758
|
-
const
|
|
759
|
-
this.setUniform("u_rotation", R), this.setUniform("u_center", [w,
|
|
785
|
+
const _ = (e + r) / 2, b = (t + i) / 2, C = Math.abs(r - e), v = Math.abs(i - t), { centerX: w, centerY: D, radians: R, aspectRatio: y } = this.calculateRotationParams(_ - C / 2, b - v / 2, C, v);
|
|
786
|
+
this.setUniform("u_rotation", R), this.setUniform("u_center", [w, D]), this.setUniform("u_aspectRatio", y);
|
|
760
787
|
} else
|
|
761
788
|
this.setUniform("u_rotation", 0), this.setUniform("u_center", [0, 0]), this.setUniform("u_aspectRatio", 1);
|
|
762
789
|
s.renderStroke(this.currentStrokeWeight), this.currentShader = null;
|
|
763
790
|
return;
|
|
764
791
|
}
|
|
765
|
-
const a = this.solidColorShader, n = (e + r) / 2,
|
|
766
|
-
this.shader(a), this.setUniform("u_color", this.currentStrokeColor), this.setUniform("u_rotation", g), this.setUniform("u_center", [d, f]), this.setUniform("u_aspectRatio",
|
|
792
|
+
const a = this.solidColorShader, n = (e + r) / 2, l = (t + i) / 2, c = Math.abs(r - e), u = Math.abs(i - t), { centerX: d, centerY: f, radians: g, aspectRatio: p } = this.calculateRotationParams(n - c / 2, l - u / 2, c, u);
|
|
793
|
+
this.shader(a), this.setUniform("u_color", this.currentStrokeColor), this.setUniform("u_rotation", g), this.setUniform("u_center", [d, f]), this.setUniform("u_aspectRatio", p), s.renderStroke(this.currentStrokeWeight), this.currentShader = null;
|
|
767
794
|
}
|
|
768
795
|
/**
|
|
769
796
|
* Calculate rotation parameters for built-in shaders (NDC coordinates)
|
|
770
797
|
*/
|
|
771
798
|
calculateRotationParams(e, t, r, i) {
|
|
772
|
-
const s = this.gl.getParameter(this.gl.VIEWPORT), a = s[2], n = s[3],
|
|
799
|
+
const s = this.gl.getParameter(this.gl.VIEWPORT), a = s[2], n = s[3], l = a / n, c = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING) !== null, u = e + r / 2, d = t + i / 2, f = u / a * 2 - 1;
|
|
773
800
|
let g;
|
|
774
801
|
c ? g = d / n * 2 - 1 : g = 1 - d / n * 2;
|
|
775
|
-
const
|
|
776
|
-
return { centerX: f, centerY: g, radians:
|
|
802
|
+
const p = this.currentRotation * Math.PI / 180;
|
|
803
|
+
return { centerX: f, centerY: g, radians: p, aspectRatio: l };
|
|
777
804
|
}
|
|
778
805
|
/**
|
|
779
806
|
* Create a new framebuffer
|
|
@@ -805,23 +832,36 @@ class fe {
|
|
|
805
832
|
get context() {
|
|
806
833
|
return this.gl;
|
|
807
834
|
}
|
|
835
|
+
/**
|
|
836
|
+
* Dispose of all WebGL resources managed by this renderer.
|
|
837
|
+
* This method is idempotent and safe to call multiple times.
|
|
838
|
+
*/
|
|
839
|
+
dispose() {
|
|
840
|
+
this.imageShader && !this.imageShader.isDisposed && this.imageShader.dispose(), this.solidColorShader && !this.solidColorShader.isDisposed && this.solidColorShader.dispose(), this.imageShader = null, this.solidColorShader = null, this.currentShader = null, this.stateStack = [];
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Check if this renderer has been disposed
|
|
844
|
+
*/
|
|
845
|
+
get isDisposed() {
|
|
846
|
+
return this.imageShader === null || this.solidColorShader === null;
|
|
847
|
+
}
|
|
808
848
|
/**
|
|
809
849
|
* Render a framebuffer at a specific position with optional scaling
|
|
810
850
|
*/
|
|
811
851
|
image(e, t, r, i, s) {
|
|
812
852
|
this.shader(this.imageShader), this.setUniform("u_texture", e.texture);
|
|
813
|
-
const { centerX: a, centerY: n, radians:
|
|
853
|
+
const { centerX: a, centerY: n, radians: l, aspectRatio: c } = this.calculateRotationParams(
|
|
814
854
|
t,
|
|
815
855
|
r,
|
|
816
856
|
i ?? e.width,
|
|
817
857
|
s ?? e.height
|
|
818
858
|
);
|
|
819
|
-
this.setUniform("u_rotation",
|
|
859
|
+
this.setUniform("u_rotation", l), this.setUniform("u_center", [a, n]), this.setUniform("u_aspectRatio", c), this.rect(t, r, i ?? e.width, s ?? e.height);
|
|
820
860
|
}
|
|
821
861
|
}
|
|
822
862
|
var m = {};
|
|
823
|
-
m.parse = function(
|
|
824
|
-
var e = function(s, a, n,
|
|
863
|
+
m.parse = function(h) {
|
|
864
|
+
var e = function(s, a, n, l) {
|
|
825
865
|
var c = m.T, u = {
|
|
826
866
|
cmap: c.cmap,
|
|
827
867
|
head: c.head,
|
|
@@ -834,115 +874,115 @@ m.parse = function(l) {
|
|
|
834
874
|
for (var f in u) {
|
|
835
875
|
var g = m.findTable(s, f, n);
|
|
836
876
|
if (g) {
|
|
837
|
-
var
|
|
838
|
-
|
|
877
|
+
var p = g[0], _ = l[p];
|
|
878
|
+
_ == null && (_ = u[f].parseTab(s, p, g[1], d)), d[f] = l[p] = _;
|
|
839
879
|
}
|
|
840
880
|
}
|
|
841
881
|
return d;
|
|
842
|
-
}, t = new Uint8Array(
|
|
882
|
+
}, t = new Uint8Array(h), r = {}, i = e(t, 0, 0, r);
|
|
843
883
|
return [i];
|
|
844
884
|
};
|
|
845
|
-
m.findTable = function(
|
|
846
|
-
for (var r = m.B, i = r.readUshort(
|
|
847
|
-
var n = r.readASCII(
|
|
848
|
-
r.readUint(
|
|
849
|
-
var
|
|
850
|
-
if (n == e) return [
|
|
885
|
+
m.findTable = function(h, e, t) {
|
|
886
|
+
for (var r = m.B, i = r.readUshort(h, t + 4), s = t + 12, a = 0; a < i; a++) {
|
|
887
|
+
var n = r.readASCII(h, s, 4);
|
|
888
|
+
r.readUint(h, s + 4);
|
|
889
|
+
var l = r.readUint(h, s + 8), c = r.readUint(h, s + 12);
|
|
890
|
+
if (n == e) return [l, c];
|
|
851
891
|
s += 16;
|
|
852
892
|
}
|
|
853
893
|
return null;
|
|
854
894
|
};
|
|
855
895
|
m.T = {};
|
|
856
896
|
m.B = {
|
|
857
|
-
readShort: function(
|
|
897
|
+
readShort: function(h, e) {
|
|
858
898
|
var t = m.B.t.uint16;
|
|
859
|
-
return t[0] =
|
|
899
|
+
return t[0] = h[e] << 8 | h[e + 1], m.B.t.int16[0];
|
|
860
900
|
},
|
|
861
|
-
readUshort: function(
|
|
862
|
-
return
|
|
901
|
+
readUshort: function(h, e) {
|
|
902
|
+
return h[e] << 8 | h[e + 1];
|
|
863
903
|
},
|
|
864
|
-
readUshorts: function(
|
|
904
|
+
readUshorts: function(h, e, t) {
|
|
865
905
|
for (var r = [], i = 0; i < t; i++)
|
|
866
|
-
r.push(m.B.readUshort(
|
|
906
|
+
r.push(m.B.readUshort(h, e + i * 2));
|
|
867
907
|
return r;
|
|
868
908
|
},
|
|
869
|
-
readUint: function(
|
|
909
|
+
readUint: function(h, e) {
|
|
870
910
|
var t = m.B.t.uint8;
|
|
871
|
-
return t[3] =
|
|
911
|
+
return t[3] = h[e], t[2] = h[e + 1], t[1] = h[e + 2], t[0] = h[e + 3], m.B.t.uint32[0];
|
|
872
912
|
},
|
|
873
|
-
readASCII: function(
|
|
874
|
-
for (var r = "", i = 0; i < t; i++) r += String.fromCharCode(
|
|
913
|
+
readASCII: function(h, e, t) {
|
|
914
|
+
for (var r = "", i = 0; i < t; i++) r += String.fromCharCode(h[e + i]);
|
|
875
915
|
return r;
|
|
876
916
|
},
|
|
877
917
|
// Simplified typed array buffer - only what's needed
|
|
878
918
|
t: function() {
|
|
879
|
-
var
|
|
919
|
+
var h = new ArrayBuffer(8);
|
|
880
920
|
return {
|
|
881
|
-
uint8: new Uint8Array(
|
|
882
|
-
int16: new Int16Array(
|
|
883
|
-
uint16: new Uint16Array(
|
|
884
|
-
uint32: new Uint32Array(
|
|
921
|
+
uint8: new Uint8Array(h),
|
|
922
|
+
int16: new Int16Array(h),
|
|
923
|
+
uint16: new Uint16Array(h),
|
|
924
|
+
uint32: new Uint32Array(h)
|
|
885
925
|
};
|
|
886
926
|
}()
|
|
887
927
|
};
|
|
888
928
|
m.T.cmap = {
|
|
889
|
-
parseTab: function(
|
|
929
|
+
parseTab: function(h, e, t) {
|
|
890
930
|
var r = { tables: [], ids: {}, off: e };
|
|
891
|
-
|
|
931
|
+
h = new Uint8Array(h.buffer, e, t), e = 0;
|
|
892
932
|
var i = m.B, s = i.readUshort, a = m.T.cmap;
|
|
893
|
-
s(
|
|
894
|
-
var n = s(
|
|
933
|
+
s(h, e), e += 2;
|
|
934
|
+
var n = s(h, e);
|
|
895
935
|
e += 2;
|
|
896
|
-
for (var
|
|
897
|
-
var u = s(
|
|
936
|
+
for (var l = [], c = 0; c < n; c++) {
|
|
937
|
+
var u = s(h, e);
|
|
898
938
|
e += 2;
|
|
899
|
-
var d = s(
|
|
939
|
+
var d = s(h, e);
|
|
900
940
|
e += 2;
|
|
901
|
-
var f = i.readUint(
|
|
941
|
+
var f = i.readUint(h, e);
|
|
902
942
|
e += 4;
|
|
903
|
-
var g = "p" + u + "e" + d,
|
|
904
|
-
if (
|
|
905
|
-
|
|
906
|
-
var
|
|
907
|
-
|
|
908
|
-
var
|
|
909
|
-
|
|
943
|
+
var g = "p" + u + "e" + d, p = l.indexOf(f);
|
|
944
|
+
if (p == -1) {
|
|
945
|
+
p = r.tables.length;
|
|
946
|
+
var _ = {};
|
|
947
|
+
l.push(f);
|
|
948
|
+
var b = _.format = s(h, f);
|
|
949
|
+
b == 4 ? _ = a.parse4(h, f, _) : b == 12 && (_ = a.parse12(h, f, _)), r.tables.push(_);
|
|
910
950
|
}
|
|
911
|
-
r.ids[g] != null && console.log("multiple tables for one platform+encoding: " + g), r.ids[g] =
|
|
951
|
+
r.ids[g] != null && console.log("multiple tables for one platform+encoding: " + g), r.ids[g] = p;
|
|
912
952
|
}
|
|
913
953
|
return r;
|
|
914
954
|
},
|
|
915
|
-
parse4: function(
|
|
955
|
+
parse4: function(h, e, t) {
|
|
916
956
|
var r = m.B, i = r.readUshort, s = r.readUshorts, a = e;
|
|
917
957
|
e += 2;
|
|
918
|
-
var n = i(
|
|
919
|
-
e += 2, i(
|
|
920
|
-
var
|
|
958
|
+
var n = i(h, e);
|
|
959
|
+
e += 2, i(h, e), e += 2;
|
|
960
|
+
var l = i(h, e);
|
|
921
961
|
e += 2;
|
|
922
|
-
var c =
|
|
923
|
-
t.searchRange = i(
|
|
962
|
+
var c = l >>> 1;
|
|
963
|
+
t.searchRange = i(h, e), e += 2, t.entrySelector = i(h, e), e += 2, t.rangeShift = i(h, e), e += 2, t.endCount = s(h, e, c), e += c * 2, e += 2, t.startCount = s(h, e, c), e += c * 2, t.idDelta = [];
|
|
924
964
|
for (var u = 0; u < c; u++)
|
|
925
|
-
t.idDelta.push(r.readShort(
|
|
926
|
-
return t.idRangeOffset = s(
|
|
965
|
+
t.idDelta.push(r.readShort(h, e)), e += 2;
|
|
966
|
+
return t.idRangeOffset = s(h, e, c), e += c * 2, t.glyphIdArray = s(h, e, a + n - e >> 1), t;
|
|
927
967
|
},
|
|
928
|
-
parse12: function(
|
|
968
|
+
parse12: function(h, e, t) {
|
|
929
969
|
var r = m.B, i = r.readUint;
|
|
930
|
-
e += 4, i(
|
|
931
|
-
var s = i(
|
|
970
|
+
e += 4, i(h, e), e += 4, i(h, e), e += 4;
|
|
971
|
+
var s = i(h, e) * 3;
|
|
932
972
|
e += 4;
|
|
933
973
|
for (var a = t.groups = new Uint32Array(s), n = 0; n < s; n += 3)
|
|
934
|
-
a[n] = i(
|
|
974
|
+
a[n] = i(h, e + (n << 2)), a[n + 1] = i(h, e + (n << 2) + 4), a[n + 2] = i(h, e + (n << 2) + 8);
|
|
935
975
|
return t;
|
|
936
976
|
}
|
|
937
977
|
};
|
|
938
978
|
m.T.head = {
|
|
939
|
-
parseTab: function(
|
|
979
|
+
parseTab: function(h, e, t) {
|
|
940
980
|
var r = m.B, i = {};
|
|
941
|
-
return e += 18, i.unitsPerEm = r.readUshort(
|
|
981
|
+
return e += 18, i.unitsPerEm = r.readUshort(h, e), e += 2, e += 16, i.xMin = r.readShort(h, e), e += 2, i.yMin = r.readShort(h, e), e += 2, i.xMax = r.readShort(h, e), e += 2, i.yMax = r.readShort(h, e), e += 2, e += 6, i.indexToLocFormat = r.readShort(h, e), i;
|
|
942
982
|
}
|
|
943
983
|
};
|
|
944
984
|
m.T.hhea = {
|
|
945
|
-
parseTab: function(
|
|
985
|
+
parseTab: function(h, e, t) {
|
|
946
986
|
var r = m.B, i = {};
|
|
947
987
|
e += 4;
|
|
948
988
|
for (var s = [
|
|
@@ -963,52 +1003,52 @@ m.T.hhea = {
|
|
|
963
1003
|
"metricDataFormat",
|
|
964
1004
|
"numberOfHMetrics"
|
|
965
1005
|
], a = 0; a < s.length; a++) {
|
|
966
|
-
var n = s[a],
|
|
967
|
-
i[n] = h
|
|
1006
|
+
var n = s[a], l = n == "advanceWidthMax" || n == "numberOfHMetrics" ? r.readUshort : r.readShort;
|
|
1007
|
+
i[n] = l(h, e + a * 2);
|
|
968
1008
|
}
|
|
969
1009
|
return i;
|
|
970
1010
|
}
|
|
971
1011
|
};
|
|
972
1012
|
m.T.hmtx = {
|
|
973
|
-
parseTab: function(
|
|
974
|
-
for (var i = m.B, s = [], a = [], n = r.maxp.numGlyphs,
|
|
975
|
-
c = i.readUshort(
|
|
1013
|
+
parseTab: function(h, e, t, r) {
|
|
1014
|
+
for (var i = m.B, s = [], a = [], n = r.maxp.numGlyphs, l = r.hhea.numberOfHMetrics, c = 0, u = 0, d = 0; d < l; )
|
|
1015
|
+
c = i.readUshort(h, e + (d << 2)), u = i.readShort(h, e + (d << 2) + 2), s.push(c), a.push(u), d++;
|
|
976
1016
|
for (; d < n; )
|
|
977
1017
|
s.push(c), a.push(u), d++;
|
|
978
1018
|
return { aWidth: s, lsBearing: a };
|
|
979
1019
|
}
|
|
980
1020
|
};
|
|
981
1021
|
m.T.maxp = {
|
|
982
|
-
parseTab: function(
|
|
1022
|
+
parseTab: function(h, e, t) {
|
|
983
1023
|
var r = m.B, i = r.readUshort, s = {};
|
|
984
|
-
return r.readUint(
|
|
1024
|
+
return r.readUint(h, e), e += 4, s.numGlyphs = i(h, e), e += 2, s;
|
|
985
1025
|
}
|
|
986
1026
|
};
|
|
987
1027
|
m.T.loca = {
|
|
988
|
-
parseTab: function(
|
|
1028
|
+
parseTab: function(h, e, t, r) {
|
|
989
1029
|
var i = m.B, s = [], a = r.head.indexToLocFormat, n = r.maxp.numGlyphs + 1;
|
|
990
|
-
if (a == 0) for (var
|
|
991
|
-
if (a == 1) for (var
|
|
1030
|
+
if (a == 0) for (var l = 0; l < n; l++) s.push(i.readUshort(h, e + (l << 1)) << 1);
|
|
1031
|
+
if (a == 1) for (var l = 0; l < n; l++) s.push(i.readUint(h, e + (l << 2)));
|
|
992
1032
|
return s;
|
|
993
1033
|
}
|
|
994
1034
|
};
|
|
995
1035
|
m.T.glyf = {
|
|
996
|
-
parseTab: function(
|
|
1036
|
+
parseTab: function(h, e, t, r) {
|
|
997
1037
|
for (var i = [], s = r.maxp.numGlyphs, a = 0; a < s; a++) i.push(null);
|
|
998
1038
|
return i;
|
|
999
1039
|
},
|
|
1000
|
-
_parseGlyf: function(
|
|
1001
|
-
var t = m.B, r =
|
|
1040
|
+
_parseGlyf: function(h, e) {
|
|
1041
|
+
var t = m.B, r = h._data, i = h.loca;
|
|
1002
1042
|
if (i[e] == i[e + 1]) return null;
|
|
1003
|
-
var s = m.findTable(r, "glyf",
|
|
1043
|
+
var s = m.findTable(r, "glyf", h._offset)[0] + i[e], a = {};
|
|
1004
1044
|
if (a.noc = t.readShort(r, s), s += 2, a.xMin = t.readShort(r, s), s += 2, a.yMin = t.readShort(r, s), s += 2, a.xMax = t.readShort(r, s), s += 2, a.yMax = t.readShort(r, s), s += 2, a.xMin >= a.xMax || a.yMin >= a.yMax) return null;
|
|
1005
1045
|
if (a.noc > 0) {
|
|
1006
1046
|
a.endPts = [];
|
|
1007
1047
|
for (var n = 0; n < a.noc; n++)
|
|
1008
1048
|
a.endPts.push(t.readUshort(r, s)), s += 2;
|
|
1009
|
-
var
|
|
1010
|
-
if (s += 2, r.length - s <
|
|
1011
|
-
s +=
|
|
1049
|
+
var l = t.readUshort(r, s);
|
|
1050
|
+
if (s += 2, r.length - s < l) return null;
|
|
1051
|
+
s += l;
|
|
1012
1052
|
var c = a.endPts[a.noc - 1] + 1;
|
|
1013
1053
|
a.flags = [];
|
|
1014
1054
|
for (var n = 0; n < c; n++) {
|
|
@@ -1022,16 +1062,16 @@ m.T.glyf = {
|
|
|
1022
1062
|
}
|
|
1023
1063
|
a.xs = [];
|
|
1024
1064
|
for (var n = 0; n < c; n++) {
|
|
1025
|
-
var g = (a.flags[n] & 2) != 0,
|
|
1026
|
-
g ? (a.xs.push(
|
|
1065
|
+
var g = (a.flags[n] & 2) != 0, p = (a.flags[n] & 16) != 0;
|
|
1066
|
+
g ? (a.xs.push(p ? r[s] : -r[s]), s++) : p ? a.xs.push(0) : (a.xs.push(t.readShort(r, s)), s += 2);
|
|
1027
1067
|
}
|
|
1028
1068
|
a.ys = [];
|
|
1029
1069
|
for (var n = 0; n < c; n++) {
|
|
1030
|
-
var g = (a.flags[n] & 4) != 0,
|
|
1031
|
-
g ? (a.ys.push(
|
|
1070
|
+
var g = (a.flags[n] & 4) != 0, p = (a.flags[n] & 32) != 0;
|
|
1071
|
+
g ? (a.ys.push(p ? r[s] : -r[s]), s++) : p ? a.ys.push(0) : (a.ys.push(t.readShort(r, s)), s += 2);
|
|
1032
1072
|
}
|
|
1033
|
-
for (var
|
|
1034
|
-
|
|
1073
|
+
for (var _ = 0, b = 0, n = 0; n < c; n++)
|
|
1074
|
+
_ += a.xs[n], b += a.ys[n], a.xs[n] = _, a.ys[n] = b;
|
|
1035
1075
|
} else
|
|
1036
1076
|
a.parts = [];
|
|
1037
1077
|
return a;
|
|
@@ -1071,8 +1111,8 @@ class me {
|
|
|
1071
1111
|
if (!(i === 65535 && s === 65535)) {
|
|
1072
1112
|
for (let a = i; a <= s; a++)
|
|
1073
1113
|
if (this._calculateGlyphIndexFormat4(e, a, r) > 0) {
|
|
1074
|
-
const
|
|
1075
|
-
t.push(
|
|
1114
|
+
const l = String.fromCodePoint(a);
|
|
1115
|
+
t.push(l);
|
|
1076
1116
|
}
|
|
1077
1117
|
}
|
|
1078
1118
|
}
|
|
@@ -1155,9 +1195,9 @@ class ge {
|
|
|
1155
1195
|
* @returns Object containing framebuffer, columns, and rows
|
|
1156
1196
|
*/
|
|
1157
1197
|
createTextureAtlas(e, t, r, i) {
|
|
1158
|
-
const s = e.length, a = Math.ceil(Math.sqrt(s)), n = Math.ceil(s / a),
|
|
1159
|
-
this._setupCanvas(
|
|
1160
|
-
const u = this._renderer.createFramebuffer(
|
|
1198
|
+
const s = e.length, a = Math.ceil(Math.sqrt(s)), n = Math.ceil(s / a), l = t.width * a, c = t.height * n;
|
|
1199
|
+
this._setupCanvas(l, c, r, i), this._renderCharactersToCanvas(e, t, a, r), this._applyBlackWhiteThreshold();
|
|
1200
|
+
const u = this._renderer.createFramebuffer(l, c, { filter: "nearest" });
|
|
1161
1201
|
return u.update(this._textureCanvas), {
|
|
1162
1202
|
framebuffer: u,
|
|
1163
1203
|
columns: a,
|
|
@@ -1185,7 +1225,7 @@ class ge {
|
|
|
1185
1225
|
*/
|
|
1186
1226
|
_renderCharactersToCanvas(e, t, r, i) {
|
|
1187
1227
|
for (let s = 0; s < e.length; s++) {
|
|
1188
|
-
const a = s % r, n = Math.floor(s / r),
|
|
1228
|
+
const a = s % r, n = Math.floor(s / r), l = a * t.width + t.width * 0.5, c = n * t.height + t.height * 0.5, u = Math.round(l - t.width * 0.5), d = Math.round(c - i * 0.5);
|
|
1189
1229
|
this._textureContext.fillText(e[s].character, u, d);
|
|
1190
1230
|
}
|
|
1191
1231
|
}
|
|
@@ -1204,7 +1244,7 @@ class ge {
|
|
|
1204
1244
|
this._textureContext.putImageData(t, 0, 0);
|
|
1205
1245
|
}
|
|
1206
1246
|
}
|
|
1207
|
-
class
|
|
1247
|
+
class _e {
|
|
1208
1248
|
/**
|
|
1209
1249
|
* Creates a new MetricsCalculation instance.
|
|
1210
1250
|
*/
|
|
@@ -1225,8 +1265,8 @@ class pe {
|
|
|
1225
1265
|
this._tempContext.font = `${t}px ${r}`;
|
|
1226
1266
|
let i = 0, s = 0;
|
|
1227
1267
|
for (const a of e) {
|
|
1228
|
-
const n = this._tempContext.measureText(a),
|
|
1229
|
-
|
|
1268
|
+
const n = this._tempContext.measureText(a), l = n.width, c = n.actualBoundingBoxAscent + n.actualBoundingBoxDescent;
|
|
1269
|
+
l > 0 && (i = Math.max(i, l), s = Math.max(s, c));
|
|
1230
1270
|
}
|
|
1231
1271
|
return {
|
|
1232
1272
|
width: Math.ceil(i),
|
|
@@ -1234,7 +1274,7 @@ class pe {
|
|
|
1234
1274
|
};
|
|
1235
1275
|
}
|
|
1236
1276
|
}
|
|
1237
|
-
class
|
|
1277
|
+
class pe {
|
|
1238
1278
|
/**
|
|
1239
1279
|
* Creates TextmodeCharacter objects with unique color assignments.
|
|
1240
1280
|
* @param characters Array of character strings
|
|
@@ -1246,8 +1286,8 @@ class _e {
|
|
|
1246
1286
|
const s = r.codePointAt(0) || 0, a = this._generateCharacterColor(i);
|
|
1247
1287
|
let n = 0;
|
|
1248
1288
|
if (t.hmtx && t.hmtx.aWidth) {
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1289
|
+
const l = this._getGlyphIndex(t, s);
|
|
1290
|
+
l > 0 && t.hmtx.aWidth[l] !== void 0 && (n = t.hmtx.aWidth[l]);
|
|
1251
1291
|
}
|
|
1252
1292
|
return {
|
|
1253
1293
|
character: r,
|
|
@@ -1346,7 +1386,7 @@ class xe {
|
|
|
1346
1386
|
o(this, "_textureAtlas");
|
|
1347
1387
|
o(this, "_metricsCalculator");
|
|
1348
1388
|
o(this, "_characterColorMapper");
|
|
1349
|
-
this._fontSize = t, this._characterExtractor = new me(), this._textureAtlas = new ge(e), this._metricsCalculator = new
|
|
1389
|
+
this._fontSize = t, this._characterExtractor = new me(), this._textureAtlas = new ge(e), this._metricsCalculator = new _e(), this._characterColorMapper = new pe();
|
|
1350
1390
|
}
|
|
1351
1391
|
/**
|
|
1352
1392
|
* Initializes the font manager by loading the font and creating the texture atlas.
|
|
@@ -1484,6 +1524,19 @@ class xe {
|
|
|
1484
1524
|
get maxGlyphDimensions() {
|
|
1485
1525
|
return this._maxGlyphDimensions;
|
|
1486
1526
|
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Dispose of all resources used by this font manager.
|
|
1529
|
+
* This method is idempotent and safe to call multiple times.
|
|
1530
|
+
*/
|
|
1531
|
+
dispose() {
|
|
1532
|
+
this._fontFramebuffer && !this._fontFramebuffer.isDisposed && this._fontFramebuffer.dispose(), this._fontFace && document.fonts.has(this._fontFace) && document.fonts.delete(this._fontFace), this._fontFramebuffer = null, this._fontFace = null, this._font = null, this._characters = [], this._maxGlyphDimensions = { width: 0, height: 0 }, this._textureColumns = 0, this._textureRows = 0;
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Check if this font manager has been disposed
|
|
1536
|
+
*/
|
|
1537
|
+
get isDisposed() {
|
|
1538
|
+
return this._fontFramebuffer === null || this._font === null;
|
|
1539
|
+
}
|
|
1487
1540
|
/** Returns the font size used for rendering. */
|
|
1488
1541
|
get fontSize() {
|
|
1489
1542
|
return this._fontSize;
|
|
@@ -1598,6 +1651,19 @@ class ve {
|
|
|
1598
1651
|
get cellHeight() {
|
|
1599
1652
|
return this._cellHeight;
|
|
1600
1653
|
}
|
|
1654
|
+
/**
|
|
1655
|
+
* Dispose of this TextmodeGrid and clean up references.
|
|
1656
|
+
* This method is idempotent and safe to call multiple times.
|
|
1657
|
+
*/
|
|
1658
|
+
dispose() {
|
|
1659
|
+
this._canvas = null, this._cols = 0, this._rows = 0, this._width = 0, this._height = 0, this._offsetX = 0, this._offsetY = 0, this._cellWidth = 0, this._cellHeight = 0;
|
|
1660
|
+
}
|
|
1661
|
+
/**
|
|
1662
|
+
* Check if this TextmodeGrid has been disposed
|
|
1663
|
+
*/
|
|
1664
|
+
get isDisposed() {
|
|
1665
|
+
return this._canvas === null;
|
|
1666
|
+
}
|
|
1601
1667
|
/** Returns the number of columns in the grid. */
|
|
1602
1668
|
get cols() {
|
|
1603
1669
|
return this._cols;
|
|
@@ -1623,7 +1689,7 @@ class ve {
|
|
|
1623
1689
|
return this._offsetY;
|
|
1624
1690
|
}
|
|
1625
1691
|
}
|
|
1626
|
-
class
|
|
1692
|
+
class be {
|
|
1627
1693
|
constructor(e, t = !1, r = {}) {
|
|
1628
1694
|
o(this, "_canvas");
|
|
1629
1695
|
o(this, "captureSource");
|
|
@@ -1633,7 +1699,7 @@ class Ce {
|
|
|
1633
1699
|
createCanvas(e, t) {
|
|
1634
1700
|
var i;
|
|
1635
1701
|
const r = document.createElement("canvas");
|
|
1636
|
-
if (r.className = "textmodeCanvas", this._isStandalone)
|
|
1702
|
+
if (r.className = "textmodeCanvas", r.style.imageRendering = "pixelated", this._isStandalone)
|
|
1637
1703
|
r.width = e || 800, r.height = t || 600, document.body.appendChild(r);
|
|
1638
1704
|
else {
|
|
1639
1705
|
const s = this.captureSource.getBoundingClientRect();
|
|
@@ -1643,8 +1709,8 @@ class Ce {
|
|
|
1643
1709
|
(a === 0 || n === 0) && u.videoWidth > 0 && u.videoHeight > 0 && (a = u.videoWidth, n = u.videoHeight);
|
|
1644
1710
|
}
|
|
1645
1711
|
r.width = a, r.height = n, r.style.position = "absolute", r.style.pointerEvents = "none";
|
|
1646
|
-
const
|
|
1647
|
-
let c = parseInt(
|
|
1712
|
+
const l = window.getComputedStyle(this.captureSource);
|
|
1713
|
+
let c = parseInt(l.zIndex || "0", 10);
|
|
1648
1714
|
isNaN(c) && (c = 0), r.style.zIndex = (c + 1).toString(), this.positionOverlayCanvas(r), (i = this.captureSource.parentNode) == null || i.insertBefore(r, this.captureSource.nextSibling);
|
|
1649
1715
|
}
|
|
1650
1716
|
return r;
|
|
@@ -1688,6 +1754,27 @@ class Ce {
|
|
|
1688
1754
|
throw new F("WebGL context could not be created. Ensure your browser supports WebGL.");
|
|
1689
1755
|
return t;
|
|
1690
1756
|
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Dispose of this TextmodeCanvas and clean up all resources.
|
|
1759
|
+
* This method is idempotent and safe to call multiple times.
|
|
1760
|
+
*/
|
|
1761
|
+
dispose() {
|
|
1762
|
+
if (this._canvas) {
|
|
1763
|
+
const e = this._canvas.getContext("webgl") || this._canvas.getContext("webgl2");
|
|
1764
|
+
if (e) {
|
|
1765
|
+
const t = e.getExtension("WEBGL_lose_context");
|
|
1766
|
+
t && t.loseContext();
|
|
1767
|
+
}
|
|
1768
|
+
this._canvas.parentNode && this._canvas.parentNode.removeChild(this._canvas), this._canvas = null;
|
|
1769
|
+
}
|
|
1770
|
+
this.captureSource = null;
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Check if this TextmodeCanvas has been disposed
|
|
1774
|
+
*/
|
|
1775
|
+
get isDisposed() {
|
|
1776
|
+
return this._canvas === null;
|
|
1777
|
+
}
|
|
1691
1778
|
get canvas() {
|
|
1692
1779
|
return this._canvas;
|
|
1693
1780
|
}
|
|
@@ -1745,6 +1832,19 @@ class U {
|
|
|
1745
1832
|
disable() {
|
|
1746
1833
|
this.enabled(!1);
|
|
1747
1834
|
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Dispose of all framebuffers used by this converter.
|
|
1837
|
+
* This method is idempotent and safe to call multiple times.
|
|
1838
|
+
*/
|
|
1839
|
+
dispose() {
|
|
1840
|
+
this._characterFramebuffer && !this._characterFramebuffer.isDisposed && this._characterFramebuffer.dispose(), this._primaryColorFramebuffer && !this._primaryColorFramebuffer.isDisposed && this._primaryColorFramebuffer.dispose(), this._secondaryColorFramebuffer && !this._secondaryColorFramebuffer.isDisposed && this._secondaryColorFramebuffer.dispose(), this._rotationFramebuffer && !this._rotationFramebuffer.isDisposed && this._rotationFramebuffer.dispose(), this._transformFramebuffer && !this._transformFramebuffer.isDisposed && this._transformFramebuffer.dispose(), this._characterFramebuffer = null, this._primaryColorFramebuffer = null, this._secondaryColorFramebuffer = null, this._rotationFramebuffer = null, this._transformFramebuffer = null;
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Check if this converter has been disposed
|
|
1844
|
+
*/
|
|
1845
|
+
get isDisposed() {
|
|
1846
|
+
return this._characterFramebuffer === null;
|
|
1847
|
+
}
|
|
1748
1848
|
/** Returns the framebuffer containing character data. */
|
|
1749
1849
|
get characterFramebuffer() {
|
|
1750
1850
|
return this._characterFramebuffer;
|
|
@@ -1770,7 +1870,7 @@ class U {
|
|
|
1770
1870
|
return this._options;
|
|
1771
1871
|
}
|
|
1772
1872
|
}
|
|
1773
|
-
class
|
|
1873
|
+
class Ce {
|
|
1774
1874
|
/**
|
|
1775
1875
|
* Create a new color palette instance.
|
|
1776
1876
|
* @param renderer The renderer instance.
|
|
@@ -1829,7 +1929,7 @@ class X extends U {
|
|
|
1829
1929
|
constructor(t, r, i, s = {}) {
|
|
1830
1930
|
super(t, r, i, s);
|
|
1831
1931
|
o(this, "palette");
|
|
1832
|
-
this.palette = new
|
|
1932
|
+
this.palette = new Ce(this.renderer, this.fontManager.getCharacterColors(" .:-=+*%@#"));
|
|
1833
1933
|
}
|
|
1834
1934
|
/**
|
|
1835
1935
|
* Sets the characters used for mapping.
|
|
@@ -2167,6 +2267,21 @@ class Ue {
|
|
|
2167
2267
|
for (const e of this.converters)
|
|
2168
2268
|
e.converter.enable();
|
|
2169
2269
|
}
|
|
2270
|
+
/**
|
|
2271
|
+
* Dispose of all resources used by this conversion pipeline.
|
|
2272
|
+
* This method is idempotent and safe to call multiple times.
|
|
2273
|
+
*/
|
|
2274
|
+
dispose() {
|
|
2275
|
+
for (const e of this.converters)
|
|
2276
|
+
e.converter && !e.converter.isDisposed && e.converter.dispose();
|
|
2277
|
+
this._characterFramebuffer && !this._characterFramebuffer.isDisposed && this._characterFramebuffer.dispose(), this._primaryColorFramebuffer && !this._primaryColorFramebuffer.isDisposed && this._primaryColorFramebuffer.dispose(), this._secondaryColorFramebuffer && !this._secondaryColorFramebuffer.isDisposed && this._secondaryColorFramebuffer.dispose(), this._rotationFramebuffer && !this._rotationFramebuffer.isDisposed && this._rotationFramebuffer.dispose(), this._transformFramebuffer && !this._transformFramebuffer.isDisposed && this._transformFramebuffer.dispose(), this._resultFramebuffer && !this._resultFramebuffer.isDisposed && this._resultFramebuffer.dispose(), this._asciiShader && !this._asciiShader.isDisposed && this._asciiShader.dispose(), this.converters = [], this._characterFramebuffer = null, this._primaryColorFramebuffer = null, this._secondaryColorFramebuffer = null, this._rotationFramebuffer = null, this._transformFramebuffer = null, this._resultFramebuffer = null, this._asciiShader = null;
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Check if this conversion pipeline has been disposed
|
|
2281
|
+
*/
|
|
2282
|
+
get isDisposed() {
|
|
2283
|
+
return this._resultFramebuffer === null || this._asciiShader === null;
|
|
2284
|
+
}
|
|
2170
2285
|
/** Returns the character framebuffer containing the combined result of all converters. */
|
|
2171
2286
|
get characterFramebuffer() {
|
|
2172
2287
|
return this._characterFramebuffer;
|
|
@@ -2287,7 +2402,7 @@ class N {
|
|
|
2287
2402
|
return `'textmode-export'-${this.generateTimestamp()}`;
|
|
2288
2403
|
}
|
|
2289
2404
|
}
|
|
2290
|
-
class
|
|
2405
|
+
class De extends H {
|
|
2291
2406
|
/**
|
|
2292
2407
|
* Extracts transform data from transform pixels
|
|
2293
2408
|
* @param transformPixels Transform framebuffer pixels
|
|
@@ -2296,10 +2411,10 @@ class Ae extends H {
|
|
|
2296
2411
|
* @returns Transform data object
|
|
2297
2412
|
*/
|
|
2298
2413
|
extractTransformData(e, t, r) {
|
|
2299
|
-
const i = e[r], s = e[r + 1], a = e[r + 2], n = i === 255,
|
|
2414
|
+
const i = e[r], s = e[r + 1], a = e[r + 2], n = i === 255, l = s === 255, c = a === 255, u = t[r], d = t[r + 1], f = u + d / 255, g = Math.round(f * 360 / 255 * 100) / 100;
|
|
2300
2415
|
return {
|
|
2301
2416
|
isInverted: n,
|
|
2302
|
-
flipHorizontal:
|
|
2417
|
+
flipHorizontal: l,
|
|
2303
2418
|
flipVertical: c,
|
|
2304
2419
|
rotation: g
|
|
2305
2420
|
};
|
|
@@ -2331,7 +2446,7 @@ class Ae extends H {
|
|
|
2331
2446
|
let i = 0;
|
|
2332
2447
|
for (let s = 0; s < t.rows; s++)
|
|
2333
2448
|
for (let a = 0; a < t.cols; a++) {
|
|
2334
|
-
const n = i * 4,
|
|
2449
|
+
const n = i * 4, l = this.getCharacterIndex(
|
|
2335
2450
|
e.characterPixels,
|
|
2336
2451
|
n
|
|
2337
2452
|
);
|
|
@@ -2347,7 +2462,7 @@ class Ae extends H {
|
|
|
2347
2462
|
}
|
|
2348
2463
|
const f = this.calculateCellPosition(a, s, t);
|
|
2349
2464
|
r.push({
|
|
2350
|
-
charIndex:
|
|
2465
|
+
charIndex: l,
|
|
2351
2466
|
primaryColor: c,
|
|
2352
2467
|
secondaryColor: u,
|
|
2353
2468
|
transform: d,
|
|
@@ -2357,7 +2472,7 @@ class Ae extends H {
|
|
|
2357
2472
|
return r;
|
|
2358
2473
|
}
|
|
2359
2474
|
}
|
|
2360
|
-
class
|
|
2475
|
+
class Ae {
|
|
2361
2476
|
/**
|
|
2362
2477
|
* Gets the glyph index for a given Unicode code point in a Typr.js font
|
|
2363
2478
|
* @param fontData The Typr.js font data
|
|
@@ -2428,29 +2543,29 @@ class Me {
|
|
|
2428
2543
|
*/
|
|
2429
2544
|
glyphToSVGPath(e, t, r, i) {
|
|
2430
2545
|
if (!e || !e.xs) return "";
|
|
2431
|
-
const { xs: s, ys: a, endPts: n, flags:
|
|
2432
|
-
if (!s || !a || !n || !
|
|
2546
|
+
const { xs: s, ys: a, endPts: n, flags: l } = e;
|
|
2547
|
+
if (!s || !a || !n || !l) return "";
|
|
2433
2548
|
let c = "", u = 0;
|
|
2434
2549
|
for (let d = 0; d < n.length; d++) {
|
|
2435
2550
|
const f = n[d];
|
|
2436
2551
|
if (!(f < u)) {
|
|
2437
2552
|
if (f >= u) {
|
|
2438
|
-
const g = t + s[u] * i,
|
|
2439
|
-
c += `M${g.toFixed(2)},${
|
|
2440
|
-
let
|
|
2441
|
-
for (;
|
|
2442
|
-
if ((
|
|
2443
|
-
const
|
|
2444
|
-
c += `L${
|
|
2553
|
+
const g = t + s[u] * i, p = r - a[u] * i;
|
|
2554
|
+
c += `M${g.toFixed(2)},${p.toFixed(2)}`;
|
|
2555
|
+
let _ = u + 1;
|
|
2556
|
+
for (; _ <= f; )
|
|
2557
|
+
if ((l[_] & 1) !== 0) {
|
|
2558
|
+
const C = t + s[_] * i, v = r - a[_] * i;
|
|
2559
|
+
c += `L${C.toFixed(2)},${v.toFixed(2)}`, _++;
|
|
2445
2560
|
} else {
|
|
2446
|
-
const
|
|
2447
|
-
let w =
|
|
2448
|
-
if ((
|
|
2561
|
+
const C = t + s[_] * i, v = r - a[_] * i;
|
|
2562
|
+
let w = _ + 1 > f ? u : _ + 1;
|
|
2563
|
+
if ((l[w] & 1) !== 0) {
|
|
2449
2564
|
const R = t + s[w] * i, y = r - a[w] * i;
|
|
2450
|
-
c += `Q${
|
|
2565
|
+
c += `Q${C.toFixed(2)},${v.toFixed(2)} ${R.toFixed(2)},${y.toFixed(2)}`, _ = w + 1;
|
|
2451
2566
|
} else {
|
|
2452
|
-
const R = t + s[w] * i, y = r - a[w] * i, P = (
|
|
2453
|
-
c += `Q${
|
|
2567
|
+
const R = t + s[w] * i, y = r - a[w] * i, P = (C + R) / 2, M = (v + y) / 2;
|
|
2568
|
+
c += `Q${C.toFixed(2)},${v.toFixed(2)} ${P.toFixed(2)},${M.toFixed(2)}`, _ = w;
|
|
2454
2569
|
}
|
|
2455
2570
|
}
|
|
2456
2571
|
c += "Z";
|
|
@@ -2474,13 +2589,13 @@ class Me {
|
|
|
2474
2589
|
const a = e.codePointAt(0) || 0, n = this.getGlyphIndex(t, a);
|
|
2475
2590
|
if (n === 0)
|
|
2476
2591
|
return this.createEmptyPath();
|
|
2477
|
-
let
|
|
2592
|
+
let l = null;
|
|
2478
2593
|
try {
|
|
2479
|
-
t.glyf && t.glyf[n] !== null ?
|
|
2594
|
+
t.glyf && t.glyf[n] !== null ? l = t.glyf[n] : m && m.T && m.T.glyf && m.T.glyf._parseGlyf && (l = m.T.glyf._parseGlyf(t, n), t.glyf && l && (t.glyf[n] = l));
|
|
2480
2595
|
} catch (c) {
|
|
2481
2596
|
console.warn(`Failed to parse glyph ${n}:`, c);
|
|
2482
2597
|
}
|
|
2483
|
-
return
|
|
2598
|
+
return l ? this.createGlyphPath(t, l, r, i, s) : this.createEmptyPath();
|
|
2484
2599
|
} catch (a) {
|
|
2485
2600
|
return console.warn(`Failed to generate path for character "${e}":`, a), this.createEmptyPath();
|
|
2486
2601
|
}
|
|
@@ -2497,19 +2612,19 @@ class Me {
|
|
|
2497
2612
|
* @param advanceWidth Character advance width
|
|
2498
2613
|
* @returns SVG path data string or null if generation fails
|
|
2499
2614
|
*/
|
|
2500
|
-
generatePositionedCharacterPath(e, t, r, i, s, a, n,
|
|
2615
|
+
generatePositionedCharacterPath(e, t, r, i, s, a, n, l) {
|
|
2501
2616
|
try {
|
|
2502
|
-
const c = n / t.head.unitsPerEm, u =
|
|
2617
|
+
const c = n / t.head.unitsPerEm, u = l * c, d = r + (s - u) / 2, f = i + (a + n * 0.7) / 2;
|
|
2503
2618
|
return this.generateCharacterPath(e, t, d, f, n).toSVG() || null;
|
|
2504
2619
|
} catch (c) {
|
|
2505
2620
|
return console.warn(`Failed to generate positioned character path for "${e}":`, c), null;
|
|
2506
2621
|
}
|
|
2507
2622
|
}
|
|
2508
2623
|
}
|
|
2509
|
-
class
|
|
2624
|
+
class Me {
|
|
2510
2625
|
constructor() {
|
|
2511
2626
|
o(this, "pathGenerator");
|
|
2512
|
-
this.pathGenerator = new
|
|
2627
|
+
this.pathGenerator = new Ae();
|
|
2513
2628
|
}
|
|
2514
2629
|
/**
|
|
2515
2630
|
* Generates the SVG header with metadata
|
|
@@ -2563,8 +2678,8 @@ class De {
|
|
|
2563
2678
|
generateTransformAttribute(e, t) {
|
|
2564
2679
|
const { transform: r, position: i } = e, s = i.cellX + t.cellWidth / 2, a = i.cellY + t.cellHeight / 2, n = [];
|
|
2565
2680
|
if (r.flipHorizontal || r.flipVertical) {
|
|
2566
|
-
const
|
|
2567
|
-
n.push(`translate(${s} ${a})`), n.push(`scale(${
|
|
2681
|
+
const l = r.flipHorizontal ? -1 : 1, c = r.flipVertical ? -1 : 1;
|
|
2682
|
+
n.push(`translate(${s} ${a})`), n.push(`scale(${l} ${c})`), n.push(`translate(${-s} ${-a})`);
|
|
2568
2683
|
}
|
|
2569
2684
|
return r.rotation && n.push(`rotate(${r.rotation} ${s} ${a})`), n.length ? ` transform="${n.join(" ")}"` : "";
|
|
2570
2685
|
}
|
|
@@ -2689,7 +2804,7 @@ class Y {
|
|
|
2689
2804
|
o(this, "dataExtractor");
|
|
2690
2805
|
o(this, "contentGenerator");
|
|
2691
2806
|
o(this, "fileHandler");
|
|
2692
|
-
this.dataExtractor = new
|
|
2807
|
+
this.dataExtractor = new De(), this.contentGenerator = new Me(), this.fileHandler = new Ie();
|
|
2693
2808
|
}
|
|
2694
2809
|
/**
|
|
2695
2810
|
* Applies default values to SVG export options
|
|
@@ -2749,7 +2864,7 @@ class Pe extends H {
|
|
|
2749
2864
|
var n;
|
|
2750
2865
|
const s = [];
|
|
2751
2866
|
let a = 0;
|
|
2752
|
-
for (let
|
|
2867
|
+
for (let l = 0; l < t.rows; l++) {
|
|
2753
2868
|
const c = [];
|
|
2754
2869
|
for (let u = 0; u < t.cols; u++) {
|
|
2755
2870
|
const d = a * 4, f = this.getCharacterIndex(
|
|
@@ -2869,8 +2984,8 @@ class Ve extends H {
|
|
|
2869
2984
|
const i = e.canvas;
|
|
2870
2985
|
if (t === 1 && r === "transparent")
|
|
2871
2986
|
return i;
|
|
2872
|
-
const s = document.createElement("canvas"), a = s.getContext("2d"), n = Math.round(i.width * t),
|
|
2873
|
-
return s.width = n, s.height =
|
|
2987
|
+
const s = document.createElement("canvas"), a = s.getContext("2d"), n = Math.round(i.width * t), l = Math.round(i.height * t);
|
|
2988
|
+
return s.width = n, s.height = l, r !== "transparent" && (a.fillStyle = r, a.fillRect(0, 0, n, l)), a.imageSmoothingEnabled = !1, a.drawImage(
|
|
2874
2989
|
i,
|
|
2875
2990
|
0,
|
|
2876
2991
|
0,
|
|
@@ -2879,7 +2994,7 @@ class Ve extends H {
|
|
|
2879
2994
|
0,
|
|
2880
2995
|
0,
|
|
2881
2996
|
n,
|
|
2882
|
-
|
|
2997
|
+
l
|
|
2883
2998
|
), s;
|
|
2884
2999
|
}
|
|
2885
3000
|
}
|
|
@@ -2930,12 +3045,12 @@ const q = {
|
|
|
2930
3045
|
png: "image/png",
|
|
2931
3046
|
jpg: "image/jpeg",
|
|
2932
3047
|
webp: "image/webp"
|
|
2933
|
-
},
|
|
3048
|
+
}, z = {
|
|
2934
3049
|
png: ".png",
|
|
2935
3050
|
jpg: ".jpg",
|
|
2936
3051
|
webp: ".webp"
|
|
2937
3052
|
};
|
|
2938
|
-
class
|
|
3053
|
+
class ze extends N {
|
|
2939
3054
|
/**
|
|
2940
3055
|
* Saves image content as a downloadable file
|
|
2941
3056
|
* @param content The image content (data URL or blob)
|
|
@@ -2944,7 +3059,7 @@ class $e extends N {
|
|
|
2944
3059
|
*/
|
|
2945
3060
|
saveImage(e, t, r) {
|
|
2946
3061
|
try {
|
|
2947
|
-
const i =
|
|
3062
|
+
const i = z[r];
|
|
2948
3063
|
typeof e == "string" ? this.saveImageFromDataURL(e, this.sanitizeFilename(t) + i) : this.saveImageFromBlob(e, this.sanitizeFilename(t) + i);
|
|
2949
3064
|
} catch (i) {
|
|
2950
3065
|
throw console.error(`Failed to save ${r.toUpperCase()} image:`, i), new Error(`Image save failed: ${i instanceof Error ? i.message : "Unknown error"}`);
|
|
@@ -2979,7 +3094,7 @@ class $e extends N {
|
|
|
2979
3094
|
* @returns True if the format is supported for saving
|
|
2980
3095
|
*/
|
|
2981
3096
|
validateSaveSupport(e) {
|
|
2982
|
-
return e in q && e in
|
|
3097
|
+
return e in q && e in z;
|
|
2983
3098
|
}
|
|
2984
3099
|
/**
|
|
2985
3100
|
* Gets the MIME type for the specified image format
|
|
@@ -2995,15 +3110,15 @@ class $e extends N {
|
|
|
2995
3110
|
* @returns The file extension (including the dot)
|
|
2996
3111
|
*/
|
|
2997
3112
|
getFileExtension(e) {
|
|
2998
|
-
return
|
|
3113
|
+
return z[e];
|
|
2999
3114
|
}
|
|
3000
3115
|
}
|
|
3001
|
-
class
|
|
3116
|
+
class $e {
|
|
3002
3117
|
constructor() {
|
|
3003
3118
|
o(this, "dataExtractor");
|
|
3004
3119
|
o(this, "contentGenerator");
|
|
3005
3120
|
o(this, "fileHandler");
|
|
3006
|
-
this.dataExtractor = new Ve(), this.contentGenerator = new ke(), this.fileHandler = new
|
|
3121
|
+
this.dataExtractor = new Ve(), this.contentGenerator = new ke(), this.fileHandler = new ze();
|
|
3007
3122
|
}
|
|
3008
3123
|
/**
|
|
3009
3124
|
* Applies default values to image export options
|
|
@@ -3117,6 +3232,9 @@ class I {
|
|
|
3117
3232
|
});
|
|
3118
3233
|
o(this, "_resizedCallback", () => {
|
|
3119
3234
|
});
|
|
3235
|
+
// Destroy state
|
|
3236
|
+
o(this, "_isDestroyed", !1);
|
|
3237
|
+
o(this, "_windowResizeListener", null);
|
|
3120
3238
|
this.captureSource = e, this._standalone = e === null, this._mode = t.renderMode ?? "auto", this._frameRateLimit = t.frameRate ?? 60, this.frameInterval = 1e3 / this._frameRateLimit;
|
|
3121
3239
|
}
|
|
3122
3240
|
/**
|
|
@@ -3127,16 +3245,16 @@ class I {
|
|
|
3127
3245
|
*/
|
|
3128
3246
|
static async create(e = null, t = {}) {
|
|
3129
3247
|
const r = new I(e, t), i = r._standalone ? t : void 0;
|
|
3130
|
-
r.textmodeCanvas = new
|
|
3248
|
+
r.textmodeCanvas = new be(r.captureSource, r._standalone, i), r._renderer = new fe(r.textmodeCanvas.getWebGLContext());
|
|
3131
3249
|
let s, a;
|
|
3132
3250
|
r._standalone ? (s = t.width || 800, a = t.height || 600) : (s = r.textmodeCanvas.width || 800, a = r.textmodeCanvas.height || 600), r._canvasFramebuffer = r._renderer.createFramebuffer(s, a), r._font = new xe(r._renderer, t.fontSize ?? 16), await r._font.initialize(t.fontSource);
|
|
3133
3251
|
const n = r._font.maxGlyphDimensions;
|
|
3134
3252
|
return r._grid = new ve(r.textmodeCanvas.canvas, n.width, n.height), r._pipeline = new Ue(r._renderer, r._font, r._grid), r.setupEventListeners(), r.startAutoRendering(), r;
|
|
3135
3253
|
}
|
|
3136
3254
|
setupEventListeners() {
|
|
3137
|
-
|
|
3255
|
+
this._windowResizeListener = () => {
|
|
3138
3256
|
this._standalone ? this._resizedCallback() : this.resize();
|
|
3139
|
-
}), window.ResizeObserver && this.captureSource && !this._standalone && (this.resizeObserver = new ResizeObserver(() => {
|
|
3257
|
+
}, window.addEventListener("resize", this._windowResizeListener), window.ResizeObserver && this.captureSource && !this._standalone && (this.resizeObserver = new ResizeObserver(() => {
|
|
3140
3258
|
this.resize();
|
|
3141
3259
|
}), this.resizeObserver.observe(this.captureSource));
|
|
3142
3260
|
}
|
|
@@ -3288,7 +3406,7 @@ class I {
|
|
|
3288
3406
|
* ```
|
|
3289
3407
|
*/
|
|
3290
3408
|
async saveCanvas(e, t = "png", r = {}) {
|
|
3291
|
-
await new
|
|
3409
|
+
await new $e().saveImage(this.textmodeCanvas, {
|
|
3292
3410
|
...r,
|
|
3293
3411
|
filename: e,
|
|
3294
3412
|
format: t
|
|
@@ -3358,7 +3476,19 @@ class I {
|
|
|
3358
3476
|
* ```
|
|
3359
3477
|
*/
|
|
3360
3478
|
render() {
|
|
3361
|
-
|
|
3479
|
+
if (this._isDestroyed) {
|
|
3480
|
+
console.warn("Cannot render: Textmodifier instance has been destroyed");
|
|
3481
|
+
return;
|
|
3482
|
+
}
|
|
3483
|
+
if (this.measureFrameRate(), this._frameCount++, !this._canvasFramebuffer || !this._renderer || !this._pipeline) {
|
|
3484
|
+
console.warn("Cannot render: Required resources have been disposed");
|
|
3485
|
+
return;
|
|
3486
|
+
}
|
|
3487
|
+
if (this._standalone ? this._canvasFramebuffer && (this._canvasFramebuffer.begin(), this._drawCallback(), this._renderer && this._renderer.reset(), this._canvasFramebuffer && this._canvasFramebuffer.end()) : this.captureSource && this._canvasFramebuffer && this._canvasFramebuffer.update(this.captureSource), !this._pipeline || !this._renderer) {
|
|
3488
|
+
console.warn("Cannot complete render: Pipeline or renderer has been disposed");
|
|
3489
|
+
return;
|
|
3490
|
+
}
|
|
3491
|
+
this._pipeline.render(this._canvasFramebuffer), this._pipeline.hasEnabledConverters() ? this._renderer && this._pipeline.texture && this._grid && (this._renderer.background(0), this._renderer.image(this._pipeline.texture, this._grid.offsetX, this._grid.offsetY, this._pipeline.texture.width, this._pipeline.texture.height)) : this._renderer && this._canvasFramebuffer && this._grid && (this._renderer.clear(), this._renderer.image(this._canvasFramebuffer, this._grid.offsetX, this._grid.offsetY, this._canvasFramebuffer.width, this._canvasFramebuffer.height));
|
|
3362
3492
|
}
|
|
3363
3493
|
resize() {
|
|
3364
3494
|
this.textmodeCanvas.resize(), this._canvasFramebuffer.resize(this.textmodeCanvas.width, this.textmodeCanvas.height), this._grid.resize(), this._pipeline.resize(), this._renderer.resetViewport(), this._mode !== "manual" && this.render();
|
|
@@ -3367,11 +3497,13 @@ class I {
|
|
|
3367
3497
|
* Start automatic rendering
|
|
3368
3498
|
*/
|
|
3369
3499
|
startAutoRendering() {
|
|
3370
|
-
if (this._mode !== "auto") return;
|
|
3500
|
+
if (this._mode !== "auto" || this._isDestroyed) return;
|
|
3371
3501
|
this.lastFrameTime = performance.now();
|
|
3372
3502
|
const e = (t) => {
|
|
3503
|
+
if (this._isDestroyed)
|
|
3504
|
+
return;
|
|
3373
3505
|
const r = t - this.lastFrameTime;
|
|
3374
|
-
r >= this.frameInterval && (this.render(), this.lastFrameTime = t - r % this.frameInterval), this.animationFrameId = requestAnimationFrame(e);
|
|
3506
|
+
r >= this.frameInterval && (this.render(), this.lastFrameTime = t - r % this.frameInterval), this._isDestroyed || (this.animationFrameId = requestAnimationFrame(e));
|
|
3375
3507
|
};
|
|
3376
3508
|
this.animationFrameId = requestAnimationFrame(e);
|
|
3377
3509
|
}
|
|
@@ -3380,6 +3512,7 @@ class I {
|
|
|
3380
3512
|
* Uses a rolling average for smoother frame rate reporting
|
|
3381
3513
|
*/
|
|
3382
3514
|
measureFrameRate() {
|
|
3515
|
+
if (this._isDestroyed) return;
|
|
3383
3516
|
const e = performance.now();
|
|
3384
3517
|
if (this.lastRenderTime > 0) {
|
|
3385
3518
|
const t = e - this.lastRenderTime;
|
|
@@ -3420,6 +3553,10 @@ class I {
|
|
|
3420
3553
|
* ```
|
|
3421
3554
|
*/
|
|
3422
3555
|
renderMode(e) {
|
|
3556
|
+
if (this._isDestroyed) {
|
|
3557
|
+
console.warn("Cannot change render mode: Textmodifier instance has been destroyed");
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3423
3560
|
this._mode !== e && (this.stopAutoRendering(), this._mode = e, e === "auto" && this.startAutoRendering());
|
|
3424
3561
|
}
|
|
3425
3562
|
/**
|
|
@@ -3973,33 +4110,77 @@ class I {
|
|
|
3973
4110
|
setUniform(e, t) {
|
|
3974
4111
|
this._renderer.setUniform(e, t);
|
|
3975
4112
|
}
|
|
4113
|
+
/**
|
|
4114
|
+
* Completely destroy this Textmodifier instance and free all associated resources.
|
|
4115
|
+
*
|
|
4116
|
+
* This method performs comprehensive cleanup of:
|
|
4117
|
+
* - WebGL resources (framebuffers, textures, shaders)
|
|
4118
|
+
* - Animation frames and timers
|
|
4119
|
+
* - Event listeners
|
|
4120
|
+
* - DOM elements
|
|
4121
|
+
* - Font resources
|
|
4122
|
+
*
|
|
4123
|
+
* After calling this method, the instance should not be used and will be eligible for garbage collection.
|
|
4124
|
+
* This method is idempotent and safe to call multiple times.
|
|
4125
|
+
*
|
|
4126
|
+
* @example
|
|
4127
|
+
* ```javascript
|
|
4128
|
+
* // Create a textmodifier instance
|
|
4129
|
+
* const textmodifier = await textmode.create(canvas);
|
|
4130
|
+
*
|
|
4131
|
+
* // Use it for rendering
|
|
4132
|
+
* textmodifier.render();
|
|
4133
|
+
*
|
|
4134
|
+
* // When done, completely clean up
|
|
4135
|
+
* textmodifier.destroy();
|
|
4136
|
+
*
|
|
4137
|
+
* // Instance is now safely disposed and ready for garbage collection
|
|
4138
|
+
* ```
|
|
4139
|
+
*/
|
|
4140
|
+
destroy() {
|
|
4141
|
+
this._isDestroyed || (this._isDestroyed = !0, this.stopAutoRendering(), this._windowResizeListener && (window.removeEventListener("resize", this._windowResizeListener), this._windowResizeListener = null), this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this._pipeline && !this._pipeline.isDisposed && this._pipeline.dispose(), this._font && !this._font.isDisposed && this._font.dispose(), this._grid && !this._grid.isDisposed && this._grid.dispose(), this._canvasFramebuffer && !this._canvasFramebuffer.isDisposed && this._canvasFramebuffer.dispose(), this._renderer && !this._renderer.isDisposed && this._renderer.dispose(), this.textmodeCanvas && !this.textmodeCanvas.isDisposed && this.textmodeCanvas.dispose(), this.captureSource = null, this.textmodeCanvas = null, this._renderer = null, this._canvasFramebuffer = null, this._font = null, this._grid = null, this._pipeline = null, this.resizeObserver = null, this._drawCallback = () => {
|
|
4142
|
+
}, this._resizedCallback = () => {
|
|
4143
|
+
}, this.animationFrameId = null, this.lastFrameTime = 0, this.lastRenderTime = 0, this._frameCount = 0, this._frameRate = 0, this.frameTimeHistory = []);
|
|
4144
|
+
}
|
|
3976
4145
|
/** Get the current grid object used for rendering. */
|
|
3977
4146
|
get grid() {
|
|
4147
|
+
if (this._isDestroyed)
|
|
4148
|
+
throw new Error("Cannot access grid: Textmodifier instance has been destroyed");
|
|
3978
4149
|
return this._grid;
|
|
3979
4150
|
}
|
|
3980
4151
|
/** Get the current font object used for rendering. */
|
|
3981
4152
|
get font() {
|
|
4153
|
+
if (this._isDestroyed)
|
|
4154
|
+
throw new Error("Cannot access font: Textmodifier instance has been destroyed");
|
|
3982
4155
|
return this._font;
|
|
3983
4156
|
}
|
|
3984
4157
|
/** Get the current rendering mode.*/
|
|
3985
4158
|
get mode() {
|
|
4159
|
+
if (this._isDestroyed)
|
|
4160
|
+
throw new Error("Cannot access mode: Textmodifier instance has been destroyed");
|
|
3986
4161
|
return this._mode;
|
|
3987
4162
|
}
|
|
3988
4163
|
/** Get the current textmode conversion pipeline. */
|
|
3989
4164
|
get pipeline() {
|
|
4165
|
+
if (this._isDestroyed)
|
|
4166
|
+
throw new Error("Cannot access pipeline: Textmodifier instance has been destroyed");
|
|
3990
4167
|
return this._pipeline;
|
|
3991
4168
|
}
|
|
3992
4169
|
/** Get the current frame count. */
|
|
3993
4170
|
get frameCount() {
|
|
3994
|
-
return this._frameCount;
|
|
4171
|
+
return this._isDestroyed ? 0 : this._frameCount;
|
|
3995
4172
|
}
|
|
3996
4173
|
/** Get the width of the canvas. */
|
|
3997
4174
|
get width() {
|
|
3998
|
-
return this.textmodeCanvas.width;
|
|
4175
|
+
return this._isDestroyed ? 0 : this.textmodeCanvas.width;
|
|
3999
4176
|
}
|
|
4000
4177
|
/** Get the height of the canvas. */
|
|
4001
4178
|
get height() {
|
|
4002
|
-
return this.textmodeCanvas.height;
|
|
4179
|
+
return this._isDestroyed ? 0 : this.textmodeCanvas.height;
|
|
4180
|
+
}
|
|
4181
|
+
/** Check if this Textmodifier instance has been destroyed. */
|
|
4182
|
+
get isDestroyed() {
|
|
4183
|
+
return this._isDestroyed;
|
|
4003
4184
|
}
|
|
4004
4185
|
}
|
|
4005
4186
|
class O {
|
|
@@ -4046,6 +4227,20 @@ class O {
|
|
|
4046
4227
|
* // Draw a rectangle with the fill color
|
|
4047
4228
|
* t.rect(x, y, 200, 150);
|
|
4048
4229
|
* });
|
|
4230
|
+
*
|
|
4231
|
+
* ////////
|
|
4232
|
+
*
|
|
4233
|
+
* // Resource management example
|
|
4234
|
+
* const textmodifier = await textmode.create(canvas);
|
|
4235
|
+
*
|
|
4236
|
+
* // Use the textmodifier...
|
|
4237
|
+
* textmodifier.render();
|
|
4238
|
+
*
|
|
4239
|
+
* // When done, completely clean up all resources
|
|
4240
|
+
* textmodifier.destroy();
|
|
4241
|
+
*
|
|
4242
|
+
* // The instance is now safely disposed and ready for garbage collection
|
|
4243
|
+
* console.log(textmodifier.isDestroyed); // true
|
|
4049
4244
|
* ```
|
|
4050
4245
|
*/
|
|
4051
4246
|
static async create(e, t = {}) {
|
|
@@ -4088,7 +4283,7 @@ const He = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
4088
4283
|
__proto__: null
|
|
4089
4284
|
}, Symbol.toStringTag, { value: "Module" })), Ne = O.create, Oe = O.setErrorLevel, We = O.version;
|
|
4090
4285
|
export {
|
|
4091
|
-
|
|
4286
|
+
be as TextmodeCanvas,
|
|
4092
4287
|
Ue as TextmodeConversionPipeline,
|
|
4093
4288
|
ne as TextmodeErrorLevel,
|
|
4094
4289
|
xe as TextmodeFont,
|