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 0000000000..3b041ad6ed Binary files /dev/null and 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 differ 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 } 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 } }