@pooder/kit 4.3.1 → 5.0.1

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.
Files changed (60) hide show
  1. package/.test-dist/src/CanvasService.js +249 -0
  2. package/.test-dist/src/ViewportSystem.js +75 -0
  3. package/.test-dist/src/background.js +203 -0
  4. package/.test-dist/src/bridgeSelection.js +20 -0
  5. package/.test-dist/src/constraints.js +237 -0
  6. package/.test-dist/src/coordinate.js +74 -0
  7. package/.test-dist/src/dieline.js +818 -0
  8. package/.test-dist/src/edgeScale.js +12 -0
  9. package/.test-dist/src/feature.js +754 -0
  10. package/.test-dist/src/featureComplete.js +32 -0
  11. package/.test-dist/src/film.js +167 -0
  12. package/.test-dist/src/geometry.js +506 -0
  13. package/.test-dist/src/image.js +1234 -0
  14. package/.test-dist/src/index.js +35 -0
  15. package/.test-dist/src/maskOps.js +270 -0
  16. package/.test-dist/src/mirror.js +104 -0
  17. package/.test-dist/src/renderSpec.js +2 -0
  18. package/.test-dist/src/ruler.js +343 -0
  19. package/.test-dist/src/sceneLayout.js +99 -0
  20. package/.test-dist/src/sceneLayoutModel.js +196 -0
  21. package/.test-dist/src/sceneView.js +40 -0
  22. package/.test-dist/src/sceneVisibility.js +42 -0
  23. package/.test-dist/src/size.js +332 -0
  24. package/.test-dist/src/tracer.js +544 -0
  25. package/.test-dist/src/units.js +30 -0
  26. package/.test-dist/src/white-ink.js +829 -0
  27. package/.test-dist/src/wrappedOffsets.js +33 -0
  28. package/.test-dist/tests/run.js +94 -0
  29. package/CHANGELOG.md +17 -0
  30. package/dist/index.d.mts +342 -37
  31. package/dist/index.d.ts +342 -37
  32. package/dist/index.js +3679 -865
  33. package/dist/index.mjs +3673 -868
  34. package/package.json +2 -2
  35. package/src/CanvasService.ts +300 -96
  36. package/src/ViewportSystem.ts +92 -92
  37. package/src/background.ts +230 -230
  38. package/src/bridgeSelection.ts +17 -0
  39. package/src/coordinate.ts +106 -106
  40. package/src/dieline.ts +1005 -973
  41. package/src/edgeScale.ts +19 -0
  42. package/src/feature.ts +83 -30
  43. package/src/film.ts +194 -194
  44. package/src/geometry.ts +242 -84
  45. package/src/image.ts +1582 -512
  46. package/src/index.ts +14 -10
  47. package/src/maskOps.ts +326 -0
  48. package/src/mirror.ts +128 -128
  49. package/src/renderSpec.ts +18 -0
  50. package/src/ruler.ts +449 -508
  51. package/src/sceneLayout.ts +121 -0
  52. package/src/sceneLayoutModel.ts +335 -0
  53. package/src/sceneVisibility.ts +49 -0
  54. package/src/size.ts +379 -0
  55. package/src/tracer.ts +719 -570
  56. package/src/units.ts +27 -27
  57. package/src/white-ink.ts +1018 -373
  58. package/src/wrappedOffsets.ts +33 -0
  59. package/tests/run.ts +118 -0
  60. package/tsconfig.test.json +15 -15
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrappedDistance = wrappedDistance;
4
+ exports.sampleWrappedOffsets = sampleWrappedOffsets;
5
+ function wrappedDistance(total, start, end) {
6
+ if (!Number.isFinite(total) || total <= 0)
7
+ return 0;
8
+ if (!Number.isFinite(start) || !Number.isFinite(end))
9
+ return 0;
10
+ const s = ((start % total) + total) % total;
11
+ const e = ((end % total) + total) % total;
12
+ return e >= s ? e - s : total - s + e;
13
+ }
14
+ function sampleWrappedOffsets(total, start, end, count) {
15
+ if (!Number.isFinite(total) || total <= 0)
16
+ return [];
17
+ if (!Number.isFinite(start) || !Number.isFinite(end))
18
+ return [];
19
+ const n = Math.max(0, Math.floor(count));
20
+ if (n <= 0)
21
+ return [];
22
+ const dist = wrappedDistance(total, start, end);
23
+ if (n === 1)
24
+ return [((start % total) + total) % total];
25
+ const step = dist / (n - 1);
26
+ const offsets = [];
27
+ for (let i = 0; i < n; i++) {
28
+ const raw = start + step * i;
29
+ const wrapped = ((raw % total) + total) % total;
30
+ offsets.push(wrapped);
31
+ }
32
+ return offsets;
33
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bridgeSelection_1 = require("../src/bridgeSelection");
4
+ const wrappedOffsets_1 = require("../src/wrappedOffsets");
5
+ const maskOps_1 = require("../src/maskOps");
6
+ const edgeScale_1 = require("../src/edgeScale");
7
+ function assert(condition, message) {
8
+ if (!condition)
9
+ throw new Error(message);
10
+ }
11
+ function testWrappedOffsets() {
12
+ assert((0, wrappedOffsets_1.wrappedDistance)(100, 10, 30) === 20, "distance 10->30 should be 20");
13
+ assert((0, wrappedOffsets_1.wrappedDistance)(100, 90, 10) === 20, "distance 90->10 should wrap to 20");
14
+ const a = (0, wrappedOffsets_1.sampleWrappedOffsets)(100, 10, 30, 5);
15
+ assert(JSON.stringify(a) === JSON.stringify([10, 15, 20, 25, 30]), `unexpected sample: ${JSON.stringify(a)}`);
16
+ const b = (0, wrappedOffsets_1.sampleWrappedOffsets)(100, 90, 10, 3);
17
+ assert(JSON.stringify(b) === JSON.stringify([90, 0, 10]), `unexpected wrap sample: ${JSON.stringify(b)}`);
18
+ }
19
+ function testBridgeSelection() {
20
+ const idx = (0, bridgeSelection_1.pickExitIndex)([
21
+ { insideAbove: true, insideBelow: true },
22
+ { insideAbove: false, insideBelow: true },
23
+ { insideAbove: false, insideBelow: false },
24
+ ]);
25
+ assert(idx === 1, `expected exit index 1, got ${idx}`);
26
+ const none = (0, bridgeSelection_1.pickExitIndex)([{ insideAbove: true, insideBelow: true }]);
27
+ assert(none === -1, `expected -1, got ${none}`);
28
+ const score = (0, bridgeSelection_1.scoreOutsideAbove)([
29
+ { outsideAbove: true },
30
+ { outsideAbove: false },
31
+ { outsideAbove: true },
32
+ ]);
33
+ assert(score === 2, `expected score 2, got ${score}`);
34
+ }
35
+ function testMaskOps() {
36
+ const width = 50;
37
+ const height = 50;
38
+ const mask = new Uint8Array(width * height);
39
+ mask[10 * width + 10] = 1;
40
+ mask[10 * width + 20] = 1;
41
+ const r = (0, maskOps_1.findMinimalConnectRadius)(mask, width, height, 20);
42
+ const closed = (0, maskOps_1.circularMorphology)(mask, width, height, r, "closing");
43
+ assert((0, maskOps_1.isMaskConnected8)(closed, width, height), `closed mask should be connected (r=${r})`);
44
+ if (r > 0) {
45
+ const closedPrev = (0, maskOps_1.circularMorphology)(mask, width, height, r - 1, "closing");
46
+ assert(!(0, maskOps_1.isMaskConnected8)(closedPrev, width, height), `r should be minimal (r=${r})`);
47
+ }
48
+ const donut = new Uint8Array(9 * 9);
49
+ for (let y = 1; y <= 7; y++) {
50
+ for (let x = 1; x <= 7; x++)
51
+ donut[y * 9 + x] = 1;
52
+ }
53
+ for (let y = 3; y <= 5; y++) {
54
+ for (let x = 3; x <= 5; x++)
55
+ donut[y * 9 + x] = 0;
56
+ }
57
+ const filled = (0, maskOps_1.fillHoles)(donut, 9, 9);
58
+ assert(filled[4 * 9 + 4] === 1, "hole should be filled");
59
+ const imgW = 2;
60
+ const imgH = 1;
61
+ const rgba = new Uint8ClampedArray([
62
+ 255, 255, 255, 255, 10, 10, 10, 254,
63
+ ]);
64
+ const imageData = { width: imgW, height: imgH, data: rgba };
65
+ const paddedWidth = imgW + 4;
66
+ const paddedHeight = imgH + 4;
67
+ const created = (0, maskOps_1.createMask)(imageData, {
68
+ threshold: 10,
69
+ padding: 2,
70
+ paddedWidth,
71
+ paddedHeight,
72
+ maskMode: "auto",
73
+ alphaOpaqueCutoff: 250,
74
+ });
75
+ assert(created[2 * paddedWidth + 2] === 0, "white pixel should be background");
76
+ assert(created[2 * paddedWidth + 3] === 1, "non-white pixel should be foreground");
77
+ }
78
+ function testEdgeScale() {
79
+ const currentMax = 100;
80
+ const baseBounds = { width: 50, height: 20 };
81
+ const expandedBounds = { width: 70, height: 40 };
82
+ const { width, height, scale } = (0, edgeScale_1.computeDetectEdgeSize)(currentMax, baseBounds, expandedBounds);
83
+ assert(scale === 2, `expected scale 2, got ${scale}`);
84
+ assert(width === 140, `expected width 140, got ${width}`);
85
+ assert(height === 80, `expected height 80, got ${height}`);
86
+ }
87
+ function main() {
88
+ testWrappedOffsets();
89
+ testBridgeSelection();
90
+ testMaskOps();
91
+ testEdgeScale();
92
+ console.log("ok");
93
+ }
94
+ main();
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 5.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - bugfix
8
+
9
+ ## 5.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - white ink tool and size tool
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @pooder/core@2.1.0
19
+
3
20
  ## 4.3.1
4
21
 
5
22
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service, EventBus } from '@pooder/core';
1
+ import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service, EventBus, ConfigurationService } from '@pooder/core';
2
2
  import { Canvas, Group, FabricObject } from 'fabric';
