@pooder/kit 5.0.0 → 5.0.1
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/.test-dist/src/dieline.js +118 -23
- package/.test-dist/src/feature.js +2 -0
- package/CHANGELOG.md +6 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +125 -33
- package/dist/index.mjs +128 -36
- package/package.json +1 -1
- package/src/dieline.ts +132 -24
|
@@ -7,6 +7,7 @@ const tracer_1 = require("./tracer");
|
|
|
7
7
|
const units_1 = require("./units");
|
|
8
8
|
const geometry_1 = require("./geometry");
|
|
9
9
|
const sceneLayoutModel_1 = require("./sceneLayoutModel");
|
|
10
|
+
const IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
10
11
|
class DielineTool {
|
|
11
12
|
constructor(options) {
|
|
12
13
|
this.id = "pooder.kit.dieline";
|
|
@@ -314,8 +315,8 @@ class DielineTool {
|
|
|
314
315
|
{
|
|
315
316
|
command: "exportCutImage",
|
|
316
317
|
title: "Export Cut Image",
|
|
317
|
-
handler: () => {
|
|
318
|
-
return this.exportCutImage();
|
|
318
|
+
handler: (options) => {
|
|
319
|
+
return this.exportCutImage(options);
|
|
319
320
|
},
|
|
320
321
|
},
|
|
321
322
|
{
|
|
@@ -445,6 +446,15 @@ class DielineTool {
|
|
|
445
446
|
? -sizeState.cutMarginMm
|
|
446
447
|
: 0;
|
|
447
448
|
}
|
|
449
|
+
bringFeatureMarkersToFront() {
|
|
450
|
+
if (!this.canvasService)
|
|
451
|
+
return;
|
|
452
|
+
const canvas = this.canvasService.canvas;
|
|
453
|
+
canvas
|
|
454
|
+
.getObjects()
|
|
455
|
+
.filter((obj) => obj?.data?.type === "feature-marker")
|
|
456
|
+
.forEach((obj) => canvas.bringObjectToFront(obj));
|
|
457
|
+
}
|
|
448
458
|
updateDieline(_emitEvent = true) {
|
|
449
459
|
if (!this.canvasService)
|
|
450
460
|
return;
|
|
@@ -632,6 +642,8 @@ class DielineTool {
|
|
|
632
642
|
else {
|
|
633
643
|
this.canvasService.canvas.bringObjectToFront(layer);
|
|
634
644
|
}
|
|
645
|
+
// Feature tool markers can extend outside trim. Keep them above dieline mask.
|
|
646
|
+
this.bringFeatureMarkersToFront();
|
|
635
647
|
const rulerLayer = this.canvasService.getLayer("ruler-overlay");
|
|
636
648
|
if (rulerLayer) {
|
|
637
649
|
this.canvasService.canvas.bringObjectToFront(rulerLayer);
|
|
@@ -655,19 +667,23 @@ class DielineTool {
|
|
|
655
667
|
pathData: this.state.pathData,
|
|
656
668
|
};
|
|
657
669
|
}
|
|
658
|
-
async exportCutImage() {
|
|
659
|
-
|
|
670
|
+
async exportCutImage(options) {
|
|
671
|
+
const debug = options?.debug === true;
|
|
672
|
+
if (!this.canvasService) {
|
|
673
|
+
console.warn("[DielineTool] exportCutImage returned null: canvas-not-ready");
|
|
660
674
|
return null;
|
|
675
|
+
}
|
|
661
676
|
const configService = this.getConfigService();
|
|
662
|
-
if (!configService)
|
|
663
|
-
|
|
664
|
-
const userLayer = this.canvasService.getLayer("user");
|
|
665
|
-
if (!userLayer)
|
|
677
|
+
if (!configService) {
|
|
678
|
+
console.warn("[DielineTool] exportCutImage returned null: config-service-not-ready");
|
|
666
679
|
return null;
|
|
680
|
+
}
|
|
667
681
|
this.syncSizeState(configService);
|
|
668
682
|
const sceneLayout = (0, sceneLayoutModel_1.computeSceneLayout)(this.canvasService, (0, sceneLayoutModel_1.readSizeState)(configService));
|
|
669
|
-
if (!sceneLayout)
|
|
683
|
+
if (!sceneLayout) {
|
|
684
|
+
console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
|
|
670
685
|
return null;
|
|
686
|
+
}
|
|
671
687
|
const { shape, radius, features, pathData } = this.state;
|
|
672
688
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
673
689
|
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
@@ -700,24 +716,103 @@ class DielineTool {
|
|
|
700
716
|
canvasWidth: canvasW,
|
|
701
717
|
canvasHeight: canvasH,
|
|
702
718
|
});
|
|
703
|
-
const clonedLayer = await userLayer.clone();
|
|
704
719
|
const clipPath = new fabric_1.Path(generatedPathData, {
|
|
705
|
-
originX: "
|
|
706
|
-
originY: "
|
|
707
|
-
left:
|
|
708
|
-
top:
|
|
720
|
+
originX: "center",
|
|
721
|
+
originY: "center",
|
|
722
|
+
left: cx,
|
|
723
|
+
top: cy,
|
|
709
724
|
absolutePositioned: true,
|
|
710
725
|
});
|
|
711
|
-
|
|
712
|
-
const
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
726
|
+
const pathOffsetX = Number(clipPath?.pathOffset?.x);
|
|
727
|
+
const pathOffsetY = Number(clipPath?.pathOffset?.y);
|
|
728
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
729
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
730
|
+
clipPath.set({
|
|
731
|
+
originX: "center",
|
|
732
|
+
originY: "center",
|
|
733
|
+
left: centerX,
|
|
734
|
+
top: centerY,
|
|
735
|
+
absolutePositioned: true,
|
|
720
736
|
});
|
|
737
|
+
clipPath.setCoords();
|
|
738
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
739
|
+
if (!Number.isFinite(pathBounds.left) ||
|
|
740
|
+
!Number.isFinite(pathBounds.top) ||
|
|
741
|
+
!Number.isFinite(pathBounds.width) ||
|
|
742
|
+
!Number.isFinite(pathBounds.height) ||
|
|
743
|
+
pathBounds.width <= 0 ||
|
|
744
|
+
pathBounds.height <= 0) {
|
|
745
|
+
console.warn("[DielineTool] exportCutImage returned null: invalid-cut-bounds", {
|
|
746
|
+
bounds: pathBounds,
|
|
747
|
+
});
|
|
748
|
+
return null;
|
|
749
|
+
}
|
|
750
|
+
const exportBounds = pathBounds;
|
|
751
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
752
|
+
return obj?.data?.layerId === IMAGE_OBJECT_LAYER_ID;
|
|
753
|
+
});
|
|
754
|
+
if (!sourceImages.length) {
|
|
755
|
+
console.warn("[DielineTool] exportCutImage returned null: no-image-objects-on-canvas");
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
const sourceCanvasWidth = Number(this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW);
|
|
759
|
+
const sourceCanvasHeight = Number(this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH);
|
|
760
|
+
const el = document.createElement("canvas");
|
|
761
|
+
const exportCanvas = new fabric_1.Canvas(el, {
|
|
762
|
+
renderOnAddRemove: false,
|
|
763
|
+
selection: false,
|
|
764
|
+
enableRetinaScaling: false,
|
|
765
|
+
preserveObjectStacking: true,
|
|
766
|
+
});
|
|
767
|
+
exportCanvas.setDimensions({
|
|
768
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
769
|
+
height: Math.max(1, sourceCanvasHeight),
|
|
770
|
+
});
|
|
771
|
+
try {
|
|
772
|
+
for (const source of sourceImages) {
|
|
773
|
+
const clone = await source.clone();
|
|
774
|
+
clone.set({
|
|
775
|
+
selectable: false,
|
|
776
|
+
evented: false,
|
|
777
|
+
});
|
|
778
|
+
clone.setCoords();
|
|
779
|
+
exportCanvas.add(clone);
|
|
780
|
+
}
|
|
781
|
+
exportCanvas.clipPath = clipPath;
|
|
782
|
+
exportCanvas.renderAll();
|
|
783
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
784
|
+
format: "png",
|
|
785
|
+
multiplier: 2,
|
|
786
|
+
left: exportBounds.left,
|
|
787
|
+
top: exportBounds.top,
|
|
788
|
+
width: exportBounds.width,
|
|
789
|
+
height: exportBounds.height,
|
|
790
|
+
});
|
|
791
|
+
if (debug) {
|
|
792
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
793
|
+
sourceCount: sourceImages.length,
|
|
794
|
+
bounds: exportBounds,
|
|
795
|
+
rawPathBounds: pathBounds,
|
|
796
|
+
pathOffset: {
|
|
797
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
798
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null,
|
|
799
|
+
},
|
|
800
|
+
clipPathCenter: {
|
|
801
|
+
x: centerX,
|
|
802
|
+
y: centerY,
|
|
803
|
+
},
|
|
804
|
+
cutRect: sceneLayout.cutRect,
|
|
805
|
+
canvasSize: {
|
|
806
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
807
|
+
height: Math.max(1, sourceCanvasHeight),
|
|
808
|
+
},
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
return dataUrl;
|
|
812
|
+
}
|
|
813
|
+
finally {
|
|
814
|
+
exportCanvas.dispose();
|
|
815
|
+
}
|
|
721
816
|
}
|
|
722
817
|
}
|
|
723
818
|
exports.DielineTool = DielineTool;
|
package/CHANGELOG.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -133,7 +133,9 @@ declare class DielineTool implements Extension {
|
|
|
133
133
|
private bringFeatureMarkersToFront;
|
|
134
134
|
updateDieline(_emitEvent?: boolean): void;
|
|
135
135
|
getGeometry(): DielineGeometry | null;
|
|
136
|
-
exportCutImage(
|
|
136
|
+
exportCutImage(options?: {
|
|
137
|
+
debug?: boolean;
|
|
138
|
+
}): Promise<string | null>;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
declare class FilmTool implements Extension {
|
package/dist/index.d.ts
CHANGED
|
@@ -133,7 +133,9 @@ declare class DielineTool implements Extension {
|
|
|
133
133
|
private bringFeatureMarkersToFront;
|
|
134
134
|
updateDieline(_emitEvent?: boolean): void;
|
|
135
135
|
getGeometry(): DielineGeometry | null;
|
|
136
|
-
exportCutImage(
|
|
136
|
+
exportCutImage(options?: {
|
|
137
|
+
debug?: boolean;
|
|
138
|
+
}): Promise<string | null>;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
declare class FilmTool implements Extension {
|
package/dist/index.js
CHANGED
|
@@ -1811,6 +1811,7 @@ function buildSceneGeometry(configService, layout) {
|
|
|
1811
1811
|
}
|
|
1812
1812
|
|
|
1813
1813
|
// src/dieline.ts
|
|
1814
|
+
var IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
1814
1815
|
var DielineTool = class {
|
|
1815
1816
|
constructor(options) {
|
|
1816
1817
|
this.id = "pooder.kit.dieline";
|
|
@@ -2137,8 +2138,8 @@ var DielineTool = class {
|
|
|
2137
2138
|
{
|
|
2138
2139
|
command: "exportCutImage",
|
|
2139
2140
|
title: "Export Cut Image",
|
|
2140
|
-
handler: () => {
|
|
2141
|
-
return this.exportCutImage();
|
|
2141
|
+
handler: (options) => {
|
|
2142
|
+
return this.exportCutImage(options);
|
|
2142
2143
|
}
|
|
2143
2144
|
},
|
|
2144
2145
|
{
|
|
@@ -2478,18 +2479,29 @@ var DielineTool = class {
|
|
|
2478
2479
|
pathData: this.state.pathData
|
|
2479
2480
|
};
|
|
2480
2481
|
}
|
|
2481
|
-
async exportCutImage() {
|
|
2482
|
-
|
|
2482
|
+
async exportCutImage(options) {
|
|
2483
|
+
var _a, _b;
|
|
2484
|
+
const debug = (options == null ? void 0 : options.debug) === true;
|
|
2485
|
+
if (!this.canvasService) {
|
|
2486
|
+
console.warn("[DielineTool] exportCutImage returned null: canvas-not-ready");
|
|
2487
|
+
return null;
|
|
2488
|
+
}
|
|
2483
2489
|
const configService = this.getConfigService();
|
|
2484
|
-
if (!configService)
|
|
2485
|
-
|
|
2486
|
-
|
|
2490
|
+
if (!configService) {
|
|
2491
|
+
console.warn(
|
|
2492
|
+
"[DielineTool] exportCutImage returned null: config-service-not-ready"
|
|
2493
|
+
);
|
|
2494
|
+
return null;
|
|
2495
|
+
}
|
|
2487
2496
|
this.syncSizeState(configService);
|
|
2488
2497
|
const sceneLayout = computeSceneLayout(
|
|
2489
2498
|
this.canvasService,
|
|
2490
2499
|
readSizeState(configService)
|
|
2491
2500
|
);
|
|
2492
|
-
if (!sceneLayout)
|
|
2501
|
+
if (!sceneLayout) {
|
|
2502
|
+
console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
|
|
2503
|
+
return null;
|
|
2504
|
+
}
|
|
2493
2505
|
const { shape, radius, features, pathData } = this.state;
|
|
2494
2506
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
2495
2507
|
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
@@ -2522,24 +2534,104 @@ var DielineTool = class {
|
|
|
2522
2534
|
canvasWidth: canvasW,
|
|
2523
2535
|
canvasHeight: canvasH
|
|
2524
2536
|
});
|
|
2525
|
-
const clonedLayer = await userLayer.clone();
|
|
2526
2537
|
const clipPath = new import_fabric2.Path(generatedPathData, {
|
|
2527
|
-
originX: "
|
|
2528
|
-
originY: "
|
|
2529
|
-
left:
|
|
2530
|
-
top:
|
|
2538
|
+
originX: "center",
|
|
2539
|
+
originY: "center",
|
|
2540
|
+
left: cx,
|
|
2541
|
+
top: cy,
|
|
2531
2542
|
absolutePositioned: true
|
|
2532
2543
|
});
|
|
2533
|
-
|
|
2534
|
-
const
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2544
|
+
const pathOffsetX = Number((_a = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _a.x);
|
|
2545
|
+
const pathOffsetY = Number((_b = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _b.y);
|
|
2546
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
2547
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
2548
|
+
clipPath.set({
|
|
2549
|
+
originX: "center",
|
|
2550
|
+
originY: "center",
|
|
2551
|
+
left: centerX,
|
|
2552
|
+
top: centerY,
|
|
2553
|
+
absolutePositioned: true
|
|
2554
|
+
});
|
|
2555
|
+
clipPath.setCoords();
|
|
2556
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
2557
|
+
if (!Number.isFinite(pathBounds.left) || !Number.isFinite(pathBounds.top) || !Number.isFinite(pathBounds.width) || !Number.isFinite(pathBounds.height) || pathBounds.width <= 0 || pathBounds.height <= 0) {
|
|
2558
|
+
console.warn("[DielineTool] exportCutImage returned null: invalid-cut-bounds", {
|
|
2559
|
+
bounds: pathBounds
|
|
2560
|
+
});
|
|
2561
|
+
return null;
|
|
2562
|
+
}
|
|
2563
|
+
const exportBounds = pathBounds;
|
|
2564
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
2565
|
+
var _a2;
|
|
2566
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID;
|
|
2567
|
+
});
|
|
2568
|
+
if (!sourceImages.length) {
|
|
2569
|
+
console.warn(
|
|
2570
|
+
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas"
|
|
2571
|
+
);
|
|
2572
|
+
return null;
|
|
2573
|
+
}
|
|
2574
|
+
const sourceCanvasWidth = Number(
|
|
2575
|
+
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW
|
|
2576
|
+
);
|
|
2577
|
+
const sourceCanvasHeight = Number(
|
|
2578
|
+
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH
|
|
2579
|
+
);
|
|
2580
|
+
const el = document.createElement("canvas");
|
|
2581
|
+
const exportCanvas = new import_fabric2.Canvas(el, {
|
|
2582
|
+
renderOnAddRemove: false,
|
|
2583
|
+
selection: false,
|
|
2584
|
+
enableRetinaScaling: false,
|
|
2585
|
+
preserveObjectStacking: true
|
|
2586
|
+
});
|
|
2587
|
+
exportCanvas.setDimensions({
|
|
2588
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
2589
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
2542
2590
|
});
|
|
2591
|
+
try {
|
|
2592
|
+
for (const source of sourceImages) {
|
|
2593
|
+
const clone = await source.clone();
|
|
2594
|
+
clone.set({
|
|
2595
|
+
selectable: false,
|
|
2596
|
+
evented: false
|
|
2597
|
+
});
|
|
2598
|
+
clone.setCoords();
|
|
2599
|
+
exportCanvas.add(clone);
|
|
2600
|
+
}
|
|
2601
|
+
exportCanvas.clipPath = clipPath;
|
|
2602
|
+
exportCanvas.renderAll();
|
|
2603
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
2604
|
+
format: "png",
|
|
2605
|
+
multiplier: 2,
|
|
2606
|
+
left: exportBounds.left,
|
|
2607
|
+
top: exportBounds.top,
|
|
2608
|
+
width: exportBounds.width,
|
|
2609
|
+
height: exportBounds.height
|
|
2610
|
+
});
|
|
2611
|
+
if (debug) {
|
|
2612
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
2613
|
+
sourceCount: sourceImages.length,
|
|
2614
|
+
bounds: exportBounds,
|
|
2615
|
+
rawPathBounds: pathBounds,
|
|
2616
|
+
pathOffset: {
|
|
2617
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
2618
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null
|
|
2619
|
+
},
|
|
2620
|
+
clipPathCenter: {
|
|
2621
|
+
x: centerX,
|
|
2622
|
+
y: centerY
|
|
2623
|
+
},
|
|
2624
|
+
cutRect: sceneLayout.cutRect,
|
|
2625
|
+
canvasSize: {
|
|
2626
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
2627
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
2628
|
+
}
|
|
2629
|
+
});
|
|
2630
|
+
}
|
|
2631
|
+
return dataUrl;
|
|
2632
|
+
} finally {
|
|
2633
|
+
exportCanvas.dispose();
|
|
2634
|
+
}
|
|
2543
2635
|
}
|
|
2544
2636
|
};
|
|
2545
2637
|
|
|
@@ -3625,7 +3717,7 @@ var FeatureTool = class {
|
|
|
3625
3717
|
// src/image.ts
|
|
3626
3718
|
var import_core5 = require("@pooder/core");
|
|
3627
3719
|
var import_fabric5 = require("fabric");
|
|
3628
|
-
var
|
|
3720
|
+
var IMAGE_OBJECT_LAYER_ID2 = "image.user";
|
|
3629
3721
|
var IMAGE_OVERLAY_LAYER_ID = "image-overlay";
|
|
3630
3722
|
var IMAGE_REPLACE_GUARD_MS = 2500;
|
|
3631
3723
|
var ImageTool = class {
|
|
@@ -3685,7 +3777,7 @@ var ImageTool = class {
|
|
|
3685
3777
|
const selectedImage = list.find(
|
|
3686
3778
|
(obj) => {
|
|
3687
3779
|
var _a2;
|
|
3688
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) ===
|
|
3780
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID2;
|
|
3689
3781
|
}
|
|
3690
3782
|
);
|
|
3691
3783
|
this.isImageSelectionActive = !!selectedImage;
|
|
@@ -3724,7 +3816,7 @@ var ImageTool = class {
|
|
|
3724
3816
|
const target = e == null ? void 0 : e.target;
|
|
3725
3817
|
const id = (_a = target == null ? void 0 : target.data) == null ? void 0 : _a.id;
|
|
3726
3818
|
const layerId = (_b = target == null ? void 0 : target.data) == null ? void 0 : _b.layerId;
|
|
3727
|
-
if (typeof id !== "string" || layerId !==
|
|
3819
|
+
if (typeof id !== "string" || layerId !== IMAGE_OBJECT_LAYER_ID2) return;
|
|
3728
3820
|
const frame = this.getFrameRect();
|
|
3729
3821
|
if (!frame.width || !frame.height) return;
|
|
3730
3822
|
const center = target.getCenterPoint ? target.getCenterPoint() : new import_fabric5.Point((_c = target.left) != null ? _c : 0, (_d = target.top) != null ? _d : 0);
|
|
@@ -4073,7 +4165,7 @@ var ImageTool = class {
|
|
|
4073
4165
|
getImageIdFromActiveObject() {
|
|
4074
4166
|
var _a, _b, _c;
|
|
4075
4167
|
const active = (_a = this.canvasService) == null ? void 0 : _a.canvas.getActiveObject();
|
|
4076
|
-
if (((_b = active == null ? void 0 : active.data) == null ? void 0 : _b.layerId) ===
|
|
4168
|
+
if (((_b = active == null ? void 0 : active.data) == null ? void 0 : _b.layerId) === IMAGE_OBJECT_LAYER_ID2 && typeof ((_c = active == null ? void 0 : active.data) == null ? void 0 : _c.id) === "string") {
|
|
4077
4169
|
return active.data.id;
|
|
4078
4170
|
}
|
|
4079
4171
|
return null;
|
|
@@ -4242,7 +4334,7 @@ var ImageTool = class {
|
|
|
4242
4334
|
if (!this.canvasService) return [];
|
|
4243
4335
|
return this.canvasService.canvas.getObjects().filter((obj) => {
|
|
4244
4336
|
var _a;
|
|
4245
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) ===
|
|
4337
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID2;
|
|
4246
4338
|
});
|
|
4247
4339
|
}
|
|
4248
4340
|
getOverlayObjects() {
|
|
@@ -4398,7 +4490,7 @@ var ImageTool = class {
|
|
|
4398
4490
|
created.set({
|
|
4399
4491
|
data: {
|
|
4400
4492
|
id: item.id,
|
|
4401
|
-
layerId:
|
|
4493
|
+
layerId: IMAGE_OBJECT_LAYER_ID2,
|
|
4402
4494
|
type: "image-item"
|
|
4403
4495
|
}
|
|
4404
4496
|
});
|
|
@@ -4413,7 +4505,7 @@ var ImageTool = class {
|
|
|
4413
4505
|
data: {
|
|
4414
4506
|
...obj.data || {},
|
|
4415
4507
|
id: item.id,
|
|
4416
|
-
layerId:
|
|
4508
|
+
layerId: IMAGE_OBJECT_LAYER_ID2,
|
|
4417
4509
|
type: "image-item"
|
|
4418
4510
|
}
|
|
4419
4511
|
});
|
|
@@ -4817,7 +4909,7 @@ var ImageTool = class {
|
|
|
4817
4909
|
const idSet = new Set(imageIds);
|
|
4818
4910
|
const sourceObjects = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
4819
4911
|
var _a2, _b2;
|
|
4820
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) ===
|
|
4912
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID2 && typeof ((_b2 = obj == null ? void 0 : obj.data) == null ? void 0 : _b2.id) === "string" && idSet.has(obj.data.id);
|
|
4821
4913
|
});
|
|
4822
4914
|
for (const source of sourceObjects) {
|
|
4823
4915
|
const clone = await source.clone();
|
|
@@ -4862,7 +4954,7 @@ var ImageTool = class {
|
|
|
4862
4954
|
var import_core6 = require("@pooder/core");
|
|
4863
4955
|
var import_fabric6 = require("fabric");
|
|
4864
4956
|
var WHITE_INK_OBJECT_LAYER_ID = "white-ink.user";
|
|
4865
|
-
var
|
|
4957
|
+
var IMAGE_OBJECT_LAYER_ID3 = "image.user";
|
|
4866
4958
|
var WHITE_INK_DEBUG_KEY = "whiteInk.debug";
|
|
4867
4959
|
var WHITE_INK_PREVIEW_IMAGE_VISIBLE_KEY = "whiteInk.previewImageVisible";
|
|
4868
4960
|
var WHITE_INK_DEFAULT_OPACITY = 0.85;
|
|
@@ -5563,7 +5655,7 @@ var WhiteInkTool = class {
|
|
|
5563
5655
|
const imageIndexes = objects.map(
|
|
5564
5656
|
(obj, index) => {
|
|
5565
5657
|
var _a;
|
|
5566
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) ===
|
|
5658
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID3 ? index : -1;
|
|
5567
5659
|
}
|
|
5568
5660
|
).filter((index) => index >= 0);
|
|
5569
5661
|
if (imageIndexes.length > 0) {
|
|
@@ -5596,7 +5688,7 @@ var WhiteInkTool = class {
|
|
|
5596
5688
|
let changed = false;
|
|
5597
5689
|
this.canvasService.canvas.getObjects().forEach((obj) => {
|
|
5598
5690
|
var _a, _b;
|
|
5599
|
-
if (((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) !==
|
|
5691
|
+
if (((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) !== IMAGE_OBJECT_LAYER_ID3) return;
|
|
5600
5692
|
if (obj.visible === visible) return;
|
|
5601
5693
|
obj.set({ visible });
|
|
5602
5694
|
(_b = obj.setCoords) == null ? void 0 : _b.call(obj);
|
package/dist/index.mjs
CHANGED
|
@@ -205,7 +205,7 @@ var BackgroundTool = class {
|
|
|
205
205
|
import {
|
|
206
206
|
ContributionPointIds as ContributionPointIds2
|
|
207
207
|
} from "@pooder/core";
|
|
208
|
-
import { Path, Pattern } from "fabric";
|
|
208
|
+
import { Canvas as FabricCanvas, Path, Pattern } from "fabric";
|
|
209
209
|
|
|
210
210
|
// src/tracer.ts
|
|
211
211
|
import paper from "paper";
|
|
@@ -1756,6 +1756,7 @@ function buildSceneGeometry(configService, layout) {
|
|
|
1756
1756
|
}
|
|
1757
1757
|
|
|
1758
1758
|
// src/dieline.ts
|
|
1759
|
+
var IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
1759
1760
|
var DielineTool = class {
|
|
1760
1761
|
constructor(options) {
|
|
1761
1762
|
this.id = "pooder.kit.dieline";
|
|
@@ -2082,8 +2083,8 @@ var DielineTool = class {
|
|
|
2082
2083
|
{
|
|
2083
2084
|
command: "exportCutImage",
|
|
2084
2085
|
title: "Export Cut Image",
|
|
2085
|
-
handler: () => {
|
|
2086
|
-
return this.exportCutImage();
|
|
2086
|
+
handler: (options) => {
|
|
2087
|
+
return this.exportCutImage(options);
|
|
2087
2088
|
}
|
|
2088
2089
|
},
|
|
2089
2090
|
{
|
|
@@ -2423,18 +2424,29 @@ var DielineTool = class {
|
|
|
2423
2424
|
pathData: this.state.pathData
|
|
2424
2425
|
};
|
|
2425
2426
|
}
|
|
2426
|
-
async exportCutImage() {
|
|
2427
|
-
|
|
2427
|
+
async exportCutImage(options) {
|
|
2428
|
+
var _a, _b;
|
|
2429
|
+
const debug = (options == null ? void 0 : options.debug) === true;
|
|
2430
|
+
if (!this.canvasService) {
|
|
2431
|
+
console.warn("[DielineTool] exportCutImage returned null: canvas-not-ready");
|
|
2432
|
+
return null;
|
|
2433
|
+
}
|
|
2428
2434
|
const configService = this.getConfigService();
|
|
2429
|
-
if (!configService)
|
|
2430
|
-
|
|
2431
|
-
|
|
2435
|
+
if (!configService) {
|
|
2436
|
+
console.warn(
|
|
2437
|
+
"[DielineTool] exportCutImage returned null: config-service-not-ready"
|
|
2438
|
+
);
|
|
2439
|
+
return null;
|
|
2440
|
+
}
|
|
2432
2441
|
this.syncSizeState(configService);
|
|
2433
2442
|
const sceneLayout = computeSceneLayout(
|
|
2434
2443
|
this.canvasService,
|
|
2435
2444
|
readSizeState(configService)
|
|
2436
2445
|
);
|
|
2437
|
-
if (!sceneLayout)
|
|
2446
|
+
if (!sceneLayout) {
|
|
2447
|
+
console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
|
|
2448
|
+
return null;
|
|
2449
|
+
}
|
|
2438
2450
|
const { shape, radius, features, pathData } = this.state;
|
|
2439
2451
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
2440
2452
|
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
@@ -2467,24 +2479,104 @@ var DielineTool = class {
|
|
|
2467
2479
|
canvasWidth: canvasW,
|
|
2468
2480
|
canvasHeight: canvasH
|
|
2469
2481
|
});
|
|
2470
|
-
const clonedLayer = await userLayer.clone();
|
|
2471
2482
|
const clipPath = new Path(generatedPathData, {
|
|
2472
|
-
originX: "
|
|
2473
|
-
originY: "
|
|
2474
|
-
left:
|
|
2475
|
-
top:
|
|
2483
|
+
originX: "center",
|
|
2484
|
+
originY: "center",
|
|
2485
|
+
left: cx,
|
|
2486
|
+
top: cy,
|
|
2476
2487
|
absolutePositioned: true
|
|
2477
2488
|
});
|
|
2478
|
-
|
|
2479
|
-
const
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2489
|
+
const pathOffsetX = Number((_a = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _a.x);
|
|
2490
|
+
const pathOffsetY = Number((_b = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _b.y);
|
|
2491
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
2492
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
2493
|
+
clipPath.set({
|
|
2494
|
+
originX: "center",
|
|
2495
|
+
originY: "center",
|
|
2496
|
+
left: centerX,
|
|
2497
|
+
top: centerY,
|
|
2498
|
+
absolutePositioned: true
|
|
2499
|
+
});
|
|
2500
|
+
clipPath.setCoords();
|
|
2501
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
2502
|
+
if (!Number.isFinite(pathBounds.left) || !Number.isFinite(pathBounds.top) || !Number.isFinite(pathBounds.width) || !Number.isFinite(pathBounds.height) || pathBounds.width <= 0 || pathBounds.height <= 0) {
|
|
2503
|
+
console.warn("[DielineTool] exportCutImage returned null: invalid-cut-bounds", {
|
|
2504
|
+
bounds: pathBounds
|
|
2505
|
+
});
|
|
2506
|
+
return null;
|
|
2507
|
+
}
|
|
2508
|
+
const exportBounds = pathBounds;
|
|
2509
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
2510
|
+
var _a2;
|
|
2511
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID;
|
|
2512
|
+
});
|
|
2513
|
+
if (!sourceImages.length) {
|
|
2514
|
+
console.warn(
|
|
2515
|
+
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas"
|
|
2516
|
+
);
|
|
2517
|
+
return null;
|
|
2518
|
+
}
|
|
2519
|
+
const sourceCanvasWidth = Number(
|
|
2520
|
+
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW
|
|
2521
|
+
);
|
|
2522
|
+
const sourceCanvasHeight = Number(
|
|
2523
|
+
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH
|
|
2524
|
+
);
|
|
2525
|
+
const el = document.createElement("canvas");
|
|
2526
|
+
const exportCanvas = new FabricCanvas(el, {
|
|
2527
|
+
renderOnAddRemove: false,
|
|
2528
|
+
selection: false,
|
|
2529
|
+
enableRetinaScaling: false,
|
|
2530
|
+
preserveObjectStacking: true
|
|
2531
|
+
});
|
|
2532
|
+
exportCanvas.setDimensions({
|
|
2533
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
2534
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
2487
2535
|
});
|
|
2536
|
+
try {
|
|
2537
|
+
for (const source of sourceImages) {
|
|
2538
|
+
const clone = await source.clone();
|
|
2539
|
+
clone.set({
|
|
2540
|
+
selectable: false,
|
|
2541
|
+
evented: false
|
|
2542
|
+
});
|
|
2543
|
+
clone.setCoords();
|
|
2544
|
+
exportCanvas.add(clone);
|
|
2545
|
+
}
|
|
2546
|
+
exportCanvas.clipPath = clipPath;
|
|
2547
|
+
exportCanvas.renderAll();
|
|
2548
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
2549
|
+
format: "png",
|
|
2550
|
+
multiplier: 2,
|
|
2551
|
+
left: exportBounds.left,
|
|
2552
|
+
top: exportBounds.top,
|
|
2553
|
+
width: exportBounds.width,
|
|
2554
|
+
height: exportBounds.height
|
|
2555
|
+
});
|
|
2556
|
+
if (debug) {
|
|
2557
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
2558
|
+
sourceCount: sourceImages.length,
|
|
2559
|
+
bounds: exportBounds,
|
|
2560
|
+
rawPathBounds: pathBounds,
|
|
2561
|
+
pathOffset: {
|
|
2562
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
2563
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null
|
|
2564
|
+
},
|
|
2565
|
+
clipPathCenter: {
|
|
2566
|
+
x: centerX,
|
|
2567
|
+
y: centerY
|
|
2568
|
+
},
|
|
2569
|
+
cutRect: sceneLayout.cutRect,
|
|
2570
|
+
canvasSize: {
|
|
2571
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
2572
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
2573
|
+
}
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
return dataUrl;
|
|
2577
|
+
} finally {
|
|
2578
|
+
exportCanvas.dispose();
|
|
2579
|
+
}
|
|
2488
2580
|
}
|
|
2489
2581
|
};
|
|
2490
2582
|
|
|
@@ -3575,8 +3667,8 @@ var FeatureTool = class {
|
|
|
3575
3667
|
import {
|
|
3576
3668
|
ContributionPointIds as ContributionPointIds5
|
|
3577
3669
|
} from "@pooder/core";
|
|
3578
|
-
import { Canvas as
|
|
3579
|
-
var
|
|
3670
|
+
import { Canvas as FabricCanvas2, Image as FabricImage, Point as Point2 } from "fabric";
|
|
3671
|
+
var IMAGE_OBJECT_LAYER_ID2 = "image.user";
|
|
3580
3672
|
var IMAGE_OVERLAY_LAYER_ID = "image-overlay";
|
|
3581
3673
|
var IMAGE_REPLACE_GUARD_MS = 2500;
|
|
3582
3674
|
var ImageTool = class {
|
|
@@ -3636,7 +3728,7 @@ var ImageTool = class {
|
|
|
3636
3728
|
const selectedImage = list.find(
|
|
3637
3729
|
(obj) => {
|
|
3638
3730
|
var _a2;
|
|
3639
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) ===
|
|
3731
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID2;
|
|
3640
3732
|
}
|
|
3641
3733
|
);
|
|
3642
3734
|
this.isImageSelectionActive = !!selectedImage;
|
|
@@ -3675,7 +3767,7 @@ var ImageTool = class {
|
|
|
3675
3767
|
const target = e == null ? void 0 : e.target;
|
|
3676
3768
|
const id = (_a = target == null ? void 0 : target.data) == null ? void 0 : _a.id;
|
|
3677
3769
|
const layerId = (_b = target == null ? void 0 : target.data) == null ? void 0 : _b.layerId;
|
|
3678
|
-
if (typeof id !== "string" || layerId !==
|
|
3770
|
+
if (typeof id !== "string" || layerId !== IMAGE_OBJECT_LAYER_ID2) return;
|
|
3679
3771
|
const frame = this.getFrameRect();
|
|
3680
3772
|
if (!frame.width || !frame.height) return;
|
|
3681
3773
|
const center = target.getCenterPoint ? target.getCenterPoint() : new Point2((_c = target.left) != null ? _c : 0, (_d = target.top) != null ? _d : 0);
|
|
@@ -4024,7 +4116,7 @@ var ImageTool = class {
|
|
|
4024
4116
|
getImageIdFromActiveObject() {
|
|
4025
4117
|
var _a, _b, _c;
|
|
4026
4118
|
const active = (_a = this.canvasService) == null ? void 0 : _a.canvas.getActiveObject();
|
|
4027
|
-
if (((_b = active == null ? void 0 : active.data) == null ? void 0 : _b.layerId) ===
|
|
4119
|
+
if (((_b = active == null ? void 0 : active.data) == null ? void 0 : _b.layerId) === IMAGE_OBJECT_LAYER_ID2 && typeof ((_c = active == null ? void 0 : active.data) == null ? void 0 : _c.id) === "string") {
|
|
4028
4120
|
return active.data.id;
|
|
4029
4121
|
}
|
|
4030
4122
|
return null;
|
|
@@ -4193,7 +4285,7 @@ var ImageTool = class {
|
|
|
4193
4285
|
if (!this.canvasService) return [];
|
|
4194
4286
|
return this.canvasService.canvas.getObjects().filter((obj) => {
|
|
4195
4287
|
var _a;
|
|
4196
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) ===
|
|
4288
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID2;
|
|
4197
4289
|
});
|
|
4198
4290
|
}
|
|
4199
4291
|
getOverlayObjects() {
|
|
@@ -4349,7 +4441,7 @@ var ImageTool = class {
|
|
|
4349
4441
|
created.set({
|
|
4350
4442
|
data: {
|
|
4351
4443
|
id: item.id,
|
|
4352
|
-
layerId:
|
|
4444
|
+
layerId: IMAGE_OBJECT_LAYER_ID2,
|
|
4353
4445
|
type: "image-item"
|
|
4354
4446
|
}
|
|
4355
4447
|
});
|
|
@@ -4364,7 +4456,7 @@ var ImageTool = class {
|
|
|
4364
4456
|
data: {
|
|
4365
4457
|
...obj.data || {},
|
|
4366
4458
|
id: item.id,
|
|
4367
|
-
layerId:
|
|
4459
|
+
layerId: IMAGE_OBJECT_LAYER_ID2,
|
|
4368
4460
|
type: "image-item"
|
|
4369
4461
|
}
|
|
4370
4462
|
});
|
|
@@ -4758,7 +4850,7 @@ var ImageTool = class {
|
|
|
4758
4850
|
const width = Math.max(1, Math.round(frame.width * multiplier));
|
|
4759
4851
|
const height = Math.max(1, Math.round(frame.height * multiplier));
|
|
4760
4852
|
const el = document.createElement("canvas");
|
|
4761
|
-
const tempCanvas = new
|
|
4853
|
+
const tempCanvas = new FabricCanvas2(el, {
|
|
4762
4854
|
renderOnAddRemove: false,
|
|
4763
4855
|
selection: false,
|
|
4764
4856
|
enableRetinaScaling: false,
|
|
@@ -4768,7 +4860,7 @@ var ImageTool = class {
|
|
|
4768
4860
|
const idSet = new Set(imageIds);
|
|
4769
4861
|
const sourceObjects = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
4770
4862
|
var _a2, _b2;
|
|
4771
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) ===
|
|
4863
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID2 && typeof ((_b2 = obj == null ? void 0 : obj.data) == null ? void 0 : _b2.id) === "string" && idSet.has(obj.data.id);
|
|
4772
4864
|
});
|
|
4773
4865
|
for (const source of sourceObjects) {
|
|
4774
4866
|
const clone = await source.clone();
|
|
@@ -4815,7 +4907,7 @@ import {
|
|
|
4815
4907
|
} from "@pooder/core";
|
|
4816
4908
|
import { Image as FabricImage2 } from "fabric";
|
|
4817
4909
|
var WHITE_INK_OBJECT_LAYER_ID = "white-ink.user";
|
|
4818
|
-
var
|
|
4910
|
+
var IMAGE_OBJECT_LAYER_ID3 = "image.user";
|
|
4819
4911
|
var WHITE_INK_DEBUG_KEY = "whiteInk.debug";
|
|
4820
4912
|
var WHITE_INK_PREVIEW_IMAGE_VISIBLE_KEY = "whiteInk.previewImageVisible";
|
|
4821
4913
|
var WHITE_INK_DEFAULT_OPACITY = 0.85;
|
|
@@ -5516,7 +5608,7 @@ var WhiteInkTool = class {
|
|
|
5516
5608
|
const imageIndexes = objects.map(
|
|
5517
5609
|
(obj, index) => {
|
|
5518
5610
|
var _a;
|
|
5519
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) ===
|
|
5611
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID3 ? index : -1;
|
|
5520
5612
|
}
|
|
5521
5613
|
).filter((index) => index >= 0);
|
|
5522
5614
|
if (imageIndexes.length > 0) {
|
|
@@ -5549,7 +5641,7 @@ var WhiteInkTool = class {
|
|
|
5549
5641
|
let changed = false;
|
|
5550
5642
|
this.canvasService.canvas.getObjects().forEach((obj) => {
|
|
5551
5643
|
var _a, _b;
|
|
5552
|
-
if (((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) !==
|
|
5644
|
+
if (((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) !== IMAGE_OBJECT_LAYER_ID3) return;
|
|
5553
5645
|
if (obj.visible === visible) return;
|
|
5554
5646
|
obj.set({ visible });
|
|
5555
5647
|
(_b = obj.setCoords) == null ? void 0 : _b.call(obj);
|
package/package.json
CHANGED
package/src/dieline.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ConfigurationContribution,
|
|
7
7
|
ConfigurationService,
|
|
8
8
|
} from "@pooder/core";
|
|
9
|
-
import { Path, Pattern } from "fabric";
|
|
9
|
+
import { Canvas as FabricCanvas, Path, Pattern } from "fabric";
|
|
10
10
|
import CanvasService from "./CanvasService";
|
|
11
11
|
import { ImageTracer } from "./tracer";
|
|
12
12
|
import { Unit } from "./coordinate";
|
|
@@ -63,6 +63,8 @@ export interface DielineState {
|
|
|
63
63
|
pathData?: string;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
const IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
67
|
+
|
|
66
68
|
export class DielineTool implements Extension {
|
|
67
69
|
id = "pooder.kit.dieline";
|
|
68
70
|
public metadata = {
|
|
@@ -424,8 +426,8 @@ export class DielineTool implements Extension {
|
|
|
424
426
|
{
|
|
425
427
|
command: "exportCutImage",
|
|
426
428
|
title: "Export Cut Image",
|
|
427
|
-
handler: () => {
|
|
428
|
-
return this.exportCutImage();
|
|
429
|
+
handler: (options?: { debug?: boolean }) => {
|
|
430
|
+
return this.exportCutImage(options);
|
|
429
431
|
},
|
|
430
432
|
},
|
|
431
433
|
{
|
|
@@ -824,19 +826,30 @@ export class DielineTool implements Extension {
|
|
|
824
826
|
} as DielineGeometry;
|
|
825
827
|
}
|
|
826
828
|
|
|
827
|
-
public async exportCutImage() {
|
|
828
|
-
|
|
829
|
+
public async exportCutImage(options?: { debug?: boolean }) {
|
|
830
|
+
const debug = options?.debug === true;
|
|
831
|
+
|
|
832
|
+
if (!this.canvasService) {
|
|
833
|
+
console.warn("[DielineTool] exportCutImage returned null: canvas-not-ready");
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
829
836
|
const configService = this.getConfigService();
|
|
830
|
-
if (!configService)
|
|
831
|
-
|
|
832
|
-
|
|
837
|
+
if (!configService) {
|
|
838
|
+
console.warn(
|
|
839
|
+
"[DielineTool] exportCutImage returned null: config-service-not-ready",
|
|
840
|
+
);
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
833
843
|
|
|
834
844
|
this.syncSizeState(configService);
|
|
835
845
|
const sceneLayout = computeSceneLayout(
|
|
836
846
|
this.canvasService,
|
|
837
847
|
readSizeState(configService),
|
|
838
848
|
);
|
|
839
|
-
if (!sceneLayout)
|
|
849
|
+
if (!sceneLayout) {
|
|
850
|
+
console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
840
853
|
|
|
841
854
|
const { shape, radius, features, pathData } = this.state;
|
|
842
855
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
@@ -874,24 +887,119 @@ export class DielineTool implements Extension {
|
|
|
874
887
|
canvasHeight: canvasH,
|
|
875
888
|
});
|
|
876
889
|
|
|
877
|
-
const clonedLayer = await userLayer.clone();
|
|
878
890
|
const clipPath = new Path(generatedPathData, {
|
|
879
|
-
originX: "
|
|
880
|
-
originY: "
|
|
881
|
-
left:
|
|
882
|
-
top:
|
|
891
|
+
originX: "center",
|
|
892
|
+
originY: "center",
|
|
893
|
+
left: cx,
|
|
894
|
+
top: cy,
|
|
883
895
|
absolutePositioned: true,
|
|
884
896
|
});
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
897
|
+
const pathOffsetX = Number((clipPath as any)?.pathOffset?.x);
|
|
898
|
+
const pathOffsetY = Number((clipPath as any)?.pathOffset?.y);
|
|
899
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
900
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
901
|
+
clipPath.set({
|
|
902
|
+
originX: "center",
|
|
903
|
+
originY: "center",
|
|
904
|
+
left: centerX,
|
|
905
|
+
top: centerY,
|
|
906
|
+
absolutePositioned: true,
|
|
895
907
|
});
|
|
908
|
+
clipPath.setCoords();
|
|
909
|
+
|
|
910
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
911
|
+
if (
|
|
912
|
+
!Number.isFinite(pathBounds.left) ||
|
|
913
|
+
!Number.isFinite(pathBounds.top) ||
|
|
914
|
+
!Number.isFinite(pathBounds.width) ||
|
|
915
|
+
!Number.isFinite(pathBounds.height) ||
|
|
916
|
+
pathBounds.width <= 0 ||
|
|
917
|
+
pathBounds.height <= 0
|
|
918
|
+
) {
|
|
919
|
+
console.warn("[DielineTool] exportCutImage returned null: invalid-cut-bounds", {
|
|
920
|
+
bounds: pathBounds,
|
|
921
|
+
});
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
const exportBounds = pathBounds;
|
|
925
|
+
|
|
926
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj: any) => {
|
|
927
|
+
return obj?.data?.layerId === IMAGE_OBJECT_LAYER_ID;
|
|
928
|
+
});
|
|
929
|
+
if (!sourceImages.length) {
|
|
930
|
+
console.warn(
|
|
931
|
+
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas",
|
|
932
|
+
);
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
const sourceCanvasWidth = Number(
|
|
937
|
+
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW,
|
|
938
|
+
);
|
|
939
|
+
const sourceCanvasHeight = Number(
|
|
940
|
+
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH,
|
|
941
|
+
);
|
|
942
|
+
|
|
943
|
+
const el = document.createElement("canvas");
|
|
944
|
+
const exportCanvas = new FabricCanvas(el, {
|
|
945
|
+
renderOnAddRemove: false,
|
|
946
|
+
selection: false,
|
|
947
|
+
enableRetinaScaling: false,
|
|
948
|
+
preserveObjectStacking: true,
|
|
949
|
+
} as any);
|
|
950
|
+
exportCanvas.setDimensions({
|
|
951
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
952
|
+
height: Math.max(1, sourceCanvasHeight),
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
try {
|
|
956
|
+
for (const source of sourceImages as any[]) {
|
|
957
|
+
const clone = await source.clone();
|
|
958
|
+
clone.set({
|
|
959
|
+
selectable: false,
|
|
960
|
+
evented: false,
|
|
961
|
+
});
|
|
962
|
+
clone.setCoords();
|
|
963
|
+
exportCanvas.add(clone);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
exportCanvas.clipPath = clipPath;
|
|
967
|
+
exportCanvas.renderAll();
|
|
968
|
+
|
|
969
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
970
|
+
format: "png",
|
|
971
|
+
multiplier: 2,
|
|
972
|
+
left: exportBounds.left,
|
|
973
|
+
top: exportBounds.top,
|
|
974
|
+
width: exportBounds.width,
|
|
975
|
+
height: exportBounds.height,
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
if (debug) {
|
|
979
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
980
|
+
sourceCount: sourceImages.length,
|
|
981
|
+
bounds: exportBounds,
|
|
982
|
+
rawPathBounds: pathBounds,
|
|
983
|
+
pathOffset: {
|
|
984
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
985
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null,
|
|
986
|
+
},
|
|
987
|
+
clipPathCenter: {
|
|
988
|
+
x: centerX,
|
|
989
|
+
y: centerY,
|
|
990
|
+
},
|
|
991
|
+
cutRect: sceneLayout.cutRect,
|
|
992
|
+
canvasSize: {
|
|
993
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
994
|
+
height: Math.max(1, sourceCanvasHeight),
|
|
995
|
+
},
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
return dataUrl;
|
|
1000
|
+
} finally {
|
|
1001
|
+
exportCanvas.dispose();
|
|
1002
|
+
}
|
|
896
1003
|
}
|
|
1004
|
+
|
|
897
1005
|
}
|