mirror of
https://github.com/rive-app/rive-flutter
synced 2025-07-05 21:55:58 +00:00
Fallback fonts for wasm
This commit is contained in:
@ -15,6 +15,7 @@ late js.JsFunction _deleteFont;
|
||||
late js.JsFunction _makeGlyphPath;
|
||||
late js.JsFunction _deleteGlyphPath;
|
||||
late js.JsFunction _shapeText;
|
||||
late js.JsFunction _setFallbackFonts;
|
||||
late js.JsFunction _deleteShapeResult;
|
||||
late js.JsFunction _breakLines;
|
||||
late js.JsFunction _deleteLines;
|
||||
@ -505,18 +506,21 @@ Future<void> initFont() async {
|
||||
html.document.body!.append(script);
|
||||
await script.onLoad.first;
|
||||
|
||||
var init = js.context['RiveText'] as js.JsFunction;
|
||||
var promise = init.apply(<dynamic>[]) as js.JsObject;
|
||||
var initWasm = js.context['RiveText'] as js.JsFunction;
|
||||
var promise = initWasm.apply(<dynamic>[]) as js.JsObject;
|
||||
var thenFunction = promise['then'] as js.JsFunction;
|
||||
var completer = Completer<void>();
|
||||
thenFunction.apply(
|
||||
<dynamic>[
|
||||
(js.JsObject module) {
|
||||
var init = module['init'] as js.JsFunction;
|
||||
init.apply(<dynamic>[]);
|
||||
_makeFont = module['makeFont'] as js.JsFunction;
|
||||
_deleteFont = module['deleteFont'] as js.JsFunction;
|
||||
_makeGlyphPath = module['makeGlyphPath'] as js.JsFunction;
|
||||
_deleteGlyphPath = module['deleteGlyphPath'] as js.JsFunction;
|
||||
_shapeText = module['shapeText'] as js.JsFunction;
|
||||
_setFallbackFonts = module['setFallbackFonts'] as js.JsFunction;
|
||||
_deleteShapeResult = module['deleteShapeResult'] as js.JsFunction;
|
||||
_breakLines = module['breakLines'] as js.JsFunction;
|
||||
_deleteLines = module['deleteLines'] as js.JsFunction;
|
||||
@ -527,3 +531,16 @@ Future<void> initFont() async {
|
||||
);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
void setFallbackFonts(List<Font> fonts) {
|
||||
_setFallbackFonts.apply(
|
||||
<dynamic>[
|
||||
Uint32List.fromList(
|
||||
fonts
|
||||
.cast<FontWasm>()
|
||||
.map((font) => font.fontPtr)
|
||||
.toList(growable: false),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -118,8 +118,6 @@ static rive::rcp<rive::Font> pickFallbackFont(rive::Span<const rive::Unichar> mi
|
||||
HBFont* font = static_cast<HBFont*>(fallbackFonts[i]);
|
||||
if (i == length - 1 || font->hasGlyph(missing))
|
||||
{
|
||||
fprintf(stderr, "FONT COUNT IS: %d\n", font->debugging_refcnt());
|
||||
|
||||
rive::rcp<rive::Font> rcFont = rive::rcp<rive::Font>(font);
|
||||
// because the font was released at load time, we need to give it an
|
||||
// extra ref whenever we bump it to a reference counted pointer.
|
||||
|
@ -219,7 +219,7 @@ do
|
||||
'-DANSI_DECLARATORS'
|
||||
}
|
||||
|
||||
filter {'system:macosx'}
|
||||
filter {'not options:arch=wasm', 'system:macosx'}
|
||||
do
|
||||
files {
|
||||
'macos/rive_text/rive_text.cpp'
|
||||
|
@ -1,7 +1,4 @@
|
||||
RiveText["onRuntimeInitialized"] = function () {
|
||||
var HEAPU8 = RiveText["HEAPU8"];
|
||||
var HEAPU32 = RiveText["HEAPU32"];
|
||||
var HEAPF32 = RiveText["HEAPF32"];
|
||||
var nativeMakeGlyphPath = RiveText["makeGlyphPath"];
|
||||
var move = 0;
|
||||
var line = 1;
|
||||
@ -13,7 +10,7 @@ RiveText["onRuntimeInitialized"] = function () {
|
||||
var verbCount = glyph[3];
|
||||
var ptsPtr = glyph[1];
|
||||
var verbPtr = glyph[2];
|
||||
var verbs = HEAPU8["subarray"](verbPtr, verbPtr + verbCount);
|
||||
var verbs = RiveText["HEAPU8"]["subarray"](verbPtr, verbPtr + verbCount);
|
||||
|
||||
let pointCount = 0;
|
||||
for (var verb of verbs) {
|
||||
@ -37,7 +34,10 @@ RiveText["onRuntimeInitialized"] = function () {
|
||||
return {
|
||||
"rawPath": glyph[0],
|
||||
"verbs": verbs,
|
||||
"points": HEAPF32["subarray"](ptsStart, ptsStart + pointCount * 2),
|
||||
"points": RiveText["HEAPF32"]["subarray"](
|
||||
ptsStart,
|
||||
ptsStart + pointCount * 2
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
@ -46,7 +46,7 @@ RiveText["onRuntimeInitialized"] = function () {
|
||||
var shapeResult = nativeShapeText(codeUnits, runsList);
|
||||
return {
|
||||
"rawResult": shapeResult,
|
||||
"results": HEAPU8["subarray"](shapeResult),
|
||||
"results": RiveText["HEAPU8"]["subarray"](shapeResult),
|
||||
};
|
||||
};
|
||||
|
||||
@ -55,7 +55,7 @@ RiveText["onRuntimeInitialized"] = function () {
|
||||
var breakResult = nativeBreakLines(shape, width, align);
|
||||
return {
|
||||
"rawResult": breakResult,
|
||||
"results": HEAPU8["subarray"](breakResult),
|
||||
"results": RiveText["HEAPU8"]["subarray"](breakResult),
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -99,6 +99,41 @@ void deleteLines(WasmPtr lines)
|
||||
delete reinterpret_cast<rive::SimpleArray<rive::SimpleArray<rive::GlyphLine>>*>(lines);
|
||||
}
|
||||
|
||||
std::vector<rive::Font*> fallbackFonts;
|
||||
|
||||
void setFallbackFonts(emscripten::val fontsList)
|
||||
{
|
||||
std::vector<int> fonts(fontsList["length"].as<unsigned>());
|
||||
{
|
||||
emscripten::val memoryView{emscripten::typed_memory_view(fonts.size(), fonts.data())};
|
||||
memoryView.call<void>("set", fontsList);
|
||||
}
|
||||
|
||||
fallbackFonts = std::vector<rive::Font*>();
|
||||
for (auto fontPtr : fonts)
|
||||
{
|
||||
fallbackFonts.push_back(reinterpret_cast<rive::Font*>(fontPtr));
|
||||
}
|
||||
}
|
||||
|
||||
static rive::rcp<rive::Font> pickFallbackFont(rive::Span<const rive::Unichar> missing)
|
||||
{
|
||||
size_t length = fallbackFonts.size();
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
HBFont* font = static_cast<HBFont*>(fallbackFonts[i]);
|
||||
if (i == length - 1 || font->hasGlyph(missing))
|
||||
{
|
||||
rive::rcp<rive::Font> rcFont = rive::rcp<rive::Font>(font);
|
||||
// because the font was released at load time, we need to give it an
|
||||
// extra ref whenever we bump it to a reference counted pointer.
|
||||
rcFont->ref();
|
||||
return rcFont;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WasmPtr shapeText(emscripten::val codeUnits, emscripten::val runsList)
|
||||
{
|
||||
std::vector<uint8_t> runsBytes(runsList["byteLength"].as<unsigned>());
|
||||
@ -121,12 +156,17 @@ WasmPtr shapeText(emscripten::val codeUnits, emscripten::val runsList)
|
||||
{
|
||||
auto result = (WasmPtr) new rive::SimpleArray<rive::Paragraph>(
|
||||
runs[0].font->shapeText(codeUnitArray, rive::Span(runs, runCount)));
|
||||
|
||||
return result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
fallbackFonts.clear();
|
||||
HBFont::gFallbackProc = pickFallbackFont;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#define OFFSET_OF(type, member) ((int)(intptr_t) & (((type*)(void*)0)->member))
|
||||
void assertSomeAssumptions()
|
||||
@ -177,10 +217,12 @@ EMSCRIPTEN_BINDINGS(RiveText)
|
||||
function("deleteGlyphPath", &deleteGlyphPath);
|
||||
|
||||
function("shapeText", &shapeText);
|
||||
function("setFallbackFonts", &setFallbackFonts);
|
||||
function("deleteShapeResult", &deleteShapeResult);
|
||||
|
||||
function("breakLines", &breakLines);
|
||||
function("deleteLines", &deleteLines);
|
||||
function("init", &init);
|
||||
|
||||
#ifdef DEBUG
|
||||
function("assertSomeAssumptions", &assertSomeAssumptions);
|
||||
|
Reference in New Issue
Block a user