From e72e2bf176b3003493bfff00377184e0442e8a6f Mon Sep 17 00:00:00 2001 From: Elena Torro Date: Tue, 10 Mar 2026 16:51:42 +0100 Subject: [PATCH 1/2] :bug: Fix stroke closing on outer strokes on paths --- .../get-file-outer-stroke-overlap-seam.json | 769 ++++++++++++++++++ .../ui/render-wasm-specs/shapes.spec.js | 28 + ...verlapping-shapes-with-outer-strokes-1.png | Bin 0 -> 50573 bytes render-wasm/src/shapes/paths.rs | 21 +- render-wasm/src/shapes/strokes.rs | 20 +- 5 files changed, 819 insertions(+), 19 deletions(-) create mode 100644 frontend/playwright/data/render-wasm/get-file-outer-stroke-overlap-seam.json create mode 100644 frontend/playwright/ui/render-wasm-specs/shapes.spec.js-snapshots/Correct-stroke-closing-at-self-intersection-of-overlapping-shapes-with-outer-strokes-1.png diff --git a/frontend/playwright/data/render-wasm/get-file-outer-stroke-overlap-seam.json b/frontend/playwright/data/render-wasm/get-file-outer-stroke-overlap-seam.json new file mode 100644 index 0000000000..2f2904618a --- /dev/null +++ b/frontend/playwright/data/render-wasm/get-file-outer-stroke-overlap-seam.json @@ -0,0 +1,769 @@ +{ + "~:features": { + "~#set": [ + "fdata/path-data", + "plugins/runtime", + "design-tokens/v1", + "variants/v1", + "layout/grid", + "styles/v2", + "fdata/pointer-map", + "fdata/objects-map", + "render-wasm/v1", + "components/v2", + "fdata/shape-data-type" + ] + }, + "~:team-id": "~uaaa00001-0001-0001-8007-000000000003", + "~:permissions": { + "~:type": "~:membership", + "~:is-owner": true, + "~:is-admin": true, + "~:can-edit": true, + "~:can-read": true, + "~:is-logged": true + }, + "~:has-media-trimmed": false, + "~:comment-thread-seqn": 0, + "~:name": "outer-stroke-overlap-seam", + "~:revn": 1, + "~:modified-at": "~m1771855365377", + "~:vern": 0, + "~:id": "~uaaa00001-0001-0001-8007-000000000001", + "~:is-shared": false, + "~:migrations": { + "~#ordered-set": [ + "legacy-2", + "legacy-3", + "legacy-5", + "legacy-6", + "legacy-7", + "legacy-8", + "legacy-9", + "legacy-10", + "legacy-11", + "legacy-12", + "legacy-13", + "legacy-14", + "legacy-16", + "legacy-17", + "legacy-18", + "legacy-19", + "legacy-25", + "legacy-26", + "legacy-27", + "legacy-28", + "legacy-29", + "legacy-31", + "legacy-32", + "legacy-33", + "legacy-34", + "legacy-36", + "legacy-37", + "legacy-38", + "legacy-39", + "legacy-40", + "legacy-41", + "legacy-42", + "legacy-43", + "legacy-44", + "legacy-45", + "legacy-46", + "legacy-47", + "legacy-48", + "legacy-49", + "legacy-50", + "legacy-51", + "legacy-52", + "legacy-53", + "legacy-54", + "legacy-55", + "legacy-56", + "legacy-57", + "legacy-59", + "legacy-62", + "legacy-65", + "legacy-66", + "legacy-67", + "0001-remove-tokens-from-groups", + "0002-normalize-bool-content-v2", + "0002-clean-shape-interactions", + "0003-fix-root-shape", + "0003-convert-path-content-v2", + "0005-deprecate-image-type", + "0006-fix-old-texts-fills", + "0008-fix-library-colors-v4", + "0009-clean-library-colors", + "0009-add-partial-text-touched-flags", + "0010-fix-swap-slots-pointing-non-existent-shapes", + "0011-fix-invalid-text-touched-flags", + "0012-fix-position-data", + "0013-fix-component-path", + "0013-clear-invalid-strokes-and-fills", + "0014-fix-tokens-lib-duplicate-ids", + "0014-clear-components-nil-objects", + "0015-fix-text-attrs-blank-strings", + "0015-clean-shadow-color", + "0016-copy-fills-from-position-data-to-text-node" + ] + }, + "~:version": 67, + "~:project-id": "~uaaa00001-0001-0001-8007-000000000004", + "~:created-at": "~m1771591980210", + "~:backend": "legacy-db", + "~:data": { + "~:pages": [ + "~uaaa00001-0001-0001-8007-000000000002" + ], + "~:pages-index": { + "~uaaa00001-0001-0001-8007-000000000002": { + "~:objects": { + "~u00000000-0000-0000-0000-000000000000": { + "~#shape": { + "~:y": 0, + "~:hide-fill-on-export": false, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "Root Frame", + "~:width": 0.01, + "~:type": "~:frame", + "~:points": [ + {"~#point": {"~:x": 0, "~:y": 0}}, + {"~#point": {"~:x": 0.01, "~:y": 0}}, + {"~#point": {"~:x": 0.01, "~:y": 0.01}}, + {"~#point": {"~:x": 0, "~:y": 0.01}} + ], + "~:r2": 0, + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:r3": 0, + "~:r1": 0, + "~:id": "~u00000000-0000-0000-0000-000000000000", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 0, + "~:proportion": 1, + "~:r4": 0, + "~:selrect": {"~#rect": {"~:x": 0, "~:y": 0, "~:width": 0.01, "~:height": 0.01, "~:x1": 0, "~:y1": 0, "~:x2": 0.01, "~:y2": 0.01}}, + "~:fills": [{"~:fill-color": "#FFFFFF", "~:fill-opacity": 1}], + "~:flip-x": null, + "~:height": 0.01, + "~:flip-y": null, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b146992e4ab5"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146992e4ab5": { + "~#shape": { + "~:y": -237, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg", + "~:width": 86.215, + "~:type": "~:group", + "~:svg-attrs": {"~:width": "86.215", "~:height": "50"}, + "~:points": [ + {"~#point": {"~:x": 1079, "~:y": -237}}, + {"~#point": {"~:x": 1165.215, "~:y": -237}}, + {"~#point": {"~:x": 1165.215, "~:y": -187}}, + {"~#point": {"~:x": 1079, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146992e4ab5", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1079, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1079, "~:y": -237, "~:width": 86.215, "~:height": 50, "~:x1": 1079, "~:y1": -237, "~:x2": 1165.215, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": false, + "~:height": 50, + "~:flip-y": false, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b146992f0a36"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146992f0a36": { + "~#shape": { + "~:y": -237, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg-g", + "~:width": 86.215, + "~:type": "~:group", + "~:svg-attrs": {}, + "~:points": [ + {"~#point": {"~:x": 1079, "~:y": -237}}, + {"~#point": {"~:x": 1165.215, "~:y": -237}}, + {"~#point": {"~:x": 1165.215, "~:y": -187}}, + {"~#point": {"~:x": 1079, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992e4ab5", + "~:svg-viewbox": {"~#rect": {"~:x": -0.000034146222333220067, "~:y": -0.000003814697265625, "~:width": 86.21503414622225, "~:height": 50.000003814697266, "~:x1": 0, "~:y1": 0, "~:x2": 86.215, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1079, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1079, "~:y": -237, "~:width": 86.215, "~:height": 50, "~:x1": 1079, "~:y1": -237, "~:x2": 1165.215, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": 50, + "~:flip-y": null, + "~:shapes": [ + "~u8f89d4e8-0efd-804d-8007-b146992fbb39", + "~u8f89d4e8-0efd-804d-8007-b146992fde2e", + "~u8f89d4e8-0efd-804d-8007-b14699303fd3", + "~u8f89d4e8-0efd-804d-8007-b1469930583b", + "~u8f89d4e8-0efd-804d-8007-b146993083e1", + "~u8f89d4e8-0efd-804d-8007-b1469930dc39", + "~u8f89d4e8-0efd-804d-8007-b146993141e4", + "~u8f89d4e8-0efd-804d-8007-b146993141e5", + "~u8f89d4e8-0efd-804d-8007-b1469931a9d0", + "~u8f89d4e8-0efd-804d-8007-b1469931a9d1" + ] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146992fbb39": { + "~#shape": { + "~:y": null, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAADGGIhEq6p9wxpukESrqn3DcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:className": "fills"}, + "~:points": [ + {"~#point": {"~:x": 1112.4849232616168, "~:y": -237.00000381469727}}, + {"~#point": {"~:x": 1131.7299204883832, "~:y": -237.00000381469727}}, + {"~#point": {"~:x": 1131.7299204883832, "~:y": -187}}, + {"~#point": {"~:x": 1112.4849232616168, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146992fbb39", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 33.484923261616885, "~:y": -0.000003814697265625, "~:width": 19.24499722676625, "~:height": 50.000003814697266, "~:x1": 33.484923261616885, "~:y1": -0.000003814697265625, "~:x2": 52.72992048838314, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1112.4849232616168, "~:y": -237.00000381469727, "~:width": 19.24499722676625, "~:height": 50.000003814697266, "~:x1": 1112.4849232616168, "~:y1": -237.00000381469727, "~:x2": 1131.729920488383, "~:y2": -187}}, + "~:fills": [{"~:fill-color": "#70d19d", "~:fill-opacity": 1}], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b146992fde2e": { + "~#shape": { + "~:y": -237, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg-g", + "~:width": 19.244997226766372, + "~:type": "~:group", + "~:svg-attrs": {"~:className": "strokes"}, + "~:points": [ + {"~#point": {"~:x": 1112.4849232616168, "~:y": -237.00000381469727}}, + {"~#point": {"~:x": 1131.7299204883832, "~:y": -237.00000381469727}}, + {"~#point": {"~:x": 1131.7299204883832, "~:y": -187}}, + {"~#point": {"~:x": 1112.4849232616168, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146992fde2e", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 33.484923261616814, "~:y": -0.000003814697265625, "~:width": 19.244997226766372, "~:height": 50.000003814697266, "~:x1": 0, "~:y1": 0, "~:x2": 86.215, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1112.4849232616168, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1112.4849232616168, "~:y": -237.00000381469727, "~:width": 19.244997226766372, "~:height": 50.000003814697266, "~:x1": 1112.4849232616168, "~:y1": -237.00000381469727, "~:x2": 1131.7299204883832, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": 50, + "~:flip-y": null, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b146992fde2f"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146992fde2f": { + "~#shape": { + "~:y": null, + "~:stroke-cap-start": "~:round", + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAADGGIhEq6p9wxpukESrqn3DcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:fill": "none", "~:style": {"~:fill": "none"}, "~:strokeLinecap": "round", "~:strokeMiterlimit": "10", "~:className": "stroke-shape"}, + "~:points": [ + {"~#point": {"~:x": 1112.4849232616168, "~:y": -237.00000381469727}}, + {"~#point": {"~:x": 1131.7299204883832, "~:y": -237.00000381469727}}, + {"~#point": {"~:x": 1131.7299204883832, "~:y": -187}}, + {"~#point": {"~:x": 1112.4849232616168, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:stroke-cap-end": "~:round", + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:stroke-linecap": "~:round", + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146992fde2f", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992fde2e", + "~:svg-viewbox": {"~#rect": {"~:x": 33.484923261616885, "~:y": -0.000003814697265625, "~:width": 19.24499722676625, "~:height": 50.000003814697266, "~:x1": 33.484923261616885, "~:y1": -0.000003814697265625, "~:x2": 52.72992048838314, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1112.4849232616168, "~:y": -237.00000381469727, "~:width": 19.24499722676625, "~:height": 50.000003814697266, "~:x1": 1112.4849232616168, "~:y1": -237.00000381469727, "~:x2": 1131.729920488383, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b14699303fd3": { + "~#shape": { + "~:y": null, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAABBBpFEthF7w+aGlUSc+ELDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:className": "fills"}, + "~:points": [ + {"~#point": {"~:x": 1122.107421875, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1165.2148778962223, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1165.2148778962223, "~:y": -187}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b14699303fd3", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 43.107421875, "~:y": 19.66923798963697, "~:width": 43.107456021222276, "~:height": 30.33076201036303, "~:x1": 43.107421875, "~:y1": 19.66923798963697, "~:x2": 86.21487789622228, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1122.107421875, "~:y": -217.33076201036303, "~:width": 43.107456021222276, "~:height": 30.33076201036303, "~:x1": 1122.107421875, "~:y1": -217.33076201036303, "~:x2": 1165.2148778962223, "~:y2": -187}}, + "~:fills": [{"~:fill-color": "#3c49ff", "~:fill-opacity": 1}], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b1469930583b": { + "~#shape": { + "~:y": -217.33076201036303, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg-g", + "~:width": 43.10745602122233, + "~:type": "~:group", + "~:svg-attrs": {"~:className": "strokes"}, + "~:points": [ + {"~#point": {"~:x": 1122.107421875, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1165.2148778962223, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1165.2148778962223, "~:y": -187}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b1469930583b", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 43.107421875, "~:y": 19.66923798963697, "~:width": 43.10745602122233, "~:height": 30.33076201036303, "~:x1": 0, "~:y1": 0, "~:x2": 86.215, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1122.107421875, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1122.107421875, "~:y": -217.33076201036303, "~:width": 43.10745602122233, "~:height": 30.33076201036303, "~:x1": 1122.107421875, "~:y1": -217.33076201036303, "~:x2": 1165.2148778962223, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": 30.33076201036303, + "~:flip-y": null, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b146993083e0"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146993083e0": { + "~#shape": { + "~:y": null, + "~:stroke-cap-start": "~:round", + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAABBBpFEthF7w+aGlUSc+ELDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:fill": "none", "~:style": {"~:fill": "none"}, "~:strokeLinecap": "round", "~:strokeMiterlimit": "10", "~:className": "stroke-shape"}, + "~:points": [ + {"~#point": {"~:x": 1122.107421875, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1165.2148778962223, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1165.2148778962223, "~:y": -187}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:stroke-cap-end": "~:round", + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:stroke-linecap": "~:round", + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146993083e0", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b1469930583b", + "~:svg-viewbox": {"~#rect": {"~:x": 43.107421875, "~:y": 19.66923798963697, "~:width": 43.107456021222276, "~:height": 30.33076201036303, "~:x1": 43.107421875, "~:y1": 19.66923798963697, "~:x2": 86.21487789622228, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1122.107421875, "~:y": -217.33076201036303, "~:width": 43.107456021222276, "~:height": 30.33076201036303, "~:x1": 1122.107421875, "~:y1": -217.33076201036303, "~:x2": 1165.2148778962223, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b146993083e1": { + "~#shape": { + "~:y": null, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAAD6/4JEnPhCw5+Ah0S2EXvDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:className": "fills"}, + "~:points": [ + {"~#point": {"~:x": 1078.9999658537777, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}}, + {"~#point": {"~:x": 1078.9999658537777, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146993083e1", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": -0.00003414622229014341, "~:y": 19.669237989636976, "~:width": 43.10745602122229, "~:height": 30.330762010363024, "~:x1": -0.00003414622229014341, "~:y1": 19.669237989636976, "~:x2": 43.107421875, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1078.9999658537777, "~:y": -217.33076201036303, "~:width": 43.10745602122229, "~:height": 30.330762010363024, "~:x1": 1078.9999658537777, "~:y1": -217.33076201036303, "~:x2": 1122.107421875, "~:y2": -187}}, + "~:fills": [{"~:fill-color": "#3c49ff", "~:fill-opacity": 1}], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b1469930dc39": { + "~#shape": { + "~:y": -217.33076201036303, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg-g", + "~:width": 43.10745602122233, + "~:type": "~:group", + "~:svg-attrs": {"~:className": "strokes"}, + "~:points": [ + {"~#point": {"~:x": 1078.9999658537777, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}}, + {"~#point": {"~:x": 1078.9999658537777, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b1469930dc39", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": -0.000034146222333220067, "~:y": 19.66923798963697, "~:width": 43.10745602122233, "~:height": 30.33076201036303, "~:x1": 0, "~:y1": 0, "~:x2": 86.215, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1079, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1078.9999658537777, "~:y": -217.33076201036303, "~:width": 43.10745602122233, "~:height": 30.33076201036303, "~:x1": 1078.9999658537777, "~:y1": -217.33076201036303, "~:x2": 1122.107421875, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": 30.33076201036303, + "~:flip-y": null, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b146993110ec"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146993110ec": { + "~#shape": { + "~:y": null, + "~:stroke-cap-start": "~:round", + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAAD6/4JEnPhCw5+Ah0S2EXvDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:fill": "none", "~:style": {"~:fill": "none"}, "~:strokeLinecap": "round", "~:strokeMiterlimit": "10", "~:className": "stroke-shape"}, + "~:points": [ + {"~#point": {"~:x": 1078.9999658537777, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -217.33076201036303}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}}, + {"~#point": {"~:x": 1078.9999658537777, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:stroke-cap-end": "~:round", + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:stroke-linecap": "~:round", + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146993110ec", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b1469930dc39", + "~:svg-viewbox": {"~#rect": {"~:x": -0.00003414622229014341, "~:y": 19.669237989636976, "~:width": 43.10745602122229, "~:height": 30.330762010363024, "~:x1": -0.00003414622229014341, "~:y1": 19.669237989636976, "~:x2": 43.107421875, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1078.9999658537777, "~:y": -217.33076201036303, "~:width": 43.10745602122229, "~:height": 30.330762010363024, "~:x1": 1078.9999658537777, "~:y1": -217.33076201036303, "~:x2": 1122.107421875, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b146993141e4": { + "~#shape": { + "~:y": null, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAAAgmoxEQb6Cw03qk0RQhmXDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:className": "fills"}, + "~:points": [ + {"~#point": {"~:x": 1122.107421875, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1149.9259006903171, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1149.9259006903171, "~:y": -187}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146993141e4", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 43.107421875, "~:y": 5.330620727377042, "~:width": 27.818478815317206, "~:height": 44.66937927262296, "~:x1": 43.107421875, "~:y1": 5.330620727377042, "~:x2": 70.9259006903172, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1122.107421875, "~:y": -231.66937927262296, "~:width": 27.818478815317206, "~:height": 44.66937927262296, "~:x1": 1122.107421875, "~:y1": -231.66937927262296, "~:x2": 1149.9259006903171, "~:y2": -187}}, + "~:fills": [{"~:fill-color": "#434cc2", "~:fill-opacity": 1}], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b146993141e5": { + "~#shape": { + "~:y": -231.66937927262296, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg-g", + "~:width": 27.81847881531712, + "~:type": "~:group", + "~:svg-attrs": {"~:className": "strokes"}, + "~:points": [ + {"~#point": {"~:x": 1122.107421875, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1149.9259006903171, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1149.9259006903171, "~:y": -187}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146993141e5", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 43.107421875, "~:y": 5.330620727377038, "~:width": 27.81847881531712, "~:height": 44.66937927262296, "~:x1": 0, "~:y1": 0, "~:x2": 86.215, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1122.107421875, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1122.107421875, "~:y": -231.66937927262296, "~:width": 27.81847881531712, "~:height": 44.66937927262296, "~:x1": 1122.107421875, "~:y1": -231.66937927262296, "~:x2": 1149.9259006903171, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": 44.66937927262296, + "~:flip-y": null, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b146993141e6"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b146993141e6": { + "~#shape": { + "~:y": null, + "~:stroke-cap-start": "~:round", + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAAAgmoxEQb6Cw03qk0RQhmXDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:fill": "none", "~:style": {"~:fill": "none"}, "~:strokeLinecap": "round", "~:strokeMiterlimit": "10", "~:className": "stroke-shape"}, + "~:points": [ + {"~#point": {"~:x": 1122.107421875, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1149.9259006903171, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1149.9259006903171, "~:y": -187}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:stroke-cap-end": "~:round", + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:stroke-linecap": "~:round", + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b146993141e6", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146993141e5", + "~:svg-viewbox": {"~#rect": {"~:x": 43.107421875, "~:y": 5.330620727377042, "~:width": 27.818478815317206, "~:height": 44.66937927262296, "~:x1": 43.107421875, "~:y1": 5.330620727377042, "~:x2": 70.9259006903172, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1122.107421875, "~:y": -231.66937927262296, "~:width": 27.818478815317206, "~:height": 44.66937927262296, "~:x1": 1122.107421875, "~:y1": -231.66937927262296, "~:x2": 1149.9259006903171, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b1469931a9d0": { + "~#shape": { + "~:y": null, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAACTnIREUIZlw8Dsi0RBvoLDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:className": "fills"}, + "~:points": [ + {"~#point": {"~:x": 1094.2889430596829, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}}, + {"~#point": {"~:x": 1094.2889430596829, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b1469931a9d0", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 15.28894305968281, "~:y": 5.330620727377026, "~:width": 27.818478815317192, "~:height": 44.669379272622976, "~:x1": 15.28894305968281, "~:y1": 5.330620727377026, "~:x2": 43.107421875, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1094.2889430596829, "~:y": -231.66937927262296, "~:width": 27.818478815317192, "~:height": 44.669379272622976, "~:x1": 1094.2889430596829, "~:y1": -231.66937927262296, "~:x2": 1122.107421875, "~:y2": -187}}, + "~:fills": [{"~:fill-color": "#434cc2", "~:fill-opacity": 1}], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + }, + "~u8f89d4e8-0efd-804d-8007-b1469931a9d1": { + "~#shape": { + "~:y": -231.66937927262296, + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:name": "svg-g", + "~:width": 27.81847881531712, + "~:type": "~:group", + "~:svg-attrs": {"~:className": "strokes"}, + "~:points": [ + {"~#point": {"~:x": 1094.2889430596829, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}}, + {"~#point": {"~:x": 1094.2889430596829, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b1469931a9d1", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b146992f0a36", + "~:svg-viewbox": {"~#rect": {"~:x": 15.288943059682879, "~:y": 5.330620727377038, "~:width": 27.81847881531712, "~:height": 44.66937927262296, "~:x1": 0, "~:y1": 0, "~:x2": 86.215, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 1094.2889430596829, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1094.2889430596829, "~:y": -231.66937927262296, "~:width": 27.81847881531712, "~:height": 44.66937927262296, "~:x1": 1094.2889430596829, "~:y1": -231.66937927262296, "~:x2": 1122.107421875, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": 44.66937927262296, + "~:flip-y": null, + "~:shapes": ["~u8f89d4e8-0efd-804d-8007-b1469931e08c"] + } + }, + "~u8f89d4e8-0efd-804d-8007-b1469931e08c": { + "~#shape": { + "~:y": null, + "~:stroke-cap-start": "~:round", + "~:transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:rotation": 0, + "~:content": {"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAABwQ4xEAAA7wwMAAACTnIREUIZlw8Dsi0RBvoLDcEOMRAAAO8M="}, + "~:name": "svg-path", + "~:width": null, + "~:type": "~:path", + "~:svg-attrs": {"~:fill": "none", "~:style": {"~:fill": "none"}, "~:strokeLinecap": "round", "~:strokeMiterlimit": "10", "~:className": "stroke-shape"}, + "~:points": [ + {"~#point": {"~:x": 1094.2889430596829, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -231.66937927262296}}, + {"~#point": {"~:x": 1122.107421875, "~:y": -187}}, + {"~#point": {"~:x": 1094.2889430596829, "~:y": -187}} + ], + "~:proportion-lock": false, + "~:stroke-cap-end": "~:round", + "~:transform-inverse": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:stroke-linecap": "~:round", + "~:svg-transform": {"~#matrix": {"~:a": 1, "~:b": 0, "~:c": 0, "~:d": 1, "~:e": 0, "~:f": 0}}, + "~:id": "~u8f89d4e8-0efd-804d-8007-b1469931e08c", + "~:parent-id": "~u8f89d4e8-0efd-804d-8007-b1469931a9d1", + "~:svg-viewbox": {"~#rect": {"~:x": 15.28894305968281, "~:y": 5.330620727377026, "~:width": 27.818478815317192, "~:height": 44.669379272622976, "~:x1": 15.28894305968281, "~:y1": 5.330620727377026, "~:x2": 43.107421875, "~:y2": 50}}, + "~:svg-defs": {}, + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [{"~:stroke-alignment": "~:outer", "~:stroke-style": "~:solid", "~:stroke-color": "#000000", "~:stroke-opacity": 1, "~:stroke-width": 1}], + "~:x": null, + "~:proportion": 1, + "~:selrect": {"~#rect": {"~:x": 1094.2889430596829, "~:y": -231.66937927262296, "~:width": 27.818478815317192, "~:height": 44.669379272622976, "~:x1": 1094.2889430596829, "~:y1": -231.66937927262296, "~:x2": 1122.107421875, "~:y2": -187}}, + "~:fills": [], + "~:flip-x": null, + "~:height": null, + "~:flip-y": null + } + } + }, + "~:id": "~uaaa00001-0001-0001-8007-000000000002", + "~:name": "Page 1" + } + }, + "~:id": "~uaaa00001-0001-0001-8007-000000000001", + "~:options": { + "~:components-v2": true, + "~:base-font-size": "16px" + } + } +} diff --git a/frontend/playwright/ui/render-wasm-specs/shapes.spec.js b/frontend/playwright/ui/render-wasm-specs/shapes.spec.js index 9d6f38351f..4d0597b9aa 100644 --- a/frontend/playwright/ui/render-wasm-specs/shapes.spec.js +++ b/frontend/playwright/ui/render-wasm-specs/shapes.spec.js @@ -485,6 +485,34 @@ test("No white seam at intersections of overlapping shapes with inner strokes", }); }); +test("Correct stroke closing at self-intersection of overlapping shapes with outer strokes", async ({ + page, +}) => { + const workspace = new WasmWorkspacePage(page); + await workspace.setupEmptyFile(); + await workspace.mockGetFile("render-wasm/get-file-outer-stroke-overlap-seam.json"); + + await workspace.goToWorkspace({ + id: "aaa00001-0001-0001-8007-000000000001", + pageId: "aaa00001-0001-0001-8007-000000000002", + }); + await workspace.waitForFirstRender(); + + await workspace.viewport.click(); + await page.keyboard.press("ControlOrMeta+A"); + const previousRenderCount = await workspace.getRenderCount(); + await page.keyboard.press("f"); + await workspace.waitForNextRender(previousRenderCount); + + await workspace.hideUI(); + + // Stricter comparison: white seam artifacts are very subtle + await expect(workspace.canvas).toHaveScreenshot({ + maxDiffPixelRatio: 0, + threshold: 0.1, + }); +}); + test("BUG 13551 - Blurs affecting other elements", async ({ page, }) => { diff --git a/frontend/playwright/ui/render-wasm-specs/shapes.spec.js-snapshots/Correct-stroke-closing-at-self-intersection-of-overlapping-shapes-with-outer-strokes-1.png b/frontend/playwright/ui/render-wasm-specs/shapes.spec.js-snapshots/Correct-stroke-closing-at-self-intersection-of-overlapping-shapes-with-outer-strokes-1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b041ad6edbe20bdfe1ed33d2ebbfe0977bc0ade GIT binary patch literal 50573 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 Uvr>x|e*NW(1{d;wz5V!q08sl1^8f$< literal 0 HcmV?d00001 diff --git a/render-wasm/src/shapes/paths.rs b/render-wasm/src/shapes/paths.rs index d6d6a8d1ef..8fa81c6b77 100644 --- a/render-wasm/src/shapes/paths.rs +++ b/render-wasm/src/shapes/paths.rs @@ -32,34 +32,25 @@ impl Default for Path { impl Path { pub fn new(segments: Vec) -> Self { let mut pb = skia::PathBuilder::new(); - let mut start = None; + // Don't auto-close the Skia path when start ≈ end. + // SVG treats these as open paths (caps apply at endpoints). + // Auto-closing changes stroke behavior from caps to joins, + // producing artifacts at self-intersection points. + // Only explicit Segment::Close should close the Skia path. for segment in segments.iter() { - let destination = match *segment { + match *segment { Segment::MoveTo(xy) => { - start = Some(xy); pb.move_to(xy); - None } Segment::LineTo(xy) => { pb.line_to(xy); - Some(xy) } Segment::CurveTo((c1, c2, xy)) => { pb.cubic_to(c1, c2, xy); - Some(xy) } Segment::Close => { pb.close(); - None - } - }; - - if let (Some(start), Some(destination)) = (start, destination) { - if math::is_close_to(destination.0, start.0) - && math::is_close_to(destination.1, start.1) - { - pb.close(); } } } diff --git a/render-wasm/src/shapes/strokes.rs b/render-wasm/src/shapes/strokes.rs index 426d5939c3..4ca3b5f906 100644 --- a/render-wasm/src/shapes/strokes.rs +++ b/render-wasm/src/shapes/strokes.rs @@ -213,12 +213,24 @@ impl Stroke { paint.set_anti_alias(antialias); if let Some(svg_attrs) = svg_attrs { - if svg_attrs.stroke_linecap == StrokeLineCap::Round { - paint.set_stroke_cap(skia::paint::Cap::Round); + match svg_attrs.stroke_linecap { + StrokeLineCap::Round => { + paint.set_stroke_cap(skia::paint::Cap::Round); + } + StrokeLineCap::Square => { + paint.set_stroke_cap(skia::paint::Cap::Square); + } + StrokeLineCap::Butt => {} // Skia default } - if svg_attrs.stroke_linejoin == StrokeLineJoin::Round { - paint.set_stroke_join(skia::paint::Join::Round); + match svg_attrs.stroke_linejoin { + StrokeLineJoin::Round => { + paint.set_stroke_join(skia::paint::Join::Round); + } + StrokeLineJoin::Bevel => { + paint.set_stroke_join(skia::paint::Join::Bevel); + } + StrokeLineJoin::Miter => {} // Skia default } } From 6ca8865e5b9ad93e6428f5e9b1c336a393f6cd0a Mon Sep 17 00:00:00 2001 From: Elena Torro Date: Thu, 12 Mar 2026 12:00:03 +0100 Subject: [PATCH 2/2] :bug: Close the subpath when possible --- render-wasm/src/math/bools.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/render-wasm/src/math/bools.rs b/render-wasm/src/math/bools.rs index 67de1e874e..0215e50dca 100644 --- a/render-wasm/src/math/bools.rs +++ b/render-wasm/src/math/bools.rs @@ -365,11 +365,10 @@ fn beziers_to_segments(beziers: &[(BezierSource, Bezier)]) -> Vec { let mut bm = init_bm(beziers); while let Some(bezier) = pop_first(&mut bm) { - result.push(Segment::MoveTo(( - bezier.1.start.x as f32, - bezier.1.start.y as f32, - ))); + let start = (bezier.1.start.x as f32, bezier.1.start.y as f32); + result.push(Segment::MoveTo(start)); push_bezier(&mut result, &bezier.1); + let mut last_end = (bezier.1.end.x as f32, bezier.1.end.y as f32); let mut next_p = BezierStart(bezier.0, bezier.1.end); loop { @@ -377,8 +376,24 @@ fn beziers_to_segments(beziers: &[(BezierSource, Bezier)]) -> Vec { break; }; push_bezier(&mut result, &next.1); + last_end = (next.1.end.x as f32, next.1.end.y as f32); next_p = BezierStart(next.0, next.1.end); } + + // Close the subpath if the last point is close to the start. + if (last_end.0 - start.0).abs() < INTERSECT_THRESHOLD_SAME + && (last_end.1 - start.1).abs() < INTERSECT_THRESHOLD_SAME + { + // Remove the redundant LineTo that goes back to start, if present. + if let Some(Segment::LineTo(p)) = result.last() { + if (p.0 - start.0).abs() < INTERSECT_THRESHOLD_SAME + && (p.1 - start.1).abs() < INTERSECT_THRESHOLD_SAME + { + result.pop(); + } + } + result.push(Segment::Close); + } } result }