mirror of
https://github.com/rive-app/rive-flutter.git
synced 2025-08-06 08:29:35 +08:00
Implement wasm abstraction for line breaker.
This commit is contained in:
@ -14,6 +14,8 @@ late js.JsFunction _makeGlyphPath;
|
||||
late js.JsFunction _deleteGlyphPath;
|
||||
late js.JsFunction _shapeText;
|
||||
late js.JsFunction _deleteShapeResult;
|
||||
late js.JsFunction _breakLines;
|
||||
late js.JsFunction _deleteBreakLinesResult;
|
||||
|
||||
class RawPathWasm extends RawPath {
|
||||
final int rawPathPtr;
|
||||
@ -129,9 +131,47 @@ class RawPathIterator extends Iterator<RawPathCommand> {
|
||||
}
|
||||
}
|
||||
|
||||
class TextLineWasm implements TextLine {
|
||||
@override
|
||||
final double baseline;
|
||||
|
||||
@override
|
||||
final double bottom;
|
||||
|
||||
@override
|
||||
final int endIndex;
|
||||
|
||||
@override
|
||||
final int endRun;
|
||||
|
||||
@override
|
||||
final int startIndex;
|
||||
|
||||
@override
|
||||
final int startRun;
|
||||
|
||||
@override
|
||||
final double startX;
|
||||
|
||||
@override
|
||||
final double top;
|
||||
|
||||
TextLineWasm({
|
||||
required this.baseline,
|
||||
required this.bottom,
|
||||
required this.endIndex,
|
||||
required this.endRun,
|
||||
required this.startIndex,
|
||||
required this.startRun,
|
||||
required this.startX,
|
||||
required this.top,
|
||||
});
|
||||
}
|
||||
|
||||
class TextShapeResultWasm extends TextShapeResult {
|
||||
final int rawPathResultsPtr;
|
||||
final List<RenderGlyphRun> runs;
|
||||
final List<TextLineWasm> lines = [];
|
||||
|
||||
TextShapeResultWasm(this.rawPathResultsPtr, this.runs);
|
||||
@override
|
||||
@ -142,6 +182,45 @@ class TextShapeResultWasm extends TextShapeResult {
|
||||
|
||||
@override
|
||||
int get runCount => runs.length;
|
||||
|
||||
@override
|
||||
void breakLines(double width, TextAlign alignment) {
|
||||
var result = _breakLines.apply(
|
||||
<dynamic>[
|
||||
rawPathResultsPtr,
|
||||
width,
|
||||
alignment.index,
|
||||
],
|
||||
) as js.JsObject;
|
||||
|
||||
var rawResult = result['rawResult'] as int;
|
||||
var linesBuffer = result['lines'] as Uint8List;
|
||||
var lineCount = result['lineCount'] as int;
|
||||
lines.clear();
|
||||
|
||||
var reader = BinaryReader.fromList(linesBuffer);
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
lines.add(
|
||||
TextLineWasm(
|
||||
startRun: reader.readUint32(),
|
||||
startIndex: reader.readUint32(),
|
||||
endRun: reader.readUint32(),
|
||||
endIndex: reader.readUint32(),
|
||||
startX: reader.readFloat32(),
|
||||
top: reader.readFloat32(),
|
||||
baseline: reader.readFloat32(),
|
||||
bottom: reader.readFloat32(),
|
||||
),
|
||||
);
|
||||
}
|
||||
_deleteBreakLinesResult.apply(<dynamic>[rawResult]);
|
||||
}
|
||||
|
||||
@override
|
||||
TextLine lineAt(int index) => lines[index];
|
||||
|
||||
@override
|
||||
int get lineCount => lines.length;
|
||||
}
|
||||
|
||||
extension ByteDataWasm on ByteData {
|
||||
@ -233,8 +312,6 @@ class RenderFontWasm extends RenderFont {
|
||||
writer.writeFloat32(run.fontSize);
|
||||
writer.writeUint32(run.unicharCount);
|
||||
}
|
||||
print(
|
||||
"SIZE OF UNITS: ${Uint32List.fromList(text.codeUnits).length} ${text.codeUnits.length}");
|
||||
|
||||
var result = _shapeText.apply(
|
||||
<dynamic>[
|
||||
@ -301,6 +378,9 @@ Future<void> initRenderFont() async {
|
||||
_deleteGlyphPath = module['deleteGlyphPath'] as js.JsFunction;
|
||||
_shapeText = module['shapeText'] as js.JsFunction;
|
||||
_deleteShapeResult = module['deleteShapeResult'] as js.JsFunction;
|
||||
_breakLines = module['breakLines'] as js.JsFunction;
|
||||
_deleteBreakLinesResult =
|
||||
module['deleteBreakLinesResult'] as js.JsFunction;
|
||||
completer.complete();
|
||||
}
|
||||
],
|
||||
|
@ -49,4 +49,14 @@ RenderFont["onRuntimeInitialized"] = function () {
|
||||
"results": HEAPU8["subarray"](shapeResult),
|
||||
};
|
||||
};
|
||||
|
||||
var nativeBreakLines = RenderFont["breakLines"];
|
||||
RenderFont["breakLines"] = function (runs, width, align) {
|
||||
var breakResult = nativeBreakLines(runs, width, align);
|
||||
return {
|
||||
"rawResult": breakResult[0],
|
||||
"lines": HEAPU8["subarray"](breakResult[1]),
|
||||
"lineCount": breakResult[2],
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ files {
|
||||
source .. 'rive-cpp/src/renderer.cpp',
|
||||
source .. 'rive-cpp/src/math/raw_path.cpp',
|
||||
source .. 'rive-cpp/src/text/renderfont_hb.cpp',
|
||||
source .. 'rive-cpp/src/text/line_breaker.cpp',
|
||||
source .. 'harfbuzz/src/hb-aat-layout.cc',
|
||||
source .. 'harfbuzz/src/hb-aat-map.cc',
|
||||
source .. 'harfbuzz/src/hb-blob.cc',
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "hb-ot.h"
|
||||
#include "hb.h"
|
||||
#include "rive/text/renderfont_hb.hpp"
|
||||
#include "rive/text/line_breaker.hpp"
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/bind.h>
|
||||
@ -78,6 +79,23 @@ WasmPtr shapeText(emscripten::val codeUnits, emscripten::val runsList) {
|
||||
return (WasmPtr) nullptr;
|
||||
}
|
||||
|
||||
struct LinesResult {
|
||||
WasmPtr result;
|
||||
WasmPtr lines;
|
||||
uint32_t lineCount;
|
||||
};
|
||||
|
||||
LinesResult breakLines(WasmPtr runsPtr, float width, uint8_t align) {
|
||||
auto runs = reinterpret_cast<rive::SimpleArray<rive::RenderGlyphRun>*>(runsPtr);
|
||||
auto result = new std::vector<rive::RenderGlyphLine>(
|
||||
rive::RenderGlyphLine::BreakLines(*runs, width, (rive::RenderTextAlign)align));
|
||||
return {(WasmPtr)result, (WasmPtr)result->data(), (uint32_t)result->size()};
|
||||
}
|
||||
|
||||
void deleteBreakLinesResult(WasmPtr breakLinesResult) {
|
||||
delete reinterpret_cast<std::vector<rive::RenderGlyphLine>*>(breakLinesResult);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(RenderFont) {
|
||||
function("makeRenderFont", &makeRenderFont, allow_raw_pointers());
|
||||
function("deleteRenderFont", &deleteRenderFont);
|
||||
@ -93,4 +111,11 @@ EMSCRIPTEN_BINDINGS(RenderFont) {
|
||||
|
||||
function("shapeText", &shapeText);
|
||||
function("deleteShapeResult", &deleteShapeResult);
|
||||
|
||||
value_array<LinesResult>("LinesResult")
|
||||
.element(&LinesResult::result)
|
||||
.element(&LinesResult::lines)
|
||||
.element(&LinesResult::lineCount);
|
||||
function("breakLines", &breakLines);
|
||||
function("deleteBreakLinesResult", &deleteBreakLinesResult);
|
||||
}
|
Reference in New Issue
Block a user