@pooder/kit 6.0.1 → 6.1.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.
- package/.test-dist/src/extensions/background/BackgroundTool.js +524 -0
- package/.test-dist/src/extensions/background/index.js +17 -0
- package/.test-dist/src/extensions/dieline/DielineTool.js +748 -0
- package/.test-dist/src/extensions/dieline/commands.js +127 -0
- package/.test-dist/src/extensions/dieline/config.js +107 -0
- package/.test-dist/src/extensions/dieline/index.js +21 -0
- package/.test-dist/src/extensions/dieline/model.js +2 -0
- package/.test-dist/src/extensions/dieline/renderer.js +2 -0
- package/.test-dist/src/extensions/feature/FeatureTool.js +914 -0
- package/.test-dist/src/extensions/feature/index.js +17 -0
- package/.test-dist/src/extensions/film/FilmTool.js +207 -0
- package/.test-dist/src/extensions/film/index.js +17 -0
- package/.test-dist/src/extensions/image/ImageTool.js +1499 -0
- package/.test-dist/src/extensions/image/commands.js +162 -0
- package/.test-dist/src/extensions/image/config.js +129 -0
- package/.test-dist/src/extensions/image/index.js +21 -0
- package/.test-dist/src/extensions/image/model.js +2 -0
- package/.test-dist/src/extensions/image/renderer.js +5 -0
- package/.test-dist/src/extensions/mirror/MirrorTool.js +104 -0
- package/.test-dist/src/extensions/mirror/index.js +17 -0
- package/.test-dist/src/extensions/ruler/RulerTool.js +442 -0
- package/.test-dist/src/extensions/ruler/index.js +17 -0
- package/.test-dist/src/extensions/sceneLayout.js +2 -93
- package/.test-dist/src/extensions/sceneLayoutModel.js +15 -200
- package/.test-dist/src/extensions/size/SizeTool.js +332 -0
- package/.test-dist/src/extensions/size/index.js +17 -0
- package/.test-dist/src/extensions/white-ink/WhiteInkTool.js +1003 -0
- package/.test-dist/src/extensions/white-ink/commands.js +148 -0
- package/.test-dist/src/extensions/white-ink/config.js +31 -0
- package/.test-dist/src/extensions/white-ink/index.js +21 -0
- package/.test-dist/src/extensions/white-ink/model.js +2 -0
- package/.test-dist/src/extensions/white-ink/renderer.js +5 -0
- package/.test-dist/src/services/SceneLayoutService.js +96 -0
- package/.test-dist/src/services/index.js +1 -0
- package/.test-dist/src/shared/constants/layers.js +25 -0
- package/.test-dist/src/shared/imaging/sourceSizeCache.js +82 -0
- package/.test-dist/src/shared/index.js +22 -0
- package/.test-dist/src/shared/runtime/sessionState.js +74 -0
- package/.test-dist/src/shared/runtime/subscriptions.js +30 -0
- package/.test-dist/src/shared/scene/frame.js +34 -0
- package/.test-dist/src/shared/scene/sceneLayoutModel.js +202 -0
- package/.test-dist/tests/run.js +116 -0
- package/CHANGELOG.md +14 -0
- package/dist/index.d.mts +390 -367
- package/dist/index.d.ts +390 -367
- package/dist/index.js +5138 -4927
- package/dist/index.mjs +1149 -1977
- package/dist/tracer-PO7CRBYY.mjs +1016 -0
- package/package.json +2 -2
- package/src/extensions/{background.ts → background/BackgroundTool.ts} +33 -50
- package/src/extensions/background/index.ts +1 -0
- package/src/extensions/{dieline.ts → dieline/DielineTool.ts} +14 -218
- package/src/extensions/dieline/commands.ts +109 -0
- package/src/extensions/dieline/config.ts +106 -0
- package/src/extensions/dieline/index.ts +5 -0
- package/src/extensions/dieline/model.ts +1 -0
- package/src/extensions/dieline/renderer.ts +1 -0
- package/src/extensions/{feature.ts → feature/FeatureTool.ts} +27 -21
- package/src/extensions/feature/index.ts +1 -0
- package/src/extensions/{film.ts → film/FilmTool.ts} +36 -48
- package/src/extensions/film/index.ts +1 -0
- package/src/extensions/{image.ts → image/ImageTool.ts} +123 -402
- package/src/extensions/image/commands.ts +176 -0
- package/src/extensions/image/config.ts +128 -0
- package/src/extensions/image/index.ts +5 -0
- package/src/extensions/image/model.ts +1 -0
- package/src/extensions/image/renderer.ts +1 -0
- package/src/extensions/{mirror.ts → mirror/MirrorTool.ts} +1 -1
- package/src/extensions/mirror/index.ts +1 -0
- package/src/extensions/{ruler.ts → ruler/RulerTool.ts} +4 -5
- package/src/extensions/ruler/index.ts +1 -0
- package/src/extensions/sceneLayout.ts +1 -140
- package/src/extensions/sceneLayoutModel.ts +1 -364
- package/src/extensions/{size.ts → size/SizeTool.ts} +7 -6
- package/src/extensions/size/index.ts +1 -0
- package/src/extensions/{white-ink.ts → white-ink/WhiteInkTool.ts} +130 -317
- package/src/extensions/white-ink/commands.ts +157 -0
- package/src/extensions/white-ink/config.ts +30 -0
- package/src/extensions/white-ink/index.ts +5 -0
- package/src/extensions/white-ink/model.ts +1 -0
- package/src/extensions/white-ink/renderer.ts +1 -0
- package/src/services/SceneLayoutService.ts +139 -0
- package/src/services/index.ts +1 -0
- package/src/shared/constants/layers.ts +23 -0
- package/src/shared/imaging/sourceSizeCache.ts +103 -0
- package/src/shared/index.ts +6 -0
- package/src/shared/runtime/sessionState.ts +105 -0
- package/src/shared/runtime/subscriptions.ts +45 -0
- package/src/shared/scene/frame.ts +46 -0
- package/src/shared/scene/sceneLayoutModel.ts +367 -0
- package/tests/run.ts +146 -0
|
@@ -2,8 +2,6 @@ import {
|
|
|
2
2
|
Extension,
|
|
3
3
|
ExtensionContext,
|
|
4
4
|
ContributionPointIds,
|
|
5
|
-
CommandContribution,
|
|
6
|
-
ConfigurationContribution,
|
|
7
5
|
ConfigurationService,
|
|
8
6
|
ToolSessionService,
|
|
9
7
|
WorkbenchService,
|
|
@@ -16,15 +14,36 @@ import {
|
|
|
16
14
|
Point,
|
|
17
15
|
controlsUtils,
|
|
18
16
|
} from "fabric";
|
|
19
|
-
import { CanvasService, RenderLayoutRect, RenderObjectSpec } from "
|
|
20
|
-
import { isDielineShape, normalizeShapeStyle } from "
|
|
21
|
-
import type { DielineShape, DielineShapeStyle } from "
|
|
22
|
-
import { generateDielinePath, getPathBounds } from "
|
|
17
|
+
import { CanvasService, RenderLayoutRect, RenderObjectSpec } from "../../services";
|
|
18
|
+
import { isDielineShape, normalizeShapeStyle } from "../dielineShape";
|
|
19
|
+
import type { DielineShape, DielineShapeStyle } from "../dielineShape";
|
|
20
|
+
import { generateDielinePath, getPathBounds } from "../geometry";
|
|
23
21
|
import {
|
|
24
22
|
buildSceneGeometry,
|
|
25
23
|
computeSceneLayout,
|
|
26
24
|
readSizeState,
|
|
27
|
-
} from "
|
|
25
|
+
} from "../../shared/scene/sceneLayoutModel";
|
|
26
|
+
import {
|
|
27
|
+
type FrameRect,
|
|
28
|
+
resolveCutFrameRect,
|
|
29
|
+
toLayoutSceneRect as toSceneLayoutRect,
|
|
30
|
+
} from "../../shared/scene/frame";
|
|
31
|
+
import {
|
|
32
|
+
createSourceSizeCache,
|
|
33
|
+
getCoverScale as getCoverScaleFromRect,
|
|
34
|
+
type SourceSize,
|
|
35
|
+
} from "../../shared/imaging/sourceSizeCache";
|
|
36
|
+
import { SubscriptionBag } from "../../shared/runtime/subscriptions";
|
|
37
|
+
import {
|
|
38
|
+
applyCommittedSnapshot,
|
|
39
|
+
runDeferredConfigUpdate,
|
|
40
|
+
} from "../../shared/runtime/sessionState";
|
|
41
|
+
import {
|
|
42
|
+
IMAGE_OBJECT_LAYER_ID,
|
|
43
|
+
IMAGE_OVERLAY_LAYER_ID,
|
|
44
|
+
} from "../../shared/constants/layers";
|
|
45
|
+
import { createImageCommands } from "./commands";
|
|
46
|
+
import { createImageConfigurations } from "./config";
|
|
28
47
|
|
|
29
48
|
export interface ImageItem {
|
|
30
49
|
id: string;
|
|
@@ -38,18 +57,6 @@ export interface ImageItem {
|
|
|
38
57
|
committedUrl?: string;
|
|
39
58
|
}
|
|
40
59
|
|
|
41
|
-
interface FrameRect {
|
|
42
|
-
left: number;
|
|
43
|
-
top: number;
|
|
44
|
-
width: number;
|
|
45
|
-
height: number;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
interface SourceSize {
|
|
49
|
-
width: number;
|
|
50
|
-
height: number;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
60
|
interface RenderImageState {
|
|
54
61
|
src: string;
|
|
55
62
|
left: number;
|
|
@@ -125,8 +132,6 @@ interface ExportUserCroppedImageResult {
|
|
|
125
132
|
imageIds: string[];
|
|
126
133
|
}
|
|
127
134
|
|
|
128
|
-
const IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
129
|
-
const IMAGE_OVERLAY_LAYER_ID = "image-overlay";
|
|
130
135
|
type ImageControlCapability = "rotate" | "scale" | "flipX" | "flipY";
|
|
131
136
|
|
|
132
137
|
interface ImageControlDescriptor {
|
|
@@ -178,7 +183,9 @@ export class ImageTool implements Extension {
|
|
|
178
183
|
private workingItems: ImageItem[] = [];
|
|
179
184
|
private hasWorkingChanges = false;
|
|
180
185
|
private loadResolvers: Map<string, () => void> = new Map();
|
|
181
|
-
private
|
|
186
|
+
private sourceSizeCache = createSourceSizeCache((src) =>
|
|
187
|
+
this.loadImageSize(src),
|
|
188
|
+
);
|
|
182
189
|
private canvasService?: CanvasService;
|
|
183
190
|
private context?: ExtensionContext;
|
|
184
191
|
private isUpdatingConfig = false;
|
|
@@ -193,10 +200,12 @@ export class ImageTool implements Extension {
|
|
|
193
200
|
private imageSpecs: RenderObjectSpec[] = [];
|
|
194
201
|
private overlaySpecs: RenderObjectSpec[] = [];
|
|
195
202
|
private renderProducerDisposable?: { dispose: () => void };
|
|
203
|
+
private readonly subscriptions = new SubscriptionBag();
|
|
196
204
|
private imageControlsByCapabilityKey: Map<string, Record<string, Control>> =
|
|
197
205
|
new Map();
|
|
198
206
|
|
|
199
207
|
activate(context: ExtensionContext) {
|
|
208
|
+
this.subscriptions.disposeAll();
|
|
200
209
|
this.context = context;
|
|
201
210
|
this.canvasService = context.services.get<CanvasService>("CanvasService");
|
|
202
211
|
if (!this.canvasService) {
|
|
@@ -239,48 +248,63 @@ export class ImageTool implements Extension {
|
|
|
239
248
|
{ priority: 300 },
|
|
240
249
|
);
|
|
241
250
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
251
|
+
this.subscriptions.on(context.eventBus, "tool:activated", this.onToolActivated);
|
|
252
|
+
this.subscriptions.on(context.eventBus, "object:modified", this.onObjectModified);
|
|
253
|
+
this.subscriptions.on(
|
|
254
|
+
context.eventBus,
|
|
255
|
+
"selection:created",
|
|
256
|
+
this.onSelectionChanged,
|
|
257
|
+
);
|
|
258
|
+
this.subscriptions.on(
|
|
259
|
+
context.eventBus,
|
|
260
|
+
"selection:updated",
|
|
261
|
+
this.onSelectionChanged,
|
|
262
|
+
);
|
|
263
|
+
this.subscriptions.on(
|
|
264
|
+
context.eventBus,
|
|
265
|
+
"selection:cleared",
|
|
266
|
+
this.onSelectionCleared,
|
|
267
|
+
);
|
|
268
|
+
this.subscriptions.on(
|
|
269
|
+
context.eventBus,
|
|
270
|
+
"scene:layout:change",
|
|
271
|
+
this.onSceneLayoutChanged,
|
|
272
|
+
);
|
|
273
|
+
this.subscriptions.on(
|
|
274
|
+
context.eventBus,
|
|
275
|
+
"scene:geometry:change",
|
|
276
|
+
this.onSceneGeometryChanged,
|
|
277
|
+
);
|
|
249
278
|
|
|
250
279
|
const configService = context.services.get<ConfigurationService>(
|
|
251
280
|
"ConfigurationService",
|
|
252
281
|
);
|
|
253
282
|
if (configService) {
|
|
254
|
-
this.items
|
|
255
|
-
configService.get("image.items", []) || [],
|
|
256
|
-
);
|
|
257
|
-
this.workingItems = this.cloneItems(this.items);
|
|
258
|
-
this.hasWorkingChanges = false;
|
|
283
|
+
this.applyCommittedItems(configService.get("image.items", []) || []);
|
|
259
284
|
|
|
260
|
-
|
|
261
|
-
|
|
285
|
+
this.subscriptions.onConfigChange(
|
|
286
|
+
configService,
|
|
287
|
+
(e: { key: string; value: any }) => {
|
|
288
|
+
if (this.isUpdatingConfig) return;
|
|
262
289
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.hasWorkingChanges = false;
|
|
290
|
+
if (e.key === "image.items") {
|
|
291
|
+
this.applyCommittedItems(e.value || []);
|
|
292
|
+
this.updateImages();
|
|
293
|
+
return;
|
|
268
294
|
}
|
|
269
|
-
this.updateImages();
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
295
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
296
|
+
if (
|
|
297
|
+
e.key.startsWith("size.") ||
|
|
298
|
+
e.key.startsWith("image.frame.") ||
|
|
299
|
+
e.key.startsWith("image.control.")
|
|
300
|
+
) {
|
|
301
|
+
if (e.key.startsWith("image.control.")) {
|
|
302
|
+
this.imageControlsByCapabilityKey.clear();
|
|
303
|
+
}
|
|
304
|
+
this.updateImages();
|
|
280
305
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
});
|
|
306
|
+
},
|
|
307
|
+
);
|
|
284
308
|
}
|
|
285
309
|
|
|
286
310
|
const toolSessionService =
|
|
@@ -294,18 +318,13 @@ export class ImageTool implements Extension {
|
|
|
294
318
|
}
|
|
295
319
|
|
|
296
320
|
deactivate(context: ExtensionContext) {
|
|
297
|
-
|
|
298
|
-
context.eventBus.off("object:modified", this.onObjectModified);
|
|
299
|
-
context.eventBus.off("selection:created", this.onSelectionChanged);
|
|
300
|
-
context.eventBus.off("selection:updated", this.onSelectionChanged);
|
|
301
|
-
context.eventBus.off("selection:cleared", this.onSelectionCleared);
|
|
302
|
-
context.eventBus.off("scene:layout:change", this.onSceneLayoutChanged);
|
|
303
|
-
context.eventBus.off("scene:geometry:change", this.onSceneGeometryChanged);
|
|
321
|
+
this.subscriptions.disposeAll();
|
|
304
322
|
this.dirtyTrackerDisposable?.dispose();
|
|
305
323
|
this.dirtyTrackerDisposable = undefined;
|
|
306
324
|
this.cropShapeHatchPattern = undefined;
|
|
307
325
|
this.cropShapeHatchPatternColor = undefined;
|
|
308
326
|
this.cropShapeHatchPatternKey = undefined;
|
|
327
|
+
this.sourceSizeCache.clear();
|
|
309
328
|
this.imageSpecs = [];
|
|
310
329
|
this.overlaySpecs = [];
|
|
311
330
|
this.imageControlsByCapabilityKey.clear();
|
|
@@ -547,287 +566,8 @@ export class ImageTool implements Extension {
|
|
|
547
566
|
},
|
|
548
567
|
},
|
|
549
568
|
],
|
|
550
|
-
[ContributionPointIds.CONFIGURATIONS]:
|
|
551
|
-
|
|
552
|
-
id: "image.items",
|
|
553
|
-
type: "array",
|
|
554
|
-
label: "Images",
|
|
555
|
-
default: [],
|
|
556
|
-
},
|
|
557
|
-
{
|
|
558
|
-
id: "image.debug",
|
|
559
|
-
type: "boolean",
|
|
560
|
-
label: "Image Debug Log",
|
|
561
|
-
default: false,
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
id: "image.control.cornerSize",
|
|
565
|
-
type: "number",
|
|
566
|
-
label: "Image Control Corner Size",
|
|
567
|
-
min: 4,
|
|
568
|
-
max: 64,
|
|
569
|
-
step: 1,
|
|
570
|
-
default: 14,
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
id: "image.control.touchCornerSize",
|
|
574
|
-
type: "number",
|
|
575
|
-
label: "Image Control Touch Corner Size",
|
|
576
|
-
min: 8,
|
|
577
|
-
max: 96,
|
|
578
|
-
step: 1,
|
|
579
|
-
default: 24,
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
id: "image.control.cornerStyle",
|
|
583
|
-
type: "select",
|
|
584
|
-
label: "Image Control Corner Style",
|
|
585
|
-
options: ["circle", "rect"],
|
|
586
|
-
default: "circle",
|
|
587
|
-
},
|
|
588
|
-
{
|
|
589
|
-
id: "image.control.cornerColor",
|
|
590
|
-
type: "color",
|
|
591
|
-
label: "Image Control Corner Color",
|
|
592
|
-
default: "#ffffff",
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
id: "image.control.cornerStrokeColor",
|
|
596
|
-
type: "color",
|
|
597
|
-
label: "Image Control Corner Stroke Color",
|
|
598
|
-
default: "#1677ff",
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
id: "image.control.transparentCorners",
|
|
602
|
-
type: "boolean",
|
|
603
|
-
label: "Image Control Transparent Corners",
|
|
604
|
-
default: false,
|
|
605
|
-
},
|
|
606
|
-
{
|
|
607
|
-
id: "image.control.borderColor",
|
|
608
|
-
type: "color",
|
|
609
|
-
label: "Image Control Border Color",
|
|
610
|
-
default: "#1677ff",
|
|
611
|
-
},
|
|
612
|
-
{
|
|
613
|
-
id: "image.control.borderScaleFactor",
|
|
614
|
-
type: "number",
|
|
615
|
-
label: "Image Control Border Width",
|
|
616
|
-
min: 0.5,
|
|
617
|
-
max: 8,
|
|
618
|
-
step: 0.1,
|
|
619
|
-
default: 1.5,
|
|
620
|
-
},
|
|
621
|
-
{
|
|
622
|
-
id: "image.control.padding",
|
|
623
|
-
type: "number",
|
|
624
|
-
label: "Image Control Padding",
|
|
625
|
-
min: 0,
|
|
626
|
-
max: 64,
|
|
627
|
-
step: 1,
|
|
628
|
-
default: 0,
|
|
629
|
-
},
|
|
630
|
-
{
|
|
631
|
-
id: "image.frame.strokeColor",
|
|
632
|
-
type: "color",
|
|
633
|
-
label: "Image Frame Stroke Color",
|
|
634
|
-
default: "#808080",
|
|
635
|
-
},
|
|
636
|
-
{
|
|
637
|
-
id: "image.frame.strokeWidth",
|
|
638
|
-
type: "number",
|
|
639
|
-
label: "Image Frame Stroke Width",
|
|
640
|
-
min: 0,
|
|
641
|
-
max: 20,
|
|
642
|
-
step: 0.5,
|
|
643
|
-
default: 2,
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
id: "image.frame.strokeStyle",
|
|
647
|
-
type: "select",
|
|
648
|
-
label: "Image Frame Stroke Style",
|
|
649
|
-
options: ["solid", "dashed", "hidden"],
|
|
650
|
-
default: "dashed",
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
id: "image.frame.dashLength",
|
|
654
|
-
type: "number",
|
|
655
|
-
label: "Image Frame Dash Length",
|
|
656
|
-
min: 1,
|
|
657
|
-
max: 40,
|
|
658
|
-
step: 1,
|
|
659
|
-
default: 8,
|
|
660
|
-
},
|
|
661
|
-
{
|
|
662
|
-
id: "image.frame.innerBackground",
|
|
663
|
-
type: "color",
|
|
664
|
-
label: "Image Frame Inner Background",
|
|
665
|
-
default: "rgba(0,0,0,0)",
|
|
666
|
-
},
|
|
667
|
-
{
|
|
668
|
-
id: "image.frame.outerBackground",
|
|
669
|
-
type: "color",
|
|
670
|
-
label: "Image Frame Outer Background",
|
|
671
|
-
default: "#f5f5f5",
|
|
672
|
-
},
|
|
673
|
-
] as ConfigurationContribution[],
|
|
674
|
-
[ContributionPointIds.COMMANDS]: [
|
|
675
|
-
{
|
|
676
|
-
command: "addImage",
|
|
677
|
-
title: "Add Image",
|
|
678
|
-
handler: async (url: string, options?: Partial<ImageItem>) => {
|
|
679
|
-
const result = await this.upsertImageEntry(url, {
|
|
680
|
-
mode: "add",
|
|
681
|
-
addOptions: options,
|
|
682
|
-
});
|
|
683
|
-
return result.id;
|
|
684
|
-
},
|
|
685
|
-
},
|
|
686
|
-
{
|
|
687
|
-
command: "upsertImage",
|
|
688
|
-
title: "Upsert Image",
|
|
689
|
-
handler: async (url: string, options: UpsertImageOptions = {}) => {
|
|
690
|
-
return await this.upsertImageEntry(url, options);
|
|
691
|
-
},
|
|
692
|
-
},
|
|
693
|
-
{
|
|
694
|
-
command: "getWorkingImages",
|
|
695
|
-
title: "Get Working Images",
|
|
696
|
-
handler: () => {
|
|
697
|
-
return this.cloneItems(this.workingItems);
|
|
698
|
-
},
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
command: "setWorkingImage",
|
|
702
|
-
title: "Set Working Image",
|
|
703
|
-
handler: (id: string, updates: Partial<ImageItem>) => {
|
|
704
|
-
this.updateImageInWorking(id, updates);
|
|
705
|
-
},
|
|
706
|
-
},
|
|
707
|
-
{
|
|
708
|
-
command: "resetWorkingImages",
|
|
709
|
-
title: "Reset Working Images",
|
|
710
|
-
handler: () => {
|
|
711
|
-
this.workingItems = this.cloneItems(this.items);
|
|
712
|
-
this.hasWorkingChanges = false;
|
|
713
|
-
this.updateImages();
|
|
714
|
-
this.emitWorkingChange();
|
|
715
|
-
},
|
|
716
|
-
},
|
|
717
|
-
{
|
|
718
|
-
command: "completeImages",
|
|
719
|
-
title: "Complete Images",
|
|
720
|
-
handler: async () => {
|
|
721
|
-
return await this.commitWorkingImagesAsCropped();
|
|
722
|
-
},
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
command: "exportUserCroppedImage",
|
|
726
|
-
title: "Export User Cropped Image",
|
|
727
|
-
handler: async (options: ExportUserCroppedImageOptions = {}) => {
|
|
728
|
-
return await this.exportUserCroppedImage(options);
|
|
729
|
-
},
|
|
730
|
-
},
|
|
731
|
-
{
|
|
732
|
-
command: "fitImageToArea",
|
|
733
|
-
title: "Fit Image to Area",
|
|
734
|
-
handler: async (
|
|
735
|
-
id: string,
|
|
736
|
-
area: {
|
|
737
|
-
width: number;
|
|
738
|
-
height: number;
|
|
739
|
-
left?: number;
|
|
740
|
-
top?: number;
|
|
741
|
-
},
|
|
742
|
-
) => {
|
|
743
|
-
await this.fitImageToArea(id, area);
|
|
744
|
-
},
|
|
745
|
-
},
|
|
746
|
-
{
|
|
747
|
-
command: "fitImageToDefaultArea",
|
|
748
|
-
title: "Fit Image to Default Area",
|
|
749
|
-
handler: async (id: string) => {
|
|
750
|
-
await this.fitImageToDefaultArea(id);
|
|
751
|
-
},
|
|
752
|
-
},
|
|
753
|
-
{
|
|
754
|
-
command: "focusImage",
|
|
755
|
-
title: "Focus Image",
|
|
756
|
-
handler: (
|
|
757
|
-
id: string | null,
|
|
758
|
-
options: { syncCanvasSelection?: boolean } = {},
|
|
759
|
-
) => {
|
|
760
|
-
return this.setImageFocus(id, options);
|
|
761
|
-
},
|
|
762
|
-
},
|
|
763
|
-
{
|
|
764
|
-
command: "removeImage",
|
|
765
|
-
title: "Remove Image",
|
|
766
|
-
handler: (id: string) => {
|
|
767
|
-
const removed = this.items.find((item) => item.id === id);
|
|
768
|
-
const next = this.items.filter((item) => item.id !== id);
|
|
769
|
-
if (next.length !== this.items.length) {
|
|
770
|
-
this.purgeSourceSizeCacheForItem(removed);
|
|
771
|
-
if (this.focusedImageId === id) {
|
|
772
|
-
this.setImageFocus(null, {
|
|
773
|
-
syncCanvasSelection: true,
|
|
774
|
-
skipRender: true,
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
this.updateConfig(next);
|
|
778
|
-
}
|
|
779
|
-
},
|
|
780
|
-
},
|
|
781
|
-
{
|
|
782
|
-
command: "updateImage",
|
|
783
|
-
title: "Update Image",
|
|
784
|
-
handler: async (
|
|
785
|
-
id: string,
|
|
786
|
-
updates: Partial<ImageItem>,
|
|
787
|
-
options: UpdateImageOptions = {},
|
|
788
|
-
) => {
|
|
789
|
-
await this.updateImage(id, updates, options);
|
|
790
|
-
},
|
|
791
|
-
},
|
|
792
|
-
{
|
|
793
|
-
command: "clearImages",
|
|
794
|
-
title: "Clear Images",
|
|
795
|
-
handler: () => {
|
|
796
|
-
this.sourceSizeBySrc.clear();
|
|
797
|
-
this.setImageFocus(null, {
|
|
798
|
-
syncCanvasSelection: true,
|
|
799
|
-
skipRender: true,
|
|
800
|
-
});
|
|
801
|
-
this.updateConfig([]);
|
|
802
|
-
},
|
|
803
|
-
},
|
|
804
|
-
{
|
|
805
|
-
command: "bringToFront",
|
|
806
|
-
title: "Bring Image to Front",
|
|
807
|
-
handler: (id: string) => {
|
|
808
|
-
const index = this.items.findIndex((item) => item.id === id);
|
|
809
|
-
if (index !== -1 && index < this.items.length - 1) {
|
|
810
|
-
const next = [...this.items];
|
|
811
|
-
const [item] = next.splice(index, 1);
|
|
812
|
-
next.push(item);
|
|
813
|
-
this.updateConfig(next);
|
|
814
|
-
}
|
|
815
|
-
},
|
|
816
|
-
},
|
|
817
|
-
{
|
|
818
|
-
command: "sendToBack",
|
|
819
|
-
title: "Send Image to Back",
|
|
820
|
-
handler: (id: string) => {
|
|
821
|
-
const index = this.items.findIndex((item) => item.id === id);
|
|
822
|
-
if (index > 0) {
|
|
823
|
-
const next = [...this.items];
|
|
824
|
-
const [item] = next.splice(index, 1);
|
|
825
|
-
next.unshift(item);
|
|
826
|
-
this.updateConfig(next);
|
|
827
|
-
}
|
|
828
|
-
},
|
|
829
|
-
},
|
|
830
|
-
] as CommandContribution[],
|
|
569
|
+
[ContributionPointIds.CONFIGURATIONS]: createImageConfigurations(),
|
|
570
|
+
[ContributionPointIds.COMMANDS]: createImageCommands(this),
|
|
831
571
|
};
|
|
832
572
|
}
|
|
833
573
|
|
|
@@ -1000,53 +740,46 @@ export class ImageTool implements Extension {
|
|
|
1000
740
|
return (configService.get(key, fallback) as T) ?? fallback;
|
|
1001
741
|
}
|
|
1002
742
|
|
|
743
|
+
private applyCommittedItems(nextItems: ImageItem[]) {
|
|
744
|
+
const session = {
|
|
745
|
+
committed: this.items,
|
|
746
|
+
working: this.workingItems,
|
|
747
|
+
hasWorkingChanges: this.hasWorkingChanges,
|
|
748
|
+
};
|
|
749
|
+
applyCommittedSnapshot(session, this.normalizeItems(nextItems), {
|
|
750
|
+
clone: (items) => this.cloneItems(items),
|
|
751
|
+
toolActive: this.isToolActive,
|
|
752
|
+
preserveDirtyWorking: true,
|
|
753
|
+
});
|
|
754
|
+
this.items = session.committed;
|
|
755
|
+
this.workingItems = session.working;
|
|
756
|
+
this.hasWorkingChanges = session.hasWorkingChanges;
|
|
757
|
+
}
|
|
758
|
+
|
|
1003
759
|
private updateConfig(newItems: ImageItem[], skipCanvasUpdate = false) {
|
|
1004
760
|
if (!this.context) return;
|
|
761
|
+
this.applyCommittedItems(newItems);
|
|
762
|
+
runDeferredConfigUpdate(
|
|
763
|
+
this,
|
|
764
|
+
() => {
|
|
765
|
+
const configService = this.context?.services.get<ConfigurationService>(
|
|
766
|
+
"ConfigurationService",
|
|
767
|
+
);
|
|
768
|
+
configService?.update("image.items", this.items);
|
|
1005
769
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
const configService = this.context.services.get<ConfigurationService>(
|
|
1014
|
-
"ConfigurationService",
|
|
770
|
+
if (!skipCanvasUpdate) {
|
|
771
|
+
this.updateImages();
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
50,
|
|
1015
775
|
);
|
|
1016
|
-
configService?.update("image.items", this.items);
|
|
1017
|
-
|
|
1018
|
-
if (!skipCanvasUpdate) {
|
|
1019
|
-
this.updateImages();
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
setTimeout(() => {
|
|
1023
|
-
this.isUpdatingConfig = false;
|
|
1024
|
-
}, 50);
|
|
1025
776
|
}
|
|
1026
777
|
|
|
1027
778
|
private getFrameRect(): FrameRect {
|
|
1028
|
-
if (!this.canvasService) {
|
|
1029
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1030
|
-
}
|
|
1031
779
|
const configService = this.context?.services.get<ConfigurationService>(
|
|
1032
780
|
"ConfigurationService",
|
|
1033
781
|
);
|
|
1034
|
-
|
|
1035
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
const sizeState = readSizeState(configService);
|
|
1039
|
-
const layout = computeSceneLayout(this.canvasService, sizeState);
|
|
1040
|
-
if (!layout) {
|
|
1041
|
-
return { left: 0, top: 0, width: 0, height: 0 };
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
return this.canvasService.toSceneRect({
|
|
1045
|
-
left: layout.cutRect.left,
|
|
1046
|
-
top: layout.cutRect.top,
|
|
1047
|
-
width: layout.cutRect.width,
|
|
1048
|
-
height: layout.cutRect.height,
|
|
1049
|
-
});
|
|
782
|
+
return resolveCutFrameRect(this.canvasService, configService);
|
|
1050
783
|
}
|
|
1051
784
|
|
|
1052
785
|
private getFrameRectScreen(frame?: FrameRect): FrameRect {
|
|
@@ -1057,13 +790,7 @@ export class ImageTool implements Extension {
|
|
|
1057
790
|
}
|
|
1058
791
|
|
|
1059
792
|
private toLayoutSceneRect(rect: FrameRect): RenderLayoutRect {
|
|
1060
|
-
return
|
|
1061
|
-
left: rect.left,
|
|
1062
|
-
top: rect.top,
|
|
1063
|
-
width: rect.width,
|
|
1064
|
-
height: rect.height,
|
|
1065
|
-
space: "scene",
|
|
1066
|
-
};
|
|
793
|
+
return toSceneLayoutRect(rect);
|
|
1067
794
|
}
|
|
1068
795
|
|
|
1069
796
|
private async resolveDefaultFitArea(): Promise<DielineFitArea | null> {
|
|
@@ -1126,26 +853,26 @@ export class ImageTool implements Extension {
|
|
|
1126
853
|
const sources = [item.url, item.sourceUrl, item.committedUrl].filter(
|
|
1127
854
|
(value): value is string => typeof value === "string" && value.length > 0,
|
|
1128
855
|
);
|
|
1129
|
-
sources.forEach((src) => this.
|
|
856
|
+
sources.forEach((src) => this.sourceSizeCache.deleteSourceSize(src));
|
|
1130
857
|
}
|
|
1131
858
|
|
|
1132
859
|
private rememberSourceSize(src: string, obj: any) {
|
|
1133
860
|
const width = Number(obj?.width || 0);
|
|
1134
861
|
const height = Number(obj?.height || 0);
|
|
1135
862
|
if (src && width > 0 && height > 0) {
|
|
1136
|
-
this.
|
|
863
|
+
this.sourceSizeCache.rememberSourceSize(src, { width, height });
|
|
1137
864
|
}
|
|
1138
865
|
}
|
|
1139
866
|
|
|
1140
867
|
private getSourceSize(src: string, obj?: any): SourceSize {
|
|
1141
|
-
const cached = src ? this.
|
|
868
|
+
const cached = src ? this.sourceSizeCache.getSourceSize(src) : undefined;
|
|
1142
869
|
if (cached) return cached;
|
|
1143
870
|
|
|
1144
871
|
const width = Number(obj?.width || 0);
|
|
1145
872
|
const height = Number(obj?.height || 0);
|
|
1146
873
|
if (src && width > 0 && height > 0) {
|
|
1147
874
|
const size = { width, height };
|
|
1148
|
-
this.
|
|
875
|
+
this.sourceSizeCache.rememberSourceSize(src, size);
|
|
1149
876
|
return size;
|
|
1150
877
|
}
|
|
1151
878
|
|
|
@@ -1153,10 +880,10 @@ export class ImageTool implements Extension {
|
|
|
1153
880
|
}
|
|
1154
881
|
|
|
1155
882
|
private async ensureSourceSize(src: string): Promise<SourceSize | null> {
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
if (cached) return cached;
|
|
883
|
+
return this.sourceSizeCache.ensureImageSize(src);
|
|
884
|
+
}
|
|
1159
885
|
|
|
886
|
+
private async loadImageSize(src: string): Promise<SourceSize | null> {
|
|
1160
887
|
try {
|
|
1161
888
|
const image = await FabricImage.fromURL(src, {
|
|
1162
889
|
crossOrigin: "anonymous",
|
|
@@ -1164,9 +891,7 @@ export class ImageTool implements Extension {
|
|
|
1164
891
|
const width = Number(image?.width || 0);
|
|
1165
892
|
const height = Number(image?.height || 0);
|
|
1166
893
|
if (width > 0 && height > 0) {
|
|
1167
|
-
|
|
1168
|
-
this.sourceSizeBySrc.set(src, size);
|
|
1169
|
-
return size;
|
|
894
|
+
return { width, height };
|
|
1170
895
|
}
|
|
1171
896
|
} catch (error) {
|
|
1172
897
|
this.debug("image:size:load-failed", {
|
|
@@ -1179,11 +904,7 @@ export class ImageTool implements Extension {
|
|
|
1179
904
|
}
|
|
1180
905
|
|
|
1181
906
|
private getCoverScale(frame: FrameRect, size: SourceSize): number {
|
|
1182
|
-
|
|
1183
|
-
const sh = Math.max(1, size.height);
|
|
1184
|
-
const fw = Math.max(1, frame.width);
|
|
1185
|
-
const fh = Math.max(1, frame.height);
|
|
1186
|
-
return Math.max(fw / sw, fh / sh);
|
|
907
|
+
return getCoverScaleFromRect(frame, size);
|
|
1187
908
|
}
|
|
1188
909
|
|
|
1189
910
|
private getFrameVisualConfig(): FrameVisualConfig {
|
|
@@ -2114,7 +1835,7 @@ export class ImageTool implements Extension {
|
|
|
2114
1835
|
}),
|
|
2115
1836
|
);
|
|
2116
1837
|
if (previousCommitted && previousCommitted !== url) {
|
|
2117
|
-
this.
|
|
1838
|
+
this.sourceSizeCache.deleteSourceSize(previousCommitted);
|
|
2118
1839
|
}
|
|
2119
1840
|
}
|
|
2120
1841
|
|