@pooder/kit 6.2.1 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.test-dist/src/extensions/dieline/renderBuilder.js +19 -2
- package/.test-dist/src/extensions/image/ImageTool.js +180 -467
- package/.test-dist/src/extensions/image/commands.js +60 -40
- package/.test-dist/src/extensions/image/imageOperations.js +75 -0
- package/.test-dist/src/extensions/image/index.js +1 -0
- package/.test-dist/src/extensions/image/model.js +4 -0
- package/.test-dist/src/extensions/image/sessionOverlay.js +148 -0
- package/.test-dist/src/extensions/ruler/RulerTool.js +1 -1
- package/.test-dist/tests/run.js +39 -5
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +252 -168
- package/dist/index.d.ts +252 -168
- package/dist/index.js +806 -846
- package/dist/index.mjs +802 -845
- package/package.json +1 -1
- package/src/extensions/dieline/renderBuilder.ts +26 -4
- package/src/extensions/image/ImageTool.ts +229 -557
- package/src/extensions/image/commands.ts +69 -48
- package/src/extensions/image/imageOperations.ts +135 -0
- package/src/extensions/image/index.ts +1 -0
- package/src/extensions/image/model.ts +13 -1
- package/src/extensions/image/sessionOverlay.ts +206 -0
- package/tests/run.ts +49 -8
package/dist/index.js
CHANGED
|
@@ -1074,6 +1074,7 @@ __export(index_exports, {
|
|
|
1074
1074
|
ViewportSystem: () => ViewportSystem,
|
|
1075
1075
|
WhiteInkTool: () => WhiteInkTool,
|
|
1076
1076
|
computeImageCoverScale: () => getCoverScale,
|
|
1077
|
+
computeImageOperationUpdates: () => computeImageOperationUpdates,
|
|
1077
1078
|
computeWhiteInkCoverScale: () => getCoverScale,
|
|
1078
1079
|
createDefaultDielineState: () => createDefaultDielineState,
|
|
1079
1080
|
createDielineCommands: () => createDielineCommands,
|
|
@@ -1083,7 +1084,9 @@ __export(index_exports, {
|
|
|
1083
1084
|
createWhiteInkCommands: () => createWhiteInkCommands,
|
|
1084
1085
|
createWhiteInkConfigurations: () => createWhiteInkConfigurations,
|
|
1085
1086
|
evaluateVisibilityExpr: () => evaluateVisibilityExpr,
|
|
1086
|
-
|
|
1087
|
+
hasAnyImageInViewState: () => hasAnyImageInViewState,
|
|
1088
|
+
readDielineState: () => readDielineState,
|
|
1089
|
+
resolveImageOperationArea: () => resolveImageOperationArea
|
|
1087
1090
|
});
|
|
1088
1091
|
module.exports = __toCommonJS(index_exports);
|
|
1089
1092
|
|
|
@@ -2270,6 +2273,442 @@ var BackgroundTool = class {
|
|
|
2270
2273
|
var import_core2 = require("@pooder/core");
|
|
2271
2274
|
var import_fabric2 = require("fabric");
|
|
2272
2275
|
|
|
2276
|
+
// src/shared/scene/frame.ts
|
|
2277
|
+
function emptyFrameRect() {
|
|
2278
|
+
return { left: 0, top: 0, width: 0, height: 0 };
|
|
2279
|
+
}
|
|
2280
|
+
function resolveCutFrameRect(canvasService, configService) {
|
|
2281
|
+
if (!canvasService || !configService) {
|
|
2282
|
+
return emptyFrameRect();
|
|
2283
|
+
}
|
|
2284
|
+
const sizeState = readSizeState(configService);
|
|
2285
|
+
const layout = computeSceneLayout(canvasService, sizeState);
|
|
2286
|
+
if (!layout) {
|
|
2287
|
+
return emptyFrameRect();
|
|
2288
|
+
}
|
|
2289
|
+
return canvasService.toSceneRect({
|
|
2290
|
+
left: layout.cutRect.left,
|
|
2291
|
+
top: layout.cutRect.top,
|
|
2292
|
+
width: layout.cutRect.width,
|
|
2293
|
+
height: layout.cutRect.height
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
function toLayoutSceneRect(rect) {
|
|
2297
|
+
return {
|
|
2298
|
+
left: rect.left,
|
|
2299
|
+
top: rect.top,
|
|
2300
|
+
width: rect.width,
|
|
2301
|
+
height: rect.height,
|
|
2302
|
+
space: "scene"
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
// src/shared/runtime/sessionState.ts
|
|
2307
|
+
function cloneWithJson(value) {
|
|
2308
|
+
return JSON.parse(JSON.stringify(value));
|
|
2309
|
+
}
|
|
2310
|
+
function applyCommittedSnapshot(session, nextCommitted, options) {
|
|
2311
|
+
const clone = options.clone;
|
|
2312
|
+
session.committed = clone(nextCommitted);
|
|
2313
|
+
const shouldPreserveDirtyWorking = options.toolActive && options.preserveDirtyWorking !== false && session.hasWorkingChanges;
|
|
2314
|
+
if (!shouldPreserveDirtyWorking) {
|
|
2315
|
+
session.working = clone(session.committed);
|
|
2316
|
+
session.hasWorkingChanges = false;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
function runDeferredConfigUpdate(state, action, cooldownMs = 0) {
|
|
2320
|
+
state.isUpdatingConfig = true;
|
|
2321
|
+
action();
|
|
2322
|
+
if (cooldownMs <= 0) {
|
|
2323
|
+
state.isUpdatingConfig = false;
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
setTimeout(() => {
|
|
2327
|
+
state.isUpdatingConfig = false;
|
|
2328
|
+
}, cooldownMs);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
// src/extensions/image/commands.ts
|
|
2332
|
+
function createImageCommands(tool) {
|
|
2333
|
+
return [
|
|
2334
|
+
{
|
|
2335
|
+
command: "addImage",
|
|
2336
|
+
id: "addImage",
|
|
2337
|
+
title: "Add Image",
|
|
2338
|
+
handler: async (url, options) => {
|
|
2339
|
+
const result = await tool.upsertImageEntry(url, {
|
|
2340
|
+
mode: "add",
|
|
2341
|
+
addOptions: options
|
|
2342
|
+
});
|
|
2343
|
+
return result.id;
|
|
2344
|
+
}
|
|
2345
|
+
},
|
|
2346
|
+
{
|
|
2347
|
+
command: "upsertImage",
|
|
2348
|
+
id: "upsertImage",
|
|
2349
|
+
title: "Upsert Image",
|
|
2350
|
+
handler: async (url, options = {}) => {
|
|
2351
|
+
return await tool.upsertImageEntry(url, options);
|
|
2352
|
+
}
|
|
2353
|
+
},
|
|
2354
|
+
{
|
|
2355
|
+
command: "applyImageOperation",
|
|
2356
|
+
id: "applyImageOperation",
|
|
2357
|
+
title: "Apply Image Operation",
|
|
2358
|
+
handler: async (id, operation, options = {}) => {
|
|
2359
|
+
await tool.applyImageOperation(id, operation, options);
|
|
2360
|
+
}
|
|
2361
|
+
},
|
|
2362
|
+
{
|
|
2363
|
+
command: "getImageViewState",
|
|
2364
|
+
id: "getImageViewState",
|
|
2365
|
+
title: "Get Image View State",
|
|
2366
|
+
handler: () => {
|
|
2367
|
+
return tool.getImageViewState();
|
|
2368
|
+
}
|
|
2369
|
+
},
|
|
2370
|
+
{
|
|
2371
|
+
command: "setImageTransform",
|
|
2372
|
+
id: "setImageTransform",
|
|
2373
|
+
title: "Set Image Transform",
|
|
2374
|
+
handler: async (id, updates, options = {}) => {
|
|
2375
|
+
await tool.setImageTransform(id, updates, options);
|
|
2376
|
+
}
|
|
2377
|
+
},
|
|
2378
|
+
{
|
|
2379
|
+
command: "imageSessionReset",
|
|
2380
|
+
id: "imageSessionReset",
|
|
2381
|
+
title: "Reset Image Session",
|
|
2382
|
+
handler: () => {
|
|
2383
|
+
tool.resetImageSession();
|
|
2384
|
+
}
|
|
2385
|
+
},
|
|
2386
|
+
{
|
|
2387
|
+
command: "completeImages",
|
|
2388
|
+
id: "completeImages",
|
|
2389
|
+
title: "Complete Images",
|
|
2390
|
+
handler: async () => {
|
|
2391
|
+
return await tool.commitWorkingImagesAsCropped();
|
|
2392
|
+
}
|
|
2393
|
+
},
|
|
2394
|
+
{
|
|
2395
|
+
command: "exportUserCroppedImage",
|
|
2396
|
+
id: "exportUserCroppedImage",
|
|
2397
|
+
title: "Export User Cropped Image",
|
|
2398
|
+
handler: async (options = {}) => {
|
|
2399
|
+
return await tool.exportUserCroppedImage(options);
|
|
2400
|
+
}
|
|
2401
|
+
},
|
|
2402
|
+
{
|
|
2403
|
+
command: "focusImage",
|
|
2404
|
+
id: "focusImage",
|
|
2405
|
+
title: "Focus Image",
|
|
2406
|
+
handler: (id, options = {}) => {
|
|
2407
|
+
return tool.setImageFocus(id, options);
|
|
2408
|
+
}
|
|
2409
|
+
},
|
|
2410
|
+
{
|
|
2411
|
+
command: "removeImage",
|
|
2412
|
+
id: "removeImage",
|
|
2413
|
+
title: "Remove Image",
|
|
2414
|
+
handler: (id) => {
|
|
2415
|
+
const sourceItems = tool.isToolActive ? tool.workingItems : tool.items;
|
|
2416
|
+
const removed = sourceItems.find((item) => item.id === id);
|
|
2417
|
+
const next = sourceItems.filter((item) => item.id !== id);
|
|
2418
|
+
if (next.length !== sourceItems.length) {
|
|
2419
|
+
tool.purgeSourceSizeCacheForItem(removed);
|
|
2420
|
+
if (tool.focusedImageId === id) {
|
|
2421
|
+
tool.setImageFocus(null, {
|
|
2422
|
+
syncCanvasSelection: true,
|
|
2423
|
+
skipRender: true
|
|
2424
|
+
});
|
|
2425
|
+
}
|
|
2426
|
+
if (tool.isToolActive) {
|
|
2427
|
+
tool.workingItems = tool.cloneItems(next);
|
|
2428
|
+
tool.hasWorkingChanges = true;
|
|
2429
|
+
tool.updateImages();
|
|
2430
|
+
tool.emitWorkingChange(id);
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
tool.updateConfig(next);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
},
|
|
2437
|
+
{
|
|
2438
|
+
command: "updateImage",
|
|
2439
|
+
id: "updateImage",
|
|
2440
|
+
title: "Update Image",
|
|
2441
|
+
handler: async (id, updates, options = {}) => {
|
|
2442
|
+
await tool.updateImage(id, updates, options);
|
|
2443
|
+
}
|
|
2444
|
+
},
|
|
2445
|
+
{
|
|
2446
|
+
command: "clearImages",
|
|
2447
|
+
id: "clearImages",
|
|
2448
|
+
title: "Clear Images",
|
|
2449
|
+
handler: () => {
|
|
2450
|
+
tool.sourceSizeCache.clear();
|
|
2451
|
+
tool.setImageFocus(null, {
|
|
2452
|
+
syncCanvasSelection: true,
|
|
2453
|
+
skipRender: true
|
|
2454
|
+
});
|
|
2455
|
+
if (tool.isToolActive) {
|
|
2456
|
+
tool.workingItems = [];
|
|
2457
|
+
tool.hasWorkingChanges = true;
|
|
2458
|
+
tool.updateImages();
|
|
2459
|
+
tool.emitWorkingChange();
|
|
2460
|
+
return;
|
|
2461
|
+
}
|
|
2462
|
+
tool.updateConfig([]);
|
|
2463
|
+
}
|
|
2464
|
+
},
|
|
2465
|
+
{
|
|
2466
|
+
command: "bringToFront",
|
|
2467
|
+
id: "bringToFront",
|
|
2468
|
+
title: "Bring Image to Front",
|
|
2469
|
+
handler: (id) => {
|
|
2470
|
+
const sourceItems = tool.isToolActive ? tool.workingItems : tool.items;
|
|
2471
|
+
const index = sourceItems.findIndex((item) => item.id === id);
|
|
2472
|
+
if (index !== -1 && index < sourceItems.length - 1) {
|
|
2473
|
+
const next = [...sourceItems];
|
|
2474
|
+
const [item] = next.splice(index, 1);
|
|
2475
|
+
next.push(item);
|
|
2476
|
+
if (tool.isToolActive) {
|
|
2477
|
+
tool.workingItems = tool.cloneItems(next);
|
|
2478
|
+
tool.hasWorkingChanges = true;
|
|
2479
|
+
tool.updateImages();
|
|
2480
|
+
tool.emitWorkingChange(id);
|
|
2481
|
+
return;
|
|
2482
|
+
}
|
|
2483
|
+
tool.updateConfig(next);
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
},
|
|
2487
|
+
{
|
|
2488
|
+
command: "sendToBack",
|
|
2489
|
+
id: "sendToBack",
|
|
2490
|
+
title: "Send Image to Back",
|
|
2491
|
+
handler: (id) => {
|
|
2492
|
+
const sourceItems = tool.isToolActive ? tool.workingItems : tool.items;
|
|
2493
|
+
const index = sourceItems.findIndex((item) => item.id === id);
|
|
2494
|
+
if (index > 0) {
|
|
2495
|
+
const next = [...sourceItems];
|
|
2496
|
+
const [item] = next.splice(index, 1);
|
|
2497
|
+
next.unshift(item);
|
|
2498
|
+
if (tool.isToolActive) {
|
|
2499
|
+
tool.workingItems = tool.cloneItems(next);
|
|
2500
|
+
tool.hasWorkingChanges = true;
|
|
2501
|
+
tool.updateImages();
|
|
2502
|
+
tool.emitWorkingChange(id);
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2505
|
+
tool.updateConfig(next);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
];
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
// src/extensions/image/config.ts
|
|
2513
|
+
function createImageConfigurations() {
|
|
2514
|
+
return [
|
|
2515
|
+
{
|
|
2516
|
+
id: "image.items",
|
|
2517
|
+
type: "array",
|
|
2518
|
+
label: "Images",
|
|
2519
|
+
default: []
|
|
2520
|
+
},
|
|
2521
|
+
{
|
|
2522
|
+
id: "image.debug",
|
|
2523
|
+
type: "boolean",
|
|
2524
|
+
label: "Image Debug Log",
|
|
2525
|
+
default: false
|
|
2526
|
+
},
|
|
2527
|
+
{
|
|
2528
|
+
id: "image.control.cornerSize",
|
|
2529
|
+
type: "number",
|
|
2530
|
+
label: "Image Control Corner Size",
|
|
2531
|
+
min: 4,
|
|
2532
|
+
max: 64,
|
|
2533
|
+
step: 1,
|
|
2534
|
+
default: 14
|
|
2535
|
+
},
|
|
2536
|
+
{
|
|
2537
|
+
id: "image.control.touchCornerSize",
|
|
2538
|
+
type: "number",
|
|
2539
|
+
label: "Image Control Touch Corner Size",
|
|
2540
|
+
min: 8,
|
|
2541
|
+
max: 96,
|
|
2542
|
+
step: 1,
|
|
2543
|
+
default: 24
|
|
2544
|
+
},
|
|
2545
|
+
{
|
|
2546
|
+
id: "image.control.cornerStyle",
|
|
2547
|
+
type: "select",
|
|
2548
|
+
label: "Image Control Corner Style",
|
|
2549
|
+
options: ["circle", "rect"],
|
|
2550
|
+
default: "circle"
|
|
2551
|
+
},
|
|
2552
|
+
{
|
|
2553
|
+
id: "image.control.cornerColor",
|
|
2554
|
+
type: "color",
|
|
2555
|
+
label: "Image Control Corner Color",
|
|
2556
|
+
default: "#ffffff"
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
id: "image.control.cornerStrokeColor",
|
|
2560
|
+
type: "color",
|
|
2561
|
+
label: "Image Control Corner Stroke Color",
|
|
2562
|
+
default: "#1677ff"
|
|
2563
|
+
},
|
|
2564
|
+
{
|
|
2565
|
+
id: "image.control.transparentCorners",
|
|
2566
|
+
type: "boolean",
|
|
2567
|
+
label: "Image Control Transparent Corners",
|
|
2568
|
+
default: false
|
|
2569
|
+
},
|
|
2570
|
+
{
|
|
2571
|
+
id: "image.control.borderColor",
|
|
2572
|
+
type: "color",
|
|
2573
|
+
label: "Image Control Border Color",
|
|
2574
|
+
default: "#1677ff"
|
|
2575
|
+
},
|
|
2576
|
+
{
|
|
2577
|
+
id: "image.control.borderScaleFactor",
|
|
2578
|
+
type: "number",
|
|
2579
|
+
label: "Image Control Border Width",
|
|
2580
|
+
min: 0.5,
|
|
2581
|
+
max: 8,
|
|
2582
|
+
step: 0.1,
|
|
2583
|
+
default: 1.5
|
|
2584
|
+
},
|
|
2585
|
+
{
|
|
2586
|
+
id: "image.control.padding",
|
|
2587
|
+
type: "number",
|
|
2588
|
+
label: "Image Control Padding",
|
|
2589
|
+
min: 0,
|
|
2590
|
+
max: 64,
|
|
2591
|
+
step: 1,
|
|
2592
|
+
default: 0
|
|
2593
|
+
},
|
|
2594
|
+
{
|
|
2595
|
+
id: "image.frame.strokeColor",
|
|
2596
|
+
type: "color",
|
|
2597
|
+
label: "Image Frame Stroke Color",
|
|
2598
|
+
default: "#808080"
|
|
2599
|
+
},
|
|
2600
|
+
{
|
|
2601
|
+
id: "image.frame.strokeWidth",
|
|
2602
|
+
type: "number",
|
|
2603
|
+
label: "Image Frame Stroke Width",
|
|
2604
|
+
min: 0,
|
|
2605
|
+
max: 20,
|
|
2606
|
+
step: 0.5,
|
|
2607
|
+
default: 2
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
id: "image.frame.strokeStyle",
|
|
2611
|
+
type: "select",
|
|
2612
|
+
label: "Image Frame Stroke Style",
|
|
2613
|
+
options: ["solid", "dashed", "hidden"],
|
|
2614
|
+
default: "dashed"
|
|
2615
|
+
},
|
|
2616
|
+
{
|
|
2617
|
+
id: "image.frame.dashLength",
|
|
2618
|
+
type: "number",
|
|
2619
|
+
label: "Image Frame Dash Length",
|
|
2620
|
+
min: 1,
|
|
2621
|
+
max: 40,
|
|
2622
|
+
step: 1,
|
|
2623
|
+
default: 8
|
|
2624
|
+
},
|
|
2625
|
+
{
|
|
2626
|
+
id: "image.frame.innerBackground",
|
|
2627
|
+
type: "color",
|
|
2628
|
+
label: "Image Frame Inner Background",
|
|
2629
|
+
default: "rgba(0,0,0,0)"
|
|
2630
|
+
},
|
|
2631
|
+
{
|
|
2632
|
+
id: "image.frame.outerBackground",
|
|
2633
|
+
type: "color",
|
|
2634
|
+
label: "Image Frame Outer Background",
|
|
2635
|
+
default: "#f5f5f5"
|
|
2636
|
+
}
|
|
2637
|
+
];
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
// src/extensions/image/imageOperations.ts
|
|
2641
|
+
function clampNormalizedAnchor(value) {
|
|
2642
|
+
return Math.max(-1, Math.min(2, value));
|
|
2643
|
+
}
|
|
2644
|
+
function toNormalizedAnchor(center, start, size) {
|
|
2645
|
+
return clampNormalizedAnchor((center - start) / Math.max(1, size));
|
|
2646
|
+
}
|
|
2647
|
+
function resolveAbsoluteScale(operation, area, source) {
|
|
2648
|
+
const widthScale = Math.max(1, area.width) / Math.max(1, source.width);
|
|
2649
|
+
const heightScale = Math.max(1, area.height) / Math.max(1, source.height);
|
|
2650
|
+
switch (operation.type) {
|
|
2651
|
+
case "cover":
|
|
2652
|
+
return Math.max(widthScale, heightScale);
|
|
2653
|
+
case "contain":
|
|
2654
|
+
return Math.min(widthScale, heightScale);
|
|
2655
|
+
case "maximizeWidth":
|
|
2656
|
+
return widthScale;
|
|
2657
|
+
case "maximizeHeight":
|
|
2658
|
+
return heightScale;
|
|
2659
|
+
default:
|
|
2660
|
+
return null;
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
function resolveImageOperationArea(args) {
|
|
2664
|
+
const spec = args.area || { type: "frame" };
|
|
2665
|
+
if (spec.type === "custom") {
|
|
2666
|
+
return {
|
|
2667
|
+
width: Math.max(1, spec.width),
|
|
2668
|
+
height: Math.max(1, spec.height),
|
|
2669
|
+
centerX: spec.centerX,
|
|
2670
|
+
centerY: spec.centerY
|
|
2671
|
+
};
|
|
2672
|
+
}
|
|
2673
|
+
if (spec.type === "viewport") {
|
|
2674
|
+
return {
|
|
2675
|
+
width: Math.max(1, args.viewport.width),
|
|
2676
|
+
height: Math.max(1, args.viewport.height),
|
|
2677
|
+
centerX: args.viewport.left + args.viewport.width / 2,
|
|
2678
|
+
centerY: args.viewport.top + args.viewport.height / 2
|
|
2679
|
+
};
|
|
2680
|
+
}
|
|
2681
|
+
return {
|
|
2682
|
+
width: Math.max(1, args.frame.width),
|
|
2683
|
+
height: Math.max(1, args.frame.height),
|
|
2684
|
+
centerX: args.frame.left + args.frame.width / 2,
|
|
2685
|
+
centerY: args.frame.top + args.frame.height / 2
|
|
2686
|
+
};
|
|
2687
|
+
}
|
|
2688
|
+
function computeImageOperationUpdates(args) {
|
|
2689
|
+
const { frame, source, operation, area } = args;
|
|
2690
|
+
if (operation.type === "resetTransform") {
|
|
2691
|
+
return {
|
|
2692
|
+
scale: 1,
|
|
2693
|
+
left: 0.5,
|
|
2694
|
+
top: 0.5,
|
|
2695
|
+
angle: 0
|
|
2696
|
+
};
|
|
2697
|
+
}
|
|
2698
|
+
const left = toNormalizedAnchor(area.centerX, frame.left, frame.width);
|
|
2699
|
+
const top = toNormalizedAnchor(area.centerY, frame.top, frame.height);
|
|
2700
|
+
if (operation.type === "center") {
|
|
2701
|
+
return { left, top };
|
|
2702
|
+
}
|
|
2703
|
+
const absoluteScale = resolveAbsoluteScale(operation, area, source);
|
|
2704
|
+
const coverScale = getCoverScale(frame, source);
|
|
2705
|
+
return {
|
|
2706
|
+
scale: Math.max(0.05, (absoluteScale || coverScale) / coverScale),
|
|
2707
|
+
left,
|
|
2708
|
+
top
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2273
2712
|
// src/extensions/geometry.ts
|
|
2274
2713
|
var import_paper = __toESM(require("paper"));
|
|
2275
2714
|
|
|
@@ -2847,390 +3286,176 @@ function generateBleedZonePath(originalOptions, offsetOptions, offset) {
|
|
|
2847
3286
|
const pathData = bleedZone.pathData;
|
|
2848
3287
|
shapeOriginal.remove();
|
|
2849
3288
|
shapeOffset.remove();
|
|
2850
|
-
bleedZone.remove();
|
|
2851
|
-
return pathData;
|
|
2852
|
-
}
|
|
2853
|
-
function getLowestPointOnDieline(options) {
|
|
2854
|
-
ensurePaper(options.width * 2, options.height * 2);
|
|
2855
|
-
import_paper.default.project.activeLayer.removeChildren();
|
|
2856
|
-
const shape = createBaseShape(options);
|
|
2857
|
-
const bounds = shape.bounds;
|
|
2858
|
-
const result = {
|
|
2859
|
-
x: bounds.center.x,
|
|
2860
|
-
y: bounds.bottom
|
|
2861
|
-
};
|
|
2862
|
-
shape.remove();
|
|
2863
|
-
return result;
|
|
2864
|
-
}
|
|
2865
|
-
function getNearestPointOnDieline(point, options) {
|
|
2866
|
-
ensurePaper(options.width * 2, options.height * 2);
|
|
2867
|
-
import_paper.default.project.activeLayer.removeChildren();
|
|
2868
|
-
const shape = createBaseShape(options);
|
|
2869
|
-
const p = new import_paper.default.Point(point.x, point.y);
|
|
2870
|
-
const location = shape.getNearestLocation(p);
|
|
2871
|
-
const result = {
|
|
2872
|
-
x: location.point.x,
|
|
2873
|
-
y: location.point.y,
|
|
2874
|
-
normal: location.normal ? { x: location.normal.x, y: location.normal.y } : void 0
|
|
2875
|
-
};
|
|
2876
|
-
shape.remove();
|
|
2877
|
-
return result;
|
|
2878
|
-
}
|
|
2879
|
-
function getPathBounds(pathData) {
|
|
2880
|
-
const path = new import_paper.default.Path();
|
|
2881
|
-
path.pathData = pathData;
|
|
2882
|
-
const bounds = path.bounds;
|
|
2883
|
-
path.remove();
|
|
2884
|
-
return {
|
|
2885
|
-
x: bounds.x,
|
|
2886
|
-
y: bounds.y,
|
|
2887
|
-
width: bounds.width,
|
|
2888
|
-
height: bounds.height
|
|
2889
|
-
};
|
|
2890
|
-
}
|
|
2891
|
-
|
|
2892
|
-
// src/shared/scene/frame.ts
|
|
2893
|
-
function emptyFrameRect() {
|
|
2894
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
2895
|
-
}
|
|
2896
|
-
function resolveCutFrameRect(canvasService, configService) {
|
|
2897
|
-
if (!canvasService || !configService) {
|
|
2898
|
-
return emptyFrameRect();
|
|
2899
|
-
}
|
|
2900
|
-
const sizeState = readSizeState(configService);
|
|
2901
|
-
const layout = computeSceneLayout(canvasService, sizeState);
|
|
2902
|
-
if (!layout) {
|
|
2903
|
-
return emptyFrameRect();
|
|
2904
|
-
}
|
|
2905
|
-
return canvasService.toSceneRect({
|
|
2906
|
-
left: layout.cutRect.left,
|
|
2907
|
-
top: layout.cutRect.top,
|
|
2908
|
-
width: layout.cutRect.width,
|
|
2909
|
-
height: layout.cutRect.height
|
|
2910
|
-
});
|
|
2911
|
-
}
|
|
2912
|
-
function toLayoutSceneRect(rect) {
|
|
2913
|
-
return {
|
|
2914
|
-
left: rect.left,
|
|
2915
|
-
top: rect.top,
|
|
2916
|
-
width: rect.width,
|
|
2917
|
-
height: rect.height,
|
|
2918
|
-
space: "scene"
|
|
2919
|
-
};
|
|
2920
|
-
}
|
|
2921
|
-
|
|
2922
|
-
// src/shared/runtime/sessionState.ts
|
|
2923
|
-
function cloneWithJson(value) {
|
|
2924
|
-
return JSON.parse(JSON.stringify(value));
|
|
2925
|
-
}
|
|
2926
|
-
function applyCommittedSnapshot(session, nextCommitted, options) {
|
|
2927
|
-
const clone = options.clone;
|
|
2928
|
-
session.committed = clone(nextCommitted);
|
|
2929
|
-
const shouldPreserveDirtyWorking = options.toolActive && options.preserveDirtyWorking !== false && session.hasWorkingChanges;
|
|
2930
|
-
if (!shouldPreserveDirtyWorking) {
|
|
2931
|
-
session.working = clone(session.committed);
|
|
2932
|
-
session.hasWorkingChanges = false;
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
function runDeferredConfigUpdate(state, action, cooldownMs = 0) {
|
|
2936
|
-
state.isUpdatingConfig = true;
|
|
2937
|
-
action();
|
|
2938
|
-
if (cooldownMs <= 0) {
|
|
2939
|
-
state.isUpdatingConfig = false;
|
|
2940
|
-
return;
|
|
2941
|
-
}
|
|
2942
|
-
setTimeout(() => {
|
|
2943
|
-
state.isUpdatingConfig = false;
|
|
2944
|
-
}, cooldownMs);
|
|
2945
|
-
}
|
|
2946
|
-
|
|
2947
|
-
// src/extensions/image/commands.ts
|
|
2948
|
-
function createImageCommands(tool) {
|
|
2949
|
-
return [
|
|
2950
|
-
{
|
|
2951
|
-
command: "addImage",
|
|
2952
|
-
id: "addImage",
|
|
2953
|
-
title: "Add Image",
|
|
2954
|
-
handler: async (url, options) => {
|
|
2955
|
-
const result = await tool.upsertImageEntry(url, {
|
|
2956
|
-
mode: "add",
|
|
2957
|
-
addOptions: options
|
|
2958
|
-
});
|
|
2959
|
-
return result.id;
|
|
2960
|
-
}
|
|
2961
|
-
},
|
|
2962
|
-
{
|
|
2963
|
-
command: "upsertImage",
|
|
2964
|
-
id: "upsertImage",
|
|
2965
|
-
title: "Upsert Image",
|
|
2966
|
-
handler: async (url, options = {}) => {
|
|
2967
|
-
return await tool.upsertImageEntry(url, options);
|
|
2968
|
-
}
|
|
2969
|
-
},
|
|
2970
|
-
{
|
|
2971
|
-
command: "getWorkingImages",
|
|
2972
|
-
id: "getWorkingImages",
|
|
2973
|
-
title: "Get Working Images",
|
|
2974
|
-
handler: () => {
|
|
2975
|
-
return tool.cloneItems(tool.workingItems);
|
|
2976
|
-
}
|
|
2977
|
-
},
|
|
2978
|
-
{
|
|
2979
|
-
command: "setWorkingImage",
|
|
2980
|
-
id: "setWorkingImage",
|
|
2981
|
-
title: "Set Working Image",
|
|
2982
|
-
handler: (id, updates) => {
|
|
2983
|
-
tool.updateImageInWorking(id, updates);
|
|
2984
|
-
}
|
|
2985
|
-
},
|
|
2986
|
-
{
|
|
2987
|
-
command: "resetWorkingImages",
|
|
2988
|
-
id: "resetWorkingImages",
|
|
2989
|
-
title: "Reset Working Images",
|
|
2990
|
-
handler: () => {
|
|
2991
|
-
tool.workingItems = tool.cloneItems(tool.items);
|
|
2992
|
-
tool.hasWorkingChanges = false;
|
|
2993
|
-
tool.updateImages();
|
|
2994
|
-
tool.emitWorkingChange();
|
|
2995
|
-
}
|
|
2996
|
-
},
|
|
2997
|
-
{
|
|
2998
|
-
command: "completeImages",
|
|
2999
|
-
id: "completeImages",
|
|
3000
|
-
title: "Complete Images",
|
|
3001
|
-
handler: async () => {
|
|
3002
|
-
return await tool.commitWorkingImagesAsCropped();
|
|
3003
|
-
}
|
|
3004
|
-
},
|
|
3005
|
-
{
|
|
3006
|
-
command: "exportUserCroppedImage",
|
|
3007
|
-
id: "exportUserCroppedImage",
|
|
3008
|
-
title: "Export User Cropped Image",
|
|
3009
|
-
handler: async (options = {}) => {
|
|
3010
|
-
return await tool.exportUserCroppedImage(options);
|
|
3011
|
-
}
|
|
3012
|
-
},
|
|
3013
|
-
{
|
|
3014
|
-
command: "fitImageToArea",
|
|
3015
|
-
id: "fitImageToArea",
|
|
3016
|
-
title: "Fit Image to Area",
|
|
3017
|
-
handler: async (id, area) => {
|
|
3018
|
-
await tool.fitImageToArea(id, area);
|
|
3019
|
-
}
|
|
3020
|
-
},
|
|
3021
|
-
{
|
|
3022
|
-
command: "fitImageToDefaultArea",
|
|
3023
|
-
id: "fitImageToDefaultArea",
|
|
3024
|
-
title: "Fit Image to Default Area",
|
|
3025
|
-
handler: async (id) => {
|
|
3026
|
-
await tool.fitImageToDefaultArea(id);
|
|
3027
|
-
}
|
|
3028
|
-
},
|
|
3029
|
-
{
|
|
3030
|
-
command: "focusImage",
|
|
3031
|
-
id: "focusImage",
|
|
3032
|
-
title: "Focus Image",
|
|
3033
|
-
handler: (id, options = {}) => {
|
|
3034
|
-
return tool.setImageFocus(id, options);
|
|
3035
|
-
}
|
|
3036
|
-
},
|
|
3037
|
-
{
|
|
3038
|
-
command: "removeImage",
|
|
3039
|
-
id: "removeImage",
|
|
3040
|
-
title: "Remove Image",
|
|
3041
|
-
handler: (id) => {
|
|
3042
|
-
const removed = tool.items.find((item) => item.id === id);
|
|
3043
|
-
const next = tool.items.filter((item) => item.id !== id);
|
|
3044
|
-
if (next.length !== tool.items.length) {
|
|
3045
|
-
tool.purgeSourceSizeCacheForItem(removed);
|
|
3046
|
-
if (tool.focusedImageId === id) {
|
|
3047
|
-
tool.setImageFocus(null, {
|
|
3048
|
-
syncCanvasSelection: true,
|
|
3049
|
-
skipRender: true
|
|
3050
|
-
});
|
|
3051
|
-
}
|
|
3052
|
-
tool.updateConfig(next);
|
|
3053
|
-
}
|
|
3054
|
-
}
|
|
3055
|
-
},
|
|
3056
|
-
{
|
|
3057
|
-
command: "updateImage",
|
|
3058
|
-
id: "updateImage",
|
|
3059
|
-
title: "Update Image",
|
|
3060
|
-
handler: async (id, updates, options = {}) => {
|
|
3061
|
-
await tool.updateImage(id, updates, options);
|
|
3062
|
-
}
|
|
3063
|
-
},
|
|
3064
|
-
{
|
|
3065
|
-
command: "clearImages",
|
|
3066
|
-
id: "clearImages",
|
|
3067
|
-
title: "Clear Images",
|
|
3068
|
-
handler: () => {
|
|
3069
|
-
tool.sourceSizeCache.clear();
|
|
3070
|
-
tool.setImageFocus(null, {
|
|
3071
|
-
syncCanvasSelection: true,
|
|
3072
|
-
skipRender: true
|
|
3073
|
-
});
|
|
3074
|
-
tool.updateConfig([]);
|
|
3075
|
-
}
|
|
3076
|
-
},
|
|
3077
|
-
{
|
|
3078
|
-
command: "bringToFront",
|
|
3079
|
-
id: "bringToFront",
|
|
3080
|
-
title: "Bring Image to Front",
|
|
3081
|
-
handler: (id) => {
|
|
3082
|
-
const index = tool.items.findIndex((item) => item.id === id);
|
|
3083
|
-
if (index !== -1 && index < tool.items.length - 1) {
|
|
3084
|
-
const next = [...tool.items];
|
|
3085
|
-
const [item] = next.splice(index, 1);
|
|
3086
|
-
next.push(item);
|
|
3087
|
-
tool.updateConfig(next);
|
|
3088
|
-
}
|
|
3089
|
-
}
|
|
3090
|
-
},
|
|
3091
|
-
{
|
|
3092
|
-
command: "sendToBack",
|
|
3093
|
-
id: "sendToBack",
|
|
3094
|
-
title: "Send Image to Back",
|
|
3095
|
-
handler: (id) => {
|
|
3096
|
-
const index = tool.items.findIndex((item) => item.id === id);
|
|
3097
|
-
if (index > 0) {
|
|
3098
|
-
const next = [...tool.items];
|
|
3099
|
-
const [item] = next.splice(index, 1);
|
|
3100
|
-
next.unshift(item);
|
|
3101
|
-
tool.updateConfig(next);
|
|
3102
|
-
}
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
];
|
|
3289
|
+
bleedZone.remove();
|
|
3290
|
+
return pathData;
|
|
3291
|
+
}
|
|
3292
|
+
function getLowestPointOnDieline(options) {
|
|
3293
|
+
ensurePaper(options.width * 2, options.height * 2);
|
|
3294
|
+
import_paper.default.project.activeLayer.removeChildren();
|
|
3295
|
+
const shape = createBaseShape(options);
|
|
3296
|
+
const bounds = shape.bounds;
|
|
3297
|
+
const result = {
|
|
3298
|
+
x: bounds.center.x,
|
|
3299
|
+
y: bounds.bottom
|
|
3300
|
+
};
|
|
3301
|
+
shape.remove();
|
|
3302
|
+
return result;
|
|
3303
|
+
}
|
|
3304
|
+
function getNearestPointOnDieline(point, options) {
|
|
3305
|
+
ensurePaper(options.width * 2, options.height * 2);
|
|
3306
|
+
import_paper.default.project.activeLayer.removeChildren();
|
|
3307
|
+
const shape = createBaseShape(options);
|
|
3308
|
+
const p = new import_paper.default.Point(point.x, point.y);
|
|
3309
|
+
const location = shape.getNearestLocation(p);
|
|
3310
|
+
const result = {
|
|
3311
|
+
x: location.point.x,
|
|
3312
|
+
y: location.point.y,
|
|
3313
|
+
normal: location.normal ? { x: location.normal.x, y: location.normal.y } : void 0
|
|
3314
|
+
};
|
|
3315
|
+
shape.remove();
|
|
3316
|
+
return result;
|
|
3106
3317
|
}
|
|
3107
3318
|
|
|
3108
|
-
// src/extensions/image/
|
|
3109
|
-
|
|
3319
|
+
// src/extensions/image/sessionOverlay.ts
|
|
3320
|
+
var EPSILON = 1e-4;
|
|
3321
|
+
var SHAPE_OUTLINE_COLOR = "rgba(255, 0, 0, 0.9)";
|
|
3322
|
+
var DEFAULT_HATCH_FILL = "rgba(255, 0, 0, 0.22)";
|
|
3323
|
+
function buildRectPath(width, height) {
|
|
3324
|
+
return `M 0 0 L ${width} 0 L ${width} ${height} L 0 ${height} Z`;
|
|
3325
|
+
}
|
|
3326
|
+
function buildViewportMaskPath(viewport, cutRect) {
|
|
3327
|
+
const cutLeft = cutRect.left - viewport.left;
|
|
3328
|
+
const cutTop = cutRect.top - viewport.top;
|
|
3110
3329
|
return [
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
}
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
{
|
|
3173
|
-
id: "image.control.borderScaleFactor",
|
|
3174
|
-
type: "number",
|
|
3175
|
-
label: "Image Control Border Width",
|
|
3176
|
-
min: 0.5,
|
|
3177
|
-
max: 8,
|
|
3178
|
-
step: 0.1,
|
|
3179
|
-
default: 1.5
|
|
3180
|
-
},
|
|
3181
|
-
{
|
|
3182
|
-
id: "image.control.padding",
|
|
3183
|
-
type: "number",
|
|
3184
|
-
label: "Image Control Padding",
|
|
3185
|
-
min: 0,
|
|
3186
|
-
max: 64,
|
|
3187
|
-
step: 1,
|
|
3188
|
-
default: 0
|
|
3189
|
-
},
|
|
3190
|
-
{
|
|
3191
|
-
id: "image.frame.strokeColor",
|
|
3192
|
-
type: "color",
|
|
3193
|
-
label: "Image Frame Stroke Color",
|
|
3194
|
-
default: "#808080"
|
|
3195
|
-
},
|
|
3196
|
-
{
|
|
3197
|
-
id: "image.frame.strokeWidth",
|
|
3198
|
-
type: "number",
|
|
3199
|
-
label: "Image Frame Stroke Width",
|
|
3200
|
-
min: 0,
|
|
3201
|
-
max: 20,
|
|
3202
|
-
step: 0.5,
|
|
3203
|
-
default: 2
|
|
3204
|
-
},
|
|
3205
|
-
{
|
|
3206
|
-
id: "image.frame.strokeStyle",
|
|
3207
|
-
type: "select",
|
|
3208
|
-
label: "Image Frame Stroke Style",
|
|
3209
|
-
options: ["solid", "dashed", "hidden"],
|
|
3210
|
-
default: "dashed"
|
|
3211
|
-
},
|
|
3212
|
-
{
|
|
3213
|
-
id: "image.frame.dashLength",
|
|
3214
|
-
type: "number",
|
|
3215
|
-
label: "Image Frame Dash Length",
|
|
3216
|
-
min: 1,
|
|
3217
|
-
max: 40,
|
|
3218
|
-
step: 1,
|
|
3219
|
-
default: 8
|
|
3220
|
-
},
|
|
3221
|
-
{
|
|
3222
|
-
id: "image.frame.innerBackground",
|
|
3223
|
-
type: "color",
|
|
3224
|
-
label: "Image Frame Inner Background",
|
|
3225
|
-
default: "rgba(0,0,0,0)"
|
|
3226
|
-
},
|
|
3227
|
-
{
|
|
3228
|
-
id: "image.frame.outerBackground",
|
|
3229
|
-
type: "color",
|
|
3230
|
-
label: "Image Frame Outer Background",
|
|
3231
|
-
default: "#f5f5f5"
|
|
3330
|
+
buildRectPath(viewport.width, viewport.height),
|
|
3331
|
+
`M ${cutLeft} ${cutTop} L ${cutLeft + cutRect.width} ${cutTop} L ${cutLeft + cutRect.width} ${cutTop + cutRect.height} L ${cutLeft} ${cutTop + cutRect.height} Z`
|
|
3332
|
+
].join(" ");
|
|
3333
|
+
}
|
|
3334
|
+
function resolveCutShapeRadiusPx(geometry, cutRect) {
|
|
3335
|
+
const visualRadius = Number.isFinite(geometry.radius) ? Math.max(0, geometry.radius) : 0;
|
|
3336
|
+
const visualOffset = Number.isFinite(geometry.offset) ? geometry.offset : 0;
|
|
3337
|
+
const rawCutRadius = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
3338
|
+
const maxRadius = Math.max(0, Math.min(cutRect.width, cutRect.height) / 2);
|
|
3339
|
+
return Math.max(0, Math.min(maxRadius, rawCutRadius));
|
|
3340
|
+
}
|
|
3341
|
+
function buildBuiltinShapeOverlayPaths(cutRect, geometry) {
|
|
3342
|
+
if (!geometry || geometry.shape === "custom") {
|
|
3343
|
+
return null;
|
|
3344
|
+
}
|
|
3345
|
+
const radius = resolveCutShapeRadiusPx(geometry, cutRect);
|
|
3346
|
+
if (geometry.shape === "rect" && radius <= EPSILON) {
|
|
3347
|
+
return null;
|
|
3348
|
+
}
|
|
3349
|
+
const shapePathData = generateDielinePath({
|
|
3350
|
+
shape: geometry.shape,
|
|
3351
|
+
shapeStyle: geometry.shapeStyle,
|
|
3352
|
+
width: Math.max(1, cutRect.width),
|
|
3353
|
+
height: Math.max(1, cutRect.height),
|
|
3354
|
+
radius,
|
|
3355
|
+
x: cutRect.width / 2,
|
|
3356
|
+
y: cutRect.height / 2,
|
|
3357
|
+
features: [],
|
|
3358
|
+
canvasWidth: Math.max(1, cutRect.width),
|
|
3359
|
+
canvasHeight: Math.max(1, cutRect.height)
|
|
3360
|
+
});
|
|
3361
|
+
if (!shapePathData) {
|
|
3362
|
+
return null;
|
|
3363
|
+
}
|
|
3364
|
+
return {
|
|
3365
|
+
shapePathData,
|
|
3366
|
+
hatchPathData: `${buildRectPath(cutRect.width, cutRect.height)} ${shapePathData}`
|
|
3367
|
+
};
|
|
3368
|
+
}
|
|
3369
|
+
function buildImageSessionOverlaySpecs(args) {
|
|
3370
|
+
const { viewport, layout, geometry, visual, hatchPattern } = args;
|
|
3371
|
+
const cutRect = layout.cutRect;
|
|
3372
|
+
const specs = [];
|
|
3373
|
+
specs.push({
|
|
3374
|
+
id: "image.cropMask.rect",
|
|
3375
|
+
type: "path",
|
|
3376
|
+
space: "screen",
|
|
3377
|
+
data: { id: "image.cropMask.rect", zIndex: 1 },
|
|
3378
|
+
props: {
|
|
3379
|
+
pathData: buildViewportMaskPath(viewport, cutRect),
|
|
3380
|
+
left: viewport.left,
|
|
3381
|
+
top: viewport.top,
|
|
3382
|
+
originX: "left",
|
|
3383
|
+
originY: "top",
|
|
3384
|
+
fill: visual.outerBackground,
|
|
3385
|
+
stroke: null,
|
|
3386
|
+
fillRule: "evenodd",
|
|
3387
|
+
selectable: false,
|
|
3388
|
+
evented: false,
|
|
3389
|
+
excludeFromExport: true,
|
|
3390
|
+
objectCaching: false
|
|
3232
3391
|
}
|
|
3233
|
-
|
|
3392
|
+
});
|
|
3393
|
+
const shapeOverlay = buildBuiltinShapeOverlayPaths(cutRect, geometry);
|
|
3394
|
+
if (shapeOverlay) {
|
|
3395
|
+
specs.push({
|
|
3396
|
+
id: "image.cropShapeHatch",
|
|
3397
|
+
type: "path",
|
|
3398
|
+
space: "screen",
|
|
3399
|
+
data: { id: "image.cropShapeHatch", zIndex: 5 },
|
|
3400
|
+
props: {
|
|
3401
|
+
pathData: shapeOverlay.hatchPathData,
|
|
3402
|
+
left: cutRect.left,
|
|
3403
|
+
top: cutRect.top,
|
|
3404
|
+
originX: "left",
|
|
3405
|
+
originY: "top",
|
|
3406
|
+
fill: hatchPattern || DEFAULT_HATCH_FILL,
|
|
3407
|
+
opacity: hatchPattern ? 1 : 0.8,
|
|
3408
|
+
stroke: null,
|
|
3409
|
+
fillRule: "evenodd",
|
|
3410
|
+
selectable: false,
|
|
3411
|
+
evented: false,
|
|
3412
|
+
excludeFromExport: true,
|
|
3413
|
+
objectCaching: false
|
|
3414
|
+
}
|
|
3415
|
+
});
|
|
3416
|
+
specs.push({
|
|
3417
|
+
id: "image.cropShapeOutline",
|
|
3418
|
+
type: "path",
|
|
3419
|
+
space: "screen",
|
|
3420
|
+
data: { id: "image.cropShapeOutline", zIndex: 6 },
|
|
3421
|
+
props: {
|
|
3422
|
+
pathData: shapeOverlay.shapePathData,
|
|
3423
|
+
left: cutRect.left,
|
|
3424
|
+
top: cutRect.top,
|
|
3425
|
+
originX: "left",
|
|
3426
|
+
originY: "top",
|
|
3427
|
+
fill: "transparent",
|
|
3428
|
+
stroke: SHAPE_OUTLINE_COLOR,
|
|
3429
|
+
strokeWidth: 1,
|
|
3430
|
+
selectable: false,
|
|
3431
|
+
evented: false,
|
|
3432
|
+
excludeFromExport: true,
|
|
3433
|
+
objectCaching: false
|
|
3434
|
+
}
|
|
3435
|
+
});
|
|
3436
|
+
}
|
|
3437
|
+
specs.push({
|
|
3438
|
+
id: "image.cropFrame",
|
|
3439
|
+
type: "rect",
|
|
3440
|
+
space: "screen",
|
|
3441
|
+
data: { id: "image.cropFrame", zIndex: 7 },
|
|
3442
|
+
props: {
|
|
3443
|
+
left: cutRect.left,
|
|
3444
|
+
top: cutRect.top,
|
|
3445
|
+
width: cutRect.width,
|
|
3446
|
+
height: cutRect.height,
|
|
3447
|
+
originX: "left",
|
|
3448
|
+
originY: "top",
|
|
3449
|
+
fill: visual.innerBackground,
|
|
3450
|
+
stroke: visual.strokeStyle === "hidden" ? "rgba(0,0,0,0)" : visual.strokeColor,
|
|
3451
|
+
strokeWidth: visual.strokeStyle === "hidden" ? 0 : visual.strokeWidth,
|
|
3452
|
+
strokeDashArray: visual.strokeStyle === "dashed" ? [visual.dashLength, visual.dashLength] : void 0,
|
|
3453
|
+
selectable: false,
|
|
3454
|
+
evented: false,
|
|
3455
|
+
excludeFromExport: true
|
|
3456
|
+
}
|
|
3457
|
+
});
|
|
3458
|
+
return specs;
|
|
3234
3459
|
}
|
|
3235
3460
|
|
|
3236
3461
|
// src/extensions/image/ImageTool.ts
|
|
@@ -3518,6 +3743,7 @@ var ImageTool = class {
|
|
|
3518
3743
|
this.clearRenderedImages();
|
|
3519
3744
|
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
3520
3745
|
this.renderProducerDisposable = void 0;
|
|
3746
|
+
this.emitImageStateChange();
|
|
3521
3747
|
if (this.canvasService) {
|
|
3522
3748
|
void this.canvasService.flushRenderFromProducers();
|
|
3523
3749
|
this.canvasService = void 0;
|
|
@@ -3692,11 +3918,21 @@ var ImageTool = class {
|
|
|
3692
3918
|
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
3693
3919
|
}
|
|
3694
3920
|
}
|
|
3921
|
+
clearSnapGuideContext() {
|
|
3922
|
+
var _a;
|
|
3923
|
+
const topContext = (_a = this.canvasService) == null ? void 0 : _a.canvas.contextTop;
|
|
3924
|
+
if (!this.canvasService || !topContext) return;
|
|
3925
|
+
this.canvasService.canvas.clearContext(topContext);
|
|
3926
|
+
}
|
|
3695
3927
|
clearSnapPreview() {
|
|
3696
3928
|
var _a;
|
|
3929
|
+
const shouldClearCanvas = this.hasRenderedSnapGuides || !!this.activeSnapX || !!this.activeSnapY;
|
|
3697
3930
|
this.activeSnapX = null;
|
|
3698
3931
|
this.activeSnapY = null;
|
|
3699
3932
|
this.hasRenderedSnapGuides = false;
|
|
3933
|
+
if (shouldClearCanvas) {
|
|
3934
|
+
this.clearSnapGuideContext();
|
|
3935
|
+
}
|
|
3700
3936
|
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
3701
3937
|
}
|
|
3702
3938
|
endMoveSnapInteraction() {
|
|
@@ -3917,9 +4153,9 @@ var ImageTool = class {
|
|
|
3917
4153
|
name: "Image",
|
|
3918
4154
|
interaction: "session",
|
|
3919
4155
|
commands: {
|
|
3920
|
-
begin: "
|
|
4156
|
+
begin: "imageSessionReset",
|
|
3921
4157
|
commit: "completeImages",
|
|
3922
|
-
rollback: "
|
|
4158
|
+
rollback: "imageSessionReset"
|
|
3923
4159
|
},
|
|
3924
4160
|
session: {
|
|
3925
4161
|
autoBegin: true,
|
|
@@ -3953,6 +4189,28 @@ var ImageTool = class {
|
|
|
3953
4189
|
cloneItems(items) {
|
|
3954
4190
|
return this.normalizeItems((items || []).map((i) => ({ ...i })));
|
|
3955
4191
|
}
|
|
4192
|
+
getViewItems() {
|
|
4193
|
+
return this.isToolActive ? this.workingItems : this.items;
|
|
4194
|
+
}
|
|
4195
|
+
getImageViewState() {
|
|
4196
|
+
this.syncToolActiveFromWorkbench();
|
|
4197
|
+
const items = this.cloneItems(this.getViewItems());
|
|
4198
|
+
const focusedItem = this.focusedImageId == null ? null : items.find((item) => item.id === this.focusedImageId) || null;
|
|
4199
|
+
return {
|
|
4200
|
+
items,
|
|
4201
|
+
hasAnyImage: items.length > 0,
|
|
4202
|
+
focusedId: this.focusedImageId,
|
|
4203
|
+
focusedItem,
|
|
4204
|
+
isToolActive: this.isToolActive,
|
|
4205
|
+
isImageSelectionActive: this.isImageSelectionActive,
|
|
4206
|
+
hasWorkingChanges: this.hasWorkingChanges,
|
|
4207
|
+
source: this.isToolActive ? "working" : "committed"
|
|
4208
|
+
};
|
|
4209
|
+
}
|
|
4210
|
+
emitImageStateChange() {
|
|
4211
|
+
var _a;
|
|
4212
|
+
(_a = this.context) == null ? void 0 : _a.eventBus.emit("image:state:change", this.getImageViewState());
|
|
4213
|
+
}
|
|
3956
4214
|
emitWorkingChange(changedId = null) {
|
|
3957
4215
|
var _a;
|
|
3958
4216
|
(_a = this.context) == null ? void 0 : _a.eventBus.emit("image:working:change", {
|
|
@@ -3988,10 +4246,13 @@ var ImageTool = class {
|
|
|
3988
4246
|
}
|
|
3989
4247
|
if (!options.skipRender) {
|
|
3990
4248
|
this.updateImages();
|
|
4249
|
+
} else {
|
|
4250
|
+
this.emitImageStateChange();
|
|
3991
4251
|
}
|
|
3992
4252
|
return { ok: true, id };
|
|
3993
4253
|
}
|
|
3994
|
-
async addImageEntry(url, options,
|
|
4254
|
+
async addImageEntry(url, options, operation) {
|
|
4255
|
+
this.syncToolActiveFromWorkbench();
|
|
3995
4256
|
const id = this.generateId();
|
|
3996
4257
|
const newItem = this.normalizeItem({
|
|
3997
4258
|
id,
|
|
@@ -3999,13 +4260,20 @@ var ImageTool = class {
|
|
|
3999
4260
|
opacity: 1,
|
|
4000
4261
|
...options
|
|
4001
4262
|
});
|
|
4002
|
-
const sessionDirtyBeforeAdd = this.isToolActive && this.hasWorkingChanges;
|
|
4003
4263
|
const waitLoaded = this.waitImageLoaded(id, true);
|
|
4004
|
-
|
|
4005
|
-
|
|
4264
|
+
if (this.isToolActive) {
|
|
4265
|
+
this.workingItems = this.cloneItems([...this.workingItems, newItem]);
|
|
4266
|
+
this.hasWorkingChanges = true;
|
|
4267
|
+
this.updateImages();
|
|
4268
|
+
this.emitWorkingChange(id);
|
|
4269
|
+
} else {
|
|
4270
|
+
this.updateConfig([...this.items, newItem]);
|
|
4271
|
+
}
|
|
4006
4272
|
const loaded = await waitLoaded;
|
|
4007
|
-
if (loaded &&
|
|
4008
|
-
await this.
|
|
4273
|
+
if (loaded && operation) {
|
|
4274
|
+
await this.applyImageOperation(id, operation, {
|
|
4275
|
+
target: this.isToolActive ? "working" : "config"
|
|
4276
|
+
});
|
|
4009
4277
|
}
|
|
4010
4278
|
if (loaded) {
|
|
4011
4279
|
this.setImageFocus(id);
|
|
@@ -4013,8 +4281,8 @@ var ImageTool = class {
|
|
|
4013
4281
|
return id;
|
|
4014
4282
|
}
|
|
4015
4283
|
async upsertImageEntry(url, options = {}) {
|
|
4284
|
+
this.syncToolActiveFromWorkbench();
|
|
4016
4285
|
const mode = options.mode || (options.id ? "replace" : "add");
|
|
4017
|
-
const fitOnAdd = options.fitOnAdd !== false;
|
|
4018
4286
|
if (mode === "replace") {
|
|
4019
4287
|
if (!options.id) {
|
|
4020
4288
|
throw new Error("replace-target-id-required");
|
|
@@ -4023,19 +4291,31 @@ var ImageTool = class {
|
|
|
4023
4291
|
if (!this.hasImageItem(targetId)) {
|
|
4024
4292
|
throw new Error("replace-target-not-found");
|
|
4025
4293
|
}
|
|
4026
|
-
|
|
4294
|
+
if (this.isToolActive) {
|
|
4295
|
+
const current = this.workingItems.find((item) => item.id === targetId) || this.items.find((item) => item.id === targetId);
|
|
4296
|
+
this.purgeSourceSizeCacheForItem(current);
|
|
4297
|
+
this.updateImageInWorking(targetId, {
|
|
4298
|
+
url,
|
|
4299
|
+
sourceUrl: url,
|
|
4300
|
+
committedUrl: void 0
|
|
4301
|
+
});
|
|
4302
|
+
} else {
|
|
4303
|
+
await this.updateImageInConfig(targetId, { url });
|
|
4304
|
+
}
|
|
4305
|
+
const loaded = await this.waitImageLoaded(targetId, true);
|
|
4306
|
+
if (loaded && options.operation) {
|
|
4307
|
+
await this.applyImageOperation(targetId, options.operation, {
|
|
4308
|
+
target: this.isToolActive ? "working" : "config"
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
if (loaded) {
|
|
4312
|
+
this.setImageFocus(targetId);
|
|
4313
|
+
}
|
|
4027
4314
|
return { id: targetId, mode: "replace" };
|
|
4028
4315
|
}
|
|
4029
|
-
const id = await this.addImageEntry(url, options.addOptions,
|
|
4316
|
+
const id = await this.addImageEntry(url, options.addOptions, options.operation);
|
|
4030
4317
|
return { id, mode: "add" };
|
|
4031
4318
|
}
|
|
4032
|
-
addItemToWorkingSessionIfNeeded(item, sessionDirtyBeforeAdd) {
|
|
4033
|
-
if (!sessionDirtyBeforeAdd || !this.isToolActive) return;
|
|
4034
|
-
if (this.workingItems.some((existing) => existing.id === item.id)) return;
|
|
4035
|
-
this.workingItems = this.cloneItems([...this.workingItems, item]);
|
|
4036
|
-
this.updateImages();
|
|
4037
|
-
this.emitWorkingChange(item.id);
|
|
4038
|
-
}
|
|
4039
4319
|
async updateImage(id, updates, options = {}) {
|
|
4040
4320
|
this.syncToolActiveFromWorkbench();
|
|
4041
4321
|
const target = options.target || "auto";
|
|
@@ -4095,41 +4375,10 @@ var ImageTool = class {
|
|
|
4095
4375
|
return resolveCutFrameRect(this.canvasService, configService);
|
|
4096
4376
|
}
|
|
4097
4377
|
getFrameRectScreen(frame) {
|
|
4098
|
-
if (!this.canvasService) {
|
|
4099
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
4100
|
-
}
|
|
4101
|
-
return this.canvasService.toScreenRect(frame || this.getFrameRect());
|
|
4102
|
-
}
|
|
4103
|
-
toLayoutSceneRect(rect) {
|
|
4104
|
-
return toLayoutSceneRect(rect);
|
|
4105
|
-
}
|
|
4106
|
-
async resolveDefaultFitArea() {
|
|
4107
|
-
if (!this.canvasService) return null;
|
|
4108
|
-
const frame = this.getFrameRect();
|
|
4109
|
-
if (frame.width <= 0 || frame.height <= 0) return null;
|
|
4110
|
-
return {
|
|
4111
|
-
width: Math.max(1, frame.width),
|
|
4112
|
-
height: Math.max(1, frame.height),
|
|
4113
|
-
left: frame.left + frame.width / 2,
|
|
4114
|
-
top: frame.top + frame.height / 2
|
|
4115
|
-
};
|
|
4116
|
-
}
|
|
4117
|
-
async fitImageToDefaultArea(id) {
|
|
4118
|
-
if (!this.canvasService) return;
|
|
4119
|
-
const area = await this.resolveDefaultFitArea();
|
|
4120
|
-
if (area) {
|
|
4121
|
-
await this.fitImageToArea(id, area);
|
|
4122
|
-
return;
|
|
4378
|
+
if (!this.canvasService) {
|
|
4379
|
+
return { left: 0, top: 0, width: 0, height: 0 };
|
|
4123
4380
|
}
|
|
4124
|
-
|
|
4125
|
-
const canvasW = Math.max(1, viewport.width || 0);
|
|
4126
|
-
const canvasH = Math.max(1, viewport.height || 0);
|
|
4127
|
-
await this.fitImageToArea(id, {
|
|
4128
|
-
width: canvasW,
|
|
4129
|
-
height: canvasH,
|
|
4130
|
-
left: viewport.left + canvasW / 2,
|
|
4131
|
-
top: viewport.top + canvasH / 2
|
|
4132
|
-
});
|
|
4381
|
+
return this.canvasService.toScreenRect(frame || this.getFrameRect());
|
|
4133
4382
|
}
|
|
4134
4383
|
getImageObjects() {
|
|
4135
4384
|
if (!this.canvasService) return [];
|
|
@@ -4229,74 +4478,37 @@ var ImageTool = class {
|
|
|
4229
4478
|
outerBackground: this.getConfig("image.frame.outerBackground", "#f5f5f5") || "#f5f5f5"
|
|
4230
4479
|
};
|
|
4231
4480
|
}
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
if (!isDielineShape(shape)) {
|
|
4481
|
+
resolveSessionOverlayState() {
|
|
4482
|
+
if (!this.canvasService || !this.context) {
|
|
4235
4483
|
return null;
|
|
4236
4484
|
}
|
|
4237
|
-
const radiusRaw = Number(raw == null ? void 0 : raw.radius);
|
|
4238
|
-
const offsetRaw = Number(raw == null ? void 0 : raw.offset);
|
|
4239
|
-
const unit = typeof (raw == null ? void 0 : raw.unit) === "string" ? raw.unit : "px";
|
|
4240
|
-
const radius = unit === "scene" || !this.canvasService ? radiusRaw : this.canvasService.toSceneLength(radiusRaw);
|
|
4241
|
-
const offset = unit === "scene" || !this.canvasService ? offsetRaw : this.canvasService.toSceneLength(offsetRaw);
|
|
4242
|
-
return {
|
|
4243
|
-
shape,
|
|
4244
|
-
shapeStyle: normalizeShapeStyle(raw == null ? void 0 : raw.shapeStyle),
|
|
4245
|
-
radius: Number.isFinite(radius) ? radius : 0,
|
|
4246
|
-
offset: Number.isFinite(offset) ? offset : 0
|
|
4247
|
-
};
|
|
4248
|
-
}
|
|
4249
|
-
async resolveSceneGeometryForOverlay() {
|
|
4250
|
-
if (!this.context) return null;
|
|
4251
|
-
const commandService = this.context.services.get("CommandService");
|
|
4252
|
-
if (commandService) {
|
|
4253
|
-
try {
|
|
4254
|
-
const raw = await Promise.resolve(
|
|
4255
|
-
commandService.executeCommand("getSceneGeometry")
|
|
4256
|
-
);
|
|
4257
|
-
const geometry2 = this.toSceneGeometryLike(raw);
|
|
4258
|
-
if (geometry2) {
|
|
4259
|
-
this.debug("overlay:sceneGeometry:command", geometry2);
|
|
4260
|
-
return geometry2;
|
|
4261
|
-
}
|
|
4262
|
-
this.debug("overlay:sceneGeometry:command:invalid", { raw });
|
|
4263
|
-
} catch (error) {
|
|
4264
|
-
this.debug("overlay:sceneGeometry:command:error", {
|
|
4265
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4266
|
-
});
|
|
4267
|
-
}
|
|
4268
|
-
}
|
|
4269
|
-
if (!this.canvasService) return null;
|
|
4270
4485
|
const configService = this.context.services.get(
|
|
4271
4486
|
"ConfigurationService"
|
|
4272
4487
|
);
|
|
4273
|
-
if (!configService)
|
|
4274
|
-
const sizeState = readSizeState(configService);
|
|
4275
|
-
const layout = computeSceneLayout(this.canvasService, sizeState);
|
|
4276
|
-
if (!layout) {
|
|
4277
|
-
this.debug("overlay:sceneGeometry:fallback:missing-layout");
|
|
4488
|
+
if (!configService) {
|
|
4278
4489
|
return null;
|
|
4279
4490
|
}
|
|
4280
|
-
const
|
|
4281
|
-
|
|
4491
|
+
const layout = computeSceneLayout(
|
|
4492
|
+
this.canvasService,
|
|
4493
|
+
readSizeState(configService)
|
|
4282
4494
|
);
|
|
4283
|
-
if (
|
|
4284
|
-
this.debug("overlay:
|
|
4495
|
+
if (!layout) {
|
|
4496
|
+
this.debug("overlay:layout:missing");
|
|
4497
|
+
return null;
|
|
4285
4498
|
}
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4499
|
+
const geometry = buildSceneGeometry(configService, layout);
|
|
4500
|
+
this.debug("overlay:state:resolved", {
|
|
4501
|
+
cutRect: layout.cutRect,
|
|
4502
|
+
shape: geometry.shape,
|
|
4503
|
+
shapeStyle: geometry.shapeStyle,
|
|
4504
|
+
radius: geometry.radius,
|
|
4505
|
+
offset: geometry.offset
|
|
4506
|
+
});
|
|
4507
|
+
return { layout, geometry };
|
|
4294
4508
|
}
|
|
4295
4509
|
getCropShapeHatchPattern(color = "rgba(255, 0, 0, 0.6)") {
|
|
4296
|
-
var _a;
|
|
4297
4510
|
if (typeof document === "undefined") return void 0;
|
|
4298
|
-
const
|
|
4299
|
-
const cacheKey = `${color}::${sceneScale.toFixed(6)}`;
|
|
4511
|
+
const cacheKey = color;
|
|
4300
4512
|
if (this.cropShapeHatchPattern && this.cropShapeHatchPatternColor === color && this.cropShapeHatchPatternKey === cacheKey) {
|
|
4301
4513
|
return this.cropShapeHatchPattern;
|
|
4302
4514
|
}
|
|
@@ -4326,138 +4538,11 @@ var ImageTool = class {
|
|
|
4326
4538
|
// @ts-ignore: Fabric Pattern accepts canvas source here.
|
|
4327
4539
|
repetition: "repeat"
|
|
4328
4540
|
});
|
|
4329
|
-
pattern.patternTransform = [
|
|
4330
|
-
1 / sceneScale,
|
|
4331
|
-
0,
|
|
4332
|
-
0,
|
|
4333
|
-
1 / sceneScale,
|
|
4334
|
-
0,
|
|
4335
|
-
0
|
|
4336
|
-
];
|
|
4337
4541
|
this.cropShapeHatchPattern = pattern;
|
|
4338
4542
|
this.cropShapeHatchPatternColor = color;
|
|
4339
4543
|
this.cropShapeHatchPatternKey = cacheKey;
|
|
4340
4544
|
return pattern;
|
|
4341
4545
|
}
|
|
4342
|
-
buildCropShapeOverlaySpecs(frame, sceneGeometry) {
|
|
4343
|
-
var _a, _b;
|
|
4344
|
-
if (!sceneGeometry) {
|
|
4345
|
-
this.debug("overlay:shape:skip", { reason: "scene-geometry-missing" });
|
|
4346
|
-
return [];
|
|
4347
|
-
}
|
|
4348
|
-
if (sceneGeometry.shape === "custom") {
|
|
4349
|
-
this.debug("overlay:shape:skip", { reason: "shape-custom" });
|
|
4350
|
-
return [];
|
|
4351
|
-
}
|
|
4352
|
-
const shape = sceneGeometry.shape;
|
|
4353
|
-
const shapeStyle = sceneGeometry.shapeStyle;
|
|
4354
|
-
const inset = 0;
|
|
4355
|
-
const shapeWidth = Math.max(1, frame.width);
|
|
4356
|
-
const shapeHeight = Math.max(1, frame.height);
|
|
4357
|
-
const radius = this.resolveCutShapeRadius(sceneGeometry, frame);
|
|
4358
|
-
this.debug("overlay:shape:geometry", {
|
|
4359
|
-
shape,
|
|
4360
|
-
frameWidth: frame.width,
|
|
4361
|
-
frameHeight: frame.height,
|
|
4362
|
-
offset: sceneGeometry.offset,
|
|
4363
|
-
shapeStyle,
|
|
4364
|
-
inset,
|
|
4365
|
-
shapeWidth,
|
|
4366
|
-
shapeHeight,
|
|
4367
|
-
baseRadius: sceneGeometry.radius,
|
|
4368
|
-
radius
|
|
4369
|
-
});
|
|
4370
|
-
const isSameAsFrame = Math.abs(shapeWidth - frame.width) <= 1e-4 && Math.abs(shapeHeight - frame.height) <= 1e-4;
|
|
4371
|
-
if (shape === "rect" && radius <= 1e-4 && isSameAsFrame) {
|
|
4372
|
-
this.debug("overlay:shape:skip", {
|
|
4373
|
-
reason: "shape-rect-no-radius"
|
|
4374
|
-
});
|
|
4375
|
-
return [];
|
|
4376
|
-
}
|
|
4377
|
-
const baseOptions = {
|
|
4378
|
-
shape,
|
|
4379
|
-
width: shapeWidth,
|
|
4380
|
-
height: shapeHeight,
|
|
4381
|
-
radius,
|
|
4382
|
-
x: frame.width / 2,
|
|
4383
|
-
y: frame.height / 2,
|
|
4384
|
-
features: [],
|
|
4385
|
-
shapeStyle,
|
|
4386
|
-
canvasWidth: frame.width,
|
|
4387
|
-
canvasHeight: frame.height
|
|
4388
|
-
};
|
|
4389
|
-
try {
|
|
4390
|
-
const shapePathData = generateDielinePath(baseOptions);
|
|
4391
|
-
const outerRectPathData = `M 0 0 L ${frame.width} 0 L ${frame.width} ${frame.height} L 0 ${frame.height} Z`;
|
|
4392
|
-
const hatchPathData = `${outerRectPathData} ${shapePathData}`;
|
|
4393
|
-
if (!shapePathData || !hatchPathData) {
|
|
4394
|
-
this.debug("overlay:shape:skip", {
|
|
4395
|
-
reason: "path-generation-empty",
|
|
4396
|
-
shape,
|
|
4397
|
-
radius
|
|
4398
|
-
});
|
|
4399
|
-
return [];
|
|
4400
|
-
}
|
|
4401
|
-
const patternFill = this.getCropShapeHatchPattern();
|
|
4402
|
-
const hatchFill = patternFill || "rgba(255, 0, 0, 0.22)";
|
|
4403
|
-
const shapeBounds = getPathBounds(shapePathData);
|
|
4404
|
-
const hatchBounds = getPathBounds(hatchPathData);
|
|
4405
|
-
const frameRect = this.toLayoutSceneRect(frame);
|
|
4406
|
-
const hatchPathLength = hatchPathData.length;
|
|
4407
|
-
const shapePathLength = shapePathData.length;
|
|
4408
|
-
const specs = [
|
|
4409
|
-
{
|
|
4410
|
-
id: "image.cropShapeHatch",
|
|
4411
|
-
type: "path",
|
|
4412
|
-
data: { id: "image.cropShapeHatch", zIndex: 5 },
|
|
4413
|
-
layout: {
|
|
4414
|
-
reference: "custom",
|
|
4415
|
-
referenceRect: frameRect,
|
|
4416
|
-
alignX: "start",
|
|
4417
|
-
alignY: "start",
|
|
4418
|
-
offsetX: hatchBounds.x,
|
|
4419
|
-
offsetY: hatchBounds.y
|
|
4420
|
-
},
|
|
4421
|
-
props: {
|
|
4422
|
-
pathData: hatchPathData,
|
|
4423
|
-
originX: "left",
|
|
4424
|
-
originY: "top",
|
|
4425
|
-
fill: hatchFill,
|
|
4426
|
-
opacity: patternFill ? 1 : 0.8,
|
|
4427
|
-
stroke: "rgba(255, 0, 0, 0.9)",
|
|
4428
|
-
strokeWidth: (_b = (_a = this.canvasService) == null ? void 0 : _a.toSceneLength(1)) != null ? _b : 1,
|
|
4429
|
-
fillRule: "evenodd",
|
|
4430
|
-
selectable: false,
|
|
4431
|
-
evented: false,
|
|
4432
|
-
excludeFromExport: true,
|
|
4433
|
-
objectCaching: false
|
|
4434
|
-
}
|
|
4435
|
-
}
|
|
4436
|
-
];
|
|
4437
|
-
this.debug("overlay:shape:built", {
|
|
4438
|
-
shape,
|
|
4439
|
-
radius,
|
|
4440
|
-
inset,
|
|
4441
|
-
shapeWidth,
|
|
4442
|
-
shapeHeight,
|
|
4443
|
-
fillRule: "evenodd",
|
|
4444
|
-
shapePathLength,
|
|
4445
|
-
hatchPathLength,
|
|
4446
|
-
shapeBounds,
|
|
4447
|
-
hatchBounds,
|
|
4448
|
-
hatchFillType: hatchFill && typeof hatchFill === "object" ? "pattern" : "color",
|
|
4449
|
-
ids: specs.map((spec) => spec.id)
|
|
4450
|
-
});
|
|
4451
|
-
return specs;
|
|
4452
|
-
} catch (error) {
|
|
4453
|
-
this.debug("overlay:shape:error", {
|
|
4454
|
-
shape,
|
|
4455
|
-
radius,
|
|
4456
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4457
|
-
});
|
|
4458
|
-
return [];
|
|
4459
|
-
}
|
|
4460
|
-
}
|
|
4461
4546
|
resolveRenderImageState(item) {
|
|
4462
4547
|
var _a;
|
|
4463
4548
|
const active = this.isToolActive;
|
|
@@ -4539,172 +4624,35 @@ var ImageTool = class {
|
|
|
4539
4624
|
}
|
|
4540
4625
|
return specs;
|
|
4541
4626
|
}
|
|
4542
|
-
buildOverlaySpecs(
|
|
4627
|
+
buildOverlaySpecs(overlayState) {
|
|
4543
4628
|
const visible = this.isImageEditingVisible();
|
|
4544
|
-
if (!visible ||
|
|
4629
|
+
if (!visible || !overlayState || !this.canvasService) {
|
|
4545
4630
|
this.debug("overlay:hidden", {
|
|
4546
4631
|
visible,
|
|
4547
|
-
|
|
4632
|
+
cutRect: overlayState == null ? void 0 : overlayState.layout.cutRect,
|
|
4548
4633
|
isToolActive: this.isToolActive,
|
|
4549
4634
|
isImageSelectionActive: this.isImageSelectionActive,
|
|
4550
4635
|
focusedImageId: this.focusedImageId
|
|
4551
4636
|
});
|
|
4552
4637
|
return [];
|
|
4553
4638
|
}
|
|
4554
|
-
const viewport = this.canvasService.
|
|
4555
|
-
const canvasW = viewport.width || 0;
|
|
4556
|
-
const canvasH = viewport.height || 0;
|
|
4557
|
-
const canvasLeft = viewport.left || 0;
|
|
4558
|
-
const canvasTop = viewport.top || 0;
|
|
4639
|
+
const viewport = this.canvasService.getScreenViewportRect();
|
|
4559
4640
|
const visual = this.getFrameVisualConfig();
|
|
4560
|
-
const
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
Math.min(canvasLeft + canvasW, frame.left)
|
|
4567
|
-
);
|
|
4568
|
-
const frameTop = Math.max(
|
|
4569
|
-
canvasTop,
|
|
4570
|
-
Math.min(canvasTop + canvasH, frame.top)
|
|
4571
|
-
);
|
|
4572
|
-
const frameRight = Math.max(
|
|
4573
|
-
frameLeft,
|
|
4574
|
-
Math.min(canvasLeft + canvasW, frame.left + frame.width)
|
|
4575
|
-
);
|
|
4576
|
-
const frameBottom = Math.max(
|
|
4577
|
-
frameTop,
|
|
4578
|
-
Math.min(canvasTop + canvasH, frame.top + frame.height)
|
|
4579
|
-
);
|
|
4580
|
-
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
4581
|
-
const topH = Math.max(0, frameTop - canvasTop);
|
|
4582
|
-
const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
|
|
4583
|
-
const leftW = Math.max(0, frameLeft - canvasLeft);
|
|
4584
|
-
const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
|
|
4585
|
-
const viewportRect = this.toLayoutSceneRect({
|
|
4586
|
-
left: canvasLeft,
|
|
4587
|
-
top: canvasTop,
|
|
4588
|
-
width: canvasW,
|
|
4589
|
-
height: canvasH
|
|
4590
|
-
});
|
|
4591
|
-
const visibleFrameBandRect = this.toLayoutSceneRect({
|
|
4592
|
-
left: canvasLeft,
|
|
4593
|
-
top: frameTop,
|
|
4594
|
-
width: canvasW,
|
|
4595
|
-
height: visibleFrameH
|
|
4596
|
-
});
|
|
4597
|
-
const frameRect = this.toLayoutSceneRect(frame);
|
|
4598
|
-
const shapeOverlay = this.buildCropShapeOverlaySpecs(frame, sceneGeometry);
|
|
4599
|
-
const mask = [
|
|
4600
|
-
{
|
|
4601
|
-
id: "image.cropMask.top",
|
|
4602
|
-
type: "rect",
|
|
4603
|
-
data: { id: "image.cropMask.top", zIndex: 1 },
|
|
4604
|
-
layout: {
|
|
4605
|
-
reference: "custom",
|
|
4606
|
-
referenceRect: viewportRect,
|
|
4607
|
-
alignX: "start",
|
|
4608
|
-
alignY: "start",
|
|
4609
|
-
width: "100%",
|
|
4610
|
-
height: topH
|
|
4611
|
-
},
|
|
4612
|
-
props: {
|
|
4613
|
-
originX: "left",
|
|
4614
|
-
originY: "top",
|
|
4615
|
-
fill: visual.outerBackground,
|
|
4616
|
-
selectable: false,
|
|
4617
|
-
evented: false
|
|
4618
|
-
}
|
|
4619
|
-
},
|
|
4620
|
-
{
|
|
4621
|
-
id: "image.cropMask.bottom",
|
|
4622
|
-
type: "rect",
|
|
4623
|
-
data: { id: "image.cropMask.bottom", zIndex: 2 },
|
|
4624
|
-
layout: {
|
|
4625
|
-
reference: "custom",
|
|
4626
|
-
referenceRect: viewportRect,
|
|
4627
|
-
alignX: "start",
|
|
4628
|
-
alignY: "end",
|
|
4629
|
-
width: "100%",
|
|
4630
|
-
height: bottomH
|
|
4631
|
-
},
|
|
4632
|
-
props: {
|
|
4633
|
-
originX: "left",
|
|
4634
|
-
originY: "top",
|
|
4635
|
-
fill: visual.outerBackground,
|
|
4636
|
-
selectable: false,
|
|
4637
|
-
evented: false
|
|
4638
|
-
}
|
|
4639
|
-
},
|
|
4640
|
-
{
|
|
4641
|
-
id: "image.cropMask.left",
|
|
4642
|
-
type: "rect",
|
|
4643
|
-
data: { id: "image.cropMask.left", zIndex: 3 },
|
|
4644
|
-
layout: {
|
|
4645
|
-
reference: "custom",
|
|
4646
|
-
referenceRect: visibleFrameBandRect,
|
|
4647
|
-
alignX: "start",
|
|
4648
|
-
alignY: "start",
|
|
4649
|
-
width: leftW,
|
|
4650
|
-
height: "100%"
|
|
4651
|
-
},
|
|
4652
|
-
props: {
|
|
4653
|
-
originX: "left",
|
|
4654
|
-
originY: "top",
|
|
4655
|
-
fill: visual.outerBackground,
|
|
4656
|
-
selectable: false,
|
|
4657
|
-
evented: false
|
|
4658
|
-
}
|
|
4659
|
-
},
|
|
4660
|
-
{
|
|
4661
|
-
id: "image.cropMask.right",
|
|
4662
|
-
type: "rect",
|
|
4663
|
-
data: { id: "image.cropMask.right", zIndex: 4 },
|
|
4664
|
-
layout: {
|
|
4665
|
-
reference: "custom",
|
|
4666
|
-
referenceRect: visibleFrameBandRect,
|
|
4667
|
-
alignX: "end",
|
|
4668
|
-
alignY: "start",
|
|
4669
|
-
width: rightW,
|
|
4670
|
-
height: "100%"
|
|
4671
|
-
},
|
|
4672
|
-
props: {
|
|
4673
|
-
originX: "left",
|
|
4674
|
-
originY: "top",
|
|
4675
|
-
fill: visual.outerBackground,
|
|
4676
|
-
selectable: false,
|
|
4677
|
-
evented: false
|
|
4678
|
-
}
|
|
4679
|
-
}
|
|
4680
|
-
];
|
|
4681
|
-
const frameSpec = {
|
|
4682
|
-
id: "image.cropFrame",
|
|
4683
|
-
type: "rect",
|
|
4684
|
-
data: { id: "image.cropFrame", zIndex: 7 },
|
|
4685
|
-
layout: {
|
|
4686
|
-
reference: "custom",
|
|
4687
|
-
referenceRect: frameRect,
|
|
4688
|
-
alignX: "start",
|
|
4689
|
-
alignY: "start",
|
|
4690
|
-
width: "100%",
|
|
4691
|
-
height: "100%"
|
|
4641
|
+
const specs = buildImageSessionOverlaySpecs({
|
|
4642
|
+
viewport: {
|
|
4643
|
+
left: viewport.left,
|
|
4644
|
+
top: viewport.top,
|
|
4645
|
+
width: viewport.width,
|
|
4646
|
+
height: viewport.height
|
|
4692
4647
|
},
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
strokeWidth: visual.strokeStyle === "hidden" ? 0 : strokeWidthScene,
|
|
4699
|
-
strokeDashArray: visual.strokeStyle === "dashed" ? [dashLengthScene, dashLengthScene] : void 0,
|
|
4700
|
-
selectable: false,
|
|
4701
|
-
evented: false
|
|
4702
|
-
}
|
|
4703
|
-
};
|
|
4704
|
-
const specs = shapeOverlay.length > 0 ? [...mask, ...shapeOverlay] : [...mask, ...shapeOverlay, frameSpec];
|
|
4648
|
+
layout: overlayState.layout,
|
|
4649
|
+
geometry: overlayState.geometry,
|
|
4650
|
+
visual,
|
|
4651
|
+
hatchPattern: this.getCropShapeHatchPattern()
|
|
4652
|
+
});
|
|
4705
4653
|
this.debug("overlay:built", {
|
|
4706
|
-
|
|
4707
|
-
shape:
|
|
4654
|
+
cutRect: overlayState.layout.cutRect,
|
|
4655
|
+
shape: overlayState.geometry.shape,
|
|
4708
4656
|
overlayIds: specs.map((spec) => {
|
|
4709
4657
|
var _a;
|
|
4710
4658
|
return {
|
|
@@ -4733,10 +4681,9 @@ var ImageTool = class {
|
|
|
4733
4681
|
}
|
|
4734
4682
|
const imageSpecs = await this.buildImageSpecs(renderItems, frame);
|
|
4735
4683
|
if (seq !== this.renderSeq) return;
|
|
4736
|
-
const
|
|
4737
|
-
if (seq !== this.renderSeq) return;
|
|
4684
|
+
const overlayState = this.resolveSessionOverlayState();
|
|
4738
4685
|
this.imageSpecs = imageSpecs;
|
|
4739
|
-
this.overlaySpecs = this.buildOverlaySpecs(
|
|
4686
|
+
this.overlaySpecs = this.buildOverlaySpecs(overlayState);
|
|
4740
4687
|
await this.canvasService.flushRenderFromProducers();
|
|
4741
4688
|
if (seq !== this.renderSeq) return;
|
|
4742
4689
|
this.refreshImageObjectInteractionState();
|
|
@@ -4763,11 +4710,38 @@ var ImageTool = class {
|
|
|
4763
4710
|
isImageSelectionActive: this.isImageSelectionActive,
|
|
4764
4711
|
focusedImageId: this.focusedImageId
|
|
4765
4712
|
});
|
|
4713
|
+
this.emitImageStateChange();
|
|
4766
4714
|
this.canvasService.requestRenderAll();
|
|
4767
4715
|
}
|
|
4768
4716
|
clampNormalized(value) {
|
|
4769
4717
|
return Math.max(-1, Math.min(2, value));
|
|
4770
4718
|
}
|
|
4719
|
+
async setImageTransform(id, updates, options = {}) {
|
|
4720
|
+
const next = {};
|
|
4721
|
+
if (Number.isFinite(updates.scale)) {
|
|
4722
|
+
next.scale = Math.max(0.05, Number(updates.scale));
|
|
4723
|
+
}
|
|
4724
|
+
if (Number.isFinite(updates.angle)) {
|
|
4725
|
+
next.angle = Number(updates.angle);
|
|
4726
|
+
}
|
|
4727
|
+
if (Number.isFinite(updates.left)) {
|
|
4728
|
+
next.left = this.clampNormalized(Number(updates.left));
|
|
4729
|
+
}
|
|
4730
|
+
if (Number.isFinite(updates.top)) {
|
|
4731
|
+
next.top = this.clampNormalized(Number(updates.top));
|
|
4732
|
+
}
|
|
4733
|
+
if (Number.isFinite(updates.opacity)) {
|
|
4734
|
+
next.opacity = Math.max(0, Math.min(1, Number(updates.opacity)));
|
|
4735
|
+
}
|
|
4736
|
+
if (!Object.keys(next).length) return;
|
|
4737
|
+
await this.updateImage(id, next, options);
|
|
4738
|
+
}
|
|
4739
|
+
resetImageSession() {
|
|
4740
|
+
this.workingItems = this.cloneItems(this.items);
|
|
4741
|
+
this.hasWorkingChanges = false;
|
|
4742
|
+
this.updateImages();
|
|
4743
|
+
this.emitWorkingChange();
|
|
4744
|
+
}
|
|
4771
4745
|
updateImageInWorking(id, updates) {
|
|
4772
4746
|
const index = this.workingItems.findIndex((item) => item.id === id);
|
|
4773
4747
|
if (index < 0) return;
|
|
@@ -4785,7 +4759,6 @@ var ImageTool = class {
|
|
|
4785
4759
|
this.emitWorkingChange(id);
|
|
4786
4760
|
}
|
|
4787
4761
|
async updateImageInConfig(id, updates) {
|
|
4788
|
-
var _a, _b, _c, _d;
|
|
4789
4762
|
const index = this.items.findIndex((item) => item.id === id);
|
|
4790
4763
|
if (index < 0) return;
|
|
4791
4764
|
const replacingSource = typeof updates.url === "string" && updates.url.length > 0;
|
|
@@ -4798,23 +4771,12 @@ var ImageTool = class {
|
|
|
4798
4771
|
...replacingSource ? {
|
|
4799
4772
|
url: replacingUrl,
|
|
4800
4773
|
sourceUrl: replacingUrl,
|
|
4801
|
-
committedUrl: void 0
|
|
4802
|
-
scale: (_a = updates.scale) != null ? _a : 1,
|
|
4803
|
-
angle: (_b = updates.angle) != null ? _b : 0,
|
|
4804
|
-
left: (_c = updates.left) != null ? _c : 0.5,
|
|
4805
|
-
top: (_d = updates.top) != null ? _d : 0.5
|
|
4774
|
+
committedUrl: void 0
|
|
4806
4775
|
} : {}
|
|
4807
4776
|
});
|
|
4808
4777
|
this.updateConfig(next);
|
|
4809
4778
|
if (replacingSource) {
|
|
4810
|
-
this.debug("replace:image:begin", { id, replacingUrl });
|
|
4811
4779
|
this.purgeSourceSizeCacheForItem(base);
|
|
4812
|
-
const loaded = await this.waitImageLoaded(id, true);
|
|
4813
|
-
this.debug("replace:image:loaded", { id, loaded });
|
|
4814
|
-
if (loaded) {
|
|
4815
|
-
await this.refitImageToFrame(id);
|
|
4816
|
-
this.setImageFocus(id);
|
|
4817
|
-
}
|
|
4818
4780
|
}
|
|
4819
4781
|
}
|
|
4820
4782
|
waitImageLoaded(id, forceWait = false) {
|
|
@@ -4832,70 +4794,43 @@ var ImageTool = class {
|
|
|
4832
4794
|
});
|
|
4833
4795
|
});
|
|
4834
4796
|
}
|
|
4835
|
-
async
|
|
4797
|
+
async resolveImageSourceSize(id, src) {
|
|
4836
4798
|
const obj = this.getImageObject(id);
|
|
4837
|
-
if (
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
const
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
const
|
|
4844
|
-
const
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
const updated = {
|
|
4848
|
-
scale: Number.isFinite(zoom) ? zoom : 1,
|
|
4849
|
-
angle: 0,
|
|
4850
|
-
left: 0.5,
|
|
4851
|
-
top: 0.5
|
|
4852
|
-
};
|
|
4853
|
-
const index = this.items.findIndex((item) => item.id === id);
|
|
4854
|
-
if (index < 0) return;
|
|
4855
|
-
const next = [...this.items];
|
|
4856
|
-
next[index] = this.normalizeItem({ ...next[index], ...updated });
|
|
4857
|
-
this.updateConfig(next);
|
|
4858
|
-
this.workingItems = this.cloneItems(next);
|
|
4859
|
-
this.hasWorkingChanges = false;
|
|
4860
|
-
this.updateImages();
|
|
4861
|
-
this.emitWorkingChange(id);
|
|
4799
|
+
if (obj) {
|
|
4800
|
+
this.rememberSourceSize(src, obj);
|
|
4801
|
+
}
|
|
4802
|
+
const ensured = await this.ensureSourceSize(src);
|
|
4803
|
+
if (ensured) return ensured;
|
|
4804
|
+
if (!obj) return null;
|
|
4805
|
+
const width = Number((obj == null ? void 0 : obj.width) || 0);
|
|
4806
|
+
const height = Number((obj == null ? void 0 : obj.height) || 0);
|
|
4807
|
+
if (width <= 0 || height <= 0) return null;
|
|
4808
|
+
return { width, height };
|
|
4862
4809
|
}
|
|
4863
|
-
async
|
|
4864
|
-
var _a, _b;
|
|
4810
|
+
async applyImageOperation(id, operation, options = {}) {
|
|
4865
4811
|
if (!this.canvasService) return;
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
const
|
|
4869
|
-
if (!obj) return;
|
|
4870
|
-
const renderItems = this.isToolActive ? this.workingItems : this.items;
|
|
4812
|
+
this.syncToolActiveFromWorkbench();
|
|
4813
|
+
const target = options.target || "auto";
|
|
4814
|
+
const renderItems = target === "working" || target === "auto" && this.isToolActive ? this.workingItems : this.items;
|
|
4871
4815
|
const current = renderItems.find((item) => item.id === id);
|
|
4872
4816
|
if (!current) return;
|
|
4873
4817
|
const render = this.resolveRenderImageState(current);
|
|
4874
|
-
this.
|
|
4875
|
-
|
|
4818
|
+
const source = await this.resolveImageSourceSize(id, render.src);
|
|
4819
|
+
if (!source) return;
|
|
4876
4820
|
const frame = this.getFrameRect();
|
|
4877
|
-
const baseCover = this.getCoverScale(frame, source);
|
|
4878
|
-
const desiredScale = Math.max(
|
|
4879
|
-
Math.max(1, area.width) / Math.max(1, source.width),
|
|
4880
|
-
Math.max(1, area.height) / Math.max(1, source.height)
|
|
4881
|
-
);
|
|
4882
4821
|
const viewport = this.canvasService.getSceneViewportRect();
|
|
4883
|
-
const
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
const
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
(areaTopPx - frame.top) / Math.max(1, frame.height)
|
|
4896
|
-
)
|
|
4897
|
-
};
|
|
4898
|
-
if (this.isToolActive) {
|
|
4822
|
+
const area = operation.type === "resetTransform" ? resolveImageOperationArea({ frame, viewport }) : resolveImageOperationArea({
|
|
4823
|
+
frame,
|
|
4824
|
+
viewport,
|
|
4825
|
+
area: operation.area
|
|
4826
|
+
});
|
|
4827
|
+
const updates = computeImageOperationUpdates({
|
|
4828
|
+
frame,
|
|
4829
|
+
source,
|
|
4830
|
+
operation,
|
|
4831
|
+
area
|
|
4832
|
+
});
|
|
4833
|
+
if (target === "working" || target === "auto" && this.isToolActive) {
|
|
4899
4834
|
this.updateImageInWorking(id, updates);
|
|
4900
4835
|
return;
|
|
4901
4836
|
}
|
|
@@ -5026,6 +4961,11 @@ var ImageTool = class {
|
|
|
5026
4961
|
}
|
|
5027
4962
|
};
|
|
5028
4963
|
|
|
4964
|
+
// src/extensions/image/model.ts
|
|
4965
|
+
function hasAnyImageInViewState(state) {
|
|
4966
|
+
return Boolean(state == null ? void 0 : state.hasAnyImage);
|
|
4967
|
+
}
|
|
4968
|
+
|
|
5029
4969
|
// src/extensions/size/SizeTool.ts
|
|
5030
4970
|
var import_core3 = require("@pooder/core");
|
|
5031
4971
|
var SizeTool = class {
|
|
@@ -5986,6 +5926,13 @@ function buildDielineRenderBundle(options) {
|
|
|
5986
5926
|
canvasWidth,
|
|
5987
5927
|
canvasHeight
|
|
5988
5928
|
};
|
|
5929
|
+
const cutFrameRect = {
|
|
5930
|
+
left: cx - cutW / 2,
|
|
5931
|
+
top: cy - cutH / 2,
|
|
5932
|
+
width: cutW,
|
|
5933
|
+
height: cutH,
|
|
5934
|
+
space: "screen"
|
|
5935
|
+
};
|
|
5989
5936
|
const specs = [];
|
|
5990
5937
|
if (insideColor && insideColor !== "transparent" && insideColor !== "rgba(0,0,0,0)" && !hasImages) {
|
|
5991
5938
|
specs.push({
|
|
@@ -6107,9 +6054,13 @@ function buildDielineRenderBundle(options) {
|
|
|
6107
6054
|
width: cutW,
|
|
6108
6055
|
height: cutH,
|
|
6109
6056
|
radius: cutR,
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6057
|
+
// Build the clip path in the cut frame's local coordinates so Fabric
|
|
6058
|
+
// does not have to infer placement from the standalone path bounds.
|
|
6059
|
+
x: cutW / 2,
|
|
6060
|
+
y: cutH / 2,
|
|
6061
|
+
features: cutFeatures,
|
|
6062
|
+
canvasWidth: cutW,
|
|
6063
|
+
canvasHeight: cutH
|
|
6113
6064
|
});
|
|
6114
6065
|
if (!clipPathData) {
|
|
6115
6066
|
return { specs, effects: [] };
|
|
@@ -6126,6 +6077,12 @@ function buildDielineRenderBundle(options) {
|
|
|
6126
6077
|
id: ids.clipSource,
|
|
6127
6078
|
type: "path",
|
|
6128
6079
|
space: "screen",
|
|
6080
|
+
layout: {
|
|
6081
|
+
reference: "custom",
|
|
6082
|
+
referenceRect: cutFrameRect,
|
|
6083
|
+
alignX: "start",
|
|
6084
|
+
alignY: "start"
|
|
6085
|
+
},
|
|
6129
6086
|
data: {
|
|
6130
6087
|
id: ids.clipSource,
|
|
6131
6088
|
type: "dieline-effect",
|
|
@@ -10935,6 +10892,7 @@ var CanvasService = class {
|
|
|
10935
10892
|
ViewportSystem,
|
|
10936
10893
|
WhiteInkTool,
|
|
10937
10894
|
computeImageCoverScale,
|
|
10895
|
+
computeImageOperationUpdates,
|
|
10938
10896
|
computeWhiteInkCoverScale,
|
|
10939
10897
|
createDefaultDielineState,
|
|
10940
10898
|
createDielineCommands,
|
|
@@ -10944,5 +10902,7 @@ var CanvasService = class {
|
|
|
10944
10902
|
createWhiteInkCommands,
|
|
10945
10903
|
createWhiteInkConfigurations,
|
|
10946
10904
|
evaluateVisibilityExpr,
|
|
10947
|
-
|
|
10905
|
+
hasAnyImageInViewState,
|
|
10906
|
+
readDielineState,
|
|
10907
|
+
resolveImageOperationArea
|
|
10948
10908
|
});
|