@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.mjs
CHANGED
|
@@ -1192,6 +1192,442 @@ import {
|
|
|
1192
1192
|
controlsUtils
|
|
1193
1193
|
} from "fabric";
|
|
1194
1194
|
|
|
1195
|
+
// src/shared/scene/frame.ts
|
|
1196
|
+
function emptyFrameRect() {
|
|
1197
|
+
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1198
|
+
}
|
|
1199
|
+
function resolveCutFrameRect(canvasService, configService) {
|
|
1200
|
+
if (!canvasService || !configService) {
|
|
1201
|
+
return emptyFrameRect();
|
|
1202
|
+
}
|
|
1203
|
+
const sizeState = readSizeState(configService);
|
|
1204
|
+
const layout = computeSceneLayout(canvasService, sizeState);
|
|
1205
|
+
if (!layout) {
|
|
1206
|
+
return emptyFrameRect();
|
|
1207
|
+
}
|
|
1208
|
+
return canvasService.toSceneRect({
|
|
1209
|
+
left: layout.cutRect.left,
|
|
1210
|
+
top: layout.cutRect.top,
|
|
1211
|
+
width: layout.cutRect.width,
|
|
1212
|
+
height: layout.cutRect.height
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
function toLayoutSceneRect(rect) {
|
|
1216
|
+
return {
|
|
1217
|
+
left: rect.left,
|
|
1218
|
+
top: rect.top,
|
|
1219
|
+
width: rect.width,
|
|
1220
|
+
height: rect.height,
|
|
1221
|
+
space: "scene"
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// src/shared/runtime/sessionState.ts
|
|
1226
|
+
function cloneWithJson(value) {
|
|
1227
|
+
return JSON.parse(JSON.stringify(value));
|
|
1228
|
+
}
|
|
1229
|
+
function applyCommittedSnapshot(session, nextCommitted, options) {
|
|
1230
|
+
const clone = options.clone;
|
|
1231
|
+
session.committed = clone(nextCommitted);
|
|
1232
|
+
const shouldPreserveDirtyWorking = options.toolActive && options.preserveDirtyWorking !== false && session.hasWorkingChanges;
|
|
1233
|
+
if (!shouldPreserveDirtyWorking) {
|
|
1234
|
+
session.working = clone(session.committed);
|
|
1235
|
+
session.hasWorkingChanges = false;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
function runDeferredConfigUpdate(state, action, cooldownMs = 0) {
|
|
1239
|
+
state.isUpdatingConfig = true;
|
|
1240
|
+
action();
|
|
1241
|
+
if (cooldownMs <= 0) {
|
|
1242
|
+
state.isUpdatingConfig = false;
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
setTimeout(() => {
|
|
1246
|
+
state.isUpdatingConfig = false;
|
|
1247
|
+
}, cooldownMs);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
// src/extensions/image/commands.ts
|
|
1251
|
+
function createImageCommands(tool) {
|
|
1252
|
+
return [
|
|
1253
|
+
{
|
|
1254
|
+
command: "addImage",
|
|
1255
|
+
id: "addImage",
|
|
1256
|
+
title: "Add Image",
|
|
1257
|
+
handler: async (url, options) => {
|
|
1258
|
+
const result = await tool.upsertImageEntry(url, {
|
|
1259
|
+
mode: "add",
|
|
1260
|
+
addOptions: options
|
|
1261
|
+
});
|
|
1262
|
+
return result.id;
|
|
1263
|
+
}
|
|
1264
|
+
},
|
|
1265
|
+
{
|
|
1266
|
+
command: "upsertImage",
|
|
1267
|
+
id: "upsertImage",
|
|
1268
|
+
title: "Upsert Image",
|
|
1269
|
+
handler: async (url, options = {}) => {
|
|
1270
|
+
return await tool.upsertImageEntry(url, options);
|
|
1271
|
+
}
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
command: "applyImageOperation",
|
|
1275
|
+
id: "applyImageOperation",
|
|
1276
|
+
title: "Apply Image Operation",
|
|
1277
|
+
handler: async (id, operation, options = {}) => {
|
|
1278
|
+
await tool.applyImageOperation(id, operation, options);
|
|
1279
|
+
}
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
command: "getImageViewState",
|
|
1283
|
+
id: "getImageViewState",
|
|
1284
|
+
title: "Get Image View State",
|
|
1285
|
+
handler: () => {
|
|
1286
|
+
return tool.getImageViewState();
|
|
1287
|
+
}
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
command: "setImageTransform",
|
|
1291
|
+
id: "setImageTransform",
|
|
1292
|
+
title: "Set Image Transform",
|
|
1293
|
+
handler: async (id, updates, options = {}) => {
|
|
1294
|
+
await tool.setImageTransform(id, updates, options);
|
|
1295
|
+
}
|
|
1296
|
+
},
|
|
1297
|
+
{
|
|
1298
|
+
command: "imageSessionReset",
|
|
1299
|
+
id: "imageSessionReset",
|
|
1300
|
+
title: "Reset Image Session",
|
|
1301
|
+
handler: () => {
|
|
1302
|
+
tool.resetImageSession();
|
|
1303
|
+
}
|
|
1304
|
+
},
|
|
1305
|
+
{
|
|
1306
|
+
command: "completeImages",
|
|
1307
|
+
id: "completeImages",
|
|
1308
|
+
title: "Complete Images",
|
|
1309
|
+
handler: async () => {
|
|
1310
|
+
return await tool.commitWorkingImagesAsCropped();
|
|
1311
|
+
}
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
command: "exportUserCroppedImage",
|
|
1315
|
+
id: "exportUserCroppedImage",
|
|
1316
|
+
title: "Export User Cropped Image",
|
|
1317
|
+
handler: async (options = {}) => {
|
|
1318
|
+
return await tool.exportUserCroppedImage(options);
|
|
1319
|
+
}
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
command: "focusImage",
|
|
1323
|
+
id: "focusImage",
|
|
1324
|
+
title: "Focus Image",
|
|
1325
|
+
handler: (id, options = {}) => {
|
|
1326
|
+
return tool.setImageFocus(id, options);
|
|
1327
|
+
}
|
|
1328
|
+
},
|
|
1329
|
+
{
|
|
1330
|
+
command: "removeImage",
|
|
1331
|
+
id: "removeImage",
|
|
1332
|
+
title: "Remove Image",
|
|
1333
|
+
handler: (id) => {
|
|
1334
|
+
const sourceItems = tool.isToolActive ? tool.workingItems : tool.items;
|
|
1335
|
+
const removed = sourceItems.find((item) => item.id === id);
|
|
1336
|
+
const next = sourceItems.filter((item) => item.id !== id);
|
|
1337
|
+
if (next.length !== sourceItems.length) {
|
|
1338
|
+
tool.purgeSourceSizeCacheForItem(removed);
|
|
1339
|
+
if (tool.focusedImageId === id) {
|
|
1340
|
+
tool.setImageFocus(null, {
|
|
1341
|
+
syncCanvasSelection: true,
|
|
1342
|
+
skipRender: true
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
if (tool.isToolActive) {
|
|
1346
|
+
tool.workingItems = tool.cloneItems(next);
|
|
1347
|
+
tool.hasWorkingChanges = true;
|
|
1348
|
+
tool.updateImages();
|
|
1349
|
+
tool.emitWorkingChange(id);
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
tool.updateConfig(next);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
},
|
|
1356
|
+
{
|
|
1357
|
+
command: "updateImage",
|
|
1358
|
+
id: "updateImage",
|
|
1359
|
+
title: "Update Image",
|
|
1360
|
+
handler: async (id, updates, options = {}) => {
|
|
1361
|
+
await tool.updateImage(id, updates, options);
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
command: "clearImages",
|
|
1366
|
+
id: "clearImages",
|
|
1367
|
+
title: "Clear Images",
|
|
1368
|
+
handler: () => {
|
|
1369
|
+
tool.sourceSizeCache.clear();
|
|
1370
|
+
tool.setImageFocus(null, {
|
|
1371
|
+
syncCanvasSelection: true,
|
|
1372
|
+
skipRender: true
|
|
1373
|
+
});
|
|
1374
|
+
if (tool.isToolActive) {
|
|
1375
|
+
tool.workingItems = [];
|
|
1376
|
+
tool.hasWorkingChanges = true;
|
|
1377
|
+
tool.updateImages();
|
|
1378
|
+
tool.emitWorkingChange();
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
tool.updateConfig([]);
|
|
1382
|
+
}
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
command: "bringToFront",
|
|
1386
|
+
id: "bringToFront",
|
|
1387
|
+
title: "Bring Image to Front",
|
|
1388
|
+
handler: (id) => {
|
|
1389
|
+
const sourceItems = tool.isToolActive ? tool.workingItems : tool.items;
|
|
1390
|
+
const index = sourceItems.findIndex((item) => item.id === id);
|
|
1391
|
+
if (index !== -1 && index < sourceItems.length - 1) {
|
|
1392
|
+
const next = [...sourceItems];
|
|
1393
|
+
const [item] = next.splice(index, 1);
|
|
1394
|
+
next.push(item);
|
|
1395
|
+
if (tool.isToolActive) {
|
|
1396
|
+
tool.workingItems = tool.cloneItems(next);
|
|
1397
|
+
tool.hasWorkingChanges = true;
|
|
1398
|
+
tool.updateImages();
|
|
1399
|
+
tool.emitWorkingChange(id);
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
tool.updateConfig(next);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
command: "sendToBack",
|
|
1408
|
+
id: "sendToBack",
|
|
1409
|
+
title: "Send Image to Back",
|
|
1410
|
+
handler: (id) => {
|
|
1411
|
+
const sourceItems = tool.isToolActive ? tool.workingItems : tool.items;
|
|
1412
|
+
const index = sourceItems.findIndex((item) => item.id === id);
|
|
1413
|
+
if (index > 0) {
|
|
1414
|
+
const next = [...sourceItems];
|
|
1415
|
+
const [item] = next.splice(index, 1);
|
|
1416
|
+
next.unshift(item);
|
|
1417
|
+
if (tool.isToolActive) {
|
|
1418
|
+
tool.workingItems = tool.cloneItems(next);
|
|
1419
|
+
tool.hasWorkingChanges = true;
|
|
1420
|
+
tool.updateImages();
|
|
1421
|
+
tool.emitWorkingChange(id);
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
tool.updateConfig(next);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
];
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// src/extensions/image/config.ts
|
|
1432
|
+
function createImageConfigurations() {
|
|
1433
|
+
return [
|
|
1434
|
+
{
|
|
1435
|
+
id: "image.items",
|
|
1436
|
+
type: "array",
|
|
1437
|
+
label: "Images",
|
|
1438
|
+
default: []
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
id: "image.debug",
|
|
1442
|
+
type: "boolean",
|
|
1443
|
+
label: "Image Debug Log",
|
|
1444
|
+
default: false
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
id: "image.control.cornerSize",
|
|
1448
|
+
type: "number",
|
|
1449
|
+
label: "Image Control Corner Size",
|
|
1450
|
+
min: 4,
|
|
1451
|
+
max: 64,
|
|
1452
|
+
step: 1,
|
|
1453
|
+
default: 14
|
|
1454
|
+
},
|
|
1455
|
+
{
|
|
1456
|
+
id: "image.control.touchCornerSize",
|
|
1457
|
+
type: "number",
|
|
1458
|
+
label: "Image Control Touch Corner Size",
|
|
1459
|
+
min: 8,
|
|
1460
|
+
max: 96,
|
|
1461
|
+
step: 1,
|
|
1462
|
+
default: 24
|
|
1463
|
+
},
|
|
1464
|
+
{
|
|
1465
|
+
id: "image.control.cornerStyle",
|
|
1466
|
+
type: "select",
|
|
1467
|
+
label: "Image Control Corner Style",
|
|
1468
|
+
options: ["circle", "rect"],
|
|
1469
|
+
default: "circle"
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
id: "image.control.cornerColor",
|
|
1473
|
+
type: "color",
|
|
1474
|
+
label: "Image Control Corner Color",
|
|
1475
|
+
default: "#ffffff"
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
id: "image.control.cornerStrokeColor",
|
|
1479
|
+
type: "color",
|
|
1480
|
+
label: "Image Control Corner Stroke Color",
|
|
1481
|
+
default: "#1677ff"
|
|
1482
|
+
},
|
|
1483
|
+
{
|
|
1484
|
+
id: "image.control.transparentCorners",
|
|
1485
|
+
type: "boolean",
|
|
1486
|
+
label: "Image Control Transparent Corners",
|
|
1487
|
+
default: false
|
|
1488
|
+
},
|
|
1489
|
+
{
|
|
1490
|
+
id: "image.control.borderColor",
|
|
1491
|
+
type: "color",
|
|
1492
|
+
label: "Image Control Border Color",
|
|
1493
|
+
default: "#1677ff"
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
id: "image.control.borderScaleFactor",
|
|
1497
|
+
type: "number",
|
|
1498
|
+
label: "Image Control Border Width",
|
|
1499
|
+
min: 0.5,
|
|
1500
|
+
max: 8,
|
|
1501
|
+
step: 0.1,
|
|
1502
|
+
default: 1.5
|
|
1503
|
+
},
|
|
1504
|
+
{
|
|
1505
|
+
id: "image.control.padding",
|
|
1506
|
+
type: "number",
|
|
1507
|
+
label: "Image Control Padding",
|
|
1508
|
+
min: 0,
|
|
1509
|
+
max: 64,
|
|
1510
|
+
step: 1,
|
|
1511
|
+
default: 0
|
|
1512
|
+
},
|
|
1513
|
+
{
|
|
1514
|
+
id: "image.frame.strokeColor",
|
|
1515
|
+
type: "color",
|
|
1516
|
+
label: "Image Frame Stroke Color",
|
|
1517
|
+
default: "#808080"
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
id: "image.frame.strokeWidth",
|
|
1521
|
+
type: "number",
|
|
1522
|
+
label: "Image Frame Stroke Width",
|
|
1523
|
+
min: 0,
|
|
1524
|
+
max: 20,
|
|
1525
|
+
step: 0.5,
|
|
1526
|
+
default: 2
|
|
1527
|
+
},
|
|
1528
|
+
{
|
|
1529
|
+
id: "image.frame.strokeStyle",
|
|
1530
|
+
type: "select",
|
|
1531
|
+
label: "Image Frame Stroke Style",
|
|
1532
|
+
options: ["solid", "dashed", "hidden"],
|
|
1533
|
+
default: "dashed"
|
|
1534
|
+
},
|
|
1535
|
+
{
|
|
1536
|
+
id: "image.frame.dashLength",
|
|
1537
|
+
type: "number",
|
|
1538
|
+
label: "Image Frame Dash Length",
|
|
1539
|
+
min: 1,
|
|
1540
|
+
max: 40,
|
|
1541
|
+
step: 1,
|
|
1542
|
+
default: 8
|
|
1543
|
+
},
|
|
1544
|
+
{
|
|
1545
|
+
id: "image.frame.innerBackground",
|
|
1546
|
+
type: "color",
|
|
1547
|
+
label: "Image Frame Inner Background",
|
|
1548
|
+
default: "rgba(0,0,0,0)"
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
id: "image.frame.outerBackground",
|
|
1552
|
+
type: "color",
|
|
1553
|
+
label: "Image Frame Outer Background",
|
|
1554
|
+
default: "#f5f5f5"
|
|
1555
|
+
}
|
|
1556
|
+
];
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
// src/extensions/image/imageOperations.ts
|
|
1560
|
+
function clampNormalizedAnchor(value) {
|
|
1561
|
+
return Math.max(-1, Math.min(2, value));
|
|
1562
|
+
}
|
|
1563
|
+
function toNormalizedAnchor(center, start, size) {
|
|
1564
|
+
return clampNormalizedAnchor((center - start) / Math.max(1, size));
|
|
1565
|
+
}
|
|
1566
|
+
function resolveAbsoluteScale(operation, area, source) {
|
|
1567
|
+
const widthScale = Math.max(1, area.width) / Math.max(1, source.width);
|
|
1568
|
+
const heightScale = Math.max(1, area.height) / Math.max(1, source.height);
|
|
1569
|
+
switch (operation.type) {
|
|
1570
|
+
case "cover":
|
|
1571
|
+
return Math.max(widthScale, heightScale);
|
|
1572
|
+
case "contain":
|
|
1573
|
+
return Math.min(widthScale, heightScale);
|
|
1574
|
+
case "maximizeWidth":
|
|
1575
|
+
return widthScale;
|
|
1576
|
+
case "maximizeHeight":
|
|
1577
|
+
return heightScale;
|
|
1578
|
+
default:
|
|
1579
|
+
return null;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
function resolveImageOperationArea(args) {
|
|
1583
|
+
const spec = args.area || { type: "frame" };
|
|
1584
|
+
if (spec.type === "custom") {
|
|
1585
|
+
return {
|
|
1586
|
+
width: Math.max(1, spec.width),
|
|
1587
|
+
height: Math.max(1, spec.height),
|
|
1588
|
+
centerX: spec.centerX,
|
|
1589
|
+
centerY: spec.centerY
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
if (spec.type === "viewport") {
|
|
1593
|
+
return {
|
|
1594
|
+
width: Math.max(1, args.viewport.width),
|
|
1595
|
+
height: Math.max(1, args.viewport.height),
|
|
1596
|
+
centerX: args.viewport.left + args.viewport.width / 2,
|
|
1597
|
+
centerY: args.viewport.top + args.viewport.height / 2
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
return {
|
|
1601
|
+
width: Math.max(1, args.frame.width),
|
|
1602
|
+
height: Math.max(1, args.frame.height),
|
|
1603
|
+
centerX: args.frame.left + args.frame.width / 2,
|
|
1604
|
+
centerY: args.frame.top + args.frame.height / 2
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
function computeImageOperationUpdates(args) {
|
|
1608
|
+
const { frame, source, operation, area } = args;
|
|
1609
|
+
if (operation.type === "resetTransform") {
|
|
1610
|
+
return {
|
|
1611
|
+
scale: 1,
|
|
1612
|
+
left: 0.5,
|
|
1613
|
+
top: 0.5,
|
|
1614
|
+
angle: 0
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
const left = toNormalizedAnchor(area.centerX, frame.left, frame.width);
|
|
1618
|
+
const top = toNormalizedAnchor(area.centerY, frame.top, frame.height);
|
|
1619
|
+
if (operation.type === "center") {
|
|
1620
|
+
return { left, top };
|
|
1621
|
+
}
|
|
1622
|
+
const absoluteScale = resolveAbsoluteScale(operation, area, source);
|
|
1623
|
+
const coverScale = getCoverScale(frame, source);
|
|
1624
|
+
return {
|
|
1625
|
+
scale: Math.max(0.05, (absoluteScale || coverScale) / coverScale),
|
|
1626
|
+
left,
|
|
1627
|
+
top
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1195
1631
|
// src/extensions/geometry.ts
|
|
1196
1632
|
import paper from "paper";
|
|
1197
1633
|
|
|
@@ -1768,391 +2204,177 @@ function generateBleedZonePath(originalOptions, offsetOptions, offset) {
|
|
|
1768
2204
|
}
|
|
1769
2205
|
const pathData = bleedZone.pathData;
|
|
1770
2206
|
shapeOriginal.remove();
|
|
1771
|
-
shapeOffset.remove();
|
|
1772
|
-
bleedZone.remove();
|
|
1773
|
-
return pathData;
|
|
1774
|
-
}
|
|
1775
|
-
function getLowestPointOnDieline(options) {
|
|
1776
|
-
ensurePaper(options.width * 2, options.height * 2);
|
|
1777
|
-
paper.project.activeLayer.removeChildren();
|
|
1778
|
-
const shape = createBaseShape(options);
|
|
1779
|
-
const bounds = shape.bounds;
|
|
1780
|
-
const result = {
|
|
1781
|
-
x: bounds.center.x,
|
|
1782
|
-
y: bounds.bottom
|
|
1783
|
-
};
|
|
1784
|
-
shape.remove();
|
|
1785
|
-
return result;
|
|
1786
|
-
}
|
|
1787
|
-
function getNearestPointOnDieline(point, options) {
|
|
1788
|
-
ensurePaper(options.width * 2, options.height * 2);
|
|
1789
|
-
paper.project.activeLayer.removeChildren();
|
|
1790
|
-
const shape = createBaseShape(options);
|
|
1791
|
-
const p = new paper.Point(point.x, point.y);
|
|
1792
|
-
const location = shape.getNearestLocation(p);
|
|
1793
|
-
const result = {
|
|
1794
|
-
x: location.point.x,
|
|
1795
|
-
y: location.point.y,
|
|
1796
|
-
normal: location.normal ? { x: location.normal.x, y: location.normal.y } : void 0
|
|
1797
|
-
};
|
|
1798
|
-
shape.remove();
|
|
1799
|
-
return result;
|
|
1800
|
-
}
|
|
1801
|
-
function getPathBounds(pathData) {
|
|
1802
|
-
const path = new paper.Path();
|
|
1803
|
-
path.pathData = pathData;
|
|
1804
|
-
const bounds = path.bounds;
|
|
1805
|
-
path.remove();
|
|
1806
|
-
return {
|
|
1807
|
-
x: bounds.x,
|
|
1808
|
-
y: bounds.y,
|
|
1809
|
-
width: bounds.width,
|
|
1810
|
-
height: bounds.height
|
|
1811
|
-
};
|
|
1812
|
-
}
|
|
1813
|
-
|
|
1814
|
-
// src/shared/scene/frame.ts
|
|
1815
|
-
function emptyFrameRect() {
|
|
1816
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1817
|
-
}
|
|
1818
|
-
function resolveCutFrameRect(canvasService, configService) {
|
|
1819
|
-
if (!canvasService || !configService) {
|
|
1820
|
-
return emptyFrameRect();
|
|
1821
|
-
}
|
|
1822
|
-
const sizeState = readSizeState(configService);
|
|
1823
|
-
const layout = computeSceneLayout(canvasService, sizeState);
|
|
1824
|
-
if (!layout) {
|
|
1825
|
-
return emptyFrameRect();
|
|
1826
|
-
}
|
|
1827
|
-
return canvasService.toSceneRect({
|
|
1828
|
-
left: layout.cutRect.left,
|
|
1829
|
-
top: layout.cutRect.top,
|
|
1830
|
-
width: layout.cutRect.width,
|
|
1831
|
-
height: layout.cutRect.height
|
|
1832
|
-
});
|
|
1833
|
-
}
|
|
1834
|
-
function toLayoutSceneRect(rect) {
|
|
1835
|
-
return {
|
|
1836
|
-
left: rect.left,
|
|
1837
|
-
top: rect.top,
|
|
1838
|
-
width: rect.width,
|
|
1839
|
-
height: rect.height,
|
|
1840
|
-
space: "scene"
|
|
1841
|
-
};
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
// src/shared/runtime/sessionState.ts
|
|
1845
|
-
function cloneWithJson(value) {
|
|
1846
|
-
return JSON.parse(JSON.stringify(value));
|
|
1847
|
-
}
|
|
1848
|
-
function applyCommittedSnapshot(session, nextCommitted, options) {
|
|
1849
|
-
const clone = options.clone;
|
|
1850
|
-
session.committed = clone(nextCommitted);
|
|
1851
|
-
const shouldPreserveDirtyWorking = options.toolActive && options.preserveDirtyWorking !== false && session.hasWorkingChanges;
|
|
1852
|
-
if (!shouldPreserveDirtyWorking) {
|
|
1853
|
-
session.working = clone(session.committed);
|
|
1854
|
-
session.hasWorkingChanges = false;
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
function runDeferredConfigUpdate(state, action, cooldownMs = 0) {
|
|
1858
|
-
state.isUpdatingConfig = true;
|
|
1859
|
-
action();
|
|
1860
|
-
if (cooldownMs <= 0) {
|
|
1861
|
-
state.isUpdatingConfig = false;
|
|
1862
|
-
return;
|
|
1863
|
-
}
|
|
1864
|
-
setTimeout(() => {
|
|
1865
|
-
state.isUpdatingConfig = false;
|
|
1866
|
-
}, cooldownMs);
|
|
1867
|
-
}
|
|
1868
|
-
|
|
1869
|
-
// src/extensions/image/commands.ts
|
|
1870
|
-
function createImageCommands(tool) {
|
|
1871
|
-
return [
|
|
1872
|
-
{
|
|
1873
|
-
command: "addImage",
|
|
1874
|
-
id: "addImage",
|
|
1875
|
-
title: "Add Image",
|
|
1876
|
-
handler: async (url, options) => {
|
|
1877
|
-
const result = await tool.upsertImageEntry(url, {
|
|
1878
|
-
mode: "add",
|
|
1879
|
-
addOptions: options
|
|
1880
|
-
});
|
|
1881
|
-
return result.id;
|
|
1882
|
-
}
|
|
1883
|
-
},
|
|
1884
|
-
{
|
|
1885
|
-
command: "upsertImage",
|
|
1886
|
-
id: "upsertImage",
|
|
1887
|
-
title: "Upsert Image",
|
|
1888
|
-
handler: async (url, options = {}) => {
|
|
1889
|
-
return await tool.upsertImageEntry(url, options);
|
|
1890
|
-
}
|
|
1891
|
-
},
|
|
1892
|
-
{
|
|
1893
|
-
command: "getWorkingImages",
|
|
1894
|
-
id: "getWorkingImages",
|
|
1895
|
-
title: "Get Working Images",
|
|
1896
|
-
handler: () => {
|
|
1897
|
-
return tool.cloneItems(tool.workingItems);
|
|
1898
|
-
}
|
|
1899
|
-
},
|
|
1900
|
-
{
|
|
1901
|
-
command: "setWorkingImage",
|
|
1902
|
-
id: "setWorkingImage",
|
|
1903
|
-
title: "Set Working Image",
|
|
1904
|
-
handler: (id, updates) => {
|
|
1905
|
-
tool.updateImageInWorking(id, updates);
|
|
1906
|
-
}
|
|
1907
|
-
},
|
|
1908
|
-
{
|
|
1909
|
-
command: "resetWorkingImages",
|
|
1910
|
-
id: "resetWorkingImages",
|
|
1911
|
-
title: "Reset Working Images",
|
|
1912
|
-
handler: () => {
|
|
1913
|
-
tool.workingItems = tool.cloneItems(tool.items);
|
|
1914
|
-
tool.hasWorkingChanges = false;
|
|
1915
|
-
tool.updateImages();
|
|
1916
|
-
tool.emitWorkingChange();
|
|
1917
|
-
}
|
|
1918
|
-
},
|
|
1919
|
-
{
|
|
1920
|
-
command: "completeImages",
|
|
1921
|
-
id: "completeImages",
|
|
1922
|
-
title: "Complete Images",
|
|
1923
|
-
handler: async () => {
|
|
1924
|
-
return await tool.commitWorkingImagesAsCropped();
|
|
1925
|
-
}
|
|
1926
|
-
},
|
|
1927
|
-
{
|
|
1928
|
-
command: "exportUserCroppedImage",
|
|
1929
|
-
id: "exportUserCroppedImage",
|
|
1930
|
-
title: "Export User Cropped Image",
|
|
1931
|
-
handler: async (options = {}) => {
|
|
1932
|
-
return await tool.exportUserCroppedImage(options);
|
|
1933
|
-
}
|
|
1934
|
-
},
|
|
1935
|
-
{
|
|
1936
|
-
command: "fitImageToArea",
|
|
1937
|
-
id: "fitImageToArea",
|
|
1938
|
-
title: "Fit Image to Area",
|
|
1939
|
-
handler: async (id, area) => {
|
|
1940
|
-
await tool.fitImageToArea(id, area);
|
|
1941
|
-
}
|
|
1942
|
-
},
|
|
1943
|
-
{
|
|
1944
|
-
command: "fitImageToDefaultArea",
|
|
1945
|
-
id: "fitImageToDefaultArea",
|
|
1946
|
-
title: "Fit Image to Default Area",
|
|
1947
|
-
handler: async (id) => {
|
|
1948
|
-
await tool.fitImageToDefaultArea(id);
|
|
1949
|
-
}
|
|
1950
|
-
},
|
|
1951
|
-
{
|
|
1952
|
-
command: "focusImage",
|
|
1953
|
-
id: "focusImage",
|
|
1954
|
-
title: "Focus Image",
|
|
1955
|
-
handler: (id, options = {}) => {
|
|
1956
|
-
return tool.setImageFocus(id, options);
|
|
1957
|
-
}
|
|
1958
|
-
},
|
|
1959
|
-
{
|
|
1960
|
-
command: "removeImage",
|
|
1961
|
-
id: "removeImage",
|
|
1962
|
-
title: "Remove Image",
|
|
1963
|
-
handler: (id) => {
|
|
1964
|
-
const removed = tool.items.find((item) => item.id === id);
|
|
1965
|
-
const next = tool.items.filter((item) => item.id !== id);
|
|
1966
|
-
if (next.length !== tool.items.length) {
|
|
1967
|
-
tool.purgeSourceSizeCacheForItem(removed);
|
|
1968
|
-
if (tool.focusedImageId === id) {
|
|
1969
|
-
tool.setImageFocus(null, {
|
|
1970
|
-
syncCanvasSelection: true,
|
|
1971
|
-
skipRender: true
|
|
1972
|
-
});
|
|
1973
|
-
}
|
|
1974
|
-
tool.updateConfig(next);
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
},
|
|
1978
|
-
{
|
|
1979
|
-
command: "updateImage",
|
|
1980
|
-
id: "updateImage",
|
|
1981
|
-
title: "Update Image",
|
|
1982
|
-
handler: async (id, updates, options = {}) => {
|
|
1983
|
-
await tool.updateImage(id, updates, options);
|
|
1984
|
-
}
|
|
1985
|
-
},
|
|
1986
|
-
{
|
|
1987
|
-
command: "clearImages",
|
|
1988
|
-
id: "clearImages",
|
|
1989
|
-
title: "Clear Images",
|
|
1990
|
-
handler: () => {
|
|
1991
|
-
tool.sourceSizeCache.clear();
|
|
1992
|
-
tool.setImageFocus(null, {
|
|
1993
|
-
syncCanvasSelection: true,
|
|
1994
|
-
skipRender: true
|
|
1995
|
-
});
|
|
1996
|
-
tool.updateConfig([]);
|
|
1997
|
-
}
|
|
1998
|
-
},
|
|
1999
|
-
{
|
|
2000
|
-
command: "bringToFront",
|
|
2001
|
-
id: "bringToFront",
|
|
2002
|
-
title: "Bring Image to Front",
|
|
2003
|
-
handler: (id) => {
|
|
2004
|
-
const index = tool.items.findIndex((item) => item.id === id);
|
|
2005
|
-
if (index !== -1 && index < tool.items.length - 1) {
|
|
2006
|
-
const next = [...tool.items];
|
|
2007
|
-
const [item] = next.splice(index, 1);
|
|
2008
|
-
next.push(item);
|
|
2009
|
-
tool.updateConfig(next);
|
|
2010
|
-
}
|
|
2011
|
-
}
|
|
2012
|
-
},
|
|
2013
|
-
{
|
|
2014
|
-
command: "sendToBack",
|
|
2015
|
-
id: "sendToBack",
|
|
2016
|
-
title: "Send Image to Back",
|
|
2017
|
-
handler: (id) => {
|
|
2018
|
-
const index = tool.items.findIndex((item) => item.id === id);
|
|
2019
|
-
if (index > 0) {
|
|
2020
|
-
const next = [...tool.items];
|
|
2021
|
-
const [item] = next.splice(index, 1);
|
|
2022
|
-
next.unshift(item);
|
|
2023
|
-
tool.updateConfig(next);
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
];
|
|
2207
|
+
shapeOffset.remove();
|
|
2208
|
+
bleedZone.remove();
|
|
2209
|
+
return pathData;
|
|
2210
|
+
}
|
|
2211
|
+
function getLowestPointOnDieline(options) {
|
|
2212
|
+
ensurePaper(options.width * 2, options.height * 2);
|
|
2213
|
+
paper.project.activeLayer.removeChildren();
|
|
2214
|
+
const shape = createBaseShape(options);
|
|
2215
|
+
const bounds = shape.bounds;
|
|
2216
|
+
const result = {
|
|
2217
|
+
x: bounds.center.x,
|
|
2218
|
+
y: bounds.bottom
|
|
2219
|
+
};
|
|
2220
|
+
shape.remove();
|
|
2221
|
+
return result;
|
|
2222
|
+
}
|
|
2223
|
+
function getNearestPointOnDieline(point, options) {
|
|
2224
|
+
ensurePaper(options.width * 2, options.height * 2);
|
|
2225
|
+
paper.project.activeLayer.removeChildren();
|
|
2226
|
+
const shape = createBaseShape(options);
|
|
2227
|
+
const p = new paper.Point(point.x, point.y);
|
|
2228
|
+
const location = shape.getNearestLocation(p);
|
|
2229
|
+
const result = {
|
|
2230
|
+
x: location.point.x,
|
|
2231
|
+
y: location.point.y,
|
|
2232
|
+
normal: location.normal ? { x: location.normal.x, y: location.normal.y } : void 0
|
|
2233
|
+
};
|
|
2234
|
+
shape.remove();
|
|
2235
|
+
return result;
|
|
2028
2236
|
}
|
|
2029
2237
|
|
|
2030
|
-
// src/extensions/image/
|
|
2031
|
-
|
|
2238
|
+
// src/extensions/image/sessionOverlay.ts
|
|
2239
|
+
var EPSILON = 1e-4;
|
|
2240
|
+
var SHAPE_OUTLINE_COLOR = "rgba(255, 0, 0, 0.9)";
|
|
2241
|
+
var DEFAULT_HATCH_FILL = "rgba(255, 0, 0, 0.22)";
|
|
2242
|
+
function buildRectPath(width, height) {
|
|
2243
|
+
return `M 0 0 L ${width} 0 L ${width} ${height} L 0 ${height} Z`;
|
|
2244
|
+
}
|
|
2245
|
+
function buildViewportMaskPath(viewport, cutRect) {
|
|
2246
|
+
const cutLeft = cutRect.left - viewport.left;
|
|
2247
|
+
const cutTop = cutRect.top - viewport.top;
|
|
2032
2248
|
return [
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
{
|
|
2095
|
-
id: "image.control.borderScaleFactor",
|
|
2096
|
-
type: "number",
|
|
2097
|
-
label: "Image Control Border Width",
|
|
2098
|
-
min: 0.5,
|
|
2099
|
-
max: 8,
|
|
2100
|
-
step: 0.1,
|
|
2101
|
-
default: 1.5
|
|
2102
|
-
},
|
|
2103
|
-
{
|
|
2104
|
-
id: "image.control.padding",
|
|
2105
|
-
type: "number",
|
|
2106
|
-
label: "Image Control Padding",
|
|
2107
|
-
min: 0,
|
|
2108
|
-
max: 64,
|
|
2109
|
-
step: 1,
|
|
2110
|
-
default: 0
|
|
2111
|
-
},
|
|
2112
|
-
{
|
|
2113
|
-
id: "image.frame.strokeColor",
|
|
2114
|
-
type: "color",
|
|
2115
|
-
label: "Image Frame Stroke Color",
|
|
2116
|
-
default: "#808080"
|
|
2117
|
-
},
|
|
2118
|
-
{
|
|
2119
|
-
id: "image.frame.strokeWidth",
|
|
2120
|
-
type: "number",
|
|
2121
|
-
label: "Image Frame Stroke Width",
|
|
2122
|
-
min: 0,
|
|
2123
|
-
max: 20,
|
|
2124
|
-
step: 0.5,
|
|
2125
|
-
default: 2
|
|
2126
|
-
},
|
|
2127
|
-
{
|
|
2128
|
-
id: "image.frame.strokeStyle",
|
|
2129
|
-
type: "select",
|
|
2130
|
-
label: "Image Frame Stroke Style",
|
|
2131
|
-
options: ["solid", "dashed", "hidden"],
|
|
2132
|
-
default: "dashed"
|
|
2133
|
-
},
|
|
2134
|
-
{
|
|
2135
|
-
id: "image.frame.dashLength",
|
|
2136
|
-
type: "number",
|
|
2137
|
-
label: "Image Frame Dash Length",
|
|
2138
|
-
min: 1,
|
|
2139
|
-
max: 40,
|
|
2140
|
-
step: 1,
|
|
2141
|
-
default: 8
|
|
2142
|
-
},
|
|
2143
|
-
{
|
|
2144
|
-
id: "image.frame.innerBackground",
|
|
2145
|
-
type: "color",
|
|
2146
|
-
label: "Image Frame Inner Background",
|
|
2147
|
-
default: "rgba(0,0,0,0)"
|
|
2148
|
-
},
|
|
2149
|
-
{
|
|
2150
|
-
id: "image.frame.outerBackground",
|
|
2151
|
-
type: "color",
|
|
2152
|
-
label: "Image Frame Outer Background",
|
|
2153
|
-
default: "#f5f5f5"
|
|
2249
|
+
buildRectPath(viewport.width, viewport.height),
|
|
2250
|
+
`M ${cutLeft} ${cutTop} L ${cutLeft + cutRect.width} ${cutTop} L ${cutLeft + cutRect.width} ${cutTop + cutRect.height} L ${cutLeft} ${cutTop + cutRect.height} Z`
|
|
2251
|
+
].join(" ");
|
|
2252
|
+
}
|
|
2253
|
+
function resolveCutShapeRadiusPx(geometry, cutRect) {
|
|
2254
|
+
const visualRadius = Number.isFinite(geometry.radius) ? Math.max(0, geometry.radius) : 0;
|
|
2255
|
+
const visualOffset = Number.isFinite(geometry.offset) ? geometry.offset : 0;
|
|
2256
|
+
const rawCutRadius = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
2257
|
+
const maxRadius = Math.max(0, Math.min(cutRect.width, cutRect.height) / 2);
|
|
2258
|
+
return Math.max(0, Math.min(maxRadius, rawCutRadius));
|
|
2259
|
+
}
|
|
2260
|
+
function buildBuiltinShapeOverlayPaths(cutRect, geometry) {
|
|
2261
|
+
if (!geometry || geometry.shape === "custom") {
|
|
2262
|
+
return null;
|
|
2263
|
+
}
|
|
2264
|
+
const radius = resolveCutShapeRadiusPx(geometry, cutRect);
|
|
2265
|
+
if (geometry.shape === "rect" && radius <= EPSILON) {
|
|
2266
|
+
return null;
|
|
2267
|
+
}
|
|
2268
|
+
const shapePathData = generateDielinePath({
|
|
2269
|
+
shape: geometry.shape,
|
|
2270
|
+
shapeStyle: geometry.shapeStyle,
|
|
2271
|
+
width: Math.max(1, cutRect.width),
|
|
2272
|
+
height: Math.max(1, cutRect.height),
|
|
2273
|
+
radius,
|
|
2274
|
+
x: cutRect.width / 2,
|
|
2275
|
+
y: cutRect.height / 2,
|
|
2276
|
+
features: [],
|
|
2277
|
+
canvasWidth: Math.max(1, cutRect.width),
|
|
2278
|
+
canvasHeight: Math.max(1, cutRect.height)
|
|
2279
|
+
});
|
|
2280
|
+
if (!shapePathData) {
|
|
2281
|
+
return null;
|
|
2282
|
+
}
|
|
2283
|
+
return {
|
|
2284
|
+
shapePathData,
|
|
2285
|
+
hatchPathData: `${buildRectPath(cutRect.width, cutRect.height)} ${shapePathData}`
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
function buildImageSessionOverlaySpecs(args) {
|
|
2289
|
+
const { viewport, layout, geometry, visual, hatchPattern } = args;
|
|
2290
|
+
const cutRect = layout.cutRect;
|
|
2291
|
+
const specs = [];
|
|
2292
|
+
specs.push({
|
|
2293
|
+
id: "image.cropMask.rect",
|
|
2294
|
+
type: "path",
|
|
2295
|
+
space: "screen",
|
|
2296
|
+
data: { id: "image.cropMask.rect", zIndex: 1 },
|
|
2297
|
+
props: {
|
|
2298
|
+
pathData: buildViewportMaskPath(viewport, cutRect),
|
|
2299
|
+
left: viewport.left,
|
|
2300
|
+
top: viewport.top,
|
|
2301
|
+
originX: "left",
|
|
2302
|
+
originY: "top",
|
|
2303
|
+
fill: visual.outerBackground,
|
|
2304
|
+
stroke: null,
|
|
2305
|
+
fillRule: "evenodd",
|
|
2306
|
+
selectable: false,
|
|
2307
|
+
evented: false,
|
|
2308
|
+
excludeFromExport: true,
|
|
2309
|
+
objectCaching: false
|
|
2154
2310
|
}
|
|
2155
|
-
|
|
2311
|
+
});
|
|
2312
|
+
const shapeOverlay = buildBuiltinShapeOverlayPaths(cutRect, geometry);
|
|
2313
|
+
if (shapeOverlay) {
|
|
2314
|
+
specs.push({
|
|
2315
|
+
id: "image.cropShapeHatch",
|
|
2316
|
+
type: "path",
|
|
2317
|
+
space: "screen",
|
|
2318
|
+
data: { id: "image.cropShapeHatch", zIndex: 5 },
|
|
2319
|
+
props: {
|
|
2320
|
+
pathData: shapeOverlay.hatchPathData,
|
|
2321
|
+
left: cutRect.left,
|
|
2322
|
+
top: cutRect.top,
|
|
2323
|
+
originX: "left",
|
|
2324
|
+
originY: "top",
|
|
2325
|
+
fill: hatchPattern || DEFAULT_HATCH_FILL,
|
|
2326
|
+
opacity: hatchPattern ? 1 : 0.8,
|
|
2327
|
+
stroke: null,
|
|
2328
|
+
fillRule: "evenodd",
|
|
2329
|
+
selectable: false,
|
|
2330
|
+
evented: false,
|
|
2331
|
+
excludeFromExport: true,
|
|
2332
|
+
objectCaching: false
|
|
2333
|
+
}
|
|
2334
|
+
});
|
|
2335
|
+
specs.push({
|
|
2336
|
+
id: "image.cropShapeOutline",
|
|
2337
|
+
type: "path",
|
|
2338
|
+
space: "screen",
|
|
2339
|
+
data: { id: "image.cropShapeOutline", zIndex: 6 },
|
|
2340
|
+
props: {
|
|
2341
|
+
pathData: shapeOverlay.shapePathData,
|
|
2342
|
+
left: cutRect.left,
|
|
2343
|
+
top: cutRect.top,
|
|
2344
|
+
originX: "left",
|
|
2345
|
+
originY: "top",
|
|
2346
|
+
fill: "transparent",
|
|
2347
|
+
stroke: SHAPE_OUTLINE_COLOR,
|
|
2348
|
+
strokeWidth: 1,
|
|
2349
|
+
selectable: false,
|
|
2350
|
+
evented: false,
|
|
2351
|
+
excludeFromExport: true,
|
|
2352
|
+
objectCaching: false
|
|
2353
|
+
}
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2356
|
+
specs.push({
|
|
2357
|
+
id: "image.cropFrame",
|
|
2358
|
+
type: "rect",
|
|
2359
|
+
space: "screen",
|
|
2360
|
+
data: { id: "image.cropFrame", zIndex: 7 },
|
|
2361
|
+
props: {
|
|
2362
|
+
left: cutRect.left,
|
|
2363
|
+
top: cutRect.top,
|
|
2364
|
+
width: cutRect.width,
|
|
2365
|
+
height: cutRect.height,
|
|
2366
|
+
originX: "left",
|
|
2367
|
+
originY: "top",
|
|
2368
|
+
fill: visual.innerBackground,
|
|
2369
|
+
stroke: visual.strokeStyle === "hidden" ? "rgba(0,0,0,0)" : visual.strokeColor,
|
|
2370
|
+
strokeWidth: visual.strokeStyle === "hidden" ? 0 : visual.strokeWidth,
|
|
2371
|
+
strokeDashArray: visual.strokeStyle === "dashed" ? [visual.dashLength, visual.dashLength] : void 0,
|
|
2372
|
+
selectable: false,
|
|
2373
|
+
evented: false,
|
|
2374
|
+
excludeFromExport: true
|
|
2375
|
+
}
|
|
2376
|
+
});
|
|
2377
|
+
return specs;
|
|
2156
2378
|
}
|
|
2157
2379
|
|
|
2158
2380
|
// src/extensions/image/ImageTool.ts
|
|
@@ -2440,6 +2662,7 @@ var ImageTool = class {
|
|
|
2440
2662
|
this.clearRenderedImages();
|
|
2441
2663
|
(_b = this.renderProducerDisposable) == null ? void 0 : _b.dispose();
|
|
2442
2664
|
this.renderProducerDisposable = void 0;
|
|
2665
|
+
this.emitImageStateChange();
|
|
2443
2666
|
if (this.canvasService) {
|
|
2444
2667
|
void this.canvasService.flushRenderFromProducers();
|
|
2445
2668
|
this.canvasService = void 0;
|
|
@@ -2614,11 +2837,21 @@ var ImageTool = class {
|
|
|
2614
2837
|
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2615
2838
|
}
|
|
2616
2839
|
}
|
|
2840
|
+
clearSnapGuideContext() {
|
|
2841
|
+
var _a;
|
|
2842
|
+
const topContext = (_a = this.canvasService) == null ? void 0 : _a.canvas.contextTop;
|
|
2843
|
+
if (!this.canvasService || !topContext) return;
|
|
2844
|
+
this.canvasService.canvas.clearContext(topContext);
|
|
2845
|
+
}
|
|
2617
2846
|
clearSnapPreview() {
|
|
2618
2847
|
var _a;
|
|
2848
|
+
const shouldClearCanvas = this.hasRenderedSnapGuides || !!this.activeSnapX || !!this.activeSnapY;
|
|
2619
2849
|
this.activeSnapX = null;
|
|
2620
2850
|
this.activeSnapY = null;
|
|
2621
2851
|
this.hasRenderedSnapGuides = false;
|
|
2852
|
+
if (shouldClearCanvas) {
|
|
2853
|
+
this.clearSnapGuideContext();
|
|
2854
|
+
}
|
|
2622
2855
|
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2623
2856
|
}
|
|
2624
2857
|
endMoveSnapInteraction() {
|
|
@@ -2839,9 +3072,9 @@ var ImageTool = class {
|
|
|
2839
3072
|
name: "Image",
|
|
2840
3073
|
interaction: "session",
|
|
2841
3074
|
commands: {
|
|
2842
|
-
begin: "
|
|
3075
|
+
begin: "imageSessionReset",
|
|
2843
3076
|
commit: "completeImages",
|
|
2844
|
-
rollback: "
|
|
3077
|
+
rollback: "imageSessionReset"
|
|
2845
3078
|
},
|
|
2846
3079
|
session: {
|
|
2847
3080
|
autoBegin: true,
|
|
@@ -2875,6 +3108,28 @@ var ImageTool = class {
|
|
|
2875
3108
|
cloneItems(items) {
|
|
2876
3109
|
return this.normalizeItems((items || []).map((i) => ({ ...i })));
|
|
2877
3110
|
}
|
|
3111
|
+
getViewItems() {
|
|
3112
|
+
return this.isToolActive ? this.workingItems : this.items;
|
|
3113
|
+
}
|
|
3114
|
+
getImageViewState() {
|
|
3115
|
+
this.syncToolActiveFromWorkbench();
|
|
3116
|
+
const items = this.cloneItems(this.getViewItems());
|
|
3117
|
+
const focusedItem = this.focusedImageId == null ? null : items.find((item) => item.id === this.focusedImageId) || null;
|
|
3118
|
+
return {
|
|
3119
|
+
items,
|
|
3120
|
+
hasAnyImage: items.length > 0,
|
|
3121
|
+
focusedId: this.focusedImageId,
|
|
3122
|
+
focusedItem,
|
|
3123
|
+
isToolActive: this.isToolActive,
|
|
3124
|
+
isImageSelectionActive: this.isImageSelectionActive,
|
|
3125
|
+
hasWorkingChanges: this.hasWorkingChanges,
|
|
3126
|
+
source: this.isToolActive ? "working" : "committed"
|
|
3127
|
+
};
|
|
3128
|
+
}
|
|
3129
|
+
emitImageStateChange() {
|
|
3130
|
+
var _a;
|
|
3131
|
+
(_a = this.context) == null ? void 0 : _a.eventBus.emit("image:state:change", this.getImageViewState());
|
|
3132
|
+
}
|
|
2878
3133
|
emitWorkingChange(changedId = null) {
|
|
2879
3134
|
var _a;
|
|
2880
3135
|
(_a = this.context) == null ? void 0 : _a.eventBus.emit("image:working:change", {
|
|
@@ -2910,10 +3165,13 @@ var ImageTool = class {
|
|
|
2910
3165
|
}
|
|
2911
3166
|
if (!options.skipRender) {
|
|
2912
3167
|
this.updateImages();
|
|
3168
|
+
} else {
|
|
3169
|
+
this.emitImageStateChange();
|
|
2913
3170
|
}
|
|
2914
3171
|
return { ok: true, id };
|
|
2915
3172
|
}
|
|
2916
|
-
async addImageEntry(url, options,
|
|
3173
|
+
async addImageEntry(url, options, operation) {
|
|
3174
|
+
this.syncToolActiveFromWorkbench();
|
|
2917
3175
|
const id = this.generateId();
|
|
2918
3176
|
const newItem = this.normalizeItem({
|
|
2919
3177
|
id,
|
|
@@ -2921,13 +3179,20 @@ var ImageTool = class {
|
|
|
2921
3179
|
opacity: 1,
|
|
2922
3180
|
...options
|
|
2923
3181
|
});
|
|
2924
|
-
const sessionDirtyBeforeAdd = this.isToolActive && this.hasWorkingChanges;
|
|
2925
3182
|
const waitLoaded = this.waitImageLoaded(id, true);
|
|
2926
|
-
|
|
2927
|
-
|
|
3183
|
+
if (this.isToolActive) {
|
|
3184
|
+
this.workingItems = this.cloneItems([...this.workingItems, newItem]);
|
|
3185
|
+
this.hasWorkingChanges = true;
|
|
3186
|
+
this.updateImages();
|
|
3187
|
+
this.emitWorkingChange(id);
|
|
3188
|
+
} else {
|
|
3189
|
+
this.updateConfig([...this.items, newItem]);
|
|
3190
|
+
}
|
|
2928
3191
|
const loaded = await waitLoaded;
|
|
2929
|
-
if (loaded &&
|
|
2930
|
-
await this.
|
|
3192
|
+
if (loaded && operation) {
|
|
3193
|
+
await this.applyImageOperation(id, operation, {
|
|
3194
|
+
target: this.isToolActive ? "working" : "config"
|
|
3195
|
+
});
|
|
2931
3196
|
}
|
|
2932
3197
|
if (loaded) {
|
|
2933
3198
|
this.setImageFocus(id);
|
|
@@ -2935,8 +3200,8 @@ var ImageTool = class {
|
|
|
2935
3200
|
return id;
|
|
2936
3201
|
}
|
|
2937
3202
|
async upsertImageEntry(url, options = {}) {
|
|
3203
|
+
this.syncToolActiveFromWorkbench();
|
|
2938
3204
|
const mode = options.mode || (options.id ? "replace" : "add");
|
|
2939
|
-
const fitOnAdd = options.fitOnAdd !== false;
|
|
2940
3205
|
if (mode === "replace") {
|
|
2941
3206
|
if (!options.id) {
|
|
2942
3207
|
throw new Error("replace-target-id-required");
|
|
@@ -2945,19 +3210,31 @@ var ImageTool = class {
|
|
|
2945
3210
|
if (!this.hasImageItem(targetId)) {
|
|
2946
3211
|
throw new Error("replace-target-not-found");
|
|
2947
3212
|
}
|
|
2948
|
-
|
|
3213
|
+
if (this.isToolActive) {
|
|
3214
|
+
const current = this.workingItems.find((item) => item.id === targetId) || this.items.find((item) => item.id === targetId);
|
|
3215
|
+
this.purgeSourceSizeCacheForItem(current);
|
|
3216
|
+
this.updateImageInWorking(targetId, {
|
|
3217
|
+
url,
|
|
3218
|
+
sourceUrl: url,
|
|
3219
|
+
committedUrl: void 0
|
|
3220
|
+
});
|
|
3221
|
+
} else {
|
|
3222
|
+
await this.updateImageInConfig(targetId, { url });
|
|
3223
|
+
}
|
|
3224
|
+
const loaded = await this.waitImageLoaded(targetId, true);
|
|
3225
|
+
if (loaded && options.operation) {
|
|
3226
|
+
await this.applyImageOperation(targetId, options.operation, {
|
|
3227
|
+
target: this.isToolActive ? "working" : "config"
|
|
3228
|
+
});
|
|
3229
|
+
}
|
|
3230
|
+
if (loaded) {
|
|
3231
|
+
this.setImageFocus(targetId);
|
|
3232
|
+
}
|
|
2949
3233
|
return { id: targetId, mode: "replace" };
|
|
2950
3234
|
}
|
|
2951
|
-
const id = await this.addImageEntry(url, options.addOptions,
|
|
3235
|
+
const id = await this.addImageEntry(url, options.addOptions, options.operation);
|
|
2952
3236
|
return { id, mode: "add" };
|
|
2953
3237
|
}
|
|
2954
|
-
addItemToWorkingSessionIfNeeded(item, sessionDirtyBeforeAdd) {
|
|
2955
|
-
if (!sessionDirtyBeforeAdd || !this.isToolActive) return;
|
|
2956
|
-
if (this.workingItems.some((existing) => existing.id === item.id)) return;
|
|
2957
|
-
this.workingItems = this.cloneItems([...this.workingItems, item]);
|
|
2958
|
-
this.updateImages();
|
|
2959
|
-
this.emitWorkingChange(item.id);
|
|
2960
|
-
}
|
|
2961
3238
|
async updateImage(id, updates, options = {}) {
|
|
2962
3239
|
this.syncToolActiveFromWorkbench();
|
|
2963
3240
|
const target = options.target || "auto";
|
|
@@ -3018,40 +3295,9 @@ var ImageTool = class {
|
|
|
3018
3295
|
}
|
|
3019
3296
|
getFrameRectScreen(frame) {
|
|
3020
3297
|
if (!this.canvasService) {
|
|
3021
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
3022
|
-
}
|
|
3023
|
-
return this.canvasService.toScreenRect(frame || this.getFrameRect());
|
|
3024
|
-
}
|
|
3025
|
-
toLayoutSceneRect(rect) {
|
|
3026
|
-
return toLayoutSceneRect(rect);
|
|
3027
|
-
}
|
|
3028
|
-
async resolveDefaultFitArea() {
|
|
3029
|
-
if (!this.canvasService) return null;
|
|
3030
|
-
const frame = this.getFrameRect();
|
|
3031
|
-
if (frame.width <= 0 || frame.height <= 0) return null;
|
|
3032
|
-
return {
|
|
3033
|
-
width: Math.max(1, frame.width),
|
|
3034
|
-
height: Math.max(1, frame.height),
|
|
3035
|
-
left: frame.left + frame.width / 2,
|
|
3036
|
-
top: frame.top + frame.height / 2
|
|
3037
|
-
};
|
|
3038
|
-
}
|
|
3039
|
-
async fitImageToDefaultArea(id) {
|
|
3040
|
-
if (!this.canvasService) return;
|
|
3041
|
-
const area = await this.resolveDefaultFitArea();
|
|
3042
|
-
if (area) {
|
|
3043
|
-
await this.fitImageToArea(id, area);
|
|
3044
|
-
return;
|
|
3298
|
+
return { left: 0, top: 0, width: 0, height: 0 };
|
|
3045
3299
|
}
|
|
3046
|
-
|
|
3047
|
-
const canvasW = Math.max(1, viewport.width || 0);
|
|
3048
|
-
const canvasH = Math.max(1, viewport.height || 0);
|
|
3049
|
-
await this.fitImageToArea(id, {
|
|
3050
|
-
width: canvasW,
|
|
3051
|
-
height: canvasH,
|
|
3052
|
-
left: viewport.left + canvasW / 2,
|
|
3053
|
-
top: viewport.top + canvasH / 2
|
|
3054
|
-
});
|
|
3300
|
+
return this.canvasService.toScreenRect(frame || this.getFrameRect());
|
|
3055
3301
|
}
|
|
3056
3302
|
getImageObjects() {
|
|
3057
3303
|
if (!this.canvasService) return [];
|
|
@@ -3151,74 +3397,37 @@ var ImageTool = class {
|
|
|
3151
3397
|
outerBackground: this.getConfig("image.frame.outerBackground", "#f5f5f5") || "#f5f5f5"
|
|
3152
3398
|
};
|
|
3153
3399
|
}
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
if (!isDielineShape(shape)) {
|
|
3400
|
+
resolveSessionOverlayState() {
|
|
3401
|
+
if (!this.canvasService || !this.context) {
|
|
3157
3402
|
return null;
|
|
3158
3403
|
}
|
|
3159
|
-
const radiusRaw = Number(raw == null ? void 0 : raw.radius);
|
|
3160
|
-
const offsetRaw = Number(raw == null ? void 0 : raw.offset);
|
|
3161
|
-
const unit = typeof (raw == null ? void 0 : raw.unit) === "string" ? raw.unit : "px";
|
|
3162
|
-
const radius = unit === "scene" || !this.canvasService ? radiusRaw : this.canvasService.toSceneLength(radiusRaw);
|
|
3163
|
-
const offset = unit === "scene" || !this.canvasService ? offsetRaw : this.canvasService.toSceneLength(offsetRaw);
|
|
3164
|
-
return {
|
|
3165
|
-
shape,
|
|
3166
|
-
shapeStyle: normalizeShapeStyle(raw == null ? void 0 : raw.shapeStyle),
|
|
3167
|
-
radius: Number.isFinite(radius) ? radius : 0,
|
|
3168
|
-
offset: Number.isFinite(offset) ? offset : 0
|
|
3169
|
-
};
|
|
3170
|
-
}
|
|
3171
|
-
async resolveSceneGeometryForOverlay() {
|
|
3172
|
-
if (!this.context) return null;
|
|
3173
|
-
const commandService = this.context.services.get("CommandService");
|
|
3174
|
-
if (commandService) {
|
|
3175
|
-
try {
|
|
3176
|
-
const raw = await Promise.resolve(
|
|
3177
|
-
commandService.executeCommand("getSceneGeometry")
|
|
3178
|
-
);
|
|
3179
|
-
const geometry2 = this.toSceneGeometryLike(raw);
|
|
3180
|
-
if (geometry2) {
|
|
3181
|
-
this.debug("overlay:sceneGeometry:command", geometry2);
|
|
3182
|
-
return geometry2;
|
|
3183
|
-
}
|
|
3184
|
-
this.debug("overlay:sceneGeometry:command:invalid", { raw });
|
|
3185
|
-
} catch (error) {
|
|
3186
|
-
this.debug("overlay:sceneGeometry:command:error", {
|
|
3187
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3188
|
-
});
|
|
3189
|
-
}
|
|
3190
|
-
}
|
|
3191
|
-
if (!this.canvasService) return null;
|
|
3192
3404
|
const configService = this.context.services.get(
|
|
3193
3405
|
"ConfigurationService"
|
|
3194
3406
|
);
|
|
3195
|
-
if (!configService)
|
|
3196
|
-
const sizeState = readSizeState(configService);
|
|
3197
|
-
const layout = computeSceneLayout(this.canvasService, sizeState);
|
|
3198
|
-
if (!layout) {
|
|
3199
|
-
this.debug("overlay:sceneGeometry:fallback:missing-layout");
|
|
3407
|
+
if (!configService) {
|
|
3200
3408
|
return null;
|
|
3201
3409
|
}
|
|
3202
|
-
const
|
|
3203
|
-
|
|
3410
|
+
const layout = computeSceneLayout(
|
|
3411
|
+
this.canvasService,
|
|
3412
|
+
readSizeState(configService)
|
|
3204
3413
|
);
|
|
3205
|
-
if (
|
|
3206
|
-
this.debug("overlay:
|
|
3414
|
+
if (!layout) {
|
|
3415
|
+
this.debug("overlay:layout:missing");
|
|
3416
|
+
return null;
|
|
3207
3417
|
}
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3418
|
+
const geometry = buildSceneGeometry(configService, layout);
|
|
3419
|
+
this.debug("overlay:state:resolved", {
|
|
3420
|
+
cutRect: layout.cutRect,
|
|
3421
|
+
shape: geometry.shape,
|
|
3422
|
+
shapeStyle: geometry.shapeStyle,
|
|
3423
|
+
radius: geometry.radius,
|
|
3424
|
+
offset: geometry.offset
|
|
3425
|
+
});
|
|
3426
|
+
return { layout, geometry };
|
|
3216
3427
|
}
|
|
3217
3428
|
getCropShapeHatchPattern(color = "rgba(255, 0, 0, 0.6)") {
|
|
3218
|
-
var _a;
|
|
3219
3429
|
if (typeof document === "undefined") return void 0;
|
|
3220
|
-
const
|
|
3221
|
-
const cacheKey = `${color}::${sceneScale.toFixed(6)}`;
|
|
3430
|
+
const cacheKey = color;
|
|
3222
3431
|
if (this.cropShapeHatchPattern && this.cropShapeHatchPatternColor === color && this.cropShapeHatchPatternKey === cacheKey) {
|
|
3223
3432
|
return this.cropShapeHatchPattern;
|
|
3224
3433
|
}
|
|
@@ -3248,138 +3457,11 @@ var ImageTool = class {
|
|
|
3248
3457
|
// @ts-ignore: Fabric Pattern accepts canvas source here.
|
|
3249
3458
|
repetition: "repeat"
|
|
3250
3459
|
});
|
|
3251
|
-
pattern.patternTransform = [
|
|
3252
|
-
1 / sceneScale,
|
|
3253
|
-
0,
|
|
3254
|
-
0,
|
|
3255
|
-
1 / sceneScale,
|
|
3256
|
-
0,
|
|
3257
|
-
0
|
|
3258
|
-
];
|
|
3259
3460
|
this.cropShapeHatchPattern = pattern;
|
|
3260
3461
|
this.cropShapeHatchPatternColor = color;
|
|
3261
3462
|
this.cropShapeHatchPatternKey = cacheKey;
|
|
3262
3463
|
return pattern;
|
|
3263
3464
|
}
|
|
3264
|
-
buildCropShapeOverlaySpecs(frame, sceneGeometry) {
|
|
3265
|
-
var _a, _b;
|
|
3266
|
-
if (!sceneGeometry) {
|
|
3267
|
-
this.debug("overlay:shape:skip", { reason: "scene-geometry-missing" });
|
|
3268
|
-
return [];
|
|
3269
|
-
}
|
|
3270
|
-
if (sceneGeometry.shape === "custom") {
|
|
3271
|
-
this.debug("overlay:shape:skip", { reason: "shape-custom" });
|
|
3272
|
-
return [];
|
|
3273
|
-
}
|
|
3274
|
-
const shape = sceneGeometry.shape;
|
|
3275
|
-
const shapeStyle = sceneGeometry.shapeStyle;
|
|
3276
|
-
const inset = 0;
|
|
3277
|
-
const shapeWidth = Math.max(1, frame.width);
|
|
3278
|
-
const shapeHeight = Math.max(1, frame.height);
|
|
3279
|
-
const radius = this.resolveCutShapeRadius(sceneGeometry, frame);
|
|
3280
|
-
this.debug("overlay:shape:geometry", {
|
|
3281
|
-
shape,
|
|
3282
|
-
frameWidth: frame.width,
|
|
3283
|
-
frameHeight: frame.height,
|
|
3284
|
-
offset: sceneGeometry.offset,
|
|
3285
|
-
shapeStyle,
|
|
3286
|
-
inset,
|
|
3287
|
-
shapeWidth,
|
|
3288
|
-
shapeHeight,
|
|
3289
|
-
baseRadius: sceneGeometry.radius,
|
|
3290
|
-
radius
|
|
3291
|
-
});
|
|
3292
|
-
const isSameAsFrame = Math.abs(shapeWidth - frame.width) <= 1e-4 && Math.abs(shapeHeight - frame.height) <= 1e-4;
|
|
3293
|
-
if (shape === "rect" && radius <= 1e-4 && isSameAsFrame) {
|
|
3294
|
-
this.debug("overlay:shape:skip", {
|
|
3295
|
-
reason: "shape-rect-no-radius"
|
|
3296
|
-
});
|
|
3297
|
-
return [];
|
|
3298
|
-
}
|
|
3299
|
-
const baseOptions = {
|
|
3300
|
-
shape,
|
|
3301
|
-
width: shapeWidth,
|
|
3302
|
-
height: shapeHeight,
|
|
3303
|
-
radius,
|
|
3304
|
-
x: frame.width / 2,
|
|
3305
|
-
y: frame.height / 2,
|
|
3306
|
-
features: [],
|
|
3307
|
-
shapeStyle,
|
|
3308
|
-
canvasWidth: frame.width,
|
|
3309
|
-
canvasHeight: frame.height
|
|
3310
|
-
};
|
|
3311
|
-
try {
|
|
3312
|
-
const shapePathData = generateDielinePath(baseOptions);
|
|
3313
|
-
const outerRectPathData = `M 0 0 L ${frame.width} 0 L ${frame.width} ${frame.height} L 0 ${frame.height} Z`;
|
|
3314
|
-
const hatchPathData = `${outerRectPathData} ${shapePathData}`;
|
|
3315
|
-
if (!shapePathData || !hatchPathData) {
|
|
3316
|
-
this.debug("overlay:shape:skip", {
|
|
3317
|
-
reason: "path-generation-empty",
|
|
3318
|
-
shape,
|
|
3319
|
-
radius
|
|
3320
|
-
});
|
|
3321
|
-
return [];
|
|
3322
|
-
}
|
|
3323
|
-
const patternFill = this.getCropShapeHatchPattern();
|
|
3324
|
-
const hatchFill = patternFill || "rgba(255, 0, 0, 0.22)";
|
|
3325
|
-
const shapeBounds = getPathBounds(shapePathData);
|
|
3326
|
-
const hatchBounds = getPathBounds(hatchPathData);
|
|
3327
|
-
const frameRect = this.toLayoutSceneRect(frame);
|
|
3328
|
-
const hatchPathLength = hatchPathData.length;
|
|
3329
|
-
const shapePathLength = shapePathData.length;
|
|
3330
|
-
const specs = [
|
|
3331
|
-
{
|
|
3332
|
-
id: "image.cropShapeHatch",
|
|
3333
|
-
type: "path",
|
|
3334
|
-
data: { id: "image.cropShapeHatch", zIndex: 5 },
|
|
3335
|
-
layout: {
|
|
3336
|
-
reference: "custom",
|
|
3337
|
-
referenceRect: frameRect,
|
|
3338
|
-
alignX: "start",
|
|
3339
|
-
alignY: "start",
|
|
3340
|
-
offsetX: hatchBounds.x,
|
|
3341
|
-
offsetY: hatchBounds.y
|
|
3342
|
-
},
|
|
3343
|
-
props: {
|
|
3344
|
-
pathData: hatchPathData,
|
|
3345
|
-
originX: "left",
|
|
3346
|
-
originY: "top",
|
|
3347
|
-
fill: hatchFill,
|
|
3348
|
-
opacity: patternFill ? 1 : 0.8,
|
|
3349
|
-
stroke: "rgba(255, 0, 0, 0.9)",
|
|
3350
|
-
strokeWidth: (_b = (_a = this.canvasService) == null ? void 0 : _a.toSceneLength(1)) != null ? _b : 1,
|
|
3351
|
-
fillRule: "evenodd",
|
|
3352
|
-
selectable: false,
|
|
3353
|
-
evented: false,
|
|
3354
|
-
excludeFromExport: true,
|
|
3355
|
-
objectCaching: false
|
|
3356
|
-
}
|
|
3357
|
-
}
|
|
3358
|
-
];
|
|
3359
|
-
this.debug("overlay:shape:built", {
|
|
3360
|
-
shape,
|
|
3361
|
-
radius,
|
|
3362
|
-
inset,
|
|
3363
|
-
shapeWidth,
|
|
3364
|
-
shapeHeight,
|
|
3365
|
-
fillRule: "evenodd",
|
|
3366
|
-
shapePathLength,
|
|
3367
|
-
hatchPathLength,
|
|
3368
|
-
shapeBounds,
|
|
3369
|
-
hatchBounds,
|
|
3370
|
-
hatchFillType: hatchFill && typeof hatchFill === "object" ? "pattern" : "color",
|
|
3371
|
-
ids: specs.map((spec) => spec.id)
|
|
3372
|
-
});
|
|
3373
|
-
return specs;
|
|
3374
|
-
} catch (error) {
|
|
3375
|
-
this.debug("overlay:shape:error", {
|
|
3376
|
-
shape,
|
|
3377
|
-
radius,
|
|
3378
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3379
|
-
});
|
|
3380
|
-
return [];
|
|
3381
|
-
}
|
|
3382
|
-
}
|
|
3383
3465
|
resolveRenderImageState(item) {
|
|
3384
3466
|
var _a;
|
|
3385
3467
|
const active = this.isToolActive;
|
|
@@ -3461,172 +3543,35 @@ var ImageTool = class {
|
|
|
3461
3543
|
}
|
|
3462
3544
|
return specs;
|
|
3463
3545
|
}
|
|
3464
|
-
buildOverlaySpecs(
|
|
3546
|
+
buildOverlaySpecs(overlayState) {
|
|
3465
3547
|
const visible = this.isImageEditingVisible();
|
|
3466
|
-
if (!visible ||
|
|
3548
|
+
if (!visible || !overlayState || !this.canvasService) {
|
|
3467
3549
|
this.debug("overlay:hidden", {
|
|
3468
3550
|
visible,
|
|
3469
|
-
|
|
3551
|
+
cutRect: overlayState == null ? void 0 : overlayState.layout.cutRect,
|
|
3470
3552
|
isToolActive: this.isToolActive,
|
|
3471
3553
|
isImageSelectionActive: this.isImageSelectionActive,
|
|
3472
3554
|
focusedImageId: this.focusedImageId
|
|
3473
3555
|
});
|
|
3474
3556
|
return [];
|
|
3475
3557
|
}
|
|
3476
|
-
const viewport = this.canvasService.
|
|
3477
|
-
const canvasW = viewport.width || 0;
|
|
3478
|
-
const canvasH = viewport.height || 0;
|
|
3479
|
-
const canvasLeft = viewport.left || 0;
|
|
3480
|
-
const canvasTop = viewport.top || 0;
|
|
3558
|
+
const viewport = this.canvasService.getScreenViewportRect();
|
|
3481
3559
|
const visual = this.getFrameVisualConfig();
|
|
3482
|
-
const
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
Math.min(canvasLeft + canvasW, frame.left)
|
|
3489
|
-
);
|
|
3490
|
-
const frameTop = Math.max(
|
|
3491
|
-
canvasTop,
|
|
3492
|
-
Math.min(canvasTop + canvasH, frame.top)
|
|
3493
|
-
);
|
|
3494
|
-
const frameRight = Math.max(
|
|
3495
|
-
frameLeft,
|
|
3496
|
-
Math.min(canvasLeft + canvasW, frame.left + frame.width)
|
|
3497
|
-
);
|
|
3498
|
-
const frameBottom = Math.max(
|
|
3499
|
-
frameTop,
|
|
3500
|
-
Math.min(canvasTop + canvasH, frame.top + frame.height)
|
|
3501
|
-
);
|
|
3502
|
-
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
3503
|
-
const topH = Math.max(0, frameTop - canvasTop);
|
|
3504
|
-
const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
|
|
3505
|
-
const leftW = Math.max(0, frameLeft - canvasLeft);
|
|
3506
|
-
const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
|
|
3507
|
-
const viewportRect = this.toLayoutSceneRect({
|
|
3508
|
-
left: canvasLeft,
|
|
3509
|
-
top: canvasTop,
|
|
3510
|
-
width: canvasW,
|
|
3511
|
-
height: canvasH
|
|
3512
|
-
});
|
|
3513
|
-
const visibleFrameBandRect = this.toLayoutSceneRect({
|
|
3514
|
-
left: canvasLeft,
|
|
3515
|
-
top: frameTop,
|
|
3516
|
-
width: canvasW,
|
|
3517
|
-
height: visibleFrameH
|
|
3518
|
-
});
|
|
3519
|
-
const frameRect = this.toLayoutSceneRect(frame);
|
|
3520
|
-
const shapeOverlay = this.buildCropShapeOverlaySpecs(frame, sceneGeometry);
|
|
3521
|
-
const mask = [
|
|
3522
|
-
{
|
|
3523
|
-
id: "image.cropMask.top",
|
|
3524
|
-
type: "rect",
|
|
3525
|
-
data: { id: "image.cropMask.top", zIndex: 1 },
|
|
3526
|
-
layout: {
|
|
3527
|
-
reference: "custom",
|
|
3528
|
-
referenceRect: viewportRect,
|
|
3529
|
-
alignX: "start",
|
|
3530
|
-
alignY: "start",
|
|
3531
|
-
width: "100%",
|
|
3532
|
-
height: topH
|
|
3533
|
-
},
|
|
3534
|
-
props: {
|
|
3535
|
-
originX: "left",
|
|
3536
|
-
originY: "top",
|
|
3537
|
-
fill: visual.outerBackground,
|
|
3538
|
-
selectable: false,
|
|
3539
|
-
evented: false
|
|
3540
|
-
}
|
|
3541
|
-
},
|
|
3542
|
-
{
|
|
3543
|
-
id: "image.cropMask.bottom",
|
|
3544
|
-
type: "rect",
|
|
3545
|
-
data: { id: "image.cropMask.bottom", zIndex: 2 },
|
|
3546
|
-
layout: {
|
|
3547
|
-
reference: "custom",
|
|
3548
|
-
referenceRect: viewportRect,
|
|
3549
|
-
alignX: "start",
|
|
3550
|
-
alignY: "end",
|
|
3551
|
-
width: "100%",
|
|
3552
|
-
height: bottomH
|
|
3553
|
-
},
|
|
3554
|
-
props: {
|
|
3555
|
-
originX: "left",
|
|
3556
|
-
originY: "top",
|
|
3557
|
-
fill: visual.outerBackground,
|
|
3558
|
-
selectable: false,
|
|
3559
|
-
evented: false
|
|
3560
|
-
}
|
|
3561
|
-
},
|
|
3562
|
-
{
|
|
3563
|
-
id: "image.cropMask.left",
|
|
3564
|
-
type: "rect",
|
|
3565
|
-
data: { id: "image.cropMask.left", zIndex: 3 },
|
|
3566
|
-
layout: {
|
|
3567
|
-
reference: "custom",
|
|
3568
|
-
referenceRect: visibleFrameBandRect,
|
|
3569
|
-
alignX: "start",
|
|
3570
|
-
alignY: "start",
|
|
3571
|
-
width: leftW,
|
|
3572
|
-
height: "100%"
|
|
3573
|
-
},
|
|
3574
|
-
props: {
|
|
3575
|
-
originX: "left",
|
|
3576
|
-
originY: "top",
|
|
3577
|
-
fill: visual.outerBackground,
|
|
3578
|
-
selectable: false,
|
|
3579
|
-
evented: false
|
|
3580
|
-
}
|
|
3581
|
-
},
|
|
3582
|
-
{
|
|
3583
|
-
id: "image.cropMask.right",
|
|
3584
|
-
type: "rect",
|
|
3585
|
-
data: { id: "image.cropMask.right", zIndex: 4 },
|
|
3586
|
-
layout: {
|
|
3587
|
-
reference: "custom",
|
|
3588
|
-
referenceRect: visibleFrameBandRect,
|
|
3589
|
-
alignX: "end",
|
|
3590
|
-
alignY: "start",
|
|
3591
|
-
width: rightW,
|
|
3592
|
-
height: "100%"
|
|
3593
|
-
},
|
|
3594
|
-
props: {
|
|
3595
|
-
originX: "left",
|
|
3596
|
-
originY: "top",
|
|
3597
|
-
fill: visual.outerBackground,
|
|
3598
|
-
selectable: false,
|
|
3599
|
-
evented: false
|
|
3600
|
-
}
|
|
3601
|
-
}
|
|
3602
|
-
];
|
|
3603
|
-
const frameSpec = {
|
|
3604
|
-
id: "image.cropFrame",
|
|
3605
|
-
type: "rect",
|
|
3606
|
-
data: { id: "image.cropFrame", zIndex: 7 },
|
|
3607
|
-
layout: {
|
|
3608
|
-
reference: "custom",
|
|
3609
|
-
referenceRect: frameRect,
|
|
3610
|
-
alignX: "start",
|
|
3611
|
-
alignY: "start",
|
|
3612
|
-
width: "100%",
|
|
3613
|
-
height: "100%"
|
|
3560
|
+
const specs = buildImageSessionOverlaySpecs({
|
|
3561
|
+
viewport: {
|
|
3562
|
+
left: viewport.left,
|
|
3563
|
+
top: viewport.top,
|
|
3564
|
+
width: viewport.width,
|
|
3565
|
+
height: viewport.height
|
|
3614
3566
|
},
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
strokeWidth: visual.strokeStyle === "hidden" ? 0 : strokeWidthScene,
|
|
3621
|
-
strokeDashArray: visual.strokeStyle === "dashed" ? [dashLengthScene, dashLengthScene] : void 0,
|
|
3622
|
-
selectable: false,
|
|
3623
|
-
evented: false
|
|
3624
|
-
}
|
|
3625
|
-
};
|
|
3626
|
-
const specs = shapeOverlay.length > 0 ? [...mask, ...shapeOverlay] : [...mask, ...shapeOverlay, frameSpec];
|
|
3567
|
+
layout: overlayState.layout,
|
|
3568
|
+
geometry: overlayState.geometry,
|
|
3569
|
+
visual,
|
|
3570
|
+
hatchPattern: this.getCropShapeHatchPattern()
|
|
3571
|
+
});
|
|
3627
3572
|
this.debug("overlay:built", {
|
|
3628
|
-
|
|
3629
|
-
shape:
|
|
3573
|
+
cutRect: overlayState.layout.cutRect,
|
|
3574
|
+
shape: overlayState.geometry.shape,
|
|
3630
3575
|
overlayIds: specs.map((spec) => {
|
|
3631
3576
|
var _a;
|
|
3632
3577
|
return {
|
|
@@ -3655,10 +3600,9 @@ var ImageTool = class {
|
|
|
3655
3600
|
}
|
|
3656
3601
|
const imageSpecs = await this.buildImageSpecs(renderItems, frame);
|
|
3657
3602
|
if (seq !== this.renderSeq) return;
|
|
3658
|
-
const
|
|
3659
|
-
if (seq !== this.renderSeq) return;
|
|
3603
|
+
const overlayState = this.resolveSessionOverlayState();
|
|
3660
3604
|
this.imageSpecs = imageSpecs;
|
|
3661
|
-
this.overlaySpecs = this.buildOverlaySpecs(
|
|
3605
|
+
this.overlaySpecs = this.buildOverlaySpecs(overlayState);
|
|
3662
3606
|
await this.canvasService.flushRenderFromProducers();
|
|
3663
3607
|
if (seq !== this.renderSeq) return;
|
|
3664
3608
|
this.refreshImageObjectInteractionState();
|
|
@@ -3685,11 +3629,38 @@ var ImageTool = class {
|
|
|
3685
3629
|
isImageSelectionActive: this.isImageSelectionActive,
|
|
3686
3630
|
focusedImageId: this.focusedImageId
|
|
3687
3631
|
});
|
|
3632
|
+
this.emitImageStateChange();
|
|
3688
3633
|
this.canvasService.requestRenderAll();
|
|
3689
3634
|
}
|
|
3690
3635
|
clampNormalized(value) {
|
|
3691
3636
|
return Math.max(-1, Math.min(2, value));
|
|
3692
3637
|
}
|
|
3638
|
+
async setImageTransform(id, updates, options = {}) {
|
|
3639
|
+
const next = {};
|
|
3640
|
+
if (Number.isFinite(updates.scale)) {
|
|
3641
|
+
next.scale = Math.max(0.05, Number(updates.scale));
|
|
3642
|
+
}
|
|
3643
|
+
if (Number.isFinite(updates.angle)) {
|
|
3644
|
+
next.angle = Number(updates.angle);
|
|
3645
|
+
}
|
|
3646
|
+
if (Number.isFinite(updates.left)) {
|
|
3647
|
+
next.left = this.clampNormalized(Number(updates.left));
|
|
3648
|
+
}
|
|
3649
|
+
if (Number.isFinite(updates.top)) {
|
|
3650
|
+
next.top = this.clampNormalized(Number(updates.top));
|
|
3651
|
+
}
|
|
3652
|
+
if (Number.isFinite(updates.opacity)) {
|
|
3653
|
+
next.opacity = Math.max(0, Math.min(1, Number(updates.opacity)));
|
|
3654
|
+
}
|
|
3655
|
+
if (!Object.keys(next).length) return;
|
|
3656
|
+
await this.updateImage(id, next, options);
|
|
3657
|
+
}
|
|
3658
|
+
resetImageSession() {
|
|
3659
|
+
this.workingItems = this.cloneItems(this.items);
|
|
3660
|
+
this.hasWorkingChanges = false;
|
|
3661
|
+
this.updateImages();
|
|
3662
|
+
this.emitWorkingChange();
|
|
3663
|
+
}
|
|
3693
3664
|
updateImageInWorking(id, updates) {
|
|
3694
3665
|
const index = this.workingItems.findIndex((item) => item.id === id);
|
|
3695
3666
|
if (index < 0) return;
|
|
@@ -3707,7 +3678,6 @@ var ImageTool = class {
|
|
|
3707
3678
|
this.emitWorkingChange(id);
|
|
3708
3679
|
}
|
|
3709
3680
|
async updateImageInConfig(id, updates) {
|
|
3710
|
-
var _a, _b, _c, _d;
|
|
3711
3681
|
const index = this.items.findIndex((item) => item.id === id);
|
|
3712
3682
|
if (index < 0) return;
|
|
3713
3683
|
const replacingSource = typeof updates.url === "string" && updates.url.length > 0;
|
|
@@ -3720,23 +3690,12 @@ var ImageTool = class {
|
|
|
3720
3690
|
...replacingSource ? {
|
|
3721
3691
|
url: replacingUrl,
|
|
3722
3692
|
sourceUrl: replacingUrl,
|
|
3723
|
-
committedUrl: void 0
|
|
3724
|
-
scale: (_a = updates.scale) != null ? _a : 1,
|
|
3725
|
-
angle: (_b = updates.angle) != null ? _b : 0,
|
|
3726
|
-
left: (_c = updates.left) != null ? _c : 0.5,
|
|
3727
|
-
top: (_d = updates.top) != null ? _d : 0.5
|
|
3693
|
+
committedUrl: void 0
|
|
3728
3694
|
} : {}
|
|
3729
3695
|
});
|
|
3730
3696
|
this.updateConfig(next);
|
|
3731
3697
|
if (replacingSource) {
|
|
3732
|
-
this.debug("replace:image:begin", { id, replacingUrl });
|
|
3733
3698
|
this.purgeSourceSizeCacheForItem(base);
|
|
3734
|
-
const loaded = await this.waitImageLoaded(id, true);
|
|
3735
|
-
this.debug("replace:image:loaded", { id, loaded });
|
|
3736
|
-
if (loaded) {
|
|
3737
|
-
await this.refitImageToFrame(id);
|
|
3738
|
-
this.setImageFocus(id);
|
|
3739
|
-
}
|
|
3740
3699
|
}
|
|
3741
3700
|
}
|
|
3742
3701
|
waitImageLoaded(id, forceWait = false) {
|
|
@@ -3754,70 +3713,43 @@ var ImageTool = class {
|
|
|
3754
3713
|
});
|
|
3755
3714
|
});
|
|
3756
3715
|
}
|
|
3757
|
-
async
|
|
3716
|
+
async resolveImageSourceSize(id, src) {
|
|
3758
3717
|
const obj = this.getImageObject(id);
|
|
3759
|
-
if (
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
const
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
const
|
|
3766
|
-
const
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
const updated = {
|
|
3770
|
-
scale: Number.isFinite(zoom) ? zoom : 1,
|
|
3771
|
-
angle: 0,
|
|
3772
|
-
left: 0.5,
|
|
3773
|
-
top: 0.5
|
|
3774
|
-
};
|
|
3775
|
-
const index = this.items.findIndex((item) => item.id === id);
|
|
3776
|
-
if (index < 0) return;
|
|
3777
|
-
const next = [...this.items];
|
|
3778
|
-
next[index] = this.normalizeItem({ ...next[index], ...updated });
|
|
3779
|
-
this.updateConfig(next);
|
|
3780
|
-
this.workingItems = this.cloneItems(next);
|
|
3781
|
-
this.hasWorkingChanges = false;
|
|
3782
|
-
this.updateImages();
|
|
3783
|
-
this.emitWorkingChange(id);
|
|
3718
|
+
if (obj) {
|
|
3719
|
+
this.rememberSourceSize(src, obj);
|
|
3720
|
+
}
|
|
3721
|
+
const ensured = await this.ensureSourceSize(src);
|
|
3722
|
+
if (ensured) return ensured;
|
|
3723
|
+
if (!obj) return null;
|
|
3724
|
+
const width = Number((obj == null ? void 0 : obj.width) || 0);
|
|
3725
|
+
const height = Number((obj == null ? void 0 : obj.height) || 0);
|
|
3726
|
+
if (width <= 0 || height <= 0) return null;
|
|
3727
|
+
return { width, height };
|
|
3784
3728
|
}
|
|
3785
|
-
async
|
|
3786
|
-
var _a, _b;
|
|
3729
|
+
async applyImageOperation(id, operation, options = {}) {
|
|
3787
3730
|
if (!this.canvasService) return;
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
const
|
|
3791
|
-
if (!obj) return;
|
|
3792
|
-
const renderItems = this.isToolActive ? this.workingItems : this.items;
|
|
3731
|
+
this.syncToolActiveFromWorkbench();
|
|
3732
|
+
const target = options.target || "auto";
|
|
3733
|
+
const renderItems = target === "working" || target === "auto" && this.isToolActive ? this.workingItems : this.items;
|
|
3793
3734
|
const current = renderItems.find((item) => item.id === id);
|
|
3794
3735
|
if (!current) return;
|
|
3795
3736
|
const render = this.resolveRenderImageState(current);
|
|
3796
|
-
this.
|
|
3797
|
-
|
|
3737
|
+
const source = await this.resolveImageSourceSize(id, render.src);
|
|
3738
|
+
if (!source) return;
|
|
3798
3739
|
const frame = this.getFrameRect();
|
|
3799
|
-
const baseCover = this.getCoverScale(frame, source);
|
|
3800
|
-
const desiredScale = Math.max(
|
|
3801
|
-
Math.max(1, area.width) / Math.max(1, source.width),
|
|
3802
|
-
Math.max(1, area.height) / Math.max(1, source.height)
|
|
3803
|
-
);
|
|
3804
3740
|
const viewport = this.canvasService.getSceneViewportRect();
|
|
3805
|
-
const
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
const
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
(areaTopPx - frame.top) / Math.max(1, frame.height)
|
|
3818
|
-
)
|
|
3819
|
-
};
|
|
3820
|
-
if (this.isToolActive) {
|
|
3741
|
+
const area = operation.type === "resetTransform" ? resolveImageOperationArea({ frame, viewport }) : resolveImageOperationArea({
|
|
3742
|
+
frame,
|
|
3743
|
+
viewport,
|
|
3744
|
+
area: operation.area
|
|
3745
|
+
});
|
|
3746
|
+
const updates = computeImageOperationUpdates({
|
|
3747
|
+
frame,
|
|
3748
|
+
source,
|
|
3749
|
+
operation,
|
|
3750
|
+
area
|
|
3751
|
+
});
|
|
3752
|
+
if (target === "working" || target === "auto" && this.isToolActive) {
|
|
3821
3753
|
this.updateImageInWorking(id, updates);
|
|
3822
3754
|
return;
|
|
3823
3755
|
}
|
|
@@ -3948,6 +3880,11 @@ var ImageTool = class {
|
|
|
3948
3880
|
}
|
|
3949
3881
|
};
|
|
3950
3882
|
|
|
3883
|
+
// src/extensions/image/model.ts
|
|
3884
|
+
function hasAnyImageInViewState(state) {
|
|
3885
|
+
return Boolean(state == null ? void 0 : state.hasAnyImage);
|
|
3886
|
+
}
|
|
3887
|
+
|
|
3951
3888
|
// src/extensions/size/SizeTool.ts
|
|
3952
3889
|
import {
|
|
3953
3890
|
ContributionPointIds as ContributionPointIds3
|
|
@@ -4912,6 +4849,13 @@ function buildDielineRenderBundle(options) {
|
|
|
4912
4849
|
canvasWidth,
|
|
4913
4850
|
canvasHeight
|
|
4914
4851
|
};
|
|
4852
|
+
const cutFrameRect = {
|
|
4853
|
+
left: cx - cutW / 2,
|
|
4854
|
+
top: cy - cutH / 2,
|
|
4855
|
+
width: cutW,
|
|
4856
|
+
height: cutH,
|
|
4857
|
+
space: "screen"
|
|
4858
|
+
};
|
|
4915
4859
|
const specs = [];
|
|
4916
4860
|
if (insideColor && insideColor !== "transparent" && insideColor !== "rgba(0,0,0,0)" && !hasImages) {
|
|
4917
4861
|
specs.push({
|
|
@@ -5033,9 +4977,13 @@ function buildDielineRenderBundle(options) {
|
|
|
5033
4977
|
width: cutW,
|
|
5034
4978
|
height: cutH,
|
|
5035
4979
|
radius: cutR,
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
4980
|
+
// Build the clip path in the cut frame's local coordinates so Fabric
|
|
4981
|
+
// does not have to infer placement from the standalone path bounds.
|
|
4982
|
+
x: cutW / 2,
|
|
4983
|
+
y: cutH / 2,
|
|
4984
|
+
features: cutFeatures,
|
|
4985
|
+
canvasWidth: cutW,
|
|
4986
|
+
canvasHeight: cutH
|
|
5039
4987
|
});
|
|
5040
4988
|
if (!clipPathData) {
|
|
5041
4989
|
return { specs, effects: [] };
|
|
@@ -5052,6 +5000,12 @@ function buildDielineRenderBundle(options) {
|
|
|
5052
5000
|
id: ids.clipSource,
|
|
5053
5001
|
type: "path",
|
|
5054
5002
|
space: "screen",
|
|
5003
|
+
layout: {
|
|
5004
|
+
reference: "custom",
|
|
5005
|
+
referenceRect: cutFrameRect,
|
|
5006
|
+
alignX: "start",
|
|
5007
|
+
alignY: "start"
|
|
5008
|
+
},
|
|
5055
5009
|
data: {
|
|
5056
5010
|
id: ids.clipSource,
|
|
5057
5011
|
type: "dieline-effect",
|
|
@@ -9876,6 +9830,7 @@ export {
|
|
|
9876
9830
|
ViewportSystem,
|
|
9877
9831
|
WhiteInkTool,
|
|
9878
9832
|
getCoverScale as computeImageCoverScale,
|
|
9833
|
+
computeImageOperationUpdates,
|
|
9879
9834
|
getCoverScale as computeWhiteInkCoverScale,
|
|
9880
9835
|
createDefaultDielineState,
|
|
9881
9836
|
createDielineCommands,
|
|
@@ -9885,5 +9840,7 @@ export {
|
|
|
9885
9840
|
createWhiteInkCommands,
|
|
9886
9841
|
createWhiteInkConfigurations,
|
|
9887
9842
|
evaluateVisibilityExpr,
|
|
9888
|
-
|
|
9843
|
+
hasAnyImageInViewState,
|
|
9844
|
+
readDielineState,
|
|
9845
|
+
resolveImageOperationArea
|
|
9889
9846
|
};
|