@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.js
CHANGED
|
@@ -434,6 +434,24 @@ var ImageTracer = class {
|
|
|
434
434
|
|
|
435
435
|
// src/coordinate.ts
|
|
436
436
|
var Coordinate = class {
|
|
437
|
+
/**
|
|
438
|
+
* Calculate layout to fit content within container while preserving aspect ratio.
|
|
439
|
+
*/
|
|
440
|
+
static calculateLayout(container, content, padding = 0) {
|
|
441
|
+
const availableWidth = Math.max(0, container.width - padding * 2);
|
|
442
|
+
const availableHeight = Math.max(0, container.height - padding * 2);
|
|
443
|
+
if (content.width === 0 || content.height === 0) {
|
|
444
|
+
return { scale: 1, offsetX: 0, offsetY: 0, width: 0, height: 0 };
|
|
445
|
+
}
|
|
446
|
+
const scaleX = availableWidth / content.width;
|
|
447
|
+
const scaleY = availableHeight / content.height;
|
|
448
|
+
const scale = Math.min(scaleX, scaleY);
|
|
449
|
+
const width = content.width * scale;
|
|
450
|
+
const height = content.height * scale;
|
|
451
|
+
const offsetX = (container.width - width) / 2;
|
|
452
|
+
const offsetY = (container.height - height) / 2;
|
|
453
|
+
return { scale, offsetX, offsetY, width, height };
|
|
454
|
+
}
|
|
437
455
|
/**
|
|
438
456
|
* Convert an absolute value to a normalized value (0-1).
|
|
439
457
|
* @param value Absolute value (e.g., pixels)
|
|
@@ -468,6 +486,21 @@ var Coordinate = class {
|
|
|
468
486
|
y: this.toAbsolute(point.y, size.height)
|
|
469
487
|
};
|
|
470
488
|
}
|
|
489
|
+
static convertUnit(value, from, to) {
|
|
490
|
+
if (from === to) return value;
|
|
491
|
+
const toMM = {
|
|
492
|
+
px: 0.264583,
|
|
493
|
+
// 1px = 0.264583mm (96 DPI)
|
|
494
|
+
mm: 1,
|
|
495
|
+
cm: 10,
|
|
496
|
+
in: 25.4
|
|
497
|
+
};
|
|
498
|
+
const mmValue = value * (from === "px" ? toMM.px : toMM[from] || 1);
|
|
499
|
+
if (to === "px") {
|
|
500
|
+
return mmValue / toMM.px;
|
|
501
|
+
}
|
|
502
|
+
return mmValue / (toMM[to] || 1);
|
|
503
|
+
}
|
|
471
504
|
};
|
|
472
505
|
|
|
473
506
|
// src/geometry.ts
|
|
@@ -524,9 +557,10 @@ function resolveHolePosition(hole, geometry, canvasSize) {
|
|
|
524
557
|
y: by + (hole.offsetY || 0)
|
|
525
558
|
};
|
|
526
559
|
} else if (hole.x !== void 0 && hole.y !== void 0) {
|
|
560
|
+
const { x, width, y, height } = geometry;
|
|
527
561
|
return {
|
|
528
|
-
x: hole.x *
|
|
529
|
-
y: hole.y *
|
|
562
|
+
x: hole.x * width + (x - width / 2) + (hole.offsetX || 0),
|
|
563
|
+
y: hole.y * height + (y - height / 2) + (hole.offsetY || 0)
|
|
530
564
|
};
|
|
531
565
|
}
|
|
532
566
|
return { x: 0, y: 0 };
|
|
@@ -580,12 +614,25 @@ function getDielineShape(options) {
|
|
|
580
614
|
let lugsPath = null;
|
|
581
615
|
let cutsPath = null;
|
|
582
616
|
holes.forEach((hole) => {
|
|
583
|
-
const
|
|
584
|
-
|
|
617
|
+
const center = new import_paper.default.Point(hole.x, hole.y);
|
|
618
|
+
const lug = hole.shape === "square" ? new import_paper.default.Path.Rectangle({
|
|
619
|
+
point: [
|
|
620
|
+
center.x - hole.outerRadius,
|
|
621
|
+
center.y - hole.outerRadius
|
|
622
|
+
],
|
|
623
|
+
size: [hole.outerRadius * 2, hole.outerRadius * 2]
|
|
624
|
+
}) : new import_paper.default.Path.Circle({
|
|
625
|
+
center,
|
|
585
626
|
radius: hole.outerRadius
|
|
586
627
|
});
|
|
587
|
-
const cut = new import_paper.default.Path.
|
|
588
|
-
|
|
628
|
+
const cut = hole.shape === "square" ? new import_paper.default.Path.Rectangle({
|
|
629
|
+
point: [
|
|
630
|
+
center.x - hole.innerRadius,
|
|
631
|
+
center.y - hole.innerRadius
|
|
632
|
+
],
|
|
633
|
+
size: [hole.innerRadius * 2, hole.innerRadius * 2]
|
|
634
|
+
}) : new import_paper.default.Path.Circle({
|
|
635
|
+
center,
|
|
589
636
|
radius: hole.innerRadius
|
|
590
637
|
});
|
|
591
638
|
if (!lugsPath) {
|
|
@@ -632,14 +679,19 @@ function getDielineShape(options) {
|
|
|
632
679
|
cutsPath.remove();
|
|
633
680
|
mainShape = temp;
|
|
634
681
|
} catch (e) {
|
|
635
|
-
console.error(
|
|
682
|
+
console.error(
|
|
683
|
+
"Geometry: Failed to subtract cutsPath from mainShape",
|
|
684
|
+
e
|
|
685
|
+
);
|
|
636
686
|
}
|
|
637
687
|
}
|
|
638
688
|
}
|
|
639
689
|
return mainShape;
|
|
640
690
|
}
|
|
641
691
|
function generateDielinePath(options) {
|
|
642
|
-
|
|
692
|
+
const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
|
|
693
|
+
const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
|
|
694
|
+
ensurePaper(paperWidth, paperHeight);
|
|
643
695
|
import_paper.default.project.activeLayer.removeChildren();
|
|
644
696
|
const mainShape = getDielineShape(options);
|
|
645
697
|
const pathData = mainShape.pathData;
|
|
@@ -663,8 +715,9 @@ function generateMaskPath(options) {
|
|
|
663
715
|
return pathData;
|
|
664
716
|
}
|
|
665
717
|
function generateBleedZonePath(options, offset) {
|
|
666
|
-
const
|
|
667
|
-
|
|
718
|
+
const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
|
|
719
|
+
const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
|
|
720
|
+
ensurePaper(paperWidth, paperHeight);
|
|
668
721
|
import_paper.default.project.activeLayer.removeChildren();
|
|
669
722
|
const shapeOriginal = getDielineShape(options);
|
|
670
723
|
let shapeOffset;
|
|
@@ -725,7 +778,12 @@ function getPathBounds(pathData) {
|
|
|
725
778
|
path.pathData = pathData;
|
|
726
779
|
const bounds = path.bounds;
|
|
727
780
|
path.remove();
|
|
728
|
-
return {
|
|
781
|
+
return {
|
|
782
|
+
x: bounds.x,
|
|
783
|
+
y: bounds.y,
|
|
784
|
+
width: bounds.width,
|
|
785
|
+
height: bounds.height
|
|
786
|
+
};
|
|
729
787
|
}
|
|
730
788
|
|
|
731
789
|
// src/dieline.ts
|
|
@@ -735,6 +793,7 @@ var DielineTool = class {
|
|
|
735
793
|
this.metadata = {
|
|
736
794
|
name: "DielineTool"
|
|
737
795
|
};
|
|
796
|
+
this.unit = "mm";
|
|
738
797
|
this.shape = "rect";
|
|
739
798
|
this.width = 500;
|
|
740
799
|
this.height = 500;
|
|
@@ -745,6 +804,7 @@ var DielineTool = class {
|
|
|
745
804
|
this.outsideColor = "#ffffff";
|
|
746
805
|
this.showBleedLines = true;
|
|
747
806
|
this.holes = [];
|
|
807
|
+
this.padding = 140;
|
|
748
808
|
if (options) {
|
|
749
809
|
Object.assign(this, options);
|
|
750
810
|
}
|
|
@@ -758,14 +818,12 @@ var DielineTool = class {
|
|
|
758
818
|
}
|
|
759
819
|
const configService = context.services.get("ConfigurationService");
|
|
760
820
|
if (configService) {
|
|
821
|
+
this.unit = configService.get("dieline.unit", this.unit);
|
|
761
822
|
this.shape = configService.get("dieline.shape", this.shape);
|
|
762
823
|
this.width = configService.get("dieline.width", this.width);
|
|
763
824
|
this.height = configService.get("dieline.height", this.height);
|
|
764
825
|
this.radius = configService.get("dieline.radius", this.radius);
|
|
765
|
-
this.
|
|
766
|
-
"dieline.borderLength",
|
|
767
|
-
this.borderLength
|
|
768
|
-
);
|
|
826
|
+
this.padding = configService.get("dieline.padding", this.padding);
|
|
769
827
|
this.offset = configService.get("dieline.offset", this.offset);
|
|
770
828
|
this.style = configService.get("dieline.style", this.style);
|
|
771
829
|
this.insideColor = configService.get(
|
|
@@ -806,6 +864,13 @@ var DielineTool = class {
|
|
|
806
864
|
contribute() {
|
|
807
865
|
return {
|
|
808
866
|
[import_core2.ContributionPointIds.CONFIGURATIONS]: [
|
|
867
|
+
{
|
|
868
|
+
id: "dieline.unit",
|
|
869
|
+
type: "select",
|
|
870
|
+
label: "Unit",
|
|
871
|
+
options: ["px", "mm", "cm", "in"],
|
|
872
|
+
default: this.unit
|
|
873
|
+
},
|
|
809
874
|
{
|
|
810
875
|
id: "dieline.shape",
|
|
811
876
|
type: "select",
|
|
@@ -841,15 +906,14 @@ var DielineTool = class {
|
|
|
841
906
|
id: "dieline.position",
|
|
842
907
|
type: "json",
|
|
843
908
|
label: "Position (Normalized)",
|
|
844
|
-
default: this.
|
|
909
|
+
default: this.radius
|
|
845
910
|
},
|
|
846
911
|
{
|
|
847
|
-
id: "dieline.
|
|
848
|
-
type: "
|
|
849
|
-
label: "
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
default: this.borderLength
|
|
912
|
+
id: "dieline.padding",
|
|
913
|
+
type: "select",
|
|
914
|
+
label: "View Padding",
|
|
915
|
+
options: [0, 10, 20, 40, 60, 100, "2%", "5%", "10%", "15%", "20%"],
|
|
916
|
+
default: this.padding
|
|
853
917
|
},
|
|
854
918
|
{
|
|
855
919
|
id: "dieline.offset",
|
|
@@ -918,7 +982,9 @@ var DielineTool = class {
|
|
|
918
982
|
const scale = currentMax / Math.max(bounds.width, bounds.height);
|
|
919
983
|
const newWidth = bounds.width * scale;
|
|
920
984
|
const newHeight = bounds.height * scale;
|
|
921
|
-
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
985
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
986
|
+
"ConfigurationService"
|
|
987
|
+
);
|
|
922
988
|
if (configService) {
|
|
923
989
|
configService.update("dieline.width", newWidth);
|
|
924
990
|
configService.update("dieline.height", newHeight);
|
|
@@ -983,12 +1049,25 @@ var DielineTool = class {
|
|
|
983
1049
|
}
|
|
984
1050
|
return new import_fabric2.Pattern({ source: canvas, repetition: "repeat" });
|
|
985
1051
|
}
|
|
1052
|
+
resolvePadding(containerWidth, containerHeight) {
|
|
1053
|
+
if (typeof this.padding === "number") {
|
|
1054
|
+
return this.padding;
|
|
1055
|
+
}
|
|
1056
|
+
if (typeof this.padding === "string") {
|
|
1057
|
+
if (this.padding.endsWith("%")) {
|
|
1058
|
+
const percent = parseFloat(this.padding) / 100;
|
|
1059
|
+
return Math.min(containerWidth, containerHeight) * percent;
|
|
1060
|
+
}
|
|
1061
|
+
return parseFloat(this.padding) || 0;
|
|
1062
|
+
}
|
|
1063
|
+
return 0;
|
|
1064
|
+
}
|
|
986
1065
|
updateDieline(emitEvent = true) {
|
|
987
|
-
var _a, _b;
|
|
988
1066
|
if (!this.canvasService) return;
|
|
989
1067
|
const layer = this.getLayer();
|
|
990
1068
|
if (!layer) return;
|
|
991
1069
|
const {
|
|
1070
|
+
unit,
|
|
992
1071
|
shape,
|
|
993
1072
|
radius,
|
|
994
1073
|
offset,
|
|
@@ -996,43 +1075,60 @@ var DielineTool = class {
|
|
|
996
1075
|
insideColor,
|
|
997
1076
|
outsideColor,
|
|
998
1077
|
position,
|
|
999
|
-
borderLength,
|
|
1000
1078
|
showBleedLines,
|
|
1001
1079
|
holes
|
|
1002
1080
|
} = this;
|
|
1003
1081
|
let { width, height } = this;
|
|
1004
1082
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1005
1083
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
const
|
|
1013
|
-
const
|
|
1084
|
+
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1085
|
+
const layout = Coordinate.calculateLayout(
|
|
1086
|
+
{ width: canvasW, height: canvasH },
|
|
1087
|
+
{ width, height },
|
|
1088
|
+
paddingPx
|
|
1089
|
+
);
|
|
1090
|
+
const scale = layout.scale;
|
|
1091
|
+
const cx = layout.offsetX + layout.width / 2;
|
|
1092
|
+
const cy = layout.offsetY + layout.height / 2;
|
|
1093
|
+
const visualWidth = layout.width;
|
|
1094
|
+
const visualHeight = layout.height;
|
|
1095
|
+
const visualRadius = radius * scale;
|
|
1096
|
+
const visualOffset = offset * scale;
|
|
1014
1097
|
layer.remove(...layer.getObjects());
|
|
1015
1098
|
const geometryForHoles = {
|
|
1016
1099
|
x: cx,
|
|
1017
1100
|
y: cy,
|
|
1018
1101
|
width: visualWidth,
|
|
1019
1102
|
height: visualHeight
|
|
1103
|
+
// Pass scale/unit context if needed by resolveHolePosition (though currently unused there)
|
|
1020
1104
|
};
|
|
1021
1105
|
const absoluteHoles = (holes || []).map((h) => {
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1106
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1107
|
+
const offsetScale = unitScale * scale;
|
|
1108
|
+
const hWithPixelOffsets = {
|
|
1109
|
+
...h,
|
|
1110
|
+
offsetX: (h.offsetX || 0) * offsetScale,
|
|
1111
|
+
offsetY: (h.offsetY || 0) * offsetScale
|
|
1112
|
+
};
|
|
1113
|
+
const pos = resolveHolePosition(hWithPixelOffsets, geometryForHoles, {
|
|
1114
|
+
width: canvasW,
|
|
1115
|
+
height: canvasH
|
|
1116
|
+
});
|
|
1027
1117
|
return {
|
|
1028
1118
|
...h,
|
|
1029
1119
|
x: pos.x,
|
|
1030
|
-
y: pos.y
|
|
1120
|
+
y: pos.y,
|
|
1121
|
+
// Scale hole radii: mm -> current unit -> pixels
|
|
1122
|
+
innerRadius: h.innerRadius * offsetScale,
|
|
1123
|
+
outerRadius: h.outerRadius * offsetScale,
|
|
1124
|
+
// Store scaled offsets in the result for consistency, though pos is already resolved
|
|
1125
|
+
offsetX: hWithPixelOffsets.offsetX,
|
|
1126
|
+
offsetY: hWithPixelOffsets.offsetY
|
|
1031
1127
|
};
|
|
1032
1128
|
});
|
|
1033
|
-
const cutW = Math.max(0,
|
|
1034
|
-
const cutH = Math.max(0,
|
|
1035
|
-
const cutR =
|
|
1129
|
+
const cutW = Math.max(0, visualWidth + visualOffset * 2);
|
|
1130
|
+
const cutH = Math.max(0, visualHeight + visualOffset * 2);
|
|
1131
|
+
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
1036
1132
|
const maskPathData = generateMaskPath({
|
|
1037
1133
|
canvasWidth: canvasW,
|
|
1038
1134
|
canvasHeight: canvasH,
|
|
@@ -1065,7 +1161,9 @@ var DielineTool = class {
|
|
|
1065
1161
|
x: cx,
|
|
1066
1162
|
y: cy,
|
|
1067
1163
|
holes: absoluteHoles,
|
|
1068
|
-
pathData: this.pathData
|
|
1164
|
+
pathData: this.pathData,
|
|
1165
|
+
canvasWidth: canvasW,
|
|
1166
|
+
canvasHeight: canvasH
|
|
1069
1167
|
});
|
|
1070
1168
|
const insideObj = new import_fabric2.Path(productPathData, {
|
|
1071
1169
|
fill: insideColor,
|
|
@@ -1082,15 +1180,17 @@ var DielineTool = class {
|
|
|
1082
1180
|
const bleedPathData = generateBleedZonePath(
|
|
1083
1181
|
{
|
|
1084
1182
|
shape,
|
|
1085
|
-
width,
|
|
1086
|
-
height,
|
|
1087
|
-
radius,
|
|
1183
|
+
width: visualWidth,
|
|
1184
|
+
height: visualHeight,
|
|
1185
|
+
radius: visualRadius,
|
|
1088
1186
|
x: cx,
|
|
1089
1187
|
y: cy,
|
|
1090
1188
|
holes: absoluteHoles,
|
|
1091
|
-
pathData: this.pathData
|
|
1189
|
+
pathData: this.pathData,
|
|
1190
|
+
canvasWidth: canvasW,
|
|
1191
|
+
canvasHeight: canvasH
|
|
1092
1192
|
},
|
|
1093
|
-
|
|
1193
|
+
visualOffset
|
|
1094
1194
|
);
|
|
1095
1195
|
if (showBleedLines !== false) {
|
|
1096
1196
|
const pattern = this.createHatchPattern("red");
|
|
@@ -1115,7 +1215,9 @@ var DielineTool = class {
|
|
|
1115
1215
|
x: cx,
|
|
1116
1216
|
y: cy,
|
|
1117
1217
|
holes: absoluteHoles,
|
|
1118
|
-
pathData: this.pathData
|
|
1218
|
+
pathData: this.pathData,
|
|
1219
|
+
canvasWidth: canvasW,
|
|
1220
|
+
canvasHeight: canvasH
|
|
1119
1221
|
});
|
|
1120
1222
|
const offsetBorderObj = new import_fabric2.Path(offsetPathData, {
|
|
1121
1223
|
fill: null,
|
|
@@ -1133,14 +1235,15 @@ var DielineTool = class {
|
|
|
1133
1235
|
}
|
|
1134
1236
|
const borderPathData = generateDielinePath({
|
|
1135
1237
|
shape,
|
|
1136
|
-
width,
|
|
1137
|
-
height,
|
|
1138
|
-
radius,
|
|
1238
|
+
width: visualWidth,
|
|
1239
|
+
height: visualHeight,
|
|
1240
|
+
radius: visualRadius,
|
|
1139
1241
|
x: cx,
|
|
1140
1242
|
y: cy,
|
|
1141
1243
|
holes: absoluteHoles,
|
|
1142
|
-
|
|
1143
|
-
|
|
1244
|
+
pathData: this.pathData,
|
|
1245
|
+
canvasWidth: canvasW,
|
|
1246
|
+
canvasHeight: canvasH
|
|
1144
1247
|
});
|
|
1145
1248
|
const borderObj = new import_fabric2.Path(borderPathData, {
|
|
1146
1249
|
fill: "transparent",
|
|
@@ -1177,115 +1280,109 @@ var DielineTool = class {
|
|
|
1177
1280
|
}
|
|
1178
1281
|
}
|
|
1179
1282
|
getGeometry() {
|
|
1180
|
-
var _a, _b;
|
|
1181
1283
|
if (!this.canvasService) return null;
|
|
1182
|
-
const { shape, width, height, radius, position,
|
|
1284
|
+
const { unit, shape, width, height, radius, position, offset } = this;
|
|
1183
1285
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1184
1286
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
const
|
|
1192
|
-
const
|
|
1287
|
+
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1288
|
+
const layout = Coordinate.calculateLayout(
|
|
1289
|
+
{ width: canvasW, height: canvasH },
|
|
1290
|
+
{ width, height },
|
|
1291
|
+
paddingPx
|
|
1292
|
+
);
|
|
1293
|
+
const scale = layout.scale;
|
|
1294
|
+
const cx = layout.offsetX + layout.width / 2;
|
|
1295
|
+
const cy = layout.offsetY + layout.height / 2;
|
|
1296
|
+
const visualWidth = layout.width;
|
|
1297
|
+
const visualHeight = layout.height;
|
|
1193
1298
|
return {
|
|
1194
1299
|
shape,
|
|
1300
|
+
unit,
|
|
1195
1301
|
x: cx,
|
|
1196
1302
|
y: cy,
|
|
1197
1303
|
width: visualWidth,
|
|
1198
1304
|
height: visualHeight,
|
|
1199
|
-
radius,
|
|
1200
|
-
offset,
|
|
1201
|
-
|
|
1305
|
+
radius: radius * scale,
|
|
1306
|
+
offset: offset * scale,
|
|
1307
|
+
// Pass scale to help other tools (like HoleTool) convert units
|
|
1308
|
+
scale,
|
|
1202
1309
|
pathData: this.pathData
|
|
1203
1310
|
};
|
|
1204
1311
|
}
|
|
1205
|
-
exportCutImage() {
|
|
1206
|
-
var _a, _b, _c, _d;
|
|
1312
|
+
async exportCutImage() {
|
|
1207
1313
|
if (!this.canvasService) return null;
|
|
1208
|
-
const
|
|
1314
|
+
const userLayer = this.canvasService.getLayer("user");
|
|
1315
|
+
if (!userLayer) return null;
|
|
1209
1316
|
const { shape, width, height, radius, position, holes } = this;
|
|
1210
|
-
const canvasW = canvas.width || 800;
|
|
1211
|
-
const canvasH = canvas.height || 600;
|
|
1212
|
-
const
|
|
1213
|
-
const
|
|
1317
|
+
const canvasW = this.canvasService.canvas.width || 800;
|
|
1318
|
+
const canvasH = this.canvasService.canvas.height || 600;
|
|
1319
|
+
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1320
|
+
const layout = Coordinate.calculateLayout(
|
|
1321
|
+
{ width: canvasW, height: canvasH },
|
|
1322
|
+
{ width, height },
|
|
1323
|
+
paddingPx
|
|
1324
|
+
);
|
|
1325
|
+
const scale = layout.scale;
|
|
1326
|
+
const cx = layout.offsetX + layout.width / 2;
|
|
1327
|
+
const cy = layout.offsetY + layout.height / 2;
|
|
1328
|
+
const visualWidth = layout.width;
|
|
1329
|
+
const visualHeight = layout.height;
|
|
1330
|
+
const visualRadius = radius * scale;
|
|
1214
1331
|
const absoluteHoles = (holes || []).map((h) => {
|
|
1332
|
+
const unit = this.unit || "mm";
|
|
1333
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1215
1334
|
const pos = resolveHolePosition(
|
|
1216
|
-
|
|
1217
|
-
|
|
1335
|
+
{
|
|
1336
|
+
...h,
|
|
1337
|
+
offsetX: (h.offsetX || 0) * unitScale * scale,
|
|
1338
|
+
offsetY: (h.offsetY || 0) * unitScale * scale
|
|
1339
|
+
},
|
|
1340
|
+
{ x: cx, y: cy, width: visualWidth, height: visualHeight },
|
|
1218
1341
|
{ width: canvasW, height: canvasH }
|
|
1219
1342
|
);
|
|
1220
1343
|
return {
|
|
1221
1344
|
...h,
|
|
1222
1345
|
x: pos.x,
|
|
1223
|
-
y: pos.y
|
|
1346
|
+
y: pos.y,
|
|
1347
|
+
innerRadius: h.innerRadius * unitScale * scale,
|
|
1348
|
+
outerRadius: h.outerRadius * unitScale * scale,
|
|
1349
|
+
offsetX: (h.offsetX || 0) * unitScale * scale,
|
|
1350
|
+
offsetY: (h.offsetY || 0) * unitScale * scale
|
|
1224
1351
|
};
|
|
1225
1352
|
});
|
|
1226
1353
|
const pathData = generateDielinePath({
|
|
1227
1354
|
shape,
|
|
1228
|
-
width,
|
|
1229
|
-
height,
|
|
1230
|
-
radius,
|
|
1355
|
+
width: visualWidth,
|
|
1356
|
+
height: visualHeight,
|
|
1357
|
+
radius: visualRadius,
|
|
1231
1358
|
x: cx,
|
|
1232
1359
|
y: cy,
|
|
1233
1360
|
holes: absoluteHoles,
|
|
1234
|
-
pathData: this.pathData
|
|
1361
|
+
pathData: this.pathData,
|
|
1362
|
+
canvasWidth: canvasW,
|
|
1363
|
+
canvasHeight: canvasH
|
|
1235
1364
|
});
|
|
1365
|
+
const clonedLayer = await userLayer.clone();
|
|
1236
1366
|
const clipPath = new import_fabric2.Path(pathData, {
|
|
1237
|
-
left: 0,
|
|
1238
|
-
top: 0,
|
|
1239
1367
|
originX: "left",
|
|
1240
1368
|
originY: "top",
|
|
1241
|
-
absolutePositioned: true
|
|
1242
|
-
});
|
|
1243
|
-
const layer = this.getLayer();
|
|
1244
|
-
const wasVisible = (_c = layer == null ? void 0 : layer.visible) != null ? _c : true;
|
|
1245
|
-
if (layer) layer.visible = false;
|
|
1246
|
-
const holeMarkers = canvas.getObjects().filter((o) => {
|
|
1247
|
-
var _a2;
|
|
1248
|
-
return ((_a2 = o.data) == null ? void 0 : _a2.type) === "hole-marker";
|
|
1249
|
-
});
|
|
1250
|
-
holeMarkers.forEach((o) => o.visible = false);
|
|
1251
|
-
const rulerLayer = canvas.getObjects().find((obj) => {
|
|
1252
|
-
var _a2;
|
|
1253
|
-
return ((_a2 = obj.data) == null ? void 0 : _a2.id) === "ruler-overlay";
|
|
1254
|
-
});
|
|
1255
|
-
const rulerWasVisible = (_d = rulerLayer == null ? void 0 : rulerLayer.visible) != null ? _d : true;
|
|
1256
|
-
if (rulerLayer) rulerLayer.visible = false;
|
|
1257
|
-
const originalClip = canvas.clipPath;
|
|
1258
|
-
canvas.clipPath = clipPath;
|
|
1259
|
-
const bbox = clipPath.getBoundingRect();
|
|
1260
|
-
const clipPathCorrected = new import_fabric2.Path(pathData, {
|
|
1261
|
-
absolutePositioned: true,
|
|
1262
1369
|
left: 0,
|
|
1263
|
-
top: 0
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
const tempBounds = tempPath.getBoundingRect();
|
|
1267
|
-
clipPathCorrected.set({
|
|
1268
|
-
left: tempBounds.left,
|
|
1269
|
-
top: tempBounds.top,
|
|
1270
|
-
originX: "left",
|
|
1271
|
-
originY: "top"
|
|
1370
|
+
top: 0,
|
|
1371
|
+
absolutePositioned: true
|
|
1372
|
+
// Important for groups
|
|
1272
1373
|
});
|
|
1273
|
-
|
|
1274
|
-
const
|
|
1275
|
-
const
|
|
1374
|
+
clonedLayer.clipPath = clipPath;
|
|
1375
|
+
const bounds = clipPath.getBoundingRect();
|
|
1376
|
+
const dataUrl = clonedLayer.toDataURL({
|
|
1276
1377
|
format: "png",
|
|
1277
1378
|
multiplier: 2,
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1379
|
+
// Better quality
|
|
1380
|
+
left: bounds.left,
|
|
1381
|
+
top: bounds.top,
|
|
1382
|
+
width: bounds.width,
|
|
1383
|
+
height: bounds.height
|
|
1282
1384
|
});
|
|
1283
|
-
|
|
1284
|
-
if (layer) layer.visible = wasVisible;
|
|
1285
|
-
if (rulerLayer) rulerLayer.visible = rulerWasVisible;
|
|
1286
|
-
holeMarkers.forEach((o) => o.visible = true);
|
|
1287
|
-
canvas.requestRenderAll();
|
|
1288
|
-
return dataURL;
|
|
1385
|
+
return dataUrl;
|
|
1289
1386
|
}
|
|
1290
1387
|
};
|
|
1291
1388
|
|
|
@@ -1556,13 +1653,21 @@ var HoleTool = class {
|
|
|
1556
1653
|
command: "addHole",
|
|
1557
1654
|
title: "Add Hole",
|
|
1558
1655
|
handler: (x, y) => {
|
|
1559
|
-
var _a, _b, _c;
|
|
1656
|
+
var _a, _b, _c, _d;
|
|
1560
1657
|
if (!this.canvasService) return false;
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
{
|
|
1565
|
-
|
|
1658
|
+
let normalizedX = 0.5;
|
|
1659
|
+
let normalizedY = 0.5;
|
|
1660
|
+
if (this.currentGeometry) {
|
|
1661
|
+
const { x: gx, y: gy, width: gw, height: gh } = this.currentGeometry;
|
|
1662
|
+
const left = gx - gw / 2;
|
|
1663
|
+
const top = gy - gh / 2;
|
|
1664
|
+
normalizedX = gw > 0 ? (x - left) / gw : 0.5;
|
|
1665
|
+
normalizedY = gh > 0 ? (y - top) / gh : 0.5;
|
|
1666
|
+
} else {
|
|
1667
|
+
const { width, height } = this.canvasService.canvas;
|
|
1668
|
+
normalizedX = Coordinate.toNormalized(x, width || 800);
|
|
1669
|
+
normalizedY = Coordinate.toNormalized(y, height || 600);
|
|
1670
|
+
}
|
|
1566
1671
|
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
1567
1672
|
"ConfigurationService"
|
|
1568
1673
|
);
|
|
@@ -1571,9 +1676,11 @@ var HoleTool = class {
|
|
|
1571
1676
|
const lastHole = currentHoles[currentHoles.length - 1];
|
|
1572
1677
|
const innerRadius = (_b = lastHole == null ? void 0 : lastHole.innerRadius) != null ? _b : 15;
|
|
1573
1678
|
const outerRadius = (_c = lastHole == null ? void 0 : lastHole.outerRadius) != null ? _c : 25;
|
|
1679
|
+
const shape = (_d = lastHole == null ? void 0 : lastHole.shape) != null ? _d : "circle";
|
|
1574
1680
|
const newHole = {
|
|
1575
|
-
x:
|
|
1576
|
-
y:
|
|
1681
|
+
x: normalizedX,
|
|
1682
|
+
y: normalizedY,
|
|
1683
|
+
shape,
|
|
1577
1684
|
innerRadius,
|
|
1578
1685
|
outerRadius
|
|
1579
1686
|
};
|
|
@@ -1605,6 +1712,7 @@ var HoleTool = class {
|
|
|
1605
1712
|
if (!this.handleDielineChange) {
|
|
1606
1713
|
this.handleDielineChange = (geometry) => {
|
|
1607
1714
|
this.currentGeometry = geometry;
|
|
1715
|
+
this.redraw();
|
|
1608
1716
|
const changed = this.enforceConstraints();
|
|
1609
1717
|
if (changed) {
|
|
1610
1718
|
this.syncHolesToDieline();
|
|
@@ -1668,7 +1776,10 @@ var HoleTool = class {
|
|
|
1668
1776
|
var _a;
|
|
1669
1777
|
const target = e.target;
|
|
1670
1778
|
if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "hole-marker") return;
|
|
1671
|
-
this.
|
|
1779
|
+
const changed = this.enforceConstraints();
|
|
1780
|
+
if (!changed) {
|
|
1781
|
+
this.syncHolesFromCanvas();
|
|
1782
|
+
}
|
|
1672
1783
|
};
|
|
1673
1784
|
canvas.on("object:modified", this.handleModified);
|
|
1674
1785
|
}
|
|
@@ -1715,10 +1826,16 @@ var HoleTool = class {
|
|
|
1715
1826
|
}
|
|
1716
1827
|
syncHolesFromCanvas() {
|
|
1717
1828
|
if (!this.canvasService) return;
|
|
1718
|
-
const objects = this.canvasService.canvas.getObjects().filter(
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1829
|
+
const objects = this.canvasService.canvas.getObjects().filter(
|
|
1830
|
+
(obj) => {
|
|
1831
|
+
var _a;
|
|
1832
|
+
return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker" || obj.name === "hole-marker";
|
|
1833
|
+
}
|
|
1834
|
+
);
|
|
1835
|
+
if (objects.length === 0 && this.holes.length > 0) {
|
|
1836
|
+
console.warn("HoleTool: No markers found on canvas to sync from");
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1722
1839
|
objects.sort(
|
|
1723
1840
|
(a, b) => {
|
|
1724
1841
|
var _a, _b, _c, _d;
|
|
@@ -1726,18 +1843,28 @@ var HoleTool = class {
|
|
|
1726
1843
|
}
|
|
1727
1844
|
);
|
|
1728
1845
|
const newHoles = objects.map((obj, i) => {
|
|
1729
|
-
var _a, _b;
|
|
1846
|
+
var _a, _b, _c, _d;
|
|
1730
1847
|
const original = this.holes[i];
|
|
1731
1848
|
const newAbsX = obj.left;
|
|
1732
1849
|
const newAbsY = obj.top;
|
|
1850
|
+
if (isNaN(newAbsX) || isNaN(newAbsY)) {
|
|
1851
|
+
console.error("HoleTool: Invalid marker coordinates", {
|
|
1852
|
+
newAbsX,
|
|
1853
|
+
newAbsY
|
|
1854
|
+
});
|
|
1855
|
+
return original;
|
|
1856
|
+
}
|
|
1857
|
+
const scale = ((_a = this.currentGeometry) == null ? void 0 : _a.scale) || 1;
|
|
1858
|
+
const unit = ((_b = this.currentGeometry) == null ? void 0 : _b.unit) || "mm";
|
|
1859
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1733
1860
|
if (original && original.anchor && this.currentGeometry) {
|
|
1734
|
-
const { x, y, width
|
|
1861
|
+
const { x, y, width, height } = this.currentGeometry;
|
|
1735
1862
|
let bx = x;
|
|
1736
1863
|
let by = y;
|
|
1737
|
-
const left = x -
|
|
1738
|
-
const right = x +
|
|
1739
|
-
const top = y -
|
|
1740
|
-
const bottom = y +
|
|
1864
|
+
const left = x - width / 2;
|
|
1865
|
+
const right = x + width / 2;
|
|
1866
|
+
const top = y - height / 2;
|
|
1867
|
+
const bottom = y + height / 2;
|
|
1741
1868
|
switch (original.anchor) {
|
|
1742
1869
|
case "top-left":
|
|
1743
1870
|
bx = left;
|
|
@@ -1778,25 +1905,42 @@ var HoleTool = class {
|
|
|
1778
1905
|
}
|
|
1779
1906
|
return {
|
|
1780
1907
|
...original,
|
|
1781
|
-
|
|
1782
|
-
|
|
1908
|
+
// Denormalize offset back to physical units (mm)
|
|
1909
|
+
offsetX: (newAbsX - bx) / scale / unitScale,
|
|
1910
|
+
offsetY: (newAbsY - by) / scale / unitScale,
|
|
1783
1911
|
// Clear direct coordinates if we use anchor
|
|
1784
1912
|
x: void 0,
|
|
1785
|
-
y: void 0
|
|
1913
|
+
y: void 0,
|
|
1914
|
+
// Ensure other properties are preserved
|
|
1915
|
+
innerRadius: original.innerRadius,
|
|
1916
|
+
outerRadius: original.outerRadius,
|
|
1917
|
+
shape: original.shape || "circle"
|
|
1786
1918
|
};
|
|
1787
1919
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
{
|
|
1792
|
-
|
|
1920
|
+
let normalizedX = 0.5;
|
|
1921
|
+
let normalizedY = 0.5;
|
|
1922
|
+
if (this.currentGeometry) {
|
|
1923
|
+
const { x, y, width, height } = this.currentGeometry;
|
|
1924
|
+
const left = x - width / 2;
|
|
1925
|
+
const top = y - height / 2;
|
|
1926
|
+
normalizedX = width > 0 ? (newAbsX - left) / width : 0.5;
|
|
1927
|
+
normalizedY = height > 0 ? (newAbsY - top) / height : 0.5;
|
|
1928
|
+
} else {
|
|
1929
|
+
const { width, height } = this.canvasService.canvas;
|
|
1930
|
+
normalizedX = Coordinate.toNormalized(newAbsX, width || 800);
|
|
1931
|
+
normalizedY = Coordinate.toNormalized(newAbsY, height || 600);
|
|
1932
|
+
}
|
|
1793
1933
|
return {
|
|
1794
1934
|
...original,
|
|
1795
|
-
x:
|
|
1796
|
-
y:
|
|
1797
|
-
//
|
|
1798
|
-
|
|
1799
|
-
|
|
1935
|
+
x: normalizedX,
|
|
1936
|
+
y: normalizedY,
|
|
1937
|
+
// Clear offsets if we are using direct normalized coordinates
|
|
1938
|
+
offsetX: void 0,
|
|
1939
|
+
offsetY: void 0,
|
|
1940
|
+
// Ensure other properties are preserved
|
|
1941
|
+
innerRadius: (_c = original == null ? void 0 : original.innerRadius) != null ? _c : 15,
|
|
1942
|
+
outerRadius: (_d = original == null ? void 0 : original.outerRadius) != null ? _d : 25,
|
|
1943
|
+
shape: (original == null ? void 0 : original.shape) || "circle"
|
|
1800
1944
|
};
|
|
1801
1945
|
});
|
|
1802
1946
|
this.holes = newHoles;
|
|
@@ -1834,24 +1978,54 @@ var HoleTool = class {
|
|
|
1834
1978
|
x: (width || 800) / 2,
|
|
1835
1979
|
y: (height || 600) / 2,
|
|
1836
1980
|
width: width || 800,
|
|
1837
|
-
height: height || 600
|
|
1981
|
+
height: height || 600,
|
|
1982
|
+
scale: 1
|
|
1983
|
+
// Default scale if no geometry loaded
|
|
1838
1984
|
};
|
|
1839
1985
|
holes.forEach((hole, index) => {
|
|
1986
|
+
const scale = geometry.scale || 1;
|
|
1987
|
+
const unit = geometry.unit || "mm";
|
|
1988
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
1989
|
+
const visualInnerRadius = hole.innerRadius * unitScale * scale;
|
|
1990
|
+
const visualOuterRadius = hole.outerRadius * unitScale * scale;
|
|
1840
1991
|
const pos = resolveHolePosition(
|
|
1841
|
-
|
|
1992
|
+
{
|
|
1993
|
+
...hole,
|
|
1994
|
+
offsetX: (hole.offsetX || 0) * unitScale * scale,
|
|
1995
|
+
offsetY: (hole.offsetY || 0) * unitScale * scale
|
|
1996
|
+
},
|
|
1842
1997
|
geometry,
|
|
1843
|
-
{ width: width
|
|
1998
|
+
{ width: geometry.width, height: geometry.height }
|
|
1999
|
+
// Use geometry dims instead of canvas
|
|
1844
2000
|
);
|
|
1845
|
-
const
|
|
1846
|
-
|
|
2001
|
+
const isSquare = hole.shape === "square";
|
|
2002
|
+
const innerMarker = isSquare ? new import_fabric4.Rect({
|
|
2003
|
+
width: visualInnerRadius * 2,
|
|
2004
|
+
height: visualInnerRadius * 2,
|
|
2005
|
+
fill: "transparent",
|
|
2006
|
+
stroke: "red",
|
|
2007
|
+
strokeWidth: 2,
|
|
2008
|
+
originX: "center",
|
|
2009
|
+
originY: "center"
|
|
2010
|
+
}) : new import_fabric4.Circle({
|
|
2011
|
+
radius: visualInnerRadius,
|
|
1847
2012
|
fill: "transparent",
|
|
1848
2013
|
stroke: "red",
|
|
1849
2014
|
strokeWidth: 2,
|
|
1850
2015
|
originX: "center",
|
|
1851
2016
|
originY: "center"
|
|
1852
2017
|
});
|
|
1853
|
-
const
|
|
1854
|
-
|
|
2018
|
+
const outerMarker = isSquare ? new import_fabric4.Rect({
|
|
2019
|
+
width: visualOuterRadius * 2,
|
|
2020
|
+
height: visualOuterRadius * 2,
|
|
2021
|
+
fill: "transparent",
|
|
2022
|
+
stroke: "#666",
|
|
2023
|
+
strokeWidth: 1,
|
|
2024
|
+
strokeDashArray: [5, 5],
|
|
2025
|
+
originX: "center",
|
|
2026
|
+
originY: "center"
|
|
2027
|
+
}) : new import_fabric4.Circle({
|
|
2028
|
+
radius: visualOuterRadius,
|
|
1855
2029
|
fill: "transparent",
|
|
1856
2030
|
stroke: "#666",
|
|
1857
2031
|
strokeWidth: 1,
|
|
@@ -1859,7 +2033,7 @@ var HoleTool = class {
|
|
|
1859
2033
|
originX: "center",
|
|
1860
2034
|
originY: "center"
|
|
1861
2035
|
});
|
|
1862
|
-
const holeGroup = new import_fabric4.Group([
|
|
2036
|
+
const holeGroup = new import_fabric4.Group([outerMarker, innerMarker], {
|
|
1863
2037
|
left: pos.x,
|
|
1864
2038
|
top: pos.y,
|
|
1865
2039
|
originX: "center",
|
|
@@ -1931,11 +2105,16 @@ var HoleTool = class {
|
|
|
1931
2105
|
var _a, _b;
|
|
1932
2106
|
const currentPos = new import_fabric4.Point(obj.left, obj.top);
|
|
1933
2107
|
const holeData = this.holes[i];
|
|
2108
|
+
const scale = geometry.scale || 1;
|
|
2109
|
+
const unit = geometry.unit || "mm";
|
|
2110
|
+
const unitScale = Coordinate.convertUnit(1, "mm", unit);
|
|
2111
|
+
const innerR = ((_a = holeData == null ? void 0 : holeData.innerRadius) != null ? _a : 15) * unitScale * scale;
|
|
2112
|
+
const outerR = ((_b = holeData == null ? void 0 : holeData.outerRadius) != null ? _b : 25) * unitScale * scale;
|
|
1934
2113
|
const newPos = this.calculateConstrainedPosition(
|
|
1935
2114
|
currentPos,
|
|
1936
2115
|
constraintGeometry,
|
|
1937
|
-
|
|
1938
|
-
|
|
2116
|
+
innerR,
|
|
2117
|
+
outerR
|
|
1939
2118
|
);
|
|
1940
2119
|
if (currentPos.distanceFrom(newPos) > 0.1) {
|
|
1941
2120
|
obj.set({
|
|
@@ -1989,17 +2168,14 @@ var HoleTool = class {
|
|
|
1989
2168
|
var import_core5 = require("@pooder/core");
|
|
1990
2169
|
var import_fabric5 = require("fabric");
|
|
1991
2170
|
var ImageTool = class {
|
|
1992
|
-
constructor(
|
|
2171
|
+
constructor() {
|
|
1993
2172
|
this.id = "pooder.kit.image";
|
|
1994
2173
|
this.metadata = {
|
|
1995
2174
|
name: "ImageTool"
|
|
1996
2175
|
};
|
|
1997
|
-
this.
|
|
1998
|
-
this.
|
|
1999
|
-
this.
|
|
2000
|
-
if (options) {
|
|
2001
|
-
Object.assign(this, options);
|
|
2002
|
-
}
|
|
2176
|
+
this.items = [];
|
|
2177
|
+
this.objectMap = /* @__PURE__ */ new Map();
|
|
2178
|
+
this.isUpdatingConfig = false;
|
|
2003
2179
|
}
|
|
2004
2180
|
activate(context) {
|
|
2005
2181
|
this.context = context;
|
|
@@ -2010,38 +2186,33 @@ var ImageTool = class {
|
|
|
2010
2186
|
}
|
|
2011
2187
|
const configService = context.services.get("ConfigurationService");
|
|
2012
2188
|
if (configService) {
|
|
2013
|
-
this.
|
|
2014
|
-
this.opacity = configService.get("image.opacity", this.opacity);
|
|
2015
|
-
this.width = configService.get("image.width", this.width);
|
|
2016
|
-
this.height = configService.get("image.height", this.height);
|
|
2017
|
-
this.angle = configService.get("image.angle", this.angle);
|
|
2018
|
-
this.left = configService.get("image.left", this.left);
|
|
2019
|
-
this.top = configService.get("image.top", this.top);
|
|
2189
|
+
this.items = configService.get("image.items", []) || [];
|
|
2020
2190
|
configService.onAnyChange((e) => {
|
|
2021
|
-
if (
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2191
|
+
if (this.isUpdatingConfig) return;
|
|
2192
|
+
let shouldUpdate = false;
|
|
2193
|
+
if (e.key === "image.items") {
|
|
2194
|
+
this.items = e.value || [];
|
|
2195
|
+
shouldUpdate = true;
|
|
2196
|
+
} else if (e.key.startsWith("dieline.") && e.key !== "dieline.holes") {
|
|
2197
|
+
shouldUpdate = true;
|
|
2198
|
+
}
|
|
2199
|
+
if (shouldUpdate) {
|
|
2200
|
+
this.updateImages();
|
|
2030
2201
|
}
|
|
2031
2202
|
});
|
|
2032
2203
|
}
|
|
2033
2204
|
this.ensureLayer();
|
|
2034
|
-
this.
|
|
2205
|
+
this.updateImages();
|
|
2035
2206
|
}
|
|
2036
2207
|
deactivate(context) {
|
|
2037
2208
|
if (this.canvasService) {
|
|
2038
2209
|
const layer = this.canvasService.getLayer("user");
|
|
2039
2210
|
if (layer) {
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2211
|
+
this.objectMap.forEach((obj) => {
|
|
2212
|
+
layer.remove(obj);
|
|
2213
|
+
});
|
|
2214
|
+
this.objectMap.clear();
|
|
2215
|
+
this.canvasService.requestRenderAll();
|
|
2045
2216
|
}
|
|
2046
2217
|
this.canvasService = void 0;
|
|
2047
2218
|
this.context = void 0;
|
|
@@ -2051,82 +2222,103 @@ var ImageTool = class {
|
|
|
2051
2222
|
return {
|
|
2052
2223
|
[import_core5.ContributionPointIds.CONFIGURATIONS]: [
|
|
2053
2224
|
{
|
|
2054
|
-
id: "image.
|
|
2055
|
-
type: "
|
|
2056
|
-
label: "
|
|
2057
|
-
default:
|
|
2058
|
-
}
|
|
2225
|
+
id: "image.items",
|
|
2226
|
+
type: "array",
|
|
2227
|
+
label: "Images",
|
|
2228
|
+
default: []
|
|
2229
|
+
}
|
|
2230
|
+
],
|
|
2231
|
+
[import_core5.ContributionPointIds.COMMANDS]: [
|
|
2059
2232
|
{
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2233
|
+
command: "addImage",
|
|
2234
|
+
title: "Add Image",
|
|
2235
|
+
handler: (url, options) => {
|
|
2236
|
+
const newItem = {
|
|
2237
|
+
id: this.generateId(),
|
|
2238
|
+
url,
|
|
2239
|
+
opacity: 1,
|
|
2240
|
+
...options
|
|
2241
|
+
};
|
|
2242
|
+
this.updateConfig([...this.items, newItem]);
|
|
2243
|
+
return newItem.id;
|
|
2244
|
+
}
|
|
2067
2245
|
},
|
|
2068
2246
|
{
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2247
|
+
command: "removeImage",
|
|
2248
|
+
title: "Remove Image",
|
|
2249
|
+
handler: (id) => {
|
|
2250
|
+
const newItems = this.items.filter((item) => item.id !== id);
|
|
2251
|
+
if (newItems.length !== this.items.length) {
|
|
2252
|
+
this.updateConfig(newItems);
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2075
2255
|
},
|
|
2076
2256
|
{
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2257
|
+
command: "updateImage",
|
|
2258
|
+
title: "Update Image",
|
|
2259
|
+
handler: (id, updates) => {
|
|
2260
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
2261
|
+
if (index !== -1) {
|
|
2262
|
+
const newItems = [...this.items];
|
|
2263
|
+
newItems[index] = { ...newItems[index], ...updates };
|
|
2264
|
+
this.updateConfig(newItems);
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2083
2267
|
},
|
|
2084
2268
|
{
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
default: this.angle
|
|
2269
|
+
command: "clearImages",
|
|
2270
|
+
title: "Clear Images",
|
|
2271
|
+
handler: () => {
|
|
2272
|
+
this.updateConfig([]);
|
|
2273
|
+
}
|
|
2091
2274
|
},
|
|
2092
2275
|
{
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2276
|
+
command: "bringToFront",
|
|
2277
|
+
title: "Bring Image to Front",
|
|
2278
|
+
handler: (id) => {
|
|
2279
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
2280
|
+
if (index !== -1 && index < this.items.length - 1) {
|
|
2281
|
+
const newItems = [...this.items];
|
|
2282
|
+
const [item] = newItems.splice(index, 1);
|
|
2283
|
+
newItems.push(item);
|
|
2284
|
+
this.updateConfig(newItems);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2099
2287
|
},
|
|
2100
2288
|
{
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
command: "setUserImage",
|
|
2112
|
-
title: "Set User Image",
|
|
2113
|
-
handler: (url, opacity, width, height, angle, left, top) => {
|
|
2114
|
-
if (this.url === url && this.opacity === opacity && this.width === width && this.height === height && this.angle === angle && this.left === left && this.top === top)
|
|
2115
|
-
return true;
|
|
2116
|
-
this.url = url;
|
|
2117
|
-
this.opacity = opacity;
|
|
2118
|
-
this.width = width;
|
|
2119
|
-
this.height = height;
|
|
2120
|
-
this.angle = angle;
|
|
2121
|
-
this.left = left;
|
|
2122
|
-
this.top = top;
|
|
2123
|
-
this.updateImage();
|
|
2124
|
-
return true;
|
|
2289
|
+
command: "sendToBack",
|
|
2290
|
+
title: "Send Image to Back",
|
|
2291
|
+
handler: (id) => {
|
|
2292
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
2293
|
+
if (index > 0) {
|
|
2294
|
+
const newItems = [...this.items];
|
|
2295
|
+
const [item] = newItems.splice(index, 1);
|
|
2296
|
+
newItems.unshift(item);
|
|
2297
|
+
this.updateConfig(newItems);
|
|
2298
|
+
}
|
|
2125
2299
|
}
|
|
2126
2300
|
}
|
|
2127
2301
|
]
|
|
2128
2302
|
};
|
|
2129
2303
|
}
|
|
2304
|
+
generateId() {
|
|
2305
|
+
return Math.random().toString(36).substring(2, 9);
|
|
2306
|
+
}
|
|
2307
|
+
updateConfig(newItems, skipCanvasUpdate = false) {
|
|
2308
|
+
if (!this.context) return;
|
|
2309
|
+
this.isUpdatingConfig = true;
|
|
2310
|
+
this.items = newItems;
|
|
2311
|
+
const configService = this.context.services.get("ConfigurationService");
|
|
2312
|
+
if (configService) {
|
|
2313
|
+
configService.update("image.items", newItems);
|
|
2314
|
+
}
|
|
2315
|
+
if (!skipCanvasUpdate) {
|
|
2316
|
+
this.updateImages();
|
|
2317
|
+
}
|
|
2318
|
+
setTimeout(() => {
|
|
2319
|
+
this.isUpdatingConfig = false;
|
|
2320
|
+
}, 50);
|
|
2321
|
+
}
|
|
2130
2322
|
ensureLayer() {
|
|
2131
2323
|
if (!this.canvasService) return;
|
|
2132
2324
|
let userLayer = this.canvasService.getLayer("user");
|
|
@@ -2158,224 +2350,194 @@ var ImageTool = class {
|
|
|
2158
2350
|
this.canvasService.requestRenderAll();
|
|
2159
2351
|
}
|
|
2160
2352
|
}
|
|
2161
|
-
|
|
2353
|
+
getLayoutInfo() {
|
|
2162
2354
|
var _a, _b;
|
|
2355
|
+
const canvasW = ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800;
|
|
2356
|
+
const canvasH = ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600;
|
|
2357
|
+
let layoutScale = 1;
|
|
2358
|
+
let layoutOffsetX = 0;
|
|
2359
|
+
let layoutOffsetY = 0;
|
|
2360
|
+
let visualWidth = canvasW;
|
|
2361
|
+
let visualHeight = canvasH;
|
|
2362
|
+
let dielinePhysicalWidth = 500;
|
|
2363
|
+
let dielinePhysicalHeight = 500;
|
|
2364
|
+
let bleedOffset = 0;
|
|
2365
|
+
if (this.context) {
|
|
2366
|
+
const configService = this.context.services.get("ConfigurationService");
|
|
2367
|
+
if (configService) {
|
|
2368
|
+
dielinePhysicalWidth = configService.get("dieline.width") || 500;
|
|
2369
|
+
dielinePhysicalHeight = configService.get("dieline.height") || 500;
|
|
2370
|
+
bleedOffset = configService.get("dieline.offset") || 0;
|
|
2371
|
+
const paddingValue = configService.get("dieline.padding") || 40;
|
|
2372
|
+
let padding = 0;
|
|
2373
|
+
if (typeof paddingValue === "number") {
|
|
2374
|
+
padding = paddingValue;
|
|
2375
|
+
} else if (typeof paddingValue === "string") {
|
|
2376
|
+
if (paddingValue.endsWith("%")) {
|
|
2377
|
+
const percent = parseFloat(paddingValue) / 100;
|
|
2378
|
+
padding = Math.min(canvasW, canvasH) * percent;
|
|
2379
|
+
} else {
|
|
2380
|
+
padding = parseFloat(paddingValue) || 0;
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
const layout = Coordinate.calculateLayout(
|
|
2384
|
+
{ width: canvasW, height: canvasH },
|
|
2385
|
+
{ width: dielinePhysicalWidth, height: dielinePhysicalHeight },
|
|
2386
|
+
padding
|
|
2387
|
+
);
|
|
2388
|
+
layoutScale = layout.scale;
|
|
2389
|
+
layoutOffsetX = layout.offsetX;
|
|
2390
|
+
layoutOffsetY = layout.offsetY;
|
|
2391
|
+
visualWidth = layout.width;
|
|
2392
|
+
visualHeight = layout.height;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
return {
|
|
2396
|
+
layoutScale,
|
|
2397
|
+
layoutOffsetX,
|
|
2398
|
+
layoutOffsetY,
|
|
2399
|
+
visualWidth,
|
|
2400
|
+
visualHeight,
|
|
2401
|
+
dielinePhysicalWidth,
|
|
2402
|
+
dielinePhysicalHeight,
|
|
2403
|
+
bleedOffset
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
updateImages() {
|
|
2163
2407
|
if (!this.canvasService) return;
|
|
2164
|
-
let { url, opacity, width, height, angle, left, top } = this;
|
|
2165
2408
|
const layer = this.canvasService.getLayer("user");
|
|
2166
2409
|
if (!layer) {
|
|
2167
2410
|
console.warn("[ImageTool] User layer not found");
|
|
2168
2411
|
return;
|
|
2169
2412
|
}
|
|
2170
|
-
const
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
this.loadImage(layer);
|
|
2176
|
-
} else {
|
|
2177
|
-
const updates = {};
|
|
2178
|
-
const canvasW = this.canvasService.canvas.width || 800;
|
|
2179
|
-
const canvasH = this.canvasService.canvas.height || 600;
|
|
2180
|
-
const centerX = canvasW / 2;
|
|
2181
|
-
const centerY = canvasH / 2;
|
|
2182
|
-
if (userImage.opacity !== opacity) updates.opacity = opacity;
|
|
2183
|
-
if (angle !== void 0 && userImage.angle !== angle)
|
|
2184
|
-
updates.angle = angle;
|
|
2185
|
-
if (userImage.originX !== "center") {
|
|
2186
|
-
userImage.set({
|
|
2187
|
-
originX: "center",
|
|
2188
|
-
originY: "center",
|
|
2189
|
-
left: userImage.left + userImage.width * userImage.scaleX / 2,
|
|
2190
|
-
top: userImage.top + userImage.height * userImage.scaleY / 2
|
|
2191
|
-
});
|
|
2192
|
-
}
|
|
2193
|
-
if (left !== void 0) {
|
|
2194
|
-
const globalLeft = Coordinate.toAbsolute(left, canvasW);
|
|
2195
|
-
const localLeft = globalLeft - centerX;
|
|
2196
|
-
if (Math.abs(userImage.left - localLeft) > 1)
|
|
2197
|
-
updates.left = localLeft;
|
|
2198
|
-
}
|
|
2199
|
-
if (top !== void 0) {
|
|
2200
|
-
const globalTop = Coordinate.toAbsolute(top, canvasH);
|
|
2201
|
-
const localTop = globalTop - centerY;
|
|
2202
|
-
if (Math.abs(userImage.top - localTop) > 1) updates.top = localTop;
|
|
2203
|
-
}
|
|
2204
|
-
if (width !== void 0 && userImage.width)
|
|
2205
|
-
updates.scaleX = width / userImage.width;
|
|
2206
|
-
if (height !== void 0 && userImage.height)
|
|
2207
|
-
updates.scaleY = height / userImage.height;
|
|
2208
|
-
if (Object.keys(updates).length > 0) {
|
|
2209
|
-
userImage.set(updates);
|
|
2210
|
-
layer.dirty = true;
|
|
2211
|
-
this.canvasService.requestRenderAll();
|
|
2212
|
-
}
|
|
2413
|
+
const currentIds = new Set(this.items.map((i) => i.id));
|
|
2414
|
+
for (const [id, obj] of this.objectMap) {
|
|
2415
|
+
if (!currentIds.has(id)) {
|
|
2416
|
+
layer.remove(obj);
|
|
2417
|
+
this.objectMap.delete(id);
|
|
2213
2418
|
}
|
|
2214
|
-
} else {
|
|
2215
|
-
this.loadImage(layer);
|
|
2216
2419
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
this._loadingUrl = url;
|
|
2223
|
-
import_fabric5.FabricImage.fromURL(url, { crossOrigin: "anonymous" }).then((image) => {
|
|
2224
|
-
var _a, _b, _c, _d, _e, _f;
|
|
2225
|
-
if (this._loadingUrl !== url) return;
|
|
2226
|
-
this._loadingUrl = null;
|
|
2227
|
-
let { opacity, width, height, angle, left, top } = this;
|
|
2228
|
-
if (this.context) {
|
|
2229
|
-
const configService = this.context.services.get(
|
|
2230
|
-
"ConfigurationService"
|
|
2231
|
-
);
|
|
2232
|
-
const dielineWidth = configService.get("dieline.width");
|
|
2233
|
-
const dielineHeight = configService.get("dieline.height");
|
|
2234
|
-
console.log(
|
|
2235
|
-
"[ImageTool] Dieline config debug:",
|
|
2236
|
-
{
|
|
2237
|
-
widthVal: dielineWidth,
|
|
2238
|
-
heightVal: dielineHeight,
|
|
2239
|
-
// Debug: dump all keys to see what is available
|
|
2240
|
-
allKeys: Array.from(
|
|
2241
|
-
((_a = configService.configValues) == null ? void 0 : _a.keys()) || []
|
|
2242
|
-
)
|
|
2243
|
-
},
|
|
2244
|
-
configService
|
|
2245
|
-
);
|
|
2246
|
-
if (width === void 0 && height === void 0) {
|
|
2247
|
-
const scale = Math.min(
|
|
2248
|
-
dielineWidth / (image.width || 1),
|
|
2249
|
-
dielineHeight / (image.height || 1)
|
|
2250
|
-
);
|
|
2251
|
-
width = (image.width || 1) * scale;
|
|
2252
|
-
height = (image.height || 1) * scale;
|
|
2253
|
-
this.width = width;
|
|
2254
|
-
this.height = height;
|
|
2255
|
-
}
|
|
2256
|
-
if (left === void 0 && top === void 0) {
|
|
2257
|
-
const dielinePos = configService == null ? void 0 : configService.get("dieline.position");
|
|
2258
|
-
if (dielinePos) {
|
|
2259
|
-
this.left = dielinePos.x;
|
|
2260
|
-
this.top = dielinePos.y;
|
|
2261
|
-
} else {
|
|
2262
|
-
this.left = 0.5;
|
|
2263
|
-
this.top = 0.5;
|
|
2264
|
-
}
|
|
2265
|
-
left = this.left;
|
|
2266
|
-
top = this.top;
|
|
2267
|
-
}
|
|
2268
|
-
}
|
|
2269
|
-
const existingImage = this.canvasService.getObject(
|
|
2270
|
-
"user-image",
|
|
2271
|
-
"user"
|
|
2272
|
-
);
|
|
2273
|
-
if (existingImage) {
|
|
2274
|
-
const defaultLeft = existingImage.left;
|
|
2275
|
-
const defaultTop = existingImage.top;
|
|
2276
|
-
const defaultAngle = existingImage.angle;
|
|
2277
|
-
const defaultScaleX = existingImage.scaleX;
|
|
2278
|
-
const defaultScaleY = existingImage.scaleY;
|
|
2279
|
-
const canvasW = ((_b = this.canvasService) == null ? void 0 : _b.canvas.width) || 800;
|
|
2280
|
-
const canvasH = ((_c = this.canvasService) == null ? void 0 : _c.canvas.height) || 600;
|
|
2281
|
-
const centerX = canvasW / 2;
|
|
2282
|
-
const centerY = canvasH / 2;
|
|
2283
|
-
let targetLeft = left !== void 0 ? left : defaultLeft;
|
|
2284
|
-
let targetTop = top !== void 0 ? top : defaultTop;
|
|
2285
|
-
const configService = (_d = this.context) == null ? void 0 : _d.services.get(
|
|
2286
|
-
"ConfigurationService"
|
|
2287
|
-
);
|
|
2288
|
-
console.log("[ImageTool] Loading EXISTING image...", {
|
|
2289
|
-
canvasW,
|
|
2290
|
-
canvasH,
|
|
2291
|
-
centerX,
|
|
2292
|
-
centerY,
|
|
2293
|
-
incomingLeft: left,
|
|
2294
|
-
incomingTop: top,
|
|
2295
|
-
dielinePos: configService == null ? void 0 : configService.get("dieline.position"),
|
|
2296
|
-
existingImage: !!existingImage
|
|
2297
|
-
});
|
|
2298
|
-
if (left !== void 0) {
|
|
2299
|
-
const globalLeft = Coordinate.toAbsolute(left, canvasW);
|
|
2300
|
-
targetLeft = globalLeft;
|
|
2301
|
-
console.log("[ImageTool] Calculated targetLeft", {
|
|
2302
|
-
globalLeft,
|
|
2303
|
-
targetLeft
|
|
2304
|
-
});
|
|
2305
|
-
}
|
|
2306
|
-
if (top !== void 0) {
|
|
2307
|
-
const globalTop = Coordinate.toAbsolute(top, canvasH);
|
|
2308
|
-
targetTop = globalTop;
|
|
2309
|
-
console.log("[ImageTool] Calculated targetTop", {
|
|
2310
|
-
globalTop,
|
|
2311
|
-
targetTop
|
|
2312
|
-
});
|
|
2313
|
-
}
|
|
2314
|
-
image.set({
|
|
2315
|
-
originX: "center",
|
|
2316
|
-
// Use center origin for easier positioning
|
|
2317
|
-
originY: "center",
|
|
2318
|
-
left: targetLeft,
|
|
2319
|
-
top: targetTop,
|
|
2320
|
-
angle: angle !== void 0 ? angle : defaultAngle,
|
|
2321
|
-
scaleX: width !== void 0 && image.width ? width / image.width : defaultScaleX,
|
|
2322
|
-
scaleY: height !== void 0 && image.height ? height / image.height : defaultScaleY
|
|
2323
|
-
});
|
|
2324
|
-
layer.remove(existingImage);
|
|
2420
|
+
const layout = this.getLayoutInfo();
|
|
2421
|
+
this.items.forEach((item, index) => {
|
|
2422
|
+
let obj = this.objectMap.get(item.id);
|
|
2423
|
+
if (!obj) {
|
|
2424
|
+
this.loadImage(item, layer, layout);
|
|
2325
2425
|
} else {
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
});
|
|
2330
|
-
if (width !== void 0 && image.width)
|
|
2331
|
-
image.scaleX = width / image.width;
|
|
2332
|
-
if (height !== void 0 && image.height)
|
|
2333
|
-
image.scaleY = height / image.height;
|
|
2334
|
-
if (angle !== void 0) image.angle = angle;
|
|
2335
|
-
const canvasW = ((_e = this.canvasService) == null ? void 0 : _e.canvas.width) || 800;
|
|
2336
|
-
const canvasH = ((_f = this.canvasService) == null ? void 0 : _f.canvas.height) || 600;
|
|
2337
|
-
const centerX = canvasW / 2;
|
|
2338
|
-
const centerY = canvasH / 2;
|
|
2339
|
-
if (left !== void 0) {
|
|
2340
|
-
image.left = Coordinate.toAbsolute(left, canvasW);
|
|
2341
|
-
} else {
|
|
2342
|
-
image.left = centerX;
|
|
2343
|
-
}
|
|
2344
|
-
if (top !== void 0) {
|
|
2345
|
-
image.top = Coordinate.toAbsolute(top, canvasH);
|
|
2346
|
-
} else {
|
|
2347
|
-
image.top = centerY;
|
|
2348
|
-
}
|
|
2426
|
+
this.updateObjectProperties(obj, item, layout);
|
|
2427
|
+
layer.remove(obj);
|
|
2428
|
+
layer.add(obj);
|
|
2349
2429
|
}
|
|
2430
|
+
});
|
|
2431
|
+
layer.dirty = true;
|
|
2432
|
+
this.canvasService.requestRenderAll();
|
|
2433
|
+
}
|
|
2434
|
+
updateObjectProperties(obj, item, layout) {
|
|
2435
|
+
const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight } = layout;
|
|
2436
|
+
const updates = {};
|
|
2437
|
+
if (obj.opacity !== item.opacity) updates.opacity = item.opacity;
|
|
2438
|
+
if (item.angle !== void 0 && obj.angle !== item.angle) updates.angle = item.angle;
|
|
2439
|
+
if (item.left !== void 0) {
|
|
2440
|
+
const globalLeft = layoutOffsetX + item.left * visualWidth;
|
|
2441
|
+
if (Math.abs(obj.left - globalLeft) > 1) updates.left = globalLeft;
|
|
2442
|
+
}
|
|
2443
|
+
if (item.top !== void 0) {
|
|
2444
|
+
const globalTop = layoutOffsetY + item.top * visualHeight;
|
|
2445
|
+
if (Math.abs(obj.top - globalTop) > 1) updates.top = globalTop;
|
|
2446
|
+
}
|
|
2447
|
+
if (item.width !== void 0 && obj.width) {
|
|
2448
|
+
const targetScaleX = item.width * layoutScale / obj.width;
|
|
2449
|
+
if (Math.abs(obj.scaleX - targetScaleX) > 1e-3) updates.scaleX = targetScaleX;
|
|
2450
|
+
}
|
|
2451
|
+
if (item.height !== void 0 && obj.height) {
|
|
2452
|
+
const targetScaleY = item.height * layoutScale / obj.height;
|
|
2453
|
+
if (Math.abs(obj.scaleY - targetScaleY) > 1e-3) updates.scaleY = targetScaleY;
|
|
2454
|
+
}
|
|
2455
|
+
if (obj.originX !== "center") {
|
|
2456
|
+
updates.originX = "center";
|
|
2457
|
+
updates.originY = "center";
|
|
2458
|
+
}
|
|
2459
|
+
if (Object.keys(updates).length > 0) {
|
|
2460
|
+
obj.set(updates);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
loadImage(item, layer, layout) {
|
|
2464
|
+
import_fabric5.Image.fromURL(item.url, { crossOrigin: "anonymous" }).then((image) => {
|
|
2465
|
+
var _a;
|
|
2466
|
+
if (!this.items.find((i) => i.id === item.id)) return;
|
|
2350
2467
|
image.set({
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2468
|
+
originX: "center",
|
|
2469
|
+
originY: "center",
|
|
2470
|
+
data: { id: item.id },
|
|
2471
|
+
uniformScaling: true,
|
|
2472
|
+
lockScalingFlip: true
|
|
2473
|
+
});
|
|
2474
|
+
image.setControlsVisibility({
|
|
2475
|
+
mt: false,
|
|
2476
|
+
mb: false,
|
|
2477
|
+
ml: false,
|
|
2478
|
+
mr: false
|
|
2355
2479
|
});
|
|
2480
|
+
let { width, height, left, top } = item;
|
|
2481
|
+
const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight, bleedOffset } = layout;
|
|
2482
|
+
if (width === void 0 && height === void 0) {
|
|
2483
|
+
const targetWidth = dielinePhysicalWidth + 2 * bleedOffset;
|
|
2484
|
+
const targetHeight = dielinePhysicalHeight + 2 * bleedOffset;
|
|
2485
|
+
const targetMax = Math.max(targetWidth, targetHeight);
|
|
2486
|
+
const imageMax = Math.max(image.width || 1, image.height || 1);
|
|
2487
|
+
const scale = targetMax / imageMax;
|
|
2488
|
+
width = (image.width || 1) * scale;
|
|
2489
|
+
height = (image.height || 1) * scale;
|
|
2490
|
+
item.width = width;
|
|
2491
|
+
item.height = height;
|
|
2492
|
+
}
|
|
2493
|
+
if (left === void 0 && top === void 0) {
|
|
2494
|
+
left = 0.5;
|
|
2495
|
+
top = 0.5;
|
|
2496
|
+
item.left = left;
|
|
2497
|
+
item.top = top;
|
|
2498
|
+
}
|
|
2499
|
+
this.updateObjectProperties(image, item, layout);
|
|
2356
2500
|
layer.add(image);
|
|
2501
|
+
this.objectMap.set(item.id, image);
|
|
2357
2502
|
image.on("modified", (e) => {
|
|
2358
|
-
|
|
2359
|
-
const matrix = image.calcTransformMatrix();
|
|
2360
|
-
const globalPoint = import_fabric5.util.transformPoint(new import_fabric5.Point(0, 0), matrix);
|
|
2361
|
-
const canvasW = ((_a2 = this.canvasService) == null ? void 0 : _a2.canvas.width) || 800;
|
|
2362
|
-
const canvasH = ((_b2 = this.canvasService) == null ? void 0 : _b2.canvas.height) || 600;
|
|
2363
|
-
this.left = Coordinate.toNormalized(globalPoint.x, canvasW);
|
|
2364
|
-
this.top = Coordinate.toNormalized(globalPoint.y, canvasH);
|
|
2365
|
-
this.angle = e.target.angle;
|
|
2366
|
-
if (image.width) this.width = e.target.width * e.target.scaleX;
|
|
2367
|
-
if (image.height) this.height = e.target.height * e.target.scaleY;
|
|
2368
|
-
if (this.context) {
|
|
2369
|
-
this.context.eventBus.emit("update");
|
|
2370
|
-
}
|
|
2503
|
+
this.handleObjectModified(item.id, image);
|
|
2371
2504
|
});
|
|
2372
2505
|
layer.dirty = true;
|
|
2373
|
-
this.canvasService.requestRenderAll();
|
|
2506
|
+
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2507
|
+
if (item.width !== width || item.height !== height || item.left !== left || item.top !== top) {
|
|
2508
|
+
this.updateImageInConfig(item.id, { width, height, left, top });
|
|
2509
|
+
}
|
|
2374
2510
|
}).catch((err) => {
|
|
2375
|
-
|
|
2376
|
-
console.error("Failed to load image", url, err);
|
|
2511
|
+
console.error("Failed to load image", item.url, err);
|
|
2377
2512
|
});
|
|
2378
2513
|
}
|
|
2514
|
+
handleObjectModified(id, image) {
|
|
2515
|
+
const layout = this.getLayoutInfo();
|
|
2516
|
+
const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight } = layout;
|
|
2517
|
+
const matrix = image.calcTransformMatrix();
|
|
2518
|
+
const globalPoint = import_fabric5.util.transformPoint(new import_fabric5.Point(0, 0), matrix);
|
|
2519
|
+
const updates = {};
|
|
2520
|
+
updates.left = (globalPoint.x - layoutOffsetX) / visualWidth;
|
|
2521
|
+
updates.top = (globalPoint.y - layoutOffsetY) / visualHeight;
|
|
2522
|
+
updates.angle = image.angle;
|
|
2523
|
+
if (image.width) {
|
|
2524
|
+
const pixelWidth = image.width * image.scaleX;
|
|
2525
|
+
updates.width = pixelWidth / layoutScale;
|
|
2526
|
+
}
|
|
2527
|
+
if (image.height) {
|
|
2528
|
+
const pixelHeight = image.height * image.scaleY;
|
|
2529
|
+
updates.height = pixelHeight / layoutScale;
|
|
2530
|
+
}
|
|
2531
|
+
this.updateImageInConfig(id, updates);
|
|
2532
|
+
}
|
|
2533
|
+
updateImageInConfig(id, updates) {
|
|
2534
|
+
const index = this.items.findIndex((i) => i.id === id);
|
|
2535
|
+
if (index !== -1) {
|
|
2536
|
+
const newItems = [...this.items];
|
|
2537
|
+
newItems[index] = { ...newItems[index], ...updates };
|
|
2538
|
+
this.updateConfig(newItems, true);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2379
2541
|
};
|
|
2380
2542
|
|
|
2381
2543
|
// src/white-ink.ts
|
|
@@ -2678,12 +2840,18 @@ var RulerTool = class {
|
|
|
2678
2840
|
this.metadata = {
|
|
2679
2841
|
name: "RulerTool"
|
|
2680
2842
|
};
|
|
2681
|
-
this.unit = "px";
|
|
2682
2843
|
this.thickness = 20;
|
|
2844
|
+
this.gap = 15;
|
|
2683
2845
|
this.backgroundColor = "#f0f0f0";
|
|
2684
2846
|
this.textColor = "#333333";
|
|
2685
2847
|
this.lineColor = "#999999";
|
|
2686
2848
|
this.fontSize = 10;
|
|
2849
|
+
// Dieline context for sync
|
|
2850
|
+
this.dielineWidth = 500;
|
|
2851
|
+
this.dielineHeight = 500;
|
|
2852
|
+
this.dielineUnit = "mm";
|
|
2853
|
+
this.dielinePadding = 40;
|
|
2854
|
+
this.dielineOffset = 0;
|
|
2687
2855
|
if (options) {
|
|
2688
2856
|
Object.assign(this, options);
|
|
2689
2857
|
}
|
|
@@ -2696,8 +2864,8 @@ var RulerTool = class {
|
|
|
2696
2864
|
}
|
|
2697
2865
|
const configService = context.services.get("ConfigurationService");
|
|
2698
2866
|
if (configService) {
|
|
2699
|
-
this.unit = configService.get("ruler.unit", this.unit);
|
|
2700
2867
|
this.thickness = configService.get("ruler.thickness", this.thickness);
|
|
2868
|
+
this.gap = configService.get("ruler.gap", this.gap);
|
|
2701
2869
|
this.backgroundColor = configService.get(
|
|
2702
2870
|
"ruler.backgroundColor",
|
|
2703
2871
|
this.backgroundColor
|
|
@@ -2705,13 +2873,38 @@ var RulerTool = class {
|
|
|
2705
2873
|
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
2706
2874
|
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
2707
2875
|
this.fontSize = configService.get("ruler.fontSize", this.fontSize);
|
|
2876
|
+
this.dielineUnit = configService.get("dieline.unit", this.dielineUnit);
|
|
2877
|
+
this.dielineWidth = configService.get("dieline.width", this.dielineWidth);
|
|
2878
|
+
this.dielineHeight = configService.get(
|
|
2879
|
+
"dieline.height",
|
|
2880
|
+
this.dielineHeight
|
|
2881
|
+
);
|
|
2882
|
+
this.dielinePadding = configService.get(
|
|
2883
|
+
"dieline.padding",
|
|
2884
|
+
this.dielinePadding
|
|
2885
|
+
);
|
|
2886
|
+
this.dielineOffset = configService.get(
|
|
2887
|
+
"dieline.offset",
|
|
2888
|
+
this.dielineOffset
|
|
2889
|
+
);
|
|
2708
2890
|
configService.onAnyChange((e) => {
|
|
2891
|
+
let shouldUpdate = false;
|
|
2709
2892
|
if (e.key.startsWith("ruler.")) {
|
|
2710
2893
|
const prop = e.key.split(".")[1];
|
|
2711
2894
|
if (prop && prop in this) {
|
|
2712
2895
|
this[prop] = e.value;
|
|
2713
|
-
|
|
2896
|
+
shouldUpdate = true;
|
|
2714
2897
|
}
|
|
2898
|
+
} else if (e.key.startsWith("dieline.")) {
|
|
2899
|
+
if (e.key === "dieline.unit") this.dielineUnit = e.value;
|
|
2900
|
+
if (e.key === "dieline.width") this.dielineWidth = e.value;
|
|
2901
|
+
if (e.key === "dieline.height") this.dielineHeight = e.value;
|
|
2902
|
+
if (e.key === "dieline.padding") this.dielinePadding = e.value;
|
|
2903
|
+
if (e.key === "dieline.offset") this.dielineOffset = e.value;
|
|
2904
|
+
shouldUpdate = true;
|
|
2905
|
+
}
|
|
2906
|
+
if (shouldUpdate) {
|
|
2907
|
+
this.updateRuler();
|
|
2715
2908
|
}
|
|
2716
2909
|
});
|
|
2717
2910
|
}
|
|
@@ -2725,13 +2918,6 @@ var RulerTool = class {
|
|
|
2725
2918
|
contribute() {
|
|
2726
2919
|
return {
|
|
2727
2920
|
[import_core7.ContributionPointIds.CONFIGURATIONS]: [
|
|
2728
|
-
{
|
|
2729
|
-
id: "ruler.unit",
|
|
2730
|
-
type: "select",
|
|
2731
|
-
label: "Unit",
|
|
2732
|
-
options: ["px", "mm", "cm", "in"],
|
|
2733
|
-
default: "px"
|
|
2734
|
-
},
|
|
2735
2921
|
{
|
|
2736
2922
|
id: "ruler.thickness",
|
|
2737
2923
|
type: "number",
|
|
@@ -2740,6 +2926,14 @@ var RulerTool = class {
|
|
|
2740
2926
|
max: 100,
|
|
2741
2927
|
default: 20
|
|
2742
2928
|
},
|
|
2929
|
+
{
|
|
2930
|
+
id: "ruler.gap",
|
|
2931
|
+
type: "number",
|
|
2932
|
+
label: "Gap",
|
|
2933
|
+
min: 0,
|
|
2934
|
+
max: 100,
|
|
2935
|
+
default: 15
|
|
2936
|
+
},
|
|
2743
2937
|
{
|
|
2744
2938
|
id: "ruler.backgroundColor",
|
|
2745
2939
|
type: "color",
|
|
@@ -2768,16 +2962,6 @@ var RulerTool = class {
|
|
|
2768
2962
|
}
|
|
2769
2963
|
],
|
|
2770
2964
|
[import_core7.ContributionPointIds.COMMANDS]: [
|
|
2771
|
-
{
|
|
2772
|
-
command: "setUnit",
|
|
2773
|
-
title: "Set Ruler Unit",
|
|
2774
|
-
handler: (unit) => {
|
|
2775
|
-
if (this.unit === unit) return true;
|
|
2776
|
-
this.unit = unit;
|
|
2777
|
-
this.updateRuler();
|
|
2778
|
-
return true;
|
|
2779
|
-
}
|
|
2780
|
-
},
|
|
2781
2965
|
{
|
|
2782
2966
|
command: "setTheme",
|
|
2783
2967
|
title: "Set Ruler Theme",
|
|
@@ -2828,6 +3012,68 @@ var RulerTool = class {
|
|
|
2828
3012
|
this.canvasService.canvas.remove(layer);
|
|
2829
3013
|
}
|
|
2830
3014
|
}
|
|
3015
|
+
createArrowLine(x1, y1, x2, y2, color) {
|
|
3016
|
+
const line = new import_fabric7.Line([x1, y1, x2, y2], {
|
|
3017
|
+
stroke: color,
|
|
3018
|
+
strokeWidth: this.thickness / 20,
|
|
3019
|
+
// Scale stroke width relative to thickness (default 1)
|
|
3020
|
+
selectable: false,
|
|
3021
|
+
evented: false
|
|
3022
|
+
});
|
|
3023
|
+
const arrowSize = Math.max(4, this.thickness * 0.3);
|
|
3024
|
+
const angle = Math.atan2(y2 - y1, x2 - x1);
|
|
3025
|
+
const endArrow = new import_fabric7.Polygon(
|
|
3026
|
+
[
|
|
3027
|
+
{ x: 0, y: 0 },
|
|
3028
|
+
{ x: -arrowSize, y: -arrowSize / 2 },
|
|
3029
|
+
{ x: -arrowSize, y: arrowSize / 2 }
|
|
3030
|
+
],
|
|
3031
|
+
{
|
|
3032
|
+
fill: color,
|
|
3033
|
+
left: x2,
|
|
3034
|
+
top: y2,
|
|
3035
|
+
originX: "right",
|
|
3036
|
+
originY: "center",
|
|
3037
|
+
angle: angle * 180 / Math.PI,
|
|
3038
|
+
selectable: false,
|
|
3039
|
+
evented: false
|
|
3040
|
+
}
|
|
3041
|
+
);
|
|
3042
|
+
const startArrow = new import_fabric7.Polygon(
|
|
3043
|
+
[
|
|
3044
|
+
{ x: 0, y: 0 },
|
|
3045
|
+
{ x: arrowSize, y: -arrowSize / 2 },
|
|
3046
|
+
{ x: arrowSize, y: arrowSize / 2 }
|
|
3047
|
+
],
|
|
3048
|
+
{
|
|
3049
|
+
fill: color,
|
|
3050
|
+
left: x1,
|
|
3051
|
+
top: y1,
|
|
3052
|
+
originX: "left",
|
|
3053
|
+
originY: "center",
|
|
3054
|
+
angle: angle * 180 / Math.PI,
|
|
3055
|
+
selectable: false,
|
|
3056
|
+
evented: false
|
|
3057
|
+
}
|
|
3058
|
+
);
|
|
3059
|
+
return new import_fabric7.Group([line, startArrow, endArrow], {
|
|
3060
|
+
selectable: false,
|
|
3061
|
+
evented: false
|
|
3062
|
+
});
|
|
3063
|
+
}
|
|
3064
|
+
resolvePadding(containerWidth, containerHeight) {
|
|
3065
|
+
if (typeof this.dielinePadding === "number") {
|
|
3066
|
+
return this.dielinePadding;
|
|
3067
|
+
}
|
|
3068
|
+
if (typeof this.dielinePadding === "string") {
|
|
3069
|
+
if (this.dielinePadding.endsWith("%")) {
|
|
3070
|
+
const percent = parseFloat(this.dielinePadding) / 100;
|
|
3071
|
+
return Math.min(containerWidth, containerHeight) * percent;
|
|
3072
|
+
}
|
|
3073
|
+
return parseFloat(this.dielinePadding) || 0;
|
|
3074
|
+
}
|
|
3075
|
+
return 0;
|
|
3076
|
+
}
|
|
2831
3077
|
updateRuler() {
|
|
2832
3078
|
if (!this.canvasService) return;
|
|
2833
3079
|
const layer = this.getLayer();
|
|
@@ -2836,95 +3082,141 @@ var RulerTool = class {
|
|
|
2836
3082
|
const { thickness, backgroundColor, lineColor, textColor, fontSize } = this;
|
|
2837
3083
|
const width = this.canvasService.canvas.width || 800;
|
|
2838
3084
|
const height = this.canvasService.canvas.height || 600;
|
|
2839
|
-
const
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
width,
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
const
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
const
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
3085
|
+
const paddingPx = this.resolvePadding(width, height);
|
|
3086
|
+
const layout = Coordinate.calculateLayout(
|
|
3087
|
+
{ width, height },
|
|
3088
|
+
{ width: this.dielineWidth, height: this.dielineHeight },
|
|
3089
|
+
paddingPx
|
|
3090
|
+
);
|
|
3091
|
+
const scale = layout.scale;
|
|
3092
|
+
const offsetX = layout.offsetX;
|
|
3093
|
+
const offsetY = layout.offsetY;
|
|
3094
|
+
const visualWidth = layout.width;
|
|
3095
|
+
const visualHeight = layout.height;
|
|
3096
|
+
const rawOffset = this.dielineOffset || 0;
|
|
3097
|
+
const effectiveOffset = rawOffset > 0 ? rawOffset : 0;
|
|
3098
|
+
const expandPixels = effectiveOffset * scale;
|
|
3099
|
+
const gap = this.gap || 15;
|
|
3100
|
+
const rulerLeft = offsetX - expandPixels;
|
|
3101
|
+
const rulerTop = offsetY - expandPixels;
|
|
3102
|
+
const rulerRight = offsetX + visualWidth + expandPixels;
|
|
3103
|
+
const rulerBottom = offsetY + visualHeight + expandPixels;
|
|
3104
|
+
const displayWidth = this.dielineWidth + effectiveOffset * 2;
|
|
3105
|
+
const displayHeight = this.dielineHeight + effectiveOffset * 2;
|
|
3106
|
+
const topRulerY = rulerTop - gap;
|
|
3107
|
+
const topRulerXStart = rulerLeft;
|
|
3108
|
+
const topRulerXEnd = rulerRight;
|
|
3109
|
+
const leftRulerX = rulerLeft - gap;
|
|
3110
|
+
const leftRulerYStart = rulerTop;
|
|
3111
|
+
const leftRulerYEnd = rulerBottom;
|
|
3112
|
+
const topDimLine = this.createArrowLine(
|
|
3113
|
+
topRulerXStart,
|
|
3114
|
+
topRulerY,
|
|
3115
|
+
topRulerXEnd,
|
|
3116
|
+
topRulerY,
|
|
3117
|
+
lineColor
|
|
3118
|
+
);
|
|
3119
|
+
layer.add(topDimLine);
|
|
3120
|
+
const extLen = 5;
|
|
3121
|
+
layer.add(
|
|
3122
|
+
new import_fabric7.Line(
|
|
3123
|
+
[
|
|
3124
|
+
topRulerXStart,
|
|
3125
|
+
topRulerY - extLen,
|
|
3126
|
+
topRulerXStart,
|
|
3127
|
+
topRulerY + extLen
|
|
3128
|
+
],
|
|
3129
|
+
{
|
|
3130
|
+
stroke: lineColor,
|
|
3131
|
+
strokeWidth: 1,
|
|
3132
|
+
selectable: false,
|
|
3133
|
+
evented: false
|
|
3134
|
+
}
|
|
3135
|
+
)
|
|
3136
|
+
);
|
|
3137
|
+
layer.add(
|
|
3138
|
+
new import_fabric7.Line(
|
|
3139
|
+
[topRulerXEnd, topRulerY - extLen, topRulerXEnd, topRulerY + extLen],
|
|
3140
|
+
{
|
|
3141
|
+
stroke: lineColor,
|
|
3142
|
+
strokeWidth: 1,
|
|
3143
|
+
selectable: false,
|
|
3144
|
+
evented: false
|
|
3145
|
+
}
|
|
3146
|
+
)
|
|
3147
|
+
);
|
|
3148
|
+
const widthStr = parseFloat(displayWidth.toFixed(2)).toString();
|
|
3149
|
+
const topTextContent = `${widthStr} ${this.dielineUnit}`;
|
|
3150
|
+
const topText = new import_fabric7.Text(topTextContent, {
|
|
3151
|
+
left: topRulerXStart + (rulerRight - rulerLeft) / 2,
|
|
3152
|
+
top: topRulerY,
|
|
3153
|
+
fontSize,
|
|
3154
|
+
fill: textColor,
|
|
3155
|
+
fontFamily: "Arial",
|
|
3156
|
+
originX: "center",
|
|
3157
|
+
originY: "center",
|
|
3158
|
+
backgroundColor,
|
|
3159
|
+
// Background mask for readability
|
|
2865
3160
|
selectable: false,
|
|
2866
3161
|
evented: false
|
|
2867
3162
|
});
|
|
2868
|
-
layer.add(
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
left: x + 2,
|
|
2889
|
-
top: 2,
|
|
2890
|
-
fontSize,
|
|
2891
|
-
fill: textColor,
|
|
2892
|
-
fontFamily: "Arial",
|
|
3163
|
+
layer.add(topText);
|
|
3164
|
+
const leftDimLine = this.createArrowLine(
|
|
3165
|
+
leftRulerX,
|
|
3166
|
+
leftRulerYStart,
|
|
3167
|
+
leftRulerX,
|
|
3168
|
+
leftRulerYEnd,
|
|
3169
|
+
lineColor
|
|
3170
|
+
);
|
|
3171
|
+
layer.add(leftDimLine);
|
|
3172
|
+
layer.add(
|
|
3173
|
+
new import_fabric7.Line(
|
|
3174
|
+
[
|
|
3175
|
+
leftRulerX - extLen,
|
|
3176
|
+
leftRulerYStart,
|
|
3177
|
+
leftRulerX + extLen,
|
|
3178
|
+
leftRulerYStart
|
|
3179
|
+
],
|
|
3180
|
+
{
|
|
3181
|
+
stroke: lineColor,
|
|
3182
|
+
strokeWidth: 1,
|
|
2893
3183
|
selectable: false,
|
|
2894
3184
|
evented: false
|
|
2895
|
-
}
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
});
|
|
2910
|
-
layer.add(line);
|
|
2911
|
-
if (y % step === 0) {
|
|
2912
|
-
const text = new import_fabric7.Text(y.toString(), {
|
|
2913
|
-
angle: -90,
|
|
2914
|
-
left: thickness / 2 - fontSize / 3,
|
|
2915
|
-
// approximate centering
|
|
2916
|
-
top: y + fontSize,
|
|
2917
|
-
fontSize,
|
|
2918
|
-
fill: textColor,
|
|
2919
|
-
fontFamily: "Arial",
|
|
2920
|
-
originX: "center",
|
|
2921
|
-
originY: "center",
|
|
3185
|
+
}
|
|
3186
|
+
)
|
|
3187
|
+
);
|
|
3188
|
+
layer.add(
|
|
3189
|
+
new import_fabric7.Line(
|
|
3190
|
+
[
|
|
3191
|
+
leftRulerX - extLen,
|
|
3192
|
+
leftRulerYEnd,
|
|
3193
|
+
leftRulerX + extLen,
|
|
3194
|
+
leftRulerYEnd
|
|
3195
|
+
],
|
|
3196
|
+
{
|
|
3197
|
+
stroke: lineColor,
|
|
3198
|
+
strokeWidth: 1,
|
|
2922
3199
|
selectable: false,
|
|
2923
3200
|
evented: false
|
|
2924
|
-
}
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
3201
|
+
}
|
|
3202
|
+
)
|
|
3203
|
+
);
|
|
3204
|
+
const heightStr = parseFloat(displayHeight.toFixed(2)).toString();
|
|
3205
|
+
const leftTextContent = `${heightStr} ${this.dielineUnit}`;
|
|
3206
|
+
const leftText = new import_fabric7.Text(leftTextContent, {
|
|
3207
|
+
left: leftRulerX,
|
|
3208
|
+
top: leftRulerYStart + (rulerBottom - rulerTop) / 2,
|
|
3209
|
+
angle: -90,
|
|
3210
|
+
fontSize,
|
|
3211
|
+
fill: textColor,
|
|
3212
|
+
fontFamily: "Arial",
|
|
3213
|
+
originX: "center",
|
|
3214
|
+
originY: "center",
|
|
3215
|
+
backgroundColor,
|
|
3216
|
+
selectable: false,
|
|
3217
|
+
evented: false
|
|
3218
|
+
});
|
|
3219
|
+
layer.add(leftText);
|
|
2928
3220
|
this.canvasService.canvas.bringObjectToFront(layer);
|
|
2929
3221
|
this.canvasService.canvas.requestRenderAll();
|
|
2930
3222
|
}
|