@pooder/kit 5.3.0 → 5.4.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.d.mts +249 -36
  3. package/dist/index.d.ts +249 -36
  4. package/dist/index.js +2374 -1049
  5. package/dist/index.mjs +2375 -1050
  6. package/package.json +1 -1
  7. package/src/extensions/background.ts +178 -85
  8. package/src/extensions/dieline.ts +1149 -1030
  9. package/src/extensions/dielineShape.ts +109 -0
  10. package/src/extensions/feature.ts +482 -366
  11. package/src/extensions/film.ts +148 -76
  12. package/src/extensions/geometry.ts +210 -44
  13. package/src/extensions/image.ts +244 -114
  14. package/src/extensions/ruler.ts +471 -268
  15. package/src/extensions/sceneLayoutModel.ts +28 -6
  16. package/src/extensions/sceneVisibility.ts +3 -10
  17. package/src/extensions/tracer.ts +1019 -980
  18. package/src/extensions/white-ink.ts +284 -231
  19. package/src/services/CanvasService.ts +543 -11
  20. package/src/services/renderSpec.ts +37 -2
  21. package/.test-dist/src/CanvasService.js +0 -249
  22. package/.test-dist/src/ViewportSystem.js +0 -75
  23. package/.test-dist/src/background.js +0 -203
  24. package/.test-dist/src/bridgeSelection.js +0 -20
  25. package/.test-dist/src/constraints.js +0 -237
  26. package/.test-dist/src/coordinate.js +0 -74
  27. package/.test-dist/src/dieline.js +0 -818
  28. package/.test-dist/src/edgeScale.js +0 -12
  29. package/.test-dist/src/extensions/background.js +0 -203
  30. package/.test-dist/src/extensions/bridgeSelection.js +0 -20
  31. package/.test-dist/src/extensions/constraints.js +0 -237
  32. package/.test-dist/src/extensions/dieline.js +0 -828
  33. package/.test-dist/src/extensions/edgeScale.js +0 -12
  34. package/.test-dist/src/extensions/feature.js +0 -825
  35. package/.test-dist/src/extensions/featureComplete.js +0 -32
  36. package/.test-dist/src/extensions/film.js +0 -167
  37. package/.test-dist/src/extensions/geometry.js +0 -545
  38. package/.test-dist/src/extensions/image.js +0 -1529
  39. package/.test-dist/src/extensions/index.js +0 -30
  40. package/.test-dist/src/extensions/maskOps.js +0 -279
  41. package/.test-dist/src/extensions/mirror.js +0 -104
  42. package/.test-dist/src/extensions/ruler.js +0 -345
  43. package/.test-dist/src/extensions/sceneLayout.js +0 -96
  44. package/.test-dist/src/extensions/sceneLayoutModel.js +0 -196
  45. package/.test-dist/src/extensions/sceneVisibility.js +0 -62
  46. package/.test-dist/src/extensions/size.js +0 -331
  47. package/.test-dist/src/extensions/tracer.js +0 -538
  48. package/.test-dist/src/extensions/white-ink.js +0 -1190
  49. package/.test-dist/src/extensions/wrappedOffsets.js +0 -33
  50. package/.test-dist/src/feature.js +0 -826
  51. package/.test-dist/src/featureComplete.js +0 -32
  52. package/.test-dist/src/film.js +0 -167
  53. package/.test-dist/src/geometry.js +0 -506
  54. package/.test-dist/src/image.js +0 -1250
  55. package/.test-dist/src/index.js +0 -18
  56. package/.test-dist/src/maskOps.js +0 -270
  57. package/.test-dist/src/mirror.js +0 -104
  58. package/.test-dist/src/renderSpec.js +0 -2
  59. package/.test-dist/src/ruler.js +0 -343
  60. package/.test-dist/src/sceneLayout.js +0 -99
  61. package/.test-dist/src/sceneLayoutModel.js +0 -196
  62. package/.test-dist/src/sceneView.js +0 -40
  63. package/.test-dist/src/sceneVisibility.js +0 -42
  64. package/.test-dist/src/services/CanvasService.js +0 -249
  65. package/.test-dist/src/services/ViewportSystem.js +0 -76
  66. package/.test-dist/src/services/index.js +0 -24
  67. package/.test-dist/src/services/renderSpec.js +0 -2
  68. package/.test-dist/src/size.js +0 -332
  69. package/.test-dist/src/tracer.js +0 -544
  70. package/.test-dist/src/units.js +0 -30
  71. package/.test-dist/src/white-ink.js +0 -829
  72. package/.test-dist/src/wrappedOffsets.js +0 -33
  73. package/.test-dist/tests/run.js +0 -94
