@openspecui/web 0.9.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/assets/BufferResource-CVUoegR6.js +185 -0
  2. package/dist/assets/CanvasRenderer-BEIcB8i1.js +1 -0
  3. package/dist/assets/Filter-Bu_qhr6H.js +1 -0
  4. package/dist/assets/RenderTargetSystem-DWouFDxU.js +172 -0
  5. package/dist/assets/WebGLRenderer-6FH_N1FV.js +156 -0
  6. package/dist/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
  7. package/dist/assets/browserAll-CLKeV1yb.js +14 -0
  8. package/dist/assets/gemini-Bk-V9kKu.png +0 -0
  9. package/dist/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
  10. package/{dist-ssg/client/assets/index-CCfVkFzN.js → dist/assets/index-BPCTI2mG.js} +1 -1
  11. package/dist/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
  12. package/dist/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
  13. package/dist/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
  14. package/{dist-ssg/client/assets/index-ftYom_wU.js → dist/assets/index-BtNuxyw4.js} +1 -1
  15. package/dist/assets/index-Bv7pWR8R.js +7 -0
  16. package/{dist-ssg/client/assets/index-D3mXuuih.js → dist/assets/index-Byr3HkRi.js} +1 -1
  17. package/dist/assets/index-CEHMo0EU.js +1385 -0
  18. package/dist/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
  19. package/dist/assets/index-CEf9wXLh.css +1 -0
  20. package/{dist-ssg/client/assets/index-ArhptQw0.js → dist/assets/index-CX13iBBs.js} +1 -1
  21. package/dist/assets/index-CoOT7eZ9.js +1 -0
  22. package/{dist-ssg/client/assets/index-B1hpa--1.js → dist/assets/index-D4AU46yO.js} +1 -1
  23. package/dist/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
  24. package/{dist-ssg/client/assets/index-AbWe21oh.js → dist/assets/index-eQZwF8qE.js} +1 -1
  25. package/dist/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
  26. package/dist/assets/webworkerAll-DjWoTx9g.js +83 -0
  27. package/dist/index.html +2 -2
  28. package/dist-ssg/client/.vite/ssr-manifest.json +3094 -504
  29. package/dist-ssg/client/assets/BufferResource-CVUoegR6.js +185 -0
  30. package/dist-ssg/client/assets/CanvasRenderer-BEIcB8i1.js +1 -0
  31. package/dist-ssg/client/assets/Filter-Bu_qhr6H.js +1 -0
  32. package/dist-ssg/client/assets/RenderTargetSystem-DWouFDxU.js +172 -0
  33. package/dist-ssg/client/assets/WebGLRenderer-6FH_N1FV.js +156 -0
  34. package/dist-ssg/client/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
  35. package/dist-ssg/client/assets/browserAll-CLKeV1yb.js +14 -0
  36. package/dist-ssg/client/assets/gemini-Bk-V9kKu.png +0 -0
  37. package/dist-ssg/client/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
  38. package/{dist/assets/index-CCfVkFzN.js → dist-ssg/client/assets/index-BPCTI2mG.js} +1 -1
  39. package/dist-ssg/client/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
  40. package/dist-ssg/client/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
  41. package/dist-ssg/client/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
  42. package/{dist/assets/index-ftYom_wU.js → dist-ssg/client/assets/index-BtNuxyw4.js} +1 -1
  43. package/dist-ssg/client/assets/index-Bv7pWR8R.js +7 -0
  44. package/{dist/assets/index-D3mXuuih.js → dist-ssg/client/assets/index-Byr3HkRi.js} +1 -1
  45. package/dist-ssg/client/assets/index-CEHMo0EU.js +1385 -0
  46. package/dist-ssg/client/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
  47. package/dist-ssg/client/assets/index-CEf9wXLh.css +1 -0
  48. package/{dist/assets/index-ArhptQw0.js → dist-ssg/client/assets/index-CX13iBBs.js} +1 -1
  49. package/dist-ssg/client/assets/index-CoOT7eZ9.js +1 -0
  50. package/{dist/assets/index-B1hpa--1.js → dist-ssg/client/assets/index-D4AU46yO.js} +1 -1
  51. package/dist-ssg/client/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
  52. package/{dist/assets/index-AbWe21oh.js → dist-ssg/client/assets/index-eQZwF8qE.js} +1 -1
  53. package/dist-ssg/client/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
  54. package/dist-ssg/client/assets/webworkerAll-DjWoTx9g.js +83 -0
  55. package/dist-ssg/client/index.html +2 -2
  56. package/dist-ssg/server/assets/BufferResource-BXrsGVSz.js +592 -0
  57. package/dist-ssg/server/assets/CanvasRenderer-D9aMd7WV.js +1530 -0
  58. package/dist-ssg/server/assets/Filter-ClU0-pLL.js +80 -0
  59. package/dist-ssg/server/assets/RenderTargetSystem-CVz6i60H.js +3037 -0
  60. package/dist-ssg/server/assets/WebGLRenderer-B0I5TP5d.js +3887 -0
  61. package/dist-ssg/server/assets/WebGPURenderer-DCgUFny7.js +2146 -0
  62. package/dist-ssg/server/assets/browserAll-BixK1BYs.js +2691 -0
  63. package/dist-ssg/server/assets/{index-BUANIFyF.js → index-3uSTc-o9.js} +3 -1
  64. package/dist-ssg/server/assets/{index-D0JVKGRJ.js → index-8uE7RyRi.js} +3 -1
  65. package/dist-ssg/server/assets/{index-DCGDP0cs.js → index-BDzDVVaf.js} +2 -0
  66. package/dist-ssg/server/assets/{index-oPcprgZH.js → index-BkJYfA64.js} +3 -1
  67. package/dist-ssg/server/assets/{index-CAP0cmVO.js → index-BvGNqnLD.js} +3 -1
  68. package/dist-ssg/server/assets/{index-DsfT46da.js → index-BvURgefh.js} +3 -1
  69. package/dist-ssg/server/assets/{index-Dk9q2o0C.js → index-C2CuXbSQ.js} +3 -1
  70. package/dist-ssg/server/assets/{index-Cmnd0jiw.js → index-C3RtR5EA.js} +3 -1
  71. package/dist-ssg/server/assets/{index-CFKaffPZ.js → index-CZtnphnE.js} +3 -1
  72. package/dist-ssg/server/assets/{index-D6n8WPGB.js → index-D0DRToHj.js} +3 -1
  73. package/dist-ssg/server/assets/{index-mJoWrrNO.js → index-D5MdLWau.js} +3 -1
  74. package/dist-ssg/server/assets/{index-Brcpp_nj.js → index-DBYODvy4.js} +3 -1
  75. package/dist-ssg/server/assets/{index-DYmgiM6_.js → index-DL23PkQi.js} +3 -1
  76. package/dist-ssg/server/assets/{index-CnRKREoz.js → index-DfcLdBOi.js} +3 -1
  77. package/dist-ssg/server/assets/{index-Bzw5T-vd.js → index-O2XMojWG.js} +3 -1
  78. package/dist-ssg/server/assets/init-CnkBvt-J.js +666 -0
  79. package/dist-ssg/server/assets/webworkerAll-DNiMFaVV.js +12 -0
  80. package/dist-ssg/server/entry-server.js +87120 -34846
  81. package/package.json +23 -5
  82. package/dist/assets/index-D-Urq2hl.css +0 -1
  83. package/dist/assets/index-DFOLYN6W.js +0 -1
  84. package/dist/assets/index-DpxkOmNJ.js +0 -7
  85. package/dist/assets/index-YZ-iXB95.js +0 -309
  86. package/dist-ssg/client/assets/index-D-Urq2hl.css +0 -1
  87. package/dist-ssg/client/assets/index-DFOLYN6W.js +0 -1
  88. package/dist-ssg/client/assets/index-DpxkOmNJ.js +0 -7
  89. package/dist-ssg/client/assets/index-YZ-iXB95.js +0 -309
