feat(canvas): remap per-boundary stroke styles when a path is edited
Instead of discarding stroke segments after a vertex edit, strokeSegmentsForEditedPath projects each stored edge index onto the edited path's edges and rebuilds every segment's geometry from the edges it now owns, so boolean results keep their per-operand colors, widths, and dash styles through the path editor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import test from "node:test";
|
||||
|
||||
import { applyEditedPathToNode, applyEditedPathToNodes, editablePathForNode, isEditablePathNode, normalizedPathDataToSvg } from "../src/ui/pages/CanvasWorkspace/canvas/editablePath.ts";
|
||||
import { applyEditedPathToNode, applyEditedPathToNodes, editablePathForNode, isEditablePathNode, normalizedPathDataToSvg, strokeSegmentsForEditedPath } from "../src/ui/pages/CanvasWorkspace/canvas/editablePath.ts";
|
||||
import { createBooleanShapeGroupNode } from "../src/ui/pages/CanvasWorkspace/canvas/shapeNode.ts";
|
||||
|
||||
const shapeNode = {
|
||||
@@ -42,18 +42,44 @@ test("persists an edited shape path and expands its canvas bounds without moving
|
||||
assert.match(editablePathForNode(edited), /^M 3 10/);
|
||||
});
|
||||
|
||||
test("discards stale per-boundary stroke geometry after editing a boolean result path", () => {
|
||||
test("preserves per-boundary colors and widths while editing a boolean result path", () => {
|
||||
const booleanResult = {
|
||||
...shapeNode,
|
||||
content: JSON.stringify({
|
||||
kind: "path",
|
||||
pathData: [1, 0, 0, 2, 1, 0, 2, 1, 1, 2, 0, 1, 11],
|
||||
strokeSegments: [{ pathData: [1, 0, 0, 2, 1, 0], strokeColor: "#7C3AED", strokeWidth: 4, strokeStyle: "solid", opacity: 1 }]
|
||||
strokeSegments: [
|
||||
{ pathData: [1, 0, 0, 2, 1, 0, 2, 1, 1], edgeIndexes: [0, 1], strokeColor: "#111111", strokeWidth: 3, strokeStyle: "solid", opacity: 1 },
|
||||
{ pathData: [1, 1, 1, 2, 0, 1, 2, 0, 0], edgeIndexes: [2, 3], strokeColor: "#7C3AED", strokeWidth: 5, strokeStyle: "solid", opacity: 1 }
|
||||
]
|
||||
})
|
||||
};
|
||||
const edited = applyEditedPathToNode(booleanResult, [1, 0, 0, 2, 100, 0, 2, 50, 60, 11]);
|
||||
const edited = applyEditedPathToNode(booleanResult, [1, 0, 0, 2, 100, 5, 2, 95, 60, 2, 0, 55, 2, 0, 0, 11]);
|
||||
const options = JSON.parse(edited.content);
|
||||
|
||||
assert.equal(JSON.parse(edited.content).strokeSegments, undefined);
|
||||
assert.deepEqual(new Set(options.strokeSegments.map((segment) => segment.strokeColor)), new Set(["#111111", "#7C3AED"]));
|
||||
assert.deepEqual(new Set(options.strokeSegments.map((segment) => segment.strokeWidth)), new Set([3, 5]));
|
||||
assert.ok(options.strokeSegments.every((segment) => segment.edgeIndexes.length > 0));
|
||||
assert.notDeepEqual(options.strokeSegments[0].pathData, JSON.parse(booleanResult.content).strokeSegments[0].pathData);
|
||||
});
|
||||
|
||||
test("keeps the closing stroke group when the path editor normalizes the edge count", () => {
|
||||
const editedPath = [1, 0, 0];
|
||||
for (let index = 1; index <= 13; index += 1) editedPath.push(2, index, index % 2);
|
||||
const styles = [
|
||||
{ edgeIndexes: [0, 1, 2, 3], strokeColor: "#111111" },
|
||||
{ edgeIndexes: [4, 5, 6, 7], strokeColor: "#7C3AED" },
|
||||
{ edgeIndexes: [8, 9, 10, 11], strokeColor: "#0EA5E9" },
|
||||
{ edgeIndexes: [12, 13, 14, 15], strokeColor: "#EF4444" }
|
||||
].map((style) => ({ ...style, pathData: [1, 0, 0, 2, 1, 0], strokeWidth: 3, strokeStyle: "solid", opacity: 1 }));
|
||||
const remapped = strokeSegmentsForEditedPath(editedPath, styles);
|
||||
|
||||
assert.equal(remapped.length, 4);
|
||||
assert.deepEqual(new Set(remapped.map((segment) => segment.strokeColor)), new Set(styles.map((segment) => segment.strokeColor)));
|
||||
assert.deepEqual(
|
||||
new Set(remapped.flatMap((segment) => segment.edgeIndexes)),
|
||||
new Set(Array.from({ length: 13 }, (_, index) => index))
|
||||
);
|
||||
});
|
||||
|
||||
test("keeps unmarked Brush strokes outside the vertex editor", () => {
|
||||
|
||||
Reference in New Issue
Block a user