@pooder/kit 5.3.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.test-dist/src/extensions/background.js +475 -131
- package/.test-dist/src/extensions/dieline.js +283 -180
- package/.test-dist/src/extensions/dielineShape.js +66 -0
- package/.test-dist/src/extensions/feature.js +388 -303
- package/.test-dist/src/extensions/film.js +133 -74
- package/.test-dist/src/extensions/geometry.js +120 -56
- package/.test-dist/src/extensions/image.js +296 -212
- package/.test-dist/src/extensions/index.js +1 -3
- package/.test-dist/src/extensions/maskOps.js +75 -20
- package/.test-dist/src/extensions/ruler.js +312 -215
- package/.test-dist/src/extensions/sceneLayoutModel.js +9 -3
- package/.test-dist/src/extensions/sceneVisibility.js +3 -10
- package/.test-dist/src/extensions/tracer.js +229 -58
- package/.test-dist/src/extensions/white-ink.js +139 -129
- package/.test-dist/src/services/CanvasService.js +888 -126
- package/.test-dist/src/services/index.js +1 -0
- package/.test-dist/src/services/visibility.js +54 -0
- package/.test-dist/tests/run.js +58 -4
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +377 -82
- package/dist/index.d.ts +377 -82
- package/dist/index.js +3920 -2178
- package/dist/index.mjs +3992 -2247
- package/package.json +1 -1
- package/src/extensions/background.ts +631 -145
- package/src/extensions/dieline.ts +280 -187
- package/src/extensions/dielineShape.ts +109 -0
- package/src/extensions/feature.ts +485 -366
- package/src/extensions/film.ts +152 -76
- package/src/extensions/geometry.ts +203 -104
- package/src/extensions/image.ts +319 -238
- package/src/extensions/index.ts +0 -1
- package/src/extensions/ruler.ts +481 -268
- package/src/extensions/sceneLayoutModel.ts +18 -6
- package/src/extensions/white-ink.ts +157 -171
- package/src/services/CanvasService.ts +1126 -140
- package/src/services/index.ts +1 -0
- package/src/services/renderSpec.ts +69 -4
- package/src/services/visibility.ts +78 -0
- package/tests/run.ts +139 -4
- package/.test-dist/src/CanvasService.js +0 -249
- package/.test-dist/src/ViewportSystem.js +0 -75
- package/.test-dist/src/background.js +0 -203
- package/.test-dist/src/bridgeSelection.js +0 -20
- package/.test-dist/src/constraints.js +0 -237
- package/.test-dist/src/dieline.js +0 -818
- package/.test-dist/src/edgeScale.js +0 -12
- package/.test-dist/src/feature.js +0 -826
- package/.test-dist/src/featureComplete.js +0 -32
- package/.test-dist/src/film.js +0 -167
- package/.test-dist/src/geometry.js +0 -506
- package/.test-dist/src/image.js +0 -1250
- package/.test-dist/src/maskOps.js +0 -270
- package/.test-dist/src/mirror.js +0 -104
- package/.test-dist/src/renderSpec.js +0 -2
- package/.test-dist/src/ruler.js +0 -343
- package/.test-dist/src/sceneLayout.js +0 -99
- package/.test-dist/src/sceneLayoutModel.js +0 -196
- package/.test-dist/src/sceneView.js +0 -40
- package/.test-dist/src/sceneVisibility.js +0 -42
- package/.test-dist/src/size.js +0 -332
- package/.test-dist/src/tracer.js +0 -544
- package/.test-dist/src/white-ink.js +0 -829
- package/.test-dist/src/wrappedOffsets.js +0 -33
- package/src/extensions/sceneVisibility.ts +0 -71
|
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FilmTool = void 0;
|
|
4
4
|
const core_1 = require("@pooder/core");
|
|
5
5
|
const fabric_1 = require("fabric");
|
|
6
|
+
const FILM_LAYER_ID = "overlay";
|
|
7
|
+
const FILM_IMAGE_ID = "film-image";
|
|
8
|
+
const DEFAULT_WIDTH = 800;
|
|
9
|
+
const DEFAULT_HEIGHT = 600;
|
|
6
10
|
class FilmTool {
|
|
7
11
|
constructor(options) {
|
|
8
12
|
this.id = "pooder.kit.film";
|
|
@@ -11,6 +15,14 @@ class FilmTool {
|
|
|
11
15
|
};
|
|
12
16
|
this.url = "";
|
|
13
17
|
this.opacity = 0.5;
|
|
18
|
+
this.specs = [];
|
|
19
|
+
this.renderSeq = 0;
|
|
20
|
+
this.renderImageUrl = "";
|
|
21
|
+
this.sourceSizeBySrc = new Map();
|
|
22
|
+
this.pendingSizeBySrc = new Map();
|
|
23
|
+
this.onCanvasResized = () => {
|
|
24
|
+
this.updateFilm();
|
|
25
|
+
};
|
|
14
26
|
if (options) {
|
|
15
27
|
Object.assign(this, options);
|
|
16
28
|
}
|
|
@@ -21,6 +33,17 @@ class FilmTool {
|
|
|
21
33
|
console.warn("CanvasService not found for FilmTool");
|
|
22
34
|
return;
|
|
23
35
|
}
|
|
36
|
+
this.renderProducerDisposable?.dispose();
|
|
37
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(this.id, () => ({
|
|
38
|
+
passes: [
|
|
39
|
+
{
|
|
40
|
+
id: FILM_LAYER_ID,
|
|
41
|
+
stack: 1000,
|
|
42
|
+
order: 0,
|
|
43
|
+
objects: this.specs,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
}), { priority: 500 });
|
|
24
47
|
const configService = context.services.get("ConfigurationService");
|
|
25
48
|
if (configService) {
|
|
26
49
|
// Load initial config
|
|
@@ -38,21 +61,21 @@ class FilmTool {
|
|
|
38
61
|
}
|
|
39
62
|
});
|
|
40
63
|
}
|
|
41
|
-
this.
|
|
64
|
+
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
42
65
|
this.updateFilm();
|
|
43
66
|
}
|
|
44
67
|
deactivate(context) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
69
|
+
this.renderSeq += 1;
|
|
70
|
+
this.specs = [];
|
|
71
|
+
this.renderImageUrl = "";
|
|
72
|
+
this.renderProducerDisposable?.dispose();
|
|
73
|
+
this.renderProducerDisposable = undefined;
|
|
74
|
+
if (!this.canvasService)
|
|
75
|
+
return;
|
|
76
|
+
void this.canvasService.flushRenderFromProducers();
|
|
77
|
+
this.canvasService.requestRenderAll();
|
|
78
|
+
this.canvasService = undefined;
|
|
56
79
|
}
|
|
57
80
|
contribute() {
|
|
58
81
|
return {
|
|
@@ -89,78 +112,114 @@ class FilmTool {
|
|
|
89
112
|
],
|
|
90
113
|
};
|
|
91
114
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const layer = this.canvasService.createLayer("overlay", {
|
|
100
|
-
width,
|
|
101
|
-
height,
|
|
102
|
-
left: 0,
|
|
103
|
-
top: 0,
|
|
104
|
-
originX: "left",
|
|
105
|
-
originY: "top",
|
|
106
|
-
selectable: false,
|
|
107
|
-
evented: false,
|
|
108
|
-
subTargetCheck: false,
|
|
109
|
-
interactive: false,
|
|
110
|
-
});
|
|
111
|
-
this.canvasService.canvas.bringObjectToFront(layer);
|
|
112
|
-
}
|
|
115
|
+
getViewportSize() {
|
|
116
|
+
const width = Number(this.canvasService?.canvas.width || 0);
|
|
117
|
+
const height = Number(this.canvasService?.canvas.height || 0);
|
|
118
|
+
return {
|
|
119
|
+
width: width > 0 ? width : DEFAULT_WIDTH,
|
|
120
|
+
height: height > 0 ? height : DEFAULT_HEIGHT,
|
|
121
|
+
};
|
|
113
122
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (!
|
|
119
|
-
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const { url, opacity } = this;
|
|
123
|
-
if (!url) {
|
|
124
|
-
const img = this.canvasService.getObject("film-image", "overlay");
|
|
125
|
-
if (img) {
|
|
126
|
-
layer.remove(img);
|
|
127
|
-
this.canvasService.requestRenderAll();
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
123
|
+
clampOpacity(value) {
|
|
124
|
+
return Math.max(0, Math.min(1, Number(value)));
|
|
125
|
+
}
|
|
126
|
+
buildFilmSpecs(imageUrl, opacity) {
|
|
127
|
+
if (!imageUrl) {
|
|
128
|
+
return [];
|
|
130
129
|
}
|
|
131
|
-
const width = this.
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
originY: "top",
|
|
130
|
+
const { width, height } = this.getViewportSize();
|
|
131
|
+
const sourceSize = this.sourceSizeBySrc.get(imageUrl);
|
|
132
|
+
const sourceWidth = Math.max(1, Number(sourceSize?.width || width));
|
|
133
|
+
const sourceHeight = Math.max(1, Number(sourceSize?.height || height));
|
|
134
|
+
const coverScale = Math.max(width / sourceWidth, height / sourceHeight);
|
|
135
|
+
return [
|
|
136
|
+
{
|
|
137
|
+
id: FILM_IMAGE_ID,
|
|
138
|
+
type: "image",
|
|
139
|
+
src: imageUrl,
|
|
140
|
+
space: "screen",
|
|
141
|
+
data: {
|
|
142
|
+
id: FILM_IMAGE_ID,
|
|
143
|
+
layerId: FILM_LAYER_ID,
|
|
144
|
+
type: "film-image",
|
|
145
|
+
},
|
|
146
|
+
props: {
|
|
149
147
|
left: 0,
|
|
150
148
|
top: 0,
|
|
151
|
-
|
|
149
|
+
originX: "left",
|
|
150
|
+
originY: "top",
|
|
151
|
+
opacity: this.clampOpacity(opacity),
|
|
152
|
+
scaleX: coverScale,
|
|
153
|
+
scaleY: coverScale,
|
|
152
154
|
selectable: false,
|
|
153
155
|
evented: false,
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
156
|
+
excludeFromExport: true,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
async ensureImageSize(src) {
|
|
162
|
+
if (!src)
|
|
163
|
+
return null;
|
|
164
|
+
const cached = this.sourceSizeBySrc.get(src);
|
|
165
|
+
if (cached)
|
|
166
|
+
return cached;
|
|
167
|
+
const pending = this.pendingSizeBySrc.get(src);
|
|
168
|
+
if (pending) {
|
|
169
|
+
return pending;
|
|
170
|
+
}
|
|
171
|
+
const task = this.loadImageSize(src);
|
|
172
|
+
this.pendingSizeBySrc.set(src, task);
|
|
173
|
+
try {
|
|
174
|
+
return await task;
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
if (this.pendingSizeBySrc.get(src) === task) {
|
|
178
|
+
this.pendingSizeBySrc.delete(src);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async loadImageSize(src) {
|
|
183
|
+
try {
|
|
184
|
+
const image = await fabric_1.FabricImage.fromURL(src, {
|
|
185
|
+
crossOrigin: "anonymous",
|
|
186
|
+
});
|
|
187
|
+
const width = Number(image?.width || 0);
|
|
188
|
+
const height = Number(image?.height || 0);
|
|
189
|
+
if (width > 0 && height > 0) {
|
|
190
|
+
const size = { width, height };
|
|
191
|
+
this.sourceSizeBySrc.set(src, size);
|
|
192
|
+
return size;
|
|
157
193
|
}
|
|
158
|
-
this.canvasService.requestRenderAll();
|
|
159
194
|
}
|
|
160
195
|
catch (error) {
|
|
161
|
-
console.error("[FilmTool] Failed to load film image",
|
|
196
|
+
console.error("[FilmTool] Failed to load film image", src, error);
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
updateFilm() {
|
|
201
|
+
void this.updateFilmAsync();
|
|
202
|
+
}
|
|
203
|
+
async updateFilmAsync() {
|
|
204
|
+
if (!this.canvasService)
|
|
205
|
+
return;
|
|
206
|
+
const seq = ++this.renderSeq;
|
|
207
|
+
const nextUrl = String(this.url || "").trim();
|
|
208
|
+
if (!nextUrl) {
|
|
209
|
+
this.renderImageUrl = "";
|
|
162
210
|
}
|
|
163
|
-
|
|
211
|
+
else if (nextUrl !== this.renderImageUrl) {
|
|
212
|
+
const loaded = await this.ensureImageSize(nextUrl);
|
|
213
|
+
if (seq !== this.renderSeq)
|
|
214
|
+
return;
|
|
215
|
+
if (loaded) {
|
|
216
|
+
this.renderImageUrl = nextUrl;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
this.specs = this.buildFilmSpecs(this.renderImageUrl, this.opacity);
|
|
220
|
+
await this.canvasService.flushRenderFromProducers();
|
|
221
|
+
if (seq !== this.renderSeq)
|
|
222
|
+
return;
|
|
164
223
|
this.canvasService.requestRenderAll();
|
|
165
224
|
}
|
|
166
225
|
}
|
|
@@ -5,13 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.resolveFeaturePosition = resolveFeaturePosition;
|
|
7
7
|
exports.generateDielinePath = generateDielinePath;
|
|
8
|
-
exports.generateMaskPath = generateMaskPath;
|
|
9
8
|
exports.generateBleedZonePath = generateBleedZonePath;
|
|
10
9
|
exports.getLowestPointOnDieline = getLowestPointOnDieline;
|
|
11
10
|
exports.getNearestPointOnDieline = getNearestPointOnDieline;
|
|
12
11
|
exports.getPathBounds = getPathBounds;
|
|
13
12
|
const paper_1 = __importDefault(require("paper"));
|
|
14
13
|
const bridgeSelection_1 = require("./bridgeSelection");
|
|
14
|
+
const dielineShape_1 = require("./dielineShape");
|
|
15
15
|
const wrappedOffsets_1 = require("./wrappedOffsets");
|
|
16
16
|
/**
|
|
17
17
|
* Resolves the absolute position of a feature based on normalized coordinates.
|
|
@@ -121,57 +121,142 @@ function selectOuterChain(args) {
|
|
|
121
121
|
return scoreA > scoreB ? pointsA : pointsB;
|
|
122
122
|
return pointsA.length <= pointsB.length ? pointsA : pointsB;
|
|
123
123
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
function fitPathItemToRect(item, rect, fitMode) {
|
|
125
|
+
const { left, top, width, height } = rect;
|
|
126
|
+
const bounds = item.bounds;
|
|
127
|
+
if (width <= 0 ||
|
|
128
|
+
height <= 0 ||
|
|
129
|
+
!Number.isFinite(bounds.width) ||
|
|
130
|
+
!Number.isFinite(bounds.height) ||
|
|
131
|
+
bounds.width <= 0 ||
|
|
132
|
+
bounds.height <= 0) {
|
|
133
|
+
item.position = new paper_1.default.Point(left + width / 2, top + height / 2);
|
|
134
|
+
return item;
|
|
135
|
+
}
|
|
136
|
+
item.translate(new paper_1.default.Point(-bounds.left, -bounds.top));
|
|
137
|
+
if (fitMode === "stretch") {
|
|
138
|
+
item.scale(width / bounds.width, height / bounds.height, new paper_1.default.Point(0, 0));
|
|
139
|
+
item.translate(new paper_1.default.Point(left, top));
|
|
140
|
+
return item;
|
|
141
|
+
}
|
|
142
|
+
const uniformScale = Math.min(width / bounds.width, height / bounds.height);
|
|
143
|
+
item.scale(uniformScale, uniformScale, new paper_1.default.Point(0, 0));
|
|
144
|
+
const scaledWidth = bounds.width * uniformScale;
|
|
145
|
+
const scaledHeight = bounds.height * uniformScale;
|
|
146
|
+
item.translate(new paper_1.default.Point(left + (width - scaledWidth) / 2, top + (height - scaledHeight) / 2));
|
|
147
|
+
return item;
|
|
148
|
+
}
|
|
149
|
+
function createNormalizedHeartPath(params) {
|
|
150
|
+
const { lobeSpread, notchDepth, tipSharpness } = params;
|
|
151
|
+
const halfSpread = 0.22 + lobeSpread * 0.18;
|
|
152
|
+
const notchY = 0.06 + notchDepth * 0.2;
|
|
153
|
+
const shoulderY = 0.24 + notchDepth * 0.2;
|
|
154
|
+
const topLift = 0.12 + (1 - notchDepth) * 0.06;
|
|
155
|
+
const topY = notchY - topLift;
|
|
156
|
+
const sideCtrlY = shoulderY - (0.18 - notchDepth * 0.08);
|
|
157
|
+
const lowerCtrlY = 0.58 + (1 - tipSharpness) * 0.16;
|
|
158
|
+
const tipCtrlX = 0.34 - tipSharpness * 0.2;
|
|
159
|
+
const notchCtrlX = 0.06 + lobeSpread * 0.06;
|
|
160
|
+
const lobeCtrlX = 0.1 + lobeSpread * 0.08;
|
|
161
|
+
const notchCtrlY = notchY - topLift * 0.45;
|
|
162
|
+
const xPeakL = 0.5 - halfSpread;
|
|
163
|
+
const xPeakR = 0.5 + halfSpread;
|
|
164
|
+
const heartPath = new paper_1.default.Path({ insert: false });
|
|
165
|
+
heartPath.moveTo(new paper_1.default.Point(0.5, notchY));
|
|
166
|
+
heartPath.cubicCurveTo(new paper_1.default.Point(0.5 - notchCtrlX, notchCtrlY), new paper_1.default.Point(xPeakL + lobeCtrlX, topY), new paper_1.default.Point(xPeakL, topY));
|
|
167
|
+
heartPath.cubicCurveTo(new paper_1.default.Point(xPeakL - lobeCtrlX, topY), new paper_1.default.Point(0, sideCtrlY), new paper_1.default.Point(0, shoulderY));
|
|
168
|
+
heartPath.cubicCurveTo(new paper_1.default.Point(0, lowerCtrlY), new paper_1.default.Point(tipCtrlX, 1), new paper_1.default.Point(0.5, 1));
|
|
169
|
+
heartPath.cubicCurveTo(new paper_1.default.Point(1 - tipCtrlX, 1), new paper_1.default.Point(1, lowerCtrlY), new paper_1.default.Point(1, shoulderY));
|
|
170
|
+
heartPath.cubicCurveTo(new paper_1.default.Point(1, sideCtrlY), new paper_1.default.Point(xPeakR + lobeCtrlX, topY), new paper_1.default.Point(xPeakR, topY));
|
|
171
|
+
heartPath.cubicCurveTo(new paper_1.default.Point(xPeakR - lobeCtrlX, topY), new paper_1.default.Point(0.5 + notchCtrlX, notchCtrlY), new paper_1.default.Point(0.5, notchY));
|
|
172
|
+
heartPath.closed = true;
|
|
173
|
+
return heartPath;
|
|
174
|
+
}
|
|
175
|
+
function createHeartBaseShape(options) {
|
|
176
|
+
const { x, y, width, height } = options;
|
|
177
|
+
const w = Math.max(0, width);
|
|
178
|
+
const h = Math.max(0, height);
|
|
179
|
+
const left = x - w / 2;
|
|
180
|
+
const top = y - h / 2;
|
|
181
|
+
const fitMode = (0, dielineShape_1.getShapeFitMode)(options.shapeStyle);
|
|
182
|
+
const heartParams = (0, dielineShape_1.getHeartShapeParams)(options.shapeStyle);
|
|
183
|
+
const rawHeart = createNormalizedHeartPath(heartParams);
|
|
184
|
+
return fitPathItemToRect(rawHeart, { left, top, width: w, height: h }, fitMode);
|
|
185
|
+
}
|
|
186
|
+
const BUILTIN_SHAPE_BUILDERS = {
|
|
187
|
+
rect: (options) => {
|
|
188
|
+
const { x, y, width, height, radius } = options;
|
|
131
189
|
return new paper_1.default.Path.Rectangle({
|
|
132
190
|
point: [x - width / 2, y - height / 2],
|
|
133
191
|
size: [Math.max(0, width), Math.max(0, height)],
|
|
134
192
|
radius: Math.max(0, radius),
|
|
135
193
|
});
|
|
136
|
-
}
|
|
137
|
-
|
|
194
|
+
},
|
|
195
|
+
circle: (options) => {
|
|
196
|
+
const { x, y, width, height } = options;
|
|
138
197
|
const r = Math.min(width, height) / 2;
|
|
139
198
|
return new paper_1.default.Path.Circle({
|
|
140
|
-
center:
|
|
199
|
+
center: new paper_1.default.Point(x, y),
|
|
141
200
|
radius: Math.max(0, r),
|
|
142
201
|
});
|
|
143
|
-
}
|
|
144
|
-
|
|
202
|
+
},
|
|
203
|
+
ellipse: (options) => {
|
|
204
|
+
const { x, y, width, height } = options;
|
|
145
205
|
return new paper_1.default.Path.Ellipse({
|
|
146
|
-
center:
|
|
206
|
+
center: new paper_1.default.Point(x, y),
|
|
147
207
|
radius: [Math.max(0, width / 2), Math.max(0, height / 2)],
|
|
148
208
|
});
|
|
209
|
+
},
|
|
210
|
+
heart: createHeartBaseShape,
|
|
211
|
+
};
|
|
212
|
+
function createCustomBaseShape(options) {
|
|
213
|
+
const { pathData, customSourceWidthPx, customSourceHeightPx, x, y, width, height, } = options;
|
|
214
|
+
if (typeof pathData !== "string" || pathData.trim().length === 0) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const center = new paper_1.default.Point(x, y);
|
|
218
|
+
const hasMultipleSubPaths = ((pathData.match(/[Mm]/g) || []).length ?? 0) > 1;
|
|
219
|
+
const path = hasMultipleSubPaths
|
|
220
|
+
? new paper_1.default.CompoundPath(pathData)
|
|
221
|
+
: (() => {
|
|
222
|
+
const single = new paper_1.default.Path();
|
|
223
|
+
single.pathData = pathData;
|
|
224
|
+
return single;
|
|
225
|
+
})();
|
|
226
|
+
const sourceWidth = Number(customSourceWidthPx ?? 0);
|
|
227
|
+
const sourceHeight = Number(customSourceHeightPx ?? 0);
|
|
228
|
+
if (Number.isFinite(sourceWidth) &&
|
|
229
|
+
Number.isFinite(sourceHeight) &&
|
|
230
|
+
sourceWidth > 0 &&
|
|
231
|
+
sourceHeight > 0 &&
|
|
232
|
+
width > 0 &&
|
|
233
|
+
height > 0) {
|
|
234
|
+
// Preserve original detect-space offset/expand by mapping source image
|
|
235
|
+
// coordinates directly into the target dieline frame.
|
|
236
|
+
const targetLeft = x - width / 2;
|
|
237
|
+
const targetTop = y - height / 2;
|
|
238
|
+
path.scale(width / sourceWidth, height / sourceHeight, new paper_1.default.Point(0, 0));
|
|
239
|
+
path.translate(new paper_1.default.Point(targetLeft, targetTop));
|
|
240
|
+
return path;
|
|
149
241
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const path = hasMultipleSubPaths
|
|
153
|
-
? new paper_1.default.CompoundPath(pathData)
|
|
154
|
-
: (() => {
|
|
155
|
-
const single = new paper_1.default.Path();
|
|
156
|
-
single.pathData = pathData;
|
|
157
|
-
return single;
|
|
158
|
-
})();
|
|
159
|
-
// Align center
|
|
242
|
+
if (width > 0 && height > 0 && path.bounds.width > 0 && path.bounds.height > 0) {
|
|
243
|
+
// Fallback for malformed custom-path metadata.
|
|
160
244
|
path.position = center;
|
|
161
|
-
|
|
162
|
-
height > 0 &&
|
|
163
|
-
path.bounds.width > 0 &&
|
|
164
|
-
path.bounds.height > 0) {
|
|
165
|
-
path.scale(width / path.bounds.width, height / path.bounds.height);
|
|
166
|
-
}
|
|
245
|
+
path.scale(width / path.bounds.width, height / path.bounds.height);
|
|
167
246
|
return path;
|
|
168
247
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
248
|
+
path.position = center;
|
|
249
|
+
return path;
|
|
250
|
+
}
|
|
251
|
+
function createBaseShape(options) {
|
|
252
|
+
const { shape } = options;
|
|
253
|
+
if (shape === "custom") {
|
|
254
|
+
const customShape = createCustomBaseShape(options);
|
|
255
|
+
if (customShape)
|
|
256
|
+
return customShape;
|
|
257
|
+
return BUILTIN_SHAPE_BUILDERS[dielineShape_1.DEFAULT_DIELINE_SHAPE](options);
|
|
174
258
|
}
|
|
259
|
+
return BUILTIN_SHAPE_BUILDERS[shape](options);
|
|
175
260
|
}
|
|
176
261
|
function resolveBridgeBasePath(shape, anchor) {
|
|
177
262
|
if (shape instanceof paper_1.default.Path) {
|
|
@@ -447,27 +532,6 @@ function generateDielinePath(options) {
|
|
|
447
532
|
finalShape.remove();
|
|
448
533
|
return pathData;
|
|
449
534
|
}
|
|
450
|
-
/**
|
|
451
|
-
* Generates the path data for the Mask (Background Overlay).
|
|
452
|
-
* Logic: Canvas SUBTRACT ProductShape
|
|
453
|
-
*/
|
|
454
|
-
function generateMaskPath(options) {
|
|
455
|
-
ensurePaper(options.canvasWidth, options.canvasHeight);
|
|
456
|
-
paper_1.default.project.activeLayer.removeChildren();
|
|
457
|
-
const { canvasWidth, canvasHeight } = options;
|
|
458
|
-
const maskRect = new paper_1.default.Path.Rectangle({
|
|
459
|
-
point: [0, 0],
|
|
460
|
-
size: [canvasWidth, canvasHeight],
|
|
461
|
-
});
|
|
462
|
-
const perimeter = getPerimeterShape(options);
|
|
463
|
-
const mainShape = applySurfaceFeatures(perimeter, options.features, options);
|
|
464
|
-
const finalMask = maskRect.subtract(mainShape);
|
|
465
|
-
maskRect.remove();
|
|
466
|
-
mainShape.remove();
|
|
467
|
-
const pathData = finalMask.pathData;
|
|
468
|
-
finalMask.remove();
|
|
469
|
-
return pathData;
|
|
470
|
-
}
|
|
471
535
|
/**
|
|
472
536
|
* Generates the path data for the Bleed Zone.
|
|
473
537
|
*/
|