apexify.js 4.9.28 → 5.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.
- package/README.md +727 -456
- package/dist/cjs/Canvas/ApexPainter.d.ts +96 -145
- package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -1
- package/dist/cjs/Canvas/ApexPainter.js +1416 -420
- package/dist/cjs/Canvas/ApexPainter.js.map +1 -1
- package/dist/cjs/Canvas/utils/Charts/charts.d.ts +7 -2
- package/dist/cjs/Canvas/utils/Charts/charts.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Charts/charts.js +3 -1
- package/dist/cjs/Canvas/utils/Charts/charts.js.map +1 -1
- package/dist/cjs/Canvas/utils/Custom/advancedLines.d.ts +75 -0
- package/dist/cjs/Canvas/utils/Custom/advancedLines.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Custom/advancedLines.js +263 -0
- package/dist/cjs/Canvas/utils/Custom/advancedLines.js.map +1 -0
- package/dist/cjs/Canvas/utils/Custom/customLines.d.ts +2 -1
- package/dist/cjs/Canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Custom/customLines.js +73 -6
- package/dist/cjs/Canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/cjs/Canvas/utils/General/batchOperations.d.ts +17 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.js +88 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.js.map +1 -0
- package/dist/cjs/Canvas/utils/General/general functions.d.ts +25 -3
- package/dist/cjs/Canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/General/general functions.js +37 -9
- package/dist/cjs/Canvas/utils/General/general functions.js.map +1 -1
- package/dist/cjs/Canvas/utils/General/imageCompression.d.ts +19 -0
- package/dist/cjs/Canvas/utils/General/imageCompression.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/General/imageCompression.js +262 -0
- package/dist/cjs/Canvas/utils/General/imageCompression.js.map +1 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.d.ts +20 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.js +227 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.js.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.d.ts +37 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.js +128 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.js.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts +67 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.js +276 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.js.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Image/imageProperties.js +181 -2
- package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js +16 -8
- package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +33 -0
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +237 -32
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.d.ts +17 -0
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.js +233 -0
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.js.map +1 -0
- package/dist/cjs/Canvas/utils/types.d.ts +171 -10
- package/dist/cjs/Canvas/utils/types.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/types.js.map +1 -1
- package/dist/cjs/Canvas/utils/utils.d.ts +9 -2
- package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/utils.js +32 -1
- package/dist/cjs/Canvas/utils/utils.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/Canvas/ApexPainter.d.ts +96 -145
- package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -1
- package/dist/esm/Canvas/ApexPainter.js +1416 -420
- package/dist/esm/Canvas/ApexPainter.js.map +1 -1
- package/dist/esm/Canvas/utils/Charts/charts.d.ts +7 -2
- package/dist/esm/Canvas/utils/Charts/charts.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Charts/charts.js +3 -1
- package/dist/esm/Canvas/utils/Charts/charts.js.map +1 -1
- package/dist/esm/Canvas/utils/Custom/advancedLines.d.ts +75 -0
- package/dist/esm/Canvas/utils/Custom/advancedLines.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Custom/advancedLines.js +263 -0
- package/dist/esm/Canvas/utils/Custom/advancedLines.js.map +1 -0
- package/dist/esm/Canvas/utils/Custom/customLines.d.ts +2 -1
- package/dist/esm/Canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Custom/customLines.js +73 -6
- package/dist/esm/Canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/esm/Canvas/utils/General/batchOperations.d.ts +17 -0
- package/dist/esm/Canvas/utils/General/batchOperations.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/General/batchOperations.js +88 -0
- package/dist/esm/Canvas/utils/General/batchOperations.js.map +1 -0
- package/dist/esm/Canvas/utils/General/general functions.d.ts +25 -3
- package/dist/esm/Canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/General/general functions.js +37 -9
- package/dist/esm/Canvas/utils/General/general functions.js.map +1 -1
- package/dist/esm/Canvas/utils/General/imageCompression.d.ts +19 -0
- package/dist/esm/Canvas/utils/General/imageCompression.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/General/imageCompression.js +262 -0
- package/dist/esm/Canvas/utils/General/imageCompression.js.map +1 -0
- package/dist/esm/Canvas/utils/General/imageStitching.d.ts +20 -0
- package/dist/esm/Canvas/utils/General/imageStitching.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/General/imageStitching.js +227 -0
- package/dist/esm/Canvas/utils/General/imageStitching.js.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.d.ts +37 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.js +128 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.js.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.d.ts +67 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.js +276 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.js.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Image/imageProperties.js +181 -2
- package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js +16 -8
- package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -1
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +33 -0
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +237 -32
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.d.ts +17 -0
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.js +233 -0
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.js.map +1 -0
- package/dist/esm/Canvas/utils/types.d.ts +171 -10
- package/dist/esm/Canvas/utils/types.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/types.js.map +1 -1
- package/dist/esm/Canvas/utils/utils.d.ts +9 -2
- package/dist/esm/Canvas/utils/utils.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/utils.js +32 -1
- package/dist/esm/Canvas/utils/utils.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/Canvas/ApexPainter.ts +1309 -267
- package/lib/Canvas/utils/Charts/charts.ts +16 -7
- package/lib/Canvas/utils/Custom/advancedLines.ts +335 -0
- package/lib/Canvas/utils/Custom/customLines.ts +84 -9
- package/lib/Canvas/utils/General/batchOperations.ts +103 -0
- package/lib/Canvas/utils/General/general functions.ts +85 -41
- package/lib/Canvas/utils/General/imageCompression.ts +316 -0
- package/lib/Canvas/utils/General/imageStitching.ts +252 -0
- package/lib/Canvas/utils/Image/imageEffects.ts +175 -0
- package/lib/Canvas/utils/Image/imageMasking.ts +335 -0
- package/lib/Canvas/utils/Image/imageProperties.ts +207 -2
- package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +455 -444
- package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +274 -36
- package/lib/Canvas/utils/Texts/textPathRenderer.ts +320 -0
- package/lib/Canvas/utils/types.ts +173 -10
- package/lib/Canvas/utils/utils.ts +49 -2
- package/package.json +69 -34
|
@@ -1,444 +1,455 @@
|
|
|
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
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
ctx.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
ctx.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
ctx.
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
ctx.
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
ctx.
|
|
423
|
-
ctx.
|
|
424
|
-
ctx.lineTo(x
|
|
425
|
-
ctx.
|
|
426
|
-
ctx.
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
ctx.
|
|
442
|
-
|
|
443
|
-
|
|
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
|
+
// Calculate proper grid spacing
|
|
110
|
+
const gridSpacing = size + spacing;
|
|
111
|
+
|
|
112
|
+
// Vertical lines - start from 0 and go to canvas width
|
|
113
|
+
for (let x = 0; x <= canvas.width; x += gridSpacing) {
|
|
114
|
+
ctx.beginPath();
|
|
115
|
+
ctx.moveTo(x, 0);
|
|
116
|
+
ctx.lineTo(x, canvas.height);
|
|
117
|
+
ctx.stroke();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Horizontal lines - start from 0 and go to canvas height
|
|
121
|
+
for (let y = 0; y <= canvas.height; y += gridSpacing) {
|
|
122
|
+
ctx.beginPath();
|
|
123
|
+
ctx.moveTo(0, y);
|
|
124
|
+
ctx.lineTo(canvas.width, y);
|
|
125
|
+
ctx.stroke();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Renders dots pattern
|
|
131
|
+
*/
|
|
132
|
+
private static renderDotsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
133
|
+
const size = options.size || 20;
|
|
134
|
+
const spacing = options.spacing || 10;
|
|
135
|
+
const color = options.color || '#ffffff';
|
|
136
|
+
|
|
137
|
+
ctx.fillStyle = color;
|
|
138
|
+
|
|
139
|
+
// Calculate proper dot spacing
|
|
140
|
+
const dotSpacing = size + spacing;
|
|
141
|
+
const dotRadius = size / 4;
|
|
142
|
+
|
|
143
|
+
// Start from spacing offset to center first dot, then continue with full spacing
|
|
144
|
+
for (let x = spacing; x <= canvas.width; x += dotSpacing) {
|
|
145
|
+
for (let y = spacing; y <= canvas.height; y += dotSpacing) {
|
|
146
|
+
ctx.beginPath();
|
|
147
|
+
ctx.arc(x, y, dotRadius, 0, Math.PI * 2);
|
|
148
|
+
ctx.fill();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Renders diagonal pattern
|
|
155
|
+
*/
|
|
156
|
+
private static renderDiagonalPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
157
|
+
const size = options.size || 20;
|
|
158
|
+
const spacing = options.spacing || 10;
|
|
159
|
+
const color = options.color || '#ffffff';
|
|
160
|
+
|
|
161
|
+
ctx.strokeStyle = color;
|
|
162
|
+
ctx.lineWidth = 2;
|
|
163
|
+
|
|
164
|
+
const diagonalSpacing = size + spacing;
|
|
165
|
+
|
|
166
|
+
// Diagonal lines going up-right
|
|
167
|
+
for (let i = -canvas.height; i <= canvas.width; i += diagonalSpacing) {
|
|
168
|
+
ctx.beginPath();
|
|
169
|
+
ctx.moveTo(i, 0);
|
|
170
|
+
ctx.lineTo(i + canvas.height, canvas.height);
|
|
171
|
+
ctx.stroke();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Renders stripes pattern
|
|
177
|
+
*/
|
|
178
|
+
private static renderStripesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
179
|
+
const size = options.size || 20;
|
|
180
|
+
const spacing = options.spacing || 10;
|
|
181
|
+
const color = options.color || '#ffffff';
|
|
182
|
+
|
|
183
|
+
ctx.fillStyle = color;
|
|
184
|
+
|
|
185
|
+
// Calculate proper stripe spacing
|
|
186
|
+
const stripeSpacing = size + spacing;
|
|
187
|
+
|
|
188
|
+
for (let y = 0; y <= canvas.height; y += stripeSpacing) {
|
|
189
|
+
ctx.fillRect(0, y, canvas.width, size);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Renders waves pattern
|
|
195
|
+
*/
|
|
196
|
+
private static renderWavesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
197
|
+
const size = options.size || 20;
|
|
198
|
+
const spacing = options.spacing || 10;
|
|
199
|
+
const color = options.color || '#ffffff';
|
|
200
|
+
|
|
201
|
+
ctx.strokeStyle = color;
|
|
202
|
+
ctx.lineWidth = 2;
|
|
203
|
+
|
|
204
|
+
for (let y = 0; y <= canvas.height; y += size + spacing) {
|
|
205
|
+
ctx.beginPath();
|
|
206
|
+
ctx.moveTo(0, y);
|
|
207
|
+
|
|
208
|
+
for (let x = 0; x <= canvas.width; x += 10) {
|
|
209
|
+
const waveY = y + Math.sin(x * 0.1) * (size / 4);
|
|
210
|
+
ctx.lineTo(x, waveY);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
ctx.stroke();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Renders crosses pattern
|
|
219
|
+
*/
|
|
220
|
+
private static renderCrossesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
221
|
+
const size = options.size || 20;
|
|
222
|
+
const spacing = options.spacing || 10;
|
|
223
|
+
const color = options.color || '#ffffff';
|
|
224
|
+
|
|
225
|
+
ctx.strokeStyle = color;
|
|
226
|
+
ctx.lineWidth = 2;
|
|
227
|
+
|
|
228
|
+
for (let x = 0; x <= canvas.width; x += size + spacing) {
|
|
229
|
+
for (let y = 0; y <= canvas.height; y += size + spacing) {
|
|
230
|
+
const crossSize = size / 2;
|
|
231
|
+
|
|
232
|
+
// Horizontal line
|
|
233
|
+
ctx.beginPath();
|
|
234
|
+
ctx.moveTo(x - crossSize, y);
|
|
235
|
+
ctx.lineTo(x + crossSize, y);
|
|
236
|
+
ctx.stroke();
|
|
237
|
+
|
|
238
|
+
// Vertical line
|
|
239
|
+
ctx.beginPath();
|
|
240
|
+
ctx.moveTo(x, y - crossSize);
|
|
241
|
+
ctx.lineTo(x, y + crossSize);
|
|
242
|
+
ctx.stroke();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Renders hexagons pattern
|
|
249
|
+
*/
|
|
250
|
+
private static renderHexagonsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
251
|
+
const size = options.size || 20;
|
|
252
|
+
const spacing = options.spacing || 10;
|
|
253
|
+
const color = options.color || '#ffffff';
|
|
254
|
+
|
|
255
|
+
ctx.strokeStyle = color;
|
|
256
|
+
ctx.lineWidth = 2;
|
|
257
|
+
|
|
258
|
+
const hexWidth = size;
|
|
259
|
+
const hexHeight = size * Math.sqrt(3) / 2;
|
|
260
|
+
|
|
261
|
+
for (let x = 0; x <= canvas.width + hexWidth; x += hexWidth + spacing) {
|
|
262
|
+
for (let y = 0; y <= canvas.height + hexHeight; y += hexHeight * 1.5 + spacing) {
|
|
263
|
+
this.drawHexagon(ctx, x, y, hexWidth / 2);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Renders checkerboard pattern
|
|
270
|
+
*/
|
|
271
|
+
private static renderCheckerboardPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
272
|
+
const size = options.size || 20;
|
|
273
|
+
const color = options.color || '#ffffff';
|
|
274
|
+
const secondaryColor = options.secondaryColor || 'transparent';
|
|
275
|
+
|
|
276
|
+
for (let x = 0; x <= canvas.width; x += size) {
|
|
277
|
+
for (let y = 0; y <= canvas.height; y += size) {
|
|
278
|
+
const isEven = ((x / size) + (y / size)) % 2 === 0;
|
|
279
|
+
ctx.fillStyle = isEven ? color : secondaryColor;
|
|
280
|
+
ctx.fillRect(x, y, size, size);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Renders diamonds pattern
|
|
287
|
+
*/
|
|
288
|
+
private static renderDiamondsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
289
|
+
const size = options.size || 20;
|
|
290
|
+
const spacing = options.spacing || 10;
|
|
291
|
+
const color = options.color || '#ffffff';
|
|
292
|
+
|
|
293
|
+
ctx.strokeStyle = color;
|
|
294
|
+
ctx.lineWidth = 2;
|
|
295
|
+
|
|
296
|
+
for (let x = 0; x <= canvas.width + size; x += size + spacing) {
|
|
297
|
+
for (let y = 0; y <= canvas.height + size; y += size + spacing) {
|
|
298
|
+
this.drawDiamond(ctx, x, y, size / 2);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Renders triangles pattern
|
|
305
|
+
*/
|
|
306
|
+
private static renderTrianglesPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
307
|
+
const size = options.size || 20;
|
|
308
|
+
const spacing = options.spacing || 10;
|
|
309
|
+
const color = options.color || '#ffffff';
|
|
310
|
+
|
|
311
|
+
ctx.strokeStyle = color;
|
|
312
|
+
ctx.lineWidth = 2;
|
|
313
|
+
|
|
314
|
+
for (let x = 0; x <= canvas.width + size; x += size + spacing) {
|
|
315
|
+
for (let y = 0; y <= canvas.height + size; y += size + spacing) {
|
|
316
|
+
this.drawTriangle(ctx, x, y, size / 2);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Renders stars pattern
|
|
323
|
+
*/
|
|
324
|
+
private static renderStarsPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
325
|
+
const size = options.size || 20;
|
|
326
|
+
const spacing = options.spacing || 10;
|
|
327
|
+
const color = options.color || '#ffffff';
|
|
328
|
+
|
|
329
|
+
ctx.fillStyle = color;
|
|
330
|
+
|
|
331
|
+
for (let x = 0; x <= canvas.width + size; x += size + spacing) {
|
|
332
|
+
for (let y = 0; y <= canvas.height + size; y += size + spacing) {
|
|
333
|
+
this.drawStar(ctx, x, y, size / 4);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Renders polka pattern (larger dots)
|
|
340
|
+
*/
|
|
341
|
+
private static renderPolkaPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): void {
|
|
342
|
+
const size = options.size || 20;
|
|
343
|
+
const spacing = options.spacing || 10;
|
|
344
|
+
const color = options.color || '#ffffff';
|
|
345
|
+
|
|
346
|
+
ctx.fillStyle = color;
|
|
347
|
+
|
|
348
|
+
for (let x = 0; x <= canvas.width; x += size + spacing) {
|
|
349
|
+
for (let y = 0; y <= canvas.height; y += size + spacing) {
|
|
350
|
+
ctx.beginPath();
|
|
351
|
+
ctx.arc(x, y, size / 2, 0, Math.PI * 2);
|
|
352
|
+
ctx.fill();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Renders custom pattern from image
|
|
359
|
+
*/
|
|
360
|
+
private static async renderCustomPattern(ctx: SKRSContext2D, canvas: Canvas, options: PatternOptions): Promise<void> {
|
|
361
|
+
if (!options.customPatternImage) return;
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
let imagePath = options.customPatternImage;
|
|
365
|
+
if (!/^https?:\/\//i.test(imagePath)) {
|
|
366
|
+
imagePath = path.join(process.cwd(), imagePath);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const image = await loadImage(imagePath);
|
|
370
|
+
const scale = options.scale || 1;
|
|
371
|
+
const repeat = options.repeat || 'repeat';
|
|
372
|
+
|
|
373
|
+
const scaledWidth = image.width * scale;
|
|
374
|
+
const scaledHeight = image.height * scale;
|
|
375
|
+
|
|
376
|
+
switch (repeat) {
|
|
377
|
+
case 'repeat':
|
|
378
|
+
for (let x = 0; x <= canvas.width; x += scaledWidth) {
|
|
379
|
+
for (let y = 0; y <= canvas.height; y += scaledHeight) {
|
|
380
|
+
ctx.drawImage(image, x, y, scaledWidth, scaledHeight);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
case 'repeat-x':
|
|
385
|
+
for (let x = 0; x <= canvas.width; x += scaledWidth) {
|
|
386
|
+
ctx.drawImage(image, x, 0, scaledWidth, scaledHeight);
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
case 'repeat-y':
|
|
390
|
+
for (let y = 0; y <= canvas.height; y += scaledHeight) {
|
|
391
|
+
ctx.drawImage(image, 0, y, scaledWidth, scaledHeight);
|
|
392
|
+
}
|
|
393
|
+
break;
|
|
394
|
+
case 'no-repeat':
|
|
395
|
+
ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight);
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
} catch (error) {
|
|
399
|
+
console.warn(`Failed to load custom pattern image: ${options.customPatternImage}`, error);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// === HELPER DRAWING FUNCTIONS ===
|
|
404
|
+
|
|
405
|
+
private static drawHexagon(ctx: SKRSContext2D, x: number, y: number, radius: number): void {
|
|
406
|
+
ctx.beginPath();
|
|
407
|
+
for (let i = 0; i < 6; i++) {
|
|
408
|
+
const angle = (i * Math.PI) / 3;
|
|
409
|
+
const px = x + radius * Math.cos(angle);
|
|
410
|
+
const py = y + radius * Math.sin(angle);
|
|
411
|
+
if (i === 0) {
|
|
412
|
+
ctx.moveTo(px, py);
|
|
413
|
+
} else {
|
|
414
|
+
ctx.lineTo(px, py);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
ctx.closePath();
|
|
418
|
+
ctx.stroke();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private static drawDiamond(ctx: SKRSContext2D, x: number, y: number, size: number): void {
|
|
422
|
+
ctx.beginPath();
|
|
423
|
+
ctx.moveTo(x, y - size);
|
|
424
|
+
ctx.lineTo(x + size, y);
|
|
425
|
+
ctx.lineTo(x, y + size);
|
|
426
|
+
ctx.lineTo(x - size, y);
|
|
427
|
+
ctx.closePath();
|
|
428
|
+
ctx.stroke();
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
private static drawTriangle(ctx: SKRSContext2D, x: number, y: number, size: number): void {
|
|
432
|
+
ctx.beginPath();
|
|
433
|
+
ctx.moveTo(x, y - size);
|
|
434
|
+
ctx.lineTo(x + size, y + size);
|
|
435
|
+
ctx.lineTo(x - size, y + size);
|
|
436
|
+
ctx.closePath();
|
|
437
|
+
ctx.stroke();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
private static drawStar(ctx: SKRSContext2D, x: number, y: number, radius: number): void {
|
|
441
|
+
ctx.beginPath();
|
|
442
|
+
for (let i = 0; i < 5; i++) {
|
|
443
|
+
const angle = (i * 4 * Math.PI) / 5;
|
|
444
|
+
const px = x + radius * Math.cos(angle);
|
|
445
|
+
const py = y + radius * Math.sin(angle);
|
|
446
|
+
if (i === 0) {
|
|
447
|
+
ctx.moveTo(px, py);
|
|
448
|
+
} else {
|
|
449
|
+
ctx.lineTo(px, py);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
ctx.closePath();
|
|
453
|
+
ctx.fill();
|
|
454
|
+
}
|
|
455
|
+
}
|