@pooder/kit 6.1.2 → 6.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.test-dist/src/extensions/background/BackgroundTool.js +177 -5
- package/.test-dist/src/extensions/constraintUtils.js +44 -0
- package/.test-dist/src/extensions/dieline/DielineTool.js +52 -409
- package/.test-dist/src/extensions/dieline/featureResolution.js +29 -0
- package/.test-dist/src/extensions/dieline/model.js +83 -0
- package/.test-dist/src/extensions/dieline/renderBuilder.js +227 -0
- package/.test-dist/src/extensions/feature/FeatureTool.js +156 -45
- package/.test-dist/src/extensions/featureCoordinates.js +21 -0
- package/.test-dist/src/extensions/featurePlacement.js +46 -0
- package/.test-dist/src/extensions/image/ImageTool.js +281 -25
- package/.test-dist/src/extensions/ruler/RulerTool.js +24 -1
- package/.test-dist/src/shared/constants/layers.js +3 -1
- package/.test-dist/tests/run.js +25 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +47 -13
- package/dist/index.d.ts +47 -13
- package/dist/index.js +1325 -977
- package/dist/index.mjs +1311 -966
- package/package.json +1 -1
- package/src/extensions/background/BackgroundTool.ts +264 -4
- package/src/extensions/dieline/DielineTool.ts +67 -548
- package/src/extensions/dieline/model.ts +165 -1
- package/src/extensions/dieline/renderBuilder.ts +301 -0
- package/src/extensions/feature/FeatureTool.ts +190 -47
- package/src/extensions/featureCoordinates.ts +35 -0
- package/src/extensions/featurePlacement.ts +118 -0
- package/src/extensions/image/ImageTool.ts +139 -157
- package/src/extensions/ruler/RulerTool.ts +24 -2
- package/src/shared/constants/layers.ts +2 -0
- package/tests/run.ts +37 -0
package/dist/index.mjs
CHANGED
|
@@ -400,6 +400,7 @@ var WHITE_INK_OBJECT_LAYER_ID = "white-ink.user";
|
|
|
400
400
|
var WHITE_INK_COVER_LAYER_ID = "white-ink.cover";
|
|
401
401
|
var WHITE_INK_OVERLAY_LAYER_ID = "white-ink.overlay";
|
|
402
402
|
var DIELINE_LAYER_ID = "dieline-overlay";
|
|
403
|
+
var FEATURE_DIELINE_LAYER_ID = "feature-dieline-overlay";
|
|
403
404
|
var FEATURE_OVERLAY_LAYER_ID = "feature-overlay";
|
|
404
405
|
var RULER_LAYER_ID = "ruler-overlay";
|
|
405
406
|
var FILM_LAYER_ID = "overlay";
|
|
@@ -541,6 +542,18 @@ function normalizeFitMode2(value, fallback) {
|
|
|
541
542
|
}
|
|
542
543
|
return fallback;
|
|
543
544
|
}
|
|
545
|
+
function normalizeRegionUnit(value, fallback) {
|
|
546
|
+
if (value === "px" || value === "normalized") {
|
|
547
|
+
return value;
|
|
548
|
+
}
|
|
549
|
+
return fallback;
|
|
550
|
+
}
|
|
551
|
+
function normalizeRegistrationFrame(value, fallback) {
|
|
552
|
+
if (value === "trim" || value === "cut" || value === "bleed" || value === "focus" || value === "viewport") {
|
|
553
|
+
return value;
|
|
554
|
+
}
|
|
555
|
+
return fallback;
|
|
556
|
+
}
|
|
544
557
|
function normalizeAnchor(value, fallback) {
|
|
545
558
|
if (typeof value !== "string") return fallback;
|
|
546
559
|
const trimmed = value.trim();
|
|
@@ -551,6 +564,63 @@ function normalizeOrder(value, fallback) {
|
|
|
551
564
|
if (!Number.isFinite(numeric)) return fallback;
|
|
552
565
|
return numeric;
|
|
553
566
|
}
|
|
567
|
+
function normalizeRegionValue(value, fallback) {
|
|
568
|
+
const numeric = Number(value);
|
|
569
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
570
|
+
}
|
|
571
|
+
function normalizeRegistrationRegion(raw, fallback) {
|
|
572
|
+
if (!raw || typeof raw !== "object") {
|
|
573
|
+
return fallback ? { ...fallback } : void 0;
|
|
574
|
+
}
|
|
575
|
+
const input = raw;
|
|
576
|
+
const base = fallback || {
|
|
577
|
+
left: 0,
|
|
578
|
+
top: 0,
|
|
579
|
+
width: 1,
|
|
580
|
+
height: 1,
|
|
581
|
+
unit: "normalized"
|
|
582
|
+
};
|
|
583
|
+
return {
|
|
584
|
+
left: normalizeRegionValue(input.left, base.left),
|
|
585
|
+
top: normalizeRegionValue(input.top, base.top),
|
|
586
|
+
width: normalizeRegionValue(input.width, base.width),
|
|
587
|
+
height: normalizeRegionValue(input.height, base.height),
|
|
588
|
+
unit: normalizeRegionUnit(input.unit, base.unit)
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
function normalizeRegistration(raw, fallback) {
|
|
592
|
+
if (!raw || typeof raw !== "object") {
|
|
593
|
+
return fallback ? {
|
|
594
|
+
sourceRegion: fallback.sourceRegion ? { ...fallback.sourceRegion } : void 0,
|
|
595
|
+
targetFrame: fallback.targetFrame,
|
|
596
|
+
fit: fallback.fit
|
|
597
|
+
} : void 0;
|
|
598
|
+
}
|
|
599
|
+
const input = raw;
|
|
600
|
+
const normalized = {
|
|
601
|
+
sourceRegion: normalizeRegistrationRegion(
|
|
602
|
+
input.sourceRegion,
|
|
603
|
+
fallback == null ? void 0 : fallback.sourceRegion
|
|
604
|
+
),
|
|
605
|
+
targetFrame: normalizeRegistrationFrame(
|
|
606
|
+
input.targetFrame,
|
|
607
|
+
(fallback == null ? void 0 : fallback.targetFrame) || "trim"
|
|
608
|
+
),
|
|
609
|
+
fit: normalizeFitMode2(input.fit, (fallback == null ? void 0 : fallback.fit) || "stretch")
|
|
610
|
+
};
|
|
611
|
+
if (!normalized.sourceRegion) {
|
|
612
|
+
return void 0;
|
|
613
|
+
}
|
|
614
|
+
return normalized;
|
|
615
|
+
}
|
|
616
|
+
function cloneRegistration(registration) {
|
|
617
|
+
if (!registration) return void 0;
|
|
618
|
+
return {
|
|
619
|
+
sourceRegion: registration.sourceRegion ? { ...registration.sourceRegion } : void 0,
|
|
620
|
+
targetFrame: registration.targetFrame,
|
|
621
|
+
fit: registration.fit
|
|
622
|
+
};
|
|
623
|
+
}
|
|
554
624
|
function normalizeLayer(raw, index, fallback) {
|
|
555
625
|
const fallbackLayer = fallback || {
|
|
556
626
|
id: `layer-${index + 1}`,
|
|
@@ -564,7 +634,10 @@ function normalizeLayer(raw, index, fallback) {
|
|
|
564
634
|
src: ""
|
|
565
635
|
};
|
|
566
636
|
if (!raw || typeof raw !== "object") {
|
|
567
|
-
return {
|
|
637
|
+
return {
|
|
638
|
+
...fallbackLayer,
|
|
639
|
+
registration: cloneRegistration(fallbackLayer.registration)
|
|
640
|
+
};
|
|
568
641
|
}
|
|
569
642
|
const input = raw;
|
|
570
643
|
const kind = normalizeLayerKind(input.kind, fallbackLayer.kind);
|
|
@@ -578,7 +651,8 @@ function normalizeLayer(raw, index, fallback) {
|
|
|
578
651
|
enabled: typeof input.enabled === "boolean" ? input.enabled : fallbackLayer.enabled,
|
|
579
652
|
exportable: typeof input.exportable === "boolean" ? input.exportable : fallbackLayer.exportable,
|
|
580
653
|
color: kind === "color" ? typeof input.color === "string" ? input.color : typeof fallbackLayer.color === "string" ? fallbackLayer.color : "#ffffff" : void 0,
|
|
581
|
-
src: kind === "image" ? typeof input.src === "string" ? input.src.trim() : typeof fallbackLayer.src === "string" ? fallbackLayer.src : "" : void 0
|
|
654
|
+
src: kind === "image" ? typeof input.src === "string" ? input.src.trim() : typeof fallbackLayer.src === "string" ? fallbackLayer.src : "" : void 0,
|
|
655
|
+
registration: kind === "image" ? normalizeRegistration(input.registration, fallbackLayer.registration) : void 0
|
|
582
656
|
};
|
|
583
657
|
}
|
|
584
658
|
function normalizeConfig(raw) {
|
|
@@ -608,7 +682,10 @@ function normalizeConfig(raw) {
|
|
|
608
682
|
function cloneConfig(config) {
|
|
609
683
|
return {
|
|
610
684
|
version: config.version,
|
|
611
|
-
layers: (config.layers || []).map((layer) => ({
|
|
685
|
+
layers: (config.layers || []).map((layer) => ({
|
|
686
|
+
...layer,
|
|
687
|
+
registration: cloneRegistration(layer.registration)
|
|
688
|
+
}))
|
|
612
689
|
};
|
|
613
690
|
}
|
|
614
691
|
function mergeConfig(base, patch) {
|
|
@@ -859,6 +936,41 @@ var BackgroundTool = class {
|
|
|
859
936
|
height: layout.trimRect.height
|
|
860
937
|
};
|
|
861
938
|
}
|
|
939
|
+
resolveTargetFrameRect(frame) {
|
|
940
|
+
if (frame === "viewport") {
|
|
941
|
+
return this.getViewportRect();
|
|
942
|
+
}
|
|
943
|
+
const layout = this.resolveSceneLayout();
|
|
944
|
+
if (!layout) {
|
|
945
|
+
return frame === "focus" ? this.getViewportRect() : null;
|
|
946
|
+
}
|
|
947
|
+
switch (frame) {
|
|
948
|
+
case "trim":
|
|
949
|
+
case "focus":
|
|
950
|
+
return {
|
|
951
|
+
left: layout.trimRect.left,
|
|
952
|
+
top: layout.trimRect.top,
|
|
953
|
+
width: layout.trimRect.width,
|
|
954
|
+
height: layout.trimRect.height
|
|
955
|
+
};
|
|
956
|
+
case "cut":
|
|
957
|
+
return {
|
|
958
|
+
left: layout.cutRect.left,
|
|
959
|
+
top: layout.cutRect.top,
|
|
960
|
+
width: layout.cutRect.width,
|
|
961
|
+
height: layout.cutRect.height
|
|
962
|
+
};
|
|
963
|
+
case "bleed":
|
|
964
|
+
return {
|
|
965
|
+
left: layout.bleedRect.left,
|
|
966
|
+
top: layout.bleedRect.top,
|
|
967
|
+
width: layout.bleedRect.width,
|
|
968
|
+
height: layout.bleedRect.height
|
|
969
|
+
};
|
|
970
|
+
default:
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
862
974
|
resolveAnchorRect(anchor) {
|
|
863
975
|
if (anchor === "focus") {
|
|
864
976
|
return this.resolveFocusRect() || this.getViewportRect();
|
|
@@ -891,6 +1003,53 @@ var BackgroundTool = class {
|
|
|
891
1003
|
scaleY: scale
|
|
892
1004
|
};
|
|
893
1005
|
}
|
|
1006
|
+
resolveRegistrationRegion(region, sourceSize) {
|
|
1007
|
+
const sourceWidth = Math.max(1, Number(sourceSize.width || 0));
|
|
1008
|
+
const sourceHeight = Math.max(1, Number(sourceSize.height || 0));
|
|
1009
|
+
const width = region.unit === "normalized" ? region.width * sourceWidth : region.width;
|
|
1010
|
+
const height = region.unit === "normalized" ? region.height * sourceHeight : region.height;
|
|
1011
|
+
const left = region.unit === "normalized" ? region.left * sourceWidth : region.left;
|
|
1012
|
+
const top = region.unit === "normalized" ? region.top * sourceHeight : region.top;
|
|
1013
|
+
if (!Number.isFinite(left) || !Number.isFinite(top) || !Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
return { left, top, width, height };
|
|
1017
|
+
}
|
|
1018
|
+
resolveRegistrationPlacement(layer, sourceSize) {
|
|
1019
|
+
const registration = layer.registration;
|
|
1020
|
+
if (!(registration == null ? void 0 : registration.sourceRegion)) return null;
|
|
1021
|
+
const targetRect = this.resolveTargetFrameRect(
|
|
1022
|
+
registration.targetFrame || "trim"
|
|
1023
|
+
);
|
|
1024
|
+
if (!targetRect) return null;
|
|
1025
|
+
const sourceRegion = this.resolveRegistrationRegion(
|
|
1026
|
+
registration.sourceRegion,
|
|
1027
|
+
sourceSize
|
|
1028
|
+
);
|
|
1029
|
+
if (!sourceRegion) return null;
|
|
1030
|
+
const fit = registration.fit || "stretch";
|
|
1031
|
+
const baseScaleX = targetRect.width / sourceRegion.width;
|
|
1032
|
+
const baseScaleY = targetRect.height / sourceRegion.height;
|
|
1033
|
+
if (fit === "stretch") {
|
|
1034
|
+
return {
|
|
1035
|
+
left: targetRect.left - sourceRegion.left * baseScaleX,
|
|
1036
|
+
top: targetRect.top - sourceRegion.top * baseScaleY,
|
|
1037
|
+
scaleX: baseScaleX,
|
|
1038
|
+
scaleY: baseScaleY
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
const uniformScale = fit === "contain" ? Math.min(baseScaleX, baseScaleY) : Math.max(baseScaleX, baseScaleY);
|
|
1042
|
+
const alignedWidth = sourceRegion.width * uniformScale;
|
|
1043
|
+
const alignedHeight = sourceRegion.height * uniformScale;
|
|
1044
|
+
const offsetLeft = targetRect.left + (targetRect.width - alignedWidth) / 2;
|
|
1045
|
+
const offsetTop = targetRect.top + (targetRect.height - alignedHeight) / 2;
|
|
1046
|
+
return {
|
|
1047
|
+
left: offsetLeft - sourceRegion.left * uniformScale,
|
|
1048
|
+
top: offsetTop - sourceRegion.top * uniformScale,
|
|
1049
|
+
scaleX: uniformScale,
|
|
1050
|
+
scaleY: uniformScale
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
894
1053
|
buildColorLayerSpec(layer) {
|
|
895
1054
|
const rect = this.resolveAnchorRect(layer.anchor);
|
|
896
1055
|
return {
|
|
@@ -924,8 +1083,11 @@ var BackgroundTool = class {
|
|
|
924
1083
|
if (!src) return [];
|
|
925
1084
|
const sourceSize = this.sourceSizeCache.getSourceSize(src);
|
|
926
1085
|
if (!sourceSize) return [];
|
|
927
|
-
const
|
|
928
|
-
|
|
1086
|
+
const placement = this.resolveRegistrationPlacement(layer, sourceSize) || this.resolveImagePlacement(
|
|
1087
|
+
this.resolveAnchorRect(layer.anchor),
|
|
1088
|
+
sourceSize,
|
|
1089
|
+
layer.fit
|
|
1090
|
+
);
|
|
929
1091
|
return [
|
|
930
1092
|
{
|
|
931
1093
|
id: `background.layer.${layer.id}.image`,
|
|
@@ -1025,7 +1187,6 @@ import {
|
|
|
1025
1187
|
Canvas as FabricCanvas,
|
|
1026
1188
|
Control,
|
|
1027
1189
|
Image as FabricImage2,
|
|
1028
|
-
Path as FabricPath,
|
|
1029
1190
|
Pattern,
|
|
1030
1191
|
Point,
|
|
1031
1192
|
controlsUtils
|
|
@@ -2000,8 +2161,6 @@ var IMAGE_DEFAULT_CONTROL_CAPABILITIES = [
|
|
|
2000
2161
|
"scale"
|
|
2001
2162
|
];
|
|
2002
2163
|
var IMAGE_MOVE_SNAP_THRESHOLD_PX = 6;
|
|
2003
|
-
var IMAGE_MOVE_SNAP_RELEASE_THRESHOLD_PX = 10;
|
|
2004
|
-
var IMAGE_SNAP_GUIDE_LAYER_ID = "image.snapGuide";
|
|
2005
2164
|
var IMAGE_CONTROL_DESCRIPTORS = [
|
|
2006
2165
|
{
|
|
2007
2166
|
key: "tl",
|
|
@@ -2048,13 +2207,15 @@ var ImageTool = class {
|
|
|
2048
2207
|
this.overlaySpecs = [];
|
|
2049
2208
|
this.activeSnapX = null;
|
|
2050
2209
|
this.activeSnapY = null;
|
|
2210
|
+
this.movingImageId = null;
|
|
2211
|
+
this.hasRenderedSnapGuides = false;
|
|
2051
2212
|
this.subscriptions = new SubscriptionBag();
|
|
2052
2213
|
this.imageControlsByCapabilityKey = /* @__PURE__ */ new Map();
|
|
2053
2214
|
this.onToolActivated = (event) => {
|
|
2054
2215
|
const before = this.isToolActive;
|
|
2055
2216
|
this.syncToolActiveFromWorkbench(event.id);
|
|
2056
2217
|
if (!this.isToolActive) {
|
|
2057
|
-
this.
|
|
2218
|
+
this.endMoveSnapInteraction();
|
|
2058
2219
|
this.setImageFocus(null, {
|
|
2059
2220
|
syncCanvasSelection: true,
|
|
2060
2221
|
skipRender: true
|
|
@@ -2105,7 +2266,7 @@ var ImageTool = class {
|
|
|
2105
2266
|
this.updateImages();
|
|
2106
2267
|
};
|
|
2107
2268
|
this.onSelectionCleared = () => {
|
|
2108
|
-
this.
|
|
2269
|
+
this.endMoveSnapInteraction();
|
|
2109
2270
|
this.setImageFocus(null, {
|
|
2110
2271
|
syncCanvasSelection: false,
|
|
2111
2272
|
skipRender: true
|
|
@@ -2114,7 +2275,8 @@ var ImageTool = class {
|
|
|
2114
2275
|
this.updateImages();
|
|
2115
2276
|
};
|
|
2116
2277
|
this.onSceneLayoutChanged = () => {
|
|
2117
|
-
|
|
2278
|
+
var _a;
|
|
2279
|
+
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2118
2280
|
this.updateImages();
|
|
2119
2281
|
};
|
|
2120
2282
|
this.onSceneGeometryChanged = () => {
|
|
@@ -2127,11 +2289,12 @@ var ImageTool = class {
|
|
|
2127
2289
|
const id = (_a = target == null ? void 0 : target.data) == null ? void 0 : _a.id;
|
|
2128
2290
|
const layerId = (_b = target == null ? void 0 : target.data) == null ? void 0 : _b.layerId;
|
|
2129
2291
|
if (typeof id !== "string" || layerId !== IMAGE_OBJECT_LAYER_ID) return;
|
|
2292
|
+
if (this.movingImageId === id) {
|
|
2293
|
+
this.applyMoveSnapToTarget(target);
|
|
2294
|
+
}
|
|
2130
2295
|
const frame = this.getFrameRect();
|
|
2296
|
+
this.endMoveSnapInteraction();
|
|
2131
2297
|
if (!frame.width || !frame.height) return;
|
|
2132
|
-
const matches = this.computeMoveSnapMatches(target, frame);
|
|
2133
|
-
this.applySnapMatchesToTarget(target, matches);
|
|
2134
|
-
this.clearSnapGuides();
|
|
2135
2298
|
const center = target.getCenterPoint ? target.getCenterPoint() : new Point((_c = target.left) != null ? _c : 0, (_d = target.top) != null ? _d : 0);
|
|
2136
2299
|
const centerScene = this.canvasService ? this.canvasService.toScenePoint({ x: center.x, y: center.y }) : { x: center.x, y: center.y };
|
|
2137
2300
|
const objectScale = Number.isFinite(target == null ? void 0 : target.scaleX) ? target.scaleX : 1;
|
|
@@ -2272,7 +2435,7 @@ var ImageTool = class {
|
|
|
2272
2435
|
this.imageSpecs = [];
|
|
2273
2436
|
this.overlaySpecs = [];
|
|
2274
2437
|
this.imageControlsByCapabilityKey.clear();
|
|
2275
|
-
this.
|
|
2438
|
+
this.endMoveSnapInteraction();
|
|
2276
2439
|
this.unbindCanvasInteractionHandlers();
|
|
2277
2440
|
this.clearRenderedImages();
|
|
2278
2441
|
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
@@ -2285,21 +2448,61 @@ var ImageTool = class {
|
|
|
2285
2448
|
}
|
|
2286
2449
|
bindCanvasInteractionHandlers() {
|
|
2287
2450
|
if (!this.canvasService || this.canvasObjectMovingHandler) return;
|
|
2451
|
+
this.canvasMouseUpHandler = (e) => {
|
|
2452
|
+
var _a;
|
|
2453
|
+
const target = this.getActiveImageTarget(e == null ? void 0 : e.target);
|
|
2454
|
+
if (target && typeof ((_a = target == null ? void 0 : target.data) == null ? void 0 : _a.id) === "string" && target.data.id === this.movingImageId) {
|
|
2455
|
+
this.applyMoveSnapToTarget(target);
|
|
2456
|
+
}
|
|
2457
|
+
this.endMoveSnapInteraction();
|
|
2458
|
+
};
|
|
2288
2459
|
this.canvasObjectMovingHandler = (e) => {
|
|
2289
2460
|
this.handleCanvasObjectMoving(e);
|
|
2290
2461
|
};
|
|
2462
|
+
this.canvasBeforeRenderHandler = () => {
|
|
2463
|
+
this.handleCanvasBeforeRender();
|
|
2464
|
+
};
|
|
2465
|
+
this.canvasAfterRenderHandler = () => {
|
|
2466
|
+
this.handleCanvasAfterRender();
|
|
2467
|
+
};
|
|
2468
|
+
this.canvasService.canvas.on("mouse:up", this.canvasMouseUpHandler);
|
|
2291
2469
|
this.canvasService.canvas.on(
|
|
2292
2470
|
"object:moving",
|
|
2293
2471
|
this.canvasObjectMovingHandler
|
|
2294
2472
|
);
|
|
2473
|
+
this.canvasService.canvas.on(
|
|
2474
|
+
"before:render",
|
|
2475
|
+
this.canvasBeforeRenderHandler
|
|
2476
|
+
);
|
|
2477
|
+
this.canvasService.canvas.on("after:render", this.canvasAfterRenderHandler);
|
|
2295
2478
|
}
|
|
2296
2479
|
unbindCanvasInteractionHandlers() {
|
|
2297
|
-
if (!this.canvasService
|
|
2298
|
-
this.
|
|
2299
|
-
"
|
|
2300
|
-
|
|
2301
|
-
)
|
|
2480
|
+
if (!this.canvasService) return;
|
|
2481
|
+
if (this.canvasMouseUpHandler) {
|
|
2482
|
+
this.canvasService.canvas.off("mouse:up", this.canvasMouseUpHandler);
|
|
2483
|
+
}
|
|
2484
|
+
if (this.canvasObjectMovingHandler) {
|
|
2485
|
+
this.canvasService.canvas.off(
|
|
2486
|
+
"object:moving",
|
|
2487
|
+
this.canvasObjectMovingHandler
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
if (this.canvasBeforeRenderHandler) {
|
|
2491
|
+
this.canvasService.canvas.off(
|
|
2492
|
+
"before:render",
|
|
2493
|
+
this.canvasBeforeRenderHandler
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
if (this.canvasAfterRenderHandler) {
|
|
2497
|
+
this.canvasService.canvas.off(
|
|
2498
|
+
"after:render",
|
|
2499
|
+
this.canvasAfterRenderHandler
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
this.canvasMouseUpHandler = void 0;
|
|
2302
2503
|
this.canvasObjectMovingHandler = void 0;
|
|
2504
|
+
this.canvasBeforeRenderHandler = void 0;
|
|
2505
|
+
this.canvasAfterRenderHandler = void 0;
|
|
2303
2506
|
}
|
|
2304
2507
|
getActiveImageTarget(target) {
|
|
2305
2508
|
var _a, _b;
|
|
@@ -2328,20 +2531,11 @@ var ImageTool = class {
|
|
|
2328
2531
|
if (!this.canvasService) return px;
|
|
2329
2532
|
return this.canvasService.toSceneLength(px);
|
|
2330
2533
|
}
|
|
2331
|
-
pickSnapMatch(candidates
|
|
2534
|
+
pickSnapMatch(candidates) {
|
|
2332
2535
|
if (!candidates.length) return null;
|
|
2333
2536
|
const snapThreshold = this.getSnapThresholdScene(
|
|
2334
2537
|
IMAGE_MOVE_SNAP_THRESHOLD_PX
|
|
2335
2538
|
);
|
|
2336
|
-
const releaseThreshold = this.getSnapThresholdScene(
|
|
2337
|
-
IMAGE_MOVE_SNAP_RELEASE_THRESHOLD_PX
|
|
2338
|
-
);
|
|
2339
|
-
if (previous) {
|
|
2340
|
-
const sticky = candidates.find((candidate) => {
|
|
2341
|
-
return candidate.lineId === previous.lineId && Math.abs(candidate.deltaScene) <= releaseThreshold;
|
|
2342
|
-
});
|
|
2343
|
-
if (sticky) return sticky;
|
|
2344
|
-
}
|
|
2345
2539
|
let best = null;
|
|
2346
2540
|
candidates.forEach((candidate) => {
|
|
2347
2541
|
if (Math.abs(candidate.deltaScene) > snapThreshold) return;
|
|
@@ -2351,8 +2545,7 @@ var ImageTool = class {
|
|
|
2351
2545
|
});
|
|
2352
2546
|
return best;
|
|
2353
2547
|
}
|
|
2354
|
-
computeMoveSnapMatches(
|
|
2355
|
-
const bounds = this.getTargetBoundsScene(target);
|
|
2548
|
+
computeMoveSnapMatches(bounds, frame) {
|
|
2356
2549
|
if (!bounds || frame.width <= 0 || frame.height <= 0) {
|
|
2357
2550
|
return { x: null, y: null };
|
|
2358
2551
|
}
|
|
@@ -2403,8 +2596,8 @@ var ImageTool = class {
|
|
|
2403
2596
|
}
|
|
2404
2597
|
];
|
|
2405
2598
|
return {
|
|
2406
|
-
x: this.pickSnapMatch(xCandidates
|
|
2407
|
-
y: this.pickSnapMatch(yCandidates
|
|
2599
|
+
x: this.pickSnapMatch(xCandidates),
|
|
2600
|
+
y: this.pickSnapMatch(yCandidates)
|
|
2408
2601
|
};
|
|
2409
2602
|
}
|
|
2410
2603
|
areSnapMatchesEqual(a, b) {
|
|
@@ -2413,136 +2606,123 @@ var ImageTool = class {
|
|
|
2413
2606
|
return a.lineId === b.lineId && a.axis === b.axis && a.kind === b.kind;
|
|
2414
2607
|
}
|
|
2415
2608
|
updateSnapMatchState(nextX, nextY) {
|
|
2609
|
+
var _a;
|
|
2416
2610
|
const changed = !this.areSnapMatchesEqual(this.activeSnapX, nextX) || !this.areSnapMatchesEqual(this.activeSnapY, nextY);
|
|
2417
2611
|
this.activeSnapX = nextX;
|
|
2418
2612
|
this.activeSnapY = nextY;
|
|
2419
2613
|
if (changed) {
|
|
2420
|
-
this.
|
|
2614
|
+
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2421
2615
|
}
|
|
2422
2616
|
}
|
|
2423
|
-
|
|
2617
|
+
clearSnapPreview() {
|
|
2424
2618
|
var _a;
|
|
2425
2619
|
this.activeSnapX = null;
|
|
2426
2620
|
this.activeSnapY = null;
|
|
2427
|
-
this.
|
|
2428
|
-
this.removeSnapGuideObject("y");
|
|
2621
|
+
this.hasRenderedSnapGuides = false;
|
|
2429
2622
|
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2430
2623
|
}
|
|
2431
|
-
|
|
2624
|
+
endMoveSnapInteraction() {
|
|
2625
|
+
this.movingImageId = null;
|
|
2626
|
+
this.clearSnapPreview();
|
|
2627
|
+
}
|
|
2628
|
+
applyMoveSnapToTarget(target) {
|
|
2629
|
+
var _a, _b, _c, _d;
|
|
2630
|
+
if (!this.canvasService) {
|
|
2631
|
+
return { x: null, y: null };
|
|
2632
|
+
}
|
|
2633
|
+
const frame = this.getFrameRect();
|
|
2634
|
+
if (frame.width <= 0 || frame.height <= 0) {
|
|
2635
|
+
return { x: null, y: null };
|
|
2636
|
+
}
|
|
2637
|
+
const bounds = this.getTargetBoundsScene(target);
|
|
2638
|
+
const matches = this.computeMoveSnapMatches(bounds, frame);
|
|
2639
|
+
const deltaScreenX = this.canvasService.toScreenLength(
|
|
2640
|
+
(_b = (_a = matches.x) == null ? void 0 : _a.deltaScene) != null ? _b : 0
|
|
2641
|
+
);
|
|
2642
|
+
const deltaScreenY = this.canvasService.toScreenLength(
|
|
2643
|
+
(_d = (_c = matches.y) == null ? void 0 : _c.deltaScene) != null ? _d : 0
|
|
2644
|
+
);
|
|
2645
|
+
if (deltaScreenX || deltaScreenY) {
|
|
2646
|
+
target.set({
|
|
2647
|
+
left: Number(target.left || 0) + deltaScreenX,
|
|
2648
|
+
top: Number(target.top || 0) + deltaScreenY
|
|
2649
|
+
});
|
|
2650
|
+
target.setCoords();
|
|
2651
|
+
}
|
|
2652
|
+
return matches;
|
|
2653
|
+
}
|
|
2654
|
+
handleCanvasBeforeRender() {
|
|
2432
2655
|
if (!this.canvasService) return;
|
|
2433
|
-
|
|
2434
|
-
const current = axis === "x" ? this.snapGuideXObject : this.snapGuideYObject;
|
|
2435
|
-
if (!current) return;
|
|
2436
|
-
canvas.remove(current);
|
|
2437
|
-
if (axis === "x") {
|
|
2438
|
-
this.snapGuideXObject = void 0;
|
|
2656
|
+
if (!this.hasRenderedSnapGuides && !this.activeSnapX && !this.activeSnapY) {
|
|
2439
2657
|
return;
|
|
2440
2658
|
}
|
|
2441
|
-
this.
|
|
2659
|
+
this.canvasService.canvas.clearContext(
|
|
2660
|
+
this.canvasService.canvas.contextTop
|
|
2661
|
+
);
|
|
2662
|
+
this.hasRenderedSnapGuides = false;
|
|
2442
2663
|
}
|
|
2443
|
-
|
|
2664
|
+
drawSnapGuideLine(from, to) {
|
|
2444
2665
|
if (!this.canvasService) return;
|
|
2445
|
-
const
|
|
2666
|
+
const ctx = this.canvasService.canvas.contextTop;
|
|
2667
|
+
if (!ctx) return;
|
|
2446
2668
|
const color = this.getConfig("image.control.borderColor", "#1677ff") || "#1677ff";
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
selectable: false,
|
|
2456
|
-
evented: false,
|
|
2457
|
-
excludeFromExport: true,
|
|
2458
|
-
objectCaching: false,
|
|
2459
|
-
data: {
|
|
2460
|
-
id: `${IMAGE_SNAP_GUIDE_LAYER_ID}.${axis}`,
|
|
2461
|
-
layerId: IMAGE_SNAP_GUIDE_LAYER_ID,
|
|
2462
|
-
type: "image-snap-guide"
|
|
2463
|
-
}
|
|
2464
|
-
});
|
|
2465
|
-
created.setCoords();
|
|
2466
|
-
canvas.add(created);
|
|
2467
|
-
canvas.bringObjectToFront(created);
|
|
2468
|
-
if (axis === "x") {
|
|
2469
|
-
this.snapGuideXObject = created;
|
|
2470
|
-
return;
|
|
2471
|
-
}
|
|
2472
|
-
this.snapGuideYObject = created;
|
|
2669
|
+
ctx.save();
|
|
2670
|
+
ctx.strokeStyle = color;
|
|
2671
|
+
ctx.lineWidth = 1;
|
|
2672
|
+
ctx.beginPath();
|
|
2673
|
+
ctx.moveTo(from.x, from.y);
|
|
2674
|
+
ctx.lineTo(to.x, to.y);
|
|
2675
|
+
ctx.stroke();
|
|
2676
|
+
ctx.restore();
|
|
2473
2677
|
}
|
|
2474
|
-
|
|
2678
|
+
handleCanvasAfterRender() {
|
|
2475
2679
|
if (!this.canvasService || !this.isImageEditingVisible()) {
|
|
2476
|
-
this.removeSnapGuideObject("x");
|
|
2477
|
-
this.removeSnapGuideObject("y");
|
|
2478
2680
|
return;
|
|
2479
2681
|
}
|
|
2480
2682
|
const frame = this.getFrameRect();
|
|
2481
2683
|
if (frame.width <= 0 || frame.height <= 0) {
|
|
2482
|
-
this.removeSnapGuideObject("x");
|
|
2483
|
-
this.removeSnapGuideObject("y");
|
|
2484
2684
|
return;
|
|
2485
2685
|
}
|
|
2486
2686
|
const frameScreen = this.getFrameRectScreen(frame);
|
|
2687
|
+
let drew = false;
|
|
2487
2688
|
if (this.activeSnapX) {
|
|
2488
2689
|
const x = this.canvasService.toScreenPoint({
|
|
2489
2690
|
x: this.activeSnapX.lineScene,
|
|
2490
2691
|
y: frame.top
|
|
2491
2692
|
}).x;
|
|
2492
|
-
this.
|
|
2493
|
-
|
|
2494
|
-
|
|
2693
|
+
this.drawSnapGuideLine(
|
|
2694
|
+
{ x, y: frameScreen.top },
|
|
2695
|
+
{ x, y: frameScreen.top + frameScreen.height }
|
|
2495
2696
|
);
|
|
2496
|
-
|
|
2497
|
-
this.removeSnapGuideObject("x");
|
|
2697
|
+
drew = true;
|
|
2498
2698
|
}
|
|
2499
2699
|
if (this.activeSnapY) {
|
|
2500
2700
|
const y = this.canvasService.toScreenPoint({
|
|
2501
2701
|
x: frame.left,
|
|
2502
2702
|
y: this.activeSnapY.lineScene
|
|
2503
2703
|
}).y;
|
|
2504
|
-
this.
|
|
2505
|
-
|
|
2506
|
-
|
|
2704
|
+
this.drawSnapGuideLine(
|
|
2705
|
+
{ x: frameScreen.left, y },
|
|
2706
|
+
{ x: frameScreen.left + frameScreen.width, y }
|
|
2507
2707
|
);
|
|
2508
|
-
|
|
2509
|
-
this.removeSnapGuideObject("y");
|
|
2708
|
+
drew = true;
|
|
2510
2709
|
}
|
|
2511
|
-
this.
|
|
2710
|
+
this.hasRenderedSnapGuides = drew;
|
|
2512
2711
|
}
|
|
2513
2712
|
handleCanvasObjectMoving(e) {
|
|
2514
|
-
var _a
|
|
2713
|
+
var _a;
|
|
2515
2714
|
const target = this.getActiveImageTarget(e == null ? void 0 : e.target);
|
|
2516
2715
|
if (!target || !this.canvasService) return;
|
|
2716
|
+
this.movingImageId = typeof ((_a = target == null ? void 0 : target.data) == null ? void 0 : _a.id) === "string" ? target.data.id : null;
|
|
2517
2717
|
const frame = this.getFrameRect();
|
|
2518
2718
|
if (frame.width <= 0 || frame.height <= 0) {
|
|
2519
|
-
this.
|
|
2719
|
+
this.endMoveSnapInteraction();
|
|
2520
2720
|
return;
|
|
2521
2721
|
}
|
|
2522
|
-
const
|
|
2523
|
-
const
|
|
2524
|
-
const deltaY = (_d = (_c = matches.y) == null ? void 0 : _c.deltaScene) != null ? _d : 0;
|
|
2525
|
-
if (deltaX || deltaY) {
|
|
2526
|
-
target.set({
|
|
2527
|
-
left: Number(target.left || 0) + this.canvasService.toScreenLength(deltaX),
|
|
2528
|
-
top: Number(target.top || 0) + this.canvasService.toScreenLength(deltaY)
|
|
2529
|
-
});
|
|
2530
|
-
target.setCoords();
|
|
2531
|
-
}
|
|
2722
|
+
const rawBounds = this.getTargetBoundsScene(target);
|
|
2723
|
+
const matches = this.computeMoveSnapMatches(rawBounds, frame);
|
|
2532
2724
|
this.updateSnapMatchState(matches.x, matches.y);
|
|
2533
2725
|
}
|
|
2534
|
-
applySnapMatchesToTarget(target, matches) {
|
|
2535
|
-
var _a, _b, _c, _d;
|
|
2536
|
-
if (!this.canvasService || !target) return;
|
|
2537
|
-
const deltaX = (_b = (_a = matches.x) == null ? void 0 : _a.deltaScene) != null ? _b : 0;
|
|
2538
|
-
const deltaY = (_d = (_c = matches.y) == null ? void 0 : _c.deltaScene) != null ? _d : 0;
|
|
2539
|
-
if (!deltaX && !deltaY) return;
|
|
2540
|
-
target.set({
|
|
2541
|
-
left: Number(target.left || 0) + this.canvasService.toScreenLength(deltaX),
|
|
2542
|
-
top: Number(target.top || 0) + this.canvasService.toScreenLength(deltaY)
|
|
2543
|
-
});
|
|
2544
|
-
target.setCoords();
|
|
2545
|
-
}
|
|
2546
2726
|
syncToolActiveFromWorkbench(fallbackId) {
|
|
2547
2727
|
var _a;
|
|
2548
2728
|
const wb = (_a = this.context) == null ? void 0 : _a.services.get("WorkbenchService");
|
|
@@ -3166,33 +3346,9 @@ var ImageTool = class {
|
|
|
3166
3346
|
originY: "top",
|
|
3167
3347
|
fill: hatchFill,
|
|
3168
3348
|
opacity: patternFill ? 1 : 0.8,
|
|
3169
|
-
stroke: null,
|
|
3170
|
-
fillRule: "evenodd",
|
|
3171
|
-
selectable: false,
|
|
3172
|
-
evented: false,
|
|
3173
|
-
excludeFromExport: true,
|
|
3174
|
-
objectCaching: false
|
|
3175
|
-
}
|
|
3176
|
-
},
|
|
3177
|
-
{
|
|
3178
|
-
id: "image.cropShapePath",
|
|
3179
|
-
type: "path",
|
|
3180
|
-
data: { id: "image.cropShapePath", zIndex: 6 },
|
|
3181
|
-
layout: {
|
|
3182
|
-
reference: "custom",
|
|
3183
|
-
referenceRect: frameRect,
|
|
3184
|
-
alignX: "start",
|
|
3185
|
-
alignY: "start",
|
|
3186
|
-
offsetX: shapeBounds.x,
|
|
3187
|
-
offsetY: shapeBounds.y
|
|
3188
|
-
},
|
|
3189
|
-
props: {
|
|
3190
|
-
pathData: shapePathData,
|
|
3191
|
-
originX: "left",
|
|
3192
|
-
originY: "top",
|
|
3193
|
-
fill: "rgba(0,0,0,0)",
|
|
3194
3349
|
stroke: "rgba(255, 0, 0, 0.9)",
|
|
3195
3350
|
strokeWidth: (_b = (_a = this.canvasService) == null ? void 0 : _a.toSceneLength(1)) != null ? _b : 1,
|
|
3351
|
+
fillRule: "evenodd",
|
|
3196
3352
|
selectable: false,
|
|
3197
3353
|
evented: false,
|
|
3198
3354
|
excludeFromExport: true,
|
|
@@ -3529,7 +3685,6 @@ var ImageTool = class {
|
|
|
3529
3685
|
isImageSelectionActive: this.isImageSelectionActive,
|
|
3530
3686
|
focusedImageId: this.focusedImageId
|
|
3531
3687
|
});
|
|
3532
|
-
this.updateSnapGuideVisuals();
|
|
3533
3688
|
this.canvasService.requestRenderAll();
|
|
3534
3689
|
}
|
|
3535
3690
|
clampNormalized(value) {
|
|
@@ -4330,225 +4485,668 @@ function createDielineConfigurations(state) {
|
|
|
4330
4485
|
];
|
|
4331
4486
|
}
|
|
4332
4487
|
|
|
4333
|
-
// src/extensions/dieline/
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
this.renderSeq = 0;
|
|
4367
|
-
this.onCanvasResized = () => {
|
|
4368
|
-
this.updateDieline();
|
|
4369
|
-
};
|
|
4370
|
-
if (options) {
|
|
4371
|
-
if (options.mainLine) {
|
|
4372
|
-
Object.assign(this.state.mainLine, options.mainLine);
|
|
4373
|
-
delete options.mainLine;
|
|
4374
|
-
}
|
|
4375
|
-
if (options.offsetLine) {
|
|
4376
|
-
Object.assign(this.state.offsetLine, options.offsetLine);
|
|
4377
|
-
delete options.offsetLine;
|
|
4378
|
-
}
|
|
4379
|
-
if (options.shapeStyle) {
|
|
4380
|
-
this.state.shapeStyle = normalizeShapeStyle(
|
|
4381
|
-
options.shapeStyle,
|
|
4382
|
-
this.state.shapeStyle
|
|
4383
|
-
);
|
|
4384
|
-
delete options.shapeStyle;
|
|
4385
|
-
}
|
|
4386
|
-
Object.assign(this.state, options);
|
|
4387
|
-
this.state.shape = normalizeDielineShape(options.shape, this.state.shape);
|
|
4488
|
+
// src/extensions/dieline/model.ts
|
|
4489
|
+
function createDefaultDielineState() {
|
|
4490
|
+
return {
|
|
4491
|
+
shape: DEFAULT_DIELINE_SHAPE,
|
|
4492
|
+
shapeStyle: { ...DEFAULT_DIELINE_SHAPE_STYLE },
|
|
4493
|
+
width: 500,
|
|
4494
|
+
height: 500,
|
|
4495
|
+
radius: 0,
|
|
4496
|
+
offset: 0,
|
|
4497
|
+
padding: 140,
|
|
4498
|
+
mainLine: {
|
|
4499
|
+
width: 2.7,
|
|
4500
|
+
color: "#FF0000",
|
|
4501
|
+
dashLength: 5,
|
|
4502
|
+
style: "solid"
|
|
4503
|
+
},
|
|
4504
|
+
offsetLine: {
|
|
4505
|
+
width: 2.7,
|
|
4506
|
+
color: "#FF0000",
|
|
4507
|
+
dashLength: 5,
|
|
4508
|
+
style: "solid"
|
|
4509
|
+
},
|
|
4510
|
+
insideColor: "rgba(0,0,0,0)",
|
|
4511
|
+
showBleedLines: true,
|
|
4512
|
+
features: []
|
|
4513
|
+
};
|
|
4514
|
+
}
|
|
4515
|
+
function readDielineState(configService, fallback) {
|
|
4516
|
+
const base = createDefaultDielineState();
|
|
4517
|
+
if (fallback) {
|
|
4518
|
+
Object.assign(base, fallback);
|
|
4519
|
+
if (fallback.mainLine) {
|
|
4520
|
+
base.mainLine = { ...base.mainLine, ...fallback.mainLine };
|
|
4388
4521
|
}
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
var _a;
|
|
4392
|
-
this.context = context;
|
|
4393
|
-
this.canvasService = context.services.get("CanvasService");
|
|
4394
|
-
if (!this.canvasService) {
|
|
4395
|
-
console.warn("CanvasService not found for DielineTool");
|
|
4396
|
-
return;
|
|
4522
|
+
if (fallback.offsetLine) {
|
|
4523
|
+
base.offsetLine = { ...base.offsetLine, ...fallback.offsetLine };
|
|
4397
4524
|
}
|
|
4398
|
-
(
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
"
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
const s = this.state;
|
|
4427
|
-
const sizeState = readSizeState(configService);
|
|
4428
|
-
s.shape = normalizeDielineShape(
|
|
4429
|
-
configService.get("dieline.shape", s.shape),
|
|
4430
|
-
s.shape
|
|
4431
|
-
);
|
|
4432
|
-
s.shapeStyle = normalizeShapeStyle(
|
|
4433
|
-
configService.get("dieline.shapeStyle", s.shapeStyle),
|
|
4434
|
-
s.shapeStyle
|
|
4435
|
-
);
|
|
4436
|
-
s.width = sizeState.actualWidthMm;
|
|
4437
|
-
s.height = sizeState.actualHeightMm;
|
|
4438
|
-
s.radius = parseLengthToMm(
|
|
4439
|
-
configService.get("dieline.radius", s.radius),
|
|
4440
|
-
"mm"
|
|
4441
|
-
);
|
|
4442
|
-
s.padding = sizeState.viewPadding;
|
|
4443
|
-
s.offset = sizeState.cutMode === "outset" ? sizeState.cutMarginMm : sizeState.cutMode === "inset" ? -sizeState.cutMarginMm : 0;
|
|
4444
|
-
s.mainLine.width = configService.get(
|
|
4445
|
-
"dieline.strokeWidth",
|
|
4446
|
-
s.mainLine.width
|
|
4447
|
-
);
|
|
4448
|
-
s.mainLine.color = configService.get(
|
|
4449
|
-
"dieline.strokeColor",
|
|
4450
|
-
s.mainLine.color
|
|
4451
|
-
);
|
|
4452
|
-
s.mainLine.dashLength = configService.get(
|
|
4525
|
+
if (fallback.shapeStyle) {
|
|
4526
|
+
base.shapeStyle = normalizeShapeStyle(fallback.shapeStyle, base.shapeStyle);
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
const sizeState = readSizeState(configService);
|
|
4530
|
+
const sourceWidth = Number(configService.get("dieline.customSourceWidthPx", 0));
|
|
4531
|
+
const sourceHeight = Number(
|
|
4532
|
+
configService.get("dieline.customSourceHeightPx", 0)
|
|
4533
|
+
);
|
|
4534
|
+
return {
|
|
4535
|
+
...base,
|
|
4536
|
+
shape: normalizeDielineShape(
|
|
4537
|
+
configService.get("dieline.shape", base.shape),
|
|
4538
|
+
base.shape
|
|
4539
|
+
),
|
|
4540
|
+
shapeStyle: normalizeShapeStyle(
|
|
4541
|
+
configService.get("dieline.shapeStyle", base.shapeStyle),
|
|
4542
|
+
base.shapeStyle
|
|
4543
|
+
),
|
|
4544
|
+
width: sizeState.actualWidthMm,
|
|
4545
|
+
height: sizeState.actualHeightMm,
|
|
4546
|
+
radius: parseLengthToMm(configService.get("dieline.radius", base.radius), "mm"),
|
|
4547
|
+
padding: sizeState.viewPadding,
|
|
4548
|
+
offset: sizeState.cutMode === "outset" ? sizeState.cutMarginMm : sizeState.cutMode === "inset" ? -sizeState.cutMarginMm : 0,
|
|
4549
|
+
mainLine: {
|
|
4550
|
+
width: configService.get("dieline.strokeWidth", base.mainLine.width),
|
|
4551
|
+
color: configService.get("dieline.strokeColor", base.mainLine.color),
|
|
4552
|
+
dashLength: configService.get(
|
|
4453
4553
|
"dieline.dashLength",
|
|
4454
|
-
|
|
4455
|
-
)
|
|
4456
|
-
|
|
4457
|
-
|
|
4554
|
+
base.mainLine.dashLength
|
|
4555
|
+
),
|
|
4556
|
+
style: configService.get("dieline.style", base.mainLine.style)
|
|
4557
|
+
},
|
|
4558
|
+
offsetLine: {
|
|
4559
|
+
width: configService.get(
|
|
4458
4560
|
"dieline.offsetStrokeWidth",
|
|
4459
|
-
|
|
4460
|
-
)
|
|
4461
|
-
|
|
4561
|
+
base.offsetLine.width
|
|
4562
|
+
),
|
|
4563
|
+
color: configService.get(
|
|
4462
4564
|
"dieline.offsetStrokeColor",
|
|
4463
|
-
|
|
4464
|
-
)
|
|
4465
|
-
|
|
4565
|
+
base.offsetLine.color
|
|
4566
|
+
),
|
|
4567
|
+
dashLength: configService.get(
|
|
4466
4568
|
"dieline.offsetDashLength",
|
|
4467
|
-
|
|
4468
|
-
)
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4569
|
+
base.offsetLine.dashLength
|
|
4570
|
+
),
|
|
4571
|
+
style: configService.get("dieline.offsetStyle", base.offsetLine.style)
|
|
4572
|
+
},
|
|
4573
|
+
insideColor: configService.get("dieline.insideColor", base.insideColor),
|
|
4574
|
+
showBleedLines: configService.get(
|
|
4575
|
+
"dieline.showBleedLines",
|
|
4576
|
+
base.showBleedLines
|
|
4577
|
+
),
|
|
4578
|
+
features: configService.get("dieline.features", base.features),
|
|
4579
|
+
pathData: configService.get("dieline.pathData", base.pathData),
|
|
4580
|
+
customSourceWidthPx: Number.isFinite(sourceWidth) && sourceWidth > 0 ? sourceWidth : void 0,
|
|
4581
|
+
customSourceHeightPx: Number.isFinite(sourceHeight) && sourceHeight > 0 ? sourceHeight : void 0
|
|
4582
|
+
};
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
// src/extensions/constraints.ts
|
|
4586
|
+
var ConstraintRegistry = class {
|
|
4587
|
+
static register(type, handler) {
|
|
4588
|
+
this.handlers.set(type, handler);
|
|
4589
|
+
}
|
|
4590
|
+
static apply(x, y, feature, context, constraints) {
|
|
4591
|
+
const list = constraints || feature.constraints;
|
|
4592
|
+
if (!list || list.length === 0) {
|
|
4593
|
+
return { x, y };
|
|
4594
|
+
}
|
|
4595
|
+
let currentX = x;
|
|
4596
|
+
let currentY = y;
|
|
4597
|
+
for (const constraint of list) {
|
|
4598
|
+
const handler = this.handlers.get(constraint.type);
|
|
4599
|
+
if (handler) {
|
|
4600
|
+
const result = handler(currentX, currentY, feature, context, constraint.params || {});
|
|
4601
|
+
currentX = result.x;
|
|
4602
|
+
currentY = result.y;
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
return { x: currentX, y: currentY };
|
|
4606
|
+
}
|
|
4607
|
+
};
|
|
4608
|
+
ConstraintRegistry.handlers = /* @__PURE__ */ new Map();
|
|
4609
|
+
var pathConstraint = (x, y, feature, context, params) => {
|
|
4610
|
+
const { dielineWidth, dielineHeight, geometry } = context;
|
|
4611
|
+
if (!geometry) return { x, y };
|
|
4612
|
+
const minX = geometry.x - geometry.width / 2;
|
|
4613
|
+
const minY = geometry.y - geometry.height / 2;
|
|
4614
|
+
const absX = minX + x * geometry.width;
|
|
4615
|
+
const absY = minY + y * geometry.height;
|
|
4616
|
+
const nearest = getNearestPointOnDieline(
|
|
4617
|
+
{ x: absX, y: absY },
|
|
4618
|
+
geometry
|
|
4619
|
+
);
|
|
4620
|
+
let finalX = nearest.x;
|
|
4621
|
+
let finalY = nearest.y;
|
|
4622
|
+
const hasOffsetParams = params.minOffset !== void 0 || params.maxOffset !== void 0;
|
|
4623
|
+
if (hasOffsetParams && nearest.normal) {
|
|
4624
|
+
const dx = absX - nearest.x;
|
|
4625
|
+
const dy = absY - nearest.y;
|
|
4626
|
+
const nx2 = nearest.normal.x;
|
|
4627
|
+
const ny2 = nearest.normal.y;
|
|
4628
|
+
const dist = dx * nx2 + dy * ny2;
|
|
4629
|
+
const scale = dielineWidth > 0 ? geometry.width / dielineWidth : 1;
|
|
4630
|
+
const rawMin = params.minOffset !== void 0 ? params.minOffset : 0;
|
|
4631
|
+
const rawMax = params.maxOffset !== void 0 ? params.maxOffset : 0;
|
|
4632
|
+
const minOffset = rawMin * scale;
|
|
4633
|
+
const maxOffset = rawMax * scale;
|
|
4634
|
+
const clampedDist = Math.max(minOffset, Math.min(dist, maxOffset));
|
|
4635
|
+
finalX = nearest.x + nx2 * clampedDist;
|
|
4636
|
+
finalY = nearest.y + ny2 * clampedDist;
|
|
4637
|
+
}
|
|
4638
|
+
const nx = geometry.width > 0 ? (finalX - minX) / geometry.width : 0.5;
|
|
4639
|
+
const ny = geometry.height > 0 ? (finalY - minY) / geometry.height : 0.5;
|
|
4640
|
+
return { x: nx, y: ny };
|
|
4641
|
+
};
|
|
4642
|
+
var edgeConstraint = (x, y, feature, context, params) => {
|
|
4643
|
+
const { dielineWidth, dielineHeight } = context;
|
|
4644
|
+
const allowedEdges = params.allowedEdges || [
|
|
4645
|
+
"top",
|
|
4646
|
+
"bottom",
|
|
4647
|
+
"left",
|
|
4648
|
+
"right"
|
|
4649
|
+
];
|
|
4650
|
+
const confine = params.confine || false;
|
|
4651
|
+
const offset = params.offset || 0;
|
|
4652
|
+
const distances = [];
|
|
4653
|
+
if (allowedEdges.includes("top"))
|
|
4654
|
+
distances.push({ edge: "top", dist: y * dielineHeight });
|
|
4655
|
+
if (allowedEdges.includes("bottom"))
|
|
4656
|
+
distances.push({ edge: "bottom", dist: (1 - y) * dielineHeight });
|
|
4657
|
+
if (allowedEdges.includes("left"))
|
|
4658
|
+
distances.push({ edge: "left", dist: x * dielineWidth });
|
|
4659
|
+
if (allowedEdges.includes("right"))
|
|
4660
|
+
distances.push({ edge: "right", dist: (1 - x) * dielineWidth });
|
|
4661
|
+
if (distances.length === 0) return { x, y };
|
|
4662
|
+
distances.sort((a, b) => a.dist - b.dist);
|
|
4663
|
+
const nearest = distances[0].edge;
|
|
4664
|
+
let newX = x;
|
|
4665
|
+
let newY = y;
|
|
4666
|
+
const fw = feature.width || 0;
|
|
4667
|
+
const fh = feature.height || 0;
|
|
4668
|
+
switch (nearest) {
|
|
4669
|
+
case "top":
|
|
4670
|
+
newY = 0 + offset / dielineHeight;
|
|
4671
|
+
if (confine) {
|
|
4672
|
+
const minX = fw / 2 / dielineWidth;
|
|
4673
|
+
const maxX = 1 - minX;
|
|
4674
|
+
newX = Math.max(minX, Math.min(newX, maxX));
|
|
4675
|
+
}
|
|
4676
|
+
break;
|
|
4677
|
+
case "bottom":
|
|
4678
|
+
newY = 1 - offset / dielineHeight;
|
|
4679
|
+
if (confine) {
|
|
4680
|
+
const minX = fw / 2 / dielineWidth;
|
|
4681
|
+
const maxX = 1 - minX;
|
|
4682
|
+
newX = Math.max(minX, Math.min(newX, maxX));
|
|
4683
|
+
}
|
|
4684
|
+
break;
|
|
4685
|
+
case "left":
|
|
4686
|
+
newX = 0 + offset / dielineWidth;
|
|
4687
|
+
if (confine) {
|
|
4688
|
+
const minY = fh / 2 / dielineHeight;
|
|
4689
|
+
const maxY = 1 - minY;
|
|
4690
|
+
newY = Math.max(minY, Math.min(newY, maxY));
|
|
4691
|
+
}
|
|
4692
|
+
break;
|
|
4693
|
+
case "right":
|
|
4694
|
+
newX = 1 - offset / dielineWidth;
|
|
4695
|
+
if (confine) {
|
|
4696
|
+
const minY = fh / 2 / dielineHeight;
|
|
4697
|
+
const maxY = 1 - minY;
|
|
4698
|
+
newY = Math.max(minY, Math.min(newY, maxY));
|
|
4699
|
+
}
|
|
4700
|
+
break;
|
|
4701
|
+
}
|
|
4702
|
+
return { x: newX, y: newY };
|
|
4703
|
+
};
|
|
4704
|
+
var internalConstraint = (x, y, feature, context, params) => {
|
|
4705
|
+
const { dielineWidth, dielineHeight } = context;
|
|
4706
|
+
const margin = params.margin || 0;
|
|
4707
|
+
const fw = feature.width || 0;
|
|
4708
|
+
const fh = feature.height || 0;
|
|
4709
|
+
const minX = (margin + fw / 2) / dielineWidth;
|
|
4710
|
+
const maxX = 1 - (margin + fw / 2) / dielineWidth;
|
|
4711
|
+
const minY = (margin + fh / 2) / dielineHeight;
|
|
4712
|
+
const maxY = 1 - (margin + fh / 2) / dielineHeight;
|
|
4713
|
+
const clampedX = minX > maxX ? 0.5 : Math.max(minX, Math.min(x, maxX));
|
|
4714
|
+
const clampedY = minY > maxY ? 0.5 : Math.max(minY, Math.min(y, maxY));
|
|
4715
|
+
return { x: clampedX, y: clampedY };
|
|
4716
|
+
};
|
|
4717
|
+
var tangentBottomConstraint = (x, y, feature, context, params) => {
|
|
4718
|
+
const { dielineWidth, dielineHeight } = context;
|
|
4719
|
+
const gap = params.gap || 0;
|
|
4720
|
+
const confineX = params.confineX !== false;
|
|
4721
|
+
const extentY = feature.shape === "circle" ? feature.radius || 0 : (feature.height || 0) / 2;
|
|
4722
|
+
const newY = 1 + (extentY + gap) / dielineHeight;
|
|
4723
|
+
let newX = x;
|
|
4724
|
+
if (confineX) {
|
|
4725
|
+
const extentX = feature.shape === "circle" ? feature.radius || 0 : (feature.width || 0) / 2;
|
|
4726
|
+
const minX = extentX / dielineWidth;
|
|
4727
|
+
const maxX = 1 - extentX / dielineWidth;
|
|
4728
|
+
newX = minX > maxX ? 0.5 : Math.max(minX, Math.min(newX, maxX));
|
|
4729
|
+
}
|
|
4730
|
+
return { x: newX, y: newY };
|
|
4731
|
+
};
|
|
4732
|
+
var lowestTangentConstraint = (x, y, feature, context, params) => {
|
|
4733
|
+
const { dielineWidth, dielineHeight, geometry } = context;
|
|
4734
|
+
if (!geometry) return { x, y };
|
|
4735
|
+
const lowest = getLowestPointOnDieline(geometry);
|
|
4736
|
+
const minY = geometry.y - geometry.height / 2;
|
|
4737
|
+
const normY = (lowest.y - minY) / geometry.height;
|
|
4738
|
+
const gap = params.gap || 0;
|
|
4739
|
+
const confineX = params.confineX !== false;
|
|
4740
|
+
const extentY = feature.shape === "circle" ? feature.radius || 0 : (feature.height || 0) / 2;
|
|
4741
|
+
const newY = normY + (extentY + gap) / dielineHeight;
|
|
4742
|
+
let newX = x;
|
|
4743
|
+
if (confineX) {
|
|
4744
|
+
const extentX = feature.shape === "circle" ? feature.radius || 0 : (feature.width || 0) / 2;
|
|
4745
|
+
const minX = extentX / dielineWidth;
|
|
4746
|
+
const maxX = 1 - extentX / dielineWidth;
|
|
4747
|
+
newX = minX > maxX ? 0.5 : Math.max(minX, Math.min(newX, maxX));
|
|
4748
|
+
}
|
|
4749
|
+
return { x: newX, y: newY };
|
|
4750
|
+
};
|
|
4751
|
+
ConstraintRegistry.register("path", pathConstraint);
|
|
4752
|
+
ConstraintRegistry.register("edge", edgeConstraint);
|
|
4753
|
+
ConstraintRegistry.register("internal", internalConstraint);
|
|
4754
|
+
ConstraintRegistry.register("tangent-bottom", tangentBottomConstraint);
|
|
4755
|
+
ConstraintRegistry.register("lowest-tangent", lowestTangentConstraint);
|
|
4756
|
+
|
|
4757
|
+
// src/extensions/featureCoordinates.ts
|
|
4758
|
+
function resolveFeaturePosition2(feature, geometry) {
|
|
4759
|
+
const { x, y, width, height } = geometry;
|
|
4760
|
+
const left = x - width / 2;
|
|
4761
|
+
const top = y - height / 2;
|
|
4762
|
+
return {
|
|
4763
|
+
x: left + feature.x * width,
|
|
4764
|
+
y: top + feature.y * height
|
|
4765
|
+
};
|
|
4766
|
+
}
|
|
4767
|
+
function normalizePointInGeometry(point, geometry) {
|
|
4768
|
+
const left = geometry.x - geometry.width / 2;
|
|
4769
|
+
const top = geometry.y - geometry.height / 2;
|
|
4770
|
+
return {
|
|
4771
|
+
x: geometry.width > 0 ? (point.x - left) / geometry.width : 0.5,
|
|
4772
|
+
y: geometry.height > 0 ? (point.y - top) / geometry.height : 0.5
|
|
4773
|
+
};
|
|
4774
|
+
}
|
|
4775
|
+
|
|
4776
|
+
// src/extensions/featurePlacement.ts
|
|
4777
|
+
function scaleFeatureForRender(feature, scale, x, y) {
|
|
4778
|
+
return {
|
|
4779
|
+
...feature,
|
|
4780
|
+
x,
|
|
4781
|
+
y,
|
|
4782
|
+
width: feature.width !== void 0 ? feature.width * scale : void 0,
|
|
4783
|
+
height: feature.height !== void 0 ? feature.height * scale : void 0,
|
|
4784
|
+
radius: feature.radius !== void 0 ? feature.radius * scale : void 0
|
|
4785
|
+
};
|
|
4786
|
+
}
|
|
4787
|
+
function resolveFeaturePlacements(features, geometry) {
|
|
4788
|
+
const dielineWidth = geometry.scale > 0 ? geometry.width / geometry.scale : geometry.width;
|
|
4789
|
+
const dielineHeight = geometry.scale > 0 ? geometry.height / geometry.scale : geometry.height;
|
|
4790
|
+
return (features || []).map((feature) => {
|
|
4791
|
+
var _a;
|
|
4792
|
+
const activeConstraints = (_a = feature.constraints) == null ? void 0 : _a.filter(
|
|
4793
|
+
(constraint) => !constraint.validateOnly
|
|
4794
|
+
);
|
|
4795
|
+
const constrained = ConstraintRegistry.apply(
|
|
4796
|
+
feature.x,
|
|
4797
|
+
feature.y,
|
|
4798
|
+
feature,
|
|
4799
|
+
{
|
|
4800
|
+
dielineWidth,
|
|
4801
|
+
dielineHeight,
|
|
4802
|
+
geometry
|
|
4803
|
+
},
|
|
4804
|
+
activeConstraints
|
|
4805
|
+
);
|
|
4806
|
+
const center = resolveFeaturePosition2(
|
|
4807
|
+
{
|
|
4808
|
+
...feature,
|
|
4809
|
+
x: constrained.x,
|
|
4810
|
+
y: constrained.y
|
|
4811
|
+
},
|
|
4812
|
+
geometry
|
|
4813
|
+
);
|
|
4814
|
+
return {
|
|
4815
|
+
feature,
|
|
4816
|
+
normalizedX: constrained.x,
|
|
4817
|
+
normalizedY: constrained.y,
|
|
4818
|
+
centerX: center.x,
|
|
4819
|
+
centerY: center.y
|
|
4820
|
+
};
|
|
4821
|
+
});
|
|
4822
|
+
}
|
|
4823
|
+
function projectPlacedFeatures(placements, geometry, scale) {
|
|
4824
|
+
return placements.map((placement) => {
|
|
4825
|
+
const normalized = normalizePointInGeometry(
|
|
4826
|
+
{ x: placement.centerX, y: placement.centerY },
|
|
4827
|
+
geometry
|
|
4828
|
+
);
|
|
4829
|
+
return scaleFeatureForRender(
|
|
4830
|
+
placement.feature,
|
|
4831
|
+
scale,
|
|
4832
|
+
normalized.x,
|
|
4833
|
+
normalized.y
|
|
4834
|
+
);
|
|
4835
|
+
});
|
|
4836
|
+
}
|
|
4837
|
+
|
|
4838
|
+
// src/extensions/dieline/renderBuilder.ts
|
|
4839
|
+
var DEFAULT_IDS = {
|
|
4840
|
+
inside: "dieline.inside",
|
|
4841
|
+
bleedZone: "dieline.bleed-zone",
|
|
4842
|
+
offsetBorder: "dieline.offset-border",
|
|
4843
|
+
border: "dieline.border",
|
|
4844
|
+
clip: "dieline.clip.image",
|
|
4845
|
+
clipSource: "dieline.effect.clip-path"
|
|
4846
|
+
};
|
|
4847
|
+
function buildDielineRenderBundle(options) {
|
|
4848
|
+
const ids = { ...DEFAULT_IDS, ...options.ids || {} };
|
|
4849
|
+
const {
|
|
4850
|
+
state,
|
|
4851
|
+
sceneLayout,
|
|
4852
|
+
canvasWidth,
|
|
4853
|
+
canvasHeight,
|
|
4854
|
+
hasImages,
|
|
4855
|
+
createHatchPattern,
|
|
4856
|
+
includeImageClipEffect = true,
|
|
4857
|
+
clipTargetPassIds = [IMAGE_OBJECT_LAYER_ID],
|
|
4858
|
+
clipVisibility
|
|
4859
|
+
} = options;
|
|
4860
|
+
const { shape, shapeStyle, radius, mainLine, offsetLine, insideColor } = state;
|
|
4861
|
+
const scale = sceneLayout.scale;
|
|
4862
|
+
const cx = sceneLayout.trimRect.centerX;
|
|
4863
|
+
const cy = sceneLayout.trimRect.centerY;
|
|
4864
|
+
const visualWidth = sceneLayout.trimRect.width;
|
|
4865
|
+
const visualHeight = sceneLayout.trimRect.height;
|
|
4866
|
+
const visualRadius = radius * scale;
|
|
4867
|
+
const cutW = sceneLayout.cutRect.width;
|
|
4868
|
+
const cutH = sceneLayout.cutRect.height;
|
|
4869
|
+
const visualOffset = (cutW - visualWidth) / 2;
|
|
4870
|
+
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
4871
|
+
const placements = resolveFeaturePlacements(state.features || [], {
|
|
4872
|
+
shape,
|
|
4873
|
+
shapeStyle,
|
|
4874
|
+
pathData: state.pathData,
|
|
4875
|
+
customSourceWidthPx: state.customSourceWidthPx,
|
|
4876
|
+
customSourceHeightPx: state.customSourceHeightPx,
|
|
4877
|
+
canvasWidth,
|
|
4878
|
+
canvasHeight,
|
|
4879
|
+
x: cx,
|
|
4880
|
+
y: cy,
|
|
4881
|
+
width: visualWidth,
|
|
4882
|
+
height: visualHeight,
|
|
4883
|
+
radius: visualRadius,
|
|
4884
|
+
scale
|
|
4885
|
+
});
|
|
4886
|
+
const absoluteFeatures = projectPlacedFeatures(
|
|
4887
|
+
placements,
|
|
4888
|
+
{
|
|
4889
|
+
x: cx,
|
|
4890
|
+
y: cy,
|
|
4891
|
+
width: visualWidth,
|
|
4892
|
+
height: visualHeight
|
|
4893
|
+
},
|
|
4894
|
+
scale
|
|
4895
|
+
);
|
|
4896
|
+
const cutFeatures = projectPlacedFeatures(
|
|
4897
|
+
placements.filter((placement) => !placement.feature.skipCut),
|
|
4898
|
+
{
|
|
4899
|
+
x: cx,
|
|
4900
|
+
y: cy,
|
|
4901
|
+
width: cutW,
|
|
4902
|
+
height: cutH
|
|
4903
|
+
},
|
|
4904
|
+
scale
|
|
4905
|
+
);
|
|
4906
|
+
const common = {
|
|
4907
|
+
shape,
|
|
4908
|
+
shapeStyle,
|
|
4909
|
+
pathData: state.pathData,
|
|
4910
|
+
customSourceWidthPx: state.customSourceWidthPx,
|
|
4911
|
+
customSourceHeightPx: state.customSourceHeightPx,
|
|
4912
|
+
canvasWidth,
|
|
4913
|
+
canvasHeight
|
|
4914
|
+
};
|
|
4915
|
+
const specs = [];
|
|
4916
|
+
if (insideColor && insideColor !== "transparent" && insideColor !== "rgba(0,0,0,0)" && !hasImages) {
|
|
4917
|
+
specs.push({
|
|
4918
|
+
id: ids.inside,
|
|
4919
|
+
type: "path",
|
|
4920
|
+
space: "screen",
|
|
4921
|
+
data: { id: ids.inside, type: "dieline" },
|
|
4922
|
+
props: {
|
|
4923
|
+
pathData: generateDielinePath({
|
|
4924
|
+
...common,
|
|
4925
|
+
width: cutW,
|
|
4926
|
+
height: cutH,
|
|
4927
|
+
radius: cutR,
|
|
4928
|
+
x: cx,
|
|
4929
|
+
y: cy,
|
|
4930
|
+
features: cutFeatures
|
|
4931
|
+
}),
|
|
4932
|
+
fill: insideColor,
|
|
4933
|
+
stroke: null,
|
|
4934
|
+
selectable: false,
|
|
4935
|
+
evented: false,
|
|
4936
|
+
originX: "left",
|
|
4937
|
+
originY: "top"
|
|
4938
|
+
}
|
|
4939
|
+
});
|
|
4940
|
+
}
|
|
4941
|
+
if (Math.abs(visualOffset) > 1e-4) {
|
|
4942
|
+
const trimPathInput = {
|
|
4943
|
+
...common,
|
|
4944
|
+
width: visualWidth,
|
|
4945
|
+
height: visualHeight,
|
|
4946
|
+
radius: visualRadius,
|
|
4947
|
+
x: cx,
|
|
4948
|
+
y: cy,
|
|
4949
|
+
features: cutFeatures
|
|
4950
|
+
};
|
|
4951
|
+
const cutPathInput = {
|
|
4952
|
+
...common,
|
|
4953
|
+
width: cutW,
|
|
4954
|
+
height: cutH,
|
|
4955
|
+
radius: cutR,
|
|
4956
|
+
x: cx,
|
|
4957
|
+
y: cy,
|
|
4958
|
+
features: cutFeatures
|
|
4959
|
+
};
|
|
4960
|
+
if (state.showBleedLines !== false) {
|
|
4961
|
+
const pattern = createHatchPattern == null ? void 0 : createHatchPattern(mainLine.color);
|
|
4962
|
+
if (pattern) {
|
|
4963
|
+
specs.push({
|
|
4964
|
+
id: ids.bleedZone,
|
|
4965
|
+
type: "path",
|
|
4966
|
+
space: "screen",
|
|
4967
|
+
data: { id: ids.bleedZone, type: "dieline" },
|
|
4968
|
+
props: {
|
|
4969
|
+
pathData: generateBleedZonePath(
|
|
4970
|
+
trimPathInput,
|
|
4971
|
+
cutPathInput,
|
|
4972
|
+
visualOffset
|
|
4973
|
+
),
|
|
4974
|
+
fill: pattern,
|
|
4975
|
+
stroke: null,
|
|
4976
|
+
selectable: false,
|
|
4977
|
+
evented: false,
|
|
4978
|
+
objectCaching: false,
|
|
4979
|
+
originX: "left",
|
|
4980
|
+
originY: "top"
|
|
4981
|
+
}
|
|
4982
|
+
});
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
specs.push({
|
|
4986
|
+
id: ids.offsetBorder,
|
|
4987
|
+
type: "path",
|
|
4988
|
+
space: "screen",
|
|
4989
|
+
data: { id: ids.offsetBorder, type: "dieline" },
|
|
4990
|
+
props: {
|
|
4991
|
+
pathData: generateDielinePath(cutPathInput),
|
|
4992
|
+
fill: null,
|
|
4993
|
+
stroke: offsetLine.style === "hidden" ? null : offsetLine.color,
|
|
4994
|
+
strokeWidth: offsetLine.width,
|
|
4995
|
+
strokeDashArray: offsetLine.style === "dashed" ? [offsetLine.dashLength, offsetLine.dashLength] : void 0,
|
|
4996
|
+
selectable: false,
|
|
4997
|
+
evented: false,
|
|
4998
|
+
originX: "left",
|
|
4999
|
+
originY: "top"
|
|
5000
|
+
}
|
|
5001
|
+
});
|
|
5002
|
+
}
|
|
5003
|
+
specs.push({
|
|
5004
|
+
id: ids.border,
|
|
5005
|
+
type: "path",
|
|
5006
|
+
space: "screen",
|
|
5007
|
+
data: { id: ids.border, type: "dieline" },
|
|
5008
|
+
props: {
|
|
5009
|
+
pathData: generateDielinePath({
|
|
5010
|
+
...common,
|
|
5011
|
+
width: visualWidth,
|
|
5012
|
+
height: visualHeight,
|
|
5013
|
+
radius: visualRadius,
|
|
5014
|
+
x: cx,
|
|
5015
|
+
y: cy,
|
|
5016
|
+
features: absoluteFeatures
|
|
5017
|
+
}),
|
|
5018
|
+
fill: "transparent",
|
|
5019
|
+
stroke: mainLine.style === "hidden" ? null : mainLine.color,
|
|
5020
|
+
strokeWidth: mainLine.width,
|
|
5021
|
+
strokeDashArray: mainLine.style === "dashed" ? [mainLine.dashLength, mainLine.dashLength] : void 0,
|
|
5022
|
+
selectable: false,
|
|
5023
|
+
evented: false,
|
|
5024
|
+
originX: "left",
|
|
5025
|
+
originY: "top"
|
|
5026
|
+
}
|
|
5027
|
+
});
|
|
5028
|
+
if (!includeImageClipEffect) {
|
|
5029
|
+
return { specs, effects: [] };
|
|
5030
|
+
}
|
|
5031
|
+
const clipPathData = generateDielinePath({
|
|
5032
|
+
...common,
|
|
5033
|
+
width: cutW,
|
|
5034
|
+
height: cutH,
|
|
5035
|
+
radius: cutR,
|
|
5036
|
+
x: cx,
|
|
5037
|
+
y: cy,
|
|
5038
|
+
features: cutFeatures
|
|
5039
|
+
});
|
|
5040
|
+
if (!clipPathData) {
|
|
5041
|
+
return { specs, effects: [] };
|
|
5042
|
+
}
|
|
5043
|
+
return {
|
|
5044
|
+
specs,
|
|
5045
|
+
effects: [
|
|
5046
|
+
{
|
|
5047
|
+
type: "clipPath",
|
|
5048
|
+
id: ids.clip,
|
|
5049
|
+
visibility: clipVisibility,
|
|
5050
|
+
targetPassIds: clipTargetPassIds,
|
|
5051
|
+
source: {
|
|
5052
|
+
id: ids.clipSource,
|
|
5053
|
+
type: "path",
|
|
5054
|
+
space: "screen",
|
|
5055
|
+
data: {
|
|
5056
|
+
id: ids.clipSource,
|
|
5057
|
+
type: "dieline-effect",
|
|
5058
|
+
effect: "clipPath"
|
|
5059
|
+
},
|
|
5060
|
+
props: {
|
|
5061
|
+
pathData: clipPathData,
|
|
5062
|
+
fill: "#000000",
|
|
5063
|
+
stroke: null,
|
|
5064
|
+
originX: "left",
|
|
5065
|
+
originY: "top",
|
|
5066
|
+
selectable: false,
|
|
5067
|
+
evented: false,
|
|
5068
|
+
excludeFromExport: true
|
|
5069
|
+
}
|
|
4497
5070
|
}
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
5071
|
+
}
|
|
5072
|
+
]
|
|
5073
|
+
};
|
|
5074
|
+
}
|
|
5075
|
+
|
|
5076
|
+
// src/extensions/dieline/DielineTool.ts
|
|
5077
|
+
var DielineTool = class {
|
|
5078
|
+
constructor(options) {
|
|
5079
|
+
this.id = "pooder.kit.dieline";
|
|
5080
|
+
this.metadata = {
|
|
5081
|
+
name: "DielineTool"
|
|
5082
|
+
};
|
|
5083
|
+
this.state = createDefaultDielineState();
|
|
5084
|
+
this.specs = [];
|
|
5085
|
+
this.effects = [];
|
|
5086
|
+
this.renderSeq = 0;
|
|
5087
|
+
this.onCanvasResized = () => {
|
|
5088
|
+
this.updateDieline();
|
|
5089
|
+
};
|
|
5090
|
+
if (options) {
|
|
5091
|
+
if (options.mainLine) {
|
|
5092
|
+
Object.assign(this.state.mainLine, options.mainLine);
|
|
5093
|
+
delete options.mainLine;
|
|
5094
|
+
}
|
|
5095
|
+
if (options.offsetLine) {
|
|
5096
|
+
Object.assign(this.state.offsetLine, options.offsetLine);
|
|
5097
|
+
delete options.offsetLine;
|
|
5098
|
+
}
|
|
5099
|
+
if (options.shapeStyle) {
|
|
5100
|
+
this.state.shapeStyle = normalizeShapeStyle(
|
|
5101
|
+
options.shapeStyle,
|
|
5102
|
+
this.state.shapeStyle
|
|
5103
|
+
);
|
|
5104
|
+
delete options.shapeStyle;
|
|
5105
|
+
}
|
|
5106
|
+
Object.assign(this.state, options);
|
|
5107
|
+
this.state.shape = normalizeDielineShape(options.shape, this.state.shape);
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
activate(context) {
|
|
5111
|
+
var _a;
|
|
5112
|
+
this.context = context;
|
|
5113
|
+
this.canvasService = context.services.get("CanvasService");
|
|
5114
|
+
if (!this.canvasService) {
|
|
5115
|
+
console.warn("CanvasService not found for DielineTool");
|
|
5116
|
+
return;
|
|
5117
|
+
}
|
|
5118
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5119
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
5120
|
+
this.id,
|
|
5121
|
+
() => ({
|
|
5122
|
+
passes: [
|
|
5123
|
+
{
|
|
5124
|
+
id: DIELINE_LAYER_ID,
|
|
5125
|
+
stack: 700,
|
|
5126
|
+
order: 0,
|
|
5127
|
+
replace: true,
|
|
5128
|
+
visibility: {
|
|
5129
|
+
op: "not",
|
|
5130
|
+
expr: {
|
|
5131
|
+
op: "activeToolIn",
|
|
5132
|
+
ids: ["pooder.kit.image", "pooder.kit.white-ink"]
|
|
5133
|
+
}
|
|
5134
|
+
},
|
|
5135
|
+
effects: this.effects,
|
|
5136
|
+
objects: this.specs
|
|
4551
5137
|
}
|
|
5138
|
+
]
|
|
5139
|
+
}),
|
|
5140
|
+
{ priority: 250 }
|
|
5141
|
+
);
|
|
5142
|
+
const configService = context.services.get(
|
|
5143
|
+
"ConfigurationService"
|
|
5144
|
+
);
|
|
5145
|
+
if (configService) {
|
|
5146
|
+
Object.assign(this.state, readDielineState(configService, this.state));
|
|
5147
|
+
configService.onAnyChange((e) => {
|
|
5148
|
+
if (e.key.startsWith("size.") || e.key.startsWith("dieline.")) {
|
|
5149
|
+
Object.assign(this.state, readDielineState(configService, this.state));
|
|
4552
5150
|
this.updateDieline();
|
|
4553
5151
|
}
|
|
4554
5152
|
});
|
|
@@ -4598,293 +5196,55 @@ var DielineTool = class {
|
|
|
4598
5196
|
const ctx = canvas.getContext("2d");
|
|
4599
5197
|
if (ctx) {
|
|
4600
5198
|
ctx.clearRect(0, 0, size, size);
|
|
4601
|
-
ctx.strokeStyle = color;
|
|
4602
|
-
ctx.lineWidth = 1;
|
|
4603
|
-
ctx.beginPath();
|
|
4604
|
-
ctx.moveTo(0, size);
|
|
4605
|
-
ctx.lineTo(size, 0);
|
|
4606
|
-
ctx.stroke();
|
|
4607
|
-
}
|
|
4608
|
-
return new Pattern2({ source: canvas, repetition: "repeat" });
|
|
4609
|
-
}
|
|
4610
|
-
getConfigService() {
|
|
4611
|
-
var _a;
|
|
4612
|
-
return (_a = this.context) == null ? void 0 : _a.services.get(
|
|
4613
|
-
"ConfigurationService"
|
|
4614
|
-
);
|
|
4615
|
-
}
|
|
4616
|
-
hasImageItems() {
|
|
4617
|
-
const configService = this.getConfigService();
|
|
4618
|
-
if (!configService) return false;
|
|
4619
|
-
const items = configService.get("image.items", []);
|
|
4620
|
-
return Array.isArray(items) && items.length > 0;
|
|
4621
|
-
}
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
const visualHeight = sceneLayout.trimRect.height;
|
|
4649
|
-
const visualRadius = radius * scale;
|
|
4650
|
-
const cutW = sceneLayout.cutRect.width;
|
|
4651
|
-
const cutH = sceneLayout.cutRect.height;
|
|
4652
|
-
const visualOffset = (cutW - visualWidth) / 2;
|
|
4653
|
-
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
4654
|
-
const absoluteFeatures = (features || []).map((f) => ({
|
|
4655
|
-
...f,
|
|
4656
|
-
x: f.x,
|
|
4657
|
-
y: f.y,
|
|
4658
|
-
width: (f.width || 0) * scale,
|
|
4659
|
-
height: (f.height || 0) * scale,
|
|
4660
|
-
radius: (f.radius || 0) * scale
|
|
4661
|
-
}));
|
|
4662
|
-
const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
|
|
4663
|
-
const specs = [];
|
|
4664
|
-
if (insideColor && insideColor !== "transparent" && insideColor !== "rgba(0,0,0,0)" && !hasImages) {
|
|
4665
|
-
const productPathData = generateDielinePath({
|
|
4666
|
-
shape,
|
|
4667
|
-
width: cutW,
|
|
4668
|
-
height: cutH,
|
|
4669
|
-
radius: cutR,
|
|
4670
|
-
x: cx,
|
|
4671
|
-
y: cy,
|
|
4672
|
-
features: cutFeatures,
|
|
4673
|
-
shapeStyle,
|
|
4674
|
-
pathData: this.state.pathData,
|
|
4675
|
-
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4676
|
-
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4677
|
-
canvasWidth: canvasW,
|
|
4678
|
-
canvasHeight: canvasH
|
|
4679
|
-
});
|
|
4680
|
-
specs.push({
|
|
4681
|
-
id: "dieline.inside",
|
|
4682
|
-
type: "path",
|
|
4683
|
-
space: "screen",
|
|
4684
|
-
data: { id: "dieline.inside", type: "dieline" },
|
|
4685
|
-
props: {
|
|
4686
|
-
pathData: productPathData,
|
|
4687
|
-
fill: insideColor,
|
|
4688
|
-
stroke: null,
|
|
4689
|
-
selectable: false,
|
|
4690
|
-
evented: false,
|
|
4691
|
-
originX: "left",
|
|
4692
|
-
originY: "top"
|
|
4693
|
-
}
|
|
4694
|
-
});
|
|
4695
|
-
}
|
|
4696
|
-
if (Math.abs(visualOffset) > 1e-4) {
|
|
4697
|
-
const bleedPathData = generateBleedZonePath(
|
|
4698
|
-
{
|
|
4699
|
-
shape,
|
|
4700
|
-
width: visualWidth,
|
|
4701
|
-
height: visualHeight,
|
|
4702
|
-
radius: visualRadius,
|
|
4703
|
-
x: cx,
|
|
4704
|
-
y: cy,
|
|
4705
|
-
features: cutFeatures,
|
|
4706
|
-
shapeStyle,
|
|
4707
|
-
pathData: this.state.pathData,
|
|
4708
|
-
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4709
|
-
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4710
|
-
canvasWidth: canvasW,
|
|
4711
|
-
canvasHeight: canvasH
|
|
4712
|
-
},
|
|
4713
|
-
{
|
|
4714
|
-
shape,
|
|
4715
|
-
width: cutW,
|
|
4716
|
-
height: cutH,
|
|
4717
|
-
radius: cutR,
|
|
4718
|
-
x: cx,
|
|
4719
|
-
y: cy,
|
|
4720
|
-
features: cutFeatures,
|
|
4721
|
-
shapeStyle,
|
|
4722
|
-
pathData: this.state.pathData,
|
|
4723
|
-
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4724
|
-
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4725
|
-
canvasWidth: canvasW,
|
|
4726
|
-
canvasHeight: canvasH
|
|
4727
|
-
},
|
|
4728
|
-
visualOffset
|
|
4729
|
-
);
|
|
4730
|
-
if (showBleedLines !== false) {
|
|
4731
|
-
const pattern = this.createHatchPattern(mainLine.color);
|
|
4732
|
-
if (pattern) {
|
|
4733
|
-
specs.push({
|
|
4734
|
-
id: "dieline.bleed-zone",
|
|
4735
|
-
type: "path",
|
|
4736
|
-
space: "screen",
|
|
4737
|
-
data: { id: "dieline.bleed-zone", type: "dieline" },
|
|
4738
|
-
props: {
|
|
4739
|
-
pathData: bleedPathData,
|
|
4740
|
-
fill: pattern,
|
|
4741
|
-
stroke: null,
|
|
4742
|
-
selectable: false,
|
|
4743
|
-
evented: false,
|
|
4744
|
-
objectCaching: false,
|
|
4745
|
-
originX: "left",
|
|
4746
|
-
originY: "top"
|
|
4747
|
-
}
|
|
4748
|
-
});
|
|
4749
|
-
}
|
|
4750
|
-
}
|
|
4751
|
-
const offsetPathData = generateDielinePath({
|
|
4752
|
-
shape,
|
|
4753
|
-
width: cutW,
|
|
4754
|
-
height: cutH,
|
|
4755
|
-
radius: cutR,
|
|
4756
|
-
x: cx,
|
|
4757
|
-
y: cy,
|
|
4758
|
-
features: cutFeatures,
|
|
4759
|
-
shapeStyle,
|
|
4760
|
-
pathData: this.state.pathData,
|
|
4761
|
-
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4762
|
-
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4763
|
-
canvasWidth: canvasW,
|
|
4764
|
-
canvasHeight: canvasH
|
|
4765
|
-
});
|
|
4766
|
-
specs.push({
|
|
4767
|
-
id: "dieline.offset-border",
|
|
4768
|
-
type: "path",
|
|
4769
|
-
space: "screen",
|
|
4770
|
-
data: { id: "dieline.offset-border", type: "dieline" },
|
|
4771
|
-
props: {
|
|
4772
|
-
pathData: offsetPathData,
|
|
4773
|
-
fill: null,
|
|
4774
|
-
stroke: offsetLine.style === "hidden" ? null : offsetLine.color,
|
|
4775
|
-
strokeWidth: offsetLine.width,
|
|
4776
|
-
strokeDashArray: offsetLine.style === "dashed" ? [offsetLine.dashLength, offsetLine.dashLength] : void 0,
|
|
4777
|
-
selectable: false,
|
|
4778
|
-
evented: false,
|
|
4779
|
-
originX: "left",
|
|
4780
|
-
originY: "top"
|
|
4781
|
-
}
|
|
4782
|
-
});
|
|
4783
|
-
}
|
|
4784
|
-
const borderPathData = generateDielinePath({
|
|
4785
|
-
shape,
|
|
4786
|
-
width: visualWidth,
|
|
4787
|
-
height: visualHeight,
|
|
4788
|
-
radius: visualRadius,
|
|
4789
|
-
x: cx,
|
|
4790
|
-
y: cy,
|
|
4791
|
-
features: absoluteFeatures,
|
|
4792
|
-
shapeStyle,
|
|
4793
|
-
pathData: this.state.pathData,
|
|
4794
|
-
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4795
|
-
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4796
|
-
canvasWidth: canvasW,
|
|
4797
|
-
canvasHeight: canvasH
|
|
4798
|
-
});
|
|
4799
|
-
specs.push({
|
|
4800
|
-
id: "dieline.border",
|
|
4801
|
-
type: "path",
|
|
4802
|
-
space: "screen",
|
|
4803
|
-
data: { id: "dieline.border", type: "dieline" },
|
|
4804
|
-
props: {
|
|
4805
|
-
pathData: borderPathData,
|
|
4806
|
-
fill: "transparent",
|
|
4807
|
-
stroke: mainLine.style === "hidden" ? null : mainLine.color,
|
|
4808
|
-
strokeWidth: mainLine.width,
|
|
4809
|
-
strokeDashArray: mainLine.style === "dashed" ? [mainLine.dashLength, mainLine.dashLength] : void 0,
|
|
4810
|
-
selectable: false,
|
|
4811
|
-
evented: false,
|
|
4812
|
-
originX: "left",
|
|
4813
|
-
originY: "top"
|
|
4814
|
-
}
|
|
4815
|
-
});
|
|
4816
|
-
return specs;
|
|
4817
|
-
}
|
|
4818
|
-
buildImageClipEffects(sceneLayout) {
|
|
4819
|
-
var _a, _b;
|
|
4820
|
-
const { shape, shapeStyle, radius, features } = this.state;
|
|
4821
|
-
const canvasW = sceneLayout.canvasWidth || ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800;
|
|
4822
|
-
const canvasH = sceneLayout.canvasHeight || ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600;
|
|
4823
|
-
const scale = sceneLayout.scale;
|
|
4824
|
-
const cx = sceneLayout.trimRect.centerX;
|
|
4825
|
-
const cy = sceneLayout.trimRect.centerY;
|
|
4826
|
-
const visualWidth = sceneLayout.trimRect.width;
|
|
4827
|
-
const visualRadius = radius * scale;
|
|
4828
|
-
const cutW = sceneLayout.cutRect.width;
|
|
4829
|
-
const cutH = sceneLayout.cutRect.height;
|
|
4830
|
-
const visualOffset = (cutW - visualWidth) / 2;
|
|
4831
|
-
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
4832
|
-
const absoluteFeatures = (features || []).map((f) => ({
|
|
4833
|
-
...f,
|
|
4834
|
-
x: f.x,
|
|
4835
|
-
y: f.y,
|
|
4836
|
-
width: (f.width || 0) * scale,
|
|
4837
|
-
height: (f.height || 0) * scale,
|
|
4838
|
-
radius: (f.radius || 0) * scale
|
|
4839
|
-
}));
|
|
4840
|
-
const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
|
|
4841
|
-
const clipPathData = generateDielinePath({
|
|
4842
|
-
shape,
|
|
4843
|
-
width: cutW,
|
|
4844
|
-
height: cutH,
|
|
4845
|
-
radius: cutR,
|
|
4846
|
-
x: cx,
|
|
4847
|
-
y: cy,
|
|
4848
|
-
features: cutFeatures,
|
|
4849
|
-
shapeStyle,
|
|
4850
|
-
pathData: this.state.pathData,
|
|
4851
|
-
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4852
|
-
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4853
|
-
canvasWidth: canvasW,
|
|
4854
|
-
canvasHeight: canvasH
|
|
4855
|
-
});
|
|
4856
|
-
if (!clipPathData) return [];
|
|
4857
|
-
return [
|
|
4858
|
-
{
|
|
4859
|
-
type: "clipPath",
|
|
4860
|
-
id: "dieline.clip.image",
|
|
4861
|
-
visibility: {
|
|
4862
|
-
op: "not",
|
|
4863
|
-
expr: { op: "anySessionActive" }
|
|
4864
|
-
},
|
|
4865
|
-
targetPassIds: [IMAGE_OBJECT_LAYER_ID],
|
|
4866
|
-
source: {
|
|
4867
|
-
id: "dieline.effect.clip-path",
|
|
4868
|
-
type: "path",
|
|
4869
|
-
space: "screen",
|
|
4870
|
-
data: {
|
|
4871
|
-
id: "dieline.effect.clip-path",
|
|
4872
|
-
type: "dieline-effect",
|
|
4873
|
-
effect: "clipPath"
|
|
4874
|
-
},
|
|
4875
|
-
props: {
|
|
4876
|
-
pathData: clipPathData,
|
|
4877
|
-
fill: "#000000",
|
|
4878
|
-
stroke: null,
|
|
4879
|
-
originX: "left",
|
|
4880
|
-
originY: "top",
|
|
4881
|
-
selectable: false,
|
|
4882
|
-
evented: false,
|
|
4883
|
-
excludeFromExport: true
|
|
4884
|
-
}
|
|
4885
|
-
}
|
|
5199
|
+
ctx.strokeStyle = color;
|
|
5200
|
+
ctx.lineWidth = 1;
|
|
5201
|
+
ctx.beginPath();
|
|
5202
|
+
ctx.moveTo(0, size);
|
|
5203
|
+
ctx.lineTo(size, 0);
|
|
5204
|
+
ctx.stroke();
|
|
5205
|
+
}
|
|
5206
|
+
return new Pattern2({ source: canvas, repetition: "repeat" });
|
|
5207
|
+
}
|
|
5208
|
+
getConfigService() {
|
|
5209
|
+
var _a;
|
|
5210
|
+
return (_a = this.context) == null ? void 0 : _a.services.get(
|
|
5211
|
+
"ConfigurationService"
|
|
5212
|
+
);
|
|
5213
|
+
}
|
|
5214
|
+
hasImageItems() {
|
|
5215
|
+
const configService = this.getConfigService();
|
|
5216
|
+
if (!configService) return false;
|
|
5217
|
+
const items = configService.get("image.items", []);
|
|
5218
|
+
return Array.isArray(items) && items.length > 0;
|
|
5219
|
+
}
|
|
5220
|
+
buildDielineSpecs(sceneLayout) {
|
|
5221
|
+
var _a, _b;
|
|
5222
|
+
const hasImages = this.hasImageItems();
|
|
5223
|
+
return buildDielineRenderBundle({
|
|
5224
|
+
state: this.state,
|
|
5225
|
+
sceneLayout,
|
|
5226
|
+
canvasWidth: sceneLayout.canvasWidth || ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800,
|
|
5227
|
+
canvasHeight: sceneLayout.canvasHeight || ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600,
|
|
5228
|
+
hasImages,
|
|
5229
|
+
createHatchPattern: (color) => this.createHatchPattern(color),
|
|
5230
|
+
includeImageClipEffect: false
|
|
5231
|
+
}).specs;
|
|
5232
|
+
}
|
|
5233
|
+
buildImageClipEffects(sceneLayout) {
|
|
5234
|
+
var _a, _b;
|
|
5235
|
+
return buildDielineRenderBundle({
|
|
5236
|
+
state: this.state,
|
|
5237
|
+
sceneLayout,
|
|
5238
|
+
canvasWidth: sceneLayout.canvasWidth || ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800,
|
|
5239
|
+
canvasHeight: sceneLayout.canvasHeight || ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600,
|
|
5240
|
+
hasImages: this.hasImageItems(),
|
|
5241
|
+
includeImageClipEffect: true,
|
|
5242
|
+
clipTargetPassIds: [IMAGE_OBJECT_LAYER_ID],
|
|
5243
|
+
clipVisibility: {
|
|
5244
|
+
op: "not",
|
|
5245
|
+
expr: { op: "anySessionActive" }
|
|
4886
5246
|
}
|
|
4887
|
-
|
|
5247
|
+
}).effects;
|
|
4888
5248
|
}
|
|
4889
5249
|
updateDieline(_emitEvent = true) {
|
|
4890
5250
|
void this.updateDielineAsync();
|
|
@@ -4894,7 +5254,7 @@ var DielineTool = class {
|
|
|
4894
5254
|
const configService = this.getConfigService();
|
|
4895
5255
|
if (!configService) return;
|
|
4896
5256
|
const seq = ++this.renderSeq;
|
|
4897
|
-
this.
|
|
5257
|
+
Object.assign(this.state, readDielineState(configService, this.state));
|
|
4898
5258
|
const sceneLayout = computeSceneLayout(
|
|
4899
5259
|
this.canvasService,
|
|
4900
5260
|
readSizeState(configService)
|
|
@@ -4949,7 +5309,7 @@ var DielineTool = class {
|
|
|
4949
5309
|
);
|
|
4950
5310
|
return null;
|
|
4951
5311
|
}
|
|
4952
|
-
this.
|
|
5312
|
+
this.state = readDielineState(configService, this.state);
|
|
4953
5313
|
const sceneLayout = computeSceneLayout(
|
|
4954
5314
|
this.canvasService,
|
|
4955
5315
|
readSizeState(configService)
|
|
@@ -4971,15 +5331,31 @@ var DielineTool = class {
|
|
|
4971
5331
|
const visualRadius = radius * scale;
|
|
4972
5332
|
const visualOffset = (cutW - sceneLayout.trimRect.width) / 2;
|
|
4973
5333
|
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
4974
|
-
const
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
5334
|
+
const placements = resolveFeaturePlacements(features || [], {
|
|
5335
|
+
shape,
|
|
5336
|
+
shapeStyle,
|
|
5337
|
+
pathData,
|
|
5338
|
+
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
5339
|
+
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
5340
|
+
canvasWidth: canvasW,
|
|
5341
|
+
canvasHeight: canvasH,
|
|
5342
|
+
x: cx,
|
|
5343
|
+
y: cy,
|
|
5344
|
+
width: sceneLayout.trimRect.width,
|
|
5345
|
+
height: sceneLayout.trimRect.height,
|
|
5346
|
+
radius: visualRadius,
|
|
5347
|
+
scale
|
|
5348
|
+
});
|
|
5349
|
+
const cutFeatures = projectPlacedFeatures(
|
|
5350
|
+
placements.filter((placement) => !placement.feature.skipCut),
|
|
5351
|
+
{
|
|
5352
|
+
x: cx,
|
|
5353
|
+
y: cy,
|
|
5354
|
+
width: cutW,
|
|
5355
|
+
height: cutH
|
|
5356
|
+
},
|
|
5357
|
+
scale
|
|
5358
|
+
);
|
|
4983
5359
|
const generatedPathData = generateDielinePath({
|
|
4984
5360
|
shape,
|
|
4985
5361
|
width: cutW,
|
|
@@ -4998,283 +5374,112 @@ var DielineTool = class {
|
|
|
4998
5374
|
const clipPath = new Path(generatedPathData, {
|
|
4999
5375
|
originX: "center",
|
|
5000
5376
|
originY: "center",
|
|
5001
|
-
left: cx,
|
|
5002
|
-
top: cy,
|
|
5003
|
-
absolutePositioned: true
|
|
5004
|
-
});
|
|
5005
|
-
const pathOffsetX = Number((_a = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _a.x);
|
|
5006
|
-
const pathOffsetY = Number((_b = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _b.y);
|
|
5007
|
-
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
5008
|
-
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
5009
|
-
clipPath.set({
|
|
5010
|
-
originX: "center",
|
|
5011
|
-
originY: "center",
|
|
5012
|
-
left: centerX,
|
|
5013
|
-
top: centerY,
|
|
5014
|
-
absolutePositioned: true
|
|
5015
|
-
});
|
|
5016
|
-
clipPath.setCoords();
|
|
5017
|
-
const pathBounds = clipPath.getBoundingRect();
|
|
5018
|
-
if (!Number.isFinite(pathBounds.left) || !Number.isFinite(pathBounds.top) || !Number.isFinite(pathBounds.width) || !Number.isFinite(pathBounds.height) || pathBounds.width <= 0 || pathBounds.height <= 0) {
|
|
5019
|
-
console.warn(
|
|
5020
|
-
"[DielineTool] exportCutImage returned null: invalid-cut-bounds",
|
|
5021
|
-
{
|
|
5022
|
-
bounds: pathBounds
|
|
5023
|
-
}
|
|
5024
|
-
);
|
|
5025
|
-
return null;
|
|
5026
|
-
}
|
|
5027
|
-
const exportBounds = pathBounds;
|
|
5028
|
-
const sourceImages = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
5029
|
-
var _a2;
|
|
5030
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID;
|
|
5031
|
-
});
|
|
5032
|
-
if (!sourceImages.length) {
|
|
5033
|
-
console.warn(
|
|
5034
|
-
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas"
|
|
5035
|
-
);
|
|
5036
|
-
return null;
|
|
5037
|
-
}
|
|
5038
|
-
const sourceCanvasWidth = Number(
|
|
5039
|
-
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW
|
|
5040
|
-
);
|
|
5041
|
-
const sourceCanvasHeight = Number(
|
|
5042
|
-
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH
|
|
5043
|
-
);
|
|
5044
|
-
const el = document.createElement("canvas");
|
|
5045
|
-
const exportCanvas = new FabricCanvas2(el, {
|
|
5046
|
-
renderOnAddRemove: false,
|
|
5047
|
-
selection: false,
|
|
5048
|
-
enableRetinaScaling: false,
|
|
5049
|
-
preserveObjectStacking: true
|
|
5050
|
-
});
|
|
5051
|
-
exportCanvas.setDimensions({
|
|
5052
|
-
width: Math.max(1, sourceCanvasWidth),
|
|
5053
|
-
height: Math.max(1, sourceCanvasHeight)
|
|
5054
|
-
});
|
|
5055
|
-
try {
|
|
5056
|
-
for (const source of sourceImages) {
|
|
5057
|
-
const clone = await source.clone();
|
|
5058
|
-
clone.set({
|
|
5059
|
-
selectable: false,
|
|
5060
|
-
evented: false
|
|
5061
|
-
});
|
|
5062
|
-
clone.setCoords();
|
|
5063
|
-
exportCanvas.add(clone);
|
|
5064
|
-
}
|
|
5065
|
-
exportCanvas.clipPath = clipPath;
|
|
5066
|
-
exportCanvas.renderAll();
|
|
5067
|
-
const dataUrl = exportCanvas.toDataURL({
|
|
5068
|
-
format: "png",
|
|
5069
|
-
multiplier: 2,
|
|
5070
|
-
left: exportBounds.left,
|
|
5071
|
-
top: exportBounds.top,
|
|
5072
|
-
width: exportBounds.width,
|
|
5073
|
-
height: exportBounds.height
|
|
5074
|
-
});
|
|
5075
|
-
if (debug) {
|
|
5076
|
-
console.info("[DielineTool] exportCutImage success", {
|
|
5077
|
-
sourceCount: sourceImages.length,
|
|
5078
|
-
bounds: exportBounds,
|
|
5079
|
-
rawPathBounds: pathBounds,
|
|
5080
|
-
pathOffset: {
|
|
5081
|
-
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
5082
|
-
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null
|
|
5083
|
-
},
|
|
5084
|
-
clipPathCenter: {
|
|
5085
|
-
x: centerX,
|
|
5086
|
-
y: centerY
|
|
5087
|
-
},
|
|
5088
|
-
cutRect: sceneLayout.cutRect,
|
|
5089
|
-
canvasSize: {
|
|
5090
|
-
width: Math.max(1, sourceCanvasWidth),
|
|
5091
|
-
height: Math.max(1, sourceCanvasHeight)
|
|
5092
|
-
}
|
|
5093
|
-
});
|
|
5094
|
-
}
|
|
5095
|
-
return dataUrl;
|
|
5096
|
-
} finally {
|
|
5097
|
-
exportCanvas.dispose();
|
|
5098
|
-
}
|
|
5099
|
-
}
|
|
5100
|
-
};
|
|
5101
|
-
|
|
5102
|
-
// src/extensions/feature/FeatureTool.ts
|
|
5103
|
-
import {
|
|
5104
|
-
ContributionPointIds as ContributionPointIds5
|
|
5105
|
-
} from "@pooder/core";
|
|
5106
|
-
|
|
5107
|
-
// src/extensions/constraints.ts
|
|
5108
|
-
var ConstraintRegistry = class {
|
|
5109
|
-
static register(type, handler) {
|
|
5110
|
-
this.handlers.set(type, handler);
|
|
5111
|
-
}
|
|
5112
|
-
static apply(x, y, feature, context, constraints) {
|
|
5113
|
-
const list = constraints || feature.constraints;
|
|
5114
|
-
if (!list || list.length === 0) {
|
|
5115
|
-
return { x, y };
|
|
5116
|
-
}
|
|
5117
|
-
let currentX = x;
|
|
5118
|
-
let currentY = y;
|
|
5119
|
-
for (const constraint of list) {
|
|
5120
|
-
const handler = this.handlers.get(constraint.type);
|
|
5121
|
-
if (handler) {
|
|
5122
|
-
const result = handler(currentX, currentY, feature, context, constraint.params || {});
|
|
5123
|
-
currentX = result.x;
|
|
5124
|
-
currentY = result.y;
|
|
5125
|
-
}
|
|
5126
|
-
}
|
|
5127
|
-
return { x: currentX, y: currentY };
|
|
5128
|
-
}
|
|
5129
|
-
};
|
|
5130
|
-
ConstraintRegistry.handlers = /* @__PURE__ */ new Map();
|
|
5131
|
-
var pathConstraint = (x, y, feature, context, params) => {
|
|
5132
|
-
const { dielineWidth, dielineHeight, geometry } = context;
|
|
5133
|
-
if (!geometry) return { x, y };
|
|
5134
|
-
const minX = geometry.x - geometry.width / 2;
|
|
5135
|
-
const minY = geometry.y - geometry.height / 2;
|
|
5136
|
-
const absX = minX + x * geometry.width;
|
|
5137
|
-
const absY = minY + y * geometry.height;
|
|
5138
|
-
const nearest = getNearestPointOnDieline(
|
|
5139
|
-
{ x: absX, y: absY },
|
|
5140
|
-
geometry
|
|
5141
|
-
);
|
|
5142
|
-
let finalX = nearest.x;
|
|
5143
|
-
let finalY = nearest.y;
|
|
5144
|
-
const hasOffsetParams = params.minOffset !== void 0 || params.maxOffset !== void 0;
|
|
5145
|
-
if (hasOffsetParams && nearest.normal) {
|
|
5146
|
-
const dx = absX - nearest.x;
|
|
5147
|
-
const dy = absY - nearest.y;
|
|
5148
|
-
const nx2 = nearest.normal.x;
|
|
5149
|
-
const ny2 = nearest.normal.y;
|
|
5150
|
-
const dist = dx * nx2 + dy * ny2;
|
|
5151
|
-
const scale = dielineWidth > 0 ? geometry.width / dielineWidth : 1;
|
|
5152
|
-
const rawMin = params.minOffset !== void 0 ? params.minOffset : 0;
|
|
5153
|
-
const rawMax = params.maxOffset !== void 0 ? params.maxOffset : 0;
|
|
5154
|
-
const minOffset = rawMin * scale;
|
|
5155
|
-
const maxOffset = rawMax * scale;
|
|
5156
|
-
const clampedDist = Math.max(minOffset, Math.min(dist, maxOffset));
|
|
5157
|
-
finalX = nearest.x + nx2 * clampedDist;
|
|
5158
|
-
finalY = nearest.y + ny2 * clampedDist;
|
|
5159
|
-
}
|
|
5160
|
-
const nx = geometry.width > 0 ? (finalX - minX) / geometry.width : 0.5;
|
|
5161
|
-
const ny = geometry.height > 0 ? (finalY - minY) / geometry.height : 0.5;
|
|
5162
|
-
return { x: nx, y: ny };
|
|
5163
|
-
};
|
|
5164
|
-
var edgeConstraint = (x, y, feature, context, params) => {
|
|
5165
|
-
const { dielineWidth, dielineHeight } = context;
|
|
5166
|
-
const allowedEdges = params.allowedEdges || [
|
|
5167
|
-
"top",
|
|
5168
|
-
"bottom",
|
|
5169
|
-
"left",
|
|
5170
|
-
"right"
|
|
5171
|
-
];
|
|
5172
|
-
const confine = params.confine || false;
|
|
5173
|
-
const offset = params.offset || 0;
|
|
5174
|
-
const distances = [];
|
|
5175
|
-
if (allowedEdges.includes("top"))
|
|
5176
|
-
distances.push({ edge: "top", dist: y * dielineHeight });
|
|
5177
|
-
if (allowedEdges.includes("bottom"))
|
|
5178
|
-
distances.push({ edge: "bottom", dist: (1 - y) * dielineHeight });
|
|
5179
|
-
if (allowedEdges.includes("left"))
|
|
5180
|
-
distances.push({ edge: "left", dist: x * dielineWidth });
|
|
5181
|
-
if (allowedEdges.includes("right"))
|
|
5182
|
-
distances.push({ edge: "right", dist: (1 - x) * dielineWidth });
|
|
5183
|
-
if (distances.length === 0) return { x, y };
|
|
5184
|
-
distances.sort((a, b) => a.dist - b.dist);
|
|
5185
|
-
const nearest = distances[0].edge;
|
|
5186
|
-
let newX = x;
|
|
5187
|
-
let newY = y;
|
|
5188
|
-
const fw = feature.width || 0;
|
|
5189
|
-
const fh = feature.height || 0;
|
|
5190
|
-
switch (nearest) {
|
|
5191
|
-
case "top":
|
|
5192
|
-
newY = 0 + offset / dielineHeight;
|
|
5193
|
-
if (confine) {
|
|
5194
|
-
const minX = fw / 2 / dielineWidth;
|
|
5195
|
-
const maxX = 1 - minX;
|
|
5196
|
-
newX = Math.max(minX, Math.min(newX, maxX));
|
|
5197
|
-
}
|
|
5198
|
-
break;
|
|
5199
|
-
case "bottom":
|
|
5200
|
-
newY = 1 - offset / dielineHeight;
|
|
5201
|
-
if (confine) {
|
|
5202
|
-
const minX = fw / 2 / dielineWidth;
|
|
5203
|
-
const maxX = 1 - minX;
|
|
5204
|
-
newX = Math.max(minX, Math.min(newX, maxX));
|
|
5205
|
-
}
|
|
5206
|
-
break;
|
|
5207
|
-
case "left":
|
|
5208
|
-
newX = 0 + offset / dielineWidth;
|
|
5209
|
-
if (confine) {
|
|
5210
|
-
const minY = fh / 2 / dielineHeight;
|
|
5211
|
-
const maxY = 1 - minY;
|
|
5212
|
-
newY = Math.max(minY, Math.min(newY, maxY));
|
|
5377
|
+
left: cx,
|
|
5378
|
+
top: cy,
|
|
5379
|
+
absolutePositioned: true
|
|
5380
|
+
});
|
|
5381
|
+
const pathOffsetX = Number((_a = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _a.x);
|
|
5382
|
+
const pathOffsetY = Number((_b = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _b.y);
|
|
5383
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
5384
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
5385
|
+
clipPath.set({
|
|
5386
|
+
originX: "center",
|
|
5387
|
+
originY: "center",
|
|
5388
|
+
left: centerX,
|
|
5389
|
+
top: centerY,
|
|
5390
|
+
absolutePositioned: true
|
|
5391
|
+
});
|
|
5392
|
+
clipPath.setCoords();
|
|
5393
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
5394
|
+
if (!Number.isFinite(pathBounds.left) || !Number.isFinite(pathBounds.top) || !Number.isFinite(pathBounds.width) || !Number.isFinite(pathBounds.height) || pathBounds.width <= 0 || pathBounds.height <= 0) {
|
|
5395
|
+
console.warn(
|
|
5396
|
+
"[DielineTool] exportCutImage returned null: invalid-cut-bounds",
|
|
5397
|
+
{
|
|
5398
|
+
bounds: pathBounds
|
|
5399
|
+
}
|
|
5400
|
+
);
|
|
5401
|
+
return null;
|
|
5402
|
+
}
|
|
5403
|
+
const exportBounds = pathBounds;
|
|
5404
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
5405
|
+
var _a2;
|
|
5406
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID;
|
|
5407
|
+
});
|
|
5408
|
+
if (!sourceImages.length) {
|
|
5409
|
+
console.warn(
|
|
5410
|
+
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas"
|
|
5411
|
+
);
|
|
5412
|
+
return null;
|
|
5413
|
+
}
|
|
5414
|
+
const sourceCanvasWidth = Number(
|
|
5415
|
+
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW
|
|
5416
|
+
);
|
|
5417
|
+
const sourceCanvasHeight = Number(
|
|
5418
|
+
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH
|
|
5419
|
+
);
|
|
5420
|
+
const el = document.createElement("canvas");
|
|
5421
|
+
const exportCanvas = new FabricCanvas2(el, {
|
|
5422
|
+
renderOnAddRemove: false,
|
|
5423
|
+
selection: false,
|
|
5424
|
+
enableRetinaScaling: false,
|
|
5425
|
+
preserveObjectStacking: true
|
|
5426
|
+
});
|
|
5427
|
+
exportCanvas.setDimensions({
|
|
5428
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
5429
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
5430
|
+
});
|
|
5431
|
+
try {
|
|
5432
|
+
for (const source of sourceImages) {
|
|
5433
|
+
const clone = await source.clone();
|
|
5434
|
+
clone.set({
|
|
5435
|
+
selectable: false,
|
|
5436
|
+
evented: false
|
|
5437
|
+
});
|
|
5438
|
+
clone.setCoords();
|
|
5439
|
+
exportCanvas.add(clone);
|
|
5213
5440
|
}
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5441
|
+
exportCanvas.clipPath = clipPath;
|
|
5442
|
+
exportCanvas.renderAll();
|
|
5443
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
5444
|
+
format: "png",
|
|
5445
|
+
multiplier: 2,
|
|
5446
|
+
left: exportBounds.left,
|
|
5447
|
+
top: exportBounds.top,
|
|
5448
|
+
width: exportBounds.width,
|
|
5449
|
+
height: exportBounds.height
|
|
5450
|
+
});
|
|
5451
|
+
if (debug) {
|
|
5452
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
5453
|
+
sourceCount: sourceImages.length,
|
|
5454
|
+
bounds: exportBounds,
|
|
5455
|
+
rawPathBounds: pathBounds,
|
|
5456
|
+
pathOffset: {
|
|
5457
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
5458
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null
|
|
5459
|
+
},
|
|
5460
|
+
clipPathCenter: {
|
|
5461
|
+
x: centerX,
|
|
5462
|
+
y: centerY
|
|
5463
|
+
},
|
|
5464
|
+
cutRect: sceneLayout.cutRect,
|
|
5465
|
+
canvasSize: {
|
|
5466
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
5467
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
5468
|
+
}
|
|
5469
|
+
});
|
|
5221
5470
|
}
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
}
|
|
5226
|
-
var internalConstraint = (x, y, feature, context, params) => {
|
|
5227
|
-
const { dielineWidth, dielineHeight } = context;
|
|
5228
|
-
const margin = params.margin || 0;
|
|
5229
|
-
const fw = feature.width || 0;
|
|
5230
|
-
const fh = feature.height || 0;
|
|
5231
|
-
const minX = (margin + fw / 2) / dielineWidth;
|
|
5232
|
-
const maxX = 1 - (margin + fw / 2) / dielineWidth;
|
|
5233
|
-
const minY = (margin + fh / 2) / dielineHeight;
|
|
5234
|
-
const maxY = 1 - (margin + fh / 2) / dielineHeight;
|
|
5235
|
-
const clampedX = minX > maxX ? 0.5 : Math.max(minX, Math.min(x, maxX));
|
|
5236
|
-
const clampedY = minY > maxY ? 0.5 : Math.max(minY, Math.min(y, maxY));
|
|
5237
|
-
return { x: clampedX, y: clampedY };
|
|
5238
|
-
};
|
|
5239
|
-
var tangentBottomConstraint = (x, y, feature, context, params) => {
|
|
5240
|
-
const { dielineWidth, dielineHeight } = context;
|
|
5241
|
-
const gap = params.gap || 0;
|
|
5242
|
-
const confineX = params.confineX !== false;
|
|
5243
|
-
const extentY = feature.shape === "circle" ? feature.radius || 0 : (feature.height || 0) / 2;
|
|
5244
|
-
const newY = 1 + (extentY + gap) / dielineHeight;
|
|
5245
|
-
let newX = x;
|
|
5246
|
-
if (confineX) {
|
|
5247
|
-
const extentX = feature.shape === "circle" ? feature.radius || 0 : (feature.width || 0) / 2;
|
|
5248
|
-
const minX = extentX / dielineWidth;
|
|
5249
|
-
const maxX = 1 - extentX / dielineWidth;
|
|
5250
|
-
newX = minX > maxX ? 0.5 : Math.max(minX, Math.min(newX, maxX));
|
|
5251
|
-
}
|
|
5252
|
-
return { x: newX, y: newY };
|
|
5253
|
-
};
|
|
5254
|
-
var lowestTangentConstraint = (x, y, feature, context, params) => {
|
|
5255
|
-
const { dielineWidth, dielineHeight, geometry } = context;
|
|
5256
|
-
if (!geometry) return { x, y };
|
|
5257
|
-
const lowest = getLowestPointOnDieline(geometry);
|
|
5258
|
-
const minY = geometry.y - geometry.height / 2;
|
|
5259
|
-
const normY = (lowest.y - minY) / geometry.height;
|
|
5260
|
-
const gap = params.gap || 0;
|
|
5261
|
-
const confineX = params.confineX !== false;
|
|
5262
|
-
const extentY = feature.shape === "circle" ? feature.radius || 0 : (feature.height || 0) / 2;
|
|
5263
|
-
const newY = normY + (extentY + gap) / dielineHeight;
|
|
5264
|
-
let newX = x;
|
|
5265
|
-
if (confineX) {
|
|
5266
|
-
const extentX = feature.shape === "circle" ? feature.radius || 0 : (feature.width || 0) / 2;
|
|
5267
|
-
const minX = extentX / dielineWidth;
|
|
5268
|
-
const maxX = 1 - extentX / dielineWidth;
|
|
5269
|
-
newX = minX > maxX ? 0.5 : Math.max(minX, Math.min(newX, maxX));
|
|
5471
|
+
return dataUrl;
|
|
5472
|
+
} finally {
|
|
5473
|
+
exportCanvas.dispose();
|
|
5474
|
+
}
|
|
5270
5475
|
}
|
|
5271
|
-
return { x: newX, y: newY };
|
|
5272
5476
|
};
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5477
|
+
|
|
5478
|
+
// src/extensions/feature/FeatureTool.ts
|
|
5479
|
+
import {
|
|
5480
|
+
ContributionPointIds as ContributionPointIds5
|
|
5481
|
+
} from "@pooder/core";
|
|
5482
|
+
import { Pattern as Pattern3 } from "fabric";
|
|
5278
5483
|
|
|
5279
5484
|
// src/extensions/featureComplete.ts
|
|
5280
5485
|
function validateFeaturesStrict(features, context) {
|
|
@@ -5317,7 +5522,9 @@ var FeatureTool = class {
|
|
|
5317
5522
|
this.isFeatureSessionActive = false;
|
|
5318
5523
|
this.sessionOriginalFeatures = null;
|
|
5319
5524
|
this.hasWorkingChanges = false;
|
|
5320
|
-
this.
|
|
5525
|
+
this.markerSpecs = [];
|
|
5526
|
+
this.sessionDielineSpecs = [];
|
|
5527
|
+
this.sessionDielineEffects = [];
|
|
5321
5528
|
this.renderSeq = 0;
|
|
5322
5529
|
this.subscriptions = new SubscriptionBag();
|
|
5323
5530
|
this.handleMoving = null;
|
|
@@ -5327,7 +5534,7 @@ var FeatureTool = class {
|
|
|
5327
5534
|
this.onToolActivated = (event) => {
|
|
5328
5535
|
this.isToolActive = event.id === this.id;
|
|
5329
5536
|
if (!this.isToolActive) {
|
|
5330
|
-
this.
|
|
5537
|
+
this.suspendFeatureSession();
|
|
5331
5538
|
}
|
|
5332
5539
|
this.updateVisibility();
|
|
5333
5540
|
};
|
|
@@ -5347,16 +5554,38 @@ var FeatureTool = class {
|
|
|
5347
5554
|
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5348
5555
|
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
5349
5556
|
this.id,
|
|
5350
|
-
() =>
|
|
5351
|
-
passes
|
|
5557
|
+
() => {
|
|
5558
|
+
const passes = [
|
|
5352
5559
|
{
|
|
5353
5560
|
id: FEATURE_OVERLAY_LAYER_ID,
|
|
5354
5561
|
stack: 880,
|
|
5355
5562
|
order: 0,
|
|
5356
|
-
|
|
5563
|
+
replace: true,
|
|
5564
|
+
objects: this.markerSpecs
|
|
5357
5565
|
}
|
|
5358
|
-
]
|
|
5359
|
-
|
|
5566
|
+
];
|
|
5567
|
+
if (this.isSessionVisible()) {
|
|
5568
|
+
passes.push(
|
|
5569
|
+
{
|
|
5570
|
+
id: DIELINE_LAYER_ID,
|
|
5571
|
+
stack: 700,
|
|
5572
|
+
order: 0,
|
|
5573
|
+
replace: false,
|
|
5574
|
+
visibility: { op: "const", value: false },
|
|
5575
|
+
objects: []
|
|
5576
|
+
},
|
|
5577
|
+
{
|
|
5578
|
+
id: FEATURE_DIELINE_LAYER_ID,
|
|
5579
|
+
stack: 705,
|
|
5580
|
+
order: 0,
|
|
5581
|
+
replace: true,
|
|
5582
|
+
effects: this.sessionDielineEffects,
|
|
5583
|
+
objects: this.sessionDielineSpecs
|
|
5584
|
+
}
|
|
5585
|
+
);
|
|
5586
|
+
}
|
|
5587
|
+
return { passes };
|
|
5588
|
+
},
|
|
5360
5589
|
{ priority: 350 }
|
|
5361
5590
|
);
|
|
5362
5591
|
const configService = context.services.get(
|
|
@@ -5371,12 +5600,22 @@ var FeatureTool = class {
|
|
|
5371
5600
|
(e) => {
|
|
5372
5601
|
if (this.isUpdatingConfig) return;
|
|
5373
5602
|
if (e.key === "dieline.features") {
|
|
5374
|
-
if (this.isFeatureSessionActive)
|
|
5603
|
+
if (this.isFeatureSessionActive && this.hasFeatureSessionDraft()) {
|
|
5604
|
+
return;
|
|
5605
|
+
}
|
|
5606
|
+
if (this.hasFeatureSessionDraft()) {
|
|
5607
|
+
this.clearFeatureSessionState();
|
|
5608
|
+
}
|
|
5375
5609
|
const next = e.value || [];
|
|
5376
5610
|
this.workingFeatures = this.cloneFeatures(next);
|
|
5377
5611
|
this.hasWorkingChanges = false;
|
|
5378
5612
|
this.redraw();
|
|
5379
5613
|
this.emitWorkingChange();
|
|
5614
|
+
return;
|
|
5615
|
+
}
|
|
5616
|
+
if (e.key.startsWith("size.") || e.key.startsWith("dieline.")) {
|
|
5617
|
+
void this.refreshGeometry();
|
|
5618
|
+
this.redraw({ enforceConstraints: true });
|
|
5380
5619
|
}
|
|
5381
5620
|
}
|
|
5382
5621
|
);
|
|
@@ -5392,7 +5631,8 @@ var FeatureTool = class {
|
|
|
5392
5631
|
deactivate(context) {
|
|
5393
5632
|
var _a;
|
|
5394
5633
|
this.subscriptions.disposeAll();
|
|
5395
|
-
this.
|
|
5634
|
+
this.restoreCommittedFeaturesToConfig();
|
|
5635
|
+
this.clearFeatureSessionState();
|
|
5396
5636
|
(_a = this.dirtyTrackerDisposable) == null ? void 0 : _a.dispose();
|
|
5397
5637
|
this.dirtyTrackerDisposable = void 0;
|
|
5398
5638
|
this.teardown();
|
|
@@ -5402,6 +5642,9 @@ var FeatureTool = class {
|
|
|
5402
5642
|
updateVisibility() {
|
|
5403
5643
|
this.redraw();
|
|
5404
5644
|
}
|
|
5645
|
+
isSessionVisible() {
|
|
5646
|
+
return this.isToolActive && this.isFeatureSessionActive;
|
|
5647
|
+
}
|
|
5405
5648
|
contribute() {
|
|
5406
5649
|
return {
|
|
5407
5650
|
[ContributionPointIds5.TOOLS]: [
|
|
@@ -5428,15 +5671,16 @@ var FeatureTool = class {
|
|
|
5428
5671
|
if (this.isFeatureSessionActive) {
|
|
5429
5672
|
return { ok: true };
|
|
5430
5673
|
}
|
|
5431
|
-
|
|
5432
|
-
|
|
5674
|
+
if (!this.hasFeatureSessionDraft()) {
|
|
5675
|
+
const original = this.getCommittedFeatures();
|
|
5676
|
+
this.sessionOriginalFeatures = this.cloneFeatures(original);
|
|
5677
|
+
this.setWorkingFeatures(this.cloneFeatures(original));
|
|
5678
|
+
this.hasWorkingChanges = false;
|
|
5679
|
+
}
|
|
5433
5680
|
this.isFeatureSessionActive = true;
|
|
5434
5681
|
await this.refreshGeometry();
|
|
5435
|
-
this.setWorkingFeatures(this.cloneFeatures(original));
|
|
5436
|
-
this.hasWorkingChanges = false;
|
|
5437
5682
|
this.redraw();
|
|
5438
5683
|
this.emitWorkingChange();
|
|
5439
|
-
this.updateCommittedFeatures([]);
|
|
5440
5684
|
return { ok: true };
|
|
5441
5685
|
}
|
|
5442
5686
|
},
|
|
@@ -5472,25 +5716,6 @@ var FeatureTool = class {
|
|
|
5472
5716
|
return true;
|
|
5473
5717
|
}
|
|
5474
5718
|
},
|
|
5475
|
-
{
|
|
5476
|
-
command: "getWorkingFeatures",
|
|
5477
|
-
title: "Get Working Features",
|
|
5478
|
-
handler: () => {
|
|
5479
|
-
return this.cloneFeatures(this.workingFeatures);
|
|
5480
|
-
}
|
|
5481
|
-
},
|
|
5482
|
-
{
|
|
5483
|
-
command: "setWorkingFeatures",
|
|
5484
|
-
title: "Set Working Features",
|
|
5485
|
-
handler: async (features) => {
|
|
5486
|
-
await this.refreshGeometry();
|
|
5487
|
-
this.setWorkingFeatures(this.cloneFeatures(features || []));
|
|
5488
|
-
this.hasWorkingChanges = true;
|
|
5489
|
-
this.redraw();
|
|
5490
|
-
this.emitWorkingChange();
|
|
5491
|
-
return { ok: true };
|
|
5492
|
-
}
|
|
5493
|
-
},
|
|
5494
5719
|
{
|
|
5495
5720
|
command: "rollbackFeatureSession",
|
|
5496
5721
|
title: "Rollback Feature Session",
|
|
@@ -5557,17 +5782,24 @@ var FeatureTool = class {
|
|
|
5557
5782
|
this.isUpdatingConfig = false;
|
|
5558
5783
|
}
|
|
5559
5784
|
}
|
|
5785
|
+
hasFeatureSessionDraft() {
|
|
5786
|
+
return Array.isArray(this.sessionOriginalFeatures);
|
|
5787
|
+
}
|
|
5560
5788
|
clearFeatureSessionState() {
|
|
5561
5789
|
this.isFeatureSessionActive = false;
|
|
5562
5790
|
this.sessionOriginalFeatures = null;
|
|
5563
5791
|
}
|
|
5564
|
-
|
|
5565
|
-
if (!this.
|
|
5792
|
+
restoreCommittedFeaturesToConfig() {
|
|
5793
|
+
if (!this.hasFeatureSessionDraft()) return;
|
|
5566
5794
|
const original = this.cloneFeatures(
|
|
5567
5795
|
this.sessionOriginalFeatures || this.getCommittedFeatures()
|
|
5568
5796
|
);
|
|
5569
5797
|
this.updateCommittedFeatures(original);
|
|
5570
|
-
|
|
5798
|
+
}
|
|
5799
|
+
suspendFeatureSession() {
|
|
5800
|
+
if (!this.isFeatureSessionActive) return;
|
|
5801
|
+
this.restoreCommittedFeaturesToConfig();
|
|
5802
|
+
this.isFeatureSessionActive = false;
|
|
5571
5803
|
}
|
|
5572
5804
|
emitWorkingChange() {
|
|
5573
5805
|
var _a;
|
|
@@ -5589,7 +5821,7 @@ var FeatureTool = class {
|
|
|
5589
5821
|
}
|
|
5590
5822
|
async resetWorkingFeaturesFromSource() {
|
|
5591
5823
|
const next = this.cloneFeatures(
|
|
5592
|
-
this.
|
|
5824
|
+
this.sessionOriginalFeatures || this.getCommittedFeatures()
|
|
5593
5825
|
);
|
|
5594
5826
|
await this.refreshGeometry();
|
|
5595
5827
|
this.setWorkingFeatures(next);
|
|
@@ -5813,11 +6045,35 @@ var FeatureTool = class {
|
|
|
5813
6045
|
this.handleSceneGeometryChange = null;
|
|
5814
6046
|
}
|
|
5815
6047
|
this.renderSeq += 1;
|
|
5816
|
-
this.
|
|
6048
|
+
this.markerSpecs = [];
|
|
6049
|
+
this.sessionDielineSpecs = [];
|
|
6050
|
+
this.sessionDielineEffects = [];
|
|
5817
6051
|
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5818
6052
|
this.renderProducerDisposable = void 0;
|
|
5819
6053
|
void this.canvasService.flushRenderFromProducers();
|
|
5820
6054
|
}
|
|
6055
|
+
createHatchPattern(color = "rgba(0, 0, 0, 0.3)") {
|
|
6056
|
+
if (typeof document === "undefined") {
|
|
6057
|
+
return void 0;
|
|
6058
|
+
}
|
|
6059
|
+
const size = 20;
|
|
6060
|
+
const canvas = document.createElement("canvas");
|
|
6061
|
+
canvas.width = size;
|
|
6062
|
+
canvas.height = size;
|
|
6063
|
+
const ctx = canvas.getContext("2d");
|
|
6064
|
+
if (ctx) {
|
|
6065
|
+
ctx.clearRect(0, 0, size, size);
|
|
6066
|
+
ctx.strokeStyle = color;
|
|
6067
|
+
ctx.lineWidth = 1;
|
|
6068
|
+
ctx.beginPath();
|
|
6069
|
+
ctx.moveTo(0, size);
|
|
6070
|
+
ctx.lineTo(size, 0);
|
|
6071
|
+
ctx.stroke();
|
|
6072
|
+
}
|
|
6073
|
+
return new Pattern3({
|
|
6074
|
+
source: canvas
|
|
6075
|
+
});
|
|
6076
|
+
}
|
|
5821
6077
|
getDraggableMarkerTarget(target) {
|
|
5822
6078
|
var _a, _b;
|
|
5823
6079
|
if (!this.isFeatureSessionActive || !this.isToolActive) return null;
|
|
@@ -5893,6 +6149,7 @@ var FeatureTool = class {
|
|
|
5893
6149
|
next[index] = updatedFeature;
|
|
5894
6150
|
this.setWorkingFeatures(next);
|
|
5895
6151
|
this.hasWorkingChanges = true;
|
|
6152
|
+
this.redraw();
|
|
5896
6153
|
this.emitWorkingChange();
|
|
5897
6154
|
}
|
|
5898
6155
|
syncGroupFromCanvas(target) {
|
|
@@ -5931,6 +6188,7 @@ var FeatureTool = class {
|
|
|
5931
6188
|
if (!changed) return;
|
|
5932
6189
|
this.setWorkingFeatures(next);
|
|
5933
6190
|
this.hasWorkingChanges = true;
|
|
6191
|
+
this.redraw();
|
|
5934
6192
|
this.emitWorkingChange();
|
|
5935
6193
|
}
|
|
5936
6194
|
redraw(options = {}) {
|
|
@@ -5939,7 +6197,10 @@ var FeatureTool = class {
|
|
|
5939
6197
|
async redrawAsync(options = {}) {
|
|
5940
6198
|
if (!this.canvasService) return;
|
|
5941
6199
|
const seq = ++this.renderSeq;
|
|
5942
|
-
this.
|
|
6200
|
+
this.markerSpecs = this.buildMarkerSpecs();
|
|
6201
|
+
const sessionRender = this.buildSessionDielineRender();
|
|
6202
|
+
this.sessionDielineSpecs = sessionRender.specs;
|
|
6203
|
+
this.sessionDielineEffects = sessionRender.effects;
|
|
5943
6204
|
if (seq !== this.renderSeq) return;
|
|
5944
6205
|
await this.canvasService.flushRenderFromProducers();
|
|
5945
6206
|
if (seq !== this.renderSeq) return;
|
|
@@ -5947,15 +6208,77 @@ var FeatureTool = class {
|
|
|
5947
6208
|
this.enforceConstraints();
|
|
5948
6209
|
}
|
|
5949
6210
|
}
|
|
5950
|
-
|
|
6211
|
+
buildSessionDielineRender() {
|
|
6212
|
+
if (!this.isSessionVisible() || !this.canvasService) {
|
|
6213
|
+
return { specs: [], effects: [] };
|
|
6214
|
+
}
|
|
6215
|
+
const configService = this.getConfigService();
|
|
6216
|
+
if (!configService) {
|
|
6217
|
+
return { specs: [], effects: [] };
|
|
6218
|
+
}
|
|
6219
|
+
const sceneLayout = computeSceneLayout(
|
|
6220
|
+
this.canvasService,
|
|
6221
|
+
readSizeState(configService)
|
|
6222
|
+
);
|
|
6223
|
+
if (!sceneLayout) {
|
|
6224
|
+
return { specs: [], effects: [] };
|
|
6225
|
+
}
|
|
6226
|
+
const state = readDielineState(configService);
|
|
6227
|
+
state.features = this.cloneFeatures(this.workingFeatures);
|
|
6228
|
+
return buildDielineRenderBundle({
|
|
6229
|
+
state,
|
|
6230
|
+
sceneLayout,
|
|
6231
|
+
canvasWidth: sceneLayout.canvasWidth || this.canvasService.canvas.width || 800,
|
|
6232
|
+
canvasHeight: sceneLayout.canvasHeight || this.canvasService.canvas.height || 600,
|
|
6233
|
+
hasImages: this.hasImageItems(),
|
|
6234
|
+
createHatchPattern: (color) => this.createHatchPattern(color),
|
|
6235
|
+
clipTargetPassIds: [IMAGE_OBJECT_LAYER_ID],
|
|
6236
|
+
clipVisibility: { op: "const", value: true },
|
|
6237
|
+
ids: {
|
|
6238
|
+
inside: "feature.session.dieline.inside",
|
|
6239
|
+
bleedZone: "feature.session.dieline.bleed-zone",
|
|
6240
|
+
offsetBorder: "feature.session.dieline.offset-border",
|
|
6241
|
+
border: "feature.session.dieline.border",
|
|
6242
|
+
clip: "feature.session.dieline.clip.image",
|
|
6243
|
+
clipSource: "feature.session.dieline.effect.clip-path"
|
|
6244
|
+
}
|
|
6245
|
+
});
|
|
6246
|
+
}
|
|
6247
|
+
hasImageItems() {
|
|
6248
|
+
const configService = this.getConfigService();
|
|
6249
|
+
if (!configService) return false;
|
|
6250
|
+
const items = configService.get("image.items", []);
|
|
6251
|
+
return Array.isArray(items) && items.length > 0;
|
|
6252
|
+
}
|
|
6253
|
+
buildMarkerSpecs() {
|
|
5951
6254
|
if (!this.isFeatureSessionActive || !this.currentGeometry || this.workingFeatures.length === 0) {
|
|
5952
6255
|
return [];
|
|
5953
6256
|
}
|
|
5954
6257
|
const groups = /* @__PURE__ */ new Map();
|
|
5955
6258
|
const singles = [];
|
|
5956
|
-
|
|
6259
|
+
const placements = resolveFeaturePlacements(
|
|
6260
|
+
this.workingFeatures,
|
|
6261
|
+
{
|
|
6262
|
+
shape: this.currentGeometry.shape,
|
|
6263
|
+
shapeStyle: this.currentGeometry.shapeStyle,
|
|
6264
|
+
pathData: this.currentGeometry.pathData,
|
|
6265
|
+
customSourceWidthPx: this.currentGeometry.customSourceWidthPx,
|
|
6266
|
+
customSourceHeightPx: this.currentGeometry.customSourceHeightPx,
|
|
6267
|
+
x: this.currentGeometry.x,
|
|
6268
|
+
y: this.currentGeometry.y,
|
|
6269
|
+
width: this.currentGeometry.width,
|
|
6270
|
+
height: this.currentGeometry.height,
|
|
6271
|
+
radius: this.currentGeometry.radius,
|
|
6272
|
+
scale: this.currentGeometry.scale || 1
|
|
6273
|
+
}
|
|
6274
|
+
);
|
|
6275
|
+
placements.forEach((placement, index) => {
|
|
6276
|
+
const feature = placement.feature;
|
|
5957
6277
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5958
|
-
const position =
|
|
6278
|
+
const position = {
|
|
6279
|
+
x: placement.centerX,
|
|
6280
|
+
y: placement.centerY
|
|
6281
|
+
};
|
|
5959
6282
|
const scale = geometry.scale || 1;
|
|
5960
6283
|
const marker = {
|
|
5961
6284
|
feature,
|
|
@@ -6532,11 +6855,12 @@ var EXTENSION_LINE_LENGTH = 5;
|
|
|
6532
6855
|
var MIN_ARROW_SIZE = 4;
|
|
6533
6856
|
var THICKNESS_TO_STROKE_WIDTH_RATIO = 20;
|
|
6534
6857
|
var DEFAULT_THICKNESS = 20;
|
|
6535
|
-
var DEFAULT_GAP =
|
|
6858
|
+
var DEFAULT_GAP = 65;
|
|
6536
6859
|
var DEFAULT_FONT_SIZE = 10;
|
|
6537
6860
|
var DEFAULT_BACKGROUND_COLOR = "#f0f0f0";
|
|
6538
6861
|
var DEFAULT_TEXT_COLOR = "#333333";
|
|
6539
6862
|
var DEFAULT_LINE_COLOR = "#999999";
|
|
6863
|
+
var RULER_DEBUG_KEY = "ruler.debug";
|
|
6540
6864
|
var RULER_THICKNESS_MIN = 10;
|
|
6541
6865
|
var RULER_THICKNESS_MAX = 100;
|
|
6542
6866
|
var RULER_GAP_MIN = 0;
|
|
@@ -6555,6 +6879,7 @@ var RulerTool = class {
|
|
|
6555
6879
|
this.textColor = DEFAULT_TEXT_COLOR;
|
|
6556
6880
|
this.lineColor = DEFAULT_LINE_COLOR;
|
|
6557
6881
|
this.fontSize = DEFAULT_FONT_SIZE;
|
|
6882
|
+
this.debugEnabled = false;
|
|
6558
6883
|
this.renderSeq = 0;
|
|
6559
6884
|
this.numericProps = /* @__PURE__ */ new Set(["thickness", "gap", "fontSize"]);
|
|
6560
6885
|
this.specs = [];
|
|
@@ -6603,7 +6928,14 @@ var RulerTool = class {
|
|
|
6603
6928
|
this.syncConfig(configService);
|
|
6604
6929
|
configService.onAnyChange((e) => {
|
|
6605
6930
|
let shouldUpdate = false;
|
|
6606
|
-
if (e.key
|
|
6931
|
+
if (e.key === RULER_DEBUG_KEY) {
|
|
6932
|
+
this.debugEnabled = e.value === true;
|
|
6933
|
+
this.log("config:update", {
|
|
6934
|
+
key: e.key,
|
|
6935
|
+
raw: e.value,
|
|
6936
|
+
normalized: this.debugEnabled
|
|
6937
|
+
});
|
|
6938
|
+
} else if (e.key.startsWith("ruler.")) {
|
|
6607
6939
|
const prop = e.key.split(".")[1];
|
|
6608
6940
|
if (prop && prop in this) {
|
|
6609
6941
|
if (this.numericProps.has(prop)) {
|
|
@@ -6690,6 +7022,12 @@ var RulerTool = class {
|
|
|
6690
7022
|
min: RULER_FONT_SIZE_MIN,
|
|
6691
7023
|
max: RULER_FONT_SIZE_MAX,
|
|
6692
7024
|
default: DEFAULT_FONT_SIZE
|
|
7025
|
+
},
|
|
7026
|
+
{
|
|
7027
|
+
id: RULER_DEBUG_KEY,
|
|
7028
|
+
type: "boolean",
|
|
7029
|
+
label: "Ruler Debug Log",
|
|
7030
|
+
default: false
|
|
6693
7031
|
}
|
|
6694
7032
|
],
|
|
6695
7033
|
[ContributionPointIds8.COMMANDS]: [
|
|
@@ -6726,7 +7064,11 @@ var RulerTool = class {
|
|
|
6726
7064
|
]
|
|
6727
7065
|
};
|
|
6728
7066
|
}
|
|
7067
|
+
isDebugEnabled() {
|
|
7068
|
+
return this.debugEnabled;
|
|
7069
|
+
}
|
|
6729
7070
|
log(step, payload) {
|
|
7071
|
+
if (!this.isDebugEnabled()) return;
|
|
6730
7072
|
if (payload) {
|
|
6731
7073
|
console.debug(`[RulerTool] ${step}`, payload);
|
|
6732
7074
|
return;
|
|
@@ -6755,6 +7097,7 @@ var RulerTool = class {
|
|
|
6755
7097
|
configService.get("ruler.fontSize", this.fontSize),
|
|
6756
7098
|
DEFAULT_FONT_SIZE
|
|
6757
7099
|
);
|
|
7100
|
+
this.debugEnabled = configService.get(RULER_DEBUG_KEY, this.debugEnabled) === true;
|
|
6758
7101
|
this.log("config:loaded", {
|
|
6759
7102
|
thickness: this.thickness,
|
|
6760
7103
|
gap: this.gap,
|
|
@@ -9534,11 +9877,13 @@ export {
|
|
|
9534
9877
|
WhiteInkTool,
|
|
9535
9878
|
getCoverScale as computeImageCoverScale,
|
|
9536
9879
|
getCoverScale as computeWhiteInkCoverScale,
|
|
9880
|
+
createDefaultDielineState,
|
|
9537
9881
|
createDielineCommands,
|
|
9538
9882
|
createDielineConfigurations,
|
|
9539
9883
|
createImageCommands,
|
|
9540
9884
|
createImageConfigurations,
|
|
9541
9885
|
createWhiteInkCommands,
|
|
9542
9886
|
createWhiteInkConfigurations,
|
|
9543
|
-
evaluateVisibilityExpr
|
|
9887
|
+
evaluateVisibilityExpr,
|
|
9888
|
+
readDielineState
|
|
9544
9889
|
};
|