#include "hb-ot.h" #include "hb.h" #include "rive/text/renderfont_hb.hpp" #include #include #include #include #include using namespace emscripten; using WasmPtr = uint32_t; WasmPtr makeRenderFont(emscripten::val byteArray) { std::vector bytes; const auto l = byteArray["byteLength"].as(); bytes.resize(l); emscripten::val memoryView{emscripten::typed_memory_view(l, bytes.data())}; memoryView.call("set", byteArray); auto result = HBRenderFont::Decode(bytes); if (result) { return (WasmPtr)result.release(); } return (WasmPtr) nullptr; } void deleteRenderFont(WasmPtr renderFont) { reinterpret_cast(renderFont)->unref(); } struct GlyphPath { WasmPtr rawPath; WasmPtr points; WasmPtr verbs; uint16_t verbCount; }; GlyphPath makeGlyphPath(WasmPtr renderFontPtr, rive::GlyphID id) { auto renderFont = reinterpret_cast(renderFontPtr); rive::RawPath* path = new rive::RawPath(renderFont->getPath(id)); return { .rawPath = (WasmPtr)path, .points = (WasmPtr)path->points().data(), .verbs = (WasmPtr)path->verbs().data(), .verbCount = (uint16_t)path->verbs().size(), }; } void deleteGlyphPath(WasmPtr rawPath) { delete reinterpret_cast(rawPath); } void deleteShapeResult(WasmPtr shaperResult) { delete reinterpret_cast*>(shaperResult); } WasmPtr shapeText(emscripten::val codeUnits, emscripten::val runsList) { std::vector runsBytes(runsList["byteLength"].as()); { emscripten::val memoryView{ emscripten::typed_memory_view(runsBytes.size(), runsBytes.data())}; memoryView.call("set", runsList); } std::vector codeUnitArray(codeUnits["length"].as()); { emscripten::val memoryView{ emscripten::typed_memory_view(codeUnitArray.size(), codeUnitArray.data())}; memoryView.call("set", codeUnits); } auto runCount = runsBytes.size() / (4 + 4 + 4); rive::RenderTextRun* runs = reinterpret_cast(runsBytes.data()); if (runCount > 0) { return (WasmPtr) new rive::SimpleArray( runs[0].font->shapeText(codeUnitArray, rive::Span(runs, runCount))); } return (WasmPtr) nullptr; } EMSCRIPTEN_BINDINGS(RenderFont) { function("makeRenderFont", &makeRenderFont, allow_raw_pointers()); function("deleteRenderFont", &deleteRenderFont); value_array("GlyphPath") .element(&GlyphPath::rawPath) .element(&GlyphPath::points) .element(&GlyphPath::verbs) .element(&GlyphPath::verbCount); function("makeGlyphPath", &makeGlyphPath); function("deleteGlyphPath", &deleteGlyphPath); function("shapeText", &shapeText); function("deleteShapeResult", &deleteShapeResult); }