@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.
@@ -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 absoluteFeatures = (features || []).map((f) => ({
254
- ...f,
255
- x: f.x,
256
- y: f.y,
257
- width: (f.width || 0) * scale,
258
- height: (f.height || 0) * scale,
259
- radius: (f.radius || 0) * scale,
260
- }));
261
- const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
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 absoluteFeatures = scaleFeatures(state, scale);
39
- const cutFeatures = absoluteFeatures.filter((feature) => !feature.skipCut);
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.forEach((feature, index) => {
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 = (0, geometry_1.resolveFeaturePosition)(feature, geometry);
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.startsWith("ruler.")) {
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,
@@ -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
@@ -1,5 +1,11 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 6.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - bugfix
8
+
3
9
  ## 6.2.0
4
10
 
5
11
  ### Minor Changes
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;