diff --git a/lib/src/controllers/one_shot_controller.dart b/lib/src/controllers/one_shot_controller.dart index 2a09cc4..b7a60a6 100644 --- a/lib/src/controllers/one_shot_controller.dart +++ b/lib/src/controllers/one_shot_controller.dart @@ -37,6 +37,6 @@ class OneShotAnimation extends SimpleAnimation { isActive ? onStart?.call() // onStop can fire while widgets are still drawing - : WidgetsBinding.instance.addPostFrameCallback((_) => onStop?.call()); + : WidgetsBinding.instance?.addPostFrameCallback((_) => onStop?.call()); } } diff --git a/lib/src/rive_core/shapes/mesh.dart b/lib/src/rive_core/shapes/mesh.dart index 2a5e055..9d574e5 100644 --- a/lib/src/rive_core/shapes/mesh.dart +++ b/lib/src/rive_core/shapes/mesh.dart @@ -21,7 +21,6 @@ class Mesh extends MeshBase with Skinnable { // be in world space. final List _vertices = []; - @override List get vertices => _vertices; ui.Vertices? _uiVertices; @@ -153,7 +152,6 @@ class Mesh extends MeshBase with Skinnable { return super.addDirt(value, recurse: recurse); } - @override Mat2D get worldTransform => skin != null ? Mat2D.identity : transformComponent.worldTransform; diff --git a/lib/src/rive_core/shapes/mesh_vertex.dart b/lib/src/rive_core/shapes/mesh_vertex.dart index 3362729..5b642ee 100644 --- a/lib/src/rive_core/shapes/mesh_vertex.dart +++ b/lib/src/rive_core/shapes/mesh_vertex.dart @@ -8,7 +8,6 @@ export 'package:rive/src/generated/shapes/mesh_vertex_base.dart'; class MeshVertex extends MeshVertexBase { Mesh? get mesh => parent as Mesh?; - @override TransformComponent get transformComponent => mesh?.transformComponent ?? Node(); diff --git a/lib/src/rive_core/src/text/built_in_font.dart b/lib/src/rive_core/src/text/built_in_font.dart deleted file mode 100644 index e6a3bcc..0000000 --- a/lib/src/rive_core/src/text/built_in_font.dart +++ /dev/null @@ -1,2 +0,0 @@ -const String builtInFontBase64 = - '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'; diff --git a/lib/src/rive_core/src/text/paragraph.dart b/lib/src/rive_core/src/text/paragraph.dart deleted file mode 100644 index 114c1db..0000000 --- a/lib/src/rive_core/src/text/paragraph.dart +++ /dev/null @@ -1,684 +0,0 @@ -import 'dart:math' as math; -import 'dart:ui'; - -import 'raw_path.dart'; -import 'shape_text.dart'; - -bool contains(Rect r, double x, double y) { - return r.left <= x && x <= r.right && r.top <= y && y <= r.bottom; -} - -Rect outset(Rect r, double dx, double dy) { - return Rect.fromLTRB(r.left - dx, r.top - dy, r.right + dx, r.bottom + dy); -} - -double pin(double min, double max, double value) { - return math.min(math.max(value, min), max); -} - -// DO NOT MODIFY the run -typedef TextRunVisitor = void Function(TextRun); - -// Returns either the original, or a new (cloned+modified) run. -// DO NOT MODIFY run.textLength -typedef TextRunMutator = TextRun Function(TextRun); - -// Given a shaped run and lineIndex (e.g. for drawing) -// DO NOT MODIFY the GlyphRun -typedef GlyphRunVisitor = void Function( - GlyphRun, int start, int end, double originX, double originY); - -enum LinePref { - start, - end, -} - -class VBar { - double x, top, bottom; - - VBar(this.x, this.top, this.bottom); -} - -abstract class Paragraph { - Rect _frame = const Rect.fromLTRB(0, 0, 0, 0); - List get textCodes; - List get textRuns; -// cached output - List _runs = []; - List _lines = []; - bool _dirty = true; - - bool get areTextRunsValid { - int len = 0; - textRuns.forEach((run) => len += run.textLength); - return len == textCodes.length; - } - - void _validateTextRuns() { - assert(areTextRunsValid); - } - - String get text => String.fromCharCodes(textCodes); - - void _validateShaping() { - if (textCodes.isEmpty) { - assert(_lines.length == 1); - assert(_runs.length == 1); - // ignore: prefer_is_empty - assert(_runs[0].glyphs.length == 0); - assert(_runs[0].xpos.length == 1); - return; - } - - GlyphLine line = _lines[0]; - line.validate(); - for (int i = 1; i < _lines.length; ++i) { - final GlyphLine nextLine = _lines[i]; - nextLine.validate(); - assert(line.textEnd == nextLine.textStart); - line = nextLine; - } - assert(line.textEnd == textCodes.length); - } - - void _makeAligned() { - double Y = _frame.top; - for (final line in _lines) { - double asc = 0; - double des = 0; - for (int i = line.startRun; i <= line.wsRun; ++i) { - final run = _runs[i]; - asc = math.min(asc, run.font.ascent * run.pointSize); - des = math.max(des, run.font.descent * run.pointSize); - } - line.top = Y; - Y -= asc; - line.baseline = Y; - Y += des; - line.bottom = Y; - } - // TODO: good place to perform left/center/right alignment - } - - void _ensureShapedLines() { - if (_dirty) { - _validateTextRuns(); - if (textCodes.isEmpty) { - return; - // _runs = [ - // GlyphRun(_defaultRun.font, _defaultRun.size, null, 0, - // Uint16List.fromList([]), Float32List.fromList([0])) - // ]; - // _lines = [GlyphLine(_runs, 0, 0, 0, 0, 0, 0, 0)]; - } else { - final breaks = GlyphRun.findWordBreaks(textCodes); - _runs = GlyphRun.shapeText(textCodes, textRuns); - _lines = GlyphLine.lineBreak(textCodes, breaks, _runs, _frame.width); - _makeAligned(); - } - _validateShaping(); - _dirty = false; - } - } - - void trunsChanged() { - _dirty = true; - } - - void textCodesChanged() { - _dirty = true; - } - - void _layoutChanged() { - _dirty = true; - } - - bool get isEmpty { - return textLength == 0; - } - - bool get isNotEmpty { - return textLength != 0; - } - - int get textLength { - return textCodes.length; - } - - Rect get bounds { - _ensureShapedLines(); - if (_lines.isEmpty) { - return Rect.zero; - } else { - return Rect.fromLTRB( - _frame.left, _frame.top, _frame.right, _lines.last.bottom); - } - } - - Rect get frame { - return _frame; - } - - set frame(Rect rect) { - if (rect == _frame) { - return; - } - if (_frame.width != rect.width) { - _layoutChanged(); - } - _frame = rect; - } - - List get lines { - _ensureShapedLines(); - return _lines; - } - - double offsetToFrameX(GlyphLine line, int textOffset) { - return _frame.left + line.offsetToX(textOffset); - } - - int offsetToLineIndex(int textOffset, LinePref pref) { - assert(textOffset >= 0 && textOffset <= textLength); - _ensureShapedLines(); - for (int i = 0; i < _lines.length; ++i) { - final line = _lines[i]; - assert(line.textStart <= textOffset); - if (textOffset <= line.textEnd) { - if (pref == LinePref.start && textOffset == line.textEnd) { - continue; - } - return i; - } - } - return _lines.length - 1; - } - - GlyphLine offsetToLine(int textOffset, LinePref pref) { - int index = offsetToLineIndex(textOffset, pref); - return _lines[index]; - } - -// [ index, offset ] - List _findRunIndexOffset(int offset) { - assert(offset >= 0 && offset <= textCodes.length); - - int prevLenths = 0; - for (int i = 0; i < textRuns.length; ++i) { - final int len = textRuns[i].textLength; - if (offset < len) { - return [i, prevLenths]; - } - prevLenths += len; - // ignore: parameter_assignments - offset -= len; - } - return [textRuns.length - 1, textCodes.length]; // last run - } - - int insert(int offset, String str) { - if (str.isEmpty) { - return 0; - } - assert(textRuns.isNotEmpty); - final pair = _findRunIndexOffset(offset); - final int index = pair[0]; - textRuns[index].textLength += str.length; - trunsChanged(); - final units = str.codeUnits; - textCodes.insertAll(offset, units); - textCodesChanged(); - return units.length; - } - - void delete(int start, int end) { - assert(start <= end); - assert(start >= 0); - assert(end <= textLength); - if (start == end) { - return; - } - - textCodes.removeRange(start, end); - textCodesChanged(); - - int i; - for (i = 0;; ++i) { - final run = textRuns[i]; - if (start < run.textLength) { - break; - } - // ignore: parameter_assignments - start -= run.textLength; - // ignore: parameter_assignments - end -= run.textLength; - } - TextRun run = textRuns[i]; - assert(start >= 0 && start < run.textLength); - if (start > 0) { - // trim leading run - final int amount = math.min(end, run.textLength) - start; - assert(amount > 0 && amount < run.textLength); - run.textLength -= amount; - // ignore: parameter_assignments - start += amount; - assert(start <= end); - // ignore: parameter_assignments - end = end - start; // now end is just a length - i += 1; - } - // remove whole runs - while (end > 0 && end >= textRuns[i].textLength) { - var run = textRuns[i]; - // ignore: parameter_assignments - end -= run.textLength; - _removeRunAt(i); - } - if (end > 0) { - textRuns[i].textLength -= end; - } - trunsChanged(); - } - - void setRun(int start, int end, TextRun newRun) { - modifyRuns(start, end, (TextRun orig) { - return newRun; - }); - } - - void removeRun(covariant TextRun run, int index) { - textRuns.removeAt(index); - } - - void insertRun(covariant TextRun run, covariant TextRun? before, - covariant TextRun? after, int index) { - textRuns.insert(index, run); - } - - void _removeRunAt(int index) { - var run = textRuns[index]; - removeRun(run, index); - } - - void _insertRun(int index, TextRun run) { - TextRun? before, after; - if (index > 0 && index <= textRuns.length) { - before = textRuns[index - 1]; - } - if (index < textRuns.length) { - after = textRuns[index]; - } - - insertRun(run, before, after, index); - } - - /// Resets everything to just the [text] with the [run]. - void setAll(String text, TextRun run) { - run.textLength = text.length; - while (textRuns.isNotEmpty) { - _removeRunAt(0); - } - _insertRun(0, run); - textCodes.clear(); - textCodes.insertAll(0, text.codeUnits); - _validateTextRuns(); - _dirty = true; - } - -// Lambda returns a new TextRun, or null to indicated that the run -// assed in need not be changed. - void modifyRuns(int start, int end, TextRunMutator mutator) { - assert(start >= 0 && start <= end); - assert(end <= textCodes.length); - int modLength = end - start; - if (modLength == 0) { - return; // snothing to modify - } - - final first = _findRunIndexOffset(start); - int trunIndex = first[0]; - int globalOffset = first[1]; - assert(globalOffset < textCodes.length); - - // Handle splitting the first run - if (start > globalOffset) { - TextRun origRun = textRuns[trunIndex]; - TextRun newRun = mutator(origRun); - if (origRun != newRun) { - final int skipLength = start - globalOffset; - newRun.textLength = origRun.textLength - skipLength; - origRun.textLength = skipLength; - _insertRun(++trunIndex, newRun); - trunsChanged(); - if (newRun.textLength > modLength) { - // oops, need to trim and readd oldRun afterwards - origRun = origRun.cloneRun(); - origRun.textLength = newRun.textLength - modLength; - newRun.textLength = modLength; - _insertRun(++trunIndex, origRun); - return; - } - modLength -= newRun.textLength; - } - trunIndex += 1; - } - - // Replace whole runs? - while (modLength > 0 && modLength >= textRuns[trunIndex].textLength) { - TextRun origRun = textRuns[trunIndex]; - modLength -= origRun.textLength; - TextRun newRun = mutator(origRun); - if (origRun != newRun) { - removeRun(origRun, trunIndex); - _insertRun(trunIndex, newRun); - trunsChanged(); - } - trunIndex += 1; - } - - // Trim the last run? - if (modLength > 0) { - TextRun origRun = textRuns[trunIndex]; - assert(modLength < origRun.textLength); - TextRun newRun = mutator(origRun); - if (origRun != newRun) { - newRun.textLength = modLength; - origRun.textLength -= modLength; - _insertRun(trunIndex, newRun); - trunsChanged(); - } - } - -// HOW CAN WE COMPARE RUNS? - if (false) { - // consolidate equal runs... - for (int i = 1; i < textRuns.length; ++i) { - if (textRuns[i - 1] == textRuns[i]) { - textRuns[i - 1].textLength += textRuns[i].textLength; - var run = textRuns[i - 1]; - _removeRunAt(i); - i -= 1; // to undo the loop's ++i - } - } - } - } - - void visitGlyphs(GlyphRunVisitor visitor) { - _ensureShapedLines(); - - for (final GlyphLine line in _lines) { - int start = line.startIndex; - for (int i = line.startRun; i <= line.wsRun; ++i) { - final run = _runs[i]; - int wsEnd = run.glyphs.length; - if (i == line.wsRun) { - // last run on this line - wsEnd = line.wsIndex; - } - visitor(run, start, wsEnd, _frame.left - line.startX, line.baseline); - start = 0; - } - } - } - - List rawGlyphRuns() { - _ensureShapedLines(); - return _runs; - } - - void visitText(TextRunVisitor visitor) { - textRuns.forEach(visitor); - } - - Rect offsetsToRect(GlyphLine line, int start, int end) { - assert(start >= line.textStart); - assert(end <= line.textEnd); - final double left = offsetToFrameX(line, start); - final double right = offsetToFrameX(line, end); - return Rect.fromLTRB(left, line.top, right, line.bottom); - } - - int xyToOffset(double x, double y) { - // ignore: parameter_assignments - x = pin(_frame.left, _frame.right, x); - // ignore: parameter_assignments - y = pin(_lines.first.top, _lines.last.bottom, y); - - // move x into xpos coordinates - // ignore: parameter_assignments - x -= _frame.left; - - for (final GlyphLine line in _lines) { - if (y <= line.bottom) { - // ignore: parameter_assignments - x += line.startX; // now we're relative to the xpos in this line - GlyphRun run = line.runs.last; - for (final GlyphRun r in line.runs) { - if (x < r.right) { - run = r; - break; - } - } - int index = run.xpos.length - 1; - for (int i = 1; i < run.xpos.length; ++i) { - if (x < run.xpos[i]) { - final mid = (run.xpos[i] + run.xpos[i - 1]) * 0.5; - index = x < mid ? i - 1 : i; - break; - } - } - return run.textStart + index; - } - } - assert(false); - return 0; - } - - VBar getVBar(int textOffset, LinePref pref) { - final line = offsetToLine(textOffset, pref); - final x = offsetToFrameX(line, textOffset); - return VBar(x, line.top, line.bottom); - } -} - -///////////////////// - -enum CursorType { - line, - path, -} - -class Cursor { - Paragraph para; - // these are logical, not necessarily sorted - int _start = 0; - int _end = 0; - - Cursor(this.para); - - CursorType get type { - return _start == _end ? CursorType.line : CursorType.path; - } - - String get text => - String.fromCharCodes(para.textCodes.sublist(fromIndex, toIndex)); - - int get start { - return _start; - } - - int get end { - return _end; - } - - int get fromIndex { - return math.min(_start, _end); - } - - int get toIndex { - return math.max(_start, _end); - } - - bool get isCollapsed => _start == _end; - - int _legalize(int index) { - return math.max(math.min(index, para.textLength), 0); - } - - void setIndex(int index) { - setRange(index, index); - } - - void setRange(int start, int end) { - _start = _legalize(start); - _end = _legalize(end); - } - - void insert(String str) { - final int from = fromIndex; - para.delete(from, toIndex); - _start = _end = from + para.insert(from, str); - } - - void delete() { - if (_start == _end) { - if (_start > 0) { - para.delete(_start - 1, _start); - _start = _end = _start - 1; - } - } else { - para.delete(fromIndex, toIndex); - _start = _end = fromIndex; - } - } - - void arrowLeft(bool extend) { - if (extend) { - _end = _legalize(_end - 1); - } else { - if (_start == _end) { - _start = _end = _legalize(_end - 1); - } - _start = _end = fromIndex; - } - } - // todo: need to not pre-swap _start and _end - - void arrowRight(bool extend) { - if (extend) { - _end = _legalize(_end + 1); - } else { - if (_start == _end) { - _start = _end = _legalize(_end + 1); - } else { - _start = _end = toIndex; - } - } - } - - void arrowUp(bool extend) { - LinePref pref = LinePref.end; // store this somehow? - - int index = para.offsetToLineIndex(_end, pref); - if (index == 0) { - _end = 0; - } else { - final double currX = para.offsetToFrameX(para._lines[index], _end); - { - int i = para.xyToOffset(currX, para._lines[index].baseline); - assert(i == _end); - } - index -= 1; - _end = para.xyToOffset(currX, para._lines[index].baseline); - } - if (!extend) { - _start = _end; - } - } - - void arrowDown(bool extend) { - LinePref pref = LinePref.end; // store this somehow? - - int index = para.offsetToLineIndex(_end, pref); - if (index == para._lines.length - 1) { - _end = para.textLength; - } else { - final double currX = para.offsetToFrameX(para._lines[index], _end); - index += 1; - _end = para.xyToOffset(currX, para._lines[index].baseline); - } - if (!extend) { - _start = _end; - } - } - - void pointerDown(double x, double y) { - // ignore: parameter_assignments - x = pin(para.frame.left, para.frame.right, x); - // ignore: parameter_assignments - y = pin(para.frame.top, para.frame.bottom, y); - _start = _end = para.xyToOffset(x, y); - } - - bool pointerMove(double x, double y) { - final newEnd = para.xyToOffset(x, y); - final changed = _end != newEnd; - _end = newEnd; - return changed; - } - - void pointerUp(double x, double y) {} - - // PointerTracker pointerTracker(double x, double y) { - // final t = _CursorPointerTracker(this); - // t.down(x, y); - // return t; - // } - - void modifyRuns(TextRunMutator mutator) { - para.modifyRuns(fromIndex, toIndex, mutator); - } - - VBar getVBar(LinePref pref) { - return para.getVBar(_end, pref); - } - - RawPath getRawPath([LinePref pref = LinePref.end]) { - final b = RawPathBuilder(); - if (type == CursorType.line) { - final bar = getVBar(pref); - const width = 1.0; - b.addLTRB(bar.x, bar.top, bar.x + width, bar.bottom); - } else { - final int from = fromIndex; - final int to = toIndex; - int index = para.offsetToLineIndex(from, LinePref.start); - int last = para.offsetToLineIndex(to, LinePref.end); - if (index == last) { - GlyphLine line = para.lines[index]; - b.addRect(para.offsetsToRect(line, from, to)); - } else { - GlyphLine line = para.lines[index]; - b.addRect(para.offsetsToRect(line, from, line.textEnd)); - while (++index < last) { - line = para.lines[index]; - b.addRect(para.offsetsToRect(line, line.textStart, line.textEnd)); - } - line = para.lines[last]; - b.addRect(para.offsetsToRect(line, line.textStart, to)); - } - } - return b.detach(); - } -} - -class SimpleParagraph extends Paragraph { - final List _textCodes = []; - final List _truns = []; - - @override - List get textCodes => _textCodes; - - @override - List get textRuns => _truns; -} diff --git a/lib/src/rive_core/src/text/raw_path.dart b/lib/src/rive_core/src/text/raw_path.dart deleted file mode 100644 index 697b9fe..0000000 --- a/lib/src/rive_core/src/text/raw_path.dart +++ /dev/null @@ -1,149 +0,0 @@ -import 'dart:typed_data'; -import 'package:flutter/material.dart'; - -const int kMove_PathVerb = 0; -const int kLine_PathVerb = 1; -const int kQuad_PathVerb = 2; -const int kConic_PathVerb = 3; -const int kCubic_PathVerb = 4; -const int kClose_PathVerb = 5; - -class IPathSink { - void moveTo(double x, double y) {} - void lineTo(double x, double y) {} - void quadTo(double x, double y, double x1, double y1) {} - void cubicTo( - double x, double y, double x1, double y1, double x2, double y2) {} - void close() {} -} - -class RawPath { - Float32List pts; - Uint8List verbs; - - RawPath(this.pts, this.verbs); - - void sinker( - Function(double, double) moveTo, - Function(double, double) lineTo, - Function(double, double, double, double) quadTo, - Function(double, double, double, double, double, double) cubicTo, - Function close) { - int i = 0; - for (final int verb in verbs) { - switch (verb) { - case kMove_PathVerb: - moveTo(pts[i + 0], pts[i + 1]); - i += 2; - break; - case kLine_PathVerb: - lineTo(pts[i + 0], pts[i + 1]); - i += 2; - break; - case kQuad_PathVerb: - quadTo(pts[i + 0], pts[i + 1], pts[i + 2], pts[i + 3]); - i += 4; - break; - case kConic_PathVerb: // not supported - assert(false); - break; - case kCubic_PathVerb: - cubicTo(pts[i + 0], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], - pts[i + 5]); - i += 6; - break; - case kClose_PathVerb: - close(); - break; - default: - throw 'unknown verb $verb'; - } - } - assert(i == pts.length); - } - - RawPath scalexy(double sx, double sy, double tx, double ty) { - final newp = Float32List(pts.length); - for (int i = 0; i < pts.length; i += 2) { - newp[i + 0] = pts[i + 0] * sx + tx; - newp[i + 1] = pts[i + 1] * sy + ty; - } - // we share verbs to save memory -- so don't modify them! - return RawPath(Float32List.fromList(newp), verbs); - } -} - -class RawPathBuilder { - List pts = []; - List vbs = []; - - void reset() { - pts = []; - vbs = []; - } - - double get lastX { - return pts[pts.length - 2]; - } - - double get lastY { - return pts[pts.length - 1]; - } - - void moveTo(double x, double y) { - pts.add(x); - pts.add(y); - vbs.add(kMove_PathVerb); - } - - void lineTo(double x, double y) { - pts.add(x); - pts.add(y); - vbs.add(kLine_PathVerb); - } - - void quadTo(double x, double y, double x1, double y1) { - pts.add(x); - pts.add(y); - pts.add(x1); - pts.add(y1); - vbs.add(kQuad_PathVerb); - } - - void cubicTo(double x, double y, double x1, double y1, double x2, double y2) { - pts.add(x); - pts.add(y); - pts.add(x1); - pts.add(y1); - pts.add(x2); - pts.add(y2); - vbs.add(kCubic_PathVerb); - } - - void close() { - vbs.add(kClose_PathVerb); - } - - void addLine(double x0, double y0, double x1, double y1) { - moveTo(x0, y0); - lineTo(x1, y1); - } - - void addLTRB(double l, double t, double r, double b) { - moveTo(l, t); - lineTo(r, t); - lineTo(r, b); - lineTo(l, b); - close(); - } - - void addRect(Rect r) { - addLTRB(r.left, r.top, r.right, r.bottom); - } - - RawPath detach() { - final rp = RawPath(Float32List.fromList(pts), Uint8List.fromList(vbs)); - reset(); - return rp; - } -} diff --git a/lib/src/rive_core/src/text/rive_font.dart b/lib/src/rive_core/src/text/rive_font.dart deleted file mode 100644 index 5611141..0000000 --- a/lib/src/rive_core/src/text/rive_font.dart +++ /dev/null @@ -1,255 +0,0 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:flutter/material.dart'; -import 'package:rive/src/rive_core/src/text/built_in_font.dart'; - -import 'raw_path.dart'; - -// for diagnostic/debugging purposes -const bool enableFontDump = false; - -class Reader { - ByteData data; - int offset = 0; - - Reader(this.data); - - int u8() { - offset += 1; - return data.getUint8(offset - 1); - } - - int s16() { - offset += 2; - return data.getInt16(offset - 2, Endian.little); - } - - int u16() { - offset += 2; - return data.getUint16(offset - 2, Endian.little); - } - - int u32() { - offset += 4; - return data.getUint32(offset - 4, Endian.little); - } - - void skipPad16() { - offset += offset & 1; - } - - Uint8List u8list(int count) { - offset += count; - return Uint8List.sublistView(data, offset - count, offset); - } - - int available() { - return data.lengthInBytes - offset; - } - - bool eof() { - return offset == data.lengthInBytes; - } -} - -int Tag(int a, int b, int c, int d) { - return (a << 24) | (b << 16) | (c << 8) | d; -} - -String fromTag(int tag) { - final int a = (tag >> 24) & 0xFF; - final int b = (tag >> 16) & 0xFF; - final int c = (tag >> 8) & 0xFF; - final int d = (tag >> 0) & 0xFF; - return '' + - String.fromCharCode(a) + - String.fromCharCode(b) + - String.fromCharCode(c) + - String.fromCharCode(d); -} - -const int kCMap_TableTag = 1668112752; // cmap -const int kAdvances_TableTag = 1751213174; // hadv -const int kInfo_TableTag = 1768842863; // info -const int kPaths_TableTag = 1885434984; // path -const int kOffsets_TableTag = 1886348902; // poff - -ByteData find_table(List dir, int tag, ByteData data) { - for (int i = 0; i < dir.length; i += 3) { - if (dir[i] == tag) { - return ByteData.view(data.buffer, dir[i + 1], dir[i + 2]); - } - } - throw 'missing ${fromTag(tag)} table'; -} - -class RiveFont { - final double _ascent = -0.9; // TODO: get from file - final double _descent = 0.2; // TODO: get from file - - final _cmap = {}; - final _advances = []; - final _rawpaths = []; - - RiveFont() { - _advances.add(0); - _rawpaths.add(null); - } - - double get ascent { - return _ascent; - } - - double get descent { - return _descent; - } - - double get height { - return _descent - _ascent; - } - - int charToGlyph(int charCode) { - int? glyph = _cmap[charCode]; - return glyph ?? 0; - } - - double getAdvance(int glyph) { - return _advances[glyph]; - } - - Path? getPath(int glyph) { - final rp = getRawPath(glyph); - if (rp != null) { - Path p = Path(); - rp.sinker(p.moveTo, p.lineTo, p.quadraticBezierTo, p.cubicTo, p.close); - return p; - } - return null; - } - - RawPath? getRawPath(int glyph) { - return _rawpaths[glyph]; - } - - Uint16List textToGlyphs(List chars, int start, int end) { - final int n = end - start; - Uint16List glyphs = Uint16List(n); - for (int i = 0; i < n; ++i) { - glyphs[i] = charToGlyph(chars[i + start]); - } - return glyphs; - } - - Float32List getAdvances(Uint16List glyphs) { - Float32List advances = Float32List(glyphs.length); - for (int i = 0; i < glyphs.length; ++i) { - advances[i] = getAdvance(glyphs[i]); - } - return advances; - } - - void _build_cmap(int glyphCount, ByteData cmapD) { - final reader = Reader(cmapD); - final int count = reader.u16(); - if (enableFontDump) { - print('cmap has $count entries'); - } - for (int i = 0; i < count; ++i) { - final int charCode = reader.u16(); - final int glyphID = reader.u16(); - assert(glyphID < glyphCount); - _cmap.putIfAbsent(charCode, () => glyphID); - } - } - - void _build_advances(int glyphCount, double scale, ByteData advD) { - assert(advD.lengthInBytes == glyphCount * 2); - final advances = Reader(advD); - for (int i = 0; i < glyphCount; ++i) { - _advances.add(advances.u16() * scale); - } - } - - RawPath _build_rawpath(double scale, ByteData pathD) { - final reader = Reader(pathD); - - final int verbCount = reader.u16(); - assert(verbCount > 0); - final int pointCount = reader.u16(); - final Float32List pts = Float32List(pointCount * 2); - - final verbs = reader.u8list(verbCount); - reader.skipPad16(); - for (int i = 0; i < pointCount * 2; ++i) { - pts[i] = reader.s16() * scale; - } - assert(reader.eof()); - return RawPath(pts, verbs); - } - - void _build_rawpaths( - int glyphCount, double scale, ByteData offD, ByteData pathD) { - final offsets = Reader(offD); - int start = offsets.u32(); - for (int i = 0; i < glyphCount; ++i) { - int end = offsets.u32(); - assert(start <= end); - - RawPath? path; - if (start < end) { - path = _build_rawpath(scale, ByteData.sublistView(pathD, start, end)); - } - _rawpaths.add(path); - - start = end; - } - } - - RiveFont.fromBinary(ByteData data) { - final Reader reader = Reader(data); - - { - int signature = reader.u32(); - int version = reader.u32(); - assert(signature == 0x23581321); - assert(version == 1); - } - final int tableCount = reader.u32(); - if (enableFontDump) { - print('tables $tableCount'); - } - - final List dir = []; - for (int i = 0; i < tableCount; ++i) { - int tag = reader.u32(); - int off = reader.u32(); - int len = reader.u32(); - if (enableFontDump) { - print('tag: ${fromTag(tag)} offset:$off length:$len'); - } - dir.add(tag); // tag - dir.add(off); // offset - dir.add(len); // length - } - - final infoReader = Reader(find_table(dir, kInfo_TableTag, data)); - final int glyphCount = infoReader.u16(); - final int upem = infoReader.u16(); - final double scale = 1.0 / upem; - if (enableFontDump) { - print('glyphs $glyphCount, upem $upem'); - } - - _build_cmap(glyphCount, find_table(dir, kCMap_TableTag, data)); - - _build_advances( - glyphCount, scale, find_table(dir, kAdvances_TableTag, data)); - - _build_rawpaths(glyphCount, scale, find_table(dir, kOffsets_TableTag, data), - find_table(dir, kPaths_TableTag, data)); - } - - static final builtIn = RiveFont.fromBinary( - ByteData.view(const Base64Decoder().convert(builtInFontBase64).buffer)); -} diff --git a/lib/src/rive_core/src/text/shape_text.dart b/lib/src/rive_core/src/text/shape_text.dart deleted file mode 100644 index 8e646bf..0000000 --- a/lib/src/rive_core/src/text/shape_text.dart +++ /dev/null @@ -1,252 +0,0 @@ -import 'dart:typed_data'; - -import 'rive_font.dart'; - -abstract class TextRun { - RiveFont get font; - double get pointSize; - int get textLength; - set textLength(int value); - - TextRun cloneRun(); -} - -class GlyphRun { - TextRun textRun; // the run this glyph run was generated from - RiveFont font; // possibly different from TextRun (substitution) - double pointSize; // possibly different from TextRun - - int textOffset; - Uint16List glyphs; - Float32List xpos; // #glyphs + 1 - - GlyphRun( - this.textRun, - this.font, - this.pointSize, - this.textOffset, - this.glyphs, - this.xpos, - ) { - assert(glyphs.length + 1 == xpos.length); - } - - double get left { - return xpos.first; - } - - double get right { - return xpos.last; - } - - double get width { - return right - left; - } - - int get textStart { - return textOffset; - } - - int get textEnd { - return textOffset + glyphs.length; - } - - static bool ws(int code) { - return code <= 32; - } - - static List shapeText(List chars, List textRuns) { - final glyphRuns = []; - int offset = 0; - double x = 0; - - for (final TextRun run in textRuns) { - if (run.textLength > 0) { - final glyphs = - run.font.textToGlyphs(chars, offset, offset + run.textLength); - final advances = run.font.getAdvances(glyphs); - final int n = glyphs.length; - final xpos = Float32List(n + 1); - for (int i = 0; i < n; ++i) { - xpos[i] = x; - x += advances[i] * run.pointSize; - } - xpos[n] = x; - glyphRuns - .add(GlyphRun(run, run.font, run.pointSize, offset, glyphs, xpos)); - offset += run.textLength; - } - } - return glyphRuns; - } - - static List findWordBreaks(List chars) { - List breaks = []; - for (int i = 0; i < chars.length;) { - // skip ws - while (i < chars.length && ws(chars[i])) { - ++i; - } - breaks.add(i); // word start - // skip non-ws - while (i < chars.length && !ws(chars[i])) { - ++i; - } - breaks.add(i); // word end - } - assert(breaks.last == chars.length); - return breaks; - } - - int offsetToIndex(int offset) { - assert(textOffset <= offset); - assert(offset - textOffset <= glyphs.length); - return offset - textOffset; - } -} - -class GlyphLine { - List runs; - int startRun; - int startIndex; - int endRun; - int endIndex; - int wsRun; - int wsIndex; - double startX; - double top = 0, baseline = 0, bottom = 0; - - void validate() { - void val(int r, int i) { - final run = runs[r]; - assert(i >= 0 && i <= run.glyphs.length); - } - - val(startRun, startIndex); - val(endRun, endIndex); - val(wsRun, wsIndex); - assert(startRun < endRun || (startRun == endRun && startIndex <= endIndex)); - assert(endRun < wsRun || (endRun == wsRun && endIndex <= wsIndex)); - } - - GlyphLine(this.runs, this.startRun, this.startIndex, this.endRun, - this.endIndex, this.wsRun, this.wsIndex, this.startX); - - int get textStart { - return runs[startRun].textStart + startIndex; - } - - int get textEnd { - return runs[wsRun].textStart + wsIndex; - } - - double offsetToX(int textOffset) { - assert(textOffset <= runs[endRun].textEnd); - for (int i = startRun; i <= endRun; ++i) { - final run = runs[i]; - if (textOffset <= run.textEnd) { - return run.xpos[textOffset - run.textStart] - startX; - } - } - assert(false); - return 0; - } - - static int _offsetToRunIndex( - List runs, int offset, int charLength) { - assert(offset >= 0); - for (int i = 1; i < runs.length; ++i) { - final run = runs[i]; - if (run.textOffset >= offset) { - return i - 1; - } - } - return runs.length - 1; - } - - static List lineBreak( - List chars, List breaks, List runs, double width) { - List lines = []; - int startRun = 0; - int startIndex = 0; - double xlimit = width; - - int prevRun = 0; - int prevIndex = 0; - - int wordStart = breaks[0]; - int wordEnd = breaks[1]; - int nextBreakIndex = 2; - int lineStartTextOffset = wordStart; - - for (;;) { - assert(wordStart <= wordEnd); // == means trailing spaces? - - int endRun = _offsetToRunIndex(runs, wordEnd, chars.length); - int endIndex = runs[endRun].offsetToIndex(wordEnd); - double pos = runs[endRun].xpos[endIndex]; - bool bumpBreakIndex = true; - if (pos > xlimit) { - int wsRun = _offsetToRunIndex(runs, wordStart, chars.length); - int wsIndex = runs[wsRun].offsetToIndex(wordStart); - - bumpBreakIndex = false; - // does just one word not fit? - if (lineStartTextOffset == wordStart) { - // walk backwards a letter at a time until we fit, stopping at - // 1 letter. - int wend = wordEnd; - while (pos > xlimit && wend - 1 > wordStart) { - wend -= 1; - prevRun = _offsetToRunIndex(runs, wend, chars.length); - prevIndex = runs[prevRun].offsetToIndex(wend); - pos = runs[prevRun].xpos[prevIndex]; - } - assert(wend < wordEnd || wend == wordEnd && wordStart + 1 == wordEnd); - if (wend == wordEnd) { - bumpBreakIndex = true; - } - - // now reset our "whitespace" marker to just be prev, since - // by defintion we have no extra whitespace on this line - wsRun = prevRun; - wsIndex = prevIndex; - wordStart = wend; - } - - // bulid the line - final lineStartX = runs[startRun].xpos[startIndex]; - lines.add(GlyphLine(runs, startRun, startIndex, prevRun, prevIndex, - wsRun, wsIndex, lineStartX)); - - // update for the next line - xlimit = runs[wsRun].xpos[wsIndex] + width; - startRun = prevRun = wsRun; - startIndex = prevIndex = wsIndex; - lineStartTextOffset = wordStart; - } else { - // we didn't go too far, so remember this word-end boundary - prevRun = endRun; - prevIndex = endIndex; - } - - if (bumpBreakIndex) { - if (nextBreakIndex < breaks.length) { - wordStart = breaks[nextBreakIndex++]; - wordEnd = breaks[nextBreakIndex++]; - } else { - break; // bust out of the loop - } - } - } - // scoop up the last line (if present) - final int tailRun = runs.length - 1; - final int tailIndex = runs[tailRun].glyphs.length; - if (startRun != tailRun || startIndex != tailIndex) { - final double startX = runs[startRun].xpos[startIndex]; - lines.add(GlyphLine(runs, startRun, startIndex, tailRun, tailIndex, - tailRun, tailIndex, startX)); - } - return lines; - } -} diff --git a/lib/src/rive_core/state_machine_controller.dart b/lib/src/rive_core/state_machine_controller.dart index 12378d6..3f56168 100644 --- a/lib/src/rive_core/state_machine_controller.dart +++ b/lib/src/rive_core/state_machine_controller.dart @@ -217,7 +217,7 @@ class StateMachineController extends RiveAnimationController { /// Handles state change callbacks void _onStateChange(LayerState layerState) => - SchedulerBinding.instance.addPostFrameCallback((_) { + SchedulerBinding.instance?.addPostFrameCallback((_) { String stateName = 'unknown'; if (layerState is AnimationState && layerState.animation != null) { stateName = layerState.animation!.name; diff --git a/lib/src/rive_render_box.dart b/lib/src/rive_render_box.dart index 8a7994a..1cd3ebe 100644 --- a/lib/src/rive_render_box.dart +++ b/lib/src/rive_render_box.dart @@ -187,7 +187,7 @@ abstract class RiveRenderBox extends RenderBox { return; } _frameCallbackId = - SchedulerBinding.instance.scheduleFrameCallback(_frameCallback); + SchedulerBinding.instance?.scheduleFrameCallback(_frameCallback) ?? -1; } /// Override this if you want to do custom viewTransform alignment. This will