@pooder/kit 6.2.0 → 6.2.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/dieline/DielineTool.js +22 -9
- package/.test-dist/src/extensions/dieline/renderBuilder.js +28 -12
- package/.test-dist/src/extensions/feature/FeatureTool.js +20 -3
- package/.test-dist/src/extensions/featureCoordinates.js +21 -0
- package/.test-dist/src/extensions/featurePlacement.js +46 -0
- package/.test-dist/src/extensions/ruler/RulerTool.js +24 -1
- package/.test-dist/tests/run.js +25 -0
- package/CHANGELOG.md +6 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +357 -197
- package/dist/index.mjs +357 -197
- package/package.json +1 -1
- package/src/extensions/dieline/DielineTool.ts +29 -9
- package/src/extensions/dieline/renderBuilder.ts +39 -13
- package/src/extensions/feature/FeatureTool.ts +23 -3
- package/src/extensions/featureCoordinates.ts +35 -0
- package/src/extensions/featurePlacement.ts +118 -0
- package/src/extensions/ruler/RulerTool.ts +24 -2
- package/tests/run.ts +37 -0
|
@@ -11,6 +11,7 @@ const commands_1 = require("./commands");
|
|
|
11
11
|
const config_1 = require("./config");
|
|
12
12
|
const model_1 = require("./model");
|
|
13
13
|
const renderBuilder_1 = require("./renderBuilder");
|
|
14
|
+
const featurePlacement_1 = require("../featurePlacement");
|
|
14
15
|
class DielineTool {
|
|
15
16
|
constructor(options) {
|
|
16
17
|
this.id = "pooder.kit.dieline";
|
|
@@ -250,15 +251,27 @@ class DielineTool {
|
|
|
250
251
|
const visualRadius = radius * scale;
|
|
251
252
|
const visualOffset = (cutW - sceneLayout.trimRect.width) / 2;
|
|
252
253
|
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
254
|
+
const placements = (0, featurePlacement_1.resolveFeaturePlacements)(features || [], {
|
|
255
|
+
shape,
|
|
256
|
+
shapeStyle,
|
|
257
|
+
pathData,
|
|
258
|
+
customSourceWidthPx: this.state.customSourceWidthPx,
|
|
259
|
+
customSourceHeightPx: this.state.customSourceHeightPx,
|
|
260
|
+
canvasWidth: canvasW,
|
|
261
|
+
canvasHeight: canvasH,
|
|
262
|
+
x: cx,
|
|
263
|
+
y: cy,
|
|
264
|
+
width: sceneLayout.trimRect.width,
|
|
265
|
+
height: sceneLayout.trimRect.height,
|
|
266
|
+
radius: visualRadius,
|
|
267
|
+
scale,
|
|
268
|
+
});
|
|
269
|
+
const cutFeatures = (0, featurePlacement_1.projectPlacedFeatures)(placements.filter((placement) => !placement.feature.skipCut), {
|
|
270
|
+
x: cx,
|
|
271
|
+
y: cy,
|
|
272
|
+
width: cutW,
|
|
273
|
+
height: cutH,
|
|
274
|
+
}, scale);
|
|
262
275
|
const generatedPathData = (0, geometry_1.generateDielinePath)({
|
|
263
276
|
shape,
|
|
264
277
|
width: cutW,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildDielineRenderBundle = buildDielineRenderBundle;
|
|
4
4
|
const geometry_1 = require("../geometry");
|
|
5
|
+
const featurePlacement_1 = require("../featurePlacement");
|
|
5
6
|
const layers_1 = require("../../shared/constants/layers");
|
|
6
7
|
const DEFAULT_IDS = {
|
|
7
8
|
inside: "dieline.inside",
|
|
@@ -11,16 +12,6 @@ const DEFAULT_IDS = {
|
|
|
11
12
|
clip: "dieline.clip.image",
|
|
12
13
|
clipSource: "dieline.effect.clip-path",
|
|
13
14
|
};
|
|
14
|
-
function scaleFeatures(state, scale) {
|
|
15
|
-
return (state.features || []).map((feature) => ({
|
|
16
|
-
...feature,
|
|
17
|
-
x: feature.x,
|
|
18
|
-
y: feature.y,
|
|
19
|
-
width: (feature.width || 0) * scale,
|
|
20
|
-
height: (feature.height || 0) * scale,
|
|
21
|
-
radius: (feature.radius || 0) * scale,
|
|
22
|
-
}));
|
|
23
|
-
}
|
|
24
15
|
function buildDielineRenderBundle(options) {
|
|
25
16
|
const ids = { ...DEFAULT_IDS, ...(options.ids || {}) };
|
|
26
17
|
const { state, sceneLayout, canvasWidth, canvasHeight, hasImages, createHatchPattern, includeImageClipEffect = true, clipTargetPassIds = [layers_1.IMAGE_OBJECT_LAYER_ID], clipVisibility, } = options;
|
|
@@ -35,8 +26,33 @@ function buildDielineRenderBundle(options) {
|
|
|
35
26
|
const cutH = sceneLayout.cutRect.height;
|
|
36
27
|
const visualOffset = (cutW - visualWidth) / 2;
|
|
37
28
|
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
38
|
-
const
|
|
39
|
-
|
|
29
|
+
const placements = (0, featurePlacement_1.resolveFeaturePlacements)(state.features || [], {
|
|
30
|
+
shape,
|
|
31
|
+
shapeStyle,
|
|
32
|
+
pathData: state.pathData,
|
|
33
|
+
customSourceWidthPx: state.customSourceWidthPx,
|
|
34
|
+
customSourceHeightPx: state.customSourceHeightPx,
|
|
35
|
+
canvasWidth,
|
|
36
|
+
canvasHeight,
|
|
37
|
+
x: cx,
|
|
38
|
+
y: cy,
|
|
39
|
+
width: visualWidth,
|
|
40
|
+
height: visualHeight,
|
|
41
|
+
radius: visualRadius,
|
|
42
|
+
scale,
|
|
43
|
+
});
|
|
44
|
+
const absoluteFeatures = (0, featurePlacement_1.projectPlacedFeatures)(placements, {
|
|
45
|
+
x: cx,
|
|
46
|
+
y: cy,
|
|
47
|
+
width: visualWidth,
|
|
48
|
+
height: visualHeight,
|
|
49
|
+
}, scale);
|
|
50
|
+
const cutFeatures = (0, featurePlacement_1.projectPlacedFeatures)(placements.filter((placement) => !placement.feature.skipCut), {
|
|
51
|
+
x: cx,
|
|
52
|
+
y: cy,
|
|
53
|
+
width: cutW,
|
|
54
|
+
height: cutH,
|
|
55
|
+
}, scale);
|
|
40
56
|
const common = {
|
|
41
57
|
shape,
|
|
42
58
|
shapeStyle,
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FeatureTool = void 0;
|
|
4
4
|
const core_1 = require("@pooder/core");
|
|
5
5
|
const fabric_1 = require("fabric");
|
|
6
|
-
const geometry_1 = require("../geometry");
|
|
7
6
|
const constraints_1 = require("../constraints");
|
|
8
7
|
const featureComplete_1 = require("../featureComplete");
|
|
8
|
+
const featurePlacement_1 = require("../featurePlacement");
|
|
9
9
|
const sceneLayoutModel_1 = require("../../shared/scene/sceneLayoutModel");
|
|
10
10
|
const layers_1 = require("../../shared/constants/layers");
|
|
11
11
|
const subscriptions_1 = require("../../shared/runtime/subscriptions");
|
|
@@ -726,9 +726,26 @@ class FeatureTool {
|
|
|
726
726
|
}
|
|
727
727
|
const groups = new Map();
|
|
728
728
|
const singles = [];
|
|
729
|
-
this.workingFeatures
|
|
729
|
+
const placements = (0, featurePlacement_1.resolveFeaturePlacements)(this.workingFeatures, {
|
|
730
|
+
shape: this.currentGeometry.shape,
|
|
731
|
+
shapeStyle: this.currentGeometry.shapeStyle,
|
|
732
|
+
pathData: this.currentGeometry.pathData,
|
|
733
|
+
customSourceWidthPx: this.currentGeometry.customSourceWidthPx,
|
|
734
|
+
customSourceHeightPx: this.currentGeometry.customSourceHeightPx,
|
|
735
|
+
x: this.currentGeometry.x,
|
|
736
|
+
y: this.currentGeometry.y,
|
|
737
|
+
width: this.currentGeometry.width,
|
|
738
|
+
height: this.currentGeometry.height,
|
|
739
|
+
radius: this.currentGeometry.radius,
|
|
740
|
+
scale: this.currentGeometry.scale || 1,
|
|
741
|
+
});
|
|
742
|
+
placements.forEach((placement, index) => {
|
|
743
|
+
const feature = placement.feature;
|
|
730
744
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
731
|
-
const position =
|
|
745
|
+
const position = {
|
|
746
|
+
x: placement.centerX,
|
|
747
|
+
y: placement.centerY,
|
|
748
|
+
};
|
|
732
749
|
const scale = geometry.scale || 1;
|
|
733
750
|
const marker = {
|
|
734
751
|
feature,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveFeaturePosition = resolveFeaturePosition;
|
|
4
|
+
exports.normalizePointInGeometry = normalizePointInGeometry;
|
|
5
|
+
function resolveFeaturePosition(feature, geometry) {
|
|
6
|
+
const { x, y, width, height } = geometry;
|
|
7
|
+
const left = x - width / 2;
|
|
8
|
+
const top = y - height / 2;
|
|
9
|
+
return {
|
|
10
|
+
x: left + feature.x * width,
|
|
11
|
+
y: top + feature.y * height,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function normalizePointInGeometry(point, geometry) {
|
|
15
|
+
const left = geometry.x - geometry.width / 2;
|
|
16
|
+
const top = geometry.y - geometry.height / 2;
|
|
17
|
+
return {
|
|
18
|
+
x: geometry.width > 0 ? (point.x - left) / geometry.width : 0.5,
|
|
19
|
+
y: geometry.height > 0 ? (point.y - top) / geometry.height : 0.5,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveFeaturePlacements = resolveFeaturePlacements;
|
|
4
|
+
exports.projectPlacedFeatures = projectPlacedFeatures;
|
|
5
|
+
const constraints_1 = require("./constraints");
|
|
6
|
+
const featureCoordinates_1 = require("./featureCoordinates");
|
|
7
|
+
function scaleFeatureForRender(feature, scale, x, y) {
|
|
8
|
+
return {
|
|
9
|
+
...feature,
|
|
10
|
+
x,
|
|
11
|
+
y,
|
|
12
|
+
width: feature.width !== undefined ? feature.width * scale : undefined,
|
|
13
|
+
height: feature.height !== undefined ? feature.height * scale : undefined,
|
|
14
|
+
radius: feature.radius !== undefined ? feature.radius * scale : undefined,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function resolveFeaturePlacements(features, geometry) {
|
|
18
|
+
const dielineWidth = geometry.scale > 0 ? geometry.width / geometry.scale : geometry.width;
|
|
19
|
+
const dielineHeight = geometry.scale > 0 ? geometry.height / geometry.scale : geometry.height;
|
|
20
|
+
return (features || []).map((feature) => {
|
|
21
|
+
const activeConstraints = feature.constraints?.filter((constraint) => !constraint.validateOnly);
|
|
22
|
+
const constrained = constraints_1.ConstraintRegistry.apply(feature.x, feature.y, feature, {
|
|
23
|
+
dielineWidth,
|
|
24
|
+
dielineHeight,
|
|
25
|
+
geometry,
|
|
26
|
+
}, activeConstraints);
|
|
27
|
+
const center = (0, featureCoordinates_1.resolveFeaturePosition)({
|
|
28
|
+
...feature,
|
|
29
|
+
x: constrained.x,
|
|
30
|
+
y: constrained.y,
|
|
31
|
+
}, geometry);
|
|
32
|
+
return {
|
|
33
|
+
feature,
|
|
34
|
+
normalizedX: constrained.x,
|
|
35
|
+
normalizedY: constrained.y,
|
|
36
|
+
centerX: center.x,
|
|
37
|
+
centerY: center.y,
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function projectPlacedFeatures(placements, geometry, scale) {
|
|
42
|
+
return placements.map((placement) => {
|
|
43
|
+
const normalized = (0, featureCoordinates_1.normalizePointInGeometry)({ x: placement.centerX, y: placement.centerY }, geometry);
|
|
44
|
+
return scaleFeatureForRender(placement.feature, scale, normalized.x, normalized.y);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -13,6 +13,7 @@ const DEFAULT_FONT_SIZE = 10;
|
|
|
13
13
|
const DEFAULT_BACKGROUND_COLOR = "#f0f0f0";
|
|
14
14
|
const DEFAULT_TEXT_COLOR = "#333333";
|
|
15
15
|
const DEFAULT_LINE_COLOR = "#999999";
|
|
16
|
+
const RULER_DEBUG_KEY = "ruler.debug";
|
|
16
17
|
const RULER_THICKNESS_MIN = 10;
|
|
17
18
|
const RULER_THICKNESS_MAX = 100;
|
|
18
19
|
const RULER_GAP_MIN = 0;
|
|
@@ -31,6 +32,7 @@ class RulerTool {
|
|
|
31
32
|
this.textColor = DEFAULT_TEXT_COLOR;
|
|
32
33
|
this.lineColor = DEFAULT_LINE_COLOR;
|
|
33
34
|
this.fontSize = DEFAULT_FONT_SIZE;
|
|
35
|
+
this.debugEnabled = false;
|
|
34
36
|
this.renderSeq = 0;
|
|
35
37
|
this.numericProps = new Set(["thickness", "gap", "fontSize"]);
|
|
36
38
|
this.specs = [];
|
|
@@ -72,7 +74,15 @@ class RulerTool {
|
|
|
72
74
|
this.syncConfig(configService);
|
|
73
75
|
configService.onAnyChange((e) => {
|
|
74
76
|
let shouldUpdate = false;
|
|
75
|
-
if (e.key
|
|
77
|
+
if (e.key === RULER_DEBUG_KEY) {
|
|
78
|
+
this.debugEnabled = e.value === true;
|
|
79
|
+
this.log("config:update", {
|
|
80
|
+
key: e.key,
|
|
81
|
+
raw: e.value,
|
|
82
|
+
normalized: this.debugEnabled,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else if (e.key.startsWith("ruler.")) {
|
|
76
86
|
const prop = e.key.split(".")[1];
|
|
77
87
|
if (prop && prop in this) {
|
|
78
88
|
if (this.numericProps.has(prop)) {
|
|
@@ -158,6 +168,12 @@ class RulerTool {
|
|
|
158
168
|
max: RULER_FONT_SIZE_MAX,
|
|
159
169
|
default: DEFAULT_FONT_SIZE,
|
|
160
170
|
},
|
|
171
|
+
{
|
|
172
|
+
id: RULER_DEBUG_KEY,
|
|
173
|
+
type: "boolean",
|
|
174
|
+
label: "Ruler Debug Log",
|
|
175
|
+
default: false,
|
|
176
|
+
},
|
|
161
177
|
],
|
|
162
178
|
[core_1.ContributionPointIds.COMMANDS]: [
|
|
163
179
|
{
|
|
@@ -187,7 +203,12 @@ class RulerTool {
|
|
|
187
203
|
],
|
|
188
204
|
};
|
|
189
205
|
}
|
|
206
|
+
isDebugEnabled() {
|
|
207
|
+
return this.debugEnabled;
|
|
208
|
+
}
|
|
190
209
|
log(step, payload) {
|
|
210
|
+
if (!this.isDebugEnabled())
|
|
211
|
+
return;
|
|
191
212
|
if (payload) {
|
|
192
213
|
console.debug(`[RulerTool] ${step}`, payload);
|
|
193
214
|
return;
|
|
@@ -201,6 +222,8 @@ class RulerTool {
|
|
|
201
222
|
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
202
223
|
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
203
224
|
this.fontSize = this.toFiniteNumber(configService.get("ruler.fontSize", this.fontSize), DEFAULT_FONT_SIZE);
|
|
225
|
+
this.debugEnabled =
|
|
226
|
+
configService.get(RULER_DEBUG_KEY, this.debugEnabled) === true;
|
|
204
227
|
this.log("config:loaded", {
|
|
205
228
|
thickness: this.thickness,
|
|
206
229
|
gap: this.gap,
|
package/.test-dist/tests/run.js
CHANGED
|
@@ -11,6 +11,7 @@ const commands_2 = require("../src/extensions/white-ink/commands");
|
|
|
11
11
|
const config_2 = require("../src/extensions/white-ink/config");
|
|
12
12
|
const commands_3 = require("../src/extensions/dieline/commands");
|
|
13
13
|
const config_3 = require("../src/extensions/dieline/config");
|
|
14
|
+
const featureCoordinates_1 = require("../src/extensions/featureCoordinates");
|
|
14
15
|
function assert(condition, message) {
|
|
15
16
|
if (!condition)
|
|
16
17
|
throw new Error(message);
|
|
@@ -91,6 +92,29 @@ function testEdgeScale() {
|
|
|
91
92
|
assert(width === 140, `expected width 140, got ${width}`);
|
|
92
93
|
assert(height === 80, `expected height 80, got ${height}`);
|
|
93
94
|
}
|
|
95
|
+
function testFeaturePlacementProjection() {
|
|
96
|
+
const trimGeometry = {
|
|
97
|
+
x: 100,
|
|
98
|
+
y: 120,
|
|
99
|
+
width: 120,
|
|
100
|
+
height: 180,
|
|
101
|
+
};
|
|
102
|
+
const cutGeometry = {
|
|
103
|
+
x: 100,
|
|
104
|
+
y: 120,
|
|
105
|
+
width: 150,
|
|
106
|
+
height: 210,
|
|
107
|
+
};
|
|
108
|
+
const trimFeature = {
|
|
109
|
+
x: 0.82,
|
|
110
|
+
y: 0.68,
|
|
111
|
+
};
|
|
112
|
+
const trimCenter = (0, featureCoordinates_1.resolveFeaturePosition)(trimFeature, trimGeometry);
|
|
113
|
+
const cutFeature = (0, featureCoordinates_1.normalizePointInGeometry)(trimCenter, cutGeometry);
|
|
114
|
+
const cutCenter = (0, featureCoordinates_1.resolveFeaturePosition)(cutFeature, cutGeometry);
|
|
115
|
+
assert(Math.abs(trimCenter.x - cutCenter.x) < 1e-6, `expected projected feature x to stay fixed, got ${trimCenter.x} vs ${cutCenter.x}`);
|
|
116
|
+
assert(Math.abs(trimCenter.y - cutCenter.y) < 1e-6, `expected projected feature y to stay fixed, got ${trimCenter.y} vs ${cutCenter.y}`);
|
|
117
|
+
}
|
|
94
118
|
function testVisibilityDsl() {
|
|
95
119
|
const layers = new Map([
|
|
96
120
|
["ruler-overlay", { exists: true, objectCount: 2 }],
|
|
@@ -259,6 +283,7 @@ function main() {
|
|
|
259
283
|
testBridgeSelection();
|
|
260
284
|
testMaskOps();
|
|
261
285
|
testEdgeScale();
|
|
286
|
+
testFeaturePlacementProjection();
|
|
262
287
|
testVisibilityDsl();
|
|
263
288
|
testContributionCompatibility();
|
|
264
289
|
console.log("ok");
|
package/CHANGELOG.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -907,6 +907,7 @@ declare class RulerTool implements Extension {
|
|
|
907
907
|
private textColor;
|
|
908
908
|
private lineColor;
|
|
909
909
|
private fontSize;
|
|
910
|
+
private debugEnabled;
|
|
910
911
|
private renderSeq;
|
|
911
912
|
private readonly numericProps;
|
|
912
913
|
private specs;
|
|
@@ -928,6 +929,7 @@ declare class RulerTool implements Extension {
|
|
|
928
929
|
[ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
|
|
929
930
|
[ContributionPointIds.COMMANDS]: CommandContribution[];
|
|
930
931
|
};
|
|
932
|
+
private isDebugEnabled;
|
|
931
933
|
private log;
|
|
932
934
|
private syncConfig;
|
|
933
935
|
private toFiniteNumber;
|
package/dist/index.d.ts
CHANGED
|
@@ -907,6 +907,7 @@ declare class RulerTool implements Extension {
|
|
|
907
907
|
private textColor;
|
|
908
908
|
private lineColor;
|
|
909
909
|
private fontSize;
|
|
910
|
+
private debugEnabled;
|
|
910
911
|
private renderSeq;
|
|
911
912
|
private readonly numericProps;
|
|
912
913
|
private specs;
|
|
@@ -928,6 +929,7 @@ declare class RulerTool implements Extension {
|
|
|
928
929
|
[ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
|
|
929
930
|
[ContributionPointIds.COMMANDS]: CommandContribution[];
|
|
930
931
|
};
|
|
932
|
+
private isDebugEnabled;
|
|
931
933
|
private log;
|
|
932
934
|
private syncConfig;
|
|
933
935
|
private toFiniteNumber;
|