@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.js
CHANGED
|
@@ -49,6 +49,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
49
49
|
// src/extensions/background.ts
|
|
50
50
|
var import_core = require("@pooder/core");
|
|
51
51
|
var import_fabric = require("fabric");
|
|
52
|
+
var BACKGROUND_LAYER_ID = "background";
|
|
53
|
+
var BACKGROUND_RECT_ID = "background-color-rect";
|
|
54
|
+
var BACKGROUND_IMAGE_ID = "background-image";
|
|
55
|
+
var DEFAULT_WIDTH = 800;
|
|
56
|
+
var DEFAULT_HEIGHT = 600;
|
|
52
57
|
var BackgroundTool = class {
|
|
53
58
|
constructor(options) {
|
|
54
59
|
this.id = "pooder.kit.background";
|
|
@@ -57,17 +62,38 @@ var BackgroundTool = class {
|
|
|
57
62
|
};
|
|
58
63
|
this.color = "";
|
|
59
64
|
this.url = "";
|
|
65
|
+
this.specs = [];
|
|
66
|
+
this.renderSeq = 0;
|
|
67
|
+
this.renderImageUrl = "";
|
|
68
|
+
this.sourceSizeBySrc = /* @__PURE__ */ new Map();
|
|
69
|
+
this.pendingSizeBySrc = /* @__PURE__ */ new Map();
|
|
70
|
+
this.onCanvasResized = () => {
|
|
71
|
+
this.updateBackground();
|
|
72
|
+
};
|
|
60
73
|
if (options) {
|
|
61
74
|
Object.assign(this, options);
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
activate(context) {
|
|
78
|
+
var _a;
|
|
65
79
|
this.canvasService = context.services.get("CanvasService");
|
|
66
80
|
if (!this.canvasService) {
|
|
67
81
|
console.warn("CanvasService not found for BackgroundTool");
|
|
68
82
|
return;
|
|
69
83
|
}
|
|
70
|
-
|
|
84
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
85
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
86
|
+
this.id,
|
|
87
|
+
() => ({
|
|
88
|
+
layerSpecs: {
|
|
89
|
+
[BACKGROUND_LAYER_ID]: this.specs
|
|
90
|
+
}
|
|
91
|
+
}),
|
|
92
|
+
{ priority: 0 }
|
|
93
|
+
);
|
|
94
|
+
const configService = context.services.get(
|
|
95
|
+
"ConfigurationService"
|
|
96
|
+
);
|
|
71
97
|
if (configService) {
|
|
72
98
|
this.color = configService.get("background.color", this.color);
|
|
73
99
|
this.url = configService.get("background.url", this.url);
|
|
@@ -91,17 +117,25 @@ var BackgroundTool = class {
|
|
|
91
117
|
}
|
|
92
118
|
});
|
|
93
119
|
}
|
|
94
|
-
this.
|
|
120
|
+
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
95
121
|
this.updateBackground();
|
|
96
122
|
}
|
|
97
123
|
deactivate(context) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
var _a;
|
|
125
|
+
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
126
|
+
this.renderSeq += 1;
|
|
127
|
+
this.specs = [];
|
|
128
|
+
this.renderImageUrl = "";
|
|
129
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
130
|
+
this.renderProducerDisposable = void 0;
|
|
131
|
+
if (!this.canvasService) return;
|
|
132
|
+
const layer = this.canvasService.getLayer(BACKGROUND_LAYER_ID);
|
|
133
|
+
if (layer) {
|
|
134
|
+
this.canvasService.canvas.remove(layer);
|
|
104
135
|
}
|
|
136
|
+
void this.canvasService.flushRenderFromProducers();
|
|
137
|
+
this.canvasService.requestRenderAll();
|
|
138
|
+
this.canvasService = void 0;
|
|
105
139
|
}
|
|
106
140
|
contribute() {
|
|
107
141
|
return {
|
|
@@ -161,88 +195,131 @@ var BackgroundTool = class {
|
|
|
161
195
|
]
|
|
162
196
|
};
|
|
163
197
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
evented: false
|
|
173
|
-
});
|
|
174
|
-
this.canvasService.canvas.sendObjectToBack(backgroundLayer);
|
|
175
|
-
}
|
|
198
|
+
getViewportSize() {
|
|
199
|
+
var _a, _b;
|
|
200
|
+
const width = Number(((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 0);
|
|
201
|
+
const height = Number(((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 0);
|
|
202
|
+
return {
|
|
203
|
+
width: width > 0 ? width : DEFAULT_WIDTH,
|
|
204
|
+
height: height > 0 ? height : DEFAULT_HEIGHT
|
|
205
|
+
};
|
|
176
206
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
207
|
+
buildBackgroundSpecs(color, imageUrl) {
|
|
208
|
+
const { width, height } = this.getViewportSize();
|
|
209
|
+
const specs = [
|
|
210
|
+
{
|
|
211
|
+
id: BACKGROUND_RECT_ID,
|
|
212
|
+
type: "rect",
|
|
213
|
+
space: "screen",
|
|
214
|
+
data: {
|
|
215
|
+
id: BACKGROUND_RECT_ID,
|
|
216
|
+
layerId: BACKGROUND_LAYER_ID,
|
|
217
|
+
type: "background-color"
|
|
218
|
+
},
|
|
219
|
+
props: {
|
|
220
|
+
left: 0,
|
|
221
|
+
top: 0,
|
|
222
|
+
width,
|
|
223
|
+
height,
|
|
224
|
+
originX: "left",
|
|
225
|
+
originY: "top",
|
|
226
|
+
fill: color,
|
|
227
|
+
selectable: false,
|
|
228
|
+
evented: false,
|
|
229
|
+
excludeFromExport: true
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
];
|
|
233
|
+
if (!imageUrl) {
|
|
234
|
+
return specs;
|
|
183
235
|
}
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
236
|
+
const sourceSize = this.sourceSizeBySrc.get(imageUrl);
|
|
237
|
+
const sourceWidth = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.width) || width));
|
|
238
|
+
const sourceHeight = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.height) || height));
|
|
239
|
+
const coverScale = Math.max(width / sourceWidth, height / sourceHeight);
|
|
240
|
+
specs.push({
|
|
241
|
+
id: BACKGROUND_IMAGE_ID,
|
|
242
|
+
type: "image",
|
|
243
|
+
src: imageUrl,
|
|
244
|
+
space: "screen",
|
|
245
|
+
data: {
|
|
246
|
+
id: BACKGROUND_IMAGE_ID,
|
|
247
|
+
layerId: BACKGROUND_LAYER_ID,
|
|
248
|
+
type: "background-image"
|
|
249
|
+
},
|
|
250
|
+
props: {
|
|
251
|
+
left: 0,
|
|
252
|
+
top: 0,
|
|
253
|
+
originX: "left",
|
|
254
|
+
originY: "top",
|
|
255
|
+
scaleX: coverScale,
|
|
256
|
+
scaleY: coverScale,
|
|
200
257
|
selectable: false,
|
|
201
258
|
evented: false,
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
259
|
+
excludeFromExport: true
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
return specs;
|
|
263
|
+
}
|
|
264
|
+
async ensureImageSize(src) {
|
|
265
|
+
if (!src) return null;
|
|
266
|
+
const cached = this.sourceSizeBySrc.get(src);
|
|
267
|
+
if (cached) return cached;
|
|
268
|
+
const pending = this.pendingSizeBySrc.get(src);
|
|
269
|
+
if (pending) {
|
|
270
|
+
return pending;
|
|
208
271
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
"background"
|
|
212
|
-
);
|
|
272
|
+
const task = this.loadImageSize(src);
|
|
273
|
+
this.pendingSizeBySrc.set(src, task);
|
|
213
274
|
try {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
} else {
|
|
219
|
-
layer.remove(img);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
} else {
|
|
223
|
-
if (url) {
|
|
224
|
-
img = await import_fabric.FabricImage.fromURL(url, { crossOrigin: "anonymous" });
|
|
225
|
-
img.set({
|
|
226
|
-
originX: "left",
|
|
227
|
-
originY: "top",
|
|
228
|
-
left: 0,
|
|
229
|
-
top: 0,
|
|
230
|
-
selectable: false,
|
|
231
|
-
evented: false,
|
|
232
|
-
data: {
|
|
233
|
-
id: "background-image"
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
img.scaleToWidth(width);
|
|
237
|
-
if (img.getScaledHeight() < height) img.scaleToHeight(height);
|
|
238
|
-
layer.add(img);
|
|
239
|
-
}
|
|
275
|
+
return await task;
|
|
276
|
+
} finally {
|
|
277
|
+
if (this.pendingSizeBySrc.get(src) === task) {
|
|
278
|
+
this.pendingSizeBySrc.delete(src);
|
|
240
279
|
}
|
|
241
|
-
this.canvasService.requestRenderAll();
|
|
242
|
-
} catch (e) {
|
|
243
|
-
console.error("[BackgroundTool] Failed to load image", e);
|
|
244
280
|
}
|
|
245
|
-
|
|
281
|
+
}
|
|
282
|
+
async loadImageSize(src) {
|
|
283
|
+
try {
|
|
284
|
+
const image = await import_fabric.FabricImage.fromURL(src, {
|
|
285
|
+
crossOrigin: "anonymous"
|
|
286
|
+
});
|
|
287
|
+
const width = Number((image == null ? void 0 : image.width) || 0);
|
|
288
|
+
const height = Number((image == null ? void 0 : image.height) || 0);
|
|
289
|
+
if (width > 0 && height > 0) {
|
|
290
|
+
const size = { width, height };
|
|
291
|
+
this.sourceSizeBySrc.set(src, size);
|
|
292
|
+
return size;
|
|
293
|
+
}
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.error("[BackgroundTool] Failed to load image", src, error);
|
|
296
|
+
}
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
updateBackground() {
|
|
300
|
+
void this.updateBackgroundAsync();
|
|
301
|
+
}
|
|
302
|
+
async updateBackgroundAsync() {
|
|
303
|
+
if (!this.canvasService) return;
|
|
304
|
+
const seq = ++this.renderSeq;
|
|
305
|
+
const color = this.color;
|
|
306
|
+
const nextUrl = String(this.url || "").trim();
|
|
307
|
+
if (!nextUrl) {
|
|
308
|
+
this.renderImageUrl = "";
|
|
309
|
+
} else if (nextUrl !== this.renderImageUrl) {
|
|
310
|
+
const loaded = await this.ensureImageSize(nextUrl);
|
|
311
|
+
if (seq !== this.renderSeq) return;
|
|
312
|
+
if (loaded) {
|
|
313
|
+
this.renderImageUrl = nextUrl;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
this.specs = this.buildBackgroundSpecs(color, this.renderImageUrl);
|
|
317
|
+
await this.canvasService.flushRenderFromProducers();
|
|
318
|
+
if (seq !== this.renderSeq) return;
|
|
319
|
+
const layer = this.canvasService.getLayer(BACKGROUND_LAYER_ID);
|
|
320
|
+
if (layer) {
|
|
321
|
+
this.canvasService.canvas.sendObjectToBack(layer);
|
|
322
|
+
}
|
|
246
323
|
this.canvasService.requestRenderAll();
|
|
247
324
|
}
|
|
248
325
|
};
|
|
@@ -251,6 +328,71 @@ var BackgroundTool = class {
|
|
|
251
328
|
var import_core2 = require("@pooder/core");
|
|
252
329
|
var import_fabric2 = require("fabric");
|
|
253
330
|
|
|
331
|
+
// src/extensions/dielineShape.ts
|
|
332
|
+
var BUILTIN_DIELINE_SHAPES = [
|
|
333
|
+
"rect",
|
|
334
|
+
"circle",
|
|
335
|
+
"ellipse",
|
|
336
|
+
"heart"
|
|
337
|
+
];
|
|
338
|
+
var DIELINE_SHAPES = [...BUILTIN_DIELINE_SHAPES, "custom"];
|
|
339
|
+
var DEFAULT_DIELINE_SHAPE = "rect";
|
|
340
|
+
var DEFAULT_HEART_SHAPE_PARAMS = {
|
|
341
|
+
lobeSpread: 0.46,
|
|
342
|
+
notchDepth: 0.24,
|
|
343
|
+
tipSharpness: 0
|
|
344
|
+
};
|
|
345
|
+
var DEFAULT_DIELINE_SHAPE_STYLE = {
|
|
346
|
+
fitMode: "contain",
|
|
347
|
+
...DEFAULT_HEART_SHAPE_PARAMS
|
|
348
|
+
};
|
|
349
|
+
function isDielineShape(value) {
|
|
350
|
+
return typeof value === "string" && DIELINE_SHAPES.includes(value);
|
|
351
|
+
}
|
|
352
|
+
function normalizeFitMode(value, fallback) {
|
|
353
|
+
if (value === "contain" || value === "stretch") return value;
|
|
354
|
+
return fallback;
|
|
355
|
+
}
|
|
356
|
+
function normalizeUnitInterval(value, fallback) {
|
|
357
|
+
const num = Number(value);
|
|
358
|
+
if (!Number.isFinite(num)) return fallback;
|
|
359
|
+
return Math.max(0, Math.min(1, num));
|
|
360
|
+
}
|
|
361
|
+
function normalizeDielineShape(value, fallback = DEFAULT_DIELINE_SHAPE) {
|
|
362
|
+
return isDielineShape(value) ? value : fallback;
|
|
363
|
+
}
|
|
364
|
+
function normalizeShapeStyle(value, fallback = DEFAULT_DIELINE_SHAPE_STYLE) {
|
|
365
|
+
var _a, _b, _c;
|
|
366
|
+
const raw = value && typeof value === "object" ? value : {};
|
|
367
|
+
return {
|
|
368
|
+
...fallback,
|
|
369
|
+
fitMode: normalizeFitMode(raw.fitMode, fallback.fitMode),
|
|
370
|
+
lobeSpread: normalizeUnitInterval(
|
|
371
|
+
raw.lobeSpread,
|
|
372
|
+
Number((_a = fallback.lobeSpread) != null ? _a : DEFAULT_HEART_SHAPE_PARAMS.lobeSpread)
|
|
373
|
+
),
|
|
374
|
+
notchDepth: normalizeUnitInterval(
|
|
375
|
+
raw.notchDepth,
|
|
376
|
+
Number((_b = fallback.notchDepth) != null ? _b : DEFAULT_HEART_SHAPE_PARAMS.notchDepth)
|
|
377
|
+
),
|
|
378
|
+
tipSharpness: normalizeUnitInterval(
|
|
379
|
+
raw.tipSharpness,
|
|
380
|
+
Number((_c = fallback.tipSharpness) != null ? _c : DEFAULT_HEART_SHAPE_PARAMS.tipSharpness)
|
|
381
|
+
)
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function getShapeFitMode(style) {
|
|
385
|
+
return normalizeShapeStyle(style).fitMode;
|
|
386
|
+
}
|
|
387
|
+
function getHeartShapeParams(style) {
|
|
388
|
+
const normalized = normalizeShapeStyle(style);
|
|
389
|
+
return {
|
|
390
|
+
lobeSpread: Number(normalized.lobeSpread),
|
|
391
|
+
notchDepth: Number(normalized.notchDepth),
|
|
392
|
+
tipSharpness: Number(normalized.tipSharpness)
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
254
396
|
// src/extensions/geometry.ts
|
|
255
397
|
var import_paper = __toESM(require("paper"));
|
|
256
398
|
|
|
@@ -393,66 +535,164 @@ function selectOuterChain(args) {
|
|
|
393
535
|
if (scoreA !== scoreB) return scoreA > scoreB ? pointsA : pointsB;
|
|
394
536
|
return pointsA.length <= pointsB.length ? pointsA : pointsB;
|
|
395
537
|
}
|
|
396
|
-
function
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
width,
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
const
|
|
410
|
-
|
|
538
|
+
function fitPathItemToRect(item, rect, fitMode) {
|
|
539
|
+
const { left, top, width, height } = rect;
|
|
540
|
+
const bounds = item.bounds;
|
|
541
|
+
if (width <= 0 || height <= 0 || !Number.isFinite(bounds.width) || !Number.isFinite(bounds.height) || bounds.width <= 0 || bounds.height <= 0) {
|
|
542
|
+
item.position = new import_paper.default.Point(left + width / 2, top + height / 2);
|
|
543
|
+
return item;
|
|
544
|
+
}
|
|
545
|
+
item.translate(new import_paper.default.Point(-bounds.left, -bounds.top));
|
|
546
|
+
if (fitMode === "stretch") {
|
|
547
|
+
item.scale(width / bounds.width, height / bounds.height, new import_paper.default.Point(0, 0));
|
|
548
|
+
item.translate(new import_paper.default.Point(left, top));
|
|
549
|
+
return item;
|
|
550
|
+
}
|
|
551
|
+
const uniformScale = Math.min(width / bounds.width, height / bounds.height);
|
|
552
|
+
item.scale(uniformScale, uniformScale, new import_paper.default.Point(0, 0));
|
|
553
|
+
const scaledWidth = bounds.width * uniformScale;
|
|
554
|
+
const scaledHeight = bounds.height * uniformScale;
|
|
555
|
+
item.translate(
|
|
556
|
+
new import_paper.default.Point(
|
|
557
|
+
left + (width - scaledWidth) / 2,
|
|
558
|
+
top + (height - scaledHeight) / 2
|
|
559
|
+
)
|
|
560
|
+
);
|
|
561
|
+
return item;
|
|
562
|
+
}
|
|
563
|
+
function createNormalizedHeartPath(params) {
|
|
564
|
+
const { lobeSpread, notchDepth, tipSharpness } = params;
|
|
565
|
+
const halfSpread = 0.22 + lobeSpread * 0.18;
|
|
566
|
+
const notchY = 0.06 + notchDepth * 0.2;
|
|
567
|
+
const shoulderY = 0.24 + notchDepth * 0.2;
|
|
568
|
+
const topLift = 0.12 + (1 - notchDepth) * 0.06;
|
|
569
|
+
const topY = notchY - topLift;
|
|
570
|
+
const sideCtrlY = shoulderY - (0.18 - notchDepth * 0.08);
|
|
571
|
+
const lowerCtrlY = 0.58 + (1 - tipSharpness) * 0.16;
|
|
572
|
+
const tipCtrlX = 0.34 - tipSharpness * 0.2;
|
|
573
|
+
const notchCtrlX = 0.06 + lobeSpread * 0.06;
|
|
574
|
+
const lobeCtrlX = 0.1 + lobeSpread * 0.08;
|
|
575
|
+
const notchCtrlY = notchY - topLift * 0.45;
|
|
576
|
+
const xPeakL = 0.5 - halfSpread;
|
|
577
|
+
const xPeakR = 0.5 + halfSpread;
|
|
578
|
+
const heartPath = new import_paper.default.Path({ insert: false });
|
|
579
|
+
heartPath.moveTo(new import_paper.default.Point(0.5, notchY));
|
|
580
|
+
heartPath.cubicCurveTo(
|
|
581
|
+
new import_paper.default.Point(0.5 - notchCtrlX, notchCtrlY),
|
|
582
|
+
new import_paper.default.Point(xPeakL + lobeCtrlX, topY),
|
|
583
|
+
new import_paper.default.Point(xPeakL, topY)
|
|
584
|
+
);
|
|
585
|
+
heartPath.cubicCurveTo(
|
|
586
|
+
new import_paper.default.Point(xPeakL - lobeCtrlX, topY),
|
|
587
|
+
new import_paper.default.Point(0, sideCtrlY),
|
|
588
|
+
new import_paper.default.Point(0, shoulderY)
|
|
589
|
+
);
|
|
590
|
+
heartPath.cubicCurveTo(
|
|
591
|
+
new import_paper.default.Point(0, lowerCtrlY),
|
|
592
|
+
new import_paper.default.Point(tipCtrlX, 1),
|
|
593
|
+
new import_paper.default.Point(0.5, 1)
|
|
594
|
+
);
|
|
595
|
+
heartPath.cubicCurveTo(
|
|
596
|
+
new import_paper.default.Point(1 - tipCtrlX, 1),
|
|
597
|
+
new import_paper.default.Point(1, lowerCtrlY),
|
|
598
|
+
new import_paper.default.Point(1, shoulderY)
|
|
599
|
+
);
|
|
600
|
+
heartPath.cubicCurveTo(
|
|
601
|
+
new import_paper.default.Point(1, sideCtrlY),
|
|
602
|
+
new import_paper.default.Point(xPeakR + lobeCtrlX, topY),
|
|
603
|
+
new import_paper.default.Point(xPeakR, topY)
|
|
604
|
+
);
|
|
605
|
+
heartPath.cubicCurveTo(
|
|
606
|
+
new import_paper.default.Point(xPeakR - lobeCtrlX, topY),
|
|
607
|
+
new import_paper.default.Point(0.5 + notchCtrlX, notchCtrlY),
|
|
608
|
+
new import_paper.default.Point(0.5, notchY)
|
|
609
|
+
);
|
|
610
|
+
heartPath.closed = true;
|
|
611
|
+
return heartPath;
|
|
612
|
+
}
|
|
613
|
+
function createHeartBaseShape(options) {
|
|
614
|
+
const { x, y, width, height } = options;
|
|
615
|
+
const w = Math.max(0, width);
|
|
616
|
+
const h = Math.max(0, height);
|
|
617
|
+
const left = x - w / 2;
|
|
618
|
+
const top = y - h / 2;
|
|
619
|
+
const fitMode = getShapeFitMode(options.shapeStyle);
|
|
620
|
+
const heartParams = getHeartShapeParams(options.shapeStyle);
|
|
621
|
+
const rawHeart = createNormalizedHeartPath(heartParams);
|
|
622
|
+
return fitPathItemToRect(rawHeart, { left, top, width: w, height: h }, fitMode);
|
|
623
|
+
}
|
|
624
|
+
var BUILTIN_SHAPE_BUILDERS = {
|
|
625
|
+
rect: (options) => {
|
|
626
|
+
const { x, y, width, height, radius } = options;
|
|
411
627
|
return new import_paper.default.Path.Rectangle({
|
|
412
628
|
point: [x - width / 2, y - height / 2],
|
|
413
629
|
size: [Math.max(0, width), Math.max(0, height)],
|
|
414
630
|
radius: Math.max(0, radius)
|
|
415
631
|
});
|
|
416
|
-
}
|
|
632
|
+
},
|
|
633
|
+
circle: (options) => {
|
|
634
|
+
const { x, y, width, height } = options;
|
|
417
635
|
const r = Math.min(width, height) / 2;
|
|
418
636
|
return new import_paper.default.Path.Circle({
|
|
419
|
-
center,
|
|
637
|
+
center: new import_paper.default.Point(x, y),
|
|
420
638
|
radius: Math.max(0, r)
|
|
421
639
|
});
|
|
422
|
-
}
|
|
640
|
+
},
|
|
641
|
+
ellipse: (options) => {
|
|
642
|
+
const { x, y, width, height } = options;
|
|
423
643
|
return new import_paper.default.Path.Ellipse({
|
|
424
|
-
center,
|
|
644
|
+
center: new import_paper.default.Point(x, y),
|
|
425
645
|
radius: [Math.max(0, width / 2), Math.max(0, height / 2)]
|
|
426
646
|
});
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
647
|
+
},
|
|
648
|
+
heart: createHeartBaseShape
|
|
649
|
+
};
|
|
650
|
+
function createCustomBaseShape(options) {
|
|
651
|
+
var _a;
|
|
652
|
+
const {
|
|
653
|
+
pathData,
|
|
654
|
+
customSourceWidthPx,
|
|
655
|
+
customSourceHeightPx,
|
|
656
|
+
x,
|
|
657
|
+
y,
|
|
658
|
+
width,
|
|
659
|
+
height
|
|
660
|
+
} = options;
|
|
661
|
+
if (typeof pathData !== "string" || pathData.trim().length === 0) {
|
|
662
|
+
return null;
|
|
663
|
+
}
|
|
664
|
+
const center = new import_paper.default.Point(x, y);
|
|
665
|
+
const hasMultipleSubPaths = ((_a = (pathData.match(/[Mm]/g) || []).length) != null ? _a : 0) > 1;
|
|
666
|
+
const path = hasMultipleSubPaths ? new import_paper.default.CompoundPath(pathData) : (() => {
|
|
667
|
+
const single = new import_paper.default.Path();
|
|
668
|
+
single.pathData = pathData;
|
|
669
|
+
return single;
|
|
670
|
+
})();
|
|
671
|
+
const sourceWidth = Number(customSourceWidthPx != null ? customSourceWidthPx : 0);
|
|
672
|
+
const sourceHeight = Number(customSourceHeightPx != null ? customSourceHeightPx : 0);
|
|
673
|
+
if (Number.isFinite(sourceWidth) && Number.isFinite(sourceHeight) && sourceWidth > 0 && sourceHeight > 0 && width > 0 && height > 0) {
|
|
674
|
+
const targetLeft = x - width / 2;
|
|
675
|
+
const targetTop = y - height / 2;
|
|
676
|
+
path.scale(width / sourceWidth, height / sourceHeight, new import_paper.default.Point(0, 0));
|
|
677
|
+
path.translate(new import_paper.default.Point(targetLeft, targetTop));
|
|
678
|
+
return path;
|
|
679
|
+
}
|
|
680
|
+
if (width > 0 && height > 0 && path.bounds.width > 0 && path.bounds.height > 0) {
|
|
448
681
|
path.position = center;
|
|
682
|
+
path.scale(width / path.bounds.width, height / path.bounds.height);
|
|
449
683
|
return path;
|
|
450
|
-
} else {
|
|
451
|
-
return new import_paper.default.Path.Rectangle({
|
|
452
|
-
point: [x - width / 2, y - height / 2],
|
|
453
|
-
size: [Math.max(0, width), Math.max(0, height)]
|
|
454
|
-
});
|
|
455
684
|
}
|
|
685
|
+
path.position = center;
|
|
686
|
+
return path;
|
|
687
|
+
}
|
|
688
|
+
function createBaseShape(options) {
|
|
689
|
+
const { shape } = options;
|
|
690
|
+
if (shape === "custom") {
|
|
691
|
+
const customShape = createCustomBaseShape(options);
|
|
692
|
+
if (customShape) return customShape;
|
|
693
|
+
return BUILTIN_SHAPE_BUILDERS[DEFAULT_DIELINE_SHAPE](options);
|
|
694
|
+
}
|
|
695
|
+
return BUILTIN_SHAPE_BUILDERS[shape](options);
|
|
456
696
|
}
|
|
457
697
|
function resolveBridgeBasePath(shape, anchor) {
|
|
458
698
|
if (shape instanceof import_paper.default.Path) {
|
|
@@ -776,6 +1016,18 @@ function getNearestPointOnDieline(point, options) {
|
|
|
776
1016
|
shape.remove();
|
|
777
1017
|
return result;
|
|
778
1018
|
}
|
|
1019
|
+
function getPathBounds(pathData) {
|
|
1020
|
+
const path = new import_paper.default.Path();
|
|
1021
|
+
path.pathData = pathData;
|
|
1022
|
+
const bounds = path.bounds;
|
|
1023
|
+
path.remove();
|
|
1024
|
+
return {
|
|
1025
|
+
x: bounds.x,
|
|
1026
|
+
y: bounds.y,
|
|
1027
|
+
width: bounds.width,
|
|
1028
|
+
height: bounds.height
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
779
1031
|
|
|
780
1032
|
// src/coordinate.ts
|
|
781
1033
|
var Coordinate = class {
|
|
@@ -864,12 +1116,6 @@ function parseLengthToMm(input, defaultUnit) {
|
|
|
864
1116
|
const unit = (_b = (_a = match[2]) == null ? void 0 : _a.toLowerCase()) != null ? _b : defaultUnit;
|
|
865
1117
|
return Coordinate.convertUnit(value, unit, "mm");
|
|
866
1118
|
}
|
|
867
|
-
function formatMm(valueMm, displayUnit, fractionDigits = 2) {
|
|
868
|
-
if (!Number.isFinite(valueMm)) return "0";
|
|
869
|
-
const value = Coordinate.convertUnit(valueMm, "mm", displayUnit);
|
|
870
|
-
const rounded = Number(value.toFixed(fractionDigits));
|
|
871
|
-
return rounded.toString();
|
|
872
|
-
}
|
|
873
1119
|
|
|
874
1120
|
// src/extensions/sceneLayoutModel.ts
|
|
875
1121
|
var DEFAULT_SIZE_STATE = {
|
|
@@ -1084,10 +1330,15 @@ function buildSceneGeometry(configService, layout) {
|
|
|
1084
1330
|
const sourceHeight = Number(
|
|
1085
1331
|
configService.get("dieline.customSourceHeightPx", 0)
|
|
1086
1332
|
);
|
|
1333
|
+
const shapeStyle = normalizeShapeStyle(
|
|
1334
|
+
configService.get("dieline.shapeStyle", DEFAULT_DIELINE_SHAPE_STYLE)
|
|
1335
|
+
);
|
|
1087
1336
|
return {
|
|
1088
|
-
shape:
|
|
1089
|
-
|
|
1090
|
-
|
|
1337
|
+
shape: normalizeDielineShape(
|
|
1338
|
+
configService.get("dieline.shape", DEFAULT_DIELINE_SHAPE)
|
|
1339
|
+
),
|
|
1340
|
+
shapeStyle,
|
|
1341
|
+
unit: "px",
|
|
1091
1342
|
x: layout.trimRect.centerX,
|
|
1092
1343
|
y: layout.trimRect.centerY,
|
|
1093
1344
|
width: layout.trimRect.width,
|
|
@@ -1120,6 +1371,7 @@ var ImageTool = class {
|
|
|
1120
1371
|
this.isImageSelectionActive = false;
|
|
1121
1372
|
this.focusedImageId = null;
|
|
1122
1373
|
this.renderSeq = 0;
|
|
1374
|
+
this.overlaySpecs = [];
|
|
1123
1375
|
this.onToolActivated = (event) => {
|
|
1124
1376
|
const before = this.isToolActive;
|
|
1125
1377
|
this.syncToolActiveFromWorkbench(event.id);
|
|
@@ -1197,28 +1449,41 @@ var ImageTool = class {
|
|
|
1197
1449
|
const frame = this.getFrameRect();
|
|
1198
1450
|
if (!frame.width || !frame.height) return;
|
|
1199
1451
|
const center = target.getCenterPoint ? target.getCenterPoint() : new import_fabric2.Point((_c = target.left) != null ? _c : 0, (_d = target.top) != null ? _d : 0);
|
|
1452
|
+
const centerScene = this.canvasService ? this.canvasService.toScenePoint({ x: center.x, y: center.y }) : { x: center.x, y: center.y };
|
|
1200
1453
|
const objectScale = Number.isFinite(target == null ? void 0 : target.scaleX) ? target.scaleX : 1;
|
|
1454
|
+
const objectScaleScene = this.toSceneObjectScale(objectScale || 1);
|
|
1201
1455
|
const workingItem = this.workingItems.find((item) => item.id === id);
|
|
1202
1456
|
const sourceKey = (workingItem == null ? void 0 : workingItem.sourceUrl) || (workingItem == null ? void 0 : workingItem.url) || "";
|
|
1203
1457
|
const sourceSize = this.getSourceSize(sourceKey, target);
|
|
1204
1458
|
const coverScale = this.getCoverScale(frame, sourceSize);
|
|
1205
1459
|
const updates = {
|
|
1206
|
-
left: this.clampNormalized((
|
|
1207
|
-
top: this.clampNormalized((
|
|
1460
|
+
left: this.clampNormalized((centerScene.x - frame.left) / frame.width),
|
|
1461
|
+
top: this.clampNormalized((centerScene.y - frame.top) / frame.height),
|
|
1208
1462
|
angle: Number.isFinite(target.angle) ? target.angle : 0,
|
|
1209
|
-
scale: Math.max(0.05,
|
|
1463
|
+
scale: Math.max(0.05, objectScaleScene / coverScale)
|
|
1210
1464
|
};
|
|
1211
1465
|
this.focusedImageId = id;
|
|
1212
1466
|
this.updateImageInWorking(id, updates);
|
|
1213
1467
|
};
|
|
1214
1468
|
}
|
|
1215
1469
|
activate(context) {
|
|
1470
|
+
var _a;
|
|
1216
1471
|
this.context = context;
|
|
1217
1472
|
this.canvasService = context.services.get("CanvasService");
|
|
1218
1473
|
if (!this.canvasService) {
|
|
1219
1474
|
console.warn("CanvasService not found for ImageTool");
|
|
1220
1475
|
return;
|
|
1221
1476
|
}
|
|
1477
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
1478
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
1479
|
+
this.id,
|
|
1480
|
+
() => ({
|
|
1481
|
+
rootLayerSpecs: {
|
|
1482
|
+
[IMAGE_OVERLAY_LAYER_ID]: this.overlaySpecs
|
|
1483
|
+
}
|
|
1484
|
+
}),
|
|
1485
|
+
{ priority: 300 }
|
|
1486
|
+
);
|
|
1222
1487
|
context.eventBus.on("tool:activated", this.onToolActivated);
|
|
1223
1488
|
context.eventBus.on("object:modified", this.onObjectModified);
|
|
1224
1489
|
context.eventBus.on("selection:created", this.onSelectionChanged);
|
|
@@ -1259,7 +1524,7 @@ var ImageTool = class {
|
|
|
1259
1524
|
this.updateImages();
|
|
1260
1525
|
}
|
|
1261
1526
|
deactivate(context) {
|
|
1262
|
-
var _a;
|
|
1527
|
+
var _a, _b;
|
|
1263
1528
|
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
1264
1529
|
context.eventBus.off("object:modified", this.onObjectModified);
|
|
1265
1530
|
context.eventBus.off("selection:created", this.onSelectionChanged);
|
|
@@ -1271,12 +1536,13 @@ var ImageTool = class {
|
|
|
1271
1536
|
this.dirtyTrackerDisposable = void 0;
|
|
1272
1537
|
this.cropShapeHatchPattern = void 0;
|
|
1273
1538
|
this.cropShapeHatchPatternColor = void 0;
|
|
1539
|
+
this.cropShapeHatchPatternKey = void 0;
|
|
1540
|
+
this.overlaySpecs = [];
|
|
1274
1541
|
this.clearRenderedImages();
|
|
1542
|
+
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
1543
|
+
this.renderProducerDisposable = void 0;
|
|
1275
1544
|
if (this.canvasService) {
|
|
1276
|
-
void this.canvasService.
|
|
1277
|
-
IMAGE_OVERLAY_LAYER_ID,
|
|
1278
|
-
[]
|
|
1279
|
-
);
|
|
1545
|
+
void this.canvasService.flushRenderFromProducers();
|
|
1280
1546
|
this.canvasService = void 0;
|
|
1281
1547
|
}
|
|
1282
1548
|
this.context = void 0;
|
|
@@ -1687,38 +1953,38 @@ var ImageTool = class {
|
|
|
1687
1953
|
if (!layout) {
|
|
1688
1954
|
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1689
1955
|
}
|
|
1690
|
-
return {
|
|
1956
|
+
return this.canvasService.toSceneRect({
|
|
1691
1957
|
left: layout.cutRect.left,
|
|
1692
1958
|
top: layout.cutRect.top,
|
|
1693
1959
|
width: layout.cutRect.width,
|
|
1694
1960
|
height: layout.cutRect.height
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
getFrameRectScreen(frame) {
|
|
1964
|
+
if (!this.canvasService) {
|
|
1965
|
+
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1966
|
+
}
|
|
1967
|
+
return this.canvasService.toScreenRect(frame || this.getFrameRect());
|
|
1968
|
+
}
|
|
1969
|
+
toLayoutSceneRect(rect) {
|
|
1970
|
+
return {
|
|
1971
|
+
left: rect.left,
|
|
1972
|
+
top: rect.top,
|
|
1973
|
+
width: rect.width,
|
|
1974
|
+
height: rect.height,
|
|
1975
|
+
space: "scene"
|
|
1695
1976
|
};
|
|
1696
1977
|
}
|
|
1697
1978
|
async resolveDefaultFitArea() {
|
|
1698
|
-
if (!this.
|
|
1699
|
-
const
|
|
1700
|
-
if (
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
const height = Number(cutRect == null ? void 0 : cutRect.height);
|
|
1708
|
-
const left = Number(cutRect == null ? void 0 : cutRect.left);
|
|
1709
|
-
const top = Number(cutRect == null ? void 0 : cutRect.top);
|
|
1710
|
-
if (!Number.isFinite(width) || !Number.isFinite(height) || !Number.isFinite(left) || !Number.isFinite(top)) {
|
|
1711
|
-
return null;
|
|
1712
|
-
}
|
|
1713
|
-
return {
|
|
1714
|
-
width: Math.max(1, width),
|
|
1715
|
-
height: Math.max(1, height),
|
|
1716
|
-
left: left + width / 2,
|
|
1717
|
-
top: top + height / 2
|
|
1718
|
-
};
|
|
1719
|
-
} catch (e) {
|
|
1720
|
-
return null;
|
|
1721
|
-
}
|
|
1979
|
+
if (!this.canvasService) return null;
|
|
1980
|
+
const frame = this.getFrameRect();
|
|
1981
|
+
if (frame.width <= 0 || frame.height <= 0) return null;
|
|
1982
|
+
return {
|
|
1983
|
+
width: Math.max(1, frame.width),
|
|
1984
|
+
height: Math.max(1, frame.height),
|
|
1985
|
+
left: frame.left + frame.width / 2,
|
|
1986
|
+
top: frame.top + frame.height / 2
|
|
1987
|
+
};
|
|
1722
1988
|
}
|
|
1723
1989
|
async fitImageToDefaultArea(id) {
|
|
1724
1990
|
if (!this.canvasService) return;
|
|
@@ -1727,13 +1993,14 @@ var ImageTool = class {
|
|
|
1727
1993
|
await this.fitImageToArea(id, area);
|
|
1728
1994
|
return;
|
|
1729
1995
|
}
|
|
1730
|
-
const
|
|
1731
|
-
const
|
|
1996
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
1997
|
+
const canvasW = Math.max(1, viewport.width || 0);
|
|
1998
|
+
const canvasH = Math.max(1, viewport.height || 0);
|
|
1732
1999
|
await this.fitImageToArea(id, {
|
|
1733
2000
|
width: canvasW,
|
|
1734
2001
|
height: canvasH,
|
|
1735
|
-
left: canvasW / 2,
|
|
1736
|
-
top: canvasH / 2
|
|
2002
|
+
left: viewport.left + canvasW / 2,
|
|
2003
|
+
top: viewport.top + canvasH / 2
|
|
1737
2004
|
});
|
|
1738
2005
|
}
|
|
1739
2006
|
getImageObjects() {
|
|
@@ -1821,13 +2088,17 @@ var ImageTool = class {
|
|
|
1821
2088
|
}
|
|
1822
2089
|
toSceneGeometryLike(raw) {
|
|
1823
2090
|
const shape = raw == null ? void 0 : raw.shape;
|
|
1824
|
-
if (shape
|
|
2091
|
+
if (!isDielineShape(shape)) {
|
|
1825
2092
|
return null;
|
|
1826
2093
|
}
|
|
1827
|
-
const
|
|
1828
|
-
const
|
|
2094
|
+
const radiusRaw = Number(raw == null ? void 0 : raw.radius);
|
|
2095
|
+
const offsetRaw = Number(raw == null ? void 0 : raw.offset);
|
|
2096
|
+
const unit = typeof (raw == null ? void 0 : raw.unit) === "string" ? raw.unit : "px";
|
|
2097
|
+
const radius = unit === "scene" || !this.canvasService ? radiusRaw : this.canvasService.toSceneLength(radiusRaw);
|
|
2098
|
+
const offset = unit === "scene" || !this.canvasService ? offsetRaw : this.canvasService.toSceneLength(offsetRaw);
|
|
1829
2099
|
return {
|
|
1830
2100
|
shape,
|
|
2101
|
+
shapeStyle: normalizeShapeStyle(raw == null ? void 0 : raw.shapeStyle),
|
|
1831
2102
|
radius: Number.isFinite(radius) ? radius : 0,
|
|
1832
2103
|
offset: Number.isFinite(offset) ? offset : 0
|
|
1833
2104
|
};
|
|
@@ -1879,8 +2150,11 @@ var ImageTool = class {
|
|
|
1879
2150
|
return Math.max(0, Math.min(maxRadius, rawCutRadius));
|
|
1880
2151
|
}
|
|
1881
2152
|
getCropShapeHatchPattern(color = "rgba(255, 0, 0, 0.6)") {
|
|
2153
|
+
var _a;
|
|
1882
2154
|
if (typeof document === "undefined") return void 0;
|
|
1883
|
-
|
|
2155
|
+
const sceneScale = ((_a = this.canvasService) == null ? void 0 : _a.getSceneScale()) || 1;
|
|
2156
|
+
const cacheKey = `${color}::${sceneScale.toFixed(6)}`;
|
|
2157
|
+
if (this.cropShapeHatchPattern && this.cropShapeHatchPatternColor === color && this.cropShapeHatchPatternKey === cacheKey) {
|
|
1884
2158
|
return this.cropShapeHatchPattern;
|
|
1885
2159
|
}
|
|
1886
2160
|
const size = 16;
|
|
@@ -1909,11 +2183,21 @@ var ImageTool = class {
|
|
|
1909
2183
|
// @ts-ignore: Fabric Pattern accepts canvas source here.
|
|
1910
2184
|
repetition: "repeat"
|
|
1911
2185
|
});
|
|
2186
|
+
pattern.patternTransform = [
|
|
2187
|
+
1 / sceneScale,
|
|
2188
|
+
0,
|
|
2189
|
+
0,
|
|
2190
|
+
1 / sceneScale,
|
|
2191
|
+
0,
|
|
2192
|
+
0
|
|
2193
|
+
];
|
|
1912
2194
|
this.cropShapeHatchPattern = pattern;
|
|
1913
2195
|
this.cropShapeHatchPatternColor = color;
|
|
2196
|
+
this.cropShapeHatchPatternKey = cacheKey;
|
|
1914
2197
|
return pattern;
|
|
1915
2198
|
}
|
|
1916
2199
|
buildCropShapeOverlaySpecs(frame, sceneGeometry) {
|
|
2200
|
+
var _a, _b;
|
|
1917
2201
|
if (!sceneGeometry) {
|
|
1918
2202
|
this.debug("overlay:shape:skip", { reason: "scene-geometry-missing" });
|
|
1919
2203
|
return [];
|
|
@@ -1923,6 +2207,7 @@ var ImageTool = class {
|
|
|
1923
2207
|
return [];
|
|
1924
2208
|
}
|
|
1925
2209
|
const shape = sceneGeometry.shape;
|
|
2210
|
+
const shapeStyle = sceneGeometry.shapeStyle;
|
|
1926
2211
|
const inset = 0;
|
|
1927
2212
|
const shapeWidth = Math.max(1, frame.width);
|
|
1928
2213
|
const shapeHeight = Math.max(1, frame.height);
|
|
@@ -1932,6 +2217,7 @@ var ImageTool = class {
|
|
|
1932
2217
|
frameWidth: frame.width,
|
|
1933
2218
|
frameHeight: frame.height,
|
|
1934
2219
|
offset: sceneGeometry.offset,
|
|
2220
|
+
shapeStyle,
|
|
1935
2221
|
inset,
|
|
1936
2222
|
shapeWidth,
|
|
1937
2223
|
shapeHeight,
|
|
@@ -1953,6 +2239,7 @@ var ImageTool = class {
|
|
|
1953
2239
|
x: frame.width / 2,
|
|
1954
2240
|
y: frame.height / 2,
|
|
1955
2241
|
features: [],
|
|
2242
|
+
shapeStyle,
|
|
1956
2243
|
canvasWidth: frame.width,
|
|
1957
2244
|
canvasHeight: frame.height
|
|
1958
2245
|
};
|
|
@@ -1970,6 +2257,9 @@ var ImageTool = class {
|
|
|
1970
2257
|
}
|
|
1971
2258
|
const patternFill = this.getCropShapeHatchPattern();
|
|
1972
2259
|
const hatchFill = patternFill || "rgba(255, 0, 0, 0.22)";
|
|
2260
|
+
const shapeBounds = getPathBounds(shapePathData);
|
|
2261
|
+
const hatchBounds = getPathBounds(hatchPathData);
|
|
2262
|
+
const frameRect = this.toLayoutSceneRect(frame);
|
|
1973
2263
|
const hatchPathLength = hatchPathData.length;
|
|
1974
2264
|
const shapePathLength = shapePathData.length;
|
|
1975
2265
|
const specs = [
|
|
@@ -1977,10 +2267,16 @@ var ImageTool = class {
|
|
|
1977
2267
|
id: "image.cropShapeHatch",
|
|
1978
2268
|
type: "path",
|
|
1979
2269
|
data: { id: "image.cropShapeHatch", zIndex: 5 },
|
|
2270
|
+
layout: {
|
|
2271
|
+
reference: "custom",
|
|
2272
|
+
referenceRect: frameRect,
|
|
2273
|
+
alignX: "start",
|
|
2274
|
+
alignY: "start",
|
|
2275
|
+
offsetX: hatchBounds.x,
|
|
2276
|
+
offsetY: hatchBounds.y
|
|
2277
|
+
},
|
|
1980
2278
|
props: {
|
|
1981
2279
|
pathData: hatchPathData,
|
|
1982
|
-
left: frame.left,
|
|
1983
|
-
top: frame.top,
|
|
1984
2280
|
originX: "left",
|
|
1985
2281
|
originY: "top",
|
|
1986
2282
|
fill: hatchFill,
|
|
@@ -1997,15 +2293,21 @@ var ImageTool = class {
|
|
|
1997
2293
|
id: "image.cropShapePath",
|
|
1998
2294
|
type: "path",
|
|
1999
2295
|
data: { id: "image.cropShapePath", zIndex: 6 },
|
|
2296
|
+
layout: {
|
|
2297
|
+
reference: "custom",
|
|
2298
|
+
referenceRect: frameRect,
|
|
2299
|
+
alignX: "start",
|
|
2300
|
+
alignY: "start",
|
|
2301
|
+
offsetX: shapeBounds.x,
|
|
2302
|
+
offsetY: shapeBounds.y
|
|
2303
|
+
},
|
|
2000
2304
|
props: {
|
|
2001
2305
|
pathData: shapePathData,
|
|
2002
|
-
left: frame.left,
|
|
2003
|
-
top: frame.top,
|
|
2004
2306
|
originX: "left",
|
|
2005
2307
|
originY: "top",
|
|
2006
2308
|
fill: "rgba(0,0,0,0)",
|
|
2007
2309
|
stroke: "rgba(255, 0, 0, 0.9)",
|
|
2008
|
-
strokeWidth: 1,
|
|
2310
|
+
strokeWidth: (_b = (_a = this.canvasService) == null ? void 0 : _a.toSceneLength(1)) != null ? _b : 1,
|
|
2009
2311
|
selectable: false,
|
|
2010
2312
|
evented: false,
|
|
2011
2313
|
excludeFromExport: true,
|
|
@@ -2022,6 +2324,8 @@ var ImageTool = class {
|
|
|
2022
2324
|
fillRule: "evenodd",
|
|
2023
2325
|
shapePathLength,
|
|
2024
2326
|
hatchPathLength,
|
|
2327
|
+
shapeBounds,
|
|
2328
|
+
hatchBounds,
|
|
2025
2329
|
hatchFillType: hatchFill && typeof hatchFill === "object" ? "pattern" : "color",
|
|
2026
2330
|
ids: specs.map((spec) => spec.id)
|
|
2027
2331
|
});
|
|
@@ -2084,6 +2388,28 @@ var ImageTool = class {
|
|
|
2084
2388
|
opacity: render.opacity
|
|
2085
2389
|
};
|
|
2086
2390
|
}
|
|
2391
|
+
toScreenObjectProps(props) {
|
|
2392
|
+
if (!this.canvasService) return props;
|
|
2393
|
+
const next = { ...props };
|
|
2394
|
+
if (Number.isFinite(next.left) || Number.isFinite(next.top)) {
|
|
2395
|
+
const mapped = this.canvasService.toScreenPoint({
|
|
2396
|
+
x: Number.isFinite(next.left) ? Number(next.left) : 0,
|
|
2397
|
+
y: Number.isFinite(next.top) ? Number(next.top) : 0
|
|
2398
|
+
});
|
|
2399
|
+
if (Number.isFinite(next.left)) next.left = mapped.x;
|
|
2400
|
+
if (Number.isFinite(next.top)) next.top = mapped.y;
|
|
2401
|
+
}
|
|
2402
|
+
const sceneScale = this.canvasService.getSceneScale();
|
|
2403
|
+
const sx = Number.isFinite(next.scaleX) ? Number(next.scaleX) : 1;
|
|
2404
|
+
const sy = Number.isFinite(next.scaleY) ? Number(next.scaleY) : 1;
|
|
2405
|
+
next.scaleX = sx * sceneScale;
|
|
2406
|
+
next.scaleY = sy * sceneScale;
|
|
2407
|
+
return next;
|
|
2408
|
+
}
|
|
2409
|
+
toSceneObjectScale(value) {
|
|
2410
|
+
if (!this.canvasService) return value;
|
|
2411
|
+
return value / this.canvasService.getSceneScale();
|
|
2412
|
+
}
|
|
2087
2413
|
getCurrentSrc(obj) {
|
|
2088
2414
|
var _a;
|
|
2089
2415
|
if (!obj) return void 0;
|
|
@@ -2133,8 +2459,9 @@ var ImageTool = class {
|
|
|
2133
2459
|
this.rememberSourceSize(render.src, obj);
|
|
2134
2460
|
const sourceSize = this.getSourceSize(render.src, obj);
|
|
2135
2461
|
const props = this.computeCanvasProps(render, sourceSize, frame);
|
|
2462
|
+
const screenProps = this.toScreenObjectProps(props);
|
|
2136
2463
|
obj.set({
|
|
2137
|
-
...
|
|
2464
|
+
...screenProps,
|
|
2138
2465
|
data: {
|
|
2139
2466
|
...obj.data || {},
|
|
2140
2467
|
id: item.id,
|
|
@@ -2200,37 +2527,67 @@ var ImageTool = class {
|
|
|
2200
2527
|
});
|
|
2201
2528
|
return [];
|
|
2202
2529
|
}
|
|
2203
|
-
const
|
|
2204
|
-
const
|
|
2530
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
2531
|
+
const canvasW = viewport.width || 0;
|
|
2532
|
+
const canvasH = viewport.height || 0;
|
|
2533
|
+
const canvasLeft = viewport.left || 0;
|
|
2534
|
+
const canvasTop = viewport.top || 0;
|
|
2205
2535
|
const visual = this.getFrameVisualConfig();
|
|
2206
|
-
const
|
|
2207
|
-
|
|
2536
|
+
const strokeWidthScene = this.canvasService.toSceneLength(
|
|
2537
|
+
visual.strokeWidth
|
|
2538
|
+
);
|
|
2539
|
+
const dashLengthScene = this.canvasService.toSceneLength(visual.dashLength);
|
|
2540
|
+
const frameLeft = Math.max(
|
|
2541
|
+
canvasLeft,
|
|
2542
|
+
Math.min(canvasLeft + canvasW, frame.left)
|
|
2543
|
+
);
|
|
2544
|
+
const frameTop = Math.max(
|
|
2545
|
+
canvasTop,
|
|
2546
|
+
Math.min(canvasTop + canvasH, frame.top)
|
|
2547
|
+
);
|
|
2208
2548
|
const frameRight = Math.max(
|
|
2209
2549
|
frameLeft,
|
|
2210
|
-
Math.min(canvasW, frame.left + frame.width)
|
|
2550
|
+
Math.min(canvasLeft + canvasW, frame.left + frame.width)
|
|
2211
2551
|
);
|
|
2212
2552
|
const frameBottom = Math.max(
|
|
2213
2553
|
frameTop,
|
|
2214
|
-
Math.min(canvasH, frame.top + frame.height)
|
|
2554
|
+
Math.min(canvasTop + canvasH, frame.top + frame.height)
|
|
2215
2555
|
);
|
|
2216
2556
|
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
2217
|
-
const topH = frameTop;
|
|
2218
|
-
const bottomH = Math.max(0, canvasH - frameBottom);
|
|
2219
|
-
const leftW = frameLeft;
|
|
2220
|
-
const rightW = Math.max(0, canvasW - frameRight);
|
|
2557
|
+
const topH = Math.max(0, frameTop - canvasTop);
|
|
2558
|
+
const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
|
|
2559
|
+
const leftW = Math.max(0, frameLeft - canvasLeft);
|
|
2560
|
+
const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
|
|
2561
|
+
const viewportRect = this.toLayoutSceneRect({
|
|
2562
|
+
left: canvasLeft,
|
|
2563
|
+
top: canvasTop,
|
|
2564
|
+
width: canvasW,
|
|
2565
|
+
height: canvasH
|
|
2566
|
+
});
|
|
2567
|
+
const visibleFrameBandRect = this.toLayoutSceneRect({
|
|
2568
|
+
left: canvasLeft,
|
|
2569
|
+
top: frameTop,
|
|
2570
|
+
width: canvasW,
|
|
2571
|
+
height: visibleFrameH
|
|
2572
|
+
});
|
|
2573
|
+
const frameRect = this.toLayoutSceneRect(frame);
|
|
2221
2574
|
const shapeOverlay = this.buildCropShapeOverlaySpecs(frame, sceneGeometry);
|
|
2222
2575
|
const mask = [
|
|
2223
2576
|
{
|
|
2224
2577
|
id: "image.cropMask.top",
|
|
2225
2578
|
type: "rect",
|
|
2226
2579
|
data: { id: "image.cropMask.top", zIndex: 1 },
|
|
2580
|
+
layout: {
|
|
2581
|
+
reference: "custom",
|
|
2582
|
+
referenceRect: viewportRect,
|
|
2583
|
+
alignX: "start",
|
|
2584
|
+
alignY: "start",
|
|
2585
|
+
width: "100%",
|
|
2586
|
+
height: topH
|
|
2587
|
+
},
|
|
2227
2588
|
props: {
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
width: canvasW,
|
|
2231
|
-
height: topH,
|
|
2232
|
-
originX: "center",
|
|
2233
|
-
originY: "center",
|
|
2589
|
+
originX: "left",
|
|
2590
|
+
originY: "top",
|
|
2234
2591
|
fill: visual.outerBackground,
|
|
2235
2592
|
selectable: false,
|
|
2236
2593
|
evented: false
|
|
@@ -2240,13 +2597,17 @@ var ImageTool = class {
|
|
|
2240
2597
|
id: "image.cropMask.bottom",
|
|
2241
2598
|
type: "rect",
|
|
2242
2599
|
data: { id: "image.cropMask.bottom", zIndex: 2 },
|
|
2600
|
+
layout: {
|
|
2601
|
+
reference: "custom",
|
|
2602
|
+
referenceRect: viewportRect,
|
|
2603
|
+
alignX: "start",
|
|
2604
|
+
alignY: "end",
|
|
2605
|
+
width: "100%",
|
|
2606
|
+
height: bottomH
|
|
2607
|
+
},
|
|
2243
2608
|
props: {
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
width: canvasW,
|
|
2247
|
-
height: bottomH,
|
|
2248
|
-
originX: "center",
|
|
2249
|
-
originY: "center",
|
|
2609
|
+
originX: "left",
|
|
2610
|
+
originY: "top",
|
|
2250
2611
|
fill: visual.outerBackground,
|
|
2251
2612
|
selectable: false,
|
|
2252
2613
|
evented: false
|
|
@@ -2256,13 +2617,17 @@ var ImageTool = class {
|
|
|
2256
2617
|
id: "image.cropMask.left",
|
|
2257
2618
|
type: "rect",
|
|
2258
2619
|
data: { id: "image.cropMask.left", zIndex: 3 },
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2620
|
+
layout: {
|
|
2621
|
+
reference: "custom",
|
|
2622
|
+
referenceRect: visibleFrameBandRect,
|
|
2623
|
+
alignX: "start",
|
|
2624
|
+
alignY: "start",
|
|
2262
2625
|
width: leftW,
|
|
2263
|
-
height:
|
|
2264
|
-
|
|
2265
|
-
|
|
2626
|
+
height: "100%"
|
|
2627
|
+
},
|
|
2628
|
+
props: {
|
|
2629
|
+
originX: "left",
|
|
2630
|
+
originY: "top",
|
|
2266
2631
|
fill: visual.outerBackground,
|
|
2267
2632
|
selectable: false,
|
|
2268
2633
|
evented: false
|
|
@@ -2272,13 +2637,17 @@ var ImageTool = class {
|
|
|
2272
2637
|
id: "image.cropMask.right",
|
|
2273
2638
|
type: "rect",
|
|
2274
2639
|
data: { id: "image.cropMask.right", zIndex: 4 },
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2640
|
+
layout: {
|
|
2641
|
+
reference: "custom",
|
|
2642
|
+
referenceRect: visibleFrameBandRect,
|
|
2643
|
+
alignX: "end",
|
|
2644
|
+
alignY: "start",
|
|
2278
2645
|
width: rightW,
|
|
2279
|
-
height:
|
|
2280
|
-
|
|
2281
|
-
|
|
2646
|
+
height: "100%"
|
|
2647
|
+
},
|
|
2648
|
+
props: {
|
|
2649
|
+
originX: "left",
|
|
2650
|
+
originY: "top",
|
|
2282
2651
|
fill: visual.outerBackground,
|
|
2283
2652
|
selectable: false,
|
|
2284
2653
|
evented: false
|
|
@@ -2289,17 +2658,21 @@ var ImageTool = class {
|
|
|
2289
2658
|
id: "image.cropFrame",
|
|
2290
2659
|
type: "rect",
|
|
2291
2660
|
data: { id: "image.cropFrame", zIndex: 7 },
|
|
2661
|
+
layout: {
|
|
2662
|
+
reference: "custom",
|
|
2663
|
+
referenceRect: frameRect,
|
|
2664
|
+
alignX: "start",
|
|
2665
|
+
alignY: "start",
|
|
2666
|
+
width: "100%",
|
|
2667
|
+
height: "100%"
|
|
2668
|
+
},
|
|
2292
2669
|
props: {
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
width: frame.width,
|
|
2296
|
-
height: frame.height,
|
|
2297
|
-
originX: "center",
|
|
2298
|
-
originY: "center",
|
|
2670
|
+
originX: "left",
|
|
2671
|
+
originY: "top",
|
|
2299
2672
|
fill: visual.innerBackground,
|
|
2300
2673
|
stroke: visual.strokeStyle === "hidden" ? "rgba(0,0,0,0)" : visual.strokeColor,
|
|
2301
|
-
strokeWidth: visual.strokeStyle === "hidden" ? 0 :
|
|
2302
|
-
strokeDashArray: visual.strokeStyle === "dashed" ? [
|
|
2674
|
+
strokeWidth: visual.strokeStyle === "hidden" ? 0 : strokeWidthScene,
|
|
2675
|
+
strokeDashArray: visual.strokeStyle === "dashed" ? [dashLengthScene, dashLengthScene] : void 0,
|
|
2303
2676
|
selectable: false,
|
|
2304
2677
|
evented: false
|
|
2305
2678
|
}
|
|
@@ -2350,10 +2723,8 @@ var ImageTool = class {
|
|
|
2350
2723
|
const sceneGeometry = await this.resolveSceneGeometryForOverlay();
|
|
2351
2724
|
if (seq !== this.renderSeq) return;
|
|
2352
2725
|
const overlaySpecs = this.buildOverlaySpecs(frame, sceneGeometry);
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
overlaySpecs
|
|
2356
|
-
);
|
|
2726
|
+
this.overlaySpecs = overlaySpecs;
|
|
2727
|
+
await this.canvasService.flushRenderFromProducers();
|
|
2357
2728
|
this.syncImageZOrder(renderItems);
|
|
2358
2729
|
const overlayCanvasCount = this.getOverlayObjects().length;
|
|
2359
2730
|
this.debug("render:done", {
|
|
@@ -2444,7 +2815,7 @@ var ImageTool = class {
|
|
|
2444
2815
|
const source = this.getSourceSize(render.src, obj);
|
|
2445
2816
|
const frame = this.getFrameRect();
|
|
2446
2817
|
const coverScale = this.getCoverScale(frame, source);
|
|
2447
|
-
const currentScale = obj.scaleX || 1;
|
|
2818
|
+
const currentScale = this.toSceneObjectScale(obj.scaleX || 1);
|
|
2448
2819
|
const zoom = Math.max(0.05, currentScale / coverScale);
|
|
2449
2820
|
const updated = {
|
|
2450
2821
|
scale: Number.isFinite(zoom) ? zoom : 1,
|
|
@@ -2481,12 +2852,13 @@ var ImageTool = class {
|
|
|
2481
2852
|
Math.max(1, area.width) / Math.max(1, source.width),
|
|
2482
2853
|
Math.max(1, area.height) / Math.max(1, source.height)
|
|
2483
2854
|
);
|
|
2484
|
-
const
|
|
2485
|
-
const
|
|
2855
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
2856
|
+
const canvasW = viewport.width || 1;
|
|
2857
|
+
const canvasH = viewport.height || 1;
|
|
2486
2858
|
const areaLeftInput = (_a = area.left) != null ? _a : 0.5;
|
|
2487
2859
|
const areaTopInput = (_b = area.top) != null ? _b : 0.5;
|
|
2488
|
-
const areaLeftPx = areaLeftInput <= 1.5 ? areaLeftInput * canvasW : areaLeftInput;
|
|
2489
|
-
const areaTopPx = areaTopInput <= 1.5 ? areaTopInput * canvasH : areaTopInput;
|
|
2860
|
+
const areaLeftPx = areaLeftInput <= 1.5 ? viewport.left + areaLeftInput * canvasW : areaLeftInput;
|
|
2861
|
+
const areaTopPx = areaTopInput <= 1.5 ? viewport.top + areaTopInput * canvasH : areaTopInput;
|
|
2490
2862
|
const updates = {
|
|
2491
2863
|
scale: Math.max(0.05, desiredScale / baseCover),
|
|
2492
2864
|
left: this.clampNormalized(
|
|
@@ -2551,7 +2923,8 @@ var ImageTool = class {
|
|
|
2551
2923
|
if (!normalizedIds.length) {
|
|
2552
2924
|
throw new Error("image-ids-required");
|
|
2553
2925
|
}
|
|
2554
|
-
const
|
|
2926
|
+
const frameScene = this.getFrameRect();
|
|
2927
|
+
const frame = this.getFrameRectScreen(frameScene);
|
|
2555
2928
|
const multiplier = Math.max(1, (_a = options.multiplier) != null ? _a : 2);
|
|
2556
2929
|
const format = options.format === "jpeg" ? "jpeg" : "png";
|
|
2557
2930
|
const width = Math.max(1, Math.round(frame.width * multiplier));
|
|
@@ -3975,6 +4348,7 @@ var ImageTracer = class {
|
|
|
3975
4348
|
|
|
3976
4349
|
// src/extensions/dieline.ts
|
|
3977
4350
|
var IMAGE_OBJECT_LAYER_ID2 = "image.user";
|
|
4351
|
+
var DIELINE_LAYER_ID = "dieline-overlay";
|
|
3978
4352
|
var DielineTool = class {
|
|
3979
4353
|
constructor(options) {
|
|
3980
4354
|
this.id = "pooder.kit.dieline";
|
|
@@ -3982,8 +4356,8 @@ var DielineTool = class {
|
|
|
3982
4356
|
name: "DielineTool"
|
|
3983
4357
|
};
|
|
3984
4358
|
this.state = {
|
|
3985
|
-
|
|
3986
|
-
|
|
4359
|
+
shape: DEFAULT_DIELINE_SHAPE,
|
|
4360
|
+
shapeStyle: { ...DEFAULT_DIELINE_SHAPE_STYLE },
|
|
3987
4361
|
width: 500,
|
|
3988
4362
|
height: 500,
|
|
3989
4363
|
radius: 0,
|
|
@@ -4006,6 +4380,8 @@ var DielineTool = class {
|
|
|
4006
4380
|
showBleedLines: true,
|
|
4007
4381
|
features: []
|
|
4008
4382
|
};
|
|
4383
|
+
this.specs = [];
|
|
4384
|
+
this.renderSeq = 0;
|
|
4009
4385
|
this.onCanvasResized = () => {
|
|
4010
4386
|
this.updateDieline();
|
|
4011
4387
|
};
|
|
@@ -4018,24 +4394,50 @@ var DielineTool = class {
|
|
|
4018
4394
|
Object.assign(this.state.offsetLine, options.offsetLine);
|
|
4019
4395
|
delete options.offsetLine;
|
|
4020
4396
|
}
|
|
4397
|
+
if (options.shapeStyle) {
|
|
4398
|
+
this.state.shapeStyle = normalizeShapeStyle(
|
|
4399
|
+
options.shapeStyle,
|
|
4400
|
+
this.state.shapeStyle
|
|
4401
|
+
);
|
|
4402
|
+
delete options.shapeStyle;
|
|
4403
|
+
}
|
|
4021
4404
|
Object.assign(this.state, options);
|
|
4405
|
+
this.state.shape = normalizeDielineShape(options.shape, this.state.shape);
|
|
4022
4406
|
}
|
|
4023
4407
|
}
|
|
4024
4408
|
activate(context) {
|
|
4409
|
+
var _a;
|
|
4025
4410
|
this.context = context;
|
|
4026
4411
|
this.canvasService = context.services.get("CanvasService");
|
|
4027
4412
|
if (!this.canvasService) {
|
|
4028
4413
|
console.warn("CanvasService not found for DielineTool");
|
|
4029
4414
|
return;
|
|
4030
4415
|
}
|
|
4416
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
4417
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
4418
|
+
this.id,
|
|
4419
|
+
() => ({
|
|
4420
|
+
layerSpecs: {
|
|
4421
|
+
[DIELINE_LAYER_ID]: this.specs
|
|
4422
|
+
},
|
|
4423
|
+
replaceLayerIds: [DIELINE_LAYER_ID]
|
|
4424
|
+
}),
|
|
4425
|
+
{ priority: 250 }
|
|
4426
|
+
);
|
|
4031
4427
|
const configService = context.services.get(
|
|
4032
4428
|
"ConfigurationService"
|
|
4033
4429
|
);
|
|
4034
4430
|
if (configService) {
|
|
4035
4431
|
const s = this.state;
|
|
4036
4432
|
const sizeState = readSizeState(configService);
|
|
4037
|
-
s.
|
|
4038
|
-
|
|
4433
|
+
s.shape = normalizeDielineShape(
|
|
4434
|
+
configService.get("dieline.shape", s.shape),
|
|
4435
|
+
s.shape
|
|
4436
|
+
);
|
|
4437
|
+
s.shapeStyle = normalizeShapeStyle(
|
|
4438
|
+
configService.get("dieline.shapeStyle", s.shapeStyle),
|
|
4439
|
+
s.shapeStyle
|
|
4440
|
+
);
|
|
4039
4441
|
s.width = sizeState.actualWidthMm;
|
|
4040
4442
|
s.height = sizeState.actualHeightMm;
|
|
4041
4443
|
s.radius = parseLengthToMm(
|
|
@@ -4095,7 +4497,6 @@ var DielineTool = class {
|
|
|
4095
4497
|
configService.onAnyChange((e) => {
|
|
4096
4498
|
if (e.key.startsWith("size.")) {
|
|
4097
4499
|
const nextSize = readSizeState(configService);
|
|
4098
|
-
s.displayUnit = nextSize.unit;
|
|
4099
4500
|
s.width = nextSize.actualWidthMm;
|
|
4100
4501
|
s.height = nextSize.actualHeightMm;
|
|
4101
4502
|
s.padding = nextSize.viewPadding;
|
|
@@ -4106,7 +4507,10 @@ var DielineTool = class {
|
|
|
4106
4507
|
if (e.key.startsWith("dieline.")) {
|
|
4107
4508
|
switch (e.key) {
|
|
4108
4509
|
case "dieline.shape":
|
|
4109
|
-
s.shape = e.value;
|
|
4510
|
+
s.shape = normalizeDielineShape(e.value, s.shape);
|
|
4511
|
+
break;
|
|
4512
|
+
case "dieline.shapeStyle":
|
|
4513
|
+
s.shapeStyle = normalizeShapeStyle(e.value, s.shapeStyle);
|
|
4110
4514
|
break;
|
|
4111
4515
|
case "dieline.radius":
|
|
4112
4516
|
s.radius = parseLengthToMm(e.value, "mm");
|
|
@@ -4162,12 +4566,18 @@ var DielineTool = class {
|
|
|
4162
4566
|
});
|
|
4163
4567
|
}
|
|
4164
4568
|
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
4165
|
-
this.createLayer();
|
|
4166
4569
|
this.updateDieline();
|
|
4167
4570
|
}
|
|
4168
4571
|
deactivate(context) {
|
|
4572
|
+
var _a;
|
|
4169
4573
|
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
4170
|
-
this.
|
|
4574
|
+
this.renderSeq += 1;
|
|
4575
|
+
this.specs = [];
|
|
4576
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
4577
|
+
this.renderProducerDisposable = void 0;
|
|
4578
|
+
if (this.canvasService) {
|
|
4579
|
+
void this.canvasService.flushRenderFromProducers();
|
|
4580
|
+
}
|
|
4171
4581
|
this.canvasService = void 0;
|
|
4172
4582
|
this.context = void 0;
|
|
4173
4583
|
}
|
|
@@ -4190,7 +4600,7 @@ var DielineTool = class {
|
|
|
4190
4600
|
id: "dieline.shape",
|
|
4191
4601
|
type: "select",
|
|
4192
4602
|
label: "Shape",
|
|
4193
|
-
options:
|
|
4603
|
+
options: Array.from(DIELINE_SHAPES),
|
|
4194
4604
|
default: s.shape
|
|
4195
4605
|
},
|
|
4196
4606
|
{
|
|
@@ -4201,6 +4611,12 @@ var DielineTool = class {
|
|
|
4201
4611
|
max: 500,
|
|
4202
4612
|
default: s.radius
|
|
4203
4613
|
},
|
|
4614
|
+
{
|
|
4615
|
+
id: "dieline.shapeStyle",
|
|
4616
|
+
type: "json",
|
|
4617
|
+
label: "Shape Style",
|
|
4618
|
+
default: s.shapeStyle
|
|
4619
|
+
},
|
|
4204
4620
|
{
|
|
4205
4621
|
id: "dieline.showBleedLines",
|
|
4206
4622
|
type: "boolean",
|
|
@@ -4376,34 +4792,6 @@ var DielineTool = class {
|
|
|
4376
4792
|
]
|
|
4377
4793
|
};
|
|
4378
4794
|
}
|
|
4379
|
-
getLayer() {
|
|
4380
|
-
var _a;
|
|
4381
|
-
return (_a = this.canvasService) == null ? void 0 : _a.getLayer("dieline-overlay");
|
|
4382
|
-
}
|
|
4383
|
-
createLayer() {
|
|
4384
|
-
if (!this.canvasService) return;
|
|
4385
|
-
const width = this.canvasService.canvas.width || 800;
|
|
4386
|
-
const height = this.canvasService.canvas.height || 600;
|
|
4387
|
-
const layer = this.canvasService.createLayer("dieline-overlay", {
|
|
4388
|
-
width,
|
|
4389
|
-
height,
|
|
4390
|
-
selectable: false,
|
|
4391
|
-
evented: false
|
|
4392
|
-
});
|
|
4393
|
-
this.canvasService.canvas.bringObjectToFront(layer);
|
|
4394
|
-
const userLayer = this.canvasService.getLayer("user");
|
|
4395
|
-
if (userLayer) {
|
|
4396
|
-
const userIndex = this.canvasService.canvas.getObjects().indexOf(userLayer);
|
|
4397
|
-
this.canvasService.canvas.moveObjectTo(layer, userIndex + 1);
|
|
4398
|
-
}
|
|
4399
|
-
}
|
|
4400
|
-
destroyLayer() {
|
|
4401
|
-
if (!this.canvasService) return;
|
|
4402
|
-
const layer = this.getLayer();
|
|
4403
|
-
if (layer) {
|
|
4404
|
-
this.canvasService.canvas.remove(layer);
|
|
4405
|
-
}
|
|
4406
|
-
}
|
|
4407
4795
|
createHatchPattern(color = "rgba(0, 0, 0, 0.3)") {
|
|
4408
4796
|
if (typeof document === "undefined") {
|
|
4409
4797
|
return void 0;
|
|
@@ -4432,7 +4820,6 @@ var DielineTool = class {
|
|
|
4432
4820
|
}
|
|
4433
4821
|
syncSizeState(configService) {
|
|
4434
4822
|
const sizeState = readSizeState(configService);
|
|
4435
|
-
this.state.displayUnit = sizeState.unit;
|
|
4436
4823
|
this.state.width = sizeState.actualWidthMm;
|
|
4437
4824
|
this.state.height = sizeState.actualHeightMm;
|
|
4438
4825
|
this.state.padding = sizeState.viewPadding;
|
|
@@ -4446,20 +4833,26 @@ var DielineTool = class {
|
|
|
4446
4833
|
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
4447
4834
|
}).forEach((obj) => canvas.bringObjectToFront(obj));
|
|
4448
4835
|
}
|
|
4449
|
-
|
|
4836
|
+
ensureLayerStacking() {
|
|
4450
4837
|
if (!this.canvasService) return;
|
|
4451
|
-
const layer = this.getLayer();
|
|
4838
|
+
const layer = this.canvasService.getLayer(DIELINE_LAYER_ID);
|
|
4452
4839
|
if (!layer) return;
|
|
4453
|
-
const
|
|
4454
|
-
if (
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4840
|
+
const userLayer = this.canvasService.getLayer("user");
|
|
4841
|
+
if (userLayer) {
|
|
4842
|
+
const layerIndex = this.canvasService.canvas.getObjects().indexOf(layer);
|
|
4843
|
+
const userIndex = this.canvasService.canvas.getObjects().indexOf(userLayer);
|
|
4844
|
+
if (layerIndex < userIndex) {
|
|
4845
|
+
this.canvasService.canvas.moveObjectTo(layer, userIndex + 1);
|
|
4846
|
+
}
|
|
4847
|
+
return;
|
|
4848
|
+
}
|
|
4849
|
+
this.canvasService.canvas.bringObjectToFront(layer);
|
|
4850
|
+
}
|
|
4851
|
+
buildDielineSpecs(sceneLayout) {
|
|
4852
|
+
var _a, _b;
|
|
4461
4853
|
const {
|
|
4462
4854
|
shape,
|
|
4855
|
+
shapeStyle,
|
|
4463
4856
|
radius,
|
|
4464
4857
|
mainLine,
|
|
4465
4858
|
offsetLine,
|
|
@@ -4468,8 +4861,8 @@ var DielineTool = class {
|
|
|
4468
4861
|
showBleedLines,
|
|
4469
4862
|
features
|
|
4470
4863
|
} = this.state;
|
|
4471
|
-
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
4472
|
-
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
4864
|
+
const canvasW = sceneLayout.canvasWidth || ((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 800;
|
|
4865
|
+
const canvasH = sceneLayout.canvasHeight || ((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 600;
|
|
4473
4866
|
const scale = sceneLayout.scale;
|
|
4474
4867
|
const cx = sceneLayout.trimRect.centerX;
|
|
4475
4868
|
const cy = sceneLayout.trimRect.centerY;
|
|
@@ -4480,7 +4873,6 @@ var DielineTool = class {
|
|
|
4480
4873
|
const cutH = sceneLayout.cutRect.height;
|
|
4481
4874
|
const visualOffset = (cutW - visualWidth) / 2;
|
|
4482
4875
|
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
4483
|
-
layer.remove(...layer.getObjects());
|
|
4484
4876
|
const absoluteFeatures = (features || []).map((f) => ({
|
|
4485
4877
|
...f,
|
|
4486
4878
|
x: f.x,
|
|
@@ -4500,21 +4892,30 @@ var DielineTool = class {
|
|
|
4500
4892
|
x: cx,
|
|
4501
4893
|
y: cy,
|
|
4502
4894
|
features: cutFeatures,
|
|
4895
|
+
shapeStyle,
|
|
4503
4896
|
pathData: this.state.pathData,
|
|
4504
4897
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4505
4898
|
customSourceHeightPx: this.state.customSourceHeightPx
|
|
4506
4899
|
});
|
|
4507
|
-
const
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4900
|
+
const specs = [
|
|
4901
|
+
{
|
|
4902
|
+
id: "dieline.mask",
|
|
4903
|
+
type: "path",
|
|
4904
|
+
space: "screen",
|
|
4905
|
+
data: { id: "dieline.mask", type: "dieline" },
|
|
4906
|
+
props: {
|
|
4907
|
+
pathData: maskPathData,
|
|
4908
|
+
fill: outsideColor,
|
|
4909
|
+
stroke: null,
|
|
4910
|
+
selectable: false,
|
|
4911
|
+
evented: false,
|
|
4912
|
+
originX: "left",
|
|
4913
|
+
originY: "top",
|
|
4914
|
+
left: 0,
|
|
4915
|
+
top: 0
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4918
|
+
];
|
|
4518
4919
|
if (insideColor && insideColor !== "transparent" && insideColor !== "rgba(0,0,0,0)") {
|
|
4519
4920
|
const productPathData = generateDielinePath({
|
|
4520
4921
|
shape,
|
|
@@ -4524,21 +4925,28 @@ var DielineTool = class {
|
|
|
4524
4925
|
x: cx,
|
|
4525
4926
|
y: cy,
|
|
4526
4927
|
features: cutFeatures,
|
|
4928
|
+
shapeStyle,
|
|
4527
4929
|
pathData: this.state.pathData,
|
|
4528
4930
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4529
4931
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4530
4932
|
canvasWidth: canvasW,
|
|
4531
4933
|
canvasHeight: canvasH
|
|
4532
4934
|
});
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4935
|
+
specs.push({
|
|
4936
|
+
id: "dieline.inside",
|
|
4937
|
+
type: "path",
|
|
4938
|
+
space: "screen",
|
|
4939
|
+
data: { id: "dieline.inside", type: "dieline" },
|
|
4940
|
+
props: {
|
|
4941
|
+
pathData: productPathData,
|
|
4942
|
+
fill: insideColor,
|
|
4943
|
+
stroke: null,
|
|
4944
|
+
selectable: false,
|
|
4945
|
+
evented: false,
|
|
4946
|
+
originX: "left",
|
|
4947
|
+
originY: "top"
|
|
4948
|
+
}
|
|
4540
4949
|
});
|
|
4541
|
-
layer.add(insideObj);
|
|
4542
4950
|
}
|
|
4543
4951
|
if (Math.abs(visualOffset) > 1e-4) {
|
|
4544
4952
|
const bleedPathData = generateBleedZonePath(
|
|
@@ -4550,6 +4958,7 @@ var DielineTool = class {
|
|
|
4550
4958
|
x: cx,
|
|
4551
4959
|
y: cy,
|
|
4552
4960
|
features: cutFeatures,
|
|
4961
|
+
shapeStyle,
|
|
4553
4962
|
pathData: this.state.pathData,
|
|
4554
4963
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4555
4964
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
@@ -4564,6 +4973,7 @@ var DielineTool = class {
|
|
|
4564
4973
|
x: cx,
|
|
4565
4974
|
y: cy,
|
|
4566
4975
|
features: cutFeatures,
|
|
4976
|
+
shapeStyle,
|
|
4567
4977
|
pathData: this.state.pathData,
|
|
4568
4978
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4569
4979
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
@@ -4575,16 +4985,22 @@ var DielineTool = class {
|
|
|
4575
4985
|
if (showBleedLines !== false) {
|
|
4576
4986
|
const pattern = this.createHatchPattern(mainLine.color);
|
|
4577
4987
|
if (pattern) {
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4988
|
+
specs.push({
|
|
4989
|
+
id: "dieline.bleed-zone",
|
|
4990
|
+
type: "path",
|
|
4991
|
+
space: "screen",
|
|
4992
|
+
data: { id: "dieline.bleed-zone", type: "dieline" },
|
|
4993
|
+
props: {
|
|
4994
|
+
pathData: bleedPathData,
|
|
4995
|
+
fill: pattern,
|
|
4996
|
+
stroke: null,
|
|
4997
|
+
selectable: false,
|
|
4998
|
+
evented: false,
|
|
4999
|
+
objectCaching: false,
|
|
5000
|
+
originX: "left",
|
|
5001
|
+
originY: "top"
|
|
5002
|
+
}
|
|
4586
5003
|
});
|
|
4587
|
-
layer.add(bleedObj);
|
|
4588
5004
|
}
|
|
4589
5005
|
}
|
|
4590
5006
|
const offsetPathData = generateDielinePath({
|
|
@@ -4595,23 +5011,30 @@ var DielineTool = class {
|
|
|
4595
5011
|
x: cx,
|
|
4596
5012
|
y: cy,
|
|
4597
5013
|
features: cutFeatures,
|
|
5014
|
+
shapeStyle,
|
|
4598
5015
|
pathData: this.state.pathData,
|
|
4599
5016
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4600
5017
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4601
5018
|
canvasWidth: canvasW,
|
|
4602
5019
|
canvasHeight: canvasH
|
|
4603
5020
|
});
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
5021
|
+
specs.push({
|
|
5022
|
+
id: "dieline.offset-border",
|
|
5023
|
+
type: "path",
|
|
5024
|
+
space: "screen",
|
|
5025
|
+
data: { id: "dieline.offset-border", type: "dieline" },
|
|
5026
|
+
props: {
|
|
5027
|
+
pathData: offsetPathData,
|
|
5028
|
+
fill: null,
|
|
5029
|
+
stroke: offsetLine.style === "hidden" ? null : offsetLine.color,
|
|
5030
|
+
strokeWidth: offsetLine.width,
|
|
5031
|
+
strokeDashArray: offsetLine.style === "dashed" ? [offsetLine.dashLength, offsetLine.dashLength] : void 0,
|
|
5032
|
+
selectable: false,
|
|
5033
|
+
evented: false,
|
|
5034
|
+
originX: "left",
|
|
5035
|
+
originY: "top"
|
|
5036
|
+
}
|
|
4613
5037
|
});
|
|
4614
|
-
layer.add(offsetBorderObj);
|
|
4615
5038
|
}
|
|
4616
5039
|
const borderPathData = generateDielinePath({
|
|
4617
5040
|
shape,
|
|
@@ -4621,39 +5044,59 @@ var DielineTool = class {
|
|
|
4621
5044
|
x: cx,
|
|
4622
5045
|
y: cy,
|
|
4623
5046
|
features: absoluteFeatures,
|
|
5047
|
+
shapeStyle,
|
|
4624
5048
|
pathData: this.state.pathData,
|
|
4625
5049
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4626
5050
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
4627
5051
|
canvasWidth: canvasW,
|
|
4628
5052
|
canvasHeight: canvasH
|
|
4629
5053
|
});
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
if (layerIndex < userIndex) {
|
|
4646
|
-
this.canvasService.canvas.moveObjectTo(layer, userIndex + 1);
|
|
5054
|
+
specs.push({
|
|
5055
|
+
id: "dieline.border",
|
|
5056
|
+
type: "path",
|
|
5057
|
+
space: "screen",
|
|
5058
|
+
data: { id: "dieline.border", type: "dieline" },
|
|
5059
|
+
props: {
|
|
5060
|
+
pathData: borderPathData,
|
|
5061
|
+
fill: "transparent",
|
|
5062
|
+
stroke: mainLine.style === "hidden" ? null : mainLine.color,
|
|
5063
|
+
strokeWidth: mainLine.width,
|
|
5064
|
+
strokeDashArray: mainLine.style === "dashed" ? [mainLine.dashLength, mainLine.dashLength] : void 0,
|
|
5065
|
+
selectable: false,
|
|
5066
|
+
evented: false,
|
|
5067
|
+
originX: "left",
|
|
5068
|
+
originY: "top"
|
|
4647
5069
|
}
|
|
4648
|
-
}
|
|
4649
|
-
|
|
5070
|
+
});
|
|
5071
|
+
return specs;
|
|
5072
|
+
}
|
|
5073
|
+
updateDieline(_emitEvent = true) {
|
|
5074
|
+
void this.updateDielineAsync();
|
|
5075
|
+
}
|
|
5076
|
+
async updateDielineAsync() {
|
|
5077
|
+
if (!this.canvasService) return;
|
|
5078
|
+
const configService = this.getConfigService();
|
|
5079
|
+
if (!configService) return;
|
|
5080
|
+
const seq = ++this.renderSeq;
|
|
5081
|
+
this.syncSizeState(configService);
|
|
5082
|
+
const sceneLayout = computeSceneLayout(
|
|
5083
|
+
this.canvasService,
|
|
5084
|
+
readSizeState(configService)
|
|
5085
|
+
);
|
|
5086
|
+
if (!sceneLayout) {
|
|
5087
|
+
if (seq !== this.renderSeq) return;
|
|
5088
|
+
this.specs = [];
|
|
5089
|
+
await this.canvasService.flushRenderFromProducers();
|
|
5090
|
+
return;
|
|
4650
5091
|
}
|
|
5092
|
+
const nextSpecs = this.buildDielineSpecs(sceneLayout);
|
|
5093
|
+
if (seq !== this.renderSeq) return;
|
|
5094
|
+
this.specs = nextSpecs;
|
|
5095
|
+
await this.canvasService.flushRenderFromProducers();
|
|
5096
|
+
if (seq !== this.renderSeq) return;
|
|
5097
|
+
this.ensureLayerStacking();
|
|
4651
5098
|
this.bringFeatureMarkersToFront();
|
|
4652
|
-
|
|
4653
|
-
if (rulerLayer) {
|
|
4654
|
-
this.canvasService.canvas.bringObjectToFront(rulerLayer);
|
|
4655
|
-
}
|
|
4656
|
-
layer.dirty = true;
|
|
5099
|
+
this.canvasService.bringLayerToFront("ruler-overlay");
|
|
4657
5100
|
this.canvasService.requestRenderAll();
|
|
4658
5101
|
}
|
|
4659
5102
|
getGeometry() {
|
|
@@ -4701,7 +5144,7 @@ var DielineTool = class {
|
|
|
4701
5144
|
);
|
|
4702
5145
|
return null;
|
|
4703
5146
|
}
|
|
4704
|
-
const { shape, radius, features, pathData } = this.state;
|
|
5147
|
+
const { shape, shapeStyle, radius, features, pathData } = this.state;
|
|
4705
5148
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
4706
5149
|
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
4707
5150
|
const scale = sceneLayout.scale;
|
|
@@ -4729,6 +5172,7 @@ var DielineTool = class {
|
|
|
4729
5172
|
x: cx,
|
|
4730
5173
|
y: cy,
|
|
4731
5174
|
features: cutFeatures,
|
|
5175
|
+
shapeStyle,
|
|
4732
5176
|
pathData,
|
|
4733
5177
|
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
4734
5178
|
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
@@ -4841,7 +5285,6 @@ var DielineTool = class {
|
|
|
4841
5285
|
|
|
4842
5286
|
// src/extensions/feature.ts
|
|
4843
5287
|
var import_core5 = require("@pooder/core");
|
|
4844
|
-
var import_fabric4 = require("fabric");
|
|
4845
5288
|
|
|
4846
5289
|
// src/extensions/constraints.ts
|
|
4847
5290
|
var ConstraintRegistry = class {
|
|
@@ -5041,6 +5484,10 @@ function completeFeaturesStrict(features, context, update) {
|
|
|
5041
5484
|
}
|
|
5042
5485
|
|
|
5043
5486
|
// src/extensions/feature.ts
|
|
5487
|
+
var FEATURE_OVERLAY_LAYER_ID = "feature-overlay";
|
|
5488
|
+
var FEATURE_STROKE_WIDTH = 2;
|
|
5489
|
+
var DEFAULT_RECT_SIZE = 10;
|
|
5490
|
+
var DEFAULT_CIRCLE_RADIUS = 5;
|
|
5044
5491
|
var FeatureTool = class {
|
|
5045
5492
|
constructor(options) {
|
|
5046
5493
|
this.id = "pooder.kit.feature";
|
|
@@ -5053,6 +5500,8 @@ var FeatureTool = class {
|
|
|
5053
5500
|
this.isFeatureSessionActive = false;
|
|
5054
5501
|
this.sessionOriginalFeatures = null;
|
|
5055
5502
|
this.hasWorkingChanges = false;
|
|
5503
|
+
this.specs = [];
|
|
5504
|
+
this.renderSeq = 0;
|
|
5056
5505
|
this.handleMoving = null;
|
|
5057
5506
|
this.handleModified = null;
|
|
5058
5507
|
this.handleSceneGeometryChange = null;
|
|
@@ -5069,12 +5518,23 @@ var FeatureTool = class {
|
|
|
5069
5518
|
}
|
|
5070
5519
|
}
|
|
5071
5520
|
activate(context) {
|
|
5521
|
+
var _a;
|
|
5072
5522
|
this.context = context;
|
|
5073
5523
|
this.canvasService = context.services.get("CanvasService");
|
|
5074
5524
|
if (!this.canvasService) {
|
|
5075
5525
|
console.warn("CanvasService not found for FeatureTool");
|
|
5076
5526
|
return;
|
|
5077
5527
|
}
|
|
5528
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5529
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
5530
|
+
this.id,
|
|
5531
|
+
() => ({
|
|
5532
|
+
rootLayerSpecs: {
|
|
5533
|
+
[FEATURE_OVERLAY_LAYER_ID]: this.specs
|
|
5534
|
+
}
|
|
5535
|
+
}),
|
|
5536
|
+
{ priority: 350 }
|
|
5537
|
+
);
|
|
5078
5538
|
const configService = context.services.get(
|
|
5079
5539
|
"ConfigurationService"
|
|
5080
5540
|
);
|
|
@@ -5113,21 +5573,7 @@ var FeatureTool = class {
|
|
|
5113
5573
|
this.context = void 0;
|
|
5114
5574
|
}
|
|
5115
5575
|
updateVisibility() {
|
|
5116
|
-
|
|
5117
|
-
const canvas = this.canvasService.canvas;
|
|
5118
|
-
const markers = canvas.getObjects().filter((obj) => {
|
|
5119
|
-
var _a;
|
|
5120
|
-
return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
5121
|
-
});
|
|
5122
|
-
markers.forEach((marker) => {
|
|
5123
|
-
marker.set({
|
|
5124
|
-
visible: this.isToolActive,
|
|
5125
|
-
// Or just selectable: false if we want them visible but locked
|
|
5126
|
-
selectable: this.isToolActive,
|
|
5127
|
-
evented: this.isToolActive
|
|
5128
|
-
});
|
|
5129
|
-
});
|
|
5130
|
-
canvas.requestRenderAll();
|
|
5576
|
+
this.redraw();
|
|
5131
5577
|
}
|
|
5132
5578
|
contribute() {
|
|
5133
5579
|
return {
|
|
@@ -5359,8 +5805,7 @@ var FeatureTool = class {
|
|
|
5359
5805
|
if (!changed) return { ok: true };
|
|
5360
5806
|
this.setWorkingFeatures(next);
|
|
5361
5807
|
this.hasWorkingChanges = true;
|
|
5362
|
-
this.redraw();
|
|
5363
|
-
this.enforceConstraints();
|
|
5808
|
+
this.redraw({ enforceConstraints: true });
|
|
5364
5809
|
this.emitWorkingChange();
|
|
5365
5810
|
return { ok: true };
|
|
5366
5811
|
}
|
|
@@ -5408,12 +5853,10 @@ var FeatureTool = class {
|
|
|
5408
5853
|
shape: "rect",
|
|
5409
5854
|
x: 0.5,
|
|
5410
5855
|
y: 0,
|
|
5411
|
-
// Top edge
|
|
5412
5856
|
width: 10,
|
|
5413
5857
|
height: 10,
|
|
5414
5858
|
rotation: 0,
|
|
5415
5859
|
renderBehavior: "edge",
|
|
5416
|
-
// Default constraint: path (snap to edge)
|
|
5417
5860
|
constraints: [{ type: "path" }]
|
|
5418
5861
|
};
|
|
5419
5862
|
this.setWorkingFeatures([...this.workingFeatures || [], newFeature]);
|
|
@@ -5456,7 +5899,7 @@ var FeatureTool = class {
|
|
|
5456
5899
|
this.emitWorkingChange();
|
|
5457
5900
|
return true;
|
|
5458
5901
|
}
|
|
5459
|
-
getGeometryForFeature(geometry,
|
|
5902
|
+
getGeometryForFeature(geometry, _feature) {
|
|
5460
5903
|
return geometry;
|
|
5461
5904
|
}
|
|
5462
5905
|
setup() {
|
|
@@ -5465,8 +5908,7 @@ var FeatureTool = class {
|
|
|
5465
5908
|
if (!this.handleSceneGeometryChange) {
|
|
5466
5909
|
this.handleSceneGeometryChange = (geometry) => {
|
|
5467
5910
|
this.currentGeometry = geometry;
|
|
5468
|
-
this.redraw();
|
|
5469
|
-
this.enforceConstraints();
|
|
5911
|
+
this.redraw({ enforceConstraints: true });
|
|
5470
5912
|
};
|
|
5471
5913
|
this.context.eventBus.on(
|
|
5472
5914
|
"scene:geometry:change",
|
|
@@ -5489,76 +5931,34 @@ var FeatureTool = class {
|
|
|
5489
5931
|
}
|
|
5490
5932
|
if (!this.handleMoving) {
|
|
5491
5933
|
this.handleMoving = (e) => {
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
} else {
|
|
5503
|
-
const index = (_d = target.data) == null ? void 0 : _d.index;
|
|
5504
|
-
if (index !== void 0) {
|
|
5505
|
-
feature = this.workingFeatures[index];
|
|
5506
|
-
}
|
|
5507
|
-
}
|
|
5508
|
-
const geometry = this.getGeometryForFeature(
|
|
5509
|
-
this.currentGeometry,
|
|
5934
|
+
const target = this.getDraggableMarkerTarget(e == null ? void 0 : e.target);
|
|
5935
|
+
if (!target || !this.currentGeometry) return;
|
|
5936
|
+
const feature = this.getFeatureForMarker(target);
|
|
5937
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5938
|
+
const snapped = this.constrainPosition(
|
|
5939
|
+
{
|
|
5940
|
+
x: Number(target.left || 0),
|
|
5941
|
+
y: Number(target.top || 0)
|
|
5942
|
+
},
|
|
5943
|
+
geometry,
|
|
5510
5944
|
feature
|
|
5511
5945
|
);
|
|
5512
|
-
const p = new import_fabric4.Point(target.left, target.top);
|
|
5513
|
-
const markerStrokeWidth = (target.strokeWidth || 2) * (target.scaleX || 1);
|
|
5514
|
-
const minDim = Math.min(
|
|
5515
|
-
target.getScaledWidth(),
|
|
5516
|
-
target.getScaledHeight()
|
|
5517
|
-
);
|
|
5518
|
-
const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
|
|
5519
|
-
const snapped = this.constrainPosition(p, geometry, limit, feature);
|
|
5520
5946
|
target.set({
|
|
5521
5947
|
left: snapped.x,
|
|
5522
5948
|
top: snapped.y
|
|
5523
5949
|
});
|
|
5950
|
+
target.setCoords();
|
|
5951
|
+
this.syncMarkerVisualsByTarget(target, snapped);
|
|
5524
5952
|
};
|
|
5525
5953
|
canvas.on("object:moving", this.handleMoving);
|
|
5526
5954
|
}
|
|
5527
5955
|
if (!this.handleModified) {
|
|
5528
5956
|
this.handleModified = (e) => {
|
|
5529
|
-
var _a
|
|
5530
|
-
const target = e.target;
|
|
5531
|
-
if (!target
|
|
5532
|
-
if ((
|
|
5533
|
-
|
|
5534
|
-
const indices = (_c = groupObj.data) == null ? void 0 : _c.indices;
|
|
5535
|
-
if (!indices) return;
|
|
5536
|
-
const groupCenter = new import_fabric4.Point(groupObj.left, groupObj.top);
|
|
5537
|
-
const newFeatures = [...this.workingFeatures];
|
|
5538
|
-
const { x, y } = this.currentGeometry;
|
|
5539
|
-
groupObj.getObjects().forEach((child, i) => {
|
|
5540
|
-
const originalIndex = indices[i];
|
|
5541
|
-
const feature = this.workingFeatures[originalIndex];
|
|
5542
|
-
const geometry = this.getGeometryForFeature(
|
|
5543
|
-
this.currentGeometry,
|
|
5544
|
-
feature
|
|
5545
|
-
);
|
|
5546
|
-
const { width, height } = geometry;
|
|
5547
|
-
const layoutLeft = x - width / 2;
|
|
5548
|
-
const layoutTop = y - height / 2;
|
|
5549
|
-
const absX = groupCenter.x + (child.left || 0);
|
|
5550
|
-
const absY = groupCenter.y + (child.top || 0);
|
|
5551
|
-
const normalizedX = width > 0 ? (absX - layoutLeft) / width : 0.5;
|
|
5552
|
-
const normalizedY = height > 0 ? (absY - layoutTop) / height : 0.5;
|
|
5553
|
-
newFeatures[originalIndex] = {
|
|
5554
|
-
...newFeatures[originalIndex],
|
|
5555
|
-
x: normalizedX,
|
|
5556
|
-
y: normalizedY
|
|
5557
|
-
};
|
|
5558
|
-
});
|
|
5559
|
-
this.setWorkingFeatures(newFeatures);
|
|
5560
|
-
this.hasWorkingChanges = true;
|
|
5561
|
-
this.emitWorkingChange();
|
|
5957
|
+
var _a;
|
|
5958
|
+
const target = this.getDraggableMarkerTarget(e == null ? void 0 : e.target);
|
|
5959
|
+
if (!target) return;
|
|
5960
|
+
if ((_a = target.data) == null ? void 0 : _a.isGroup) {
|
|
5961
|
+
this.syncGroupFromCanvas(target);
|
|
5562
5962
|
} else {
|
|
5563
5963
|
this.syncFeatureFromCanvas(target);
|
|
5564
5964
|
}
|
|
@@ -5567,6 +5967,7 @@ var FeatureTool = class {
|
|
|
5567
5967
|
}
|
|
5568
5968
|
}
|
|
5569
5969
|
teardown() {
|
|
5970
|
+
var _a;
|
|
5570
5971
|
if (!this.canvasService) return;
|
|
5571
5972
|
const canvas = this.canvasService.canvas;
|
|
5572
5973
|
if (this.handleMoving) {
|
|
@@ -5584,14 +5985,25 @@ var FeatureTool = class {
|
|
|
5584
5985
|
);
|
|
5585
5986
|
this.handleSceneGeometryChange = null;
|
|
5586
5987
|
}
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5988
|
+
this.renderSeq += 1;
|
|
5989
|
+
this.specs = [];
|
|
5990
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
5991
|
+
this.renderProducerDisposable = void 0;
|
|
5992
|
+
void this.canvasService.flushRenderFromProducers();
|
|
5993
|
+
}
|
|
5994
|
+
getDraggableMarkerTarget(target) {
|
|
5995
|
+
var _a, _b;
|
|
5996
|
+
if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "feature-marker") return null;
|
|
5997
|
+
if (((_b = target.data) == null ? void 0 : _b.markerRole) !== "handle") return null;
|
|
5998
|
+
return target;
|
|
5999
|
+
}
|
|
6000
|
+
getFeatureForMarker(target) {
|
|
6001
|
+
const data = (target == null ? void 0 : target.data) || {};
|
|
6002
|
+
const index = data.isGroup ? this.toFeatureIndex(data.anchorIndex) : this.toFeatureIndex(data.index);
|
|
6003
|
+
if (index === null) return void 0;
|
|
6004
|
+
return this.workingFeatures[index];
|
|
5593
6005
|
}
|
|
5594
|
-
constrainPosition(p, geometry,
|
|
6006
|
+
constrainPosition(p, geometry, feature) {
|
|
5595
6007
|
var _a;
|
|
5596
6008
|
if (!feature) {
|
|
5597
6009
|
return { x: p.x, y: p.y };
|
|
@@ -5622,231 +6034,374 @@ var FeatureTool = class {
|
|
|
5622
6034
|
y: minY + constrained.y * geometry.height
|
|
5623
6035
|
};
|
|
5624
6036
|
}
|
|
6037
|
+
toNormalizedPoint(point, geometry) {
|
|
6038
|
+
const left = geometry.x - geometry.width / 2;
|
|
6039
|
+
const top = geometry.y - geometry.height / 2;
|
|
6040
|
+
return {
|
|
6041
|
+
x: geometry.width > 0 ? (point.x - left) / geometry.width : 0.5,
|
|
6042
|
+
y: geometry.height > 0 ? (point.y - top) / geometry.height : 0.5
|
|
6043
|
+
};
|
|
6044
|
+
}
|
|
5625
6045
|
syncFeatureFromCanvas(target) {
|
|
5626
6046
|
var _a;
|
|
5627
|
-
if (!this.currentGeometry
|
|
5628
|
-
const index = (_a = target.data) == null ? void 0 : _a.index;
|
|
5629
|
-
if (index ===
|
|
5630
|
-
return;
|
|
6047
|
+
if (!this.currentGeometry) return;
|
|
6048
|
+
const index = this.toFeatureIndex((_a = target.data) == null ? void 0 : _a.index);
|
|
6049
|
+
if (index === null || index >= this.workingFeatures.length) return;
|
|
5631
6050
|
const feature = this.workingFeatures[index];
|
|
5632
6051
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5633
|
-
const
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
6052
|
+
const normalized = this.toNormalizedPoint(
|
|
6053
|
+
{
|
|
6054
|
+
x: Number(target.left || 0),
|
|
6055
|
+
y: Number(target.top || 0)
|
|
6056
|
+
},
|
|
6057
|
+
geometry
|
|
6058
|
+
);
|
|
5638
6059
|
const updatedFeature = {
|
|
5639
6060
|
...feature,
|
|
5640
|
-
x:
|
|
5641
|
-
y:
|
|
5642
|
-
// Could also update rotation if we allowed rotating markers
|
|
6061
|
+
x: normalized.x,
|
|
6062
|
+
y: normalized.y
|
|
5643
6063
|
};
|
|
5644
|
-
const
|
|
5645
|
-
|
|
5646
|
-
this.setWorkingFeatures(
|
|
6064
|
+
const next = [...this.workingFeatures];
|
|
6065
|
+
next[index] = updatedFeature;
|
|
6066
|
+
this.setWorkingFeatures(next);
|
|
5647
6067
|
this.hasWorkingChanges = true;
|
|
5648
6068
|
this.emitWorkingChange();
|
|
5649
6069
|
}
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
const
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
6070
|
+
syncGroupFromCanvas(target) {
|
|
6071
|
+
var _a, _b;
|
|
6072
|
+
if (!this.currentGeometry) return;
|
|
6073
|
+
const indices = this.readGroupIndices((_a = target.data) == null ? void 0 : _a.indices);
|
|
6074
|
+
if (indices.length === 0) return;
|
|
6075
|
+
const offsets = this.readGroupMemberOffsets((_b = target.data) == null ? void 0 : _b.memberOffsets, indices);
|
|
6076
|
+
const anchorCenter = {
|
|
6077
|
+
x: Number(target.left || 0),
|
|
6078
|
+
y: Number(target.top || 0)
|
|
6079
|
+
};
|
|
6080
|
+
const next = [...this.workingFeatures];
|
|
6081
|
+
let changed = false;
|
|
6082
|
+
offsets.forEach((entry) => {
|
|
6083
|
+
const index = entry.index;
|
|
6084
|
+
if (index < 0 || index >= next.length) return;
|
|
6085
|
+
const feature = next[index];
|
|
6086
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
6087
|
+
const normalized = this.toNormalizedPoint(
|
|
6088
|
+
{
|
|
6089
|
+
x: anchorCenter.x + entry.dx,
|
|
6090
|
+
y: anchorCenter.y + entry.dy
|
|
6091
|
+
},
|
|
6092
|
+
geometry
|
|
6093
|
+
);
|
|
6094
|
+
if (feature.x !== normalized.x || feature.y !== normalized.y) {
|
|
6095
|
+
next[index] = {
|
|
6096
|
+
...feature,
|
|
6097
|
+
x: normalized.x,
|
|
6098
|
+
y: normalized.y
|
|
6099
|
+
};
|
|
6100
|
+
changed = true;
|
|
6101
|
+
}
|
|
5657
6102
|
});
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
6103
|
+
if (!changed) return;
|
|
6104
|
+
this.setWorkingFeatures(next);
|
|
6105
|
+
this.hasWorkingChanges = true;
|
|
6106
|
+
this.emitWorkingChange();
|
|
6107
|
+
}
|
|
6108
|
+
redraw(options = {}) {
|
|
6109
|
+
void this.redrawAsync(options);
|
|
6110
|
+
}
|
|
6111
|
+
async redrawAsync(options = {}) {
|
|
6112
|
+
if (!this.canvasService) return;
|
|
6113
|
+
const seq = ++this.renderSeq;
|
|
6114
|
+
this.specs = this.buildFeatureSpecs();
|
|
6115
|
+
if (seq !== this.renderSeq) return;
|
|
6116
|
+
await this.canvasService.flushRenderFromProducers();
|
|
6117
|
+
if (seq !== this.renderSeq) return;
|
|
6118
|
+
this.syncOverlayOrder();
|
|
6119
|
+
if (options.enforceConstraints) {
|
|
6120
|
+
this.enforceConstraints();
|
|
5662
6121
|
}
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
6122
|
+
}
|
|
6123
|
+
syncOverlayOrder() {
|
|
6124
|
+
if (!this.canvasService) return;
|
|
6125
|
+
this.canvasService.bringLayerToFront(FEATURE_OVERLAY_LAYER_ID);
|
|
6126
|
+
this.canvasService.bringLayerToFront("ruler-overlay");
|
|
6127
|
+
}
|
|
6128
|
+
buildFeatureSpecs() {
|
|
6129
|
+
if (!this.currentGeometry || this.workingFeatures.length === 0) {
|
|
6130
|
+
return [];
|
|
6131
|
+
}
|
|
6132
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5666
6133
|
const singles = [];
|
|
5667
|
-
this.workingFeatures.forEach((
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
6134
|
+
this.workingFeatures.forEach((feature, index) => {
|
|
6135
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
6136
|
+
const position = resolveFeaturePosition(feature, geometry);
|
|
6137
|
+
const scale = geometry.scale || 1;
|
|
6138
|
+
const marker = {
|
|
6139
|
+
feature,
|
|
6140
|
+
index,
|
|
6141
|
+
position,
|
|
6142
|
+
geometry,
|
|
6143
|
+
scale
|
|
6144
|
+
};
|
|
6145
|
+
if (feature.groupId) {
|
|
6146
|
+
const list = groups.get(feature.groupId) || [];
|
|
6147
|
+
list.push(marker);
|
|
6148
|
+
groups.set(feature.groupId, list);
|
|
6149
|
+
return;
|
|
5673
6150
|
}
|
|
6151
|
+
singles.push(marker);
|
|
6152
|
+
});
|
|
6153
|
+
const specs = [];
|
|
6154
|
+
singles.forEach((marker) => {
|
|
6155
|
+
this.appendMarkerSpecs(specs, marker, {
|
|
6156
|
+
markerRole: "handle",
|
|
6157
|
+
isGroup: false
|
|
6158
|
+
});
|
|
6159
|
+
});
|
|
6160
|
+
groups.forEach((members, groupId) => {
|
|
6161
|
+
if (!members.length) return;
|
|
6162
|
+
const anchor = members[0];
|
|
6163
|
+
const memberOffsets = members.map((member) => ({
|
|
6164
|
+
index: member.index,
|
|
6165
|
+
dx: member.position.x - anchor.position.x,
|
|
6166
|
+
dy: member.position.y - anchor.position.y
|
|
6167
|
+
}));
|
|
6168
|
+
const indices = members.map((member) => member.index);
|
|
6169
|
+
members.filter((member) => member.index !== anchor.index).forEach((member) => {
|
|
6170
|
+
this.appendMarkerSpecs(specs, member, {
|
|
6171
|
+
markerRole: "member",
|
|
6172
|
+
isGroup: false,
|
|
6173
|
+
groupId
|
|
6174
|
+
});
|
|
6175
|
+
});
|
|
6176
|
+
this.appendMarkerSpecs(specs, anchor, {
|
|
6177
|
+
markerRole: "handle",
|
|
6178
|
+
isGroup: true,
|
|
6179
|
+
groupId,
|
|
6180
|
+
indices,
|
|
6181
|
+
anchorIndex: anchor.index,
|
|
6182
|
+
memberOffsets
|
|
6183
|
+
});
|
|
5674
6184
|
});
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
6185
|
+
return specs;
|
|
6186
|
+
}
|
|
6187
|
+
appendMarkerSpecs(specs, marker, options) {
|
|
6188
|
+
var _a, _b, _c, _d, _e;
|
|
6189
|
+
const { feature, index, position, scale, geometry } = marker;
|
|
6190
|
+
const baseRadius = feature.shape === "circle" ? (_a = feature.radius) != null ? _a : DEFAULT_CIRCLE_RADIUS : (_b = feature.radius) != null ? _b : 0;
|
|
6191
|
+
const baseWidth = feature.shape === "circle" ? baseRadius * 2 : (_c = feature.width) != null ? _c : DEFAULT_RECT_SIZE;
|
|
6192
|
+
const baseHeight = feature.shape === "circle" ? baseRadius * 2 : (_d = feature.height) != null ? _d : DEFAULT_RECT_SIZE;
|
|
6193
|
+
const visualWidth = baseWidth * scale;
|
|
6194
|
+
const visualHeight = baseHeight * scale;
|
|
6195
|
+
const visualRadius = baseRadius * scale;
|
|
6196
|
+
const color = feature.color || (feature.operation === "add" ? "#00FF00" : "#FF0000");
|
|
6197
|
+
const strokeDash = feature.strokeDash || (feature.operation === "subtract" ? [4, 4] : void 0);
|
|
6198
|
+
const interactive = options.markerRole === "handle";
|
|
6199
|
+
const baseData = this.buildMarkerData(marker, options);
|
|
6200
|
+
const commonProps = {
|
|
6201
|
+
visible: this.isToolActive,
|
|
6202
|
+
selectable: interactive && this.isToolActive,
|
|
6203
|
+
evented: interactive && this.isToolActive,
|
|
6204
|
+
hasControls: false,
|
|
6205
|
+
hasBorders: false,
|
|
6206
|
+
hoverCursor: interactive ? "move" : "default",
|
|
6207
|
+
lockRotation: true,
|
|
6208
|
+
lockScalingX: true,
|
|
6209
|
+
lockScalingY: true,
|
|
6210
|
+
fill: "transparent",
|
|
6211
|
+
stroke: color,
|
|
6212
|
+
strokeWidth: FEATURE_STROKE_WIDTH,
|
|
6213
|
+
strokeDashArray: strokeDash,
|
|
6214
|
+
originX: "center",
|
|
6215
|
+
originY: "center",
|
|
6216
|
+
left: position.x,
|
|
6217
|
+
top: position.y,
|
|
6218
|
+
angle: feature.rotation || 0
|
|
6219
|
+
};
|
|
6220
|
+
const markerId = this.markerId(index);
|
|
6221
|
+
if (feature.shape === "rect") {
|
|
6222
|
+
specs.push({
|
|
6223
|
+
id: markerId,
|
|
6224
|
+
type: "rect",
|
|
6225
|
+
space: "screen",
|
|
6226
|
+
data: baseData,
|
|
6227
|
+
props: {
|
|
6228
|
+
...commonProps,
|
|
5685
6229
|
width: visualWidth,
|
|
5686
6230
|
height: visualHeight,
|
|
5687
6231
|
rx: visualRadius,
|
|
5688
|
-
ry: visualRadius
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
shape.rotate(feature.rotation);
|
|
6232
|
+
ry: visualRadius
|
|
6233
|
+
}
|
|
6234
|
+
});
|
|
6235
|
+
} else {
|
|
6236
|
+
specs.push({
|
|
6237
|
+
id: markerId,
|
|
6238
|
+
type: "rect",
|
|
6239
|
+
space: "screen",
|
|
6240
|
+
data: baseData,
|
|
6241
|
+
props: {
|
|
6242
|
+
...commonProps,
|
|
6243
|
+
width: visualWidth,
|
|
6244
|
+
height: visualHeight,
|
|
6245
|
+
rx: visualRadius,
|
|
6246
|
+
ry: visualRadius
|
|
6247
|
+
}
|
|
6248
|
+
});
|
|
6249
|
+
}
|
|
6250
|
+
if (((_e = feature.bridge) == null ? void 0 : _e.type) === "vertical") {
|
|
6251
|
+
const featureTopY = position.y - visualHeight / 2;
|
|
6252
|
+
const dielineTopY = geometry.y - geometry.height / 2;
|
|
6253
|
+
const bridgeHeight = Math.max(0, featureTopY - dielineTopY);
|
|
6254
|
+
if (bridgeHeight <= 1e-3) {
|
|
6255
|
+
return;
|
|
5713
6256
|
}
|
|
5714
|
-
|
|
5715
|
-
|
|
6257
|
+
specs.push({
|
|
6258
|
+
id: this.bridgeIndicatorId(index),
|
|
6259
|
+
type: "rect",
|
|
6260
|
+
space: "screen",
|
|
6261
|
+
data: {
|
|
6262
|
+
...baseData,
|
|
6263
|
+
markerRole: "indicator",
|
|
6264
|
+
markerOffsetX: 0,
|
|
6265
|
+
markerOffsetY: -visualHeight / 2
|
|
6266
|
+
},
|
|
6267
|
+
props: {
|
|
6268
|
+
visible: this.isToolActive,
|
|
6269
|
+
selectable: false,
|
|
6270
|
+
evented: false,
|
|
5716
6271
|
width: visualWidth,
|
|
5717
|
-
height:
|
|
5718
|
-
// Arbitrary long length to show direction
|
|
6272
|
+
height: bridgeHeight,
|
|
5719
6273
|
fill: "transparent",
|
|
5720
6274
|
stroke: "#888",
|
|
5721
6275
|
strokeWidth: 1,
|
|
5722
6276
|
strokeDashArray: [2, 2],
|
|
5723
|
-
originX: "center",
|
|
5724
|
-
originY: "bottom",
|
|
5725
|
-
// Anchor at bottom so it extends up
|
|
5726
|
-
left: pos.x,
|
|
5727
|
-
top: pos.y - visualHeight / 2,
|
|
5728
|
-
// Start from top of feature
|
|
5729
6277
|
opacity: 0.5,
|
|
5730
|
-
selectable: false,
|
|
5731
|
-
evented: false
|
|
5732
|
-
});
|
|
5733
|
-
const group = new import_fabric4.Group([bridgeIndicator, shape], {
|
|
5734
6278
|
originX: "center",
|
|
5735
|
-
originY: "
|
|
5736
|
-
left:
|
|
5737
|
-
top:
|
|
5738
|
-
}
|
|
5739
|
-
return group;
|
|
5740
|
-
}
|
|
5741
|
-
return shape;
|
|
5742
|
-
};
|
|
5743
|
-
singles.forEach(({ feature, index }) => {
|
|
5744
|
-
const geometry2 = this.getGeometryForFeature(
|
|
5745
|
-
this.currentGeometry,
|
|
5746
|
-
feature
|
|
5747
|
-
);
|
|
5748
|
-
const pos = resolveFeaturePosition(feature, geometry2);
|
|
5749
|
-
const marker = createMarkerShape(feature, pos);
|
|
5750
|
-
marker.set({
|
|
5751
|
-
visible: this.isToolActive,
|
|
5752
|
-
selectable: this.isToolActive,
|
|
5753
|
-
evented: this.isToolActive,
|
|
5754
|
-
hasControls: false,
|
|
5755
|
-
hasBorders: false,
|
|
5756
|
-
hoverCursor: "move",
|
|
5757
|
-
lockRotation: true,
|
|
5758
|
-
lockScalingX: true,
|
|
5759
|
-
lockScalingY: true,
|
|
5760
|
-
data: { type: "feature-marker", index, isGroup: false }
|
|
5761
|
-
});
|
|
5762
|
-
canvas.add(marker);
|
|
5763
|
-
canvas.bringObjectToFront(marker);
|
|
5764
|
-
});
|
|
5765
|
-
Object.keys(groups).forEach((groupId) => {
|
|
5766
|
-
const members = groups[groupId];
|
|
5767
|
-
if (members.length === 0) return;
|
|
5768
|
-
const shapes = members.map(({ feature }) => {
|
|
5769
|
-
const geometry2 = this.getGeometryForFeature(
|
|
5770
|
-
this.currentGeometry,
|
|
5771
|
-
feature
|
|
5772
|
-
);
|
|
5773
|
-
const pos = resolveFeaturePosition(feature, geometry2);
|
|
5774
|
-
return createMarkerShape(feature, pos);
|
|
6279
|
+
originY: "bottom",
|
|
6280
|
+
left: position.x,
|
|
6281
|
+
top: position.y - visualHeight / 2
|
|
6282
|
+
}
|
|
5775
6283
|
});
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
6284
|
+
}
|
|
6285
|
+
}
|
|
6286
|
+
buildMarkerData(marker, options) {
|
|
6287
|
+
const data = {
|
|
6288
|
+
type: "feature-marker",
|
|
6289
|
+
index: marker.index,
|
|
6290
|
+
featureId: marker.feature.id,
|
|
6291
|
+
markerRole: options.markerRole,
|
|
6292
|
+
markerOffsetX: 0,
|
|
6293
|
+
markerOffsetY: 0,
|
|
6294
|
+
isGroup: options.isGroup
|
|
6295
|
+
};
|
|
6296
|
+
if (options.groupId) data.groupId = options.groupId;
|
|
6297
|
+
if (options.indices) data.indices = options.indices;
|
|
6298
|
+
if (options.anchorIndex !== void 0) data.anchorIndex = options.anchorIndex;
|
|
6299
|
+
if (options.memberOffsets) data.memberOffsets = options.memberOffsets;
|
|
6300
|
+
return data;
|
|
6301
|
+
}
|
|
6302
|
+
markerId(index) {
|
|
6303
|
+
return `feature.marker.${index}`;
|
|
6304
|
+
}
|
|
6305
|
+
bridgeIndicatorId(index) {
|
|
6306
|
+
return `feature.marker.${index}.bridge`;
|
|
6307
|
+
}
|
|
6308
|
+
toFeatureIndex(value) {
|
|
6309
|
+
const numeric = Number(value);
|
|
6310
|
+
if (!Number.isInteger(numeric) || numeric < 0) return null;
|
|
6311
|
+
return numeric;
|
|
6312
|
+
}
|
|
6313
|
+
readGroupIndices(raw) {
|
|
6314
|
+
if (!Array.isArray(raw)) return [];
|
|
6315
|
+
return raw.map((value) => this.toFeatureIndex(value)).filter((value) => value !== null);
|
|
6316
|
+
}
|
|
6317
|
+
readGroupMemberOffsets(raw, fallbackIndices = []) {
|
|
6318
|
+
if (Array.isArray(raw)) {
|
|
6319
|
+
const parsed = raw.map((entry) => {
|
|
6320
|
+
const index = this.toFeatureIndex(entry == null ? void 0 : entry.index);
|
|
6321
|
+
const dx = Number(entry == null ? void 0 : entry.dx);
|
|
6322
|
+
const dy = Number(entry == null ? void 0 : entry.dy);
|
|
6323
|
+
if (index === null || !Number.isFinite(dx) || !Number.isFinite(dy)) {
|
|
6324
|
+
return null;
|
|
5796
6325
|
}
|
|
6326
|
+
return { index, dx, dy };
|
|
6327
|
+
}).filter((value) => !!value);
|
|
6328
|
+
if (parsed.length > 0) return parsed;
|
|
6329
|
+
}
|
|
6330
|
+
return fallbackIndices.map((index) => ({ index, dx: 0, dy: 0 }));
|
|
6331
|
+
}
|
|
6332
|
+
syncMarkerVisualsByTarget(target, center) {
|
|
6333
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6334
|
+
if ((_a = target.data) == null ? void 0 : _a.isGroup) {
|
|
6335
|
+
const indices = this.readGroupIndices((_b = target.data) == null ? void 0 : _b.indices);
|
|
6336
|
+
const offsets = this.readGroupMemberOffsets((_c = target.data) == null ? void 0 : _c.memberOffsets, indices);
|
|
6337
|
+
offsets.forEach((entry) => {
|
|
6338
|
+
this.syncMarkerVisualObjectsToCenter(entry.index, {
|
|
6339
|
+
x: center.x + entry.dx,
|
|
6340
|
+
y: center.y + entry.dy
|
|
6341
|
+
});
|
|
5797
6342
|
});
|
|
5798
|
-
|
|
5799
|
-
|
|
6343
|
+
(_d = this.canvasService) == null ? void 0 : _d.requestRenderAll();
|
|
6344
|
+
return;
|
|
6345
|
+
}
|
|
6346
|
+
const index = this.toFeatureIndex((_e = target.data) == null ? void 0 : _e.index);
|
|
6347
|
+
if (index === null) return;
|
|
6348
|
+
this.syncMarkerVisualObjectsToCenter(index, center);
|
|
6349
|
+
(_f = this.canvasService) == null ? void 0 : _f.requestRenderAll();
|
|
6350
|
+
}
|
|
6351
|
+
syncMarkerVisualObjectsToCenter(index, center) {
|
|
6352
|
+
if (!this.canvasService) return;
|
|
6353
|
+
const markers = this.canvasService.canvas.getObjects().filter(
|
|
6354
|
+
(obj) => {
|
|
6355
|
+
var _a, _b;
|
|
6356
|
+
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;
|
|
6357
|
+
}
|
|
6358
|
+
);
|
|
6359
|
+
markers.forEach((marker) => {
|
|
6360
|
+
var _a, _b;
|
|
6361
|
+
const offsetX = Number(((_a = marker == null ? void 0 : marker.data) == null ? void 0 : _a.markerOffsetX) || 0);
|
|
6362
|
+
const offsetY = Number(((_b = marker == null ? void 0 : marker.data) == null ? void 0 : _b.markerOffsetY) || 0);
|
|
6363
|
+
marker.set({
|
|
6364
|
+
left: center.x + offsetX,
|
|
6365
|
+
top: center.y + offsetY
|
|
6366
|
+
});
|
|
6367
|
+
marker.setCoords();
|
|
5800
6368
|
});
|
|
5801
|
-
this.canvasService.requestRenderAll();
|
|
5802
6369
|
}
|
|
5803
6370
|
enforceConstraints() {
|
|
5804
6371
|
if (!this.canvasService || !this.currentGeometry) return;
|
|
5805
|
-
const
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
});
|
|
5810
|
-
markers.forEach((marker) => {
|
|
5811
|
-
var _a, _b, _c;
|
|
5812
|
-
let feature;
|
|
5813
|
-
if ((_a = marker.data) == null ? void 0 : _a.isGroup) {
|
|
5814
|
-
const indices = (_b = marker.data) == null ? void 0 : _b.indices;
|
|
5815
|
-
if (indices && indices.length > 0) {
|
|
5816
|
-
feature = this.workingFeatures[indices[0]];
|
|
5817
|
-
}
|
|
5818
|
-
} else {
|
|
5819
|
-
const index = (_c = marker.data) == null ? void 0 : _c.index;
|
|
5820
|
-
if (index !== void 0) {
|
|
5821
|
-
feature = this.workingFeatures[index];
|
|
5822
|
-
}
|
|
6372
|
+
const handles = this.canvasService.canvas.getObjects().filter(
|
|
6373
|
+
(obj) => {
|
|
6374
|
+
var _a, _b;
|
|
6375
|
+
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";
|
|
5823
6376
|
}
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
);
|
|
5828
|
-
const
|
|
5829
|
-
const minDim = Math.min(
|
|
5830
|
-
marker.getScaledWidth(),
|
|
5831
|
-
marker.getScaledHeight()
|
|
5832
|
-
);
|
|
5833
|
-
const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
|
|
6377
|
+
);
|
|
6378
|
+
handles.forEach((marker) => {
|
|
6379
|
+
const feature = this.getFeatureForMarker(marker);
|
|
6380
|
+
if (!feature) return;
|
|
6381
|
+
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
5834
6382
|
const snapped = this.constrainPosition(
|
|
5835
|
-
|
|
6383
|
+
{
|
|
6384
|
+
x: Number(marker.left || 0),
|
|
6385
|
+
y: Number(marker.top || 0)
|
|
6386
|
+
},
|
|
5836
6387
|
geometry,
|
|
5837
|
-
limit,
|
|
5838
6388
|
feature
|
|
5839
6389
|
);
|
|
5840
6390
|
marker.set({ left: snapped.x, top: snapped.y });
|
|
5841
6391
|
marker.setCoords();
|
|
6392
|
+
this.syncMarkerVisualsByTarget(marker, snapped);
|
|
5842
6393
|
});
|
|
5843
|
-
canvas.requestRenderAll();
|
|
6394
|
+
this.canvasService.canvas.requestRenderAll();
|
|
5844
6395
|
}
|
|
5845
6396
|
};
|
|
5846
6397
|
|
|
5847
6398
|
// src/extensions/film.ts
|
|
5848
6399
|
var import_core6 = require("@pooder/core");
|
|
5849
|
-
var
|
|
6400
|
+
var import_fabric4 = require("fabric");
|
|
6401
|
+
var FILM_LAYER_ID = "overlay";
|
|
6402
|
+
var FILM_IMAGE_ID = "film-image";
|
|
6403
|
+
var DEFAULT_WIDTH2 = 800;
|
|
6404
|
+
var DEFAULT_HEIGHT2 = 600;
|
|
5850
6405
|
var FilmTool = class {
|
|
5851
6406
|
constructor(options) {
|
|
5852
6407
|
this.id = "pooder.kit.film";
|
|
@@ -5855,17 +6410,38 @@ var FilmTool = class {
|
|
|
5855
6410
|
};
|
|
5856
6411
|
this.url = "";
|
|
5857
6412
|
this.opacity = 0.5;
|
|
6413
|
+
this.specs = [];
|
|
6414
|
+
this.renderSeq = 0;
|
|
6415
|
+
this.renderImageUrl = "";
|
|
6416
|
+
this.sourceSizeBySrc = /* @__PURE__ */ new Map();
|
|
6417
|
+
this.pendingSizeBySrc = /* @__PURE__ */ new Map();
|
|
6418
|
+
this.onCanvasResized = () => {
|
|
6419
|
+
this.updateFilm();
|
|
6420
|
+
};
|
|
5858
6421
|
if (options) {
|
|
5859
6422
|
Object.assign(this, options);
|
|
5860
6423
|
}
|
|
5861
6424
|
}
|
|
5862
6425
|
activate(context) {
|
|
6426
|
+
var _a;
|
|
5863
6427
|
this.canvasService = context.services.get("CanvasService");
|
|
5864
6428
|
if (!this.canvasService) {
|
|
5865
6429
|
console.warn("CanvasService not found for FilmTool");
|
|
5866
6430
|
return;
|
|
5867
6431
|
}
|
|
5868
|
-
|
|
6432
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6433
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
6434
|
+
this.id,
|
|
6435
|
+
() => ({
|
|
6436
|
+
layerSpecs: {
|
|
6437
|
+
[FILM_LAYER_ID]: this.specs
|
|
6438
|
+
}
|
|
6439
|
+
}),
|
|
6440
|
+
{ priority: 500 }
|
|
6441
|
+
);
|
|
6442
|
+
const configService = context.services.get(
|
|
6443
|
+
"ConfigurationService"
|
|
6444
|
+
);
|
|
5869
6445
|
if (configService) {
|
|
5870
6446
|
this.url = configService.get("film.url", this.url);
|
|
5871
6447
|
this.opacity = configService.get("film.opacity", this.opacity);
|
|
@@ -5882,21 +6458,21 @@ var FilmTool = class {
|
|
|
5882
6458
|
}
|
|
5883
6459
|
});
|
|
5884
6460
|
}
|
|
5885
|
-
this.
|
|
6461
|
+
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
5886
6462
|
this.updateFilm();
|
|
5887
6463
|
}
|
|
5888
6464
|
deactivate(context) {
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
6465
|
+
var _a;
|
|
6466
|
+
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
6467
|
+
this.renderSeq += 1;
|
|
6468
|
+
this.specs = [];
|
|
6469
|
+
this.renderImageUrl = "";
|
|
6470
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6471
|
+
this.renderProducerDisposable = void 0;
|
|
6472
|
+
if (!this.canvasService) return;
|
|
6473
|
+
void this.canvasService.flushRenderFromProducers();
|
|
6474
|
+
this.canvasService.requestRenderAll();
|
|
6475
|
+
this.canvasService = void 0;
|
|
5900
6476
|
}
|
|
5901
6477
|
contribute() {
|
|
5902
6478
|
return {
|
|
@@ -5932,73 +6508,108 @@ var FilmTool = class {
|
|
|
5932
6508
|
]
|
|
5933
6509
|
};
|
|
5934
6510
|
}
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
height,
|
|
5944
|
-
left: 0,
|
|
5945
|
-
top: 0,
|
|
5946
|
-
originX: "left",
|
|
5947
|
-
originY: "top",
|
|
5948
|
-
selectable: false,
|
|
5949
|
-
evented: false,
|
|
5950
|
-
subTargetCheck: false,
|
|
5951
|
-
interactive: false
|
|
5952
|
-
});
|
|
5953
|
-
this.canvasService.canvas.bringObjectToFront(layer);
|
|
5954
|
-
}
|
|
6511
|
+
getViewportSize() {
|
|
6512
|
+
var _a, _b;
|
|
6513
|
+
const width = Number(((_a = this.canvasService) == null ? void 0 : _a.canvas.width) || 0);
|
|
6514
|
+
const height = Number(((_b = this.canvasService) == null ? void 0 : _b.canvas.height) || 0);
|
|
6515
|
+
return {
|
|
6516
|
+
width: width > 0 ? width : DEFAULT_WIDTH2,
|
|
6517
|
+
height: height > 0 ? height : DEFAULT_HEIGHT2
|
|
6518
|
+
};
|
|
5955
6519
|
}
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
return;
|
|
5962
|
-
}
|
|
5963
|
-
const { url, opacity } = this;
|
|
5964
|
-
if (!url) {
|
|
5965
|
-
const img2 = this.canvasService.getObject("film-image", "overlay");
|
|
5966
|
-
if (img2) {
|
|
5967
|
-
layer.remove(img2);
|
|
5968
|
-
this.canvasService.requestRenderAll();
|
|
5969
|
-
}
|
|
5970
|
-
return;
|
|
6520
|
+
clampOpacity(value) {
|
|
6521
|
+
return Math.max(0, Math.min(1, Number(value)));
|
|
6522
|
+
}
|
|
6523
|
+
buildFilmSpecs(imageUrl, opacity) {
|
|
6524
|
+
if (!imageUrl) {
|
|
6525
|
+
return [];
|
|
5971
6526
|
}
|
|
5972
|
-
const width = this.
|
|
5973
|
-
const
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
6527
|
+
const { width, height } = this.getViewportSize();
|
|
6528
|
+
const sourceSize = this.sourceSizeBySrc.get(imageUrl);
|
|
6529
|
+
const sourceWidth = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.width) || width));
|
|
6530
|
+
const sourceHeight = Math.max(1, Number((sourceSize == null ? void 0 : sourceSize.height) || height));
|
|
6531
|
+
const coverScale = Math.max(width / sourceWidth, height / sourceHeight);
|
|
6532
|
+
return [
|
|
6533
|
+
{
|
|
6534
|
+
id: FILM_IMAGE_ID,
|
|
6535
|
+
type: "image",
|
|
6536
|
+
src: imageUrl,
|
|
6537
|
+
space: "screen",
|
|
6538
|
+
data: {
|
|
6539
|
+
id: FILM_IMAGE_ID,
|
|
6540
|
+
layerId: FILM_LAYER_ID,
|
|
6541
|
+
type: "film-image"
|
|
6542
|
+
},
|
|
6543
|
+
props: {
|
|
5988
6544
|
left: 0,
|
|
5989
6545
|
top: 0,
|
|
5990
|
-
|
|
6546
|
+
originX: "left",
|
|
6547
|
+
originY: "top",
|
|
6548
|
+
opacity: this.clampOpacity(opacity),
|
|
6549
|
+
scaleX: coverScale,
|
|
6550
|
+
scaleY: coverScale,
|
|
5991
6551
|
selectable: false,
|
|
5992
6552
|
evented: false,
|
|
5993
|
-
|
|
5994
|
-
}
|
|
5995
|
-
|
|
6553
|
+
excludeFromExport: true
|
|
6554
|
+
}
|
|
6555
|
+
}
|
|
6556
|
+
];
|
|
6557
|
+
}
|
|
6558
|
+
async ensureImageSize(src) {
|
|
6559
|
+
if (!src) return null;
|
|
6560
|
+
const cached = this.sourceSizeBySrc.get(src);
|
|
6561
|
+
if (cached) return cached;
|
|
6562
|
+
const pending = this.pendingSizeBySrc.get(src);
|
|
6563
|
+
if (pending) {
|
|
6564
|
+
return pending;
|
|
6565
|
+
}
|
|
6566
|
+
const task = this.loadImageSize(src);
|
|
6567
|
+
this.pendingSizeBySrc.set(src, task);
|
|
6568
|
+
try {
|
|
6569
|
+
return await task;
|
|
6570
|
+
} finally {
|
|
6571
|
+
if (this.pendingSizeBySrc.get(src) === task) {
|
|
6572
|
+
this.pendingSizeBySrc.delete(src);
|
|
6573
|
+
}
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
async loadImageSize(src) {
|
|
6577
|
+
try {
|
|
6578
|
+
const image = await import_fabric4.FabricImage.fromURL(src, {
|
|
6579
|
+
crossOrigin: "anonymous"
|
|
6580
|
+
});
|
|
6581
|
+
const width = Number((image == null ? void 0 : image.width) || 0);
|
|
6582
|
+
const height = Number((image == null ? void 0 : image.height) || 0);
|
|
6583
|
+
if (width > 0 && height > 0) {
|
|
6584
|
+
const size = { width, height };
|
|
6585
|
+
this.sourceSizeBySrc.set(src, size);
|
|
6586
|
+
return size;
|
|
5996
6587
|
}
|
|
5997
|
-
this.canvasService.requestRenderAll();
|
|
5998
6588
|
} catch (error) {
|
|
5999
|
-
console.error("[FilmTool] Failed to load film image",
|
|
6589
|
+
console.error("[FilmTool] Failed to load film image", src, error);
|
|
6590
|
+
}
|
|
6591
|
+
return null;
|
|
6592
|
+
}
|
|
6593
|
+
updateFilm() {
|
|
6594
|
+
void this.updateFilmAsync();
|
|
6595
|
+
}
|
|
6596
|
+
async updateFilmAsync() {
|
|
6597
|
+
if (!this.canvasService) return;
|
|
6598
|
+
const seq = ++this.renderSeq;
|
|
6599
|
+
const nextUrl = String(this.url || "").trim();
|
|
6600
|
+
if (!nextUrl) {
|
|
6601
|
+
this.renderImageUrl = "";
|
|
6602
|
+
} else if (nextUrl !== this.renderImageUrl) {
|
|
6603
|
+
const loaded = await this.ensureImageSize(nextUrl);
|
|
6604
|
+
if (seq !== this.renderSeq) return;
|
|
6605
|
+
if (loaded) {
|
|
6606
|
+
this.renderImageUrl = nextUrl;
|
|
6607
|
+
}
|
|
6000
6608
|
}
|
|
6001
|
-
|
|
6609
|
+
this.specs = this.buildFilmSpecs(this.renderImageUrl, this.opacity);
|
|
6610
|
+
await this.canvasService.flushRenderFromProducers();
|
|
6611
|
+
if (seq !== this.renderSeq) return;
|
|
6612
|
+
this.canvasService.bringLayerToFront(FILM_LAYER_ID);
|
|
6002
6613
|
this.canvasService.requestRenderAll();
|
|
6003
6614
|
}
|
|
6004
6615
|
};
|
|
@@ -6095,19 +6706,37 @@ var MirrorTool = class {
|
|
|
6095
6706
|
|
|
6096
6707
|
// src/extensions/ruler.ts
|
|
6097
6708
|
var import_core8 = require("@pooder/core");
|
|
6098
|
-
var
|
|
6709
|
+
var RULER_LAYER_ID = "ruler-overlay";
|
|
6710
|
+
var EXTENSION_LINE_LENGTH = 5;
|
|
6711
|
+
var MIN_ARROW_SIZE = 4;
|
|
6712
|
+
var THICKNESS_TO_STROKE_WIDTH_RATIO = 20;
|
|
6713
|
+
var DEFAULT_THICKNESS = 20;
|
|
6714
|
+
var DEFAULT_GAP = 45;
|
|
6715
|
+
var DEFAULT_FONT_SIZE = 10;
|
|
6716
|
+
var DEFAULT_BACKGROUND_COLOR = "#f0f0f0";
|
|
6717
|
+
var DEFAULT_TEXT_COLOR = "#333333";
|
|
6718
|
+
var DEFAULT_LINE_COLOR = "#999999";
|
|
6719
|
+
var RULER_THICKNESS_MIN = 10;
|
|
6720
|
+
var RULER_THICKNESS_MAX = 100;
|
|
6721
|
+
var RULER_GAP_MIN = 0;
|
|
6722
|
+
var RULER_GAP_MAX = 100;
|
|
6723
|
+
var RULER_FONT_SIZE_MIN = 8;
|
|
6724
|
+
var RULER_FONT_SIZE_MAX = 24;
|
|
6099
6725
|
var RulerTool = class {
|
|
6100
6726
|
constructor(options) {
|
|
6101
6727
|
this.id = "pooder.kit.ruler";
|
|
6102
6728
|
this.metadata = {
|
|
6103
6729
|
name: "RulerTool"
|
|
6104
6730
|
};
|
|
6105
|
-
this.thickness =
|
|
6106
|
-
this.gap =
|
|
6107
|
-
this.backgroundColor =
|
|
6108
|
-
this.textColor =
|
|
6109
|
-
this.lineColor =
|
|
6110
|
-
this.fontSize =
|
|
6731
|
+
this.thickness = DEFAULT_THICKNESS;
|
|
6732
|
+
this.gap = DEFAULT_GAP;
|
|
6733
|
+
this.backgroundColor = DEFAULT_BACKGROUND_COLOR;
|
|
6734
|
+
this.textColor = DEFAULT_TEXT_COLOR;
|
|
6735
|
+
this.lineColor = DEFAULT_LINE_COLOR;
|
|
6736
|
+
this.fontSize = DEFAULT_FONT_SIZE;
|
|
6737
|
+
this.renderSeq = 0;
|
|
6738
|
+
this.numericProps = /* @__PURE__ */ new Set(["thickness", "gap", "fontSize"]);
|
|
6739
|
+
this.specs = [];
|
|
6111
6740
|
this.onCanvasResized = () => {
|
|
6112
6741
|
this.updateRuler();
|
|
6113
6742
|
};
|
|
@@ -6116,50 +6745,73 @@ var RulerTool = class {
|
|
|
6116
6745
|
}
|
|
6117
6746
|
}
|
|
6118
6747
|
activate(context) {
|
|
6748
|
+
var _a;
|
|
6119
6749
|
this.context = context;
|
|
6120
6750
|
this.canvasService = context.services.get("CanvasService");
|
|
6121
6751
|
if (!this.canvasService) {
|
|
6122
|
-
console.warn("CanvasService not found
|
|
6752
|
+
console.warn("[RulerTool] CanvasService not found.");
|
|
6123
6753
|
return;
|
|
6124
6754
|
}
|
|
6755
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6756
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
6757
|
+
this.id,
|
|
6758
|
+
() => ({
|
|
6759
|
+
rootLayerSpecs: {
|
|
6760
|
+
[RULER_LAYER_ID]: this.specs
|
|
6761
|
+
},
|
|
6762
|
+
replaceRootLayerIds: [RULER_LAYER_ID]
|
|
6763
|
+
}),
|
|
6764
|
+
{ priority: 400 }
|
|
6765
|
+
);
|
|
6125
6766
|
const configService = context.services.get(
|
|
6126
6767
|
"ConfigurationService"
|
|
6127
6768
|
);
|
|
6128
6769
|
if (configService) {
|
|
6129
|
-
this.
|
|
6130
|
-
this.gap = configService.get("ruler.gap", this.gap);
|
|
6131
|
-
this.backgroundColor = configService.get(
|
|
6132
|
-
"ruler.backgroundColor",
|
|
6133
|
-
this.backgroundColor
|
|
6134
|
-
);
|
|
6135
|
-
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
6136
|
-
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
6137
|
-
this.fontSize = configService.get("ruler.fontSize", this.fontSize);
|
|
6770
|
+
this.syncConfig(configService);
|
|
6138
6771
|
configService.onAnyChange((e) => {
|
|
6139
6772
|
let shouldUpdate = false;
|
|
6140
6773
|
if (e.key.startsWith("ruler.")) {
|
|
6141
6774
|
const prop = e.key.split(".")[1];
|
|
6142
6775
|
if (prop && prop in this) {
|
|
6143
|
-
this
|
|
6776
|
+
if (this.numericProps.has(prop)) {
|
|
6777
|
+
this[prop] = this.toFiniteNumber(
|
|
6778
|
+
e.value,
|
|
6779
|
+
this[prop]
|
|
6780
|
+
);
|
|
6781
|
+
} else {
|
|
6782
|
+
this[prop] = e.value;
|
|
6783
|
+
}
|
|
6144
6784
|
shouldUpdate = true;
|
|
6785
|
+
this.log("config:update", {
|
|
6786
|
+
key: e.key,
|
|
6787
|
+
raw: e.value,
|
|
6788
|
+
normalized: this[prop]
|
|
6789
|
+
});
|
|
6145
6790
|
}
|
|
6146
6791
|
} else if (e.key.startsWith("size.")) {
|
|
6147
6792
|
shouldUpdate = true;
|
|
6793
|
+
this.log("size:update", { key: e.key, value: e.value });
|
|
6148
6794
|
}
|
|
6149
6795
|
if (shouldUpdate) {
|
|
6150
6796
|
this.updateRuler();
|
|
6151
6797
|
}
|
|
6152
6798
|
});
|
|
6153
6799
|
}
|
|
6154
|
-
this.createLayer();
|
|
6155
6800
|
context.eventBus.on("canvas:resized", this.onCanvasResized);
|
|
6156
6801
|
this.updateRuler();
|
|
6157
6802
|
}
|
|
6158
6803
|
deactivate(context) {
|
|
6804
|
+
var _a;
|
|
6159
6805
|
context.eventBus.off("canvas:resized", this.onCanvasResized);
|
|
6160
|
-
this.
|
|
6806
|
+
this.specs = [];
|
|
6807
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
6808
|
+
this.renderProducerDisposable = void 0;
|
|
6809
|
+
if (this.canvasService) {
|
|
6810
|
+
void this.canvasService.flushRenderFromProducers();
|
|
6811
|
+
}
|
|
6161
6812
|
this.canvasService = void 0;
|
|
6162
6813
|
this.context = void 0;
|
|
6814
|
+
this.renderSeq = 0;
|
|
6163
6815
|
}
|
|
6164
6816
|
contribute() {
|
|
6165
6817
|
return {
|
|
@@ -6168,43 +6820,43 @@ var RulerTool = class {
|
|
|
6168
6820
|
id: "ruler.thickness",
|
|
6169
6821
|
type: "number",
|
|
6170
6822
|
label: "Thickness",
|
|
6171
|
-
min:
|
|
6172
|
-
max:
|
|
6173
|
-
default:
|
|
6823
|
+
min: RULER_THICKNESS_MIN,
|
|
6824
|
+
max: RULER_THICKNESS_MAX,
|
|
6825
|
+
default: DEFAULT_THICKNESS
|
|
6174
6826
|
},
|
|
6175
6827
|
{
|
|
6176
6828
|
id: "ruler.gap",
|
|
6177
6829
|
type: "number",
|
|
6178
6830
|
label: "Gap",
|
|
6179
|
-
min:
|
|
6180
|
-
max:
|
|
6181
|
-
default:
|
|
6831
|
+
min: RULER_GAP_MIN,
|
|
6832
|
+
max: RULER_GAP_MAX,
|
|
6833
|
+
default: DEFAULT_GAP
|
|
6182
6834
|
},
|
|
6183
6835
|
{
|
|
6184
6836
|
id: "ruler.backgroundColor",
|
|
6185
6837
|
type: "color",
|
|
6186
6838
|
label: "Background Color",
|
|
6187
|
-
default:
|
|
6839
|
+
default: DEFAULT_BACKGROUND_COLOR
|
|
6188
6840
|
},
|
|
6189
6841
|
{
|
|
6190
6842
|
id: "ruler.textColor",
|
|
6191
6843
|
type: "color",
|
|
6192
6844
|
label: "Text Color",
|
|
6193
|
-
default:
|
|
6845
|
+
default: DEFAULT_TEXT_COLOR
|
|
6194
6846
|
},
|
|
6195
6847
|
{
|
|
6196
6848
|
id: "ruler.lineColor",
|
|
6197
6849
|
type: "color",
|
|
6198
6850
|
label: "Line Color",
|
|
6199
|
-
default:
|
|
6851
|
+
default: DEFAULT_LINE_COLOR
|
|
6200
6852
|
},
|
|
6201
6853
|
{
|
|
6202
6854
|
id: "ruler.fontSize",
|
|
6203
6855
|
type: "number",
|
|
6204
6856
|
label: "Font Size",
|
|
6205
|
-
min:
|
|
6206
|
-
max:
|
|
6207
|
-
default:
|
|
6857
|
+
min: RULER_FONT_SIZE_MIN,
|
|
6858
|
+
max: RULER_FONT_SIZE_MAX,
|
|
6859
|
+
default: DEFAULT_FONT_SIZE
|
|
6208
6860
|
}
|
|
6209
6861
|
],
|
|
6210
6862
|
[import_core8.ContributionPointIds.COMMANDS]: [
|
|
@@ -6217,12 +6869,23 @@ var RulerTool = class {
|
|
|
6217
6869
|
textColor: this.textColor,
|
|
6218
6870
|
lineColor: this.lineColor,
|
|
6219
6871
|
fontSize: this.fontSize,
|
|
6220
|
-
thickness: this.thickness
|
|
6872
|
+
thickness: this.thickness,
|
|
6873
|
+
gap: this.gap
|
|
6221
6874
|
};
|
|
6222
6875
|
const newState = { ...oldState, ...theme };
|
|
6223
|
-
if (JSON.stringify(newState) === JSON.stringify(oldState))
|
|
6876
|
+
if (JSON.stringify(newState) === JSON.stringify(oldState)) {
|
|
6224
6877
|
return true;
|
|
6878
|
+
}
|
|
6225
6879
|
Object.assign(this, newState);
|
|
6880
|
+
this.thickness = this.toFiniteNumber(
|
|
6881
|
+
this.thickness,
|
|
6882
|
+
DEFAULT_THICKNESS
|
|
6883
|
+
);
|
|
6884
|
+
this.gap = this.toFiniteNumber(this.gap, DEFAULT_GAP);
|
|
6885
|
+
this.fontSize = this.toFiniteNumber(
|
|
6886
|
+
this.fontSize,
|
|
6887
|
+
DEFAULT_FONT_SIZE
|
|
6888
|
+
);
|
|
6226
6889
|
this.updateRuler();
|
|
6227
6890
|
return true;
|
|
6228
6891
|
}
|
|
@@ -6230,225 +6893,367 @@ var RulerTool = class {
|
|
|
6230
6893
|
]
|
|
6231
6894
|
};
|
|
6232
6895
|
}
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6896
|
+
log(step, payload) {
|
|
6897
|
+
if (payload) {
|
|
6898
|
+
console.debug(`[RulerTool] ${step}`, payload);
|
|
6899
|
+
return;
|
|
6900
|
+
}
|
|
6901
|
+
console.debug(`[RulerTool] ${step}`);
|
|
6236
6902
|
}
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6903
|
+
syncConfig(configService) {
|
|
6904
|
+
this.thickness = this.toFiniteNumber(
|
|
6905
|
+
configService.get("ruler.thickness", this.thickness),
|
|
6906
|
+
DEFAULT_THICKNESS
|
|
6907
|
+
);
|
|
6908
|
+
this.gap = Math.max(
|
|
6909
|
+
0,
|
|
6910
|
+
this.toFiniteNumber(
|
|
6911
|
+
configService.get("ruler.gap", this.gap),
|
|
6912
|
+
DEFAULT_GAP
|
|
6913
|
+
)
|
|
6914
|
+
);
|
|
6915
|
+
this.backgroundColor = configService.get(
|
|
6916
|
+
"ruler.backgroundColor",
|
|
6917
|
+
this.backgroundColor
|
|
6918
|
+
);
|
|
6919
|
+
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
6920
|
+
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
6921
|
+
this.fontSize = this.toFiniteNumber(
|
|
6922
|
+
configService.get("ruler.fontSize", this.fontSize),
|
|
6923
|
+
DEFAULT_FONT_SIZE
|
|
6924
|
+
);
|
|
6925
|
+
this.log("config:loaded", {
|
|
6926
|
+
thickness: this.thickness,
|
|
6927
|
+
gap: this.gap,
|
|
6928
|
+
fontSize: this.fontSize,
|
|
6929
|
+
backgroundColor: this.backgroundColor,
|
|
6930
|
+
textColor: this.textColor,
|
|
6931
|
+
lineColor: this.lineColor
|
|
6251
6932
|
});
|
|
6252
|
-
canvas.bringObjectToFront(layer);
|
|
6253
6933
|
}
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
if (layer) {
|
|
6258
|
-
this.canvasService.canvas.remove(layer);
|
|
6259
|
-
}
|
|
6934
|
+
toFiniteNumber(value, fallback) {
|
|
6935
|
+
const numeric = Number(value);
|
|
6936
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
6260
6937
|
}
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
const
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6938
|
+
toSceneDisplayLength(value) {
|
|
6939
|
+
if (!this.canvasService) return value;
|
|
6940
|
+
return this.canvasService.toSceneLength(value);
|
|
6941
|
+
}
|
|
6942
|
+
formatLengthMm(valueMm, unit) {
|
|
6943
|
+
const converted = fromMm(valueMm, unit);
|
|
6944
|
+
const fractionDigits = unit === "in" ? 3 : 2;
|
|
6945
|
+
return Number(converted.toFixed(fractionDigits)).toString();
|
|
6946
|
+
}
|
|
6947
|
+
buildLinePath(start, end) {
|
|
6948
|
+
const dx = end.x - start.x;
|
|
6949
|
+
const dy = end.y - start.y;
|
|
6950
|
+
return `M 0 0 L ${dx} ${dy}`;
|
|
6951
|
+
}
|
|
6952
|
+
buildStartArrowPath(size) {
|
|
6953
|
+
return `M 0 0 L ${size} ${-size / 2} L ${size} ${size / 2} Z`;
|
|
6954
|
+
}
|
|
6955
|
+
buildEndArrowPath(size) {
|
|
6956
|
+
return `M 0 0 L ${-size} ${-size / 2} L ${-size} ${size / 2} Z`;
|
|
6957
|
+
}
|
|
6958
|
+
createPathSpec(id, pathData, position, options) {
|
|
6959
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
6960
|
+
return {
|
|
6961
|
+
id,
|
|
6962
|
+
type: "path",
|
|
6963
|
+
data: {
|
|
6964
|
+
id,
|
|
6965
|
+
type: "ruler"
|
|
6966
|
+
},
|
|
6967
|
+
props: {
|
|
6968
|
+
pathData,
|
|
6969
|
+
left: position.x,
|
|
6970
|
+
top: position.y,
|
|
6971
|
+
originX: (_a = options.originX) != null ? _a : "left",
|
|
6972
|
+
originY: (_b = options.originY) != null ? _b : "top",
|
|
6973
|
+
angle: (_c = options.angle) != null ? _c : 0,
|
|
6974
|
+
stroke: (_d = options.stroke) != null ? _d : null,
|
|
6975
|
+
fill: (_e = options.fill) != null ? _e : null,
|
|
6976
|
+
strokeWidth: (_f = options.strokeWidth) != null ? _f : 1,
|
|
6977
|
+
strokeLineCap: (_g = options.strokeLineCap) != null ? _g : "butt",
|
|
6284
6978
|
selectable: false,
|
|
6285
|
-
evented: false
|
|
6979
|
+
evented: false,
|
|
6980
|
+
excludeFromExport: true
|
|
6286
6981
|
}
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6982
|
+
};
|
|
6983
|
+
}
|
|
6984
|
+
createTextSpec(id, text, position, angle = 0) {
|
|
6985
|
+
return {
|
|
6986
|
+
id,
|
|
6987
|
+
type: "text",
|
|
6988
|
+
data: {
|
|
6989
|
+
id,
|
|
6990
|
+
type: "ruler"
|
|
6991
|
+
},
|
|
6992
|
+
props: {
|
|
6993
|
+
text,
|
|
6994
|
+
left: position.x,
|
|
6995
|
+
top: position.y,
|
|
6996
|
+
angle,
|
|
6997
|
+
fontSize: this.toSceneDisplayLength(this.fontSize),
|
|
6998
|
+
fill: this.textColor,
|
|
6999
|
+
fontFamily: "Arial",
|
|
7000
|
+
originX: "center",
|
|
6299
7001
|
originY: "center",
|
|
6300
|
-
|
|
7002
|
+
backgroundColor: this.backgroundColor,
|
|
6301
7003
|
selectable: false,
|
|
6302
|
-
evented: false
|
|
7004
|
+
evented: false,
|
|
7005
|
+
excludeFromExport: true
|
|
6303
7006
|
}
|
|
6304
|
-
|
|
6305
|
-
return new import_fabric6.Group([line, startArrow, endArrow], {
|
|
6306
|
-
selectable: false,
|
|
6307
|
-
evented: false
|
|
6308
|
-
});
|
|
7007
|
+
};
|
|
6309
7008
|
}
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
layer.remove(...layer.getObjects());
|
|
6316
|
-
const { backgroundColor, lineColor, textColor, fontSize } = this;
|
|
6317
|
-
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
6318
|
-
"ConfigurationService"
|
|
7009
|
+
buildRulerSpecs(input) {
|
|
7010
|
+
const { left, top, right, bottom, widthLabel, heightLabel } = input;
|
|
7011
|
+
const gap = Math.max(
|
|
7012
|
+
0,
|
|
7013
|
+
this.toSceneDisplayLength(this.toFiniteNumber(this.gap, DEFAULT_GAP))
|
|
6319
7014
|
);
|
|
6320
|
-
|
|
6321
|
-
const
|
|
6322
|
-
const
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
const cutRect = layout.cutRect;
|
|
6326
|
-
const useCutAsRuler = layout.cutMode === "outset";
|
|
6327
|
-
const rulerRect = useCutAsRuler ? cutRect : trimRect;
|
|
6328
|
-
const gap = this.gap || 15;
|
|
6329
|
-
const rulerLeft = rulerRect.left;
|
|
6330
|
-
const rulerTop = rulerRect.top;
|
|
6331
|
-
const rulerRight = rulerRect.left + rulerRect.width;
|
|
6332
|
-
const rulerBottom = rulerRect.top + rulerRect.height;
|
|
6333
|
-
const displayWidthMm = useCutAsRuler ? layout.cutWidthMm : layout.trimWidthMm;
|
|
6334
|
-
const displayHeightMm = useCutAsRuler ? layout.cutHeightMm : layout.trimHeightMm;
|
|
6335
|
-
const displayUnit = sizeState.unit;
|
|
6336
|
-
const topRulerY = rulerTop - gap;
|
|
6337
|
-
const topRulerXStart = rulerLeft;
|
|
6338
|
-
const topRulerXEnd = rulerRight;
|
|
6339
|
-
const leftRulerX = rulerLeft - gap;
|
|
6340
|
-
const leftRulerYStart = rulerTop;
|
|
6341
|
-
const leftRulerYEnd = rulerBottom;
|
|
6342
|
-
const topDimLine = this.createArrowLine(
|
|
6343
|
-
topRulerXStart,
|
|
6344
|
-
topRulerY,
|
|
6345
|
-
topRulerXEnd,
|
|
6346
|
-
topRulerY,
|
|
6347
|
-
lineColor
|
|
7015
|
+
const topY = top - gap;
|
|
7016
|
+
const leftX = left - gap;
|
|
7017
|
+
const arrowSize = Math.max(
|
|
7018
|
+
this.toSceneDisplayLength(MIN_ARROW_SIZE),
|
|
7019
|
+
this.toSceneDisplayLength(this.thickness * 0.3)
|
|
6348
7020
|
);
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
[
|
|
6354
|
-
topRulerXStart,
|
|
6355
|
-
topRulerY - extLen,
|
|
6356
|
-
topRulerXStart,
|
|
6357
|
-
topRulerY + extLen
|
|
6358
|
-
],
|
|
6359
|
-
{
|
|
6360
|
-
stroke: lineColor,
|
|
6361
|
-
strokeWidth: 1,
|
|
6362
|
-
selectable: false,
|
|
6363
|
-
evented: false
|
|
6364
|
-
}
|
|
7021
|
+
const strokeWidth = Math.max(
|
|
7022
|
+
this.toSceneDisplayLength(1),
|
|
7023
|
+
this.toSceneDisplayLength(
|
|
7024
|
+
this.thickness / THICKNESS_TO_STROKE_WIDTH_RATIO
|
|
6365
7025
|
)
|
|
6366
7026
|
);
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
7027
|
+
const extensionLength = this.toSceneDisplayLength(EXTENSION_LINE_LENGTH);
|
|
7028
|
+
const topLineAngleDeg = 0;
|
|
7029
|
+
const leftLineAngleDeg = 90;
|
|
7030
|
+
const topMidX = left + (right - left) / 2;
|
|
7031
|
+
const leftMidY = top + (bottom - top) / 2;
|
|
7032
|
+
const topLineStartX = Math.min(left + arrowSize, topMidX);
|
|
7033
|
+
const topLineEndX = Math.max(right - arrowSize, topMidX);
|
|
7034
|
+
const leftLineStartY = Math.min(top + arrowSize, leftMidY);
|
|
7035
|
+
const leftLineEndY = Math.max(bottom - arrowSize, leftMidY);
|
|
7036
|
+
const specs = [];
|
|
7037
|
+
specs.push(
|
|
7038
|
+
this.createPathSpec(
|
|
7039
|
+
"ruler.top.line",
|
|
7040
|
+
this.buildLinePath(
|
|
7041
|
+
{ x: topLineStartX, y: topY },
|
|
7042
|
+
{ x: topLineEndX, y: topY }
|
|
7043
|
+
),
|
|
7044
|
+
{ x: topLineStartX, y: topY },
|
|
6370
7045
|
{
|
|
6371
|
-
stroke: lineColor,
|
|
6372
|
-
strokeWidth
|
|
6373
|
-
|
|
6374
|
-
evented: false
|
|
7046
|
+
stroke: this.lineColor,
|
|
7047
|
+
strokeWidth,
|
|
7048
|
+
strokeLineCap: "butt"
|
|
6375
7049
|
}
|
|
6376
|
-
)
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
backgroundColor,
|
|
6389
|
-
// Background mask for readability
|
|
6390
|
-
selectable: false,
|
|
6391
|
-
evented: false
|
|
6392
|
-
});
|
|
6393
|
-
layer.add(topText);
|
|
6394
|
-
const leftDimLine = this.createArrowLine(
|
|
6395
|
-
leftRulerX,
|
|
6396
|
-
leftRulerYStart,
|
|
6397
|
-
leftRulerX,
|
|
6398
|
-
leftRulerYEnd,
|
|
6399
|
-
lineColor
|
|
6400
|
-
);
|
|
6401
|
-
layer.add(leftDimLine);
|
|
6402
|
-
layer.add(
|
|
6403
|
-
new import_fabric6.Line(
|
|
6404
|
-
[
|
|
6405
|
-
leftRulerX - extLen,
|
|
6406
|
-
leftRulerYStart,
|
|
6407
|
-
leftRulerX + extLen,
|
|
6408
|
-
leftRulerYStart
|
|
6409
|
-
],
|
|
6410
|
-
{
|
|
6411
|
-
stroke: lineColor,
|
|
6412
|
-
strokeWidth: 1,
|
|
6413
|
-
selectable: false,
|
|
6414
|
-
evented: false
|
|
7050
|
+
),
|
|
7051
|
+
this.createPathSpec(
|
|
7052
|
+
"ruler.top.arrow.start",
|
|
7053
|
+
this.buildStartArrowPath(arrowSize),
|
|
7054
|
+
{ x: left, y: topY },
|
|
7055
|
+
{
|
|
7056
|
+
fill: this.lineColor,
|
|
7057
|
+
stroke: this.lineColor,
|
|
7058
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7059
|
+
originX: "left",
|
|
7060
|
+
originY: "center",
|
|
7061
|
+
angle: topLineAngleDeg
|
|
6415
7062
|
}
|
|
6416
|
-
)
|
|
7063
|
+
),
|
|
7064
|
+
this.createPathSpec(
|
|
7065
|
+
"ruler.top.arrow.end",
|
|
7066
|
+
this.buildEndArrowPath(arrowSize),
|
|
7067
|
+
{ x: right, y: topY },
|
|
7068
|
+
{
|
|
7069
|
+
fill: this.lineColor,
|
|
7070
|
+
stroke: this.lineColor,
|
|
7071
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7072
|
+
originX: "right",
|
|
7073
|
+
originY: "center",
|
|
7074
|
+
angle: topLineAngleDeg
|
|
7075
|
+
}
|
|
7076
|
+
),
|
|
7077
|
+
this.createPathSpec(
|
|
7078
|
+
"ruler.top.ext.start",
|
|
7079
|
+
this.buildLinePath(
|
|
7080
|
+
{ x: left, y: topY - extensionLength },
|
|
7081
|
+
{ x: left, y: topY + extensionLength }
|
|
7082
|
+
),
|
|
7083
|
+
{ x: left, y: topY - extensionLength },
|
|
7084
|
+
{
|
|
7085
|
+
stroke: this.lineColor,
|
|
7086
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7087
|
+
}
|
|
7088
|
+
),
|
|
7089
|
+
this.createPathSpec(
|
|
7090
|
+
"ruler.top.ext.end",
|
|
7091
|
+
this.buildLinePath(
|
|
7092
|
+
{ x: right, y: topY - extensionLength },
|
|
7093
|
+
{ x: right, y: topY + extensionLength }
|
|
7094
|
+
),
|
|
7095
|
+
{ x: right, y: topY - extensionLength },
|
|
7096
|
+
{
|
|
7097
|
+
stroke: this.lineColor,
|
|
7098
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7099
|
+
}
|
|
7100
|
+
),
|
|
7101
|
+
this.createTextSpec("ruler.top.label", widthLabel, {
|
|
7102
|
+
x: left + (right - left) / 2,
|
|
7103
|
+
y: topY
|
|
7104
|
+
})
|
|
6417
7105
|
);
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
{
|
|
6427
|
-
stroke: lineColor,
|
|
6428
|
-
strokeWidth
|
|
6429
|
-
|
|
6430
|
-
evented: false
|
|
7106
|
+
specs.push(
|
|
7107
|
+
this.createPathSpec(
|
|
7108
|
+
"ruler.left.line",
|
|
7109
|
+
this.buildLinePath(
|
|
7110
|
+
{ x: leftX, y: leftLineStartY },
|
|
7111
|
+
{ x: leftX, y: leftLineEndY }
|
|
7112
|
+
),
|
|
7113
|
+
{ x: leftX, y: leftLineStartY },
|
|
7114
|
+
{
|
|
7115
|
+
stroke: this.lineColor,
|
|
7116
|
+
strokeWidth,
|
|
7117
|
+
strokeLineCap: "butt"
|
|
6431
7118
|
}
|
|
7119
|
+
),
|
|
7120
|
+
this.createPathSpec(
|
|
7121
|
+
"ruler.left.arrow.start",
|
|
7122
|
+
this.buildStartArrowPath(arrowSize),
|
|
7123
|
+
{ x: leftX, y: top },
|
|
7124
|
+
{
|
|
7125
|
+
fill: this.lineColor,
|
|
7126
|
+
stroke: this.lineColor,
|
|
7127
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7128
|
+
originX: "left",
|
|
7129
|
+
originY: "center",
|
|
7130
|
+
angle: leftLineAngleDeg
|
|
7131
|
+
}
|
|
7132
|
+
),
|
|
7133
|
+
this.createPathSpec(
|
|
7134
|
+
"ruler.left.arrow.end",
|
|
7135
|
+
this.buildEndArrowPath(arrowSize),
|
|
7136
|
+
{ x: leftX, y: bottom },
|
|
7137
|
+
{
|
|
7138
|
+
fill: this.lineColor,
|
|
7139
|
+
stroke: this.lineColor,
|
|
7140
|
+
strokeWidth: this.toSceneDisplayLength(1),
|
|
7141
|
+
originX: "right",
|
|
7142
|
+
originY: "center",
|
|
7143
|
+
angle: leftLineAngleDeg
|
|
7144
|
+
}
|
|
7145
|
+
),
|
|
7146
|
+
this.createPathSpec(
|
|
7147
|
+
"ruler.left.ext.start",
|
|
7148
|
+
this.buildLinePath(
|
|
7149
|
+
{ x: leftX - extensionLength, y: top },
|
|
7150
|
+
{ x: leftX + extensionLength, y: top }
|
|
7151
|
+
),
|
|
7152
|
+
{ x: leftX - extensionLength, y: top },
|
|
7153
|
+
{
|
|
7154
|
+
stroke: this.lineColor,
|
|
7155
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7156
|
+
}
|
|
7157
|
+
),
|
|
7158
|
+
this.createPathSpec(
|
|
7159
|
+
"ruler.left.ext.end",
|
|
7160
|
+
this.buildLinePath(
|
|
7161
|
+
{ x: leftX - extensionLength, y: bottom },
|
|
7162
|
+
{ x: leftX + extensionLength, y: bottom }
|
|
7163
|
+
),
|
|
7164
|
+
{ x: leftX - extensionLength, y: bottom },
|
|
7165
|
+
{
|
|
7166
|
+
stroke: this.lineColor,
|
|
7167
|
+
strokeWidth: this.toSceneDisplayLength(1)
|
|
7168
|
+
}
|
|
7169
|
+
),
|
|
7170
|
+
this.createTextSpec(
|
|
7171
|
+
"ruler.left.label",
|
|
7172
|
+
heightLabel,
|
|
7173
|
+
{
|
|
7174
|
+
x: leftX,
|
|
7175
|
+
y: top + (bottom - top) / 2
|
|
7176
|
+
},
|
|
7177
|
+
-90
|
|
6432
7178
|
)
|
|
6433
7179
|
);
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
7180
|
+
return specs;
|
|
7181
|
+
}
|
|
7182
|
+
updateRuler() {
|
|
7183
|
+
void this.updateRulerAsync();
|
|
7184
|
+
}
|
|
7185
|
+
async updateRulerAsync() {
|
|
7186
|
+
var _a, _b;
|
|
7187
|
+
if (!this.canvasService) return;
|
|
7188
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
7189
|
+
"ConfigurationService"
|
|
7190
|
+
);
|
|
7191
|
+
if (!configService) return;
|
|
7192
|
+
const seq = ++this.renderSeq;
|
|
7193
|
+
const sizeState = readSizeState(configService);
|
|
7194
|
+
const layout = computeSceneLayout(this.canvasService, sizeState);
|
|
7195
|
+
this.log("render:start", {
|
|
7196
|
+
seq,
|
|
7197
|
+
unit: sizeState.unit,
|
|
7198
|
+
gap: this.gap,
|
|
7199
|
+
thickness: this.thickness,
|
|
7200
|
+
fontSize: this.fontSize,
|
|
7201
|
+
hasLayout: !!layout,
|
|
7202
|
+
scale: (_b = layout == null ? void 0 : layout.scale) != null ? _b : null
|
|
6448
7203
|
});
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
7204
|
+
if (!layout || layout.scale <= 0) {
|
|
7205
|
+
if (seq !== this.renderSeq) return;
|
|
7206
|
+
this.log("render:skip", { seq, reason: "invalid-layout" });
|
|
7207
|
+
this.specs = [];
|
|
7208
|
+
await this.canvasService.flushRenderFromProducers();
|
|
7209
|
+
return;
|
|
7210
|
+
}
|
|
7211
|
+
const geometry = buildSceneGeometry(configService, layout);
|
|
7212
|
+
if (geometry.unit !== "px") {
|
|
7213
|
+
console.warn("[RulerTool] Unexpected geometry unit.", geometry.unit);
|
|
7214
|
+
}
|
|
7215
|
+
const centerScene = this.canvasService.toScenePoint({
|
|
7216
|
+
x: geometry.x,
|
|
7217
|
+
y: geometry.y
|
|
7218
|
+
});
|
|
7219
|
+
const widthScene = this.canvasService.toSceneLength(geometry.width);
|
|
7220
|
+
const heightScene = this.canvasService.toSceneLength(geometry.height);
|
|
7221
|
+
const rulerLeft = centerScene.x - widthScene / 2;
|
|
7222
|
+
const rulerTop = centerScene.y - heightScene / 2;
|
|
7223
|
+
const rulerRight = rulerLeft + widthScene;
|
|
7224
|
+
const rulerBottom = rulerTop + heightScene;
|
|
7225
|
+
const widthMm = widthScene;
|
|
7226
|
+
const heightMm = heightScene;
|
|
7227
|
+
const unit = sizeState.unit;
|
|
7228
|
+
const widthLabel = `${this.formatLengthMm(widthMm, unit)} ${unit}`;
|
|
7229
|
+
const heightLabel = `${this.formatLengthMm(heightMm, unit)} ${unit}`;
|
|
7230
|
+
const specs = this.buildRulerSpecs({
|
|
7231
|
+
left: rulerLeft,
|
|
7232
|
+
top: rulerTop,
|
|
7233
|
+
right: rulerRight,
|
|
7234
|
+
bottom: rulerBottom,
|
|
7235
|
+
widthLabel,
|
|
7236
|
+
heightLabel
|
|
7237
|
+
});
|
|
7238
|
+
this.log("render:geometry", {
|
|
7239
|
+
seq,
|
|
7240
|
+
left: rulerLeft,
|
|
7241
|
+
top: rulerTop,
|
|
7242
|
+
right: rulerRight,
|
|
7243
|
+
bottom: rulerBottom,
|
|
7244
|
+
widthScene,
|
|
7245
|
+
heightScene,
|
|
7246
|
+
widthMm,
|
|
7247
|
+
heightMm,
|
|
7248
|
+
specCount: specs.length
|
|
7249
|
+
});
|
|
7250
|
+
if (seq !== this.renderSeq) return;
|
|
7251
|
+
this.specs = specs;
|
|
7252
|
+
await this.canvasService.flushRenderFromProducers();
|
|
7253
|
+
if (seq !== this.renderSeq) return;
|
|
7254
|
+
this.canvasService.bringLayerToFront(RULER_LAYER_ID);
|
|
7255
|
+
this.canvasService.requestRenderAll();
|
|
7256
|
+
this.log("render:done", { seq });
|
|
6452
7257
|
}
|
|
6453
7258
|
};
|
|
6454
7259
|
|
|
@@ -6485,6 +7290,9 @@ var WhiteInkTool = class {
|
|
|
6485
7290
|
this.printWithWhiteInk = true;
|
|
6486
7291
|
this.previewImageVisible = true;
|
|
6487
7292
|
this.renderSeq = 0;
|
|
7293
|
+
this.whiteSpecs = [];
|
|
7294
|
+
this.coverSpecs = [];
|
|
7295
|
+
this.overlaySpecs = [];
|
|
6488
7296
|
this.onToolActivated = (event) => {
|
|
6489
7297
|
const before = this.isToolActive;
|
|
6490
7298
|
this.syncToolActiveFromWorkbench(event.id);
|
|
@@ -6522,12 +7330,25 @@ var WhiteInkTool = class {
|
|
|
6522
7330
|
};
|
|
6523
7331
|
}
|
|
6524
7332
|
activate(context) {
|
|
7333
|
+
var _a;
|
|
6525
7334
|
this.context = context;
|
|
6526
7335
|
this.canvasService = context.services.get("CanvasService");
|
|
6527
7336
|
if (!this.canvasService) {
|
|
6528
7337
|
console.warn("CanvasService not found for WhiteInkTool");
|
|
6529
7338
|
return;
|
|
6530
7339
|
}
|
|
7340
|
+
(_a = this.renderProducerDisposable) == null ? void 0 : _a.dispose();
|
|
7341
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(
|
|
7342
|
+
this.id,
|
|
7343
|
+
() => ({
|
|
7344
|
+
rootLayerSpecs: {
|
|
7345
|
+
[WHITE_INK_OBJECT_LAYER_ID]: this.whiteSpecs,
|
|
7346
|
+
[WHITE_INK_COVER_LAYER_ID]: this.coverSpecs,
|
|
7347
|
+
[WHITE_INK_OVERLAY_LAYER_ID]: this.overlaySpecs
|
|
7348
|
+
}
|
|
7349
|
+
}),
|
|
7350
|
+
{ priority: 260 }
|
|
7351
|
+
);
|
|
6531
7352
|
context.eventBus.on("tool:activated", this.onToolActivated);
|
|
6532
7353
|
context.eventBus.on("scene:layout:change", this.onSceneLayoutChanged);
|
|
6533
7354
|
context.eventBus.on("object:added", this.onObjectAdded);
|
|
@@ -6593,7 +7414,7 @@ var WhiteInkTool = class {
|
|
|
6593
7414
|
this.updateWhiteInks();
|
|
6594
7415
|
}
|
|
6595
7416
|
deactivate(context) {
|
|
6596
|
-
var _a;
|
|
7417
|
+
var _a, _b;
|
|
6597
7418
|
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
6598
7419
|
context.eventBus.off("scene:layout:change", this.onSceneLayoutChanged);
|
|
6599
7420
|
context.eventBus.off("object:added", this.onObjectAdded);
|
|
@@ -6604,6 +7425,11 @@ var WhiteInkTool = class {
|
|
|
6604
7425
|
this.dirtyTrackerDisposable = void 0;
|
|
6605
7426
|
this.clearRenderedWhiteInks();
|
|
6606
7427
|
this.applyImageVisibilityForWhiteInk(false);
|
|
7428
|
+
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
7429
|
+
this.renderProducerDisposable = void 0;
|
|
7430
|
+
if (this.canvasService) {
|
|
7431
|
+
void this.canvasService.flushRenderFromProducers();
|
|
7432
|
+
}
|
|
6607
7433
|
this.canvasService = void 0;
|
|
6608
7434
|
this.context = void 0;
|
|
6609
7435
|
}
|
|
@@ -7026,11 +7852,20 @@ var WhiteInkTool = class {
|
|
|
7026
7852
|
if (!layout) {
|
|
7027
7853
|
return { left: 0, top: 0, width: 0, height: 0 };
|
|
7028
7854
|
}
|
|
7029
|
-
return {
|
|
7855
|
+
return this.canvasService.toSceneRect({
|
|
7030
7856
|
left: layout.cutRect.left,
|
|
7031
7857
|
top: layout.cutRect.top,
|
|
7032
7858
|
width: layout.cutRect.width,
|
|
7033
7859
|
height: layout.cutRect.height
|
|
7860
|
+
});
|
|
7861
|
+
}
|
|
7862
|
+
toLayoutSceneRect(rect) {
|
|
7863
|
+
return {
|
|
7864
|
+
left: rect.left,
|
|
7865
|
+
top: rect.top,
|
|
7866
|
+
width: rect.width,
|
|
7867
|
+
height: rect.height,
|
|
7868
|
+
space: "scene"
|
|
7034
7869
|
};
|
|
7035
7870
|
}
|
|
7036
7871
|
getImageObjects() {
|
|
@@ -7053,7 +7888,7 @@ var WhiteInkTool = class {
|
|
|
7053
7888
|
return (_a = obj == null ? void 0 : obj._originalElement) == null ? void 0 : _a.src;
|
|
7054
7889
|
}
|
|
7055
7890
|
getImageSnapshot(obj) {
|
|
7056
|
-
var _a;
|
|
7891
|
+
var _a, _b;
|
|
7057
7892
|
if (!obj) return null;
|
|
7058
7893
|
const src = this.getCurrentSrc(obj);
|
|
7059
7894
|
if (!src) return null;
|
|
@@ -7061,14 +7896,18 @@ var WhiteInkTool = class {
|
|
|
7061
7896
|
const width = Number((obj == null ? void 0 : obj.width) || 0);
|
|
7062
7897
|
const height = Number((obj == null ? void 0 : obj.height) || 0);
|
|
7063
7898
|
this.rememberSourceSize(src, { width, height });
|
|
7899
|
+
const sceneScale = ((_a = this.canvasService) == null ? void 0 : _a.getSceneScale()) || 1;
|
|
7900
|
+
const leftScreen = Number.isFinite(obj == null ? void 0 : obj.left) ? Number(obj.left) : 0;
|
|
7901
|
+
const topScreen = Number.isFinite(obj == null ? void 0 : obj.top) ? Number(obj.top) : 0;
|
|
7902
|
+
const scenePoint = this.canvasService ? this.canvasService.toScenePoint({ x: leftScreen, y: topScreen }) : { x: leftScreen, y: topScreen };
|
|
7064
7903
|
return {
|
|
7065
|
-
id: String(((
|
|
7904
|
+
id: String(((_b = obj == null ? void 0 : obj.data) == null ? void 0 : _b.id) || "image"),
|
|
7066
7905
|
src,
|
|
7067
7906
|
element,
|
|
7068
|
-
left:
|
|
7069
|
-
top:
|
|
7070
|
-
scaleX: Number.isFinite(obj == null ? void 0 : obj.scaleX) ? Number(obj.scaleX) : 1,
|
|
7071
|
-
scaleY: Number.isFinite(obj == null ? void 0 : obj.scaleY) ? Number(obj.scaleY) : 1,
|
|
7907
|
+
left: scenePoint.x,
|
|
7908
|
+
top: scenePoint.y,
|
|
7909
|
+
scaleX: (Number.isFinite(obj == null ? void 0 : obj.scaleX) ? Number(obj.scaleX) : 1) / sceneScale,
|
|
7910
|
+
scaleY: (Number.isFinite(obj == null ? void 0 : obj.scaleY) ? Number(obj.scaleY) : 1) / sceneScale,
|
|
7072
7911
|
angle: Number.isFinite(obj == null ? void 0 : obj.angle) ? Number(obj.angle) : 0,
|
|
7073
7912
|
originX: typeof (obj == null ? void 0 : obj.originX) === "string" ? obj.originX : "center",
|
|
7074
7913
|
originY: typeof (obj == null ? void 0 : obj.originY) === "string" ? obj.originY : "center",
|
|
@@ -7243,8 +8082,11 @@ var WhiteInkTool = class {
|
|
|
7243
8082
|
var _a, _b;
|
|
7244
8083
|
if (!this.isToolActive || !this.canvasService) return [];
|
|
7245
8084
|
if (frame.width <= 0 || frame.height <= 0) return [];
|
|
7246
|
-
const
|
|
7247
|
-
const
|
|
8085
|
+
const viewport = this.canvasService.getSceneViewportRect();
|
|
8086
|
+
const canvasW = viewport.width || 0;
|
|
8087
|
+
const canvasH = viewport.height || 0;
|
|
8088
|
+
const canvasLeft = viewport.left || 0;
|
|
8089
|
+
const canvasTop = viewport.top || 0;
|
|
7248
8090
|
const strokeColor = this.getConfig("image.frame.strokeColor", "#808080") || "#808080";
|
|
7249
8091
|
const strokeWidthRaw = Number(
|
|
7250
8092
|
(_a = this.getConfig("image.frame.strokeWidth", 2)) != null ? _a : 2
|
|
@@ -7256,21 +8098,42 @@ var WhiteInkTool = class {
|
|
|
7256
8098
|
const innerBackground = this.getConfig("image.frame.innerBackground", "rgba(0,0,0,0)") || "rgba(0,0,0,0)";
|
|
7257
8099
|
const strokeWidth = Number.isFinite(strokeWidthRaw) ? Math.max(0, strokeWidthRaw) : 2;
|
|
7258
8100
|
const dashLength = Number.isFinite(dashLengthRaw) ? Math.max(1, dashLengthRaw) : 8;
|
|
7259
|
-
const
|
|
7260
|
-
const
|
|
8101
|
+
const strokeWidthScene = this.canvasService.toSceneLength(strokeWidth);
|
|
8102
|
+
const dashLengthScene = this.canvasService.toSceneLength(dashLength);
|
|
8103
|
+
const frameLeft = Math.max(
|
|
8104
|
+
canvasLeft,
|
|
8105
|
+
Math.min(canvasLeft + canvasW, frame.left)
|
|
8106
|
+
);
|
|
8107
|
+
const frameTop = Math.max(
|
|
8108
|
+
canvasTop,
|
|
8109
|
+
Math.min(canvasTop + canvasH, frame.top)
|
|
8110
|
+
);
|
|
7261
8111
|
const frameRight = Math.max(
|
|
7262
8112
|
frameLeft,
|
|
7263
|
-
Math.min(canvasW, frame.left + frame.width)
|
|
8113
|
+
Math.min(canvasLeft + canvasW, frame.left + frame.width)
|
|
7264
8114
|
);
|
|
7265
8115
|
const frameBottom = Math.max(
|
|
7266
8116
|
frameTop,
|
|
7267
|
-
Math.min(canvasH, frame.top + frame.height)
|
|
8117
|
+
Math.min(canvasTop + canvasH, frame.top + frame.height)
|
|
7268
8118
|
);
|
|
7269
8119
|
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
7270
|
-
const topH = frameTop;
|
|
7271
|
-
const bottomH = Math.max(0, canvasH - frameBottom);
|
|
7272
|
-
const leftW = frameLeft;
|
|
7273
|
-
const rightW = Math.max(0, canvasW - frameRight);
|
|
8120
|
+
const topH = Math.max(0, frameTop - canvasTop);
|
|
8121
|
+
const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
|
|
8122
|
+
const leftW = Math.max(0, frameLeft - canvasLeft);
|
|
8123
|
+
const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
|
|
8124
|
+
const viewportRect = this.toLayoutSceneRect({
|
|
8125
|
+
left: canvasLeft,
|
|
8126
|
+
top: canvasTop,
|
|
8127
|
+
width: canvasW,
|
|
8128
|
+
height: canvasH
|
|
8129
|
+
});
|
|
8130
|
+
const visibleFrameBandRect = this.toLayoutSceneRect({
|
|
8131
|
+
left: canvasLeft,
|
|
8132
|
+
top: frameTop,
|
|
8133
|
+
width: canvasW,
|
|
8134
|
+
height: visibleFrameH
|
|
8135
|
+
});
|
|
8136
|
+
const frameRect = this.toLayoutSceneRect(frame);
|
|
7274
8137
|
const maskSpecs = [
|
|
7275
8138
|
{
|
|
7276
8139
|
id: "white-ink.cropMask.top",
|
|
@@ -7280,13 +8143,17 @@ var WhiteInkTool = class {
|
|
|
7280
8143
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7281
8144
|
type: "white-ink-mask"
|
|
7282
8145
|
},
|
|
8146
|
+
layout: {
|
|
8147
|
+
reference: "custom",
|
|
8148
|
+
referenceRect: viewportRect,
|
|
8149
|
+
alignX: "start",
|
|
8150
|
+
alignY: "start",
|
|
8151
|
+
width: "100%",
|
|
8152
|
+
height: topH
|
|
8153
|
+
},
|
|
7283
8154
|
props: {
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
width: canvasW,
|
|
7287
|
-
height: topH,
|
|
7288
|
-
originX: "center",
|
|
7289
|
-
originY: "center",
|
|
8155
|
+
originX: "left",
|
|
8156
|
+
originY: "top",
|
|
7290
8157
|
fill: outerBackground,
|
|
7291
8158
|
selectable: false,
|
|
7292
8159
|
evented: false,
|
|
@@ -7301,13 +8168,17 @@ var WhiteInkTool = class {
|
|
|
7301
8168
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7302
8169
|
type: "white-ink-mask"
|
|
7303
8170
|
},
|
|
8171
|
+
layout: {
|
|
8172
|
+
reference: "custom",
|
|
8173
|
+
referenceRect: viewportRect,
|
|
8174
|
+
alignX: "start",
|
|
8175
|
+
alignY: "end",
|
|
8176
|
+
width: "100%",
|
|
8177
|
+
height: bottomH
|
|
8178
|
+
},
|
|
7304
8179
|
props: {
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
width: canvasW,
|
|
7308
|
-
height: bottomH,
|
|
7309
|
-
originX: "center",
|
|
7310
|
-
originY: "center",
|
|
8180
|
+
originX: "left",
|
|
8181
|
+
originY: "top",
|
|
7311
8182
|
fill: outerBackground,
|
|
7312
8183
|
selectable: false,
|
|
7313
8184
|
evented: false,
|
|
@@ -7322,13 +8193,17 @@ var WhiteInkTool = class {
|
|
|
7322
8193
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7323
8194
|
type: "white-ink-mask"
|
|
7324
8195
|
},
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
8196
|
+
layout: {
|
|
8197
|
+
reference: "custom",
|
|
8198
|
+
referenceRect: visibleFrameBandRect,
|
|
8199
|
+
alignX: "start",
|
|
8200
|
+
alignY: "start",
|
|
7328
8201
|
width: leftW,
|
|
7329
|
-
height:
|
|
7330
|
-
|
|
7331
|
-
|
|
8202
|
+
height: "100%"
|
|
8203
|
+
},
|
|
8204
|
+
props: {
|
|
8205
|
+
originX: "left",
|
|
8206
|
+
originY: "top",
|
|
7332
8207
|
fill: outerBackground,
|
|
7333
8208
|
selectable: false,
|
|
7334
8209
|
evented: false,
|
|
@@ -7343,13 +8218,17 @@ var WhiteInkTool = class {
|
|
|
7343
8218
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7344
8219
|
type: "white-ink-mask"
|
|
7345
8220
|
},
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
8221
|
+
layout: {
|
|
8222
|
+
reference: "custom",
|
|
8223
|
+
referenceRect: visibleFrameBandRect,
|
|
8224
|
+
alignX: "end",
|
|
8225
|
+
alignY: "start",
|
|
7349
8226
|
width: rightW,
|
|
7350
|
-
height:
|
|
7351
|
-
|
|
7352
|
-
|
|
8227
|
+
height: "100%"
|
|
8228
|
+
},
|
|
8229
|
+
props: {
|
|
8230
|
+
originX: "left",
|
|
8231
|
+
originY: "top",
|
|
7353
8232
|
fill: outerBackground,
|
|
7354
8233
|
selectable: false,
|
|
7355
8234
|
evented: false,
|
|
@@ -7367,17 +8246,21 @@ var WhiteInkTool = class {
|
|
|
7367
8246
|
layerId: WHITE_INK_OVERLAY_LAYER_ID,
|
|
7368
8247
|
type: "white-ink-frame"
|
|
7369
8248
|
},
|
|
8249
|
+
layout: {
|
|
8250
|
+
reference: "custom",
|
|
8251
|
+
referenceRect: frameRect,
|
|
8252
|
+
alignX: "start",
|
|
8253
|
+
alignY: "start",
|
|
8254
|
+
width: "100%",
|
|
8255
|
+
height: "100%"
|
|
8256
|
+
},
|
|
7370
8257
|
props: {
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
width: frame.width,
|
|
7374
|
-
height: frame.height,
|
|
7375
|
-
originX: "center",
|
|
7376
|
-
originY: "center",
|
|
8258
|
+
originX: "left",
|
|
8259
|
+
originY: "top",
|
|
7377
8260
|
fill: innerBackground,
|
|
7378
8261
|
stroke: strokeColor,
|
|
7379
|
-
strokeWidth,
|
|
7380
|
-
strokeDashArray: [
|
|
8262
|
+
strokeWidth: strokeWidthScene,
|
|
8263
|
+
strokeDashArray: [dashLengthScene, dashLengthScene],
|
|
7381
8264
|
selectable: false,
|
|
7382
8265
|
evented: false,
|
|
7383
8266
|
excludeFromExport: true
|
|
@@ -7453,50 +8336,30 @@ var WhiteInkTool = class {
|
|
|
7453
8336
|
}
|
|
7454
8337
|
).filter((index) => index >= 0);
|
|
7455
8338
|
let whiteInsertIndex = imageIndexes.length ? Math.min(...imageIndexes) : this.resolveDefaultInsertIndex(currentObjects);
|
|
7456
|
-
|
|
7457
|
-
canvas.moveObjectTo(obj, whiteInsertIndex);
|
|
7458
|
-
whiteInsertIndex += 1;
|
|
7459
|
-
});
|
|
7460
|
-
const afterWhiteObjects = canvas.getObjects();
|
|
7461
|
-
const afterImageIndexes = afterWhiteObjects.map(
|
|
7462
|
-
(obj, index) => {
|
|
7463
|
-
var _a;
|
|
7464
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID3 ? index : -1;
|
|
7465
|
-
}
|
|
7466
|
-
).filter((index) => index >= 0);
|
|
7467
|
-
let coverInsertIndex = afterImageIndexes.length ? Math.max(...afterImageIndexes) + 1 : whiteInsertIndex;
|
|
8339
|
+
let coverInsertIndex = whiteInsertIndex;
|
|
7468
8340
|
coverObjects.forEach((obj) => {
|
|
7469
8341
|
canvas.moveObjectTo(obj, coverInsertIndex);
|
|
7470
8342
|
coverInsertIndex += 1;
|
|
7471
8343
|
});
|
|
8344
|
+
whiteInsertIndex = coverInsertIndex;
|
|
8345
|
+
whiteObjects.forEach((obj) => {
|
|
8346
|
+
canvas.moveObjectTo(obj, whiteInsertIndex);
|
|
8347
|
+
whiteInsertIndex += 1;
|
|
8348
|
+
});
|
|
7472
8349
|
frameObjects.forEach((obj) => canvas.bringObjectToFront(obj));
|
|
7473
8350
|
canvas.getObjects().filter((obj) => {
|
|
7474
8351
|
var _a;
|
|
7475
8352
|
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OVERLAY_LAYER_ID2;
|
|
7476
8353
|
}).forEach((obj) => canvas.bringObjectToFront(obj));
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
canvas.bringObjectToFront(dielineOverlay);
|
|
7480
|
-
}
|
|
7481
|
-
const rulerOverlay = this.canvasService.getLayer("ruler-overlay");
|
|
7482
|
-
if (rulerOverlay) {
|
|
7483
|
-
canvas.bringObjectToFront(rulerOverlay);
|
|
7484
|
-
}
|
|
8354
|
+
this.canvasService.bringLayerToFront("dieline-overlay");
|
|
8355
|
+
this.canvasService.bringLayerToFront("ruler-overlay");
|
|
7485
8356
|
}
|
|
7486
8357
|
clearRenderedWhiteInks() {
|
|
7487
8358
|
if (!this.canvasService) return;
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
);
|
|
7492
|
-
void this.canvasService.applyObjectSpecsToRootLayer(
|
|
7493
|
-
WHITE_INK_COVER_LAYER_ID,
|
|
7494
|
-
[]
|
|
7495
|
-
);
|
|
7496
|
-
void this.canvasService.applyObjectSpecsToRootLayer(
|
|
7497
|
-
WHITE_INK_OVERLAY_LAYER_ID,
|
|
7498
|
-
[]
|
|
7499
|
-
);
|
|
8359
|
+
this.whiteSpecs = [];
|
|
8360
|
+
this.coverSpecs = [];
|
|
8361
|
+
this.overlaySpecs = [];
|
|
8362
|
+
this.canvasService.requestRenderFromProducers();
|
|
7500
8363
|
}
|
|
7501
8364
|
purgeSourceCaches(item) {
|
|
7502
8365
|
const sourceUrl = this.resolveSourceUrl(item);
|
|
@@ -7563,20 +8426,12 @@ var WhiteInkTool = class {
|
|
|
7563
8426
|
}
|
|
7564
8427
|
}
|
|
7565
8428
|
}
|
|
7566
|
-
|
|
7567
|
-
WHITE_INK_OBJECT_LAYER_ID,
|
|
7568
|
-
whiteSpecs
|
|
7569
|
-
);
|
|
8429
|
+
this.whiteSpecs = whiteSpecs;
|
|
7570
8430
|
if (seq !== this.renderSeq) return;
|
|
7571
|
-
|
|
7572
|
-
WHITE_INK_COVER_LAYER_ID,
|
|
7573
|
-
coverSpecs
|
|
7574
|
-
);
|
|
8431
|
+
this.coverSpecs = coverSpecs;
|
|
7575
8432
|
if (seq !== this.renderSeq) return;
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
frameSpecs
|
|
7579
|
-
);
|
|
8433
|
+
this.overlaySpecs = frameSpecs;
|
|
8434
|
+
await this.canvasService.flushRenderFromProducers();
|
|
7580
8435
|
if (seq !== this.renderSeq) return;
|
|
7581
8436
|
this.syncZOrder();
|
|
7582
8437
|
this.canvasService.requestRenderAll();
|
|
@@ -7806,23 +8661,16 @@ var SceneVisibilityService = class {
|
|
|
7806
8661
|
const dielineLayer = this.canvasService.getLayer("dieline-overlay");
|
|
7807
8662
|
if (dielineLayer) {
|
|
7808
8663
|
const visible = !HIDDEN_DIELINE_TOOLS.has(this.activeToolId || "");
|
|
7809
|
-
|
|
7810
|
-
dielineLayer.set({ visible });
|
|
7811
|
-
}
|
|
7812
|
-
}
|
|
7813
|
-
const rulerLayer = this.canvasService.getLayer("ruler-overlay");
|
|
7814
|
-
if (rulerLayer) {
|
|
7815
|
-
const visible = !HIDDEN_RULER_TOOLS.has(this.activeToolId || "");
|
|
7816
|
-
if (rulerLayer.visible !== visible) {
|
|
7817
|
-
rulerLayer.set({ visible });
|
|
7818
|
-
}
|
|
8664
|
+
this.canvasService.setLayerVisibility("dieline-overlay", visible);
|
|
7819
8665
|
}
|
|
8666
|
+
const rulerVisible = !HIDDEN_RULER_TOOLS.has(this.activeToolId || "");
|
|
8667
|
+
this.canvasService.setLayerVisibility("ruler-overlay", rulerVisible);
|
|
7820
8668
|
this.canvasService.requestRenderAll();
|
|
7821
8669
|
}
|
|
7822
8670
|
};
|
|
7823
8671
|
|
|
7824
8672
|
// src/services/CanvasService.ts
|
|
7825
|
-
var
|
|
8673
|
+
var import_fabric5 = require("fabric");
|
|
7826
8674
|
|
|
7827
8675
|
// src/services/ViewportSystem.ts
|
|
7828
8676
|
var ViewportSystem = class {
|
|
@@ -7900,10 +8748,17 @@ var ViewportSystem = class {
|
|
|
7900
8748
|
// src/services/CanvasService.ts
|
|
7901
8749
|
var CanvasService = class {
|
|
7902
8750
|
constructor(el, options) {
|
|
7903
|
-
|
|
8751
|
+
this.renderProducers = /* @__PURE__ */ new Map();
|
|
8752
|
+
this.producerOrder = 0;
|
|
8753
|
+
this.producerFlushRequested = false;
|
|
8754
|
+
this.producerLoopPending = false;
|
|
8755
|
+
this.producerLoopPromise = null;
|
|
8756
|
+
this.managedProducerLayerIds = /* @__PURE__ */ new Set();
|
|
8757
|
+
this.managedProducerRootLayerIds = /* @__PURE__ */ new Set();
|
|
8758
|
+
if (el instanceof import_fabric5.Canvas) {
|
|
7904
8759
|
this.canvas = el;
|
|
7905
8760
|
} else {
|
|
7906
|
-
this.canvas = new
|
|
8761
|
+
this.canvas = new import_fabric5.Canvas(el, {
|
|
7907
8762
|
preserveObjectStacking: true,
|
|
7908
8763
|
...options
|
|
7909
8764
|
});
|
|
@@ -7932,8 +8787,156 @@ var CanvasService = class {
|
|
|
7932
8787
|
this.canvas.on("object:removed", forward("object:removed"));
|
|
7933
8788
|
}
|
|
7934
8789
|
dispose() {
|
|
8790
|
+
this.renderProducers.clear();
|
|
8791
|
+
this.managedProducerLayerIds.clear();
|
|
8792
|
+
this.managedProducerRootLayerIds.clear();
|
|
8793
|
+
this.producerFlushRequested = false;
|
|
7935
8794
|
this.canvas.dispose();
|
|
7936
8795
|
}
|
|
8796
|
+
registerRenderProducer(toolId, producer, options = {}) {
|
|
8797
|
+
const normalizedToolId = String(toolId || "").trim();
|
|
8798
|
+
if (!normalizedToolId) {
|
|
8799
|
+
throw new Error(
|
|
8800
|
+
"[CanvasService] registerRenderProducer requires a toolId."
|
|
8801
|
+
);
|
|
8802
|
+
}
|
|
8803
|
+
if (typeof producer !== "function") {
|
|
8804
|
+
throw new Error(
|
|
8805
|
+
`[CanvasService] registerRenderProducer("${normalizedToolId}") requires a producer function.`
|
|
8806
|
+
);
|
|
8807
|
+
}
|
|
8808
|
+
const entry = {
|
|
8809
|
+
toolId: normalizedToolId,
|
|
8810
|
+
producer,
|
|
8811
|
+
priority: Number.isFinite(options.priority) ? Number(options.priority) : 0,
|
|
8812
|
+
order: this.producerOrder++
|
|
8813
|
+
};
|
|
8814
|
+
this.renderProducers.set(normalizedToolId, entry);
|
|
8815
|
+
this.requestRenderFromProducers();
|
|
8816
|
+
return {
|
|
8817
|
+
dispose: () => {
|
|
8818
|
+
this.unregisterRenderProducer(normalizedToolId);
|
|
8819
|
+
}
|
|
8820
|
+
};
|
|
8821
|
+
}
|
|
8822
|
+
unregisterRenderProducer(toolId) {
|
|
8823
|
+
const normalizedToolId = String(toolId || "").trim();
|
|
8824
|
+
if (!normalizedToolId) return false;
|
|
8825
|
+
const removed = this.renderProducers.delete(normalizedToolId);
|
|
8826
|
+
if (removed) {
|
|
8827
|
+
this.requestRenderFromProducers();
|
|
8828
|
+
}
|
|
8829
|
+
return removed;
|
|
8830
|
+
}
|
|
8831
|
+
requestRenderFromProducers() {
|
|
8832
|
+
this.producerFlushRequested = true;
|
|
8833
|
+
this.scheduleProducerLoop();
|
|
8834
|
+
}
|
|
8835
|
+
async flushRenderFromProducers() {
|
|
8836
|
+
this.requestRenderFromProducers();
|
|
8837
|
+
if (this.producerLoopPromise) {
|
|
8838
|
+
await this.producerLoopPromise;
|
|
8839
|
+
}
|
|
8840
|
+
}
|
|
8841
|
+
scheduleProducerLoop() {
|
|
8842
|
+
if (this.producerLoopPending) return;
|
|
8843
|
+
this.producerLoopPending = true;
|
|
8844
|
+
this.producerLoopPromise = Promise.resolve().then(() => this.runProducerLoop()).catch((error) => {
|
|
8845
|
+
console.error("[CanvasService] render producer loop failed.", error);
|
|
8846
|
+
}).finally(() => {
|
|
8847
|
+
this.producerLoopPending = false;
|
|
8848
|
+
if (this.producerFlushRequested) {
|
|
8849
|
+
this.scheduleProducerLoop();
|
|
8850
|
+
}
|
|
8851
|
+
});
|
|
8852
|
+
}
|
|
8853
|
+
async runProducerLoop() {
|
|
8854
|
+
while (this.producerFlushRequested) {
|
|
8855
|
+
this.producerFlushRequested = false;
|
|
8856
|
+
await this.collectAndApplyProducerSpecs();
|
|
8857
|
+
}
|
|
8858
|
+
}
|
|
8859
|
+
sortedRenderProducerEntries() {
|
|
8860
|
+
return Array.from(this.renderProducers.values()).sort((a, b) => {
|
|
8861
|
+
if (a.priority !== b.priority) {
|
|
8862
|
+
return a.priority - b.priority;
|
|
8863
|
+
}
|
|
8864
|
+
if (a.order !== b.order) {
|
|
8865
|
+
return a.order - b.order;
|
|
8866
|
+
}
|
|
8867
|
+
return a.toolId.localeCompare(b.toolId);
|
|
8868
|
+
});
|
|
8869
|
+
}
|
|
8870
|
+
appendLayerSpecMap(map, source) {
|
|
8871
|
+
if (!source) return;
|
|
8872
|
+
Object.entries(source).forEach(([layerId, specs]) => {
|
|
8873
|
+
if (!Array.isArray(specs)) return;
|
|
8874
|
+
const list = map.get(layerId) || [];
|
|
8875
|
+
list.push(...specs);
|
|
8876
|
+
map.set(layerId, list);
|
|
8877
|
+
});
|
|
8878
|
+
}
|
|
8879
|
+
async collectAndApplyProducerSpecs() {
|
|
8880
|
+
const groupLayerSpecs = /* @__PURE__ */ new Map();
|
|
8881
|
+
const rootLayerSpecs = /* @__PURE__ */ new Map();
|
|
8882
|
+
const replaceLayerIds = /* @__PURE__ */ new Set();
|
|
8883
|
+
const replaceRootLayerIds = /* @__PURE__ */ new Set();
|
|
8884
|
+
const entries = this.sortedRenderProducerEntries();
|
|
8885
|
+
for (const entry of entries) {
|
|
8886
|
+
try {
|
|
8887
|
+
const result = await entry.producer();
|
|
8888
|
+
if (!result) continue;
|
|
8889
|
+
this.appendLayerSpecMap(groupLayerSpecs, result.layerSpecs);
|
|
8890
|
+
this.appendLayerSpecMap(rootLayerSpecs, result.rootLayerSpecs);
|
|
8891
|
+
if (Array.isArray(result.replaceLayerIds)) {
|
|
8892
|
+
result.replaceLayerIds.forEach((layerId) => {
|
|
8893
|
+
if (layerId) replaceLayerIds.add(layerId);
|
|
8894
|
+
});
|
|
8895
|
+
}
|
|
8896
|
+
if (Array.isArray(result.replaceRootLayerIds)) {
|
|
8897
|
+
result.replaceRootLayerIds.forEach((layerId) => {
|
|
8898
|
+
if (layerId) replaceRootLayerIds.add(layerId);
|
|
8899
|
+
});
|
|
8900
|
+
}
|
|
8901
|
+
} catch (error) {
|
|
8902
|
+
console.error(
|
|
8903
|
+
`[CanvasService] render producer "${entry.toolId}" failed.`,
|
|
8904
|
+
error
|
|
8905
|
+
);
|
|
8906
|
+
}
|
|
8907
|
+
}
|
|
8908
|
+
const nextLayerIds = new Set(groupLayerSpecs.keys());
|
|
8909
|
+
const nextRootLayerIds = new Set(rootLayerSpecs.keys());
|
|
8910
|
+
for (const [layerId, specs] of groupLayerSpecs.entries()) {
|
|
8911
|
+
if (replaceLayerIds.has(layerId)) {
|
|
8912
|
+
const layer = this.getLayer(layerId);
|
|
8913
|
+
if (layer) {
|
|
8914
|
+
layer.getObjects().forEach((obj) => layer.remove(obj));
|
|
8915
|
+
}
|
|
8916
|
+
}
|
|
8917
|
+
await this.applyObjectSpecsToLayer(layerId, specs, { render: false });
|
|
8918
|
+
}
|
|
8919
|
+
for (const layerId of this.managedProducerLayerIds) {
|
|
8920
|
+
if (nextLayerIds.has(layerId)) continue;
|
|
8921
|
+
const layer = this.getLayer(layerId);
|
|
8922
|
+
if (!layer) continue;
|
|
8923
|
+
await this.applyObjectSpecsToContainer(layer, [], { render: false });
|
|
8924
|
+
}
|
|
8925
|
+
for (const [layerId, specs] of rootLayerSpecs.entries()) {
|
|
8926
|
+
if (replaceRootLayerIds.has(layerId)) {
|
|
8927
|
+
const existing = this.getRootLayerObjects(layerId);
|
|
8928
|
+
existing.forEach((obj) => this.canvas.remove(obj));
|
|
8929
|
+
}
|
|
8930
|
+
await this.applyObjectSpecsToRootLayer(layerId, specs, { render: false });
|
|
8931
|
+
}
|
|
8932
|
+
for (const layerId of this.managedProducerRootLayerIds) {
|
|
8933
|
+
if (nextRootLayerIds.has(layerId)) continue;
|
|
8934
|
+
await this.applyObjectSpecsToRootLayer(layerId, [], { render: false });
|
|
8935
|
+
}
|
|
8936
|
+
this.managedProducerLayerIds = nextLayerIds;
|
|
8937
|
+
this.managedProducerRootLayerIds = nextRootLayerIds;
|
|
8938
|
+
this.requestRenderAll();
|
|
8939
|
+
}
|
|
7937
8940
|
/**
|
|
7938
8941
|
* Get a layer (Group) by its ID.
|
|
7939
8942
|
* We assume layers are Groups directly on the canvas with a data.id property.
|
|
@@ -7956,7 +8959,7 @@ var CanvasService = class {
|
|
|
7956
8959
|
...options,
|
|
7957
8960
|
data: { ...options.data, id }
|
|
7958
8961
|
};
|
|
7959
|
-
layer = new
|
|
8962
|
+
layer = new import_fabric5.Group([], defaultOptions);
|
|
7960
8963
|
this.canvas.add(layer);
|
|
7961
8964
|
}
|
|
7962
8965
|
return layer;
|
|
@@ -7988,13 +8991,206 @@ var CanvasService = class {
|
|
|
7988
8991
|
(_a = this.eventBus) == null ? void 0 : _a.emit("canvas:resized", { width, height });
|
|
7989
8992
|
this.requestRenderAll();
|
|
7990
8993
|
}
|
|
8994
|
+
getSceneScale() {
|
|
8995
|
+
const scale = Number(this.viewport.scale);
|
|
8996
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
8997
|
+
}
|
|
8998
|
+
getSceneOffset() {
|
|
8999
|
+
const offset = this.viewport.offset;
|
|
9000
|
+
const x = Number(offset.x);
|
|
9001
|
+
const y = Number(offset.y);
|
|
9002
|
+
return {
|
|
9003
|
+
x: Number.isFinite(x) ? x : 0,
|
|
9004
|
+
y: Number.isFinite(y) ? y : 0
|
|
9005
|
+
};
|
|
9006
|
+
}
|
|
9007
|
+
toScreenPoint(point) {
|
|
9008
|
+
const scale = this.getSceneScale();
|
|
9009
|
+
const offset = this.getSceneOffset();
|
|
9010
|
+
return {
|
|
9011
|
+
x: point.x * scale + offset.x,
|
|
9012
|
+
y: point.y * scale + offset.y
|
|
9013
|
+
};
|
|
9014
|
+
}
|
|
9015
|
+
toScenePoint(point) {
|
|
9016
|
+
const scale = this.getSceneScale();
|
|
9017
|
+
const offset = this.getSceneOffset();
|
|
9018
|
+
return {
|
|
9019
|
+
x: (point.x - offset.x) / scale,
|
|
9020
|
+
y: (point.y - offset.y) / scale
|
|
9021
|
+
};
|
|
9022
|
+
}
|
|
9023
|
+
toScreenLength(value) {
|
|
9024
|
+
return value * this.getSceneScale();
|
|
9025
|
+
}
|
|
9026
|
+
toSceneLength(value) {
|
|
9027
|
+
return value / this.getSceneScale();
|
|
9028
|
+
}
|
|
9029
|
+
toScreenRect(rect) {
|
|
9030
|
+
const start = this.toScreenPoint({ x: rect.left, y: rect.top });
|
|
9031
|
+
return {
|
|
9032
|
+
left: start.x,
|
|
9033
|
+
top: start.y,
|
|
9034
|
+
width: this.toScreenLength(rect.width),
|
|
9035
|
+
height: this.toScreenLength(rect.height)
|
|
9036
|
+
};
|
|
9037
|
+
}
|
|
9038
|
+
toSceneRect(rect) {
|
|
9039
|
+
const start = this.toScenePoint({ x: rect.left, y: rect.top });
|
|
9040
|
+
return {
|
|
9041
|
+
left: start.x,
|
|
9042
|
+
top: start.y,
|
|
9043
|
+
width: this.toSceneLength(rect.width),
|
|
9044
|
+
height: this.toSceneLength(rect.height)
|
|
9045
|
+
};
|
|
9046
|
+
}
|
|
9047
|
+
getSceneViewportRect() {
|
|
9048
|
+
const width = Number(this.canvas.width || 0);
|
|
9049
|
+
const height = Number(this.canvas.height || 0);
|
|
9050
|
+
return this.toSceneRect({ left: 0, top: 0, width, height });
|
|
9051
|
+
}
|
|
9052
|
+
getScreenViewportRect() {
|
|
9053
|
+
return {
|
|
9054
|
+
left: 0,
|
|
9055
|
+
top: 0,
|
|
9056
|
+
width: Number(this.canvas.width || 0),
|
|
9057
|
+
height: Number(this.canvas.height || 0)
|
|
9058
|
+
};
|
|
9059
|
+
}
|
|
9060
|
+
toSpaceRect(rect, from, to) {
|
|
9061
|
+
if (from === to) return { ...rect };
|
|
9062
|
+
if (from === "scene") {
|
|
9063
|
+
return this.toScreenRect(rect);
|
|
9064
|
+
}
|
|
9065
|
+
return this.toSceneRect(rect);
|
|
9066
|
+
}
|
|
9067
|
+
resolveLayoutLength(value, base) {
|
|
9068
|
+
if (typeof value === "number") {
|
|
9069
|
+
return Number.isFinite(value) ? value : void 0;
|
|
9070
|
+
}
|
|
9071
|
+
if (typeof value !== "string") {
|
|
9072
|
+
return void 0;
|
|
9073
|
+
}
|
|
9074
|
+
const raw = value.trim();
|
|
9075
|
+
if (!raw) return void 0;
|
|
9076
|
+
if (raw.endsWith("%")) {
|
|
9077
|
+
const percent = parseFloat(raw.slice(0, -1));
|
|
9078
|
+
if (!Number.isFinite(percent)) return void 0;
|
|
9079
|
+
return base * percent / 100;
|
|
9080
|
+
}
|
|
9081
|
+
const parsed = parseFloat(raw);
|
|
9082
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
9083
|
+
}
|
|
9084
|
+
resolveLayoutInsets(inset, reference) {
|
|
9085
|
+
var _a, _b, _c, _d, _e;
|
|
9086
|
+
if (typeof inset === "number" || typeof inset === "string") {
|
|
9087
|
+
const all = (_a = this.resolveLayoutLength(
|
|
9088
|
+
inset,
|
|
9089
|
+
Math.min(reference.width, reference.height)
|
|
9090
|
+
)) != null ? _a : 0;
|
|
9091
|
+
return { top: all, right: all, bottom: all, left: all };
|
|
9092
|
+
}
|
|
9093
|
+
const source = inset || {};
|
|
9094
|
+
const top = (_b = this.resolveLayoutLength(source.top, reference.height)) != null ? _b : 0;
|
|
9095
|
+
const right = (_c = this.resolveLayoutLength(source.right, reference.width)) != null ? _c : 0;
|
|
9096
|
+
const bottom = (_d = this.resolveLayoutLength(source.bottom, reference.height)) != null ? _d : 0;
|
|
9097
|
+
const left = (_e = this.resolveLayoutLength(source.left, reference.width)) != null ? _e : 0;
|
|
9098
|
+
return { top, right, bottom, left };
|
|
9099
|
+
}
|
|
9100
|
+
resolveLayoutReferenceRect(layout, space) {
|
|
9101
|
+
if (layout.referenceRect) {
|
|
9102
|
+
const sourceSpace = layout.referenceRect.space || space;
|
|
9103
|
+
return this.toSpaceRect(layout.referenceRect, sourceSpace, space);
|
|
9104
|
+
}
|
|
9105
|
+
const reference = layout.reference || "sceneViewport";
|
|
9106
|
+
if (reference === "screenViewport") {
|
|
9107
|
+
const screenRect = this.getScreenViewportRect();
|
|
9108
|
+
return space === "screen" ? screenRect : this.toSceneRect(screenRect);
|
|
9109
|
+
}
|
|
9110
|
+
const sceneRect = this.getSceneViewportRect();
|
|
9111
|
+
return space === "scene" ? sceneRect : this.toScreenRect(sceneRect);
|
|
9112
|
+
}
|
|
9113
|
+
alignFactor(value) {
|
|
9114
|
+
if (value === "end") return 1;
|
|
9115
|
+
if (value === "center") return 0.5;
|
|
9116
|
+
return 0;
|
|
9117
|
+
}
|
|
9118
|
+
normalizeOriginX(value) {
|
|
9119
|
+
if (value === "center") return "center";
|
|
9120
|
+
if (value === "right") return "right";
|
|
9121
|
+
return "left";
|
|
9122
|
+
}
|
|
9123
|
+
normalizeOriginY(value) {
|
|
9124
|
+
if (value === "center") return "center";
|
|
9125
|
+
if (value === "bottom") return "bottom";
|
|
9126
|
+
return "top";
|
|
9127
|
+
}
|
|
9128
|
+
originFactor(value) {
|
|
9129
|
+
if (value === "center") return 0.5;
|
|
9130
|
+
if (value === "right" || value === "bottom") return 1;
|
|
9131
|
+
return 0;
|
|
9132
|
+
}
|
|
9133
|
+
resolveLayoutProps(spec, props) {
|
|
9134
|
+
var _a, _b, _c, _d;
|
|
9135
|
+
const layout = spec.layout;
|
|
9136
|
+
if (!layout) {
|
|
9137
|
+
return { ...props };
|
|
9138
|
+
}
|
|
9139
|
+
const space = spec.space || "scene";
|
|
9140
|
+
const reference = this.resolveLayoutReferenceRect(layout, space);
|
|
9141
|
+
const inset = this.resolveLayoutInsets(layout.inset, reference);
|
|
9142
|
+
const area = {
|
|
9143
|
+
left: reference.left + inset.left,
|
|
9144
|
+
top: reference.top + inset.top,
|
|
9145
|
+
width: Math.max(0, reference.width - inset.left - inset.right),
|
|
9146
|
+
height: Math.max(0, reference.height - inset.top - inset.bottom)
|
|
9147
|
+
};
|
|
9148
|
+
const next = { ...props };
|
|
9149
|
+
const width = (_a = this.resolveLayoutLength(layout.width, area.width)) != null ? _a : Number.isFinite(next.width) ? Number(next.width) : void 0;
|
|
9150
|
+
const height = (_b = this.resolveLayoutLength(layout.height, area.height)) != null ? _b : Number.isFinite(next.height) ? Number(next.height) : void 0;
|
|
9151
|
+
if (width !== void 0) next.width = width;
|
|
9152
|
+
if (height !== void 0) next.height = height;
|
|
9153
|
+
const alignX = this.alignFactor(layout.alignX);
|
|
9154
|
+
const alignY = this.alignFactor(layout.alignY);
|
|
9155
|
+
const offsetX = (_c = this.resolveLayoutLength(layout.offsetX, area.width)) != null ? _c : 0;
|
|
9156
|
+
const offsetY = (_d = this.resolveLayoutLength(layout.offsetY, area.height)) != null ? _d : 0;
|
|
9157
|
+
const objectWidth = Number.isFinite(next.width) ? Number(next.width) : 0;
|
|
9158
|
+
const objectHeight = Number.isFinite(next.height) ? Number(next.height) : 0;
|
|
9159
|
+
const objectLeft = area.left + (area.width - objectWidth) * alignX + offsetX;
|
|
9160
|
+
const objectTop = area.top + (area.height - objectHeight) * alignY + offsetY;
|
|
9161
|
+
const originX = this.normalizeOriginX(next.originX);
|
|
9162
|
+
const originY = this.normalizeOriginY(next.originY);
|
|
9163
|
+
next.left = objectLeft + objectWidth * this.originFactor(originX);
|
|
9164
|
+
next.top = objectTop + objectHeight * this.originFactor(originY);
|
|
9165
|
+
return next;
|
|
9166
|
+
}
|
|
9167
|
+
setLayerVisibility(layerId, visible) {
|
|
9168
|
+
const layer = this.getLayer(layerId);
|
|
9169
|
+
if (layer) {
|
|
9170
|
+
layer.set({ visible });
|
|
9171
|
+
}
|
|
9172
|
+
const objects = this.getRootLayerObjects(layerId);
|
|
9173
|
+
objects.forEach((obj) => {
|
|
9174
|
+
var _a, _b;
|
|
9175
|
+
(_a = obj.set) == null ? void 0 : _a.call(obj, { visible });
|
|
9176
|
+
(_b = obj.setCoords) == null ? void 0 : _b.call(obj);
|
|
9177
|
+
});
|
|
9178
|
+
}
|
|
9179
|
+
bringLayerToFront(layerId) {
|
|
9180
|
+
const layer = this.getLayer(layerId);
|
|
9181
|
+
if (layer) {
|
|
9182
|
+
this.canvas.bringObjectToFront(layer);
|
|
9183
|
+
}
|
|
9184
|
+
const objects = this.getRootLayerObjects(layerId);
|
|
9185
|
+
objects.forEach((obj) => this.canvas.bringObjectToFront(obj));
|
|
9186
|
+
}
|
|
7991
9187
|
async applyLayerSpec(spec) {
|
|
7992
9188
|
const layer = this.createLayer(spec.id, spec.props || {});
|
|
7993
9189
|
await this.applyObjectSpecsToContainer(layer, spec.objects);
|
|
7994
9190
|
}
|
|
7995
|
-
async applyObjectSpecsToLayer(layerId, objects) {
|
|
9191
|
+
async applyObjectSpecsToLayer(layerId, objects, options = {}) {
|
|
7996
9192
|
const layer = this.createLayer(layerId, {});
|
|
7997
|
-
await this.applyObjectSpecsToContainer(layer, objects);
|
|
9193
|
+
await this.applyObjectSpecsToContainer(layer, objects, options);
|
|
7998
9194
|
}
|
|
7999
9195
|
getRootLayerObjects(layerId) {
|
|
8000
9196
|
return this.canvas.getObjects().filter((obj) => {
|
|
@@ -8002,7 +9198,7 @@ var CanvasService = class {
|
|
|
8002
9198
|
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === layerId;
|
|
8003
9199
|
});
|
|
8004
9200
|
}
|
|
8005
|
-
async applyObjectSpecsToRootLayer(layerId, specs) {
|
|
9201
|
+
async applyObjectSpecsToRootLayer(layerId, specs, options = {}) {
|
|
8006
9202
|
const desiredIds = new Set(specs.map((s) => s.id));
|
|
8007
9203
|
const existing = this.getRootLayerObjects(layerId);
|
|
8008
9204
|
existing.forEach((obj) => {
|
|
@@ -8036,9 +9232,11 @@ var CanvasService = class {
|
|
|
8036
9232
|
}
|
|
8037
9233
|
this.patchFabricObject(current, spec, { layerId });
|
|
8038
9234
|
}
|
|
8039
|
-
|
|
9235
|
+
if (options.render !== false) {
|
|
9236
|
+
this.requestRenderAll();
|
|
9237
|
+
}
|
|
8040
9238
|
}
|
|
8041
|
-
async applyObjectSpecsToContainer(container, specs) {
|
|
9239
|
+
async applyObjectSpecsToContainer(container, specs, options = {}) {
|
|
8042
9240
|
const desiredIds = new Set(specs.map((s) => s.id));
|
|
8043
9241
|
const existing = container.getObjects();
|
|
8044
9242
|
existing.forEach((obj) => {
|
|
@@ -8074,7 +9272,9 @@ var CanvasService = class {
|
|
|
8074
9272
|
this.moveObjectInContainer(container, current, index);
|
|
8075
9273
|
}
|
|
8076
9274
|
container.dirty = true;
|
|
8077
|
-
|
|
9275
|
+
if (options.render !== false) {
|
|
9276
|
+
this.requestRenderAll();
|
|
9277
|
+
}
|
|
8078
9278
|
}
|
|
8079
9279
|
patchFabricObject(obj, spec, extraData) {
|
|
8080
9280
|
const nextData = {
|
|
@@ -8083,9 +9283,33 @@ var CanvasService = class {
|
|
|
8083
9283
|
...extraData || {},
|
|
8084
9284
|
id: spec.id
|
|
8085
9285
|
};
|
|
8086
|
-
|
|
9286
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9287
|
+
obj.set({ ...props, data: nextData });
|
|
8087
9288
|
obj.setCoords();
|
|
8088
9289
|
}
|
|
9290
|
+
resolveFabricProps(spec, props) {
|
|
9291
|
+
const space = spec.space || "scene";
|
|
9292
|
+
const next = this.resolveLayoutProps(spec, props);
|
|
9293
|
+
if (space === "screen") {
|
|
9294
|
+
return next;
|
|
9295
|
+
}
|
|
9296
|
+
const hasLeft = Number.isFinite(next.left);
|
|
9297
|
+
const hasTop = Number.isFinite(next.top);
|
|
9298
|
+
if (hasLeft || hasTop) {
|
|
9299
|
+
const mapped = this.toScreenPoint({
|
|
9300
|
+
x: hasLeft ? Number(next.left) : 0,
|
|
9301
|
+
y: hasTop ? Number(next.top) : 0
|
|
9302
|
+
});
|
|
9303
|
+
if (hasLeft) next.left = mapped.x;
|
|
9304
|
+
if (hasTop) next.top = mapped.y;
|
|
9305
|
+
}
|
|
9306
|
+
const rawScaleX = Number.isFinite(next.scaleX) ? Number(next.scaleX) : 1;
|
|
9307
|
+
const rawScaleY = Number.isFinite(next.scaleY) ? Number(next.scaleY) : 1;
|
|
9308
|
+
const sceneScale = this.getSceneScale();
|
|
9309
|
+
next.scaleX = rawScaleX * sceneScale;
|
|
9310
|
+
next.scaleY = rawScaleY * sceneScale;
|
|
9311
|
+
return next;
|
|
9312
|
+
}
|
|
8089
9313
|
moveObjectInContainer(container, obj, index) {
|
|
8090
9314
|
if (!obj) return;
|
|
8091
9315
|
const moveObjectTo = container.moveObjectTo;
|
|
@@ -8105,10 +9329,11 @@ var CanvasService = class {
|
|
|
8105
9329
|
}
|
|
8106
9330
|
}
|
|
8107
9331
|
async createFabricObject(spec) {
|
|
8108
|
-
var _a, _b;
|
|
9332
|
+
var _a, _b, _c, _d;
|
|
8109
9333
|
if (spec.type === "rect") {
|
|
8110
|
-
const
|
|
8111
|
-
|
|
9334
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9335
|
+
const rect = new import_fabric5.Rect({
|
|
9336
|
+
...props,
|
|
8112
9337
|
data: { ...spec.data || {}, id: spec.id }
|
|
8113
9338
|
});
|
|
8114
9339
|
rect.setCoords();
|
|
@@ -8117,8 +9342,9 @@ var CanvasService = class {
|
|
|
8117
9342
|
if (spec.type === "path") {
|
|
8118
9343
|
const pathData = ((_a = spec.props) == null ? void 0 : _a.path) || ((_b = spec.props) == null ? void 0 : _b.pathData);
|
|
8119
9344
|
if (!pathData) return void 0;
|
|
8120
|
-
const
|
|
8121
|
-
|
|
9345
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9346
|
+
const path = new import_fabric5.Path(pathData, {
|
|
9347
|
+
...props,
|
|
8122
9348
|
data: { ...spec.data || {}, id: spec.id }
|
|
8123
9349
|
});
|
|
8124
9350
|
path.setCoords();
|
|
@@ -8126,14 +9352,25 @@ var CanvasService = class {
|
|
|
8126
9352
|
}
|
|
8127
9353
|
if (spec.type === "image") {
|
|
8128
9354
|
if (!spec.src) return void 0;
|
|
8129
|
-
const image = await
|
|
9355
|
+
const image = await import_fabric5.Image.fromURL(spec.src, { crossOrigin: "anonymous" });
|
|
9356
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
8130
9357
|
image.set({
|
|
8131
|
-
...
|
|
9358
|
+
...props,
|
|
8132
9359
|
data: { ...spec.data || {}, id: spec.id }
|
|
8133
9360
|
});
|
|
8134
9361
|
image.setCoords();
|
|
8135
9362
|
return image;
|
|
8136
9363
|
}
|
|
9364
|
+
if (spec.type === "text") {
|
|
9365
|
+
const content = String((_d = (_c = spec.props) == null ? void 0 : _c.text) != null ? _d : "");
|
|
9366
|
+
const props = this.resolveFabricProps(spec, spec.props || {});
|
|
9367
|
+
const text = new import_fabric5.Text(content, {
|
|
9368
|
+
...props,
|
|
9369
|
+
data: { ...spec.data || {}, id: spec.id }
|
|
9370
|
+
});
|
|
9371
|
+
text.setCoords();
|
|
9372
|
+
return text;
|
|
9373
|
+
}
|
|
8137
9374
|
return void 0;
|
|
8138
9375
|
}
|
|
8139
9376
|
};
|