@pooder/kit 3.3.0 → 3.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 3.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - bugfix
8
+
3
9
  ## 3.3.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -166,8 +166,7 @@ interface ImageItem {
166
166
  id: string;
167
167
  url: string;
168
168
  opacity: number;
169
- width?: number;
170
- height?: number;
169
+ scale?: number;
171
170
  angle?: number;
172
171
  left?: number;
173
172
  top?: number;
@@ -179,6 +178,7 @@ declare class ImageTool implements Extension {
179
178
  };
180
179
  private items;
181
180
  private objectMap;
181
+ private loadResolvers;
182
182
  private canvasService?;
183
183
  private context?;
184
184
  private isUpdatingConfig;
package/dist/index.d.ts CHANGED
@@ -166,8 +166,7 @@ interface ImageItem {
166
166
  id: string;
167
167
  url: string;
168
168
  opacity: number;
169
- width?: number;
170
- height?: number;
169
+ scale?: number;
171
170
  angle?: number;
172
171
  left?: number;
173
172
  top?: number;
@@ -179,6 +178,7 @@ declare class ImageTool implements Extension {
179
178
  };
180
179
  private items;
181
180
  private objectMap;
181
+ private loadResolvers;
182
182
  private canvasService?;
183
183
  private context?;
184
184
  private isUpdatingConfig;
package/dist/index.js CHANGED
@@ -255,7 +255,7 @@ var ImageTracer = class {
255
255
  * @param options Configuration options.
256
256
  */
257
257
  static async trace(imageUrl, options = {}) {
258
- var _a, _b;
258
+ var _a, _b, _c, _d, _e;
259
259
  const img = await this.loadImage(imageUrl);
260
260
  const width = img.width;
261
261
  const height = img.height;
@@ -266,21 +266,213 @@ var ImageTracer = class {
266
266
  if (!ctx) throw new Error("Could not get 2D context");
267
267
  ctx.drawImage(img, 0, 0);
268
268
  const imageData = ctx.getImageData(0, 0, width, height);
269
- const points = this.marchingSquares(imageData, (_a = options.threshold) != null ? _a : 10);
270
- let finalPoints = points;
271
- if (options.scaleToWidth && options.scaleToHeight && points.length > 0) {
269
+ const threshold = (_a = options.threshold) != null ? _a : 10;
270
+ const adaptiveRadius = Math.max(
271
+ 5,
272
+ Math.floor(Math.max(width, height) * 0.02)
273
+ );
274
+ const radius = (_b = options.morphologyRadius) != null ? _b : adaptiveRadius;
275
+ let mask = this.createMask(imageData, threshold);
276
+ if (radius > 0) {
277
+ mask = this.dilate(mask, width, height, radius);
278
+ mask = this.erode(mask, width, height, radius);
279
+ mask = this.fillHoles(mask, width, height);
280
+ }
281
+ const allContourPoints = this.traceAllContours(mask, width, height);
282
+ if (allContourPoints.length === 0) {
283
+ const w = (_c = options.scaleToWidth) != null ? _c : width;
284
+ const h = (_d = options.scaleToHeight) != null ? _d : height;
285
+ return `M 0 0 L ${w} 0 L ${w} ${h} L 0 ${h} Z`;
286
+ }
287
+ const primaryContour = allContourPoints.sort(
288
+ (a, b) => b.length - a.length
289
+ )[0];
290
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
291
+ for (const p of primaryContour) {
292
+ if (p.x < minX) minX = p.x;
293
+ if (p.y < minY) minY = p.y;
294
+ if (p.x > maxX) maxX = p.x;
295
+ if (p.y > maxY) maxY = p.y;
296
+ }
297
+ const globalBounds = {
298
+ minX,
299
+ minY,
300
+ width: maxX - minX,
301
+ height: maxY - minY
302
+ };
303
+ let finalPoints = primaryContour;
304
+ if (options.scaleToWidth && options.scaleToHeight) {
272
305
  finalPoints = this.scalePoints(
273
- points,
306
+ primaryContour,
274
307
  options.scaleToWidth,
275
- options.scaleToHeight
308
+ options.scaleToHeight,
309
+ globalBounds
276
310
  );
277
311
  }
278
312
  const simplifiedPoints = this.douglasPeucker(
279
313
  finalPoints,
280
- (_b = options.simplifyTolerance) != null ? _b : 0.5
314
+ (_e = options.simplifyTolerance) != null ? _e : 2
281
315
  );
282
316
  return this.pointsToSVG(simplifiedPoints);
283
317
  }
318
+ static createMask(imageData, threshold) {
319
+ const { width, height, data } = imageData;
320
+ const mask = new Uint8Array(width * height);
321
+ for (let i = 0; i < width * height; i++) {
322
+ const idx = i * 4;
323
+ const r = data[idx];
324
+ const g = data[idx + 1];
325
+ const b = data[idx + 2];
326
+ const a = data[idx + 3];
327
+ if (a > threshold && !(r > 240 && g > 240 && b > 240)) {
328
+ mask[i] = 1;
329
+ } else {
330
+ mask[i] = 0;
331
+ }
332
+ }
333
+ return mask;
334
+ }
335
+ /**
336
+ * Fast 1D-separable Dilation
337
+ */
338
+ static dilate(mask, width, height, radius) {
339
+ const horizontal = new Uint8Array(width * height);
340
+ for (let y = 0; y < height; y++) {
341
+ let count = 0;
342
+ for (let x = -radius; x < width; x++) {
343
+ if (x + radius < width && mask[y * width + x + radius]) count++;
344
+ if (x - radius - 1 >= 0 && mask[y * width + x - radius - 1]) count--;
345
+ if (x >= 0) horizontal[y * width + x] = count > 0 ? 1 : 0;
346
+ }
347
+ }
348
+ const vertical = new Uint8Array(width * height);
349
+ for (let x = 0; x < width; x++) {
350
+ let count = 0;
351
+ for (let y = -radius; y < height; y++) {
352
+ if (y + radius < height && horizontal[(y + radius) * width + x])
353
+ count++;
354
+ if (y - radius - 1 >= 0 && horizontal[(y - radius - 1) * width + x])
355
+ count--;
356
+ if (y >= 0) vertical[y * width + x] = count > 0 ? 1 : 0;
357
+ }
358
+ }
359
+ return vertical;
360
+ }
361
+ /**
362
+ * Fast 1D-separable Erosion
363
+ */
364
+ static erode(mask, width, height, radius) {
365
+ const horizontal = new Uint8Array(width * height);
366
+ for (let y = 0; y < height; y++) {
367
+ let count = 0;
368
+ for (let x = -radius; x < width; x++) {
369
+ if (x + radius < width && mask[y * width + x + radius]) count++;
370
+ if (x - radius - 1 >= 0 && mask[y * width + x - radius - 1]) count--;
371
+ if (x >= 0) {
372
+ const winWidth = Math.min(x + radius, width - 1) - Math.max(x - radius, 0) + 1;
373
+ horizontal[y * width + x] = count === winWidth ? 1 : 0;
374
+ }
375
+ }
376
+ }
377
+ const vertical = new Uint8Array(width * height);
378
+ for (let x = 0; x < width; x++) {
379
+ let count = 0;
380
+ for (let y = -radius; y < height; y++) {
381
+ if (y + radius < height && horizontal[(y + radius) * width + x])
382
+ count++;
383
+ if (y - radius - 1 >= 0 && horizontal[(y - radius - 1) * width + x])
384
+ count--;
385
+ if (y >= 0) {
386
+ const winHeight = Math.min(y + radius, height - 1) - Math.max(y - radius, 0) + 1;
387
+ vertical[y * width + x] = count === winHeight ? 1 : 0;
388
+ }
389
+ }
390
+ }
391
+ return vertical;
392
+ }
393
+ /**
394
+ * Fills internal holes in the binary mask using flood fill from edges.
395
+ */
396
+ static fillHoles(mask, width, height) {
397
+ const background = new Uint8Array(width * height);
398
+ const queue = [];
399
+ for (let x = 0; x < width; x++) {
400
+ if (mask[x] === 0) {
401
+ background[x] = 1;
402
+ queue.push([x, 0]);
403
+ }
404
+ const lastRow = (height - 1) * width + x;
405
+ if (mask[lastRow] === 0) {
406
+ background[lastRow] = 1;
407
+ queue.push([x, height - 1]);
408
+ }
409
+ }
410
+ for (let y = 1; y < height - 1; y++) {
411
+ if (mask[y * width] === 0) {
412
+ background[y * width] = 1;
413
+ queue.push([0, y]);
414
+ }
415
+ if (mask[y * width + width - 1] === 0) {
416
+ background[y * width + width - 1] = 1;
417
+ queue.push([width - 1, y]);
418
+ }
419
+ }
420
+ const dirs = [
421
+ [0, 1],
422
+ [0, -1],
423
+ [1, 0],
424
+ [-1, 0]
425
+ ];
426
+ let head = 0;
427
+ while (head < queue.length) {
428
+ const [cx, cy] = queue[head++];
429
+ for (const [dx, dy] of dirs) {
430
+ const nx = cx + dx;
431
+ const ny = cy + dy;
432
+ if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
433
+ const nidx = ny * width + nx;
434
+ if (mask[nidx] === 0 && background[nidx] === 0) {
435
+ background[nidx] = 1;
436
+ queue.push([nx, ny]);
437
+ }
438
+ }
439
+ }
440
+ }
441
+ const filledMask = new Uint8Array(width * height);
442
+ for (let i = 0; i < width * height; i++) {
443
+ filledMask[i] = background[i] === 0 ? 1 : 0;
444
+ }
445
+ return filledMask;
446
+ }
447
+ /**
448
+ * Traces all contours in the mask with optimized start-point detection
449
+ */
450
+ static traceAllContours(mask, width, height) {
451
+ const visited = new Uint8Array(width * height);
452
+ const allContours = [];
453
+ for (let y = 0; y < height; y++) {
454
+ for (let x = 0; x < width; x++) {
455
+ const idx = y * width + x;
456
+ if (mask[idx] && !visited[idx]) {
457
+ const isLeftEdge = x === 0 || mask[idx - 1] === 0;
458
+ if (isLeftEdge) {
459
+ const contour = this.marchingSquares(
460
+ mask,
461
+ visited,
462
+ x,
463
+ y,
464
+ width,
465
+ height
466
+ );
467
+ if (contour.length > 2) {
468
+ allContours.push(contour);
469
+ }
470
+ }
471
+ }
472
+ }
473
+ }
474
+ return allContours;
475
+ }
284
476
  static loadImage(url) {
285
477
  return new Promise((resolve, reject) => {
286
478
  const img = new Image();
@@ -294,33 +486,11 @@ var ImageTracer = class {
294
486
  * Moore-Neighbor Tracing Algorithm
295
487
  * More robust for irregular shapes than simple Marching Squares walker.
296
488
  */
297
- static marchingSquares(imageData, alphaThreshold) {
298
- const width = imageData.width;
299
- const height = imageData.height;
300
- const data = imageData.data;
489
+ static marchingSquares(mask, visited, startX, startY, width, height) {
301
490
  const isSolid = (x, y) => {
302
491
  if (x < 0 || x >= width || y < 0 || y >= height) return false;
303
- const index = (y * width + x) * 4;
304
- const r = data[index];
305
- const g = data[index + 1];
306
- const b = data[index + 2];
307
- const a = data[index + 3];
308
- if (a <= alphaThreshold) return false;
309
- if (r > 240 && g > 240 && b > 240) return false;
310
- return true;
492
+ return mask[y * width + x] === 1;
311
493
  };
312
- let startX = -1;
313
- let startY = -1;
314
- searchLoop: for (let y = 0; y < height; y++) {
315
- for (let x = 0; x < width; x++) {
316
- if (isSolid(x, y)) {
317
- startX = x;
318
- startY = y;
319
- break searchLoop;
320
- }
321
- }
322
- }
323
- if (startX === -1) return [];
324
494
  const points = [];
325
495
  let cx = startX;
326
496
  let cy = startY;
@@ -339,6 +509,7 @@ var ImageTracer = class {
339
509
  let steps = 0;
340
510
  do {
341
511
  points.push({ x: cx, y: cy });
512
+ visited[cy * width + cx] = 1;
342
513
  let found = false;
343
514
  for (let i = 0; i < 8; i++) {
344
515
  const idx = (backtrack + 1 + i) % 8;
@@ -347,16 +518,12 @@ var ImageTracer = class {
347
518
  if (isSolid(nx, ny)) {
348
519
  cx = nx;
349
520
  cy = ny;
350
- backtrack = (idx + 4) % 8;
351
- backtrack = (idx + 4 + 1) % 8;
352
521
  backtrack = (idx + 4 + 1) % 8;
353
522
  found = true;
354
523
  break;
355
524
  }
356
525
  }
357
- if (!found) {
358
- break;
359
- }
526
+ if (!found) break;
360
527
  steps++;
361
528
  } while ((cx !== startX || cy !== startY) && steps < maxSteps);
362
529
  return points;
@@ -405,23 +572,14 @@ var ImageTracer = class {
405
572
  dy = p.y - y;
406
573
  return dx * dx + dy * dy;
407
574
  }
408
- static scalePoints(points, targetWidth, targetHeight) {
575
+ static scalePoints(points, targetWidth, targetHeight, bounds) {
409
576
  if (points.length === 0) return points;
410
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
411
- for (const p of points) {
412
- if (p.x < minX) minX = p.x;
413
- if (p.y < minY) minY = p.y;
414
- if (p.x > maxX) maxX = p.x;
415
- if (p.y > maxY) maxY = p.y;
416
- }
417
- const srcW = maxX - minX;
418
- const srcH = maxY - minY;
419
- if (srcW === 0 || srcH === 0) return points;
420
- const scaleX = targetWidth / srcW;
421
- const scaleY = targetHeight / srcH;
577
+ if (bounds.width === 0 || bounds.height === 0) return points;
578
+ const scaleX = targetWidth / bounds.width;
579
+ const scaleY = targetHeight / bounds.height;
422
580
  return points.map((p) => ({
423
- x: (p.x - minX) * scaleX,
424
- y: (p.y - minY) * scaleY
581
+ x: (p.x - bounds.minX) * scaleX,
582
+ y: (p.y - bounds.minY) * scaleY
425
583
  }));
426
584
  }
427
585
  static pointsToSVG(points) {
@@ -2175,6 +2333,7 @@ var ImageTool = class {
2175
2333
  };
2176
2334
  this.items = [];
2177
2335
  this.objectMap = /* @__PURE__ */ new Map();
2336
+ this.loadResolvers = /* @__PURE__ */ new Map();
2178
2337
  this.isUpdatingConfig = false;
2179
2338
  }
2180
2339
  activate(context) {
@@ -2184,19 +2343,15 @@ var ImageTool = class {
2184
2343
  console.warn("CanvasService not found for ImageTool");
2185
2344
  return;
2186
2345
  }
2187
- const configService = context.services.get("ConfigurationService");
2346
+ const configService = context.services.get(
2347
+ "ConfigurationService"
2348
+ );
2188
2349
  if (configService) {
2189
2350
  this.items = configService.get("image.items", []) || [];
2190
2351
  configService.onAnyChange((e) => {
2191
2352
  if (this.isUpdatingConfig) return;
2192
- let shouldUpdate = false;
2193
2353
  if (e.key === "image.items") {
2194
2354
  this.items = e.value || [];
2195
- shouldUpdate = true;
2196
- } else if (e.key.startsWith("dieline.") && e.key !== "dieline.holes") {
2197
- shouldUpdate = true;
2198
- }
2199
- if (shouldUpdate) {
2200
2355
  this.updateImages();
2201
2356
  }
2202
2357
  });
@@ -2232,15 +2387,39 @@ var ImageTool = class {
2232
2387
  {
2233
2388
  command: "addImage",
2234
2389
  title: "Add Image",
2235
- handler: (url, options) => {
2390
+ handler: async (url, options) => {
2391
+ const id = this.generateId();
2236
2392
  const newItem = {
2237
- id: this.generateId(),
2393
+ id,
2238
2394
  url,
2239
2395
  opacity: 1,
2240
2396
  ...options
2241
2397
  };
2398
+ const promise = new Promise((resolve) => {
2399
+ this.loadResolvers.set(id, () => resolve(id));
2400
+ });
2242
2401
  this.updateConfig([...this.items, newItem]);
2243
- return newItem.id;
2402
+ return promise;
2403
+ }
2404
+ },
2405
+ {
2406
+ command: "fitImageToArea",
2407
+ title: "Fit Image to Area",
2408
+ handler: (id, area) => {
2409
+ var _a, _b;
2410
+ const item = this.items.find((i) => i.id === id);
2411
+ const obj = this.objectMap.get(id);
2412
+ if (item && obj && obj.width && obj.height) {
2413
+ const scale = Math.max(
2414
+ area.width / obj.width,
2415
+ area.height / obj.height
2416
+ );
2417
+ this.updateImageInConfig(id, {
2418
+ scale,
2419
+ left: (_a = area.left) != null ? _a : 0.5,
2420
+ top: (_b = area.top) != null ? _b : 0.5
2421
+ });
2422
+ }
2244
2423
  }
2245
2424
  },
2246
2425
  {
@@ -2308,7 +2487,9 @@ var ImageTool = class {
2308
2487
  if (!this.context) return;
2309
2488
  this.isUpdatingConfig = true;
2310
2489
  this.items = newItems;
2311
- const configService = this.context.services.get("ConfigurationService");
2490
+ const configService = this.context.services.get(
2491
+ "ConfigurationService"
2492
+ );
2312
2493
  if (configService) {
2313
2494
  configService.update("image.items", newItems);
2314
2495
  }
@@ -2354,53 +2535,12 @@ var ImageTool = class {
2354
2535
  var _a, _b;
2355
2536
  const canvasW = ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800;
2356
2537
  const canvasH = ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600;
2357
- let layoutScale = 1;
2358
- let layoutOffsetX = 0;
2359
- let layoutOffsetY = 0;
2360
- let visualWidth = canvasW;
2361
- let visualHeight = canvasH;
2362
- let dielinePhysicalWidth = 500;
2363
- let dielinePhysicalHeight = 500;
2364
- let bleedOffset = 0;
2365
- if (this.context) {
2366
- const configService = this.context.services.get("ConfigurationService");
2367
- if (configService) {
2368
- dielinePhysicalWidth = configService.get("dieline.width") || 500;
2369
- dielinePhysicalHeight = configService.get("dieline.height") || 500;
2370
- bleedOffset = configService.get("dieline.offset") || 0;
2371
- const paddingValue = configService.get("dieline.padding") || 40;
2372
- let padding = 0;
2373
- if (typeof paddingValue === "number") {
2374
- padding = paddingValue;
2375
- } else if (typeof paddingValue === "string") {
2376
- if (paddingValue.endsWith("%")) {
2377
- const percent = parseFloat(paddingValue) / 100;
2378
- padding = Math.min(canvasW, canvasH) * percent;
2379
- } else {
2380
- padding = parseFloat(paddingValue) || 0;
2381
- }
2382
- }
2383
- const layout = Coordinate.calculateLayout(
2384
- { width: canvasW, height: canvasH },
2385
- { width: dielinePhysicalWidth, height: dielinePhysicalHeight },
2386
- padding
2387
- );
2388
- layoutScale = layout.scale;
2389
- layoutOffsetX = layout.offsetX;
2390
- layoutOffsetY = layout.offsetY;
2391
- visualWidth = layout.width;
2392
- visualHeight = layout.height;
2393
- }
2394
- }
2395
2538
  return {
2396
- layoutScale,
2397
- layoutOffsetX,
2398
- layoutOffsetY,
2399
- visualWidth,
2400
- visualHeight,
2401
- dielinePhysicalWidth,
2402
- dielinePhysicalHeight,
2403
- bleedOffset
2539
+ layoutScale: 1,
2540
+ layoutOffsetX: 0,
2541
+ layoutOffsetY: 0,
2542
+ visualWidth: canvasW,
2543
+ visualHeight: canvasH
2404
2544
  };
2405
2545
  }
2406
2546
  updateImages() {
@@ -2423,8 +2563,8 @@ var ImageTool = class {
2423
2563
  if (!obj) {
2424
2564
  this.loadImage(item, layer, layout);
2425
2565
  } else {
2426
- this.updateObjectProperties(obj, item, layout);
2427
2566
  layer.remove(obj);
2567
+ this.updateObjectProperties(obj, item, layout);
2428
2568
  layer.add(obj);
2429
2569
  }
2430
2570
  });
@@ -2432,10 +2572,17 @@ var ImageTool = class {
2432
2572
  this.canvasService.requestRenderAll();
2433
2573
  }
2434
2574
  updateObjectProperties(obj, item, layout) {
2435
- const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight } = layout;
2575
+ const {
2576
+ layoutScale,
2577
+ layoutOffsetX,
2578
+ layoutOffsetY,
2579
+ visualWidth,
2580
+ visualHeight
2581
+ } = layout;
2436
2582
  const updates = {};
2437
2583
  if (obj.opacity !== item.opacity) updates.opacity = item.opacity;
2438
- if (item.angle !== void 0 && obj.angle !== item.angle) updates.angle = item.angle;
2584
+ if (item.angle !== void 0 && obj.angle !== item.angle)
2585
+ updates.angle = item.angle;
2439
2586
  if (item.left !== void 0) {
2440
2587
  const globalLeft = layoutOffsetX + item.left * visualWidth;
2441
2588
  if (Math.abs(obj.left - globalLeft) > 1) updates.left = globalLeft;
@@ -2444,13 +2591,12 @@ var ImageTool = class {
2444
2591
  const globalTop = layoutOffsetY + item.top * visualHeight;
2445
2592
  if (Math.abs(obj.top - globalTop) > 1) updates.top = globalTop;
2446
2593
  }
2447
- if (item.width !== void 0 && obj.width) {
2448
- const targetScaleX = item.width * layoutScale / obj.width;
2449
- if (Math.abs(obj.scaleX - targetScaleX) > 1e-3) updates.scaleX = targetScaleX;
2450
- }
2451
- if (item.height !== void 0 && obj.height) {
2452
- const targetScaleY = item.height * layoutScale / obj.height;
2453
- if (Math.abs(obj.scaleY - targetScaleY) > 1e-3) updates.scaleY = targetScaleY;
2594
+ if (item.scale !== void 0) {
2595
+ const targetScale = item.scale * layoutScale;
2596
+ if (Math.abs(obj.scaleX - targetScale) > 1e-3) {
2597
+ updates.scaleX = targetScale;
2598
+ updates.scaleY = targetScale;
2599
+ }
2454
2600
  }
2455
2601
  if (obj.originX !== "center") {
2456
2602
  updates.originX = "center";
@@ -2458,6 +2604,7 @@ var ImageTool = class {
2458
2604
  }
2459
2605
  if (Object.keys(updates).length > 0) {
2460
2606
  obj.set(updates);
2607
+ obj.setCoords();
2461
2608
  }
2462
2609
  }
2463
2610
  loadImage(item, layer, layout) {
@@ -2477,18 +2624,10 @@ var ImageTool = class {
2477
2624
  ml: false,
2478
2625
  mr: false
2479
2626
  });
2480
- let { width, height, left, top } = item;
2481
- const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight, bleedOffset } = layout;
2482
- if (width === void 0 && height === void 0) {
2483
- const targetWidth = dielinePhysicalWidth + 2 * bleedOffset;
2484
- const targetHeight = dielinePhysicalHeight + 2 * bleedOffset;
2485
- const targetMax = Math.max(targetWidth, targetHeight);
2486
- const imageMax = Math.max(image.width || 1, image.height || 1);
2487
- const scale = targetMax / imageMax;
2488
- width = (image.width || 1) * scale;
2489
- height = (image.height || 1) * scale;
2490
- item.width = width;
2491
- item.height = height;
2627
+ let { scale, left, top } = item;
2628
+ if (scale === void 0) {
2629
+ scale = 1;
2630
+ item.scale = scale;
2492
2631
  }
2493
2632
  if (left === void 0 && top === void 0) {
2494
2633
  left = 0.5;
@@ -2499,13 +2638,18 @@ var ImageTool = class {
2499
2638
  this.updateObjectProperties(image, item, layout);
2500
2639
  layer.add(image);
2501
2640
  this.objectMap.set(item.id, image);
2641
+ const resolver = this.loadResolvers.get(item.id);
2642
+ if (resolver) {
2643
+ resolver();
2644
+ this.loadResolvers.delete(item.id);
2645
+ }
2502
2646
  image.on("modified", (e) => {
2503
2647
  this.handleObjectModified(item.id, image);
2504
2648
  });
2505
2649
  layer.dirty = true;
2506
2650
  (_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
2507
- if (item.width !== width || item.height !== height || item.left !== left || item.top !== top) {
2508
- this.updateImageInConfig(item.id, { width, height, left, top });
2651
+ if (item.scale !== scale || item.left !== left || item.top !== top) {
2652
+ this.updateImageInConfig(item.id, { scale, left, top }, true);
2509
2653
  }
2510
2654
  }).catch((err) => {
2511
2655
  console.error("Failed to load image", item.url, err);
@@ -2513,29 +2657,28 @@ var ImageTool = class {
2513
2657
  }
2514
2658
  handleObjectModified(id, image) {
2515
2659
  const layout = this.getLayoutInfo();
2516
- const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight } = layout;
2660
+ const {
2661
+ layoutScale,
2662
+ layoutOffsetX,
2663
+ layoutOffsetY,
2664
+ visualWidth,
2665
+ visualHeight
2666
+ } = layout;
2517
2667
  const matrix = image.calcTransformMatrix();
2518
2668
  const globalPoint = import_fabric5.util.transformPoint(new import_fabric5.Point(0, 0), matrix);
2519
2669
  const updates = {};
2520
2670
  updates.left = (globalPoint.x - layoutOffsetX) / visualWidth;
2521
2671
  updates.top = (globalPoint.y - layoutOffsetY) / visualHeight;
2522
2672
  updates.angle = image.angle;
2523
- if (image.width) {
2524
- const pixelWidth = image.width * image.scaleX;
2525
- updates.width = pixelWidth / layoutScale;
2526
- }
2527
- if (image.height) {
2528
- const pixelHeight = image.height * image.scaleY;
2529
- updates.height = pixelHeight / layoutScale;
2530
- }
2531
- this.updateImageInConfig(id, updates);
2673
+ updates.scale = image.scaleX / layoutScale;
2674
+ this.updateImageInConfig(id, updates, true);
2532
2675
  }
2533
- updateImageInConfig(id, updates) {
2676
+ updateImageInConfig(id, updates, skipCanvasUpdate = false) {
2534
2677
  const index = this.items.findIndex((i) => i.id === id);
2535
2678
  if (index !== -1) {
2536
2679
  const newItems = [...this.items];
2537
2680
  newItems[index] = { ...newItems[index], ...updates };
2538
- this.updateConfig(newItems, true);
2681
+ this.updateConfig(newItems, skipCanvasUpdate);
2539
2682
  }
2540
2683
  }
2541
2684
  };