@pooder/kit 6.1.1 → 6.2.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.
@@ -3,43 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DielineTool = void 0;
4
4
  const core_1 = require("@pooder/core");
5
5
  const fabric_1 = require("fabric");
6
- const units_1 = require("../../units");
7
- const dielineShape_1 = require("../dielineShape");
8
6
  const geometry_1 = require("../geometry");
7
+ const dielineShape_1 = require("../dielineShape");
9
8
  const sceneLayoutModel_1 = require("../../shared/scene/sceneLayoutModel");
10
9
  const layers_1 = require("../../shared/constants/layers");
11
10
  const commands_1 = require("./commands");
12
11
  const config_1 = require("./config");
12
+ const model_1 = require("./model");
13
+ const renderBuilder_1 = require("./renderBuilder");
13
14
  class DielineTool {
14
15
  constructor(options) {
15
16
  this.id = "pooder.kit.dieline";
16
17
  this.metadata = {
17
18
  name: "DielineTool",
18
19
  };
19
- this.state = {
20
- shape: dielineShape_1.DEFAULT_DIELINE_SHAPE,
21
- shapeStyle: { ...dielineShape_1.DEFAULT_DIELINE_SHAPE_STYLE },
22
- width: 500,
23
- height: 500,
24
- radius: 0,
25
- offset: 0,
26
- padding: 140,
27
- mainLine: {
28
- width: 2.7,
29
- color: "#FF0000",
30
- dashLength: 5,
31
- style: "solid",
32
- },
33
- offsetLine: {
34
- width: 2.7,
35
- color: "#FF0000",
36
- dashLength: 5,
37
- style: "solid",
38
- },
39
- insideColor: "rgba(0,0,0,0)",
40
- showBleedLines: true,
41
- features: [],
42
- };
20
+ this.state = (0, model_1.createDefaultDielineState)();
43
21
  this.specs = [];
44
22
  this.effects = [];
45
23
  this.renderSeq = 0;
@@ -93,121 +71,11 @@ class DielineTool {
93
71
  }), { priority: 250 });
94
72
  const configService = context.services.get("ConfigurationService");
