apexify.js 4.9.26 → 4.9.28

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 (108) hide show
  1. package/README.md +437 -47
  2. package/dist/cjs/Canvas/ApexPainter.d.ts +122 -78
  3. package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -1
  4. package/dist/cjs/Canvas/ApexPainter.js +461 -352
  5. package/dist/cjs/Canvas/ApexPainter.js.map +1 -1
  6. package/dist/cjs/Canvas/utils/Background/bg.d.ts +23 -11
  7. package/dist/cjs/Canvas/utils/Background/bg.d.ts.map +1 -1
  8. package/dist/cjs/Canvas/utils/Background/bg.js +174 -107
  9. package/dist/cjs/Canvas/utils/Background/bg.js.map +1 -1
  10. package/dist/cjs/Canvas/utils/Custom/customLines.js +2 -2
  11. package/dist/cjs/Canvas/utils/Custom/customLines.js.map +1 -1
  12. package/dist/cjs/Canvas/utils/Image/imageFilters.d.ts +11 -0
  13. package/dist/cjs/Canvas/utils/Image/imageFilters.d.ts.map +1 -0
  14. package/dist/cjs/Canvas/utils/Image/imageFilters.js +307 -0
  15. package/dist/cjs/Canvas/utils/Image/imageFilters.js.map +1 -0
  16. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts +47 -112
  17. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
  18. package/dist/cjs/Canvas/utils/Image/imageProperties.js +229 -560
  19. package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -1
  20. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.d.ts +11 -0
  21. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.d.ts.map +1 -0
  22. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.js +351 -0
  23. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.js.map +1 -0
  24. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.d.ts +11 -0
  25. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.d.ts.map +1 -0
  26. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.js +215 -0
  27. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.js.map +1 -0
  28. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts +71 -0
  29. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -0
  30. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js +392 -0
  31. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -0
  32. package/dist/cjs/Canvas/utils/Shapes/shapes.d.ts +29 -0
  33. package/dist/cjs/Canvas/utils/Shapes/shapes.d.ts.map +1 -0
  34. package/dist/cjs/Canvas/utils/Shapes/shapes.js +334 -0
  35. package/dist/cjs/Canvas/utils/Shapes/shapes.js.map +1 -0
  36. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +127 -0
  37. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -0
  38. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +365 -0
  39. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -0
  40. package/dist/cjs/Canvas/utils/types.d.ts +227 -131
  41. package/dist/cjs/Canvas/utils/types.d.ts.map +1 -1
  42. package/dist/cjs/Canvas/utils/types.js +0 -1
  43. package/dist/cjs/Canvas/utils/types.js.map +1 -1
  44. package/dist/cjs/Canvas/utils/utils.d.ts +7 -4
  45. package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -1
  46. package/dist/cjs/Canvas/utils/utils.js +17 -7
  47. package/dist/cjs/Canvas/utils/utils.js.map +1 -1
  48. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  49. package/dist/esm/Canvas/ApexPainter.d.ts +122 -78
  50. package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -1
  51. package/dist/esm/Canvas/ApexPainter.js +461 -352
  52. package/dist/esm/Canvas/ApexPainter.js.map +1 -1
  53. package/dist/esm/Canvas/utils/Background/bg.d.ts +23 -11
  54. package/dist/esm/Canvas/utils/Background/bg.d.ts.map +1 -1
  55. package/dist/esm/Canvas/utils/Background/bg.js +174 -107
  56. package/dist/esm/Canvas/utils/Background/bg.js.map +1 -1
  57. package/dist/esm/Canvas/utils/Custom/customLines.js +2 -2
  58. package/dist/esm/Canvas/utils/Custom/customLines.js.map +1 -1
  59. package/dist/esm/Canvas/utils/Image/imageFilters.d.ts +11 -0
  60. package/dist/esm/Canvas/utils/Image/imageFilters.d.ts.map +1 -0
  61. package/dist/esm/Canvas/utils/Image/imageFilters.js +307 -0
  62. package/dist/esm/Canvas/utils/Image/imageFilters.js.map +1 -0
  63. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts +47 -112
  64. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
  65. package/dist/esm/Canvas/utils/Image/imageProperties.js +229 -560
  66. package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -1
  67. package/dist/esm/Canvas/utils/Image/professionalImageFilters.d.ts +11 -0
  68. package/dist/esm/Canvas/utils/Image/professionalImageFilters.d.ts.map +1 -0
  69. package/dist/esm/Canvas/utils/Image/professionalImageFilters.js +351 -0
  70. package/dist/esm/Canvas/utils/Image/professionalImageFilters.js.map +1 -0
  71. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.d.ts +11 -0
  72. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.d.ts.map +1 -0
  73. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.js +215 -0
  74. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.js.map +1 -0
  75. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts +71 -0
  76. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -0
  77. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js +392 -0
  78. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -0
  79. package/dist/esm/Canvas/utils/Shapes/shapes.d.ts +29 -0
  80. package/dist/esm/Canvas/utils/Shapes/shapes.d.ts.map +1 -0
  81. package/dist/esm/Canvas/utils/Shapes/shapes.js +334 -0
  82. package/dist/esm/Canvas/utils/Shapes/shapes.js.map +1 -0
  83. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +127 -0
  84. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -0
  85. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +365 -0
  86. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -0
  87. package/dist/esm/Canvas/utils/types.d.ts +227 -131
  88. package/dist/esm/Canvas/utils/types.d.ts.map +1 -1
  89. package/dist/esm/Canvas/utils/types.js +0 -1
  90. package/dist/esm/Canvas/utils/types.js.map +1 -1
  91. package/dist/esm/Canvas/utils/utils.d.ts +7 -4
  92. package/dist/esm/Canvas/utils/utils.d.ts.map +1 -1
  93. package/dist/esm/Canvas/utils/utils.js +17 -7
  94. package/dist/esm/Canvas/utils/utils.js.map +1 -1
  95. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  96. package/lib/Canvas/ApexPainter.ts +1325 -1218
  97. package/lib/Canvas/utils/Background/bg.ts +247 -173
  98. package/lib/Canvas/utils/Custom/customLines.ts +3 -3
  99. package/lib/Canvas/utils/Image/imageFilters.ts +356 -0
  100. package/lib/Canvas/utils/Image/imageProperties.ts +322 -775
  101. package/lib/Canvas/utils/Image/professionalImageFilters.ts +391 -0
  102. package/lib/Canvas/utils/Image/simpleProfessionalFilters.ts +229 -0
  103. package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +444 -0
  104. package/lib/Canvas/utils/Shapes/shapes.ts +528 -0
  105. package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +478 -0
  106. package/lib/Canvas/utils/types.ts +301 -117
  107. package/lib/Canvas/utils/utils.ts +85 -72
  108. package/package.json +106 -188
