diff --git a/frontend/playwright/data/render-wasm/get-file-text-images.json b/frontend/playwright/data/render-wasm/get-file-text-images.json index a320062251..18020f2c1e 100644 --- a/frontend/playwright/data/render-wasm/get-file-text-images.json +++ b/frontend/playwright/data/render-wasm/get-file-text-images.json @@ -24,11 +24,11 @@ }, "~:has-media-trimmed": false, "~:comment-thread-seqn": 0, - "~:name": "New File 7", - "~:revn": 66, - "~:modified-at": "~m1750422866332", + "~:name": "New File 7 (copy)", + "~:revn": 233, + "~:modified-at": "~m1753186774115", "~:vern": 0, - "~:id": "~u6bd7c17d-4f59-815e-8006-5e96453952b0", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4149b9a", "~:is-shared": false, "~:migrations": { "~#ordered-set": [ @@ -94,7 +94,12 @@ "0006-fix-old-texts-fills", "0007-clear-invalid-strokes-and-fills-v2", "0008-fix-library-colors-opacity", - "0009-add-partial-text-touched-flags" + "0009-add-partial-text-touched-flags", + "0002-normalize-bool-content-v2", + "0004-clean-shadow-color", + "0008-fix-library-colors-v4", + "0003-convert-path-content-v2", + "0009-clean-library-colors" ] }, "~:version": 67, @@ -199,6 +204,7 @@ "~u4b4f5ff7-44ac-808a-8006-5e980c195547", "~uef609b51-0d34-80f3-8006-5e9934d0368b", "~u4b4f5ff7-44ac-808a-8006-5e968ea9bb4b", + "~u8e0276b0-5131-8065-8006-87c8d5780f60", "~u4b4f5ff7-44ac-808a-8006-5e974ec5dede", "~u4b4f5ff7-44ac-808a-8006-5e9771af0c6e", "~u4b4f5ff7-44ac-808a-8006-5e9775677e20", @@ -206,9 +212,11 @@ "~u4b4f5ff7-44ac-808a-8006-5e98597c0d17", "~uef609b51-0d34-80f3-8006-5e995b054836", "~uef609b51-0d34-80f3-8006-5e9929d3fa47", + "~u8e0276b0-5131-8065-8006-87c8c98fa23d", "~uef609b51-0d34-80f3-8006-5e9880f79b0b", + "~u2e773f0c-bc2a-8063-8006-75d73e978b13", "~uef609b51-0d34-80f3-8006-5e98ba9c0e14", - "~uef609b51-0d34-80f3-8006-5e98cb62758b" + "~u8e0276b0-5131-8065-8006-87c89da3209e" ] } }, @@ -255,7 +263,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -285,7 +293,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -496,7 +504,7 @@ "~:stroke-width": 3, "~:stroke-opacity": 1, "~:stroke-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e97441071cc", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e17", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -523,6 +531,238 @@ "~:flip-y": null } }, + "~u8e0276b0-5131-8065-8006-87c8c98fa23d": { + "~#shape": { + "~:y": 601.000025231285, + "~:transform": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:rotation": 0, + "~:grow-type": "~:fixed", + "~:content": { + "~:type": "root", + "~:key": "26bzlb8q9d5", + "~:children": [ + { + "~:type": "paragraph-set", + "~:children": [ + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:children": [ + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "xz2qooo55r", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro", + "~:text": "🔥" + }, + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "bcqsnxgrmw", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro", + "~:text": "👩🏿\u200d🚀" + }, + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "vaxp7xayt3", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro", + "~:text": "👺" + }, + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "1con6sm4643", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro", + "~:text": "🚀" + } + ], + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:text-align": "left", + "~:font-id": "sourcesanspro", + "~:key": "10k4ei57t29", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:text-direction": "ltr", + "~:type": "paragraph", + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro" + }, + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:children": [ + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "qopgplegd0", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro", + "~:text": "" + } + ], + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:text-align": "left", + "~:font-id": "sourcesanspro", + "~:key": "2cmxi1d1shv", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:text-direction": "ltr", + "~:type": "paragraph", + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [], + "~:font-family": "sourcesanspro" + } + ] + } + ], + "~:vertical-align": "top" + }, + "~:hide-in-viewer": false, + "~:name": "Text", + "~:width": 284.00006512267055, + "~:type": "~:text", + "~:points": [ + { + "~#point": { + "~:x": 533.9999873919224, + "~:y": 601.0000252312851 + } + }, + { + "~#point": { + "~:x": 818.0000525145931, + "~:y": 601.0000252312851 + } + }, + { + "~#point": { + "~:x": 818.0000525145931, + "~:y": 690.9999714607172 + } + }, + { + "~#point": { + "~:x": 533.9999873919224, + "~:y": 690.9999714607172 + } + } + ], + "~:layout-item-h-sizing": "~:fix", + "~:transform-inverse": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:layout-item-v-sizing": "~:fix", + "~:id": "~u8e0276b0-5131-8065-8006-87c8c98fa23d", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:x": 533.9999873919226, + "~:shadow": [ + { + "~:color": { + "~:color": "#000000", + "~:opacity": 0.2 + }, + "~:spread": 0, + "~:offset-y": 4, + "~:style": "~:drop-shadow", + "~:blur": 0, + "~:hidden": false, + "~:id": "~uef609b51-0d34-80f3-8006-5e992e5ed7a5", + "~:offset-x": 4 + } + ], + "~:selrect": { + "~#rect": { + "~:x": 533.9999873919226, + "~:y": 601.000025231285, + "~:width": 284.00006512267055, + "~:height": 89.99994622943211, + "~:x1": 533.9999873919226, + "~:y1": 601.000025231285, + "~:x2": 818.0000525145931, + "~:y2": 690.9999714607171 + } + }, + "~:flip-x": null, + "~:height": 89.99994622943211, + "~:flip-y": null + } + }, "~uef609b51-0d34-80f3-8006-5e99460c12bb": { "~#shape": { "~:y": 550.7500897584513, @@ -642,6 +882,21 @@ } ], "~:x": 185.92164040549193, + "~:shadow": [ + { + "~:color": { + "~:color": "#000000", + "~:opacity": 0.2 + }, + "~:spread": 0, + "~:offset-y": 4, + "~:style": "~:drop-shadow", + "~:blur": 4, + "~:hidden": false, + "~:id": "~u8e0276b0-5131-8065-8006-87c8c509cf28", + "~:offset-x": 4 + } + ], "~:selrect": { "~#rect": { "~:x": 185.92164040549193, @@ -795,6 +1050,254 @@ "~:flip-y": null } }, + "~u8e0276b0-5131-8065-8006-87c89da3209e": { + "~#shape": { + "~:y": 385.0000058244965, + "~:transform": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:rotation": 0, + "~:grow-type": "~:auto-height", + "~:content": { + "~:type": "root", + "~:key": "23iz9tepv1l", + "~:children": [ + { + "~:type": "paragraph-set", + "~:children": [ + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:children": [ + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "t8mkaljm92", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": "❤️ " + }, + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "c76y0hiuuk", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": "I " + }, + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "59c3kg7hq8", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": "" + }, + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "1k1u2qulfoc", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": "l" + }, + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "10ufqdlvs3i", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "line-through", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": "ove" + }, + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "2ezx1yspc8b", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "line-through", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": " unicode ❤️" + } + ], + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:text-align": "left", + "~:font-id": "sourcesanspro", + "~:key": "2bd6up3z17w", + "~:font-size": "0", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:text-direction": "ltr", + "~:type": "paragraph", + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#cf2222", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace" + } + ] + } + ], + "~:vertical-align": "top" + }, + "~:name": "❤️ I hate emoji ❤️", + "~:width": 208.99999371708827, + "~:type": "~:text", + "~:points": [ + { + "~#point": { + "~:x": 528.9999767398235, + "~:y": 385.0000058244965 + } + }, + { + "~#point": { + "~:x": 737.9999704569117, + "~:y": 385.0000058244965 + } + }, + { + "~#point": { + "~:x": 737.9999704569117, + "~:y": 414.0000052154978 + } + }, + { + "~#point": { + "~:x": 528.9999767398235, + "~:y": 414.0000052154978 + } + } + ], + "~:layout-item-h-sizing": "~:fix", + "~:transform-inverse": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:layout-item-v-sizing": "~:fix", + "~:id": "~u8e0276b0-5131-8065-8006-87c89da3209e", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 528.9999767398235, + "~:selrect": { + "~#rect": { + "~:x": 528.9999767398235, + "~:y": 385.0000058244965, + "~:width": 208.99999371708827, + "~:height": 28.999999391001325, + "~:x1": 528.9999767398235, + "~:y1": 385.0000058244965, + "~:x2": 737.9999704569118, + "~:y2": 414.0000052154978 + } + }, + "~:flip-x": null, + "~:height": 28.999999391001325, + "~:flip-y": null + } + }, "~u4b4f5ff7-44ac-808a-8006-5e9771af0c6e": { "~#shape": { "~:y": 318.9999734620724, @@ -838,7 +1341,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -868,7 +1371,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -997,7 +1500,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -1027,7 +1530,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -1113,17 +1616,178 @@ "~:flip-y": null } }, - "~uef609b51-0d34-80f3-8006-5e995b054836": { + "~u2e773f0c-bc2a-8063-8006-75d73e978b13": { "~#shape": { - "~:y": 553.4624040823653, + "~:y": 271.0000103742148, "~:transform": { "~#matrix": { - "~:a": 0.8191520419506291, - "~:b": 0.5735764396905747, - "~:c": -0.5735764396905756, - "~:d": 0.8191520419506286, - "~:e": 1.0800249583553523e-12, - "~:f": 1.3642420526593924e-12 + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:rotation": 0, + "~:grow-type": "~:fixed", + "~:content": { + "~:type": "root", + "~:key": "23iz9tepv1l", + "~:children": [ + { + "~:type": "paragraph-set", + "~:children": [ + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:children": [ + { + "~:line-height": "", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "t8mkaljm92", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "underline", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#000000", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", + "~:text": "❤️ I love unicode ❤️" + } + ], + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:text-align": "center", + "~:font-id": "sourcesanspro", + "~:key": "2bd6up3z17w", + "~:font-size": "24", + "~:font-weight": "normal", + "~:typography-ref-file": null, + "~:text-direction": "ltr", + "~:type": "paragraph", + "~:font-variant-id": "regular", + "~:text-decoration": "underline", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#000000", + "~:fill-opacity": 1 + } + ], + "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace" + } + ] + } + ], + "~:vertical-align": "center" + }, + "~:name": "❤️ I hate emoji ❤️", + "~:width": 337.10167609832115, + "~:type": "~:text", + "~:points": [ + { + "~#point": { + "~:x": 401.0000094603646, + "~:y": 271.0000103742148 + } + }, + { + "~#point": { + "~:x": 738.1016855586857, + "~:y": 271.0000103742148 + } + }, + { + "~#point": { + "~:x": 738.1016855586857, + "~:y": 427.0000100565906 + } + }, + { + "~#point": { + "~:x": 401.0000094603646, + "~:y": 427.0000100565906 + } + } + ], + "~:layout-item-h-sizing": "~:fix", + "~:transform-inverse": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:layout-item-v-sizing": "~:fix", + "~:id": "~u2e773f0c-bc2a-8063-8006-75d73e978b13", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [ + { + "~:stroke-style": "~:solid", + "~:stroke-alignment": "~:center", + "~:stroke-width": 1, + "~:stroke-color": "#ff0000", + "~:stroke-opacity": 1 + } + ], + "~:x": 401.0000094603646, + "~:shadow": [ + { + "~:color": { + "~:color": "#000000", + "~:opacity": 0.2 + }, + "~:spread": 0, + "~:offset-y": 4, + "~:style": "~:drop-shadow", + "~:blur": 0, + "~:hidden": false, + "~:id": "~ue2a1cacc-c6fc-80da-8006-75d7e4b7c7c4", + "~:offset-x": 4 + } + ], + "~:selrect": { + "~#rect": { + "~:x": 401.0000094603646, + "~:y": 271.0000103742148, + "~:width": 337.10167609832115, + "~:height": 155.9999996823758, + "~:x1": 401.0000094603646, + "~:y1": 271.0000103742148, + "~:x2": 738.1016855586857, + "~:y2": 427.0000100565906 + } + }, + "~:flip-x": null, + "~:height": 155.9999996823758, + "~:flip-y": null + } + }, + "~uef609b51-0d34-80f3-8006-5e995b054836": { + "~#shape": { + "~:y": 639.3084266396007, + "~:transform": { + "~#matrix": { + "~:a": 0.8191520484026025, + "~:b": 0.573576430476201, + "~:c": -0.5735763609931022, + "~:d": 0.8191520970551878, + "~:e": -1.7053025658242404e-13, + "~:f": 1.5916157281026244e-12 } }, "~:rotation": 35, @@ -1213,7 +1877,7 @@ "~:text-align": "left", "~:font-id": "sourcesanspro", "~:key": "10k4ei57t29", - "~:font-size": "0", + "~:font-size": "36", "~:font-weight": "400", "~:typography-ref-file": null, "~:text-direction": "ltr", @@ -1235,7 +1899,7 @@ "~:text-transform": "none", "~:font-id": "sourcesanspro", "~:key": "qopgplegd0", - "~:font-size": "0", + "~:font-size": "36", "~:font-weight": "400", "~:typography-ref-file": null, "~:font-variant-id": "regular", @@ -1251,7 +1915,7 @@ "~:text-align": "left", "~:font-id": "sourcesanspro", "~:key": "2cmxi1d1shv", - "~:font-size": "0", + "~:font-size": "36", "~:font-weight": "400", "~:typography-ref-file": null, "~:text-direction": "ltr", @@ -1269,70 +1933,70 @@ }, "~:hide-in-viewer": false, "~:name": "Text", - "~:width": 180.00002134842015, + "~:width": 246.95674553757414, "~:type": "~:text", "~:points": [ { "~#point": { - "~:x": 282.3845213766798, - "~:y": 506.00002254111644 + "~:x": 378.98816289302283, + "~:y": 574.0000033957591 } }, { "~#point": { - "~:x": 429.831906415395, - "~:y": 609.2437939303707 + "~:x": 581.2832868669669, + "~:y": 715.6485719832203 } }, { "~#point": { - "~:x": 403.4473830964035, - "~:y": 646.9247979902748 + "~:x": 546.2951287824992, + "~:y": 765.616849994829 } }, { "~#point": { - "~:x": 255.99999805768823, - "~:y": 543.6810266010206 + "~:x": 344.0000048085549, + "~:y": 623.9682814073681 } } ], "~:layout-item-h-sizing": "~:fix", "~:transform-inverse": { "~#matrix": { - "~:a": 0.8191520419506279, - "~:b": -0.5735764396905741, - "~:c": 0.573576439690575, - "~:d": 0.8191520419506283, - "~:e": -1.667201749434965e-12, - "~:f": -4.980447927604343e-13 + "~:a": 0.8191520970551903, + "~:b": -0.5735764304762028, + "~:c": 0.5735763609931039, + "~:d": 0.819152048402605, + "~:e": -7.732229401336406e-13, + "~:f": -1.4015874198038063e-12 } }, "~:layout-item-v-sizing": "~:fix", "~:id": "~uef609b51-0d34-80f3-8006-5e995b054836", "~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000", - "~:x": 252.9159415623315, + "~:x": 339.16327306897387, "~:selrect": { "~#rect": { - "~:x": 252.9159415623315, - "~:y": 553.4624040823653, - "~:width": 180.00002134842015, - "~:height": 46.000012366660485, - "~:x1": 252.9159415623315, - "~:y1": 553.4624040823653, - "~:x2": 432.91596291075166, - "~:y2": 599.4624164490258 + "~:x": 339.16327306897387, + "~:y": 639.3084266396007, + "~:width": 246.95674553757414, + "~:height": 61.00000011138661, + "~:x1": 339.16327306897387, + "~:y1": 639.3084266396007, + "~:x2": 586.120018606548, + "~:y2": 700.3084267509873 } }, "~:flip-x": null, - "~:height": 46.000012366660485, + "~:height": 61.00000011138661, "~:flip-y": null } }, "~uef609b51-0d34-80f3-8006-5e98ba9c0e14": { "~#shape": { - "~:y": 321.99998189293103, + "~:y": 429.00000200979923, "~:transform": { "~#matrix": { "~:a": 1, @@ -1344,7 +2008,7 @@ } }, "~:rotation": 0, - "~:grow-type": "~:auto-width", + "~:grow-type": "~:auto-height", "~:content": { "~:type": "root", "~:key": "23iz9tepv1l", @@ -1367,11 +2031,11 @@ "~:font-weight": "normal", "~:typography-ref-file": null, "~:font-variant-id": "regular", - "~:text-decoration": "none", + "~:text-decoration": "line-through", "~:letter-spacing": "0", "~:fills": [ { - "~:fill-color": "#000000", + "~:fill-color": "#cf2222", "~:fill-opacity": 1 } ], @@ -1393,7 +2057,7 @@ "~:letter-spacing": "0", "~:fills": [ { - "~:fill-color": "#000000", + "~:fill-color": "#cf2222", "~:fill-opacity": 1 } ], @@ -1411,11 +2075,11 @@ "~:font-weight": "normal", "~:typography-ref-file": null, "~:font-variant-id": "regular", - "~:text-decoration": "none", + "~:text-decoration": "line-through", "~:letter-spacing": "0", "~:fills": [ { - "~:fill-color": "#000000", + "~:fill-color": "#cf2222", "~:fill-opacity": 1 } ], @@ -1425,7 +2089,7 @@ ], "~:typography-ref-id": null, "~:text-transform": "none", - "~:text-align": "center", + "~:text-align": "left", "~:font-id": "sourcesanspro", "~:key": "2bd6up3z17w", "~:font-size": "0", @@ -1438,7 +2102,7 @@ "~:letter-spacing": "0", "~:fills": [ { - "~:fill-color": "#000000", + "~:fill-color": "#cf2222", "~:fill-opacity": 1 } ], @@ -1447,37 +2111,38 @@ ] } ], - "~:vertical-align": "" + "~:vertical-align": "top" }, "~:name": "❤️ I hate emoji ❤️", - "~:width": 208.99999821277834, + "~:width": 208.99999371708827, "~:type": "~:text", "~:points": [ { "~#point": { - "~:x": 377.99998569086324, - "~:y": 321.99998189293103 + "~:x": 528.9999767398235, + "~:y": 429.00000200979923 } }, { "~#point": { - "~:x": 586.9999839036416, - "~:y": 321.99998189293103 + "~:x": 737.9999704569117, + "~:y": 429.00000200979923 } }, { "~#point": { - "~:x": 586.9999839036416, - "~:y": 351.9999805349818 + "~:x": 737.9999704569117, + "~:y": 458.00000140080056 } }, { "~#point": { - "~:x": 377.99998569086324, - "~:y": 351.9999805349818 + "~:x": 528.9999767398235, + "~:y": 458.00000140080056 } } ], + "~:layout-item-h-sizing": "~:fix", "~:transform-inverse": { "~#matrix": { "~:a": 1, @@ -1488,33 +2153,26 @@ "~:f": 0 } }, + "~:layout-item-v-sizing": "~:fix", "~:id": "~uef609b51-0d34-80f3-8006-5e98ba9c0e14", "~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000", - "~:strokes": [ - { - "~:stroke-style": "~:solid", - "~:stroke-alignment": "~:center", - "~:stroke-width": 1, - "~:stroke-color": "#ff0000", - "~:stroke-opacity": 1 - } - ], - "~:x": 377.99998569086324, + "~:strokes": [], + "~:x": 528.9999767398235, "~:selrect": { "~#rect": { - "~:x": 377.99998569086324, - "~:y": 321.99998189293103, - "~:width": 208.99999821277834, - "~:height": 29.99999864205074, - "~:x1": 377.99998569086324, - "~:y1": 321.99998189293103, - "~:x2": 586.9999839036416, - "~:y2": 351.9999805349818 + "~:x": 528.9999767398235, + "~:y": 429.00000200979923, + "~:width": 208.99999371708827, + "~:height": 28.999999391001325, + "~:x1": 528.9999767398235, + "~:y1": 429.00000200979923, + "~:x2": 737.9999704569118, + "~:y2": 458.00000140080056 } }, "~:flip-x": null, - "~:height": 29.99999864205074, + "~:height": 28.999999391001325, "~:flip-y": null } }, @@ -1669,9 +2327,9 @@ "~:flip-y": null } }, - "~uef609b51-0d34-80f3-8006-5e98cb62758b": { + "~uef609b51-0d34-80f3-8006-5e9880f79b0b": { "~#shape": { - "~:y": 373.0000183528921, + "~:y": 269.00000893934515, "~:transform": { "~#matrix": { "~:a": 1, @@ -1683,7 +2341,7 @@ } }, "~:rotation": 0, - "~:grow-type": "~:fixed", + "~:grow-type": "~:auto-height", "~:content": { "~:type": "root", "~:key": "23iz9tepv1l", @@ -1706,28 +2364,6 @@ "~:font-weight": "normal", "~:typography-ref-file": null, "~:font-variant-id": "regular", - "~:text-decoration": "none", - "~:letter-spacing": "0", - "~:fills": [ - { - "~:fill-color": "#000000", - "~:fill-opacity": 1 - } - ], - "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", - "~:text": "❤️ I " - }, - { - "~:line-height": "", - "~:font-style": "normal", - "~:typography-ref-id": null, - "~:text-transform": "none", - "~:font-id": "sourcesanspro", - "~:key": "59c3kg7hq8", - "~:font-size": "24", - "~:font-weight": "normal", - "~:typography-ref-file": null, - "~:font-variant-id": "regular", "~:text-decoration": "line-through", "~:letter-spacing": "0", "~:fills": [ @@ -1737,37 +2373,15 @@ } ], "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", - "~:text": "love" - }, - { - "~:line-height": "", - "~:font-style": "normal", - "~:typography-ref-id": null, - "~:text-transform": "none", - "~:font-id": "sourcesanspro", - "~:key": "2ezx1yspc8b", - "~:font-size": "24", - "~:font-weight": "normal", - "~:typography-ref-file": null, - "~:font-variant-id": "regular", - "~:text-decoration": "none", - "~:letter-spacing": "0", - "~:fills": [ - { - "~:fill-color": "#000000", - "~:fill-opacity": 1 - } - ], - "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", - "~:text": " unicode ❤️" + "~:text": "❤️ I love unicode ❤️" } ], "~:typography-ref-id": null, "~:text-transform": "none", - "~:text-align": "center", + "~:text-align": "right", "~:font-id": "sourcesanspro", "~:key": "2bd6up3z17w", - "~:font-size": "0", + "~:font-size": "24", "~:font-weight": "normal", "~:typography-ref-file": null, "~:text-direction": "ltr", @@ -1789,31 +2403,31 @@ "~:vertical-align": "" }, "~:name": "❤️ I hate emoji ❤️", - "~:width": 148.00002662937948, + "~:width": 298.9999928235038, "~:type": "~:text", "~:points": [ { "~#point": { - "~:x": 350.0000044405443, - "~:y": 373.0000183528921 + "~:x": 439.0000065171845, + "~:y": 269.00000893934515 } }, { "~#point": { - "~:x": 498.0000310699237, - "~:y": 373.0000183528921 + "~:x": 737.9999993406883, + "~:y": 269.00000893934515 } }, { "~#point": { - "~:x": 498.0000310699237, - "~:y": 439.9999976771411 + "~:x": 737.9999993406883, + "~:y": 298.0000082477825 } }, { "~#point": { - "~:x": 350.0000044405443, - "~:y": 439.9999976771411 + "~:x": 439.0000065171845, + "~:y": 298.0000082477825 } } ], @@ -1829,183 +2443,39 @@ } }, "~:layout-item-v-sizing": "~:fix", - "~:id": "~uef609b51-0d34-80f3-8006-5e98cb62758b", - "~:parent-id": "~u00000000-0000-0000-0000-000000000000", - "~:frame-id": "~u00000000-0000-0000-0000-000000000000", - "~:strokes": [ - { - "~:stroke-style": "~:solid", - "~:stroke-alignment": "~:center", - "~:stroke-width": 1, - "~:stroke-color": "#ff0000", - "~:stroke-opacity": 1 - } - ], - "~:x": 350.00000444054433, - "~:selrect": { - "~#rect": { - "~:x": 350.00000444054433, - "~:y": 373.0000183528921, - "~:width": 148.00002662937948, - "~:height": 66.99997932424901, - "~:x1": 350.00000444054433, - "~:y1": 373.0000183528921, - "~:x2": 498.0000310699238, - "~:y2": 439.9999976771411 - } - }, - "~:flip-x": null, - "~:height": 66.99997932424901, - "~:flip-y": null - } - }, - "~uef609b51-0d34-80f3-8006-5e9880f79b0b": { - "~#shape": { - "~:y": 270.00000668846326, - "~:transform": { - "~#matrix": { - "~:a": 1, - "~:b": 0, - "~:c": 0, - "~:d": 1, - "~:e": 0, - "~:f": 0 - } - }, - "~:rotation": 0, - "~:grow-type": "~:auto-width", - "~:content": { - "~:type": "root", - "~:key": "23iz9tepv1l", - "~:children": [ - { - "~:type": "paragraph-set", - "~:children": [ - { - "~:line-height": "1.2", - "~:font-style": "normal", - "~:children": [ - { - "~:line-height": "", - "~:font-style": "normal", - "~:typography-ref-id": null, - "~:text-transform": "none", - "~:font-id": "sourcesanspro", - "~:key": "t8mkaljm92", - "~:font-size": "24", - "~:font-weight": "normal", - "~:typography-ref-file": null, - "~:font-variant-id": "regular", - "~:text-decoration": "none", - "~:letter-spacing": "0", - "~:fills": [ - { - "~:fill-color": "#000000", - "~:fill-opacity": 1 - } - ], - "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace", - "~:text": "❤️ I love unicode ❤️" - } - ], - "~:typography-ref-id": null, - "~:text-transform": "none", - "~:text-align": "center", - "~:font-id": "sourcesanspro", - "~:key": "2bd6up3z17w", - "~:font-size": "24", - "~:font-weight": "normal", - "~:typography-ref-file": null, - "~:text-direction": "ltr", - "~:type": "paragraph", - "~:font-variant-id": "regular", - "~:text-decoration": "none", - "~:letter-spacing": "0", - "~:fills": [ - { - "~:fill-color": "#000000", - "~:fill-opacity": 1 - } - ], - "~:font-family": "\"Droid Sans Mono\", \"monospace\", monospace" - } - ] - } - ], - "~:vertical-align": "" - }, - "~:name": "❤️ I hate emoji ❤️", - "~:width": 208.99999821277834, - "~:type": "~:text", - "~:points": [ - { - "~#point": { - "~:x": 377.99998569086324, - "~:y": 270.00000668846326 - } - }, - { - "~#point": { - "~:x": 586.9999839036416, - "~:y": 270.00000668846326 - } - }, - { - "~#point": { - "~:x": 586.9999839036416, - "~:y": 300.000005330514 - } - }, - { - "~#point": { - "~:x": 377.99998569086324, - "~:y": 300.000005330514 - } - } - ], - "~:transform-inverse": { - "~#matrix": { - "~:a": 1, - "~:b": 0, - "~:c": 0, - "~:d": 1, - "~:e": 0, - "~:f": 0 - } - }, "~:id": "~uef609b51-0d34-80f3-8006-5e9880f79b0b", "~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000", "~:strokes": [ { "~:stroke-style": "~:solid", - "~:stroke-alignment": "~:center", + "~:stroke-alignment": "~:outer", "~:stroke-width": 1, - "~:stroke-color": "#ff0000", + "~:stroke-color": "#e12020", "~:stroke-opacity": 1 } ], - "~:x": 377.99998569086324, + "~:x": 439.0000065171845, "~:selrect": { "~#rect": { - "~:x": 377.99998569086324, - "~:y": 270.00000668846326, - "~:width": 208.99999821277834, - "~:height": 29.99999864205074, - "~:x1": 377.99998569086324, - "~:y1": 270.00000668846326, - "~:x2": 586.9999839036416, - "~:y2": 300.000005330514 + "~:x": 439.0000065171845, + "~:y": 269.00000893934515, + "~:width": 298.9999928235038, + "~:height": 28.99999930843734, + "~:x1": 439.0000065171845, + "~:y1": 269.00000893934515, + "~:x2": 737.9999993406883, + "~:y2": 298.0000082477825 } }, "~:flip-x": null, - "~:height": 29.99999864205074, + "~:height": 28.99999930843734, "~:flip-y": null } }, "~u4b4f5ff7-44ac-808a-8006-5e98597c0d17": { "~#shape": { - "~:y": 455.0000055686013, + "~:y": 477.00001285883695, "~:transform": { "~#matrix": { "~:a": 1, @@ -2064,7 +2534,7 @@ "~:text": "👩🏿\u200d🚀" }, { - "~:line-height": "1.2", + "~:line-height": "", "~:font-style": "normal", "~:typography-ref-id": null, "~:text-transform": "none", @@ -2081,7 +2551,7 @@ "~:text": "👺" }, { - "~:line-height": "1.2", + "~:line-height": "", "~:font-style": "normal", "~:typography-ref-id": null, "~:text-transform": "none", @@ -2159,31 +2629,31 @@ }, "~:hide-in-viewer": false, "~:name": "Text", - "~:width": 180.0000180039333, + "~:width": 275.0000084325211, "~:type": "~:text", "~:points": [ { "~#point": { - "~:x": 400.9999895156452, - "~:y": 455.0000055686013 + "~:x": 528.9999944726543, + "~:y": 477.00001285883695 } }, { "~#point": { - "~:x": 581.0000075195785, - "~:y": 455.0000055686013 + "~:x": 804.0000029051753, + "~:y": 477.00001285883695 } }, { "~#point": { - "~:x": 581.0000075195785, - "~:y": 501.0000170805595 + "~:x": 804.0000029051753, + "~:y": 532.9999970710649 } }, { "~#point": { - "~:x": 400.9999895156452, - "~:y": 501.0000170805595 + "~:x": 528.9999944726543, + "~:y": 532.9999970710649 } } ], @@ -2199,24 +2669,25 @@ } }, "~:layout-item-v-sizing": "~:fix", + "~:hidden": false, "~:id": "~u4b4f5ff7-44ac-808a-8006-5e98597c0d17", "~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000", - "~:x": 400.9999895156452, + "~:x": 528.9999944726542, "~:selrect": { "~#rect": { - "~:x": 400.9999895156452, - "~:y": 455.0000055686013, - "~:width": 180.0000180039333, - "~:height": 46.00001151195818, - "~:x1": 400.9999895156452, - "~:y1": 455.0000055686013, - "~:x2": 581.0000075195785, - "~:y2": 501.0000170805595 + "~:x": 528.9999944726542, + "~:y": 477.00001285883695, + "~:width": 275.0000084325211, + "~:height": 55.9999842122279, + "~:x1": 528.9999944726542, + "~:y1": 477.00001285883695, + "~:x2": 804.0000029051753, + "~:y2": 532.9999970710649 } }, "~:flip-x": null, - "~:height": 46.00001151195818, + "~:height": 55.9999842122279, "~:flip-y": null } }, @@ -2263,7 +2734,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -2293,7 +2764,7 @@ { "~:fill-opacity": 1, "~:fill-image": { - "~:id": "~u6bd7c17d-4f59-815e-8006-5e9765e0fabd", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e18", "~:width": 443, "~:height": 441, "~:mtype": "image/png", @@ -2517,7 +2988,7 @@ }, "~uef609b51-0d34-80f3-8006-5e9929d3fa47": { "~#shape": { - "~:y": 519.0000103369729, + "~:y": 537.9999565667342, "~:transform": { "~#matrix": { "~:a": 1, @@ -2615,7 +3086,7 @@ "~:text-align": "left", "~:font-id": "sourcesanspro", "~:key": "10k4ei57t29", - "~:font-size": "0", + "~:font-size": "36", "~:font-weight": "400", "~:typography-ref-file": null, "~:text-direction": "ltr", @@ -2637,7 +3108,7 @@ "~:text-transform": "none", "~:font-id": "sourcesanspro", "~:key": "qopgplegd0", - "~:font-size": "0", + "~:font-size": "36", "~:font-weight": "400", "~:typography-ref-file": null, "~:font-variant-id": "regular", @@ -2653,7 +3124,7 @@ "~:text-align": "left", "~:font-id": "sourcesanspro", "~:key": "2cmxi1d1shv", - "~:font-size": "0", + "~:font-size": "36", "~:font-weight": "400", "~:typography-ref-file": null, "~:text-direction": "ltr", @@ -2671,31 +3142,31 @@ }, "~:hide-in-viewer": false, "~:name": "Text", - "~:width": 180.0000180039333, + "~:width": 284.0000651226706, "~:type": "~:text", "~:points": [ { "~#point": { - "~:x": 400.9999895156452, - "~:y": 519.0000103369729 + "~:x": 441.9999797625279, + "~:y": 537.9999565667343 } }, { "~#point": { - "~:x": 581.0000075195785, - "~:y": 519.0000103369729 + "~:x": 726.0000448851986, + "~:y": 537.9999565667343 } }, { "~#point": { - "~:x": 581.0000075195785, - "~:y": 565.000021848931 + "~:x": 726.0000448851986, + "~:y": 627.9999027961665 } }, { "~#point": { - "~:x": 400.9999895156452, - "~:y": 565.000021848931 + "~:x": 441.9999797625279, + "~:y": 627.9999027961665 } } ], @@ -2714,7 +3185,7 @@ "~:id": "~uef609b51-0d34-80f3-8006-5e9929d3fa47", "~:parent-id": "~u00000000-0000-0000-0000-000000000000", "~:frame-id": "~u00000000-0000-0000-0000-000000000000", - "~:x": 400.9999895156452, + "~:x": 441.99997976252797, "~:shadow": [ { "~:color": { @@ -2732,18 +3203,185 @@ ], "~:selrect": { "~#rect": { - "~:x": 400.9999895156452, - "~:y": 519.0000103369729, - "~:width": 180.0000180039333, - "~:height": 46.00001151195818, - "~:x1": 400.9999895156452, - "~:y1": 519.0000103369729, - "~:x2": 581.0000075195785, - "~:y2": 565.000021848931 + "~:x": 441.99997976252797, + "~:y": 537.9999565667342, + "~:width": 284.0000651226706, + "~:height": 89.99994622943211, + "~:x1": 441.99997976252797, + "~:y1": 537.9999565667342, + "~:x2": 726.0000448851986, + "~:y2": 627.9999027961663 } }, "~:flip-x": null, - "~:height": 46.00001151195818, + "~:height": 89.99994622943211, + "~:flip-y": null + } + }, + "~u8e0276b0-5131-8065-8006-87c8d5780f60": { + "~#shape": { + "~:y": 213.00001923843956, + "~:transform": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:rotation": 0, + "~:grow-type": "~:auto-width", + "~:content": { + "~:type": "root", + "~:key": "sgffdxj3ur", + "~:children": [ + { + "~:type": "paragraph-set", + "~:children": [ + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:children": [ + { + "~:line-height": "1.2", + "~:font-style": "normal", + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:font-id": "sourcesanspro", + "~:key": "qropsg36kw", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#15d12e", + "~:fill-opacity": 1 + } + ], + "~:font-family": "sourcesanspro", + "~:text": "hello world" + } + ], + "~:typography-ref-id": null, + "~:text-transform": "none", + "~:text-align": "left", + "~:font-id": "sourcesanspro", + "~:key": "dctsmh90vx", + "~:font-size": "36", + "~:font-weight": "400", + "~:typography-ref-file": null, + "~:text-direction": "ltr", + "~:type": "paragraph", + "~:font-variant-id": "regular", + "~:text-decoration": "none", + "~:letter-spacing": "0", + "~:fills": [ + { + "~:fill-color": "#15d12e", + "~:fill-opacity": 1 + } + ], + "~:font-family": "sourcesanspro" + } + ] + } + ], + "~:vertical-align": "top" + }, + "~:hide-in-viewer": false, + "~:name": "Text", + "~:width": 170.00000804662704, + "~:type": "~:text", + "~:points": [ + { + "~#point": { + "~:x": 186.99999576807022, + "~:y": 213.00001923843956 + } + }, + { + "~#point": { + "~:x": 357.00000381469727, + "~:y": 213.00001923843956 + } + }, + { + "~#point": { + "~:x": 357.00000381469727, + "~:y": 256.00001721188164 + } + }, + { + "~#point": { + "~:x": 186.99999576807022, + "~:y": 256.00001721188164 + } + } + ], + "~:transform-inverse": { + "~#matrix": { + "~:a": 1, + "~:b": 0, + "~:c": 0, + "~:d": 1, + "~:e": 0, + "~:f": 0 + } + }, + "~:id": "~u8e0276b0-5131-8065-8006-87c8d5780f60", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [ + { + "~:stroke-style": "~:solid", + "~:stroke-alignment": "~:outer", + "~:stroke-width": 3, + "~:stroke-opacity": 0.2, + "~:stroke-image": { + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4170e17", + "~:width": 443, + "~:height": 441, + "~:mtype": "image/png", + "~:name": "pattern.png", + "~:keep-aspect-ratio": true + } + } + ], + "~:x": 186.99999576807022, + "~:shadow": [ + { + "~:color": { + "~:color": "#000000", + "~:opacity": 0.2 + }, + "~:spread": 0, + "~:offset-y": 4, + "~:style": "~:drop-shadow", + "~:blur": 0, + "~:hidden": false, + "~:id": "~u8e0276b0-5131-8065-8006-87c8dad912bb", + "~:offset-x": 4 + } + ], + "~:selrect": { + "~#rect": { + "~:x": 186.99999576807022, + "~:y": 213.00001923843956, + "~:width": 170.00000804662704, + "~:height": 42.99999797344208, + "~:x1": 186.99999576807022, + "~:y1": 213.00001923843956, + "~:x2": 357.00000381469727, + "~:y2": 256.00001721188164 + } + }, + "~:flip-x": null, + "~:height": 42.99999797344208, "~:flip-y": null } } @@ -2752,7 +3390,7 @@ "~:name": "Page 1" } }, - "~:id": "~u6bd7c17d-4f59-815e-8006-5e96453952b0", + "~:id": "~u4f89252d-ebbc-813e-8006-8699e4149b9a", "~:options": { "~:components-v2": true, "~:base-font-size": "16px" diff --git a/frontend/playwright/ui/render-wasm-specs/texts.spec.js b/frontend/playwright/ui/render-wasm-specs/texts.spec.js index 8f810dadc2..37fd52fcd8 100644 --- a/frontend/playwright/ui/render-wasm-specs/texts.spec.js +++ b/frontend/playwright/ui/render-wasm-specs/texts.spec.js @@ -126,8 +126,8 @@ test("Renders a file with texts with images", async ({ page }) => { await workspace.setupEmptyFile(); await workspace.mockFileMediaAsset( [ - "6bd7c17d-4f59-815e-8006-5e9765e0fabd", - "6bd7c17d-4f59-815e-8006-5e97441071cc" + "4f89252d-ebbc-813e-8006-8699e4170e17", + "4f89252d-ebbc-813e-8006-8699e4170e18" ], "render-wasm/assets/pattern.png", ); diff --git a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-styled-texts-1.png b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-styled-texts-1.png index e3f1130431..05ed08a325 100644 Binary files a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-styled-texts-1.png and b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-styled-texts-1.png differ diff --git a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-text-decoration-1.png b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-text-decoration-1.png index de5e1b4d8b..ef5a1c4ac6 100644 Binary files a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-text-decoration-1.png and b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-text-decoration-1.png differ diff --git a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-that-use-custom-fonts-1.png b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-that-use-custom-fonts-1.png index 88c1f8e7aa..932baa3da2 100644 Binary files a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-that-use-custom-fonts-1.png and b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-that-use-custom-fonts-1.png differ diff --git a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-with-images-1.png b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-with-images-1.png index a4b5ea307f..2d539b53ff 100644 Binary files a/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-with-images-1.png and b/frontend/playwright/ui/render-wasm-specs/texts.spec.js-snapshots/Renders-a-file-with-texts-with-images-1.png differ diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 1fad158a07..ae25a366b4 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -302,10 +302,12 @@ impl RenderState { self.surfaces.reset(self.background_color); } + #[allow(dead_code)] pub fn get_canvas_at(&mut self, surface_id: SurfaceId) -> &skia::Canvas { self.surfaces.canvas(surface_id) } + #[allow(dead_code)] pub fn restore_canvas(&mut self, surface_id: SurfaceId) { self.surfaces.canvas(surface_id).restore(); } @@ -462,13 +464,22 @@ impl RenderState { let text_content = text_content.new_bounds(shape.selrect()); let mut paragraphs = text_content.get_skia_paragraphs(); - shadows::render_text_drop_shadows(self, &shape, &mut paragraphs, antialias); - text::render(self, &shape, &mut paragraphs, None); + if !shape.has_strokes() { + shadows::render_text_drop_shadows(self, &shape, &mut paragraphs, antialias); + } + + text::render(self, &shape, &mut paragraphs, None, None); if shape.has_inner_strokes() { // Inner strokes paints need the text fill to apply correctly their blend modes // (e.g., SrcATop, DstOver) - text::render(self, &shape, &mut paragraphs, Some(SurfaceId::Strokes)); + text::render( + self, + &shape, + &mut paragraphs, + Some(SurfaceId::Strokes), + None, + ); } for stroke in shape.strokes().rev() { @@ -488,6 +499,7 @@ impl RenderState { None, Some(&mut stroke_paragraphs), antialias, + None, ); shadows::render_text_inner_shadows( self, @@ -531,7 +543,7 @@ impl RenderState { for stroke in shape.strokes().rev() { shadows::render_stroke_drop_shadows(self, &shape, stroke, antialias); - strokes::render(self, &shape, stroke, None, None, None, antialias); + strokes::render(self, &shape, stroke, None, None, None, antialias, None); shadows::render_stroke_inner_shadows(self, &shape, stroke, antialias); } diff --git a/render-wasm/src/render/shadows.rs b/render-wasm/src/render/shadows.rs index a8dd60183b..7426f978a7 100644 --- a/render-wasm/src/render/shadows.rs +++ b/render-wasm/src/render/shadows.rs @@ -3,7 +3,7 @@ use crate::render::strokes; use crate::render::text::{self}; use crate::shapes::{Shadow, Shape, Stroke, Type}; use skia_safe::textlayout::ParagraphBuilder; -use skia_safe::{canvas::SaveLayerRec, Paint, Path}; +use skia_safe::{Paint, Path}; // Fill Shadows pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { @@ -59,6 +59,7 @@ pub fn render_stroke_drop_shadows( filter.as_ref(), None, antialias, + None, ) } } @@ -81,6 +82,7 @@ pub fn render_stroke_inner_shadows( filter.as_ref(), None, antialias, + None, ) } } @@ -89,7 +91,7 @@ pub fn render_stroke_inner_shadows( pub fn render_text_drop_shadows( render_state: &mut RenderState, shape: &Shape, - paragraphs: &mut [ParagraphBuilder], + paragraphs: &mut [Vec], antialias: bool, ) { for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) { @@ -124,29 +126,24 @@ pub fn render_text_drop_shadow( render_state: &mut RenderState, shape: &Shape, shadow: &Shadow, - paragraphs: &mut [ParagraphBuilder], + paragraphs: &mut [Vec], antialias: bool, ) { let paint = shadow.get_drop_shadow_paint(antialias); - let mask_paint = paint.clone(); - let mask = SaveLayerRec::default().paint(&mask_paint); - let canvas = render_state.get_canvas_at(SurfaceId::DropShadows); - canvas.save_layer(&mask); text::render( render_state, shape, paragraphs, Some(SurfaceId::DropShadows), + Some(&paint), ); - - render_state.restore_canvas(SurfaceId::DropShadows); } pub fn render_text_inner_shadows( render_state: &mut RenderState, shape: &Shape, - paragraphs: &mut [ParagraphBuilder], + paragraphs: &mut [Vec], antialias: bool, ) { for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) { @@ -158,24 +155,18 @@ pub fn render_text_inner_shadow( render_state: &mut RenderState, shape: &Shape, shadow: &Shadow, - paragraphs: &mut [ParagraphBuilder], + paragraphs: &mut [Vec], antialias: bool, ) { let paint = shadow.get_inner_shadow_paint(antialias); - let mask_paint = paint.clone(); - let mask = SaveLayerRec::default().paint(&mask_paint); - let canvas = render_state.get_canvas_at(SurfaceId::InnerShadows); - - canvas.save_layer(&mask); text::render( render_state, shape, paragraphs, Some(SurfaceId::InnerShadows), + Some(&paint), ); - - render_state.restore_canvas(SurfaceId::InnerShadows); } // Render text paths (unused) diff --git a/render-wasm/src/render/strokes.rs b/render-wasm/src/render/strokes.rs index eee72a9d1a..327643a4f4 100644 --- a/render-wasm/src/render/strokes.rs +++ b/render-wasm/src/render/strokes.rs @@ -479,14 +479,16 @@ fn draw_image_stroke_in_container( canvas.restore(); } +#[allow(clippy::too_many_arguments)] pub fn render( render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, surface_id: Option, shadow: Option<&ImageFilter>, - paragraphs: Option<&mut [ParagraphBuilder]>, + paragraphs: Option<&mut Vec>>, antialias: bool, + paint: Option<&skia::Paint>, ) { let scale = render_state.get_scale(); let canvas = render_state @@ -527,6 +529,7 @@ pub fn render( shape, paragraphs.expect("Text shapes should have paragraphs"), Some(SurfaceId::Strokes), + paint, ); } shape_type @ (Type::Path(_) | Type::Bool(_)) => { diff --git a/render-wasm/src/render/text.rs b/render-wasm/src/render/text.rs index c12a77b492..db01676ad3 100644 --- a/render-wasm/src/render/text.rs +++ b/render-wasm/src/render/text.rs @@ -1,93 +1,141 @@ use super::{RenderState, Shape, SurfaceId}; use crate::shapes::VerticalAlign; +use crate::utils::get_font_collection; use skia_safe::{textlayout::ParagraphBuilder, FontMetrics, Paint, Path}; pub fn render( render_state: &mut RenderState, shape: &Shape, - paragraphs: &mut [ParagraphBuilder], + paragraphs: &mut [Vec], surface_id: Option, + paint: Option<&Paint>, ) { + let fonts = get_font_collection(); let canvas = render_state .surfaces .canvas(surface_id.unwrap_or(SurfaceId::Fills)); - - let mut offset_y = 0.0; let container_height = shape.selrect().height(); - for builder in paragraphs { - let mut skia_paragraph = builder.build(); - skia_paragraph.layout(shape.bounds().width()); - let paragraph_height: f32 = skia_paragraph.height(); + // Calculate total height for vertical alignment + let total_content_height = calculate_all_paragraphs_height(paragraphs, shape.bounds().width()); + let mut global_offset_y = match shape.vertical_align() { + VerticalAlign::Center => (container_height - total_content_height) / 2.0, + VerticalAlign::Bottom => container_height - total_content_height, + _ => 0.0, + }; - let paragraph_offset_y = match shape.vertical_align() { - VerticalAlign::Center => (container_height - paragraph_height) / 2.0, - VerticalAlign::Bottom => container_height - paragraph_height, - _ => 0.0, - }; + for group in paragraphs { + let mut group_offset_y = global_offset_y; + let group_len = group.len(); - offset_y += paragraph_offset_y; + for (index, builder) in group.iter_mut().enumerate() { + let mut skia_paragraph = builder.build(); - let xy = (shape.selrect().x(), shape.selrect().y() + offset_y); - skia_paragraph.paint(canvas, xy); - - offset_y += paragraph_height; - - for line_metrics in skia_paragraph.get_line_metrics().iter() { - let style_metrics: Vec<_> = line_metrics - .get_style_metrics(line_metrics.start_index..line_metrics.end_index) - .into_iter() - .collect(); - - let mut current_x_offset = 0.0; - let total_line_width = line_metrics.width as f32; - let total_chars = line_metrics.end_index - line_metrics.start_index; - - // No text decoration for empty lines - if total_chars == 0 || style_metrics.is_empty() { + if paint.is_some() && index == 0 { + let text = builder.get_text().to_string(); + let mut paragraph_builder = + ParagraphBuilder::new(&builder.get_paragraph_style(), fonts); + let mut text_style: skia_safe::Handle<_> = builder.peek_style(); + let current_paint = text_style.foreground().clone(); + let blend_mode = current_paint.as_blend_mode(); + let mut new_paint = paint.unwrap().clone(); + if blend_mode != Some(skia_safe::BlendMode::SrcIn) { + new_paint.set_stroke_width(current_paint.stroke_width()); + new_paint.set_style(skia_safe::PaintStyle::StrokeAndFill); + } + new_paint.set_anti_alias(true); + text_style.set_foreground_paint(&new_paint); + paragraph_builder.reset(); + paragraph_builder.push_style(&text_style); + paragraph_builder.add_text(&text); + skia_paragraph = paragraph_builder.build(); + } else if paint.is_some() && index > 0 { continue; } - for (i, (index, style_metric)) in style_metrics.iter().enumerate() { - let text_style = style_metric.text_style; - let font_metrics = style_metric.font_metrics; - let next_index = style_metrics - .get(i + 1) - .map(|(next_i, _)| *next_i) - .unwrap_or(line_metrics.end_index); - let char_count = next_index - index; - let segment_width = if total_chars > 0 { - (char_count as f32 / total_chars as f32) * total_line_width - } else { - char_count as f32 * font_metrics.avg_char_width - }; + skia_paragraph.layout(shape.bounds().width()); - if text_style.decoration().ty - != skia_safe::textlayout::TextDecoration::NO_DECORATION - { - let decoration_type = text_style.decoration().ty; - let text_left = xy.0 + current_x_offset; - let text_top = xy.1 + line_metrics.baseline as f32 - line_metrics.ascent as f32; - let text_width = segment_width; - let line_height = line_metrics.height as f32; + let paragraph_height = skia_paragraph.height(); + let xy = (shape.selrect().x(), shape.selrect().y() + group_offset_y); + skia_paragraph.paint(canvas, xy); - let r = calculate_text_decoration_rect( - decoration_type, - font_metrics, - text_left, - text_top, - text_width, - line_height, - ); + for line_metrics in skia_paragraph.get_line_metrics().iter() { + let style_metrics: Vec<_> = line_metrics + .get_style_metrics(line_metrics.start_index..line_metrics.end_index) + .into_iter() + .collect(); - if let Some(decoration_rect) = r { - let decoration_paint = text_style.foreground(); - canvas.draw_rect(decoration_rect, &decoration_paint); - } + let mut current_x_offset = 0.0; + let total_line_width = line_metrics.width as f32; + let total_chars = line_metrics.end_index - line_metrics.start_index; + + // Calculate line's actual start position considering text alignment + // let paragraph_width = shape.bounds().width(); + let line_start_offset = line_metrics.left as f32; + + // No text decoration for empty lines + if total_chars == 0 || style_metrics.is_empty() { + continue; } - current_x_offset += segment_width; + for (i, (index, style_metric)) in style_metrics.iter().enumerate() { + let text_style = style_metric.text_style; + let font_metrics = style_metric.font_metrics; + let next_index = style_metrics + .get(i + 1) + .map(|(next_i, _)| *next_i) + .unwrap_or(line_metrics.end_index); + let char_count = next_index - index; + let segment_width = if total_chars > 0 { + (char_count as f32 / total_chars as f32) * total_line_width + } else { + char_count as f32 * font_metrics.avg_char_width + }; + if text_style.decoration().ty + != skia_safe::textlayout::TextDecoration::NO_DECORATION + { + let decoration_type = text_style.decoration().ty; + let text_left = xy.0 + line_start_offset + current_x_offset; + let text_top = + xy.1 + line_metrics.baseline as f32 - line_metrics.ascent as f32; + let text_width = segment_width; + let line_height = line_metrics.height as f32; + + let r = calculate_text_decoration_rect( + decoration_type, + font_metrics, + text_left, + text_top, + text_width, + line_height, + ); + + if let Some(decoration_rect) = r { + let decoration_paint = text_style.foreground(); + canvas.draw_rect(decoration_rect, &decoration_paint); + } + } + current_x_offset += segment_width; + } } + + // Only increment group_offset_y for regular paragraphs (single element groups) + // For stroke groups (multiple elements), keep same offset for blending + if group_len == 1 { + group_offset_y += paragraph_height; + } + // For stroke groups (group_len > 1), don't increment group_offset_y within the group + // This ensures all stroke variants render at the same position for proper blending + } + + // For stroke groups (multiple elements), increment global_offset_y once per group + if group_len > 1 { + let mut first_paragraph = group[0].build(); + first_paragraph.layout(shape.bounds().width()); + global_offset_y += first_paragraph.height(); + } else { + // For regular paragraphs, global_offset_y was already incremented inside the loop + global_offset_y = group_offset_y; } } } @@ -124,6 +172,36 @@ pub fn calculate_text_decoration_rect( } } +fn calculate_total_paragraphs_height(paragraphs: &mut [ParagraphBuilder], width: f32) -> f32 { + paragraphs + .iter_mut() + .map(|p| { + let mut paragraph = p.build(); + paragraph.layout(width); + paragraph.height() + }) + .sum() +} + +fn calculate_all_paragraphs_height( + paragraph_groups: &mut [Vec], + width: f32, +) -> f32 { + paragraph_groups + .iter_mut() + .map(|group| { + // For stroke groups, only count the first paragraph to avoid double-counting + if group.len() > 1 { + let mut paragraph = group[0].build(); + paragraph.layout(width); + paragraph.height() + } else { + calculate_total_paragraphs_height(group, width) + } + }) + .sum() +} + // Render text paths (unused) #[allow(dead_code)] pub fn render_as_path( diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index 840cf4a33b..7ef5f4819d 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -966,6 +966,10 @@ impl Shape { !self.fills.is_empty() } + pub fn has_strokes(&self) -> bool { + !self.strokes.is_empty() + } + pub fn has_inner_strokes(&self) -> bool { self.strokes.iter().any(|s| s.kind == StrokeKind::Inner) } diff --git a/render-wasm/src/shapes/text.rs b/render-wasm/src/shapes/text.rs index b388984328..6beac6d7e8 100644 --- a/render-wasm/src/shapes/text.rs +++ b/render-wasm/src/shapes/text.rs @@ -40,14 +40,13 @@ pub struct TextContent { pub grow_type: GrowType, } -pub fn set_paragraphs_width(width: f32, paragraphs: &mut [ParagraphBuilder]) { - for p in paragraphs { - // We first set max so we can get the min_intrinsic_width (this is the min word size) - // then after we set either the real with or the min. - // This is done this way so the words are not break into lines. - let mut paragraph = p.build(); - paragraph.layout(f32::MAX); - paragraph.layout(f32::max(width, paragraph.min_intrinsic_width().ceil())); +pub fn set_paragraphs_width(width: f32, paragraphs: &mut Vec>) { + for group in paragraphs { + for p in group { + let mut paragraph = p.build(); + paragraph.layout(f32::MAX); + paragraph.layout(f32::max(width, paragraph.min_intrinsic_width().ceil())); + } } } @@ -93,58 +92,60 @@ impl TextContent { self.paragraphs.push(paragraph); } - pub fn to_paragraphs(&self) -> Vec { + pub fn to_paragraphs(&self) -> Vec> { let fonts = get_font_collection(); let fallback_fonts = get_fallback_fonts(); - self.paragraphs - .iter() - .map(|p| { - let paragraph_style = p.paragraph_to_style(); - let mut builder = ParagraphBuilder::new(¶graph_style, fonts); - for leaf in &p.children { - let text_style = leaf.to_style(p, &self.bounds, fallback_fonts); - let text = leaf.apply_text_transform(); - builder.push_style(&text_style); - builder.add_text(&text); - builder.pop(); - } - builder - }) - .collect() + let mut paragraph_group = Vec::new(); + + for paragraph in &self.paragraphs { + let paragraph_style = paragraph.paragraph_to_style(); + let mut builder = ParagraphBuilder::new(¶graph_style, fonts); + for leaf in ¶graph.children { + let text_style = leaf.to_style(paragraph, &self.bounds, fallback_fonts); + let text = leaf.apply_text_transform(); + builder.push_style(&text_style); + builder.add_text(&text); + } + paragraph_group.push(vec![builder]); + } + + paragraph_group } - pub fn to_stroke_paragraphs(&self, stroke: &Stroke, bounds: &Rect) -> Vec { + pub fn to_stroke_paragraphs( + &self, + stroke: &Stroke, + bounds: &Rect, + ) -> Vec> { let fallback_fonts = get_fallback_fonts(); let stroke_paints = get_text_stroke_paints(stroke, bounds); let fonts = get_font_collection(); + let mut paragraph_group = Vec::new(); - stroke_paints - .into_iter() - .flat_map(|stroke_paint| { - self.paragraphs - .iter() - .map(|paragraph| { - let paragraph_style = paragraph.paragraph_to_style(); - let mut builder = ParagraphBuilder::new(¶graph_style, fonts); - for leaf in ¶graph.children { - let stroke_style = - leaf.to_stroke_style(paragraph, &stroke_paint, fallback_fonts); - let text: String = leaf.apply_text_transform(); - builder.push_style(&stroke_style); - builder.add_text(&text); - builder.pop(); - } - builder - }) - .collect::>() - }) - .collect() + for paragraph in &self.paragraphs { + let mut stroke_paragraphs = Vec::new(); + for stroke_paint in &stroke_paints { + let paragraph_style = paragraph.paragraph_to_style(); + let mut builder = ParagraphBuilder::new(¶graph_style, fonts); + for leaf in ¶graph.children { + let stroke_style = + leaf.to_stroke_style(paragraph, stroke_paint, fallback_fonts); + let text: String = leaf.apply_text_transform(); + builder.push_style(&stroke_style); + builder.add_text(&text); + } + stroke_paragraphs.push(builder); + } + paragraph_group.push(stroke_paragraphs); + } + + paragraph_group } pub fn collect_paragraphs( &self, - mut paragraphs: Vec, - ) -> Vec { + mut paragraphs: Vec>, + ) -> Vec> { if self.grow_type() == GrowType::AutoWidth { set_paragraphs_width(f32::MAX, &mut paragraphs); let max_width = auto_width(&mut paragraphs).ceil(); @@ -155,7 +156,7 @@ impl TextContent { paragraphs } - pub fn get_skia_paragraphs(&self) -> Vec { + pub fn get_skia_paragraphs(&self) -> Vec> { self.collect_paragraphs(self.to_paragraphs()) } @@ -163,7 +164,7 @@ impl TextContent { &self, stroke: &Stroke, bounds: &Rect, - ) -> Vec { + ) -> Vec> { self.collect_paragraphs(self.to_stroke_paragraphs(stroke, bounds)) } @@ -637,27 +638,33 @@ impl From<&Vec> for RawTextData { } } -pub fn auto_width(paragraphs: &mut [ParagraphBuilder]) -> f32 { +pub fn auto_width(paragraphs: &mut [Vec]) -> f32 { paragraphs.iter_mut().fold(0.0, |auto_width, p| { - let mut paragraph = p.build(); - paragraph.layout(f32::MAX); - f32::max(paragraph.max_intrinsic_width(), auto_width) + p.iter_mut().fold(auto_width, |auto_width, paragraph| { + let mut paragraph = paragraph.build(); + paragraph.layout(f32::MAX); + f32::max(paragraph.max_intrinsic_width(), auto_width) + }) }) } -pub fn max_width(paragraphs: &mut [ParagraphBuilder]) -> f32 { +pub fn max_width(paragraphs: &mut [Vec]) -> f32 { paragraphs.iter_mut().fold(0.0, |max_width, p| { - let mut paragraph = p.build(); - paragraph.layout(f32::MAX); - f32::max(paragraph.max_width(), max_width) + p.iter_mut().fold(max_width, |max_width, paragraph| { + let mut paragraph = paragraph.build(); + paragraph.layout(f32::MAX); + f32::max(paragraph.max_width(), max_width) + }) }) } -pub fn auto_height(paragraphs: &mut [ParagraphBuilder], width: f32) -> f32 { +pub fn auto_height(paragraphs: &mut [Vec], width: f32) -> f32 { paragraphs.iter_mut().fold(0.0, |auto_height, p| { - let mut paragraph = p.build(); - paragraph.layout(width); - auto_height + paragraph.height() + p.iter_mut().fold(auto_height, |auto_height, paragraph| { + let mut paragraph = paragraph.build(); + paragraph.layout(width); + auto_height + paragraph.height() + }) }) }