@nmmty/lazycanvas 0.5.2 → 0.6.0-dev.1a1f37

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 (33) hide show
  1. package/dist/structures/components/ClearLayer.d.ts +5 -1
  2. package/dist/structures/components/Group.d.ts +15 -1
  3. package/dist/structures/components/Group.js +19 -0
  4. package/dist/structures/components/ImageLayer.d.ts +8 -4
  5. package/dist/structures/components/ImageLayer.js +16 -9
  6. package/dist/structures/components/MorphLayer.d.ts +8 -4
  7. package/dist/structures/components/MorphLayer.js +16 -9
  8. package/dist/structures/managers/RenderManager.js +2 -23
  9. package/dist/types/types.d.ts +48 -20
  10. package/dist/utils/utils.js +53 -84
  11. package/package.json +3 -2
  12. package/dist/structures/helpers/readers/SVGReader.d.ts +0 -20
  13. package/dist/structures/helpers/readers/SVGReader.js +0 -577
  14. package/dist/structures/helpers/readers/YAMLReader.d.ts +0 -0
  15. package/dist/structures/helpers/readers/YAMLReader.js +0 -1
  16. package/dist/types/LazyCanvas.d.ts +0 -18
  17. package/dist/types/components/BaseLayer.d.ts +0 -49
  18. package/dist/types/components/BezierLayer.d.ts +0 -11
  19. package/dist/types/components/ClearLayer.d.ts +0 -19
  20. package/dist/types/components/Group.d.ts +0 -8
  21. package/dist/types/components/ImageLayer.d.ts +0 -15
  22. package/dist/types/components/LineLayer.d.ts +0 -12
  23. package/dist/types/components/MorphLayer.d.ts +0 -14
  24. package/dist/types/components/QuadraticLayer.d.ts +0 -11
  25. package/dist/types/components/TextLayer.d.ts +0 -28
  26. package/dist/types/helpers/Font.d.ts +0 -12
  27. package/dist/types/helpers/Gradient.d.ts +0 -19
  28. package/dist/types/helpers/Link.d.ts +0 -7
  29. package/dist/types/helpers/Pattern.d.ts +0 -7
  30. package/dist/types/managers/AnimationManager.d.ts +0 -14
  31. package/dist/types/managers/FontsManager.d.ts +0 -6
  32. package/dist/types/managers/LayersManager.d.ts +0 -7
  33. package/dist/types/managers/RenderManager.d.ts +0 -6
