Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Alejandro Alonso 2026-03-27 13:54:38 +01:00
commit dff381c4fe
5 changed files with 1015 additions and 813 deletions

View File

@ -10,6 +10,7 @@
"fdata/pointer-map", "fdata/pointer-map",
"fdata/objects-map", "fdata/objects-map",
"render-wasm/v1", "render-wasm/v1",
"text-editor-wasm/v1",
"components/v2", "components/v2",
"fdata/shape-data-type" "fdata/shape-data-type"
] ]
@ -25,11 +26,11 @@
}, },
"~:has-media-trimmed": false, "~:has-media-trimmed": false,
"~:comment-thread-seqn": 0, "~:comment-thread-seqn": 0,
"~:name": "gaps", "~:name": "New File 11",
"~:revn": 79, "~:revn": 19,
"~:modified-at": "~m1771855365377", "~:modified-at": "~m1774524674610",
"~:vern": 0, "~:vern": 0,
"~:id": "~ueffcbebc-b8c8-802f-8007-9a0b2e2c863f", "~:id": "~u273cd825-9673-81c2-8007-c5b6c5207a98",
"~:is-shared": false, "~:is-shared": false,
"~:migrations": { "~:migrations": {
"~#ordered-set": [ "~#ordered-set": [
@ -104,19 +105,20 @@
"0014-clear-components-nil-objects", "0014-clear-components-nil-objects",
"0015-fix-text-attrs-blank-strings", "0015-fix-text-attrs-blank-strings",
"0015-clean-shadow-color", "0015-clean-shadow-color",
"0016-copy-fills-from-position-data-to-text-node" "0016-copy-fills-from-position-data-to-text-node",
"0017-fix-layout-flex-dir"
] ]
}, },
"~:version": 67, "~:version": 67,
"~:project-id": "~ueba8fa2e-4140-8084-8005-448635da32b4", "~:project-id": "~ueba8fa2e-4140-8084-8005-448635da32b4",
"~:created-at": "~m1771591980210", "~:created-at": "~m1774522642561",
"~:backend": "legacy-db", "~:backend": "legacy-db",
"~:data": { "~:data": {
"~:pages": [ "~:pages": [
"~ueffcbebc-b8c8-802f-8007-9a0b2e2c8640" "~u273cd825-9673-81c2-8007-c5b6c5207a99"
], ],
"~:pages-index": { "~:pages-index": {
"~ueffcbebc-b8c8-802f-8007-9a0b2e2c8640": { "~u273cd825-9673-81c2-8007-c5b6c5207a99": {
"~:objects": { "~:objects": {
"~u00000000-0000-0000-0000-000000000000": { "~u00000000-0000-0000-0000-000000000000": {
"~#shape": { "~#shape": {
@ -205,17 +207,18 @@
"~:height": 0.01, "~:height": 0.01,
"~:flip-y": null, "~:flip-y": null,
"~:shapes": [ "~:shapes": [
"~u36e8a3ad-2b63-8008-8007-9a0b2f24ca4e", "~u91d336c9-02e5-806a-8007-c5b91b180723",
"~ufbc43ead-a2ce-8058-8007-9a0daf843e09", "~u91d336c9-02e5-806a-8007-c5b91b180724",
"~ufbc43ead-a2ce-8058-8007-9a0dbe2f49b8", "~u91d336c9-02e5-806a-8007-c5b91b180725",
"~u5bebb998-d617-801b-8007-9a3fbd5cc804", "~u91d336c9-02e5-806a-8007-c5b91b185c8b",
"~u80e2fa5a-cd1c-8043-8007-9d8aaca49f40" "~u91d336c9-02e5-806a-8007-c5b91b185c8c",
"~u91d336c9-02e5-806a-8007-c5b925214f02"
] ]
} }
}, },
"~ufbc43ead-a2ce-8058-8007-9a0dbe2f49b8": { "~u91d336c9-02e5-806a-8007-c5b94496a8b5": {
"~#shape": { "~#shape": {
"~:y": null, "~:y": 837.000020861669,
"~:transform": { "~:transform": {
"~#matrix": { "~#matrix": {
"~:a": 1, "~:a": 1,
@ -228,35 +231,33 @@
}, },
"~:rotation": 0, "~:rotation": 0,
"~:grow-type": "~:fixed", "~:grow-type": "~:fixed",
"~:content": { "~:hide-in-viewer": false,
"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAAD/f5dEM2EsRAIAAAAAAAAAAAAAAAAAAAAAAAAAUhmnRABACkQCAAAAAAAAAAAAAAAAAAAAAAAAAP8/vET//01EAgAAAAAAAAAAAAAAAAAAAAAAAAD/f5dEM2EsRA==" "~:name": "Rectangle",
}, "~:width": 384,
"~:name": "Path", "~:type": "~:rect",
"~:width": null,
"~:type": "~:path",
"~:points": [ "~:points": [
{ {
"~#point": { "~#point": {
"~:x": 1212.00003372852, "~:x": 91,
"~:y": 553.000012923003 "~:y": 837.000020861669
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1506.00004755679, "~:x": 475,
"~:y": 553.000012923003 "~:y": 837.000020861669
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1506.00004755679, "~:x": 475,
"~:y": 823.999993849517 "~:y": 1239.99999684096
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1212.00003372852, "~:x": 91,
"~:y": 823.999993849517 "~:y": 1239.99999684096
} }
} }
], ],
@ -273,49 +274,42 @@
} }
}, },
"~:r3": 0, "~:r3": 0,
"~:constraints-v": "~:top",
"~:constraints-h": "~:left",
"~:r1": 0, "~:r1": 0,
"~:id": "~ufbc43ead-a2ce-8058-8007-9a0dbe2f49b8", "~:id": "~u91d336c9-02e5-806a-8007-c5b94496a8b5",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:parent-id": "~u91d336c9-02e5-806a-8007-c5b925214f02",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u91d336c9-02e5-806a-8007-c5b925214f02",
"~:strokes": [ "~:strokes": [],
{ "~:x": 91,
"~:stroke-alignment": "~:inner",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 10
}
],
"~:x": null,
"~:proportion": 1, "~:proportion": 1,
"~:shadow": [],
"~:r4": 0, "~:r4": 0,
"~:selrect": { "~:selrect": {
"~#rect": { "~#rect": {
"~:x": 1212.00003372852, "~:x": 91,
"~:y": 553.000012923003, "~:y": 837.000020861669,
"~:width": 294.000013828278, "~:width": 384,
"~:height": 270.999980926514, "~:height": 402.999975979287,
"~:x1": 1212.00003372852, "~:x1": 91,
"~:y1": 553.000012923003, "~:y1": 837.000020861669,
"~:x2": 1506.00004755679, "~:x2": 475,
"~:y2": 823.999993849517 "~:y2": 1239.99999684096
} }
}, },
"~:fills": [ "~:fills": [
{ {
"~:fill-color": "#ffffff", "~:fill-color": "#f7f7f7",
"~:fill-opacity": 1 "~:fill-opacity": 1
} }
], ],
"~:flip-x": null, "~:flip-x": null,
"~:height": null, "~:height": 402.999975979287,
"~:flip-y": null "~:flip-y": null
} }
}, },
"~u36e8a3ad-2b63-8008-8007-9a0b2f24ca4e": { "~u91d336c9-02e5-806a-8007-c5b91b185c8b": {
"~#shape": { "~#shape": {
"~:y": 122.000001761754, "~:y": 1213.9999834293,
"~:transform": { "~:transform": {
"~#matrix": { "~#matrix": {
"~:a": 1, "~:a": 1,
@ -334,26 +328,26 @@
"~:points": [ "~:points": [
{ {
"~#point": { "~#point": {
"~:x": 694.000014750112, "~:x": 449.999977263741,
"~:y": 122.000001761754 "~:y": 1213.9999834293
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1158.00000219805, "~:x": 913.999964711679,
"~:y": 122.000001761754 "~:y": 1213.9999834293
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1158.00000219805, "~:x": 913.999964711679,
"~:y": 499.999980116278 "~:y": 1591.99996178383
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 694.000014750112, "~:x": 449.999977263741,
"~:y": 499.999980116278 "~:y": 1591.99996178383
} }
} }
], ],
@ -371,7 +365,7 @@
}, },
"~:r3": 0, "~:r3": 0,
"~:r1": 0, "~:r1": 0,
"~:id": "~u36e8a3ad-2b63-8008-8007-9a0b2f24ca4e", "~:id": "~u91d336c9-02e5-806a-8007-c5b91b185c8b",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000",
"~:strokes": [ "~:strokes": [
@ -381,29 +375,22 @@
"~:stroke-color": "#000000", "~:stroke-color": "#000000",
"~:stroke-opacity": 1, "~:stroke-opacity": 1,
"~:stroke-width": 100 "~:stroke-width": 100
},
{
"~:stroke-alignment": "~:outer",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 100
} }
], ],
"~:x": 694.000014750113, "~:x": 449.999977263741,
"~:proportion": 1, "~:proportion": 1,
"~:shadow": [], "~:shadow": [],
"~:r4": 0, "~:r4": 0,
"~:selrect": { "~:selrect": {
"~#rect": { "~#rect": {
"~:x": 694.000014750113, "~:x": 449.999977263741,
"~:y": 122.000001761754, "~:y": 1213.9999834293,
"~:width": 463.999987447937, "~:width": 463.999987447937,
"~:height": 377.999978354524, "~:height": 377.999978354524,
"~:x1": 694.000014750113, "~:x1": 449.999977263741,
"~:y1": 122.000001761754, "~:y1": 1213.9999834293,
"~:x2": 1158.00000219805, "~:x2": 913.999964711678,
"~:y2": 499.999980116278 "~:y2": 1591.99996178383
} }
}, },
"~:fills": [ "~:fills": [
@ -417,121 +404,9 @@
"~:flip-y": null "~:flip-y": null
} }
}, },
"~ufbc43ead-a2ce-8058-8007-9a0daf843e09": { "~u91d336c9-02e5-806a-8007-c5b91b185c8c": {
"~#shape": { "~#shape": {
"~:y": 262.999997589325, "~:y": 384,
"~:transform": {
"~#matrix": {
"~:a": 1,
"~:b": 0,
"~:c": 0,
"~:d": 1,
"~:e": 0,
"~:f": 0
}
},
"~:rotation": 0,
"~:grow-type": "~:fixed",
"~:hide-in-viewer": false,
"~:name": "Ellipse",
"~:width": 266.000036716461,
"~:type": "~:circle",
"~:points": [
{
"~#point": {
"~:x": 1271.00000137752,
"~:y": 262.999997589325
}
},
{
"~#point": {
"~:x": 1537.00003809398,
"~:y": 262.999997589325
}
},
{
"~#point": {
"~:x": 1537.00003809398,
"~:y": 483.000033828949
}
},
{
"~#point": {
"~:x": 1271.00000137752,
"~:y": 483.000033828949
}
}
],
"~: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": "~ufbc43ead-a2ce-8058-8007-9a0daf843e09",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000",
"~:strokes": [
{
"~:stroke-alignment": "~:inner",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 10
}
],
"~:x": 1271.00000137752,
"~:proportion": 1,
"~:shadow": [
{
"~:id": "~u9c6321b5-aeab-809f-8007-971f9e232191",
"~:style": "~:drop-shadow",
"~:color": {
"~:color": "#000000",
"~:opacity": 1
},
"~:offset-x": 4,
"~:offset-y": 4,
"~:blur": 0,
"~:spread": 0,
"~:hidden": true
}
],
"~:r4": 0,
"~:selrect": {
"~#rect": {
"~:x": 1271.00000137752,
"~:y": 262.999997589325,
"~:width": 266.000036716461,
"~:height": 220.000036239624,
"~:x1": 1271.00000137752,
"~:y1": 262.999997589325,
"~:x2": 1537.00003809398,
"~:y2": 483.000033828949
}
},
"~:fills": [
{
"~:fill-color": "#ffffff",
"~:fill-opacity": 1
}
],
"~:flip-x": null,
"~:height": 220.000036239624,
"~:flip-y": null
}
},
"~u80e2fa5a-cd1c-8043-8007-9d8aaca49f40": {
"~#shape": {
"~:y": -286.999972473494,
"~:transform": { "~:transform": {
"~#matrix": { "~#matrix": {
"~:a": 1, "~:a": 1,
@ -558,13 +433,11 @@
{ {
"~:line-height": "1.2", "~:line-height": "1.2",
"~:font-style": "normal", "~:font-style": "normal",
"~:typography-ref-id": null,
"~:text-transform": "none", "~:text-transform": "none",
"~:font-id": "sourcesanspro", "~:font-id": "sourcesanspro",
"~:key": "170uyffw5ph", "~:key": "170uyffw5ph",
"~:font-size": "400", "~:font-size": "400",
"~:font-weight": "400", "~:font-weight": "400",
"~:typography-ref-file": null,
"~:font-variant-id": "regular", "~:font-variant-id": "regular",
"~:text-decoration": "none", "~:text-decoration": "none",
"~:letter-spacing": "0", "~:letter-spacing": "0",
@ -578,14 +451,12 @@
"~:text": "HELLO" "~:text": "HELLO"
} }
], ],
"~:typography-ref-id": null,
"~:text-transform": "none", "~:text-transform": "none",
"~:text-align": "left", "~:text-align": "left",
"~:font-id": "sourcesanspro", "~:font-id": "sourcesanspro",
"~:key": "psg8ayj675", "~:key": "psg8ayj675",
"~:font-size": "400", "~:font-size": "400",
"~:font-weight": "400", "~:font-weight": "400",
"~:typography-ref-file": null,
"~:text-direction": "ltr", "~:text-direction": "ltr",
"~:type": "paragraph", "~:type": "paragraph",
"~:font-variant-id": "regular", "~:font-variant-id": "regular",
@ -611,26 +482,26 @@
"~:points": [ "~:points": [
{ {
"~#point": { "~#point": {
"~:x": 545.000013504691, "~:x": 301,
"~:y": -286.999972473494 "~:y": 384
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1661.00005303713, "~:x": 1417.00003953244,
"~:y": -286.999972473494 "~:y": 384
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1661.00005303713, "~:x": 1417.00003953244,
"~:y": 193.000017549648 "~:y": 863.999990023142
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 545.000013504691, "~:x": 301,
"~:y": 193.000017549648 "~:y": 863.999990023142
} }
} }
], ],
@ -644,11 +515,11 @@
"~:f": 0 "~:f": 0
} }
}, },
"~:id": "~u80e2fa5a-cd1c-8043-8007-9d8aaca49f40", "~:id": "~u91d336c9-02e5-806a-8007-c5b91b185c8c",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:position-data": [ "~:position-data": [
{ {
"~:y": 211.980041503906, "~:y": 882.979949951172,
"~:line-height": "1.2", "~:line-height": "1.2",
"~:font-style": "normal", "~:font-style": "normal",
"~:text-transform": "none", "~:text-transform": "none",
@ -661,7 +532,7 @@
"~:font-variant-id": "regular", "~:font-variant-id": "regular",
"~:text-decoration": "none", "~:text-decoration": "none",
"~:letter-spacing": "0", "~:letter-spacing": "0",
"~:x": 545, "~:x": 301,
"~:fills": [ "~:fills": [
{ {
"~:fill-color": "#ffffff", "~:fill-color": "#ffffff",
@ -670,7 +541,7 @@
], ],
"~:direction": "ltr", "~:direction": "ltr",
"~:font-family": "sourcesanspro", "~:font-family": "sourcesanspro",
"~:height": 517.960021972656, "~:height": 517.9599609375,
"~:text": "HELLO" "~:text": "HELLO"
} }
], ],
@ -684,27 +555,125 @@
"~:stroke-opacity": 1 "~:stroke-opacity": 1
} }
], ],
"~:x": 545.000013504691, "~:x": 301,
"~:selrect": { "~:selrect": {
"~#rect": { "~#rect": {
"~:x": 545.000013504691, "~:x": 301,
"~:y": -286.999972473494, "~:y": 384,
"~:width": 1116.00003953244, "~:width": 1116.00003953244,
"~:height": 479.999990023141, "~:height": 479.999990023141,
"~:x1": 545.000013504691, "~:x1": 301,
"~:y1": -286.999972473494, "~:y1": 384,
"~:x2": 1661.00005303713, "~:x2": 1417.00003953244,
"~:y2": 193.000017549648 "~:y2": 863.999990023141
} }
}, },
"~:fills": [],
"~:flip-x": null, "~:flip-x": null,
"~:height": 479.999990023141, "~:height": 479.999990023141,
"~:flip-y": null "~:flip-y": null
} }
}, },
"~u5bebb998-d617-801b-8007-9a3fbd5cc804": { "~u91d336c9-02e5-806a-8007-c5b925214f02": {
"~#shape": { "~#shape": {
"~:y": 543.00001095581, "~:y": 894.000017464198,
"~:hide-fill-on-export": false,
"~:transform": {
"~#matrix": {
"~:a": 1,
"~:b": 0,
"~:c": 0,
"~:d": 1,
"~:e": 0,
"~:f": 0
}
},
"~:rotation": 0,
"~:grow-type": "~:fixed",
"~:hide-in-viewer": false,
"~:name": "Board",
"~:width": 264,
"~:type": "~:frame",
"~:points": [
{
"~#point": {
"~:x": 169,
"~:y": 894.000017464198
}
},
{
"~#point": {
"~:x": 433,
"~:y": 894.000017464198
}
},
{
"~#point": {
"~:x": 433,
"~:y": 1212.99999845028
}
},
{
"~#point": {
"~:x": 169,
"~:y": 1212.99999845028
}
}
],
"~:r2": 20,
"~:show-content": false,
"~:proportion-lock": false,
"~:transform-inverse": {
"~#matrix": {
"~:a": 1,
"~:b": 0,
"~:c": 0,
"~:d": 1,
"~:e": 0,
"~:f": 0
}
},
"~:r3": 20,
"~:r1": 20,
"~:id": "~u91d336c9-02e5-806a-8007-c5b925214f02",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000",
"~:strokes": [
{
"~:stroke-alignment": "~:inner",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 10
}
],
"~:x": 169,
"~:proportion": 1,
"~:r4": 20,
"~:selrect": {
"~#rect": {
"~:x": 169,
"~:y": 894.000017464198,
"~:width": 264,
"~:height": 318.999980986085,
"~:x1": 169,
"~:y1": 894.000017464198,
"~:x2": 433,
"~:y2": 1212.99999845028
}
},
"~:fills": [],
"~:flip-x": null,
"~:height": 318.999980986085,
"~:flip-y": null,
"~:shapes": [
"~u91d336c9-02e5-806a-8007-c5b94496a8b5"
]
}
},
"~u91d336c9-02e5-806a-8007-c5b91b180723": {
"~#shape": {
"~:y": 792.999974235248,
"~:transform": { "~:transform": {
"~#matrix": { "~#matrix": {
"~:a": 1, "~:a": 1,
@ -723,26 +692,26 @@
"~:points": [ "~:points": [
{ {
"~#point": { "~#point": {
"~:x": 693.999990768432, "~:x": 450.000001245421,
"~:y": 543.00001095581 "~:y": 792.999974235248
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1157.99997821637, "~:x": 913.999988693359,
"~:y": 543.00001095581 "~:y": 792.999974235248
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 1157.99997821637, "~:x": 913.999988693359,
"~:y": 920.999989310334 "~:y": 1170.99995258977
} }
}, },
{ {
"~#point": { "~#point": {
"~:x": 693.999990768432, "~:x": 450.000001245421,
"~:y": 920.999989310334 "~:y": 1170.99995258977
} }
} }
], ],
@ -760,7 +729,7 @@
}, },
"~:r3": 0, "~:r3": 0,
"~:r1": 0, "~:r1": 0,
"~:id": "~u5bebb998-d617-801b-8007-9a3fbd5cc804", "~:id": "~u91d336c9-02e5-806a-8007-c5b91b180723",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000",
"~:strokes": [ "~:strokes": [
@ -770,22 +739,29 @@
"~:stroke-color": "#000000", "~:stroke-color": "#000000",
"~:stroke-opacity": 1, "~:stroke-opacity": 1,
"~:stroke-width": 100 "~:stroke-width": 100
},
{
"~:stroke-alignment": "~:outer",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 100
} }
], ],
"~:x": 693.999990768432, "~:x": 450.000001245422,
"~:proportion": 1, "~:proportion": 1,
"~:shadow": [], "~:shadow": [],
"~:r4": 0, "~:r4": 0,
"~:selrect": { "~:selrect": {
"~#rect": { "~#rect": {
"~:x": 693.999990768432, "~:x": 450.000001245422,
"~:y": 543.00001095581, "~:y": 792.999974235248,
"~:width": 463.999987447937, "~:width": 463.999987447937,
"~:height": 377.999978354524, "~:height": 377.999978354524,
"~:x1": 693.999990768432, "~:x1": 450.000001245422,
"~:y1": 543.00001095581, "~:y1": 792.999974235248,
"~:x2": 1157.99997821637, "~:x2": 913.999988693359,
"~:y2": 920.999989310334 "~:y2": 1170.99995258977
} }
}, },
"~:fills": [ "~:fills": [
@ -798,17 +774,229 @@
"~:height": 377.999978354524, "~:height": 377.999978354524,
"~:flip-y": null "~:flip-y": null
} }
},
"~u91d336c9-02e5-806a-8007-c5b91b180724": {
"~#shape": {
"~:y": 933.999970062819,
"~:transform": {
"~#matrix": {
"~:a": 1,
"~:b": 0,
"~:c": 0,
"~:d": 1,
"~:e": 0,
"~:f": 0
} }
}, },
"~:id": "~ueffcbebc-b8c8-802f-8007-9a0b2e2c8640", "~:rotation": 0,
"~:grow-type": "~:fixed",
"~:hide-in-viewer": false,
"~:name": "Ellipse",
"~:width": 266.000036716461,
"~:type": "~:circle",
"~:points": [
{
"~#point": {
"~:x": 1026.99998787283,
"~:y": 933.999970062819
}
},
{
"~#point": {
"~:x": 1293.00002458929,
"~:y": 933.999970062819
}
},
{
"~#point": {
"~:x": 1293.00002458929,
"~:y": 1154.00000630244
}
},
{
"~#point": {
"~:x": 1026.99998787283,
"~:y": 1154.00000630244
}
}
],
"~: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": "~u91d336c9-02e5-806a-8007-c5b91b180724",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000",
"~:strokes": [
{
"~:stroke-alignment": "~:inner",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 10
}
],
"~:x": 1026.99998787283,
"~:proportion": 1,
"~:shadow": [
{
"~:id": "~u9c6321b5-aeab-809f-8007-971f9e232191",
"~:style": "~:drop-shadow",
"~:color": {
"~:color": "#000000",
"~:opacity": 1
},
"~:offset-x": 4,
"~:offset-y": 4,
"~:blur": 0,
"~:spread": 0,
"~:hidden": true
}
],
"~:r4": 0,
"~:selrect": {
"~#rect": {
"~:x": 1026.99998787283,
"~:y": 933.999970062819,
"~:width": 266.000036716461,
"~:height": 220.000036239624,
"~:x1": 1026.99998787283,
"~:y1": 933.999970062819,
"~:x2": 1293.00002458929,
"~:y2": 1154.00000630244
}
},
"~:fills": [
{
"~:fill-color": "#ffffff",
"~:fill-opacity": 1
}
],
"~:flip-x": null,
"~:height": 220.000036239624,
"~:flip-y": null
}
},
"~u91d336c9-02e5-806a-8007-c5b91b180725": {
"~#shape": {
"~:y": null,
"~:transform": {
"~#matrix": {
"~:a": 1,
"~:b": 0,
"~:c": 0,
"~:d": 1,
"~:e": 0,
"~:f": 0
}
},
"~:rotation": 0,
"~:grow-type": "~:fixed",
"~:content": {
"~#penpot/path-data": "~bAQAAAAAAAAAAAAAAAAAAAAAAAAD+/3FEmRCqRAIAAAAAAAAAAAAAAAAAAAAAAAAAUpmIRAAAmUQCAAAAAAAAAAAAAAAAAAAAAAAAAP+/nUT/37pEAgAAAAAAAAAAAAAAAAAAAAAAAAD+/3FEmRCqRA=="
},
"~:name": "Path",
"~:width": null,
"~:type": "~:path",
"~:points": [
{
"~#point": {
"~:x": 968.000020223829,
"~:y": 1223.9999853965
}
},
{
"~#point": {
"~:x": 1262.0000340521,
"~:y": 1223.9999853965
}
},
{
"~#point": {
"~:x": 1262.0000340521,
"~:y": 1494.99996632301
}
},
{
"~#point": {
"~:x": 968.000020223829,
"~:y": 1494.99996632301
}
}
],
"~: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": "~u91d336c9-02e5-806a-8007-c5b91b180725",
"~:parent-id": "~u00000000-0000-0000-0000-000000000000",
"~:frame-id": "~u00000000-0000-0000-0000-000000000000",
"~:strokes": [
{
"~:stroke-alignment": "~:inner",
"~:stroke-style": "~:solid",
"~:stroke-color": "#000000",
"~:stroke-opacity": 1,
"~:stroke-width": 10
}
],
"~:x": null,
"~:proportion": 1,
"~:shadow": [],
"~:r4": 0,
"~:selrect": {
"~#rect": {
"~:x": 968.000020223829,
"~:y": 1223.9999853965,
"~:width": 294.000013828278,
"~:height": 270.999980926514,
"~:x1": 968.000020223829,
"~:y1": 1223.9999853965,
"~:x2": 1262.00003405211,
"~:y2": 1494.99996632301
}
},
"~:fills": [
{
"~:fill-color": "#ffffff",
"~:fill-opacity": 1
}
],
"~:flip-x": null,
"~:height": null,
"~:flip-y": null
}
}
},
"~:id": "~u273cd825-9673-81c2-8007-c5b6c5207a99",
"~:name": "Page 1", "~:name": "Page 1",
"~:background": "#000000" "~:background": "#000000"
} }
}, },
"~:id": "~ueffcbebc-b8c8-802f-8007-9a0b2e2c863f", "~:id": "~u273cd825-9673-81c2-8007-c5b6c5207a98",
"~:options": { "~:options": {
"~:components-v2": true, "~:components-v2": true,
"~:base-font-size": "16px" "~:base-font-size": "16px"
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -115,6 +115,7 @@ impl NodeRenderState {
&self, &self,
element: &Shape, element: &Shape,
offset: Option<(f32, f32)>, offset: Option<(f32, f32)>,
clip_inset: Option<f32>,
) -> Option<ClipStack> { ) -> Option<ClipStack> {
if self.id.is_nil() || !element.clip() { if self.id.is_nil() || !element.clip() {
return self.clip_bounds.clone(); return self.clip_bounds.clone();
@ -138,6 +139,10 @@ impl NodeRenderState {
_ => None, _ => None,
}; };
if let Some(clip_inset) = clip_inset.filter(|&e| e > 0.0) {
bounds.inset((clip_inset, clip_inset));
}
Self::append_clip(self.clip_bounds.clone(), (bounds, corners, transform)) Self::append_clip(self.clip_bounds.clone(), (bounds, corners, transform))
} }
@ -2441,8 +2446,18 @@ impl RenderState {
}); });
if element.is_recursive() { if element.is_recursive() {
let children_clip_bounds = // Shrink the child clip by ~1 device px when the frame has an inner stroke, same
node_render_state.get_children_clip_bounds(element, None); // epsilon as `fills::render` inset, so clipped overflow does not sit under the
// stroke band drawn later in `render_shape_exit`.
let clip_inset_for_children = (matches!(element.shape_type, Type::Frame(_))
&& element.clip()
&& element.has_inner_stroke())
.then_some(1.0 / scale);
let children_clip_bounds = node_render_state.get_children_clip_bounds(
element,
None,
clip_inset_for_children,
);
let children_ids: Vec<_> = if can_flatten { let children_ids: Vec<_> = if can_flatten {
// Container was flattened: get simplified children (which skip this level) // Container was flattened: get simplified children (which skip this level)

View File

@ -3,15 +3,7 @@ use skia_safe::{self as skia, Paint, RRect};
use super::{filters, RenderState, SurfaceId}; use super::{filters, RenderState, SurfaceId};
use crate::error::Result; use crate::error::Result;
use crate::render::get_source_rect; use crate::render::get_source_rect;
use crate::shapes::{merge_fills, Fill, Frame, ImageFill, Rect, Shape, StrokeKind, Type}; use crate::shapes::{merge_fills, Fill, Frame, ImageFill, Rect, Shape, Type};
/// True when the shape has at least one visible inner stroke.
fn has_inner_stroke(shape: &Shape) -> bool {
let is_open = shape.is_open();
shape
.visible_strokes()
.any(|s| s.render_kind(is_open) == StrokeKind::Inner)
}
fn draw_image_fill( fn draw_image_fill(
render_state: &mut RenderState, render_state: &mut RenderState,
@ -113,7 +105,7 @@ pub fn render(
} }
let scale = render_state.get_scale().max(1e-6); let scale = render_state.get_scale().max(1e-6);
let inset = if has_inner_stroke(shape) { let inset = if shape.has_inner_stroke() {
Some(1.0 / scale) Some(1.0 / scale)
} else { } else {
None None

View File

@ -1603,6 +1603,13 @@ impl Shape {
.count() .count()
} }
/// True when the shape has at least one visible inner stroke (open paths render strokes as center).
pub fn has_inner_stroke(&self) -> bool {
let is_open = self.is_open();
self.visible_strokes()
.any(|s| s.render_kind(is_open) == StrokeKind::Inner)
}
pub fn drop_shadow_paints(&self) -> Vec<skia_safe::Paint> { pub fn drop_shadow_paints(&self) -> Vec<skia_safe::Paint> {
let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect(); let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect();