@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 +6 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +287 -144
- package/dist/index.mjs +287 -144
- package/package.json +1 -1
- package/src/image.ts +113 -138
- package/src/tracer.ts +278 -164
package/CHANGELOG.md
CHANGED
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
|
-
|
|
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
|
-
|
|
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
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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 {
|
|
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)
|
|
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.
|
|
2448
|
-
const
|
|
2449
|
-
if (Math.abs(obj.scaleX -
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
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 {
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
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.
|
|
2508
|
-
this.updateImageInConfig(item.id, {
|
|
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 {
|
|
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
|
-
|
|
2524
|
-
|
|
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,
|
|
2681
|
+
this.updateConfig(newItems, skipCanvasUpdate);
|
|
2539
2682
|
}
|
|
2540
2683
|
}
|
|
2541
2684
|
};
|