@umituz/web-canvas 1.0.1 → 1.0.3

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.
@@ -2,6 +2,7 @@ import { a as CanvasConfig, c as CanvasDimensions, b as CanvasContextConfig, d a
2
2
 
3
3
  declare class CanvasRenderer {
4
4
  private config;
5
+ private imageCache;
5
6
  constructor(config?: CanvasConfig);
6
7
  /**
7
8
  * Create a new canvas element
@@ -36,9 +37,17 @@ declare class CanvasRenderer {
36
37
  */
37
38
  drawImage(ctx: CanvasRenderingContext2D, imageSource: string | HTMLImageElement, x: number, y: number, width?: number, height?: number): Promise<void>;
38
39
  /**
39
- * Load image from URL
40
+ * Load image from URL with caching
40
41
  */
41
42
  private loadImage;
43
+ /**
44
+ * Clear image cache to free memory
45
+ */
46
+ clearImageCache(): void;
47
+ /**
48
+ * Get cache size for monitoring
49
+ */
50
+ getCacheSize(): number;
42
51
  /**
43
52
  * Create gradient
44
53
  */
@@ -70,24 +79,30 @@ declare class CanvasRenderer {
70
79
  */
71
80
 
72
81
  declare class PatternRenderer {
82
+ private patternCanvasCache;
83
+ private readonly MAX_CACHE_SIZE;
73
84
  /**
74
85
  * Render pattern on canvas
75
86
  */
76
87
  renderPattern(ctx: CanvasRenderingContext2D, pattern: BackgroundPattern, dimensions: CanvasDimensions, color?: string): void;
77
88
  /**
78
- * Render dot pattern
89
+ * Clear pattern cache to free memory
90
+ */
91
+ clearCache(): void;
92
+ /**
93
+ * Render dot pattern - optimized with batch rendering
79
94
  */
80
95
  private renderDotPattern;
81
96
  /**
82
- * Render grid pattern
97
+ * Render grid pattern - optimized with single path
83
98
  */
84
99
  private renderGridPattern;
85
100
  /**
86
- * Render line pattern
101
+ * Render line pattern - optimized with single path
87
102
  */
88
103
  private renderLinePattern;
89
104
  /**
90
- * Render wave pattern
105
+ * Render wave pattern - optimized with pre-calculated values
91
106
  */
92
107
  private renderWavePattern;
93
108
  /**
@@ -105,7 +120,13 @@ declare class ScreenshotRenderer {
105
120
  private canvasRenderer;
106
121
  private patternRenderer;
107
122
  private deviceConfigService;
123
+ private renderCache;
124
+ private readonly MAX_CACHE_SIZE;
108
125
  constructor();
126
+ /**
127
+ * Clear render cache to free memory
128
+ */
129
+ clearCache(): void;
109
130
  /**
110
131
  * Render device frame
111
132
  */
@@ -123,7 +144,7 @@ declare class ScreenshotRenderer {
123
144
  */
124
145
  private renderNotch;
125
146
  /**
126
- * Render background
147
+ * Render background - optimized
127
148
  */
128
149
  renderBackground(ctx: CanvasRenderingContext2D, design: ScreenshotDesign, dimensions: CanvasDimensions): void;
129
150
  /**
@@ -159,6 +180,9 @@ declare class ScreenshotRenderer {
159
180
  declare class DeviceConfigService {
160
181
  private static instance;
161
182
  private devices;
183
+ private phonesCache;
184
+ private tabletsCache;
185
+ private allDevicesCache;
162
186
  private constructor();
163
187
  static getInstance(): DeviceConfigService;
164
188
  private initializeDevices;
@@ -49,6 +49,9 @@ var DEFAULT_DEVICE_CONFIG = {
49
49
  // src/infrastructure/services/DeviceConfigService.ts
50
50
  var DeviceConfigService = class _DeviceConfigService {
51
51
  constructor() {
52
+ this.phonesCache = null;
53
+ this.tabletsCache = null;
54
+ this.allDevicesCache = null;
52
55
  this.devices = /* @__PURE__ */ new Map();
53
56
  this.initializeDevices();
54
57
  }
@@ -145,13 +148,22 @@ var DeviceConfigService = class _DeviceConfigService {
145
148
  return this.devices.get(deviceType);
146
149
  }
147
150
  getAllDevices() {
148
- return Array.from(this.devices.values());
151
+ if (!this.allDevicesCache) {
152
+ this.allDevicesCache = Array.from(this.devices.values());
153
+ }
154
+ return this.allDevicesCache;
149
155
  }
150
156
  getPhones() {
151
- return this.getAllDevices().filter((d) => d.isPhone);
157
+ if (!this.phonesCache) {
158
+ this.phonesCache = this.getAllDevices().filter((d) => d.isPhone);
159
+ }
160
+ return this.phonesCache;
152
161
  }
153
162
  getTablets() {
154
- return this.getAllDevices().filter((d) => d.isTablet);
163
+ if (!this.tabletsCache) {
164
+ this.tabletsCache = this.getAllDevices().filter((d) => d.isTablet);
165
+ }
166
+ return this.tabletsCache;
155
167
  }
156
168
  isPhone(deviceType) {
157
169
  const config = this.getDeviceConfig(deviceType);
@@ -181,6 +193,7 @@ var DEFAULT_CANVAS_CONFIG = {
181
193
  var CanvasRenderer = class {
182
194
  constructor(config = DEFAULT_CANVAS_CONFIG) {
183
195
  this.config = { ...DEFAULT_CANVAS_CONFIG, ...config };
196
+ this.imageCache = /* @__PURE__ */ new Map();
184
197
  }
185
198
  /**
186
199
  * Create a new canvas element
@@ -282,17 +295,37 @@ var CanvasRenderer = class {
282
295
  }
283
296
  }
284
297
  /**
285
- * Load image from URL
298
+ * Load image from URL with caching
286
299
  */
287
300
  loadImage(url) {
301
+ if (this.imageCache.has(url)) {
302
+ return Promise.resolve(this.imageCache.get(url));
303
+ }
288
304
  return new Promise((resolve, reject) => {
289
305
  const img = new Image();
290
- img.crossOrigin = this.config.useCORS ? "anonymous" : void 0;
291
- img.onload = () => resolve(img);
306
+ if (this.config.useCORS) {
307
+ img.crossOrigin = "anonymous";
308
+ }
309
+ img.onload = () => {
310
+ this.imageCache.set(url, img);
311
+ resolve(img);
312
+ };
292
313
  img.onerror = () => reject(new Error(`Failed to load image: ${url}`));
293
314
  img.src = url;
294
315
  });
295
316
  }
317
+ /**
318
+ * Clear image cache to free memory
319
+ */
320
+ clearImageCache() {
321
+ this.imageCache.clear();
322
+ }
323
+ /**
324
+ * Get cache size for monitoring
325
+ */
326
+ getCacheSize() {
327
+ return this.imageCache.size;
328
+ }
296
329
  /**
297
330
  * Create gradient
298
331
  */
@@ -374,10 +407,15 @@ var CanvasRenderer = class {
374
407
 
375
408
  // src/infrastructure/renderers/PatternRenderer.ts
376
409
  var PatternRenderer = class {
410
+ constructor() {
411
+ this.patternCanvasCache = /* @__PURE__ */ new Map();
412
+ this.MAX_CACHE_SIZE = 10;
413
+ }
377
414
  /**
378
415
  * Render pattern on canvas
379
416
  */
380
417
  renderPattern(ctx, pattern, dimensions, color = "#000000") {
418
+ if (pattern === "none") return;
381
419
  ctx.save();
382
420
  ctx.globalAlpha = 0.1;
383
421
  switch (pattern) {
@@ -396,62 +434,65 @@ var PatternRenderer = class {
396
434
  case "checkers":
397
435
  this.renderCheckerPattern(ctx, dimensions, color);
398
436
  break;
399
- case "none":
400
- default:
401
- break;
402
437
  }
403
438
  ctx.restore();
404
439
  }
405
440
  /**
406
- * Render dot pattern
441
+ * Clear pattern cache to free memory
442
+ */
443
+ clearCache() {
444
+ this.patternCanvasCache.clear();
445
+ }
446
+ /**
447
+ * Render dot pattern - optimized with batch rendering
407
448
  */
408
449
  renderDotPattern(ctx, dimensions, color) {
409
450
  ctx.fillStyle = color;
410
451
  const spacing = 30;
452
+ const radius = 2;
453
+ ctx.beginPath();
411
454
  for (let x = spacing; x < dimensions.width; x += spacing) {
412
455
  for (let y = spacing; y < dimensions.height; y += spacing) {
413
- ctx.beginPath();
414
- ctx.arc(x, y, 2, 0, Math.PI * 2);
415
- ctx.fill();
456
+ ctx.moveTo(x + radius, y);
457
+ ctx.arc(x, y, radius, 0, Math.PI * 2);
416
458
  }
417
459
  }
460
+ ctx.fill();
418
461
  }
419
462
  /**
420
- * Render grid pattern
463
+ * Render grid pattern - optimized with single path
421
464
  */
422
465
  renderGridPattern(ctx, dimensions, color) {
423
466
  ctx.strokeStyle = color;
424
467
  ctx.lineWidth = 1;
425
468
  const spacing = 30;
469
+ ctx.beginPath();
426
470
  for (let x = 0; x <= dimensions.width; x += spacing) {
427
- ctx.beginPath();
428
471
  ctx.moveTo(x, 0);
429
472
  ctx.lineTo(x, dimensions.height);
430
- ctx.stroke();
431
473
  }
432
474
  for (let y = 0; y <= dimensions.height; y += spacing) {
433
- ctx.beginPath();
434
475
  ctx.moveTo(0, y);
435
476
  ctx.lineTo(dimensions.width, y);
436
- ctx.stroke();
437
477
  }
478
+ ctx.stroke();
438
479
  }
439
480
  /**
440
- * Render line pattern
481
+ * Render line pattern - optimized with single path
441
482
  */
442
483
  renderLinePattern(ctx, dimensions, color) {
443
484
  ctx.strokeStyle = color;
444
485
  ctx.lineWidth = 2;
445
486
  const spacing = 20;
487
+ ctx.beginPath();
446
488
  for (let y = spacing; y < dimensions.height; y += spacing) {
447
- ctx.beginPath();
448
489
  ctx.moveTo(0, y);
449
490
  ctx.lineTo(dimensions.width, y);
450
- ctx.stroke();
451
491
  }
492
+ ctx.stroke();
452
493
  }
453
494
  /**
454
- * Render wave pattern
495
+ * Render wave pattern - optimized with pre-calculated values
455
496
  */
456
497
  renderWavePattern(ctx, dimensions, color) {
457
498
  ctx.strokeStyle = color;
@@ -459,15 +500,15 @@ var PatternRenderer = class {
459
500
  const amplitude = 10;
460
501
  const frequency = 0.1;
461
502
  const spacing = 40;
503
+ const step = 5;
462
504
  for (let y = spacing; y < dimensions.height; y += spacing) {
463
505
  ctx.beginPath();
464
- for (let x = 0; x <= dimensions.width; x += 5) {
506
+ const startX = 0;
507
+ const startY = y + Math.sin(startX * frequency) * amplitude;
508
+ ctx.moveTo(startX, startY);
509
+ for (let x = step; x <= dimensions.width; x += step) {
465
510
  const waveY = y + Math.sin(x * frequency) * amplitude;
466
- if (x === 0) {
467
- ctx.moveTo(x, waveY);
468
- } else {
469
- ctx.lineTo(x, waveY);
470
- }
511
+ ctx.lineTo(x, waveY);
471
512
  }
472
513
  ctx.stroke();
473
514
  }
@@ -490,10 +531,20 @@ var PatternRenderer = class {
490
531
  // src/infrastructure/renderers/ScreenshotRenderer.ts
491
532
  var ScreenshotRenderer = class {
492
533
  constructor() {
534
+ this.renderCache = /* @__PURE__ */ new Map();
535
+ this.MAX_CACHE_SIZE = 5;
493
536
  this.canvasRenderer = new CanvasRenderer();
494
537
  this.patternRenderer = new PatternRenderer();
495
538
  this.deviceConfigService = DeviceConfigService.getInstance();
496
539
  }
540
+ /**
541
+ * Clear render cache to free memory
542
+ */
543
+ clearCache() {
544
+ this.renderCache.clear();
545
+ this.canvasRenderer.clearImageCache?.();
546
+ this.patternRenderer.clearCache?.();
547
+ }
497
548
  /**
498
549
  * Render device frame
499
550
  */
@@ -545,7 +596,7 @@ var ScreenshotRenderer = class {
545
596
  ctx.fill();
546
597
  }
547
598
  /**
548
- * Render background
599
+ * Render background - optimized
549
600
  */
550
601
  renderBackground(ctx, design, dimensions) {
551
602
  if (design.backgroundGradientEnd) {
@@ -3,7 +3,7 @@ import {
3
3
  DeviceConfigService,
4
4
  PatternRenderer,
5
5
  ScreenshotRenderer
6
- } from "../chunk-WMKPCJFI.mjs";
6
+ } from "../chunk-UOGTEMIJ.mjs";
7
7
  import "../chunk-MC6PNV2F.mjs";
8
8
  export {
9
9
  CanvasRenderer,