@@ -0,0 +1,1530 @@
1
+ import { X as DOMAdapter, Y as groupD8, Z as Color, _ as bgr2rgb, $ as multiplyHexColors, M as Matrix, y as ExtensionType, a0 as Graphics, D as warn, z as Texture, a1 as generateTextureMatrix, a2 as shapeBuilders, a3 as buildLine, a4 as FillGradient, a5 as FillPattern, a6 as CanvasSource, a7 as AbstractRenderer, R as RendererType, H as extensions } from "../entry-server.js";
2
+ import { R as RenderTargetSystem, S as SharedSystems, B as BlendModePipe, a as BatcherPipe, b as SpritePipe, c as RenderGroupPipe, A as AlphaMaskPipe, C as CustomRenderPipe } from "./RenderTargetSystem-CVz6i60H.js";
3
+ import "util";
4
+ import "crypto";
5
+ import "async_hooks";
6
+ import "stream";
7
+ import "process";
8
+ import "buffer";
9
+ import "node:process";
10
+ import "node:path";
11
+ import "node:url";
12
+ import "./Filter-ClU0-pLL.js";
13
+ let canUseNewCanvasBlendModesValue;
14
+ function createColoredCanvas(color) {
15
+ const canvas = DOMAdapter.get().createCanvas(6, 1);
16
+ const context = canvas.getContext("2d");
17
+ context.fillStyle = color;
18
+ context.fillRect(0, 0, 6, 1);
19
+ return canvas;
20
+ }
21
+ function canUseNewCanvasBlendModes() {
22
+ if (canUseNewCanvasBlendModesValue !== void 0) {
23
+ return canUseNewCanvasBlendModesValue;
24
+ }
25
+ try {
26
+ const magenta = createColoredCanvas("#ff00ff");
27
+ const yellow = createColoredCanvas("#ffff00");
28
+ const canvas = DOMAdapter.get().createCanvas(6, 1);
29
+ const context = canvas.getContext("2d");
30
+ context.globalCompositeOperation = "multiply";
31
+ context.drawImage(magenta, 0, 0);
32
+ context.drawImage(yellow, 2, 0);
33
+ const imageData = context.getImageData(2, 0, 1, 1);
34
+ if (!imageData) {
35
+ canUseNewCanvasBlendModesValue = false;
36
+ } else {
37
+ const data = imageData.data;
38
+ canUseNewCanvasBlendModesValue = data[0] === 255 && data[1] === 0 && data[2] === 0;
39
+ }
40
+ } catch (_error) {
41
+ canUseNewCanvasBlendModesValue = false;
42
+ }
43
+ return canUseNewCanvasBlendModesValue;
44
+ }
45
+ const canvasUtils = {
46
+ canvas: null,
47
+ convertTintToImage: false,
48
+ cacheStepsPerColorChannel: 8,
49
+ canUseMultiply: canUseNewCanvasBlendModes(),
50
+ tintMethod: null,
51
+ _canvasSourceCache: /* @__PURE__ */ new WeakMap(),
52
+ _unpremultipliedCache: /* @__PURE__ */ new WeakMap(),
53
+ getCanvasSource: (texture) => {
54
+ const source = texture.source;
55
+ const resource = source?.resource;
56
+ if (!resource) {
57
+ return null;
58
+ }
59
+ const isPMA = source.alphaMode === "premultiplied-alpha";
60
+ const resourceWidth = source.resourceWidth ?? source.pixelWidth;
61
+ const resourceHeight = source.resourceHeight ?? source.pixelHeight;
62
+ const needsResize = resourceWidth !== source.pixelWidth || resourceHeight !== source.pixelHeight;
63
+ if (isPMA) {
64
+ if (resource instanceof HTMLCanvasElement || typeof OffscreenCanvas !== "undefined" && resource instanceof OffscreenCanvas) {
65
+ if (!needsResize) {
66
+ return resource;
67
+ }
68
+ }
69
+ const cached = canvasUtils._unpremultipliedCache.get(source);
70
+ if (cached?.resourceId === source._resourceId) {
71
+ return cached.canvas;
72
+ }
73
+ }
74
+ if (resource instanceof Uint8Array || resource instanceof Uint8ClampedArray || resource instanceof Int8Array || resource instanceof Uint16Array || resource instanceof Int16Array || resource instanceof Uint32Array || resource instanceof Int32Array || resource instanceof Float32Array || resource instanceof ArrayBuffer) {
75
+ const cached = canvasUtils._canvasSourceCache.get(source);
76
+ if (cached?.resourceId === source._resourceId) {
77
+ return cached.canvas;
78
+ }
79
+ const canvas = DOMAdapter.get().createCanvas(source.pixelWidth, source.pixelHeight);
80
+ const context = canvas.getContext("2d");
81
+ const imageData = context.createImageData(source.pixelWidth, source.pixelHeight);
82
+ const data = imageData.data;
83
+ const bytes = resource instanceof ArrayBuffer ? new Uint8Array(resource) : new Uint8Array(resource.buffer, resource.byteOffset, resource.byteLength);
84
+ if (source.format === "bgra8unorm") {
85
+ for (let i = 0; i < data.length && i + 3 < bytes.length; i += 4) {
86
+ data[i] = bytes[i + 2];
87
+ data[i + 1] = bytes[i + 1];
88
+ data[i + 2] = bytes[i];
89
+ data[i + 3] = bytes[i + 3];
90
+ }
91
+ } else {
92
+ data.set(bytes.subarray(0, data.length));
93
+ }
94
+ context.putImageData(imageData, 0, 0);
95
+ canvasUtils._canvasSourceCache.set(source, { canvas, resourceId: source._resourceId });
96
+ return canvas;
97
+ }
98
+ if (isPMA) {
99
+ const canvas = DOMAdapter.get().createCanvas(source.pixelWidth, source.pixelHeight);
100
+ const context = canvas.getContext("2d", { willReadFrequently: true });
101
+ canvas.width = source.pixelWidth;
102
+ canvas.height = source.pixelHeight;
103
+ context.drawImage(resource, 0, 0);
104
+ const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
105
+ const data = imageData.data;
106
+ for (let i = 0; i < data.length; i += 4) {
107
+ const a = data[i + 3];
108
+ if (a > 0) {
109
+ const alphaInv = 255 / a;
110
+ data[i] = Math.min(255, data[i] * alphaInv + 0.5);
111
+ data[i + 1] = Math.min(255, data[i + 1] * alphaInv + 0.5);
112
+ data[i + 2] = Math.min(255, data[i + 2] * alphaInv + 0.5);
113
+ }
114
+ }
115
+ context.putImageData(imageData, 0, 0);
116
+ canvasUtils._unpremultipliedCache.set(source, { canvas, resourceId: source._resourceId });
117
+ return canvas;
118
+ }
119
+ if (needsResize) {
120
+ const cached = canvasUtils._canvasSourceCache.get(source);
121
+ if (cached?.resourceId === source._resourceId) {
122
+ return cached.canvas;
123
+ }
124
+ const canvas = DOMAdapter.get().createCanvas(source.pixelWidth, source.pixelHeight);
125
+ const context = canvas.getContext("2d");
126
+ canvas.width = source.pixelWidth;
127
+ canvas.height = source.pixelHeight;
128
+ context.drawImage(resource, 0, 0);
129
+ canvasUtils._canvasSourceCache.set(source, { canvas, resourceId: source._resourceId });
130
+ return canvas;
131
+ }
132
+ return resource;
133
+ },
134
+ getTintedCanvas: (sprite, color) => {
135
+ const texture = sprite.texture;
136
+ const stringColor = Color.shared.setValue(color).toHex();
137
+ const cache = texture.tintCache || (texture.tintCache = {});
138
+ const cachedCanvas = cache[stringColor];
139
+ const resourceId = texture.source._resourceId;
140
+ if (cachedCanvas?.tintId === resourceId) {
141
+ return cachedCanvas;
142
+ }
143
+ const canvas = cachedCanvas && "getContext" in cachedCanvas ? cachedCanvas : DOMAdapter.get().createCanvas();
144
+ canvasUtils.tintMethod(texture, color, canvas);
145
+ canvas.tintId = resourceId;
146
+ {
147
+ cache[stringColor] = canvas;
148
+ }
149
+ return cache[stringColor];
150
+ },
151
+ getTintedPattern: (texture, color) => {
152
+ const stringColor = Color.shared.setValue(color).toHex();
153
+ const cache = texture.patternCache || (texture.patternCache = {});
154
+ const resourceId = texture.source._resourceId;
155
+ let pattern = cache[stringColor];
156
+ if (pattern?.tintId === resourceId) {
157
+ return pattern;
158
+ }
159
+ if (!canvasUtils.canvas) {
160
+ canvasUtils.canvas = DOMAdapter.get().createCanvas();
161
+ }
162
+ canvasUtils.tintMethod(texture, color, canvasUtils.canvas);
163
+ const context = canvasUtils.canvas.getContext("2d");
164
+ pattern = context.createPattern(canvasUtils.canvas, "repeat");
165
+ pattern.tintId = resourceId;
166
+ cache[stringColor] = pattern;
167
+ return pattern;
168
+ },
169
+ /**
170
+ * Applies a transform to a CanvasPattern.
171
+ * @param pattern - The pattern to apply the transform to.
172
+ * @param matrix - The matrix to apply.
173
+ * @param matrix.a
174
+ * @param matrix.b
175
+ * @param matrix.c
176
+ * @param matrix.d
177
+ * @param matrix.tx
178
+ * @param matrix.ty
179
+ * @param invert
180
+ */
181
+ applyPatternTransform: (pattern, matrix, invert = true) => {
182
+ if (!matrix) return;
183
+ const patternAny = pattern;
184
+ if (!patternAny.setTransform) return;
185
+ const DOMMatrixCtor = globalThis.DOMMatrix;
186
+ if (!DOMMatrixCtor) return;
187
+ const domMatrix = new DOMMatrixCtor([matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty]);
188
+ patternAny.setTransform(invert ? domMatrix.inverse() : domMatrix);
189
+ },
190
+ tintWithMultiply: (texture, color, canvas) => {
191
+ const context = canvas.getContext("2d");
192
+ const crop = texture.frame.clone();
193
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
194
+ const rotate = texture.rotate;
195
+ crop.x *= resolution;
196
+ crop.y *= resolution;
197
+ crop.width *= resolution;
198
+ crop.height *= resolution;
199
+ const isVertical = groupD8.isVertical(rotate);
200
+ const outWidth = isVertical ? crop.height : crop.width;
201
+ const outHeight = isVertical ? crop.width : crop.height;
202
+ canvas.width = Math.ceil(outWidth);
203
+ canvas.height = Math.ceil(outHeight);
204
+ context.save();
205
+ context.fillStyle = Color.shared.setValue(color).toHex();
206
+ context.fillRect(0, 0, outWidth, outHeight);
207
+ context.globalCompositeOperation = "multiply";
208
+ const source = canvasUtils.getCanvasSource(texture);
209
+ if (!source) {
210
+ context.restore();
211
+ return;
212
+ }
213
+ if (rotate) {
214
+ canvasUtils._applyInverseRotation(context, rotate, crop.width, crop.height);
215
+ }
216
+ context.drawImage(
217
+ source,
218
+ crop.x,
219
+ crop.y,
220
+ crop.width,
221
+ crop.height,
222
+ 0,
223
+ 0,
224
+ crop.width,
225
+ crop.height
226
+ );
227
+ context.globalCompositeOperation = "destination-atop";
228
+ context.drawImage(
229
+ source,
230
+ crop.x,
231
+ crop.y,
232
+ crop.width,
233
+ crop.height,
234
+ 0,
235
+ 0,
236
+ crop.width,
237
+ crop.height
238
+ );
239
+ context.restore();
240
+ },
241
+ tintWithOverlay: (texture, color, canvas) => {
242
+ const context = canvas.getContext("2d");
243
+ const crop = texture.frame.clone();
244
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
245
+ const rotate = texture.rotate;
246
+ crop.x *= resolution;
247
+ crop.y *= resolution;
248
+ crop.width *= resolution;
249
+ crop.height *= resolution;
250
+ const isVertical = groupD8.isVertical(rotate);
251
+ const outWidth = isVertical ? crop.height : crop.width;
252
+ const outHeight = isVertical ? crop.width : crop.height;
253
+ canvas.width = Math.ceil(outWidth);
254
+ canvas.height = Math.ceil(outHeight);
255
+ context.save();
256
+ context.globalCompositeOperation = "copy";
257
+ context.fillStyle = Color.shared.setValue(color).toHex();
258
+ context.fillRect(0, 0, outWidth, outHeight);
259
+ context.globalCompositeOperation = "destination-atop";
260
+ const source = canvasUtils.getCanvasSource(texture);
261
+ if (!source) {
262
+ context.restore();
263
+ return;
264
+ }
265
+ if (rotate) {
266
+ canvasUtils._applyInverseRotation(context, rotate, crop.width, crop.height);
267
+ }
268
+ context.drawImage(
269
+ source,
270
+ crop.x,
271
+ crop.y,
272
+ crop.width,
273
+ crop.height,
274
+ 0,
275
+ 0,
276
+ crop.width,
277
+ crop.height
278
+ );
279
+ context.restore();
280
+ },
281
+ tintWithPerPixel: (texture, color, canvas) => {
282
+ const context = canvas.getContext("2d");
283
+ const crop = texture.frame.clone();
284
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
285
+ const rotate = texture.rotate;
286
+ crop.x *= resolution;
287
+ crop.y *= resolution;
288
+ crop.width *= resolution;
289
+ crop.height *= resolution;
290
+ const isVertical = groupD8.isVertical(rotate);
291
+ const outWidth = isVertical ? crop.height : crop.width;
292
+ const outHeight = isVertical ? crop.width : crop.height;
293
+ canvas.width = Math.ceil(outWidth);
294
+ canvas.height = Math.ceil(outHeight);
295
+ context.save();
296
+ context.globalCompositeOperation = "copy";
297
+ const source = canvasUtils.getCanvasSource(texture);
298
+ if (!source) {
299
+ context.restore();
300
+ return;
301
+ }
302
+ if (rotate) {
303
+ canvasUtils._applyInverseRotation(context, rotate, crop.width, crop.height);
304
+ }
305
+ context.drawImage(
306
+ source,
307
+ crop.x,
308
+ crop.y,
309
+ crop.width,
310
+ crop.height,
311
+ 0,
312
+ 0,
313
+ crop.width,
314
+ crop.height
315
+ );
316
+ context.restore();
317
+ const r = color >> 16 & 255;
318
+ const g = color >> 8 & 255;
319
+ const b = color & 255;
320
+ const imageData = context.getImageData(0, 0, outWidth, outHeight);
321
+ const data = imageData.data;
322
+ for (let i = 0; i < data.length; i += 4) {
323
+ data[i] = data[i] * r / 255;
324
+ data[i + 1] = data[i + 1] * g / 255;
325
+ data[i + 2] = data[i + 2] * b / 255;
326
+ }
327
+ context.putImageData(imageData, 0, 0);
328
+ },
329
+ /**
330
+ * Applies inverse rotation transform to context for texture packer rotation compensation.
331
+ * Supports all 16 groupD8 symmetries (rotations and reflections).
332
+ * @param context - Canvas 2D context
333
+ * @param rotate - The groupD8 rotation value
334
+ * @param srcWidth - Source crop width (before rotation)
335
+ * @param srcHeight - Source crop height (before rotation)
336
+ */
337
+ _applyInverseRotation: (context, rotate, srcWidth, srcHeight) => {
338
+ const inv = groupD8.inv(rotate);
339
+ const a = groupD8.uX(inv);
340
+ const b = groupD8.uY(inv);
341
+ const c = groupD8.vX(inv);
342
+ const d = groupD8.vY(inv);
343
+ const tx = -Math.min(0, a * srcWidth, c * srcHeight, a * srcWidth + c * srcHeight);
344
+ const ty = -Math.min(0, b * srcWidth, d * srcHeight, b * srcWidth + d * srcHeight);
345
+ context.transform(a, b, c, d, tx, ty);
346
+ }
347
+ };
348
+ canvasUtils.tintMethod = canvasUtils.canUseMultiply ? canvasUtils.tintWithMultiply : canvasUtils.tintWithPerPixel;
349
+ const _CanvasBatchAdaptor = class _CanvasBatchAdaptor2 {
350
+ static _getPatternRepeat(addressModeU, addressModeV) {
351
+ const repeatU = addressModeU && addressModeU !== "clamp-to-edge";
352
+ const repeatV = addressModeV && addressModeV !== "clamp-to-edge";
353
+ if (repeatU && repeatV) return "repeat";
354
+ if (repeatU) return "repeat-x";
355
+ if (repeatV) return "repeat-y";
356
+ return "no-repeat";
357
+ }
358
+ start(batchPipe, geometry, shader) {
359
+ }
360
+ execute(batchPipe, batch) {
361
+ const elements = batch.elements;
362
+ if (!elements || !elements.length) return;
363
+ const renderer = batchPipe.renderer;
364
+ const contextSystem = renderer.canvasContext;
365
+ const context = contextSystem.activeContext;
366
+ for (let i = 0; i < elements.length; i++) {
367
+ const element = elements[i];
368
+ if (!element.packAsQuad) continue;
369
+ const quad = element;
370
+ const texture = quad.texture;
371
+ const source = texture ? canvasUtils.getCanvasSource(texture) : null;
372
+ if (!source) continue;
373
+ const textureStyle = texture.source.style;
374
+ const smoothProperty = contextSystem.smoothProperty;
375
+ const shouldSmooth = textureStyle.scaleMode !== "nearest";
376
+ if (context[smoothProperty] !== shouldSmooth) {
377
+ context[smoothProperty] = shouldSmooth;
378
+ }
379
+ contextSystem.setBlendMode(batch.blendMode);
380
+ const globalColor = renderer.globalUniforms.globalUniformData?.worldColor ?? 4294967295;
381
+ const argb = quad.color;
382
+ const globalAlpha = (globalColor >>> 24 & 255) / 255;
383
+ const quadAlpha = (argb >>> 24 & 255) / 255;
384
+ const filterAlpha = renderer.filter?.alphaMultiplier ?? 1;
385
+ const alpha = globalAlpha * quadAlpha * filterAlpha;
386
+ if (alpha <= 0) continue;
387
+ context.globalAlpha = alpha;
388
+ const globalTint = globalColor & 16777215;
389
+ const quadTint = argb & 16777215;
390
+ const tint = bgr2rgb(multiplyHexColors(quadTint, globalTint));
391
+ const frame = texture.frame;
392
+ const repeatU = textureStyle.addressModeU ?? textureStyle.addressMode;
393
+ const repeatV = textureStyle.addressModeV ?? textureStyle.addressMode;
394
+ const repeat = _CanvasBatchAdaptor2._getPatternRepeat(repeatU, repeatV);
395
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
396
+ const isFromCachedRenderGroup = quad.renderable?.renderGroup?.isCachedAsTexture;
397
+ const sx = frame.x * resolution;
398
+ const sy = frame.y * resolution;
399
+ const sw = frame.width * resolution;
400
+ const sh = frame.height * resolution;
401
+ const bounds = quad.bounds;
402
+ const isRootTarget = renderer.renderTarget.renderTarget.isRoot;
403
+ const dx = bounds.minX;
404
+ const dy = bounds.minY;
405
+ const dw = bounds.maxX - bounds.minX;
406
+ const dh = bounds.maxY - bounds.minY;
407
+ const rotate = texture.rotate;
408
+ const uvs = texture.uvs;
409
+ const uvMin = Math.min(uvs.x0, uvs.x1, uvs.x2, uvs.x3, uvs.y0, uvs.y1, uvs.y2, uvs.y3);
410
+ const uvMax = Math.max(uvs.x0, uvs.x1, uvs.x2, uvs.x3, uvs.y0, uvs.y1, uvs.y2, uvs.y3);
411
+ const needsRepeat = repeat !== "no-repeat" && (uvMin < 0 || uvMax > 1);
412
+ const willUseProcessedCanvas = !needsRepeat && (tint !== 16777215 || rotate);
413
+ const applyRotateTransform = rotate && !willUseProcessedCanvas;
414
+ if (applyRotateTransform) {
415
+ _CanvasBatchAdaptor2._tempPatternMatrix.copyFrom(quad.transform);
416
+ groupD8.matrixAppendRotationInv(
417
+ _CanvasBatchAdaptor2._tempPatternMatrix,
418
+ rotate,
419
+ dx,
420
+ dy,
421
+ dw,
422
+ dh
423
+ );
424
+ contextSystem.setContextTransform(
425
+ _CanvasBatchAdaptor2._tempPatternMatrix,
426
+ quad.roundPixels === 1,
427
+ void 0,
428
+ isFromCachedRenderGroup && isRootTarget
429
+ );
430
+ } else {
431
+ contextSystem.setContextTransform(
432
+ quad.transform,
433
+ quad.roundPixels === 1,
434
+ void 0,
435
+ isFromCachedRenderGroup && isRootTarget
436
+ );
437
+ }
438
+ const drawX = applyRotateTransform ? 0 : dx;
439
+ const drawY = applyRotateTransform ? 0 : dy;
440
+ const drawW = dw;
441
+ const drawH = dh;
442
+ if (needsRepeat) {
443
+ let patternSource = source;
444
+ const canTint = tint !== 16777215 && !rotate;
445
+ const fitsFrame = frame.width <= texture.source.width && frame.height <= texture.source.height;
446
+ if (canTint && fitsFrame) {
447
+ patternSource = canvasUtils.getTintedCanvas({ texture }, tint);
448
+ }
449
+ const pattern = context.createPattern(patternSource, repeat);
450
+ if (!pattern) continue;
451
+ const denomX = drawW;
452
+ const denomY = drawH;
453
+ if (denomX === 0 || denomY === 0) continue;
454
+ const invDx = 1 / denomX;
455
+ const invDy = 1 / denomY;
456
+ const a = (uvs.x1 - uvs.x0) * invDx;
457
+ const b = (uvs.y1 - uvs.y0) * invDx;
458
+ const c = (uvs.x3 - uvs.x0) * invDy;
459
+ const d = (uvs.y3 - uvs.y0) * invDy;
460
+ const tx = uvs.x0 - a * drawX - c * drawY;
461
+ const ty = uvs.y0 - b * drawX - d * drawY;
462
+ const pixelWidth = texture.source.pixelWidth;
463
+ const pixelHeight = texture.source.pixelHeight;
464
+ _CanvasBatchAdaptor2._tempPatternMatrix.set(
465
+ a * pixelWidth,
466
+ b * pixelHeight,
467
+ c * pixelWidth,
468
+ d * pixelHeight,
469
+ tx * pixelWidth,
470
+ ty * pixelHeight
471
+ );
472
+ canvasUtils.applyPatternTransform(pattern, _CanvasBatchAdaptor2._tempPatternMatrix);
473
+ context.fillStyle = pattern;
474
+ context.fillRect(drawX, drawY, drawW, drawH);
475
+ } else {
476
+ const needsProcessing = tint !== 16777215 || rotate;
477
+ const processedSource = needsProcessing ? canvasUtils.getTintedCanvas({ texture }, tint) : source;
478
+ const isProcessed = processedSource !== source;
479
+ context.drawImage(
480
+ processedSource,
481
+ isProcessed ? 0 : sx,
482
+ isProcessed ? 0 : sy,
483
+ isProcessed ? processedSource.width : sw,
484
+ isProcessed ? processedSource.height : sh,
485
+ drawX,
486
+ drawY,
487
+ drawW,
488
+ drawH
489
+ );
490
+ }
491
+ }
492
+ }
493
+ };
494
+ _CanvasBatchAdaptor._tempPatternMatrix = new Matrix();
495
+ _CanvasBatchAdaptor.extension = {
496
+ type: [
497
+ ExtensionType.CanvasPipesAdaptor
498
+ ],
499
+ name: "batch"
500
+ };
501
+ let CanvasBatchAdaptor = _CanvasBatchAdaptor;
502
+ class CanvasColorMaskPipe {
503
+ constructor(renderer) {
504
+ this._colorStack = [];
505
+ this._colorStackIndex = 0;
506
+ this._currentColor = 0;
507
+ this._renderer = renderer;
508
+ }
509
+ buildStart() {
510
+ this._colorStack[0] = 15;
511
+ this._colorStackIndex = 1;
512
+ this._currentColor = 15;
513
+ }
514
+ push(mask, _container, instructionSet) {
515
+ this._renderer.renderPipes.batch.break(instructionSet);
516
+ const colorStack = this._colorStack;
517
+ colorStack[this._colorStackIndex] = colorStack[this._colorStackIndex - 1] & mask.mask;
518
+ const currentColor = this._colorStack[this._colorStackIndex];
519
+ if (currentColor !== this._currentColor) {
520
+ this._currentColor = currentColor;
521
+ instructionSet.add({
522
+ renderPipeId: "colorMask",
523
+ colorMask: currentColor,
524
+ canBundle: false
525
+ });
526
+ }
527
+ this._colorStackIndex++;
528
+ }
529
+ pop(_mask, _container, instructionSet) {
530
+ this._renderer.renderPipes.batch.break(instructionSet);
531
+ const colorStack = this._colorStack;
532
+ this._colorStackIndex--;
533
+ const currentColor = colorStack[this._colorStackIndex - 1];
534
+ if (currentColor !== this._currentColor) {
535
+ this._currentColor = currentColor;
536
+ instructionSet.add({
537
+ renderPipeId: "colorMask",
538
+ colorMask: currentColor,
539
+ canBundle: false
540
+ });
541
+ }
542
+ }
543
+ execute(_instruction) {
544
+ }
545
+ destroy() {
546
+ this._renderer = null;
547
+ this._colorStack = null;
548
+ }
549
+ }
550
+ CanvasColorMaskPipe.extension = {
551
+ type: [
552
+ ExtensionType.CanvasPipes
553
+ ],
554
+ name: "colorMask"
555
+ };
556
+ function buildRoundedRectPath$1(context, x, y, width, height, radius) {
557
+ radius = Math.max(0, Math.min(radius, Math.min(width, height) / 2));
558
+ context.moveTo(x + radius, y);
559
+ context.lineTo(x + width - radius, y);
560
+ context.quadraticCurveTo(x + width, y, x + width, y + radius);
561
+ context.lineTo(x + width, y + height - radius);
562
+ context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
563
+ context.lineTo(x + radius, y + height);
564
+ context.quadraticCurveTo(x, y + height, x, y + height - radius);
565
+ context.lineTo(x, y + radius);
566
+ context.quadraticCurveTo(x, y, x + radius, y);
567
+ }
568
+ function buildShapePath$1(context, shape) {
569
+ switch (shape.type) {
570
+ case "rectangle": {
571
+ const rect = shape;
572
+ context.rect(rect.x, rect.y, rect.width, rect.height);
573
+ break;
574
+ }
575
+ case "roundedRectangle": {
576
+ const rect = shape;
577
+ buildRoundedRectPath$1(context, rect.x, rect.y, rect.width, rect.height, rect.radius);
578
+ break;
579
+ }
580
+ case "circle": {
581
+ const circle = shape;
582
+ context.moveTo(circle.x + circle.radius, circle.y);
583
+ context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
584
+ break;
585
+ }
586
+ case "ellipse": {
587
+ const ellipse = shape;
588
+ if (context.ellipse) {
589
+ context.moveTo(ellipse.x + ellipse.halfWidth, ellipse.y);
590
+ context.ellipse(ellipse.x, ellipse.y, ellipse.halfWidth, ellipse.halfHeight, 0, 0, Math.PI * 2);
591
+ } else {
592
+ context.save();
593
+ context.translate(ellipse.x, ellipse.y);
594
+ context.scale(ellipse.halfWidth, ellipse.halfHeight);
595
+ context.moveTo(1, 0);
596
+ context.arc(0, 0, 1, 0, Math.PI * 2);
597
+ context.restore();
598
+ }
599
+ break;
600
+ }
601
+ case "triangle": {
602
+ const tri = shape;
603
+ context.moveTo(tri.x, tri.y);
604
+ context.lineTo(tri.x2, tri.y2);
605
+ context.lineTo(tri.x3, tri.y3);
606
+ context.closePath();
607
+ break;
608
+ }
609
+ case "polygon":
610
+ default: {
611
+ const poly = shape;
612
+ const points = poly.points;
613
+ if (!points?.length) break;
614
+ context.moveTo(points[0], points[1]);
615
+ for (let i = 2; i < points.length; i += 2) {
616
+ context.lineTo(points[i], points[i + 1]);
617
+ }
618
+ if (poly.closePath) {
619
+ context.closePath();
620
+ }
621
+ break;
622
+ }
623
+ }
624
+ }
625
+ function addHolePaths$1(context, holes) {
626
+ if (!holes?.length) return false;
627
+ for (let i = 0; i < holes.length; i++) {
628
+ const hole = holes[i];
629
+ if (!hole?.shape) continue;
630
+ const transform = hole.transform;
631
+ const hasTransform = transform && !transform.isIdentity();
632
+ if (hasTransform) {
633
+ context.save();
634
+ context.transform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
635
+ }
636
+ buildShapePath$1(context, hole.shape);
637
+ if (hasTransform) {
638
+ context.restore();
639
+ }
640
+ }
641
+ return true;
642
+ }
643
+ class CanvasStencilMaskPipe {
644
+ constructor(renderer) {
645
+ this._warnedMaskTypes = /* @__PURE__ */ new Set();
646
+ this._canvasMaskStack = [];
647
+ this._renderer = renderer;
648
+ }
649
+ push(mask, _container, instructionSet) {
650
+ this._renderer.renderPipes.batch.break(instructionSet);
651
+ instructionSet.add({
652
+ renderPipeId: "stencilMask",
653
+ action: "pushMaskBegin",
654
+ mask,
655
+ inverse: _container._maskOptions.inverse,
656
+ canBundle: false
657
+ });
658
+ }
659
+ pop(_mask, _container, instructionSet) {
660
+ this._renderer.renderPipes.batch.break(instructionSet);
661
+ instructionSet.add({
662
+ renderPipeId: "stencilMask",
663
+ action: "popMaskEnd",
664
+ mask: _mask,
665
+ inverse: _container._maskOptions.inverse,
666
+ canBundle: false
667
+ });
668
+ }
669
+ execute(instruction) {
670
+ if (instruction.action !== "pushMaskBegin" && instruction.action !== "popMaskEnd") {
671
+ return;
672
+ }
673
+ const canvasRenderer = this._renderer;
674
+ const contextSystem = canvasRenderer.canvasContext;
675
+ const context = contextSystem?.activeContext;
676
+ if (!context) return;
677
+ if (instruction.action === "popMaskEnd") {
678
+ const didClip = this._canvasMaskStack.pop();
679
+ if (didClip) {
680
+ context.restore();
681
+ }
682
+ return;
683
+ }
684
+ if (instruction.inverse) {
685
+ this._warnOnce(
686
+ "inverse",
687
+ "CanvasRenderer: inverse masks are not supported on Canvas2D; ignoring inverse flag."
688
+ );
689
+ }
690
+ const maskContainer = instruction.mask.mask;
691
+ if (!(maskContainer instanceof Graphics)) {
692
+ this._warnOnce(
693
+ "nonGraphics",
694
+ "CanvasRenderer: only Graphics masks are supported in Canvas2D; skipping mask."
695
+ );
696
+ this._canvasMaskStack.push(false);
697
+ return;
698
+ }
699
+ const graphics = maskContainer;
700
+ const instructions = graphics.context?.instructions;
701
+ if (!instructions?.length) {
702
+ this._canvasMaskStack.push(false);
703
+ return;
704
+ }
705
+ context.save();
706
+ contextSystem.setContextTransform(
707
+ graphics.groupTransform,
708
+ (canvasRenderer._roundPixels | graphics._roundPixels) === 1
709
+ );
710
+ context.beginPath();
711
+ let drewPath = false;
712
+ let hasHoles = false;
713
+ for (let i = 0; i < instructions.length; i++) {
714
+ const instructionData = instructions[i];
715
+ const action = instructionData.action;
716
+ if (action !== "fill" && action !== "stroke") continue;
717
+ const data = instructionData.data;
718
+ const shapePath = data?.path?.shapePath;
719
+ if (!shapePath?.shapePrimitives?.length) continue;
720
+ const shapePrimitives = shapePath.shapePrimitives;
721
+ for (let j = 0; j < shapePrimitives.length; j++) {
722
+ const primitive = shapePrimitives[j];
723
+ if (!primitive?.shape) continue;
724
+ const transform = primitive.transform;
725
+ const hasTransform = transform && !transform.isIdentity();
726
+ if (hasTransform) {
727
+ context.save();
728
+ context.transform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
729
+ }
730
+ buildShapePath$1(context, primitive.shape);
731
+ hasHoles = addHolePaths$1(context, primitive.holes) || hasHoles;
732
+ drewPath = true;
733
+ if (hasTransform) {
734
+ context.restore();
735
+ }
736
+ }
737
+ }
738
+ if (!drewPath) {
739
+ context.restore();
740
+ this._canvasMaskStack.push(false);
741
+ return;
742
+ }
743
+ if (hasHoles) {
744
+ context.clip("evenodd");
745
+ } else {
746
+ context.clip();
747
+ }
748
+ this._canvasMaskStack.push(true);
749
+ }
750
+ destroy() {
751
+ this._renderer = null;
752
+ this._warnedMaskTypes = null;
753
+ this._canvasMaskStack = null;
754
+ }
755
+ _warnOnce(key, message) {
756
+ if (this._warnedMaskTypes.has(key)) return;
757
+ this._warnedMaskTypes.add(key);
758
+ warn(message);
759
+ }
760
+ }
761
+ CanvasStencilMaskPipe.extension = {
762
+ type: [
763
+ ExtensionType.CanvasPipes
764
+ ],
765
+ name: "stencilMask"
766
+ };
767
+ const FALLBACK_BLEND = "source-over";
768
+ function mapCanvasBlendModesToPixi() {
769
+ const supportsAdvanced = canUseNewCanvasBlendModes();
770
+ const map = /* @__PURE__ */ Object.create(null);
771
+ map.inherit = FALLBACK_BLEND;
772
+ map.none = FALLBACK_BLEND;
773
+ map.normal = "source-over";
774
+ map.add = "lighter";
775
+ map.multiply = supportsAdvanced ? "multiply" : FALLBACK_BLEND;
776
+ map.screen = supportsAdvanced ? "screen" : FALLBACK_BLEND;
777
+ map.overlay = supportsAdvanced ? "overlay" : FALLBACK_BLEND;
778
+ map.darken = supportsAdvanced ? "darken" : FALLBACK_BLEND;
779
+ map.lighten = supportsAdvanced ? "lighten" : FALLBACK_BLEND;
780
+ map["color-dodge"] = supportsAdvanced ? "color-dodge" : FALLBACK_BLEND;
781
+ map["color-burn"] = supportsAdvanced ? "color-burn" : FALLBACK_BLEND;
782
+ map["hard-light"] = supportsAdvanced ? "hard-light" : FALLBACK_BLEND;
783
+ map["soft-light"] = supportsAdvanced ? "soft-light" : FALLBACK_BLEND;
784
+ map.difference = supportsAdvanced ? "difference" : FALLBACK_BLEND;
785
+ map.exclusion = supportsAdvanced ? "exclusion" : FALLBACK_BLEND;
786
+ map.saturation = supportsAdvanced ? "saturation" : FALLBACK_BLEND;
787
+ map.color = supportsAdvanced ? "color" : FALLBACK_BLEND;
788
+ map.luminosity = supportsAdvanced ? "luminosity" : FALLBACK_BLEND;
789
+ map["linear-burn"] = supportsAdvanced ? "color-burn" : FALLBACK_BLEND;
790
+ map["linear-dodge"] = supportsAdvanced ? "color-dodge" : FALLBACK_BLEND;
791
+ map["linear-light"] = supportsAdvanced ? "hard-light" : FALLBACK_BLEND;
792
+ map["pin-light"] = supportsAdvanced ? "hard-light" : FALLBACK_BLEND;
793
+ map["vivid-light"] = supportsAdvanced ? "hard-light" : FALLBACK_BLEND;
794
+ map["hard-mix"] = FALLBACK_BLEND;
795
+ map.negation = supportsAdvanced ? "difference" : FALLBACK_BLEND;
796
+ map["normal-npm"] = map.normal;
797
+ map["add-npm"] = map.add;
798
+ map["screen-npm"] = map.screen;
799
+ map.erase = "destination-out";
800
+ map.subtract = FALLBACK_BLEND;
801
+ map.divide = FALLBACK_BLEND;
802
+ map.min = FALLBACK_BLEND;
803
+ map.max = FALLBACK_BLEND;
804
+ return map;
805
+ }
806
+ const tempMatrix$1 = new Matrix();
807
+ class CanvasContextSystem {
808
+ /**
809
+ * @param renderer - The owning CanvasRenderer.
810
+ */
811
+ constructor(renderer) {
812
+ this.activeResolution = 1;
813
+ this.smoothProperty = "imageSmoothingEnabled";
814
+ this.blendModes = mapCanvasBlendModesToPixi();
815
+ this._activeBlendMode = "normal";
816
+ this._projTransform = null;
817
+ this._outerBlend = false;
818
+ this._warnedBlendModes = /* @__PURE__ */ new Set();
819
+ this._renderer = renderer;
820
+ }
821
+ resolutionChange(resolution) {
822
+ this.activeResolution = resolution;
823
+ }
824
+ /** Initializes the root context and smoothing flag selection. */
825
+ init() {
826
+ const alpha = this._renderer.background.alpha < 1;
827
+ this.rootContext = this._renderer.canvas.getContext(
828
+ "2d",
829
+ { alpha }
830
+ );
831
+ this.activeContext = this.rootContext;
832
+ this.activeResolution = this._renderer.resolution;
833
+ if (!this.rootContext.imageSmoothingEnabled) {
834
+ const rc = this.rootContext;
835
+ if (rc.webkitImageSmoothingEnabled) {
836
+ this.smoothProperty = "webkitImageSmoothingEnabled";
837
+ } else if (rc.mozImageSmoothingEnabled) {
838
+ this.smoothProperty = "mozImageSmoothingEnabled";
839
+ } else if (rc.oImageSmoothingEnabled) {
840
+ this.smoothProperty = "oImageSmoothingEnabled";
841
+ } else if (rc.msImageSmoothingEnabled) {
842
+ this.smoothProperty = "msImageSmoothingEnabled";
843
+ }
844
+ }
845
+ }
846
+ /**
847
+ * Sets the current transform on the active context.
848
+ * @param transform - Transform to apply.
849
+ * @param roundPixels - Whether to round translation to integers.
850
+ * @param localResolution - Optional local resolution multiplier.
851
+ * @param skipGlobalTransform - If true, skip applying the global world transform matrix.
852
+ */
853
+ setContextTransform(transform, roundPixels, localResolution, skipGlobalTransform) {
854
+ const globalTransform = skipGlobalTransform ? Matrix.IDENTITY : this._renderer.globalUniforms.globalUniformData?.worldTransformMatrix || Matrix.IDENTITY;
855
+ let mat = tempMatrix$1;
856
+ mat.copyFrom(globalTransform);
857
+ mat.append(transform);
858
+ const proj = this._projTransform;
859
+ const contextResolution = this.activeResolution;
860
+ localResolution = localResolution || contextResolution;
861
+ if (proj) {
862
+ const finalMat = Matrix.shared;
863
+ finalMat.copyFrom(mat);
864
+ finalMat.prepend(proj);
865
+ mat = finalMat;
866
+ }
867
+ if (roundPixels) {
868
+ this.activeContext.setTransform(
869
+ mat.a * localResolution,
870
+ mat.b * localResolution,
871
+ mat.c * localResolution,
872
+ mat.d * localResolution,
873
+ mat.tx * contextResolution | 0,
874
+ mat.ty * contextResolution | 0
875
+ );
876
+ } else {
877
+ this.activeContext.setTransform(
878
+ mat.a * localResolution,
879
+ mat.b * localResolution,
880
+ mat.c * localResolution,
881
+ mat.d * localResolution,
882
+ mat.tx * contextResolution,
883
+ mat.ty * contextResolution
884
+ );
885
+ }
886
+ }
887
+ /**
888
+ * Clears the current render target, optionally filling with a color.
889
+ * @param clearColor - Color to fill after clearing.
890
+ * @param alpha - Alpha override for the clear color.
891
+ */
892
+ clear(clearColor, alpha) {
893
+ const context = this.activeContext;
894
+ const renderer = this._renderer;
895
+ context.clearRect(0, 0, renderer.width, renderer.height);
896
+ if (clearColor) {
897
+ const color = Color.shared.setValue(clearColor);
898
+ context.globalAlpha = alpha ?? color.alpha;
899
+ context.fillStyle = color.toHex();
900
+ context.fillRect(0, 0, renderer.width, renderer.height);
901
+ context.globalAlpha = 1;
902
+ }
903
+ }
904
+ /**
905
+ * Sets the active blend mode.
906
+ * @param blendMode - Pixi blend mode.
907
+ */
908
+ setBlendMode(blendMode) {
909
+ if (this._activeBlendMode === blendMode) return;
910
+ this._activeBlendMode = blendMode;
911
+ this._outerBlend = false;
912
+ const mappedBlend = this.blendModes[blendMode];
913
+ if (!mappedBlend) {
914
+ if (!this._warnedBlendModes.has(blendMode)) {
915
+ console.warn(
916
+ `CanvasRenderer: blend mode "${blendMode}" is not supported in Canvas2D; falling back to "source-over".`
917
+ );
918
+ this._warnedBlendModes.add(blendMode);
919
+ }
920
+ this.activeContext.globalCompositeOperation = "source-over";
921
+ return;
922
+ }
923
+ this.activeContext.globalCompositeOperation = mappedBlend;
924
+ }
925
+ /** Releases context references. */
926
+ destroy() {
927
+ this.rootContext = null;
928
+ this.activeContext = null;
929
+ this._warnedBlendModes.clear();
930
+ }
931
+ }
932
+ CanvasContextSystem.extension = {
933
+ type: [
934
+ ExtensionType.CanvasSystem
935
+ ],
936
+ name: "canvasContext"
937
+ };
938
+ class CanvasLimitsSystem {
939
+ constructor() {
940
+ this.maxTextures = 16;
941
+ this.maxBatchableTextures = 16;
942
+ this.maxUniformBindings = 0;
943
+ }
944
+ init() {
945
+ }
946
+ }
947
+ CanvasLimitsSystem.extension = {
948
+ type: [
949
+ ExtensionType.CanvasSystem
950
+ ],
951
+ name: "limits"
952
+ };
953
+ const emptyCanvasStyle = "#808080";
954
+ const tempMatrix = new Matrix();
955
+ const tempTextureMatrix = new Matrix();
956
+ const tempGradientMatrix = new Matrix();
957
+ const tempPatternMatrix = new Matrix();
958
+ function fillTriangles(context, vertices, indices) {
959
+ context.beginPath();
960
+ for (let i = 0; i < indices.length; i += 3) {
961
+ const i0 = indices[i] * 2;
962
+ const i1 = indices[i + 1] * 2;
963
+ const i2 = indices[i + 2] * 2;
964
+ context.moveTo(vertices[i0], vertices[i0 + 1]);
965
+ context.lineTo(vertices[i1], vertices[i1 + 1]);
966
+ context.lineTo(vertices[i2], vertices[i2 + 1]);
967
+ context.closePath();
968
+ }
969
+ context.fill();
970
+ }
971
+ function colorToHex(color) {
972
+ const clamped = color & 16777215;
973
+ return `#${clamped.toString(16).padStart(6, "0")}`;
974
+ }
975
+ function buildRoundedRectPath(context, x, y, width, height, radius) {
976
+ radius = Math.max(0, Math.min(radius, Math.min(width, height) / 2));
977
+ context.moveTo(x + radius, y);
978
+ context.lineTo(x + width - radius, y);
979
+ context.quadraticCurveTo(x + width, y, x + width, y + radius);
980
+ context.lineTo(x + width, y + height - radius);
981
+ context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
982
+ context.lineTo(x + radius, y + height);
983
+ context.quadraticCurveTo(x, y + height, x, y + height - radius);
984
+ context.lineTo(x, y + radius);
985
+ context.quadraticCurveTo(x, y, x + radius, y);
986
+ }
987
+ function buildShapePath(context, shape) {
988
+ switch (shape.type) {
989
+ case "rectangle": {
990
+ const rect = shape;
991
+ context.rect(rect.x, rect.y, rect.width, rect.height);
992
+ break;
993
+ }
994
+ case "roundedRectangle": {
995
+ const rect = shape;
996
+ buildRoundedRectPath(context, rect.x, rect.y, rect.width, rect.height, rect.radius);
997
+ break;
998
+ }
999
+ case "circle": {
1000
+ const circle = shape;
1001
+ context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
1002
+ break;
1003
+ }
1004
+ case "ellipse": {
1005
+ const ellipse = shape;
1006
+ if (context.ellipse) {
1007
+ context.ellipse(ellipse.x, ellipse.y, ellipse.halfWidth, ellipse.halfHeight, 0, 0, Math.PI * 2);
1008
+ } else {
1009
+ context.save();
1010
+ context.translate(ellipse.x, ellipse.y);
1011
+ context.scale(ellipse.halfWidth, ellipse.halfHeight);
1012
+ context.arc(0, 0, 1, 0, Math.PI * 2);
1013
+ context.restore();
1014
+ }
1015
+ break;
1016
+ }
1017
+ case "triangle": {
1018
+ const tri = shape;
1019
+ context.moveTo(tri.x, tri.y);
1020
+ context.lineTo(tri.x2, tri.y2);
1021
+ context.lineTo(tri.x3, tri.y3);
1022
+ context.closePath();
1023
+ break;
1024
+ }
1025
+ case "polygon":
1026
+ default: {
1027
+ const poly = shape;
1028
+ const points = poly.points;
1029
+ if (!points?.length) break;
1030
+ context.moveTo(points[0], points[1]);
1031
+ for (let i = 2; i < points.length; i += 2) {
1032
+ context.lineTo(points[i], points[i + 1]);
1033
+ }
1034
+ if (poly.closePath) {
1035
+ context.closePath();
1036
+ }
1037
+ break;
1038
+ }
1039
+ }
1040
+ }
1041
+ function addHolePaths(context, holes) {
1042
+ if (!holes?.length) return false;
1043
+ for (let i = 0; i < holes.length; i++) {
1044
+ const hole = holes[i];
1045
+ if (!hole?.shape) continue;
1046
+ const transform = hole.transform;
1047
+ const hasTransform = transform && !transform.isIdentity();
1048
+ if (hasTransform) {
1049
+ context.save();
1050
+ context.transform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
1051
+ }
1052
+ buildShapePath(context, hole.shape);
1053
+ if (hasTransform) {
1054
+ context.restore();
1055
+ }
1056
+ }
1057
+ return true;
1058
+ }
1059
+ function getCanvasStyle(style, tint, textureMatrix, currentTransform) {
1060
+ const fill = style.fill;
1061
+ if (fill instanceof FillGradient) {
1062
+ fill.buildGradient();
1063
+ const gradientTexture = fill.texture;
1064
+ if (gradientTexture) {
1065
+ const pattern = canvasUtils.getTintedPattern(gradientTexture, tint);
1066
+ const patternMatrix = textureMatrix ? tempPatternMatrix.copyFrom(textureMatrix).scale(gradientTexture.source.pixelWidth, gradientTexture.source.pixelHeight) : tempPatternMatrix.copyFrom(fill.transform);
1067
+ if (currentTransform && !style.textureSpace) {
1068
+ patternMatrix.append(currentTransform);
1069
+ }
1070
+ canvasUtils.applyPatternTransform(pattern, patternMatrix);
1071
+ return pattern;
1072
+ }
1073
+ }
1074
+ if (fill instanceof FillPattern) {
1075
+ const pattern = canvasUtils.getTintedPattern(fill.texture, tint);
1076
+ canvasUtils.applyPatternTransform(pattern, fill.transform);
1077
+ return pattern;
1078
+ }
1079
+ const texture = style.texture;
1080
+ if (texture && texture !== Texture.WHITE) {
1081
+ if (!texture.source.resource) {
1082
+ return emptyCanvasStyle;
1083
+ }
1084
+ const pattern = canvasUtils.getTintedPattern(texture, tint);
1085
+ const patternMatrix = textureMatrix ? tempPatternMatrix.copyFrom(textureMatrix).scale(texture.source.pixelWidth, texture.source.pixelHeight) : style.matrix;
1086
+ canvasUtils.applyPatternTransform(pattern, patternMatrix);
1087
+ return pattern;
1088
+ }
1089
+ return colorToHex(tint);
1090
+ }
1091
+ class CanvasGraphicsAdaptor {
1092
+ constructor() {
1093
+ this.shader = null;
1094
+ }
1095
+ contextChange(renderer) {
1096
+ }
1097
+ execute(graphicsPipe, renderable) {
1098
+ const renderer = graphicsPipe.renderer;
1099
+ const contextSystem = renderer.canvasContext;
1100
+ const context = contextSystem.activeContext;
1101
+ const baseTransform = renderable.groupTransform;
1102
+ const globalColor = renderer.globalUniforms.globalUniformData?.worldColor ?? 4294967295;
1103
+ const groupColorAlpha = renderable.groupColorAlpha;
1104
+ const globalAlpha = (globalColor >>> 24 & 255) / 255;
1105
+ const groupAlphaValue = (groupColorAlpha >>> 24 & 255) / 255;
1106
+ const filterAlpha = renderer.filter?.alphaMultiplier ?? 1;
1107
+ const groupAlpha = globalAlpha * groupAlphaValue * filterAlpha;
1108
+ if (groupAlpha <= 0) return;
1109
+ const globalTint = globalColor & 16777215;
1110
+ const groupTintBGR = groupColorAlpha & 16777215;
1111
+ const groupTint = bgr2rgb(multiplyHexColors(groupTintBGR, globalTint));
1112
+ const roundPixels = renderer._roundPixels | renderable._roundPixels;
1113
+ context.save();
1114
+ contextSystem.setContextTransform(baseTransform, roundPixels === 1);
1115
+ contextSystem.setBlendMode(renderable.groupBlendMode);
1116
+ const instructions = renderable.context.instructions;
1117
+ for (let i = 0; i < instructions.length; i++) {
1118
+ const instruction = instructions[i];
1119
+ if (instruction.action === "texture") {
1120
+ const data2 = instruction.data;
1121
+ const texture = data2.image;
1122
+ const source = texture ? canvasUtils.getCanvasSource(texture) : null;
1123
+ if (!source) continue;
1124
+ const alpha2 = data2.alpha * groupAlpha;
1125
+ if (alpha2 <= 0) continue;
1126
+ const tint2 = multiplyHexColors(data2.style, groupTint);
1127
+ context.globalAlpha = alpha2;
1128
+ let drawSource = source;
1129
+ if (tint2 !== 16777215) {
1130
+ drawSource = canvasUtils.getTintedCanvas({ texture }, tint2);
1131
+ }
1132
+ const frame = texture.frame;
1133
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
1134
+ let sx = frame.x * resolution;
1135
+ let sy = frame.y * resolution;
1136
+ const sw = frame.width * resolution;
1137
+ const sh = frame.height * resolution;
1138
+ if (drawSource !== source) {
1139
+ sx = 0;
1140
+ sy = 0;
1141
+ }
1142
+ const transform = data2.transform;
1143
+ const hasTransform = transform && !transform.isIdentity();
1144
+ const rotate = texture.rotate;
1145
+ if (hasTransform || rotate) {
1146
+ tempMatrix.copyFrom(baseTransform);
1147
+ if (hasTransform) {
1148
+ tempMatrix.append(transform);
1149
+ }
1150
+ if (rotate) {
1151
+ groupD8.matrixAppendRotationInv(tempMatrix, rotate, data2.dx, data2.dy, data2.dw, data2.dh);
1152
+ }
1153
+ contextSystem.setContextTransform(tempMatrix, roundPixels === 1);
1154
+ } else {
1155
+ contextSystem.setContextTransform(baseTransform, roundPixels === 1);
1156
+ }
1157
+ context.drawImage(
1158
+ drawSource,
1159
+ sx,
1160
+ sy,
1161
+ drawSource === source ? sw : drawSource.width,
1162
+ drawSource === source ? sh : drawSource.height,
1163
+ rotate ? 0 : data2.dx,
1164
+ rotate ? 0 : data2.dy,
1165
+ data2.dw,
1166
+ data2.dh
1167
+ );
1168
+ if (hasTransform || rotate) {
1169
+ contextSystem.setContextTransform(baseTransform, roundPixels === 1);
1170
+ }
1171
+ continue;
1172
+ }
1173
+ const data = instruction.data;
1174
+ const shapePath = data?.path?.shapePath;
1175
+ if (!shapePath?.shapePrimitives?.length) continue;
1176
+ const style = data.style;
1177
+ const tint = multiplyHexColors(style.color, groupTint);
1178
+ const alpha = style.alpha * groupAlpha;
1179
+ if (alpha <= 0) continue;
1180
+ const isStroke = instruction.action === "stroke";
1181
+ context.globalAlpha = alpha;
1182
+ if (isStroke) {
1183
+ const strokeStyle = style;
1184
+ context.lineWidth = strokeStyle.width;
1185
+ context.lineCap = strokeStyle.cap;
1186
+ context.lineJoin = strokeStyle.join;
1187
+ context.miterLimit = strokeStyle.miterLimit;
1188
+ }
1189
+ const shapePrimitives = shapePath.shapePrimitives;
1190
+ if (!isStroke && data.hole?.shapePath?.shapePrimitives?.length) {
1191
+ const lastShape = shapePrimitives[shapePrimitives.length - 1];
1192
+ lastShape.holes = data.hole.shapePath.shapePrimitives;
1193
+ }
1194
+ for (let j = 0; j < shapePrimitives.length; j++) {
1195
+ const primitive = shapePrimitives[j];
1196
+ if (!primitive?.shape) continue;
1197
+ const transform = primitive.transform;
1198
+ const hasTransform = transform && !transform.isIdentity();
1199
+ const hasTexture = style.texture && style.texture !== Texture.WHITE;
1200
+ const textureTransform = style.textureSpace === "global" ? transform : null;
1201
+ const textureMatrix = hasTexture ? generateTextureMatrix(tempTextureMatrix, style, primitive.shape, textureTransform) : null;
1202
+ const currentTransform = hasTransform ? tempGradientMatrix.copyFrom(baseTransform).append(transform) : baseTransform;
1203
+ const canvasStyle = getCanvasStyle(
1204
+ style,
1205
+ tint,
1206
+ textureMatrix,
1207
+ currentTransform
1208
+ );
1209
+ if (hasTransform) {
1210
+ context.save();
1211
+ context.transform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
1212
+ }
1213
+ if (isStroke) {
1214
+ const strokeStyle = style;
1215
+ const useStrokeGeometry = strokeStyle.alignment !== 0.5 && !strokeStyle.pixelLine;
1216
+ if (useStrokeGeometry) {
1217
+ const points = [];
1218
+ const vertices = [];
1219
+ const indices = [];
1220
+ const shapeBuilder = shapeBuilders[primitive.shape.type];
1221
+ if (shapeBuilder?.build(primitive.shape, points)) {
1222
+ const close = primitive.shape.closePath ?? true;
1223
+ buildLine(points, strokeStyle, false, close, vertices, indices);
1224
+ context.fillStyle = canvasStyle;
1225
+ fillTriangles(context, vertices, indices);
1226
+ } else {
1227
+ context.strokeStyle = canvasStyle;
1228
+ context.beginPath();
1229
+ buildShapePath(context, primitive.shape);
1230
+ context.stroke();
1231
+ }
1232
+ } else {
1233
+ context.strokeStyle = canvasStyle;
1234
+ context.beginPath();
1235
+ buildShapePath(context, primitive.shape);
1236
+ context.stroke();
1237
+ }
1238
+ } else {
1239
+ context.fillStyle = canvasStyle;
1240
+ context.beginPath();
1241
+ buildShapePath(context, primitive.shape);
1242
+ const hasHoles = addHolePaths(context, primitive.holes);
1243
+ if (hasHoles) {
1244
+ context.fill("evenodd");
1245
+ } else {
1246
+ context.fill();
1247
+ }
1248
+ }
1249
+ if (hasTransform) {
1250
+ context.restore();
1251
+ }
1252
+ }
1253
+ }
1254
+ context.restore();
1255
+ }
1256
+ destroy() {
1257
+ this.shader = null;
1258
+ }
1259
+ }
1260
+ CanvasGraphicsAdaptor.extension = {
1261
+ type: [
1262
+ ExtensionType.CanvasPipesAdaptor
1263
+ ],
1264
+ name: "graphics"
1265
+ };
1266
+ class CanvasRenderTargetAdaptor {
1267
+ /**
1268
+ * Initializes the adaptor.
1269
+ * @param renderer - Canvas renderer instance.
1270
+ * @param renderTargetSystem - The render target system.
1271
+ * @advanced
1272
+ */
1273
+ init(renderer, renderTargetSystem) {
1274
+ this._renderer = renderer;
1275
+ this._renderTargetSystem = renderTargetSystem;
1276
+ }
1277
+ /**
1278
+ * Creates a GPU render target for canvas.
1279
+ * @param renderTarget - Render target to initialize.
1280
+ * @advanced
1281
+ */
1282
+ initGpuRenderTarget(renderTarget) {
1283
+ const colorTexture = renderTarget.colorTexture;
1284
+ const { canvas, context } = this._ensureCanvas(colorTexture);
1285
+ return {
1286
+ canvas,
1287
+ context,
1288
+ width: canvas.width,
1289
+ height: canvas.height
1290
+ };
1291
+ }
1292
+ /**
1293
+ * Resizes the backing canvas for a render target.
1294
+ * @param renderTarget - Render target to resize.
1295
+ * @advanced
1296
+ */
1297
+ resizeGpuRenderTarget(renderTarget) {
1298
+ const colorTexture = renderTarget.colorTexture;
1299
+ const { canvas } = this._ensureCanvas(colorTexture);
1300
+ canvas.width = renderTarget.pixelWidth;
1301
+ canvas.height = renderTarget.pixelHeight;
1302
+ }
1303
+ /**
1304
+ * Starts a render pass on the canvas target.
1305
+ * @param renderTarget - Target to render to.
1306
+ * @param clear - Clear mode.
1307
+ * @param clearColor - Optional clear color.
1308
+ * @param viewport - Optional viewport.
1309
+ * @advanced
1310
+ */
1311
+ startRenderPass(renderTarget, clear, clearColor, viewport) {
1312
+ const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
1313
+ this._renderer.canvasContext.activeContext = gpuRenderTarget.context;
1314
+ this._renderer.canvasContext.activeResolution = renderTarget.resolution;
1315
+ if (clear) {
1316
+ this.clear(renderTarget, clear, clearColor, viewport);
1317
+ }
1318
+ }
1319
+ /**
1320
+ * Clears the render target.
1321
+ * @param renderTarget - Target to clear.
1322
+ * @param _clear - Clear mode (unused).
1323
+ * @param clearColor - Optional clear color.
1324
+ * @param viewport - Optional viewport rectangle.
1325
+ * @advanced
1326
+ */
1327
+ clear(renderTarget, _clear, clearColor, viewport) {
1328
+ const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
1329
+ const context = gpuRenderTarget.context;
1330
+ const bounds = viewport || { x: 0, y: 0, width: renderTarget.pixelWidth, height: renderTarget.pixelHeight };
1331
+ context.setTransform(1, 0, 0, 1, 0, 0);
1332
+ context.clearRect(bounds.x, bounds.y, bounds.width, bounds.height);
1333
+ if (clearColor) {
1334
+ const color = Color.shared.setValue(clearColor);
1335
+ if (color.alpha > 0) {
1336
+ context.globalAlpha = color.alpha;
1337
+ context.fillStyle = color.toHex();
1338
+ context.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
1339
+ context.globalAlpha = 1;
1340
+ }
1341
+ }
1342
+ }
1343
+ /**
1344
+ * Finishes the render pass (no-op for canvas).
1345
+ * @advanced
1346
+ */
1347
+ finishRenderPass() {
1348
+ }
1349
+ /**
1350
+ * Copies a render target into a texture source.
1351
+ * @param {RenderTarget} sourceRenderSurfaceTexture - Source render target.
1352
+ * @param {Texture} destinationTexture - Destination texture.
1353
+ * @param {object} originSrc - Source origin.
1354
+ * @param {number} originSrc.x - Source x origin.
1355
+ * @param {number} originSrc.y - Source y origin.
1356
+ * @param {object} size - Copy size.
1357
+ * @param {number} size.width - Copy width.
1358
+ * @param {number} size.height - Copy height.
1359
+ * @param {object} [originDest] - Destination origin.
1360
+ * @param {number} originDest.x - Destination x origin.
1361
+ * @param {number} originDest.y - Destination y origin.
1362
+ * @advanced
1363
+ */
1364
+ copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
1365
+ const sourceGpuTarget = this._renderTargetSystem.getGpuRenderTarget(sourceRenderSurfaceTexture);
1366
+ const sourceCanvas = sourceGpuTarget.canvas;
1367
+ const destSource = destinationTexture.source;
1368
+ const { context } = this._ensureCanvas(destSource);
1369
+ const dx = originDest?.x ?? 0;
1370
+ const dy = originDest?.y ?? 0;
1371
+ context.drawImage(
1372
+ sourceCanvas,
1373
+ originSrc.x,
1374
+ originSrc.y,
1375
+ size.width,
1376
+ size.height,
1377
+ dx,
1378
+ dy,
1379
+ size.width,
1380
+ size.height
1381
+ );
1382
+ destSource.update();
1383
+ return destinationTexture;
1384
+ }
1385
+ /**
1386
+ * Destroys a GPU render target (no-op for canvas).
1387
+ * @param _gpuRenderTarget - Target to destroy.
1388
+ * @advanced
1389
+ */
1390
+ destroyGpuRenderTarget(_gpuRenderTarget) {
1391
+ }
1392
+ _ensureCanvas(source) {
1393
+ let canvas = source.resource;
1394
+ if (!canvas || !CanvasSource.test(canvas)) {
1395
+ canvas = DOMAdapter.get().createCanvas(source.pixelWidth, source.pixelHeight);
1396
+ source.resource = canvas;
1397
+ }
1398
+ if (canvas.width !== source.pixelWidth || canvas.height !== source.pixelHeight) {
1399
+ canvas.width = source.pixelWidth;
1400
+ canvas.height = source.pixelHeight;
1401
+ }
1402
+ const context = canvas.getContext("2d");
1403
+ return { canvas, context };
1404
+ }
1405
+ }
1406
+ class CanvasRenderTargetSystem extends RenderTargetSystem {
1407
+ constructor(renderer) {
1408
+ super(renderer);
1409
+ this.adaptor = new CanvasRenderTargetAdaptor();
1410
+ this.adaptor.init(renderer, this);
1411
+ }
1412
+ }
1413
+ CanvasRenderTargetSystem.extension = {
1414
+ type: [ExtensionType.CanvasSystem],
1415
+ name: "renderTarget"
1416
+ };
1417
+ class CanvasTextureSystem {
1418
+ /**
1419
+ * @param renderer - The owning CanvasRenderer.
1420
+ */
1421
+ constructor(renderer) {
1422
+ }
1423
+ /** Initializes the system (no-op for canvas). */
1424
+ init() {
1425
+ }
1426
+ /**
1427
+ * Initializes a texture source (no-op for canvas).
1428
+ * @param _source - Texture source.
1429
+ */
1430
+ initSource(_source) {
1431
+ }
1432
+ /**
1433
+ * Creates a canvas containing the texture's frame.
1434
+ * @param texture - Texture to render.
1435
+ */
1436
+ generateCanvas(texture) {
1437
+ const canvas = DOMAdapter.get().createCanvas();
1438
+ const context = canvas.getContext("2d");
1439
+ const source = canvasUtils.getCanvasSource(texture);
1440
+ if (!source) {
1441
+ return canvas;
1442
+ }
1443
+ const frame = texture.frame;
1444
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
1445
+ const sx = frame.x * resolution;
1446
+ const sy = frame.y * resolution;
1447
+ const sw = frame.width * resolution;
1448
+ const sh = frame.height * resolution;
1449
+ canvas.width = Math.ceil(sw);
1450
+ canvas.height = Math.ceil(sh);
1451
+ context.drawImage(
1452
+ source,
1453
+ sx,
1454
+ sy,
1455
+ sw,
1456
+ sh,
1457
+ 0,
1458
+ 0,
1459
+ sw,
1460
+ sh
1461
+ );
1462
+ return canvas;
1463
+ }
1464
+ /**
1465
+ * Reads pixel data from a texture.
1466
+ * @param texture - Texture to read.
1467
+ */
1468
+ getPixels(texture) {
1469
+ const canvas = this.generateCanvas(texture);
1470
+ const context = canvas.getContext("2d", { willReadFrequently: true });
1471
+ const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
1472
+ return {
1473
+ pixels: imageData.data,
1474
+ width: canvas.width,
1475
+ height: canvas.height
1476
+ };
1477
+ }
1478
+ /** Destroys the system (no-op for canvas). */
1479
+ destroy() {
1480
+ }
1481
+ }
1482
+ CanvasTextureSystem.extension = {
1483
+ type: [
1484
+ ExtensionType.CanvasSystem
1485
+ ],
1486
+ name: "texture"
1487
+ };
1488
+ const DefaultCanvasSystems = [
1489
+ ...SharedSystems,
1490
+ CanvasContextSystem,
1491
+ CanvasLimitsSystem,
1492
+ CanvasTextureSystem,
1493
+ CanvasRenderTargetSystem
1494
+ ];
1495
+ const DefaultCanvasPipes = [
1496
+ BlendModePipe,
1497
+ BatcherPipe,
1498
+ SpritePipe,
1499
+ RenderGroupPipe,
1500
+ AlphaMaskPipe,
1501
+ CanvasStencilMaskPipe,
1502
+ CanvasColorMaskPipe,
1503
+ CustomRenderPipe
1504
+ ];
1505
+ const DefaultCanvasAdapters = [
1506
+ CanvasBatchAdaptor,
1507
+ CanvasGraphicsAdaptor
1508
+ ];
1509
+ const systems = [];
1510
+ const renderPipes = [];
1511
+ const renderPipeAdaptors = [];
1512
+ extensions.handleByNamedList(ExtensionType.CanvasSystem, systems);
1513
+ extensions.handleByNamedList(ExtensionType.CanvasPipes, renderPipes);
1514
+ extensions.handleByNamedList(ExtensionType.CanvasPipesAdaptor, renderPipeAdaptors);
1515
+ extensions.add(...DefaultCanvasSystems, ...DefaultCanvasPipes, ...DefaultCanvasAdapters);
1516
+ class CanvasRenderer extends AbstractRenderer {
1517
+ constructor() {
1518
+ const systemConfig = {
1519
+ name: "canvas",
1520
+ type: RendererType.CANVAS,
1521
+ systems,
1522
+ renderPipes,
1523
+ renderPipeAdaptors
1524
+ };
1525
+ super(systemConfig);
1526
+ }
1527
+ }
1528
+ export {
1529
+ CanvasRenderer
1530
+ };