@@ -1,20 +0,0 @@
1
- export declare class SVGReader {
2
- private static parseSVG;
3
- private static createImageLayer;
4
- private static createEllipseImageLayer;
5
- private static createRectLayer;
6
- private static createEllipseLayer;
7
- private static createCircleLayer;
8
- private static createLineLayer;
9
- private static createGradient;
10
- private static createPattern;
11
- private static createPath2DLayer;
12
- private static createClipPathLayer;
13
- private static createGroupLayer;
14
- private static applyTransform;
15
- private static findElementById;
16
- private static extractIdFromUrl;
17
- private fillStyle;
18
- private static handleUseElement;
19
- static readSVG(svg: string): Promise<any>;
20
- }
@@ -1,577 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SVGReader = void 0;
4
- const svgson_1 = require("svgson");
5
- const fs_1 = require("fs");
6
- const index_1 = require("../../../index");
7
- class SVGReader {
8
- static async parseSVG(svg) {
9
- let loadedSVG = await fs_1.promises.readFile(svg);
10
- return (0, svgson_1.parse)(loadedSVG.toString());
11
- }
12
- static async createImageLayer(svg) {
13
- const imageLayer = new index_1.ImageLayer();
14
- const src = svg.attributes['xlink:href'] || svg.attributes.href;
15
- if (svg.attributes.id)
16
- imageLayer.id = svg.attributes.id;
17
- if (svg.attributes['fill-opacity'])
18
- imageLayer.props.opacity = Number(svg.attributes['fill-opacity']);
19
- if (src.startsWith('data:image')) {
20
- const base64Data = src.replace(/^data:image\/\w+;base64,/, "");
21
- const buffer = Buffer.from(base64Data, 'base64');
22
- imageLayer.props.src = buffer;
23
- }
24
- else {
25
- imageLayer.props.src = src;
26
- }
27
- imageLayer.props.x = Number(svg.attributes.x) || 0;
28
- imageLayer.props.y = Number(svg.attributes.y) || 0;
29
- imageLayer.props.centring = 'start-top';
30
- imageLayer.props.size.width = Number(svg.attributes.width);
31
- imageLayer.props.size.height = Number(svg.attributes.height);
32
- if (svg.attributes.transform) {
33
- SVGReader.applyTransform(svg.attributes.transform, imageLayer);
34
- }
35
- return imageLayer;
36
- }
37
- static async createEllipseImageLayer(svg, path) {
38
- const ellipseImageLayer = new index_1.ImageLayer();
39
- const src = svg.attributes['xlink:href'] || svg.attributes.href;
40
- ellipseImageLayer.data.id = svg.attributes.id;
41
- if (svg.attributes['fill-opacity'])
42
- ellipseImageLayer.data.alpha = Number(svg.attributes['fill-opacity']);
43
- if (src.startsWith('data:image')) {
44
- const base64Data = src.replace(/^data:image\/\w+;base64,/, "");
45
- const buffer = Buffer.from(base64Data, 'base64');
46
- ellipseImageLayer.data.image = buffer;
47
- }
48
- else {
49
- ellipseImageLayer.data.image = src;
50
- }
51
- ellipseImageLayer.data.x = Number(svg.attributes.x) || 0;
52
- ellipseImageLayer.data.y = Number(svg.attributes.y) || 0;
53
- ellipseImageLayer.data.centering = 'legacy';
54
- ellipseImageLayer.data.width = Number(svg.attributes.width);
55
- ellipseImageLayer.data.height = Number(svg.attributes.height);
56
- ellipseImageLayer.data.path = path;
57
- if (svg.attributes.transform) {
58
- SVGReader.applyTransform(svg.attributes.transform, ellipseImageLayer);
59
- }
60
- ellipseImageLayer.data.fromSVG = true;
61
- return ellipseImageLayer;
62
- }
63
- static async createRectLayer(svg, svgObject) {
64
- let rectLayer = new index_1.MorphLayer();
65
- if (svg.attributes.rx || svg.attributes.ry) {
66
- rectLayer.props.size.radius = Math.min(Number(svg.attributes.rx) || 0, Number(svg.attributes.ry) || 0);
67
- }
68
- if (svg.attributes.id)
69
- rectLayer.id = svg.attributes.id;
70
- if (svg.attributes.fill && svg.attributes.fill !== 'none') {
71
- rectLayer.props.fillStyle = await this.fillStyle(svg, svgObject);
72
- }
73
- else {
74
- rectLayer.props.fillStyle = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
75
- }
76
- rectLayer.props.filled = svg.attributes.fill !== 'none';
77
- if (svg.attributes['fill-opacity'])
78
- rectLayer.props.opacity = Number(svg.attributes['fill-opacity']);
79
- rectLayer.props.x = Number(svg.attributes.x) || 0;
80
- rectLayer.props.y = Number(svg.attributes.y) || 0;
81
- rectLayer.props.centring = 'start-top';
82
- rectLayer.props.size.width = Number(svg.attributes.width);
83
- rectLayer.props.size.height = Number(svg.attributes.height);
84
- if (svg.attributes.transform) {
85
- SVGReader.applyTransform(svg.attributes.transform, rectLayer);
86
- }
87
- return rectLayer;
88
- }
89
- static async createEllipseLayer(svg, svgObject) {
90
- const ellipseLayer = new index_1.MorphLayer();
91
- if (svg.attributes.id)
92
- ellipseLayer.id = svg.attributes.id;
93
- if (svg.attributes.fill && svg.attributes.fill !== 'none') {
94
- let id = SVGReader.extractIdFromUrl(svg.attributes.fill);
95
- if (id) {
96
- let element = SVGReader.findElementById(svgObject, id);
97
- if (element.name === "pattern") {
98
- ellipseLayer.props.fillStyle = await SVGReader.createPattern(element, svgObject, svg);
99
- }
100
- else if (['linearGradient', 'radialGradient'].includes(element.name)) {
101
- ellipseLayer.props.fillStyle = await SVGReader.createGradient(element, svgObject, svg);
102
- }
103
- }
104
- else {
105
- ellipseLayer.props.fillStyle = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
106
- }
107
- }
108
- else {
109
- ellipseLayer.data.color = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
110
- }
111
- ellipseLayer.data.fill = svg.attributes.fill !== 'none';
112
- if (svg.attributes['fill-opacity'])
113
- ellipseLayer.data.alpha = Number(svg.attributes['fill-opacity']);
114
- ellipseLayer.data.x = Number(svg.attributes.x) || 0;
115
- ellipseLayer.data.y = Number(svg.attributes.y) || 0;
116
- ellipseLayer.data.centering = 'legacy';
117
- ellipseLayer.data.width = Number(svg.attributes.width);
118
- ellipseLayer.data.height = Number(svg.attributes.height);
119
- if (svg.attributes.transform) {
120
- SVGReader.applyTransform(svg.attributes.transform, ellipseLayer);
121
- }
122
- return ellipseLayer;
123
- }
124
- static async createCircleLayer(svg, svgObject) {
125
- const circleLayer = new index_1.MorphLayer();
126
- circleLayer.data.id = svg.attributes.id || `CircleLayer-${Math.random().toString(36).substring(2, 15)}`;
127
- if (svg.attributes.fill && svg.attributes.fill !== 'none') {
128
- let id = SVGReader.extractIdFromUrl(svg.attributes.fill);
129
- if (id) {
130
- let element = SVGReader.findElementById(svgObject, id);
131
- if (element.name === "pattern") {
132
- circleLayer.data.color = await SVGReader.createPattern(element, svgObject, svg);
133
- }
134
- else if (['linearGradient', 'radialGradient'].includes(element.name)) {
135
- circleLayer.data.color = await SVGReader.createGradient(element, svgObject, svg);
136
- }
137
- }
138
- else {
139
- circleLayer.data.color = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
140
- }
141
- }
142
- else {
143
- circleLayer.data.color = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
144
- }
145
- circleLayer.data.fill = svg.attributes.fill !== 'none';
146
- if (svg.attributes['fill-opacity'])
147
- circleLayer.data.alpha = Number(svg.attributes['fill-opacity']);
148
- circleLayer.data.x = Number(svg.attributes.cx) || 0;
149
- circleLayer.data.y = Number(svg.attributes.cy) || 0;
150
- circleLayer.data.radius = Number(svg.attributes.r);
151
- if (svg.attributes.transform) {
152
- SVGReader.applyTransform(svg.attributes.transform, circleLayer);
153
- }
154
- return circleLayer;
155
- }
156
- static async createLineLayer(svg, svgObject) {
157
- const lineLayer = new index_1.LineLayer();
158
- lineLayer.data.id = svg.attributes.id || `LineLayer-${Math.random().toString(36).substring(2, 15)}`;
159
- if (svg.attributes.fill && svg.attributes.fill !== 'none') {
160
- let id = SVGReader.extractIdFromUrl(svg.attributes.fill);
161
- if (id) {
162
- let element = SVGReader.findElementById(svgObject, id);
163
- if (element.name === "pattern") {
164
- lineLayer.data.color = await SVGReader.createPattern(element, svgObject, svg);
165
- }
166
- else if (['linearGradient', 'radialGradient'].includes(element.name)) {
167
- lineLayer.data.color = await SVGReader.createGradient(element, svgObject, svg);
168
- }
169
- }
170
- else {
171
- lineLayer.data.color = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
172
- }
173
- }
174
- else {
175
- lineLayer.data.color = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
176
- }
177
- lineLayer.data.fill = svg.attributes.fill !== 'none';
178
- if (svg.attributes['fill-opacity'])
179
- lineLayer.data.alpha = Number(svg.attributes['fill-opacity']);
180
- for (let i = 0; i < 2; i++) {
181
- lineLayer.data.points.push({
182
- x: Number(svg.attributes[`x${i + 1}`]),
183
- y: Number(svg.attributes[`y${i + 1}`])
184
- });
185
- }
186
- if (svg.attributes.transform) {
187
- SVGReader.applyTransform(svg.attributes.transform, lineLayer);
188
- }
189
- return lineLayer;
190
- }
191
- static async createGradient(svg, svgObject, parent) {
192
- const gradient = new index_1.Gradient();
193
- gradient.data.id = svg.attributes.id || `Gradient-${Math.random().toString(36).substring(2, 15)}`;
194
- gradient.data.gradientType = svg.name === 'linearGradient' ? 'linear' : 'radial';
195
- let baseXOne = (parent.attributes.x !== undefined
196
- ? Number(parent.attributes.x)
197
- : (parent.attributes.x1 !== undefined
198
- ? Number(parent.attributes.x1)
199
- : Number(parent.attributes.cx) - Number(parent.attributes.r)));
200
- let baseYOne = (parent.attributes.y !== undefined
201
- ? Number(parent.attributes.y)
202
- : (parent.attributes.y1 !== undefined
203
- ? Number(parent.attributes.y1)
204
- : Number(parent.attributes.cy) - Number(parent.attributes.r)));
205
- let baseXTwo = (parent.attributes.x !== undefined
206
- ? Number(parent.attributes.x)
207
- : (parent.attributes.x2 !== undefined
208
- ? Number(parent.attributes.x2)
209
- : Number(parent.attributes.cx) - Number(parent.attributes.r)));
210
- let baseYTwo = (parent.attributes.y !== undefined
211
- ? Number(parent.attributes.y)
212
- : (parent.attributes.y2 !== undefined
213
- ? Number(parent.attributes.y2)
214
- : Number(parent.attributes.cy) - Number(parent.attributes.r)));
215
- gradient.data.points = [
216
- {
217
- x: baseXOne + (svg.attributes.x1 !== undefined
218
- ? (parent.attributes.width !== undefined ? parent.attributes.width * Number(svg.attributes.x1) : baseXOne * Number(svg.attributes.x1))
219
- : Number(svg.attributes.fx) * (parent.attributes.width !== undefined ? Number(parent.attributes.width) : Number(parent.attributes.r) * 2)),
220
- y: baseYOne + (svg.attributes.y1 !== undefined
221
- ? (parent.attributes.height !== undefined ? parent.attributes.height * Number(svg.attributes.y1) : baseYOne * Number(svg.attributes.y1))
222
- : Number(svg.attributes.fy) * (parent.attributes.height !== undefined ? Number(parent.attributes.height) : Number(parent.attributes.r) * 2))
223
- },
224
- {
225
- x: baseXTwo + (svg.attributes.x2 !== undefined
226
- ? (parent.attributes.width !== undefined ? parent.attributes.width * Number(svg.attributes.x2) : baseXTwo * Number(svg.attributes.x2))
227
- : Number(svg.attributes.cx) * (parent.attributes.width !== undefined ? Number(parent.attributes.width) : Number(parent.attributes.r) * 2)),
228
- y: baseYTwo + (svg.attributes.y2 !== undefined
229
- ? (parent.attributes.height !== undefined ? parent.attributes.height * Number(svg.attributes.y2) : baseYTwo * Number(svg.attributes.y2))
230
- : Number(svg.attributes.cy) * (parent.attributes.height !== undefined ? Number(parent.attributes.height) : Number(parent.attributes.r) * 2))
231
- }
232
- ];
233
- if (svg.name === "radialGradient") {
234
- gradient.data.radius = Number(parent.attributes.r) ? (Number(parent.attributes.r) * Number(svg.attributes.r)) * 2 : Math.min((Number(parent.attributes.width) * Number(svg.attributes.r)), (Number(parent.attributes.height) * Number(svg.attributes.r)));
235
- }
236
- for (const colorStop of svg.children) {
237
- let color = colorStop.attributes['stop-color'];
238
- let offset = colorStop.attributes['offset'].replace('%', '');
239
- gradient.data.colorPoints.push({ color, position: Number(offset) / 100 });
240
- }
241
- return gradient;
242
- }
243
- static async createPattern(svg, svgObject, parent) {
244
- const pattern = new index_1.Pattern();
245
- pattern.data.id = svg.attributes.id || `Pattern-${Math.random().toString(36).substring(2, 15)}`;
246
- pattern.data.patternType = index_1.PatternType.repeat;
247
- let layers = [];
248
- for (const child of svg.children) {
249
- let layer;
250
- switch (child.name) {
251
- case 'image':
252
- layer = await SVGReader.createImageLayer(child);
253
- break;
254
- case 'path':
255
- layer = await SVGReader.createPath2DLayer(child, svgObject);
256
- break;
257
- case 'g':
258
- const group = await SVGReader.createGroupLayer(child, svgObject);
259
- layers.push(...group);
260
- break;
261
- case 'clipPath':
262
- layer = await SVGReader.createClipPathLayer(child);
263
- break;
264
- case 'use':
265
- layer = await SVGReader.handleUseElement(child, svgObject, svg);
266
- break;
267
- case 'rect':
268
- layer = await SVGReader.createRectLayer(child, svgObject);
269
- break;
270
- case 'ellipse':
271
- layer = await SVGReader.createEllipseLayer(child, svgObject);
272
- break;
273
- case 'circle':
274
- layer = await SVGReader.createCircleLayer(child, svgObject);
275
- break;
276
- case 'line':
277
- layer = await SVGReader.createLineLayer(child, svgObject);
278
- break;
279
- default:
280
- console.warn(`Unsupported SVG element: ${child.name}`);
281
- }
282
- if (layer) {
283
- layers.push(layer);
284
- }
285
- }
286
- let width = Number(svg.attributes['width']);
287
- let height = Number(svg.attributes['height']);
288
- width = width < 1 ? width * (Number(parent.attributes['width']) ? Number(parent.attributes['width']) : (Number(parent.attributes['r']) * 2)) : width;
289
- height = height < 1 ? height * (Number(parent.attributes['height']) ? Number(parent.attributes['height']) : (Number(parent.attributes['r']) * 2)) : height;
290
- pattern.data.pattern = {
291
- data: new index_1.LazyCanvas()
292
- .createNewCanvas(width, height)
293
- .addLayers(...layers),
294
- type: "canvas"
295
- };
296
- return pattern;
297
- }
298
- static async createPath2DLayer(svg, svgObject) {
299
- const path2DLayer = new index_1.Path2DLayer(svg.attributes.d);
300
- path2DLayer.data.id = svg.attributes.id || `Path2DLayer-${Math.random().toString(36).substring(2, 15)}`;
301
- if (svg.attributes.fill && svg.attributes.fill !== 'none') {
302
- let id = SVGReader.extractIdFromUrl(svg.attributes.fill);
303
- if (id) {
304
- let element = SVGReader.findElementById(svgObject, id);
305
- if (element.name === "pattern") {
306
- path2DLayer.data.color = await SVGReader.createPattern(element, svgObject, svg);
307
- }
308
- else if (['linearGradient', 'radialGradient'].includes(element.name)) {
309
- path2DLayer.data.color = await SVGReader.createGradient(element, svgObject, svg);
310
- }
311
- }
312
- else {
313
- path2DLayer.data.fillStyle = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
314
- }
315
- }
316
- else {
317
- path2DLayer.data.fillStyle = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
318
- }
319
- path2DLayer.data.filled = svg.attributes.fill !== 'none';
320
- if (svg.attributes['fill-opacity'])
321
- path2DLayer.data.alpha = Number(svg.attributes['fill-opacity']);
322
- path2DLayer.data.lineWidth = svg.attributes['stroke-width'] ? Number(svg.attributes['stroke-width']) : 1;
323
- if (svg.attributes.transform) {
324
- SVGReader.applyTransform(svg.attributes.transform, path2DLayer);
325
- }
326
- return path2DLayer;
327
- }
328
- static async createClipPathLayer(svg) {
329
- const clipPathLayer = new index_1.Path2DLayer(svg.children.map((child) => child.attributes.d).join(' '));
330
- clipPathLayer.data.clipPath = true;
331
- clipPathLayer.data.id = svg.attributes.id || `Path2DLayer-${Math.random().toString(36).substring(2, 15)}`;
332
- if (svg.attributes.transform) {
333
- SVGReader.applyTransform(svg.attributes.transform, clipPathLayer);
334
- }
335
- return clipPathLayer;
336
- }
337
- //private static async createTextLayer(svg: any, parent: any): Promise<any[] | TextLayer> {
338
- // if (svg.children.length !== 0) {
339
- // const textGroup = []
340
- // for (const child of svg.children) {
341
- // let layer;
342
- // switch (child.name) {
343
- // case 'text':
344
- // layer = await SVGReader.createTextLayer(child, svg);
345
- // break;
346
- // case 'tspan':
347
- // console.log(child)
348
- // layer = await SVGReader.createTextLayer(child, svg);
349
- // break;
350
- // default:
351
- // console.warn(`Unsupported SVG element: ${child.name}`);
352
- // }
353
- // if (layer) {
354
- // // @ts-ignore
355
- // textGroup.push(...layer);
356
- // }
357
- // }
358
- // return textGroup
359
- // } else {
360
- // const textLayer = new TextLayer()
361
- // textLayer.data.id = svg.attributes.id || `TextLayer-${Math.random().toString(36).substring(2, 15)}`;
362
- // textLayer.data.x = svg.attributes.x || parent.attributes.x || 0
363
- // textLayer.data.y = svg.attributes.y || parent.attributes.y || 0
364
- // textLayer.data.size = svg.attributes['font-size'] || parent.attributes['font-size'] || 20
365
- // textLayer.data.align = svg.attributes['anchor'] || parent.attributes['anchor'] || 'left'
366
- //
367
- // return textLayer
368
- // }
369
- //}
370
- static async createGroupLayer(svg, svgObject) {
371
- const groupLayers = [];
372
- for (const child of svg.children) {
373
- let layer;
374
- switch (child.name) {
375
- case 'image':
376
- layer = await SVGReader.createImageLayer(child);
377
- break;
378
- case 'path':
379
- layer = await SVGReader.createPath2DLayer(child, svgObject);
380
- break;
381
- case 'g':
382
- const group = await SVGReader.createGroupLayer(child, svgObject);
383
- groupLayers.push(...group);
384
- break;
385
- case 'clipPath':
386
- layer = await SVGReader.createClipPathLayer(child);
387
- break;
388
- case 'use':
389
- layer = await SVGReader.handleUseElement(child, svgObject, svg);
390
- break;
391
- case 'rect':
392
- layer = await SVGReader.createRectLayer(child, svgObject);
393
- break;
394
- case 'ellipse':
395
- layer = await SVGReader.createEllipseLayer(child, svgObject);
396
- break;
397
- case 'circle':
398
- layer = await SVGReader.createCircleLayer(child, svgObject);
399
- break;
400
- case 'line':
401
- layer = await SVGReader.createLineLayer(child, svgObject);
402
- break;
403
- default:
404
- console.warn(`Unsupported SVG element: ${child.name}`);
405
- }
406
- if (layer) {
407
- groupLayers.push(layer);
408
- }
409
- }
410
- return groupLayers;
411
- }
412
- static applyTransform(transform, layer) {
413
- const matrixMatch = transform.match(/matrix\(([^)]+)\)/);
414
- const scaleMatch = transform.match(/scale\(([^)]+)\)/);
415
- const translateMatch = transform.match(/translate\(([^)]+)\)/);
416
- const rotateMatch = transform.match(/rotate\(([^)]+)\)/);
417
- if (matrixMatch) {
418
- const [a, b, c, d, e, f] = matrixMatch[1].split(' ').map(Number);
419
- layer.data.transform.matrix = { a, b, c, d, e, f };
420
- layer.data.centering = 'legacy';
421
- }
422
- else if (scaleMatch) {
423
- const [sx, sy] = scaleMatch[1].split(' ').map(Number);
424
- layer.data.transform.scale = { x: sx, y: sy };
425
- }
426
- else if (translateMatch) {
427
- const [tx, ty] = translateMatch[1].split(' ').map(Number);
428
- layer.data.transform.translate = { x: tx, y: ty };
429
- }
430
- else if (rotateMatch) {
431
- const [angle, cx, cy] = rotateMatch[1].split(' ').map(Number);
432
- layer.data.transform.rotate = angle;
433
- }
434
- }
435
- static findElementById(svgObject, id) {
436
- const queue = [svgObject];
437
- while (queue.length > 0) {
438
- const current = queue.shift();
439
- if (current.attributes && current.attributes.id === id) {
440
- return current;
441
- }
442
- if (current.children) {
443
- queue.push(...current.children);
444
- }
445
- }
446
- throw new Error(`Element with id ${id} not found`);
447
- }
448
- static extractIdFromUrl(url) {
449
- const regex = /url\(#([^)]+)\)/;
450
- const match = url.match(regex);
451
- return match ? match[1] : null;
452
- }
453
- async fillStyle(svg, svgObject) {
454
- let fill, style;
455
- let id = SVGReader.extractIdFromUrl(svg.attributes.fill);
456
- if (id) {
457
- let element = SVGReader.findElementById(svgObject, id);
458
- if (element.name === "pattern") {
459
- fill = await SVGReader.createPattern(element, svgObject, svg);
460
- }
461
- else if (['linearGradient', 'radialGradient'].includes(element.name)) {
462
- fill = await SVGReader.createGradient(element, svgObject, svg);
463
- }
464
- }
465
- else {
466
- style = svg.attributes.fill === 'none' ? svg.attributes.stroke : svg.attributes.fill || 'black';
467
- }
468
- return { fill, style };
469
- }
470
- static async handleUseElement(svg, svgObject, from) {
471
- const href = svg.attributes['xlink:href'] || svg.attributes.href;
472
- const clipPath = from.attributes['clip-path'];
473
- const id = href.replace('#', '');
474
- const referencedElement = SVGReader.findElementById(svgObject, id);
475
- let layer;
476
- switch (referencedElement.name) {
477
- case 'image':
478
- if (clipPath) {
479
- let id = SVGReader.extractIdFromUrl(from.attributes['clip-path']);
480
- if (!id)
481
- return console.warn(`Could not extract id from clipPath: ${from.attributes['clip-path']}`);
482
- let element = SVGReader.findElementById(svgObject, id);
483
- layer = await SVGReader.createEllipseImageLayer(referencedElement, element.children[0].attributes.d);
484
- }
485
- else {
486
- layer = await SVGReader.createImageLayer(referencedElement);
487
- }
488
- break;
489
- case 'path':
490
- layer = await SVGReader.createPath2DLayer(referencedElement, svgObject);
491
- break;
492
- default:
493
- throw new Error(`Unsupported element referenced by <use>: ${referencedElement.name}`);
494
- }
495
- if (svg.attributes.transform) {
496
- SVGReader.applyTransform(svg.attributes.transform, layer);
497
- }
498
- return layer;
499
- }
500
- static async readSVG(svg) {
501
- const svgObject = await SVGReader.parseSVG(svg);
502
- const layers = [];
503
- for (const svgElement of svgObject.children) {
504
- let layer;
505
- switch (svgElement.name) {
506
- case 'defs':
507
- for (const child of svgElement.children) {
508
- if (child.name === 'image') {
509
- layer = await SVGReader.createImageLayer(child);
510
- }
511
- else if (child.name === 'clipPath') {
512
- layer = await SVGReader.createClipPathLayer(child);
513
- }
514
- }
515
- break;
516
- case 'path':
517
- layer = await SVGReader.createPath2DLayer(svgElement, svgObject);
518
- break;
519
- case 'g':
520
- const group = await SVGReader.createGroupLayer(svgElement, svgObject);
521
- for (const element of group) {
522
- let search = layers.find((l) => l.data.id === element.data.id);
523
- if (!search)
524
- layers.push(element);
525
- else {
526
- layers.splice(layers.indexOf(search), 1, element);
527
- }
528
- }
529
- break;
530
- case 'clipPath':
531
- layer = await SVGReader.createClipPathLayer(svgElement);
532
- break;
533
- case 'use':
534
- layer = await SVGReader.handleUseElement(svgElement, svgObject, svgObject);
535
- break;
536
- case 'rect':
537
- layer = await SVGReader.createRectLayer(svgElement, svgObject);
538
- break;
539
- case 'ellipse':
540
- layer = await SVGReader.createEllipseLayer(svgElement, svgObject);
541
- break;
542
- case 'circle':
543
- layer = await SVGReader.createCircleLayer(svgElement, svgObject);
544
- break;
545
- case 'line':
546
- layer = await SVGReader.createLineLayer(svgElement, svgObject);
547
- break;
548
- //case 'text':
549
- // const textGroup = await SVGReader.createTextLayer(svgElement, svgObject);
550
- // if (Array.isArray(textGroup)) {
551
- // for (const element of textGroup) {
552
- // let search = layers.find((l) => l.data.id === element.data.id);
553
- // if (!search) layers.push(element);
554
- // else {
555
- // layers.splice(layers.indexOf(search), 1, element);
556
- // }
557
- // }
558
- // } else {
559
- // layer = textGroup;
560
- // }
561
- // break;
562
- default:
563
- console.warn(`Unsupported SVG element: ${svgElement.name}`);
564
- }
565
- if (layer) {
566
- let search = layers.find((l) => l.data.id === layer.data.id);
567
- if (!search)
568
- layers.push(layer);
569
- else {
570
- layers.splice(layers.indexOf(search), 1, layer);
571
- }
572
- }
573
- }
574
- return layers;
575
- }
576
- }
577
- exports.SVGReader = SVGReader;
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,18 +0,0 @@
1
- import { Canvas, SKRSContext2D } from "@napi-rs/canvas";
2
- import { LayersManager } from "../structures/managers/LayersManager";
3
- import { RenderManager } from "../structures/managers/RenderManager";
4
- import { FontsManager } from "../structures/managers/FontsManager";
5
- import { AnimationManager } from "../structures/managers/AnimationManager";
6
- import { AnyExport } from "../";
7
-
8
- export interface ILazyCanvas {
9
- width: number;
10
- height: number;
11
- canvas: Canvas;
12
- ctx: SKRSContext2D;
13
- layers: LayersManager;
14
- render: RenderManager;
15
- fonts: FontsManager;
16
- animation: AnimationManager;
17
- exportType: AnyExport;
18
- }
@@ -1,49 +0,0 @@
1
- import { ColorType, ScaleType, AnyCentring, AnyGlobalCompositeOperation } from "../";
2
- import { LayerType } from "../enum";
3
-
4
- export interface IBaseLayer {
5
- id: string;
6
- type: LayerType;
7
- zIndex: number;
8
- visible: boolean;
9
- props: IBaseLayerProps;
10
- }
11
-
12
- export interface IBaseLayerProps {
13
- x: ScaleType;
14
- y: ScaleType;
15
- centring: AnyCentring;
16
- filter: string;
17
- opacity: number;
18
- filled: boolean;
19
- fillStyle: ColorType;
20
- stroke: {
21
- width: number;
22
- cap: CanvasLineCap;
23
- join: CanvasLineJoin;
24
- dashOffset: number;
25
- dash: number[];
26
- miterLimit: number;
27
- };
28
- shadow: {
29
- color: string;
30
- blur: number;
31
- offsetX: number;
32
- offsetY: number;
33
- };
34
- transform: Transform;
35
- globalComposite: AnyGlobalCompositeOperation;
36
- }
37
-
38
- export interface Transform {
39
- rotate: number;
40
- scale: {
41
- x: number;
42
- y: number;
43
- };
44
- translate: {
45
- x: number;
46
- y: number;
47
- };
48
- matrix: DOMMatrix2DInit;
49
- }
@@ -1,11 +0,0 @@
1
- import { IBaseLayer, IBaseLayerProps } from "./BaseLayer";
2
- import { Point } from "../";
3
-
4
- export interface IBezierLayer extends IBaseLayer {
5
- props: IBezierLayerProps;
6
- }
7
-
8
- export interface IBezierLayerProps extends IBaseLayerProps {
9
- controlPoints: Array<Point>;
10
- endPoint: Point;
11
- }