@@ -0,0 +1,444 @@
1
+ import { SKRSContext2D, Canvas } from '@napi-rs/canvas';
2
+ import { PatternOptions, GradientConfig } from '../types';
3
+ import { createGradientFill } from '../Image/imageProperties';
4
+ import { loadImage } from '@napi-rs/canvas';
5
+ import path from 'path';
6
+
7
+ /**
8
+ * Enhanced pattern renderer supporting all pattern types
9
+ */
10
+ export class EnhancedPatternRenderer {
11
+ /**
12
+ * Renders a pattern overlay on the canvas
13
+ * @param ctx - Canvas 2D context
14
+ * @param canvas - Canvas instance
15
+ * @param patternOptions - Pattern configuration
16
+ */
17
+ static async renderPattern(
18
+ ctx: SKRSContext2D,
19
+ canvas: Canvas,
20
+ patternOptions: PatternOptions
21
+ ): Promise<void> {
22
+ if (!patternOptions || !patternOptions.type) return;
23
+
24
+ ctx.save();
25
+
26
+ try {
27
+ // Set pattern opacity
28
+ const opacity = patternOptions.opacity !== undefined ? patternOptions.opacity : 0.3;
29
+ ctx.globalAlpha = opacity;
30
+
31
+ // Set blend mode
32
+ const blendMode = patternOptions.blendMode || 'overlay';
33
+ ctx.globalCompositeOperation = blendMode;
34
+
35
+ // Apply rotation if specified
36
+ if (patternOptions.rotation && patternOptions.rotation !== 0) {
37
+ const centerX = canvas.width / 2;
38
+ const centerY = canvas.height / 2;
39
+ ctx.translate(centerX, centerY);
40
+ ctx.rotate((patternOptions.rotation * Math.PI) / 180);
41
+ ctx.translate(-centerX, -centerY);
42
+ }
43
+
44
+ // Apply offset if specified
45
+ if (patternOptions.offsetX || patternOptions.offsetY) {
46
+ ctx.translate(patternOptions.offsetX || 0, patternOptions.offsetY || 0);
47
+ }
48
+
49
+ // Render based on pattern type
50
+ switch (patternOptions.type) {
51
+ case 'grid':
52
+ this.renderGridPattern(ctx, canvas, patternOptions);
53
+ break;
54
+ case 'dots':
55
+ this.renderDotsPattern(ctx, canvas, patternOptions);
56
+ break;
57
+ case 'diagonal':
58
+ this.renderDiagonalPattern(ctx, canvas, patternOptions);
59
+ break;
60
+ case 'stripes':
61
+ this.renderStripesPattern(ctx, canvas, patternOptions);
62
+ break;
63
+ case 'waves':
64
+ this.renderWavesPattern(ctx, canvas, patternOptions);
65
+ break;
66
+ case 'crosses':
67
+ this.renderCrossesPattern(ctx, canvas, patternOptions);
68
+ break;
69
+ case 'hexagons':
70
+ this.renderHexagonsPattern(ctx, canvas, patternOptions);
71
+ break;
72
+ case 'checkerboard':
73
+ this.renderCheckerboardPattern(ctx, canvas, patternOptions);
74
+ break;
75
+ case 'diamonds':
76
+ this.renderDiamondsPattern(ctx, canvas, patternOptions);
77
+ break;
78
+ case 'triangles':
79
+ this.renderTrianglesPattern(ctx, canvas, patternOptions);
80
+ break;
81
+ case 'stars':
82
+ this.renderStarsPattern(ctx, canvas, patternOptions);
83
+ break;
84
+ case 'polka':
85
+ this.renderPolkaPattern(ctx, canvas, patternOptions);
86
+ break;
87
+ case 'custom':
88
+ await this.renderCustomPattern(ctx, canvas, patternOptions);
89
+ break;
90
+ default:
91
+ console.warn(`Unknown pattern type: ${patternOptions.type}`);
92
+ }
93
+ } finally {
94
+ ctx.restore();
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Renders grid pattern
100
+ */
101
+ private static renderGridPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
102
+ const size = options.size || 20;
103
+ const spacing = options.spacing || 10;
104
+ const color = options.color || '#ffffff';
105
+
106
+ ctx.strokeStyle = color;
107
+ ctx.lineWidth = 1;
108
+
109
+ // Vertical lines
110
+ for (let x = 0; x <= canvas.width; x += size + spacing) {
111
+ ctx.beginPath();
112
+ ctx.moveTo(x, 0);
113
+ ctx.lineTo(x, canvas.height);
114
+ ctx.stroke();
115
+ }
116
+
117
+ // Horizontal lines
118
+ for (let y = 0; y <= canvas.height; y += size + spacing) {
119
+ ctx.beginPath();
120
+ ctx.moveTo(0, y);
121
+ ctx.lineTo(canvas.width, y);
122
+ ctx.stroke();
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Renders dots pattern
128
+ */
129
+ private static renderDotsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
130
+ const size = options.size || 20;
131
+ const spacing = options.spacing || 10;
132
+ const color = options.color || '#ffffff';
133
+
134
+ ctx.fillStyle = color;
135
+
136
+ for (let x = 0; x <= canvas.width; x += size + spacing) {
137
+ for (let y = 0; y <= canvas.height; y += size + spacing) {
138
+ ctx.beginPath();
139
+ ctx.arc(x, y, size / 4, 0, Math.PI * 2);
140
+ ctx.fill();
141
+ }
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Renders diagonal pattern
147
+ */
148
+ private static renderDiagonalPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
149
+ const size = options.size || 20;
150
+ const spacing = options.spacing || 10;
151
+ const color = options.color || '#ffffff';
152
+
153
+ ctx.strokeStyle = color;
154
+ ctx.lineWidth = 2;
155
+
156
+ const diagonalSpacing = size + spacing;
157
+
158
+ // Diagonal lines going up-right
159
+ for (let i = -canvas.height; i <= canvas.width; i += diagonalSpacing) {
160
+ ctx.beginPath();
161
+ ctx.moveTo(i, 0);
162
+ ctx.lineTo(i + canvas.height, canvas.height);
163
+ ctx.stroke();
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Renders stripes pattern
169
+ */
170
+ private static renderStripesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
171
+ const size = options.size || 20;
172
+ const spacing = options.spacing || 10;
173
+ const color = options.color || '#ffffff';
174
+
175
+ ctx.fillStyle = color;
176
+
177
+ for (let y = 0; y <= canvas.height; y += size + spacing) {
178
+ ctx.fillRect(0, y, canvas.width, size);
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Renders waves pattern
184
+ */
185
+ private static renderWavesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
186
+ const size = options.size || 20;
187
+ const spacing = options.spacing || 10;
188
+ const color = options.color || '#ffffff';
189
+
190
+ ctx.strokeStyle = color;
191
+ ctx.lineWidth = 2;
192
+
193
+ for (let y = 0; y <= canvas.height; y += size + spacing) {
194
+ ctx.beginPath();
195
+ ctx.moveTo(0, y);
196
+
197
+ for (let x = 0; x <= canvas.width; x += 10) {
198
+ const waveY = y + Math.sin(x * 0.1) * (size / 4);
199
+ ctx.lineTo(x, waveY);
200
+ }
201
+
202
+ ctx.stroke();
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Renders crosses pattern
208
+ */
209
+ private static renderCrossesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
210
+ const size = options.size || 20;
211
+ const spacing = options.spacing || 10;
212
+ const color = options.color || '#ffffff';
213
+
214
+ ctx.strokeStyle = color;
215
+ ctx.lineWidth = 2;
216
+
217
+ for (let x = 0; x <= canvas.width; x += size + spacing) {
218
+ for (let y = 0; y <= canvas.height; y += size + spacing) {
219
+ const crossSize = size / 2;
220
+
221
+ // Horizontal line
222
+ ctx.beginPath();
223
+ ctx.moveTo(x - crossSize, y);
224
+ ctx.lineTo(x + crossSize, y);
225
+ ctx.stroke();
226
+
227
+ // Vertical line
228
+ ctx.beginPath();
229
+ ctx.moveTo(x, y - crossSize);
230
+ ctx.lineTo(x, y + crossSize);
231
+ ctx.stroke();
232
+ }
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Renders hexagons pattern
238
+ */
239
+ private static renderHexagonsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
240
+ const size = options.size || 20;
241
+ const spacing = options.spacing || 10;
242
+ const color = options.color || '#ffffff';
243
+
244
+ ctx.strokeStyle = color;
245
+ ctx.lineWidth = 2;
246
+
247
+ const hexWidth = size;
248
+ const hexHeight = size * Math.sqrt(3) / 2;
249
+
250
+ for (let x = 0; x <= canvas.width + hexWidth; x += hexWidth + spacing) {
251
+ for (let y = 0; y <= canvas.height + hexHeight; y += hexHeight * 1.5 + spacing) {
252
+ this.drawHexagon(ctx, x, y, hexWidth / 2);
253
+ }
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Renders checkerboard pattern
259
+ */
260
+ private static renderCheckerboardPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
261
+ const size = options.size || 20;
262
+ const color = options.color || '#ffffff';
263
+ const secondaryColor = options.secondaryColor || 'transparent';
264
+
265
+ for (let x = 0; x <= canvas.width; x += size) {
266
+ for (let y = 0; y <= canvas.height; y += size) {
267
+ const isEven = ((x / size) + (y / size)) % 2 === 0;
268
+ ctx.fillStyle = isEven ? color : secondaryColor;
269
+ ctx.fillRect(x, y, size, size);
270
+ }
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Renders diamonds pattern
276
+ */
277
+ private static renderDiamondsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
278
+ const size = options.size || 20;
279
+ const spacing = options.spacing || 10;
280
+ const color = options.color || '#ffffff';
281
+
282
+ ctx.strokeStyle = color;
283
+ ctx.lineWidth = 2;
284
+
285
+ for (let x = 0; x <= canvas.width + size; x += size + spacing) {
286
+ for (let y = 0; y <= canvas.height + size; y += size + spacing) {
287
+ this.drawDiamond(ctx, x, y, size / 2);
288
+ }
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Renders triangles pattern
294
+ */
295
+ private static renderTrianglesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
296
+ const size = options.size || 20;
297
+ const spacing = options.spacing || 10;
298
+ const color = options.color || '#ffffff';
299
+
300
+ ctx.strokeStyle = color;
301
+ ctx.lineWidth = 2;
302
+
303
+ for (let x = 0; x <= canvas.width + size; x += size + spacing) {
304
+ for (let y = 0; y <= canvas.height + size; y += size + spacing) {
305
+ this.drawTriangle(ctx, x, y, size / 2);
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Renders stars pattern
312
+ */
313
+ private static renderStarsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
314
+ const size = options.size || 20;
315
+ const spacing = options.spacing || 10;
316
+ const color = options.color || '#ffffff';
317
+
318
+ ctx.fillStyle = color;
319
+
320
+ for (let x = 0; x <= canvas.width + size; x += size + spacing) {
321
+ for (let y = 0; y <= canvas.height + size; y += size + spacing) {
322
+ this.drawStar(ctx, x, y, size / 4);
323
+ }
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Renders polka pattern (larger dots)
329
+ */
330
+ private static renderPolkaPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
331
+ const size = options.size || 20;
332
+ const spacing = options.spacing || 10;
333
+ const color = options.color || '#ffffff';
334
+
335
+ ctx.fillStyle = color;
336
+
337
+ for (let x = 0; x <= canvas.width; x += size + spacing) {
338
+ for (let y = 0; y <= canvas.height; y += size + spacing) {
339
+ ctx.beginPath();
340
+ ctx.arc(x, y, size / 2, 0, Math.PI * 2);
341
+ ctx.fill();
342
+ }
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Renders custom pattern from image
348
+ */
349
+ private static async renderCustomPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): Promise<void> {
350
+ if (!options.customPatternImage) return;
351
+
352
+ try {
353
+ let imagePath = options.customPatternImage;
354
+ if (!/^https?:\/\//i.test(imagePath)) {
355
+ imagePath = path.join(process.cwd(), imagePath);
356
+ }
357
+
358
+ const image = await loadImage(imagePath);
359
+ const scale = options.scale || 1;
360
+ const repeat = options.repeat || 'repeat';
361
+
362
+ const scaledWidth = image.width * scale;
363
+ const scaledHeight = image.height * scale;
364
+
365
+ switch (repeat) {
366
+ case 'repeat':
367
+ for (let x = 0; x <= canvas.width; x += scaledWidth) {
368
+ for (let y = 0; y <= canvas.height; y += scaledHeight) {
369
+ ctx.drawImage(image, x, y, scaledWidth, scaledHeight);
370
+ }
371
+ }
372
+ break;
373
+ case 'repeat-x':
374
+ for (let x = 0; x <= canvas.width; x += scaledWidth) {
375
+ ctx.drawImage(image, x, 0, scaledWidth, scaledHeight);
376
+ }
377
+ break;
378
+ case 'repeat-y':
379
+ for (let y = 0; y <= canvas.height; y += scaledHeight) {
380
+ ctx.drawImage(image, 0, y, scaledWidth, scaledHeight);
381
+ }
382
+ break;
383
+ case 'no-repeat':
384
+ ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight);
385
+ break;
386
+ }
387
+ } catch (error) {
388
+ console.warn(`Failed to load custom pattern image: ${options.customPatternImage}`, error);
389
+ }
390
+ }
391
+
392
+ // === HELPER DRAWING FUNCTIONS ===
393
+
394
+ private static drawHexagon(ctx: SKRSContext2D, x: number, y: number, radius: number): void {
395
+ ctx.beginPath();
396
+ for (let i = 0; i < 6; i++) {
397
+ const angle = (i * Math.PI) / 3;
398
+ const px = x + radius * Math.cos(angle);
399
+ const py = y + radius * Math.sin(angle);
400
+ if (i === 0) {
401
+ ctx.moveTo(px, py);
402
+ } else {
403
+ ctx.lineTo(px, py);
404
+ }
405
+ }
406
+ ctx.closePath();
407
+ ctx.stroke();
408
+ }
409
+
410
+ private static drawDiamond(ctx: SKRSContext2D, x: number, y: number, size: number): void {
411
+ ctx.beginPath();
412
+ ctx.moveTo(x, y - size);
413
+ ctx.lineTo(x + size, y);
414
+ ctx.lineTo(x, y + size);
415
+ ctx.lineTo(x - size, y);
416
+ ctx.closePath();
417
+ ctx.stroke();
418
+ }
419
+
420
+ private static drawTriangle(ctx: SKRSContext2D, x: number, y: number, size: number): void {
421
+ ctx.beginPath();
422
+ ctx.moveTo(x, y - size);
423
+ ctx.lineTo(x + size, y + size);
424
+ ctx.lineTo(x - size, y + size);
425
+ ctx.closePath();
426
+ ctx.stroke();
427
+ }
428
+
429
+ private static drawStar(ctx: SKRSContext2D, x: number, y: number, radius: number): void {
430
+ ctx.beginPath();
431
+ for (let i = 0; i < 5; i++) {
432
+ const angle = (i * 4 * Math.PI) / 5;
433
+ const px = x + radius * Math.cos(angle);
434
+ const py = y + radius * Math.sin(angle);
435
+ if (i === 0) {
436
+ ctx.moveTo(px, py);
437
+ } else {
438
+ ctx.lineTo(px, py);
439
+ }
440
+ }
441
+ ctx.closePath();
442
+ ctx.fill();
443
+ }
444
+ }