@pooder/kit 3.1.0 → 3.3.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 +17 -0
- package/dist/index.d.mts +40 -24
- package/dist/index.d.ts +40 -24
- package/dist/index.js +849 -557
- package/dist/index.mjs +854 -562
- package/package.json +2 -2
- package/src/coordinate.ts +57 -0
- package/src/dieline.ts +196 -129
- package/src/geometry.ts +56 -21
- package/src/hole.ts +163 -56
- package/src/image.ts +355 -363
- package/src/ruler.ts +295 -120
package/dist/index.mjs
CHANGED
|
@@ -394,6 +394,24 @@ var ImageTracer = class {
|
|
|
394
394
|
|
|
395
395
|
// src/coordinate.ts
|
|
396
396
|
var Coordinate = class {
|
|
397
|
+
/**
|
|
398
|
+
* Calculate layout to fit content within container while preserving aspect ratio.
|
|
399
|
+
*/
|
|
400
|
+
static calculateLayout(container, content, padding = 0) {
|
|
401
|
+
const availableWidth = Math.max(0, container.width - padding * 2);
|
|
402
|
+
const availableHeight = Math.max(0, container.height - padding * 2);
|
|
403
|
+
if (content.width === 0 || content.height === 0) {
|
|
404
|
+
return { scale: 1, offsetX: 0, offsetY: 0, width: 0, height: 0 };
|
|
405
|
+
}
|
|
406
|
+
const scaleX = availableWidth / content.width;
|
|
407
|
+
const scaleY = availableHeight / content.height;
|
|
408
|
+
const scale = Math.min(scaleX, scaleY);
|
|
409
|
+
const width = content.width * scale;
|
|
410
|
+
const height = content.height * scale;
|
|
411
|
+
const offsetX = (container.width - width) / 2;
|
|
412
|
+
const offsetY = (container.height - height) / 2;
|
|
413
|
+
return { scale, offsetX, offsetY, width, height };
|
|
414
|
+
}
|
|
397
415
|
/**
|
|
398
416
|
* Convert an absolute value to a normalized value (0-1).
|
|
399
417
|
* @param value Absolute value (e.g., pixels)
|
|
@@ -428,6 +446,21 @@ var Coordinate = class {
|
|
|
428
446
|
y: this.toAbsolute(point.y, size.height)
|
|
429
447
|
};
|
|
430
448
|
}
|
|
449
|
+
static convertUnit(value, from, to) {
|
|
450
|
+
if (from === to) return value;
|
|
451
|
+
const toMM = {
|
|
452
|
+
px: 0.264583,
|
|
453
|
+
// 1px = 0.264583mm (96 DPI)
|
|
454
|
+
mm: 1,
|
|
455
|
+
cm: 10,
|
|
456
|
+
in: 25.4
|
|
457
|
+
};
|
|
458
|
+
const mmValue = value * (from === "px" ? toMM.px : toMM[from] || 1);
|
|
459
|
+
if (to === "px") {
|
|
460
|
+
return mmValue / toMM.px;
|
|
461
|
+
}
|
|
462
|
+
return mmValue / (toMM[to] || 1);
|
|
463
|
+
}
|
|
431
464
|
};
|
|
432
465
|
|
|
433
466
|
// src/geometry.ts
|
|
@@ -484,9 +517,10 @@ function resolveHolePosition(hole, geometry, canvasSize) {
|
|
|
484
517
|
y: by + (hole.offsetY || 0)
|
|
485
518
|
};
|
|
486
519
|
} else if (hole.x !== void 0 && hole.y !== void 0) {
|
|
520
|
+
const { x, width, y, height } = geometry;
|
|
487
521
|
return {
|
|
488
|
-
x: hole.x *
|
|
489
|
-
y: hole.y *
|
|
522
|
+
x: hole.x * width + (x - width / 2) + (hole.offsetX || 0),
|
|
523
|
+
y: hole.y * height + (y - height / 2) + (hole.offsetY || 0)
|
|
490
524
|
};
|
|
491
525
|
}
|
|
492
526
|
return { x: 0, y: 0 };
|
|
@@ -540,12 +574,25 @@ function getDielineShape(options) {
|
|
|
540
574
|
let lugsPath = null;
|
|
541
575
|
let cutsPath = null;
|
|
542
576
|
holes.forEach((hole) => {
|
|
543
|
-
const
|
|
544
|
-
|
|
577
|
+
const center = new paper.Point(hole.x, hole.y);
|
|
578
|
+
const lug = hole.shape === "square" ? new paper.Path.Rectangle({
|
|
579
|
+
point: [
|
|
580
|
+
center.x - hole.outerRadius,
|
|
581
|
+
center.y - hole.outerRadius
|
|
582
|
+
],
|
|
583
|
+
size: [hole.outerRadius * 2, hole.outerRadius * 2]
|
|
584
|
+
}) : new paper.Path.Circle({
|
|
585
|
+
center,
|
|
545
586
|
radius: hole.outerRadius
|
|
546
587
|
});
|
|
547
|
-
const cut = new paper.Path.
|
|
548
|
-
|
|
588
|
+
const cut = hole.shape === "square" ? new paper.Path.Rectangle({
|
|
589
|
+
point: [
|
|
590
|
+
center.x - hole.innerRadius,
|
|
591
|
+
center.y - hole.innerRadius
|
|
592
|
+
],
|
|
593
|
+
size: [hole.innerRadius * 2, hole.innerRadius * 2]
|
|
594
|
+
}) : new paper.Path.Circle({
|
|
595
|
+
center,
|
|
549
596
|
radius: hole.innerRadius
|
|
550
597
|
});
|
|
551
598
|
if (!lugsPath) {
|
|
@@ -592,14 +639,19 @@ function getDielineShape(options) {
|
|
|
592
639
|
cutsPath.remove();
|
|
593
640
|
mainShape = temp;
|
|
594
641
|
} catch (e) {
|
|
595
|
-
console.error(
|
|
642
|
+
console.error(
|
|
643
|
+
"Geometry: Failed to subtract cutsPath from mainShape",
|
|
644
|
+
e
|
|
645
|
+
);
|
|
596
646
|
}
|
|
597
647
|
}
|
|
598
648
|
}
|
|
599
649
|
return mainShape;
|
|
600
650
|
}
|
|
601
651
|
function generateDielinePath(options) {
|
|
602
|
-
|
|
652
|
+
const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
|
|
653
|
+
const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
|
|
654
|
+
ensurePaper(paperWidth, paperHeight);
|
|
603
655
|
paper.project.activeLayer.removeChildren();
|
|
604
656
|
const mainShape = getDielineShape(options);
|
|
605
657
|
const pathData = mainShape.pathData;
|
|
@@ -623,8 +675,9 @@ function generateMaskPath(options) {
|
|
|
623
675
|
return pathData;
|
|
624
676
|
}
|
|
625
677
|
function generateBleedZonePath(options, offset) {
|
|
626
|
-
const
|
|
627
|
-
|
|
678
|
+
const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
|
|
679
|
+
const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
|
|
680
|
+
ensurePaper(paperWidth, paperHeight);
|
|
628
681
|
paper.project.activeLayer.removeChildren();
|
|
629
682
|
const shapeOriginal = getDielineShape(options);
|
|
630
683
|
let shapeOffset;
|
|
@@ -685,7 +738,12 @@ function getPathBounds(pathData) {
|
|
|
685
738
|
path.pathData = pathData;
|
|
686
739
|
const bounds = path.bounds;
|
|
687
740
|
path.remove();
|
|
688
|
-
return {
|
|
741
|
+
return {
|
|
742
|
+
x: bounds.x,
|
|
743
|
+
y: bounds.y,
|
|
744
|
+
width: bounds.width,
|
|
745
|
+
height: bounds.height
|
|
746
|
+
};
|
|
689
747
|
}
|
|
690
748
|
|
|
691
749
|
// src/dieline.ts
|
|
@@ -695,6 +753,7 @@ var DielineTool = class {
|
|
|
695
753
|
this.metadata = {
|
|
696
754
|
name: "DielineTool"
|
|
697
755
|
};
|
|
756
|
+
this.unit = "mm";
|
|
698
757
|
this.shape = "rect";
|
|
699
758
|
this.width = 500;
|
|
700
759
|
this.height = 500;
|
|
@@ -705,6 +764,7 @@ var DielineTool = class {
|
|
|
705
764
|
this.outsideColor = "#ffffff";
|
|
706
765
|
this.showBleedLines = true;
|
|
707
766
|
this.holes = [];
|
|
767
|
+
this.padding = 140;
|
|
708
768
|
if (options) {
|
|
709
769
|
Object.assign(this, options);
|
|
710
770
|
}
|
|
@@ -718,14 +778,12 @@ var DielineTool = class {
|
|
|
718
778
|
}
|
|
719
779
|
const configService = context.services.get("ConfigurationService");
|
|
720
780
|
if (configService) {
|
|
781
|
+
this.unit = configService.get("dieline.unit", this.unit);
|
|
721
782
|
this.shape = configService.get("dieline.shape", this.shape);
|
|
722
783
|
this.width = configService.get("dieline.width", this.width);
|
|
723
784
|
this.height = configService.get("dieline.height", this.height);
|
|
724
785
|
this.radius = configService.get("dieline.radius", this.radius);
|
|
725
|
-
this.
|
|
726
|
-
"dieline.borderLength",
|
|
727
|
-
this.borderLength
|
|
728
|
-
);
|
|
786
|
+
this.padding = configService.get("dieline.padding", this.padding);
|
|
729
787
|
this.offset = configService.get("dieline.offset", this.offset);
|
|
730
788
|
this.style = configService.get("dieline.style", this.style);
|
|
731
789
|
this.insideColor = configService.get(
|
|
@@ -766,6 +824,13 @@ var DielineTool = class {
|
|
|
766
824
|
contribute() {
|
|
767
825
|
return {
|
|
768
826
|
[ContributionPointIds2.CONFIGURATIONS]: [
|
|
827
|
+
{
|
|
828
|
+
id: "dieline.unit",
|
|
829
|
+
type: "select",
|
|
830
|
+
label: "Unit",
|
|
831
|
+
options: ["px", "mm", "cm", "in"],
|
|
832
|
+
default: this.unit
|
|
833
|
+
},
|
|
769
834
|
{
|
|
770
835
|
id: "dieline.shape",
|
|
771
836
|
type: "select",
|
|
@@ -801,15 +866,14 @@ var DielineTool = class {
|
|
|
801
866
|
id: "dieline.position",
|
|
802
867
|
type: "json",
|
|
803
868
|
label: "Position (Normalized)",
|
|
804
|
-
default: this.
|
|
869
|
+
default: this.radius
|
|
805
870
|
},
|
|
806
871
|
{
|
|
807
|
-
id: "dieline.
|
|
808
|
-
type: "
|
|
809
|
-
label: "
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
default: this.borderLength
|
|
872
|
+
id: "dieline.padding",
|
|
873
|
+
type: "select",
|
|
874
|
+
label: "View Padding",
|
|
875
|
+
options: [0, 10, 20, 40, 60, 100, "2%", "5%", "10%", "15%", "20%"],
|
|
876
|
+
default: this.padding
|
|
813
877
|
},
|
|
814
878
|
{
|
|
815
879
|
id: "dieline.offset",
|
|
@@ -878,7 +942,9 @@ var DielineTool = class {
|
|
|
878
942
|
const scale = currentMax / Math.max(bounds.width, bounds.height);
|
|
879
943
|
const newWidth = bounds.width * scale;
|
|
880
944
|
const newHeight = bounds.height * scale;
|
|
881
|
-
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
945
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
946
|
+
"ConfigurationService"
|
|
947
|
+
);
|
|
882
948
|
if (configService) {
|
|
883
949
|
configService.update("dieline.width", newWidth);
|
|
884
950
|
configService.update("dieline.height", newHeight);
|
|
@@ -943,12 +1009,25 @@ var DielineTool = class {
|
|
|
943
1009
|
}
|
|
944
1010
|
return new Pattern({ source: canvas, repetition: "repeat" });
|
|
945
1011
|
}
|
|
1012
|
+
resolvePadding(containerWidth, containerHeight) {
|
|
1013
|
+
if (typeof this.padding === "number") {
|
|
1014
|
+
return this.padding;
|
|
1015
|
+
}
|
|
1016
|
+
if (typeof this.padding === "string") {
|
|
1017
|
+
if (this.padding.endsWith("%")) {
|
|
1018
|
+
const percent = parseFloat(this.padding) / 100;
|
|
1019
|
+
return Math.min(containerWidth, containerHeight) * percent;
|
|
1020
|
+
}
|
|
1021
|
+
return parseFloat(this.padding) || 0;
|
|
1022
|
+
}
|
|
1023
|
+
return 0;
|
|
1024
|
+
}
|
|
946
1025
|
updateDieline(emitEvent = true) {
|
|
947
|
-
var _a, _b;
|
|
948
1026
|
if (!this.canvasService) return;
|
|
949
1027
|
const layer = this.getLayer();
|
|
950
1028
|
if (!layer) return;
|
|
951
1029
|
const {
|
|
1030
|
+
unit,
|
|
952
1031
|
shape,
|
|
953
1032
|
radius,
|
|
954
1033
|
offset,
|
|
@@ -956,43 +1035,60 @@ var DielineTool = class {
|
|
|
956
1035
|
insideColor,
|
|
957
1036
|
outsideColor,
|
|
958
1037
|
position,
|
|
959
|
-
borderLength,
|
|
960
1038
|
showBleedLines,
|
|
961
1039
|
holes
|
|
962
1040
|
} = this;
|
|
963
1041
|
let { width, height } = this;
|
|
964
1042
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
965
1043
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
const
|
|
973
|
-
const
|
|
1044
|
+
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1045
|
+
const layout = Coordinate.calculateLayout(
|
|
1046
|
+
{ width: canvasW, height: canvasH },
|
|
1047
|
+
{ width, height },
|
|
1048
|
+
paddingPx
|
|
1049
|
+
);
|
|
1050
|
+
const scale = layout.scale;
|
|
1051
|
+
const cx = layout.offsetX + layout.width / 2;
|
|
1052
|
+
const cy = layout.offsetY + layout.height / 2;
|
|
1053
|
+
const visualWidth = layout.width;
|
|
1054
|
+
const visualHeight = layout.height;
|
|
1055
|
+
const visualRadius = radius * scale;
|
|
1056
|
+
const visualOffset = offset * scale;
|
|
974
1057
|
layer.remove(...layer.getObjects());
|
|
975
1058
|
const geometryForHoles = {
|
|
976
1059
|
x: cx,
|
|
977
1060
|
y: cy,
|
|
978
1061
|
width: visualWidth,
|
|
979
1062
|
height: visualHeight
|
|
1063
|
+
// Pass scale/unit context if needed by resolveHolePosition (though currently unused there)
|
|
980
1064
|
};
|
|
981
1065
|
const absoluteHoles = (holes || []).map((h) => {
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1066
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1067
|
+
const offsetScale = unitScale * scale;
|
|
1068
|
+
const hWithPixelOffsets = {
|
|
1069
|
+
...h,
|
|
1070
|
+
offsetX: (h.offsetX || 0) * offsetScale,
|
|
1071
|
+
offsetY: (h.offsetY || 0) * offsetScale
|
|
1072
|
+
};
|
|
1073
|
+
const pos = resolveHolePosition(hWithPixelOffsets, geometryForHoles, {
|
|
1074
|
+
width: canvasW,
|
|
1075
|
+
height: canvasH
|
|
1076
|
+
});
|
|
987
1077
|
return {
|
|
988
1078
|
...h,
|
|
989
1079
|
x: pos.x,
|
|
990
|
-
y: pos.y
|
|
1080
|
+
y: pos.y,
|
|
1081
|
+
// Scale hole radii: mm -> current unit -> pixels
|
|
1082
|
+
innerRadius: h.innerRadius * offsetScale,
|
|
1083
|
+
outerRadius: h.outerRadius * offsetScale,
|
|
1084
|
+
// Store scaled offsets in the result for consistency, though pos is already resolved
|
|
1085
|
+
offsetX: hWithPixelOffsets.offsetX,
|
|
1086
|
+
offsetY: hWithPixelOffsets.offsetY
|
|
991
1087
|
};
|
|
992
1088
|
});
|
|
993
|
-
const cutW = Math.max(0,
|
|
994
|
-
const cutH = Math.max(0,
|
|
995
|
-
const cutR =
|
|
1089
|
+
const cutW = Math.max(0, visualWidth + visualOffset * 2);
|
|
1090
|
+
const cutH = Math.max(0, visualHeight + visualOffset * 2);
|
|
1091
|
+
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
996
1092
|
const maskPathData = generateMaskPath({
|
|
997
1093
|
canvasWidth: canvasW,
|
|
998
1094
|
canvasHeight: canvasH,
|
|
@@ -1025,7 +1121,9 @@ var DielineTool = class {
|
|
|
1025
1121
|
x: cx,
|
|
1026
1122
|
y: cy,
|
|
1027
1123
|
holes: absoluteHoles,
|
|
1028
|
-
pathData: this.pathData
|
|
1124
|
+
pathData: this.pathData,
|
|
1125
|
+
canvasWidth: canvasW,
|
|
1126
|
+
canvasHeight: canvasH
|
|
1029
1127
|
});
|
|
1030
1128
|
const insideObj = new Path(productPathData, {
|
|
1031
1129
|
fill: insideColor,
|
|
@@ -1042,15 +1140,17 @@ var DielineTool = class {
|
|
|
1042
1140
|
const bleedPathData = generateBleedZonePath(
|
|
1043
1141
|
{
|
|
1044
1142
|
shape,
|
|
1045
|
-
width,
|
|
1046
|
-
height,
|
|
1047
|
-
radius,
|
|
1143
|
+
width: visualWidth,
|
|
1144
|
+
height: visualHeight,
|
|
1145
|
+
radius: visualRadius,
|
|
1048
1146
|
x: cx,
|
|
1049
1147
|
y: cy,
|
|
1050
1148
|
holes: absoluteHoles,
|
|
1051
|
-
pathData: this.pathData
|
|
1149
|
+
pathData: this.pathData,
|
|
1150
|
+
canvasWidth: canvasW,
|
|
1151
|
+
canvasHeight: canvasH
|
|
1052
1152
|
},
|
|
1053
|
-
|
|
1153
|
+
visualOffset
|
|
1054
1154
|
);
|
|
1055
1155
|
if (showBleedLines !== false) {
|
|
1056
1156
|
const pattern = this.createHatchPattern("red");
|
|
@@ -1075,7 +1175,9 @@ var DielineTool = class {
|
|
|
1075
1175
|
x: cx,
|
|
1076
1176
|
y: cy,
|
|
1077
1177
|
holes: absoluteHoles,
|
|
1078
|
-
pathData: this.pathData
|
|
1178
|
+
pathData: this.pathData,
|
|
1179
|
+
canvasWidth: canvasW,
|
|
1180
|
+
canvasHeight: canvasH
|
|
1079
1181
|
});
|
|
1080
1182
|
const offsetBorderObj = new Path(offsetPathData, {
|
|
1081
1183
|
fill: null,
|
|
@@ -1093,14 +1195,15 @@ var DielineTool = class {
|
|
|
1093
1195
|
}
|
|
1094
1196
|
const borderPathData = generateDielinePath({
|
|
1095
1197
|
shape,
|
|
1096
|
-
width,
|
|
1097
|
-
height,
|
|
1098
|
-
radius,
|
|
1198
|
+
width: visualWidth,
|
|
1199
|
+
height: visualHeight,
|
|
1200
|
+
radius: visualRadius,
|
|
1099
1201
|
x: cx,
|
|
1100
1202
|
y: cy,
|
|
1101
1203
|
holes: absoluteHoles,
|
|
1102
|
-
|
|
1103
|
-
|
|
1204
|
+
pathData: this.pathData,
|
|
1205
|
+
canvasWidth: canvasW,
|
|
1206
|
+
canvasHeight: canvasH
|
|
1104
1207
|
});
|
|
1105
1208
|
const borderObj = new Path(borderPathData, {
|
|
1106
1209
|
fill: "transparent",
|
|
@@ -1137,115 +1240,109 @@ var DielineTool = class {
|
|
|
1137
1240
|
}
|
|
1138
1241
|
}
|
|
1139
1242
|
getGeometry() {
|
|
1140
|
-
var _a, _b;
|
|
1141
1243
|
if (!this.canvasService) return null;
|
|
1142
|
-
const { shape, width, height, radius, position,
|
|
1244
|
+
const { unit, shape, width, height, radius, position, offset } = this;
|
|
1143
1245
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1144
1246
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
const
|
|
1152
|
-
const
|
|
1247
|
+
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1248
|
+
const layout = Coordinate.calculateLayout(
|
|
1249
|
+
{ width: canvasW, height: canvasH },
|
|
1250
|
+
{ width, height },
|
|
1251
|
+
paddingPx
|
|
1252
|
+
);
|
|
1253
|
+
const scale = layout.scale;
|
|
1254
|
+
const cx = layout.offsetX + layout.width / 2;
|
|
1255
|
+
const cy = layout.offsetY + layout.height / 2;
|
|
1256
|
+
const visualWidth = layout.width;
|
|
1257
|
+
const visualHeight = layout.height;
|
|
1153
1258
|
return {
|
|
1154
1259
|
shape,
|
|
1260
|
+
unit,
|
|
1155
1261
|
x: cx,
|
|
1156
1262
|
y: cy,
|
|
1157
1263
|
width: visualWidth,
|
|
1158
1264
|
height: visualHeight,
|
|
1159
|
-
radius,
|
|
1160
|
-
offset,
|
|
1161
|
-
|
|
1265
|
+
radius: radius * scale,
|
|
1266
|
+
offset: offset * scale,
|
|
1267
|
+
// Pass scale to help other tools (like HoleTool) convert units
|
|
1268
|
+
scale,
|
|
1162
1269
|
pathData: this.pathData
|
|
1163
1270
|
};
|
|
1164
1271
|
}
|
|
1165
|
-
exportCutImage() {
|
|
1166
|
-
var _a, _b, _c, _d;
|
|
1272
|
+
async exportCutImage() {
|
|
1167
1273
|
if (!this.canvasService) return null;
|
|
1168
|
-
const
|
|
1274
|
+
const userLayer = this.canvasService.getLayer("user");
|
|
1275
|
+
if (!userLayer) return null;
|
|
1169
1276
|
const { shape, width, height, radius, position, holes } = this;
|
|
1170
|
-
const canvasW = canvas.width || 800;
|
|
1171
|
-
const canvasH = canvas.height || 600;
|
|
1172
|
-
const
|
|
1173
|
-
const
|
|
1277
|
+
const canvasW = this.canvasService.canvas.width || 800;
|
|
1278
|
+
const canvasH = this.canvasService.canvas.height || 600;
|
|
1279
|
+
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1280
|
+
const layout = Coordinate.calculateLayout(
|
|
1281
|
+
{ width: canvasW, height: canvasH },
|
|
1282
|
+
{ width, height },
|
|
1283
|
+
paddingPx
|
|
1284
|
+
);
|
|
1285
|
+
const scale = layout.scale;
|
|
1286
|
+
const cx = layout.offsetX + layout.width / 2;
|
|
1287
|
+
const cy = layout.offsetY + layout.height / 2;
|
|
1288
|
+
const visualWidth = layout.width;
|
|
1289
|
+
const visualHeight = layout.height;
|
|
1290
|
+
const visualRadius = radius * scale;
|
|
1174
1291
|
const absoluteHoles = (holes || []).map((h) => {
|
|
1292
|
+
const unit = this.unit || "mm";
|
|
1293
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1175
1294
|
const pos = resolveHolePosition(
|
|
1176
|
-
|
|
1177
|
-
|
|
1295
|
+
{
|
|
1296
|
+
...h,
|
|
1297
|
+
offsetX: (h.offsetX || 0) * unitScale * scale,
|
|
1298
|
+
offsetY: (h.offsetY || 0) * unitScale * scale
|
|
1299
|
+
},
|
|
1300
|
+
{ x: cx, y: cy, width: visualWidth, height: visualHeight },
|
|
1178
1301
|
{ width: canvasW, height: canvasH }
|
|
1179
1302
|
);
|
|
1180
1303
|
return {
|
|
1181
1304
|
...h,
|
|
1182
1305
|
x: pos.x,
|
|
1183
|
-
y: pos.y
|
|
1306
|
+
y: pos.y,
|
|
1307
|
+
innerRadius: h.innerRadius * unitScale * scale,
|
|
1308
|
+
outerRadius: h.outerRadius * unitScale * scale,
|
|
1309
|
+
offsetX: (h.offsetX || 0) * unitScale * scale,
|
|
1310
|
+
offsetY: (h.offsetY || 0) * unitScale * scale
|
|
1184
1311
|
};
|
|
1185
1312
|
});
|
|
1186
1313
|
const pathData = generateDielinePath({
|
|
1187
1314
|
shape,
|
|
1188
|
-
width,
|
|
1189
|
-
height,
|
|
1190
|
-
radius,
|
|
1315
|
+
width: visualWidth,
|
|
1316
|
+
height: visualHeight,
|
|
1317
|
+
radius: visualRadius,
|
|
1191
1318
|
x: cx,
|
|
1192
1319
|
y: cy,
|
|
1193
1320
|
holes: absoluteHoles,
|
|
1194
|
-
pathData: this.pathData
|
|
1321
|
+
pathData: this.pathData,
|
|
1322
|
+
canvasWidth: canvasW,
|
|
1323
|
+
canvasHeight: canvasH
|
|
1195
1324
|
});
|
|
1325
|
+
const clonedLayer = await userLayer.clone();
|
|
1196
1326
|
const clipPath = new Path(pathData, {
|
|
1197
|
-
left: 0,
|
|
1198
|
-
top: 0,
|
|
1199
1327
|
originX: "left",
|
|
1200
1328
|
originY: "top",
|
|
1201
|
-
absolutePositioned: true
|
|
1202
|
-
});
|
|
1203
|
-
const layer = this.getLayer();
|
|
1204
|
-
const wasVisible = (_c = layer == null ? void 0 : layer.visible) != null ? _c : true;
|
|
1205
|
-
if (layer) layer.visible = false;
|
|
1206
|
-
const holeMarkers = canvas.getObjects().filter((o) => {
|
|
1207
|
-
var _a2;
|
|
1208
|
-
return ((_a2 = o.data) == null ? void 0 : _a2.type) === "hole-marker";
|
|
1209
|
-
});
|
|
1210
|
-
holeMarkers.forEach((o) => o.visible = false);
|
|
1211
|
-
const rulerLayer = canvas.getObjects().find((obj) => {
|
|
1212
|
-
var _a2;
|
|
1213
|
-
return ((_a2 = obj.data) == null ? void 0 : _a2.id) === "ruler-overlay";
|
|
1214
|
-
});
|
|
1215
|
-
const rulerWasVisible = (_d = rulerLayer == null ? void 0 : rulerLayer.visible) != null ? _d : true;
|
|
1216
|
-
if (rulerLayer) rulerLayer.visible = false;
|
|
1217
|
-
const originalClip = canvas.clipPath;
|
|
1218
|
-
canvas.clipPath = clipPath;
|
|
1219
|
-
const bbox = clipPath.getBoundingRect();
|
|
1220
|
-
const clipPathCorrected = new Path(pathData, {
|
|
1221
|
-
absolutePositioned: true,
|
|
1222
1329
|
left: 0,
|
|
1223
|
-
top: 0
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
const tempBounds = tempPath.getBoundingRect();
|
|
1227
|
-
clipPathCorrected.set({
|
|
1228
|
-
left: tempBounds.left,
|
|
1229
|
-
top: tempBounds.top,
|
|
1230
|
-
originX: "left",
|
|
1231
|
-
originY: "top"
|
|
1330
|
+
top: 0,
|
|
1331
|
+
absolutePositioned: true
|
|
1332
|
+
// Important for groups
|
|
1232
1333
|
});
|
|
1233
|
-
|
|
1234
|
-
const
|
|
1235
|
-
const
|
|
1334
|
+
clonedLayer.clipPath = clipPath;
|
|
1335
|
+
const bounds = clipPath.getBoundingRect();
|
|
1336
|
+
const dataUrl = clonedLayer.toDataURL({
|
|
1236
1337
|
format: "png",
|
|
1237
1338
|
multiplier: 2,
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1339
|
+
// Better quality
|
|
1340
|
+
left: bounds.left,
|
|
1341
|
+
top: bounds.top,
|
|
1342
|
+
width: bounds.width,
|
|
1343
|
+
height: bounds.height
|
|
1242
1344
|
});
|
|
1243
|
-
|
|
1244
|
-
if (layer) layer.visible = wasVisible;
|
|
1245
|
-
if (rulerLayer) rulerLayer.visible = rulerWasVisible;
|
|
1246
|
-
holeMarkers.forEach((o) => o.visible = true);
|
|
1247
|
-
canvas.requestRenderAll();
|
|
1248
|
-
return dataURL;
|
|
1345
|
+
return dataUrl;
|
|
1249
1346
|
}
|
|
1250
1347
|
};
|
|
1251
1348
|
|
|
@@ -1414,7 +1511,7 @@ var FilmTool = class {
|
|
|
1414
1511
|
import {
|
|
1415
1512
|
ContributionPointIds as ContributionPointIds4
|
|
1416
1513
|
} from "@pooder/core";
|
|
1417
|
-
import { Circle, Group, Point } from "fabric";
|
|
1514
|
+
import { Circle, Group, Point, Rect as Rect2 } from "fabric";
|
|
1418
1515
|
var HoleTool = class {
|
|
1419
1516
|
constructor(options) {
|
|
1420
1517
|
this.id = "pooder.kit.hole";
|
|
@@ -1520,13 +1617,21 @@ var HoleTool = class {
|
|
|
1520
1617
|
command: "addHole",
|
|
1521
1618
|
title: "Add Hole",
|
|
1522
1619
|
handler: (x, y) => {
|
|
1523
|
-
var _a, _b, _c;
|
|
1620
|
+
var _a, _b, _c, _d;
|
|
1524
1621
|
if (!this.canvasService) return false;
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
{
|
|
1529
|
-
|
|
1622
|
+
let normalizedX = 0.5;
|
|
1623
|
+
let normalizedY = 0.5;
|
|
1624
|
+
if (this.currentGeometry) {
|
|
1625
|
+
const { x: gx, y: gy, width: gw, height: gh } = this.currentGeometry;
|
|
1626
|
+
const left = gx - gw / 2;
|
|
1627
|
+
const top = gy - gh / 2;
|
|
1628
|
+
normalizedX = gw > 0 ? (x - left) / gw : 0.5;
|
|
1629
|
+
normalizedY = gh > 0 ? (y - top) / gh : 0.5;
|
|
1630
|
+
} else {
|
|
1631
|
+
const { width, height } = this.canvasService.canvas;
|
|
1632
|
+
normalizedX = Coordinate.toNormalized(x, width || 800);
|
|
1633
|
+
normalizedY = Coordinate.toNormalized(y, height || 600);
|
|
1634
|
+
}
|
|
1530
1635
|
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
1531
1636
|
"ConfigurationService"
|
|
1532
1637
|
);
|
|
@@ -1535,9 +1640,11 @@ var HoleTool = class {
|
|
|
1535
1640
|
const lastHole = currentHoles[currentHoles.length - 1];
|
|
1536
1641
|
const innerRadius = (_b = lastHole == null ? void 0 : lastHole.innerRadius) != null ? _b : 15;
|
|
1537
1642
|
const outerRadius = (_c = lastHole == null ? void 0 : lastHole.outerRadius) != null ? _c : 25;
|
|
1643
|
+
const shape = (_d = lastHole == null ? void 0 : lastHole.shape) != null ? _d : "circle";
|
|
1538
1644
|
const newHole = {
|
|
1539
|
-
x:
|
|
1540
|
-
y:
|
|
1645
|
+
x: normalizedX,
|
|
1646
|
+
y: normalizedY,
|
|
1647
|
+
shape,
|
|
1541
1648
|
innerRadius,
|
|
1542
1649
|
outerRadius
|
|
1543
1650
|
};
|
|
@@ -1569,6 +1676,7 @@ var HoleTool = class {
|
|
|
1569
1676
|
if (!this.handleDielineChange) {
|
|
1570
1677
|
this.handleDielineChange = (geometry) => {
|
|
1571
1678
|
this.currentGeometry = geometry;
|
|
1679
|
+
this.redraw();
|
|
1572
1680
|
const changed = this.enforceConstraints();
|
|
1573
1681
|
if (changed) {
|
|
1574
1682
|
this.syncHolesToDieline();
|
|
@@ -1632,7 +1740,10 @@ var HoleTool = class {
|
|
|
1632
1740
|
var _a;
|
|
1633
1741
|
const target = e.target;
|
|
1634
1742
|
if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "hole-marker") return;
|
|
1635
|
-
this.
|
|
1743
|
+
const changed = this.enforceConstraints();
|
|
1744
|
+
if (!changed) {
|
|
1745
|
+
this.syncHolesFromCanvas();
|
|
1746
|
+
}
|
|
1636
1747
|
};
|
|
1637
1748
|
canvas.on("object:modified", this.handleModified);
|
|
1638
1749
|
}
|
|
@@ -1679,10 +1790,16 @@ var HoleTool = class {
|
|
|
1679
1790
|
}
|
|
1680
1791
|
syncHolesFromCanvas() {
|
|
1681
1792
|
if (!this.canvasService) return;
|
|
1682
|
-
const objects = this.canvasService.canvas.getObjects().filter(
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1793
|
+
const objects = this.canvasService.canvas.getObjects().filter(
|
|
1794
|
+
(obj) => {
|
|
1795
|
+
var _a;
|
|
1796
|
+
return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker" || obj.name === "hole-marker";
|
|
1797
|
+
}
|
|
1798
|
+
);
|
|
1799
|
+
if (objects.length === 0 && this.holes.length > 0) {
|
|
1800
|
+
console.warn("HoleTool: No markers found on canvas to sync from");
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1686
1803
|
objects.sort(
|
|
1687
1804
|
(a, b) => {
|
|
1688
1805
|
var _a, _b, _c, _d;
|
|
@@ -1690,18 +1807,28 @@ var HoleTool = class {
|
|
|
1690
1807
|
}
|
|
1691
1808
|
);
|
|
1692
1809
|
const newHoles = objects.map((obj, i) => {
|
|
1693
|
-
var _a, _b;
|
|
1810
|
+
var _a, _b, _c, _d;
|
|
1694
1811
|
const original = this.holes[i];
|
|
1695
1812
|
const newAbsX = obj.left;
|
|
1696
1813
|
const newAbsY = obj.top;
|
|
1814
|
+
if (isNaN(newAbsX) || isNaN(newAbsY)) {
|
|
1815
|
+
console.error("HoleTool: Invalid marker coordinates", {
|
|
1816
|
+
newAbsX,
|
|
1817
|
+
newAbsY
|
|
1818
|
+
});
|
|
1819
|
+
return original;
|
|
1820
|
+
}
|
|
1821
|
+
const scale = ((_a = this.currentGeometry) == null ? void 0 : _a.scale) || 1;
|
|
1822
|
+
const unit = ((_b = this.currentGeometry) == null ? void 0 : _b.unit) || "mm";
|
|
1823
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1697
1824
|
if (original && original.anchor && this.currentGeometry) {
|
|
1698
|
-
const { x, y, width
|
|
1825
|
+
const { x, y, width, height } = this.currentGeometry;
|
|
1699
1826
|
let bx = x;
|
|
1700
1827
|
let by = y;
|
|
1701
|
-
const left = x -
|
|
1702
|
-
const right = x +
|
|
1703
|
-
const top = y -
|
|
1704
|
-
const bottom = y +
|
|
1828
|
+
const left = x - width / 2;
|
|
1829
|
+
const right = x + width / 2;
|
|
1830
|
+
const top = y - height / 2;
|
|
1831
|
+
const bottom = y + height / 2;
|
|
1705
1832
|
switch (original.anchor) {
|
|
1706
1833
|
case "top-left":
|
|
1707
1834
|
bx = left;
|
|
@@ -1742,25 +1869,42 @@ var HoleTool = class {
|
|
|
1742
1869
|
}
|
|
1743
1870
|
return {
|
|
1744
1871
|
...original,
|
|
1745
|
-
|
|
1746
|
-
|
|
1872
|
+
// Denormalize offset back to physical units (mm)
|
|
1873
|
+
offsetX: (newAbsX - bx) / scale / unitScale,
|
|
1874
|
+
offsetY: (newAbsY - by) / scale / unitScale,
|
|
1747
1875
|
// Clear direct coordinates if we use anchor
|
|
1748
1876
|
x: void 0,
|
|
1749
|
-
y: void 0
|
|
1877
|
+
y: void 0,
|
|
1878
|
+
// Ensure other properties are preserved
|
|
1879
|
+
innerRadius: original.innerRadius,
|
|
1880
|
+
outerRadius: original.outerRadius,
|
|
1881
|
+
shape: original.shape || "circle"
|
|
1750
1882
|
};
|
|
1751
1883
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
{
|
|
1756
|
-
|
|
1884
|
+
let normalizedX = 0.5;
|
|
1885
|
+
let normalizedY = 0.5;
|
|
1886
|
+
if (this.currentGeometry) {
|
|
1887
|
+
const { x, y, width, height } = this.currentGeometry;
|
|
1888
|
+
const left = x - width / 2;
|
|
1889
|
+
const top = y - height / 2;
|
|
1890
|
+
normalizedX = width > 0 ? (newAbsX - left) / width : 0.5;
|
|
1891
|
+
normalizedY = height > 0 ? (newAbsY - top) / height : 0.5;
|
|
1892
|
+
} else {
|
|
1893
|
+
const { width, height } = this.canvasService.canvas;
|
|
1894
|
+
normalizedX = Coordinate.toNormalized(newAbsX, width || 800);
|
|
1895
|
+
normalizedY = Coordinate.toNormalized(newAbsY, height || 600);
|
|
1896
|
+
}
|
|
1757
1897
|
return {
|
|
1758
1898
|
...original,
|
|
1759
|
-
x:
|
|
1760
|
-
y:
|
|
1761
|
-
//
|
|
1762
|
-
|
|
1763
|
-
|
|
1899
|
+
x: normalizedX,
|
|
1900
|
+
y: normalizedY,
|
|
1901
|
+
// Clear offsets if we are using direct normalized coordinates
|
|
1902
|
+
offsetX: void 0,
|
|
1903
|
+
offsetY: void 0,
|
|
1904
|
+
// Ensure other properties are preserved
|
|
1905
|
+
innerRadius: (_c = original == null ? void 0 : original.innerRadius) != null ? _c : 15,
|
|
1906
|
+
outerRadius: (_d = original == null ? void 0 : original.outerRadius) != null ? _d : 25,
|
|
1907
|
+
shape: (original == null ? void 0 : original.shape) || "circle"
|
|
1764
1908
|
};
|
|
1765
1909
|
});
|
|
1766
1910
|
this.holes = newHoles;
|
|
@@ -1798,24 +1942,54 @@ var HoleTool = class {
|
|
|
1798
1942
|
x: (width || 800) / 2,
|
|
1799
1943
|
y: (height || 600) / 2,
|
|
1800
1944
|
width: width || 800,
|
|
1801
|
-
height: height || 600
|
|
1945
|
+
height: height || 600,
|
|
1946
|
+
scale: 1
|
|
1947
|
+
// Default scale if no geometry loaded
|
|
1802
1948
|
};
|
|
1803
1949
|
holes.forEach((hole, index) => {
|
|
1950
|
+
const scale = geometry.scale || 1;
|
|
1951
|
+
const unit = geometry.unit || "mm";
|
|
1952
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1953
|
+
const visualInnerRadius = hole.innerRadius * unitScale * scale;
|
|
1954
|
+
const visualOuterRadius = hole.outerRadius * unitScale * scale;
|
|
1804
1955
|
const pos = resolveHolePosition(
|
|
1805
|
-
|
|
1956
|
+
{
|
|
1957
|
+
...hole,
|
|
1958
|
+
offsetX: (hole.offsetX || 0) * unitScale * scale,
|
|
1959
|
+
offsetY: (hole.offsetY || 0) * unitScale * scale
|
|
1960
|
+
},
|
|
1806
1961
|
geometry,
|
|
1807
|
-
{ width: width
|
|
1962
|
+
{ width: geometry.width, height: geometry.height }
|
|
1963
|
+
// Use geometry dims instead of canvas
|
|
1808
1964
|
);
|
|
1809
|
-
const
|
|
1810
|
-
|
|
1965
|
+
const isSquare = hole.shape === "square";
|
|
1966
|
+
const innerMarker = isSquare ? new Rect2({
|
|
1967
|
+
width: visualInnerRadius * 2,
|
|
1968
|
+
height: visualInnerRadius * 2,
|
|
1969
|
+
fill: "transparent",
|
|
1970
|
+
stroke: "red",
|
|
1971
|
+
strokeWidth: 2,
|
|
1972
|
+
originX: "center",
|
|
1973
|
+
originY: "center"
|
|
1974
|
+
}) : new Circle({
|
|
1975
|
+
radius: visualInnerRadius,
|
|
1811
1976
|
fill: "transparent",
|
|
1812
1977
|
stroke: "red",
|
|
1813
1978
|
strokeWidth: 2,
|
|
1814
1979
|
originX: "center",
|
|
1815
1980
|
originY: "center"
|
|
1816
1981
|
});
|
|
1817
|
-
const
|
|
1818
|
-
|
|
1982
|
+
const outerMarker = isSquare ? new Rect2({
|
|
1983
|
+
width: visualOuterRadius * 2,
|
|
1984
|
+
height: visualOuterRadius * 2,
|
|
1985
|
+
fill: "transparent",
|
|
1986
|
+
stroke: "#666",
|
|
1987
|
+
strokeWidth: 1,
|
|
1988
|
+
strokeDashArray: [5, 5],
|
|
1989
|
+
originX: "center",
|
|
1990
|
+
originY: "center"
|
|
1991
|
+
}) : new Circle({
|
|
1992
|
+
radius: visualOuterRadius,
|
|
1819
1993
|
fill: "transparent",
|
|
1820
1994
|
stroke: "#666",
|
|
1821
1995
|
strokeWidth: 1,
|
|
@@ -1823,7 +1997,7 @@ var HoleTool = class {
|
|
|
1823
1997
|
originX: "center",
|
|
1824
1998
|
originY: "center"
|
|
1825
1999
|
});
|
|
1826
|
-
const holeGroup = new Group([
|
|
2000
|
+
const holeGroup = new Group([outerMarker, innerMarker], {
|
|
1827
2001
|
left: pos.x,
|
|
1828
2002
|
top: pos.y,
|
|
1829
2003
|
originX: "center",
|
|
@@ -1895,11 +2069,16 @@ var HoleTool = class {
|
|
|
1895
2069
|
var _a, _b;
|
|
1896
2070
|
const currentPos = new Point(obj.left, obj.top);
|
|
1897
2071
|
const holeData = this.holes[i];
|
|
2072
|
+
const scale = geometry.scale || 1;
|
|
2073
|
+
const unit = geometry.unit || "mm";
|
|
2074
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
2075
|
+
const innerR = ((_a = holeData == null ? void 0 : holeData.innerRadius) != null ? _a : 15) * unitScale * scale;
|
|
2076
|
+
const outerR = ((_b = holeData == null ? void 0 : holeData.outerRadius) != null ? _b : 25) * unitScale * scale;
|
|
1898
2077
|
const newPos = this.calculateConstrainedPosition(
|
|
1899
2078
|
currentPos,
|
|
1900
2079
|
constraintGeometry,
|
|
1901
|
-
|
|
1902
|
-
|
|
2080
|
+
innerR,
|
|
2081
|
+
outerR
|
|
1903
2082
|
);
|
|
1904
2083
|
if (currentPos.distanceFrom(newPos) > 0.1) {
|
|
1905
2084
|
obj.set({
|
|
@@ -1953,19 +2132,16 @@ var HoleTool = class {
|
|
|
1953
2132
|
import {
|
|
1954
2133
|
ContributionPointIds as ContributionPointIds5
|
|
1955
2134
|
} from "@pooder/core";
|
|
1956
|
-
import {
|
|
2135
|
+
import { Image as Image4, Point as Point2, util } from "fabric";
|
|
1957
2136
|
var ImageTool = class {
|
|
1958
|
-
constructor(
|
|
2137
|
+
constructor() {
|
|
1959
2138
|
this.id = "pooder.kit.image";
|
|
1960
2139
|
this.metadata = {
|
|
1961
2140
|
name: "ImageTool"
|
|
1962
2141
|
};
|
|
1963
|
-
this.
|
|
1964
|
-
this.
|
|
1965
|
-
this.
|
|
1966
|
-
if (options) {
|
|
1967
|
-
Object.assign(this, options);
|
|
1968
|
-
}
|
|
2142
|
+
this.items = [];
|
|
2143
|
+
this.objectMap = /* @__PURE__ */ new Map();
|
|
2144
|
+
this.isUpdatingConfig = false;
|
|
1969
2145
|
}
|
|
1970
2146
|
activate(context) {
|
|
1971
2147
|
this.context = context;
|
|
@@ -1976,38 +2152,33 @@ var ImageTool = class {
|
|
|
1976
2152
|
}
|
|
1977
2153
|
const configService = context.services.get("ConfigurationService");
|
|
1978
2154
|
if (configService) {
|
|
1979
|
-
this.
|
|
1980
|
-
this.opacity = configService.get("image.opacity", this.opacity);
|
|
1981
|
-
this.width = configService.get("image.width", this.width);
|
|
1982
|
-
this.height = configService.get("image.height", this.height);
|
|
1983
|
-
this.angle = configService.get("image.angle", this.angle);
|
|
1984
|
-
this.left = configService.get("image.left", this.left);
|
|
1985
|
-
this.top = configService.get("image.top", this.top);
|
|
2155
|
+
this.items = configService.get("image.items", []) || [];
|
|
1986
2156
|
configService.onAnyChange((e) => {
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2157
|
+
if (this.isUpdatingConfig) return;
|
|
2158
|
+
let shouldUpdate = false;
|
|
2159
|
+
if (e.key === "image.items") {
|
|
2160
|
+
this.items = e.value || [];
|
|
2161
|
+
shouldUpdate = true;
|
|
2162
|
+
} else if (e.key.startsWith("dieline.") && e.key !== "dieline.holes") {
|
|
2163
|
+
shouldUpdate = true;
|
|
2164
|
+
}
|
|
2165
|
+
if (shouldUpdate) {
|
|
2166
|
+
this.updateImages();
|
|
1996
2167
|
}
|
|
1997
2168
|
});
|
|
1998
2169
|
}
|
|
1999
2170
|
this.ensureLayer();
|
|
2000
|
-
this.
|
|
2171
|
+
this.updateImages();
|
|
2001
2172
|
}
|
|
2002
2173
|
deactivate(context) {
|
|
2003
2174
|
if (this.canvasService) {
|
|
2004
2175
|
const layer = this.canvasService.getLayer("user");
|
|
2005
2176
|
if (layer) {
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2177
|
+
this.objectMap.forEach((obj) => {
|
|
2178
|
+
layer.remove(obj);
|
|
2179
|
+
});
|
|
2180
|
+
this.objectMap.clear();
|
|
2181
|
+
this.canvasService.requestRenderAll();
|
|
2011
2182
|
}
|
|
2012
2183
|
this.canvasService = void 0;
|
|
2013
2184
|
this.context = void 0;
|
|
@@ -2017,82 +2188,103 @@ var ImageTool = class {
|
|
|
2017
2188
|
return {
|
|
2018
2189
|
[ContributionPointIds5.CONFIGURATIONS]: [
|
|
2019
2190
|
{
|
|
2020
|
-
id: "image.
|
|
2021
|
-
type: "
|
|
2022
|
-
label: "
|
|
2023
|
-
default:
|
|
2024
|
-
}
|
|
2191
|
+
id: "image.items",
|
|
2192
|
+
type: "array",
|
|
2193
|
+
label: "Images",
|
|
2194
|
+
default: []
|
|
2195
|
+
}
|
|
2196
|
+
],
|
|
2197
|
+
[ContributionPointIds5.COMMANDS]: [
|
|
2025
2198
|
{
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2199
|
+
command: "addImage",
|
|
2200
|
+
title: "Add Image",
|
|
2201
|
+
handler: (url, options) => {
|
|
2202
|
+
const newItem = {
|
|
2203
|
+
id: this.generateId(),
|
|
2204
|
+
url,
|
|
2205
|
+
opacity: 1,
|
|
2206
|
+
...options
|
|
2207
|
+
};
|
|
2208
|
+
this.updateConfig([...this.items, newItem]);
|
|
2209
|
+
return newItem.id;
|
|
2210
|
+
}
|
|
2033
2211
|
},
|
|
2034
2212
|
{
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2213
|
+
command: "removeImage",
|
|
2214
|
+
title: "Remove Image",
|
|
2215
|
+
handler: (id) => {
|
|
2216
|
+
const newItems = this.items.filter((item) => item.id !== id);
|
|
2217
|
+
if (newItems.length !== this.items.length) {
|
|
2218
|
+
this.updateConfig(newItems);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2041
2221
|
},
|
|
2042
2222
|
{
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2223
|
+
command: "updateImage",
|
|
2224
|
+
title: "Update Image",
|
|
2225
|
+
handler: (id, updates) => {
|
|
2226
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
2227
|
+
if (index !== -1) {
|
|
2228
|
+
const newItems = [...this.items];
|
|
2229
|
+
newItems[index] = { ...newItems[index], ...updates };
|
|
2230
|
+
this.updateConfig(newItems);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2049
2233
|
},
|
|
2050
2234
|
{
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
default: this.angle
|
|
2235
|
+
command: "clearImages",
|
|
2236
|
+
title: "Clear Images",
|
|
2237
|
+
handler: () => {
|
|
2238
|
+
this.updateConfig([]);
|
|
2239
|
+
}
|
|
2057
2240
|
},
|
|
2058
2241
|
{
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2242
|
+
command: "bringToFront",
|
|
2243
|
+
title: "Bring Image to Front",
|
|
2244
|
+
handler: (id) => {
|
|
2245
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
2246
|
+
if (index !== -1 && index < this.items.length - 1) {
|
|
2247
|
+
const newItems = [...this.items];
|
|
2248
|
+
const [item] = newItems.splice(index, 1);
|
|
2249
|
+
newItems.push(item);
|
|
2250
|
+
this.updateConfig(newItems);
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2065
2253
|
},
|
|
2066
2254
|
{
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
command: "setUserImage",
|
|
2078
|
-
title: "Set User Image",
|
|
2079
|
-
handler: (url, opacity, width, height, angle, left, top) => {
|
|
2080
|
-
if (this.url === url && this.opacity === opacity && this.width === width && this.height === height && this.angle === angle && this.left === left && this.top === top)
|
|
2081
|
-
return true;
|
|
2082
|
-
this.url = url;
|
|
2083
|
-
this.opacity = opacity;
|
|
2084
|
-
this.width = width;
|
|
2085
|
-
this.height = height;
|
|
2086
|
-
this.angle = angle;
|
|
2087
|
-
this.left = left;
|
|
2088
|
-
this.top = top;
|
|
2089
|
-
this.updateImage();
|
|
2090
|
-
return true;
|
|
2255
|
+
command: "sendToBack",
|
|
2256
|
+
title: "Send Image to Back",
|
|
2257
|
+
handler: (id) => {
|
|
2258
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
2259
|
+
if (index > 0) {
|
|
2260
|
+
const newItems = [...this.items];
|
|
2261
|
+
const [item] = newItems.splice(index, 1);
|
|
2262
|
+
newItems.unshift(item);
|
|
2263
|
+
this.updateConfig(newItems);
|
|
2264
|
+
}
|
|
2091
2265
|
}
|
|
2092
2266
|
}
|
|
2093
2267
|
]
|
|
2094
2268
|
};
|
|
2095
2269
|
}
|
|
2270
|
+
generateId() {
|
|
2271
|
+
return Math.random().toString(36).substring(2, 9);
|
|
2272
|
+
}
|
|
2273
|
+
updateConfig(newItems, skipCanvasUpdate = false) {
|
|
2274
|
+
if (!this.context) return;
|
|
2275
|
+
this.isUpdatingConfig = true;
|
|
2276
|
+
this.items = newItems;
|
|
2277
|
+
const configService = this.context.services.get("ConfigurationService");
|
|
2278
|
+
if (configService) {
|
|
2279
|
+
configService.update("image.items", newItems);
|
|
2280
|
+
}
|
|
2281
|
+
if (!skipCanvasUpdate) {
|
|
2282
|
+
this.updateImages();
|
|
2283
|
+
}
|
|
2284
|
+
setTimeout(() => {
|
|
2285
|
+
this.isUpdatingConfig = false;
|
|
2286
|
+
}, 50);
|
|
2287
|
+
}
|
|
2096
2288
|
ensureLayer() {
|
|
2097
2289
|
if (!this.canvasService) return;
|
|
2098
2290
|
let userLayer = this.canvasService.getLayer("user");
|
|
@@ -2124,224 +2316,194 @@ var ImageTool = class {
|
|
|
2124
2316
|
this.canvasService.requestRenderAll();
|
|
2125
2317
|
}
|
|
2126
2318
|
}
|
|
2127
|
-
|
|
2319
|
+
getLayoutInfo() {
|
|
2128
2320
|
var _a, _b;
|
|
2321
|
+
const canvasW = ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800;
|
|
2322
|
+
const canvasH = ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600;
|
|
2323
|
+
let layoutScale = 1;
|
|
2324
|
+
let layoutOffsetX = 0;
|
|
2325
|
+
let layoutOffsetY = 0;
|
|
2326
|
+
let visualWidth = canvasW;
|
|
2327
|
+
let visualHeight = canvasH;
|
|
2328
|
+
let dielinePhysicalWidth = 500;
|
|
2329
|
+
let dielinePhysicalHeight = 500;
|
|
2330
|
+
let bleedOffset = 0;
|
|
2331
|
+
if (this.context) {
|
|
2332
|
+
const configService = this.context.services.get("ConfigurationService");
|
|
2333
|
+
if (configService) {
|
|
2334
|
+
dielinePhysicalWidth = configService.get("dieline.width") || 500;
|
|
2335
|
+
dielinePhysicalHeight = configService.get("dieline.height") || 500;
|
|
2336
|
+
bleedOffset = configService.get("dieline.offset") || 0;
|
|
2337
|
+
const paddingValue = configService.get("dieline.padding") || 40;
|
|
2338
|
+
let padding = 0;
|
|
2339
|
+
if (typeof paddingValue === "number") {
|
|
2340
|
+
padding = paddingValue;
|
|
2341
|
+
} else if (typeof paddingValue === "string") {
|
|
2342
|
+
if (paddingValue.endsWith("%")) {
|
|
2343
|
+
const percent = parseFloat(paddingValue) / 100;
|
|
2344
|
+
padding = Math.min(canvasW, canvasH) * percent;
|
|
2345
|
+
} else {
|
|
2346
|
+
padding = parseFloat(paddingValue) || 0;
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
const layout = Coordinate.calculateLayout(
|
|
2350
|
+
{ width: canvasW, height: canvasH },
|
|
2351
|
+
{ width: dielinePhysicalWidth, height: dielinePhysicalHeight },
|
|
2352
|
+
padding
|
|
2353
|
+
);
|
|
2354
|
+
layoutScale = layout.scale;
|
|
2355
|
+
layoutOffsetX = layout.offsetX;
|
|
2356
|
+
layoutOffsetY = layout.offsetY;
|
|
2357
|
+
visualWidth = layout.width;
|
|
2358
|
+
visualHeight = layout.height;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
return {
|
|
2362
|
+
layoutScale,
|
|
2363
|
+
layoutOffsetX,
|
|
2364
|
+
layoutOffsetY,
|
|
2365
|
+
visualWidth,
|
|
2366
|
+
visualHeight,
|
|
2367
|
+
dielinePhysicalWidth,
|
|
2368
|
+
dielinePhysicalHeight,
|
|
2369
|
+
bleedOffset
|
|
2370
|
+
};
|
|
2371
|
+
}
|
|
2372
|
+
updateImages() {
|
|
2129
2373
|
if (!this.canvasService) return;
|
|
2130
|
-
let { url, opacity, width, height, angle, left, top } = this;
|
|
2131
2374
|
const layer = this.canvasService.getLayer("user");
|
|
2132
2375
|
if (!layer) {
|
|
2133
2376
|
console.warn("[ImageTool] User layer not found");
|
|
2134
2377
|
return;
|
|
2135
2378
|
}
|
|
2136
|
-
const
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
this.loadImage(layer);
|
|
2142
|
-
} else {
|
|
2143
|
-
const updates = {};
|
|
2144
|
-
const canvasW = this.canvasService.canvas.width || 800;
|
|
2145
|
-
const canvasH = this.canvasService.canvas.height || 600;
|
|
2146
|
-
const centerX = canvasW / 2;
|
|
2147
|
-
const centerY = canvasH / 2;
|
|
2148
|
-
if (userImage.opacity !== opacity) updates.opacity = opacity;
|
|
2149
|
-
if (angle !== void 0 && userImage.angle !== angle)
|
|
2150
|
-
updates.angle = angle;
|
|
2151
|
-
if (userImage.originX !== "center") {
|
|
2152
|
-
userImage.set({
|
|
2153
|
-
originX: "center",
|
|
2154
|
-
originY: "center",
|
|
2155
|
-
left: userImage.left + userImage.width * userImage.scaleX / 2,
|
|
2156
|
-
top: userImage.top + userImage.height * userImage.scaleY / 2
|
|
2157
|
-
});
|
|
2158
|
-
}
|
|
2159
|
-
if (left !== void 0) {
|
|
2160
|
-
const globalLeft = Coordinate.toAbsolute(left, canvasW);
|
|
2161
|
-
const localLeft = globalLeft - centerX;
|
|
2162
|
-
if (Math.abs(userImage.left - localLeft) > 1)
|
|
2163
|
-
updates.left = localLeft;
|
|
2164
|
-
}
|
|
2165
|
-
if (top !== void 0) {
|
|
2166
|
-
const globalTop = Coordinate.toAbsolute(top, canvasH);
|
|
2167
|
-
const localTop = globalTop - centerY;
|
|
2168
|
-
if (Math.abs(userImage.top - localTop) > 1) updates.top = localTop;
|
|
2169
|
-
}
|
|
2170
|
-
if (width !== void 0 && userImage.width)
|
|
2171
|
-
updates.scaleX = width / userImage.width;
|
|
2172
|
-
if (height !== void 0 && userImage.height)
|
|
2173
|
-
updates.scaleY = height / userImage.height;
|
|
2174
|
-
if (Object.keys(updates).length > 0) {
|
|
2175
|
-
userImage.set(updates);
|
|
2176
|
-
layer.dirty = true;
|
|
2177
|
-
this.canvasService.requestRenderAll();
|
|
2178
|
-
}
|
|
2379
|
+
const currentIds = new Set(this.items.map((i) => i.id));
|
|
2380
|
+
for (const [id, obj] of this.objectMap) {
|
|
2381
|
+
if (!currentIds.has(id)) {
|
|
2382
|
+
layer.remove(obj);
|
|
2383
|
+
this.objectMap.delete(id);
|
|
2179
2384
|
}
|
|
2180
|
-
} else {
|
|
2181
|
-
this.loadImage(layer);
|
|
2182
2385
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
this._loadingUrl = url;
|
|
2189
|
-
Image4.fromURL(url, { crossOrigin: "anonymous" }).then((image) => {
|
|
2190
|
-
var _a, _b, _c, _d, _e, _f;
|
|
2191
|
-
if (this._loadingUrl !== url) return;
|
|
2192
|
-
this._loadingUrl = null;
|
|
2193
|
-
let { opacity, width, height, angle, left, top } = this;
|
|
2194
|
-
if (this.context) {
|
|
2195
|
-
const configService = this.context.services.get(
|
|
2196
|
-
"ConfigurationService"
|
|
2197
|
-
);
|
|
2198
|
-
const dielineWidth = configService.get("dieline.width");
|
|
2199
|
-
const dielineHeight = configService.get("dieline.height");
|
|
2200
|
-
console.log(
|
|
2201
|
-
"[ImageTool] Dieline config debug:",
|
|
2202
|
-
{
|
|
2203
|
-
widthVal: dielineWidth,
|
|
2204
|
-
heightVal: dielineHeight,
|
|
2205
|
-
// Debug: dump all keys to see what is available
|
|
2206
|
-
allKeys: Array.from(
|
|
2207
|
-
((_a = configService.configValues) == null ? void 0 : _a.keys()) || []
|
|
2208
|
-
)
|
|
2209
|
-
},
|
|
2210
|
-
configService
|
|
2211
|
-
);
|
|
2212
|
-
if (width === void 0 && height === void 0) {
|
|
2213
|
-
const scale = Math.min(
|
|
2214
|
-
dielineWidth / (image.width || 1),
|
|
2215
|
-
dielineHeight / (image.height || 1)
|
|
2216
|
-
);
|
|
2217
|
-
width = (image.width || 1) * scale;
|
|
2218
|
-
height = (image.height || 1) * scale;
|
|
2219
|
-
this.width = width;
|
|
2220
|
-
this.height = height;
|
|
2221
|
-
}
|
|
2222
|
-
if (left === void 0 && top === void 0) {
|
|
2223
|
-
const dielinePos = configService == null ? void 0 : configService.get("dieline.position");
|
|
2224
|
-
if (dielinePos) {
|
|
2225
|
-
this.left = dielinePos.x;
|
|
2226
|
-
this.top = dielinePos.y;
|
|
2227
|
-
} else {
|
|
2228
|
-
this.left = 0.5;
|
|
2229
|
-
this.top = 0.5;
|
|
2230
|
-
}
|
|
2231
|
-
left = this.left;
|
|
2232
|
-
top = this.top;
|
|
2233
|
-
}
|
|
2234
|
-
}
|
|
2235
|
-
const existingImage = this.canvasService.getObject(
|
|
2236
|
-
"user-image",
|
|
2237
|
-
"user"
|
|
2238
|
-
);
|
|
2239
|
-
if (existingImage) {
|
|
2240
|
-
const defaultLeft = existingImage.left;
|
|
2241
|
-
const defaultTop = existingImage.top;
|
|
2242
|
-
const defaultAngle = existingImage.angle;
|
|
2243
|
-
const defaultScaleX = existingImage.scaleX;
|
|
2244
|
-
const defaultScaleY = existingImage.scaleY;
|
|
2245
|
-
const canvasW = ((_b = this.canvasService) == null ? void 0 : _b.canvas.width) || 800;
|
|
2246
|
-
const canvasH = ((_c = this.canvasService) == null ? void 0 : _c.canvas.height) || 600;
|
|
2247
|
-
const centerX = canvasW / 2;
|
|
2248
|
-
const centerY = canvasH / 2;
|
|
2249
|
-
let targetLeft = left !== void 0 ? left : defaultLeft;
|
|
2250
|
-
let targetTop = top !== void 0 ? top : defaultTop;
|
|
2251
|
-
const configService = (_d = this.context) == null ? void 0 : _d.services.get(
|
|
2252
|
-
"ConfigurationService"
|
|
2253
|
-
);
|
|
2254
|
-
console.log("[ImageTool] Loading EXISTING image...", {
|
|
2255
|
-
canvasW,
|
|
2256
|
-
canvasH,
|
|
2257
|
-
centerX,
|
|
2258
|
-
centerY,
|
|
2259
|
-
incomingLeft: left,
|
|
2260
|
-
incomingTop: top,
|
|
2261
|
-
dielinePos: configService == null ? void 0 : configService.get("dieline.position"),
|
|
2262
|
-
existingImage: !!existingImage
|
|
2263
|
-
});
|
|
2264
|
-
if (left !== void 0) {
|
|
2265
|
-
const globalLeft = Coordinate.toAbsolute(left, canvasW);
|
|
2266
|
-
targetLeft = globalLeft;
|
|
2267
|
-
console.log("[ImageTool] Calculated targetLeft", {
|
|
2268
|
-
globalLeft,
|
|
2269
|
-
targetLeft
|
|
2270
|
-
});
|
|
2271
|
-
}
|
|
2272
|
-
if (top !== void 0) {
|
|
2273
|
-
const globalTop = Coordinate.toAbsolute(top, canvasH);
|
|
2274
|
-
targetTop = globalTop;
|
|
2275
|
-
console.log("[ImageTool] Calculated targetTop", {
|
|
2276
|
-
globalTop,
|
|
2277
|
-
targetTop
|
|
2278
|
-
});
|
|
2279
|
-
}
|
|
2280
|
-
image.set({
|
|
2281
|
-
originX: "center",
|
|
2282
|
-
// Use center origin for easier positioning
|
|
2283
|
-
originY: "center",
|
|
2284
|
-
left: targetLeft,
|
|
2285
|
-
top: targetTop,
|
|
2286
|
-
angle: angle !== void 0 ? angle : defaultAngle,
|
|
2287
|
-
scaleX: width !== void 0 && image.width ? width / image.width : defaultScaleX,
|
|
2288
|
-
scaleY: height !== void 0 && image.height ? height / image.height : defaultScaleY
|
|
2289
|
-
});
|
|
2290
|
-
layer.remove(existingImage);
|
|
2386
|
+
const layout = this.getLayoutInfo();
|
|
2387
|
+
this.items.forEach((item, index) => {
|
|
2388
|
+
let obj = this.objectMap.get(item.id);
|
|
2389
|
+
if (!obj) {
|
|
2390
|
+
this.loadImage(item, layer, layout);
|
|
2291
2391
|
} else {
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
});
|
|
2296
|
-
if (width !== void 0 && image.width)
|
|
2297
|
-
image.scaleX = width / image.width;
|
|
2298
|
-
if (height !== void 0 && image.height)
|
|
2299
|
-
image.scaleY = height / image.height;
|
|
2300
|
-
if (angle !== void 0) image.angle = angle;
|
|
2301
|
-
const canvasW = ((_e = this.canvasService) == null ? void 0 : _e.canvas.width) || 800;
|
|
2302
|
-
const canvasH = ((_f = this.canvasService) == null ? void 0 : _f.canvas.height) || 600;
|
|
2303
|
-
const centerX = canvasW / 2;
|
|
2304
|
-
const centerY = canvasH / 2;
|
|
2305
|
-
if (left !== void 0) {
|
|
2306
|
-
image.left = Coordinate.toAbsolute(left, canvasW);
|
|
2307
|
-
} else {
|
|
2308
|
-
image.left = centerX;
|
|
2309
|
-
}
|
|
2310
|
-
if (top !== void 0) {
|
|
2311
|
-
image.top = Coordinate.toAbsolute(top, canvasH);
|
|
2312
|
-
} else {
|
|
2313
|
-
image.top = centerY;
|
|
2314
|
-
}
|
|
2392
|
+
this.updateObjectProperties(obj, item, layout);
|
|
2393
|
+
layer.remove(obj);
|
|
2394
|
+
layer.add(obj);
|
|
2315
2395
|
}
|
|
2396
|
+
});
|
|
2397
|
+
layer.dirty = true;
|
|
2398
|
+
this.canvasService.requestRenderAll();
|
|
2399
|
+
}
|
|
2400
|
+
updateObjectProperties(obj, item, layout) {
|
|
2401
|
+
const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight } = layout;
|
|
2402
|
+
const updates = {};
|
|
2403
|
+
if (obj.opacity !== item.opacity) updates.opacity = item.opacity;
|
|
2404
|
+
if (item.angle !== void 0 && obj.angle !== item.angle) updates.angle = item.angle;
|
|
2405
|
+
if (item.left !== void 0) {
|
|
2406
|
+
const globalLeft = layoutOffsetX + item.left * visualWidth;
|
|
2407
|
+
if (Math.abs(obj.left - globalLeft) > 1) updates.left = globalLeft;
|
|
2408
|
+
}
|
|
2409
|
+
if (item.top !== void 0) {
|
|
2410
|
+
const globalTop = layoutOffsetY + item.top * visualHeight;
|
|
2411
|
+
if (Math.abs(obj.top - globalTop) > 1) updates.top = globalTop;
|
|
2412
|
+
}
|
|
2413
|
+
if (item.width !== void 0 && obj.width) {
|
|
2414
|
+
const targetScaleX = item.width * layoutScale / obj.width;
|
|
2415
|
+
if (Math.abs(obj.scaleX - targetScaleX) > 1e-3) updates.scaleX = targetScaleX;
|
|
2416
|
+
}
|
|
2417
|
+
if (item.height !== void 0 && obj.height) {
|
|
2418
|
+
const targetScaleY = item.height * layoutScale / obj.height;
|
|
2419
|
+
if (Math.abs(obj.scaleY - targetScaleY) > 1e-3) updates.scaleY = targetScaleY;
|
|
2420
|
+
}
|
|
2421
|
+
if (obj.originX !== "center") {
|
|
2422
|
+
updates.originX = "center";
|
|
2423
|
+
updates.originY = "center";
|
|
2424
|
+
}
|
|
2425
|
+
if (Object.keys(updates).length > 0) {
|
|
2426
|
+
obj.set(updates);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
loadImage(item, layer, layout) {
|
|
2430
|
+
Image4.fromURL(item.url, { crossOrigin: "anonymous" }).then((image) => {
|
|
2431
|
+
var _a;
|
|
2432
|
+
if (!this.items.find((i) => i.id === item.id)) return;
|
|
2316
2433
|
image.set({
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2434
|
+
originX: "center",
|
|
2435
|
+
originY: "center",
|
|
2436
|
+
data: { id: item.id },
|
|
2437
|
+
uniformScaling: true,
|
|
2438
|
+
lockScalingFlip: true
|
|
2439
|
+
});
|
|
2440
|
+
image.setControlsVisibility({
|
|
2441
|
+
mt: false,
|
|
2442
|
+
mb: false,
|
|
2443
|
+
ml: false,
|
|
2444
|
+
mr: false
|
|
2321
2445
|
});
|
|
2446
|
+
let { width, height, left, top } = item;
|
|
2447
|
+
const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight, bleedOffset } = layout;
|
|
2448
|
+
if (width === void 0 && height === void 0) {
|
|
2449
|
+
const targetWidth = dielinePhysicalWidth + 2 * bleedOffset;
|
|
2450
|
+
const targetHeight = dielinePhysicalHeight + 2 * bleedOffset;
|
|
2451
|
+
const targetMax = Math.max(targetWidth, targetHeight);
|
|
2452
|
+
const imageMax = Math.max(image.width || 1, image.height || 1);
|
|
2453
|
+
const scale = targetMax / imageMax;
|
|
2454
|
+
width = (image.width || 1) * scale;
|
|
2455
|
+
height = (image.height || 1) * scale;
|
|
2456
|
+
item.width = width;
|
|
2457
|
+
item.height = height;
|
|
2458
|
+
}
|
|
2459
|
+
if (left === void 0 && top === void 0) {
|
|
2460
|
+
left = 0.5;
|
|
2461
|
+
top = 0.5;
|
|
2462
|
+
item.left = left;
|
|
2463
|
+
item.top = top;
|
|
2464
|
+
}
|
|
2465
|
+
this.updateObjectProperties(image, item, layout);
|
|
2322
2466
|
layer.add(image);
|
|
2467
|
+
this.objectMap.set(item.id, image);
|
|
2323
2468
|
image.on("modified", (e) => {
|
|
2324
|
-
|
|
2325
|
-
const matrix = image.calcTransformMatrix();
|
|
2326
|
-
const globalPoint = util.transformPoint(new Point2(0, 0), matrix);
|
|
2327
|
-
const canvasW = ((_a2 = this.canvasService) == null ? void 0 : _a2.canvas.width) || 800;
|
|
2328
|
-
const canvasH = ((_b2 = this.canvasService) == null ? void 0 : _b2.canvas.height) || 600;
|
|
2329
|
-
this.left = Coordinate.toNormalized(globalPoint.x, canvasW);
|
|
2330
|
-
this.top = Coordinate.toNormalized(globalPoint.y, canvasH);
|
|
2331
|
-
this.angle = e.target.angle;
|
|
2332
|
-
if (image.width) this.width = e.target.width * e.target.scaleX;
|
|
2333
|
-
if (image.height) this.height = e.target.height * e.target.scaleY;
|
|
2334
|
-
if (this.context) {
|
|
2335
|
-
this.context.eventBus.emit("update");
|
|
2336
|
-
}
|
|
2469
|
+
this.handleObjectModified(item.id, image);
|
|
2337
2470
|
});
|
|
2338
2471
|
layer.dirty = true;
|
|
2339
|
-
this.canvasService.requestRenderAll();
|
|
2472
|
+
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2473
|
+
if (item.width !== width || item.height !== height || item.left !== left || item.top !== top) {
|
|
2474
|
+
this.updateImageInConfig(item.id, { width, height, left, top });
|
|
2475
|
+
}
|
|
2340
2476
|
}).catch((err) => {
|
|
2341
|
-
|
|
2342
|
-
console.error("Failed to load image", url, err);
|
|
2477
|
+
console.error("Failed to load image", item.url, err);
|
|
2343
2478
|
});
|
|
2344
2479
|
}
|
|
2480
|
+
handleObjectModified(id, image) {
|
|
2481
|
+
const layout = this.getLayoutInfo();
|
|
2482
|
+
const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight } = layout;
|
|
2483
|
+
const matrix = image.calcTransformMatrix();
|
|
2484
|
+
const globalPoint = util.transformPoint(new Point2(0, 0), matrix);
|
|
2485
|
+
const updates = {};
|
|
2486
|
+
updates.left = (globalPoint.x - layoutOffsetX) / visualWidth;
|
|
2487
|
+
updates.top = (globalPoint.y - layoutOffsetY) / visualHeight;
|
|
2488
|
+
updates.angle = image.angle;
|
|
2489
|
+
if (image.width) {
|
|
2490
|
+
const pixelWidth = image.width * image.scaleX;
|
|
2491
|
+
updates.width = pixelWidth / layoutScale;
|
|
2492
|
+
}
|
|
2493
|
+
if (image.height) {
|
|
2494
|
+
const pixelHeight = image.height * image.scaleY;
|
|
2495
|
+
updates.height = pixelHeight / layoutScale;
|
|
2496
|
+
}
|
|
2497
|
+
this.updateImageInConfig(id, updates);
|
|
2498
|
+
}
|
|
2499
|
+
updateImageInConfig(id, updates) {
|
|
2500
|
+
const index = this.items.findIndex((i) => i.id === id);
|
|
2501
|
+
if (index !== -1) {
|
|
2502
|
+
const newItems = [...this.items];
|
|
2503
|
+
newItems[index] = { ...newItems[index], ...updates };
|
|
2504
|
+
this.updateConfig(newItems, true);
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2345
2507
|
};
|
|
2346
2508
|
|
|
2347
2509
|
// src/white-ink.ts
|
|
@@ -2641,19 +2803,25 @@ var WhiteInkTool = class {
|
|
|
2641
2803
|
import {
|
|
2642
2804
|
ContributionPointIds as ContributionPointIds7
|
|
2643
2805
|
} from "@pooder/core";
|
|
2644
|
-
import {
|
|
2806
|
+
import { Line, Text, Group as Group2, Polygon } from "fabric";
|
|
2645
2807
|
var RulerTool = class {
|
|
2646
2808
|
constructor(options) {
|
|
2647
2809
|
this.id = "pooder.kit.ruler";
|
|
2648
2810
|
this.metadata = {
|
|
2649
2811
|
name: "RulerTool"
|
|
2650
2812
|
};
|
|
2651
|
-
this.unit = "px";
|
|
2652
2813
|
this.thickness = 20;
|
|
2814
|
+
this.gap = 15;
|
|
2653
2815
|
this.backgroundColor = "#f0f0f0";
|
|
2654
2816
|
this.textColor = "#333333";
|
|
2655
2817
|
this.lineColor = "#999999";
|
|
2656
2818
|
this.fontSize = 10;
|
|
2819
|
+
// Dieline context for sync
|
|
2820
|
+
this.dielineWidth = 500;
|
|
2821
|
+
this.dielineHeight = 500;
|
|
2822
|
+
this.dielineUnit = "mm";
|
|
2823
|
+
this.dielinePadding = 40;
|
|
2824
|
+
this.dielineOffset = 0;
|
|
2657
2825
|
if (options) {
|
|
2658
2826
|
Object.assign(this, options);
|
|
2659
2827
|
}
|
|
@@ -2666,8 +2834,8 @@ var RulerTool = class {
|
|
|
2666
2834
|
}
|
|
2667
2835
|
const configService = context.services.get("ConfigurationService");
|
|
2668
2836
|
if (configService) {
|
|
2669
|
-
this.unit = configService.get("ruler.unit", this.unit);
|
|
2670
2837
|
this.thickness = configService.get("ruler.thickness", this.thickness);
|
|
2838
|
+
this.gap = configService.get("ruler.gap", this.gap);
|
|
2671
2839
|
this.backgroundColor = configService.get(
|
|
2672
2840
|
"ruler.backgroundColor",
|
|
2673
2841
|
this.backgroundColor
|
|
@@ -2675,13 +2843,38 @@ var RulerTool = class {
|
|
|
2675
2843
|
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
2676
2844
|
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
2677
2845
|
this.fontSize = configService.get("ruler.fontSize", this.fontSize);
|
|
2846
|
+
this.dielineUnit = configService.get("dieline.unit", this.dielineUnit);
|
|
2847
|
+
this.dielineWidth = configService.get("dieline.width", this.dielineWidth);
|
|
2848
|
+
this.dielineHeight = configService.get(
|
|
2849
|
+
"dieline.height",
|
|
2850
|
+
this.dielineHeight
|
|
2851
|
+
);
|
|
2852
|
+
this.dielinePadding = configService.get(
|
|
2853
|
+
"dieline.padding",
|
|
2854
|
+
this.dielinePadding
|
|
2855
|
+
);
|
|
2856
|
+
this.dielineOffset = configService.get(
|
|
2857
|
+
"dieline.offset",
|
|
2858
|
+
this.dielineOffset
|
|
2859
|
+
);
|
|
2678
2860
|
configService.onAnyChange((e) => {
|
|
2861
|
+
let shouldUpdate = false;
|
|
2679
2862
|
if (e.key.startsWith("ruler.")) {
|
|
2680
2863
|
const prop = e.key.split(".")[1];
|
|
2681
2864
|
if (prop && prop in this) {
|
|
2682
2865
|
this[prop] = e.value;
|
|
2683
|
-
|
|
2866
|
+
shouldUpdate = true;
|
|
2684
2867
|
}
|
|
2868
|
+
} else if (e.key.startsWith("dieline.")) {
|
|
2869
|
+
if (e.key === "dieline.unit") this.dielineUnit = e.value;
|
|
2870
|
+
if (e.key === "dieline.width") this.dielineWidth = e.value;
|
|
2871
|
+
if (e.key === "dieline.height") this.dielineHeight = e.value;
|
|
2872
|
+
if (e.key === "dieline.padding") this.dielinePadding = e.value;
|
|
2873
|
+
if (e.key === "dieline.offset") this.dielineOffset = e.value;
|
|
2874
|
+
shouldUpdate = true;
|
|
2875
|
+
}
|
|
2876
|
+
if (shouldUpdate) {
|
|
2877
|
+
this.updateRuler();
|
|
2685
2878
|
}
|
|
2686
2879
|
});
|
|
2687
2880
|
}
|
|
@@ -2695,13 +2888,6 @@ var RulerTool = class {
|
|
|
2695
2888
|
contribute() {
|
|
2696
2889
|
return {
|
|
2697
2890
|
[ContributionPointIds7.CONFIGURATIONS]: [
|
|
2698
|
-
{
|
|
2699
|
-
id: "ruler.unit",
|
|
2700
|
-
type: "select",
|
|
2701
|
-
label: "Unit",
|
|
2702
|
-
options: ["px", "mm", "cm", "in"],
|
|
2703
|
-
default: "px"
|
|
2704
|
-
},
|
|
2705
2891
|
{
|
|
2706
2892
|
id: "ruler.thickness",
|
|
2707
2893
|
type: "number",
|
|
@@ -2710,6 +2896,14 @@ var RulerTool = class {
|
|
|
2710
2896
|
max: 100,
|
|
2711
2897
|
default: 20
|
|
2712
2898
|
},
|
|
2899
|
+
{
|
|
2900
|
+
id: "ruler.gap",
|
|
2901
|
+
type: "number",
|
|
2902
|
+
label: "Gap",
|
|
2903
|
+
min: 0,
|
|
2904
|
+
max: 100,
|
|
2905
|
+
default: 15
|
|
2906
|
+
},
|
|
2713
2907
|
{
|
|
2714
2908
|
id: "ruler.backgroundColor",
|
|
2715
2909
|
type: "color",
|
|
@@ -2738,16 +2932,6 @@ var RulerTool = class {
|
|
|
2738
2932
|
}
|
|
2739
2933
|
],
|
|
2740
2934
|
[ContributionPointIds7.COMMANDS]: [
|
|
2741
|
-
{
|
|
2742
|
-
command: "setUnit",
|
|
2743
|
-
title: "Set Ruler Unit",
|
|
2744
|
-
handler: (unit) => {
|
|
2745
|
-
if (this.unit === unit) return true;
|
|
2746
|
-
this.unit = unit;
|
|
2747
|
-
this.updateRuler();
|
|
2748
|
-
return true;
|
|
2749
|
-
}
|
|
2750
|
-
},
|
|
2751
2935
|
{
|
|
2752
2936
|
command: "setTheme",
|
|
2753
2937
|
title: "Set Ruler Theme",
|
|
@@ -2798,6 +2982,68 @@ var RulerTool = class {
|
|
|
2798
2982
|
this.canvasService.canvas.remove(layer);
|
|
2799
2983
|
}
|
|
2800
2984
|
}
|
|
2985
|
+
createArrowLine(x1, y1, x2, y2, color) {
|
|
2986
|
+
const line = new Line([x1, y1, x2, y2], {
|
|
2987
|
+
stroke: color,
|
|
2988
|
+
strokeWidth: this.thickness / 20,
|
|
2989
|
+
// Scale stroke width relative to thickness (default 1)
|
|
2990
|
+
selectable: false,
|
|
2991
|
+
evented: false
|
|
2992
|
+
});
|
|
2993
|
+
const arrowSize = Math.max(4, this.thickness * 0.3);
|
|
2994
|
+
const angle = Math.atan2(y2 - y1, x2 - x1);
|
|
2995
|
+
const endArrow = new Polygon(
|
|
2996
|
+
[
|
|
2997
|
+
{ x: 0, y: 0 },
|
|
2998
|
+
{ x: -arrowSize, y: -arrowSize / 2 },
|
|
2999
|
+
{ x: -arrowSize, y: arrowSize / 2 }
|
|
3000
|
+
],
|
|
3001
|
+
{
|
|
3002
|
+
fill: color,
|
|
3003
|
+
left: x2,
|
|
3004
|
+
top: y2,
|
|
3005
|
+
originX: "right",
|
|
3006
|
+
originY: "center",
|
|
3007
|
+
angle: angle * 180 / Math.PI,
|
|
3008
|
+
selectable: false,
|
|
3009
|
+
evented: false
|
|
3010
|
+
}
|
|
3011
|
+
);
|
|
3012
|
+
const startArrow = new Polygon(
|
|
3013
|
+
[
|
|
3014
|
+
{ x: 0, y: 0 },
|
|
3015
|
+
{ x: arrowSize, y: -arrowSize / 2 },
|
|
3016
|
+
{ x: arrowSize, y: arrowSize / 2 }
|
|
3017
|
+
],
|
|
3018
|
+
{
|
|
3019
|
+
fill: color,
|
|
3020
|
+
left: x1,
|
|
3021
|
+
top: y1,
|
|
3022
|
+
originX: "left",
|
|
3023
|
+
originY: "center",
|
|
3024
|
+
angle: angle * 180 / Math.PI,
|
|
3025
|
+
selectable: false,
|
|
3026
|
+
evented: false
|
|
3027
|
+
}
|
|
3028
|
+
);
|
|
3029
|
+
return new Group2([line, startArrow, endArrow], {
|
|
3030
|
+
selectable: false,
|
|
3031
|
+
evented: false
|
|
3032
|
+
});
|
|
3033
|
+
}
|
|
3034
|
+
resolvePadding(containerWidth, containerHeight) {
|
|
3035
|
+
if (typeof this.dielinePadding === "number") {
|
|
3036
|
+
return this.dielinePadding;
|
|
3037
|
+
}
|
|
3038
|
+
if (typeof this.dielinePadding === "string") {
|
|
3039
|
+
if (this.dielinePadding.endsWith("%")) {
|
|
3040
|
+
const percent = parseFloat(this.dielinePadding) / 100;
|
|
3041
|
+
return Math.min(containerWidth, containerHeight) * percent;
|
|
3042
|
+
}
|
|
3043
|
+
return parseFloat(this.dielinePadding) || 0;
|
|
3044
|
+
}
|
|
3045
|
+
return 0;
|
|
3046
|
+
}
|
|
2801
3047
|
updateRuler() {
|
|
2802
3048
|
if (!this.canvasService) return;
|
|
2803
3049
|
const layer = this.getLayer();
|
|
@@ -2806,95 +3052,141 @@ var RulerTool = class {
|
|
|
2806
3052
|
const { thickness, backgroundColor, lineColor, textColor, fontSize } = this;
|
|
2807
3053
|
const width = this.canvasService.canvas.width || 800;
|
|
2808
3054
|
const height = this.canvasService.canvas.height || 600;
|
|
2809
|
-
const
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
width,
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
const
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
const
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
3055
|
+
const paddingPx = this.resolvePadding(width, height);
|
|
3056
|
+
const layout = Coordinate.calculateLayout(
|
|
3057
|
+
{ width, height },
|
|
3058
|
+
{ width: this.dielineWidth, height: this.dielineHeight },
|
|
3059
|
+
paddingPx
|
|
3060
|
+
);
|
|
3061
|
+
const scale = layout.scale;
|
|
3062
|
+
const offsetX = layout.offsetX;
|
|
3063
|
+
const offsetY = layout.offsetY;
|
|
3064
|
+
const visualWidth = layout.width;
|
|
3065
|
+
const visualHeight = layout.height;
|
|
3066
|
+
const rawOffset = this.dielineOffset || 0;
|
|
3067
|
+
const effectiveOffset = rawOffset > 0 ? rawOffset : 0;
|
|
3068
|
+
const expandPixels = effectiveOffset * scale;
|
|
3069
|
+
const gap = this.gap || 15;
|
|
3070
|
+
const rulerLeft = offsetX - expandPixels;
|
|
3071
|
+
const rulerTop = offsetY - expandPixels;
|
|
3072
|
+
const rulerRight = offsetX + visualWidth + expandPixels;
|
|
3073
|
+
const rulerBottom = offsetY + visualHeight + expandPixels;
|
|
3074
|
+
const displayWidth = this.dielineWidth + effectiveOffset * 2;
|
|
3075
|
+
const displayHeight = this.dielineHeight + effectiveOffset * 2;
|
|
3076
|
+
const topRulerY = rulerTop - gap;
|
|
3077
|
+
const topRulerXStart = rulerLeft;
|
|
3078
|
+
const topRulerXEnd = rulerRight;
|
|
3079
|
+
const leftRulerX = rulerLeft - gap;
|
|
3080
|
+
const leftRulerYStart = rulerTop;
|
|
3081
|
+
const leftRulerYEnd = rulerBottom;
|
|
3082
|
+
const topDimLine = this.createArrowLine(
|
|
3083
|
+
topRulerXStart,
|
|
3084
|
+
topRulerY,
|
|
3085
|
+
topRulerXEnd,
|
|
3086
|
+
topRulerY,
|
|
3087
|
+
lineColor
|
|
3088
|
+
);
|
|
3089
|
+
layer.add(topDimLine);
|
|
3090
|
+
const extLen = 5;
|
|
3091
|
+
layer.add(
|
|
3092
|
+
new Line(
|
|
3093
|
+
[
|
|
3094
|
+
topRulerXStart,
|
|
3095
|
+
topRulerY - extLen,
|
|
3096
|
+
topRulerXStart,
|
|
3097
|
+
topRulerY + extLen
|
|
3098
|
+
],
|
|
3099
|
+
{
|
|
3100
|
+
stroke: lineColor,
|
|
3101
|
+
strokeWidth: 1,
|
|
3102
|
+
selectable: false,
|
|
3103
|
+
evented: false
|
|
3104
|
+
}
|
|
3105
|
+
)
|
|
3106
|
+
);
|
|
3107
|
+
layer.add(
|
|
3108
|
+
new Line(
|
|
3109
|
+
[topRulerXEnd, topRulerY - extLen, topRulerXEnd, topRulerY + extLen],
|
|
3110
|
+
{
|
|
3111
|
+
stroke: lineColor,
|
|
3112
|
+
strokeWidth: 1,
|
|
3113
|
+
selectable: false,
|
|
3114
|
+
evented: false
|
|
3115
|
+
}
|
|
3116
|
+
)
|
|
3117
|
+
);
|
|
3118
|
+
const widthStr = parseFloat(displayWidth.toFixed(2)).toString();
|
|
3119
|
+
const topTextContent = `${widthStr} ${this.dielineUnit}`;
|
|
3120
|
+
const topText = new Text(topTextContent, {
|
|
3121
|
+
left: topRulerXStart + (rulerRight - rulerLeft) / 2,
|
|
3122
|
+
top: topRulerY,
|
|
3123
|
+
fontSize,
|
|
3124
|
+
fill: textColor,
|
|
3125
|
+
fontFamily: "Arial",
|
|
3126
|
+
originX: "center",
|
|
3127
|
+
originY: "center",
|
|
3128
|
+
backgroundColor,
|
|
3129
|
+
// Background mask for readability
|
|
2835
3130
|
selectable: false,
|
|
2836
3131
|
evented: false
|
|
2837
3132
|
});
|
|
2838
|
-
layer.add(
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
left: x + 2,
|
|
2859
|
-
top: 2,
|
|
2860
|
-
fontSize,
|
|
2861
|
-
fill: textColor,
|
|
2862
|
-
fontFamily: "Arial",
|
|
3133
|
+
layer.add(topText);
|
|
3134
|
+
const leftDimLine = this.createArrowLine(
|
|
3135
|
+
leftRulerX,
|
|
3136
|
+
leftRulerYStart,
|
|
3137
|
+
leftRulerX,
|
|
3138
|
+
leftRulerYEnd,
|
|
3139
|
+
lineColor
|
|
3140
|
+
);
|
|
3141
|
+
layer.add(leftDimLine);
|
|
3142
|
+
layer.add(
|
|
3143
|
+
new Line(
|
|
3144
|
+
[
|
|
3145
|
+
leftRulerX - extLen,
|
|
3146
|
+
leftRulerYStart,
|
|
3147
|
+
leftRulerX + extLen,
|
|
3148
|
+
leftRulerYStart
|
|
3149
|
+
],
|
|
3150
|
+
{
|
|
3151
|
+
stroke: lineColor,
|
|
3152
|
+
strokeWidth: 1,
|
|
2863
3153
|
selectable: false,
|
|
2864
3154
|
evented: false
|
|
2865
|
-
}
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
});
|
|
2880
|
-
layer.add(line);
|
|
2881
|
-
if (y % step === 0) {
|
|
2882
|
-
const text = new Text(y.toString(), {
|
|
2883
|
-
angle: -90,
|
|
2884
|
-
left: thickness / 2 - fontSize / 3,
|
|
2885
|
-
// approximate centering
|
|
2886
|
-
top: y + fontSize,
|
|
2887
|
-
fontSize,
|
|
2888
|
-
fill: textColor,
|
|
2889
|
-
fontFamily: "Arial",
|
|
2890
|
-
originX: "center",
|
|
2891
|
-
originY: "center",
|
|
3155
|
+
}
|
|
3156
|
+
)
|
|
3157
|
+
);
|
|
3158
|
+
layer.add(
|
|
3159
|
+
new Line(
|
|
3160
|
+
[
|
|
3161
|
+
leftRulerX - extLen,
|
|
3162
|
+
leftRulerYEnd,
|
|
3163
|
+
leftRulerX + extLen,
|
|
3164
|
+
leftRulerYEnd
|
|
3165
|
+
],
|
|
3166
|
+
{
|
|
3167
|
+
stroke: lineColor,
|
|
3168
|
+
strokeWidth: 1,
|
|
2892
3169
|
selectable: false,
|
|
2893
3170
|
evented: false
|
|
2894
|
-
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
3171
|
+
}
|
|
3172
|
+
)
|
|
3173
|
+
);
|
|
3174
|
+
const heightStr = parseFloat(displayHeight.toFixed(2)).toString();
|
|
3175
|
+
const leftTextContent = `${heightStr} ${this.dielineUnit}`;
|
|
3176
|
+
const leftText = new Text(leftTextContent, {
|
|
3177
|
+
left: leftRulerX,
|
|
3178
|
+
top: leftRulerYStart + (rulerBottom - rulerTop) / 2,
|
|
3179
|
+
angle: -90,
|
|
3180
|
+
fontSize,
|
|
3181
|
+
fill: textColor,
|
|
3182
|
+
fontFamily: "Arial",
|
|
3183
|
+
originX: "center",
|
|
3184
|
+
originY: "center",
|
|
3185
|
+
backgroundColor,
|
|
3186
|
+
selectable: false,
|
|
3187
|
+
evented: false
|
|
3188
|
+
});
|
|
3189
|
+
layer.add(leftText);
|
|
2898
3190
|
this.canvasService.canvas.bringObjectToFront(layer);
|
|
2899
3191
|
this.canvasService.canvas.requestRenderAll();
|
|
2900
3192
|
}
|
|
@@ -2993,7 +3285,7 @@ var MirrorTool = class {
|
|
|
2993
3285
|
};
|
|
2994
3286
|
|
|
2995
3287
|
// src/CanvasService.ts
|
|
2996
|
-
import { Canvas, Group as
|
|
3288
|
+
import { Canvas, Group as Group3 } from "fabric";
|
|
2997
3289
|
var CanvasService = class {
|
|
2998
3290
|
constructor(el, options) {
|
|
2999
3291
|
if (el instanceof Canvas) {
|
|
@@ -3030,7 +3322,7 @@ var CanvasService = class {
|
|
|
3030
3322
|
...options,
|
|
3031
3323
|
data: { ...options.data, id }
|
|
3032
3324
|
};
|
|
3033
|
-
layer = new
|
|
3325
|
+
layer = new Group3([], defaultOptions);
|
|
3034
3326
|
this.canvas.add(layer);
|
|
3035
3327
|
}
|
|
3036
3328
|
return layer;
|