Fixes for pub publish to remove all warnings.

This commit is contained in:
Luigi Rosso
2022-03-15 19:59:23 -07:00
parent fd3c3abe91
commit 2fe38ca337
10 changed files with 3 additions and 1348 deletions

View File

@ -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());
}
}

View File

@ -21,7 +21,6 @@ class Mesh extends MeshBase with Skinnable<MeshVertex> {
// be in world space.
final List<MeshVertex> _vertices = [];
@override
List<MeshVertex> get vertices => _vertices;
ui.Vertices? _uiVertices;
@ -153,7 +152,6 @@ class Mesh extends MeshBase with Skinnable<MeshVertex> {
return super.addDirt(value, recurse: recurse);
}
@override
Mat2D get worldTransform =>
skin != null ? Mat2D.identity : transformComponent.worldTransform;

View File

@ -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();

File diff suppressed because one or more lines are too long

View File

@ -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<int> get textCodes;
List<TextRun> get textRuns;
// cached output
List<GlyphRun> _runs = [];
List<GlyphLine> _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<GlyphLine> 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<int> _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<GlyphRun> 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<int> _textCodes = [];
final List<TextRun> _truns = [];
@override
List<int> get textCodes => _textCodes;
@override
List<TextRun> get textRuns => _truns;
}

View File

@ -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<double> pts = [];
List<int> 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;
}
}

View File

@ -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<int> 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 = <int, int>{};
final _advances = <double>[];
final _rawpaths = <RawPath?>[];
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<int> 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<int> 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));
}

View File

@ -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<GlyphRun> shapeText(List<int> chars, List<TextRun> textRuns) {
final glyphRuns = <GlyphRun>[];
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<int> findWordBreaks(List<int> chars) {
List<int> 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<GlyphRun> 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<GlyphRun> 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<GlyphLine> lineBreak(
List<int> chars, List<int> breaks, List<GlyphRun> runs, double width) {
List<GlyphLine> 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;
}
}

View File

@ -217,7 +217,7 @@ class StateMachineController extends RiveAnimationController<CoreContext> {
/// 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;

View File

@ -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