textmode.js 0.1.6-beta.2 → 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.
- package/dist/textmode.esm.js +532 -644
- package/dist/textmode.esm.min.js +522 -634
- package/dist/textmode.umd.js +13 -13
- package/dist/textmode.umd.min.js +13 -13
- package/dist/types/rendering/webgl/Framebuffer.d.ts +11 -0
- package/dist/types/rendering/webgl/Renderer.d.ts +14 -2
- package/dist/types/rendering/webgl/StateCache.d.ts +6 -0
- package/package.json +1 -1
package/dist/textmode.esm.min.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var o = (h, e, t) =>
|
|
4
|
-
class
|
|
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 =
|
|
6
|
+
const s = x.createFormattedMessage(t, i);
|
|
7
7
|
super(s);
|
|
8
8
|
o(this, "originalError");
|
|
9
9
|
o(this, "context");
|
|
@@ -18,10 +18,10 @@ class F extends Error {
|
|
|
18
18
|
i += `
|
|
19
19
|
|
|
20
20
|
📋 Context:`;
|
|
21
|
-
for (const [s,
|
|
22
|
-
const
|
|
21
|
+
for (const [s, a] of Object.entries(r)) {
|
|
22
|
+
const n = x.formatValue(a);
|
|
23
23
|
i += `
|
|
24
|
-
- ${s}: ${
|
|
24
|
+
- ${s}: ${n}`;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
return i += `
|
|
@@ -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) =>
|
|
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((
|
|
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
|
|
50
|
-
const
|
|
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
|
|
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(
|
|
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(
|
|
79
|
+
), console.error(x.createFormattedMessage(e, t)), console.groupEnd(), !1;
|
|
80
80
|
case 3:
|
|
81
81
|
default:
|
|
82
|
-
const s = new
|
|
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(
|
|
107
|
-
let
|
|
108
|
-
const
|
|
109
|
-
|
|
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
|
|
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
|
|
@@ -189,16 +218,16 @@ class oe {
|
|
|
189
218
|
get(e, t, r, i) {
|
|
190
219
|
const { gl: s } = this;
|
|
191
220
|
if (e === void 0 && t === void 0) {
|
|
192
|
-
const
|
|
193
|
-
return s.bindFramebuffer(s.FRAMEBUFFER, this._framebuffer), s.readPixels(0, 0, this._width, this._height, s.RGBA, s.UNSIGNED_BYTE,
|
|
221
|
+
const a = new Uint8Array(this._width * this._height * 4), n = s.getParameter(s.FRAMEBUFFER_BINDING);
|
|
222
|
+
return s.bindFramebuffer(s.FRAMEBUFFER, this._framebuffer), s.readPixels(0, 0, this._width, this._height, s.RGBA, s.UNSIGNED_BYTE, a), s.bindFramebuffer(s.FRAMEBUFFER, n), a;
|
|
194
223
|
} else if (r === void 0 && i === void 0) {
|
|
195
224
|
(e < 0 || t < 0 || e >= this._width || t >= this._height) && (console.warn("The x and y values passed to Framebuffer.get are outside of its range and will be clamped."), e = Math.max(0, Math.min(e, this._width - 1)), t = Math.max(0, Math.min(t, this._height - 1)));
|
|
196
|
-
const
|
|
197
|
-
return s.bindFramebuffer(s.FRAMEBUFFER, this._framebuffer), s.readPixels(e, t, 1, 1, s.RGBA, s.UNSIGNED_BYTE,
|
|
225
|
+
const a = new Uint8Array(4), n = s.getParameter(s.FRAMEBUFFER_BINDING);
|
|
226
|
+
return s.bindFramebuffer(s.FRAMEBUFFER, this._framebuffer), s.readPixels(e, t, 1, 1, s.RGBA, s.UNSIGNED_BYTE, a), s.bindFramebuffer(s.FRAMEBUFFER, n), [a[0], a[1], a[2], a[3]];
|
|
198
227
|
} else {
|
|
199
228
|
e = Math.max(0, Math.min(e, this._width - 1)), t = Math.max(0, Math.min(t, this._height - 1)), r = Math.max(1, Math.min(r, this._width - e)), i = Math.max(1, Math.min(i, this._height - t));
|
|
200
|
-
const
|
|
201
|
-
return s.bindFramebuffer(s.FRAMEBUFFER, this._framebuffer), s.readPixels(e, t, r, i, s.RGBA, s.UNSIGNED_BYTE,
|
|
229
|
+
const a = new Uint8Array(r * i * 4), n = s.getParameter(s.FRAMEBUFFER_BINDING);
|
|
230
|
+
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
231
|
}
|
|
203
232
|
}
|
|
204
233
|
/**
|
|
@@ -224,247 +253,14 @@ class oe {
|
|
|
224
253
|
get pixels() {
|
|
225
254
|
return this._pixels;
|
|
226
255
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
o(this, "gl");
|
|
231
|
-
o(this, "x");
|
|
232
|
-
o(this, "y");
|
|
233
|
-
this.gl = e, this.x = t, this.y = r;
|
|
234
|
-
}
|
|
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 n = e.getParameter(e.VIEWPORT), a = n[2], l = n[3], c = e.getParameter(e.FRAMEBUFFER_BINDING) !== null, u = t / a * 2 - 1, d = (t + i) / a * 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, n) {
|
|
305
|
-
super(t, r, i);
|
|
306
|
-
o(this, "width");
|
|
307
|
-
o(this, "height");
|
|
308
|
-
this.width = s, this.height = n;
|
|
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), n = new M(this.gl, this.x, this.y, t, this.height);
|
|
324
|
-
r.render(), i.render(), s.render(), n.render();
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
class le {
|
|
328
|
-
constructor(e, t, r, i, s, n) {
|
|
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 a = e.getParameter(e.VIEWPORT), l = a[2], c = a[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 = n / 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, n, a, 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
|
-
n,
|
|
416
|
-
1,
|
|
417
|
-
0,
|
|
418
|
-
// corner3 (end + perpendicular)
|
|
419
|
-
r,
|
|
420
|
-
i,
|
|
421
|
-
0,
|
|
422
|
-
1,
|
|
423
|
-
// corner2 (start - perpendicular)
|
|
424
|
-
a,
|
|
425
|
-
l,
|
|
426
|
-
1,
|
|
427
|
-
1,
|
|
428
|
-
// corner4 (end - perpendicular)
|
|
429
|
-
s,
|
|
430
|
-
n,
|
|
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, n) {
|
|
448
|
-
super(t, r, i);
|
|
449
|
-
o(this, "x2");
|
|
450
|
-
o(this, "y2");
|
|
451
|
-
this.x2 = s, this.y2 = n;
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Lines don't support fill rendering - this method does nothing.
|
|
455
|
-
* Lines are rendered only with stroke properties.
|
|
456
|
-
*/
|
|
457
|
-
renderFill() {
|
|
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;
|
|
458
259
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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");
|
|
@@ -477,8 +273,8 @@ class y {
|
|
|
477
273
|
createProgram(e, t) {
|
|
478
274
|
const r = this.createShader(this.gl.VERTEX_SHADER, e), i = this.createShader(this.gl.FRAGMENT_SHADER, t), s = this.gl.createProgram();
|
|
479
275
|
if (this.gl.attachShader(s, r), this.gl.attachShader(s, i), this.gl.linkProgram(s), !this.gl.getProgramParameter(s, this.gl.LINK_STATUS)) {
|
|
480
|
-
const
|
|
481
|
-
throw new Error(`Shader program link error: ${
|
|
276
|
+
const a = this.gl.getProgramInfoLog(s);
|
|
277
|
+
throw new Error(`Shader program link error: ${a}`);
|
|
482
278
|
}
|
|
483
279
|
return this.gl.deleteShader(r), this.gl.deleteShader(i), s;
|
|
484
280
|
}
|
|
@@ -528,7 +324,7 @@ class y {
|
|
|
528
324
|
this.gl.uniform1i(r, t ? 1 : 0);
|
|
529
325
|
else if (Array.isArray(t))
|
|
530
326
|
if (i && (i.type === this.gl.INT_VEC2 || i.type === this.gl.INT_VEC3 || i.type === this.gl.INT_VEC4)) {
|
|
531
|
-
const s = t.map((
|
|
327
|
+
const s = t.map((a) => Math.floor(a));
|
|
532
328
|
switch (s.length) {
|
|
533
329
|
case 2:
|
|
534
330
|
this.gl.uniform2iv(r, s);
|
|
@@ -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);}",
|
|
616
|
-
class
|
|
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
|
-
|
|
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
|
|
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:
|
|
754
|
-
this.setUniform("u_rotation",
|
|
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
|
-
|
|
559
|
+
this.drawRectImmediate(e, t, r, i), this.currentShader = null;
|
|
758
560
|
return;
|
|
759
561
|
}
|
|
760
|
-
const
|
|
761
|
-
|
|
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
|
|
777
|
-
this.setUniform("u_rotation", R), this.setUniform("u_center", [
|
|
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
|
-
|
|
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
|
-
|
|
784
|
-
this.
|
|
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.
|
|
791
|
-
|
|
792
|
-
c ? g = d / a * 2 - 1 : g = 1 - d / a * 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
|
|
610
|
+
return new $(this.gl, e, t, r);
|
|
801
611
|
}
|
|
802
612
|
/**
|
|
803
613
|
* Fill the current framebuffer with a solid color
|
|
@@ -812,11 +622,10 @@ class fe {
|
|
|
812
622
|
this.gl.clearColor(e, t, r, i), this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
813
623
|
}
|
|
814
624
|
/**
|
|
815
|
-
* Ensure viewport matches canvas dimensions
|
|
625
|
+
* Ensure viewport matches canvas dimensions
|
|
816
626
|
*/
|
|
817
|
-
resetViewport(
|
|
818
|
-
|
|
819
|
-
this.gl.viewport(0, 0, r, i);
|
|
627
|
+
resetViewport() {
|
|
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);
|
|
820
629
|
}
|
|
821
630
|
/**
|
|
822
631
|
* Get the WebGL context
|
|
@@ -829,25 +638,132 @@ class fe {
|
|
|
829
638
|
* This method is idempotent and safe to call multiple times.
|
|
830
639
|
*/
|
|
831
640
|
dispose() {
|
|
832
|
-
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 = [];
|
|
833
642
|
}
|
|
834
643
|
/**
|
|
835
644
|
* Render a framebuffer at a specific position with optional scaling
|
|
836
645
|
*/
|
|
837
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
|
+
}
|
|
838
654
|
this.shader(this.imageShader), this.setUniform("u_texture", e.texture);
|
|
839
|
-
const { centerX:
|
|
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,
|
|
840
690
|
t,
|
|
691
|
+
0,
|
|
692
|
+
l,
|
|
693
|
+
// top-left
|
|
694
|
+
e,
|
|
695
|
+
t,
|
|
696
|
+
0,
|
|
697
|
+
l,
|
|
698
|
+
// top-left
|
|
841
699
|
r,
|
|
842
|
-
i
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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);
|
|
846
762
|
}
|
|
847
763
|
}
|
|
848
764
|
var m = {};
|
|
849
765
|
m.parse = function(h) {
|
|
850
|
-
var e = function(s,
|
|
766
|
+
var e = function(s, a, n, l) {
|
|
851
767
|
var c = m.T, u = {
|
|
852
768
|
cmap: c.cmap,
|
|
853
769
|
head: c.head,
|
|
@@ -856,12 +772,12 @@ m.parse = function(h) {
|
|
|
856
772
|
hmtx: c.hmtx,
|
|
857
773
|
loca: c.loca,
|
|
858
774
|
glyf: c.glyf
|
|
859
|
-
}, d = { _data: s, _index:
|
|
775
|
+
}, d = { _data: s, _index: a, _offset: n };
|
|
860
776
|
for (var f in u) {
|
|
861
|
-
var g = m.findTable(s, f,
|
|
777
|
+
var g = m.findTable(s, f, n);
|
|
862
778
|
if (g) {
|
|
863
|
-
var
|
|
864
|
-
p == null && (p = u[f].parseTab(s,
|
|
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;
|
|
865
781
|
}
|
|
866
782
|
}
|
|
867
783
|
return d;
|
|
@@ -869,11 +785,11 @@ m.parse = function(h) {
|
|
|
869
785
|
return [i];
|
|
870
786
|
};
|
|
871
787
|
m.findTable = function(h, e, t) {
|
|
872
|
-
for (var r = m.B, i = r.readUshort(h, t + 4), s = t + 12,
|
|
873
|
-
var
|
|
788
|
+
for (var r = m.B, i = r.readUshort(h, t + 4), s = t + 12, a = 0; a < i; a++) {
|
|
789
|
+
var n = r.readASCII(h, s, 4);
|
|
874
790
|
r.readUint(h, s + 4);
|
|
875
791
|
var l = r.readUint(h, s + 8), c = r.readUint(h, s + 12);
|
|
876
|
-
if (
|
|
792
|
+
if (n == e) return [l, c];
|
|
877
793
|
s += 16;
|
|
878
794
|
}
|
|
879
795
|
return null;
|
|
@@ -915,33 +831,33 @@ m.T.cmap = {
|
|
|
915
831
|
parseTab: function(h, e, t) {
|
|
916
832
|
var r = { tables: [], ids: {}, off: e };
|
|
917
833
|
h = new Uint8Array(h.buffer, e, t), e = 0;
|
|
918
|
-
var i = m.B, s = i.readUshort,
|
|
834
|
+
var i = m.B, s = i.readUshort, a = m.T.cmap;
|
|
919
835
|
s(h, e), e += 2;
|
|
920
|
-
var
|
|
836
|
+
var n = s(h, e);
|
|
921
837
|
e += 2;
|
|
922
|
-
for (var l = [], c = 0; c <
|
|
838
|
+
for (var l = [], c = 0; c < n; c++) {
|
|
923
839
|
var u = s(h, e);
|
|
924
840
|
e += 2;
|
|
925
841
|
var d = s(h, e);
|
|
926
842
|
e += 2;
|
|
927
843
|
var f = i.readUint(h, e);
|
|
928
844
|
e += 4;
|
|
929
|
-
var g = "p" + u + "e" + d,
|
|
930
|
-
if (
|
|
931
|
-
|
|
845
|
+
var g = "p" + u + "e" + d, v = l.indexOf(f);
|
|
846
|
+
if (v == -1) {
|
|
847
|
+
v = r.tables.length;
|
|
932
848
|
var p = {};
|
|
933
849
|
l.push(f);
|
|
934
850
|
var b = p.format = s(h, f);
|
|
935
|
-
b == 4 ? p =
|
|
851
|
+
b == 4 ? p = a.parse4(h, f, p) : b == 12 && (p = a.parse12(h, f, p)), r.tables.push(p);
|
|
936
852
|
}
|
|
937
|
-
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;
|
|
938
854
|
}
|
|
939
855
|
return r;
|
|
940
856
|
},
|
|
941
857
|
parse4: function(h, e, t) {
|
|
942
|
-
var r = m.B, i = r.readUshort, s = r.readUshorts,
|
|
858
|
+
var r = m.B, i = r.readUshort, s = r.readUshorts, a = e;
|
|
943
859
|
e += 2;
|
|
944
|
-
var
|
|
860
|
+
var n = i(h, e);
|
|
945
861
|
e += 2, i(h, e), e += 2;
|
|
946
862
|
var l = i(h, e);
|
|
947
863
|
e += 2;
|
|
@@ -949,15 +865,15 @@ m.T.cmap = {
|
|
|
949
865
|
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 = [];
|
|
950
866
|
for (var u = 0; u < c; u++)
|
|
951
867
|
t.idDelta.push(r.readShort(h, e)), e += 2;
|
|
952
|
-
return t.idRangeOffset = s(h, e, c), e += c * 2, t.glyphIdArray = s(h, e,
|
|
868
|
+
return t.idRangeOffset = s(h, e, c), e += c * 2, t.glyphIdArray = s(h, e, a + n - e >> 1), t;
|
|
953
869
|
},
|
|
954
870
|
parse12: function(h, e, t) {
|
|
955
871
|
var r = m.B, i = r.readUint;
|
|
956
872
|
e += 4, i(h, e), e += 4, i(h, e), e += 4;
|
|
957
873
|
var s = i(h, e) * 3;
|
|
958
874
|
e += 4;
|
|
959
|
-
for (var
|
|
960
|
-
n
|
|
875
|
+
for (var a = t.groups = new Uint32Array(s), n = 0; n < s; n += 3)
|
|
876
|
+
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);
|
|
961
877
|
return t;
|
|
962
878
|
}
|
|
963
879
|
};
|
|
@@ -988,20 +904,20 @@ m.T.hhea = {
|
|
|
988
904
|
"res3",
|
|
989
905
|
"metricDataFormat",
|
|
990
906
|
"numberOfHMetrics"
|
|
991
|
-
],
|
|
992
|
-
var
|
|
993
|
-
i[
|
|
907
|
+
], a = 0; a < s.length; a++) {
|
|
908
|
+
var n = s[a], l = n == "advanceWidthMax" || n == "numberOfHMetrics" ? r.readUshort : r.readShort;
|
|
909
|
+
i[n] = l(h, e + a * 2);
|
|
994
910
|
}
|
|
995
911
|
return i;
|
|
996
912
|
}
|
|
997
913
|
};
|
|
998
914
|
m.T.hmtx = {
|
|
999
915
|
parseTab: function(h, e, t, r) {
|
|
1000
|
-
for (var i = m.B, s = [],
|
|
1001
|
-
c = i.readUshort(h, e + (d << 2)), u = i.readShort(h, e + (d << 2) + 2), s.push(c),
|
|
1002
|
-
for (; d <
|
|
1003
|
-
s.push(c),
|
|
1004
|
-
return { aWidth: s, lsBearing:
|
|
916
|
+
for (var i = m.B, s = [], a = [], n = r.maxp.numGlyphs, l = r.hhea.numberOfHMetrics, c = 0, u = 0, d = 0; d < l; )
|
|
917
|
+
c = i.readUshort(h, e + (d << 2)), u = i.readShort(h, e + (d << 2) + 2), s.push(c), a.push(u), d++;
|
|
918
|
+
for (; d < n; )
|
|
919
|
+
s.push(c), a.push(u), d++;
|
|
920
|
+
return { aWidth: s, lsBearing: a };
|
|
1005
921
|
}
|
|
1006
922
|
};
|
|
1007
923
|
m.T.maxp = {
|
|
@@ -1012,59 +928,59 @@ m.T.maxp = {
|
|
|
1012
928
|
};
|
|
1013
929
|
m.T.loca = {
|
|
1014
930
|
parseTab: function(h, e, t, r) {
|
|
1015
|
-
var i = m.B, s = [],
|
|
1016
|
-
if (
|
|
1017
|
-
if (
|
|
931
|
+
var i = m.B, s = [], a = r.head.indexToLocFormat, n = r.maxp.numGlyphs + 1;
|
|
932
|
+
if (a == 0) for (var l = 0; l < n; l++) s.push(i.readUshort(h, e + (l << 1)) << 1);
|
|
933
|
+
if (a == 1) for (var l = 0; l < n; l++) s.push(i.readUint(h, e + (l << 2)));
|
|
1018
934
|
return s;
|
|
1019
935
|
}
|
|
1020
936
|
};
|
|
1021
937
|
m.T.glyf = {
|
|
1022
938
|
parseTab: function(h, e, t, r) {
|
|
1023
|
-
for (var i = [], s = r.maxp.numGlyphs,
|
|
939
|
+
for (var i = [], s = r.maxp.numGlyphs, a = 0; a < s; a++) i.push(null);
|
|
1024
940
|
return i;
|
|
1025
941
|
},
|
|
1026
942
|
_parseGlyf: function(h, e) {
|
|
1027
943
|
var t = m.B, r = h._data, i = h.loca;
|
|
1028
944
|
if (i[e] == i[e + 1]) return null;
|
|
1029
|
-
var s = m.findTable(r, "glyf", h._offset)[0] + i[e],
|
|
1030
|
-
if (
|
|
1031
|
-
if (
|
|
1032
|
-
|
|
1033
|
-
for (var
|
|
1034
|
-
|
|
945
|
+
var s = m.findTable(r, "glyf", h._offset)[0] + i[e], a = {};
|
|
946
|
+
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;
|
|
947
|
+
if (a.noc > 0) {
|
|
948
|
+
a.endPts = [];
|
|
949
|
+
for (var n = 0; n < a.noc; n++)
|
|
950
|
+
a.endPts.push(t.readUshort(r, s)), s += 2;
|
|
1035
951
|
var l = t.readUshort(r, s);
|
|
1036
952
|
if (s += 2, r.length - s < l) return null;
|
|
1037
953
|
s += l;
|
|
1038
|
-
var c =
|
|
1039
|
-
|
|
1040
|
-
for (var
|
|
954
|
+
var c = a.endPts[a.noc - 1] + 1;
|
|
955
|
+
a.flags = [];
|
|
956
|
+
for (var n = 0; n < c; n++) {
|
|
1041
957
|
var u = r[s];
|
|
1042
|
-
if (s++,
|
|
958
|
+
if (s++, a.flags.push(u), u & 8) {
|
|
1043
959
|
var d = r[s];
|
|
1044
960
|
s++;
|
|
1045
961
|
for (var f = 0; f < d; f++)
|
|
1046
|
-
|
|
962
|
+
a.flags.push(u), n++;
|
|
1047
963
|
}
|
|
1048
964
|
}
|
|
1049
|
-
|
|
1050
|
-
for (var
|
|
1051
|
-
var g = (
|
|
1052
|
-
g ? (
|
|
965
|
+
a.xs = [];
|
|
966
|
+
for (var n = 0; n < c; n++) {
|
|
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);
|
|
1053
969
|
}
|
|
1054
|
-
|
|
1055
|
-
for (var
|
|
1056
|
-
var g = (
|
|
1057
|
-
g ? (
|
|
970
|
+
a.ys = [];
|
|
971
|
+
for (var n = 0; n < c; n++) {
|
|
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);
|
|
1058
974
|
}
|
|
1059
|
-
for (var p = 0, b = 0,
|
|
1060
|
-
p +=
|
|
975
|
+
for (var p = 0, b = 0, n = 0; n < c; n++)
|
|
976
|
+
p += a.xs[n], b += a.ys[n], a.xs[n] = p, a.ys[n] = b;
|
|
1061
977
|
} else
|
|
1062
|
-
|
|
1063
|
-
return
|
|
978
|
+
a.parts = [];
|
|
979
|
+
return a;
|
|
1064
980
|
}
|
|
1065
981
|
};
|
|
1066
982
|
typeof module < "u" && module.exports ? module.exports = m : typeof window < "u" && (window.Typr = m);
|
|
1067
|
-
class
|
|
983
|
+
class oe {
|
|
1068
984
|
/**
|
|
1069
985
|
* Extracts all available characters from a font's cmap tables.
|
|
1070
986
|
* @param font The parsed font object from Typr
|
|
@@ -1095,9 +1011,9 @@ class me {
|
|
|
1095
1011
|
for (let r = 0; r < e.startCount.length; r++) {
|
|
1096
1012
|
const i = e.startCount[r], s = e.endCount[r];
|
|
1097
1013
|
if (!(i === 65535 && s === 65535)) {
|
|
1098
|
-
for (let
|
|
1099
|
-
if (this._calculateGlyphIndexFormat4(e,
|
|
1100
|
-
const l = String.fromCodePoint(
|
|
1014
|
+
for (let a = i; a <= s; a++)
|
|
1015
|
+
if (this._calculateGlyphIndexFormat4(e, a, r) > 0) {
|
|
1016
|
+
const l = String.fromCodePoint(a);
|
|
1101
1017
|
t.push(l);
|
|
1102
1018
|
}
|
|
1103
1019
|
}
|
|
@@ -1114,10 +1030,10 @@ class me {
|
|
|
1114
1030
|
if (!e.groups)
|
|
1115
1031
|
return t;
|
|
1116
1032
|
for (let r = 0; r < e.groups.length; r += 3) {
|
|
1117
|
-
const i = e.groups[r], s = e.groups[r + 1],
|
|
1118
|
-
for (let
|
|
1119
|
-
if (
|
|
1120
|
-
const c = String.fromCodePoint(
|
|
1033
|
+
const i = e.groups[r], s = e.groups[r + 1], a = e.groups[r + 2];
|
|
1034
|
+
for (let n = i; n <= s; n++)
|
|
1035
|
+
if (a + (n - i) > 0) {
|
|
1036
|
+
const c = String.fromCodePoint(n);
|
|
1121
1037
|
t.push(c);
|
|
1122
1038
|
}
|
|
1123
1039
|
}
|
|
@@ -1161,7 +1077,7 @@ class me {
|
|
|
1161
1077
|
return !(t >= 0 && t <= 31 && t !== 9 && t !== 10 && t !== 13 || t >= 127 && t <= 159);
|
|
1162
1078
|
}
|
|
1163
1079
|
}
|
|
1164
|
-
class
|
|
1080
|
+
class he {
|
|
1165
1081
|
/**
|
|
1166
1082
|
* Creates a new TextureAtlasCreation instance.
|
|
1167
1083
|
* @param renderer The WebGL renderer instance
|
|
@@ -1181,13 +1097,13 @@ class ge {
|
|
|
1181
1097
|
* @returns Object containing framebuffer, columns, and rows
|
|
1182
1098
|
*/
|
|
1183
1099
|
createTextureAtlas(e, t, r, i) {
|
|
1184
|
-
const s = e.length,
|
|
1185
|
-
this._setupCanvas(l, c, r, i), this._renderCharactersToCanvas(e, t,
|
|
1100
|
+
const s = e.length, a = Math.ceil(Math.sqrt(s)), n = Math.ceil(s / a), l = t.width * a, c = t.height * n;
|
|
1101
|
+
this._setupCanvas(l, c, r, i), this._renderCharactersToCanvas(e, t, a, r), this._applyBlackWhiteThreshold();
|
|
1186
1102
|
const u = this._renderer.createFramebuffer(l, c, { filter: "nearest" });
|
|
1187
1103
|
return u.update(this._textureCanvas), {
|
|
1188
1104
|
framebuffer: u,
|
|
1189
|
-
columns:
|
|
1190
|
-
rows:
|
|
1105
|
+
columns: a,
|
|
1106
|
+
rows: n
|
|
1191
1107
|
};
|
|
1192
1108
|
}
|
|
1193
1109
|
/**
|
|
@@ -1211,7 +1127,7 @@ class ge {
|
|
|
1211
1127
|
*/
|
|
1212
1128
|
_renderCharactersToCanvas(e, t, r, i) {
|
|
1213
1129
|
for (let s = 0; s < e.length; s++) {
|
|
1214
|
-
const
|
|
1130
|
+
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);
|
|
1215
1131
|
this._textureContext.fillText(e[s].character, u, d);
|
|
1216
1132
|
}
|
|
1217
1133
|
}
|
|
@@ -1224,13 +1140,13 @@ class ge {
|
|
|
1224
1140
|
_applyBlackWhiteThreshold(e = 128) {
|
|
1225
1141
|
const t = this._textureContext.getImageData(0, 0, this._textureCanvas.width, this._textureCanvas.height), r = t.data;
|
|
1226
1142
|
for (let i = 0; i < r.length; i += 4) {
|
|
1227
|
-
const s = 0.299 * r[i] + 0.587 * r[i + 1] + 0.114 * r[i + 2],
|
|
1228
|
-
r[i] =
|
|
1143
|
+
const s = 0.299 * r[i] + 0.587 * r[i + 1] + 0.114 * r[i + 2], a = e + 32, n = s > a ? 255 : 0;
|
|
1144
|
+
r[i] = n, r[i + 1] = n, r[i + 2] = n;
|
|
1229
1145
|
}
|
|
1230
1146
|
this._textureContext.putImageData(t, 0, 0);
|
|
1231
1147
|
}
|
|
1232
1148
|
}
|
|
1233
|
-
class
|
|
1149
|
+
class le {
|
|
1234
1150
|
/**
|
|
1235
1151
|
* Creates a new MetricsCalculation instance.
|
|
1236
1152
|
*/
|
|
@@ -1250,8 +1166,8 @@ class pe {
|
|
|
1250
1166
|
calculateMaxGlyphDimensions(e, t, r) {
|
|
1251
1167
|
this._tempContext.font = `${t}px ${r}`;
|
|
1252
1168
|
let i = 0, s = 0;
|
|
1253
|
-
for (const
|
|
1254
|
-
const
|
|
1169
|
+
for (const a of e) {
|
|
1170
|
+
const n = this._tempContext.measureText(a), l = n.width, c = n.actualBoundingBoxAscent + n.actualBoundingBoxDescent;
|
|
1255
1171
|
l > 0 && (i = Math.max(i, l), s = Math.max(s, c));
|
|
1256
1172
|
}
|
|
1257
1173
|
return {
|
|
@@ -1260,7 +1176,7 @@ class pe {
|
|
|
1260
1176
|
};
|
|
1261
1177
|
}
|
|
1262
1178
|
}
|
|
1263
|
-
class
|
|
1179
|
+
class ce {
|
|
1264
1180
|
/**
|
|
1265
1181
|
* Creates TextmodeCharacter objects with unique color assignments.
|
|
1266
1182
|
* @param characters Array of character strings
|
|
@@ -1269,17 +1185,17 @@ class _e {
|
|
|
1269
1185
|
*/
|
|
1270
1186
|
createCharacterObjects(e, t) {
|
|
1271
1187
|
return e.map((r, i) => {
|
|
1272
|
-
const s = r.codePointAt(0) || 0,
|
|
1273
|
-
let
|
|
1188
|
+
const s = r.codePointAt(0) || 0, a = this._generateCharacterColor(i);
|
|
1189
|
+
let n = 0;
|
|
1274
1190
|
if (t.hmtx && t.hmtx.aWidth) {
|
|
1275
1191
|
const l = this._getGlyphIndex(t, s);
|
|
1276
|
-
l > 0 && t.hmtx.aWidth[l] !== void 0 && (
|
|
1192
|
+
l > 0 && t.hmtx.aWidth[l] !== void 0 && (n = t.hmtx.aWidth[l]);
|
|
1277
1193
|
}
|
|
1278
1194
|
return {
|
|
1279
1195
|
character: r,
|
|
1280
1196
|
unicode: s,
|
|
1281
|
-
color:
|
|
1282
|
-
advanceWidth:
|
|
1197
|
+
color: a,
|
|
1198
|
+
advanceWidth: n
|
|
1283
1199
|
};
|
|
1284
1200
|
});
|
|
1285
1201
|
}
|
|
@@ -1300,11 +1216,11 @@ class _e {
|
|
|
1300
1216
|
if (i.idRangeOffset[s] === 0)
|
|
1301
1217
|
return t + i.idDelta[s] & 65535;
|
|
1302
1218
|
{
|
|
1303
|
-
const
|
|
1304
|
-
if (
|
|
1305
|
-
const
|
|
1306
|
-
if (
|
|
1307
|
-
return
|
|
1219
|
+
const a = i.idRangeOffset[s] / 2 + (t - i.startCount[s]) - (i.startCount.length - s);
|
|
1220
|
+
if (a >= 0 && a < i.glyphIdArray.length) {
|
|
1221
|
+
const n = i.glyphIdArray[a];
|
|
1222
|
+
if (n !== 0)
|
|
1223
|
+
return n + i.idDelta[s] & 65535;
|
|
1308
1224
|
}
|
|
1309
1225
|
}
|
|
1310
1226
|
}
|
|
@@ -1327,7 +1243,7 @@ class _e {
|
|
|
1327
1243
|
* @returns RGB color as a tuple [r, g, b], or [0, 0, 0] if not found
|
|
1328
1244
|
*/
|
|
1329
1245
|
getCharacterColor(e, t) {
|
|
1330
|
-
if (!
|
|
1246
|
+
if (!_.validate(
|
|
1331
1247
|
typeof e == "string" && e.length === 1,
|
|
1332
1248
|
"Character must be a single character string.",
|
|
1333
1249
|
{ method: "getCharacterColor", providedValue: e }
|
|
@@ -1343,14 +1259,14 @@ class _e {
|
|
|
1343
1259
|
* @returns Array of RGB colors for each character
|
|
1344
1260
|
*/
|
|
1345
1261
|
getCharacterColors(e, t) {
|
|
1346
|
-
return
|
|
1262
|
+
return _.validate(
|
|
1347
1263
|
typeof e == "string" && e.length > 0,
|
|
1348
1264
|
"Characters must be a string with at least one character.",
|
|
1349
1265
|
{ method: "getCharacterColors", providedValue: e }
|
|
1350
1266
|
) ? e.split("").map((r) => this.getCharacterColor(r, t) || [0, 0, 0]) : [[0, 0, 0]];
|
|
1351
1267
|
}
|
|
1352
1268
|
}
|
|
1353
|
-
class
|
|
1269
|
+
class ue {
|
|
1354
1270
|
/**
|
|
1355
1271
|
* Creates a new TextmodeFont instance.
|
|
1356
1272
|
* @param renderer Renderer instance for texture creation
|
|
@@ -1372,7 +1288,7 @@ class ve {
|
|
|
1372
1288
|
o(this, "_textureAtlas");
|
|
1373
1289
|
o(this, "_metricsCalculator");
|
|
1374
1290
|
o(this, "_characterColorMapper");
|
|
1375
|
-
this._fontSize = t, this._characterExtractor = new
|
|
1291
|
+
this._fontSize = t, this._characterExtractor = new oe(), this._textureAtlas = new he(e), this._metricsCalculator = new le(), this._characterColorMapper = new ce();
|
|
1376
1292
|
}
|
|
1377
1293
|
/**
|
|
1378
1294
|
* Initializes the font manager by loading the font and creating the texture atlas.
|
|
@@ -1385,10 +1301,10 @@ class ve {
|
|
|
1385
1301
|
if (e) {
|
|
1386
1302
|
const r = await fetch(e);
|
|
1387
1303
|
if (!r.ok)
|
|
1388
|
-
throw new
|
|
1304
|
+
throw new x(`Failed to load font file: ${r.status} ${r.statusText}`);
|
|
1389
1305
|
t = await r.arrayBuffer();
|
|
1390
1306
|
} else
|
|
1391
|
-
throw new
|
|
1307
|
+
throw new x("Embedded font not available. This appears to be a minified build - please provide `fontSource`.");
|
|
1392
1308
|
await this._loadFontFace(t), this._font = m.parse(t)[0], await this._initializeFont();
|
|
1393
1309
|
}
|
|
1394
1310
|
/**
|
|
@@ -1421,7 +1337,7 @@ class ve {
|
|
|
1421
1337
|
try {
|
|
1422
1338
|
const t = await fetch(e);
|
|
1423
1339
|
if (!t.ok)
|
|
1424
|
-
throw new
|
|
1340
|
+
throw new x(`Failed to load font file: ${t.status} ${t.statusText}`);
|
|
1425
1341
|
const r = await t.arrayBuffer();
|
|
1426
1342
|
await this._loadFontFace(r);
|
|
1427
1343
|
const i = m.parse(r);
|
|
@@ -1429,7 +1345,7 @@ class ve {
|
|
|
1429
1345
|
throw new Error("Failed to parse font file");
|
|
1430
1346
|
this._font = i[0], await this._initializeFont();
|
|
1431
1347
|
} catch (t) {
|
|
1432
|
-
throw new
|
|
1348
|
+
throw new x(`Failed to load font: ${t instanceof Error ? t.message : "Unknown error"}`, t);
|
|
1433
1349
|
}
|
|
1434
1350
|
}
|
|
1435
1351
|
/**
|
|
@@ -1526,7 +1442,7 @@ class ve {
|
|
|
1526
1442
|
return this._font;
|
|
1527
1443
|
}
|
|
1528
1444
|
}
|
|
1529
|
-
class
|
|
1445
|
+
class de {
|
|
1530
1446
|
/**
|
|
1531
1447
|
* Create a new grid instance.
|
|
1532
1448
|
* @param canvas The canvas element used to determine the grid dimensions.
|
|
@@ -1563,9 +1479,8 @@ class xe {
|
|
|
1563
1479
|
*/
|
|
1564
1480
|
reset() {
|
|
1565
1481
|
if (!this._fixedDimensions) {
|
|
1566
|
-
const e = this._canvas.
|
|
1567
|
-
|
|
1568
|
-
[this._cols, this._rows] = [Math.floor(t / this._cellWidth), Math.floor(r / this._cellHeight)];
|
|
1482
|
+
const e = this._canvas.width, t = this._canvas.height;
|
|
1483
|
+
[this._cols, this._rows] = [Math.floor(e / this._cellWidth), Math.floor(t / this._cellHeight)];
|
|
1569
1484
|
}
|
|
1570
1485
|
this._resizeGrid();
|
|
1571
1486
|
}
|
|
@@ -1573,9 +1488,8 @@ class xe {
|
|
|
1573
1488
|
* Reset the total grid width & height, and the offset to the outer canvas.
|
|
1574
1489
|
*/
|
|
1575
1490
|
_resizeGrid() {
|
|
1576
|
-
const e = this._canvas.
|
|
1577
|
-
|
|
1578
|
-
this._width = this._cols * this._cellWidth, this._height = this._rows * this._cellHeight, this._offsetX = Math.floor((t - this._width) / 2), this._offsetY = Math.floor((r - this._height) / 2);
|
|
1491
|
+
const e = this._canvas.width, t = this._canvas.height;
|
|
1492
|
+
this._width = this._cols * this._cellWidth, this._height = this._rows * this._cellHeight, this._offsetX = Math.floor((e - this._width) / 2), this._offsetY = Math.floor((t - this._height) / 2);
|
|
1579
1493
|
}
|
|
1580
1494
|
/**
|
|
1581
1495
|
* Re-assign the grid cell dimensions and `reset()` the grid.
|
|
@@ -1663,7 +1577,7 @@ class xe {
|
|
|
1663
1577
|
return this._offsetY;
|
|
1664
1578
|
}
|
|
1665
1579
|
}
|
|
1666
|
-
class
|
|
1580
|
+
class fe {
|
|
1667
1581
|
constructor(e, t = !1, r = {}) {
|
|
1668
1582
|
o(this, "_canvas");
|
|
1669
1583
|
o(this, "captureSource");
|
|
@@ -1679,12 +1593,12 @@ class be {
|
|
|
1679
1593
|
r.width = e || 800, r.height = t || 600, document.body.appendChild(r);
|
|
1680
1594
|
else {
|
|
1681
1595
|
const s = this.captureSource.getBoundingClientRect();
|
|
1682
|
-
let
|
|
1596
|
+
let a = Math.round(s.width), n = Math.round(s.height);
|
|
1683
1597
|
if (this.captureSource instanceof HTMLVideoElement) {
|
|
1684
1598
|
const u = this.captureSource;
|
|
1685
|
-
(
|
|
1599
|
+
(a === 0 || n === 0) && u.videoWidth > 0 && u.videoHeight > 0 && (a = u.videoWidth, n = u.videoHeight);
|
|
1686
1600
|
}
|
|
1687
|
-
r.width =
|
|
1601
|
+
r.width = a, r.height = n, r.style.position = "absolute", r.style.pointerEvents = "none";
|
|
1688
1602
|
const l = window.getComputedStyle(this.captureSource);
|
|
1689
1603
|
let c = parseInt(l.zIndex || "0", 10);
|
|
1690
1604
|
isNaN(c) && (c = 0), r.style.zIndex = (c + 1).toString(), this.positionOverlayCanvas(r), (i = this.captureSource.parentNode) == null || i.insertBefore(r, this.captureSource.nextSibling);
|
|
@@ -1707,8 +1621,8 @@ class be {
|
|
|
1707
1621
|
const r = this.captureSource.getBoundingClientRect();
|
|
1708
1622
|
let i = Math.round(r.width), s = Math.round(r.height);
|
|
1709
1623
|
if (this.captureSource instanceof HTMLVideoElement) {
|
|
1710
|
-
const
|
|
1711
|
-
(i === 0 || s === 0) &&
|
|
1624
|
+
const a = this.captureSource;
|
|
1625
|
+
(i === 0 || s === 0) && a.videoWidth > 0 && a.videoHeight > 0 && (i = a.videoWidth, s = a.videoHeight);
|
|
1712
1626
|
}
|
|
1713
1627
|
this._canvas.width = i, this._canvas.height = s, this.positionOverlayCanvas(this._canvas);
|
|
1714
1628
|
}
|
|
@@ -1727,22 +1641,14 @@ class be {
|
|
|
1727
1641
|
powerPreference: "high-performance"
|
|
1728
1642
|
}, t = this._canvas.getContext("webgl2", e) || this._canvas.getContext("webgl", e);
|
|
1729
1643
|
if (!t)
|
|
1730
|
-
throw new
|
|
1644
|
+
throw new x("WebGL context could not be created. Ensure your browser supports WebGL.");
|
|
1731
1645
|
return t;
|
|
1732
1646
|
}
|
|
1733
1647
|
/**
|
|
1734
1648
|
* Get the effective rendering dimensions accounting for CSS transforms
|
|
1735
1649
|
*/
|
|
1736
1650
|
getEffectiveRenderingDimensions() {
|
|
1737
|
-
|
|
1738
|
-
return { width: 0, height: 0 };
|
|
1739
|
-
const e = this._canvas.getBoundingClientRect(), t = Math.round(e.width), r = Math.round(e.height);
|
|
1740
|
-
if (this._isStandalone) {
|
|
1741
|
-
const i = this._canvas.width, s = this._canvas.height;
|
|
1742
|
-
if (t !== i || r !== s)
|
|
1743
|
-
return { width: t, height: r };
|
|
1744
|
-
}
|
|
1745
|
-
return { width: this._canvas.width, height: this._canvas.height };
|
|
1651
|
+
return this._canvas ? { width: this._canvas.width, height: this._canvas.height } : { width: 0, height: 0 };
|
|
1746
1652
|
}
|
|
1747
1653
|
/**
|
|
1748
1654
|
* Check if the canvas is affected by CSS transforms
|
|
@@ -1788,7 +1694,7 @@ class be {
|
|
|
1788
1694
|
return this._canvas.height;
|
|
1789
1695
|
}
|
|
1790
1696
|
}
|
|
1791
|
-
class
|
|
1697
|
+
class D {
|
|
1792
1698
|
/**
|
|
1793
1699
|
* Creates a new TextmodeConverter instance.
|
|
1794
1700
|
* @param renderer Renderer instance for texture creation
|
|
@@ -1867,7 +1773,7 @@ class U {
|
|
|
1867
1773
|
return this._options;
|
|
1868
1774
|
}
|
|
1869
1775
|
}
|
|
1870
|
-
class
|
|
1776
|
+
class me {
|
|
1871
1777
|
/**
|
|
1872
1778
|
* Create a new color palette instance.
|
|
1873
1779
|
* @param renderer The renderer instance.
|
|
@@ -1891,8 +1797,8 @@ class Ce {
|
|
|
1891
1797
|
this._framebuffer.width !== e && this._framebuffer.resize(e, t);
|
|
1892
1798
|
const r = new Uint8Array(e * t * 4);
|
|
1893
1799
|
for (let i = 0; i < e; i++) {
|
|
1894
|
-
const s = i < this._colors.length ? this._colors[i] : [0, 0, 0],
|
|
1895
|
-
r[
|
|
1800
|
+
const s = i < this._colors.length ? this._colors[i] : [0, 0, 0], a = i * 4;
|
|
1801
|
+
r[a] = s[0], r[a + 1] = s[1], r[a + 2] = s[2], r[a + 3] = 255;
|
|
1896
1802
|
}
|
|
1897
1803
|
this._framebuffer.updatePixels(r, e, t);
|
|
1898
1804
|
}
|
|
@@ -1922,18 +1828,18 @@ class Ce {
|
|
|
1922
1828
|
return this._framebuffer.texture;
|
|
1923
1829
|
}
|
|
1924
1830
|
}
|
|
1925
|
-
class
|
|
1831
|
+
class N extends D {
|
|
1926
1832
|
constructor(t, r, i, s = {}) {
|
|
1927
1833
|
super(t, r, i, s);
|
|
1928
1834
|
o(this, "palette");
|
|
1929
|
-
this.palette = new
|
|
1835
|
+
this.palette = new me(this.renderer, this.fontManager.getCharacterColors(" .:-=+*%@#"));
|
|
1930
1836
|
}
|
|
1931
1837
|
/**
|
|
1932
1838
|
* Sets the characters used for mapping.
|
|
1933
1839
|
* @param characters The characters to use for mapping, usually ordered from darkest to brightest.
|
|
1934
1840
|
*/
|
|
1935
1841
|
characters(t) {
|
|
1936
|
-
|
|
1842
|
+
_.validate(
|
|
1937
1843
|
this.fontManager.hasAllCharacters(t),
|
|
1938
1844
|
"One or more characters do not exist in the current font.",
|
|
1939
1845
|
{ method: "characters", providedValue: t }
|
|
@@ -1948,25 +1854,25 @@ class O extends U {
|
|
|
1948
1854
|
* @param a Alpha component (0-255).
|
|
1949
1855
|
*/
|
|
1950
1856
|
characterColor(t, r, i, s = 255) {
|
|
1951
|
-
let
|
|
1857
|
+
let a, n, l, c;
|
|
1952
1858
|
if (typeof t == "string") {
|
|
1953
1859
|
const u = this.parseHexColor(t);
|
|
1954
1860
|
if (!u) {
|
|
1955
|
-
|
|
1861
|
+
_.validate(
|
|
1956
1862
|
!1,
|
|
1957
1863
|
"Invalid hex color format. Use '#FF0000', '#F00', 'FF0000', or 'F00'.",
|
|
1958
1864
|
{ method: "characterColor", providedValue: t }
|
|
1959
1865
|
);
|
|
1960
1866
|
return;
|
|
1961
1867
|
}
|
|
1962
|
-
[
|
|
1963
|
-
} else if (
|
|
1964
|
-
[
|
|
1868
|
+
[a, n, l, c] = u;
|
|
1869
|
+
} else if (a = t, n = r !== void 0 ? r : t, l = i !== void 0 ? i : t, c = s, !_.validate(
|
|
1870
|
+
[a, n, l, c].every((u) => u >= 0 && u <= 255),
|
|
1965
1871
|
"Character color values must be between 0 and 255",
|
|
1966
|
-
{ method: "characterColor", providedValues: { r:
|
|
1872
|
+
{ method: "characterColor", providedValues: { r: a, g: n, b: l, a: c } }
|
|
1967
1873
|
))
|
|
1968
1874
|
return;
|
|
1969
|
-
this._options.characterColor = [
|
|
1875
|
+
this._options.characterColor = [a / 255, n / 255, l / 255, c / 255];
|
|
1970
1876
|
}
|
|
1971
1877
|
/**
|
|
1972
1878
|
* Sets the character color mode.
|
|
@@ -1975,7 +1881,7 @@ class O extends U {
|
|
|
1975
1881
|
* @param mode The color mode to use for characters.
|
|
1976
1882
|
*/
|
|
1977
1883
|
characterColorMode(t) {
|
|
1978
|
-
|
|
1884
|
+
_.validate(
|
|
1979
1885
|
["sampled", "fixed"].includes(t),
|
|
1980
1886
|
"Invalid character color mode. Must be 'sampled' or 'fixed'.",
|
|
1981
1887
|
{ method: "characterColorMode", providedValue: t }
|
|
@@ -1990,25 +1896,25 @@ class O extends U {
|
|
|
1990
1896
|
* @param a Alpha component (0-255).
|
|
1991
1897
|
*/
|
|
1992
1898
|
cellColor(t, r, i, s = 255) {
|
|
1993
|
-
let
|
|
1899
|
+
let a, n, l, c;
|
|
1994
1900
|
if (typeof t == "string") {
|
|
1995
1901
|
const u = this.parseHexColor(t);
|
|
1996
1902
|
if (!u) {
|
|
1997
|
-
|
|
1903
|
+
_.validate(
|
|
1998
1904
|
!1,
|
|
1999
1905
|
"Invalid hex color format. Use '#FF0000', '#F00', 'FF0000', or 'F00'.",
|
|
2000
1906
|
{ method: "cellColor", providedValue: t }
|
|
2001
1907
|
);
|
|
2002
1908
|
return;
|
|
2003
1909
|
}
|
|
2004
|
-
[
|
|
2005
|
-
} else if (
|
|
2006
|
-
[
|
|
1910
|
+
[a, n, l, c] = u;
|
|
1911
|
+
} else if (a = t, n = r !== void 0 ? r : t, l = i !== void 0 ? i : t, c = s, !_.validate(
|
|
1912
|
+
[a, n, l, c].every((u) => u >= 0 && u <= 255),
|
|
2007
1913
|
"Cell color values must be between 0 and 255",
|
|
2008
|
-
{ method: "cellColor", providedValues: { r:
|
|
1914
|
+
{ method: "cellColor", providedValues: { r: a, g: n, b: l, a: c } }
|
|
2009
1915
|
))
|
|
2010
1916
|
return;
|
|
2011
|
-
this._options.cellColor = [
|
|
1917
|
+
this._options.cellColor = [a / 255, n / 255, l / 255, c / 255];
|
|
2012
1918
|
}
|
|
2013
1919
|
/**
|
|
2014
1920
|
* Sets the cell color mode.
|
|
@@ -2017,7 +1923,7 @@ class O extends U {
|
|
|
2017
1923
|
* @param mode The color mode to use for background cells.
|
|
2018
1924
|
*/
|
|
2019
1925
|
cellColorMode(t) {
|
|
2020
|
-
|
|
1926
|
+
_.validate(
|
|
2021
1927
|
["sampled", "fixed"].includes(t),
|
|
2022
1928
|
"Invalid cell color mode. Must be 'sampled' or 'fixed'.",
|
|
2023
1929
|
{ method: "cellColorMode", providedValue: t }
|
|
@@ -2028,7 +1934,7 @@ class O extends U {
|
|
|
2028
1934
|
* @param invert If `true`, the character color becomes the cell color and vice versa.
|
|
2029
1935
|
*/
|
|
2030
1936
|
invert(t) {
|
|
2031
|
-
|
|
1937
|
+
_.validate(
|
|
2032
1938
|
typeof t == "boolean" || typeof t == "number" && Number.isInteger(t),
|
|
2033
1939
|
"Invert must be a boolean value or an integer (0 for false, any other number for true).",
|
|
2034
1940
|
{ method: "invert", providedValue: t }
|
|
@@ -2039,7 +1945,7 @@ class O extends U {
|
|
|
2039
1945
|
* @param angle The rotation angle in degrees.
|
|
2040
1946
|
*/
|
|
2041
1947
|
rotation(t) {
|
|
2042
|
-
if (!
|
|
1948
|
+
if (!_.validate(
|
|
2043
1949
|
typeof t == "number",
|
|
2044
1950
|
"Rotation angle must be a number.",
|
|
2045
1951
|
{ method: "rotation", providedValue: t }
|
|
@@ -2054,7 +1960,7 @@ class O extends U {
|
|
|
2054
1960
|
* @param flip If `true`, characters are flipped horizontally. If `false`, no flip is applied.
|
|
2055
1961
|
*/
|
|
2056
1962
|
flipHorizontally(t) {
|
|
2057
|
-
|
|
1963
|
+
_.validate(
|
|
2058
1964
|
typeof t == "boolean" || typeof t == "number" && Number.isInteger(t),
|
|
2059
1965
|
"Flip horizontally must be a boolean value or an integer (0 for false, any other number for true).",
|
|
2060
1966
|
{ method: "flipHorizontally", providedValue: t }
|
|
@@ -2065,7 +1971,7 @@ class O extends U {
|
|
|
2065
1971
|
* @param flip If `true`, characters are flipped vertically. If `false`, no flip is applied.
|
|
2066
1972
|
*/
|
|
2067
1973
|
flipVertically(t) {
|
|
2068
|
-
|
|
1974
|
+
_.validate(
|
|
2069
1975
|
typeof t == "boolean" || typeof t == "number" && Number.isInteger(t),
|
|
2070
1976
|
"Flip vertically must be a boolean value or an integer (0 for false, any other number for true).",
|
|
2071
1977
|
{ method: "flipVertically", providedValue: t }
|
|
@@ -2079,13 +1985,13 @@ class O extends U {
|
|
|
2079
1985
|
parseHexColor(t) {
|
|
2080
1986
|
if (t = t.replace(/^#/, ""), !/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(t))
|
|
2081
1987
|
return null;
|
|
2082
|
-
t.length === 3 && (t = t.split("").map((
|
|
1988
|
+
t.length === 3 && (t = t.split("").map((a) => a + a).join(""));
|
|
2083
1989
|
const r = parseInt(t.slice(0, 2), 16), i = parseInt(t.slice(2, 4), 16), s = parseInt(t.slice(4, 6), 16);
|
|
2084
1990
|
return [r, i, s, 255];
|
|
2085
1991
|
}
|
|
2086
1992
|
}
|
|
2087
|
-
var
|
|
2088
|
-
const
|
|
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 = {
|
|
2089
1995
|
/** Enable/disable the renderer */
|
|
2090
1996
|
enabled: !0,
|
|
2091
1997
|
/** Characters used for brightness mapping (from darkest to brightest) */
|
|
@@ -2111,7 +2017,7 @@ const Re = {
|
|
|
2111
2017
|
/** Range of brightness values to map to ASCII characters */
|
|
2112
2018
|
brightnessRange: [0, 255]
|
|
2113
2019
|
};
|
|
2114
|
-
class L extends
|
|
2020
|
+
class L extends N {
|
|
2115
2021
|
/**
|
|
2116
2022
|
* Creates a new TextmodeBrightnessConverter instance.
|
|
2117
2023
|
* @param renderer Renderer instance for texture creation
|
|
@@ -2120,14 +2026,14 @@ class L extends O {
|
|
|
2120
2026
|
* @ignore
|
|
2121
2027
|
*/
|
|
2122
2028
|
constructor(t, r, i) {
|
|
2123
|
-
super(t, r, i, { ...
|
|
2029
|
+
super(t, r, i, { ...xe });
|
|
2124
2030
|
o(this, "sampleShader");
|
|
2125
2031
|
o(this, "colorFillShader");
|
|
2126
2032
|
o(this, "charMappingShader");
|
|
2127
2033
|
o(this, "transformFillShader");
|
|
2128
2034
|
o(this, "rotationFillShader");
|
|
2129
2035
|
o(this, "sampleFramebuffer");
|
|
2130
|
-
this.sampleShader = new y(t.context, T,
|
|
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);
|
|
2131
2037
|
}
|
|
2132
2038
|
convert(t) {
|
|
2133
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();
|
|
@@ -2143,21 +2049,21 @@ class L extends O {
|
|
|
2143
2049
|
* @param range Array of two numbers `[min, max]`, where `min` is darkest and `max` is brightest.
|
|
2144
2050
|
*/
|
|
2145
2051
|
brightnessRange(t) {
|
|
2146
|
-
|
|
2052
|
+
_.validate(
|
|
2147
2053
|
Array.isArray(t) && t.length === 2 && t.every((r) => typeof r == "number" && r >= 0 && r <= 255),
|
|
2148
2054
|
"Brightness range must be an array of two numbers between 0 and 255.",
|
|
2149
2055
|
{ method: "brightnessRange", providedValue: t }
|
|
2150
2056
|
) && (this._options.brightnessRange = t);
|
|
2151
2057
|
}
|
|
2152
2058
|
}
|
|
2153
|
-
const
|
|
2059
|
+
const Pe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2154
2060
|
__proto__: null,
|
|
2155
2061
|
TextmodeBrightnessConverter: L,
|
|
2156
|
-
TextmodeConverter:
|
|
2157
|
-
TextmodeFeatureConverter:
|
|
2062
|
+
TextmodeConverter: D,
|
|
2063
|
+
TextmodeFeatureConverter: N
|
|
2158
2064
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2159
|
-
var
|
|
2160
|
-
class
|
|
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 {
|
|
2161
2067
|
/**
|
|
2162
2068
|
* Creates an instance of TextmodeConversionPipeline.
|
|
2163
2069
|
* @param renderer The renderer to use for the pipeline.
|
|
@@ -2177,9 +2083,9 @@ class Ue {
|
|
|
2177
2083
|
o(this, "_secondaryColorFramebuffer");
|
|
2178
2084
|
o(this, "_rotationFramebuffer");
|
|
2179
2085
|
o(this, "_transformFramebuffer");
|
|
2180
|
-
this.renderer = e, this.font = t, this.grid = r, this._asciiShader = this.renderer.createShader(T,
|
|
2086
|
+
this.renderer = e, this.font = t, this.grid = r, this._asciiShader = this.renderer.createShader(T, Ce), this.converters = [
|
|
2181
2087
|
{ name: "brightness", converter: new L(e, t, r) },
|
|
2182
|
-
{ name: "custom", converter: new
|
|
2088
|
+
{ name: "custom", converter: new D(e, t, r) }
|
|
2183
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);
|
|
2184
2090
|
}
|
|
2185
2091
|
/**
|
|
@@ -2190,13 +2096,13 @@ class Ue {
|
|
|
2190
2096
|
render(e) {
|
|
2191
2097
|
for (const r of this.converters) {
|
|
2192
2098
|
const i = r.converter;
|
|
2193
|
-
i.options.enabled && i instanceof
|
|
2099
|
+
i.options.enabled && i instanceof N && i.convert(e);
|
|
2194
2100
|
}
|
|
2195
2101
|
const t = (r, i) => {
|
|
2196
2102
|
r.begin(), this.renderer.clear();
|
|
2197
2103
|
for (const s of this.converters) {
|
|
2198
|
-
const
|
|
2199
|
-
|
|
2104
|
+
const a = s.converter;
|
|
2105
|
+
a.options.enabled && this.renderer.image(i(a), 0, 0);
|
|
2200
2106
|
}
|
|
2201
2107
|
r.end();
|
|
2202
2108
|
};
|
|
@@ -2208,15 +2114,15 @@ class Ue {
|
|
|
2208
2114
|
* @returns The requested `TextmodeConverter` instance.
|
|
2209
2115
|
*/
|
|
2210
2116
|
get(e) {
|
|
2211
|
-
if (!
|
|
2117
|
+
if (!_.validate(
|
|
2212
2118
|
typeof e == "string" && e.length > 0,
|
|
2213
2119
|
"Converter name must be a non-empty string.",
|
|
2214
2120
|
{ method: "converter", providedValue: e }
|
|
2215
2121
|
))
|
|
2216
2122
|
return;
|
|
2217
2123
|
const t = this.converters.find((i) => i.name === e), r = t == null ? void 0 : t.converter;
|
|
2218
|
-
if (
|
|
2219
|
-
r instanceof
|
|
2124
|
+
if (_.validate(
|
|
2125
|
+
r instanceof D,
|
|
2220
2126
|
`Converter "${e}" is not a valid TextmodeConverter.`,
|
|
2221
2127
|
{ method: "converter", providedValue: e, converterInstance: r }
|
|
2222
2128
|
))
|
|
@@ -2229,33 +2135,33 @@ class Ue {
|
|
|
2229
2135
|
* @returns The newly created {@link TextmodeConverter} instance or `void` if the addition failed.
|
|
2230
2136
|
*/
|
|
2231
2137
|
add(e, t) {
|
|
2232
|
-
if (!
|
|
2138
|
+
if (!_.validate(
|
|
2233
2139
|
typeof e == "string" && e.length > 0,
|
|
2234
2140
|
"Converter name must be a non-empty string.",
|
|
2235
2141
|
{ method: "add", providedValue: e }
|
|
2236
|
-
) || !
|
|
2142
|
+
) || !_.validate(
|
|
2237
2143
|
t === "brightness" || t === "custom",
|
|
2238
2144
|
`Converter type must be either "brightness" or "custom". Provided: ${t}`,
|
|
2239
2145
|
{ method: "add", providedValue: t }
|
|
2240
2146
|
))
|
|
2241
2147
|
return;
|
|
2242
2148
|
let r;
|
|
2243
|
-
return t === "brightness" ? r = new L(this.renderer, this.font, this.grid) : r = new
|
|
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;
|
|
2244
2150
|
}
|
|
2245
2151
|
/**
|
|
2246
2152
|
* Removes a converter from the pipeline by name or instance.
|
|
2247
2153
|
* @param nameOrInstance The unique name of the converter or the converter instance to remove.
|
|
2248
2154
|
*/
|
|
2249
2155
|
remove(e) {
|
|
2250
|
-
if (!
|
|
2251
|
-
typeof e == "string" || e instanceof
|
|
2156
|
+
if (!_.validate(
|
|
2157
|
+
typeof e == "string" || e instanceof D,
|
|
2252
2158
|
"Parameter must be either a string (converter name) or a TextmodeConverter instance.",
|
|
2253
2159
|
{ method: "remove", providedValue: e }
|
|
2254
2160
|
))
|
|
2255
2161
|
return;
|
|
2256
2162
|
let t = -1;
|
|
2257
2163
|
if (typeof e == "string") {
|
|
2258
|
-
if (!
|
|
2164
|
+
if (!_.validate(
|
|
2259
2165
|
e.length > 0,
|
|
2260
2166
|
"Converter name must be a non-empty string.",
|
|
2261
2167
|
{ method: "remove", providedValue: e }
|
|
@@ -2264,7 +2170,7 @@ class Ue {
|
|
|
2264
2170
|
t = this.converters.findIndex((r) => r.name === e);
|
|
2265
2171
|
} else
|
|
2266
2172
|
t = this.converters.findIndex((r) => r.converter === e);
|
|
2267
|
-
|
|
2173
|
+
_.validate(
|
|
2268
2174
|
t !== -1,
|
|
2269
2175
|
typeof e == "string" ? `Converter with name "${e}" not found in pipeline.` : "Converter instance not found in pipeline.",
|
|
2270
2176
|
{ method: "remove", providedValue: e, convertersCount: this.converters.length }
|
|
@@ -2343,13 +2249,13 @@ class H {
|
|
|
2343
2249
|
* @returns Object containing all pixel data arrays
|
|
2344
2250
|
*/
|
|
2345
2251
|
extractFramebufferData(e) {
|
|
2346
|
-
const t = e.get("brightness"), r = t == null ? void 0 : t.characterFramebuffer, i = t == null ? void 0 : t.primaryColorFramebuffer, s = t == null ? void 0 : t.secondaryColorFramebuffer,
|
|
2347
|
-
return r == null || r.loadPixels(), i == null || i.loadPixels(), s == null || s.loadPixels(),
|
|
2252
|
+
const t = e.get("brightness"), r = t == null ? void 0 : t.characterFramebuffer, i = t == null ? void 0 : t.primaryColorFramebuffer, s = t == null ? void 0 : t.secondaryColorFramebuffer, a = t == null ? void 0 : t.transformFramebuffer, n = t == null ? void 0 : t.rotationFramebuffer;
|
|
2253
|
+
return r == null || r.loadPixels(), i == null || i.loadPixels(), s == null || s.loadPixels(), a == null || a.loadPixels(), n == null || n.loadPixels(), {
|
|
2348
2254
|
characterPixels: (r == null ? void 0 : r.pixels) || new Uint8Array(0),
|
|
2349
2255
|
primaryColorPixels: (i == null ? void 0 : i.pixels) || new Uint8Array(0),
|
|
2350
2256
|
secondaryColorPixels: (s == null ? void 0 : s.pixels) || new Uint8Array(0),
|
|
2351
|
-
transformPixels: (
|
|
2352
|
-
rotationPixels: (
|
|
2257
|
+
transformPixels: (a == null ? void 0 : a.pixels) || new Uint8Array(0),
|
|
2258
|
+
rotationPixels: (n == null ? void 0 : n.pixels) || new Uint8Array(0)
|
|
2353
2259
|
};
|
|
2354
2260
|
}
|
|
2355
2261
|
/**
|
|
@@ -2396,8 +2302,8 @@ class X {
|
|
|
2396
2302
|
*/
|
|
2397
2303
|
downloadFile(e, t, r) {
|
|
2398
2304
|
try {
|
|
2399
|
-
const i = this.createBlob(e, r), s = URL.createObjectURL(i),
|
|
2400
|
-
|
|
2305
|
+
const i = this.createBlob(e, r), s = URL.createObjectURL(i), a = document.createElement("a");
|
|
2306
|
+
a.href = s, a.download = t, a.style.display = "none", a.rel = "noopener", document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(s);
|
|
2401
2307
|
} catch (i) {
|
|
2402
2308
|
throw console.error("Failed to download file:", i), new Error(`File download failed: ${i instanceof Error ? i.message : "Unknown error"}`);
|
|
2403
2309
|
}
|
|
@@ -2435,7 +2341,7 @@ class X {
|
|
|
2435
2341
|
return `'textmode-export'-${this.generateTimestamp()}`;
|
|
2436
2342
|
}
|
|
2437
2343
|
}
|
|
2438
|
-
class
|
|
2344
|
+
class we extends H {
|
|
2439
2345
|
/**
|
|
2440
2346
|
* Extracts transform data from transform pixels
|
|
2441
2347
|
* @param transformPixels Transform framebuffer pixels
|
|
@@ -2444,9 +2350,9 @@ class Ae extends H {
|
|
|
2444
2350
|
* @returns Transform data object
|
|
2445
2351
|
*/
|
|
2446
2352
|
extractTransformData(e, t, r) {
|
|
2447
|
-
const i = e[r], s = e[r + 1],
|
|
2353
|
+
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;
|
|
2448
2354
|
return {
|
|
2449
|
-
isInverted:
|
|
2355
|
+
isInverted: n,
|
|
2450
2356
|
flipHorizontal: l,
|
|
2451
2357
|
flipVertical: c,
|
|
2452
2358
|
rotation: g
|
|
@@ -2478,22 +2384,22 @@ class Ae extends H {
|
|
|
2478
2384
|
const r = [];
|
|
2479
2385
|
let i = 0;
|
|
2480
2386
|
for (let s = 0; s < t.rows; s++)
|
|
2481
|
-
for (let
|
|
2482
|
-
const
|
|
2387
|
+
for (let a = 0; a < t.cols; a++) {
|
|
2388
|
+
const n = i * 4, l = this.getCharacterIndex(
|
|
2483
2389
|
e.characterPixels,
|
|
2484
|
-
|
|
2390
|
+
n
|
|
2485
2391
|
);
|
|
2486
|
-
let c = this.pixelsToRGBA(e.primaryColorPixels,
|
|
2392
|
+
let c = this.pixelsToRGBA(e.primaryColorPixels, n), u = this.pixelsToRGBA(e.secondaryColorPixels, n);
|
|
2487
2393
|
const d = this.extractTransformData(
|
|
2488
2394
|
e.transformPixels,
|
|
2489
2395
|
e.rotationPixels,
|
|
2490
|
-
|
|
2396
|
+
n
|
|
2491
2397
|
);
|
|
2492
2398
|
if (d.isInverted) {
|
|
2493
2399
|
const g = c;
|
|
2494
2400
|
c = u, u = g;
|
|
2495
2401
|
}
|
|
2496
|
-
const f = this.calculateCellPosition(
|
|
2402
|
+
const f = this.calculateCellPosition(a, s, t);
|
|
2497
2403
|
r.push({
|
|
2498
2404
|
charIndex: l,
|
|
2499
2405
|
primaryColor: c,
|
|
@@ -2505,7 +2411,7 @@ class Ae extends H {
|
|
|
2505
2411
|
return r;
|
|
2506
2412
|
}
|
|
2507
2413
|
}
|
|
2508
|
-
class
|
|
2414
|
+
class ye {
|
|
2509
2415
|
/**
|
|
2510
2416
|
* Gets the glyph index for a given Unicode code point in a Typr.js font
|
|
2511
2417
|
* @param fontData The Typr.js font data
|
|
@@ -2522,11 +2428,11 @@ class Me {
|
|
|
2522
2428
|
if (i.idRangeOffset[s] === 0)
|
|
2523
2429
|
return t + i.idDelta[s] & 65535;
|
|
2524
2430
|
{
|
|
2525
|
-
const
|
|
2526
|
-
if (
|
|
2527
|
-
const
|
|
2528
|
-
if (
|
|
2529
|
-
return
|
|
2431
|
+
const a = i.idRangeOffset[s] / 2 + (t - i.startCount[s]) - (i.startCount.length - s);
|
|
2432
|
+
if (a >= 0 && a < i.glyphIdArray.length) {
|
|
2433
|
+
const n = i.glyphIdArray[a];
|
|
2434
|
+
if (n !== 0)
|
|
2435
|
+
return n + i.idDelta[s] & 65535;
|
|
2530
2436
|
}
|
|
2531
2437
|
}
|
|
2532
2438
|
}
|
|
@@ -2555,15 +2461,15 @@ class Me {
|
|
|
2555
2461
|
createGlyphPath(e, t, r, i, s) {
|
|
2556
2462
|
if (!t || !t.xs || t.xs.length === 0)
|
|
2557
2463
|
return this.createEmptyPath();
|
|
2558
|
-
const
|
|
2464
|
+
const a = s / e.head.unitsPerEm;
|
|
2559
2465
|
return {
|
|
2560
2466
|
getBoundingBox: () => ({
|
|
2561
|
-
x1: r + t.xMin *
|
|
2562
|
-
y1: i + -t.yMax *
|
|
2563
|
-
x2: r + t.xMax *
|
|
2564
|
-
y2: i + -t.yMin *
|
|
2467
|
+
x1: r + t.xMin * a,
|
|
2468
|
+
y1: i + -t.yMax * a,
|
|
2469
|
+
x2: r + t.xMax * a,
|
|
2470
|
+
y2: i + -t.yMin * a
|
|
2565
2471
|
}),
|
|
2566
|
-
toSVG: () => this.glyphToSVGPath(t, r, i,
|
|
2472
|
+
toSVG: () => this.glyphToSVGPath(t, r, i, a)
|
|
2567
2473
|
};
|
|
2568
2474
|
}
|
|
2569
2475
|
/**
|
|
@@ -2576,29 +2482,29 @@ class Me {
|
|
|
2576
2482
|
*/
|
|
2577
2483
|
glyphToSVGPath(e, t, r, i) {
|
|
2578
2484
|
if (!e || !e.xs) return "";
|
|
2579
|
-
const { xs: s, ys:
|
|
2580
|
-
if (!s || !
|
|
2485
|
+
const { xs: s, ys: a, endPts: n, flags: l } = e;
|
|
2486
|
+
if (!s || !a || !n || !l) return "";
|
|
2581
2487
|
let c = "", u = 0;
|
|
2582
|
-
for (let d = 0; d <
|
|
2583
|
-
const f =
|
|
2488
|
+
for (let d = 0; d < n.length; d++) {
|
|
2489
|
+
const f = n[d];
|
|
2584
2490
|
if (!(f < u)) {
|
|
2585
2491
|
if (f >= u) {
|
|
2586
|
-
const g = t + s[u] * i,
|
|
2587
|
-
c += `M${g.toFixed(2)},${
|
|
2492
|
+
const g = t + s[u] * i, v = r - a[u] * i;
|
|
2493
|
+
c += `M${g.toFixed(2)},${v.toFixed(2)}`;
|
|
2588
2494
|
let p = u + 1;
|
|
2589
2495
|
for (; p <= f; )
|
|
2590
2496
|
if ((l[p] & 1) !== 0) {
|
|
2591
|
-
const
|
|
2592
|
-
c += `L${
|
|
2497
|
+
const w = t + s[p] * i, F = r - a[p] * i;
|
|
2498
|
+
c += `L${w.toFixed(2)},${F.toFixed(2)}`, p++;
|
|
2593
2499
|
} else {
|
|
2594
|
-
const
|
|
2595
|
-
let
|
|
2596
|
-
if ((l[
|
|
2597
|
-
const
|
|
2598
|
-
c += `Q${
|
|
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;
|
|
2599
2505
|
} else {
|
|
2600
|
-
const
|
|
2601
|
-
c += `Q${
|
|
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;
|
|
2602
2508
|
}
|
|
2603
2509
|
}
|
|
2604
2510
|
c += "Z";
|
|
@@ -2619,18 +2525,18 @@ class Me {
|
|
|
2619
2525
|
*/
|
|
2620
2526
|
generateCharacterPath(e, t, r, i, s) {
|
|
2621
2527
|
try {
|
|
2622
|
-
const
|
|
2623
|
-
if (
|
|
2528
|
+
const a = e.codePointAt(0) || 0, n = this.getGlyphIndex(t, a);
|
|
2529
|
+
if (n === 0)
|
|
2624
2530
|
return this.createEmptyPath();
|
|
2625
2531
|
let l = null;
|
|
2626
2532
|
try {
|
|
2627
|
-
t.glyf && t.glyf[
|
|
2533
|
+
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));
|
|
2628
2534
|
} catch (c) {
|
|
2629
|
-
console.warn(`Failed to parse glyph ${
|
|
2535
|
+
console.warn(`Failed to parse glyph ${n}:`, c);
|
|
2630
2536
|
}
|
|
2631
2537
|
return l ? this.createGlyphPath(t, l, r, i, s) : this.createEmptyPath();
|
|
2632
|
-
} catch (
|
|
2633
|
-
return console.warn(`Failed to generate path for character "${e}":`,
|
|
2538
|
+
} catch (a) {
|
|
2539
|
+
return console.warn(`Failed to generate path for character "${e}":`, a), this.createEmptyPath();
|
|
2634
2540
|
}
|
|
2635
2541
|
}
|
|
2636
2542
|
/**
|
|
@@ -2645,19 +2551,19 @@ class Me {
|
|
|
2645
2551
|
* @param advanceWidth Character advance width
|
|
2646
2552
|
* @returns SVG path data string or null if generation fails
|
|
2647
2553
|
*/
|
|
2648
|
-
generatePositionedCharacterPath(e, t, r, i, s,
|
|
2554
|
+
generatePositionedCharacterPath(e, t, r, i, s, a, n, l) {
|
|
2649
2555
|
try {
|
|
2650
|
-
const c =
|
|
2651
|
-
return this.generateCharacterPath(e, t, d, f,
|
|
2556
|
+
const c = n / t.head.unitsPerEm, u = l * c, d = r + (s - u) / 2, f = i + (a + n * 0.7) / 2;
|
|
2557
|
+
return this.generateCharacterPath(e, t, d, f, n).toSVG() || null;
|
|
2652
2558
|
} catch (c) {
|
|
2653
2559
|
return console.warn(`Failed to generate positioned character path for "${e}":`, c), null;
|
|
2654
2560
|
}
|
|
2655
2561
|
}
|
|
2656
2562
|
}
|
|
2657
|
-
class
|
|
2563
|
+
class Te {
|
|
2658
2564
|
constructor() {
|
|
2659
2565
|
o(this, "pathGenerator");
|
|
2660
|
-
this.pathGenerator = new
|
|
2566
|
+
this.pathGenerator = new ye();
|
|
2661
2567
|
}
|
|
2662
2568
|
/**
|
|
2663
2569
|
* Generates the SVG header with metadata
|
|
@@ -2709,12 +2615,12 @@ class De {
|
|
|
2709
2615
|
* @returns Transform attribute string or empty string
|
|
2710
2616
|
*/
|
|
2711
2617
|
generateTransformAttribute(e, t) {
|
|
2712
|
-
const { transform: r, position: i } = e, s = i.cellX + t.cellWidth / 2,
|
|
2618
|
+
const { transform: r, position: i } = e, s = i.cellX + t.cellWidth / 2, a = i.cellY + t.cellHeight / 2, n = [];
|
|
2713
2619
|
if (r.flipHorizontal || r.flipVertical) {
|
|
2714
2620
|
const l = r.flipHorizontal ? -1 : 1, c = r.flipVertical ? -1 : 1;
|
|
2715
|
-
|
|
2621
|
+
n.push(`translate(${s} ${a})`), n.push(`scale(${l} ${c})`), n.push(`translate(${-s} ${-a})`);
|
|
2716
2622
|
}
|
|
2717
|
-
return r.rotation &&
|
|
2623
|
+
return r.rotation && n.push(`rotate(${r.rotation} ${s} ${a})`), n.length ? ` transform="${n.join(" ")}"` : "";
|
|
2718
2624
|
}
|
|
2719
2625
|
/**
|
|
2720
2626
|
* Generates background rectangle for a cell
|
|
@@ -2743,7 +2649,7 @@ class De {
|
|
|
2743
2649
|
const s = r.characters[e.charIndex];
|
|
2744
2650
|
if (!s)
|
|
2745
2651
|
return "";
|
|
2746
|
-
const
|
|
2652
|
+
const a = this.pathGenerator.generatePositionedCharacterPath(
|
|
2747
2653
|
s.character,
|
|
2748
2654
|
r.font,
|
|
2749
2655
|
e.position.cellX,
|
|
@@ -2753,12 +2659,12 @@ class De {
|
|
|
2753
2659
|
r.fontSize,
|
|
2754
2660
|
s.advanceWidth
|
|
2755
2661
|
);
|
|
2756
|
-
if (!
|
|
2662
|
+
if (!a)
|
|
2757
2663
|
return "";
|
|
2758
|
-
const
|
|
2664
|
+
const n = this.rgbaToColorString(e.primaryColor);
|
|
2759
2665
|
return i.drawMode === "stroke" ? `
|
|
2760
|
-
<path id="${`path-${e.charIndex}-${e.position.cellX}-${e.position.cellY}`.replace(/\./g, "-")}" d="${
|
|
2761
|
-
<path d="${
|
|
2666
|
+
<path id="${`path-${e.charIndex}-${e.position.cellX}-${e.position.cellY}`.replace(/\./g, "-")}" d="${a}" stroke="${n}" stroke-width="${i.strokeWidth}" fill="none" />` : `
|
|
2667
|
+
<path d="${a}" fill="${n}" />`;
|
|
2762
2668
|
}
|
|
2763
2669
|
/**
|
|
2764
2670
|
* Generates complete SVG content for a single cell
|
|
@@ -2771,10 +2677,10 @@ class De {
|
|
|
2771
2677
|
generateCellContent(e, t, r, i) {
|
|
2772
2678
|
let s = "";
|
|
2773
2679
|
s += this.generateCellBackground(e, t, i);
|
|
2774
|
-
const
|
|
2775
|
-
return
|
|
2776
|
-
<g${
|
|
2777
|
-
</g>`) : s +=
|
|
2680
|
+
const a = this.generateTransformAttribute(e, t), n = this.generateCharacterPath(e, t, r, i);
|
|
2681
|
+
return n && (a ? (s += `
|
|
2682
|
+
<g${a}>`, s += n, s += `
|
|
2683
|
+
</g>`) : s += n), s;
|
|
2778
2684
|
}
|
|
2779
2685
|
/**
|
|
2780
2686
|
* Generates the complete SVG content from cell data
|
|
@@ -2788,8 +2694,8 @@ class De {
|
|
|
2788
2694
|
let s = this.generateSVGHeader(t);
|
|
2789
2695
|
s += this.generateBackground(t, i), s += `
|
|
2790
2696
|
<g id="ascii-cells">`;
|
|
2791
|
-
for (const
|
|
2792
|
-
s += this.generateCellContent(
|
|
2697
|
+
for (const a of e)
|
|
2698
|
+
s += this.generateCellContent(a, t, r, i);
|
|
2793
2699
|
return s += this.generateSVGFooter(), s;
|
|
2794
2700
|
}
|
|
2795
2701
|
/**
|
|
@@ -2802,7 +2708,7 @@ class De {
|
|
|
2802
2708
|
`).replace(/[ \t]+$/gm, "");
|
|
2803
2709
|
}
|
|
2804
2710
|
}
|
|
2805
|
-
class
|
|
2711
|
+
class Se extends X {
|
|
2806
2712
|
/**
|
|
2807
2713
|
* Creates a downloadable blob from SVG content
|
|
2808
2714
|
* @param svgContent The SVG content string
|
|
@@ -2832,12 +2738,12 @@ class Ie extends X {
|
|
|
2832
2738
|
this.downloadSVG(e, t || this.generateDefaultFilename());
|
|
2833
2739
|
}
|
|
2834
2740
|
}
|
|
2835
|
-
class
|
|
2741
|
+
class q {
|
|
2836
2742
|
constructor() {
|
|
2837
2743
|
o(this, "dataExtractor");
|
|
2838
2744
|
o(this, "contentGenerator");
|
|
2839
2745
|
o(this, "fileHandler");
|
|
2840
|
-
this.dataExtractor = new
|
|
2746
|
+
this.dataExtractor = new we(), this.contentGenerator = new Te(), this.fileHandler = new Se();
|
|
2841
2747
|
}
|
|
2842
2748
|
/**
|
|
2843
2749
|
* Applies default values to SVG export options
|
|
@@ -2862,13 +2768,13 @@ class Y {
|
|
|
2862
2768
|
const r = this.applyDefaultOptions(t), i = this.dataExtractor.extractFramebufferData(e.pipeline), s = this.dataExtractor.extractSVGCellData(
|
|
2863
2769
|
i,
|
|
2864
2770
|
e.grid
|
|
2865
|
-
),
|
|
2771
|
+
), a = this.contentGenerator.generateSVGContent(
|
|
2866
2772
|
s,
|
|
2867
2773
|
e.grid,
|
|
2868
2774
|
e.font,
|
|
2869
2775
|
r
|
|
2870
2776
|
);
|
|
2871
|
-
return this.contentGenerator.optimizeSVGContent(
|
|
2777
|
+
return this.contentGenerator.optimizeSVGContent(a);
|
|
2872
2778
|
}
|
|
2873
2779
|
/**
|
|
2874
2780
|
* Exports SVG content to a downloadable file
|
|
@@ -2884,7 +2790,7 @@ class Y {
|
|
|
2884
2790
|
}
|
|
2885
2791
|
}
|
|
2886
2792
|
}
|
|
2887
|
-
class
|
|
2793
|
+
class Re extends H {
|
|
2888
2794
|
/**
|
|
2889
2795
|
* Extracts character data for TXT generation
|
|
2890
2796
|
* @param framebufferData Framebuffer pixel data
|
|
@@ -2894,24 +2800,24 @@ class Pe extends H {
|
|
|
2894
2800
|
* @returns 2D array of characters (rows x columns)
|
|
2895
2801
|
*/
|
|
2896
2802
|
extractCharacterGrid(e, t, r, i = " ") {
|
|
2897
|
-
var
|
|
2803
|
+
var n;
|
|
2898
2804
|
const s = [];
|
|
2899
|
-
let
|
|
2805
|
+
let a = 0;
|
|
2900
2806
|
for (let l = 0; l < t.rows; l++) {
|
|
2901
2807
|
const c = [];
|
|
2902
2808
|
for (let u = 0; u < t.cols; u++) {
|
|
2903
|
-
const d =
|
|
2809
|
+
const d = a * 4, f = this.getCharacterIndex(
|
|
2904
2810
|
e.characterPixels,
|
|
2905
2811
|
d
|
|
2906
|
-
), g = ((
|
|
2907
|
-
c.push(g),
|
|
2812
|
+
), g = ((n = r.characters[f]) == null ? void 0 : n.character) || i;
|
|
2813
|
+
c.push(g), a++;
|
|
2908
2814
|
}
|
|
2909
2815
|
s.push(c);
|
|
2910
2816
|
}
|
|
2911
2817
|
return s;
|
|
2912
2818
|
}
|
|
2913
2819
|
}
|
|
2914
|
-
class
|
|
2820
|
+
class Ee {
|
|
2915
2821
|
/**
|
|
2916
2822
|
* Generates TXT content from a 2D character array
|
|
2917
2823
|
* @param characterGrid 2D array of characters (rows x columns)
|
|
@@ -2921,8 +2827,8 @@ class Be {
|
|
|
2921
2827
|
generateTXTContent(e, t) {
|
|
2922
2828
|
const r = [];
|
|
2923
2829
|
for (const s of e) {
|
|
2924
|
-
let
|
|
2925
|
-
t.preserveTrailingSpaces || (
|
|
2830
|
+
let a = s.join("");
|
|
2831
|
+
t.preserveTrailingSpaces || (a = a.replace(/\s+$/, "")), r.push(a);
|
|
2926
2832
|
}
|
|
2927
2833
|
const i = t.lineEnding === "crlf" ? `\r
|
|
2928
2834
|
` : `
|
|
@@ -2930,7 +2836,7 @@ class Be {
|
|
|
2930
2836
|
return r.join(i);
|
|
2931
2837
|
}
|
|
2932
2838
|
}
|
|
2933
|
-
class
|
|
2839
|
+
class Ue extends X {
|
|
2934
2840
|
/**
|
|
2935
2841
|
* Saves TXT content as a downloadable file
|
|
2936
2842
|
* @param content The TXT content to save
|
|
@@ -2954,12 +2860,12 @@ class Ge extends X {
|
|
|
2954
2860
|
return t === ".txt" || t.length <= 4 ? this.generateDefaultFilename() : t;
|
|
2955
2861
|
}
|
|
2956
2862
|
}
|
|
2957
|
-
class
|
|
2863
|
+
class K {
|
|
2958
2864
|
constructor() {
|
|
2959
2865
|
o(this, "dataExtractor");
|
|
2960
2866
|
o(this, "contentGenerator");
|
|
2961
2867
|
o(this, "fileHandler");
|
|
2962
|
-
this.dataExtractor = new
|
|
2868
|
+
this.dataExtractor = new Re(), this.contentGenerator = new Ee(), this.fileHandler = new Ue();
|
|
2963
2869
|
}
|
|
2964
2870
|
/**
|
|
2965
2871
|
* Applies default values to TXT export options
|
|
@@ -3005,7 +2911,7 @@ class j {
|
|
|
3005
2911
|
}
|
|
3006
2912
|
}
|
|
3007
2913
|
}
|
|
3008
|
-
class
|
|
2914
|
+
class Me extends H {
|
|
3009
2915
|
/**
|
|
3010
2916
|
* Captures the current state of the textmode canvas as image data
|
|
3011
2917
|
* @param canvas The canvas data containing the rendered textmode graphics
|
|
@@ -3017,8 +2923,8 @@ class Ve extends H {
|
|
|
3017
2923
|
const i = e.canvas;
|
|
3018
2924
|
if (t === 1 && r === "transparent")
|
|
3019
2925
|
return i;
|
|
3020
|
-
const s = document.createElement("canvas"),
|
|
3021
|
-
return s.width =
|
|
2926
|
+
const s = document.createElement("canvas"), a = s.getContext("2d"), n = Math.round(i.width * t), l = Math.round(i.height * t);
|
|
2927
|
+
return s.width = n, s.height = l, r !== "transparent" && (a.fillStyle = r, a.fillRect(0, 0, n, l)), a.imageSmoothingEnabled = !1, a.drawImage(
|
|
3022
2928
|
i,
|
|
3023
2929
|
0,
|
|
3024
2930
|
0,
|
|
@@ -3026,12 +2932,12 @@ class Ve extends H {
|
|
|
3026
2932
|
i.height,
|
|
3027
2933
|
0,
|
|
3028
2934
|
0,
|
|
3029
|
-
|
|
2935
|
+
n,
|
|
3030
2936
|
l
|
|
3031
2937
|
), s;
|
|
3032
2938
|
}
|
|
3033
2939
|
}
|
|
3034
|
-
class
|
|
2940
|
+
class Ae {
|
|
3035
2941
|
/**
|
|
3036
2942
|
* Generates image data from canvas
|
|
3037
2943
|
* @param canvas The canvas containing the image data
|
|
@@ -3050,10 +2956,10 @@ class ke {
|
|
|
3050
2956
|
*/
|
|
3051
2957
|
async generateImageBlob(e, t) {
|
|
3052
2958
|
return new Promise((r, i) => {
|
|
3053
|
-
const s = this.getMimeType(t.format),
|
|
3054
|
-
|
|
2959
|
+
const s = this.getMimeType(t.format), a = (n) => {
|
|
2960
|
+
n ? r(n) : i(new Error(`Failed to generate ${t.format.toUpperCase()} blob`));
|
|
3055
2961
|
};
|
|
3056
|
-
t.format === "png" ? e.toBlob(
|
|
2962
|
+
t.format === "png" ? e.toBlob(a, s) : e.toBlob(a, s, t.quality);
|
|
3057
2963
|
});
|
|
3058
2964
|
}
|
|
3059
2965
|
/**
|
|
@@ -3074,16 +2980,16 @@ class ke {
|
|
|
3074
2980
|
}
|
|
3075
2981
|
}
|
|
3076
2982
|
}
|
|
3077
|
-
const
|
|
2983
|
+
const Q = {
|
|
3078
2984
|
png: "image/png",
|
|
3079
2985
|
jpg: "image/jpeg",
|
|
3080
2986
|
webp: "image/webp"
|
|
3081
|
-
},
|
|
2987
|
+
}, V = {
|
|
3082
2988
|
png: ".png",
|
|
3083
2989
|
jpg: ".jpg",
|
|
3084
2990
|
webp: ".webp"
|
|
3085
2991
|
};
|
|
3086
|
-
class
|
|
2992
|
+
class De extends X {
|
|
3087
2993
|
/**
|
|
3088
2994
|
* Saves image content as a downloadable file
|
|
3089
2995
|
* @param content The image content (data URL or blob)
|
|
@@ -3092,7 +2998,7 @@ class ze extends X {
|
|
|
3092
2998
|
*/
|
|
3093
2999
|
saveImage(e, t, r) {
|
|
3094
3000
|
try {
|
|
3095
|
-
const i =
|
|
3001
|
+
const i = V[r];
|
|
3096
3002
|
typeof e == "string" ? this.saveImageFromDataURL(e, this.sanitizeFilename(t) + i) : this.saveImageFromBlob(e, this.sanitizeFilename(t) + i);
|
|
3097
3003
|
} catch (i) {
|
|
3098
3004
|
throw console.error(`Failed to save ${r.toUpperCase()} image:`, i), new Error(`Image save failed: ${i instanceof Error ? i.message : "Unknown error"}`);
|
|
@@ -3127,7 +3033,7 @@ class ze extends X {
|
|
|
3127
3033
|
* @returns True if the format is supported for saving
|
|
3128
3034
|
*/
|
|
3129
3035
|
validateSaveSupport(e) {
|
|
3130
|
-
return e in
|
|
3036
|
+
return e in Q && e in V;
|
|
3131
3037
|
}
|
|
3132
3038
|
/**
|
|
3133
3039
|
* Gets the MIME type for the specified image format
|
|
@@ -3135,7 +3041,7 @@ class ze extends X {
|
|
|
3135
3041
|
* @returns The MIME type string
|
|
3136
3042
|
*/
|
|
3137
3043
|
getMimeType(e) {
|
|
3138
|
-
return
|
|
3044
|
+
return Q[e];
|
|
3139
3045
|
}
|
|
3140
3046
|
/**
|
|
3141
3047
|
* Gets the file extension for the specified image format
|
|
@@ -3143,15 +3049,15 @@ class ze extends X {
|
|
|
3143
3049
|
* @returns The file extension (including the dot)
|
|
3144
3050
|
*/
|
|
3145
3051
|
getFileExtension(e) {
|
|
3146
|
-
return
|
|
3052
|
+
return V[e];
|
|
3147
3053
|
}
|
|
3148
3054
|
}
|
|
3149
|
-
class
|
|
3055
|
+
class Ie {
|
|
3150
3056
|
constructor() {
|
|
3151
3057
|
o(this, "dataExtractor");
|
|
3152
3058
|
o(this, "contentGenerator");
|
|
3153
3059
|
o(this, "fileHandler");
|
|
3154
|
-
this.dataExtractor = new
|
|
3060
|
+
this.dataExtractor = new Me(), this.contentGenerator = new Ae(), this.fileHandler = new De();
|
|
3155
3061
|
}
|
|
3156
3062
|
/**
|
|
3157
3063
|
* Applies default values to image export options
|
|
@@ -3234,7 +3140,7 @@ class $e {
|
|
|
3234
3140
|
}
|
|
3235
3141
|
}
|
|
3236
3142
|
}
|
|
3237
|
-
class
|
|
3143
|
+
class k {
|
|
3238
3144
|
constructor(e = null, t = {}) {
|
|
3239
3145
|
/** The element to capture content from (optional for standalone mode) */
|
|
3240
3146
|
o(this, "captureSource");
|
|
@@ -3278,15 +3184,12 @@ class I {
|
|
|
3278
3184
|
* @ignore
|
|
3279
3185
|
*/
|
|
3280
3186
|
static async create(e = null, t = {}) {
|
|
3281
|
-
const r = new
|
|
3282
|
-
r.textmodeCanvas = new
|
|
3283
|
-
let s,
|
|
3284
|
-
r._standalone ? (s = t.width || 800,
|
|
3285
|
-
const
|
|
3286
|
-
return r._grid = new
|
|
3287
|
-
const l = r.textmodeCanvas.getEffectiveRenderingDimensions();
|
|
3288
|
-
r._renderer.resetViewport(l.width, l.height), r._mode === "auto" && r.render();
|
|
3289
|
-
}), r.startAutoRendering(), r;
|
|
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());
|
|
3189
|
+
let s, a;
|
|
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);
|
|
3191
|
+
const n = r._font.maxGlyphDimensions;
|
|
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;
|
|
3290
3193
|
}
|
|
3291
3194
|
setupEventListeners() {
|
|
3292
3195
|
this._windowResizeListener = () => {
|
|
@@ -3334,7 +3237,7 @@ class I {
|
|
|
3334
3237
|
* ```
|
|
3335
3238
|
*/
|
|
3336
3239
|
toString(e = {}) {
|
|
3337
|
-
return new
|
|
3240
|
+
return new K().generateTXT(this, e);
|
|
3338
3241
|
}
|
|
3339
3242
|
/**
|
|
3340
3243
|
* Export the current textmode rendering to a TXT file.
|
|
@@ -3359,7 +3262,7 @@ class I {
|
|
|
3359
3262
|
* ```
|
|
3360
3263
|
*/
|
|
3361
3264
|
saveStrings(e = {}) {
|
|
3362
|
-
new
|
|
3265
|
+
new K().saveTXT(this, e);
|
|
3363
3266
|
}
|
|
3364
3267
|
/**
|
|
3365
3268
|
* Generate the current textmode rendering as an SVG string.
|
|
@@ -3388,7 +3291,7 @@ class I {
|
|
|
3388
3291
|
* ```
|
|
3389
3292
|
*/
|
|
3390
3293
|
toSVG(e = {}) {
|
|
3391
|
-
return new
|
|
3294
|
+
return new q().generateSVG(this, e);
|
|
3392
3295
|
}
|
|
3393
3296
|
/**
|
|
3394
3297
|
* Export the current textmode rendering to an SVG file.
|
|
@@ -3412,7 +3315,7 @@ class I {
|
|
|
3412
3315
|
* ```
|
|
3413
3316
|
*/
|
|
3414
3317
|
saveSVG(e = {}) {
|
|
3415
|
-
new
|
|
3318
|
+
new q().saveSVG(this, e);
|
|
3416
3319
|
}
|
|
3417
3320
|
/**
|
|
3418
3321
|
* Export the current textmode rendering to an image file.
|
|
@@ -3443,7 +3346,7 @@ class I {
|
|
|
3443
3346
|
* ```
|
|
3444
3347
|
*/
|
|
3445
3348
|
async saveCanvas(e, t = "png", r = {}) {
|
|
3446
|
-
await new
|
|
3349
|
+
await new Ie().saveImage(this.textmodeCanvas, {
|
|
3447
3350
|
...r,
|
|
3448
3351
|
filename: e,
|
|
3449
3352
|
format: t
|
|
@@ -3527,12 +3430,7 @@ class I {
|
|
|
3527
3430
|
}
|
|
3528
3431
|
}
|
|
3529
3432
|
resize() {
|
|
3530
|
-
|
|
3531
|
-
const e = this.textmodeCanvas.getEffectiveRenderingDimensions();
|
|
3532
|
-
this._renderer.resetViewport(e.width, e.height);
|
|
3533
|
-
} else
|
|
3534
|
-
this._renderer.resetViewport();
|
|
3535
|
-
this._mode !== "manual" && this.render();
|
|
3433
|
+
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();
|
|
3536
3434
|
}
|
|
3537
3435
|
/**
|
|
3538
3436
|
* Start automatic rendering
|
|
@@ -3710,7 +3608,7 @@ class I {
|
|
|
3710
3608
|
* ```
|
|
3711
3609
|
*/
|
|
3712
3610
|
redraw(e = 1) {
|
|
3713
|
-
if (
|
|
3611
|
+
if (_.validate(
|
|
3714
3612
|
typeof e == "number" && e > 0 && Number.isInteger(e),
|
|
3715
3613
|
"Redraw count must be a positive integer.",
|
|
3716
3614
|
{ method: "redraw", providedValue: e }
|
|
@@ -3766,16 +3664,11 @@ class I {
|
|
|
3766
3664
|
* ```
|
|
3767
3665
|
*/
|
|
3768
3666
|
fontSize(e) {
|
|
3769
|
-
|
|
3667
|
+
_.validate(
|
|
3770
3668
|
typeof e == "number" && e > 0,
|
|
3771
3669
|
"Font size must be a positive number greater than 0.",
|
|
3772
3670
|
{ method: "fontSize", providedValue: e }
|
|
3773
|
-
) && this._font.fontSize !== e)
|
|
3774
|
-
if (this._font.setFontSize(e), this._grid.resizeCellPixelDimensions(this._font.maxGlyphDimensions.width, this._font.maxGlyphDimensions.height), this._pipeline.resize(), this._standalone) {
|
|
3775
|
-
const t = this.textmodeCanvas.getEffectiveRenderingDimensions();
|
|
3776
|
-
this._renderer.resetViewport(t.width, t.height);
|
|
3777
|
-
} else
|
|
3778
|
-
this._renderer.resetViewport();
|
|
3671
|
+
) && this._font.fontSize !== e && (this._font.setFontSize(e), this._grid.resizeCellPixelDimensions(this._font.maxGlyphDimensions.width, this._font.maxGlyphDimensions.height), this._pipeline.resize(), this._renderer.resetViewport());
|
|
3779
3672
|
}
|
|
3780
3673
|
/**
|
|
3781
3674
|
* Set a draw callback function that will be executed before each render.
|
|
@@ -3842,12 +3735,7 @@ class I {
|
|
|
3842
3735
|
* @param height The new height of the canvas.
|
|
3843
3736
|
*/
|
|
3844
3737
|
resizeCanvas(e, t) {
|
|
3845
|
-
|
|
3846
|
-
const r = this.textmodeCanvas.getEffectiveRenderingDimensions();
|
|
3847
|
-
this._renderer.resetViewport(r.width, r.height);
|
|
3848
|
-
} else
|
|
3849
|
-
this._renderer.resetViewport();
|
|
3850
|
-
this._mode !== "manual" && this.render();
|
|
3738
|
+
this.textmodeCanvas.resize(e, t), this._canvasFramebuffer.resize(this.textmodeCanvas.width, this.textmodeCanvas.height), this._grid.resize(), this._pipeline.resize(), this._renderer.resetViewport(), this._mode !== "manual" && this.render();
|
|
3851
3739
|
}
|
|
3852
3740
|
/**
|
|
3853
3741
|
* @inheritDoc TextmodeConversionPipeline.get
|
|
@@ -4368,7 +4256,7 @@ class I {
|
|
|
4368
4256
|
return this._isDisposed;
|
|
4369
4257
|
}
|
|
4370
4258
|
}
|
|
4371
|
-
class
|
|
4259
|
+
class O {
|
|
4372
4260
|
/**
|
|
4373
4261
|
* Create a {@link Textmodifier} instance for textmode rendering.
|
|
4374
4262
|
*
|
|
@@ -4430,10 +4318,10 @@ class N {
|
|
|
4430
4318
|
*/
|
|
4431
4319
|
static async create(e, t = {}) {
|
|
4432
4320
|
if (e instanceof HTMLCanvasElement || e instanceof HTMLVideoElement)
|
|
4433
|
-
return
|
|
4321
|
+
return k.create(e, t);
|
|
4434
4322
|
{
|
|
4435
4323
|
const r = e || {};
|
|
4436
|
-
return
|
|
4324
|
+
return k.create(null, r);
|
|
4437
4325
|
}
|
|
4438
4326
|
}
|
|
4439
4327
|
/**
|
|
@@ -4447,7 +4335,7 @@ class N {
|
|
|
4447
4335
|
* ```
|
|
4448
4336
|
*/
|
|
4449
4337
|
static setErrorLevel(e) {
|
|
4450
|
-
|
|
4338
|
+
_.setGlobalLevel(e);
|
|
4451
4339
|
}
|
|
4452
4340
|
/**
|
|
4453
4341
|
* Returns the current version of the `textmode.js` library.
|
|
@@ -4458,27 +4346,27 @@ class N {
|
|
|
4458
4346
|
* ```
|
|
4459
4347
|
*/
|
|
4460
4348
|
static get version() {
|
|
4461
|
-
return "0.1.6-beta.
|
|
4349
|
+
return "0.1.6-beta.4";
|
|
4462
4350
|
}
|
|
4463
4351
|
constructor() {
|
|
4464
4352
|
throw new Error("Textmode is a static class and cannot be instantiated.");
|
|
4465
4353
|
}
|
|
4466
4354
|
}
|
|
4467
|
-
const
|
|
4355
|
+
const Be = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4468
4356
|
__proto__: null
|
|
4469
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
4357
|
+
}, Symbol.toStringTag, { value: "Module" })), ke = O.create, Ve = O.setErrorLevel, ze = O.version;
|
|
4470
4358
|
export {
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
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
|
|
4484
4372
|
};
|