mirror of
https://github.com/rive-app/rive-flutter.git
synced 2025-08-06 16:40:27 +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 _deleteGlyphPath;
|
||||||
late js.JsFunction _shapeText;
|
late js.JsFunction _shapeText;
|
||||||
late js.JsFunction _deleteShapeResult;
|
late js.JsFunction _deleteShapeResult;
|
||||||
|
late js.JsFunction _breakLines;
|
||||||
|
late js.JsFunction _deleteBreakLinesResult;
|
||||||
|
|
||||||
class RawPathWasm extends RawPath {
|
class RawPathWasm extends RawPath {
|
||||||
final int rawPathPtr;
|
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 {
|
class TextShapeResultWasm extends TextShapeResult {
|
||||||
final int rawPathResultsPtr;
|
final int rawPathResultsPtr;
|
||||||
final List<RenderGlyphRun> runs;
|
final List<RenderGlyphRun> runs;
|
||||||
|
final List<TextLineWasm> lines = [];
|
||||||
|
|
||||||
TextShapeResultWasm(this.rawPathResultsPtr, this.runs);
|
TextShapeResultWasm(this.rawPathResultsPtr, this.runs);
|
||||||
@override
|
@override
|
||||||
@ -142,6 +182,45 @@ class TextShapeResultWasm extends TextShapeResult {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
int get runCount => runs.length;
|
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 {
|
extension ByteDataWasm on ByteData {
|
||||||
@ -233,8 +312,6 @@ class RenderFontWasm extends RenderFont {
|
|||||||
writer.writeFloat32(run.fontSize);
|
writer.writeFloat32(run.fontSize);
|
||||||
writer.writeUint32(run.unicharCount);
|
writer.writeUint32(run.unicharCount);
|
||||||
}
|
}
|
||||||
print(
|
|
||||||
"SIZE OF UNITS: ${Uint32List.fromList(text.codeUnits).length} ${text.codeUnits.length}");
|
|
||||||
|
|
||||||
var result = _shapeText.apply(
|
var result = _shapeText.apply(
|
||||||
<dynamic>[
|
<dynamic>[
|
||||||
@ -301,6 +378,9 @@ Future<void> initRenderFont() async {
|
|||||||
_deleteGlyphPath = module['deleteGlyphPath'] as js.JsFunction;
|
_deleteGlyphPath = module['deleteGlyphPath'] as js.JsFunction;
|
||||||
_shapeText = module['shapeText'] as js.JsFunction;
|
_shapeText = module['shapeText'] as js.JsFunction;
|
||||||
_deleteShapeResult = module['deleteShapeResult'] as js.JsFunction;
|
_deleteShapeResult = module['deleteShapeResult'] as js.JsFunction;
|
||||||
|
_breakLines = module['breakLines'] as js.JsFunction;
|
||||||
|
_deleteBreakLinesResult =
|
||||||
|
module['deleteBreakLinesResult'] as js.JsFunction;
|
||||||
completer.complete();
|
completer.complete();
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -49,4 +49,14 @@ RenderFont["onRuntimeInitialized"] = function () {
|
|||||||
"results": HEAPU8["subarray"](shapeResult),
|
"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/renderer.cpp',
|
||||||
source .. 'rive-cpp/src/math/raw_path.cpp',
|
source .. 'rive-cpp/src/math/raw_path.cpp',
|
||||||
source .. 'rive-cpp/src/text/renderfont_hb.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-layout.cc',
|
||||||
source .. 'harfbuzz/src/hb-aat-map.cc',
|
source .. 'harfbuzz/src/hb-aat-map.cc',
|
||||||
source .. 'harfbuzz/src/hb-blob.cc',
|
source .. 'harfbuzz/src/hb-blob.cc',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "hb-ot.h"
|
#include "hb-ot.h"
|
||||||
#include "hb.h"
|
#include "hb.h"
|
||||||
#include "rive/text/renderfont_hb.hpp"
|
#include "rive/text/renderfont_hb.hpp"
|
||||||
|
#include "rive/text/line_breaker.hpp"
|
||||||
|
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/bind.h>
|
#include <emscripten/bind.h>
|
||||||
@ -78,6 +79,23 @@ WasmPtr shapeText(emscripten::val codeUnits, emscripten::val runsList) {
|
|||||||
return (WasmPtr) nullptr;
|
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) {
|
EMSCRIPTEN_BINDINGS(RenderFont) {
|
||||||
function("makeRenderFont", &makeRenderFont, allow_raw_pointers());
|
function("makeRenderFont", &makeRenderFont, allow_raw_pointers());
|
||||||
function("deleteRenderFont", &deleteRenderFont);
|
function("deleteRenderFont", &deleteRenderFont);
|
||||||
@ -93,4 +111,11 @@ EMSCRIPTEN_BINDINGS(RenderFont) {
|
|||||||
|
|
||||||
function("shapeText", &shapeText);
|
function("shapeText", &shapeText);
|
||||||
function("deleteShapeResult", &deleteShapeResult);
|
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