3
3
 
4
4
  declare class BackgroundTool implements Extension {
@@ -107,10 +107,20 @@ declare class DielineTool implements Extension {
107
107
  private state;
108
108
  private canvasService?;
109
109
  private context?;
110
+ private onCanvasResized;
110
111
  constructor(options?: Partial<DielineState>);
111
112
  activate(context: ExtensionContext): void;
112
113
  deactivate(context: ExtensionContext): void;
113
114
  contribute(): {
115
+ [ContributionPointIds.TOOLS]: {
116
+ id: string;
117
+ name: string;
118
+ interaction: string;
119
+ session: {
120
+ autoBegin: boolean;
121
+ leavePolicy: string;
122
+ };
123
+ }[];
114
124
  [ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
115
125
  [ContributionPointIds.COMMANDS]: CommandContribution[];
116
126
  };
@@ -118,10 +128,14 @@ declare class DielineTool implements Extension {
118
128
  private createLayer;
119
129
  private destroyLayer;
120
130
  private createHatchPattern;
121
- private resolvePadding;
122
- updateDieline(emitEvent?: boolean): void;
131
+ private getConfigService;
132
+ private syncSizeState;
133
+ private bringFeatureMarkersToFront;
134
+ updateDieline(_emitEvent?: boolean): void;
123
135
  getGeometry(): DielineGeometry | null;
124
- exportCutImage(): Promise<string | null>;
136
+ exportCutImage(options?: {
137
+ debug?: boolean;
138
+ }): Promise<string | null>;
125
139
  }
126
140
 
127
141
  declare class FilmTool implements Extension {
@@ -164,9 +178,11 @@ declare class FeatureTool implements Extension {
164
178
  private context?;
165
179
  private isUpdatingConfig;
166
180
  private isToolActive;
181
+ private hasWorkingChanges;
182
+ private dirtyTrackerDisposable?;
167
183
  private handleMoving;
168
184
  private handleModified;
169
- private handleDielineChange;
185
+ private handleSceneGeometryChange;
170
186
  private currentGeometry;
171
187
  constructor(options?: Partial<{
172
188
  features: ConstraintFeature[];
@@ -176,6 +192,20 @@ declare class FeatureTool implements Extension {
176
192
  private onToolActivated;
177
193
  private updateVisibility;
178
194
  contribute(): {
195
+ [ContributionPointIds.TOOLS]: {
196
+ id: string;
197
+ name: string;
198
+ interaction: string;
199
+ commands: {
200
+ begin: string;
201
+ commit: string;
202
+ rollback: string;
203
+ };
204
+ session: {
205
+ autoBegin: boolean;
206
+ leavePolicy: string;
207
+ };
208
+ }[];
179
209
  [ContributionPointIds.COMMANDS]: CommandContribution[];
180
210
  };
181
211
  private cloneFeatures;
@@ -203,6 +233,8 @@ interface ImageItem {
203
233
  angle?: number;
204
234
  left?: number;
205
235
  top?: number;
236
+ sourceUrl?: string;
237
+ committedUrl?: string;
206
238
  }
207
239
  declare class ImageTool implements Extension {
208
240
  id: string;
@@ -210,59 +242,182 @@ declare class ImageTool implements Extension {
210
242
  name: string;
211
243
  };
212
244
  private items;
213
- private objectMap;
245
+ private workingItems;
246
+ private hasWorkingChanges;
214
247
  private loadResolvers;
248
+ private sourceSizeBySrc;
215
249
  private canvasService?;
216
250
  private context?;
217
251
  private isUpdatingConfig;
218
252
  private isToolActive;
253
+ private isImageSelectionActive;
254
+ private focusedImageId;
255
+ private suppressSelectionClearUntil;
256
+ private renderSeq;
257
+ private dirtyTrackerDisposable?;
219
258
  activate(context: ExtensionContext): void;
220
259
  deactivate(context: ExtensionContext): void;
221
260
  private onToolActivated;
222
- private updateInteractivity;
261
+ private onSelectionChanged;
262
+ private onSelectionCleared;
263
+ private onSceneLayoutChanged;
264
+ private syncToolActiveFromWorkbench;
265
+ private isImageEditingVisible;
266
+ private isDebugEnabled;
267
+ private debug;
223
268
  contribute(): {
269
+ [ContributionPointIds.TOOLS]: {
270
+ id: string;
271
+ name: string;
272
+ interaction: string;
273
+ commands: {
274
+ begin: string;
275
+ commit: string;
276
+ rollback: string;
277
+ };
278
+ session: {
279
+ autoBegin: boolean;
280
+ leavePolicy: string;
281
+ };
282
+ }[];
224
283
  [ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
225
284
  [ContributionPointIds.COMMANDS]: CommandContribution[];
226
285
  };
286
+ private normalizeItem;
287
+ private normalizeItems;
288
+ private cloneItems;
227
289
  private generateId;
290
+ private getImageIdFromActiveObject;
291
+ private resolveReplaceTargetId;
292
+ private addImageEntry;
293
+ private upsertImageEntry;
294
+ private addItemToWorkingSessionIfNeeded;
295
+ private updateImage;
296
+ private getConfig;
228
297
  private updateConfig;
229
- private ensureLayer;
230
- private getLayoutInfo;
298
+ private getFrameRect;
299
+ private resolveDefaultFitArea;
300
+ private fitImageToDefaultArea;
301
+ private getImageObjects;
302
+ private getOverlayObjects;
303
+ private getImageObject;
304
+ private clearRenderedImages;
305
+ private purgeSourceSizeCacheForItem;
306
+ private rememberSourceSize;
307
+ private getSourceSize;
308
+ private getCoverScale;
309
+ private getFrameVisualConfig;
310
+ private resolveRenderImageState;
311
+ private computeCanvasProps;
312
+ private getCurrentSrc;
313
+ private upsertImageObject;
314
+ private syncImageZOrder;
315
+ private buildOverlaySpecs;
231
316
  private updateImages;
232
- private updateObjectProperties;
233
- private loadImage;
234
- private handleObjectModified;
317
+ private updateImagesAsync;
318
+ private clampNormalized;
319
+ private onObjectModified;
320
+ private updateImageInWorking;
235
321
  private updateImageInConfig;
322
+ private waitImageLoaded;
323
+ private refitImageToFrame;
324
+ private focusImageSelection;
325
+ private fitImageToArea;
326
+ private commitWorkingImagesAsCropped;
327
+ private exportCroppedImageByIds;
328
+ private exportImageFrameUrl;
236
329
  }
237
330
 
331
+ interface WhiteInkItem {
332
+ id: string;
333
+ sourceUrl?: string;
334
+ url?: string;
335
+ opacity: number;
336
+ }
238
337
  declare class WhiteInkTool implements Extension {
239
338
  id: string;
240
339
  metadata: {
241
340
  name: string;
242
341
  };
243
- private customMask;
244
- private opacity;
245
- private enableClip;
342
+ private items;
343
+ private workingItems;
344
+ private hasWorkingChanges;
345
+ private sourceSizeBySrc;
346
+ private previewMaskBySource;
347
+ private pendingPreviewMaskBySource;
246
348
  private canvasService?;
247
- private syncHandler;
248
- private _loadingUrl;
249
- constructor(options?: Partial<{
250
- customMask: string;
251
- opacity: number;
252
- enableClip: boolean;
253
- }>);
349
+ private context?;
350
+ private isUpdatingConfig;
351
+ private isToolActive;
352
+ private printWithWhiteInk;
353
+ private previewImageVisible;
354
+ private renderSeq;
355
+ private dirtyTrackerDisposable?;
254
356
  activate(context: ExtensionContext): void;
255
357
  deactivate(context: ExtensionContext): void;
256
358
  contribute(): {
359
+ [ContributionPointIds.TOOLS]: {
360
+ id: string;
361
+ name: string;
362
+ interaction: string;
363
+ commands: {
364
+ begin: string;
365
+ commit: string;
366
+ rollback: string;
367
+ };
368
+ session: {
369
+ autoBegin: boolean;
370
+ leavePolicy: string;
371
+ };
372
+ }[];
257
373
  [ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
258
374
  [ContributionPointIds.COMMANDS]: CommandContribution[];
259
375
  };
260
- private setup;
261
- private teardown;
262
- private updateWhiteInk;
263
- private loadWhiteInk;
264
- private applyClipPath;
265
- private syncWithUserImage;
376
+ private onToolActivated;
377
+ private onSceneLayoutChanged;
378
+ private onObjectAdded;
379
+ private migrateLegacyConfigIfNeeded;
380
+ private syncToolActiveFromWorkbench;
381
+ private isPreviewActive;
382
+ private isDebugEnabled;
383
+ private debug;
384
+ private resolveSourceUrl;
385
+ private clampOpacity;
386
+ private normalizeItem;
387
+ private normalizeItems;
388
+ private cloneItems;
389
+ private generateId;
390
+ private getConfig;
391
+ private resolveReplaceTargetId;
392
+ private updateConfig;
393
+ private addWhiteInkEntry;
394
+ private upsertWhiteInkEntry;
395
+ private addItemToWorkingSessionIfNeeded;
396
+ private updateWhiteInkItem;
397
+ private updateWhiteInkInWorking;
398
+ private updateWhiteInkInConfig;
399
+ private removeWhiteInk;
400
+ private clearWhiteInks;
401
+ private completeWhiteInks;
402
+ private getFrameRect;
403
+ private getWhiteInkObjects;
404
+ private getWhiteInkObject;
405
+ private clearRenderedWhiteInks;
406
+ private purgeSourceCaches;
407
+ private rememberSourceSize;
408
+ private getSourceSize;
409
+ private getCoverScale;
410
+ private resolveRenderState;
411
+ private computeCanvasProps;
412
+ private getCurrentSrc;
413
+ private upsertWhiteInkObject;
414
+ private syncZOrder;
415
+ private applyImagePreviewVisibility;
416
+ private updateWhiteInks;
417
+ private updateWhiteInksAsync;
418
+ private getPreviewMaskSource;
419
+ private createOpaqueMaskSource;
420
+ private loadImageElement;
266
421
  }
267
422
 
268
423
  declare class RulerTool implements Extension {
@@ -276,12 +431,9 @@ declare class RulerTool implements Extension {
276
431
  private textColor;
277
432
  private lineColor;
278
433
  private fontSize;
279
- private dielineWidth;
280
- private dielineHeight;
281
- private dielineDisplayUnit;
282
- private dielinePadding;
283
- private dielineOffset;
284
434
  private canvasService?;
435
+ private context?;
436
+ private onCanvasResized;
285
437
  constructor(options?: Partial<{
286
438
  thickness: number;
287
439
  backgroundColor: string;
@@ -299,7 +451,6 @@ declare class RulerTool implements Extension {
299
451
  private createLayer;
300
452
  private destroyLayer;
301
453
  private createArrowLine;
302
- private resolvePadding;
303
454
  private updateRuler;
304
455
  }
305
456
 
@@ -326,8 +477,56 @@ declare class MirrorTool implements Extension {
326
477
  private applyMirror;
327
478
  }
328
479
 
329
- declare function parseLengthToMm(input: number | string, defaultUnit: Unit): number;
330
- declare function formatMm(valueMm: number, displayUnit: Unit, fractionDigits?: number): string;
480
+ declare class SizeTool implements Extension {
481
+ id: string;
482
+ metadata: {
483
+ name: string;
484
+ };
485
+ private context?;
486
+ private canvasService?;
487
+ activate(context: ExtensionContext): void;
488
+ deactivate(_context: ExtensionContext): void;
489
+ contribute(): {
490
+ [ContributionPointIds.TOOLS]: {
491
+ id: string;
492
+ name: string;
493
+ interaction: string;
494
+ }[];
495
+ [ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
496
+ [ContributionPointIds.COMMANDS]: CommandContribution[];
497
+ };
498
+ private getConfigService;
499
+ private ensureDefaults;
500
+ private emitStateChanged;
501
+ private getStateForUI;
502
+ private updateDimensions;
503
+ private setConstraintMode;
504
+ private setUnit;
505
+ private setCut;
506
+ private getSelectedImageSize;
507
+ }
508
+
509
+ declare class SceneLayoutService implements Extension {
510
+ id: string;
511
+ metadata: {
512
+ name: string;
513
+ };
514
+ private context?;
515
+ private canvasService?;
516
+ private configService?;
517
+ private lastLayout;
518
+ private lastGeometry;
519
+ private onConfigChange?;
520
+ activate(context: ExtensionContext): void;
521
+ deactivate(context: ExtensionContext): void;
522
+ contribute(): {
523
+ [ContributionPointIds.COMMANDS]: CommandContribution[];
524
+ };
525
+ private onCanvasResized;
526
+ private refresh;
527
+ private getLayout;
528
+ private getGeometry;
529
+ }
331
530
 
332
531
  declare class ViewportSystem {
333
532
  private _containerSize;
@@ -348,6 +547,21 @@ declare class ViewportSystem {
348
547
  toPhysicalPoint(point: Point): Point;
349
548
  }
350
549
 
550
+ type RenderObjectType = "rect" | "image" | "path";
551
+ type RenderProps = Record<string, any>;
552
+ interface RenderObjectSpec {
553
+ id: string;
554
+ type: RenderObjectType;
555
+ props: RenderProps;
556
+ data?: Record<string, any>;
557
+ src?: string;
558
+ }
559
+ interface RenderLayerSpec {
560
+ id: string;
561
+ objects: RenderObjectSpec[];
562
+ props?: RenderProps;
563
+ }
564
+
351
565
  declare class CanvasService implements Service {
352
566
  canvas: Canvas;
353
567
  viewport: ViewportSystem;
@@ -370,6 +584,97 @@ declare class CanvasService implements Service {
370
584
  */
371
585
  getObject(id: string, layerId?: string): FabricObject | undefined;
372
586
  requestRenderAll(): void;
587
+ resize(width: number, height: number): void;
588
+ applyLayerSpec(spec: RenderLayerSpec): Promise<void>;
589
+ applyObjectSpecsToLayer(layerId: string, objects: RenderObjectSpec[]): Promise<void>;
590
+ getRootLayerObjects(layerId: string): FabricObject[];
591
+ applyObjectSpecsToRootLayer(layerId: string, specs: RenderObjectSpec[]): Promise<void>;
592
+ private applyObjectSpecsToContainer;
593
+ private patchFabricObject;
594
+ private moveObjectInContainer;
595
+ private createFabricObject;
596
+ }
597
+
598
+ type SizeConstraintMode = "free" | "lockAspect" | "equal";
599
+ type CutMode = "trim" | "outset" | "inset";
600
+ interface SizeState {
601
+ unit: Unit;
602
+ actualWidthMm: number;
603
+ actualHeightMm: number;
604
+ constraintMode: SizeConstraintMode;
605
+ aspectRatio: number;
606
+ cutMode: CutMode;
607
+ cutMarginMm: number;
608
+ viewPadding: number | string;
609
+ minMm: number;
610
+ maxMm: number;
611
+ stepMm: number;
612
+ }
613
+ interface SceneRect {
614
+ left: number;
615
+ top: number;
616
+ width: number;
617
+ height: number;
618
+ centerX: number;
619
+ centerY: number;
620
+ }
621
+ interface SceneLayoutSnapshot {
622
+ scale: number;
623
+ canvasWidth: number;
624
+ canvasHeight: number;
625
+ trimRect: SceneRect;
626
+ cutRect: SceneRect;
627
+ bleedRect: SceneRect;
628
+ trimWidthMm: number;
629
+ trimHeightMm: number;
630
+ cutWidthMm: number;
631
+ cutHeightMm: number;
632
+ cutMode: CutMode;
633
+ cutMarginMm: number;
634
+ }
635
+ interface SceneGeometrySnapshot {
636
+ shape: "rect" | "circle" | "ellipse" | "custom";
637
+ unit: "mm";
638
+ displayUnit: Unit;
639
+ x: number;
640
+ y: number;
641
+ width: number;
642
+ height: number;
643
+ radius: number;
644
+ offset: number;
645
+ scale: number;
646
+ pathData?: string;
647
+ }
648
+ declare function sanitizeMmValue(valueMm: number, limits: {
649
+ minMm: number;
650
+ maxMm: number;
651
+ stepMm: number;
652
+ }): number;
653
+ declare function normalizeUnit(value: unknown): Unit;
654
+ declare function normalizeConstraintMode(value: unknown): SizeConstraintMode;
655
+ declare function normalizeCutMode(value: unknown): CutMode;
656
+ declare function toMm(value: number, fromUnit: Unit): number;
657
+ declare function fromMm(valueMm: number, toUnit: Unit): number;
658
+ declare function resolvePaddingPx(raw: number | string, containerWidth: number, containerHeight: number): number;
659
+ declare function readSizeState(configService: ConfigurationService): SizeState;
660
+ declare function computeSceneLayout(canvasService: CanvasService, size: SizeState): SceneLayoutSnapshot | null;
661
+ declare function buildSceneGeometry(configService: ConfigurationService, layout: SceneLayoutSnapshot): SceneGeometrySnapshot;
662
+
663
+ declare class SceneVisibilityService implements Extension {
664
+ id: string;
665
+ metadata: {
666
+ name: string;
667
+ };
668
+ private canvasService?;
669
+ private activeToolId;
670
+ activate(context: ExtensionContext): void;
671
+ deactivate(context: ExtensionContext): void;
672
+ private onToolActivated;
673
+ private onObjectAdded;
674
+ private apply;
373
675
  }
374
676
 
375
- export { BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LineStyle, MirrorTool, RulerTool, WhiteInkTool, formatMm, parseLengthToMm };
677
+ declare function parseLengthToMm(input: number | string, defaultUnit: Unit): number;
678
+ declare function formatMm(valueMm: number, displayUnit: Unit, fractionDigits?: number): string;
679
+
680
+ export { BackgroundTool, CanvasService, type CutMode, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LineStyle, MirrorTool, RulerTool, type SceneGeometrySnapshot, SceneLayoutService, type SceneLayoutSnapshot, type SceneRect, SceneVisibilityService, type SizeConstraintMode, type SizeState, SizeTool, type WhiteInkItem, WhiteInkTool, buildSceneGeometry, computeSceneLayout, formatMm, fromMm, normalizeConstraintMode, normalizeCutMode, normalizeUnit, parseLengthToMm, readSizeState, resolvePaddingPx, sanitizeMmValue, toMm };