@pooder/kit 5.3.1 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/index.d.mts +243 -36
- package/dist/index.d.ts +243 -36
- package/dist/index.js +2278 -1041
- package/dist/index.mjs +2278 -1041
- package/package.json +1 -1
- package/src/coordinate.ts +106 -106
- package/src/extensions/background.ts +323 -230
- package/src/extensions/bridgeSelection.ts +17 -17
- package/src/extensions/constraints.ts +322 -322
- package/src/extensions/dieline.ts +1149 -1076
- package/src/extensions/dielineShape.ts +109 -0
- package/src/extensions/edgeScale.ts +19 -19
- package/src/extensions/feature.ts +1137 -1021
- package/src/extensions/featureComplete.ts +46 -46
- package/src/extensions/film.ts +266 -194
- package/src/extensions/geometry.ts +885 -752
- package/src/extensions/image.ts +2054 -1926
- package/src/extensions/index.ts +11 -11
- package/src/extensions/maskOps.ts +283 -283
- package/src/extensions/mirror.ts +128 -128
- package/src/extensions/ruler.ts +654 -451
- package/src/extensions/sceneLayout.ts +140 -140
- package/src/extensions/sceneLayoutModel.ts +364 -352
- package/src/extensions/sceneVisibility.ts +64 -71
- package/src/extensions/size.ts +389 -389
- package/src/extensions/tracer.ts +1019 -1019
- package/src/extensions/white-ink.ts +1567 -1514
- package/src/extensions/wrappedOffsets.ts +33 -33
- package/src/index.ts +2 -2
- package/src/services/CanvasService.ts +832 -300
- package/src/services/ViewportSystem.ts +95 -95
- package/src/services/index.ts +3 -3
- package/src/services/renderSpec.ts +53 -18
- package/src/units.ts +27 -27
- package/tests/run.ts +118 -118
- package/tsconfig.test.json +15 -15
- 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/coordinate.js +0 -74
- package/.test-dist/src/dieline.js +0 -818
- package/.test-dist/src/edgeScale.js +0 -12
- package/.test-dist/src/extensions/background.js +0 -203
- package/.test-dist/src/extensions/bridgeSelection.js +0 -20
- package/.test-dist/src/extensions/constraints.js +0 -237
- package/.test-dist/src/extensions/dieline.js +0 -828
- package/.test-dist/src/extensions/edgeScale.js +0 -12
- package/.test-dist/src/extensions/feature.js +0 -825
- package/.test-dist/src/extensions/featureComplete.js +0 -32
- package/.test-dist/src/extensions/film.js +0 -167
- package/.test-dist/src/extensions/geometry.js +0 -545
- package/.test-dist/src/extensions/image.js +0 -1529
- package/.test-dist/src/extensions/index.js +0 -30
- package/.test-dist/src/extensions/maskOps.js +0 -279
- package/.test-dist/src/extensions/mirror.js +0 -104
- package/.test-dist/src/extensions/ruler.js +0 -345
- package/.test-dist/src/extensions/sceneLayout.js +0 -96
- package/.test-dist/src/extensions/sceneLayoutModel.js +0 -196
- package/.test-dist/src/extensions/sceneVisibility.js +0 -62
- package/.test-dist/src/extensions/size.js +0 -331
- package/.test-dist/src/extensions/tracer.js +0 -538
- package/.test-dist/src/extensions/white-ink.js +0 -1190
- package/.test-dist/src/extensions/wrappedOffsets.js +0 -33
- 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/index.js +0 -18
- 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/services/CanvasService.js +0 -249
- package/.test-dist/src/services/ViewportSystem.js +0 -76
- package/.test-dist/src/services/index.js +0 -24
- package/.test-dist/src/services/renderSpec.js +0 -2
- package/.test-dist/src/size.js +0 -332
- package/.test-dist/src/tracer.js +0 -544
- package/.test-dist/src/units.js +0 -30
- package/.test-dist/src/white-ink.js +0 -829
- package/.test-dist/src/wrappedOffsets.js +0 -33
- package/.test-dist/tests/run.js +0 -94
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ContributionPointIds
|
|
4
4
|
} from "@pooder/core";
|
|
5
|
-
import {
|
|
5
|
+
import { FabricImage } from "fabric";
|
|
6
|
+
var BACKGROUND_LAYER_ID = "background";
|
|
7
|
+
var BACKGROUND_RECT_ID = "background-color-rect";
|
|
8
|
+
var BACKGROUND_IMAGE_ID = "background-image";
|
|
9
|
+
var DEFAULT_WIDTH = 800;
|
|
10
|
+
var DEFAULT_HEIGHT = 600;
|
|
6
11
|
var BackgroundTool = class {
|
|
7
12
|
constructor(options) {
|
|
8
13
|
this.id = "pooder.kit.background";
|
|
@@ -11,17 +16,38 @@ var BackgroundTool = class {
|
|
|
11
16
|
};
|
|
12
17
|
this.color = "";
|
|
13
18
|
this.url = "";
|
|
19
|
+
this.specs = [];
|
|
20
|
+
this.renderSeq = 0;
|
|
21
|
+
this.renderImageUrl = "";
|
|
22
|
+
this.sourceSizeBySrc = /* @__PURE__ */ new Map();
|
|
23
|
+
this.pendingSizeBySrc = /* @__PURE__ */ new Map();
|
|
24
|
+
this.onCanvasResized = () => {
|
|
25
|
+
this.updateBackground();
|
|
26
|
+
};
|
|
14
27
|
if (options) {
|
|
15
28
|
Object.assign(this, options);
|
|
16
29
|
}
|
|
17
30
|
}
|
|
18
31
|
activate(context) {
|
|
32
|
+
var _a;
|
|
19
33
|
this.canvasService = context.services.get("CanvasService");
|
|
20
34
|
if (!this.canvasService) {
|
|
21
35
|
console.warn("CanvasService not found for BackgroundTool");
|
|
22
36
|
return;
|
|
23
37
|
}
|
|
24
|
-
|
|
38
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
39
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
40
|
+
this.id,
|
|
41
|
+
() => ({
|
|
42
|
+
layerSpecs: {
|
|
43
|
+
[BACKGROUND_LAYER_ID]: this.specs
|
|
44
|
+
}
|
|
45
|
+
}),
|
|
46
|
+
{ priority: 0 }
|
|
47
|
+
);
|
|
48
|
+
const configService = context.services.get(
|
|
49
|
+
"ConfigurationService"
|
|
50
|
+
);
|
|
25
51
|
if (configService) {
|
|
26
52
|
this.color = configService.get("background.color", this.color);
|
|
27
53
|
this.url = configService.get("background.url", this.url);
|
|
@@ -45,17 +71,25 @@ var BackgroundTool = class {
|
|
|
45
71
|
}
|
|
46
72
|
});
|
|
47
73
|
}
|
|
48
|
-
this.
|
|
74
|
+
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
49
75
|
this.updateBackground();
|
|
50
76
|
}
|
|
51
77
|
deactivate(context) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
var _a;
|
|
79
|
+
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
80
|
+
this.renderSeq += 1;
|
|
81
|
+
this.specs = [];
|
|
82
|
+
this.renderImageUrl = "";
|
|
83
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
84
|
+
this.renderProducerDisposable = void 0;
|
|
85
|
+
if (!this.canvasService) return;
|
|
86
|
+
const layer = this.canvasService.getLayer(BACKGROUND_LAYER_ID);
|
|
87
|
+
if (layer) {
|
|
88
|
+
this.canvasService.canvas.remove(layer);
|
|
58
89
|
}
|
|
90
|
+
void this.canvasService.flushRenderFromProducers();
|
|
91
|
+
this.canvasService.requestRenderAll();
|
|
92
|
+
this.canvasService = void 0;
|
|
59
93
|
}
|
|
60
94
|
contribute() {
|
|
61
95
|
return {
|
|
@@ -115,88 +149,131 @@ var BackgroundTool = class {
|
|
|
115
149
|
]
|
|
116
150
|
};
|
|
117
151
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
evented: false
|
|
127
|
-
});
|
|
128
|
-
this.canvasService.canvas.sendObjectToBack(backgroundLayer);
|
|
129
|
-
}
|
|
152
|
+
getViewportSize() {
|
|
153
|
+
var _a, _b;
|
|
154
|
+
const width = Number(((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 0);
|
|
155
|
+
const height = Number(((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 0);
|
|
156
|
+
return {
|
|
157
|
+
width: width > 0 ? width : DEFAULT_WIDTH,
|
|
158
|
+
height: height > 0 ? height : DEFAULT_HEIGHT
|
|
159
|
+
};
|
|
130
160
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
161
|
+
buildBackgroundSpecs(color, imageUrl) {
|
|
162
|
+
const { width, height } = this.getViewportSize();
|
|
163
|
+
const specs = [
|
|
164
|
+
{
|
|
165
|
+
id: BACKGROUND_RECT_ID,
|
|
166
|
+
type: "rect",
|
|
167
|
+
space: "screen",
|
|
168
|
+
data: {
|
|
169
|
+
id: BACKGROUND_RECT_ID,
|
|
170
|
+
layerId: BACKGROUND_LAYER_ID,
|
|
171
|
+
type: "background-color"
|
|
172
|
+
},
|
|
173
|
+
props: {
|
|
174
|
+
left: 0,
|
|
175
|
+
top: 0,
|
|
176
|
+
width,
|
|
177
|
+
height,
|
|
178
|
+
originX: "left",
|
|
179
|
+
originY: "top",
|
|
180
|
+
fill: color,
|
|
181
|
+
selectable: false,
|
|
182
|
+
evented: false,
|
|
183
|
+
excludeFromExport: true
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
];
|
|
187
|
+
if (!imageUrl) {
|
|
188
|
+
return specs;
|
|
137
189
|
}
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
190
|
+
const sourceSize = this.sourceSizeBySrc.get(imageUrl);
|
|
191
|
+
const sourceWidth = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.width) || width));
|
|
192
|
+
const sourceHeight = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.height) || height));
|
|
193
|
+
const coverScale = Math.max(width / sourceWidth, height / sourceHeight);
|
|
194
|
+
specs.push({
|
|
195
|
+
id: BACKGROUND_IMAGE_ID,
|
|
196
|
+
type: "image",
|
|
197
|
+
src: imageUrl,
|
|
198
|
+
space: "screen",
|
|
199
|
+
data: {
|
|
200
|
+
id: BACKGROUND_IMAGE_ID,
|
|
201
|
+
layerId: BACKGROUND_LAYER_ID,
|
|
202
|
+
type: "background-image"
|
|
203
|
+
},
|
|
204
|
+
props: {
|
|
205
|
+
left: 0,
|
|
206
|
+
top: 0,
|
|
207
|
+
originX: "left",
|
|
208
|
+
originY: "top",
|
|
209
|
+
scaleX: coverScale,
|
|
210
|
+
scaleY: coverScale,
|
|
154
211
|
selectable: false,
|
|
155
212
|
evented: false,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
213
|
+
excludeFromExport: true
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
return specs;
|
|
217
|
+
}
|
|
218
|
+
async ensureImageSize(src) {
|
|
219
|
+
if (!src) return null;
|
|
220
|
+
const cached = this.sourceSizeBySrc.get(src);
|
|
221
|
+
if (cached) return cached;
|
|
222
|
+
const pending = this.pendingSizeBySrc.get(src);
|
|
223
|
+
if (pending) {
|
|
224
|
+
return pending;
|
|
162
225
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"background"
|
|
166
|
-
);
|
|
226
|
+
const task = this.loadImageSize(src);
|
|
227
|
+
this.pendingSizeBySrc.set(src, task);
|
|
167
228
|
try {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
} else {
|
|
173
|
-
layer.remove(img);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
if (url) {
|
|
178
|
-
img = await Image2.fromURL(url, { crossOrigin: "anonymous" });
|
|
179
|
-
img.set({
|
|
180
|
-
originX: "left",
|
|
181
|
-
originY: "top",
|
|
182
|
-
left: 0,
|
|
183
|
-
top: 0,
|
|
184
|
-
selectable: false,
|
|
185
|
-
evented: false,
|
|
186
|
-
data: {
|
|
187
|
-
id: "background-image"
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
img.scaleToWidth(width);
|
|
191
|
-
if (img.getScaledHeight() < height) img.scaleToHeight(height);
|
|
192
|
-
layer.add(img);
|
|
193
|
-
}
|
|
229
|
+
return await task;
|
|
230
|
+
} finally {
|
|
231
|
+
if (this.pendingSizeBySrc.get(src) === task) {
|
|
232
|
+
this.pendingSizeBySrc.delete(src);
|
|
194
233
|
}
|
|
195
|
-
this.canvasService.requestRenderAll();
|
|
196
|
-
} catch (e) {
|
|
197
|
-
console.error("[BackgroundTool] Failed to load image", e);
|
|
198
234
|
}
|
|
199
|
-
|
|
235
|
+
}
|
|
236
|
+
async loadImageSize(src) {
|
|
237
|
+
try {
|
|
238
|
+
const image = await FabricImage.fromURL(src, {
|
|
239
|
+
crossOrigin: "anonymous"
|
|
240
|
+
});
|
|
241
|
+
const width = Number((image == null ? void 0 : image.width) || 0);
|
|
242
|
+
const height = Number((image == null ? void 0 : image.height) || 0);
|
|
243
|
+
if (width > 0 && height > 0) {
|
|
244
|
+
const size = { width, height };
|
|
245
|
+
this.sourceSizeBySrc.set(src, size);
|
|
246
|
+
return size;
|
|
247
|
+
}
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.error("[BackgroundTool] Failed to load image", src, error);
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
updateBackground() {
|
|
254
|
+
void this.updateBackgroundAsync();
|
|
255
|
+
}
|
|
256
|
+
async updateBackgroundAsync() {
|
|
257
|
+
if (!this.canvasService) return;
|
|
258
|
+
const seq = ++this.renderSeq;
|
|
259
|
+
const color = this.color;
|
|
260
|
+
const nextUrl = String(this.url || "").trim();
|
|
261
|
+
if (!nextUrl) {
|
|
262
|
+
this.renderImageUrl = "";
|
|
263
|
+
} else if (nextUrl !== this.renderImageUrl) {
|
|
264
|
+
const loaded = await this.ensureImageSize(nextUrl);
|
|
265
|
+
if (seq !== this.renderSeq) return;
|
|
266
|
+
if (loaded) {
|
|
267
|
+
this.renderImageUrl = nextUrl;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
this.specs = this.buildBackgroundSpecs(color, this.renderImageUrl);
|
|
271
|
+
await this.canvasService.flushRenderFromProducers();
|
|
272
|
+
if (seq !== this.renderSeq) return;
|
|
273
|
+
const layer = this.canvasService.getLayer(BACKGROUND_LAYER_ID);
|
|
274
|
+
if (layer) {
|
|
275
|
+
this.canvasService.canvas.sendObjectToBack(layer);
|
|
276
|
+
}
|
|
200
277
|
this.canvasService.requestRenderAll();
|
|
201
278
|
}
|
|
202
279
|
};
|
|
@@ -207,11 +284,76 @@ import {
|
|
|
207
284
|
} from "@pooder/core";
|
|
208
285
|
import {
|
|
209
286
|
Canvas as FabricCanvas,
|
|
210
|
-
Image as
|
|
287
|
+
Image as FabricImage2,
|
|
211
288
|
Pattern,
|
|
212
289
|
Point
|
|
213
290
|
} from "fabric";
|
|
214
291
|
|
|
292
|
+
// src/extensions/dielineShape.ts
|
|
293
|
+
var BUILTIN_DIELINE_SHAPES = [
|
|
294
|
+
"rect",
|
|
295
|
+
"circle",
|
|
296
|
+
"ellipse",
|
|
297
|
+
"heart"
|
|
298
|
+
];
|
|
299
|
+
var DIELINE_SHAPES = [...BUILTIN_DIELINE_SHAPES, "custom"];
|
|
300
|
+
var DEFAULT_DIELINE_SHAPE = "rect";
|
|
301
|
+
var DEFAULT_HEART_SHAPE_PARAMS = {
|
|
302
|
+
lobeSpread: 0.46,
|
|
303
|
+
notchDepth: 0.24,
|
|
304
|
+
tipSharpness: 0
|
|
305
|
+
};
|
|
306
|
+
var DEFAULT_DIELINE_SHAPE_STYLE = {
|
|
307
|
+
fitMode: "contain",
|
|
308
|
+
...DEFAULT_HEART_SHAPE_PARAMS
|
|
309
|
+
};
|
|
310
|
+
function isDielineShape(value) {
|
|
311
|
+
return typeof value === "string" && DIELINE_SHAPES.includes(value);
|
|
312
|
+
}
|
|
313
|
+
function normalizeFitMode(value, fallback) {
|
|
314
|
+
if (value === "contain" || value === "stretch") return value;
|
|
315
|
+
return fallback;
|
|
316
|
+
}
|
|
317
|
+
function normalizeUnitInterval(value, fallback) {
|
|
318
|
+
const num = Number(value);
|
|
319
|
+
if (!Number.isFinite(num)) return fallback;
|
|
320
|
+
return Math.max(0, Math.min(1, num));
|
|
321
|
+
}
|
|
322
|
+
function normalizeDielineShape(value, fallback = DEFAULT_DIELINE_SHAPE) {
|
|
323
|
+
return isDielineShape(value) ? value : fallback;
|
|
324
|
+
}
|
|
325
|
+
function normalizeShapeStyle(value, fallback = DEFAULT_DIELINE_SHAPE_STYLE) {
|
|
326
|
+
var _a, _b, _c;
|
|
327
|
+
const raw = value && typeof value === "object" ? value : {};
|
|
328
|
+
return {
|
|
329
|
+
...fallback,
|
|
330
|
+
fitMode: normalizeFitMode(raw.fitMode, fallback.fitMode),
|
|
331
|
+
lobeSpread: normalizeUnitInterval(
|
|
332
|
+
raw.lobeSpread,
|
|
333
|
+
Number((_a = fallback.lobeSpread) != null ? _a : DEFAULT_HEART_SHAPE_PARAMS.lobeSpread)
|
|
334
|
+
),
|
|
335
|
+
notchDepth: normalizeUnitInterval(
|
|
336
|
+
raw.notchDepth,
|
|
337
|
+
Number((_b = fallback.notchDepth) != null ? _b : DEFAULT_HEART_SHAPE_PARAMS.notchDepth)
|
|
338
|
+
),
|
|
339
|
+
tipSharpness: normalizeUnitInterval(
|
|
340
|
+
raw.tipSharpness,
|
|
341
|
+
Number((_c = fallback.tipSharpness) != null ? _c : DEFAULT_HEART_SHAPE_PARAMS.tipSharpness)
|
|
342
|
+
)
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function getShapeFitMode(style) {
|
|
346
|
+
return normalizeShapeStyle(style).fitMode;
|
|
347
|
+
}
|
|
348
|
+
function getHeartShapeParams(style) {
|
|
349
|
+
const normalized = normalizeShapeStyle(style);
|
|
350
|
+
return {
|
|
351
|
+
lobeSpread: Number(normalized.lobeSpread),
|
|
352
|
+
notchDepth: Number(normalized.notchDepth),
|
|
353
|
+
tipSharpness: Number(normalized.tipSharpness)
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
215
357
|
// src/extensions/geometry.ts
|
|
216
358
|
import paper from "paper";
|
|
217
359
|
|
|
@@ -354,66 +496,164 @@ function selectOuterChain(args) {
|
|
|
354
496
|
if (scoreA !== scoreB) return scoreA > scoreB ? pointsA : pointsB;
|
|
355
497
|
return pointsA.length <= pointsB.length ? pointsA : pointsB;
|
|
356
498
|
}
|
|
357
|
-
function
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
width,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
const
|
|
371
|
-
|
|
499
|
+
function fitPathItemToRect(item, rect, fitMode) {
|
|
500
|
+
const { left, top, width, height } = rect;
|
|
501
|
+
const bounds = item.bounds;
|
|
502
|
+
if (width <= 0 || height <= 0 || !Number.isFinite(bounds.width) || !Number.isFinite(bounds.height) || bounds.width <= 0 || bounds.height <= 0) {
|
|
503
|
+
item.position = new paper.Point(left + width / 2, top + height / 2);
|
|
504
|
+
return item;
|
|
505
|
+
}
|
|
506
|
+
item.translate(new paper.Point(-bounds.left, -bounds.top));
|
|
507
|
+
if (fitMode === "stretch") {
|
|
508
|
+
item.scale(width / bounds.width, height / bounds.height, new paper.Point(0, 0));
|
|
509
|
+
item.translate(new paper.Point(left, top));
|
|
510
|
+
return item;
|
|
511
|
+
}
|
|
512
|
+
const uniformScale = Math.min(width / bounds.width, height / bounds.height);
|
|
513
|
+
item.scale(uniformScale, uniformScale, new paper.Point(0, 0));
|
|
514
|
+
const scaledWidth = bounds.width * uniformScale;
|
|
515
|
+
const scaledHeight = bounds.height * uniformScale;
|
|
516
|
+
item.translate(
|
|
517
|
+
new paper.Point(
|
|
518
|
+
left + (width - scaledWidth) / 2,
|
|
519
|
+
top + (height - scaledHeight) / 2
|
|
520
|
+
)
|
|
521
|
+
);
|
|
522
|
+
return item;
|
|
523
|
+
}
|
|
524
|
+
function createNormalizedHeartPath(params) {
|
|
525
|
+
const { lobeSpread, notchDepth, tipSharpness } = params;
|
|
526
|
+
const halfSpread = 0.22 + lobeSpread * 0.18;
|
|
527
|
+
const notchY = 0.06 + notchDepth * 0.2;
|
|
528
|
+
const shoulderY = 0.24 + notchDepth * 0.2;
|
|
529
|
+
const topLift = 0.12 + (1 - notchDepth) * 0.06;
|
|
530
|
+
const topY = notchY - topLift;
|
|
531
|
+
const sideCtrlY = shoulderY - (0.18 - notchDepth * 0.08);
|
|
532
|
+
const lowerCtrlY = 0.58 + (1 - tipSharpness) * 0.16;
|
|
533
|
+
const tipCtrlX = 0.34 - tipSharpness * 0.2;
|
|
534
|
+
const notchCtrlX = 0.06 + lobeSpread * 0.06;
|
|
535
|
+
const lobeCtrlX = 0.1 + lobeSpread * 0.08;
|
|
536
|
+
const notchCtrlY = notchY - topLift * 0.45;
|
|
537
|
+
const xPeakL = 0.5 - halfSpread;
|
|
538
|
+
const xPeakR = 0.5 + halfSpread;
|
|
539
|
+
const heartPath = new paper.Path({ insert: false });
|
|
540
|
+
heartPath.moveTo(new paper.Point(0.5, notchY));
|
|
541
|
+
heartPath.cubicCurveTo(
|
|
542
|
+
new paper.Point(0.5 - notchCtrlX, notchCtrlY),
|
|
543
|
+
new paper.Point(xPeakL + lobeCtrlX, topY),
|
|
544
|
+
new paper.Point(xPeakL, topY)
|
|
545
|
+
);
|
|
546
|
+
heartPath.cubicCurveTo(
|
|
547
|
+
new paper.Point(xPeakL - lobeCtrlX, topY),
|
|
548
|
+
new paper.Point(0, sideCtrlY),
|
|
549
|
+
new paper.Point(0, shoulderY)
|
|
550
|
+
);
|
|
551
|
+
heartPath.cubicCurveTo(
|
|
552
|
+
new paper.Point(0, lowerCtrlY),
|
|
553
|
+
new paper.Point(tipCtrlX, 1),
|
|
554
|
+
new paper.Point(0.5, 1)
|
|
555
|
+
);
|
|
556
|
+
heartPath.cubicCurveTo(
|
|
557
|
+
new paper.Point(1 - tipCtrlX, 1),
|
|
558
|
+
new paper.Point(1, lowerCtrlY),
|
|
559
|
+
new paper.Point(1, shoulderY)
|
|
560
|
+
);
|
|
561
|
+
heartPath.cubicCurveTo(
|
|
562
|
+
new paper.Point(1, sideCtrlY),
|
|
563
|
+
new paper.Point(xPeakR + lobeCtrlX, topY),
|
|
564
|
+
new paper.Point(xPeakR, topY)
|
|
565
|
+
);
|
|
566
|
+
heartPath.cubicCurveTo(
|
|
567
|
+
new paper.Point(xPeakR - lobeCtrlX, topY),
|
|
568
|
+
new paper.Point(0.5 + notchCtrlX, notchCtrlY),
|
|
569
|
+
new paper.Point(0.5, notchY)
|
|
570
|
+
);
|
|
571
|
+
heartPath.closed = true;
|
|
572
|
+
return heartPath;
|
|
573
|
+
}
|
|
574
|
+
function createHeartBaseShape(options) {
|
|
575
|
+
const { x, y, width, height } = options;
|
|
576
|
+
const w = Math.max(0, width);
|
|
577
|
+
const h = Math.max(0, height);
|
|
578
|
+
const left = x - w / 2;
|
|
579
|
+
const top = y - h / 2;
|
|
580
|
+
const fitMode = getShapeFitMode(options.shapeStyle);
|
|
581
|
+
const heartParams = getHeartShapeParams(options.shapeStyle);
|
|
582
|
+
const rawHeart = createNormalizedHeartPath(heartParams);
|
|
583
|
+
return fitPathItemToRect(rawHeart, { left, top, width: w, height: h }, fitMode);
|
|
584
|
+
}
|
|
585
|
+
var BUILTIN_SHAPE_BUILDERS = {
|
|
586
|
+
rect: (options) => {
|
|
587
|
+
const { x, y, width, height, radius } = options;
|
|
372
588
|
return new paper.Path.Rectangle({
|
|
373
589
|
point: [x - width / 2, y - height / 2],
|
|
374
590
|
size: [Math.max(0, width), Math.max(0, height)],
|
|
375
591
|
radius: Math.max(0, radius)
|
|
376
592
|
});
|
|
377
|
-
}
|
|
593
|
+
},
|
|
594
|
+
circle: (options) => {
|
|
595
|
+
const { x, y, width, height } = options;
|
|
378
596
|
const r = Math.min(width, height) / 2;
|
|
379
597
|
return new paper.Path.Circle({
|
|
380
|
-
center,
|
|
598
|
+
center: new paper.Point(x, y),
|
|
381
599
|
radius: Math.max(0, r)
|
|
382
600
|
});
|
|
383
|
-
}
|
|
601
|
+
},
|
|
602
|
+
ellipse: (options) => {
|
|
603
|
+
const { x, y, width, height } = options;
|
|
384
604
|
return new paper.Path.Ellipse({
|
|
385
|
-
center,
|
|
605
|
+
center: new paper.Point(x, y),
|
|
386
606
|
radius: [Math.max(0, width / 2), Math.max(0, height / 2)]
|
|
387
607
|
});
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
608
|
+
},
|
|
609
|
+
heart: createHeartBaseShape
|
|
610
|
+
};
|
|
611
|
+
function createCustomBaseShape(options) {
|
|
612
|
+
var _a;
|
|
613
|
+
const {
|
|
614
|
+
pathData,
|
|
615
|
+
customSourceWidthPx,
|
|
616
|
+
customSourceHeightPx,
|
|
617
|
+
x,
|
|
618
|
+
y,
|
|
619
|
+
width,
|
|
620
|
+
height
|
|
621
|
+
} = options;
|
|
622
|
+
if (typeof pathData !== "string" || pathData.trim().length === 0) {
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
const center = new paper.Point(x, y);
|
|
626
|
+
const hasMultipleSubPaths = ((_a = (pathData.match(/[Mm]/g) || []).length) != null ? _a : 0) > 1;
|
|
627
|
+
const path = hasMultipleSubPaths ? new paper.CompoundPath(pathData) : (() => {
|
|
628
|
+
const single = new paper.Path();
|
|
629
|
+
single.pathData = pathData;
|
|
630
|
+
return single;
|
|
631
|
+
})();
|
|
632
|
+
const sourceWidth = Number(customSourceWidthPx != null ? customSourceWidthPx : 0);
|
|
633
|
+
const sourceHeight = Number(customSourceHeightPx != null ? customSourceHeightPx : 0);
|
|
634
|
+
if (Number.isFinite(sourceWidth) && Number.isFinite(sourceHeight) && sourceWidth > 0 && sourceHeight > 0 && width > 0 && height > 0) {
|
|
635
|
+
const targetLeft = x - width / 2;
|
|
636
|
+
const targetTop = y - height / 2;
|
|
637
|
+
path.scale(width / sourceWidth, height / sourceHeight, new paper.Point(0, 0));
|
|
638
|
+
path.translate(new paper.Point(targetLeft, targetTop));
|
|
639
|
+
return path;
|
|
640
|
+
}
|
|
641
|
+
if (width > 0 && height > 0 && path.bounds.width > 0 && path.bounds.height > 0) {
|
|
409
642
|
path.position = center;
|
|
643
|
+
path.scale(width / path.bounds.width, height / path.bounds.height);
|
|
410
644
|
return path;
|
|
411
|
-
} else {
|
|
412
|
-
return new paper.Path.Rectangle({
|
|
413
|
-
point: [x - width / 2, y - height / 2],
|
|
414
|
-
size: [Math.max(0, width), Math.max(0, height)]
|
|
415
|
-
});
|
|
416
645
|
}
|
|
646
|
+
path.position = center;
|
|
647
|
+
return path;
|
|
648
|
+
}
|
|
649
|
+
function createBaseShape(options) {
|
|
650
|
+
const { shape } = options;
|
|
651
|
+
if (shape === "custom") {
|
|
652
|
+
const customShape = createCustomBaseShape(options);
|
|
653
|
+
if (customShape) return customShape;
|
|
654
|
+
return BUILTIN_SHAPE_BUILDERS[DEFAULT_DIELINE_SHAPE](options);
|
|
655
|
+
}
|
|
656
|
+
return BUILTIN_SHAPE_BUILDERS[shape](options);
|
|
417
657
|
}
|
|
418
658
|
function resolveBridgeBasePath(shape, anchor) {
|
|
419
659
|
if (shape instanceof paper.Path) {
|
|
@@ -737,6 +977,18 @@ function getNearestPointOnDieline(point, options) {
|
|
|
737
977
|
shape.remove();
|
|
738
978
|
return result;
|
|
739
979
|
}
|
|
980
|
+
function getPathBounds(pathData) {
|
|
981
|
+
const path = new paper.Path();
|
|
982
|
+
path.pathData = pathData;
|
|
983
|
+
const bounds = path.bounds;
|
|
984
|
+
path.remove();
|
|
985
|
+
return {
|
|
986
|
+
x: bounds.x,
|
|
987
|
+
y: bounds.y,
|
|
988
|
+
width: bounds.width,
|
|
989
|
+
height: bounds.height
|
|
990
|
+
};
|
|
991
|
+
}
|
|
740
992
|
|
|
741
993
|
// src/coordinate.ts
|
|
742
994
|
var Coordinate = class {
|
|
@@ -825,12 +1077,6 @@ function parseLengthToMm(input, defaultUnit) {
|
|
|
825
1077
|
const unit = (_b = (_a = match[2]) == null ? void 0 : _a.toLowerCase()) != null ? _b : defaultUnit;
|
|
826
1078
|
return Coordinate.convertUnit(value, unit, "mm");
|
|
827
1079
|
}
|
|
828
|
-
function formatMm(valueMm, displayUnit, fractionDigits = 2) {
|
|
829
|
-
if (!Number.isFinite(valueMm)) return "0";
|
|
830
|
-
const value = Coordinate.convertUnit(valueMm, "mm", displayUnit);
|
|
831
|
-
const rounded = Number(value.toFixed(fractionDigits));
|
|
832
|
-
return rounded.toString();
|
|
833
|
-
}
|
|
834
1080
|
|
|
835
1081
|
// src/extensions/sceneLayoutModel.ts
|
|
836
1082
|
var DEFAULT_SIZE_STATE = {
|
|
@@ -1045,10 +1291,15 @@ function buildSceneGeometry(configService, layout) {
|
|
|
1045
1291
|
const sourceHeight = Number(
|
|
1046
1292
|
configService.get("dieline.customSourceHeightPx", 0)
|
|
1047
1293
|
);
|
|
1294
|
+
const shapeStyle = normalizeShapeStyle(
|
|
1295
|
+
configService.get("dieline.shapeStyle", DEFAULT_DIELINE_SHAPE_STYLE)
|
|
1296
|
+
);
|
|
1048
1297
|
return {
|
|
1049
|
-
shape:
|
|
1050
|
-
|
|
1051
|
-
|
|
1298
|
+
shape: normalizeDielineShape(
|
|
1299
|
+
configService.get("dieline.shape", DEFAULT_DIELINE_SHAPE)
|
|
1300
|
+
),
|
|
1301
|
+
shapeStyle,
|
|
1302
|
+
unit: "px",
|
|
1052
1303
|
x: layout.trimRect.centerX,
|
|
1053
1304
|
y: layout.trimRect.centerY,
|
|
1054
1305
|
width: layout.trimRect.width,
|
|
@@ -1081,6 +1332,7 @@ var ImageTool = class {
|
|
|
1081
1332
|
this.isImageSelectionActive = false;
|
|
1082
1333
|
this.focusedImageId = null;
|
|
1083
1334
|
this.renderSeq = 0;
|
|
1335
|
+
this.overlaySpecs = [];
|
|
1084
1336
|
this.onToolActivated = (event) => {
|
|
1085
1337
|
const before = this.isToolActive;
|
|
1086
1338
|
this.syncToolActiveFromWorkbench(event.id);
|
|
@@ -1158,28 +1410,41 @@ var ImageTool = class {
|
|
|
1158
1410
|
const frame = this.getFrameRect();
|
|
1159
1411
|
if (!frame.width || !frame.height) return;
|
|
1160
1412
|
const center = target.getCenterPoint ? target.getCenterPoint() : new Point((_c = target.left) != null ? _c : 0, (_d = target.top) != null ? _d : 0);
|
|
1413
|
+
const centerScene = this.canvasService ? this.canvasService.toScenePoint({ x: center.x, y: center.y }) : { x: center.x, y: center.y };
|
|
1161
1414
|
const objectScale = Number.isFinite(target == null ? void 0 : target.scaleX) ? target.scaleX : 1;
|
|
1415
|
+
const objectScaleScene = this.toSceneObjectScale(objectScale || 1);
|
|
1162
1416
|
const workingItem = this.workingItems.find((item) => item.id === id);
|
|
1163
1417
|
const sourceKey = (workingItem == null ? void 0 : workingItem.sourceUrl) || (workingItem == null ? void 0 : workingItem.url) || "";
|
|
1164
1418
|
const sourceSize = this.getSourceSize(sourceKey, target);
|
|
1165
1419
|
const coverScale = this.getCoverScale(frame, sourceSize);
|
|
1166
1420
|
const updates = {
|
|
1167
|
-
left: this.clampNormalized((
|
|
1168
|
-
top: this.clampNormalized((
|
|
1421
|
+
left: this.clampNormalized((centerScene.x - frame.left) / frame.width),
|
|
1422
|
+
top: this.clampNormalized((centerScene.y - frame.top) / frame.height),
|
|
1169
1423
|
angle: Number.isFinite(target.angle) ? target.angle : 0,
|
|
1170
|
-
scale: Math.max(0.05,
|
|
1424
|
+
scale: Math.max(0.05, objectScaleScene / coverScale)
|
|
1171
1425
|
};
|
|
1172
1426
|
this.focusedImageId = id;
|
|
1173
1427
|
this.updateImageInWorking(id, updates);
|
|
1174
1428
|
};
|
|
1175
1429
|
}
|
|
1176
1430
|
activate(context) {
|
|
1431
|
+
var _a;
|
|
1177
1432
|
this.context = context;
|
|
1178
1433
|
this.canvasService = context.services.get("CanvasService");
|
|
1179
1434
|
if (!this.canvasService) {
|
|
1180
1435
|
console.warn("CanvasService not found for ImageTool");
|
|
1181
1436
|
return;
|
|
1182
1437
|
}
|
|
1438
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
1439
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
1440
|
+
this.id,
|
|
1441
|
+
() => ({
|
|
1442
|
+
rootLayerSpecs: {
|
|
1443
|
+
[IMAGE_OVERLAY_LAYER_ID]: this.overlaySpecs
|
|
1444
|
+
}
|
|
1445
|
+
}),
|
|
1446
|
+
{ priority: 300 }
|
|
1447
|
+
);
|
|
1183
1448
|
context.eventBus.on("tool:activated", this.onToolActivated);
|
|
1184
1449
|
context.eventBus.on("object:modified", this.onObjectModified);
|
|
1185
1450
|
context.eventBus.on("selection:created", this.onSelectionChanged);
|
|
@@ -1220,7 +1485,7 @@ var ImageTool = class {
|
|
|
1220
1485
|
this.updateImages();
|
|
1221
1486
|
}
|
|
1222
1487
|
deactivate(context) {
|
|
1223
|
-
var _a;
|
|
1488
|
+
var _a, _b;
|
|
1224
1489
|
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
1225
1490
|
context.eventBus.off("object:modified", this.onObjectModified);
|
|
1226
1491
|
context.eventBus.off("selection:created", this.onSelectionChanged);
|
|
@@ -1232,12 +1497,13 @@ var ImageTool = class {
|
|
|
1232
1497
|
this.dirtyTrackerDisposable = void 0;
|
|
1233
1498
|
this.cropShapeHatchPattern = void 0;
|
|
1234
1499
|
this.cropShapeHatchPatternColor = void 0;
|
|
1500
|
+
this.cropShapeHatchPatternKey = void 0;
|
|
1501
|
+
this.overlaySpecs = [];
|
|
1235
1502
|
this.clearRenderedImages();
|
|
1503
|
+
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
1504
|
+
this.renderProducerDisposable = void 0;
|
|
1236
1505
|
if (this.canvasService) {
|
|
1237
|
-
void this.canvasService.
|
|
1238
|
-
IMAGE_OVERLAY_LAYER_ID,
|
|
1239
|
-
[]
|
|
1240
|
-
);
|
|
1506
|
+
void this.canvasService.flushRenderFromProducers();
|
|
1241
1507
|
this.canvasService = void 0;
|
|
1242
1508
|
}
|
|
1243
1509
|
this.context = void 0;
|
|
@@ -1648,38 +1914,38 @@ var ImageTool = class {
|
|
|
1648
1914
|
if (!layout) {
|
|
1649
1915
|
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1650
1916
|
}
|
|
1651
|
-
return {
|
|
1917
|
+
return this.canvasService.toSceneRect({
|
|
1652
1918
|
left: layout.cutRect.left,
|
|
1653
1919
|
top: layout.cutRect.top,
|
|
1654
1920
|
width: layout.cutRect.width,
|
|
1655
1921
|
height: layout.cutRect.height
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
getFrameRectScreen(frame) {
|
|
1925
|
+
if (!this.canvasService) {
|
|
1926
|
+
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1927
|
+
}
|
|
1928
|
+
return this.canvasService.toScreenRect(frame || this.getFrameRect());
|
|
1929
|
+
}
|
|
1930
|
+
toLayoutSceneRect(rect) {
|
|
1931
|
+
return {
|
|
1932
|
+
left: rect.left,
|
|
1933
|
+
top: rect.top,
|
|
1934
|
+
width: rect.width,
|
|
1935
|
+
height: rect.height,
|
|
1936
|
+
space: "scene"
|
|
1656
1937
|
};
|
|
1657
1938
|
}
|
|
1658
1939
|
async resolveDefaultFitArea() {
|
|
1659
|
-
if (!this.
|
|
1660
|
-
const
|
|
1661
|
-
if (
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
const height = Number(cutRect == null ? void 0 : cutRect.height);
|
|
1669
|
-
const left = Number(cutRect == null ? void 0 : cutRect.left);
|
|
1670
|
-
const top = Number(cutRect == null ? void 0 : cutRect.top);
|
|
1671
|
-
if (!Number.isFinite(width) || !Number.isFinite(height) || !Number.isFinite(left) || !Number.isFinite(top)) {
|
|
1672
|
-
return null;
|
|
1673
|
-
}
|
|
1674
|
-
return {
|
|
1675
|
-
width: Math.max(1, width),
|
|
1676
|
-
height: Math.max(1, height),
|
|
1677
|
-
left: left + width / 2,
|
|
1678
|
-
top: top + height / 2
|
|
1679
|
-
};
|
|
1680
|
-
} catch (e) {
|
|
1681
|
-
return null;
|
|
1682
|
-
}
|
|
1940
|
+
if (!this.canvasService) return null;
|
|
1941
|
+
const frame = this.getFrameRect();
|
|
1942
|
+
if (frame.width <= 0 || frame.height <= 0) return null;
|
|
1943
|
+
return {
|
|
1944
|
+
width: Math.max(1, frame.width),
|
|
1945
|
+
height: Math.max(1, frame.height),
|
|
1946
|
+
left: frame.left + frame.width / 2,
|
|
1947
|
+
top: frame.top + frame.height / 2
|
|
1948
|
+
};
|
|
1683
1949
|
}
|
|
1684
1950
|
async fitImageToDefaultArea(id) {
|
|
1685
1951
|
if (!this.canvasService) return;
|
|
@@ -1688,13 +1954,14 @@ var ImageTool = class {
|
|
|
1688
1954
|
await this.fitImageToArea(id, area);
|
|
1689
1955
|
return;
|
|
1690
1956
|
}
|
|
1691
|
-
const
|
|
1692
|
-
const
|
|
1957
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
1958
|
+
const canvasW = Math.max(1, viewport.width || 0);
|
|
1959
|
+
const canvasH = Math.max(1, viewport.height || 0);
|
|
1693
1960
|
await this.fitImageToArea(id, {
|
|
1694
1961
|
width: canvasW,
|
|
1695
1962
|
height: canvasH,
|
|
1696
|
-
left: canvasW / 2,
|
|
1697
|
-
top: canvasH / 2
|
|
1963
|
+
left: viewport.left + canvasW / 2,
|
|
1964
|
+
top: viewport.top + canvasH / 2
|
|
1698
1965
|
});
|
|
1699
1966
|
}
|
|
1700
1967
|
getImageObjects() {
|
|
@@ -1782,13 +2049,17 @@ var ImageTool = class {
|
|
|
1782
2049
|
}
|
|
1783
2050
|
toSceneGeometryLike(raw) {
|
|
1784
2051
|
const shape = raw == null ? void 0 : raw.shape;
|
|
1785
|
-
if (shape
|
|
2052
|
+
if (!isDielineShape(shape)) {
|
|
1786
2053
|
return null;
|
|
1787
2054
|
}
|
|
1788
|
-
const
|
|
1789
|
-
const
|
|
2055
|
+
const radiusRaw = Number(raw == null ? void 0 : raw.radius);
|
|
2056
|
+
const offsetRaw = Number(raw == null ? void 0 : raw.offset);
|
|
2057
|
+
const unit = typeof (raw == null ? void 0 : raw.unit) === "string" ? raw.unit : "px";
|
|
2058
|
+
const radius = unit === "scene" || !this.canvasService ? radiusRaw : this.canvasService.toSceneLength(radiusRaw);
|
|
2059
|
+
const offset = unit === "scene" || !this.canvasService ? offsetRaw : this.canvasService.toSceneLength(offsetRaw);
|
|
1790
2060
|
return {
|
|
1791
2061
|
shape,
|
|
2062
|
+
shapeStyle: normalizeShapeStyle(raw == null ? void 0 : raw.shapeStyle),
|
|
1792
2063
|
radius: Number.isFinite(radius) ? radius : 0,
|
|
1793
2064
|
offset: Number.isFinite(offset) ? offset : 0
|
|
1794
2065
|
};
|
|
@@ -1840,8 +2111,11 @@ var ImageTool = class {
|
|
|
1840
2111
|
return Math.max(0, Math.min(maxRadius, rawCutRadius));
|
|
1841
2112
|
}
|
|
1842
2113
|
getCropShapeHatchPattern(color = "rgba(255, 0, 0, 0.6)") {
|
|
2114
|
+
var _a;
|
|
1843
2115
|
if (typeof document === "undefined") return void 0;
|
|
1844
|
-
|
|
2116
|
+
const sceneScale = ((_a = this.canvasService) == null ? void 0 : _a.getSceneScale()) || 1;
|
|
2117
|
+
const cacheKey = `${color}::${sceneScale.toFixed(6)}`;
|
|
2118
|
+
if (this.cropShapeHatchPattern && this.cropShapeHatchPatternColor === color && this.cropShapeHatchPatternKey === cacheKey) {
|
|
1845
2119
|
return this.cropShapeHatchPattern;
|
|
1846
2120
|
}
|
|
1847
2121
|
const size = 16;
|
|
@@ -1870,11 +2144,21 @@ var ImageTool = class {
|
|
|
1870
2144
|
// @ts-ignore: Fabric Pattern accepts canvas source here.
|
|
1871
2145
|
repetition: "repeat"
|
|
1872
2146
|
});
|
|
2147
|
+
pattern.patternTransform = [
|
|
2148
|
+
1 / sceneScale,
|
|
2149
|
+
0,
|
|
2150
|
+
0,
|
|
2151
|
+
1 / sceneScale,
|
|
2152
|
+
0,
|
|
2153
|
+
0
|
|
2154
|
+
];
|
|
1873
2155
|
this.cropShapeHatchPattern = pattern;
|
|
1874
2156
|
this.cropShapeHatchPatternColor = color;
|
|
2157
|
+
this.cropShapeHatchPatternKey = cacheKey;
|
|
1875
2158
|
return pattern;
|
|
1876
2159
|
}
|
|
1877
2160
|
buildCropShapeOverlaySpecs(frame, sceneGeometry) {
|
|
2161
|
+
var _a, _b;
|
|
1878
2162
|
if (!sceneGeometry) {
|
|
1879
2163
|
this.debug("overlay:shape:skip", { reason: "scene-geometry-missing" });
|
|
1880
2164
|
return [];
|
|
@@ -1884,6 +2168,7 @@ var ImageTool = class {
|
|
|
1884
2168
|
return [];
|
|
1885
2169
|
}
|
|
1886
2170
|
const shape = sceneGeometry.shape;
|
|
2171
|
+
const shapeStyle = sceneGeometry.shapeStyle;
|
|
1887
2172
|
const inset = 0;
|
|
1888
2173
|
const shapeWidth = Math.max(1, frame.width);
|
|
1889
2174
|
const shapeHeight = Math.max(1, frame.height);
|
|
@@ -1893,6 +2178,7 @@ var ImageTool = class {
|
|
|
1893
2178
|
frameWidth: frame.width,
|
|
1894
2179
|
frameHeight: frame.height,
|
|
1895
2180
|
offset: sceneGeometry.offset,
|
|
2181
|
+
shapeStyle,
|
|
1896
2182
|
inset,
|
|
1897
2183
|
shapeWidth,
|
|
1898
2184
|
shapeHeight,
|
|
@@ -1914,6 +2200,7 @@ var ImageTool = class {
|
|
|
1914
2200
|
x: frame.width / 2,
|
|
1915
2201
|
y: frame.height / 2,
|
|
1916
2202
|
features: [],
|
|
2203
|
+
shapeStyle,
|
|
1917
2204
|
canvasWidth: frame.width,
|
|
1918
2205
|
canvasHeight: frame.height
|
|
1919
2206
|
};
|
|
@@ -1931,6 +2218,9 @@ var ImageTool = class {
|
|
|
1931
2218
|
}
|
|
1932
2219
|
const patternFill = this.getCropShapeHatchPattern();
|
|
1933
2220
|
const hatchFill = patternFill || "rgba(255, 0, 0, 0.22)";
|
|
2221
|
+
const shapeBounds = getPathBounds(shapePathData);
|
|
2222
|
+
const hatchBounds = getPathBounds(hatchPathData);
|
|
2223
|
+
const frameRect = this.toLayoutSceneRect(frame);
|
|
1934
2224
|
const hatchPathLength = hatchPathData.length;
|
|
1935
2225
|
const shapePathLength = shapePathData.length;
|
|
1936
2226
|
const specs = [
|
|
@@ -1938,10 +2228,16 @@ var ImageTool = class {
|
|
|
1938
2228
|
id: "image.cropShapeHatch",
|
|
1939
2229
|
type: "path",
|
|
1940
2230
|
data: { id: "image.cropShapeHatch", zIndex: 5 },
|
|
2231
|
+
layout: {
|
|
2232
|
+
reference: "custom",
|
|
2233
|
+
referenceRect: frameRect,
|
|
2234
|
+
alignX: "start",
|
|
2235
|
+
alignY: "start",
|
|
2236
|
+
offsetX: hatchBounds.x,
|
|
2237
|
+
offsetY: hatchBounds.y
|
|
2238
|
+
},
|
|
1941
2239
|
props: {
|
|
1942
2240
|
pathData: hatchPathData,
|
|
1943
|
-
left: frame.left,
|
|
1944
|
-
top: frame.top,
|
|
1945
2241
|
originX: "left",
|
|
1946
2242
|
originY: "top",
|
|
1947
2243
|
fill: hatchFill,
|
|
@@ -1958,15 +2254,21 @@ var ImageTool = class {
|
|
|
1958
2254
|
id: "image.cropShapePath",
|
|
1959
2255
|
type: "path",
|
|
1960
2256
|
data: { id: "image.cropShapePath", zIndex: 6 },
|
|
2257
|
+
layout: {
|
|
2258
|
+
reference: "custom",
|
|
2259
|
+
referenceRect: frameRect,
|
|
2260
|
+
alignX: "start",
|
|
2261
|
+
alignY: "start",
|
|
2262
|
+
offsetX: shapeBounds.x,
|
|
2263
|
+
offsetY: shapeBounds.y
|
|
2264
|
+
},
|
|
1961
2265
|
props: {
|
|
1962
2266
|
pathData: shapePathData,
|
|
1963
|
-
left: frame.left,
|
|
1964
|
-
top: frame.top,
|
|
1965
2267
|
originX: "left",
|
|
1966
2268
|
originY: "top",
|
|
1967
2269
|
fill: "rgba(0,0,0,0)",
|
|
1968
2270
|
stroke: "rgba(255, 0, 0, 0.9)",
|
|
1969
|
-
strokeWidth: 1,
|
|
2271
|
+
strokeWidth: (_b = (_a = this.canvasService) == null ? void 0 : _a.toSceneLength(1)) != null ? _b : 1,
|
|
1970
2272
|
selectable: false,
|
|
1971
2273
|
evented: false,
|
|
1972
2274
|
excludeFromExport: true,
|
|
@@ -1983,6 +2285,8 @@ var ImageTool = class {
|
|
|
1983
2285
|
fillRule: "evenodd",
|
|
1984
2286
|
shapePathLength,
|
|
1985
2287
|
hatchPathLength,
|
|
2288
|
+
shapeBounds,
|
|
2289
|
+
hatchBounds,
|
|
1986
2290
|
hatchFillType: hatchFill && typeof hatchFill === "object" ? "pattern" : "color",
|
|
1987
2291
|
ids: specs.map((spec) => spec.id)
|
|
1988
2292
|
});
|
|
@@ -2045,6 +2349,28 @@ var ImageTool = class {
|
|
|
2045
2349
|
opacity: render.opacity
|
|
2046
2350
|
};
|
|
2047
2351
|
}
|
|
2352
|
+
toScreenObjectProps(props) {
|
|
2353
|
+
if (!this.canvasService) return props;
|
|
2354
|
+
const next = { ...props };
|
|
2355
|
+
if (Number.isFinite(next.left) || Number.isFinite(next.top)) {
|
|
2356
|
+
const mapped = this.canvasService.toScreenPoint({
|
|
2357
|
+
x: Number.isFinite(next.left) ? Number(next.left) : 0,
|
|
2358
|
+
y: Number.isFinite(next.top) ? Number(next.top) : 0
|
|
2359
|
+
});
|
|
2360
|
+
if (Number.isFinite(next.left)) next.left = mapped.x;
|
|
2361
|
+
if (Number.isFinite(next.top)) next.top = mapped.y;
|
|
2362
|
+
}
|
|
2363
|
+
const sceneScale = this.canvasService.getSceneScale();
|
|
2364
|
+
const sx = Number.isFinite(next.scaleX) ? Number(next.scaleX) : 1;
|
|
2365
|
+
const sy = Number.isFinite(next.scaleY) ? Number(next.scaleY) : 1;
|
|
2366
|
+
next.scaleX = sx * sceneScale;
|
|
2367
|
+
next.scaleY = sy * sceneScale;
|
|
2368
|
+
return next;
|
|
2369
|
+
}
|
|
2370
|
+
toSceneObjectScale(value) {
|
|
2371
|
+
if (!this.canvasService) return value;
|
|
2372
|
+
return value / this.canvasService.getSceneScale();
|
|
2373
|
+
}
|
|
2048
2374
|
getCurrentSrc(obj) {
|
|
2049
2375
|
var _a;
|
|
2050
2376
|
if (!obj) return void 0;
|
|
@@ -2077,7 +2403,7 @@ var ImageTool = class {
|
|
|
2077
2403
|
obj = void 0;
|
|
2078
2404
|
}
|
|
2079
2405
|
if (!obj) {
|
|
2080
|
-
const created = await
|
|
2406
|
+
const created = await FabricImage2.fromURL(render.src, {
|
|
2081
2407
|
crossOrigin: "anonymous"
|
|
2082
2408
|
});
|
|
2083
2409
|
if (seq !== this.renderSeq) return;
|
|
@@ -2094,8 +2420,9 @@ var ImageTool = class {
|
|
|
2094
2420
|
this.rememberSourceSize(render.src, obj);
|
|
2095
2421
|
const sourceSize = this.getSourceSize(render.src, obj);
|
|
2096
2422
|
const props = this.computeCanvasProps(render, sourceSize, frame);
|
|
2423
|
+
const screenProps = this.toScreenObjectProps(props);
|
|
2097
2424
|
obj.set({
|
|
2098
|
-
...
|
|
2425
|
+
...screenProps,
|
|
2099
2426
|
data: {
|
|
2100
2427
|
...obj.data || {},
|
|
2101
2428
|
id: item.id,
|
|
@@ -2161,37 +2488,67 @@ var ImageTool = class {
|
|
|
2161
2488
|
});
|
|
2162
2489
|
return [];
|
|
2163
2490
|
}
|
|
2164
|
-
const
|
|
2165
|
-
const
|
|
2491
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
2492
|
+
const canvasW = viewport.width || 0;
|
|
2493
|
+
const canvasH = viewport.height || 0;
|
|
2494
|
+
const canvasLeft = viewport.left || 0;
|
|
2495
|
+
const canvasTop = viewport.top || 0;
|
|
2166
2496
|
const visual = this.getFrameVisualConfig();
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2497
|
+
const strokeWidthScene = this.canvasService.toSceneLength(
|
|
2498
|
+
visual.strokeWidth
|
|
2499
|
+
);
|
|
2500
|
+
const dashLengthScene = this.canvasService.toSceneLength(visual.dashLength);
|
|
2501
|
+
const frameLeft = Math.max(
|
|
2502
|
+
canvasLeft,
|
|
2503
|
+
Math.min(canvasLeft + canvasW, frame.left)
|
|
2504
|
+
);
|
|
2505
|
+
const frameTop = Math.max(
|
|
2506
|
+
canvasTop,
|
|
2507
|
+
Math.min(canvasTop + canvasH, frame.top)
|
|
2508
|
+
);
|
|
2169
2509
|
const frameRight = Math.max(
|
|
2170
2510
|
frameLeft,
|
|
2171
|
-
Math.min(canvasW, frame.left + frame.width)
|
|
2511
|
+
Math.min(canvasLeft + canvasW, frame.left + frame.width)
|
|
2172
2512
|
);
|
|
2173
2513
|
const frameBottom = Math.max(
|
|
2174
2514
|
frameTop,
|
|
2175
|
-
Math.min(canvasH, frame.top + frame.height)
|
|
2515
|
+
Math.min(canvasTop + canvasH, frame.top + frame.height)
|
|
2176
2516
|
);
|
|
2177
2517
|
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
2178
|
-
const topH = frameTop;
|
|
2179
|
-
const bottomH = Math.max(0, canvasH - frameBottom);
|
|
2180
|
-
const leftW = frameLeft;
|
|
2181
|
-
const rightW = Math.max(0, canvasW - frameRight);
|
|
2518
|
+
const topH = Math.max(0, frameTop - canvasTop);
|
|
2519
|
+
const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
|
|
2520
|
+
const leftW = Math.max(0, frameLeft - canvasLeft);
|
|
2521
|
+
const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
|
|
2522
|
+
const viewportRect = this.toLayoutSceneRect({
|
|
2523
|
+
left: canvasLeft,
|
|
2524
|
+
top: canvasTop,
|
|
2525
|
+
width: canvasW,
|
|
2526
|
+
height: canvasH
|
|
2527
|
+
});
|
|
2528
|
+
const visibleFrameBandRect = this.toLayoutSceneRect({
|
|
2529
|
+
left: canvasLeft,
|
|
2530
|
+
top: frameTop,
|
|
2531
|
+
width: canvasW,
|
|
2532
|
+
height: visibleFrameH
|
|
2533
|
+
});
|
|
2534
|
+
const frameRect = this.toLayoutSceneRect(frame);
|
|
2182
2535
|
const shapeOverlay = this.buildCropShapeOverlaySpecs(frame, sceneGeometry);
|
|
2183
2536
|
const mask = [
|
|
2184
2537
|
{
|
|
2185
2538
|
id: "image.cropMask.top",
|
|
2186
2539
|
type: "rect",
|
|
2187
2540
|
data: { id: "image.cropMask.top", zIndex: 1 },
|
|
2541
|
+
layout: {
|
|
2542
|
+
reference: "custom",
|
|
2543
|
+
referenceRect: viewportRect,
|
|
2544
|
+
alignX: "start",
|
|
2545
|
+
alignY: "start",
|
|
2546
|
+
width: "100%",
|
|
2547
|
+
height: topH
|
|
2548
|
+
},
|
|
2188
2549
|
props: {
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
width: canvasW,
|
|
2192
|
-
height: topH,
|
|
2193
|
-
originX: "center",
|
|
2194
|
-
originY: "center",
|
|
2550
|
+
originX: "left",
|
|
2551
|
+
originY: "top",
|
|
2195
2552
|
fill: visual.outerBackground,
|
|
2196
2553
|
selectable: false,
|
|
2197
2554
|
evented: false
|
|
@@ -2201,13 +2558,17 @@ var ImageTool = class {
|
|
|
2201
2558
|
id: "image.cropMask.bottom",
|
|
2202
2559
|
type: "rect",
|
|
2203
2560
|
data: { id: "image.cropMask.bottom", zIndex: 2 },
|
|
2561
|
+
layout: {
|
|
2562
|
+
reference: "custom",
|
|
2563
|
+
referenceRect: viewportRect,
|
|
2564
|
+
alignX: "start",
|
|
2565
|
+
alignY: "end",
|
|
2566
|
+
width: "100%",
|
|
2567
|
+
height: bottomH
|
|
2568
|
+
},
|
|
2204
2569
|
props: {
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
width: canvasW,
|
|
2208
|
-
height: bottomH,
|
|
2209
|
-
originX: "center",
|
|
2210
|
-
originY: "center",
|
|
2570
|
+
originX: "left",
|
|
2571
|
+
originY: "top",
|
|
2211
2572
|
fill: visual.outerBackground,
|
|
2212
2573
|
selectable: false,
|
|
2213
2574
|
evented: false
|
|
@@ -2217,13 +2578,17 @@ var ImageTool = class {
|
|
|
2217
2578
|
id: "image.cropMask.left",
|
|
2218
2579
|
type: "rect",
|
|
2219
2580
|
data: { id: "image.cropMask.left", zIndex: 3 },
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2581
|
+
layout: {
|
|
2582
|
+
reference: "custom",
|
|
2583
|
+
referenceRect: visibleFrameBandRect,
|
|
2584
|
+
alignX: "start",
|
|
2585
|
+
alignY: "start",
|
|
2223
2586
|
width: leftW,
|
|
2224
|
-
height:
|
|
2225
|
-
|
|
2226
|
-
|
|
2587
|
+
height: "100%"
|
|
2588
|
+
},
|
|
2589
|
+
props: {
|
|
2590
|
+
originX: "left",
|
|
2591
|
+
originY: "top",
|
|
2227
2592
|
fill: visual.outerBackground,
|
|
2228
2593
|
selectable: false,
|
|
2229
2594
|
evented: false
|
|
@@ -2233,13 +2598,17 @@ var ImageTool = class {
|
|
|
2233
2598
|
id: "image.cropMask.right",
|
|
2234
2599
|
type: "rect",
|
|
2235
2600
|
data: { id: "image.cropMask.right", zIndex: 4 },
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2601
|
+
layout: {
|
|
2602
|
+
reference: "custom",
|
|
2603
|
+
referenceRect: visibleFrameBandRect,
|
|
2604
|
+
alignX: "end",
|
|
2605
|
+
alignY: "start",
|
|
2239
2606
|
width: rightW,
|
|
2240
|
-
height:
|
|
2241
|
-
|
|
2242
|
-
|
|
2607
|
+
height: "100%"
|
|
2608
|
+
},
|
|
2609
|
+
props: {
|
|
2610
|
+
originX: "left",
|
|
2611
|
+
originY: "top",
|
|
2243
2612
|
fill: visual.outerBackground,
|
|
2244
2613
|
selectable: false,
|
|
2245
2614
|
evented: false
|
|
@@ -2250,17 +2619,21 @@ var ImageTool = class {
|
|
|
2250
2619
|
id: "image.cropFrame",
|
|
2251
2620
|
type: "rect",
|
|
2252
2621
|
data: { id: "image.cropFrame", zIndex: 7 },
|
|
2622
|
+
layout: {
|
|
2623
|
+
reference: "custom",
|
|
2624
|
+
referenceRect: frameRect,
|
|
2625
|
+
alignX: "start",
|
|
2626
|
+
alignY: "start",
|
|
2627
|
+
width: "100%",
|
|
2628
|
+
height: "100%"
|
|
2629
|
+
},
|
|
2253
2630
|
props: {
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
width: frame.width,
|
|
2257
|
-
height: frame.height,
|
|
2258
|
-
originX: "center",
|
|
2259
|
-
originY: "center",
|
|
2631
|
+
originX: "left",
|
|
2632
|
+
originY: "top",
|
|
2260
2633
|
fill: visual.innerBackground,
|
|
2261
2634
|
stroke: visual.strokeStyle === "hidden" ? "rgba(0,0,0,0)" : visual.strokeColor,
|
|
2262
|
-
strokeWidth: visual.strokeStyle === "hidden" ? 0 :
|
|
2263
|
-
strokeDashArray: visual.strokeStyle === "dashed" ? [
|
|
2635
|
+
strokeWidth: visual.strokeStyle === "hidden" ? 0 : strokeWidthScene,
|
|
2636
|
+
strokeDashArray: visual.strokeStyle === "dashed" ? [dashLengthScene, dashLengthScene] : void 0,
|
|
2264
2637
|
selectable: false,
|
|
2265
2638
|
evented: false
|
|
2266
2639
|
}
|
|
@@ -2311,10 +2684,8 @@ var ImageTool = class {
|
|
|
2311
2684
|
const sceneGeometry = await this.resolveSceneGeometryForOverlay();
|
|
2312
2685
|
if (seq !== this.renderSeq) return;
|
|
2313
2686
|
const overlaySpecs = this.buildOverlaySpecs(frame, sceneGeometry);
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
overlaySpecs
|
|
2317
|
-
);
|
|
2687
|
+
this.overlaySpecs = overlaySpecs;
|
|
2688
|
+
await this.canvasService.flushRenderFromProducers();
|
|
2318
2689
|
this.syncImageZOrder(renderItems);
|
|
2319
2690
|
const overlayCanvasCount = this.getOverlayObjects().length;
|
|
2320
2691
|
this.debug("render:done", {
|
|
@@ -2405,7 +2776,7 @@ var ImageTool = class {
|
|
|
2405
2776
|
const source = this.getSourceSize(render.src, obj);
|
|
2406
2777
|
const frame = this.getFrameRect();
|
|
2407
2778
|
const coverScale = this.getCoverScale(frame, source);
|
|
2408
|
-
const currentScale = obj.scaleX || 1;
|
|
2779
|
+
const currentScale = this.toSceneObjectScale(obj.scaleX || 1);
|
|
2409
2780
|
const zoom = Math.max(0.05, currentScale / coverScale);
|
|
2410
2781
|
const updated = {
|
|
2411
2782
|
scale: Number.isFinite(zoom) ? zoom : 1,
|
|
@@ -2442,12 +2813,13 @@ var ImageTool = class {
|
|
|
2442
2813
|
Math.max(1, area.width) / Math.max(1, source.width),
|
|
2443
2814
|
Math.max(1, area.height) / Math.max(1, source.height)
|
|
2444
2815
|
);
|
|
2445
|
-
const
|
|
2446
|
-
const
|
|
2816
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
2817
|
+
const canvasW = viewport.width || 1;
|
|
2818
|
+
const canvasH = viewport.height || 1;
|
|
2447
2819
|
const areaLeftInput = (_a = area.left) != null ? _a : 0.5;
|
|
2448
2820
|
const areaTopInput = (_b = area.top) != null ? _b : 0.5;
|
|
2449
|
-
const areaLeftPx = areaLeftInput <= 1.5 ? areaLeftInput * canvasW : areaLeftInput;
|
|
2450
|
-
const areaTopPx = areaTopInput <= 1.5 ? areaTopInput * canvasH : areaTopInput;
|
|
2821
|
+
const areaLeftPx = areaLeftInput <= 1.5 ? viewport.left + areaLeftInput * canvasW : areaLeftInput;
|
|
2822
|
+
const areaTopPx = areaTopInput <= 1.5 ? viewport.top + areaTopInput * canvasH : areaTopInput;
|
|
2451
2823
|
const updates = {
|
|
2452
2824
|
scale: Math.max(0.05, desiredScale / baseCover),
|
|
2453
2825
|
left: this.clampNormalized(
|
|
@@ -2512,7 +2884,8 @@ var ImageTool = class {
|
|
|
2512
2884
|
if (!normalizedIds.length) {
|
|
2513
2885
|
throw new Error("image-ids-required");
|
|
2514
2886
|
}
|
|
2515
|
-
const
|
|
2887
|
+
const frameScene = this.getFrameRect();
|
|
2888
|
+
const frame = this.getFrameRectScreen(frameScene);
|
|
2516
2889
|
const multiplier = Math.max(1, (_a = options.multiplier) != null ? _a : 2);
|
|
2517
2890
|
const format = options.format === "jpeg" ? "jpeg" : "png";
|
|
2518
2891
|
const width = Math.max(1, Math.round(frame.width * multiplier));
|
|
@@ -3940,6 +4313,7 @@ var ImageTracer = class {
|
|
|
3940
4313
|
|
|
3941
4314
|
// src/extensions/dieline.ts
|
|
3942
4315
|
var IMAGE_OBJECT_LAYER_ID2 = "image.user";
|
|
4316
|
+
var DIELINE_LAYER_ID = "dieline-overlay";
|
|
3943
4317
|
var DielineTool = class {
|
|
3944
4318
|
constructor(options) {
|
|
3945
4319
|
this.id = "pooder.kit.dieline";
|
|
@@ -3947,8 +4321,8 @@ var DielineTool = class {
|
|
|
3947
4321
|
name: "DielineTool"
|
|
3948
4322
|
};
|
|
3949
4323
|
this.state = {
|
|
3950
|
-
|
|
3951
|
-
|
|
4324
|
+
shape: DEFAULT_DIELINE_SHAPE,
|
|
4325
|
+
shapeStyle: { ...DEFAULT_DIELINE_SHAPE_STYLE },
|
|
3952
4326
|
width: 500,
|
|
3953
4327
|
height: 500,
|
|
3954
4328
|
radius: 0,
|
|
@@ -3971,6 +4345,8 @@ var DielineTool = class {
|
|
|
3971
4345
|
showBleedLines: true,
|
|
3972
4346
|
features: []
|
|
3973
4347
|
};
|
|
4348
|
+
this.specs = [];
|
|
4349
|
+
this.renderSeq = 0;
|
|
3974
4350
|
this.onCanvasResized = () => {
|
|
3975
4351
|
this.updateDieline();
|
|
3976
4352
|
};
|
|
@@ -3983,24 +4359,50 @@ var DielineTool = class {
|
|
|
3983
4359
|
Object.assign(this.state.offsetLine, options.offsetLine);
|
|
3984
4360
|
delete options.offsetLine;
|
|
3985
4361
|
}
|
|
4362
|
+
if (options.shapeStyle) {
|
|
4363
|
+
this.state.shapeStyle = normalizeShapeStyle(
|
|
4364
|
+
options.shapeStyle,
|
|
4365
|
+
this.state.shapeStyle
|
|
4366
|
+
);
|
|
4367
|
+
delete options.shapeStyle;
|
|
4368
|
+
}
|
|
3986
4369
|
Object.assign(this.state, options);
|
|
4370
|
+
this.state.shape = normalizeDielineShape(options.shape, this.state.shape);
|
|
3987
4371
|
}
|
|
3988
4372
|
}
|
|
3989
4373
|
activate(context) {
|
|
4374
|
+
var _a;
|
|
3990
4375
|
this.context = context;
|
|
3991
4376
|
this.canvasService = context.services.get("CanvasService");
|
|
3992
4377
|
if (!this.canvasService) {
|
|
3993
4378
|
console.warn("CanvasService not found for DielineTool");
|
|
3994
4379
|
return;
|
|
3995
4380
|
}
|
|
4381
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
4382
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
4383
|
+
this.id,
|
|
4384
|
+
() => ({
|
|
4385
|
+
layerSpecs: {
|
|
4386
|
+
[DIELINE_LAYER_ID]: this.specs
|
|
4387
|
+
},
|
|
4388
|
+
replaceLayerIds: [DIELINE_LAYER_ID]
|
|
4389
|
+
}),
|
|
4390
|
+
{ priority: 250 }
|
|
4391
|
+
);
|
|
3996
4392
|
const configService = context.services.get(
|
|
3997
4393
|
"ConfigurationService"
|
|
3998
4394
|
);
|
|
3999
4395
|
if (configService) {
|
|
4000
4396
|
const s = this.state;
|
|
4001
4397
|
const sizeState = readSizeState(configService);
|
|
4002
|
-
s.
|
|
4003
|
-
|
|
4398
|
+
s.shape = normalizeDielineShape(
|
|
4399
|
+
configService.get("dieline.shape", s.shape),
|
|
4400
|
+
s.shape
|
|
4401
|
+
);
|
|
4402
|
+
s.shapeStyle = normalizeShapeStyle(
|
|
4403
|
+
configService.get("dieline.shapeStyle", s.shapeStyle),
|
|
4404
|
+
s.shapeStyle
|
|
4405
|
+
);
|
|
4004
4406
|
s.width = sizeState.actualWidthMm;
|
|
4005
4407
|
s.height = sizeState.actualHeightMm;
|
|
4006
4408
|
s.radius = parseLengthToMm(
|
|
@@ -4060,7 +4462,6 @@ var DielineTool = class {
|
|
|
4060
4462
|
configService.onAnyChange((e) => {
|
|
4061
4463
|
if (e.key.startsWith("size.")) {
|
|
4062
4464
|
const nextSize = readSizeState(configService);
|
|
4063
|
-
s.displayUnit = nextSize.unit;
|
|
4064
4465
|
s.width = nextSize.actualWidthMm;
|
|
4065
4466
|
s.height = nextSize.actualHeightMm;
|
|
4066
4467
|
s.padding = nextSize.viewPadding;
|
|
@@ -4071,7 +4472,10 @@ var DielineTool = class {
|
|
|
4071
4472
|
if (e.key.startsWith("dieline.")) {
|
|
4072
4473
|
switch (e.key) {
|
|
4073
4474
|
case "dieline.shape":
|
|
4074
|
-
s.shape = e.value;
|
|
4475
|
+
s.shape = normalizeDielineShape(e.value, s.shape);
|
|
4476
|
+
break;
|
|
4477
|
+
case "dieline.shapeStyle":
|
|
4478
|
+
s.shapeStyle = normalizeShapeStyle(e.value, s.shapeStyle);
|
|
4075
4479
|
break;
|
|
4076
4480
|
case "dieline.radius":
|
|
4077
4481
|
s.radius = parseLengthToMm(e.value, "mm");
|
|
@@ -4127,12 +4531,18 @@ var DielineTool = class {
|
|
|
4127
4531
|
});
|
|
4128
4532
|
}
|
|
4129
4533
|
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
4130
|
-
this.createLayer();
|
|
4131
4534
|
this.updateDieline();
|
|
4132
4535
|
}
|
|
4133
4536
|
deactivate(context) {
|
|
4537
|
+
var _a;
|
|
4134
4538
|
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
4135
|
-
this.
|
|
4539
|
+
this.renderSeq += 1;
|
|
4540
|
+
this.specs = [];
|
|
4541
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
4542
|
+
this.renderProducerDisposable = void 0;
|
|
4543
|
+
if (this.canvasService) {
|
|
4544
|
+
void this.canvasService.flushRenderFromProducers();
|
|
4545
|
+
}
|
|
4136
4546
|
this.canvasService = void 0;
|
|
4137
4547
|
this.context = void 0;
|
|
4138
4548
|
}
|
|
@@ -4155,7 +4565,7 @@ var DielineTool = class {
|
|
|
4155
4565
|
id: "dieline.shape",
|
|
4156
4566
|
type: "select",
|
|
4157
4567
|
label: "Shape",
|
|
4158
|
-
options:
|
|
4568
|
+
options: Array.from(DIELINE_SHAPES),
|
|
4159
4569
|
default: s.shape
|
|
4160
4570
|
},
|
|
4161
4571
|
{
|
|
@@ -4166,6 +4576,12 @@ var DielineTool = class {
|
|
|
4166
4576
|
max: 500,
|
|
4167
4577
|
default: s.radius
|
|
4168
4578
|
},
|
|
4579
|
+
{
|
|
4580
|
+
id: "dieline.shapeStyle",
|
|
4581
|
+
type: "json",
|
|
4582
|
+
label: "Shape Style",
|
|
4583
|
+
default: s.shapeStyle
|
|
4584
|
+
},
|
|
4169
4585
|
{
|
|
4170
4586
|
id: "dieline.showBleedLines",
|
|
4171
4587
|
type: "boolean",
|
|
@@ -4341,34 +4757,6 @@ var DielineTool = class {
|
|
|
4341
4757
|
]
|
|
4342
4758
|
};
|
|
4343
4759
|
}
|
|
4344
|
-
getLayer() {
|
|
4345
|
-
var _a;
|
|
4346
|
-
return (_a = this.canvasService) == null ? void 0 : _a.getLayer("dieline-overlay");
|
|
4347
|
-
}
|
|
4348
|
-
createLayer() {
|
|
4349
|
-
if (!this.canvasService) return;
|
|
4350
|
-
const width = this.canvasService.canvas.width || 800;
|
|
4351
|
-
const height = this.canvasService.canvas.height || 600;
|
|
4352
|
-
const layer = this.canvasService.createLayer("dieline-overlay", {
|
|
4353
|
-
width,
|
|
4354
|
-
height,
|
|
4355
|
-
selectable: false,
|
|
4356
|
-
evented: false
|
|
4357
|
-
});
|
|
4358
|
-
this.canvasService.canvas.bringObjectToFront(layer);
|
|
4359
|
-
const userLayer = this.canvasService.getLayer("user");
|
|
4360
|
-
if (userLayer) {
|
|
4361
|
-
const userIndex = this.canvasService.canvas.getObjects().indexOf(userLayer);
|
|
4362
|
-
this.canvasService.canvas.moveObjectTo(layer, userIndex + 1);
|
|
4363
|
-
}
|
|
4364
|
-
}
|
|
4365
|
-
destroyLayer() {
|
|
4366
|
-
if (!this.canvasService) return;
|
|
4367
|
-
const layer = this.getLayer();
|
|
4368
|
-
if (layer) {
|
|
4369
|
-
this.canvasService.canvas.remove(layer);
|
|
4370
|
-
}
|
|
4371
|
-
}
|
|
4372
4760
|
createHatchPattern(color = "rgba(0, 0, 0, 0.3)") {
|
|
4373
4761
|
if (typeof document === "undefined") {
|
|
4374
4762
|
return void 0;
|
|
@@ -4397,7 +4785,6 @@ var DielineTool = class {
|
|
|
4397
4785
|
}
|
|
4398
4786
|
syncSizeState(configService) {
|
|
4399
4787
|
const sizeState = readSizeState(configService);
|
|
4400
|
-
this.state.displayUnit = sizeState.unit;
|
|
4401
4788
|
this.state.width = sizeState.actualWidthMm;
|
|
4402
4789
|
this.state.height = sizeState.actualHeightMm;
|
|
4403
4790
|
this.state.padding = sizeState.viewPadding;
|
|
@@ -4411,20 +4798,26 @@ var DielineTool = class {
|
|
|
4411
4798
|
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
4412
4799
|
}).forEach((obj) => canvas.bringObjectToFront(obj));
|
|
4413
4800
|
}
|
|
4414
|
-
|
|
4801
|
+
ensureLayerStacking() {
|
|
4415
4802
|
if (!this.canvasService) return;
|
|
4416
|
-
const layer = this.getLayer();
|
|
4803
|
+
const layer = this.canvasService.getLayer(DIELINE_LAYER_ID);
|
|
4417
4804
|
if (!layer) return;
|
|
4418
|
-
const
|
|
4419
|
-
if (
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4805
|
+
const userLayer = this.canvasService.getLayer("user");
|
|
4806
|
+
if (userLayer) {
|
|
4807
|
+
const layerIndex = this.canvasService.canvas.getObjects().indexOf(layer);
|
|
4808
|
+
const userIndex = this.canvasService.canvas.getObjects().indexOf(userLayer);
|
|
4809
|
+
if (layerIndex < userIndex) {
|
|
4810
|
+
this.canvasService.canvas.moveObjectTo(layer, userIndex + 1);
|
|
4811
|
+
}
|
|
4812
|
+
return;
|
|
4813
|
+
}
|
|
4814
|
+
this.canvasService.canvas.bringObjectToFront(layer);
|
|
4815
|
+
}
|
|
4816
|
+
buildDielineSpecs(sceneLayout) {
|
|
4817
|
+
var _a, _b;
|
|
4426
4818
|
const {
|
|
4427
4819
|
shape,
|
|
4820
|
+
shapeStyle,
|
|
4428
4821
|
radius,
|
|
4429
4822
|
mainLine,
|
|
4430
4823
|
offsetLine,
|
|
@@ -4433,8 +4826,8 @@ var DielineTool = class {
|
|
|
4433
4826
|
showBleedLines,
|
|
4434
4827
|
features
|
|
4435
4828
|
} = this.state;
|
|
4436
|
-
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
4437
|
-
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
4829
|
+
const canvasW = sceneLayout.canvasWidth || ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800;
|
|
4830
|
+
const canvasH = sceneLayout.canvasHeight || ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600;
|
|
4438
4831
|
const scale = sceneLayout.scale;
|
|
4439
4832
|
const cx = sceneLayout.trimRect.centerX;
|
|
4440
4833
|
const cy = sceneLayout.trimRect.centerY;
|
|
@@ -4445,7 +4838,6 @@ var DielineTool = class {
|
|
|
4445
4838
|
const cutH = sceneLayout.cutRect.height;
|
|
4446
4839
|
const visualOffset = (cutW - visualWidth) / 2;
|
|
4447
4840
|
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
4448
|
-
layer.remove(...layer.getObjects());
|
|
4449
4841
|
const absoluteFeatures = (features || []).map((f) => ({
|
|
4450
4842
|
...f,
|
|
4451
4843
|
x: f.x,
|
|
@@ -4465,21 +4857,30 @@ var DielineTool = class {
|
|
|
4465
4857
|
x: cx,
|
|
4466
4858
|
y: cy,
|
|
4467
4859
|
features: cutFeatures,
|
|
4860
|
+
shapeStyle,
|
|
4468
4861
|
pathData: this.state.pathData,
|
|
4469
4862
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4470
4863
|
customSourceHeightPx: this.state.customSourceHeightPx
|
|
4471
4864
|
});
|
|
4472
|
-
const
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4865
|
+
const specs = [
|
|
4866
|
+
{
|
|
4867
|
+
id: "dieline.mask",
|
|
4868
|
+
type: "path",
|
|
4869
|
+
space: "screen",
|
|
4870
|
+
data: { id: "dieline.mask", type: "dieline" },
|
|
4871
|
+
props: {
|
|
4872
|
+
pathData: maskPathData,
|
|
4873
|
+
fill: outsideColor,
|
|
4874
|
+
stroke: null,
|
|
4875
|
+
selectable: false,
|
|
4876
|
+
evented: false,
|
|
4877
|
+
originX: "left",
|
|
4878
|
+
originY: "top",
|
|
4879
|
+
left: 0,
|
|
4880
|
+
top: 0
|
|
4881
|
+
}
|
|
4882
|
+
}
|
|
4883
|
+
];
|
|
4483
4884
|
if (insideColor && insideColor !== "transparent" && insideColor !== "rgba(0,0,0,0)") {
|
|
4484
4885
|
const productPathData = generateDielinePath({
|
|
4485
4886
|
shape,
|
|
@@ -4489,21 +4890,28 @@ var DielineTool = class {
|
|
|
4489
4890
|
x: cx,
|
|
4490
4891
|
y: cy,
|
|
4491
4892
|
features: cutFeatures,
|
|
4893
|
+
shapeStyle,
|
|
4492
4894
|
pathData: this.state.pathData,
|
|
4493
4895
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4494
4896
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4495
4897
|
canvasWidth: canvasW,
|
|
4496
4898
|
canvasHeight: canvasH
|
|
4497
4899
|
});
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4900
|
+
specs.push({
|
|
4901
|
+
id: "dieline.inside",
|
|
4902
|
+
type: "path",
|
|
4903
|
+
space: "screen",
|
|
4904
|
+
data: { id: "dieline.inside", type: "dieline" },
|
|
4905
|
+
props: {
|
|
4906
|
+
pathData: productPathData,
|
|
4907
|
+
fill: insideColor,
|
|
4908
|
+
stroke: null,
|
|
4909
|
+
selectable: false,
|
|
4910
|
+
evented: false,
|
|
4911
|
+
originX: "left",
|
|
4912
|
+
originY: "top"
|
|
4913
|
+
}
|
|
4505
4914
|
});
|
|
4506
|
-
layer.add(insideObj);
|
|
4507
4915
|
}
|
|
4508
4916
|
if (Math.abs(visualOffset) > 1e-4) {
|
|
4509
4917
|
const bleedPathData = generateBleedZonePath(
|
|
@@ -4515,6 +4923,7 @@ var DielineTool = class {
|
|
|
4515
4923
|
x: cx,
|
|
4516
4924
|
y: cy,
|
|
4517
4925
|
features: cutFeatures,
|
|
4926
|
+
shapeStyle,
|
|
4518
4927
|
pathData: this.state.pathData,
|
|
4519
4928
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4520
4929
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
@@ -4529,6 +4938,7 @@ var DielineTool = class {
|
|
|
4529
4938
|
x: cx,
|
|
4530
4939
|
y: cy,
|
|
4531
4940
|
features: cutFeatures,
|
|
4941
|
+
shapeStyle,
|
|
4532
4942
|
pathData: this.state.pathData,
|
|
4533
4943
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4534
4944
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
@@ -4540,16 +4950,22 @@ var DielineTool = class {
|
|
|
4540
4950
|
if (showBleedLines !== false) {
|
|
4541
4951
|
const pattern = this.createHatchPattern(mainLine.color);
|
|
4542
4952
|
if (pattern) {
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4953
|
+
specs.push({
|
|
4954
|
+
id: "dieline.bleed-zone",
|
|
4955
|
+
type: "path",
|
|
4956
|
+
space: "screen",
|
|
4957
|
+
data: { id: "dieline.bleed-zone", type: "dieline" },
|
|
4958
|
+
props: {
|
|
4959
|
+
pathData: bleedPathData,
|
|
4960
|
+
fill: pattern,
|
|
4961
|
+
stroke: null,
|
|
4962
|
+
selectable: false,
|
|
4963
|
+
evented: false,
|
|
4964
|
+
objectCaching: false,
|
|
4965
|
+
originX: "left",
|
|
4966
|
+
originY: "top"
|
|
4967
|
+
}
|
|
4551
4968
|
});
|
|
4552
|
-
layer.add(bleedObj);
|
|
4553
4969
|
}
|
|
4554
4970
|
}
|
|
4555
4971
|
const offsetPathData = generateDielinePath({
|
|
@@ -4560,23 +4976,30 @@ var DielineTool = class {
|
|
|
4560
4976
|
x: cx,
|
|
4561
4977
|
y: cy,
|
|
4562
4978
|
features: cutFeatures,
|
|
4979
|
+
shapeStyle,
|
|
4563
4980
|
pathData: this.state.pathData,
|
|
4564
4981
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4565
4982
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4566
4983
|
canvasWidth: canvasW,
|
|
4567
4984
|
canvasHeight: canvasH
|
|
4568
4985
|
});
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4986
|
+
specs.push({
|
|
4987
|
+
id: "dieline.offset-border",
|
|
4988
|
+
type: "path",
|
|
4989
|
+
space: "screen",
|
|
4990
|
+
data: { id: "dieline.offset-border", type: "dieline" },
|
|
4991
|
+
props: {
|
|
4992
|
+
pathData: offsetPathData,
|
|
4993
|
+
fill: null,
|
|
4994
|
+
stroke: offsetLine.style === "hidden" ? null : offsetLine.color,
|
|
4995
|
+
strokeWidth: offsetLine.width,
|
|
4996
|
+
strokeDashArray: offsetLine.style === "dashed" ? [offsetLine.dashLength, offsetLine.dashLength] : void 0,
|
|
4997
|
+
selectable: false,
|
|
4998
|
+
evented: false,
|
|
4999
|
+
originX: "left",
|
|
5000
|
+
originY: "top"
|
|
5001
|
+
}
|
|
4578
5002
|
});
|
|
4579
|
-
layer.add(offsetBorderObj);
|
|
4580
5003
|
}
|
|
4581
5004
|
const borderPathData = generateDielinePath({
|
|
4582
5005
|
shape,
|
|
@@ -4586,39 +5009,59 @@ var DielineTool = class {
|
|
|
4586
5009
|
x: cx,
|
|
4587
5010
|
y: cy,
|
|
4588
5011
|
features: absoluteFeatures,
|
|
5012
|
+
shapeStyle,
|
|
4589
5013
|
pathData: this.state.pathData,
|
|
4590
5014
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4591
5015
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4592
5016
|
canvasWidth: canvasW,
|
|
4593
5017
|
canvasHeight: canvasH
|
|
4594
5018
|
});
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
if (layerIndex < userIndex) {
|
|
4611
|
-
this.canvasService.canvas.moveObjectTo(layer, userIndex + 1);
|
|
5019
|
+
specs.push({
|
|
5020
|
+
id: "dieline.border",
|
|
5021
|
+
type: "path",
|
|
5022
|
+
space: "screen",
|
|
5023
|
+
data: { id: "dieline.border", type: "dieline" },
|
|
5024
|
+
props: {
|
|
5025
|
+
pathData: borderPathData,
|
|
5026
|
+
fill: "transparent",
|
|
5027
|
+
stroke: mainLine.style === "hidden" ? null : mainLine.color,
|
|
5028
|
+
strokeWidth: mainLine.width,
|
|
5029
|
+
strokeDashArray: mainLine.style === "dashed" ? [mainLine.dashLength, mainLine.dashLength] : void 0,
|
|
5030
|
+
selectable: false,
|
|
5031
|
+
evented: false,
|
|
5032
|
+
originX: "left",
|
|
5033
|
+
originY: "top"
|
|
4612
5034
|
}
|
|
4613
|
-
}
|
|
4614
|
-
|
|
5035
|
+
});
|
|
5036
|
+
return specs;
|
|
5037
|
+
}
|
|
5038
|
+
updateDieline(_emitEvent = true) {
|
|
5039
|
+
void this.updateDielineAsync();
|
|
5040
|
+
}
|
|
5041
|
+
async updateDielineAsync() {
|
|
5042
|
+
if (!this.canvasService) return;
|
|
5043
|
+
const configService = this.getConfigService();
|
|
5044
|
+
if (!configService) return;
|
|
5045
|
+
const seq = ++this.renderSeq;
|
|
5046
|
+
this.syncSizeState(configService);
|
|
5047
|
+
const sceneLayout = computeSceneLayout(
|
|
5048
|
+
this.canvasService,
|
|
5049
|
+
readSizeState(configService)
|
|
5050
|
+
);
|
|
5051
|
+
if (!sceneLayout) {
|
|
5052
|
+
if (seq !== this.renderSeq) return;
|
|
5053
|
+
this.specs = [];
|
|
5054
|
+
await this.canvasService.flushRenderFromProducers();
|
|
5055
|
+
return;
|
|
4615
5056
|
}
|
|
5057
|
+
const nextSpecs = this.buildDielineSpecs(sceneLayout);
|
|
5058
|
+
if (seq !== this.renderSeq) return;
|
|
5059
|
+
this.specs = nextSpecs;
|
|
5060
|
+
await this.canvasService.flushRenderFromProducers();
|
|
5061
|
+
if (seq !== this.renderSeq) return;
|
|
5062
|
+
this.ensureLayerStacking();
|
|
4616
5063
|
this.bringFeatureMarkersToFront();
|
|
4617
|
-
|
|
4618
|
-
if (rulerLayer) {
|
|
4619
|
-
this.canvasService.canvas.bringObjectToFront(rulerLayer);
|
|
4620
|
-
}
|
|
4621
|
-
layer.dirty = true;
|
|
5064
|
+
this.canvasService.bringLayerToFront("ruler-overlay");
|
|
4622
5065
|
this.canvasService.requestRenderAll();
|
|
4623
5066
|
}
|
|
4624
5067
|
getGeometry() {
|
|
@@ -4666,7 +5109,7 @@ var DielineTool = class {
|
|
|
4666
5109
|
);
|
|
4667
5110
|
return null;
|
|
4668
5111
|
}
|
|
4669
|
-
const { shape, radius, features, pathData } = this.state;
|
|
5112
|
+
const { shape, shapeStyle, radius, features, pathData } = this.state;
|
|
4670
5113
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
4671
5114
|
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
4672
5115
|
const scale = sceneLayout.scale;
|
|
@@ -4694,6 +5137,7 @@ var DielineTool = class {
|
|
|
4694
5137
|
x: cx,
|
|
4695
5138
|
y: cy,
|
|
4696
5139
|
features: cutFeatures,
|
|
5140
|
+
shapeStyle,
|
|
4697
5141
|
pathData,
|
|
4698
5142
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4699
5143
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
@@ -4808,7 +5252,6 @@ var DielineTool = class {
|
|
|
4808
5252
|
import {
|
|
4809
5253
|
ContributionPointIds as ContributionPointIds5
|
|
4810
5254
|
} from "@pooder/core";
|
|
4811
|
-
import { Circle, Group, Point as Point2, Rect as Rect2 } from "fabric";
|
|
4812
5255
|
|
|
4813
5256
|
// src/extensions/constraints.ts
|
|
4814
5257
|
var ConstraintRegistry = class {
|
|
@@ -5008,6 +5451,10 @@ function completeFeaturesStrict(features, context, update) {
|
|
|
5008
5451
|
}
|
|
5009
5452
|
|
|
5010
5453
|
// src/extensions/feature.ts
|
|
5454
|
+
var FEATURE_OVERLAY_LAYER_ID = "feature-overlay";
|
|
5455
|
+
var FEATURE_STROKE_WIDTH = 2;
|
|
5456
|
+
var DEFAULT_RECT_SIZE = 10;
|
|
5457
|
+
var DEFAULT_CIRCLE_RADIUS = 5;
|
|
5011
5458
|
var FeatureTool = class {
|
|
5012
5459
|
constructor(options) {
|
|
5013
5460
|
this.id = "pooder.kit.feature";
|
|
@@ -5020,6 +5467,8 @@ var FeatureTool = class {
|
|
|
5020
5467
|
this.isFeatureSessionActive = false;
|
|
5021
5468
|
this.sessionOriginalFeatures = null;
|
|
5022
5469
|
this.hasWorkingChanges = false;
|
|
5470
|
+
this.specs = [];
|
|
5471
|
+
this.renderSeq = 0;
|
|
5023
5472
|
this.handleMoving = null;
|
|
5024
5473
|
this.handleModified = null;
|
|
5025
5474
|
this.handleSceneGeometryChange = null;
|
|
@@ -5036,12 +5485,23 @@ var FeatureTool = class {
|
|
|
5036
5485
|
}
|
|
5037
5486
|
}
|
|
5038
5487
|
activate(context) {
|
|
5488
|
+
var _a;
|
|
5039
5489
|
this.context = context;
|
|
5040
5490
|
this.canvasService = context.services.get("CanvasService");
|
|
5041
5491
|
if (!this.canvasService) {
|
|
5042
5492
|
console.warn("CanvasService not found for FeatureTool");
|
|
5043
5493
|
return;
|
|
5044
5494
|
}
|
|
5495
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5496
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
5497
|
+
this.id,
|
|
5498
|
+
() => ({
|
|
5499
|
+
rootLayerSpecs: {
|
|
5500
|
+
[FEATURE_OVERLAY_LAYER_ID]: this.specs
|
|
5501
|
+
}
|
|
5502
|
+
}),
|
|
5503
|
+
{ priority: 350 }
|
|
5504
|
+
);
|
|
5045
5505
|
const configService = context.services.get(
|
|
5046
5506
|
"ConfigurationService"
|
|
5047
5507
|
);
|
|
@@ -5080,21 +5540,7 @@ var FeatureTool = class {
|
|
|
5080
5540
|
this.context = void 0;
|
|
5081
5541
|
}
|
|
5082
5542
|
updateVisibility() {
|
|
5083
|
-
|
|
5084
|
-
const canvas = this.canvasService.canvas;
|
|
5085
|
-
const markers = canvas.getObjects().filter((obj) => {
|
|
5086
|
-
var _a;
|
|
5087
|
-
return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
5088
|
-
});
|
|
5089
|
-
markers.forEach((marker) => {
|
|
5090
|
-
marker.set({
|
|
5091
|
-
visible: this.isToolActive,
|
|
5092
|
-
// Or just selectable: false if we want them visible but locked
|
|
5093
|
-
selectable: this.isToolActive,
|
|
5094
|
-
evented: this.isToolActive
|
|
5095
|
-
});
|
|
5096
|
-
});
|
|
5097
|
-
canvas.requestRenderAll();
|
|
5543
|
+
this.redraw();
|
|
5098
5544
|
}
|
|
5099
5545
|
contribute() {
|
|
5100
5546
|
return {
|
|
@@ -5326,8 +5772,7 @@ var FeatureTool = class {
|
|
|
5326
5772
|
if (!changed) return { ok: true };
|
|
5327
5773
|
this.setWorkingFeatures(next);
|
|
5328
5774
|
this.hasWorkingChanges = true;
|
|
5329
|
-
this.redraw();
|
|
5330
|
-
this.enforceConstraints();
|
|
5775
|
+
this.redraw({ enforceConstraints: true });
|
|
5331
5776
|
this.emitWorkingChange();
|
|
5332
5777
|
return { ok: true };
|
|
5333
5778
|
}
|
|
@@ -5375,12 +5820,10 @@ var FeatureTool = class {
|
|
|
5375
5820
|
shape: "rect",
|
|
5376
5821
|
x: 0.5,
|
|
5377
5822
|
y: 0,
|
|
5378
|
-
// Top edge
|
|
5379
5823
|
width: 10,
|
|
5380
5824
|
height: 10,
|
|
5381
5825
|
rotation: 0,
|
|
5382
5826
|
renderBehavior: "edge",
|
|
5383
|
-
// Default constraint: path (snap to edge)
|
|
5384
5827
|
constraints: [{ type: "path" }]
|
|
5385
5828
|
};
|
|
5386
5829
|
this.setWorkingFeatures([...this.workingFeatures || [], newFeature]);
|
|
@@ -5423,7 +5866,7 @@ var FeatureTool = class {
|
|
|
5423
5866
|
this.emitWorkingChange();
|
|
5424
5867
|
return true;
|
|
5425
5868
|
}
|
|
5426
|
-
getGeometryForFeature(geometry,
|
|
5869
|
+
getGeometryForFeature(geometry, _feature) {
|
|
5427
5870
|
return geometry;
|
|
5428
5871
|
}
|
|
5429
5872
|
setup() {
|
|
@@ -5432,8 +5875,7 @@ var FeatureTool = class {
|
|
|
5432
5875
|
if (!this.handleSceneGeometryChange) {
|
|
5433
5876
|
this.handleSceneGeometryChange = (geometry) => {
|
|
5434
5877
|
this.currentGeometry = geometry;
|
|
5435
|
-
this.redraw();
|
|
5436
|
-
this.enforceConstraints();
|
|
5878
|
+
this.redraw({ enforceConstraints: true });
|
|
5437
5879
|
};
|
|
5438
5880
|
this.context.eventBus.on(
|
|
5439
5881
|
"scene:geometry:change",
|
|
@@ -5456,76 +5898,34 @@ var FeatureTool = class {
|
|
|
5456
5898
|
}
|
|
5457
5899
|
if (!this.handleMoving) {
|
|
5458
5900
|
this.handleMoving = (e) => {
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
} else {
|
|
5470
|
-
const index = (_d = target.data) == null ? void 0 : _d.index;
|
|
5471
|
-
if (index !== void 0) {
|
|
5472
|
-
feature = this.workingFeatures[index];
|
|
5473
|
-
}
|
|
5474
|
-
}
|
|
5475
|
-
const geometry = this.getGeometryForFeature(
|
|
5476
|
-
this.currentGeometry,
|
|
5901
|
+
const target = this.getDraggableMarkerTarget(e == null ? void 0 : e.target);
|
|
5902
|
+
if (!target || !this.currentGeometry) return;
|
|
5903
|
+
const feature = this.getFeatureForMarker(target);
|
|
5904
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5905
|
+
const snapped = this.constrainPosition(
|
|
5906
|
+
{
|
|
5907
|
+
x: Number(target.left || 0),
|
|
5908
|
+
y: Number(target.top || 0)
|
|
5909
|
+
},
|
|
5910
|
+
geometry,
|
|
5477
5911
|
feature
|
|
5478
5912
|
);
|
|
5479
|
-
const p = new Point2(target.left, target.top);
|
|
5480
|
-
const markerStrokeWidth = (target.strokeWidth || 2) * (target.scaleX || 1);
|
|
5481
|
-
const minDim = Math.min(
|
|
5482
|
-
target.getScaledWidth(),
|
|
5483
|
-
target.getScaledHeight()
|
|
5484
|
-
);
|
|
5485
|
-
const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
|
|
5486
|
-
const snapped = this.constrainPosition(p, geometry, limit, feature);
|
|
5487
5913
|
target.set({
|
|
5488
5914
|
left: snapped.x,
|
|
5489
5915
|
top: snapped.y
|
|
5490
5916
|
});
|
|
5917
|
+
target.setCoords();
|
|
5918
|
+
this.syncMarkerVisualsByTarget(target, snapped);
|
|
5491
5919
|
};
|
|
5492
5920
|
canvas.on("object:moving", this.handleMoving);
|
|
5493
5921
|
}
|
|
5494
5922
|
if (!this.handleModified) {
|
|
5495
5923
|
this.handleModified = (e) => {
|
|
5496
|
-
var _a
|
|
5497
|
-
const target = e.target;
|
|
5498
|
-
if (!target
|
|
5499
|
-
if ((
|
|
5500
|
-
|
|
5501
|
-
const indices = (_c = groupObj.data) == null ? void 0 : _c.indices;
|
|
5502
|
-
if (!indices) return;
|
|
5503
|
-
const groupCenter = new Point2(groupObj.left, groupObj.top);
|
|
5504
|
-
const newFeatures = [...this.workingFeatures];
|
|
5505
|
-
const { x, y } = this.currentGeometry;
|
|
5506
|
-
groupObj.getObjects().forEach((child, i) => {
|
|
5507
|
-
const originalIndex = indices[i];
|
|
5508
|
-
const feature = this.workingFeatures[originalIndex];
|
|
5509
|
-
const geometry = this.getGeometryForFeature(
|
|
5510
|
-
this.currentGeometry,
|
|
5511
|
-
feature
|
|
5512
|
-
);
|
|
5513
|
-
const { width, height } = geometry;
|
|
5514
|
-
const layoutLeft = x - width / 2;
|
|
5515
|
-
const layoutTop = y - height / 2;
|
|
5516
|
-
const absX = groupCenter.x + (child.left || 0);
|
|
5517
|
-
const absY = groupCenter.y + (child.top || 0);
|
|
5518
|
-
const normalizedX = width > 0 ? (absX - layoutLeft) / width : 0.5;
|
|
5519
|
-
const normalizedY = height > 0 ? (absY - layoutTop) / height : 0.5;
|
|
5520
|
-
newFeatures[originalIndex] = {
|
|
5521
|
-
...newFeatures[originalIndex],
|
|
5522
|
-
x: normalizedX,
|
|
5523
|
-
y: normalizedY
|
|
5524
|
-
};
|
|
5525
|
-
});
|
|
5526
|
-
this.setWorkingFeatures(newFeatures);
|
|
5527
|
-
this.hasWorkingChanges = true;
|
|
5528
|
-
this.emitWorkingChange();
|
|
5924
|
+
var _a;
|
|
5925
|
+
const target = this.getDraggableMarkerTarget(e == null ? void 0 : e.target);
|
|
5926
|
+
if (!target) return;
|
|
5927
|
+
if ((_a = target.data) == null ? void 0 : _a.isGroup) {
|
|
5928
|
+
this.syncGroupFromCanvas(target);
|
|
5529
5929
|
} else {
|
|
5530
5930
|
this.syncFeatureFromCanvas(target);
|
|
5531
5931
|
}
|
|
@@ -5534,6 +5934,7 @@ var FeatureTool = class {
|
|
|
5534
5934
|
}
|
|
5535
5935
|
}
|
|
5536
5936
|
teardown() {
|
|
5937
|
+
var _a;
|
|
5537
5938
|
if (!this.canvasService) return;
|
|
5538
5939
|
const canvas = this.canvasService.canvas;
|
|
5539
5940
|
if (this.handleMoving) {
|
|
@@ -5551,14 +5952,25 @@ var FeatureTool = class {
|
|
|
5551
5952
|
);
|
|
5552
5953
|
this.handleSceneGeometryChange = null;
|
|
5553
5954
|
}
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
this.canvasService.requestRenderAll();
|
|
5955
|
+
this.renderSeq += 1;
|
|
5956
|
+
this.specs = [];
|
|
5957
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5958
|
+
this.renderProducerDisposable = void 0;
|
|
5959
|
+
void this.canvasService.flushRenderFromProducers();
|
|
5560
5960
|
}
|
|
5561
|
-
|
|
5961
|
+
getDraggableMarkerTarget(target) {
|
|
5962
|
+
var _a, _b;
|
|
5963
|
+
if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "feature-marker") return null;
|
|
5964
|
+
if (((_b = target.data) == null ? void 0 : _b.markerRole) !== "handle") return null;
|
|
5965
|
+
return target;
|
|
5966
|
+
}
|
|
5967
|
+
getFeatureForMarker(target) {
|
|
5968
|
+
const data = (target == null ? void 0 : target.data) || {};
|
|
5969
|
+
const index = data.isGroup ? this.toFeatureIndex(data.anchorIndex) : this.toFeatureIndex(data.index);
|
|
5970
|
+
if (index === null) return void 0;
|
|
5971
|
+
return this.workingFeatures[index];
|
|
5972
|
+
}
|
|
5973
|
+
constrainPosition(p, geometry, feature) {
|
|
5562
5974
|
var _a;
|
|
5563
5975
|
if (!feature) {
|
|
5564
5976
|
return { x: p.x, y: p.y };
|
|
@@ -5589,225 +6001,364 @@ var FeatureTool = class {
|
|
|
5589
6001
|
y: minY + constrained.y * geometry.height
|
|
5590
6002
|
};
|
|
5591
6003
|
}
|
|
6004
|
+
toNormalizedPoint(point, geometry) {
|
|
6005
|
+
const left = geometry.x - geometry.width / 2;
|
|
6006
|
+
const top = geometry.y - geometry.height / 2;
|
|
6007
|
+
return {
|
|
6008
|
+
x: geometry.width > 0 ? (point.x - left) / geometry.width : 0.5,
|
|
6009
|
+
y: geometry.height > 0 ? (point.y - top) / geometry.height : 0.5
|
|
6010
|
+
};
|
|
6011
|
+
}
|
|
5592
6012
|
syncFeatureFromCanvas(target) {
|
|
5593
6013
|
var _a;
|
|
5594
|
-
if (!this.currentGeometry
|
|
5595
|
-
const index = (_a = target.data) == null ? void 0 : _a.index;
|
|
5596
|
-
if (index ===
|
|
5597
|
-
return;
|
|
6014
|
+
if (!this.currentGeometry) return;
|
|
6015
|
+
const index = this.toFeatureIndex((_a = target.data) == null ? void 0 : _a.index);
|
|
6016
|
+
if (index === null || index >= this.workingFeatures.length) return;
|
|
5598
6017
|
const feature = this.workingFeatures[index];
|
|
5599
6018
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5600
|
-
const
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
6019
|
+
const normalized = this.toNormalizedPoint(
|
|
6020
|
+
{
|
|
6021
|
+
x: Number(target.left || 0),
|
|
6022
|
+
y: Number(target.top || 0)
|
|
6023
|
+
},
|
|
6024
|
+
geometry
|
|
6025
|
+
);
|
|
5605
6026
|
const updatedFeature = {
|
|
5606
6027
|
...feature,
|
|
5607
|
-
x:
|
|
5608
|
-
y:
|
|
5609
|
-
// Could also update rotation if we allowed rotating markers
|
|
6028
|
+
x: normalized.x,
|
|
6029
|
+
y: normalized.y
|
|
5610
6030
|
};
|
|
5611
|
-
const
|
|
5612
|
-
|
|
5613
|
-
this.setWorkingFeatures(
|
|
6031
|
+
const next = [...this.workingFeatures];
|
|
6032
|
+
next[index] = updatedFeature;
|
|
6033
|
+
this.setWorkingFeatures(next);
|
|
5614
6034
|
this.hasWorkingChanges = true;
|
|
5615
6035
|
this.emitWorkingChange();
|
|
5616
6036
|
}
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
const
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
6037
|
+
syncGroupFromCanvas(target) {
|
|
6038
|
+
var _a, _b;
|
|
6039
|
+
if (!this.currentGeometry) return;
|
|
6040
|
+
const indices = this.readGroupIndices((_a = target.data) == null ? void 0 : _a.indices);
|
|
6041
|
+
if (indices.length === 0) return;
|
|
6042
|
+
const offsets = this.readGroupMemberOffsets((_b = target.data) == null ? void 0 : _b.memberOffsets, indices);
|
|
6043
|
+
const anchorCenter = {
|
|
6044
|
+
x: Number(target.left || 0),
|
|
6045
|
+
y: Number(target.top || 0)
|
|
6046
|
+
};
|
|
6047
|
+
const next = [...this.workingFeatures];
|
|
6048
|
+
let changed = false;
|
|
6049
|
+
offsets.forEach((entry) => {
|
|
6050
|
+
const index = entry.index;
|
|
6051
|
+
if (index < 0 || index >= next.length) return;
|
|
6052
|
+
const feature = next[index];
|
|
6053
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
6054
|
+
const normalized = this.toNormalizedPoint(
|
|
6055
|
+
{
|
|
6056
|
+
x: anchorCenter.x + entry.dx,
|
|
6057
|
+
y: anchorCenter.y + entry.dy
|
|
6058
|
+
},
|
|
6059
|
+
geometry
|
|
6060
|
+
);
|
|
6061
|
+
if (feature.x !== normalized.x || feature.y !== normalized.y) {
|
|
6062
|
+
next[index] = {
|
|
6063
|
+
...feature,
|
|
6064
|
+
x: normalized.x,
|
|
6065
|
+
y: normalized.y
|
|
6066
|
+
};
|
|
6067
|
+
changed = true;
|
|
6068
|
+
}
|
|
5624
6069
|
});
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
6070
|
+
if (!changed) return;
|
|
6071
|
+
this.setWorkingFeatures(next);
|
|
6072
|
+
this.hasWorkingChanges = true;
|
|
6073
|
+
this.emitWorkingChange();
|
|
6074
|
+
}
|
|
6075
|
+
redraw(options = {}) {
|
|
6076
|
+
void this.redrawAsync(options);
|
|
6077
|
+
}
|
|
6078
|
+
async redrawAsync(options = {}) {
|
|
6079
|
+
if (!this.canvasService) return;
|
|
6080
|
+
const seq = ++this.renderSeq;
|
|
6081
|
+
this.specs = this.buildFeatureSpecs();
|
|
6082
|
+
if (seq !== this.renderSeq) return;
|
|
6083
|
+
await this.canvasService.flushRenderFromProducers();
|
|
6084
|
+
if (seq !== this.renderSeq) return;
|
|
6085
|
+
this.syncOverlayOrder();
|
|
6086
|
+
if (options.enforceConstraints) {
|
|
6087
|
+
this.enforceConstraints();
|
|
5629
6088
|
}
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
6089
|
+
}
|
|
6090
|
+
syncOverlayOrder() {
|
|
6091
|
+
if (!this.canvasService) return;
|
|
6092
|
+
this.canvasService.bringLayerToFront(FEATURE_OVERLAY_LAYER_ID);
|
|
6093
|
+
this.canvasService.bringLayerToFront("ruler-overlay");
|
|
6094
|
+
}
|
|
6095
|
+
buildFeatureSpecs() {
|
|
6096
|
+
if (!this.currentGeometry || this.workingFeatures.length === 0) {
|
|
6097
|
+
return [];
|
|
6098
|
+
}
|
|
6099
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5633
6100
|
const singles = [];
|
|
5634
|
-
this.workingFeatures.forEach((
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
6101
|
+
this.workingFeatures.forEach((feature, index) => {
|
|
6102
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
6103
|
+
const position = resolveFeaturePosition(feature, geometry);
|
|
6104
|
+
const scale = geometry.scale || 1;
|
|
6105
|
+
const marker = {
|
|
6106
|
+
feature,
|
|
6107
|
+
index,
|
|
6108
|
+
position,
|
|
6109
|
+
geometry,
|
|
6110
|
+
scale
|
|
6111
|
+
};
|
|
6112
|
+
if (feature.groupId) {
|
|
6113
|
+
const list = groups.get(feature.groupId) || [];
|
|
6114
|
+
list.push(marker);
|
|
6115
|
+
groups.set(feature.groupId, list);
|
|
6116
|
+
return;
|
|
5640
6117
|
}
|
|
6118
|
+
singles.push(marker);
|
|
6119
|
+
});
|
|
6120
|
+
const specs = [];
|
|
6121
|
+
singles.forEach((marker) => {
|
|
6122
|
+
this.appendMarkerSpecs(specs, marker, {
|
|
6123
|
+
markerRole: "handle",
|
|
6124
|
+
isGroup: false
|
|
6125
|
+
});
|
|
6126
|
+
});
|
|
6127
|
+
groups.forEach((members, groupId) => {
|
|
6128
|
+
if (!members.length) return;
|
|
6129
|
+
const anchor = members[0];
|
|
6130
|
+
const memberOffsets = members.map((member) => ({
|
|
6131
|
+
index: member.index,
|
|
6132
|
+
dx: member.position.x - anchor.position.x,
|
|
6133
|
+
dy: member.position.y - anchor.position.y
|
|
6134
|
+
}));
|
|
6135
|
+
const indices = members.map((member) => member.index);
|
|
6136
|
+
members.filter((member) => member.index !== anchor.index).forEach((member) => {
|
|
6137
|
+
this.appendMarkerSpecs(specs, member, {
|
|
6138
|
+
markerRole: "member",
|
|
6139
|
+
isGroup: false,
|
|
6140
|
+
groupId
|
|
6141
|
+
});
|
|
6142
|
+
});
|
|
6143
|
+
this.appendMarkerSpecs(specs, anchor, {
|
|
6144
|
+
markerRole: "handle",
|
|
6145
|
+
isGroup: true,
|
|
6146
|
+
groupId,
|
|
6147
|
+
indices,
|
|
6148
|
+
anchorIndex: anchor.index,
|
|
6149
|
+
memberOffsets
|
|
6150
|
+
});
|
|
5641
6151
|
});
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
6152
|
+
return specs;
|
|
6153
|
+
}
|
|
6154
|
+
appendMarkerSpecs(specs, marker, options) {
|
|
6155
|
+
var _a, _b, _c, _d, _e;
|
|
6156
|
+
const { feature, index, position, scale, geometry } = marker;
|
|
6157
|
+
const baseRadius = feature.shape === "circle" ? (_a = feature.radius) != null ? _a : DEFAULT_CIRCLE_RADIUS : (_b = feature.radius) != null ? _b : 0;
|
|
6158
|
+
const baseWidth = feature.shape === "circle" ? baseRadius * 2 : (_c = feature.width) != null ? _c : DEFAULT_RECT_SIZE;
|
|
6159
|
+
const baseHeight = feature.shape === "circle" ? baseRadius * 2 : (_d = feature.height) != null ? _d : DEFAULT_RECT_SIZE;
|
|
6160
|
+
const visualWidth = baseWidth * scale;
|
|
6161
|
+
const visualHeight = baseHeight * scale;
|
|
6162
|
+
const visualRadius = baseRadius * scale;
|
|
6163
|
+
const color = feature.color || (feature.operation === "add" ? "#00FF00" : "#FF0000");
|
|
6164
|
+
const strokeDash = feature.strokeDash || (feature.operation === "subtract" ? [4, 4] : void 0);
|
|
6165
|
+
const interactive = options.markerRole === "handle";
|
|
6166
|
+
const baseData = this.buildMarkerData(marker, options);
|
|
6167
|
+
const commonProps = {
|
|
6168
|
+
visible: this.isToolActive,
|
|
6169
|
+
selectable: interactive && this.isToolActive,
|
|
6170
|
+
evented: interactive && this.isToolActive,
|
|
6171
|
+
hasControls: false,
|
|
6172
|
+
hasBorders: false,
|
|
6173
|
+
hoverCursor: interactive ? "move" : "default",
|
|
6174
|
+
lockRotation: true,
|
|
6175
|
+
lockScalingX: true,
|
|
6176
|
+
lockScalingY: true,
|
|
6177
|
+
fill: "transparent",
|
|
6178
|
+
stroke: color,
|
|
6179
|
+
strokeWidth: FEATURE_STROKE_WIDTH,
|
|
6180
|
+
strokeDashArray: strokeDash,
|
|
6181
|
+
originX: "center",
|
|
6182
|
+
originY: "center",
|
|
6183
|
+
left: position.x,
|
|
6184
|
+
top: position.y,
|
|
6185
|
+
angle: feature.rotation || 0
|
|
6186
|
+
};
|
|
6187
|
+
const markerId = this.markerId(index);
|
|
6188
|
+
if (feature.shape === "rect") {
|
|
6189
|
+
specs.push({
|
|
6190
|
+
id: markerId,
|
|
6191
|
+
type: "rect",
|
|
6192
|
+
space: "screen",
|
|
6193
|
+
data: baseData,
|
|
6194
|
+
props: {
|
|
6195
|
+
...commonProps,
|
|
5652
6196
|
width: visualWidth,
|
|
5653
6197
|
height: visualHeight,
|
|
5654
6198
|
rx: visualRadius,
|
|
5655
|
-
ry: visualRadius
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
shape.rotate(feature.rotation);
|
|
6199
|
+
ry: visualRadius
|
|
6200
|
+
}
|
|
6201
|
+
});
|
|
6202
|
+
} else {
|
|
6203
|
+
specs.push({
|
|
6204
|
+
id: markerId,
|
|
6205
|
+
type: "rect",
|
|
6206
|
+
space: "screen",
|
|
6207
|
+
data: baseData,
|
|
6208
|
+
props: {
|
|
6209
|
+
...commonProps,
|
|
6210
|
+
width: visualWidth,
|
|
6211
|
+
height: visualHeight,
|
|
6212
|
+
rx: visualRadius,
|
|
6213
|
+
ry: visualRadius
|
|
6214
|
+
}
|
|
6215
|
+
});
|
|
6216
|
+
}
|
|
6217
|
+
if (((_e = feature.bridge) == null ? void 0 : _e.type) === "vertical") {
|
|
6218
|
+
const featureTopY = position.y - visualHeight / 2;
|
|
6219
|
+
const dielineTopY = geometry.y - geometry.height / 2;
|
|
6220
|
+
const bridgeHeight = Math.max(0, featureTopY - dielineTopY);
|
|
6221
|
+
if (bridgeHeight <= 1e-3) {
|
|
6222
|
+
return;
|
|
5680
6223
|
}
|
|
5681
|
-
|
|
5682
|
-
|
|
6224
|
+
specs.push({
|
|
6225
|
+
id: this.bridgeIndicatorId(index),
|
|
6226
|
+
type: "rect",
|
|
6227
|
+
space: "screen",
|
|
6228
|
+
data: {
|
|
6229
|
+
...baseData,
|
|
6230
|
+
markerRole: "indicator",
|
|
6231
|
+
markerOffsetX: 0,
|
|
6232
|
+
markerOffsetY: -visualHeight / 2
|
|
6233
|
+
},
|
|
6234
|
+
props: {
|
|
6235
|
+
visible: this.isToolActive,
|
|
6236
|
+
selectable: false,
|
|
6237
|
+
evented: false,
|
|
5683
6238
|
width: visualWidth,
|
|
5684
|
-
height:
|
|
5685
|
-
// Arbitrary long length to show direction
|
|
6239
|
+
height: bridgeHeight,
|
|
5686
6240
|
fill: "transparent",
|
|
5687
6241
|
stroke: "#888",
|
|
5688
6242
|
strokeWidth: 1,
|
|
5689
6243
|
strokeDashArray: [2, 2],
|
|
5690
|
-
originX: "center",
|
|
5691
|
-
originY: "bottom",
|
|
5692
|
-
// Anchor at bottom so it extends up
|
|
5693
|
-
left: pos.x,
|
|
5694
|
-
top: pos.y - visualHeight / 2,
|
|
5695
|
-
// Start from top of feature
|
|
5696
6244
|
opacity: 0.5,
|
|
5697
|
-
selectable: false,
|
|
5698
|
-
evented: false
|
|
5699
|
-
});
|
|
5700
|
-
const group = new Group([bridgeIndicator, shape], {
|
|
5701
6245
|
originX: "center",
|
|
5702
|
-
originY: "
|
|
5703
|
-
left:
|
|
5704
|
-
top:
|
|
5705
|
-
}
|
|
5706
|
-
return group;
|
|
5707
|
-
}
|
|
5708
|
-
return shape;
|
|
5709
|
-
};
|
|
5710
|
-
singles.forEach(({ feature, index }) => {
|
|
5711
|
-
const geometry2 = this.getGeometryForFeature(
|
|
5712
|
-
this.currentGeometry,
|
|
5713
|
-
feature
|
|
5714
|
-
);
|
|
5715
|
-
const pos = resolveFeaturePosition(feature, geometry2);
|
|
5716
|
-
const marker = createMarkerShape(feature, pos);
|
|
5717
|
-
marker.set({
|
|
5718
|
-
visible: this.isToolActive,
|
|
5719
|
-
selectable: this.isToolActive,
|
|
5720
|
-
evented: this.isToolActive,
|
|
5721
|
-
hasControls: false,
|
|
5722
|
-
hasBorders: false,
|
|
5723
|
-
hoverCursor: "move",
|
|
5724
|
-
lockRotation: true,
|
|
5725
|
-
lockScalingX: true,
|
|
5726
|
-
lockScalingY: true,
|
|
5727
|
-
data: { type: "feature-marker", index, isGroup: false }
|
|
5728
|
-
});
|
|
5729
|
-
canvas.add(marker);
|
|
5730
|
-
canvas.bringObjectToFront(marker);
|
|
5731
|
-
});
|
|
5732
|
-
Object.keys(groups).forEach((groupId) => {
|
|
5733
|
-
const members = groups[groupId];
|
|
5734
|
-
if (members.length === 0) return;
|
|
5735
|
-
const shapes = members.map(({ feature }) => {
|
|
5736
|
-
const geometry2 = this.getGeometryForFeature(
|
|
5737
|
-
this.currentGeometry,
|
|
5738
|
-
feature
|
|
5739
|
-
);
|
|
5740
|
-
const pos = resolveFeaturePosition(feature, geometry2);
|
|
5741
|
-
return createMarkerShape(feature, pos);
|
|
6246
|
+
originY: "bottom",
|
|
6247
|
+
left: position.x,
|
|
6248
|
+
top: position.y - visualHeight / 2
|
|
6249
|
+
}
|
|
5742
6250
|
});
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6253
|
+
buildMarkerData(marker, options) {
|
|
6254
|
+
const data = {
|
|
6255
|
+
type: "feature-marker",
|
|
6256
|
+
index: marker.index,
|
|
6257
|
+
featureId: marker.feature.id,
|
|
6258
|
+
markerRole: options.markerRole,
|
|
6259
|
+
markerOffsetX: 0,
|
|
6260
|
+
markerOffsetY: 0,
|
|
6261
|
+
isGroup: options.isGroup
|
|
6262
|
+
};
|
|
6263
|
+
if (options.groupId) data.groupId = options.groupId;
|
|
6264
|
+
if (options.indices) data.indices = options.indices;
|
|
6265
|
+
if (options.anchorIndex !== void 0) data.anchorIndex = options.anchorIndex;
|
|
6266
|
+
if (options.memberOffsets) data.memberOffsets = options.memberOffsets;
|
|
6267
|
+
return data;
|
|
6268
|
+
}
|
|
6269
|
+
markerId(index) {
|
|
6270
|
+
return `feature.marker.${index}`;
|
|
6271
|
+
}
|
|
6272
|
+
bridgeIndicatorId(index) {
|
|
6273
|
+
return `feature.marker.${index}.bridge`;
|
|
6274
|
+
}
|
|
6275
|
+
toFeatureIndex(value) {
|
|
6276
|
+
const numeric = Number(value);
|
|
6277
|
+
if (!Number.isInteger(numeric) || numeric < 0) return null;
|
|
6278
|
+
return numeric;
|
|
6279
|
+
}
|
|
6280
|
+
readGroupIndices(raw) {
|
|
6281
|
+
if (!Array.isArray(raw)) return [];
|
|
6282
|
+
return raw.map((value) => this.toFeatureIndex(value)).filter((value) => value !== null);
|
|
6283
|
+
}
|
|
6284
|
+
readGroupMemberOffsets(raw, fallbackIndices = []) {
|
|
6285
|
+
if (Array.isArray(raw)) {
|
|
6286
|
+
const parsed = raw.map((entry) => {
|
|
6287
|
+
const index = this.toFeatureIndex(entry == null ? void 0 : entry.index);
|
|
6288
|
+
const dx = Number(entry == null ? void 0 : entry.dx);
|
|
6289
|
+
const dy = Number(entry == null ? void 0 : entry.dy);
|
|
6290
|
+
if (index === null || !Number.isFinite(dx) || !Number.isFinite(dy)) {
|
|
6291
|
+
return null;
|
|
5763
6292
|
}
|
|
6293
|
+
return { index, dx, dy };
|
|
6294
|
+
}).filter((value) => !!value);
|
|
6295
|
+
if (parsed.length > 0) return parsed;
|
|
6296
|
+
}
|
|
6297
|
+
return fallbackIndices.map((index) => ({ index, dx: 0, dy: 0 }));
|
|
6298
|
+
}
|
|
6299
|
+
syncMarkerVisualsByTarget(target, center) {
|
|
6300
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6301
|
+
if ((_a = target.data) == null ? void 0 : _a.isGroup) {
|
|
6302
|
+
const indices = this.readGroupIndices((_b = target.data) == null ? void 0 : _b.indices);
|
|
6303
|
+
const offsets = this.readGroupMemberOffsets((_c = target.data) == null ? void 0 : _c.memberOffsets, indices);
|
|
6304
|
+
offsets.forEach((entry) => {
|
|
6305
|
+
this.syncMarkerVisualObjectsToCenter(entry.index, {
|
|
6306
|
+
x: center.x + entry.dx,
|
|
6307
|
+
y: center.y + entry.dy
|
|
6308
|
+
});
|
|
5764
6309
|
});
|
|
5765
|
-
|
|
5766
|
-
|
|
6310
|
+
(_d = this.canvasService) == null ? void 0 : _d.requestRenderAll();
|
|
6311
|
+
return;
|
|
6312
|
+
}
|
|
6313
|
+
const index = this.toFeatureIndex((_e = target.data) == null ? void 0 : _e.index);
|
|
6314
|
+
if (index === null) return;
|
|
6315
|
+
this.syncMarkerVisualObjectsToCenter(index, center);
|
|
6316
|
+
(_f = this.canvasService) == null ? void 0 : _f.requestRenderAll();
|
|
6317
|
+
}
|
|
6318
|
+
syncMarkerVisualObjectsToCenter(index, center) {
|
|
6319
|
+
if (!this.canvasService) return;
|
|
6320
|
+
const markers = this.canvasService.canvas.getObjects().filter(
|
|
6321
|
+
(obj) => {
|
|
6322
|
+
var _a, _b;
|
|
6323
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.type) === "feature-marker" && this.toFeatureIndex((_b = obj == null ? void 0 : obj.data) == null ? void 0 : _b.index) === index;
|
|
6324
|
+
}
|
|
6325
|
+
);
|
|
6326
|
+
markers.forEach((marker) => {
|
|
6327
|
+
var _a, _b;
|
|
6328
|
+
const offsetX = Number(((_a = marker == null ? void 0 : marker.data) == null ? void 0 : _a.markerOffsetX) || 0);
|
|
6329
|
+
const offsetY = Number(((_b = marker == null ? void 0 : marker.data) == null ? void 0 : _b.markerOffsetY) || 0);
|
|
6330
|
+
marker.set({
|
|
6331
|
+
left: center.x + offsetX,
|
|
6332
|
+
top: center.y + offsetY
|
|
6333
|
+
});
|
|
6334
|
+
marker.setCoords();
|
|
5767
6335
|
});
|
|
5768
|
-
this.canvasService.requestRenderAll();
|
|
5769
6336
|
}
|
|
5770
6337
|
enforceConstraints() {
|
|
5771
6338
|
if (!this.canvasService || !this.currentGeometry) return;
|
|
5772
|
-
const
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
});
|
|
5777
|
-
markers.forEach((marker) => {
|
|
5778
|
-
var _a, _b, _c;
|
|
5779
|
-
let feature;
|
|
5780
|
-
if ((_a = marker.data) == null ? void 0 : _a.isGroup) {
|
|
5781
|
-
const indices = (_b = marker.data) == null ? void 0 : _b.indices;
|
|
5782
|
-
if (indices && indices.length > 0) {
|
|
5783
|
-
feature = this.workingFeatures[indices[0]];
|
|
5784
|
-
}
|
|
5785
|
-
} else {
|
|
5786
|
-
const index = (_c = marker.data) == null ? void 0 : _c.index;
|
|
5787
|
-
if (index !== void 0) {
|
|
5788
|
-
feature = this.workingFeatures[index];
|
|
5789
|
-
}
|
|
6339
|
+
const handles = this.canvasService.canvas.getObjects().filter(
|
|
6340
|
+
(obj) => {
|
|
6341
|
+
var _a, _b;
|
|
6342
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.type) === "feature-marker" && ((_b = obj == null ? void 0 : obj.data) == null ? void 0 : _b.markerRole) === "handle";
|
|
5790
6343
|
}
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
);
|
|
5795
|
-
const
|
|
5796
|
-
const minDim = Math.min(
|
|
5797
|
-
marker.getScaledWidth(),
|
|
5798
|
-
marker.getScaledHeight()
|
|
5799
|
-
);
|
|
5800
|
-
const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
|
|
6344
|
+
);
|
|
6345
|
+
handles.forEach((marker) => {
|
|
6346
|
+
const feature = this.getFeatureForMarker(marker);
|
|
6347
|
+
if (!feature) return;
|
|
6348
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5801
6349
|
const snapped = this.constrainPosition(
|
|
5802
|
-
|
|
6350
|
+
{
|
|
6351
|
+
x: Number(marker.left || 0),
|
|
6352
|
+
y: Number(marker.top || 0)
|
|
6353
|
+
},
|
|
5803
6354
|
geometry,
|
|
5804
|
-
limit,
|
|
5805
6355
|
feature
|
|
5806
6356
|
);
|
|
5807
6357
|
marker.set({ left: snapped.x, top: snapped.y });
|
|
5808
6358
|
marker.setCoords();
|
|
6359
|
+
this.syncMarkerVisualsByTarget(marker, snapped);
|
|
5809
6360
|
});
|
|
5810
|
-
canvas.requestRenderAll();
|
|
6361
|
+
this.canvasService.canvas.requestRenderAll();
|
|
5811
6362
|
}
|
|
5812
6363
|
};
|
|
5813
6364
|
|
|
@@ -5815,7 +6366,11 @@ var FeatureTool = class {
|
|
|
5815
6366
|
import {
|
|
5816
6367
|
ContributionPointIds as ContributionPointIds6
|
|
5817
6368
|
} from "@pooder/core";
|
|
5818
|
-
import { FabricImage as
|
|
6369
|
+
import { FabricImage as FabricImage3 } from "fabric";
|
|
6370
|
+
var FILM_LAYER_ID = "overlay";
|
|
6371
|
+
var FILM_IMAGE_ID = "film-image";
|
|
6372
|
+
var DEFAULT_WIDTH2 = 800;
|
|
6373
|
+
var DEFAULT_HEIGHT2 = 600;
|
|
5819
6374
|
var FilmTool = class {
|
|
5820
6375
|
constructor(options) {
|
|
5821
6376
|
this.id = "pooder.kit.film";
|
|
@@ -5824,17 +6379,38 @@ var FilmTool = class {
|
|
|
5824
6379
|
};
|
|
5825
6380
|
this.url = "";
|
|
5826
6381
|
this.opacity = 0.5;
|
|
6382
|
+
this.specs = [];
|
|
6383
|
+
this.renderSeq = 0;
|
|
6384
|
+
this.renderImageUrl = "";
|
|
6385
|
+
this.sourceSizeBySrc = /* @__PURE__ */ new Map();
|
|
6386
|
+
this.pendingSizeBySrc = /* @__PURE__ */ new Map();
|
|
6387
|
+
this.onCanvasResized = () => {
|
|
6388
|
+
this.updateFilm();
|
|
6389
|
+
};
|
|
5827
6390
|
if (options) {
|
|
5828
6391
|
Object.assign(this, options);
|
|
5829
6392
|
}
|
|
5830
6393
|
}
|
|
5831
6394
|
activate(context) {
|
|
6395
|
+
var _a;
|
|
5832
6396
|
this.canvasService = context.services.get("CanvasService");
|
|
5833
6397
|
if (!this.canvasService) {
|
|
5834
6398
|
console.warn("CanvasService not found for FilmTool");
|
|
5835
6399
|
return;
|
|
5836
6400
|
}
|
|
5837
|
-
|
|
6401
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6402
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
6403
|
+
this.id,
|
|
6404
|
+
() => ({
|
|
6405
|
+
layerSpecs: {
|
|
6406
|
+
[FILM_LAYER_ID]: this.specs
|
|
6407
|
+
}
|
|
6408
|
+
}),
|
|
6409
|
+
{ priority: 500 }
|
|
6410
|
+
);
|
|
6411
|
+
const configService = context.services.get(
|
|
6412
|
+
"ConfigurationService"
|
|
6413
|
+
);
|
|
5838
6414
|
if (configService) {
|
|
5839
6415
|
this.url = configService.get("film.url", this.url);
|
|
5840
6416
|
this.opacity = configService.get("film.opacity", this.opacity);
|
|
@@ -5851,21 +6427,21 @@ var FilmTool = class {
|
|
|
5851
6427
|
}
|
|
5852
6428
|
});
|
|
5853
6429
|
}
|
|
5854
|
-
this.
|
|
6430
|
+
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
5855
6431
|
this.updateFilm();
|
|
5856
6432
|
}
|
|
5857
6433
|
deactivate(context) {
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
6434
|
+
var _a;
|
|
6435
|
+
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
6436
|
+
this.renderSeq += 1;
|
|
6437
|
+
this.specs = [];
|
|
6438
|
+
this.renderImageUrl = "";
|
|
6439
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6440
|
+
this.renderProducerDisposable = void 0;
|
|
6441
|
+
if (!this.canvasService) return;
|
|
6442
|
+
void this.canvasService.flushRenderFromProducers();
|
|
6443
|
+
this.canvasService.requestRenderAll();
|
|
6444
|
+
this.canvasService = void 0;
|
|
5869
6445
|
}
|
|
5870
6446
|
contribute() {
|
|
5871
6447
|
return {
|
|
@@ -5901,73 +6477,108 @@ var FilmTool = class {
|
|
|
5901
6477
|
]
|
|
5902
6478
|
};
|
|
5903
6479
|
}
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
height,
|
|
5913
|
-
left: 0,
|
|
5914
|
-
top: 0,
|
|
5915
|
-
originX: "left",
|
|
5916
|
-
originY: "top",
|
|
5917
|
-
selectable: false,
|
|
5918
|
-
evented: false,
|
|
5919
|
-
subTargetCheck: false,
|
|
5920
|
-
interactive: false
|
|
5921
|
-
});
|
|
5922
|
-
this.canvasService.canvas.bringObjectToFront(layer);
|
|
5923
|
-
}
|
|
6480
|
+
getViewportSize() {
|
|
6481
|
+
var _a, _b;
|
|
6482
|
+
const width = Number(((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 0);
|
|
6483
|
+
const height = Number(((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 0);
|
|
6484
|
+
return {
|
|
6485
|
+
width: width > 0 ? width : DEFAULT_WIDTH2,
|
|
6486
|
+
height: height > 0 ? height : DEFAULT_HEIGHT2
|
|
6487
|
+
};
|
|
5924
6488
|
}
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
return;
|
|
5931
|
-
}
|
|
5932
|
-
const { url, opacity } = this;
|
|
5933
|
-
if (!url) {
|
|
5934
|
-
const img2 = this.canvasService.getObject("film-image", "overlay");
|
|
5935
|
-
if (img2) {
|
|
5936
|
-
layer.remove(img2);
|
|
5937
|
-
this.canvasService.requestRenderAll();
|
|
5938
|
-
}
|
|
5939
|
-
return;
|
|
6489
|
+
clampOpacity(value) {
|
|
6490
|
+
return Math.max(0, Math.min(1, Number(value)));
|
|
6491
|
+
}
|
|
6492
|
+
buildFilmSpecs(imageUrl, opacity) {
|
|
6493
|
+
if (!imageUrl) {
|
|
6494
|
+
return [];
|
|
5940
6495
|
}
|
|
5941
|
-
const width = this.
|
|
5942
|
-
const
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
6496
|
+
const { width, height } = this.getViewportSize();
|
|
6497
|
+
const sourceSize = this.sourceSizeBySrc.get(imageUrl);
|
|
6498
|
+
const sourceWidth = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.width) || width));
|
|
6499
|
+
const sourceHeight = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.height) || height));
|
|
6500
|
+
const coverScale = Math.max(width / sourceWidth, height / sourceHeight);
|
|
6501
|
+
return [
|
|
6502
|
+
{
|
|
6503
|
+
id: FILM_IMAGE_ID,
|
|
6504
|
+
type: "image",
|
|
6505
|
+
src: imageUrl,
|
|
6506
|
+
space: "screen",
|
|
6507
|
+
data: {
|
|
6508
|
+
id: FILM_IMAGE_ID,
|
|
6509
|
+
layerId: FILM_LAYER_ID,
|
|
6510
|
+
type: "film-image"
|
|
6511
|
+
},
|
|
6512
|
+
props: {
|
|
5957
6513
|
left: 0,
|
|
5958
6514
|
top: 0,
|
|
5959
|
-
|
|
6515
|
+
originX: "left",
|
|
6516
|
+
originY: "top",
|
|
6517
|
+
opacity: this.clampOpacity(opacity),
|
|
6518
|
+
scaleX: coverScale,
|
|
6519
|
+
scaleY: coverScale,
|
|
5960
6520
|
selectable: false,
|
|
5961
6521
|
evented: false,
|
|
5962
|
-
|
|
5963
|
-
}
|
|
5964
|
-
|
|
6522
|
+
excludeFromExport: true
|
|
6523
|
+
}
|
|
6524
|
+
}
|
|
6525
|
+
];
|
|
6526
|
+
}
|
|
6527
|
+
async ensureImageSize(src) {
|
|
6528
|
+
if (!src) return null;
|
|
6529
|
+
const cached = this.sourceSizeBySrc.get(src);
|
|
6530
|
+
if (cached) return cached;
|
|
6531
|
+
const pending = this.pendingSizeBySrc.get(src);
|
|
6532
|
+
if (pending) {
|
|
6533
|
+
return pending;
|
|
6534
|
+
}
|
|
6535
|
+
const task = this.loadImageSize(src);
|
|
6536
|
+
this.pendingSizeBySrc.set(src, task);
|
|
6537
|
+
try {
|
|
6538
|
+
return await task;
|
|
6539
|
+
} finally {
|
|
6540
|
+
if (this.pendingSizeBySrc.get(src) === task) {
|
|
6541
|
+
this.pendingSizeBySrc.delete(src);
|
|
6542
|
+
}
|
|
6543
|
+
}
|
|
6544
|
+
}
|
|
6545
|
+
async loadImageSize(src) {
|
|
6546
|
+
try {
|
|
6547
|
+
const image = await FabricImage3.fromURL(src, {
|
|
6548
|
+
crossOrigin: "anonymous"
|
|
6549
|
+
});
|
|
6550
|
+
const width = Number((image == null ? void 0 : image.width) || 0);
|
|
6551
|
+
const height = Number((image == null ? void 0 : image.height) || 0);
|
|
6552
|
+
if (width > 0 && height > 0) {
|
|
6553
|
+
const size = { width, height };
|
|
6554
|
+
this.sourceSizeBySrc.set(src, size);
|
|
6555
|
+
return size;
|
|
5965
6556
|
}
|
|
5966
|
-
this.canvasService.requestRenderAll();
|
|
5967
6557
|
} catch (error) {
|
|
5968
|
-
console.error("[FilmTool] Failed to load film image",
|
|
6558
|
+
console.error("[FilmTool] Failed to load film image", src, error);
|
|
6559
|
+
}
|
|
6560
|
+
return null;
|
|
6561
|
+
}
|
|
6562
|
+
updateFilm() {
|
|
6563
|
+
void this.updateFilmAsync();
|
|
6564
|
+
}
|
|
6565
|
+
async updateFilmAsync() {
|
|
6566
|
+
if (!this.canvasService) return;
|
|
6567
|
+
const seq = ++this.renderSeq;
|
|
6568
|
+
const nextUrl = String(this.url || "").trim();
|
|
6569
|
+
if (!nextUrl) {
|
|
6570
|
+
this.renderImageUrl = "";
|
|
6571
|
+
} else if (nextUrl !== this.renderImageUrl) {
|
|
6572
|
+
const loaded = await this.ensureImageSize(nextUrl);
|
|
6573
|
+
if (seq !== this.renderSeq) return;
|
|
6574
|
+
if (loaded) {
|
|
6575
|
+
this.renderImageUrl = nextUrl;
|
|
6576
|
+
}
|
|
5969
6577
|
}
|
|
5970
|
-
|
|
6578
|
+
this.specs = this.buildFilmSpecs(this.renderImageUrl, this.opacity);
|
|
6579
|
+
await this.canvasService.flushRenderFromProducers();
|
|
6580
|
+
if (seq !== this.renderSeq) return;
|
|
6581
|
+
this.canvasService.bringLayerToFront(FILM_LAYER_ID);
|
|
5971
6582
|
this.canvasService.requestRenderAll();
|
|
5972
6583
|
}
|
|
5973
6584
|
};
|
|
@@ -6068,19 +6679,37 @@ var MirrorTool = class {
|
|
|
6068
6679
|
import {
|
|
6069
6680
|
ContributionPointIds as ContributionPointIds8
|
|
6070
6681
|
} from "@pooder/core";
|
|
6071
|
-
|
|
6682
|
+
var RULER_LAYER_ID = "ruler-overlay";
|
|
6683
|
+
var EXTENSION_LINE_LENGTH = 5;
|
|
6684
|
+
var MIN_ARROW_SIZE = 4;
|
|
6685
|
+
var THICKNESS_TO_STROKE_WIDTH_RATIO = 20;
|
|
6686
|
+
var DEFAULT_THICKNESS = 20;
|
|
6687
|
+
var DEFAULT_GAP = 45;
|
|
6688
|
+
var DEFAULT_FONT_SIZE = 10;
|
|
6689
|
+
var DEFAULT_BACKGROUND_COLOR = "#f0f0f0";
|
|
6690
|
+
var DEFAULT_TEXT_COLOR = "#333333";
|
|
6691
|
+
var DEFAULT_LINE_COLOR = "#999999";
|
|
6692
|
+
var RULER_THICKNESS_MIN = 10;
|
|
6693
|
+
var RULER_THICKNESS_MAX = 100;
|
|
6694
|
+
var RULER_GAP_MIN = 0;
|
|
6695
|
+
var RULER_GAP_MAX = 100;
|
|
6696
|
+
var RULER_FONT_SIZE_MIN = 8;
|
|
6697
|
+
var RULER_FONT_SIZE_MAX = 24;
|
|
6072
6698
|
var RulerTool = class {
|
|
6073
6699
|
constructor(options) {
|
|
6074
6700
|
this.id = "pooder.kit.ruler";
|
|
6075
6701
|
this.metadata = {
|
|
6076
6702
|
name: "RulerTool"
|
|
6077
6703
|
};
|
|
6078
|
-
this.thickness =
|
|
6079
|
-
this.gap =
|
|
6080
|
-
this.backgroundColor =
|
|
6081
|
-
this.textColor =
|
|
6082
|
-
this.lineColor =
|
|
6083
|
-
this.fontSize =
|
|
6704
|
+
this.thickness = DEFAULT_THICKNESS;
|
|
6705
|
+
this.gap = DEFAULT_GAP;
|
|
6706
|
+
this.backgroundColor = DEFAULT_BACKGROUND_COLOR;
|
|
6707
|
+
this.textColor = DEFAULT_TEXT_COLOR;
|
|
6708
|
+
this.lineColor = DEFAULT_LINE_COLOR;
|
|
6709
|
+
this.fontSize = DEFAULT_FONT_SIZE;
|
|
6710
|
+
this.renderSeq = 0;
|
|
6711
|
+
this.numericProps = /* @__PURE__ */ new Set(["thickness", "gap", "fontSize"]);
|
|
6712
|
+
this.specs = [];
|
|
6084
6713
|
this.onCanvasResized = () => {
|
|
6085
6714
|
this.updateRuler();
|
|
6086
6715
|
};
|
|
@@ -6089,50 +6718,73 @@ var RulerTool = class {
|
|
|
6089
6718
|
}
|
|
6090
6719
|
}
|
|
6091
6720
|
activate(context) {
|
|
6721
|
+
var _a;
|
|
6092
6722
|
this.context = context;
|
|
6093
6723
|
this.canvasService = context.services.get("CanvasService");
|
|
6094
6724
|
if (!this.canvasService) {
|
|
6095
|
-
console.warn("CanvasService not found
|
|
6725
|
+
console.warn("[RulerTool] CanvasService not found.");
|
|
6096
6726
|
return;
|
|
6097
6727
|
}
|
|
6728
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6729
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
6730
|
+
this.id,
|
|
6731
|
+
() => ({
|
|
6732
|
+
rootLayerSpecs: {
|
|
6733
|
+
[RULER_LAYER_ID]: this.specs
|
|
6734
|
+
},
|
|
6735
|
+
replaceRootLayerIds: [RULER_LAYER_ID]
|
|
6736
|
+
}),
|
|
6737
|
+
{ priority: 400 }
|
|
6738
|
+
);
|
|
6098
6739
|
const configService = context.services.get(
|
|
6099
6740
|
"ConfigurationService"
|
|
6100
6741
|
);
|
|
6101
6742
|
if (configService) {
|
|
6102
|
-
this.
|
|
6103
|
-
this.gap = configService.get("ruler.gap", this.gap);
|
|
6104
|
-
this.backgroundColor = configService.get(
|
|
6105
|
-
"ruler.backgroundColor",
|
|
6106
|
-
this.backgroundColor
|
|
6107
|
-
);
|
|
6108
|
-
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
6109
|
-
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
6110
|
-
this.fontSize = configService.get("ruler.fontSize", this.fontSize);
|
|
6743
|
+
this.syncConfig(configService);
|
|
6111
6744
|
configService.onAnyChange((e) => {
|
|
6112
6745
|
let shouldUpdate = false;
|
|
6113
6746
|
if (e.key.startsWith("ruler.")) {
|
|
6114
6747
|
const prop = e.key.split(".")[1];
|
|
6115
6748
|
if (prop && prop in this) {
|
|
6116
|
-
this
|
|
6749
|
+
if (this.numericProps.has(prop)) {
|
|
6750
|
+
this[prop] = this.toFiniteNumber(
|
|
6751
|
+
e.value,
|
|
6752
|
+
this[prop]
|
|
6753
|
+
);
|
|
6754
|
+
} else {
|
|
6755
|
+
this[prop] = e.value;
|
|
6756
|
+
}
|
|
6117
6757
|
shouldUpdate = true;
|
|
6758
|
+
this.log("config:update", {
|
|
6759
|
+
key: e.key,
|
|
6760
|
+
raw: e.value,
|
|
6761
|
+
normalized: this[prop]
|
|
6762
|
+
});
|
|
6118
6763
|
}
|
|
6119
6764
|
} else if (e.key.startsWith("size.")) {
|
|
6120
6765
|
shouldUpdate = true;
|
|
6766
|
+
this.log("size:update", { key: e.key, value: e.value });
|
|
6121
6767
|
}
|
|
6122
6768
|
if (shouldUpdate) {
|
|
6123
6769
|
this.updateRuler();
|
|
6124
6770
|
}
|
|
6125
6771
|
});
|
|
6126
6772
|
}
|
|
6127
|
-
this.createLayer();
|
|
6128
6773
|
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
6129
6774
|
this.updateRuler();
|
|
6130
6775
|
}
|
|
6131
6776
|
deactivate(context) {
|
|
6777
|
+
var _a;
|
|
6132
6778
|
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
6133
|
-
this.
|
|
6779
|
+
this.specs = [];
|
|
6780
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6781
|
+
this.renderProducerDisposable = void 0;
|
|
6782
|
+
if (this.canvasService) {
|
|
6783
|
+
void this.canvasService.flushRenderFromProducers();
|
|
6784
|
+
}
|
|
6134
6785
|
this.canvasService = void 0;
|
|
6135
6786
|
this.context = void 0;
|
|
6787
|
+
this.renderSeq = 0;
|
|
6136
6788
|
}
|
|
6137
6789
|
contribute() {
|
|
6138
6790
|
return {
|
|
@@ -6141,43 +6793,43 @@ var RulerTool = class {
|
|
|
6141
6793
|
id: "ruler.thickness",
|
|
6142
6794
|
type: "number",
|
|
6143
6795
|
label: "Thickness",
|
|
6144
|
-
min:
|
|
6145
|
-
max:
|
|
6146
|
-
default:
|
|
6796
|
+
min: RULER_THICKNESS_MIN,
|
|
6797
|
+
max: RULER_THICKNESS_MAX,
|
|
6798
|
+
default: DEFAULT_THICKNESS
|
|
6147
6799
|
},
|
|
6148
6800
|
{
|
|
6149
6801
|
id: "ruler.gap",
|
|
6150
6802
|
type: "number",
|
|
6151
6803
|
label: "Gap",
|
|
6152
|
-
min:
|
|
6153
|
-
max:
|
|
6154
|
-
default:
|
|
6804
|
+
min: RULER_GAP_MIN,
|
|
6805
|
+
max: RULER_GAP_MAX,
|
|
6806
|
+
default: DEFAULT_GAP
|
|
6155
6807
|
},
|
|
6156
6808
|
{
|
|
6157
6809
|
id: "ruler.backgroundColor",
|
|
6158
6810
|
type: "color",
|
|
6159
6811
|
label: "Background Color",
|
|
6160
|
-
default:
|
|
6812
|
+
default: DEFAULT_BACKGROUND_COLOR
|
|
6161
6813
|
},
|
|
6162
6814
|
{
|
|
6163
6815
|
id: "ruler.textColor",
|
|
6164
6816
|
type: "color",
|
|
6165
6817
|
label: "Text Color",
|
|
6166
|
-
default:
|
|
6818
|
+
default: DEFAULT_TEXT_COLOR
|
|
6167
6819
|
},
|
|
6168
6820
|
{
|
|
6169
6821
|
id: "ruler.lineColor",
|
|
6170
6822
|
type: "color",
|
|
6171
6823
|
label: "Line Color",
|
|
6172
|
-
default:
|
|
6824
|
+
default: DEFAULT_LINE_COLOR
|
|
6173
6825
|
},
|
|
6174
6826
|
{
|
|
6175
6827
|
id: "ruler.fontSize",
|
|
6176
6828
|
type: "number",
|
|
6177
6829
|
label: "Font Size",
|
|
6178
|
-
min:
|
|
6179
|
-
max:
|
|
6180
|
-
default:
|
|
6830
|
+
min: RULER_FONT_SIZE_MIN,
|
|
6831
|
+
max: RULER_FONT_SIZE_MAX,
|
|
6832
|
+
default: DEFAULT_FONT_SIZE
|
|
6181
6833
|
}
|
|
6182
6834
|
],
|
|
6183
6835
|
[ContributionPointIds8.COMMANDS]: [
|
|
@@ -6190,12 +6842,23 @@ var RulerTool = class {
|
|
|
6190
6842
|
textColor: this.textColor,
|
|
6191
6843
|
lineColor: this.lineColor,
|
|
6192
6844
|
fontSize: this.fontSize,
|
|
6193
|
-
thickness: this.thickness
|
|
6845
|
+
thickness: this.thickness,
|
|
6846
|
+
gap: this.gap
|
|
6194
6847
|
};
|
|
6195
6848
|
const newState = { ...oldState, ...theme };
|
|
6196
|
-
if (JSON.stringify(newState) === JSON.stringify(oldState))
|
|
6849
|
+
if (JSON.stringify(newState) === JSON.stringify(oldState)) {
|
|
6197
6850
|
return true;
|
|
6851
|
+
}
|
|
6198
6852
|
Object.assign(this, newState);
|
|
6853
|
+
this.thickness = this.toFiniteNumber(
|
|
6854
|
+
this.thickness,
|
|
6855
|
+
DEFAULT_THICKNESS
|
|
6856
|
+
);
|
|
6857
|
+
this.gap = this.toFiniteNumber(this.gap, DEFAULT_GAP);
|
|
6858
|
+
this.fontSize = this.toFiniteNumber(
|
|
6859
|
+
this.fontSize,
|
|
6860
|
+
DEFAULT_FONT_SIZE
|
|
6861
|
+
);
|
|
6199
6862
|
this.updateRuler();
|
|
6200
6863
|
return true;
|
|
6201
6864
|
}
|
|
@@ -6203,225 +6866,367 @@ var RulerTool = class {
|
|
|
6203
6866
|
]
|
|
6204
6867
|
};
|
|
6205
6868
|
}
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6869
|
+
log(step, payload) {
|
|
6870
|
+
if (payload) {
|
|
6871
|
+
console.debug(`[RulerTool] ${step}`, payload);
|
|
6872
|
+
return;
|
|
6873
|
+
}
|
|
6874
|
+
console.debug(`[RulerTool] ${step}`);
|
|
6209
6875
|
}
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6876
|
+
syncConfig(configService) {
|
|
6877
|
+
this.thickness = this.toFiniteNumber(
|
|
6878
|
+
configService.get("ruler.thickness", this.thickness),
|
|
6879
|
+
DEFAULT_THICKNESS
|
|
6880
|
+
);
|
|
6881
|
+
this.gap = Math.max(
|
|
6882
|
+
0,
|
|
6883
|
+
this.toFiniteNumber(
|
|
6884
|
+
configService.get("ruler.gap", this.gap),
|
|
6885
|
+
DEFAULT_GAP
|
|
6886
|
+
)
|
|
6887
|
+
);
|
|
6888
|
+
this.backgroundColor = configService.get(
|
|
6889
|
+
"ruler.backgroundColor",
|
|
6890
|
+
this.backgroundColor
|
|
6891
|
+
);
|
|
6892
|
+
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
6893
|
+
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
6894
|
+
this.fontSize = this.toFiniteNumber(
|
|
6895
|
+
configService.get("ruler.fontSize", this.fontSize),
|
|
6896
|
+
DEFAULT_FONT_SIZE
|
|
6897
|
+
);
|
|
6898
|
+
this.log("config:loaded", {
|
|
6899
|
+
thickness: this.thickness,
|
|
6900
|
+
gap: this.gap,
|
|
6901
|
+
fontSize: this.fontSize,
|
|
6902
|
+
backgroundColor: this.backgroundColor,
|
|
6903
|
+
textColor: this.textColor,
|
|
6904
|
+
lineColor: this.lineColor
|
|
6224
6905
|
});
|
|
6225
|
-
canvas.bringObjectToFront(layer);
|
|
6226
6906
|
}
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
if (layer) {
|
|
6231
|
-
this.canvasService.canvas.remove(layer);
|
|
6232
|
-
}
|
|
6907
|
+
toFiniteNumber(value, fallback) {
|
|
6908
|
+
const numeric = Number(value);
|
|
6909
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
6233
6910
|
}
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
const
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6911
|
+
toSceneDisplayLength(value) {
|
|
6912
|
+
if (!this.canvasService) return value;
|
|
6913
|
+
return this.canvasService.toSceneLength(value);
|
|
6914
|
+
}
|
|
6915
|
+
formatLengthMm(valueMm, unit) {
|
|
6916
|
+
const converted = fromMm(valueMm, unit);
|
|
6917
|
+
const fractionDigits = unit === "in" ? 3 : 2;
|
|
6918
|
+
return Number(converted.toFixed(fractionDigits)).toString();
|
|
6919
|
+
}
|
|
6920
|
+
buildLinePath(start, end) {
|
|
6921
|
+
const dx = end.x - start.x;
|
|
6922
|
+
const dy = end.y - start.y;
|
|
6923
|
+
return `M 0 0 L ${dx} ${dy}`;
|
|
6924
|
+
}
|
|
6925
|
+
buildStartArrowPath(size) {
|
|
6926
|
+
return `M 0 0 L ${size} ${-size / 2} L ${size} ${size / 2} Z`;
|
|
6927
|
+
}
|
|
6928
|
+
buildEndArrowPath(size) {
|
|
6929
|
+
return `M 0 0 L ${-size} ${-size / 2} L ${-size} ${size / 2} Z`;
|
|
6930
|
+
}
|
|
6931
|
+
createPathSpec(id, pathData, position, options) {
|
|
6932
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
6933
|
+
return {
|
|
6934
|
+
id,
|
|
6935
|
+
type: "path",
|
|
6936
|
+
data: {
|
|
6937
|
+
id,
|
|
6938
|
+
type: "ruler"
|
|
6939
|
+
},
|
|
6940
|
+
props: {
|
|
6941
|
+
pathData,
|
|
6942
|
+
left: position.x,
|
|
6943
|
+
top: position.y,
|
|
6944
|
+
originX: (_a = options.originX) != null ? _a : "left",
|
|
6945
|
+
originY: (_b = options.originY) != null ? _b : "top",
|
|
6946
|
+
angle: (_c = options.angle) != null ? _c : 0,
|
|
6947
|
+
stroke: (_d = options.stroke) != null ? _d : null,
|
|
6948
|
+
fill: (_e = options.fill) != null ? _e : null,
|
|
6949
|
+
strokeWidth: (_f = options.strokeWidth) != null ? _f : 1,
|
|
6950
|
+
strokeLineCap: (_g = options.strokeLineCap) != null ? _g : "butt",
|
|
6257
6951
|
selectable: false,
|
|
6258
|
-
evented: false
|
|
6952
|
+
evented: false,
|
|
6953
|
+
excludeFromExport: true
|
|
6259
6954
|
}
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6955
|
+
};
|
|
6956
|
+
}
|
|
6957
|
+
createTextSpec(id, text, position, angle = 0) {
|
|
6958
|
+
return {
|
|
6959
|
+
id,
|
|
6960
|
+
type: "text",
|
|
6961
|
+
data: {
|
|
6962
|
+
id,
|
|
6963
|
+
type: "ruler"
|
|
6964
|
+
},
|
|
6965
|
+
props: {
|
|
6966
|
+
text,
|
|
6967
|
+
left: position.x,
|
|
6968
|
+
top: position.y,
|
|
6969
|
+
angle,
|
|
6970
|
+
fontSize: this.toSceneDisplayLength(this.fontSize),
|
|
6971
|
+
fill: this.textColor,
|
|
6972
|
+
fontFamily: "Arial",
|
|
6973
|
+
originX: "center",
|
|
6272
6974
|
originY: "center",
|
|
6273
|
-
|
|
6975
|
+
backgroundColor: this.backgroundColor,
|
|
6274
6976
|
selectable: false,
|
|
6275
|
-
evented: false
|
|
6977
|
+
evented: false,
|
|
6978
|
+
excludeFromExport: true
|
|
6276
6979
|
}
|
|
6277
|
-
|
|
6278
|
-
return new Group2([line, startArrow, endArrow], {
|
|
6279
|
-
selectable: false,
|
|
6280
|
-
evented: false
|
|
6281
|
-
});
|
|
6980
|
+
};
|
|
6282
6981
|
}
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
layer.remove(...layer.getObjects());
|
|
6289
|
-
const { backgroundColor, lineColor, textColor, fontSize } = this;
|
|
6290
|
-
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
6291
|
-
"ConfigurationService"
|
|
6982
|
+
buildRulerSpecs(input) {
|
|
6983
|
+
const { left, top, right, bottom, widthLabel, heightLabel } = input;
|
|
6984
|
+
const gap = Math.max(
|
|
6985
|
+
0,
|
|
6986
|
+
this.toSceneDisplayLength(this.toFiniteNumber(this.gap, DEFAULT_GAP))
|
|
6292
6987
|
);
|
|
6293
|
-
|
|
6294
|
-
const
|
|
6295
|
-
const
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
const cutRect = layout.cutRect;
|
|
6299
|
-
const useCutAsRuler = layout.cutMode === "outset";
|
|
6300
|
-
const rulerRect = useCutAsRuler ? cutRect : trimRect;
|
|
6301
|
-
const gap = this.gap || 15;
|
|
6302
|
-
const rulerLeft = rulerRect.left;
|
|
6303
|
-
const rulerTop = rulerRect.top;
|
|
6304
|
-
const rulerRight = rulerRect.left + rulerRect.width;
|
|
6305
|
-
const rulerBottom = rulerRect.top + rulerRect.height;
|
|
6306
|
-
const displayWidthMm = useCutAsRuler ? layout.cutWidthMm : layout.trimWidthMm;
|
|
6307
|
-
const displayHeightMm = useCutAsRuler ? layout.cutHeightMm : layout.trimHeightMm;
|
|
6308
|
-
const displayUnit = sizeState.unit;
|
|
6309
|
-
const topRulerY = rulerTop - gap;
|
|
6310
|
-
const topRulerXStart = rulerLeft;
|
|
6311
|
-
const topRulerXEnd = rulerRight;
|
|
6312
|
-
const leftRulerX = rulerLeft - gap;
|
|
6313
|
-
const leftRulerYStart = rulerTop;
|
|
6314
|
-
const leftRulerYEnd = rulerBottom;
|
|
6315
|
-
const topDimLine = this.createArrowLine(
|
|
6316
|
-
topRulerXStart,
|
|
6317
|
-
topRulerY,
|
|
6318
|
-
topRulerXEnd,
|
|
6319
|
-
topRulerY,
|
|
6320
|
-
lineColor
|
|
6988
|
+
const topY = top - gap;
|
|
6989
|
+
const leftX = left - gap;
|
|
6990
|
+
const arrowSize = Math.max(
|
|
6991
|
+
this.toSceneDisplayLength(MIN_ARROW_SIZE),
|
|
6992
|
+
this.toSceneDisplayLength(this.thickness * 0.3)
|
|
6321
6993
|
);
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
[
|
|
6327
|
-
topRulerXStart,
|
|
6328
|
-
topRulerY - extLen,
|
|
6329
|
-
topRulerXStart,
|
|
6330
|
-
topRulerY + extLen
|
|
6331
|
-
],
|
|
6332
|
-
{
|
|
6333
|
-
stroke: lineColor,
|
|
6334
|
-
strokeWidth: 1,
|
|
6335
|
-
selectable: false,
|
|
6336
|
-
evented: false
|
|
6337
|
-
}
|
|
6994
|
+
const strokeWidth = Math.max(
|
|
6995
|
+
this.toSceneDisplayLength(1),
|
|
6996
|
+
this.toSceneDisplayLength(
|
|
6997
|
+
this.thickness / THICKNESS_TO_STROKE_WIDTH_RATIO
|
|
6338
6998
|
)
|
|
6339
6999
|
);
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
7000
|
+
const extensionLength = this.toSceneDisplayLength(EXTENSION_LINE_LENGTH);
|
|
7001
|
+
const topLineAngleDeg = 0;
|
|
7002
|
+
const leftLineAngleDeg = 90;
|
|
7003
|
+
const topMidX = left + (right - left) / 2;
|
|
7004
|
+
const leftMidY = top + (bottom - top) / 2;
|
|
7005
|
+
const topLineStartX = Math.min(left + arrowSize, topMidX);
|
|
7006
|
+
const topLineEndX = Math.max(right - arrowSize, topMidX);
|
|
7007
|
+
const leftLineStartY = Math.min(top + arrowSize, leftMidY);
|
|
7008
|
+
const leftLineEndY = Math.max(bottom - arrowSize, leftMidY);
|
|
7009
|
+
const specs = [];
|
|
7010
|
+
specs.push(
|
|
7011
|
+
this.createPathSpec(
|
|
7012
|
+
"ruler.top.line",
|
|
7013
|
+
this.buildLinePath(
|
|
7014
|
+
{ x: topLineStartX, y: topY },
|
|
7015
|
+
{ x: topLineEndX, y: topY }
|
|
7016
|
+
),
|
|
7017
|
+
{ x: topLineStartX, y: topY },
|
|
6343
7018
|
{
|
|
6344
|
-
stroke: lineColor,
|
|
6345
|
-
strokeWidth
|
|
6346
|
-
|
|
6347
|
-
evented: false
|
|
7019
|
+
stroke: this.lineColor,
|
|
7020
|
+
strokeWidth,
|
|
7021
|
+
strokeLineCap: "butt"
|
|
6348
7022
|
}
|
|
6349
|
-
)
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
backgroundColor,
|
|
6362
|
-
// Background mask for readability
|
|
6363
|
-
selectable: false,
|
|
6364
|
-
evented: false
|
|
6365
|
-
});
|
|
6366
|
-
layer.add(topText);
|
|
6367
|
-
const leftDimLine = this.createArrowLine(
|
|
6368
|
-
leftRulerX,
|
|
6369
|
-
leftRulerYStart,
|
|
6370
|
-
leftRulerX,
|
|
6371
|
-
leftRulerYEnd,
|
|
6372
|
-
lineColor
|
|
6373
|
-
);
|
|
6374
|
-
layer.add(leftDimLine);
|
|
6375
|
-
layer.add(
|
|
6376
|
-
new Line(
|
|
6377
|
-
[
|
|
6378
|
-
leftRulerX - extLen,
|
|
6379
|
-
leftRulerYStart,
|
|
6380
|
-
leftRulerX + extLen,
|
|
6381
|
-
leftRulerYStart
|
|
6382
|
-
],
|
|
6383
|
-
{
|
|
6384
|
-
stroke: lineColor,
|
|
6385
|
-
strokeWidth: 1,
|
|
6386
|
-
selectable: false,
|
|
6387
|
-
evented: false
|
|
7023
|
+
),
|
|
7024
|
+
this.createPathSpec(
|
|
7025
|
+
"ruler.top.arrow.start",
|
|
7026
|
+
this.buildStartArrowPath(arrowSize),
|
|
7027
|
+
{ x: left, y: topY },
|
|
7028
|
+
{
|
|
7029
|
+
fill: this.lineColor,
|
|
7030
|
+
stroke: this.lineColor,
|
|
7031
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7032
|
+
originX: "left",
|
|
7033
|
+
originY: "center",
|
|
7034
|
+
angle: topLineAngleDeg
|
|
6388
7035
|
}
|
|
6389
|
-
)
|
|
7036
|
+
),
|
|
7037
|
+
this.createPathSpec(
|
|
7038
|
+
"ruler.top.arrow.end",
|
|
7039
|
+
this.buildEndArrowPath(arrowSize),
|
|
7040
|
+
{ x: right, y: topY },
|
|
7041
|
+
{
|
|
7042
|
+
fill: this.lineColor,
|
|
7043
|
+
stroke: this.lineColor,
|
|
7044
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7045
|
+
originX: "right",
|
|
7046
|
+
originY: "center",
|
|
7047
|
+
angle: topLineAngleDeg
|
|
7048
|
+
}
|
|
7049
|
+
),
|
|
7050
|
+
this.createPathSpec(
|
|
7051
|
+
"ruler.top.ext.start",
|
|
7052
|
+
this.buildLinePath(
|
|
7053
|
+
{ x: left, y: topY - extensionLength },
|
|
7054
|
+
{ x: left, y: topY + extensionLength }
|
|
7055
|
+
),
|
|
7056
|
+
{ x: left, y: topY - extensionLength },
|
|
7057
|
+
{
|
|
7058
|
+
stroke: this.lineColor,
|
|
7059
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7060
|
+
}
|
|
7061
|
+
),
|
|
7062
|
+
this.createPathSpec(
|
|
7063
|
+
"ruler.top.ext.end",
|
|
7064
|
+
this.buildLinePath(
|
|
7065
|
+
{ x: right, y: topY - extensionLength },
|
|
7066
|
+
{ x: right, y: topY + extensionLength }
|
|
7067
|
+
),
|
|
7068
|
+
{ x: right, y: topY - extensionLength },
|
|
7069
|
+
{
|
|
7070
|
+
stroke: this.lineColor,
|
|
7071
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7072
|
+
}
|
|
7073
|
+
),
|
|
7074
|
+
this.createTextSpec("ruler.top.label", widthLabel, {
|
|
7075
|
+
x: left + (right - left) / 2,
|
|
7076
|
+
y: topY
|
|
7077
|
+
})
|
|
6390
7078
|
);
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
{
|
|
6400
|
-
stroke: lineColor,
|
|
6401
|
-
strokeWidth
|
|
6402
|
-
|
|
6403
|
-
evented: false
|
|
7079
|
+
specs.push(
|
|
7080
|
+
this.createPathSpec(
|
|
7081
|
+
"ruler.left.line",
|
|
7082
|
+
this.buildLinePath(
|
|
7083
|
+
{ x: leftX, y: leftLineStartY },
|
|
7084
|
+
{ x: leftX, y: leftLineEndY }
|
|
7085
|
+
),
|
|
7086
|
+
{ x: leftX, y: leftLineStartY },
|
|
7087
|
+
{
|
|
7088
|
+
stroke: this.lineColor,
|
|
7089
|
+
strokeWidth,
|
|
7090
|
+
strokeLineCap: "butt"
|
|
6404
7091
|
}
|
|
7092
|
+
),
|
|
7093
|
+
this.createPathSpec(
|
|
7094
|
+
"ruler.left.arrow.start",
|
|
7095
|
+
this.buildStartArrowPath(arrowSize),
|
|
7096
|
+
{ x: leftX, y: top },
|
|
7097
|
+
{
|
|
7098
|
+
fill: this.lineColor,
|
|
7099
|
+
stroke: this.lineColor,
|
|
7100
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7101
|
+
originX: "left",
|
|
7102
|
+
originY: "center",
|
|
7103
|
+
angle: leftLineAngleDeg
|
|
7104
|
+
}
|
|
7105
|
+
),
|
|
7106
|
+
this.createPathSpec(
|
|
7107
|
+
"ruler.left.arrow.end",
|
|
7108
|
+
this.buildEndArrowPath(arrowSize),
|
|
7109
|
+
{ x: leftX, y: bottom },
|
|
7110
|
+
{
|
|
7111
|
+
fill: this.lineColor,
|
|
7112
|
+
stroke: this.lineColor,
|
|
7113
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7114
|
+
originX: "right",
|
|
7115
|
+
originY: "center",
|
|
7116
|
+
angle: leftLineAngleDeg
|
|
7117
|
+
}
|
|
7118
|
+
),
|
|
7119
|
+
this.createPathSpec(
|
|
7120
|
+
"ruler.left.ext.start",
|
|
7121
|
+
this.buildLinePath(
|
|
7122
|
+
{ x: leftX - extensionLength, y: top },
|
|
7123
|
+
{ x: leftX + extensionLength, y: top }
|
|
7124
|
+
),
|
|
7125
|
+
{ x: leftX - extensionLength, y: top },
|
|
7126
|
+
{
|
|
7127
|
+
stroke: this.lineColor,
|
|
7128
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7129
|
+
}
|
|
7130
|
+
),
|
|
7131
|
+
this.createPathSpec(
|
|
7132
|
+
"ruler.left.ext.end",
|
|
7133
|
+
this.buildLinePath(
|
|
7134
|
+
{ x: leftX - extensionLength, y: bottom },
|
|
7135
|
+
{ x: leftX + extensionLength, y: bottom }
|
|
7136
|
+
),
|
|
7137
|
+
{ x: leftX - extensionLength, y: bottom },
|
|
7138
|
+
{
|
|
7139
|
+
stroke: this.lineColor,
|
|
7140
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7141
|
+
}
|
|
7142
|
+
),
|
|
7143
|
+
this.createTextSpec(
|
|
7144
|
+
"ruler.left.label",
|
|
7145
|
+
heightLabel,
|
|
7146
|
+
{
|
|
7147
|
+
x: leftX,
|
|
7148
|
+
y: top + (bottom - top) / 2
|
|
7149
|
+
},
|
|
7150
|
+
-90
|
|
6405
7151
|
)
|
|
6406
7152
|
);
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
7153
|
+
return specs;
|
|
7154
|
+
}
|
|
7155
|
+
updateRuler() {
|
|
7156
|
+
void this.updateRulerAsync();
|
|
7157
|
+
}
|
|
7158
|
+
async updateRulerAsync() {
|
|
7159
|
+
var _a, _b;
|
|
7160
|
+
if (!this.canvasService) return;
|
|
7161
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
7162
|
+
"ConfigurationService"
|
|
7163
|
+
);
|
|
7164
|
+
if (!configService) return;
|
|
7165
|
+
const seq = ++this.renderSeq;
|
|
7166
|
+
const sizeState = readSizeState(configService);
|
|
7167
|
+
const layout = computeSceneLayout(this.canvasService, sizeState);
|
|
7168
|
+
this.log("render:start", {
|
|
7169
|
+
seq,
|
|
7170
|
+
unit: sizeState.unit,
|
|
7171
|
+
gap: this.gap,
|
|
7172
|
+
thickness: this.thickness,
|
|
7173
|
+
fontSize: this.fontSize,
|
|
7174
|
+
hasLayout: !!layout,
|
|
7175
|
+
scale: (_b = layout == null ? void 0 : layout.scale) != null ? _b : null
|
|
6421
7176
|
});
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
7177
|
+
if (!layout || layout.scale <= 0) {
|
|
7178
|
+
if (seq !== this.renderSeq) return;
|
|
7179
|
+
this.log("render:skip", { seq, reason: "invalid-layout" });
|
|
7180
|
+
this.specs = [];
|
|
7181
|
+
await this.canvasService.flushRenderFromProducers();
|
|
7182
|
+
return;
|
|
7183
|
+
}
|
|
7184
|
+
const geometry = buildSceneGeometry(configService, layout);
|
|
7185
|
+
if (geometry.unit !== "px") {
|
|
7186
|
+
console.warn("[RulerTool] Unexpected geometry unit.", geometry.unit);
|
|
7187
|
+
}
|
|
7188
|
+
const centerScene = this.canvasService.toScenePoint({
|
|
7189
|
+
x: geometry.x,
|
|
7190
|
+
y: geometry.y
|
|
7191
|
+
});
|
|
7192
|
+
const widthScene = this.canvasService.toSceneLength(geometry.width);
|
|
7193
|
+
const heightScene = this.canvasService.toSceneLength(geometry.height);
|
|
7194
|
+
const rulerLeft = centerScene.x - widthScene / 2;
|
|
7195
|
+
const rulerTop = centerScene.y - heightScene / 2;
|
|
7196
|
+
const rulerRight = rulerLeft + widthScene;
|
|
7197
|
+
const rulerBottom = rulerTop + heightScene;
|
|
7198
|
+
const widthMm = widthScene;
|
|
7199
|
+
const heightMm = heightScene;
|
|
7200
|
+
const unit = sizeState.unit;
|
|
7201
|
+
const widthLabel = `${this.formatLengthMm(widthMm, unit)} ${unit}`;
|
|
7202
|
+
const heightLabel = `${this.formatLengthMm(heightMm, unit)} ${unit}`;
|
|
7203
|
+
const specs = this.buildRulerSpecs({
|
|
7204
|
+
left: rulerLeft,
|
|
7205
|
+
top: rulerTop,
|
|
7206
|
+
right: rulerRight,
|
|
7207
|
+
bottom: rulerBottom,
|
|
7208
|
+
widthLabel,
|
|
7209
|
+
heightLabel
|
|
7210
|
+
});
|
|
7211
|
+
this.log("render:geometry", {
|
|
7212
|
+
seq,
|
|
7213
|
+
left: rulerLeft,
|
|
7214
|
+
top: rulerTop,
|
|
7215
|
+
right: rulerRight,
|
|
7216
|
+
bottom: rulerBottom,
|
|
7217
|
+
widthScene,
|
|
7218
|
+
heightScene,
|
|
7219
|
+
widthMm,
|
|
7220
|
+
heightMm,
|
|
7221
|
+
specCount: specs.length
|
|
7222
|
+
});
|
|
7223
|
+
if (seq !== this.renderSeq) return;
|
|
7224
|
+
this.specs = specs;
|
|
7225
|
+
await this.canvasService.flushRenderFromProducers();
|
|
7226
|
+
if (seq !== this.renderSeq) return;
|
|
7227
|
+
this.canvasService.bringLayerToFront(RULER_LAYER_ID);
|
|
7228
|
+
this.canvasService.requestRenderAll();
|
|
7229
|
+
this.log("render:done", { seq });
|
|
6425
7230
|
}
|
|
6426
7231
|
};
|
|
6427
7232
|
|
|
@@ -6460,6 +7265,9 @@ var WhiteInkTool = class {
|
|
|
6460
7265
|
this.printWithWhiteInk = true;
|
|
6461
7266
|
this.previewImageVisible = true;
|
|
6462
7267
|
this.renderSeq = 0;
|
|
7268
|
+
this.whiteSpecs = [];
|
|
7269
|
+
this.coverSpecs = [];
|
|
7270
|
+
this.overlaySpecs = [];
|
|
6463
7271
|
this.onToolActivated = (event) => {
|
|
6464
7272
|
const before = this.isToolActive;
|
|
6465
7273
|
this.syncToolActiveFromWorkbench(event.id);
|
|
@@ -6497,12 +7305,25 @@ var WhiteInkTool = class {
|
|
|
6497
7305
|
};
|
|
6498
7306
|
}
|
|
6499
7307
|
activate(context) {
|
|
7308
|
+
var _a;
|
|
6500
7309
|
this.context = context;
|
|
6501
7310
|
this.canvasService = context.services.get("CanvasService");
|
|
6502
7311
|
if (!this.canvasService) {
|
|
6503
7312
|
console.warn("CanvasService not found for WhiteInkTool");
|
|
6504
7313
|
return;
|
|
6505
7314
|
}
|
|
7315
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
7316
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
7317
|
+
this.id,
|
|
7318
|
+
() => ({
|
|
7319
|
+
rootLayerSpecs: {
|
|
7320
|
+
[WHITE_INK_OBJECT_LAYER_ID]: this.whiteSpecs,
|
|
7321
|
+
[WHITE_INK_COVER_LAYER_ID]: this.coverSpecs,
|
|
7322
|
+
[WHITE_INK_OVERLAY_LAYER_ID]: this.overlaySpecs
|
|
7323
|
+
}
|
|
7324
|
+
}),
|
|
7325
|
+
{ priority: 260 }
|
|
7326
|
+
);
|
|
6506
7327
|
context.eventBus.on("tool:activated", this.onToolActivated);
|
|
6507
7328
|
context.eventBus.on("scene:layout:change", this.onSceneLayoutChanged);
|
|
6508
7329
|
context.eventBus.on("object:added", this.onObjectAdded);
|
|
@@ -6568,7 +7389,7 @@ var WhiteInkTool = class {
|
|
|
6568
7389
|
this.updateWhiteInks();
|
|
6569
7390
|
}
|
|
6570
7391
|
deactivate(context) {
|
|
6571
|
-
var _a;
|
|
7392
|
+
var _a, _b;
|
|
6572
7393
|
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
6573
7394
|
context.eventBus.off("scene:layout:change", this.onSceneLayoutChanged);
|
|
6574
7395
|
context.eventBus.off("object:added", this.onObjectAdded);
|
|
@@ -6579,6 +7400,11 @@ var WhiteInkTool = class {
|
|
|
6579
7400
|
this.dirtyTrackerDisposable = void 0;
|
|
6580
7401
|
this.clearRenderedWhiteInks();
|
|
6581
7402
|
this.applyImageVisibilityForWhiteInk(false);
|
|
7403
|
+
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
7404
|
+
this.renderProducerDisposable = void 0;
|
|
7405
|
+
if (this.canvasService) {
|
|
7406
|
+
void this.canvasService.flushRenderFromProducers();
|
|
7407
|
+
}
|
|
6582
7408
|
this.canvasService = void 0;
|
|
6583
7409
|
this.context = void 0;
|
|
6584
7410
|
}
|
|
@@ -7001,11 +7827,20 @@ var WhiteInkTool = class {
|
|
|
7001
7827
|
if (!layout) {
|
|
7002
7828
|
return { left: 0, top: 0, width: 0, height: 0 };
|
|
7003
7829
|
}
|
|
7004
|
-
return {
|
|
7830
|
+
return this.canvasService.toSceneRect({
|
|
7005
7831
|
left: layout.cutRect.left,
|
|
7006
7832
|
top: layout.cutRect.top,
|
|
7007
7833
|
width: layout.cutRect.width,
|
|
7008
7834
|
height: layout.cutRect.height
|
|
7835
|
+
});
|
|
7836
|
+
}
|
|
7837
|
+
toLayoutSceneRect(rect) {
|
|
7838
|
+
return {
|
|
7839
|
+
left: rect.left,
|
|
7840
|
+
top: rect.top,
|
|
7841
|
+
width: rect.width,
|
|
7842
|
+
height: rect.height,
|
|
7843
|
+
space: "scene"
|
|
7009
7844
|
};
|
|
7010
7845
|
}
|
|
7011
7846
|
getImageObjects() {
|
|
@@ -7028,7 +7863,7 @@ var WhiteInkTool = class {
|
|
|
7028
7863
|
return (_a = obj == null ? void 0 : obj._originalElement) == null ? void 0 : _a.src;
|
|
7029
7864
|
}
|
|
7030
7865
|
getImageSnapshot(obj) {
|
|
7031
|
-
var _a;
|
|
7866
|
+
var _a, _b;
|
|
7032
7867
|
if (!obj) return null;
|
|
7033
7868
|
const src = this.getCurrentSrc(obj);
|
|
7034
7869
|
if (!src) return null;
|
|
@@ -7036,14 +7871,18 @@ var WhiteInkTool = class {
|
|
|
7036
7871
|
const width = Number((obj == null ? void 0 : obj.width) || 0);
|
|
7037
7872
|
const height = Number((obj == null ? void 0 : obj.height) || 0);
|
|
7038
7873
|
this.rememberSourceSize(src, { width, height });
|
|
7874
|
+
const sceneScale = ((_a = this.canvasService) == null ? void 0 : _a.getSceneScale()) || 1;
|
|
7875
|
+
const leftScreen = Number.isFinite(obj == null ? void 0 : obj.left) ? Number(obj.left) : 0;
|
|
7876
|
+
const topScreen = Number.isFinite(obj == null ? void 0 : obj.top) ? Number(obj.top) : 0;
|
|
7877
|
+
const scenePoint = this.canvasService ? this.canvasService.toScenePoint({ x: leftScreen, y: topScreen }) : { x: leftScreen, y: topScreen };
|
|
7039
7878
|
return {
|
|
7040
|
-
id: String(((
|
|
7879
|
+
id: String(((_b = obj == null ? void 0 : obj.data) == null ? void 0 : _b.id) || "image"),
|
|
7041
7880
|
src,
|
|
7042
7881
|
element,
|
|
7043
|
-
left:
|
|
7044
|
-
top:
|
|
7045
|
-
scaleX: Number.isFinite(obj == null ? void 0 : obj.scaleX) ? Number(obj.scaleX) : 1,
|
|
7046
|
-
scaleY: Number.isFinite(obj == null ? void 0 : obj.scaleY) ? Number(obj.scaleY) : 1,
|
|
7882
|
+
left: scenePoint.x,
|
|
7883
|
+
top: scenePoint.y,
|
|
7884
|
+
scaleX: (Number.isFinite(obj == null ? void 0 : obj.scaleX) ? Number(obj.scaleX) : 1) / sceneScale,
|
|
7885
|
+
scaleY: (Number.isFinite(obj == null ? void 0 : obj.scaleY) ? Number(obj.scaleY) : 1) / sceneScale,
|
|
7047
7886
|
angle: Number.isFinite(obj == null ? void 0 : obj.angle) ? Number(obj.angle) : 0,
|
|
7048
7887
|
originX: typeof (obj == null ? void 0 : obj.originX) === "string" ? obj.originX : "center",
|
|
7049
7888
|
originY: typeof (obj == null ? void 0 : obj.originY) === "string" ? obj.originY : "center",
|
|
@@ -7218,8 +8057,11 @@ var WhiteInkTool = class {
|
|
|
7218
8057
|
var _a, _b;
|
|
7219
8058
|
if (!this.isToolActive || !this.canvasService) return [];
|
|
7220
8059
|
if (frame.width <= 0 || frame.height <= 0) return [];
|
|
7221
|
-
const
|
|
7222
|
-
const
|
|
8060
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
8061
|
+
const canvasW = viewport.width || 0;
|
|
8062
|
+
const canvasH = viewport.height || 0;
|
|
8063
|
+
const canvasLeft = viewport.left || 0;
|
|
8064
|
+
const canvasTop = viewport.top || 0;
|
|
7223
8065
|
const strokeColor = this.getConfig("image.frame.strokeColor", "#808080") || "#808080";
|
|
7224
8066
|
const strokeWidthRaw = Number(
|
|
7225
8067
|
(_a = this.getConfig("image.frame.strokeWidth", 2)) != null ? _a : 2
|
|
@@ -7231,21 +8073,42 @@ var WhiteInkTool = class {
|
|
|
7231
8073
|
const innerBackground = this.getConfig("image.frame.innerBackground", "rgba(0,0,0,0)") || "rgba(0,0,0,0)";
|
|
7232
8074
|
const strokeWidth = Number.isFinite(strokeWidthRaw) ? Math.max(0, strokeWidthRaw) : 2;
|
|
7233
8075
|
const dashLength = Number.isFinite(dashLengthRaw) ? Math.max(1, dashLengthRaw) : 8;
|
|
7234
|
-
const
|
|
7235
|
-
const
|
|
8076
|
+
const strokeWidthScene = this.canvasService.toSceneLength(strokeWidth);
|
|
8077
|
+
const dashLengthScene = this.canvasService.toSceneLength(dashLength);
|
|
8078
|
+
const frameLeft = Math.max(
|
|
8079
|
+
canvasLeft,
|
|
8080
|
+
Math.min(canvasLeft + canvasW, frame.left)
|
|
8081
|
+
);
|
|
8082
|
+
const frameTop = Math.max(
|
|
8083
|
+
canvasTop,
|
|
8084
|
+
Math.min(canvasTop + canvasH, frame.top)
|
|
8085
|
+
);
|
|
7236
8086
|
const frameRight = Math.max(
|
|
7237
8087
|
frameLeft,
|
|
7238
|
-
Math.min(canvasW, frame.left + frame.width)
|
|
8088
|
+
Math.min(canvasLeft + canvasW, frame.left + frame.width)
|
|
7239
8089
|
);
|
|
7240
8090
|
const frameBottom = Math.max(
|
|
7241
8091
|
frameTop,
|
|
7242
|
-
Math.min(canvasH, frame.top + frame.height)
|
|
8092
|
+
Math.min(canvasTop + canvasH, frame.top + frame.height)
|
|
7243
8093
|
);
|
|
7244
8094
|
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
7245
|
-
const topH = frameTop;
|
|
7246
|
-
const bottomH = Math.max(0, canvasH - frameBottom);
|
|
7247
|
-
const leftW = frameLeft;
|
|
7248
|
-
const rightW = Math.max(0, canvasW - frameRight);
|
|
8095
|
+
const topH = Math.max(0, frameTop - canvasTop);
|
|
8096
|
+
const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
|
|
8097
|
+
const leftW = Math.max(0, frameLeft - canvasLeft);
|
|
8098
|
+
const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
|
|
8099
|
+
const viewportRect = this.toLayoutSceneRect({
|
|
8100
|
+
left: canvasLeft,
|
|
8101
|
+
top: canvasTop,
|
|
8102
|
+
width: canvasW,
|
|
8103
|
+
height: canvasH
|
|
8104
|
+
});
|
|
8105
|
+
const visibleFrameBandRect = this.toLayoutSceneRect({
|
|
8106
|
+
left: canvasLeft,
|
|
8107
|
+
top: frameTop,
|
|
8108
|
+
width: canvasW,
|
|
8109
|
+
height: visibleFrameH
|
|
8110
|
+
});
|
|
8111
|
+
const frameRect = this.toLayoutSceneRect(frame);
|
|
7249
8112
|
const maskSpecs = [
|
|
7250
8113
|
{
|
|
7251
8114
|
id: "white-ink.cropMask.top",
|
|
@@ -7255,13 +8118,17 @@ var WhiteInkTool = class {
|
|
|
7255
8118
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7256
8119
|
type: "white-ink-mask"
|
|
7257
8120
|
},
|
|
8121
|
+
layout: {
|
|
8122
|
+
reference: "custom",
|
|
8123
|
+
referenceRect: viewportRect,
|
|
8124
|
+
alignX: "start",
|
|
8125
|
+
alignY: "start",
|
|
8126
|
+
width: "100%",
|
|
8127
|
+
height: topH
|
|
8128
|
+
},
|
|
7258
8129
|
props: {
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
width: canvasW,
|
|
7262
|
-
height: topH,
|
|
7263
|
-
originX: "center",
|
|
7264
|
-
originY: "center",
|
|
8130
|
+
originX: "left",
|
|
8131
|
+
originY: "top",
|
|
7265
8132
|
fill: outerBackground,
|
|
7266
8133
|
selectable: false,
|
|
7267
8134
|
evented: false,
|
|
@@ -7276,13 +8143,17 @@ var WhiteInkTool = class {
|
|
|
7276
8143
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7277
8144
|
type: "white-ink-mask"
|
|
7278
8145
|
},
|
|
8146
|
+
layout: {
|
|
8147
|
+
reference: "custom",
|
|
8148
|
+
referenceRect: viewportRect,
|
|
8149
|
+
alignX: "start",
|
|
8150
|
+
alignY: "end",
|
|
8151
|
+
width: "100%",
|
|
8152
|
+
height: bottomH
|
|
8153
|
+
},
|
|
7279
8154
|
props: {
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
width: canvasW,
|
|
7283
|
-
height: bottomH,
|
|
7284
|
-
originX: "center",
|
|
7285
|
-
originY: "center",
|
|
8155
|
+
originX: "left",
|
|
8156
|
+
originY: "top",
|
|
7286
8157
|
fill: outerBackground,
|
|
7287
8158
|
selectable: false,
|
|
7288
8159
|
evented: false,
|
|
@@ -7297,13 +8168,17 @@ var WhiteInkTool = class {
|
|
|
7297
8168
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7298
8169
|
type: "white-ink-mask"
|
|
7299
8170
|
},
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
8171
|
+
layout: {
|
|
8172
|
+
reference: "custom",
|
|
8173
|
+
referenceRect: visibleFrameBandRect,
|
|
8174
|
+
alignX: "start",
|
|
8175
|
+
alignY: "start",
|
|
7303
8176
|
width: leftW,
|
|
7304
|
-
height:
|
|
7305
|
-
|
|
7306
|
-
|
|
8177
|
+
height: "100%"
|
|
8178
|
+
},
|
|
8179
|
+
props: {
|
|
8180
|
+
originX: "left",
|
|
8181
|
+
originY: "top",
|
|
7307
8182
|
fill: outerBackground,
|
|
7308
8183
|
selectable: false,
|
|
7309
8184
|
evented: false,
|
|
@@ -7318,13 +8193,17 @@ var WhiteInkTool = class {
|
|
|
7318
8193
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7319
8194
|
type: "white-ink-mask"
|
|
7320
8195
|
},
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
8196
|
+
layout: {
|
|
8197
|
+
reference: "custom",
|
|
8198
|
+
referenceRect: visibleFrameBandRect,
|
|
8199
|
+
alignX: "end",
|
|
8200
|
+
alignY: "start",
|
|
7324
8201
|
width: rightW,
|
|
7325
|
-
height:
|
|
7326
|
-
|
|
7327
|
-
|
|
8202
|
+
height: "100%"
|
|
8203
|
+
},
|
|
8204
|
+
props: {
|
|
8205
|
+
originX: "left",
|
|
8206
|
+
originY: "top",
|
|
7328
8207
|
fill: outerBackground,
|
|
7329
8208
|
selectable: false,
|
|
7330
8209
|
evented: false,
|
|
@@ -7342,17 +8221,21 @@ var WhiteInkTool = class {
|
|
|
7342
8221
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7343
8222
|
type: "white-ink-frame"
|
|
7344
8223
|
},
|
|
8224
|
+
layout: {
|
|
8225
|
+
reference: "custom",
|
|
8226
|
+
referenceRect: frameRect,
|
|
8227
|
+
alignX: "start",
|
|
8228
|
+
alignY: "start",
|
|
8229
|
+
width: "100%",
|
|
8230
|
+
height: "100%"
|
|
8231
|
+
},
|
|
7345
8232
|
props: {
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
width: frame.width,
|
|
7349
|
-
height: frame.height,
|
|
7350
|
-
originX: "center",
|
|
7351
|
-
originY: "center",
|
|
8233
|
+
originX: "left",
|
|
8234
|
+
originY: "top",
|
|
7352
8235
|
fill: innerBackground,
|
|
7353
8236
|
stroke: strokeColor,
|
|
7354
|
-
strokeWidth,
|
|
7355
|
-
strokeDashArray: [
|
|
8237
|
+
strokeWidth: strokeWidthScene,
|
|
8238
|
+
strokeDashArray: [dashLengthScene, dashLengthScene],
|
|
7356
8239
|
selectable: false,
|
|
7357
8240
|
evented: false,
|
|
7358
8241
|
excludeFromExport: true
|
|
@@ -7428,50 +8311,30 @@ var WhiteInkTool = class {
|
|
|
7428
8311
|
}
|
|
7429
8312
|
).filter((index) => index >= 0);
|
|
7430
8313
|
let whiteInsertIndex = imageIndexes.length ? Math.min(...imageIndexes) : this.resolveDefaultInsertIndex(currentObjects);
|
|
7431
|
-
|
|
7432
|
-
canvas.moveObjectTo(obj, whiteInsertIndex);
|
|
7433
|
-
whiteInsertIndex += 1;
|
|
7434
|
-
});
|
|
7435
|
-
const afterWhiteObjects = canvas.getObjects();
|
|
7436
|
-
const afterImageIndexes = afterWhiteObjects.map(
|
|
7437
|
-
(obj, index) => {
|
|
7438
|
-
var _a;
|
|
7439
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID3 ? index : -1;
|
|
7440
|
-
}
|
|
7441
|
-
).filter((index) => index >= 0);
|
|
7442
|
-
let coverInsertIndex = afterImageIndexes.length ? Math.max(...afterImageIndexes) + 1 : whiteInsertIndex;
|
|
8314
|
+
let coverInsertIndex = whiteInsertIndex;
|
|
7443
8315
|
coverObjects.forEach((obj) => {
|
|
7444
8316
|
canvas.moveObjectTo(obj, coverInsertIndex);
|
|
7445
8317
|
coverInsertIndex += 1;
|
|
7446
8318
|
});
|
|
8319
|
+
whiteInsertIndex = coverInsertIndex;
|
|
8320
|
+
whiteObjects.forEach((obj) => {
|
|
8321
|
+
canvas.moveObjectTo(obj, whiteInsertIndex);
|
|
8322
|
+
whiteInsertIndex += 1;
|
|
8323
|
+
});
|
|
7447
8324
|
frameObjects.forEach((obj) => canvas.bringObjectToFront(obj));
|
|
7448
8325
|
canvas.getObjects().filter((obj) => {
|
|
7449
8326
|
var _a;
|
|
7450
8327
|
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OVERLAY_LAYER_ID2;
|
|
7451
8328
|
}).forEach((obj) => canvas.bringObjectToFront(obj));
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
canvas.bringObjectToFront(dielineOverlay);
|
|
7455
|
-
}
|
|
7456
|
-
const rulerOverlay = this.canvasService.getLayer("ruler-overlay");
|
|
7457
|
-
if (rulerOverlay) {
|
|
7458
|
-
canvas.bringObjectToFront(rulerOverlay);
|
|
7459
|
-
}
|
|
8329
|
+
this.canvasService.bringLayerToFront("dieline-overlay");
|
|
8330
|
+
this.canvasService.bringLayerToFront("ruler-overlay");
|
|
7460
8331
|
}
|
|
7461
8332
|
clearRenderedWhiteInks() {
|
|
7462
8333
|
if (!this.canvasService) return;
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
);
|
|
7467
|
-
void this.canvasService.applyObjectSpecsToRootLayer(
|
|
7468
|
-
WHITE_INK_COVER_LAYER_ID,
|
|
7469
|
-
[]
|
|
7470
|
-
);
|
|
7471
|
-
void this.canvasService.applyObjectSpecsToRootLayer(
|
|
7472
|
-
WHITE_INK_OVERLAY_LAYER_ID,
|
|
7473
|
-
[]
|
|
7474
|
-
);
|
|
8334
|
+
this.whiteSpecs = [];
|
|
8335
|
+
this.coverSpecs = [];
|
|
8336
|
+
this.overlaySpecs = [];
|
|
8337
|
+
this.canvasService.requestRenderFromProducers();
|
|
7475
8338
|
}
|
|
7476
8339
|
purgeSourceCaches(item) {
|
|
7477
8340
|
const sourceUrl = this.resolveSourceUrl(item);
|
|
@@ -7538,20 +8401,12 @@ var WhiteInkTool = class {
|
|
|
7538
8401
|
}
|
|
7539
8402
|
}
|
|
7540
8403
|
}
|
|
7541
|
-
|
|
7542
|
-
WHITE_INK_OBJECT_LAYER_ID,
|
|
7543
|
-
whiteSpecs
|
|
7544
|
-
);
|
|
8404
|
+
this.whiteSpecs = whiteSpecs;
|
|
7545
8405
|
if (seq !== this.renderSeq) return;
|
|
7546
|
-
|
|
7547
|
-
WHITE_INK_COVER_LAYER_ID,
|
|
7548
|
-
coverSpecs
|
|
7549
|
-
);
|
|
8406
|
+
this.coverSpecs = coverSpecs;
|
|
7550
8407
|
if (seq !== this.renderSeq) return;
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
frameSpecs
|
|
7554
|
-
);
|
|
8408
|
+
this.overlaySpecs = frameSpecs;
|
|
8409
|
+
await this.canvasService.flushRenderFromProducers();
|
|
7555
8410
|
if (seq !== this.renderSeq) return;
|
|
7556
8411
|
this.syncZOrder();
|
|
7557
8412
|
this.canvasService.requestRenderAll();
|
|
@@ -7784,23 +8639,16 @@ var SceneVisibilityService = class {
|
|
|
7784
8639
|
const dielineLayer = this.canvasService.getLayer("dieline-overlay");
|
|
7785
8640
|
if (dielineLayer) {
|
|
7786
8641
|
const visible = !HIDDEN_DIELINE_TOOLS.has(this.activeToolId || "");
|
|
7787
|
-
|
|
7788
|
-
dielineLayer.set({ visible });
|
|
7789
|
-
}
|
|
7790
|
-
}
|
|
7791
|
-
const rulerLayer = this.canvasService.getLayer("ruler-overlay");
|
|
7792
|
-
if (rulerLayer) {
|
|
7793
|
-
const visible = !HIDDEN_RULER_TOOLS.has(this.activeToolId || "");
|
|
7794
|
-
if (rulerLayer.visible !== visible) {
|
|
7795
|
-
rulerLayer.set({ visible });
|
|
7796
|
-
}
|
|
8642
|
+
this.canvasService.setLayerVisibility("dieline-overlay", visible);
|
|
7797
8643
|
}
|
|
8644
|
+
const rulerVisible = !HIDDEN_RULER_TOOLS.has(this.activeToolId || "");
|
|
8645
|
+
this.canvasService.setLayerVisibility("ruler-overlay", rulerVisible);
|
|
7798
8646
|
this.canvasService.requestRenderAll();
|
|
7799
8647
|
}
|
|
7800
8648
|
};
|
|
7801
8649
|
|
|
7802
8650
|
// src/services/CanvasService.ts
|
|
7803
|
-
import { Canvas, Group
|
|
8651
|
+
import { Canvas, Group, Rect, Path as Path2, Image as Image2, Text } from "fabric";
|
|
7804
8652
|
|
|
7805
8653
|
// src/services/ViewportSystem.ts
|
|
7806
8654
|
var ViewportSystem = class {
|
|
@@ -7878,6 +8726,13 @@ var ViewportSystem = class {
|
|
|
7878
8726
|
// src/services/CanvasService.ts
|
|
7879
8727
|
var CanvasService = class {
|
|
7880
8728
|
constructor(el, options) {
|
|
8729
|
+
this.renderProducers = /* @__PURE__ */ new Map();
|
|
8730
|
+
this.producerOrder = 0;
|
|
8731
|
+
this.producerFlushRequested = false;
|
|
8732
|
+
this.producerLoopPending = false;
|
|
8733
|
+
this.producerLoopPromise = null;
|
|
8734
|
+
this.managedProducerLayerIds = /* @__PURE__ */ new Set();
|
|
8735
|
+
this.managedProducerRootLayerIds = /* @__PURE__ */ new Set();
|
|
7881
8736
|
if (el instanceof Canvas) {
|
|
7882
8737
|
this.canvas = el;
|
|
7883
8738
|
} else {
|
|
@@ -7910,8 +8765,156 @@ var CanvasService = class {
|
|
|
7910
8765
|
this.canvas.on("object:removed", forward("object:removed"));
|
|
7911
8766
|
}
|
|
7912
8767
|
dispose() {
|
|
8768
|
+
this.renderProducers.clear();
|
|
8769
|
+
this.managedProducerLayerIds.clear();
|
|
8770
|
+
this.managedProducerRootLayerIds.clear();
|
|
8771
|
+
this.producerFlushRequested = false;
|
|
7913
8772
|
this.canvas.dispose();
|
|
7914
8773
|
}
|
|
8774
|
+
registerRenderProducer(toolId, producer, options = {}) {
|
|
8775
|
+
const normalizedToolId = String(toolId || "").trim();
|
|
8776
|
+
if (!normalizedToolId) {
|
|
8777
|
+
throw new Error(
|
|
8778
|
+
"[CanvasService] registerRenderProducer requires a toolId."
|
|
8779
|
+
);
|
|
8780
|
+
}
|
|
8781
|
+
if (typeof producer !== "function") {
|
|
8782
|
+
throw new Error(
|
|
8783
|
+
`[CanvasService] registerRenderProducer("${normalizedToolId}") requires a producer function.`
|
|
8784
|
+
);
|
|
8785
|
+
}
|
|
8786
|
+
const entry = {
|
|
8787
|
+
toolId: normalizedToolId,
|
|
8788
|
+
producer,
|
|
8789
|
+
priority: Number.isFinite(options.priority) ? Number(options.priority) : 0,
|
|
8790
|
+
order: this.producerOrder++
|
|
8791
|
+
};
|
|
8792
|
+
this.renderProducers.set(normalizedToolId, entry);
|
|
8793
|
+
this.requestRenderFromProducers();
|
|
8794
|
+
return {
|
|
8795
|
+
dispose: () => {
|
|
8796
|
+
this.unregisterRenderProducer(normalizedToolId);
|
|
8797
|
+
}
|
|
8798
|
+
};
|
|
8799
|
+
}
|
|
8800
|
+
unregisterRenderProducer(toolId) {
|
|
8801
|
+
const normalizedToolId = String(toolId || "").trim();
|
|
8802
|
+
if (!normalizedToolId) return false;
|
|
8803
|
+
const removed = this.renderProducers.delete(normalizedToolId);
|
|
8804
|
+
if (removed) {
|
|
8805
|
+
this.requestRenderFromProducers();
|
|
8806
|
+
}
|
|
8807
|
+
return removed;
|
|
8808
|
+
}
|
|
8809
|
+
requestRenderFromProducers() {
|
|
8810
|
+
this.producerFlushRequested = true;
|
|
8811
|
+
this.scheduleProducerLoop();
|
|
8812
|
+
}
|
|
8813
|
+
async flushRenderFromProducers() {
|
|
8814
|
+
this.requestRenderFromProducers();
|
|
8815
|
+
if (this.producerLoopPromise) {
|
|
8816
|
+
await this.producerLoopPromise;
|
|
8817
|
+
}
|
|
8818
|
+
}
|
|
8819
|
+
scheduleProducerLoop() {
|
|
8820
|
+
if (this.producerLoopPending) return;
|
|
8821
|
+
this.producerLoopPending = true;
|
|
8822
|
+
this.producerLoopPromise = Promise.resolve().then(() => this.runProducerLoop()).catch((error) => {
|
|
8823
|
+
console.error("[CanvasService] render producer loop failed.", error);
|
|
8824
|
+
}).finally(() => {
|
|
8825
|
+
this.producerLoopPending = false;
|
|
8826
|
+
if (this.producerFlushRequested) {
|
|
8827
|
+
this.scheduleProducerLoop();
|
|
8828
|
+
}
|
|
8829
|
+
});
|
|
8830
|
+
}
|
|
8831
|
+
async runProducerLoop() {
|
|
8832
|
+
while (this.producerFlushRequested) {
|
|
8833
|
+
this.producerFlushRequested = false;
|
|
8834
|
+
await this.collectAndApplyProducerSpecs();
|
|
8835
|
+
}
|
|
8836
|
+
}
|
|
8837
|
+
sortedRenderProducerEntries() {
|
|
8838
|
+
return Array.from(this.renderProducers.values()).sort((a, b) => {
|
|
8839
|
+
if (a.priority !== b.priority) {
|
|
8840
|
+
return a.priority - b.priority;
|
|
8841
|
+
}
|
|
8842
|
+
if (a.order !== b.order) {
|
|
8843
|
+
return a.order - b.order;
|
|
8844
|
+
}
|
|
8845
|
+
return a.toolId.localeCompare(b.toolId);
|
|
8846
|
+
});
|
|
8847
|
+
}
|
|
8848
|
+
appendLayerSpecMap(map, source) {
|
|
8849
|
+
if (!source) return;
|
|
8850
|
+
Object.entries(source).forEach(([layerId, specs]) => {
|
|
8851
|
+
if (!Array.isArray(specs)) return;
|
|
8852
|
+
const list = map.get(layerId) || [];
|
|
8853
|
+
list.push(...specs);
|
|
8854
|
+
map.set(layerId, list);
|
|
8855
|
+
});
|
|
8856
|
+
}
|
|
8857
|
+
async collectAndApplyProducerSpecs() {
|
|
8858
|
+
const groupLayerSpecs = /* @__PURE__ */ new Map();
|
|
8859
|
+
const rootLayerSpecs = /* @__PURE__ */ new Map();
|
|
8860
|
+
const replaceLayerIds = /* @__PURE__ */ new Set();
|
|
8861
|
+
const replaceRootLayerIds = /* @__PURE__ */ new Set();
|
|
8862
|
+
const entries = this.sortedRenderProducerEntries();
|
|
8863
|
+
for (const entry of entries) {
|
|
8864
|
+
try {
|
|
8865
|
+
const result = await entry.producer();
|
|
8866
|
+
if (!result) continue;
|
|
8867
|
+
this.appendLayerSpecMap(groupLayerSpecs, result.layerSpecs);
|
|
8868
|
+
this.appendLayerSpecMap(rootLayerSpecs, result.rootLayerSpecs);
|
|
8869
|
+
if (Array.isArray(result.replaceLayerIds)) {
|
|
8870
|
+
result.replaceLayerIds.forEach((layerId) => {
|
|
8871
|
+
if (layerId) replaceLayerIds.add(layerId);
|
|
8872
|
+
});
|
|
8873
|
+
}
|
|
8874
|
+
if (Array.isArray(result.replaceRootLayerIds)) {
|
|
8875
|
+
result.replaceRootLayerIds.forEach((layerId) => {
|
|
8876
|
+
if (layerId) replaceRootLayerIds.add(layerId);
|
|
8877
|
+
});
|
|
8878
|
+
}
|
|
8879
|
+
} catch (error) {
|
|
8880
|
+
console.error(
|
|
8881
|
+
`[CanvasService] render producer "${entry.toolId}" failed.`,
|
|
8882
|
+
error
|
|
8883
|
+
);
|
|
8884
|
+
}
|
|
8885
|
+
}
|
|
8886
|
+
const nextLayerIds = new Set(groupLayerSpecs.keys());
|
|
8887
|
+
const nextRootLayerIds = new Set(rootLayerSpecs.keys());
|
|
8888
|
+
for (const [layerId, specs] of groupLayerSpecs.entries()) {
|
|
8889
|
+
if (replaceLayerIds.has(layerId)) {
|
|
8890
|
+
const layer = this.getLayer(layerId);
|
|
8891
|
+
if (layer) {
|
|
8892
|
+
layer.getObjects().forEach((obj) => layer.remove(obj));
|
|
8893
|
+
}
|
|
8894
|
+
}
|
|
8895
|
+
await this.applyObjectSpecsToLayer(layerId, specs, { render: false });
|
|
8896
|
+
}
|
|
8897
|
+
for (const layerId of this.managedProducerLayerIds) {
|
|
8898
|
+
if (nextLayerIds.has(layerId)) continue;
|
|
8899
|
+
const layer = this.getLayer(layerId);
|
|
8900
|
+
if (!layer) continue;
|
|
8901
|
+
await this.applyObjectSpecsToContainer(layer, [], { render: false });
|
|
8902
|
+
}
|
|
8903
|
+
for (const [layerId, specs] of rootLayerSpecs.entries()) {
|
|
8904
|
+
if (replaceRootLayerIds.has(layerId)) {
|
|
8905
|
+
const existing = this.getRootLayerObjects(layerId);
|
|
8906
|
+
existing.forEach((obj) => this.canvas.remove(obj));
|
|
8907
|
+
}
|
|
8908
|
+
await this.applyObjectSpecsToRootLayer(layerId, specs, { render: false });
|
|
8909
|
+
}
|
|
8910
|
+
for (const layerId of this.managedProducerRootLayerIds) {
|
|
8911
|
+
if (nextRootLayerIds.has(layerId)) continue;
|
|
8912
|
+
await this.applyObjectSpecsToRootLayer(layerId, [], { render: false });
|
|
8913
|
+
}
|
|
8914
|
+
this.managedProducerLayerIds = nextLayerIds;
|
|
8915
|
+
this.managedProducerRootLayerIds = nextRootLayerIds;
|
|
8916
|
+
this.requestRenderAll();
|
|
8917
|
+
}
|
|
7915
8918
|
/**
|
|
7916
8919
|
* Get a layer (Group) by its ID.
|
|
7917
8920
|
* We assume layers are Groups directly on the canvas with a data.id property.
|
|
@@ -7934,7 +8937,7 @@ var CanvasService = class {
|
|
|
7934
8937
|
...options,
|
|
7935
8938
|
data: { ...options.data, id }
|
|
7936
8939
|
};
|
|
7937
|
-
layer = new
|
|
8940
|
+
layer = new Group([], defaultOptions);
|
|
7938
8941
|
this.canvas.add(layer);
|
|
7939
8942
|
}
|
|
7940
8943
|
return layer;
|
|
@@ -7966,13 +8969,206 @@ var CanvasService = class {
|
|
|
7966
8969
|
(_a = this.eventBus) == null ? void 0 : _a.emit("canvas:resized", { width, height });
|
|
7967
8970
|
this.requestRenderAll();
|
|
7968
8971
|
}
|
|
8972
|
+
getSceneScale() {
|
|
8973
|
+
const scale = Number(this.viewport.scale);
|
|
8974
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
8975
|
+
}
|
|
8976
|
+
getSceneOffset() {
|
|
8977
|
+
const offset = this.viewport.offset;
|
|
8978
|
+
const x = Number(offset.x);
|
|
8979
|
+
const y = Number(offset.y);
|
|
8980
|
+
return {
|
|
8981
|
+
x: Number.isFinite(x) ? x : 0,
|
|
8982
|
+
y: Number.isFinite(y) ? y : 0
|
|
8983
|
+
};
|
|
8984
|
+
}
|
|
8985
|
+
toScreenPoint(point) {
|
|
8986
|
+
const scale = this.getSceneScale();
|
|
8987
|
+
const offset = this.getSceneOffset();
|
|
8988
|
+
return {
|
|
8989
|
+
x: point.x * scale + offset.x,
|
|
8990
|
+
y: point.y * scale + offset.y
|
|
8991
|
+
};
|
|
8992
|
+
}
|
|
8993
|
+
toScenePoint(point) {
|
|
8994
|
+
const scale = this.getSceneScale();
|
|
8995
|
+
const offset = this.getSceneOffset();
|
|
8996
|
+
return {
|
|
8997
|
+
x: (point.x - offset.x) / scale,
|
|
8998
|
+
y: (point.y - offset.y) / scale
|
|
8999
|
+
};
|
|
9000
|
+
}
|
|
9001
|
+
toScreenLength(value) {
|
|
9002
|
+
return value * this.getSceneScale();
|
|
9003
|
+
}
|
|
9004
|
+
toSceneLength(value) {
|
|
9005
|
+
return value / this.getSceneScale();
|
|
9006
|
+
}
|
|
9007
|
+
toScreenRect(rect) {
|
|
9008
|
+
const start = this.toScreenPoint({ x: rect.left, y: rect.top });
|
|
9009
|
+
return {
|
|
9010
|
+
left: start.x,
|
|
9011
|
+
top: start.y,
|
|
9012
|
+
width: this.toScreenLength(rect.width),
|
|
9013
|
+
height: this.toScreenLength(rect.height)
|
|
9014
|
+
};
|
|
9015
|
+
}
|
|
9016
|
+
toSceneRect(rect) {
|
|
9017
|
+
const start = this.toScenePoint({ x: rect.left, y: rect.top });
|
|
9018
|
+
return {
|
|
9019
|
+
left: start.x,
|
|
9020
|
+
top: start.y,
|
|
9021
|
+
width: this.toSceneLength(rect.width),
|
|
9022
|
+
height: this.toSceneLength(rect.height)
|
|
9023
|
+
};
|
|
9024
|
+
}
|
|
9025
|
+
getSceneViewportRect() {
|
|
9026
|
+
const width = Number(this.canvas.width || 0);
|
|
9027
|
+
const height = Number(this.canvas.height || 0);
|
|
9028
|
+
return this.toSceneRect({ left: 0, top: 0, width, height });
|
|
9029
|
+
}
|
|
9030
|
+
getScreenViewportRect() {
|
|
9031
|
+
return {
|
|
9032
|
+
left: 0,
|
|
9033
|
+
top: 0,
|
|
9034
|
+
width: Number(this.canvas.width || 0),
|
|
9035
|
+
height: Number(this.canvas.height || 0)
|
|
9036
|
+
};
|
|
9037
|
+
}
|
|
9038
|
+
toSpaceRect(rect, from, to) {
|
|
9039
|
+
if (from === to) return { ...rect };
|
|
9040
|
+
if (from === "scene") {
|
|
9041
|
+
return this.toScreenRect(rect);
|
|
9042
|
+
}
|
|
9043
|
+
return this.toSceneRect(rect);
|
|
9044
|
+
}
|
|
9045
|
+
resolveLayoutLength(value, base) {
|
|
9046
|
+
if (typeof value === "number") {
|
|
9047
|
+
return Number.isFinite(value) ? value : void 0;
|
|
9048
|
+
}
|
|
9049
|
+
if (typeof value !== "string") {
|
|
9050
|
+
return void 0;
|
|
9051
|
+
}
|
|
9052
|
+
const raw = value.trim();
|
|
9053
|
+
if (!raw) return void 0;
|
|
9054
|
+
if (raw.endsWith("%")) {
|
|
9055
|
+
const percent = parseFloat(raw.slice(0, -1));
|
|
9056
|
+
if (!Number.isFinite(percent)) return void 0;
|
|
9057
|
+
return base * percent / 100;
|
|
9058
|
+
}
|
|
9059
|
+
const parsed = parseFloat(raw);
|
|
9060
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
9061
|
+
}
|
|
9062
|
+
resolveLayoutInsets(inset, reference) {
|
|
9063
|
+
var _a, _b, _c, _d, _e;
|
|
9064
|
+
if (typeof inset === "number" || typeof inset === "string") {
|
|
9065
|
+
const all = (_a = this.resolveLayoutLength(
|
|
9066
|
+
inset,
|
|
9067
|
+
Math.min(reference.width, reference.height)
|
|
9068
|
+
)) != null ? _a : 0;
|
|
9069
|
+
return { top: all, right: all, bottom: all, left: all };
|
|
9070
|
+
}
|
|
9071
|
+
const source = inset || {};
|
|
9072
|
+
const top = (_b = this.resolveLayoutLength(source.top, reference.height)) != null ? _b : 0;
|
|
9073
|
+
const right = (_c = this.resolveLayoutLength(source.right, reference.width)) != null ? _c : 0;
|
|
9074
|
+
const bottom = (_d = this.resolveLayoutLength(source.bottom, reference.height)) != null ? _d : 0;
|
|
9075
|
+
const left = (_e = this.resolveLayoutLength(source.left, reference.width)) != null ? _e : 0;
|
|
9076
|
+
return { top, right, bottom, left };
|
|
9077
|
+
}
|
|
9078
|
+
resolveLayoutReferenceRect(layout, space) {
|
|
9079
|
+
if (layout.referenceRect) {
|
|
9080
|
+
const sourceSpace = layout.referenceRect.space || space;
|
|
9081
|
+
return this.toSpaceRect(layout.referenceRect, sourceSpace, space);
|
|
9082
|
+
}
|
|
9083
|
+
const reference = layout.reference || "sceneViewport";
|
|
9084
|
+
if (reference === "screenViewport") {
|
|
9085
|
+
const screenRect = this.getScreenViewportRect();
|
|
9086
|
+
return space === "screen" ? screenRect : this.toSceneRect(screenRect);
|
|
9087
|
+
}
|
|
9088
|
+
const sceneRect = this.getSceneViewportRect();
|
|
9089
|
+
return space === "scene" ? sceneRect : this.toScreenRect(sceneRect);
|
|
9090
|
+
}
|
|
9091
|
+
alignFactor(value) {
|
|
9092
|
+
if (value === "end") return 1;
|
|
9093
|
+
if (value === "center") return 0.5;
|
|
9094
|
+
return 0;
|
|
9095
|
+
}
|
|
9096
|
+
normalizeOriginX(value) {
|
|
9097
|
+
if (value === "center") return "center";
|
|
9098
|
+
if (value === "right") return "right";
|
|
9099
|
+
return "left";
|
|
9100
|
+
}
|
|
9101
|
+
normalizeOriginY(value) {
|
|
9102
|
+
if (value === "center") return "center";
|
|
9103
|
+
if (value === "bottom") return "bottom";
|
|
9104
|
+
return "top";
|
|
9105
|
+
}
|
|
9106
|
+
originFactor(value) {
|
|
9107
|
+
if (value === "center") return 0.5;
|
|
9108
|
+
if (value === "right" || value === "bottom") return 1;
|
|
9109
|
+
return 0;
|
|
9110
|
+
}
|
|
9111
|
+
resolveLayoutProps(spec, props) {
|
|
9112
|
+
var _a, _b, _c, _d;
|
|
9113
|
+
const layout = spec.layout;
|
|
9114
|
+
if (!layout) {
|
|
9115
|
+
return { ...props };
|
|
9116
|
+
}
|
|
9117
|
+
const space = spec.space || "scene";
|
|
9118
|
+
const reference = this.resolveLayoutReferenceRect(layout, space);
|
|
9119
|
+
const inset = this.resolveLayoutInsets(layout.inset, reference);
|
|
9120
|
+
const area = {
|
|
9121
|
+
left: reference.left + inset.left,
|
|
9122
|
+
top: reference.top + inset.top,
|
|
9123
|
+
width: Math.max(0, reference.width - inset.left - inset.right),
|
|
9124
|
+
height: Math.max(0, reference.height - inset.top - inset.bottom)
|
|
9125
|
+
};
|
|
9126
|
+
const next = { ...props };
|
|
9127
|
+
const width = (_a = this.resolveLayoutLength(layout.width, area.width)) != null ? _a : Number.isFinite(next.width) ? Number(next.width) : void 0;
|
|
9128
|
+
const height = (_b = this.resolveLayoutLength(layout.height, area.height)) != null ? _b : Number.isFinite(next.height) ? Number(next.height) : void 0;
|
|
9129
|
+
if (width !== void 0) next.width = width;
|
|
9130
|
+
if (height !== void 0) next.height = height;
|
|
9131
|
+
const alignX = this.alignFactor(layout.alignX);
|
|
9132
|
+
const alignY = this.alignFactor(layout.alignY);
|
|
9133
|
+
const offsetX = (_c = this.resolveLayoutLength(layout.offsetX, area.width)) != null ? _c : 0;
|
|
9134
|
+
const offsetY = (_d = this.resolveLayoutLength(layout.offsetY, area.height)) != null ? _d : 0;
|
|
9135
|
+
const objectWidth = Number.isFinite(next.width) ? Number(next.width) : 0;
|
|
9136
|
+
const objectHeight = Number.isFinite(next.height) ? Number(next.height) : 0;
|
|
9137
|
+
const objectLeft = area.left + (area.width - objectWidth) * alignX + offsetX;
|
|
9138
|
+
const objectTop = area.top + (area.height - objectHeight) * alignY + offsetY;
|
|
9139
|
+
const originX = this.normalizeOriginX(next.originX);
|
|
9140
|
+
const originY = this.normalizeOriginY(next.originY);
|
|
9141
|
+
next.left = objectLeft + objectWidth * this.originFactor(originX);
|
|
9142
|
+
next.top = objectTop + objectHeight * this.originFactor(originY);
|
|
9143
|
+
return next;
|
|
9144
|
+
}
|
|
9145
|
+
setLayerVisibility(layerId, visible) {
|
|
9146
|
+
const layer = this.getLayer(layerId);
|
|
9147
|
+
if (layer) {
|
|
9148
|
+
layer.set({ visible });
|
|
9149
|
+
}
|
|
9150
|
+
const objects = this.getRootLayerObjects(layerId);
|
|
9151
|
+
objects.forEach((obj) => {
|
|
9152
|
+
var _a, _b;
|
|
9153
|
+
(_a = obj.set) == null ? void 0 : _a.call(obj, { visible });
|
|
9154
|
+
(_b = obj.setCoords) == null ? void 0 : _b.call(obj);
|
|
9155
|
+
});
|
|
9156
|
+
}
|
|
9157
|
+
bringLayerToFront(layerId) {
|
|
9158
|
+
const layer = this.getLayer(layerId);
|
|
9159
|
+
if (layer) {
|
|
9160
|
+
this.canvas.bringObjectToFront(layer);
|
|
9161
|
+
}
|
|
9162
|
+
const objects = this.getRootLayerObjects(layerId);
|
|
9163
|
+
objects.forEach((obj) => this.canvas.bringObjectToFront(obj));
|
|
9164
|
+
}
|
|
7969
9165
|
async applyLayerSpec(spec) {
|
|
7970
9166
|
const layer = this.createLayer(spec.id, spec.props || {});
|
|
7971
9167
|
await this.applyObjectSpecsToContainer(layer, spec.objects);
|
|
7972
9168
|
}
|
|
7973
|
-
async applyObjectSpecsToLayer(layerId, objects) {
|
|
9169
|
+
async applyObjectSpecsToLayer(layerId, objects, options = {}) {
|
|
7974
9170
|
const layer = this.createLayer(layerId, {});
|
|
7975
|
-
await this.applyObjectSpecsToContainer(layer, objects);
|
|
9171
|
+
await this.applyObjectSpecsToContainer(layer, objects, options);
|
|
7976
9172
|
}
|
|
7977
9173
|
getRootLayerObjects(layerId) {
|
|
7978
9174
|
return this.canvas.getObjects().filter((obj) => {
|
|
@@ -7980,7 +9176,7 @@ var CanvasService = class {
|
|
|
7980
9176
|
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === layerId;
|
|
7981
9177
|
});
|
|
7982
9178
|
}
|
|
7983
|
-
async applyObjectSpecsToRootLayer(layerId, specs) {
|
|
9179
|
+
async applyObjectSpecsToRootLayer(layerId, specs, options = {}) {
|
|
7984
9180
|
const desiredIds = new Set(specs.map((s) => s.id));
|
|
7985
9181
|
const existing = this.getRootLayerObjects(layerId);
|
|
7986
9182
|
existing.forEach((obj) => {
|
|
@@ -8014,9 +9210,11 @@ var CanvasService = class {
|
|
|
8014
9210
|
}
|
|
8015
9211
|
this.patchFabricObject(current, spec, { layerId });
|
|
8016
9212
|
}
|
|
8017
|
-
|
|
9213
|
+
if (options.render !== false) {
|
|
9214
|
+
this.requestRenderAll();
|
|
9215
|
+
}
|
|
8018
9216
|
}
|
|
8019
|
-
async applyObjectSpecsToContainer(container, specs) {
|
|
9217
|
+
async applyObjectSpecsToContainer(container, specs, options = {}) {
|
|
8020
9218
|
const desiredIds = new Set(specs.map((s) => s.id));
|
|
8021
9219
|
const existing = container.getObjects();
|
|
8022
9220
|
existing.forEach((obj) => {
|
|
@@ -8052,7 +9250,9 @@ var CanvasService = class {
|
|
|
8052
9250
|
this.moveObjectInContainer(container, current, index);
|
|
8053
9251
|
}
|
|
8054
9252
|
container.dirty = true;
|
|
8055
|
-
|
|
9253
|
+
if (options.render !== false) {
|
|
9254
|
+
this.requestRenderAll();
|
|
9255
|
+
}
|
|
8056
9256
|
}
|
|
8057
9257
|
patchFabricObject(obj, spec, extraData) {
|
|
8058
9258
|
const nextData = {
|
|
@@ -8061,9 +9261,33 @@ var CanvasService = class {
|
|
|
8061
9261
|
...extraData || {},
|
|
8062
9262
|
id: spec.id
|
|
8063
9263
|
};
|
|
8064
|
-
|
|
9264
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9265
|
+
obj.set({ ...props, data: nextData });
|
|
8065
9266
|
obj.setCoords();
|
|
8066
9267
|
}
|
|
9268
|
+
resolveFabricProps(spec, props) {
|
|
9269
|
+
const space = spec.space || "scene";
|
|
9270
|
+
const next = this.resolveLayoutProps(spec, props);
|
|
9271
|
+
if (space === "screen") {
|
|
9272
|
+
return next;
|
|
9273
|
+
}
|
|
9274
|
+
const hasLeft = Number.isFinite(next.left);
|
|
9275
|
+
const hasTop = Number.isFinite(next.top);
|
|
9276
|
+
if (hasLeft || hasTop) {
|
|
9277
|
+
const mapped = this.toScreenPoint({
|
|
9278
|
+
x: hasLeft ? Number(next.left) : 0,
|
|
9279
|
+
y: hasTop ? Number(next.top) : 0
|
|
9280
|
+
});
|
|
9281
|
+
if (hasLeft) next.left = mapped.x;
|
|
9282
|
+
if (hasTop) next.top = mapped.y;
|
|
9283
|
+
}
|
|
9284
|
+
const rawScaleX = Number.isFinite(next.scaleX) ? Number(next.scaleX) : 1;
|
|
9285
|
+
const rawScaleY = Number.isFinite(next.scaleY) ? Number(next.scaleY) : 1;
|
|
9286
|
+
const sceneScale = this.getSceneScale();
|
|
9287
|
+
next.scaleX = rawScaleX * sceneScale;
|
|
9288
|
+
next.scaleY = rawScaleY * sceneScale;
|
|
9289
|
+
return next;
|
|
9290
|
+
}
|
|
8067
9291
|
moveObjectInContainer(container, obj, index) {
|
|
8068
9292
|
if (!obj) return;
|
|
8069
9293
|
const moveObjectTo = container.moveObjectTo;
|
|
@@ -8083,10 +9307,11 @@ var CanvasService = class {
|
|
|
8083
9307
|
}
|
|
8084
9308
|
}
|
|
8085
9309
|
async createFabricObject(spec) {
|
|
8086
|
-
var _a, _b;
|
|
9310
|
+
var _a, _b, _c, _d;
|
|
8087
9311
|
if (spec.type === "rect") {
|
|
8088
|
-
const
|
|
8089
|
-
|
|
9312
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9313
|
+
const rect = new Rect({
|
|
9314
|
+
...props,
|
|
8090
9315
|
data: { ...spec.data || {}, id: spec.id }
|
|
8091
9316
|
});
|
|
8092
9317
|
rect.setCoords();
|
|
@@ -8095,8 +9320,9 @@ var CanvasService = class {
|
|
|
8095
9320
|
if (spec.type === "path") {
|
|
8096
9321
|
const pathData = ((_a = spec.props) == null ? void 0 : _a.path) || ((_b = spec.props) == null ? void 0 : _b.pathData);
|
|
8097
9322
|
if (!pathData) return void 0;
|
|
9323
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
8098
9324
|
const path = new Path2(pathData, {
|
|
8099
|
-
...
|
|
9325
|
+
...props,
|
|
8100
9326
|
data: { ...spec.data || {}, id: spec.id }
|
|
8101
9327
|
});
|
|
8102
9328
|
path.setCoords();
|
|
@@ -8104,14 +9330,25 @@ var CanvasService = class {
|
|
|
8104
9330
|
}
|
|
8105
9331
|
if (spec.type === "image") {
|
|
8106
9332
|
if (!spec.src) return void 0;
|
|
8107
|
-
const image = await
|
|
9333
|
+
const image = await Image2.fromURL(spec.src, { crossOrigin: "anonymous" });
|
|
9334
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
8108
9335
|
image.set({
|
|
8109
|
-
...
|
|
9336
|
+
...props,
|
|
8110
9337
|
data: { ...spec.data || {}, id: spec.id }
|
|
8111
9338
|
});
|
|
8112
9339
|
image.setCoords();
|
|
8113
9340
|
return image;
|
|
8114
9341
|
}
|
|
9342
|
+
if (spec.type === "text") {
|
|
9343
|
+
const content = String((_d = (_c = spec.props) == null ? void 0 : _c.text) != null ? _d : "");
|
|
9344
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9345
|
+
const text = new Text(content, {
|
|
9346
|
+
...props,
|
|
9347
|
+
data: { ...spec.data || {}, id: spec.id }
|
|
9348
|
+
});
|
|
9349
|
+
text.setCoords();
|
|
9350
|
+
return text;
|
|
9351
|
+
}
|
|
8115
9352
|
return void 0;
|
|
8116
9353
|
}
|
|
8117
9354
|
};
|