textmode.js 0.1.6-beta.3 → 0.1.6-beta.4

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.
@@ -1,9 +1,9 @@
1
- var se = Object.defineProperty;
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
- class F extends Error {
1
+ var ee = Object.defineProperty;
2
+ var te = (h, e, t) => e in h ? ee(h, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[e] = t;
3
+ var o = (h, e, t) => te(h, typeof e != "symbol" ? e + "" : e, t);
4
+ class x extends Error {
5
5
  constructor(t, r, i = {}) {
6
- const s = F.createFormattedMessage(t, i);
6
+ const s = x.createFormattedMessage(t, i);
7
7
  super(s);
8
8
  o(this, "originalError");
9
9
  o(this, "context");
@@ -19,7 +19,7 @@ class F extends Error {
19
19
 
20
20
  📋 Context:`;
21
21
  for (const [s, a] of Object.entries(r)) {
22
- const n = F.formatValue(a);
22
+ const n = x.formatValue(a);
23
23
  i += `
24
24
  - ${s}: ${n}`;
25
25
  }
@@ -38,16 +38,16 @@ class F extends Error {
38
38
  if (typeof t == "string") return `"${t}"`;
39
39
  if (typeof t == "number" || typeof t == "boolean") return String(t);
40
40
  if (Array.isArray(t))
41
- return t.length === 0 ? "[]" : t.length <= 5 ? `[${t.map((r) => F.formatValue(r)).join(", ")}]` : `[${t.slice(0, 3).map((r) => F.formatValue(r)).join(", ")}, ... +${t.length - 3} more]`;
41
+ return t.length === 0 ? "[]" : t.length <= 5 ? `[${t.map((r) => x.formatValue(r)).join(", ")}]` : `[${t.slice(0, 3).map((r) => x.formatValue(r)).join(", ")}, ... +${t.length - 3} more]`;
42
42
  if (typeof t == "object") {
43
43
  const r = Object.keys(t);
44
- return r.length === 0 ? "{}" : r.length <= 3 ? `{ ${r.map((a) => `${a}: ${F.formatValue(t[a])}`).join(", ")} }` : `{ ${r.slice(0, 2).map((s) => `${s}: ${F.formatValue(t[s])}`).join(", ")}, ... +${r.length - 2} more }`;
44
+ return r.length === 0 ? "{}" : r.length <= 3 ? `{ ${r.map((a) => `${a}: ${x.formatValue(t[a])}`).join(", ")} }` : `{ ${r.slice(0, 2).map((s) => `${s}: ${x.formatValue(t[s])}`).join(", ")}, ... +${r.length - 2} more }`;
45
45
  }
46
46
  return String(t);
47
47
  }
48
48
  }
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
- const E = class E {
49
+ var re = /* @__PURE__ */ ((h) => (h[h.SILENT = 0] = "SILENT", h[h.WARNING = 1] = "WARNING", h[h.ERROR = 2] = "ERROR", h[h.THROW = 3] = "THROW", h))(re || {});
50
+ const A = class A {
51
51
  constructor() {
52
52
  o(this, "_options", {
53
53
  globalLevel: 3
@@ -55,7 +55,7 @@ const E = class E {
55
55
  });
56
56
  }
57
57
  static getInstance() {
58
- return E._instance || (E._instance = new E()), E._instance;
58
+ return A._instance || (A._instance = new A()), A._instance;
59
59
  }
60
60
  /**
61
61
  * Handle an error based on the configured settings
@@ -71,15 +71,15 @@ const E = class E {
71
71
  return console.group(
72
72
  `%c${i} Oops! (╯°□°)╯︵ Something went wrong in your code.`,
73
73
  "color: #f44336; font-weight: bold; background: #ffebee; padding: 2px 6px; border-radius: 3px;"
74
- ), console.warn(F.createFormattedMessage(e, t)), console.groupEnd(), !1;
74
+ ), console.warn(x.createFormattedMessage(e, t)), console.groupEnd(), !1;
75
75
  case 2:
76
76
  return console.group(
77
77
  `%c${i} Oops! (╯°□°)╯︵ Something went wrong in your code.`,
78
78
  "color: #f44336; font-weight: bold; background: #ffebee; padding: 2px 6px; border-radius: 3px;"
79
- ), console.error(F.createFormattedMessage(e, t)), console.groupEnd(), !1;
79
+ ), console.error(x.createFormattedMessage(e, t)), console.groupEnd(), !1;
80
80
  case 3:
81
81
  default:
82
- const s = new F(e, r, t);
82
+ const s = new x(e, r, t);
83
83
  throw console.group(
84
84
  `%c${i} Oops! (╯°□°)╯︵ Something went wrong in your code.`,
85
85
  "color: #d32f2f; font-weight: bold; background: #ffcdd2; padding: 2px 6px; border-radius: 3px;"
@@ -103,10 +103,19 @@ const E = class E {
103
103
  this._options.globalLevel = e;
104
104
  }
105
105
  };
106
- o(E, "_instance", null);
107
- let $ = E;
108
- const v = $.getInstance();
109
- class oe {
106
+ o(A, "_instance", null);
107
+ let z = A;
108
+ const _ = z.getInstance(), Z = /* @__PURE__ */ new WeakMap(), ie = /* @__PURE__ */ new WeakMap();
109
+ function P(h, e) {
110
+ Z.set(h, e);
111
+ }
112
+ function j(h) {
113
+ return Z.get(h);
114
+ }
115
+ function B(h, e) {
116
+ ie.set(h, e);
117
+ }
118
+ const I = class I {
110
119
  constructor(e, t, r = t, i = {}) {
111
120
  o(this, "gl");
112
121
  o(this, "_framebuffer");
@@ -116,6 +125,8 @@ class oe {
116
125
  o(this, "options");
117
126
  o(this, "previousState", null);
118
127
  o(this, "_pixels", null);
128
+ // Tracks the last upload origin; no longer required for rendering since we flip at upload time
129
+ o(this, "_isFromCanvasSource", !1);
119
130
  this.gl = e, this._width = t, this._height = r, this.options = {
120
131
  filter: "nearest",
121
132
  wrap: "clamp",
@@ -124,6 +135,20 @@ class oe {
124
135
  ...i
125
136
  }, this._texture = this.createTexture(), this._framebuffer = e.createFramebuffer(), this.attachTexture();
126
137
  }
138
+ getMaxTextureUnits() {
139
+ let e = I.maxTextureUnitsMap.get(this.gl);
140
+ return e === void 0 && (e = this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS), I.maxTextureUnitsMap.set(this.gl, e)), e;
141
+ }
142
+ /**
143
+ * Unbind the provided texture from any texture unit where it is currently bound.
144
+ * This prevents framebuffer-texture feedback loops when rendering to this framebuffer.
145
+ */
146
+ unbindTextureAcrossUnits(e) {
147
+ const t = this.gl, r = t.getParameter(t.ACTIVE_TEXTURE), i = this.getMaxTextureUnits();
148
+ for (let s = 0; s < i; s++)
149
+ t.activeTexture(t.TEXTURE0 + s), t.getParameter(t.TEXTURE_BINDING_2D) === e && t.bindTexture(t.TEXTURE_2D, null);
150
+ t.activeTexture(r);
151
+ }
127
152
  createTexture() {
128
153
  const { gl: e } = this, t = e.createTexture();
129
154
  e.bindTexture(e.TEXTURE_2D, t);
@@ -143,14 +168,18 @@ class oe {
143
168
  */
144
169
  update(e) {
145
170
  const { gl: t } = this;
146
- e instanceof HTMLVideoElement && e.readyState < 2 || (t.bindTexture(t.TEXTURE_2D, this._texture), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, e), t.bindTexture(t.TEXTURE_2D, null));
171
+ if (e instanceof HTMLVideoElement && e.readyState < 2)
172
+ return;
173
+ t.bindTexture(t.TEXTURE_2D, this._texture);
174
+ const r = t.getParameter(t.UNPACK_FLIP_Y_WEBGL);
175
+ t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL, 1), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, e), t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL, r ? 1 : 0), t.bindTexture(t.TEXTURE_2D, null), this._isFromCanvasSource = !1;
147
176
  }
148
177
  /**
149
178
  * Update the framebuffer texture with pixel data
150
179
  */
151
180
  updatePixels(e, t, r) {
152
181
  const { gl: i } = this;
153
- i.bindTexture(i.TEXTURE_2D, this._texture), i.texImage2D(i.TEXTURE_2D, 0, i.RGBA, t, r, 0, i.RGBA, i.UNSIGNED_BYTE, e), i.bindTexture(i.TEXTURE_2D, null);
182
+ i.bindTexture(i.TEXTURE_2D, this._texture), i.texImage2D(i.TEXTURE_2D, 0, i.RGBA, t, r, 0, i.RGBA, i.UNSIGNED_BYTE, e), i.bindTexture(i.TEXTURE_2D, null), this._isFromCanvasSource = !1;
154
183
  }
155
184
  /**
156
185
  * Resize the framebuffer
@@ -167,7 +196,7 @@ class oe {
167
196
  this.previousState = {
168
197
  framebuffer: e.getParameter(e.FRAMEBUFFER_BINDING),
169
198
  viewport: e.getParameter(e.VIEWPORT)
170
- }, e.bindFramebuffer(e.FRAMEBUFFER, this._framebuffer), e.viewport(0, 0, this._width, this._height);
199
+ }, e.bindFramebuffer(e.FRAMEBUFFER, this._framebuffer), e.viewport(0, 0, this._width, this._height), this.unbindTextureAcrossUnits(this._texture), B(e, !0), P(e, [0, 0, this._width, this._height]), this._isFromCanvasSource = !1;
171
200
  }
172
201
  /**
173
202
  * End rendering to this framebuffer and restore previous state
@@ -175,7 +204,7 @@ class oe {
175
204
  end() {
176
205
  if (!this.previousState) return;
177
206
  const { gl: e } = this;
178
- e.bindFramebuffer(e.FRAMEBUFFER, this.previousState.framebuffer), e.viewport(...this.previousState.viewport), this.previousState = null;
207
+ e.bindFramebuffer(e.FRAMEBUFFER, this.previousState.framebuffer), e.viewport(...this.previousState.viewport), B(e, !!this.previousState.framebuffer), P(e, this.previousState.viewport), this.previousState = null;
179
208
  }
180
209
  /**
181
210
  * Load pixel data from the framebuffer into the pixels array
@@ -224,247 +253,14 @@ class oe {
224
253
  get pixels() {
225
254
  return this._pixels;
226
255
  }
227
- }
228
- class Q {
229
- constructor(e, t, r) {
230
- o(this, "gl");
231
- o(this, "x");
232
- o(this, "y");
233
- this.gl = e, this.x = t, this.y = r;
256
+ /** True if the last content update came from a canvas/video or raw pixels (top-left origin). False if rendered via FBO (bottom-left). */
257
+ get isFromCanvasSource() {
258
+ return this._isFromCanvasSource;
234
259
  }
235
- }
236
- class M {
237
- constructor(e, t, r, i, s) {
238
- /** The WebGL rendering context */
239
- o(this, "gl");
240
- /** The vertex buffer containing position and texture coordinates */
241
- o(this, "vertexBuffer");
242
- /** The number of vertices in this geometry (always 6 for two triangles) */
243
- o(this, "vertexCount", 6);
244
- /** Bytes per vertex: depends on position format (vec2 vs vec3) */
245
- o(this, "bytesPerVertex");
246
- this.gl = e, this.bytesPerVertex = 16;
247
- 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;
248
- let f, g;
249
- c ? (f = r / l * 2 - 1, g = (r + s) / l * 2 - 1) : (f = 1 - r / l * 2, g = 1 - (r + s) / l * 2);
250
- let _, p, b, C;
251
- _ = u, b = d, p = f, C = g;
252
- const x = this.generateVertices(_, p, b, C);
253
- this.vertexBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer), e.bufferData(e.ARRAY_BUFFER, x, e.STATIC_DRAW);
254
- }
255
- /**
256
- * Generate vertex data for the rectangle with texture coordinates
257
- * @private
258
- */
259
- generateVertices(e, t, r, i) {
260
- return new Float32Array([
261
- e,
262
- i,
263
- 0,
264
- 1,
265
- // bottom-left
266
- r,
267
- i,
268
- 1,
269
- 1,
270
- // bottom-right
271
- e,
272
- t,
273
- 0,
274
- 0,
275
- // top-left
276
- e,
277
- t,
278
- 0,
279
- 0,
280
- // top-left
281
- r,
282
- i,
283
- 1,
284
- 1,
285
- // bottom-right
286
- r,
287
- t,
288
- 1,
289
- 0
290
- // top-right
291
- ]);
292
- }
293
- /**
294
- * Render the rectangle using position and texture coordinate attributes
295
- */
296
- render() {
297
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
298
- const e = this.gl.getParameter(this.gl.CURRENT_PROGRAM);
299
- let t = this.gl.getAttribLocation(e, "a_position"), r = this.gl.getAttribLocation(e, "a_texCoord");
300
- 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);
301
- }
302
- }
303
- class he extends Q {
304
- constructor(t, r, i, s, a) {
305
- super(t, r, i);
306
- o(this, "width");
307
- o(this, "height");
308
- this.width = s, this.height = a;
309
- }
310
- /**
311
- * Render the filled rectangle using the existing Rectangle geometry.
312
- */
313
- renderFill() {
314
- new M(this.gl, this.x, this.y, this.width, this.height).render();
315
- }
316
- /**
317
- * Render the stroke rectangle as four separate Rectangle instances for each edge.
318
- * This approach ensures clean corners with proper overlap and leverages existing geometry.
319
- * @param weight The stroke thickness in pixels
320
- */
321
- renderStroke(t) {
322
- if (t <= 0) return;
323
- const r = new M(this.gl, this.x, this.y, this.width, t), i = new M(this.gl, this.x + this.width - t, this.y, t, this.height), s = new M(this.gl, this.x, this.y + this.height - t, this.width, t), a = new M(this.gl, this.x, this.y, t, this.height);
324
- r.render(), i.render(), s.render(), a.render();
325
- }
326
- }
327
- class le {
328
- constructor(e, t, r, i, s, a) {
329
- /** The WebGL rendering context */
330
- o(this, "gl");
331
- /** The vertex buffer containing position and texture coordinates */
332
- o(this, "vertexBuffer");
333
- /** The number of vertices in this geometry (always 6 for two triangles) */
334
- o(this, "vertexCount", 6);
335
- /** Bytes per vertex: vec2+vec2 = 16 bytes */
336
- o(this, "bytesPerVertex");
337
- this.gl = e, this.bytesPerVertex = 16;
338
- 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);
339
- if (g === 0) {
340
- const ie = this.generateVertices(0, 0, 0, 0);
341
- this.vertexBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer), e.bufferData(e.ARRAY_BUFFER, ie, e.STATIC_DRAW);
342
- return;
343
- }
344
- const _ = d / g, b = -(f / g), C = _, x = a / 2, w = t + b * x, A = r + C * x, R = t - b * x, S = r - C * x, P = i + b * x, D = s + C * x, Z = i - b * x, W = s - C * x, J = w / l * 2 - 1, K = R / l * 2 - 1, ee = P / l * 2 - 1, te = Z / l * 2 - 1;
345
- let B, G, V, k;
346
- u ? (B = A / c * 2 - 1, G = S / c * 2 - 1, V = D / c * 2 - 1, k = W / c * 2 - 1) : (B = 1 - A / c * 2, G = 1 - S / c * 2, V = 1 - D / c * 2, k = 1 - W / c * 2);
347
- const re = this.generateLineVertices(
348
- J,
349
- B,
350
- K,
351
- G,
352
- ee,
353
- V,
354
- te,
355
- k
356
- );
357
- this.vertexBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer), e.bufferData(e.ARRAY_BUFFER, re, e.STATIC_DRAW);
358
- }
359
- /**
360
- * Generate vertex data for a rectangle representing the line with texture coordinates
361
- * @private
362
- */
363
- generateVertices(e, t, r, i) {
364
- return new Float32Array([
365
- e,
366
- i,
367
- 0,
368
- 1,
369
- // bottom-left
370
- r,
371
- i,
372
- 1,
373
- 1,
374
- // bottom-right
375
- e,
376
- t,
377
- 0,
378
- 0,
379
- // top-left
380
- e,
381
- t,
382
- 0,
383
- 0,
384
- // top-left
385
- r,
386
- i,
387
- 1,
388
- 1,
389
- // bottom-right
390
- r,
391
- t,
392
- 1,
393
- 0
394
- // top-right
395
- ]);
396
- }
397
- /**
398
- * Generate vertex data for the line rectangle with texture coordinates
399
- * Uses the four corners calculated based on line direction and thickness
400
- * @private
401
- */
402
- generateLineVertices(e, t, r, i, s, a, n, l) {
403
- return new Float32Array([
404
- e,
405
- t,
406
- 0,
407
- 0,
408
- // corner1 (start + perpendicular)
409
- r,
410
- i,
411
- 0,
412
- 1,
413
- // corner2 (start - perpendicular)
414
- s,
415
- a,
416
- 1,
417
- 0,
418
- // corner3 (end + perpendicular)
419
- r,
420
- i,
421
- 0,
422
- 1,
423
- // corner2 (start - perpendicular)
424
- n,
425
- l,
426
- 1,
427
- 1,
428
- // corner4 (end - perpendicular)
429
- s,
430
- a,
431
- 1,
432
- 0
433
- // corner3 (end + perpendicular)
434
- ]);
435
- }
436
- /**
437
- * Render the line using position and texture coordinate attributes
438
- */
439
- render() {
440
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
441
- const e = this.gl.getParameter(this.gl.CURRENT_PROGRAM);
442
- let t = this.gl.getAttribLocation(e, "a_position"), r = this.gl.getAttribLocation(e, "a_texCoord");
443
- 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);
444
- }
445
- }
446
- class ce extends Q {
447
- constructor(t, r, i, s, a) {
448
- super(t, r, i);
449
- o(this, "x2");
450
- o(this, "y2");
451
- this.x2 = s, this.y2 = a;
452
- }
453
- /**
454
- * Lines don't support fill rendering - this method does nothing.
455
- * Lines are rendered only with stroke properties.
456
- */
457
- renderFill() {
458
- }
459
- /**
460
- * Render the line with the specified stroke weight.
461
- * @param weight The stroke thickness in pixels
462
- */
463
- renderStroke(t) {
464
- if (t <= 0) return;
465
- new le(this.gl, this.x, this.y, this.x2, this.y2, t).render();
466
- }
467
- }
260
+ };
261
+ /** Cache for MAX_TEXTURE_IMAGE_UNITS per-context */
262
+ o(I, "maxTextureUnitsMap", /* @__PURE__ */ new WeakMap());
263
+ let $ = I;
468
264
  class y {
469
265
  constructor(e, t, r) {
470
266
  o(this, "gl");
@@ -612,13 +408,15 @@ class y {
612
408
  this.textureUnitCounter = 0;
613
409
  }
614
410
  }
615
- var T = "attribute vec2 a_position;attribute vec2 a_texCoord;varying vec2 v_uv;uniform float u_rotation;uniform vec2 u_center;uniform float u_aspectRatio;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){v_uv=a_texCoord;vec2 pos=a_position;pos-=u_center;pos.x*=u_aspectRatio;pos=rotate2D(-u_rotation)*pos;pos.x/=u_aspectRatio;pos+=u_center;gl_Position=vec4(pos,0.0,1.0);}", ue = "precision lowp float;uniform sampler2D u_texture;varying vec2 v_uv;void main(){gl_FragColor=texture2D(u_texture,v_uv);}", de = "precision lowp float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}";
616
- class fe {
411
+ var T = "attribute vec2 a_position;attribute vec2 a_texCoord;varying vec2 v_uv;uniform float u_rotation;uniform vec2 u_center;uniform float u_aspectRatio;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){v_uv=a_texCoord;vec2 pos=a_position;pos-=u_center;pos.x*=u_aspectRatio;pos=rotate2D(-u_rotation)*pos;pos.x/=u_aspectRatio;pos+=u_center;gl_Position=vec4(pos,0.0,1.0);}", se = "precision lowp float;uniform sampler2D u_texture;varying vec2 v_uv;void main(){gl_FragColor=texture2D(u_texture,v_uv);}", ae = "precision lowp float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}";
412
+ class ne {
617
413
  constructor(e) {
618
414
  o(this, "gl");
619
415
  o(this, "imageShader");
620
416
  o(this, "solidColorShader");
621
417
  o(this, "currentShader", null);
418
+ // Cached attrib locations for current program
419
+ o(this, "attribCache");
622
420
  // Fill state management - default: white fill enabled
623
421
  o(this, "currentFillColor", [1, 1, 1, 1]);
624
422
  o(this, "fillMode", !0);
@@ -631,13 +429,18 @@ class fe {
631
429
  // in degrees
632
430
  // State stack for push/pop functionality
633
431
  o(this, "stateStack", []);
634
- this.gl = e, this.imageShader = new y(this.gl, T, ue), this.solidColorShader = new y(this.gl, T, de), this.gl.enable(this.gl.BLEND), this.gl.blendEquation(this.gl.FUNC_ADD), this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
432
+ // ----- Immediate-mode helpers that use a single static VBO (no per-call allocation) -----
433
+ o(this, "unitBuffer", null);
434
+ o(this, "bytesPerVertex", 16);
435
+ // vec2 + vec2
436
+ o(this, "scratchFramebuffer", null);
437
+ this.gl = e, this.imageShader = new y(this.gl, T, se), this.solidColorShader = new y(this.gl, T, ae), this.attribCache = /* @__PURE__ */ new Map(), this.gl.enable(this.gl.BLEND), this.gl.blendEquation(this.gl.FUNC_ADD), this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA), P(this.gl, [0, 0, this.gl.canvas.width, this.gl.canvas.height]), B(this.gl, !1);
635
438
  }
636
439
  /**
637
440
  * Set the current shader
638
441
  */
639
442
  shader(e) {
640
- this.currentShader = e, e.use();
443
+ this.currentShader !== e && (this.currentShader = e, e.use());
641
444
  }
642
445
  /**
643
446
  * Sets the fill color for subsequent rendering operations
@@ -729,7 +532,7 @@ class fe {
729
532
  * across frames and be managed by push/pop or explicit calls.
730
533
  */
731
534
  reset() {
732
- this.currentShader = null, this.stateStack = [], this.currentRotation = 0, this.fillMode = !0, this.strokeMode = !0, this.currentFillColor = [1, 1, 1, 1], this.currentStrokeColor = [0, 0, 0, 1], this.currentStrokeWeight = 1;
535
+ this.currentShader = null, this.stateStack = [], this.currentRotation = 0;
733
536
  }
734
537
  createShader(e, t) {
735
538
  return new y(this.gl, e, t);
@@ -747,18 +550,22 @@ class fe {
747
550
  * Draw a rectangle with the current fill and/or stroke settings
748
551
  */
749
552
  rect(e, t, r, i) {
750
- const s = new he(this.gl, e, t, r, i);
751
553
  if (this.currentShader !== null) {
752
554
  if (this.currentRotation !== 0) {
753
- const { centerX: d, centerY: f, radians: g, aspectRatio: _ } = this.calculateRotationParams(e, t, r, i);
754
- this.setUniform("u_rotation", g), this.setUniform("u_center", [d, f]), this.setUniform("u_aspectRatio", _);
555
+ const { centerX: f, centerY: g, radians: v, aspectRatio: p } = this.calculateRotationParams(e, t, r, i);
556
+ this.setUniform("u_rotation", v), this.setUniform("u_center", [f, g]), this.setUniform("u_aspectRatio", p);
755
557
  } else
756
558
  this.setUniform("u_rotation", 0), this.setUniform("u_center", [0, 0]), this.setUniform("u_aspectRatio", 1);
757
- s.renderFill(), this.currentShader = null;
559
+ this.drawRectImmediate(e, t, r, i), this.currentShader = null;
758
560
  return;
759
561
  }
760
- const a = this.solidColorShader, { centerX: n, centerY: l, radians: c, aspectRatio: u } = this.calculateRotationParams(e, t, r, i);
761
- 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;
562
+ const a = this.solidColorShader, n = this.currentRotation !== 0;
563
+ let l = 0, c = 0, u = 0, d = 1;
564
+ if (n) {
565
+ const f = this.calculateRotationParams(e, t, r, i);
566
+ l = f.centerX, c = f.centerY, u = f.radians, d = f.aspectRatio;
567
+ }
568
+ this.fillMode && (this.shader(a), this.setUniform("u_color", this.currentFillColor), n && (this.setUniform("u_rotation", u), this.setUniform("u_center", [l, c]), this.setUniform("u_aspectRatio", d)), this.drawRectImmediate(e, t, r, i)), this.strokeMode && this.currentStrokeWeight > 0 && (this.shader(a), this.setUniform("u_color", this.currentStrokeColor), n && (this.setUniform("u_rotation", u), this.setUniform("u_center", [l, c]), this.setUniform("u_aspectRatio", d)), this.drawRectStrokeImmediate(e, t, r, i, this.currentStrokeWeight));
762
569
  }
763
570
  /**
764
571
  * Draw a line from (x1, y1) to (x2, y2) with the current stroke settings.
@@ -769,35 +576,38 @@ class fe {
769
576
  * @param y2 Y-coordinate of the line end point
770
577
  */
771
578
  line(e, t, r, i) {
772
- if (!this.strokeMode) return;
773
- const s = new ce(this.gl, e, t, r, i);
774
579
  if (this.currentShader !== null) {
580
+ const b = (e + r) / 2, w = (t + i) / 2, F = Math.abs(r - e) || 1, C = Math.abs(i - t) || 1;
775
581
  if (this.currentRotation !== 0) {
776
- const p = (e + r) / 2, b = (t + i) / 2, C = Math.abs(r - e), x = Math.abs(i - t), { centerX: w, centerY: A, radians: R, aspectRatio: S } = this.calculateRotationParams(p - C / 2, b - x / 2, C, x);
777
- this.setUniform("u_rotation", R), this.setUniform("u_center", [w, A]), this.setUniform("u_aspectRatio", S);
582
+ const { centerX: U, centerY: S, radians: R, aspectRatio: E } = this.calculateRotationParams(b - F / 2, w - C / 2, F, C);
583
+ this.setUniform("u_rotation", R), this.setUniform("u_center", [U, S]), this.setUniform("u_aspectRatio", E);
778
584
  } else
779
585
  this.setUniform("u_rotation", 0), this.setUniform("u_center", [0, 0]), this.setUniform("u_aspectRatio", 1);
780
- s.renderStroke(this.currentStrokeWeight), this.currentShader = null;
586
+ const G = this.currentStrokeWeight > 0 ? this.currentStrokeWeight : 1;
587
+ this.drawLineImmediate(e, t, r, i, G), this.currentShader = null;
781
588
  return;
782
589
  }
783
- 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: _ } = this.calculateRotationParams(n - c / 2, l - u / 2, c, u);
784
- this.shader(a), this.setUniform("u_color", this.currentStrokeColor), this.setUniform("u_rotation", g), this.setUniform("u_center", [d, f]), this.setUniform("u_aspectRatio", _), s.renderStroke(this.currentStrokeWeight), this.currentShader = null;
590
+ if (!this.strokeMode || this.currentStrokeWeight <= 0) return;
591
+ const a = this.solidColorShader, n = (e + r) / 2, l = (t + i) / 2, c = Math.abs(r - e) || 1, u = Math.abs(i - t) || 1, d = this.currentRotation !== 0;
592
+ let f = 0, g = 0, v = 0, p = 1;
593
+ if (d) {
594
+ const b = this.calculateRotationParams(n - c / 2, l - u / 2, c, u);
595
+ f = b.centerX, g = b.centerY, v = b.radians, p = b.aspectRatio;
596
+ }
597
+ this.shader(a), this.setUniform("u_color", this.currentStrokeColor), d && (this.setUniform("u_rotation", v), this.setUniform("u_center", [f, g]), this.setUniform("u_aspectRatio", p)), this.drawLineImmediate(e, t, r, i, this.currentStrokeWeight);
785
598
  }
786
599
  /**
787
600
  * Calculate rotation parameters for built-in shaders (NDC coordinates)
788
601
  */
789
602
  calculateRotationParams(e, t, r, i) {
790
- 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;
791
- let g;
792
- c ? g = d / n * 2 - 1 : g = 1 - d / n * 2;
793
- const _ = this.currentRotation * Math.PI / 180;
794
- return { centerX: f, centerY: g, radians: _, aspectRatio: l };
603
+ const s = j(this.gl) || [0, 0, this.gl.canvas.width, this.gl.canvas.height], a = s[2], n = s[3], l = a / n, c = e + r / 2, u = t + i / 2, d = c / a * 2 - 1, f = 1 - u / n * 2, g = this.currentRotation * Math.PI / 180;
604
+ return { centerX: d, centerY: f, radians: g, aspectRatio: l };
795
605
  }
796
606
  /**
797
607
  * Create a new framebuffer
798
608
  */
799
609
  createFramebuffer(e, t, r = {}) {
800
- return new oe(this.gl, e, t, r);
610
+ return new $(this.gl, e, t, r);
801
611
  }
802
612
  /**
803
613
  * Fill the current framebuffer with a solid color
@@ -815,7 +625,7 @@ class fe {
815
625
  * Ensure viewport matches canvas dimensions
816
626
  */
817
627
  resetViewport() {
818
- this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
628
+ this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height), P(this.gl, [0, 0, this.gl.canvas.width, this.gl.canvas.height]), B(this.gl, !1);
819
629
  }
820
630
  /**
821
631
  * Get the WebGL context
@@ -828,20 +638,127 @@ class fe {
828
638
  * This method is idempotent and safe to call multiple times.
829
639
  */
830
640
  dispose() {
831
- this.imageShader.dispose(), this.solidColorShader.dispose(), this.imageShader = null, this.solidColorShader = null, this.currentShader = null, this.stateStack = [];
641
+ this.scratchFramebuffer && (this.scratchFramebuffer.dispose(), this.scratchFramebuffer = null), this.imageShader.dispose(), this.solidColorShader.dispose(), this.imageShader = null, this.solidColorShader = null, this.currentShader = null, this.stateStack = [];
832
642
  }
833
643
  /**
834
644
  * Render a framebuffer at a specific position with optional scaling
835
645
  */
836
646
  image(e, t, r, i, s) {
647
+ const a = this.gl, n = i ?? e.width, l = s ?? e.height, c = a.getParameter(a.FRAMEBUFFER_BINDING);
648
+ if (c && e.framebuffer === c) {
649
+ (!this.scratchFramebuffer || this.scratchFramebuffer.width !== n || this.scratchFramebuffer.height !== l) && (this.scratchFramebuffer && this.scratchFramebuffer.dispose(), this.scratchFramebuffer = this.createFramebuffer(n, l)), this.scratchFramebuffer.begin(), this.clear(0, 0, 0, 0), this.shader(this.imageShader), this.setUniform("u_texture", e.texture), this.setUniform("u_rotation", 0), this.setUniform("u_center", [0, 0]), this.setUniform("u_aspectRatio", 1), this.drawRectImmediate(0, 0, n, l), this.scratchFramebuffer.end(), this.shader(this.imageShader);
650
+ const d = this.currentRotation !== 0 ? this.calculateRotationParams(t, r, n, l) : { centerX: 0, centerY: 0, radians: 0, aspectRatio: 1 };
651
+ this.setUniform("u_texture", this.scratchFramebuffer.texture), this.setUniform("u_rotation", d.radians), this.setUniform("u_center", [d.centerX, d.centerY]), this.setUniform("u_aspectRatio", d.aspectRatio), this.drawRectImmediate(t, r, n, l), a.bindTexture(a.TEXTURE_2D, null), this.currentShader = null;
652
+ return;
653
+ }
837
654
  this.shader(this.imageShader), this.setUniform("u_texture", e.texture);
838
- const { centerX: a, centerY: n, radians: l, aspectRatio: c } = this.calculateRotationParams(
655
+ const u = this.currentRotation !== 0 ? this.calculateRotationParams(t, r, n, l) : { centerX: 0, centerY: 0, radians: 0, aspectRatio: 1 };
656
+ this.setUniform("u_rotation", u.radians), this.setUniform("u_center", [u.centerX, u.centerY]), this.setUniform("u_aspectRatio", u.aspectRatio), this.drawRectImmediate(t, r, n, l), a.bindTexture(a.TEXTURE_2D, null), this.currentShader = null;
657
+ }
658
+ ensureUnitBuffer() {
659
+ if (this.unitBuffer) return;
660
+ const e = this.gl;
661
+ this.unitBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.unitBuffer);
662
+ }
663
+ enableAttribs() {
664
+ const e = this.gl, t = e.getParameter(e.CURRENT_PROGRAM);
665
+ let r = this.attribCache.get(t);
666
+ return r || (r = {
667
+ a_position: e.getAttribLocation(t, "a_position"),
668
+ a_texCoord: e.getAttribLocation(t, "a_texCoord")
669
+ }, this.attribCache.set(t, r)), e.enableVertexAttribArray(r.a_position), e.vertexAttribPointer(r.a_position, 2, e.FLOAT, !1, this.bytesPerVertex, 0), e.enableVertexAttribArray(r.a_texCoord), e.vertexAttribPointer(r.a_texCoord, 2, e.FLOAT, !1, this.bytesPerVertex, 8), { positionLoc: r.a_position, texLoc: r.a_texCoord };
670
+ }
671
+ disableAttribs(e, t) {
672
+ const r = this.gl;
673
+ r.disableVertexAttribArray(e), r.disableVertexAttribArray(t);
674
+ }
675
+ uploadQuadNDC(e, t, r, i) {
676
+ const s = this.gl;
677
+ this.ensureUnitBuffer(), s.bindBuffer(s.ARRAY_BUFFER, this.unitBuffer);
678
+ const a = 0, n = 0, l = 1, c = 1, u = new Float32Array([
679
+ e,
680
+ i,
681
+ 0,
682
+ a,
683
+ // bottom-left
684
+ r,
685
+ i,
686
+ 1,
687
+ n,
688
+ // bottom-right
689
+ e,
690
+ t,
691
+ 0,
692
+ l,
693
+ // top-left
694
+ e,
839
695
  t,
696
+ 0,
697
+ l,
698
+ // top-left
840
699
  r,
841
- i ?? e.width,
842
- s ?? e.height
843
- );
844
- 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);
700
+ i,
701
+ 1,
702
+ n,
703
+ // bottom-right
704
+ r,
705
+ t,
706
+ 1,
707
+ c
708
+ // top-right
709
+ ]);
710
+ s.bufferData(s.ARRAY_BUFFER, u, s.DYNAMIC_DRAW);
711
+ }
712
+ toNDC(e, t) {
713
+ const r = this.gl, i = j(r) || [0, 0, r.canvas.width, r.canvas.height], s = i[2], a = i[3], n = e / s * 2 - 1, l = 1 - t / a * 2;
714
+ return { nx: n, ny: l };
715
+ }
716
+ drawRectImmediate(e, t, r, i) {
717
+ const s = this.toNDC(e, t), a = this.toNDC(e + r, t + i);
718
+ this.uploadQuadNDC(s.nx, s.ny, a.nx, a.ny);
719
+ const n = this.enableAttribs();
720
+ this.gl.drawArrays(this.gl.TRIANGLES, 0, 6), this.disableAttribs(n.positionLoc, n.texLoc);
721
+ }
722
+ drawRectStrokeImmediate(e, t, r, i, s) {
723
+ this.drawRectImmediate(e, t, r, s), this.drawRectImmediate(e + r - s, t, s, i), this.drawRectImmediate(e, t + i - s, r, s), this.drawRectImmediate(e, t, s, i);
724
+ }
725
+ drawLineImmediate(e, t, r, i, s) {
726
+ const a = r - e, n = i - t, l = Math.hypot(a, n);
727
+ if (l === 0) {
728
+ this.drawRectImmediate(e - s / 2, t - s / 2, s, s);
729
+ return;
730
+ }
731
+ const c = a / l, d = -(n / l), f = c, g = s / 2, v = e + d * g, p = t + f * g, b = e - d * g, w = t - f * g, F = r + d * g, C = i + f * g, G = r - d * g, U = i - f * g, S = this.toNDC(v, p), R = this.toNDC(b, w), E = this.toNDC(F, C), W = this.toNDC(G, U), M = this.gl;
732
+ this.ensureUnitBuffer(), M.bindBuffer(M.ARRAY_BUFFER, this.unitBuffer);
733
+ const J = new Float32Array([
734
+ S.nx,
735
+ S.ny,
736
+ 0,
737
+ 0,
738
+ R.nx,
739
+ R.ny,
740
+ 0,
741
+ 1,
742
+ E.nx,
743
+ E.ny,
744
+ 1,
745
+ 0,
746
+ R.nx,
747
+ R.ny,
748
+ 0,
749
+ 1,
750
+ W.nx,
751
+ W.ny,
752
+ 1,
753
+ 1,
754
+ E.nx,
755
+ E.ny,
756
+ 1,
757
+ 0
758
+ ]);
759
+ M.bufferData(M.ARRAY_BUFFER, J, M.DYNAMIC_DRAW);
760
+ const Y = this.enableAttribs();
761
+ M.drawArrays(M.TRIANGLES, 0, 6), this.disableAttribs(Y.positionLoc, Y.texLoc);
845
762
  }
846
763
  }
847
764
  var m = {};
@@ -859,8 +776,8 @@ m.parse = function(h) {
859
776
  for (var f in u) {
860
777
  var g = m.findTable(s, f, n);
861
778
  if (g) {
862
- var _ = g[0], p = l[_];
863
- p == null && (p = u[f].parseTab(s, _, g[1], d)), d[f] = l[_] = p;
779
+ var v = g[0], p = l[v];
780
+ p == null && (p = u[f].parseTab(s, v, g[1], d)), d[f] = l[v] = p;
864
781
  }
865
782
  }
866
783
  return d;
@@ -925,15 +842,15 @@ m.T.cmap = {
925
842
  e += 2;
926
843
  var f = i.readUint(h, e);
927
844
  e += 4;
928
- var g = "p" + u + "e" + d, _ = l.indexOf(f);
929
- if (_ == -1) {
930
- _ = r.tables.length;
845
+ var g = "p" + u + "e" + d, v = l.indexOf(f);
846
+ if (v == -1) {
847
+ v = r.tables.length;
931
848
  var p = {};
932
849
  l.push(f);
933
850
  var b = p.format = s(h, f);
934
851
  b == 4 ? p = a.parse4(h, f, p) : b == 12 && (p = a.parse12(h, f, p)), r.tables.push(p);
935
852
  }
936
- r.ids[g] != null && console.log("multiple tables for one platform+encoding: " + g), r.ids[g] = _;
853
+ r.ids[g] != null && console.log("multiple tables for one platform+encoding: " + g), r.ids[g] = v;
937
854
  }
938
855
  return r;
939
856
  },
@@ -1047,13 +964,13 @@ m.T.glyf = {
1047
964
  }
1048
965
  a.xs = [];
1049
966
  for (var n = 0; n < c; n++) {
1050
- var g = (a.flags[n] & 2) != 0, _ = (a.flags[n] & 16) != 0;
1051
- g ? (a.xs.push(_ ? r[s] : -r[s]), s++) : _ ? a.xs.push(0) : (a.xs.push(t.readShort(r, s)), s += 2);
967
+ var g = (a.flags[n] & 2) != 0, v = (a.flags[n] & 16) != 0;
968
+ g ? (a.xs.push(v ? r[s] : -r[s]), s++) : v ? a.xs.push(0) : (a.xs.push(t.readShort(r, s)), s += 2);
1052
969
  }
1053
970
  a.ys = [];
1054
971
  for (var n = 0; n < c; n++) {
1055
- var g = (a.flags[n] & 4) != 0, _ = (a.flags[n] & 32) != 0;
1056
- g ? (a.ys.push(_ ? r[s] : -r[s]), s++) : _ ? a.ys.push(0) : (a.ys.push(t.readShort(r, s)), s += 2);
972
+ var g = (a.flags[n] & 4) != 0, v = (a.flags[n] & 32) != 0;
973
+ g ? (a.ys.push(v ? r[s] : -r[s]), s++) : v ? a.ys.push(0) : (a.ys.push(t.readShort(r, s)), s += 2);
1057
974
  }
1058
975
  for (var p = 0, b = 0, n = 0; n < c; n++)
1059
976
  p += a.xs[n], b += a.ys[n], a.xs[n] = p, a.ys[n] = b;
@@ -1063,7 +980,7 @@ m.T.glyf = {
1063
980
  }
1064
981
  };
1065
982
  typeof module < "u" && module.exports ? module.exports = m : typeof window < "u" && (window.Typr = m);
1066
- class me {
983
+ class oe {
1067
984
  /**
1068
985
  * Extracts all available characters from a font's cmap tables.
1069
986
  * @param font The parsed font object from Typr
@@ -1160,7 +1077,7 @@ class me {
1160
1077
  return !(t >= 0 && t <= 31 && t !== 9 && t !== 10 && t !== 13 || t >= 127 && t <= 159);
1161
1078
  }
1162
1079
  }
1163
- class ge {
1080
+ class he {
1164
1081
  /**
1165
1082
  * Creates a new TextureAtlasCreation instance.
1166
1083
  * @param renderer The WebGL renderer instance
@@ -1229,7 +1146,7 @@ class ge {
1229
1146
  this._textureContext.putImageData(t, 0, 0);
1230
1147
  }
1231
1148
  }
1232
- class pe {
1149
+ class le {
1233
1150
  /**
1234
1151
  * Creates a new MetricsCalculation instance.
1235
1152
  */
@@ -1259,7 +1176,7 @@ class pe {
1259
1176
  };
1260
1177
  }
1261
1178
  }
1262
- class _e {
1179
+ class ce {
1263
1180
  /**
1264
1181
  * Creates TextmodeCharacter objects with unique color assignments.
1265
1182
  * @param characters Array of character strings
@@ -1326,7 +1243,7 @@ class _e {
1326
1243
  * @returns RGB color as a tuple [r, g, b], or [0, 0, 0] if not found
1327
1244
  */
1328
1245
  getCharacterColor(e, t) {
1329
- if (!v.validate(
1246
+ if (!_.validate(
1330
1247
  typeof e == "string" && e.length === 1,
1331
1248
  "Character must be a single character string.",
1332
1249
  { method: "getCharacterColor", providedValue: e }
@@ -1342,14 +1259,14 @@ class _e {
1342
1259
  * @returns Array of RGB colors for each character
1343
1260
  */
1344
1261
  getCharacterColors(e, t) {
1345
- return v.validate(
1262
+ return _.validate(
1346
1263
  typeof e == "string" && e.length > 0,
1347
1264
  "Characters must be a string with at least one character.",
1348
1265
  { method: "getCharacterColors", providedValue: e }
1349
1266
  ) ? e.split("").map((r) => this.getCharacterColor(r, t) || [0, 0, 0]) : [[0, 0, 0]];
1350
1267
  }
1351
1268
  }
1352
- class ve {
1269
+ class ue {
1353
1270
  /**
1354
1271
  * Creates a new TextmodeFont instance.
1355
1272
  * @param renderer Renderer instance for texture creation
@@ -1371,7 +1288,7 @@ class ve {
1371
1288
  o(this, "_textureAtlas");
1372
1289
  o(this, "_metricsCalculator");
1373
1290
  o(this, "_characterColorMapper");
1374
- this._fontSize = t, this._characterExtractor = new me(), this._textureAtlas = new ge(e), this._metricsCalculator = new pe(), this._characterColorMapper = new _e();
1291
+ this._fontSize = t, this._characterExtractor = new oe(), this._textureAtlas = new he(e), this._metricsCalculator = new le(), this._characterColorMapper = new ce();
1375
1292
  }
1376
1293
  /**
1377
1294
  * Initializes the font manager by loading the font and creating the texture atlas.
@@ -1384,10 +1301,10 @@ class ve {
1384
1301
  if (e) {
1385
1302
  const r = await fetch(e);
1386
1303
  if (!r.ok)
1387
- throw new F(`Failed to load font file: ${r.status} ${r.statusText}`);
1304
+ throw new x(`Failed to load font file: ${r.status} ${r.statusText}`);
1388
1305
  t = await r.arrayBuffer();
1389
1306
  } else
1390
- throw new F("Embedded font not available. This appears to be a minified build - please provide `fontSource`.");
1307
+ throw new x("Embedded font not available. This appears to be a minified build - please provide `fontSource`.");
1391
1308
  await this._loadFontFace(t), this._font = m.parse(t)[0], await this._initializeFont();
1392
1309
  }
1393
1310
  /**
@@ -1420,7 +1337,7 @@ class ve {
1420
1337
  try {
1421
1338
  const t = await fetch(e);
1422
1339
  if (!t.ok)
1423
- throw new F(`Failed to load font file: ${t.status} ${t.statusText}`);
1340
+ throw new x(`Failed to load font file: ${t.status} ${t.statusText}`);
1424
1341
  const r = await t.arrayBuffer();
1425
1342
  await this._loadFontFace(r);
1426
1343
  const i = m.parse(r);
@@ -1428,7 +1345,7 @@ class ve {
1428
1345
  throw new Error("Failed to parse font file");
1429
1346
  this._font = i[0], await this._initializeFont();
1430
1347
  } catch (t) {
1431
- throw new F(`Failed to load font: ${t instanceof Error ? t.message : "Unknown error"}`, t);
1348
+ throw new x(`Failed to load font: ${t instanceof Error ? t.message : "Unknown error"}`, t);
1432
1349
  }
1433
1350
  }
1434
1351
  /**
@@ -1525,7 +1442,7 @@ class ve {
1525
1442
  return this._font;
1526
1443
  }
1527
1444
  }
1528
- class xe {
1445
+ class de {
1529
1446
  /**
1530
1447
  * Create a new grid instance.
1531
1448
  * @param canvas The canvas element used to determine the grid dimensions.
@@ -1660,7 +1577,7 @@ class xe {
1660
1577
  return this._offsetY;
1661
1578
  }
1662
1579
  }
1663
- class be {
1580
+ class fe {
1664
1581
  constructor(e, t = !1, r = {}) {
1665
1582
  o(this, "_canvas");
1666
1583
  o(this, "captureSource");
@@ -1724,7 +1641,7 @@ class be {
1724
1641
  powerPreference: "high-performance"
1725
1642
  }, t = this._canvas.getContext("webgl2", e) || this._canvas.getContext("webgl", e);
1726
1643
  if (!t)
1727
- throw new F("WebGL context could not be created. Ensure your browser supports WebGL.");
1644
+ throw new x("WebGL context could not be created. Ensure your browser supports WebGL.");
1728
1645
  return t;
1729
1646
  }
1730
1647
  /**
@@ -1777,7 +1694,7 @@ class be {
1777
1694
  return this._canvas.height;
1778
1695
  }
1779
1696
  }
1780
- class U {
1697
+ class D {
1781
1698
  /**
1782
1699
  * Creates a new TextmodeConverter instance.
1783
1700
  * @param renderer Renderer instance for texture creation
@@ -1856,7 +1773,7 @@ class U {
1856
1773
  return this._options;
1857
1774
  }
1858
1775
  }
1859
- class Ce {
1776
+ class me {
1860
1777
  /**
1861
1778
  * Create a new color palette instance.
1862
1779
  * @param renderer The renderer instance.
@@ -1911,18 +1828,18 @@ class Ce {
1911
1828
  return this._framebuffer.texture;
1912
1829
  }
1913
1830
  }
1914
- class O extends U {
1831
+ class N extends D {
1915
1832
  constructor(t, r, i, s = {}) {
1916
1833
  super(t, r, i, s);
1917
1834
  o(this, "palette");
1918
- this.palette = new Ce(this.renderer, this.fontManager.getCharacterColors(" .:-=+*%@#"));
1835
+ this.palette = new me(this.renderer, this.fontManager.getCharacterColors(" .:-=+*%@#"));
1919
1836
  }
1920
1837
  /**
1921
1838
  * Sets the characters used for mapping.
1922
1839
  * @param characters The characters to use for mapping, usually ordered from darkest to brightest.
1923
1840
  */
1924
1841
  characters(t) {
1925
- v.validate(
1842
+ _.validate(
1926
1843
  this.fontManager.hasAllCharacters(t),
1927
1844
  "One or more characters do not exist in the current font.",
1928
1845
  { method: "characters", providedValue: t }
@@ -1941,7 +1858,7 @@ class O extends U {
1941
1858
  if (typeof t == "string") {
1942
1859
  const u = this.parseHexColor(t);
1943
1860
  if (!u) {
1944
- v.validate(
1861
+ _.validate(
1945
1862
  !1,
1946
1863
  "Invalid hex color format. Use '#FF0000', '#F00', 'FF0000', or 'F00'.",
1947
1864
  { method: "characterColor", providedValue: t }
@@ -1949,7 +1866,7 @@ class O extends U {
1949
1866
  return;
1950
1867
  }
1951
1868
  [a, n, l, c] = u;
1952
- } else if (a = t, n = r !== void 0 ? r : t, l = i !== void 0 ? i : t, c = s, !v.validate(
1869
+ } else if (a = t, n = r !== void 0 ? r : t, l = i !== void 0 ? i : t, c = s, !_.validate(
1953
1870
  [a, n, l, c].every((u) => u >= 0 && u <= 255),
1954
1871
  "Character color values must be between 0 and 255",
1955
1872
  { method: "characterColor", providedValues: { r: a, g: n, b: l, a: c } }
@@ -1964,7 +1881,7 @@ class O extends U {
1964
1881
  * @param mode The color mode to use for characters.
1965
1882
  */
1966
1883
  characterColorMode(t) {
1967
- v.validate(
1884
+ _.validate(
1968
1885
  ["sampled", "fixed"].includes(t),
1969
1886
  "Invalid character color mode. Must be 'sampled' or 'fixed'.",
1970
1887
  { method: "characterColorMode", providedValue: t }
@@ -1983,7 +1900,7 @@ class O extends U {
1983
1900
  if (typeof t == "string") {
1984
1901
  const u = this.parseHexColor(t);
1985
1902
  if (!u) {
1986
- v.validate(
1903
+ _.validate(
1987
1904
  !1,
1988
1905
  "Invalid hex color format. Use '#FF0000', '#F00', 'FF0000', or 'F00'.",
1989
1906
  { method: "cellColor", providedValue: t }
@@ -1991,7 +1908,7 @@ class O extends U {
1991
1908
  return;
1992
1909
  }
1993
1910
  [a, n, l, c] = u;
1994
- } else if (a = t, n = r !== void 0 ? r : t, l = i !== void 0 ? i : t, c = s, !v.validate(
1911
+ } else if (a = t, n = r !== void 0 ? r : t, l = i !== void 0 ? i : t, c = s, !_.validate(
1995
1912
  [a, n, l, c].every((u) => u >= 0 && u <= 255),
1996
1913
  "Cell color values must be between 0 and 255",
1997
1914
  { method: "cellColor", providedValues: { r: a, g: n, b: l, a: c } }
@@ -2006,7 +1923,7 @@ class O extends U {
2006
1923
  * @param mode The color mode to use for background cells.
2007
1924
  */
2008
1925
  cellColorMode(t) {
2009
- v.validate(
1926
+ _.validate(
2010
1927
  ["sampled", "fixed"].includes(t),
2011
1928
  "Invalid cell color mode. Must be 'sampled' or 'fixed'.",
2012
1929
  { method: "cellColorMode", providedValue: t }
@@ -2017,7 +1934,7 @@ class O extends U {
2017
1934
  * @param invert If `true`, the character color becomes the cell color and vice versa.
2018
1935
  */
2019
1936
  invert(t) {
2020
- v.validate(
1937
+ _.validate(
2021
1938
  typeof t == "boolean" || typeof t == "number" && Number.isInteger(t),
2022
1939
  "Invert must be a boolean value or an integer (0 for false, any other number for true).",
2023
1940
  { method: "invert", providedValue: t }
@@ -2028,7 +1945,7 @@ class O extends U {
2028
1945
  * @param angle The rotation angle in degrees.
2029
1946
  */
2030
1947
  rotation(t) {
2031
- if (!v.validate(
1948
+ if (!_.validate(
2032
1949
  typeof t == "number",
2033
1950
  "Rotation angle must be a number.",
2034
1951
  { method: "rotation", providedValue: t }
@@ -2043,7 +1960,7 @@ class O extends U {
2043
1960
  * @param flip If `true`, characters are flipped horizontally. If `false`, no flip is applied.
2044
1961
  */
2045
1962
  flipHorizontally(t) {
2046
- v.validate(
1963
+ _.validate(
2047
1964
  typeof t == "boolean" || typeof t == "number" && Number.isInteger(t),
2048
1965
  "Flip horizontally must be a boolean value or an integer (0 for false, any other number for true).",
2049
1966
  { method: "flipHorizontally", providedValue: t }
@@ -2054,7 +1971,7 @@ class O extends U {
2054
1971
  * @param flip If `true`, characters are flipped vertically. If `false`, no flip is applied.
2055
1972
  */
2056
1973
  flipVertically(t) {
2057
- v.validate(
1974
+ _.validate(
2058
1975
  typeof t == "boolean" || typeof t == "number" && Number.isInteger(t),
2059
1976
  "Flip vertically must be a boolean value or an integer (0 for false, any other number for true).",
2060
1977
  { method: "flipVertically", providedValue: t }
@@ -2073,8 +1990,8 @@ class O extends U {
2073
1990
  return [r, i, s, 255];
2074
1991
  }
2075
1992
  }
2076
- var Fe = "precision lowp float;uniform sampler2D u_sketchTexture;uniform vec2 u_gridCellDimensions;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec2 cellCenter=(floor(v_uv*u_gridCellDimensions)+vec2(0.5))/u_gridCellDimensions;vec4 color=texture2D(u_sketchTexture,cellCenter);float brightness=dot(color.rgb,vec3(0.299,0.587,0.114));float brightnessValue=brightness*255.0;if(brightnessValue>=u_brightnessRange.x&&brightnessValue<=u_brightnessRange.y){gl_FragColor=color;}else{gl_FragColor=vec4(0.0);}}", we = "precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_fillColor;uniform bool u_useFixedColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){if(u_useFixedColor){gl_FragColor=u_fillColor;}else{gl_FragColor=sampleColor;}}else{gl_FragColor=vec4(0.0);}}", ye = "precision lowp float;uniform sampler2D u_sampleTexture;uniform bool u_invert;uniform bool u_flipHorizontally;uniform bool u_flipVertically;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){float invertValue=u_invert ? 1.0 : 0.0;float flipHValue=u_flipHorizontally ? 1.0 : 0.0;float flipVValue=u_flipVertically ? 1.0 : 0.0;gl_FragColor=vec4(invertValue,flipHValue,flipVValue,1.0);}else{gl_FragColor=vec4(0.0);}}", Te = "precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_rotationColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){gl_FragColor=u_rotationColor;}else{gl_FragColor=vec4(0.0);}}", Se = "precision lowp float;uniform sampler2D u_colorSampleFramebuffer;uniform sampler2D u_charPaletteTexture;uniform vec2 u_charPaletteSize;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec4 color=texture2D(u_colorSampleFramebuffer,v_uv);if(color.a==0.0){gl_FragColor=vec4(0.0);return;}float brightness=dot(color.rgb,vec3(0.299,0.587,0.114))*255.0;vec2 range=u_brightnessRange;if(brightness<range.x||brightness>range.y){gl_FragColor=vec4(0.0);return;}float t=(brightness-range.x)/(range.y-range.x);float idx=clamp(floor(t*u_charPaletteSize.x),0.0,u_charPaletteSize.x-1.0);vec3 charColor=texture2D(u_charPaletteTexture,vec2((idx+0.5)/u_charPaletteSize.x,0.0)).rgb;gl_FragColor=vec4(charColor,1.0);}";
2077
- const Re = {
1993
+ var ge = "precision lowp float;uniform sampler2D u_sketchTexture;uniform vec2 u_gridCellDimensions;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec2 cellCenter=(floor(v_uv*u_gridCellDimensions)+vec2(0.5))/u_gridCellDimensions;vec4 color=texture2D(u_sketchTexture,cellCenter);float brightness=dot(color.rgb,vec3(0.299,0.587,0.114));float brightnessValue=brightness*255.0;if(brightnessValue>=u_brightnessRange.x&&brightnessValue<=u_brightnessRange.y){gl_FragColor=color;}else{gl_FragColor=vec4(0.0);}}", pe = "precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_fillColor;uniform bool u_useFixedColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){if(u_useFixedColor){gl_FragColor=u_fillColor;}else{gl_FragColor=sampleColor;}}else{gl_FragColor=vec4(0.0);}}", _e = "precision lowp float;uniform sampler2D u_sampleTexture;uniform bool u_invert;uniform bool u_flipHorizontally;uniform bool u_flipVertically;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){float invertValue=u_invert ? 1.0 : 0.0;float flipHValue=u_flipHorizontally ? 1.0 : 0.0;float flipVValue=u_flipVertically ? 1.0 : 0.0;gl_FragColor=vec4(invertValue,flipHValue,flipVValue,1.0);}else{gl_FragColor=vec4(0.0);}}", ve = "precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_rotationColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){gl_FragColor=u_rotationColor;}else{gl_FragColor=vec4(0.0);}}", be = "precision lowp float;uniform sampler2D u_colorSampleFramebuffer;uniform sampler2D u_charPaletteTexture;uniform vec2 u_charPaletteSize;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec4 color=texture2D(u_colorSampleFramebuffer,v_uv);if(color.a==0.0){gl_FragColor=vec4(0.0);return;}float brightness=dot(color.rgb,vec3(0.299,0.587,0.114))*255.0;vec2 range=u_brightnessRange;if(brightness<range.x||brightness>range.y){gl_FragColor=vec4(0.0);return;}float t=(brightness-range.x)/(range.y-range.x);float idx=clamp(floor(t*u_charPaletteSize.x),0.0,u_charPaletteSize.x-1.0);vec3 charColor=texture2D(u_charPaletteTexture,vec2((idx+0.5)/u_charPaletteSize.x,0.0)).rgb;gl_FragColor=vec4(charColor,1.0);}";
1994
+ const xe = {
2078
1995
  /** Enable/disable the renderer */
2079
1996
  enabled: !0,
2080
1997
  /** Characters used for brightness mapping (from darkest to brightest) */
@@ -2100,7 +2017,7 @@ const Re = {
2100
2017
  /** Range of brightness values to map to ASCII characters */
2101
2018
  brightnessRange: [0, 255]
2102
2019
  };
2103
- class L extends O {
2020
+ class L extends N {
2104
2021
  /**
2105
2022
  * Creates a new TextmodeBrightnessConverter instance.
2106
2023
  * @param renderer Renderer instance for texture creation
@@ -2109,14 +2026,14 @@ class L extends O {
2109
2026
  * @ignore
2110
2027
  */
2111
2028
  constructor(t, r, i) {
2112
- super(t, r, i, { ...Re });
2029
+ super(t, r, i, { ...xe });
2113
2030
  o(this, "sampleShader");
2114
2031
  o(this, "colorFillShader");
2115
2032
  o(this, "charMappingShader");
2116
2033
  o(this, "transformFillShader");
2117
2034
  o(this, "rotationFillShader");
2118
2035
  o(this, "sampleFramebuffer");
2119
- this.sampleShader = new y(t.context, T, Fe), this.colorFillShader = new y(t.context, T, we), this.transformFillShader = new y(t.context, T, ye), this.rotationFillShader = new y(t.context, T, Te), this.charMappingShader = new y(t.context, T, Se), this.sampleFramebuffer = this.renderer.createFramebuffer(this.grid.cols, this.grid.rows);
2036
+ this.sampleShader = new y(t.context, T, ge), this.colorFillShader = new y(t.context, T, pe), this.transformFillShader = new y(t.context, T, _e), this.rotationFillShader = new y(t.context, T, ve), this.charMappingShader = new y(t.context, T, be), this.sampleFramebuffer = this.renderer.createFramebuffer(this.grid.cols, this.grid.rows);
2120
2037
  }
2121
2038
  convert(t) {
2122
2039
  this.sampleFramebuffer.begin(), this.renderer.clear(), this.renderer.shader(this.sampleShader), this.renderer.setUniform("u_sketchTexture", t), this.renderer.setUniform("u_gridCellDimensions", [this.grid.cols, this.grid.rows]), this.renderer.setUniform("u_brightnessRange", this._options.brightnessRange), this.renderer.rect(0, 0, this.grid.cols, this.grid.rows), this.sampleFramebuffer.end(), this._primaryColorFramebuffer.begin(), this.renderer.clear(), this.renderer.shader(this.colorFillShader), this.renderer.setUniform("u_sampleTexture", this.sampleFramebuffer.texture), this.renderer.setUniform("u_fillColor", this._options.characterColor), this.renderer.setUniform("u_useFixedColor", this._options.characterColorMode === "fixed"), this.renderer.rect(0, 0, this.grid.cols, this.grid.rows), this._primaryColorFramebuffer.end(), this._secondaryColorFramebuffer.begin(), this.renderer.clear(), this.renderer.shader(this.colorFillShader), this.renderer.setUniform("u_sampleTexture", this.sampleFramebuffer.texture), this.renderer.setUniform("u_fillColor", this._options.cellColor), this.renderer.setUniform("u_useFixedColor", this._options.cellColorMode === "fixed"), this.renderer.rect(0, 0, this.grid.cols, this.grid.rows), this._secondaryColorFramebuffer.end(), this._transformFramebuffer.begin(), this.renderer.clear(), this.renderer.shader(this.transformFillShader), this.renderer.setUniform("u_sampleTexture", this.sampleFramebuffer.texture), this.renderer.setUniform("u_invert", this._options.invert), this.renderer.setUniform("u_flipHorizontally", this._options.flipHorizontally), this.renderer.setUniform("u_flipVertically", this._options.flipVertically), this.renderer.rect(0, 0, this.grid.cols, this.grid.rows), this._transformFramebuffer.end(), this._rotationFramebuffer.begin(), this.renderer.clear(), this.renderer.shader(this.rotationFillShader), this.renderer.setUniform("u_sampleTexture", this.sampleFramebuffer.texture), this.renderer.setUniform("u_rotationColor", this._options.rotation), this.renderer.rect(0, 0, this.grid.cols, this.grid.rows), this._rotationFramebuffer.end(), this._characterFramebuffer.begin(), this.renderer.clear(0, 0, 0, 0), this.renderer.shader(this.charMappingShader), this.renderer.setUniform("u_colorSampleFramebuffer", this.sampleFramebuffer.texture), this.renderer.setUniform("u_charPaletteTexture", this.palette.texture), this.renderer.setUniform("u_charPaletteSize", [this.palette.colors.length, 1]), this.renderer.setUniform("u_brightnessRange", this._options.brightnessRange), this.renderer.rect(0, 0, this.grid.cols, this.grid.rows), this._characterFramebuffer.end();
@@ -2132,21 +2049,21 @@ class L extends O {
2132
2049
  * @param range Array of two numbers `[min, max]`, where `min` is darkest and `max` is brightest.
2133
2050
  */
2134
2051
  brightnessRange(t) {
2135
- v.validate(
2052
+ _.validate(
2136
2053
  Array.isArray(t) && t.length === 2 && t.every((r) => typeof r == "number" && r >= 0 && r <= 255),
2137
2054
  "Brightness range must be an array of two numbers between 0 and 255.",
2138
2055
  { method: "brightnessRange", providedValue: t }
2139
2056
  ) && (this._options.brightnessRange = t);
2140
2057
  }
2141
2058
  }
2142
- const Oe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2059
+ const Pe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2143
2060
  __proto__: null,
2144
2061
  TextmodeBrightnessConverter: L,
2145
- TextmodeConverter: U,
2146
- TextmodeFeatureConverter: O
2062
+ TextmodeConverter: D,
2063
+ TextmodeFeatureConverter: N
2147
2064
  }, Symbol.toStringTag, { value: "Module" }));
2148
- var Ee = "precision mediump float;uniform sampler2D u_characterTexture;uniform vec2 u_charsetDimensions;uniform sampler2D u_primaryColorTexture;uniform sampler2D u_secondaryColorTexture;uniform sampler2D u_transformTexture;uniform sampler2D u_asciiCharacterTexture;uniform sampler2D u_rotationTexture;uniform sampler2D u_captureTexture;uniform vec2 u_captureDimensions;uniform int u_backgroundMode;uniform vec2 u_gridCellDimensions;uniform vec2 u_gridPixelDimensions;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){vec2 adjustedCoord=gl_FragCoord.xy/u_gridPixelDimensions;vec2 gridCoord=adjustedCoord*u_gridCellDimensions;vec2 cellCoord=floor(gridCoord);vec2 charIndexTexCoord=(cellCoord+0.5)/u_gridCellDimensions;vec4 primaryColor=texture2D(u_primaryColorTexture,charIndexTexCoord);vec4 secondaryColor=texture2D(u_secondaryColorTexture,charIndexTexCoord);vec4 transformColor=texture2D(u_transformTexture,charIndexTexCoord);bool isInverted=transformColor.r>0.5;bool flipHorizontal=transformColor.g>0.5;bool flipVertical=transformColor.b>0.5;vec4 encodedIndexVec=texture2D(u_asciiCharacterTexture,charIndexTexCoord);if(encodedIndexVec.a<0.01){gl_FragColor=(u_backgroundMode==0)? vec4(0.0):texture2D(u_captureTexture,gl_FragCoord.xy/u_captureDimensions);return;}int charIndex=int(encodedIndexVec.r*255.0+0.5)+int(encodedIndexVec.g*255.0+0.5)*256;int charCol=int(mod(float(charIndex),u_charsetDimensions.x));int charRow=charIndex/int(u_charsetDimensions.x);vec2 charCoord=vec2(charCol,charRow)/u_charsetDimensions;vec4 rotationColor=texture2D(u_rotationTexture,charIndexTexCoord);float scaledAngle=rotationColor.r*255.0+rotationColor.g;float rotationAngle=(scaledAngle*360.0/255.0)*0.017453292;vec2 fractionalPart=fract(gridCoord)-0.5;if(flipHorizontal)fractionalPart.x=-fractionalPart.x;if(flipVertical)fractionalPart.y=-fractionalPart.y;fractionalPart=rotate2D(rotationAngle)*fractionalPart+0.5;vec2 cellSize=1.0/u_charsetDimensions;vec2 texCoord=charCoord+fractionalPart*cellSize;vec2 cellMax=charCoord+cellSize;if(any(lessThan(texCoord,charCoord))||any(greaterThan(texCoord,cellMax))){gl_FragColor=isInverted ? primaryColor : secondaryColor;return;}vec4 charTexel=texture2D(u_characterTexture,texCoord);if(isInverted)charTexel.rgb=1.0-charTexel.rgb;gl_FragColor=mix(secondaryColor,primaryColor,charTexel);}";
2149
- class Ue {
2065
+ var Ce = "precision mediump float;uniform sampler2D u_characterTexture;uniform vec2 u_charsetDimensions;uniform sampler2D u_primaryColorTexture;uniform sampler2D u_secondaryColorTexture;uniform sampler2D u_transformTexture;uniform sampler2D u_asciiCharacterTexture;uniform sampler2D u_rotationTexture;uniform sampler2D u_captureTexture;uniform vec2 u_captureDimensions;uniform int u_backgroundMode;uniform vec2 u_gridCellDimensions;uniform vec2 u_gridPixelDimensions;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){vec2 adjustedCoord=gl_FragCoord.xy/u_gridPixelDimensions;vec2 gridCoord=adjustedCoord*u_gridCellDimensions;vec2 cellCoord=floor(gridCoord);vec2 charIndexTexCoord=(cellCoord+0.5)/u_gridCellDimensions;vec4 primaryColor=texture2D(u_primaryColorTexture,charIndexTexCoord);vec4 secondaryColor=texture2D(u_secondaryColorTexture,charIndexTexCoord);vec4 transformColor=texture2D(u_transformTexture,charIndexTexCoord);bool isInverted=transformColor.r>0.5;bool flipHorizontal=transformColor.g>0.5;bool flipVertical=transformColor.b>0.5;vec4 encodedIndexVec=texture2D(u_asciiCharacterTexture,charIndexTexCoord);if(encodedIndexVec.a<0.01){gl_FragColor=(u_backgroundMode==0)? vec4(0.0):texture2D(u_captureTexture,gl_FragCoord.xy/u_captureDimensions);return;}int charIndex=int(encodedIndexVec.r*255.0+0.5)+int(encodedIndexVec.g*255.0+0.5)*256;int charCol=int(mod(float(charIndex),u_charsetDimensions.x));int charRow=charIndex/int(u_charsetDimensions.x);float flippedRow=(u_charsetDimensions.y-1.0)-float(charRow);vec2 charCoord=vec2(float(charCol),flippedRow)/u_charsetDimensions;vec4 rotationColor=texture2D(u_rotationTexture,charIndexTexCoord);float scaledAngle=rotationColor.r*255.0+rotationColor.g;float rotationAngle=(scaledAngle*360.0/255.0)*0.017453292;vec2 fractionalPart=fract(gridCoord)-0.5;if(flipHorizontal)fractionalPart.x=-fractionalPart.x;if(flipVertical)fractionalPart.y=-fractionalPart.y;fractionalPart=rotate2D(rotationAngle)*fractionalPart+0.5;vec2 cellSize=1.0/u_charsetDimensions;vec2 texCoord=charCoord+fractionalPart*cellSize;vec2 cellMax=charCoord+cellSize;if(any(lessThan(texCoord,charCoord))||any(greaterThan(texCoord,cellMax))){gl_FragColor=isInverted ? primaryColor : secondaryColor;return;}vec4 charTexel=texture2D(u_characterTexture,texCoord);if(isInverted)charTexel.rgb=1.0-charTexel.rgb;gl_FragColor=mix(secondaryColor,primaryColor,charTexel);}";
2066
+ class Fe {
2150
2067
  /**
2151
2068
  * Creates an instance of TextmodeConversionPipeline.
2152
2069
  * @param renderer The renderer to use for the pipeline.
@@ -2166,9 +2083,9 @@ class Ue {
2166
2083
  o(this, "_secondaryColorFramebuffer");
2167
2084
  o(this, "_rotationFramebuffer");
2168
2085
  o(this, "_transformFramebuffer");
2169
- this.renderer = e, this.font = t, this.grid = r, this._asciiShader = this.renderer.createShader(T, Ee), this.converters = [
2086
+ this.renderer = e, this.font = t, this.grid = r, this._asciiShader = this.renderer.createShader(T, Ce), this.converters = [
2170
2087
  { name: "brightness", converter: new L(e, t, r) },
2171
- { name: "custom", converter: new U(e, t, r) }
2088
+ { name: "custom", converter: new D(e, t, r) }
2172
2089
  ], this._characterFramebuffer = this.renderer.createFramebuffer(r.cols, r.rows), this._primaryColorFramebuffer = this.renderer.createFramebuffer(r.cols, r.rows), this._secondaryColorFramebuffer = this.renderer.createFramebuffer(r.cols, r.rows), this._rotationFramebuffer = this.renderer.createFramebuffer(r.cols, r.rows), this._transformFramebuffer = this.renderer.createFramebuffer(r.cols, r.rows), this._resultFramebuffer = this.renderer.createFramebuffer(this.grid.width, this.grid.height);
2173
2090
  }
2174
2091
  /**
@@ -2179,7 +2096,7 @@ class Ue {
2179
2096
  render(e) {
2180
2097
  for (const r of this.converters) {
2181
2098
  const i = r.converter;
2182
- i.options.enabled && i instanceof O && i.convert(e);
2099
+ i.options.enabled && i instanceof N && i.convert(e);
2183
2100
  }
2184
2101
  const t = (r, i) => {
2185
2102
  r.begin(), this.renderer.clear();
@@ -2197,15 +2114,15 @@ class Ue {
2197
2114
  * @returns The requested `TextmodeConverter` instance.
2198
2115
  */
2199
2116
  get(e) {
2200
- if (!v.validate(
2117
+ if (!_.validate(
2201
2118
  typeof e == "string" && e.length > 0,
2202
2119
  "Converter name must be a non-empty string.",
2203
2120
  { method: "converter", providedValue: e }
2204
2121
  ))
2205
2122
  return;
2206
2123
  const t = this.converters.find((i) => i.name === e), r = t == null ? void 0 : t.converter;
2207
- if (v.validate(
2208
- r instanceof U,
2124
+ if (_.validate(
2125
+ r instanceof D,
2209
2126
  `Converter "${e}" is not a valid TextmodeConverter.`,
2210
2127
  { method: "converter", providedValue: e, converterInstance: r }
2211
2128
  ))
@@ -2218,33 +2135,33 @@ class Ue {
2218
2135
  * @returns The newly created {@link TextmodeConverter} instance or `void` if the addition failed.
2219
2136
  */
2220
2137
  add(e, t) {
2221
- if (!v.validate(
2138
+ if (!_.validate(
2222
2139
  typeof e == "string" && e.length > 0,
2223
2140
  "Converter name must be a non-empty string.",
2224
2141
  { method: "add", providedValue: e }
2225
- ) || !v.validate(
2142
+ ) || !_.validate(
2226
2143
  t === "brightness" || t === "custom",
2227
2144
  `Converter type must be either "brightness" or "custom". Provided: ${t}`,
2228
2145
  { method: "add", providedValue: t }
2229
2146
  ))
2230
2147
  return;
2231
2148
  let r;
2232
- return t === "brightness" ? r = new L(this.renderer, this.font, this.grid) : r = new U(this.renderer, this.font, this.grid), this.converters.push({ name: e, converter: r }), r;
2149
+ return t === "brightness" ? r = new L(this.renderer, this.font, this.grid) : r = new D(this.renderer, this.font, this.grid), this.converters.push({ name: e, converter: r }), r;
2233
2150
  }
2234
2151
  /**
2235
2152
  * Removes a converter from the pipeline by name or instance.
2236
2153
  * @param nameOrInstance The unique name of the converter or the converter instance to remove.
2237
2154
  */
2238
2155
  remove(e) {
2239
- if (!v.validate(
2240
- typeof e == "string" || e instanceof U,
2156
+ if (!_.validate(
2157
+ typeof e == "string" || e instanceof D,
2241
2158
  "Parameter must be either a string (converter name) or a TextmodeConverter instance.",
2242
2159
  { method: "remove", providedValue: e }
2243
2160
  ))
2244
2161
  return;
2245
2162
  let t = -1;
2246
2163
  if (typeof e == "string") {
2247
- if (!v.validate(
2164
+ if (!_.validate(
2248
2165
  e.length > 0,
2249
2166
  "Converter name must be a non-empty string.",
2250
2167
  { method: "remove", providedValue: e }
@@ -2253,7 +2170,7 @@ class Ue {
2253
2170
  t = this.converters.findIndex((r) => r.name === e);
2254
2171
  } else
2255
2172
  t = this.converters.findIndex((r) => r.converter === e);
2256
- v.validate(
2173
+ _.validate(
2257
2174
  t !== -1,
2258
2175
  typeof e == "string" ? `Converter with name "${e}" not found in pipeline.` : "Converter instance not found in pipeline.",
2259
2176
  { method: "remove", providedValue: e, convertersCount: this.converters.length }
@@ -2424,7 +2341,7 @@ class X {
2424
2341
  return `'textmode-export'-${this.generateTimestamp()}`;
2425
2342
  }
2426
2343
  }
2427
- class Ae extends H {
2344
+ class we extends H {
2428
2345
  /**
2429
2346
  * Extracts transform data from transform pixels
2430
2347
  * @param transformPixels Transform framebuffer pixels
@@ -2494,7 +2411,7 @@ class Ae extends H {
2494
2411
  return r;
2495
2412
  }
2496
2413
  }
2497
- class Me {
2414
+ class ye {
2498
2415
  /**
2499
2416
  * Gets the glyph index for a given Unicode code point in a Typr.js font
2500
2417
  * @param fontData The Typr.js font data
@@ -2572,22 +2489,22 @@ class Me {
2572
2489
  const f = n[d];
2573
2490
  if (!(f < u)) {
2574
2491
  if (f >= u) {
2575
- const g = t + s[u] * i, _ = r - a[u] * i;
2576
- c += `M${g.toFixed(2)},${_.toFixed(2)}`;
2492
+ const g = t + s[u] * i, v = r - a[u] * i;
2493
+ c += `M${g.toFixed(2)},${v.toFixed(2)}`;
2577
2494
  let p = u + 1;
2578
2495
  for (; p <= f; )
2579
2496
  if ((l[p] & 1) !== 0) {
2580
- const C = t + s[p] * i, x = r - a[p] * i;
2581
- c += `L${C.toFixed(2)},${x.toFixed(2)}`, p++;
2497
+ const w = t + s[p] * i, F = r - a[p] * i;
2498
+ c += `L${w.toFixed(2)},${F.toFixed(2)}`, p++;
2582
2499
  } else {
2583
- const C = t + s[p] * i, x = r - a[p] * i;
2584
- let w = p + 1 > f ? u : p + 1;
2585
- if ((l[w] & 1) !== 0) {
2586
- const R = t + s[w] * i, S = r - a[w] * i;
2587
- c += `Q${C.toFixed(2)},${x.toFixed(2)} ${R.toFixed(2)},${S.toFixed(2)}`, p = w + 1;
2500
+ const w = t + s[p] * i, F = r - a[p] * i;
2501
+ let C = p + 1 > f ? u : p + 1;
2502
+ if ((l[C] & 1) !== 0) {
2503
+ const U = t + s[C] * i, S = r - a[C] * i;
2504
+ c += `Q${w.toFixed(2)},${F.toFixed(2)} ${U.toFixed(2)},${S.toFixed(2)}`, p = C + 1;
2588
2505
  } else {
2589
- const R = t + s[w] * i, S = r - a[w] * i, P = (C + R) / 2, D = (x + S) / 2;
2590
- c += `Q${C.toFixed(2)},${x.toFixed(2)} ${P.toFixed(2)},${D.toFixed(2)}`, p = w;
2506
+ const U = t + s[C] * i, S = r - a[C] * i, R = (w + U) / 2, E = (F + S) / 2;
2507
+ c += `Q${w.toFixed(2)},${F.toFixed(2)} ${R.toFixed(2)},${E.toFixed(2)}`, p = C;
2591
2508
  }
2592
2509
  }
2593
2510
  c += "Z";
@@ -2643,10 +2560,10 @@ class Me {
2643
2560
  }
2644
2561
  }
2645
2562
  }
2646
- class De {
2563
+ class Te {
2647
2564
  constructor() {
2648
2565
  o(this, "pathGenerator");
2649
- this.pathGenerator = new Me();
2566
+ this.pathGenerator = new ye();
2650
2567
  }
2651
2568
  /**
2652
2569
  * Generates the SVG header with metadata
@@ -2791,7 +2708,7 @@ class De {
2791
2708
  `).replace(/[ \t]+$/gm, "");
2792
2709
  }
2793
2710
  }
2794
- class Ie extends X {
2711
+ class Se extends X {
2795
2712
  /**
2796
2713
  * Creates a downloadable blob from SVG content
2797
2714
  * @param svgContent The SVG content string
@@ -2821,12 +2738,12 @@ class Ie extends X {
2821
2738
  this.downloadSVG(e, t || this.generateDefaultFilename());
2822
2739
  }
2823
2740
  }
2824
- class Y {
2741
+ class q {
2825
2742
  constructor() {
2826
2743
  o(this, "dataExtractor");
2827
2744
  o(this, "contentGenerator");
2828
2745
  o(this, "fileHandler");
2829
- this.dataExtractor = new Ae(), this.contentGenerator = new De(), this.fileHandler = new Ie();
2746
+ this.dataExtractor = new we(), this.contentGenerator = new Te(), this.fileHandler = new Se();
2830
2747
  }
2831
2748
  /**
2832
2749
  * Applies default values to SVG export options
@@ -2873,7 +2790,7 @@ class Y {
2873
2790
  }
2874
2791
  }
2875
2792
  }
2876
- class Pe extends H {
2793
+ class Re extends H {
2877
2794
  /**
2878
2795
  * Extracts character data for TXT generation
2879
2796
  * @param framebufferData Framebuffer pixel data
@@ -2900,7 +2817,7 @@ class Pe extends H {
2900
2817
  return s;
2901
2818
  }
2902
2819
  }
2903
- class Be {
2820
+ class Ee {
2904
2821
  /**
2905
2822
  * Generates TXT content from a 2D character array
2906
2823
  * @param characterGrid 2D array of characters (rows x columns)
@@ -2919,7 +2836,7 @@ class Be {
2919
2836
  return r.join(i);
2920
2837
  }
2921
2838
  }
2922
- class Ge extends X {
2839
+ class Ue extends X {
2923
2840
  /**
2924
2841
  * Saves TXT content as a downloadable file
2925
2842
  * @param content The TXT content to save
@@ -2943,12 +2860,12 @@ class Ge extends X {
2943
2860
  return t === ".txt" || t.length <= 4 ? this.generateDefaultFilename() : t;
2944
2861
  }
2945
2862
  }
2946
- class j {
2863
+ class K {
2947
2864
  constructor() {
2948
2865
  o(this, "dataExtractor");
2949
2866
  o(this, "contentGenerator");
2950
2867
  o(this, "fileHandler");
2951
- this.dataExtractor = new Pe(), this.contentGenerator = new Be(), this.fileHandler = new Ge();
2868
+ this.dataExtractor = new Re(), this.contentGenerator = new Ee(), this.fileHandler = new Ue();
2952
2869
  }
2953
2870
  /**
2954
2871
  * Applies default values to TXT export options
@@ -2994,7 +2911,7 @@ class j {
2994
2911
  }
2995
2912
  }
2996
2913
  }
2997
- class Ve extends H {
2914
+ class Me extends H {
2998
2915
  /**
2999
2916
  * Captures the current state of the textmode canvas as image data
3000
2917
  * @param canvas The canvas data containing the rendered textmode graphics
@@ -3020,7 +2937,7 @@ class Ve extends H {
3020
2937
  ), s;
3021
2938
  }
3022
2939
  }
3023
- class ke {
2940
+ class Ae {
3024
2941
  /**
3025
2942
  * Generates image data from canvas
3026
2943
  * @param canvas The canvas containing the image data
@@ -3063,16 +2980,16 @@ class ke {
3063
2980
  }
3064
2981
  }
3065
2982
  }
3066
- const q = {
2983
+ const Q = {
3067
2984
  png: "image/png",
3068
2985
  jpg: "image/jpeg",
3069
2986
  webp: "image/webp"
3070
- }, z = {
2987
+ }, V = {
3071
2988
  png: ".png",
3072
2989
  jpg: ".jpg",
3073
2990
  webp: ".webp"
3074
2991
  };
3075
- class ze extends X {
2992
+ class De extends X {
3076
2993
  /**
3077
2994
  * Saves image content as a downloadable file
3078
2995
  * @param content The image content (data URL or blob)
@@ -3081,7 +2998,7 @@ class ze extends X {
3081
2998
  */
3082
2999
  saveImage(e, t, r) {
3083
3000
  try {
3084
- const i = z[r];
3001
+ const i = V[r];
3085
3002
  typeof e == "string" ? this.saveImageFromDataURL(e, this.sanitizeFilename(t) + i) : this.saveImageFromBlob(e, this.sanitizeFilename(t) + i);
3086
3003
  } catch (i) {
3087
3004
  throw console.error(`Failed to save ${r.toUpperCase()} image:`, i), new Error(`Image save failed: ${i instanceof Error ? i.message : "Unknown error"}`);
@@ -3116,7 +3033,7 @@ class ze extends X {
3116
3033
  * @returns True if the format is supported for saving
3117
3034
  */
3118
3035
  validateSaveSupport(e) {
3119
- return e in q && e in z;
3036
+ return e in Q && e in V;
3120
3037
  }
3121
3038
  /**
3122
3039
  * Gets the MIME type for the specified image format
@@ -3124,7 +3041,7 @@ class ze extends X {
3124
3041
  * @returns The MIME type string
3125
3042
  */
3126
3043
  getMimeType(e) {
3127
- return q[e];
3044
+ return Q[e];
3128
3045
  }
3129
3046
  /**
3130
3047
  * Gets the file extension for the specified image format
@@ -3132,15 +3049,15 @@ class ze extends X {
3132
3049
  * @returns The file extension (including the dot)
3133
3050
  */
3134
3051
  getFileExtension(e) {
3135
- return z[e];
3052
+ return V[e];
3136
3053
  }
3137
3054
  }
3138
- class $e {
3055
+ class Ie {
3139
3056
  constructor() {
3140
3057
  o(this, "dataExtractor");
3141
3058
  o(this, "contentGenerator");
3142
3059
  o(this, "fileHandler");
3143
- this.dataExtractor = new Ve(), this.contentGenerator = new ke(), this.fileHandler = new ze();
3060
+ this.dataExtractor = new Me(), this.contentGenerator = new Ae(), this.fileHandler = new De();
3144
3061
  }
3145
3062
  /**
3146
3063
  * Applies default values to image export options
@@ -3223,7 +3140,7 @@ class $e {
3223
3140
  }
3224
3141
  }
3225
3142
  }
3226
- class I {
3143
+ class k {
3227
3144
  constructor(e = null, t = {}) {
3228
3145
  /** The element to capture content from (optional for standalone mode) */
3229
3146
  o(this, "captureSource");
@@ -3267,12 +3184,12 @@ class I {
3267
3184
  * @ignore
3268
3185
  */
3269
3186
  static async create(e = null, t = {}) {
3270
- const r = new I(e, t), i = r._standalone ? t : void 0;
3271
- r.textmodeCanvas = new be(r.captureSource, r._standalone, i), r._renderer = new fe(r.textmodeCanvas.getWebGLContext());
3187
+ const r = new k(e, t), i = r._standalone ? t : void 0;
3188
+ r.textmodeCanvas = new fe(r.captureSource, r._standalone, i), r._renderer = new ne(r.textmodeCanvas.getWebGLContext());
3272
3189
  let s, a;
3273
- 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 ve(r._renderer, t.fontSize ?? 16), await r._font.initialize(t.fontSource);
3190
+ 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 ue(r._renderer, t.fontSize ?? 16), await r._font.initialize(t.fontSource);
3274
3191
  const n = r._font.maxGlyphDimensions;
3275
- return r._grid = new xe(r.textmodeCanvas.canvas, n.width, n.height), r._pipeline = new Ue(r._renderer, r._font, r._grid), r.setupEventListeners(), r.startAutoRendering(), r;
3192
+ return r._grid = new de(r.textmodeCanvas.canvas, n.width, n.height), r._pipeline = new Fe(r._renderer, r._font, r._grid), r.setupEventListeners(), r.startAutoRendering(), r;
3276
3193
  }
3277
3194
  setupEventListeners() {
3278
3195
  this._windowResizeListener = () => {
@@ -3320,7 +3237,7 @@ class I {
3320
3237
  * ```
3321
3238
  */
3322
3239
  toString(e = {}) {
3323
- return new j().generateTXT(this, e);
3240
+ return new K().generateTXT(this, e);
3324
3241
  }
3325
3242
  /**
3326
3243
  * Export the current textmode rendering to a TXT file.
@@ -3345,7 +3262,7 @@ class I {
3345
3262
  * ```
3346
3263
  */
3347
3264
  saveStrings(e = {}) {
3348
- new j().saveTXT(this, e);
3265
+ new K().saveTXT(this, e);
3349
3266
  }
3350
3267
  /**
3351
3268
  * Generate the current textmode rendering as an SVG string.
@@ -3374,7 +3291,7 @@ class I {
3374
3291
  * ```
3375
3292
  */
3376
3293
  toSVG(e = {}) {
3377
- return new Y().generateSVG(this, e);
3294
+ return new q().generateSVG(this, e);
3378
3295
  }
3379
3296
  /**
3380
3297
  * Export the current textmode rendering to an SVG file.
@@ -3398,7 +3315,7 @@ class I {
3398
3315
  * ```
3399
3316
  */
3400
3317
  saveSVG(e = {}) {
3401
- new Y().saveSVG(this, e);
3318
+ new q().saveSVG(this, e);
3402
3319
  }
3403
3320
  /**
3404
3321
  * Export the current textmode rendering to an image file.
@@ -3429,7 +3346,7 @@ class I {
3429
3346
  * ```
3430
3347
  */
3431
3348
  async saveCanvas(e, t = "png", r = {}) {
3432
- await new $e().saveImage(this.textmodeCanvas, {
3349
+ await new Ie().saveImage(this.textmodeCanvas, {
3433
3350
  ...r,
3434
3351
  filename: e,
3435
3352
  format: t
@@ -3691,7 +3608,7 @@ class I {
3691
3608
  * ```
3692
3609
  */
3693
3610
  redraw(e = 1) {
3694
- if (v.validate(
3611
+ if (_.validate(
3695
3612
  typeof e == "number" && e > 0 && Number.isInteger(e),
3696
3613
  "Redraw count must be a positive integer.",
3697
3614
  { method: "redraw", providedValue: e }
@@ -3747,7 +3664,7 @@ class I {
3747
3664
  * ```
3748
3665
  */
3749
3666
  fontSize(e) {
3750
- v.validate(
3667
+ _.validate(
3751
3668
  typeof e == "number" && e > 0,
3752
3669
  "Font size must be a positive number greater than 0.",
3753
3670
  { method: "fontSize", providedValue: e }
@@ -4339,7 +4256,7 @@ class I {
4339
4256
  return this._isDisposed;
4340
4257
  }
4341
4258
  }
4342
- class N {
4259
+ class O {
4343
4260
  /**
4344
4261
  * Create a {@link Textmodifier} instance for textmode rendering.
4345
4262
  *
@@ -4401,10 +4318,10 @@ class N {
4401
4318
  */
4402
4319
  static async create(e, t = {}) {
4403
4320
  if (e instanceof HTMLCanvasElement || e instanceof HTMLVideoElement)
4404
- return I.create(e, t);
4321
+ return k.create(e, t);
4405
4322
  {
4406
4323
  const r = e || {};
4407
- return I.create(null, r);
4324
+ return k.create(null, r);
4408
4325
  }
4409
4326
  }
4410
4327
  /**
@@ -4418,7 +4335,7 @@ class N {
4418
4335
  * ```
4419
4336
  */
4420
4337
  static setErrorLevel(e) {
4421
- v.setGlobalLevel(e);
4338
+ _.setGlobalLevel(e);
4422
4339
  }
4423
4340
  /**
4424
4341
  * Returns the current version of the `textmode.js` library.
@@ -4429,27 +4346,27 @@ class N {
4429
4346
  * ```
4430
4347
  */
4431
4348
  static get version() {
4432
- return "0.1.6-beta.3";
4349
+ return "0.1.6-beta.4";
4433
4350
  }
4434
4351
  constructor() {
4435
4352
  throw new Error("Textmode is a static class and cannot be instantiated.");
4436
4353
  }
4437
4354
  }
4438
- const He = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
4355
+ const Be = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
4439
4356
  __proto__: null
4440
- }, Symbol.toStringTag, { value: "Module" })), Xe = N.create, Ne = N.setErrorLevel, We = N.version;
4357
+ }, Symbol.toStringTag, { value: "Module" })), ke = O.create, Ve = O.setErrorLevel, ze = O.version;
4441
4358
  export {
4442
- be as TextmodeCanvas,
4443
- Ue as TextmodeConversionPipeline,
4444
- ne as TextmodeErrorLevel,
4445
- ve as TextmodeFont,
4446
- xe as TextmodeGrid,
4447
- I as Textmodifier,
4448
- Oe as converters,
4449
- Xe as create,
4450
- N as default,
4451
- He as export,
4452
- Ne as setErrorLevel,
4453
- N as textmode,
4454
- We as version
4359
+ fe as TextmodeCanvas,
4360
+ Fe as TextmodeConversionPipeline,
4361
+ re as TextmodeErrorLevel,
4362
+ ue as TextmodeFont,
4363
+ de as TextmodeGrid,
4364
+ k as Textmodifier,
4365
+ Pe as converters,
4366
+ ke as create,
4367
+ O as default,
4368
+ Be as export,
4369
+ Ve as setErrorLevel,
4370
+ O as textmode,
4371
+ ze as version
4455
4372
  };