@@ -8,7 +8,7 @@ import {
8
8
  ToolSessionService,
9
9
  WorkbenchService,
10
10
  } from "@pooder/core";
11
- import { CanvasService, RenderObjectSpec } from "../services";
11
+ import { CanvasService, RenderLayoutRect, RenderObjectSpec } from "../services";
12
12
  import { computeSceneLayout, readSizeState } from "./sceneLayoutModel";
13
13
 
14
14
  export interface WhiteInkItem {
@@ -56,21 +56,21 @@ interface ImageSnapshot {
56
56
  height: number;
57
57
  }
58
58
 
59
- interface ImagePlacementState {
60
- id: string;
61
- sourceUrl: string;
62
- committedUrl: string;
63
- left: number;
64
- top: number;
65
- scale: number;
66
- angle: number;
67
- }
68
-
69
- interface RenderSources {
70
- whiteSrc: string;
71
- coverSrc: string;
72
- whiteScaleAdjustX: number;
73
- whiteScaleAdjustY: number;
59
+ interface ImagePlacementState {
60
+ id: string;
61
+ sourceUrl: string;
62
+ committedUrl: string;
63
+ left: number;
64
+ top: number;
65
+ scale: number;
66
+ angle: number;
67
+ }
68
+
69
+ interface RenderSources {
70
+ whiteSrc: string;
71
+ coverSrc: string;
72
+ whiteScaleAdjustX: number;
73
+ whiteScaleAdjustY: number;
74
74
  }
75
75
 
76
76
  interface UpsertWhiteInkOptions {
@@ -125,6 +125,10 @@ export class WhiteInkTool implements Extension {
125
125
  private previewImageVisible = true;
126
126
  private renderSeq = 0;
127
127
  private dirtyTrackerDisposable?: { dispose(): void };
128
+ private whiteSpecs: RenderObjectSpec[] = [];
129
+ private coverSpecs: RenderObjectSpec[] = [];
130
+ private overlaySpecs: RenderObjectSpec[] = [];
131
+ private renderProducerDisposable?: { dispose: () => void };
128
132
 
129
133
  activate(context: ExtensionContext) {
130
134
  this.context = context;
@@ -133,6 +137,18 @@ export class WhiteInkTool implements Extension {
133
137
  console.warn("CanvasService not found for WhiteInkTool");
134
138
  return;
135
139
  }
140
+ this.renderProducerDisposable?.dispose();
141
+ this.renderProducerDisposable = this.canvasService.registerRenderProducer(
142
+ this.id,
143
+ () => ({
144
+ rootLayerSpecs: {
145
+ [WHITE_INK_OBJECT_LAYER_ID]: this.whiteSpecs,
146
+ [WHITE_INK_COVER_LAYER_ID]: this.coverSpecs,
147
+ [WHITE_INK_OVERLAY_LAYER_ID]: this.overlaySpecs,
148
+ },
149
+ }),
150
+ { priority: 260 },
151
+ );
136
152
 
137
153
  context.eventBus.on("tool:activated", this.onToolActivated);
138
154
  context.eventBus.on("scene:layout:change", this.onSceneLayoutChanged);
@@ -223,6 +239,11 @@ export class WhiteInkTool implements Extension {
223
239
  this.dirtyTrackerDisposable = undefined;
224
240
  this.clearRenderedWhiteInks();
225
241
  this.applyImageVisibilityForWhiteInk(false);
242
+ this.renderProducerDisposable?.dispose();
243
+ this.renderProducerDisposable = undefined;
244
+ if (this.canvasService) {
245
+ void this.canvasService.flushRenderFromProducers();
246
+ }
226
247
 
227
248
  this.canvasService = undefined;
228
249
  this.context = undefined;
@@ -747,11 +768,21 @@ export class WhiteInkTool implements Extension {
747
768
  return { left: 0, top: 0, width: 0, height: 0 };
748
769
  }
749
770
 
750
- return {
771
+ return this.canvasService.toSceneRect({
751
772
  left: layout.cutRect.left,
752
773
  top: layout.cutRect.top,
753
774
  width: layout.cutRect.width,
754
775
  height: layout.cutRect.height,
776
+ });
777
+ }
778
+
779
+ private toLayoutSceneRect(rect: FrameRect): RenderLayoutRect {
780
+ return {
781
+ left: rect.left,
782
+ top: rect.top,
783
+ width: rect.width,
784
+ height: rect.height,
785
+ space: "scene",
755
786
  };
756
787
  }
757
788
 
@@ -786,15 +817,23 @@ export class WhiteInkTool implements Extension {
786
817
  const width = Number(obj?.width || 0);
787
818
  const height = Number(obj?.height || 0);
788
819
  this.rememberSourceSize(src, { width, height });
820
+ const sceneScale = this.canvasService?.getSceneScale() || 1;
821
+ const leftScreen = Number.isFinite(obj?.left) ? Number(obj.left) : 0;
822
+ const topScreen = Number.isFinite(obj?.top) ? Number(obj.top) : 0;
823
+ const scenePoint = this.canvasService
824
+ ? this.canvasService.toScenePoint({ x: leftScreen, y: topScreen })
825
+ : { x: leftScreen, y: topScreen };
789
826
 
790
827
  return {
791
828
  id: String(obj?.data?.id || "image"),
792
829
  src,
793
830
  element,
794
- left: Number.isFinite(obj?.left) ? Number(obj.left) : 0,
795
- top: Number.isFinite(obj?.top) ? Number(obj.top) : 0,
796
- scaleX: Number.isFinite(obj?.scaleX) ? Number(obj.scaleX) : 1,
797
- scaleY: Number.isFinite(obj?.scaleY) ? Number(obj.scaleY) : 1,
831
+ left: scenePoint.x,
832
+ top: scenePoint.y,
833
+ scaleX:
834
+ (Number.isFinite(obj?.scaleX) ? Number(obj.scaleX) : 1) / sceneScale,
835
+ scaleY:
836
+ (Number.isFinite(obj?.scaleY) ? Number(obj.scaleY) : 1) / sceneScale,
798
837
  angle: Number.isFinite(obj?.angle) ? Number(obj.angle) : 0,
799
838
  originX: typeof obj?.originX === "string" ? obj.originX : "center",
800
839
  originY: typeof obj?.originY === "string" ? obj.originY : "center",
@@ -807,116 +846,118 @@ export class WhiteInkTool implements Extension {
807
846
  };
808
847
  }
809
848
 
810
- private getImagePlacementState(id?: string): ImagePlacementState | null {
811
- const rawItems = this.getConfig<any[]>("image.items", []);
812
- if (!Array.isArray(rawItems) || rawItems.length === 0) return null;
813
-
814
- const matched =
815
- (id
816
- ? rawItems.find(
817
- (item: any) =>
818
- item &&
819
- typeof item === "object" &&
820
- typeof item.id === "string" &&
821
- item.id === id,
822
- )
823
- : undefined) || rawItems[0];
824
-
825
- if (!matched || typeof matched !== "object") return null;
826
-
827
- const sourceUrl =
828
- typeof matched.sourceUrl === "string" && matched.sourceUrl.length > 0
829
- ? matched.sourceUrl
830
- : typeof matched.url === "string"
831
- ? matched.url
832
- : "";
833
- const committedUrl =
834
- typeof matched.committedUrl === "string" ? matched.committedUrl : "";
835
-
836
- return {
837
- id:
838
- typeof matched.id === "string" && matched.id.length > 0
839
- ? matched.id
840
- : id || "image",
841
- sourceUrl,
842
- committedUrl,
843
- left: Number.isFinite(matched.left) ? Number(matched.left) : 0.5,
844
- top: Number.isFinite(matched.top) ? Number(matched.top) : 0.5,
845
- scale: Number.isFinite(matched.scale) ? Math.max(0.05, matched.scale) : 1,
846
- angle: Number.isFinite(matched.angle) ? matched.angle : 0,
847
- };
848
- }
849
-
850
- private shouldRestoreSnapshotToSource(
851
- snapshot: ImageSnapshot,
852
- placement: ImagePlacementState,
853
- ): boolean {
854
- if (!placement.sourceUrl || !placement.committedUrl) return false;
855
- if (placement.sourceUrl === placement.committedUrl) return false;
856
- return snapshot.src === placement.committedUrl;
857
- }
858
-
859
- private getCoverScale(frame: FrameRect, source: SourceSize): number {
860
- const frameW = Math.max(1, frame.width);
861
- const frameH = Math.max(1, frame.height);
862
- const sourceW = Math.max(1, source.width);
863
- const sourceH = Math.max(1, source.height);
864
- return Math.max(frameW / sourceW, frameH / sourceH);
865
- }
866
-
867
- private async ensureSourceSize(sourceUrl: string): Promise<SourceSize | null> {
868
- if (!sourceUrl) return null;
869
- const cached = this.getSourceSize(sourceUrl);
870
- if (cached) return cached;
871
-
872
- try {
873
- const image = await this.loadImageElement(sourceUrl);
874
- const size = this.getElementSize(image);
875
- if (!size) return null;
876
- this.rememberSourceSize(sourceUrl, size);
877
- return {
878
- width: size.width,
879
- height: size.height,
880
- };
881
- } catch {
882
- return null;
883
- }
884
- }
885
-
886
- private async resolveAlignedImageSnapshot(
887
- snapshot: ImageSnapshot,
888
- ): Promise<ImageSnapshot> {
889
- const placement = this.getImagePlacementState(snapshot.id);
890
- if (!placement) return snapshot;
891
- if (!this.shouldRestoreSnapshotToSource(snapshot, placement)) {
892
- return snapshot;
893
- }
894
-
895
- const frame = this.getFrameRect();
896
- if (frame.width <= 0 || frame.height <= 0) {
897
- return snapshot;
898
- }
899
-
900
- const sourceSize = await this.ensureSourceSize(placement.sourceUrl);
901
- if (!sourceSize) return snapshot;
902
-
903
- const coverScale = this.getCoverScale(frame, sourceSize);
904
-
905
- return {
906
- ...snapshot,
907
- src: placement.sourceUrl,
908
- element: undefined,
909
- left: frame.left + placement.left * frame.width,
910
- top: frame.top + placement.top * frame.height,
911
- scaleX: coverScale * placement.scale,
912
- scaleY: coverScale * placement.scale,
913
- angle: placement.angle,
914
- originX: "center",
915
- originY: "center",
916
- width: sourceSize.width,
917
- height: sourceSize.height,
918
- };
919
- }
849
+ private getImagePlacementState(id?: string): ImagePlacementState | null {
850
+ const rawItems = this.getConfig<any[]>("image.items", []);
851
+ if (!Array.isArray(rawItems) || rawItems.length === 0) return null;
852
+
853
+ const matched =
854
+ (id
855
+ ? rawItems.find(
856
+ (item: any) =>
857
+ item &&
858
+ typeof item === "object" &&
859
+ typeof item.id === "string" &&
860
+ item.id === id,
861
+ )
862
+ : undefined) || rawItems[0];
863
+
864
+ if (!matched || typeof matched !== "object") return null;
865
+
866
+ const sourceUrl =
867
+ typeof matched.sourceUrl === "string" && matched.sourceUrl.length > 0
868
+ ? matched.sourceUrl
869
+ : typeof matched.url === "string"
870
+ ? matched.url
871
+ : "";
872
+ const committedUrl =
873
+ typeof matched.committedUrl === "string" ? matched.committedUrl : "";
874
+
875
+ return {
876
+ id:
877
+ typeof matched.id === "string" && matched.id.length > 0
878
+ ? matched.id
879
+ : id || "image",
880
+ sourceUrl,
881
+ committedUrl,
882
+ left: Number.isFinite(matched.left) ? Number(matched.left) : 0.5,
883
+ top: Number.isFinite(matched.top) ? Number(matched.top) : 0.5,
884
+ scale: Number.isFinite(matched.scale) ? Math.max(0.05, matched.scale) : 1,
885
+ angle: Number.isFinite(matched.angle) ? matched.angle : 0,
886
+ };
887
+ }
888
+
889
+ private shouldRestoreSnapshotToSource(
890
+ snapshot: ImageSnapshot,
891
+ placement: ImagePlacementState,
892
+ ): boolean {
893
+ if (!placement.sourceUrl || !placement.committedUrl) return false;
894
+ if (placement.sourceUrl === placement.committedUrl) return false;
895
+ return snapshot.src === placement.committedUrl;
896
+ }
897
+
898
+ private getCoverScale(frame: FrameRect, source: SourceSize): number {
899
+ const frameW = Math.max(1, frame.width);
900
+ const frameH = Math.max(1, frame.height);
901
+ const sourceW = Math.max(1, source.width);
902
+ const sourceH = Math.max(1, source.height);
903
+ return Math.max(frameW / sourceW, frameH / sourceH);
904
+ }
905
+
906
+ private async ensureSourceSize(
907
+ sourceUrl: string,
908
+ ): Promise<SourceSize | null> {
909
+ if (!sourceUrl) return null;
910
+ const cached = this.getSourceSize(sourceUrl);
911
+ if (cached) return cached;
912
+
913
+ try {
914
+ const image = await this.loadImageElement(sourceUrl);
915
+ const size = this.getElementSize(image);
916
+ if (!size) return null;
917
+ this.rememberSourceSize(sourceUrl, size);
918
+ return {
919
+ width: size.width,
920
+ height: size.height,
921
+ };
922
+ } catch {
923
+ return null;
924
+ }
925
+ }
926
+
927
+ private async resolveAlignedImageSnapshot(
928
+ snapshot: ImageSnapshot,
929
+ ): Promise<ImageSnapshot> {
930
+ const placement = this.getImagePlacementState(snapshot.id);
931
+ if (!placement) return snapshot;
932
+ if (!this.shouldRestoreSnapshotToSource(snapshot, placement)) {
933
+ return snapshot;
934
+ }
935
+
936
+ const frame = this.getFrameRect();
937
+ if (frame.width <= 0 || frame.height <= 0) {
938
+ return snapshot;
939
+ }
940
+
941
+ const sourceSize = await this.ensureSourceSize(placement.sourceUrl);
942
+ if (!sourceSize) return snapshot;
943
+
944
+ const coverScale = this.getCoverScale(frame, sourceSize);
945
+
946
+ return {
947
+ ...snapshot,
948
+ src: placement.sourceUrl,
949
+ element: undefined,
950
+ left: frame.left + placement.left * frame.width,
951
+ top: frame.top + placement.top * frame.height,
952
+ scaleX: coverScale * placement.scale,
953
+ scaleY: coverScale * placement.scale,
954
+ angle: placement.angle,
955
+ originX: "center",
956
+ originY: "center",
957
+ width: sourceSize.width,
958
+ height: sourceSize.height,
959
+ };
960
+ }
920
961
  private getImageElementFromObject(obj: any): any {
921
962
  if (!obj) return null;
922
963
  if (typeof obj.getElement === "function") {
@@ -1025,8 +1066,11 @@ export class WhiteInkTool implements Extension {
1025
1066
  if (!this.isToolActive || !this.canvasService) return [];
1026
1067
  if (frame.width <= 0 || frame.height <= 0) return [];
1027
1068
 
1028
- const canvasW = this.canvasService.canvas.width || 0;
1029
- const canvasH = this.canvasService.canvas.height || 0;
1069
+ const viewport = this.canvasService.getSceneViewportRect();
1070
+ const canvasW = viewport.width || 0;
1071
+ const canvasH = viewport.height || 0;
1072
+ const canvasLeft = viewport.left || 0;
1073
+ const canvasTop = viewport.top || 0;
1030
1074
  const strokeColor =
1031
1075
  this.getConfig<string>("image.frame.strokeColor", "#808080") || "#808080";
1032
1076
  const strokeWidthRaw = Number(
@@ -1048,23 +1092,44 @@ export class WhiteInkTool implements Extension {
1048
1092
  const dashLength = Number.isFinite(dashLengthRaw)
1049
1093
  ? Math.max(1, dashLengthRaw)
1050
1094
  : 8;
1095
+ const strokeWidthScene = this.canvasService.toSceneLength(strokeWidth);
1096
+ const dashLengthScene = this.canvasService.toSceneLength(dashLength);
1051
1097
 
1052
- const frameLeft = Math.max(0, Math.min(canvasW, frame.left));
1053
- const frameTop = Math.max(0, Math.min(canvasH, frame.top));
1098
+ const frameLeft = Math.max(
1099
+ canvasLeft,
1100
+ Math.min(canvasLeft + canvasW, frame.left),
1101
+ );
1102
+ const frameTop = Math.max(
1103
+ canvasTop,
1104
+ Math.min(canvasTop + canvasH, frame.top),
1105
+ );
1054
1106
  const frameRight = Math.max(
1055
1107
  frameLeft,
1056
- Math.min(canvasW, frame.left + frame.width),
1108
+ Math.min(canvasLeft + canvasW, frame.left + frame.width),
1057
1109
  );
1058
1110
  const frameBottom = Math.max(
1059
1111
  frameTop,
1060
- Math.min(canvasH, frame.top + frame.height),
1112
+ Math.min(canvasTop + canvasH, frame.top + frame.height),
1061
1113
  );
1062
1114
  const visibleFrameH = Math.max(0, frameBottom - frameTop);
1063
1115
 
1064
- const topH = frameTop;
1065
- const bottomH = Math.max(0, canvasH - frameBottom);
1066
- const leftW = frameLeft;
1067
- const rightW = Math.max(0, canvasW - frameRight);
1116
+ const topH = Math.max(0, frameTop - canvasTop);
1117
+ const bottomH = Math.max(0, canvasTop + canvasH - frameBottom);
1118
+ const leftW = Math.max(0, frameLeft - canvasLeft);
1119
+ const rightW = Math.max(0, canvasLeft + canvasW - frameRight);
1120
+ const viewportRect = this.toLayoutSceneRect({
1121
+ left: canvasLeft,
1122
+ top: canvasTop,
1123
+ width: canvasW,
1124
+ height: canvasH,
1125
+ });
1126
+ const visibleFrameBandRect = this.toLayoutSceneRect({
1127
+ left: canvasLeft,
1128
+ top: frameTop,
1129
+ width: canvasW,
1130
+ height: visibleFrameH,
1131
+ });
1132
+ const frameRect = this.toLayoutSceneRect(frame);
1068
1133
 
1069
1134
  const maskSpecs: RenderObjectSpec[] = [
1070
1135
  {
@@ -1075,13 +1140,17 @@ export class WhiteInkTool implements Extension {
1075
1140
  layerId: WHITE_INK_OVERLAY_LAYER_ID,
1076
1141
  type: "white-ink-mask",
1077
1142
  },
1078
- props: {
1079
- left: canvasW / 2,
1080
- top: topH / 2,
1081
- width: canvasW,
1143
+ layout: {
1144
+ reference: "custom",
1145
+ referenceRect: viewportRect,
1146
+ alignX: "start",
1147
+ alignY: "start",
1148
+ width: "100%",
1082
1149
  height: topH,
1083
- originX: "center",
1084
- originY: "center",
1150
+ },
1151
+ props: {
1152
+ originX: "left",
1153
+ originY: "top",
1085
1154
  fill: outerBackground,
1086
1155
  selectable: false,
1087
1156
  evented: false,
@@ -1096,13 +1165,17 @@ export class WhiteInkTool implements Extension {
1096
1165
  layerId: WHITE_INK_OVERLAY_LAYER_ID,
1097
1166
  type: "white-ink-mask",
1098
1167
  },
1099
- props: {
1100
- left: canvasW / 2,
1101
- top: frameBottom + bottomH / 2,
1102
- width: canvasW,
1168
+ layout: {
1169
+ reference: "custom",
1170
+ referenceRect: viewportRect,
1171
+ alignX: "start",
1172
+ alignY: "end",
1173
+ width: "100%",
1103
1174
  height: bottomH,
1104
- originX: "center",
1105
- originY: "center",
1175
+ },
1176
+ props: {
1177
+ originX: "left",
1178
+ originY: "top",
1106
1179
  fill: outerBackground,
1107
1180
  selectable: false,
1108
1181
  evented: false,
@@ -1117,13 +1190,17 @@ export class WhiteInkTool implements Extension {
1117
1190
  layerId: WHITE_INK_OVERLAY_LAYER_ID,
1118
1191
  type: "white-ink-mask",
1119
1192
  },
1120
- props: {
1121
- left: leftW / 2,
1122
- top: frameTop + visibleFrameH / 2,
1193
+ layout: {
1194
+ reference: "custom",
1195
+ referenceRect: visibleFrameBandRect,
1196
+ alignX: "start",
1197
+ alignY: "start",
1123
1198
  width: leftW,
1124
- height: visibleFrameH,
1125
- originX: "center",
1126
- originY: "center",
1199
+ height: "100%",
1200
+ },
1201
+ props: {
1202
+ originX: "left",
1203
+ originY: "top",
1127
1204
  fill: outerBackground,
1128
1205
  selectable: false,
1129
1206
  evented: false,
@@ -1138,13 +1215,17 @@ export class WhiteInkTool implements Extension {
1138
1215
  layerId: WHITE_INK_OVERLAY_LAYER_ID,
1139
1216
  type: "white-ink-mask",
1140
1217
  },
1141
- props: {
1142
- left: frameRight + rightW / 2,
1143
- top: frameTop + visibleFrameH / 2,
1218
+ layout: {
1219
+ reference: "custom",
1220
+ referenceRect: visibleFrameBandRect,
1221
+ alignX: "end",
1222
+ alignY: "start",
1144
1223
  width: rightW,
1145
- height: visibleFrameH,
1146
- originX: "center",
1147
- originY: "center",
1224
+ height: "100%",
1225
+ },
1226
+ props: {
1227
+ originX: "left",
1228
+ originY: "top",
1148
1229
  fill: outerBackground,
1149
1230
  selectable: false,
1150
1231
  evented: false,
@@ -1163,17 +1244,21 @@ export class WhiteInkTool implements Extension {
1163
1244
  layerId: WHITE_INK_OVERLAY_LAYER_ID,
1164
1245
  type: "white-ink-frame",
1165
1246
  },
1247
+ layout: {
1248
+ reference: "custom",
1249
+ referenceRect: frameRect,
1250
+ alignX: "start",
1251
+ alignY: "start",
1252
+ width: "100%",
1253
+ height: "100%",
1254
+ },
1166
1255
  props: {
1167
- left: frame.left + frame.width / 2,
1168
- top: frame.top + frame.height / 2,
1169
- width: frame.width,
1170
- height: frame.height,
1171
- originX: "center",
1172
- originY: "center",
1256
+ originX: "left",
1257
+ originY: "top",
1173
1258
  fill: innerBackground,
1174
1259
  stroke: strokeColor,
1175
- strokeWidth,
1176
- strokeDashArray: [dashLength, dashLength],
1260
+ strokeWidth: strokeWidthScene,
1261
+ strokeDashArray: [dashLengthScene, dashLengthScene],
1177
1262
  selectable: false,
1178
1263
  evented: false,
1179
1264
  excludeFromExport: true,
@@ -1262,30 +1347,22 @@ export class WhiteInkTool implements Extension {
1262
1347
  )
1263
1348
  .filter((index: number) => index >= 0);
1264
1349
 
1265
- let whiteInsertIndex = imageIndexes.length
1266
- ? Math.min(...imageIndexes)
1267
- : this.resolveDefaultInsertIndex(currentObjects);
1268
-
1269
- whiteObjects.forEach((obj) => {
1270
- canvas.moveObjectTo(obj, whiteInsertIndex);
1271
- whiteInsertIndex += 1;
1272
- });
1273
-
1274
- const afterWhiteObjects = canvas.getObjects();
1275
- const afterImageIndexes = afterWhiteObjects
1276
- .map((obj: any, index: number) =>
1277
- obj?.data?.layerId === IMAGE_OBJECT_LAYER_ID ? index : -1,
1278
- )
1279
- .filter((index: number) => index >= 0);
1280
-
1281
- let coverInsertIndex = afterImageIndexes.length
1282
- ? Math.max(...afterImageIndexes) + 1
1283
- : whiteInsertIndex;
1284
-
1285
- coverObjects.forEach((obj) => {
1286
- canvas.moveObjectTo(obj, coverInsertIndex);
1287
- coverInsertIndex += 1;
1288
- });
1350
+ let whiteInsertIndex = imageIndexes.length
1351
+ ? Math.min(...imageIndexes)
1352
+ : this.resolveDefaultInsertIndex(currentObjects);
1353
+
1354
+ let coverInsertIndex = whiteInsertIndex;
1355
+
1356
+ coverObjects.forEach((obj) => {
1357
+ canvas.moveObjectTo(obj, coverInsertIndex);
1358
+ coverInsertIndex += 1;
1359
+ });
1360
+
1361
+ whiteInsertIndex = coverInsertIndex;
1362
+ whiteObjects.forEach((obj) => {
1363
+ canvas.moveObjectTo(obj, whiteInsertIndex);
1364
+ whiteInsertIndex += 1;
1365
+ });
1289
1366
 
1290
1367
  frameObjects.forEach((obj) => canvas.bringObjectToFront(obj));
1291
1368
 
@@ -1294,31 +1371,16 @@ export class WhiteInkTool implements Extension {
1294
1371
  .filter((obj: any) => obj?.data?.layerId === IMAGE_OVERLAY_LAYER_ID)
1295
1372
  .forEach((obj: any) => canvas.bringObjectToFront(obj));
1296
1373
 
1297
- const dielineOverlay = this.canvasService.getLayer("dieline-overlay");
1298
- if (dielineOverlay) {
1299
- canvas.bringObjectToFront(dielineOverlay as any);
1300
- }
1301
-
1302
- const rulerOverlay = this.canvasService.getLayer("ruler-overlay");
1303
- if (rulerOverlay) {
1304
- canvas.bringObjectToFront(rulerOverlay as any);
1305
- }
1374
+ this.canvasService.bringLayerToFront("dieline-overlay");
1375
+ this.canvasService.bringLayerToFront("ruler-overlay");
1306
1376
  }
1307
1377
 
1308
1378
  private clearRenderedWhiteInks() {
1309
1379
  if (!this.canvasService) return;
1310
- void this.canvasService.applyObjectSpecsToRootLayer(
1311
- WHITE_INK_OBJECT_LAYER_ID,
1312
- [],
1313
- );
1314
- void this.canvasService.applyObjectSpecsToRootLayer(
1315
- WHITE_INK_COVER_LAYER_ID,
1316
- [],
1317
- );
1318
- void this.canvasService.applyObjectSpecsToRootLayer(
1319
- WHITE_INK_OVERLAY_LAYER_ID,
1320
- [],
1321
- );
1380
+ this.whiteSpecs = [];
1381
+ this.coverSpecs = [];
1382
+ this.overlaySpecs = [];
1383
+ this.canvasService.requestRenderFromProducers();
1322
1384
  }
1323
1385
 
1324
1386
  private purgeSourceCaches(item?: WhiteInkItem) {
@@ -1397,22 +1459,14 @@ export class WhiteInkTool implements Extension {
1397
1459
  }
1398
1460
  }
1399
1461
 
1400
- await this.canvasService.applyObjectSpecsToRootLayer(
1401
- WHITE_INK_OBJECT_LAYER_ID,
1402
- whiteSpecs,
1403
- );
1462
+ this.whiteSpecs = whiteSpecs;
1404
1463
  if (seq !== this.renderSeq) return;
1405
1464
 
1406
- await this.canvasService.applyObjectSpecsToRootLayer(
1407
- WHITE_INK_COVER_LAYER_ID,
1408
- coverSpecs,
1409
- );
1465
+ this.coverSpecs = coverSpecs;
1410
1466
  if (seq !== this.renderSeq) return;
1411
1467
 
1412
- await this.canvasService.applyObjectSpecsToRootLayer(
1413
- WHITE_INK_OVERLAY_LAYER_ID,
1414
- frameSpecs,
1415
- );
1468
+ this.overlaySpecs = frameSpecs;
1469
+ await this.canvasService.flushRenderFromProducers();
1416
1470
  if (seq !== this.renderSeq) return;
1417
1471
 
1418
1472
  this.syncZOrder();
@@ -1522,4 +1576,3 @@ export class WhiteInkTool implements Extension {
1522
1576
  });
1523
1577
  }
1524
1578
  }
1525
-