From f6fe41af96356ffe65b8c2efa24c4bafb8cb1fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Torr=C3=B3?= Date: Fri, 30 May 2025 12:10:34 +0200 Subject: [PATCH] :wrench: Add texts playground (#6599) --- frontend/resources/wasm-playground/js/lib.js | 85 +++++++++++++- frontend/resources/wasm-playground/paths.html | 4 +- frontend/resources/wasm-playground/plus.html | 4 +- frontend/resources/wasm-playground/rects.html | 4 +- frontend/resources/wasm-playground/texts.html | 105 ++++++++++++++++++ 5 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 frontend/resources/wasm-playground/texts.html diff --git a/frontend/resources/wasm-playground/js/lib.js b/frontend/resources/wasm-playground/js/lib.js index 4aefe6701..b4bd846a6 100644 --- a/frontend/resources/wasm-playground/js/lib.js +++ b/frontend/resources/wasm-playground/js/lib.js @@ -92,7 +92,7 @@ export function addShapeSolidFill(argb) { Module._add_shape_fill(); } -export function addShapeSolidStroleFill(argb) { +export function addShapeSolidStrokeFill(argb) { const ptr = allocBytes(160); const heap = getHeapU32(); const dv = new DataView(heap.buffer); @@ -230,3 +230,86 @@ export function setupInteraction(canvas) { canvas.addEventListener("mouseup", () => { isPanning = false; }); canvas.addEventListener("mouseout", () => { isPanning = false; }); } + +export function addTextShape(x, y, fontSize, text) { + const numLeaves = 1; // Single text leaf for simplicity + const paragraphAttrSize = 48; + const leafAttrSize = 56; + const fillSize = 160; + const textBuffer = new TextEncoder().encode(text); + const textSize = textBuffer.byteLength; + + // Calculate fills + const fills = [ + { + type: "solid", + color: getRandomColor(), + opacity: getRandomFloat(0.5, 1.0), + }, + ]; + const totalFills = fills.length; + const totalFillsSize = totalFills * fillSize; + + // Calculate metadata and total buffer size + const metadataSize = paragraphAttrSize + leafAttrSize + totalFillsSize; + const totalSize = metadataSize + textSize; + + // Allocate buffer + const bufferPtr = allocBytes(totalSize); + const heap = new Uint8Array(Module.HEAPU8.buffer, bufferPtr, totalSize); + const dview = new DataView(heap.buffer, bufferPtr, totalSize); + + // Set number of leaves + dview.setUint32(0, numLeaves, true); + + // Serialize paragraph attributes + dview.setUint8(4, 1); // text-align: left + dview.setUint8(5, 0); // text-direction: LTR + dview.setUint8(6, 0); // text-decoration: none + dview.setUint8(7, 0); // text-transform: none + dview.setFloat32(8, 1.2, true); // line-height + dview.setFloat32(12, 0, true); // letter-spacing + dview.setUint32(16, 0, true); // typography-ref-file (UUID part 1) + dview.setUint32(20, 0, true); // typography-ref-file (UUID part 2) + dview.setUint32(24, 0, true); // typography-ref-file (UUID part 3) + dview.setInt32(28, 0, true); // typography-ref-file (UUID part 4) + dview.setUint32(32, 0, true); // typography-ref-id (UUID part 1) + dview.setUint32(36, 0, true); // typography-ref-id (UUID part 2) + dview.setUint32(40, 0, true); // typography-ref-id (UUID part 3) + dview.setInt32(44, 0, true); // typography-ref-id (UUID part 4) + + // Serialize leaf attributes + const leafOffset = paragraphAttrSize; + dview.setUint8(leafOffset, 0); // font-style: normal + dview.setFloat32(leafOffset + 4, fontSize, true); // font-size + dview.setUint32(leafOffset + 8, 400, true); // font-weight: normal + dview.setUint32(leafOffset + 12, 0, true); // font-id (UUID part 1) + dview.setUint32(leafOffset + 16, 0, true); // font-id (UUID part 2) + dview.setUint32(leafOffset + 20, 0, true); // font-id (UUID part 3) + dview.setInt32(leafOffset + 24, 0, true); // font-id (UUID part 4) + dview.setInt32(leafOffset + 28, 0, true); // font-family hash + dview.setUint32(leafOffset + 32, 0, true); // font-variant-id (UUID part 1) + dview.setUint32(leafOffset + 36, 0, true); // font-variant-id (UUID part 2) + dview.setUint32(leafOffset + 40, 0, true); // font-variant-id (UUID part 3) + dview.setInt32(leafOffset + 44, 0, true); // font-variant-id (UUID part 4) + dview.setInt32(leafOffset + 48, textSize, true); // text-length + dview.setInt32(leafOffset + 52, totalFills, true); // total fills count + + // Serialize fills + let fillOffset = leafOffset + leafAttrSize; + fills.forEach((fill) => { + if (fill.type === "solid") { + const argb = hexToU32ARGB(fill.color, fill.opacity); + dview.setUint8(fillOffset, 0x00, true); // Fill type: solid + dview.setUint32(fillOffset + 4, argb, true); + fillOffset += fillSize; // Move to the next fill + } + }); + + // Add text content + const textOffset = metadataSize; + heap.set(textBuffer, textOffset); + + // Call the WebAssembly function + Module._set_shape_text_content(); +} \ No newline at end of file diff --git a/frontend/resources/wasm-playground/paths.html b/frontend/resources/wasm-playground/paths.html index ee4cc0ea2..ecc56af20 100644 --- a/frontend/resources/wasm-playground/paths.html +++ b/frontend/resources/wasm-playground/paths.html @@ -27,7 +27,7 @@ import { init, addShapeSolidFill, assignCanvas, hexToU32ARGB, getRandomInt, getRandomColor, getRandomFloat, useShape, setShapeChildren, setupInteraction, set_parent, draw_star, - addShapeSolidStroleFill + addShapeSolidStrokeFill } from './js/lib.js'; const canvas = document.getElementById("canvas"); @@ -66,7 +66,7 @@ Module._add_shape_center_stroke(10, 0, 0, 0); const argb2 = hexToU32ARGB(color, getRandomFloat(0.1, 1.0)); - addShapeSolidStroleFill(argb2); + addShapeSolidStrokeFill(argb2); } diff --git a/frontend/resources/wasm-playground/plus.html b/frontend/resources/wasm-playground/plus.html index 9ed6734bf..cd63ae677 100644 --- a/frontend/resources/wasm-playground/plus.html +++ b/frontend/resources/wasm-playground/plus.html @@ -27,7 +27,7 @@ import { init, addShapeSolidFill, assignCanvas, hexToU32ARGB, getRandomInt, getRandomColor, getRandomFloat, useShape, setShapeChildren, setupInteraction, set_parent, allocBytes, - addShapeSolidStroleFill, getHeapU32 + addShapeSolidStrokeFill, getHeapU32 } from './js/lib.js'; const canvas = document.getElementById("canvas"); @@ -90,7 +90,7 @@ const color = getRandomColor(); Module._add_shape_center_stroke(10, 0, 0, 0); const argb2 = hexToU32ARGB(color, getRandomFloat(0.1, 1.0)); - addShapeSolidStroleFill(argb2); + addShapeSolidStrokeFill(argb2); } diff --git a/frontend/resources/wasm-playground/rects.html b/frontend/resources/wasm-playground/rects.html index 2d6e40e7c..bb05ecbda 100644 --- a/frontend/resources/wasm-playground/rects.html +++ b/frontend/resources/wasm-playground/rects.html @@ -26,7 +26,7 @@ import initWasmModule from '/js/render_wasm.js'; import { init, addShapeSolidFill, assignCanvas, hexToU32ARGB, getRandomInt, getRandomColor, - getRandomFloat, useShape, setShapeChildren, setupInteraction, addShapeSolidStroleFill + getRandomFloat, useShape, setShapeChildren, setupInteraction, addShapeSolidStrokeFill } from './js/lib.js'; const canvas = document.getElementById("canvas"); @@ -64,7 +64,7 @@ Module._add_shape_center_stroke(10, 0, 0, 0); const argb2 = hexToU32ARGB(color, getRandomFloat(0.1, 1.0)); - addShapeSolidStroleFill(argb2); + addShapeSolidStrokeFill(argb2); } useShape("00000000-0000-0000-0000-000000000000"); diff --git a/frontend/resources/wasm-playground/texts.html b/frontend/resources/wasm-playground/texts.html new file mode 100644 index 000000000..9dfacbc5d --- /dev/null +++ b/frontend/resources/wasm-playground/texts.html @@ -0,0 +1,105 @@ + + + + + WASM + WebGL2 Texts + + + + + + + \ No newline at end of file