95
73
  if (configService) {
96
- // Load initial config
97
- const s = this.state;
98
- const sizeState = (0, sceneLayoutModel_1.readSizeState)(configService);
99
- s.shape = (0, dielineShape_1.normalizeDielineShape)(configService.get("dieline.shape", s.shape), s.shape);
100
- s.shapeStyle = (0, dielineShape_1.normalizeShapeStyle)(configService.get("dieline.shapeStyle", s.shapeStyle), s.shapeStyle);
101
- s.width = sizeState.actualWidthMm;
102
- s.height = sizeState.actualHeightMm;
103
- s.radius = (0, units_1.parseLengthToMm)(configService.get("dieline.radius", s.radius), "mm");
104
- s.padding = sizeState.viewPadding;
105
- s.offset =
106
- sizeState.cutMode === "outset"
107
- ? sizeState.cutMarginMm
108
- : sizeState.cutMode === "inset"
109
- ? -sizeState.cutMarginMm
110
- : 0;
111
- // Main Line
112
- s.mainLine.width = configService.get("dieline.strokeWidth", s.mainLine.width);
113
- s.mainLine.color = configService.get("dieline.strokeColor", s.mainLine.color);
114
- s.mainLine.dashLength = configService.get("dieline.dashLength", s.mainLine.dashLength);
115
- s.mainLine.style = configService.get("dieline.style", s.mainLine.style);
116
- // Offset Line
117
- s.offsetLine.width = configService.get("dieline.offsetStrokeWidth", s.offsetLine.width);
118
- s.offsetLine.color = configService.get("dieline.offsetStrokeColor", s.offsetLine.color);
119
- s.offsetLine.dashLength = configService.get("dieline.offsetDashLength", s.offsetLine.dashLength);
120
- s.offsetLine.style = configService.get("dieline.offsetStyle", s.offsetLine.style);
121
- s.insideColor = configService.get("dieline.insideColor", s.insideColor);
122
- s.showBleedLines = configService.get("dieline.showBleedLines", s.showBleedLines);
123
- s.features = configService.get("dieline.features", s.features);
124
- s.pathData = configService.get("dieline.pathData", s.pathData);
125
- const sourceWidth = Number(configService.get("dieline.customSourceWidthPx", 0));
126
- const sourceHeight = Number(configService.get("dieline.customSourceHeightPx", 0));
127
- s.customSourceWidthPx =
128
- Number.isFinite(sourceWidth) && sourceWidth > 0
129
- ? sourceWidth
130
- : undefined;
131
- s.customSourceHeightPx =
132
- Number.isFinite(sourceHeight) && sourceHeight > 0
133
- ? sourceHeight
134
- : undefined;
74
+ Object.assign(this.state, (0, model_1.readDielineState)(configService, this.state));
135
75
  // Listen for changes
136
76
  configService.onAnyChange((e) => {
137
- if (e.key.startsWith("size.")) {
138
- const nextSize = (0, sceneLayoutModel_1.readSizeState)(configService);
139
- s.width = nextSize.actualWidthMm;
140
- s.height = nextSize.actualHeightMm;
141
- s.padding = nextSize.viewPadding;
142
- s.offset =
143
- nextSize.cutMode === "outset"
144
- ? nextSize.cutMarginMm
145
- : nextSize.cutMode === "inset"
146
- ? -nextSize.cutMarginMm
147
- : 0;
148
- this.updateDieline();
149
- return;
150
- }
151
- if (e.key.startsWith("dieline.")) {
152
- switch (e.key) {
153
- case "dieline.shape":
154
- s.shape = (0, dielineShape_1.normalizeDielineShape)(e.value, s.shape);
155
- break;
156
- case "dieline.shapeStyle":
157
- s.shapeStyle = (0, dielineShape_1.normalizeShapeStyle)(e.value, s.shapeStyle);
158
- break;
159
- case "dieline.radius":
160
- s.radius = (0, units_1.parseLengthToMm)(e.value, "mm");
161
- break;
162
- case "dieline.strokeWidth":
163
- s.mainLine.width = e.value;
164
- break;
165
- case "dieline.strokeColor":
166
- s.mainLine.color = e.value;
167
- break;
168
- case "dieline.dashLength":
169
- s.mainLine.dashLength = e.value;
170
- break;
171
- case "dieline.style":
172
- s.mainLine.style = e.value;
173
- break;
174
- case "dieline.offsetStrokeWidth":
175
- s.offsetLine.width = e.value;
176
- break;
177
- case "dieline.offsetStrokeColor":
178
- s.offsetLine.color = e.value;
179
- break;
180
- case "dieline.offsetDashLength":
181
- s.offsetLine.dashLength = e.value;
182
- break;
183
- case "dieline.offsetStyle":
184
- s.offsetLine.style = e.value;
185
- break;
186
- case "dieline.insideColor":
187
- s.insideColor = e.value;
188
- break;
189
- case "dieline.showBleedLines":
190
- s.showBleedLines = e.value;
191
- break;
192
- case "dieline.features":
193
- s.features = e.value;
194
- break;
195
- case "dieline.pathData":
196
- s.pathData = e.value;
197
- break;
198
- case "dieline.customSourceWidthPx":
199
- s.customSourceWidthPx =
200
- Number.isFinite(Number(e.value)) && Number(e.value) > 0
201
- ? Number(e.value)
202
- : undefined;
203
- break;
204
- case "dieline.customSourceHeightPx":
205
- s.customSourceHeightPx =
206
- Number.isFinite(Number(e.value)) && Number(e.value) > 0
207
- ? Number(e.value)
208
- : undefined;
209
- break;
210
- }
77
+ if (e.key.startsWith("size.") || e.key.startsWith("dieline.")) {
78
+ Object.assign(this.state, (0, model_1.readDielineState)(configService, this.state));
211
79
  this.updateDieline();
212
80
  }
213
81
  });
@@ -278,270 +146,32 @@ class DielineTool {
278
146
  const items = configService.get("image.items", []);
279
147
  return Array.isArray(items) && items.length > 0;
280
148
  }
281
- syncSizeState(configService) {
282
- const sizeState = (0, sceneLayoutModel_1.readSizeState)(configService);
283
- this.state.width = sizeState.actualWidthMm;
284
- this.state.height = sizeState.actualHeightMm;
285
- this.state.padding = sizeState.viewPadding;
286
- this.state.offset =
287
- sizeState.cutMode === "outset"
288
- ? sizeState.cutMarginMm
289
- : sizeState.cutMode === "inset"
290
- ? -sizeState.cutMarginMm
291
- : 0;
292
- }
293
149
  buildDielineSpecs(sceneLayout) {
294
- const { shape, shapeStyle, radius, mainLine, offsetLine, insideColor, showBleedLines, features, } = this.state;
295
150
  const hasImages = this.hasImageItems();
296
- const canvasW = sceneLayout.canvasWidth || this.canvasService?.canvas.width || 800;
297
- const canvasH = sceneLayout.canvasHeight || this.canvasService?.canvas.height || 600;
298
- const scale = sceneLayout.scale;
299
- const cx = sceneLayout.trimRect.centerX;
300
- const cy = sceneLayout.trimRect.centerY;
301
- const visualWidth = sceneLayout.trimRect.width;
302
- const visualHeight = sceneLayout.trimRect.height;
303
- const visualRadius = radius * scale;
304
- const cutW = sceneLayout.cutRect.width;
305
- const cutH = sceneLayout.cutRect.height;
306
- const visualOffset = (cutW - visualWidth) / 2;
307
- const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
308
- const absoluteFeatures = (features || []).map((f) => ({
309
- ...f,
310
- x: f.x,
311
- y: f.y,
312
- width: (f.width || 0) * scale,
313
- height: (f.height || 0) * scale,
314
- radius: (f.radius || 0) * scale,
315
- }));
316
- const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
317
- const specs = [];
318
- if (insideColor &&
319
- insideColor !== "transparent" &&
320
- insideColor !== "rgba(0,0,0,0)" &&
321
- !hasImages) {
322
- const productPathData = (0, geometry_1.generateDielinePath)({
323
- shape,
324
- width: cutW,
325
- height: cutH,
326
- radius: cutR,
327
- x: cx,
328
- y: cy,
329
- features: cutFeatures,
330
- shapeStyle,
331
- pathData: this.state.pathData,
332
- customSourceWidthPx: this.state.customSourceWidthPx,
333
- customSourceHeightPx: this.state.customSourceHeightPx,
334
- canvasWidth: canvasW,
335
- canvasHeight: canvasH,
336
- });
337
- specs.push({
338
- id: "dieline.inside",
339
- type: "path",
340
- space: "screen",
341
- data: { id: "dieline.inside", type: "dieline" },
342
- props: {
343
- pathData: productPathData,
344
- fill: insideColor,
345
- stroke: null,
346
- selectable: false,
347
- evented: false,
348
- originX: "left",
349
- originY: "top",
350
- },
351
- });
352
- }
353
- if (Math.abs(visualOffset) > 0.0001) {
354
- const bleedPathData = (0, geometry_1.generateBleedZonePath)({
355
- shape,
356
- width: visualWidth,
357
- height: visualHeight,
358
- radius: visualRadius,
359
- x: cx,
360
- y: cy,
361
- features: cutFeatures,
362
- shapeStyle,
363
- pathData: this.state.pathData,
364
- customSourceWidthPx: this.state.customSourceWidthPx,
365
- customSourceHeightPx: this.state.customSourceHeightPx,
366
- canvasWidth: canvasW,
367
- canvasHeight: canvasH,
368
- }, {
369
- shape,
370
- width: cutW,
371
- height: cutH,
372
- radius: cutR,
373
- x: cx,
374
- y: cy,
375
- features: cutFeatures,
376
- shapeStyle,
377
- pathData: this.state.pathData,
378
- customSourceWidthPx: this.state.customSourceWidthPx,
379
- customSourceHeightPx: this.state.customSourceHeightPx,
380
- canvasWidth: canvasW,
381
- canvasHeight: canvasH,
382
- }, visualOffset);
383
- if (showBleedLines !== false) {
384
- const pattern = this.createHatchPattern(mainLine.color);
385
- if (pattern) {
386
- specs.push({
387
- id: "dieline.bleed-zone",
388
- type: "path",
389
- space: "screen",
390
- data: { id: "dieline.bleed-zone", type: "dieline" },
391
- props: {
392
- pathData: bleedPathData,
393
- fill: pattern,
394
- stroke: null,
395
- selectable: false,
396
- evented: false,
397
- objectCaching: false,
398
- originX: "left",
399
- originY: "top",
400
- },
401
- });
402
- }
403
- }
404
- const offsetPathData = (0, geometry_1.generateDielinePath)({
405
- shape,
406
- width: cutW,
407
- height: cutH,
408
- radius: cutR,
409
- x: cx,
410
- y: cy,
411
- features: cutFeatures,
412
- shapeStyle,
413
- pathData: this.state.pathData,
414
- customSourceWidthPx: this.state.customSourceWidthPx,
415
- customSourceHeightPx: this.state.customSourceHeightPx,
416
- canvasWidth: canvasW,
417
- canvasHeight: canvasH,
418
- });
419
- specs.push({
420
- id: "dieline.offset-border",
421
- type: "path",
422
- space: "screen",
423
- data: { id: "dieline.offset-border", type: "dieline" },
424
- props: {
425
- pathData: offsetPathData,
426
- fill: null,
427
- stroke: offsetLine.style === "hidden" ? null : offsetLine.color,
428
- strokeWidth: offsetLine.width,
429
- strokeDashArray: offsetLine.style === "dashed"
430
- ? [offsetLine.dashLength, offsetLine.dashLength]
431
- : undefined,
432
- selectable: false,
433
- evented: false,
434
- originX: "left",
435
- originY: "top",
436
- },
437
- });
438
- }
439
- const borderPathData = (0, geometry_1.generateDielinePath)({
440
- shape,
441
- width: visualWidth,
442
- height: visualHeight,
443
- radius: visualRadius,
444
- x: cx,
445
- y: cy,
446
- features: absoluteFeatures,
447
- shapeStyle,
448
- pathData: this.state.pathData,
449
- customSourceWidthPx: this.state.customSourceWidthPx,
450
- customSourceHeightPx: this.state.customSourceHeightPx,
451
- canvasWidth: canvasW,
452
- canvasHeight: canvasH,
453
- });
454
- specs.push({
455
- id: "dieline.border",
456
- type: "path",
457
- space: "screen",
458
- data: { id: "dieline.border", type: "dieline" },
459
- props: {
460
- pathData: borderPathData,
461
- fill: "transparent",
462
- stroke: mainLine.style === "hidden" ? null : mainLine.color,
463
- strokeWidth: mainLine.width,
464
- strokeDashArray: mainLine.style === "dashed"
465
- ? [mainLine.dashLength, mainLine.dashLength]
466
- : undefined,
467
- selectable: false,
468
- evented: false,
469
- originX: "left",
470
- originY: "top",
471
- },
472
- });
473
- return specs;
151
+ return (0, renderBuilder_1.buildDielineRenderBundle)({
152
+ state: this.state,
153
+ sceneLayout,
154
+ canvasWidth: sceneLayout.canvasWidth || this.canvasService?.canvas.width || 800,
155
+ canvasHeight: sceneLayout.canvasHeight || this.canvasService?.canvas.height || 600,
156
+ hasImages,
157
+ createHatchPattern: (color) => this.createHatchPattern(color),
158
+ includeImageClipEffect: false,
159
+ }).specs;
474
160
  }
475
161
  buildImageClipEffects(sceneLayout) {
476
- const { shape, shapeStyle, radius, features } = this.state;
477
- const canvasW = sceneLayout.canvasWidth || this.canvasService?.canvas.width || 800;
478
- const canvasH = sceneLayout.canvasHeight || this.canvasService?.canvas.height || 600;
479
- const scale = sceneLayout.scale;
480
- const cx = sceneLayout.trimRect.centerX;
481
- const cy = sceneLayout.trimRect.centerY;
482
- const visualWidth = sceneLayout.trimRect.width;
483
- const visualRadius = radius * scale;
484
- const cutW = sceneLayout.cutRect.width;
485
- const cutH = sceneLayout.cutRect.height;
486
- const visualOffset = (cutW - visualWidth) / 2;
487
- const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
488
- const absoluteFeatures = (features || []).map((f) => ({
489
- ...f,
490
- x: f.x,
491
- y: f.y,
492
- width: (f.width || 0) * scale,
493
- height: (f.height || 0) * scale,
494
- radius: (f.radius || 0) * scale,
495
- }));
496
- const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
497
- const clipPathData = (0, geometry_1.generateDielinePath)({
498
- shape,
499
- width: cutW,
500
- height: cutH,
501
- radius: cutR,
502
- x: cx,
503
- y: cy,
504
- features: cutFeatures,
505
- shapeStyle,
506
- pathData: this.state.pathData,
507
- customSourceWidthPx: this.state.customSourceWidthPx,
508
- customSourceHeightPx: this.state.customSourceHeightPx,
509
- canvasWidth: canvasW,
510
- canvasHeight: canvasH,
511
- });
512
- if (!clipPathData)
513
- return [];
514
- return [
515
- {
516
- type: "clipPath",
517
- id: "dieline.clip.image",
518
- visibility: {
519
- op: "not",
520
- expr: { op: "anySessionActive" },
521
- },
522
- targetPassIds: [layers_1.IMAGE_OBJECT_LAYER_ID],
523
- source: {
524
- id: "dieline.effect.clip-path",
525
- type: "path",
526
- space: "screen",
527
- data: {
528
- id: "dieline.effect.clip-path",
529
- type: "dieline-effect",
530
- effect: "clipPath",
531
- },
532
- props: {
533
- pathData: clipPathData,
534
- fill: "#000000",
535
- stroke: null,
536
- originX: "left",
537
- originY: "top",
538
- selectable: false,
539
- evented: false,
540
- excludeFromExport: true,
541
- },
542
- },
162
+ return (0, renderBuilder_1.buildDielineRenderBundle)({
163
+ state: this.state,
164
+ sceneLayout,
165
+ canvasWidth: sceneLayout.canvasWidth || this.canvasService?.canvas.width || 800,
166
+ canvasHeight: sceneLayout.canvasHeight || this.canvasService?.canvas.height || 600,
167
+ hasImages: this.hasImageItems(),
168
+ includeImageClipEffect: true,
169
+ clipTargetPassIds: [layers_1.IMAGE_OBJECT_LAYER_ID],
170
+ clipVisibility: {
171
+ op: "not",
172
+ expr: { op: "anySessionActive" },
543
173
  },
544
- ];
174
+ }).effects;
545
175
  }
546
176
  updateDieline(_emitEvent = true) {
547
177
  void this.updateDielineAsync();
@@ -553,7 +183,7 @@ class DielineTool {
553
183
  if (!configService)
554
184
  return;
555
185
  const seq = ++this.renderSeq;
556
- this.syncSizeState(configService);
186
+ Object.assign(this.state, (0, model_1.readDielineState)(configService, this.state));
557
187
  const sceneLayout = (0, sceneLayoutModel_1.computeSceneLayout)(this.canvasService, (0, sceneLayoutModel_1.readSizeState)(configService));
558
188
  if (!sceneLayout) {
559
189
  if (seq !== this.renderSeq)
@@ -603,7 +233,7 @@ class DielineTool {
603
233
  console.warn("[DielineTool] exportCutImage returned null: config-service-not-ready");
604
234
  return null;
605
235
  }
606
- this.syncSizeState(configService);
236
+ this.state = (0, model_1.readDielineState)(configService, this.state);
607
237
  const sceneLayout = (0, sceneLayoutModel_1.computeSceneLayout)(this.canvasService, (0, sceneLayoutModel_1.readSizeState)(configService));
608
238
  if (!sceneLayout) {
609
239
  console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConstrainedFeaturesForGeometry = resolveConstrainedFeaturesForGeometry;
4
+ function resolveConstrainedFeaturesForGeometry(args) {
5
+ const { features, geometry, applyConstraints } = args;
6
+ const context = {
7
+ dielineWidth: geometry.width,
8
+ dielineHeight: geometry.height,
9
+ geometry: {
10
+ ...geometry,
11
+ features: [],
12
+ },
13
+ };
14
+ return (features || []).map((feature) => {
15
+ const activeConstraints = feature.constraints?.filter((constraint) => !constraint.validateOnly);
16
+ if (!activeConstraints?.length) {
17
+ return feature;
18
+ }
19
+ const constrained = applyConstraints(feature.x, feature.y, feature, context, activeConstraints);
20
+ if (constrained.x === feature.x && constrained.y === feature.y) {
21
+ return feature;
22
+ }
23
+ return {
24
+ ...feature,
25
+ x: constrained.x,
26
+ y: constrained.y,
27
+ };
28
+ });
29
+ }
@@ -1,2 +1,85 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDefaultDielineState = createDefaultDielineState;
4
+ exports.readDielineState = readDielineState;
5
+ const units_1 = require("../../units");
6
+ const dielineShape_1 = require("../dielineShape");
7
+ const sceneLayoutModel_1 = require("../../shared/scene/sceneLayoutModel");
8
+ function createDefaultDielineState() {
9
+ return {
10
+ shape: dielineShape_1.DEFAULT_DIELINE_SHAPE,
11
+ shapeStyle: { ...dielineShape_1.DEFAULT_DIELINE_SHAPE_STYLE },
12
+ width: 500,
13
+ height: 500,
14
+ radius: 0,
15
+ offset: 0,
16
+ padding: 140,
17
+ mainLine: {
18
+ width: 2.7,
19
+ color: "#FF0000",
20
+ dashLength: 5,
21
+ style: "solid",
22
+ },
23
+ offsetLine: {
24
+ width: 2.7,
25
+ color: "#FF0000",
26
+ dashLength: 5,
27
+ style: "solid",
28
+ },
29
+ insideColor: "rgba(0,0,0,0)",
30
+ showBleedLines: true,
31
+ features: [],
32
+ };
33
+ }
34
+ function readDielineState(configService, fallback) {
35
+ const base = createDefaultDielineState();
36
+ if (fallback) {
37
+ Object.assign(base, fallback);
38
+ if (fallback.mainLine) {
39
+ base.mainLine = { ...base.mainLine, ...fallback.mainLine };
40
+ }
41
+ if (fallback.offsetLine) {
42
+ base.offsetLine = { ...base.offsetLine, ...fallback.offsetLine };
43
+ }
44
+ if (fallback.shapeStyle) {
45
+ base.shapeStyle = (0, dielineShape_1.normalizeShapeStyle)(fallback.shapeStyle, base.shapeStyle);
46
+ }
47
+ }
48
+ const sizeState = (0, sceneLayoutModel_1.readSizeState)(configService);
49
+ const sourceWidth = Number(configService.get("dieline.customSourceWidthPx", 0));
50
+ const sourceHeight = Number(configService.get("dieline.customSourceHeightPx", 0));
51
+ return {
52
+ ...base,
53
+ shape: (0, dielineShape_1.normalizeDielineShape)(configService.get("dieline.shape", base.shape), base.shape),
54
+ shapeStyle: (0, dielineShape_1.normalizeShapeStyle)(configService.get("dieline.shapeStyle", base.shapeStyle), base.shapeStyle),
55
+ width: sizeState.actualWidthMm,
56
+ height: sizeState.actualHeightMm,
57
+ radius: (0, units_1.parseLengthToMm)(configService.get("dieline.radius", base.radius), "mm"),
58
+ padding: sizeState.viewPadding,
59
+ offset: sizeState.cutMode === "outset"
60
+ ? sizeState.cutMarginMm
61
+ : sizeState.cutMode === "inset"
62
+ ? -sizeState.cutMarginMm
63
+ : 0,
64
+ mainLine: {
65
+ width: configService.get("dieline.strokeWidth", base.mainLine.width),
66
+ color: configService.get("dieline.strokeColor", base.mainLine.color),
67
+ dashLength: configService.get("dieline.dashLength", base.mainLine.dashLength),
68
+ style: configService.get("dieline.style", base.mainLine.style),
69
+ },
70
+ offsetLine: {
71
+ width: configService.get("dieline.offsetStrokeWidth", base.offsetLine.width),
72
+ color: configService.get("dieline.offsetStrokeColor", base.offsetLine.color),
73
+ dashLength: configService.get("dieline.offsetDashLength", base.offsetLine.dashLength),
74
+ style: configService.get("dieline.offsetStyle", base.offsetLine.style),
75
+ },
76
+ insideColor: configService.get("dieline.insideColor", base.insideColor),
77
+ showBleedLines: configService.get("dieline.showBleedLines", base.showBleedLines),
78
+ features: configService.get("dieline.features", base.features),
79
+ pathData: configService.get("dieline.pathData", base.pathData),
80
+ customSourceWidthPx: Number.isFinite(sourceWidth) && sourceWidth > 0 ? sourceWidth : undefined,
81
+ customSourceHeightPx: Number.isFinite(sourceHeight) && sourceHeight > 0
82
+ ? sourceHeight
83
+ : undefined,
84
+ };
85
+ }