@pooder/kit 3.2.0 → 3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 3.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - hole shape
8
+
3
9
  ## 3.2.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -29,6 +29,7 @@ type PositionAnchor = "top-left" | "top-center" | "top-right" | "center-left" |
29
29
  interface HoleData {
30
30
  x?: number;
31
31
  y?: number;
32
+ shape?: "circle" | "square";
32
33
  anchor?: PositionAnchor;
33
34
  offsetX?: number;
34
35
  offsetY?: number;
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ type PositionAnchor = "top-left" | "top-center" | "top-right" | "center-left" |
29
29
  interface HoleData {
30
30
  x?: number;
31
31
  y?: number;
32
+ shape?: "circle" | "square";
32
33
  anchor?: PositionAnchor;
33
34
  offsetX?: number;
34
35
  offsetY?: number;
package/dist/index.js CHANGED
@@ -614,12 +614,25 @@ function getDielineShape(options) {
614
614
  let lugsPath = null;
615
615
  let cutsPath = null;
616
616
  holes.forEach((hole) => {
617
- const lug = new import_paper.default.Path.Circle({
618
- center: [hole.x, hole.y],
617
+ const center = new import_paper.default.Point(hole.x, hole.y);
618
+ const lug = hole.shape === "square" ? new import_paper.default.Path.Rectangle({
619
+ point: [
620
+ center.x - hole.outerRadius,
621
+ center.y - hole.outerRadius
622
+ ],
623
+ size: [hole.outerRadius * 2, hole.outerRadius * 2]
624
+ }) : new import_paper.default.Path.Circle({
625
+ center,
619
626
  radius: hole.outerRadius
620
627
  });
621
- const cut = new import_paper.default.Path.Circle({
622
- center: [hole.x, hole.y],
628
+ const cut = hole.shape === "square" ? new import_paper.default.Path.Rectangle({
629
+ point: [
630
+ center.x - hole.innerRadius,
631
+ center.y - hole.innerRadius
632
+ ],
633
+ size: [hole.innerRadius * 2, hole.innerRadius * 2]
634
+ }) : new import_paper.default.Path.Circle({
635
+ center,
623
636
  radius: hole.innerRadius
624
637
  });
625
638
  if (!lugsPath) {
@@ -676,7 +689,9 @@ function getDielineShape(options) {
676
689
  return mainShape;
677
690
  }
678
691
  function generateDielinePath(options) {
679
- ensurePaper(options.width * 2, options.height * 2);
692
+ const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
693
+ const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
694
+ ensurePaper(paperWidth, paperHeight);
680
695
  import_paper.default.project.activeLayer.removeChildren();
681
696
  const mainShape = getDielineShape(options);
682
697
  const pathData = mainShape.pathData;
@@ -700,8 +715,9 @@ function generateMaskPath(options) {
700
715
  return pathData;
701
716
  }
702
717
  function generateBleedZonePath(options, offset) {
703
- const maxDim = Math.max(options.width, options.height) + Math.abs(offset) * 4;
704
- ensurePaper(maxDim, maxDim);
718
+ const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
719
+ const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
720
+ ensurePaper(paperWidth, paperHeight);
705
721
  import_paper.default.project.activeLayer.removeChildren();
706
722
  const shapeOriginal = getDielineShape(options);
707
723
  let shapeOffset;
@@ -1145,7 +1161,9 @@ var DielineTool = class {
1145
1161
  x: cx,
1146
1162
  y: cy,
1147
1163
  holes: absoluteHoles,
1148
- pathData: this.pathData
1164
+ pathData: this.pathData,
1165
+ canvasWidth: canvasW,
1166
+ canvasHeight: canvasH
1149
1167
  });
1150
1168
  const insideObj = new import_fabric2.Path(productPathData, {
1151
1169
  fill: insideColor,
@@ -1168,7 +1186,9 @@ var DielineTool = class {
1168
1186
  x: cx,
1169
1187
  y: cy,
1170
1188
  holes: absoluteHoles,
1171
- pathData: this.pathData
1189
+ pathData: this.pathData,
1190
+ canvasWidth: canvasW,
1191
+ canvasHeight: canvasH
1172
1192
  },
1173
1193
  visualOffset
1174
1194
  );
@@ -1195,7 +1215,9 @@ var DielineTool = class {
1195
1215
  x: cx,
1196
1216
  y: cy,
1197
1217
  holes: absoluteHoles,
1198
- pathData: this.pathData
1218
+ pathData: this.pathData,
1219
+ canvasWidth: canvasW,
1220
+ canvasHeight: canvasH
1199
1221
  });
1200
1222
  const offsetBorderObj = new import_fabric2.Path(offsetPathData, {
1201
1223
  fill: null,
@@ -1219,7 +1241,9 @@ var DielineTool = class {
1219
1241
  x: cx,
1220
1242
  y: cy,
1221
1243
  holes: absoluteHoles,
1222
- pathData: this.pathData
1244
+ pathData: this.pathData,
1245
+ canvasWidth: canvasW,
1246
+ canvasHeight: canvasH
1223
1247
  });
1224
1248
  const borderObj = new import_fabric2.Path(borderPathData, {
1225
1249
  fill: "transparent",
@@ -1334,7 +1358,9 @@ var DielineTool = class {
1334
1358
  x: cx,
1335
1359
  y: cy,
1336
1360
  holes: absoluteHoles,
1337
- pathData: this.pathData
1361
+ pathData: this.pathData,
1362
+ canvasWidth: canvasW,
1363
+ canvasHeight: canvasH
1338
1364
  });
1339
1365
  const clonedLayer = await userLayer.clone();
1340
1366
  const clipPath = new import_fabric2.Path(pathData, {
@@ -1627,7 +1653,7 @@ var HoleTool = class {
1627
1653
  command: "addHole",
1628
1654
  title: "Add Hole",
1629
1655
  handler: (x, y) => {
1630
- var _a, _b, _c;
1656
+ var _a, _b, _c, _d;
1631
1657
  if (!this.canvasService) return false;
1632
1658
  let normalizedX = 0.5;
1633
1659
  let normalizedY = 0.5;
@@ -1650,9 +1676,11 @@ var HoleTool = class {
1650
1676
  const lastHole = currentHoles[currentHoles.length - 1];
1651
1677
  const innerRadius = (_b = lastHole == null ? void 0 : lastHole.innerRadius) != null ? _b : 15;
1652
1678
  const outerRadius = (_c = lastHole == null ? void 0 : lastHole.outerRadius) != null ? _c : 25;
1679
+ const shape = (_d = lastHole == null ? void 0 : lastHole.shape) != null ? _d : "circle";
1653
1680
  const newHole = {
1654
1681
  x: normalizedX,
1655
1682
  y: normalizedY,
1683
+ shape,
1656
1684
  innerRadius,
1657
1685
  outerRadius
1658
1686
  };
@@ -1684,6 +1712,7 @@ var HoleTool = class {
1684
1712
  if (!this.handleDielineChange) {
1685
1713
  this.handleDielineChange = (geometry) => {
1686
1714
  this.currentGeometry = geometry;
1715
+ this.redraw();
1687
1716
  const changed = this.enforceConstraints();
1688
1717
  if (changed) {
1689
1718
  this.syncHolesToDieline();
@@ -1797,10 +1826,16 @@ var HoleTool = class {
1797
1826
  }
1798
1827
  syncHolesFromCanvas() {
1799
1828
  if (!this.canvasService) return;
1800
- const objects = this.canvasService.canvas.getObjects().filter((obj) => {
1801
- var _a;
1802
- return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1803
- });
1829
+ const objects = this.canvasService.canvas.getObjects().filter(
1830
+ (obj) => {
1831
+ var _a;
1832
+ return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker" || obj.name === "hole-marker";
1833
+ }
1834
+ );
1835
+ if (objects.length === 0 && this.holes.length > 0) {
1836
+ console.warn("HoleTool: No markers found on canvas to sync from");
1837
+ return;
1838
+ }
1804
1839
  objects.sort(
1805
1840
  (a, b) => {
1806
1841
  var _a, _b, _c, _d;
@@ -1812,6 +1847,13 @@ var HoleTool = class {
1812
1847
  const original = this.holes[i];
1813
1848
  const newAbsX = obj.left;
1814
1849
  const newAbsY = obj.top;
1850
+ if (isNaN(newAbsX) || isNaN(newAbsY)) {
1851
+ console.error("HoleTool: Invalid marker coordinates", {
1852
+ newAbsX,
1853
+ newAbsY
1854
+ });
1855
+ return original;
1856
+ }
1815
1857
  const scale = ((_a = this.currentGeometry) == null ? void 0 : _a.scale) || 1;
1816
1858
  const unit = ((_b = this.currentGeometry) == null ? void 0 : _b.unit) || "mm";
1817
1859
  const unitScale = Coordinate.convertUnit(1, "mm", unit);
@@ -1868,7 +1910,11 @@ var HoleTool = class {
1868
1910
  offsetY: (newAbsY - by) / scale / unitScale,
1869
1911
  // Clear direct coordinates if we use anchor
1870
1912
  x: void 0,
1871
- y: void 0
1913
+ y: void 0,
1914
+ // Ensure other properties are preserved
1915
+ innerRadius: original.innerRadius,
1916
+ outerRadius: original.outerRadius,
1917
+ shape: original.shape || "circle"
1872
1918
  };
1873
1919
  }
1874
1920
  let normalizedX = 0.5;
@@ -1888,9 +1934,13 @@ var HoleTool = class {
1888
1934
  ...original,
1889
1935
  x: normalizedX,
1890
1936
  y: normalizedY,
1891
- // Ensure radii are preserved
1937
+ // Clear offsets if we are using direct normalized coordinates
1938
+ offsetX: void 0,
1939
+ offsetY: void 0,
1940
+ // Ensure other properties are preserved
1892
1941
  innerRadius: (_c = original == null ? void 0 : original.innerRadius) != null ? _c : 15,
1893
- outerRadius: (_d = original == null ? void 0 : original.outerRadius) != null ? _d : 25
1942
+ outerRadius: (_d = original == null ? void 0 : original.outerRadius) != null ? _d : 25,
1943
+ shape: (original == null ? void 0 : original.shape) || "circle"
1894
1944
  };
1895
1945
  });
1896
1946
  this.holes = newHoles;
@@ -1948,7 +1998,16 @@ var HoleTool = class {
1948
1998
  { width: geometry.width, height: geometry.height }
1949
1999
  // Use geometry dims instead of canvas
1950
2000
  );
1951
- const innerCircle = new import_fabric4.Circle({
2001
+ const isSquare = hole.shape === "square";
2002
+ const innerMarker = isSquare ? new import_fabric4.Rect({
2003
+ width: visualInnerRadius * 2,
2004
+ height: visualInnerRadius * 2,
2005
+ fill: "transparent",
2006
+ stroke: "red",
2007
+ strokeWidth: 2,
2008
+ originX: "center",
2009
+ originY: "center"
2010
+ }) : new import_fabric4.Circle({
1952
2011
  radius: visualInnerRadius,
1953
2012
  fill: "transparent",
1954
2013
  stroke: "red",
@@ -1956,7 +2015,16 @@ var HoleTool = class {
1956
2015
  originX: "center",
1957
2016
  originY: "center"
1958
2017
  });
1959
- const outerCircle = new import_fabric4.Circle({
2018
+ const outerMarker = isSquare ? new import_fabric4.Rect({
2019
+ width: visualOuterRadius * 2,
2020
+ height: visualOuterRadius * 2,
2021
+ fill: "transparent",
2022
+ stroke: "#666",
2023
+ strokeWidth: 1,
2024
+ strokeDashArray: [5, 5],
2025
+ originX: "center",
2026
+ originY: "center"
2027
+ }) : new import_fabric4.Circle({
1960
2028
  radius: visualOuterRadius,
1961
2029
  fill: "transparent",
1962
2030
  stroke: "#666",
@@ -1965,7 +2033,7 @@ var HoleTool = class {
1965
2033
  originX: "center",
1966
2034
  originY: "center"
1967
2035
  });
1968
- const holeGroup = new import_fabric4.Group([outerCircle, innerCircle], {
2036
+ const holeGroup = new import_fabric4.Group([outerMarker, innerMarker], {
1969
2037
  left: pos.x,
1970
2038
  top: pos.y,
1971
2039
  originX: "center",
@@ -2293,12 +2361,25 @@ var ImageTool = class {
2293
2361
  let visualHeight = canvasH;
2294
2362
  let dielinePhysicalWidth = 500;
2295
2363
  let dielinePhysicalHeight = 500;
2364
+ let bleedOffset = 0;
2296
2365
  if (this.context) {
2297
2366
  const configService = this.context.services.get("ConfigurationService");
2298
2367
  if (configService) {
2299
2368
  dielinePhysicalWidth = configService.get("dieline.width") || 500;
2300
2369
  dielinePhysicalHeight = configService.get("dieline.height") || 500;
2301
- const padding = configService.get("dieline.padding") || 40;
2370
+ bleedOffset = configService.get("dieline.offset") || 0;
2371
+ const paddingValue = configService.get("dieline.padding") || 40;
2372
+ let padding = 0;
2373
+ if (typeof paddingValue === "number") {
2374
+ padding = paddingValue;
2375
+ } else if (typeof paddingValue === "string") {
2376
+ if (paddingValue.endsWith("%")) {
2377
+ const percent = parseFloat(paddingValue) / 100;
2378
+ padding = Math.min(canvasW, canvasH) * percent;
2379
+ } else {
2380
+ padding = parseFloat(paddingValue) || 0;
2381
+ }
2382
+ }
2302
2383
  const layout = Coordinate.calculateLayout(
2303
2384
  { width: canvasW, height: canvasH },
2304
2385
  { width: dielinePhysicalWidth, height: dielinePhysicalHeight },
@@ -2318,7 +2399,8 @@ var ImageTool = class {
2318
2399
  visualWidth,
2319
2400
  visualHeight,
2320
2401
  dielinePhysicalWidth,
2321
- dielinePhysicalHeight
2402
+ dielinePhysicalHeight,
2403
+ bleedOffset
2322
2404
  };
2323
2405
  }
2324
2406
  updateImages() {
@@ -2385,22 +2467,26 @@ var ImageTool = class {
2385
2467
  image.set({
2386
2468
  originX: "center",
2387
2469
  originY: "center",
2388
- data: { id: item.id }
2470
+ data: { id: item.id },
2471
+ uniformScaling: true,
2472
+ lockScalingFlip: true
2473
+ });
2474
+ image.setControlsVisibility({
2475
+ mt: false,
2476
+ mb: false,
2477
+ ml: false,
2478
+ mr: false
2389
2479
  });
2390
2480
  let { width, height, left, top } = item;
2391
- const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight } = layout;
2481
+ const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight, bleedOffset } = layout;
2392
2482
  if (width === void 0 && height === void 0) {
2393
- const imgAspect = (image.width || 1) / (image.height || 1);
2394
- const dielineAspect = dielinePhysicalWidth / dielinePhysicalHeight;
2395
- if (imgAspect > dielineAspect) {
2396
- const w = dielinePhysicalWidth;
2397
- width = w;
2398
- height = w / imgAspect;
2399
- } else {
2400
- const h = dielinePhysicalHeight;
2401
- height = h;
2402
- width = h * imgAspect;
2403
- }
2483
+ const targetWidth = dielinePhysicalWidth + 2 * bleedOffset;
2484
+ const targetHeight = dielinePhysicalHeight + 2 * bleedOffset;
2485
+ const targetMax = Math.max(targetWidth, targetHeight);
2486
+ const imageMax = Math.max(image.width || 1, image.height || 1);
2487
+ const scale = targetMax / imageMax;
2488
+ width = (image.width || 1) * scale;
2489
+ height = (image.height || 1) * scale;
2404
2490
  item.width = width;
2405
2491
  item.height = height;
2406
2492
  }
package/dist/index.mjs CHANGED
@@ -574,12 +574,25 @@ function getDielineShape(options) {
574
574
  let lugsPath = null;
575
575
  let cutsPath = null;
576
576
  holes.forEach((hole) => {
577
- const lug = new paper.Path.Circle({
578
- center: [hole.x, hole.y],
577
+ const center = new paper.Point(hole.x, hole.y);
578
+ const lug = hole.shape === "square" ? new paper.Path.Rectangle({
579
+ point: [
580
+ center.x - hole.outerRadius,
581
+ center.y - hole.outerRadius
582
+ ],
583
+ size: [hole.outerRadius * 2, hole.outerRadius * 2]
584
+ }) : new paper.Path.Circle({
585
+ center,
579
586
  radius: hole.outerRadius
580
587
  });
581
- const cut = new paper.Path.Circle({
582
- center: [hole.x, hole.y],
588
+ const cut = hole.shape === "square" ? new paper.Path.Rectangle({
589
+ point: [
590
+ center.x - hole.innerRadius,
591
+ center.y - hole.innerRadius
592
+ ],
593
+ size: [hole.innerRadius * 2, hole.innerRadius * 2]
594
+ }) : new paper.Path.Circle({
595
+ center,
583
596
  radius: hole.innerRadius
584
597
  });
585
598
  if (!lugsPath) {
@@ -636,7 +649,9 @@ function getDielineShape(options) {
636
649
  return mainShape;
637
650
  }
638
651
  function generateDielinePath(options) {
639
- ensurePaper(options.width * 2, options.height * 2);
652
+ const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
653
+ const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
654
+ ensurePaper(paperWidth, paperHeight);
640
655
  paper.project.activeLayer.removeChildren();
641
656
  const mainShape = getDielineShape(options);
642
657
  const pathData = mainShape.pathData;
@@ -660,8 +675,9 @@ function generateMaskPath(options) {
660
675
  return pathData;
661
676
  }
662
677
  function generateBleedZonePath(options, offset) {
663
- const maxDim = Math.max(options.width, options.height) + Math.abs(offset) * 4;
664
- ensurePaper(maxDim, maxDim);
678
+ const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
679
+ const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
680
+ ensurePaper(paperWidth, paperHeight);
665
681
  paper.project.activeLayer.removeChildren();
666
682
  const shapeOriginal = getDielineShape(options);
667
683
  let shapeOffset;
@@ -1105,7 +1121,9 @@ var DielineTool = class {
1105
1121
  x: cx,
1106
1122
  y: cy,
1107
1123
  holes: absoluteHoles,
1108
- pathData: this.pathData
1124
+ pathData: this.pathData,
1125
+ canvasWidth: canvasW,
1126
+ canvasHeight: canvasH
1109
1127
  });
1110
1128
  const insideObj = new Path(productPathData, {
1111
1129
  fill: insideColor,
@@ -1128,7 +1146,9 @@ var DielineTool = class {
1128
1146
  x: cx,
1129
1147
  y: cy,
1130
1148
  holes: absoluteHoles,
1131
- pathData: this.pathData
1149
+ pathData: this.pathData,
1150
+ canvasWidth: canvasW,
1151
+ canvasHeight: canvasH
1132
1152
  },
1133
1153
  visualOffset
1134
1154
  );
@@ -1155,7 +1175,9 @@ var DielineTool = class {
1155
1175
  x: cx,
1156
1176
  y: cy,
1157
1177
  holes: absoluteHoles,
1158
- pathData: this.pathData
1178
+ pathData: this.pathData,
1179
+ canvasWidth: canvasW,
1180
+ canvasHeight: canvasH
1159
1181
  });
1160
1182
  const offsetBorderObj = new Path(offsetPathData, {
1161
1183
  fill: null,
@@ -1179,7 +1201,9 @@ var DielineTool = class {
1179
1201
  x: cx,
1180
1202
  y: cy,
1181
1203
  holes: absoluteHoles,
1182
- pathData: this.pathData
1204
+ pathData: this.pathData,
1205
+ canvasWidth: canvasW,
1206
+ canvasHeight: canvasH
1183
1207
  });
1184
1208
  const borderObj = new Path(borderPathData, {
1185
1209
  fill: "transparent",
@@ -1294,7 +1318,9 @@ var DielineTool = class {
1294
1318
  x: cx,
1295
1319
  y: cy,
1296
1320
  holes: absoluteHoles,
1297
- pathData: this.pathData
1321
+ pathData: this.pathData,
1322
+ canvasWidth: canvasW,
1323
+ canvasHeight: canvasH
1298
1324
  });
1299
1325
  const clonedLayer = await userLayer.clone();
1300
1326
  const clipPath = new Path(pathData, {
@@ -1485,7 +1511,7 @@ var FilmTool = class {
1485
1511
  import {
1486
1512
  ContributionPointIds as ContributionPointIds4
1487
1513
  } from "@pooder/core";
1488
- import { Circle, Group, Point } from "fabric";
1514
+ import { Circle, Group, Point, Rect as Rect2 } from "fabric";
1489
1515
  var HoleTool = class {
1490
1516
  constructor(options) {
1491
1517
  this.id = "pooder.kit.hole";
@@ -1591,7 +1617,7 @@ var HoleTool = class {
1591
1617
  command: "addHole",
1592
1618
  title: "Add Hole",
1593
1619
  handler: (x, y) => {
1594
- var _a, _b, _c;
1620
+ var _a, _b, _c, _d;
1595
1621
  if (!this.canvasService) return false;
1596
1622
  let normalizedX = 0.5;
1597
1623
  let normalizedY = 0.5;
@@ -1614,9 +1640,11 @@ var HoleTool = class {
1614
1640
  const lastHole = currentHoles[currentHoles.length - 1];
1615
1641
  const innerRadius = (_b = lastHole == null ? void 0 : lastHole.innerRadius) != null ? _b : 15;
1616
1642
  const outerRadius = (_c = lastHole == null ? void 0 : lastHole.outerRadius) != null ? _c : 25;
1643
+ const shape = (_d = lastHole == null ? void 0 : lastHole.shape) != null ? _d : "circle";
1617
1644
  const newHole = {
1618
1645
  x: normalizedX,
1619
1646
  y: normalizedY,
1647
+ shape,
1620
1648
  innerRadius,
1621
1649
  outerRadius
1622
1650
  };
@@ -1648,6 +1676,7 @@ var HoleTool = class {
1648
1676
  if (!this.handleDielineChange) {
1649
1677
  this.handleDielineChange = (geometry) => {
1650
1678
  this.currentGeometry = geometry;
1679
+ this.redraw();
1651
1680
  const changed = this.enforceConstraints();
1652
1681
  if (changed) {
1653
1682
  this.syncHolesToDieline();
@@ -1761,10 +1790,16 @@ var HoleTool = class {
1761
1790
  }
1762
1791
  syncHolesFromCanvas() {
1763
1792
  if (!this.canvasService) return;
1764
- const objects = this.canvasService.canvas.getObjects().filter((obj) => {
1765
- var _a;
1766
- return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1767
- });
1793
+ const objects = this.canvasService.canvas.getObjects().filter(
1794
+ (obj) => {
1795
+ var _a;
1796
+ return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker" || obj.name === "hole-marker";
1797
+ }
1798
+ );
1799
+ if (objects.length === 0 && this.holes.length > 0) {
1800
+ console.warn("HoleTool: No markers found on canvas to sync from");
1801
+ return;
1802
+ }
1768
1803
  objects.sort(
1769
1804
  (a, b) => {
1770
1805
  var _a, _b, _c, _d;
@@ -1776,6 +1811,13 @@ var HoleTool = class {
1776
1811
  const original = this.holes[i];
1777
1812
  const newAbsX = obj.left;
1778
1813
  const newAbsY = obj.top;
1814
+ if (isNaN(newAbsX) || isNaN(newAbsY)) {
1815
+ console.error("HoleTool: Invalid marker coordinates", {
1816
+ newAbsX,
1817
+ newAbsY
1818
+ });
1819
+ return original;
1820
+ }
1779
1821
  const scale = ((_a = this.currentGeometry) == null ? void 0 : _a.scale) || 1;
1780
1822
  const unit = ((_b = this.currentGeometry) == null ? void 0 : _b.unit) || "mm";
1781
1823
  const unitScale = Coordinate.convertUnit(1, "mm", unit);
@@ -1832,7 +1874,11 @@ var HoleTool = class {
1832
1874
  offsetY: (newAbsY - by) / scale / unitScale,
1833
1875
  // Clear direct coordinates if we use anchor
1834
1876
  x: void 0,
1835
- y: void 0
1877
+ y: void 0,
1878
+ // Ensure other properties are preserved
1879
+ innerRadius: original.innerRadius,
1880
+ outerRadius: original.outerRadius,
1881
+ shape: original.shape || "circle"
1836
1882
  };
1837
1883
  }
1838
1884
  let normalizedX = 0.5;
@@ -1852,9 +1898,13 @@ var HoleTool = class {
1852
1898
  ...original,
1853
1899
  x: normalizedX,
1854
1900
  y: normalizedY,
1855
- // Ensure radii are preserved
1901
+ // Clear offsets if we are using direct normalized coordinates
1902
+ offsetX: void 0,
1903
+ offsetY: void 0,
1904
+ // Ensure other properties are preserved
1856
1905
  innerRadius: (_c = original == null ? void 0 : original.innerRadius) != null ? _c : 15,
1857
- outerRadius: (_d = original == null ? void 0 : original.outerRadius) != null ? _d : 25
1906
+ outerRadius: (_d = original == null ? void 0 : original.outerRadius) != null ? _d : 25,
1907
+ shape: (original == null ? void 0 : original.shape) || "circle"
1858
1908
  };
1859
1909
  });
1860
1910
  this.holes = newHoles;
@@ -1912,7 +1962,16 @@ var HoleTool = class {
1912
1962
  { width: geometry.width, height: geometry.height }
1913
1963
  // Use geometry dims instead of canvas
1914
1964
  );
1915
- const innerCircle = new Circle({
1965
+ const isSquare = hole.shape === "square";
1966
+ const innerMarker = isSquare ? new Rect2({
1967
+ width: visualInnerRadius * 2,
1968
+ height: visualInnerRadius * 2,
1969
+ fill: "transparent",
1970
+ stroke: "red",
1971
+ strokeWidth: 2,
1972
+ originX: "center",
1973
+ originY: "center"
1974
+ }) : new Circle({
1916
1975
  radius: visualInnerRadius,
1917
1976
  fill: "transparent",
1918
1977
  stroke: "red",
@@ -1920,7 +1979,16 @@ var HoleTool = class {
1920
1979
  originX: "center",
1921
1980
  originY: "center"
1922
1981
  });
1923
- const outerCircle = new Circle({
1982
+ const outerMarker = isSquare ? new Rect2({
1983
+ width: visualOuterRadius * 2,
1984
+ height: visualOuterRadius * 2,
1985
+ fill: "transparent",
1986
+ stroke: "#666",
1987
+ strokeWidth: 1,
1988
+ strokeDashArray: [5, 5],
1989
+ originX: "center",
1990
+ originY: "center"
1991
+ }) : new Circle({
1924
1992
  radius: visualOuterRadius,
1925
1993
  fill: "transparent",
1926
1994
  stroke: "#666",
@@ -1929,7 +1997,7 @@ var HoleTool = class {
1929
1997
  originX: "center",
1930
1998
  originY: "center"
1931
1999
  });
1932
- const holeGroup = new Group([outerCircle, innerCircle], {
2000
+ const holeGroup = new Group([outerMarker, innerMarker], {
1933
2001
  left: pos.x,
1934
2002
  top: pos.y,
1935
2003
  originX: "center",
@@ -2259,12 +2327,25 @@ var ImageTool = class {
2259
2327
  let visualHeight = canvasH;
2260
2328
  let dielinePhysicalWidth = 500;
2261
2329
  let dielinePhysicalHeight = 500;
2330
+ let bleedOffset = 0;
2262
2331
  if (this.context) {
2263
2332
  const configService = this.context.services.get("ConfigurationService");
2264
2333
  if (configService) {
2265
2334
  dielinePhysicalWidth = configService.get("dieline.width") || 500;
2266
2335
  dielinePhysicalHeight = configService.get("dieline.height") || 500;
2267
- const padding = configService.get("dieline.padding") || 40;
2336
+ bleedOffset = configService.get("dieline.offset") || 0;
2337
+ const paddingValue = configService.get("dieline.padding") || 40;
2338
+ let padding = 0;
2339
+ if (typeof paddingValue === "number") {
2340
+ padding = paddingValue;
2341
+ } else if (typeof paddingValue === "string") {
2342
+ if (paddingValue.endsWith("%")) {
2343
+ const percent = parseFloat(paddingValue) / 100;
2344
+ padding = Math.min(canvasW, canvasH) * percent;
2345
+ } else {
2346
+ padding = parseFloat(paddingValue) || 0;
2347
+ }
2348
+ }
2268
2349
  const layout = Coordinate.calculateLayout(
2269
2350
  { width: canvasW, height: canvasH },
2270
2351
  { width: dielinePhysicalWidth, height: dielinePhysicalHeight },
@@ -2284,7 +2365,8 @@ var ImageTool = class {
2284
2365
  visualWidth,
2285
2366
  visualHeight,
2286
2367
  dielinePhysicalWidth,
2287
- dielinePhysicalHeight
2368
+ dielinePhysicalHeight,
2369
+ bleedOffset
2288
2370
  };
2289
2371
  }
2290
2372
  updateImages() {
@@ -2351,22 +2433,26 @@ var ImageTool = class {
2351
2433
  image.set({
2352
2434
  originX: "center",
2353
2435
  originY: "center",
2354
- data: { id: item.id }
2436
+ data: { id: item.id },
2437
+ uniformScaling: true,
2438
+ lockScalingFlip: true
2439
+ });
2440
+ image.setControlsVisibility({
2441
+ mt: false,
2442
+ mb: false,
2443
+ ml: false,
2444
+ mr: false
2355
2445
  });
2356
2446
  let { width, height, left, top } = item;
2357
- const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight } = layout;
2447
+ const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight, bleedOffset } = layout;
2358
2448
  if (width === void 0 && height === void 0) {
2359
- const imgAspect = (image.width || 1) / (image.height || 1);
2360
- const dielineAspect = dielinePhysicalWidth / dielinePhysicalHeight;
2361
- if (imgAspect > dielineAspect) {
2362
- const w = dielinePhysicalWidth;
2363
- width = w;
2364
- height = w / imgAspect;
2365
- } else {
2366
- const h = dielinePhysicalHeight;
2367
- height = h;
2368
- width = h * imgAspect;
2369
- }
2449
+ const targetWidth = dielinePhysicalWidth + 2 * bleedOffset;
2450
+ const targetHeight = dielinePhysicalHeight + 2 * bleedOffset;
2451
+ const targetMax = Math.max(targetWidth, targetHeight);
2452
+ const imageMax = Math.max(image.width || 1, image.height || 1);
2453
+ const scale = targetMax / imageMax;
2454
+ width = (image.width || 1) * scale;
2455
+ height = (image.height || 1) * scale;
2370
2456
  item.width = width;
2371
2457
  item.height = height;
2372
2458
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pooder/kit",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Standard plugins for Pooder editor",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
package/src/dieline.ts CHANGED
@@ -493,6 +493,8 @@ export class DielineTool implements Extension {
493
493
  y: cy,
494
494
  holes: absoluteHoles,
495
495
  pathData: this.pathData,
496
+ canvasWidth: canvasW,
497
+ canvasHeight: canvasH,
496
498
  });
497
499
 
498
500
  const insideObj = new Path(productPathData, {
@@ -518,6 +520,8 @@ export class DielineTool implements Extension {
518
520
  y: cy,
519
521
  holes: absoluteHoles,
520
522
  pathData: this.pathData,
523
+ canvasWidth: canvasW,
524
+ canvasHeight: canvasH,
521
525
  },
522
526
  visualOffset,
523
527
  );
@@ -549,6 +553,8 @@ export class DielineTool implements Extension {
549
553
  y: cy,
550
554
  holes: absoluteHoles,
551
555
  pathData: this.pathData,
556
+ canvasWidth: canvasW,
557
+ canvasHeight: canvasH,
552
558
  });
553
559
 
554
560
  const offsetBorderObj = new Path(offsetPathData, {
@@ -577,6 +583,8 @@ export class DielineTool implements Extension {
577
583
  y: cy,
578
584
  holes: absoluteHoles,
579
585
  pathData: this.pathData,
586
+ canvasWidth: canvasW,
587
+ canvasHeight: canvasH,
580
588
  });
581
589
 
582
590
  const borderObj = new Path(borderPathData, {
@@ -730,6 +738,8 @@ export class DielineTool implements Extension {
730
738
  y: cy,
731
739
  holes: absoluteHoles,
732
740
  pathData: this.pathData,
741
+ canvasWidth: canvasW,
742
+ canvasHeight: canvasH,
733
743
  });
734
744
 
735
745
  // 2. Prepare for Export
package/src/geometry.ts CHANGED
@@ -14,6 +14,7 @@ export type PositionAnchor =
14
14
  export interface HoleData {
15
15
  x?: number;
16
16
  y?: number;
17
+ shape?: "circle" | "square";
17
18
  anchor?: PositionAnchor;
18
19
  offsetX?: number;
19
20
  offsetY?: number;
@@ -103,6 +104,8 @@ export interface GeometryOptions {
103
104
  y: number;
104
105
  holes: Array<HoleData>;
105
106
  pathData?: string;
107
+ canvasWidth?: number;
108
+ canvasHeight?: number;
106
109
  }
107
110
 
108
111
  export interface MaskGeometryOptions extends GeometryOptions {
@@ -287,21 +290,41 @@ function getDielineShape(options: GeometryOptions): paper.PathItem {
287
290
  let cutsPath: paper.PathItem | null = null;
288
291
 
289
292
  holes.forEach((hole) => {
293
+ const center = new paper.Point(hole.x!, hole.y!);
294
+
290
295
  // Create Lug (Outer Radius)
291
- const lug = new paper.Path.Circle({
292
- center: [hole.x, hole.y],
293
- radius: hole.outerRadius,
294
- });
296
+ const lug =
297
+ hole.shape === "square"
298
+ ? new paper.Path.Rectangle({
299
+ point: [
300
+ center.x - hole.outerRadius,
301
+ center.y - hole.outerRadius,
302
+ ],
303
+ size: [hole.outerRadius * 2, hole.outerRadius * 2],
304
+ })
305
+ : new paper.Path.Circle({
306
+ center: center,
307
+ radius: hole.outerRadius,
308
+ });
295
309
 
296
310
  // REMOVED: Intersects check. We want to process all holes defined in config.
297
311
  // If a hole is completely outside, it might form an island, but that's better than missing it.
298
312
  // Users can remove the hole if they don't want it.
299
313
 
300
314
  // Create Cut (Inner Radius)
301
- const cut = new paper.Path.Circle({
302
- center: [hole.x, hole.y],
303
- radius: hole.innerRadius,
304
- });
315
+ const cut =
316
+ hole.shape === "square"
317
+ ? new paper.Path.Rectangle({
318
+ point: [
319
+ center.x - hole.innerRadius,
320
+ center.y - hole.innerRadius,
321
+ ],
322
+ size: [hole.innerRadius * 2, hole.innerRadius * 2],
323
+ })
324
+ : new paper.Path.Circle({
325
+ center: center,
326
+ radius: hole.innerRadius,
327
+ });
305
328
 
306
329
  // Union Lugs
307
330
  if (!lugsPath) {
@@ -373,7 +396,9 @@ function getDielineShape(options: GeometryOptions): paper.PathItem {
373
396
  * Logic: (BaseShape UNION IntersectingLugs) SUBTRACT Cuts
374
397
  */
375
398
  export function generateDielinePath(options: GeometryOptions): string {
376
- ensurePaper(options.width * 2, options.height * 2);
399
+ const paperWidth = options.canvasWidth || options.width * 2 || 2000;
400
+ const paperHeight = options.canvasHeight || options.height * 2 || 2000;
401
+ ensurePaper(paperWidth, paperHeight);
377
402
  paper.project.activeLayer.removeChildren();
378
403
 
379
404
  const mainShape = getDielineShape(options);
@@ -423,8 +448,9 @@ export function generateBleedZonePath(
423
448
  offset: number,
424
449
  ): string {
425
450
  // Ensure canvas is large enough
426
- const maxDim = Math.max(options.width, options.height) + Math.abs(offset) * 4;
427
- ensurePaper(maxDim, maxDim);
451
+ const paperWidth = options.canvasWidth || options.width * 2 || 2000;
452
+ const paperHeight = options.canvasHeight || options.height * 2 || 2000;
453
+ ensurePaper(paperWidth, paperHeight);
428
454
  paper.project.activeLayer.removeChildren();
429
455
 
430
456
  // 1. Original Shape
package/src/hole.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  ConfigurationContribution,
7
7
  ConfigurationService,
8
8
  } from "@pooder/core";
9
- import { Circle, Group, Point } from "fabric";
9
+ import { Circle, Group, Point, Rect } from "fabric";
10
10
  import CanvasService from "./CanvasService";
11
11
  import { DielineGeometry } from "./dieline";
12
12
  import {
@@ -179,10 +179,12 @@ export class HoleTool implements Extension {
179
179
  const lastHole = currentHoles[currentHoles.length - 1];
180
180
  const innerRadius = lastHole?.innerRadius ?? 15;
181
181
  const outerRadius = lastHole?.outerRadius ?? 25;
182
+ const shape = lastHole?.shape ?? "circle";
182
183
 
183
184
  const newHole = {
184
185
  x: normalizedX,
185
186
  y: normalizedY,
187
+ shape,
186
188
  innerRadius,
187
189
  outerRadius,
188
190
  };
@@ -216,6 +218,7 @@ export class HoleTool implements Extension {
216
218
  if (!this.handleDielineChange) {
217
219
  this.handleDielineChange = (geometry: DielineGeometry) => {
218
220
  this.currentGeometry = geometry;
221
+ this.redraw();
219
222
  const changed = this.enforceConstraints();
220
223
  // Only sync if constraints actually moved something
221
224
  if (changed) {
@@ -367,21 +370,38 @@ export class HoleTool implements Extension {
367
370
  if (!this.canvasService) return;
368
371
  const objects = this.canvasService.canvas
369
372
  .getObjects()
370
- .filter((obj: any) => obj.data?.type === "hole-marker");
373
+ .filter(
374
+ (obj: any) =>
375
+ obj.data?.type === "hole-marker" || obj.name === "hole-marker",
376
+ );
377
+
378
+ // If we have markers but no state, or mismatch, we should be careful.
379
+ // However, if we just dragged one, we expect them to match.
380
+ if (objects.length === 0 && this.holes.length > 0) {
381
+ console.warn("HoleTool: No markers found on canvas to sync from");
382
+ return;
383
+ }
371
384
 
372
- // Sort objects by index
385
+ // Sort objects by index to match this.holes order
373
386
  objects.sort(
374
- (a: any, b: any) => (a.data?.index ?? 0) - (b.data?.index ?? 0)
387
+ (a: any, b: any) => (a.data?.index ?? 0) - (b.data?.index ?? 0),
375
388
  );
376
389
 
377
390
  // Update holes based on canvas positions
378
- // We need to preserve original hole properties (radii, anchor)
379
- // If a hole has an anchor, we update offsetX/Y instead of x/y
380
391
  const newHoles = objects.map((obj, i) => {
381
392
  const original = this.holes[i];
382
393
  const newAbsX = obj.left!;
383
394
  const newAbsY = obj.top!;
384
395
 
396
+ // Validate coordinates to prevent NaN issues
397
+ if (isNaN(newAbsX) || isNaN(newAbsY)) {
398
+ console.error("HoleTool: Invalid marker coordinates", {
399
+ newAbsX,
400
+ newAbsY,
401
+ });
402
+ return original;
403
+ }
404
+
385
405
  // Get current scale to denormalize offsets
386
406
  const scale = this.currentGeometry?.scale || 1;
387
407
  const unit = this.currentGeometry?.unit || "mm";
@@ -435,7 +455,7 @@ export class HoleTool implements Extension {
435
455
  by = bottom;
436
456
  break;
437
457
  }
438
-
458
+
439
459
  return {
440
460
  ...original,
441
461
  // Denormalize offset back to physical units (mm)
@@ -444,11 +464,14 @@ export class HoleTool implements Extension {
444
464
  // Clear direct coordinates if we use anchor
445
465
  x: undefined,
446
466
  y: undefined,
467
+ // Ensure other properties are preserved
468
+ innerRadius: original.innerRadius,
469
+ outerRadius: original.outerRadius,
470
+ shape: original.shape || "circle",
447
471
  };
448
472
  }
449
473
 
450
474
  // If no anchor, use normalized coordinates relative to Dieline Geometry
451
- // normalized = (absolute - (center - width/2)) / width
452
475
  let normalizedX = 0.5;
453
476
  let normalizedY = 0.5;
454
477
 
@@ -459,19 +482,23 @@ export class HoleTool implements Extension {
459
482
  normalizedX = width > 0 ? (newAbsX - left) / width : 0.5;
460
483
  normalizedY = height > 0 ? (newAbsY - top) / height : 0.5;
461
484
  } else {
462
- // Fallback to Canvas normalization if no geometry (should rare)
485
+ // Fallback to Canvas normalization
463
486
  const { width, height } = this.canvasService!.canvas;
464
487
  normalizedX = Coordinate.toNormalized(newAbsX, width || 800);
465
488
  normalizedY = Coordinate.toNormalized(newAbsY, height || 600);
466
489
  }
467
-
490
+
468
491
  return {
469
492
  ...original,
470
493
  x: normalizedX,
471
494
  y: normalizedY,
472
- // Ensure radii are preserved
495
+ // Clear offsets if we are using direct normalized coordinates
496
+ offsetX: undefined,
497
+ offsetY: undefined,
498
+ // Ensure other properties are preserved
473
499
  innerRadius: original?.innerRadius ?? 15,
474
500
  outerRadius: original?.outerRadius ?? 25,
501
+ shape: original?.shape || "circle",
475
502
  };
476
503
  });
477
504
 
@@ -544,26 +571,49 @@ export class HoleTool implements Extension {
544
571
  { width: geometry.width, height: geometry.height } // Use geometry dims instead of canvas
545
572
  );
546
573
 
547
- const innerCircle = new Circle({
548
- radius: visualInnerRadius,
549
- fill: "transparent",
550
- stroke: "red",
551
- strokeWidth: 2,
552
- originX: "center",
553
- originY: "center",
554
- });
574
+ const isSquare = hole.shape === "square";
575
+
576
+ const innerMarker = isSquare
577
+ ? new Rect({
578
+ width: visualInnerRadius * 2,
579
+ height: visualInnerRadius * 2,
580
+ fill: "transparent",
581
+ stroke: "red",
582
+ strokeWidth: 2,
583
+ originX: "center",
584
+ originY: "center",
585
+ })
586
+ : new Circle({
587
+ radius: visualInnerRadius,
588
+ fill: "transparent",
589
+ stroke: "red",
590
+ strokeWidth: 2,
591
+ originX: "center",
592
+ originY: "center",
593
+ });
555
594
 
556
- const outerCircle = new Circle({
557
- radius: visualOuterRadius,
558
- fill: "transparent",
559
- stroke: "#666",
560
- strokeWidth: 1,
561
- strokeDashArray: [5, 5],
562
- originX: "center",
563
- originY: "center",
564
- });
595
+ const outerMarker = isSquare
596
+ ? new Rect({
597
+ width: visualOuterRadius * 2,
598
+ height: visualOuterRadius * 2,
599
+ fill: "transparent",
600
+ stroke: "#666",
601
+ strokeWidth: 1,
602
+ strokeDashArray: [5, 5],
603
+ originX: "center",
604
+ originY: "center",
605
+ })
606
+ : new Circle({
607
+ radius: visualOuterRadius,
608
+ fill: "transparent",
609
+ stroke: "#666",
610
+ strokeWidth: 1,
611
+ strokeDashArray: [5, 5],
612
+ originX: "center",
613
+ originY: "center",
614
+ });
565
615
 
566
- const holeGroup = new Group([outerCircle, innerCircle], {
616
+ const holeGroup = new Group([outerMarker, innerMarker], {
567
617
  left: pos.x,
568
618
  top: pos.y,
569
619
  originX: "center",
package/src/image.ts CHANGED
@@ -241,13 +241,27 @@ export class ImageTool implements Extension {
241
241
  let visualHeight = canvasH;
242
242
  let dielinePhysicalWidth = 500;
243
243
  let dielinePhysicalHeight = 500;
244
+ let bleedOffset = 0;
244
245
 
245
246
  if (this.context) {
246
247
  const configService = this.context.services.get<ConfigurationService>("ConfigurationService");
247
248
  if (configService) {
248
249
  dielinePhysicalWidth = configService.get("dieline.width") || 500;
249
250
  dielinePhysicalHeight = configService.get("dieline.height") || 500;
250
- const padding = configService.get("dieline.padding") || 40;
251
+ bleedOffset = configService.get("dieline.offset") || 0;
252
+
253
+ const paddingValue = configService.get("dieline.padding") || 40;
254
+ let padding = 0;
255
+ if (typeof paddingValue === "number") {
256
+ padding = paddingValue;
257
+ } else if (typeof paddingValue === "string") {
258
+ if (paddingValue.endsWith("%")) {
259
+ const percent = parseFloat(paddingValue) / 100;
260
+ padding = Math.min(canvasW, canvasH) * percent;
261
+ } else {
262
+ padding = parseFloat(paddingValue) || 0;
263
+ }
264
+ }
251
265
 
252
266
  const layout = Coordinate.calculateLayout(
253
267
  { width: canvasW, height: canvasH },
@@ -269,7 +283,8 @@ export class ImageTool implements Extension {
269
283
  visualWidth,
270
284
  visualHeight,
271
285
  dielinePhysicalWidth,
272
- dielinePhysicalHeight
286
+ dielinePhysicalHeight,
287
+ bleedOffset
273
288
  };
274
289
  }
275
290
 
@@ -378,26 +393,34 @@ export class ImageTool implements Extension {
378
393
  originX: "center",
379
394
  originY: "center",
380
395
  data: { id: item.id },
396
+ uniformScaling: true,
397
+ lockScalingFlip: true,
398
+ });
399
+
400
+ image.setControlsVisibility({
401
+ mt: false,
402
+ mb: false,
403
+ ml: false,
404
+ mr: false,
381
405
  });
382
406
 
383
407
  // Initial Layout
384
408
  let { width, height, left, top } = item;
385
- const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight } = layout;
409
+ const { layoutScale, layoutOffsetX, layoutOffsetY, visualWidth, visualHeight, dielinePhysicalWidth, dielinePhysicalHeight, bleedOffset } = layout;
386
410
 
387
411
  // Auto-scale if needed
388
412
  if (width === undefined && height === undefined) {
389
- const imgAspect = (image.width || 1) / (image.height || 1);
390
- const dielineAspect = dielinePhysicalWidth / dielinePhysicalHeight;
413
+ // Calculate target dimensions including bleed
414
+ const targetWidth = dielinePhysicalWidth + 2 * bleedOffset;
415
+ const targetHeight = dielinePhysicalHeight + 2 * bleedOffset;
416
+
417
+ // "适应最长边" (Fit to longest side) logic
418
+ const targetMax = Math.max(targetWidth, targetHeight);
419
+ const imageMax = Math.max(image.width || 1, image.height || 1);
420
+ const scale = targetMax / imageMax;
391
421
 
392
- if (imgAspect > dielineAspect) {
393
- const w = dielinePhysicalWidth;
394
- width = w;
395
- height = w / imgAspect;
396
- } else {
397
- const h = dielinePhysicalHeight;
398
- height = h;
399
- width = h * imgAspect;
400
- }
422
+ width = (image.width || 1) * scale;
423
+ height = (image.height || 1) * scale;
401
424
 
402
425
  // Update item with defaults
403
426
  item.width = width;