Unverified Commit 9cc72df7 authored by Pierre-Louis's avatar Pierre-Louis Committed by GitHub

Use `curly_braces_in_flow_control_structures` for `foundation`, `gestures`,...

Use `curly_braces_in_flow_control_structures` for `foundation`, `gestures`, `painting`, `physics` (#104610)

* Use `curly_braces_in_flow_control_structures` for `foundation`

* Use `curly_braces_in_flow_control_structures` for `gestures`

* Use `curly_braces_in_flow_control_structures` for `painting`

* Use `curly_braces_in_flow_control_structures` for `physics`

* fix comments

* remove trailing space

* fix TODO style
parent 2b14e993
...@@ -37,10 +37,11 @@ class BitField<T extends dynamic> implements bitfield.BitField<T> { ...@@ -37,10 +37,11 @@ class BitField<T extends dynamic> implements bitfield.BitField<T> {
void operator []=(T index, bool value) { void operator []=(T index, bool value) {
final int intIndex = index.index as int; final int intIndex = index.index as int;
assert(intIndex < _length); assert(intIndex < _length);
if (value) if (value) {
_bits = _bits | (1 << intIndex); _bits = _bits | (1 << intIndex);
else } else {
_bits = _bits & ~(1 << intIndex); _bits = _bits & ~(1 << intIndex);
}
} }
@override @override
......
...@@ -23,12 +23,14 @@ platform.TargetPlatform get defaultTargetPlatform { ...@@ -23,12 +23,14 @@ platform.TargetPlatform get defaultTargetPlatform {
result = platform.TargetPlatform.windows; result = platform.TargetPlatform.windows;
} }
assert(() { assert(() {
if (Platform.environment.containsKey('FLUTTER_TEST')) if (Platform.environment.containsKey('FLUTTER_TEST')) {
result = platform.TargetPlatform.android; result = platform.TargetPlatform.android;
}
return true; return true;
}()); }());
if (platform.debugDefaultTargetPlatformOverride != null) if (platform.debugDefaultTargetPlatformOverride != null) {
result = platform.debugDefaultTargetPlatformOverride; result = platform.debugDefaultTargetPlatformOverride;
}
if (result == null) { if (result == null) {
throw FlutterError( throw FlutterError(
'Unknown platform.\n' 'Unknown platform.\n'
......
...@@ -622,8 +622,9 @@ class FlutterErrorDetails with Diagnosticable { ...@@ -622,8 +622,9 @@ class FlutterErrorDetails with Diagnosticable {
longMessage = ' $exception'; longMessage = ' $exception';
} }
longMessage = longMessage.trimRight(); longMessage = longMessage.trimRight();
if (longMessage.isEmpty) if (longMessage.isEmpty) {
longMessage = ' <no message available>'; longMessage = ' <no message available>';
}
return longMessage; return longMessage;
} }
...@@ -690,8 +691,9 @@ class FlutterErrorDetails with Diagnosticable { ...@@ -690,8 +691,9 @@ class FlutterErrorDetails with Diagnosticable {
// strip out that header when we see it. // strip out that header when we see it.
final String prefix = '${exception.runtimeType}: '; final String prefix = '${exception.runtimeType}: ';
String message = exceptionAsString(); String message = exceptionAsString();
if (message.startsWith(prefix)) if (message.startsWith(prefix)) {
message = message.substring(prefix.length); message = message.substring(prefix.length);
}
properties.add(ErrorSummary(message)); properties.add(ErrorSummary(message));
} }
} }
...@@ -1002,8 +1004,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti ...@@ -1002,8 +1004,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
return true; return true;
}()); }());
final bool reportError = isInDebugMode || details.silent != true; // could be null final bool reportError = isInDebugMode || details.silent != true; // could be null
if (!reportError && !forceReport) if (!reportError && !forceReport) {
return; return;
}
if (_errorCount == 0 || forceReport) { if (_errorCount == 0 || forceReport) {
// Diagnostics is only available in debug mode. In profile and release modes fallback to plain print. // Diagnostics is only available in debug mode. In profile and release modes fallback to plain print.
if (isInDebugMode) { if (isInDebugMode) {
...@@ -1115,8 +1118,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti ...@@ -1115,8 +1118,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
if (skipped == 1) { if (skipped == 1) {
result.add('(elided one frame from ${where.single})'); result.add('(elided one frame from ${where.single})');
} else if (skipped > 1) { } else if (skipped > 1) {
if (where.length > 1) if (where.length > 1) {
where[where.length - 1] = 'and ${where.last}'; where[where.length - 1] = 'and ${where.last}';
}
if (where.length > 2) { if (where.length > 2) {
result.add('(elided $skipped frames from ${where.join(", ")})'); result.add('(elided $skipped frames from ${where.join(", ")})');
} else { } else {
...@@ -1190,8 +1194,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti ...@@ -1190,8 +1194,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
/// ///
/// The `label` argument, if present, will be printed before the stack. /// The `label` argument, if present, will be printed before the stack.
void debugPrintStack({StackTrace? stackTrace, String? label, int? maxFrames}) { void debugPrintStack({StackTrace? stackTrace, String? label, int? maxFrames}) {
if (label != null) if (label != null) {
debugPrint(label); debugPrint(label);
}
if (stackTrace == null) { if (stackTrace == null) {
stackTrace = StackTrace.current; stackTrace = StackTrace.current;
} else { } else {
...@@ -1208,8 +1213,9 @@ void debugPrintStack({StackTrace? stackTrace, String? label, int? maxFrames}) { ...@@ -1208,8 +1213,9 @@ void debugPrintStack({StackTrace? stackTrace, String? label, int? maxFrames}) {
line.contains('dart:sdk_internal'); line.contains('dart:sdk_internal');
}); });
} }
if (maxFrames != null) if (maxFrames != null) {
lines = lines.take(maxFrames); lines = lines.take(maxFrames);
}
debugPrint(FlutterError.defaultStackFilter(lines).join('\n')); debugPrint(FlutterError.defaultStackFilter(lines).join('\n'));
} }
...@@ -1252,8 +1258,9 @@ class DiagnosticsStackTrace extends DiagnosticsBlock { ...@@ -1252,8 +1258,9 @@ class DiagnosticsStackTrace extends DiagnosticsBlock {
StackTrace? stack, StackTrace? stack,
IterableFilter<String>? stackFilter, IterableFilter<String>? stackFilter,
) { ) {
if (stack == null) if (stack == null) {
return <DiagnosticsNode>[]; return <DiagnosticsNode>[];
}
final IterableFilter<String> filter = stackFilter ?? FlutterError.defaultStackFilter; final IterableFilter<String> filter = stackFilter ?? FlutterError.defaultStackFilter;
final Iterable<String> frames = filter('${FlutterError.demangleStackTrace(stack)}'.trimRight().split('\n')); final Iterable<String> frames = filter('${FlutterError.demangleStackTrace(stack)}'.trimRight().split('\n'));
return frames.map<DiagnosticsNode>(_createStackFrame).toList(); return frames.map<DiagnosticsNode>(_createStackFrame).toList();
......
...@@ -191,8 +191,9 @@ class CachingIterable<E> extends IterableBase<E> { ...@@ -191,8 +191,9 @@ class CachingIterable<E> extends IterableBase<E> {
} }
bool _fillNext() { bool _fillNext() {
if (!_prefillIterator.moveNext()) if (!_prefillIterator.moveNext()) {
return false; return false;
}
_results.add(_prefillIterator.current); _results.add(_prefillIterator.current);
return true; return true;
} }
...@@ -207,18 +208,21 @@ class _LazyListIterator<E> implements Iterator<E> { ...@@ -207,18 +208,21 @@ class _LazyListIterator<E> implements Iterator<E> {
@override @override
E get current { E get current {
assert(_index >= 0); // called "current" before "moveNext()" assert(_index >= 0); // called "current" before "moveNext()"
if (_index < 0 || _index == _owner._results.length) if (_index < 0 || _index == _owner._results.length) {
throw StateError('current can not be call after moveNext has returned false'); throw StateError('current can not be call after moveNext has returned false');
}
return _owner._results[_index]; return _owner._results[_index];
} }
@override @override
bool moveNext() { bool moveNext() {
if (_index >= _owner._results.length) if (_index >= _owner._results.length) {
return false; return false;
}
_index += 1; _index += 1;
if (_index == _owner._results.length) if (_index == _owner._results.length) {
return _owner._fillNext(); return _owner._fillNext();
}
return true; return true;
} }
} }
......
...@@ -827,8 +827,9 @@ abstract class BindingBase { ...@@ -827,8 +827,9 @@ abstract class BindingBase {
developer.registerExtension(methodName, (String method, Map<String, String> parameters) async { developer.registerExtension(methodName, (String method, Map<String, String> parameters) async {
assert(method == methodName); assert(method == methodName);
assert(() { assert(() {
if (debugInstrumentationEnabled) if (debugInstrumentationEnabled) {
debugPrint('service extension method received: $method($parameters)'); debugPrint('service extension method received: $method($parameters)');
}
return true; return true;
}()); }());
......
...@@ -225,20 +225,23 @@ class ChangeNotifier implements Listenable { ...@@ -225,20 +225,23 @@ class ChangeNotifier implements Listenable {
final List<VoidCallback?> newListeners = List<VoidCallback?>.filled(_count, null); final List<VoidCallback?> newListeners = List<VoidCallback?>.filled(_count, null);
// Listeners before the index are at the same place. // Listeners before the index are at the same place.
for (int i = 0; i < index; i++) for (int i = 0; i < index; i++) {
newListeners[i] = _listeners[i]; newListeners[i] = _listeners[i];
}
// Listeners after the index move towards the start of the list. // Listeners after the index move towards the start of the list.
for (int i = index; i < _count; i++) for (int i = index; i < _count; i++) {
newListeners[i] = _listeners[i + 1]; newListeners[i] = _listeners[i + 1];
}
_listeners = newListeners; _listeners = newListeners;
} else { } else {
// When there are more listeners than half the length of the list, we only // When there are more listeners than half the length of the list, we only
// shift our listeners, so that we avoid to reallocate memory for the // shift our listeners, so that we avoid to reallocate memory for the
// whole list. // whole list.
for (int i = index; i < _count; i++) for (int i = index; i < _count; i++) {
_listeners[i] = _listeners[i + 1]; _listeners[i] = _listeners[i + 1];
}
_listeners[_count] = null; _listeners[_count] = null;
} }
} }
...@@ -319,8 +322,9 @@ class ChangeNotifier implements Listenable { ...@@ -319,8 +322,9 @@ class ChangeNotifier implements Listenable {
@pragma('vm:notify-debugger-on-exception') @pragma('vm:notify-debugger-on-exception')
void notifyListeners() { void notifyListeners() {
assert(debugAssertNotDisposed()); assert(debugAssertNotDisposed());
if (_count == 0) if (_count == 0) {
return; return;
}
// To make sure that listeners removed during this iteration are not called, // To make sure that listeners removed during this iteration are not called,
// we set them to null, but we don't shrink the list right away. // we set them to null, but we don't shrink the list right away.
...@@ -439,8 +443,9 @@ class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> { ...@@ -439,8 +443,9 @@ class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {
T get value => _value; T get value => _value;
T _value; T _value;
set value(T newValue) { set value(T newValue) {
if (_value == newValue) if (_value == newValue) {
return; return;
}
_value = newValue; _value = newValue;
notifyListeners(); notifyListeners();
} }
......
...@@ -20,15 +20,19 @@ ...@@ -20,15 +20,19 @@
/// * [listEquals], which does something similar for lists. /// * [listEquals], which does something similar for lists.
/// * [mapEquals], which does something similar for maps. /// * [mapEquals], which does something similar for maps.
bool setEquals<T>(Set<T>? a, Set<T>? b) { bool setEquals<T>(Set<T>? a, Set<T>? b) {
if (a == null) if (a == null) {
return b == null; return b == null;
if (b == null || a.length != b.length) }
if (b == null || a.length != b.length) {
return false; return false;
if (identical(a, b)) }
if (identical(a, b)) {
return true; return true;
}
for (final T value in a) { for (final T value in a) {
if (!b.contains(value)) if (!b.contains(value)) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -49,15 +53,19 @@ bool setEquals<T>(Set<T>? a, Set<T>? b) { ...@@ -49,15 +53,19 @@ bool setEquals<T>(Set<T>? a, Set<T>? b) {
/// * [setEquals], which does something similar for sets. /// * [setEquals], which does something similar for sets.
/// * [mapEquals], which does something similar for maps. /// * [mapEquals], which does something similar for maps.
bool listEquals<T>(List<T>? a, List<T>? b) { bool listEquals<T>(List<T>? a, List<T>? b) {
if (a == null) if (a == null) {
return b == null; return b == null;
if (b == null || a.length != b.length) }
if (b == null || a.length != b.length) {
return false; return false;
if (identical(a, b)) }
if (identical(a, b)) {
return true; return true;
}
for (int index = 0; index < a.length; index += 1) { for (int index = 0; index < a.length; index += 1) {
if (a[index] != b[index]) if (a[index] != b[index]) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -78,12 +86,15 @@ bool listEquals<T>(List<T>? a, List<T>? b) { ...@@ -78,12 +86,15 @@ bool listEquals<T>(List<T>? a, List<T>? b) {
/// * [setEquals], which does something similar for sets. /// * [setEquals], which does something similar for sets.
/// * [listEquals], which does something similar for lists. /// * [listEquals], which does something similar for lists.
bool mapEquals<T, U>(Map<T, U>? a, Map<T, U>? b) { bool mapEquals<T, U>(Map<T, U>? a, Map<T, U>? b) {
if (a == null) if (a == null) {
return b == null; return b == null;
if (b == null || a.length != b.length) }
if (b == null || a.length != b.length) {
return false; return false;
if (identical(a, b)) }
if (identical(a, b)) {
return true; return true;
}
for (final T key in a.keys) { for (final T key in a.keys) {
if (!b.containsKey(key) || b[key] != a[key]) { if (!b.containsKey(key) || b[key] != a[key]) {
return false; return false;
......
...@@ -54,8 +54,9 @@ Future<Uint8List> consolidateHttpClientResponseBytes( ...@@ -54,8 +54,9 @@ Future<Uint8List> consolidateHttpClientResponseBytes(
final _OutputBuffer output = _OutputBuffer(); final _OutputBuffer output = _OutputBuffer();
ByteConversionSink sink = output; ByteConversionSink sink = output;
int? expectedContentLength = response.contentLength; int? expectedContentLength = response.contentLength;
if (expectedContentLength == -1) if (expectedContentLength == -1) {
expectedContentLength = null; expectedContentLength = null;
}
switch (response.compressionState) { switch (response.compressionState) {
case HttpClientResponseCompressionState.compressed: case HttpClientResponseCompressionState.compressed:
if (autoUncompress) { if (autoUncompress) {
......
...@@ -26,8 +26,9 @@ bool debugAssertAllFoundationVarsUnset(String reason, { DebugPrintCallback debug ...@@ -26,8 +26,9 @@ bool debugAssertAllFoundationVarsUnset(String reason, { DebugPrintCallback debug
if (debugPrint != debugPrintOverride || if (debugPrint != debugPrintOverride ||
debugDefaultTargetPlatformOverride != null || debugDefaultTargetPlatformOverride != null ||
debugDoublePrecision != null || debugDoublePrecision != null ||
debugBrightnessOverride != null) debugBrightnessOverride != null) {
throw FlutterError(reason); throw FlutterError(reason);
}
return true; return true;
}()); }());
return true; return true;
......
...@@ -89,8 +89,9 @@ class ValueKey<T> extends LocalKey { ...@@ -89,8 +89,9 @@ class ValueKey<T> extends LocalKey {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ValueKey<T> return other is ValueKey<T>
&& other.value == value; && other.value == value;
} }
...@@ -103,8 +104,9 @@ class ValueKey<T> extends LocalKey { ...@@ -103,8 +104,9 @@ class ValueKey<T> extends LocalKey {
final String valueString = T == String ? "<'$value'>" : '<$value>'; final String valueString = T == String ? "<'$value'>" : '<$value>';
// The crazy on the next line is a workaround for // The crazy on the next line is a workaround for
// https://github.com/dart-lang/sdk/issues/33297 // https://github.com/dart-lang/sdk/issues/33297
if (runtimeType == _TypeLiteral<ValueKey<T>>().type) if (runtimeType == _TypeLiteral<ValueKey<T>>().type) {
return '[$valueString]'; return '[$valueString]';
}
return '[$T $valueString]'; return '[$T $valueString]';
} }
} }
......
...@@ -216,10 +216,11 @@ class LicenseEntryWithLineBreaks extends LicenseEntry { ...@@ -216,10 +216,11 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
// The following is a wild heuristic for guessing the indentation level. // The following is a wild heuristic for guessing the indentation level.
// It happens to work for common variants of the BSD and LGPL licenses. // It happens to work for common variants of the BSD and LGPL licenses.
if (currentParagraphIndentation == null) { if (currentParagraphIndentation == null) {
if (currentLineIndent > 10) if (currentLineIndent > 10) {
currentParagraphIndentation = LicenseParagraph.centeredIndent; currentParagraphIndentation = LicenseParagraph.centeredIndent;
else } else {
currentParagraphIndentation = currentLineIndent ~/ 3; currentParagraphIndentation = currentLineIndent ~/ 3;
}
} }
state = _LicenseEntryWithLineBreaksParserState.inParagraph; state = _LicenseEntryWithLineBreaksParserState.inParagraph;
} }
...@@ -313,14 +314,16 @@ class LicenseRegistry { ...@@ -313,14 +314,16 @@ class LicenseRegistry {
/// ///
/// Generating the list of licenses is expensive. /// Generating the list of licenses is expensive.
static Stream<LicenseEntry> get licenses { static Stream<LicenseEntry> get licenses {
if (_collectors == null) if (_collectors == null) {
return const Stream<LicenseEntry>.empty(); return const Stream<LicenseEntry>.empty();
}
late final StreamController<LicenseEntry> controller; late final StreamController<LicenseEntry> controller;
controller = StreamController<LicenseEntry>( controller = StreamController<LicenseEntry>(
onListen: () async { onListen: () async {
for (final LicenseEntryCollector collector in _collectors!) for (final LicenseEntryCollector collector in _collectors!) {
await controller.addStream(collector()); await controller.addStream(collector());
}
await controller.close(); await controller.close();
}, },
); );
......
...@@ -128,14 +128,16 @@ class AbstractNode { ...@@ -128,14 +128,16 @@ class AbstractNode {
assert(child._parent == null); assert(child._parent == null);
assert(() { assert(() {
AbstractNode node = this; AbstractNode node = this;
while (node.parent != null) while (node.parent != null) {
node = node.parent!; node = node.parent!;
}
assert(node != child); // indicates we are about to create a cycle assert(node != child); // indicates we are about to create a cycle
return true; return true;
}()); }());
child._parent = this; child._parent = this;
if (attached) if (attached) {
child.attach(_owner!); child.attach(_owner!);
}
redepthChild(child); redepthChild(child);
} }
...@@ -149,7 +151,8 @@ class AbstractNode { ...@@ -149,7 +151,8 @@ class AbstractNode {
assert(child._parent == this); assert(child._parent == this);
assert(child.attached == attached); assert(child.attached == attached);
child._parent = null; child._parent = null;
if (attached) if (attached) {
child.detach(); child.detach();
}
} }
} }
...@@ -57,8 +57,9 @@ class ObserverList<T> extends Iterable<T> { ...@@ -57,8 +57,9 @@ class ObserverList<T> extends Iterable<T> {
@override @override
bool contains(Object? element) { bool contains(Object? element) {
if (_list.length < 3) if (_list.length < 3) {
return _list.contains(element); return _list.contains(element);
}
if (_isDirty) { if (_isDirty) {
_set.addAll(_list); _set.addAll(_list);
......
...@@ -55,8 +55,9 @@ void debugPrintThrottled(String? message, { int? wrapWidth }) { ...@@ -55,8 +55,9 @@ void debugPrintThrottled(String? message, { int? wrapWidth }) {
} else { } else {
_debugPrintBuffer.addAll(messageLines); _debugPrintBuffer.addAll(messageLines);
} }
if (!_debugPrintScheduled) if (!_debugPrintScheduled) {
_debugPrintTask(); _debugPrintTask();
}
} }
int _debugPrintedCharacters = 0; int _debugPrintedCharacters = 0;
const int _kDebugPrintCapacity = 12 * 1024; const int _kDebugPrintCapacity = 12 * 1024;
...@@ -130,14 +131,16 @@ Iterable<String> debugWordWrap(String message, int width, { String wrapIndent = ...@@ -130,14 +131,16 @@ Iterable<String> debugWordWrap(String message, int width, { String wrapIndent =
while (true) { while (true) {
switch (mode) { switch (mode) {
case _WordWrapParseMode.inSpace: // at start of break point (or start of line); can't break until next break case _WordWrapParseMode.inSpace: // at start of break point (or start of line); can't break until next break
while ((index < message.length) && (message[index] == ' ')) while ((index < message.length) && (message[index] == ' ')) {
index += 1; index += 1;
}
lastWordStart = index; lastWordStart = index;
mode = _WordWrapParseMode.inWord; mode = _WordWrapParseMode.inWord;
break; break;
case _WordWrapParseMode.inWord: // looking for a good break point case _WordWrapParseMode.inWord: // looking for a good break point
while ((index < message.length) && (message[index] != ' ')) while ((index < message.length) && (message[index] != ' ')) {
index += 1; index += 1;
}
mode = _WordWrapParseMode.atBreak; mode = _WordWrapParseMode.atBreak;
break; break;
case _WordWrapParseMode.atBreak: // at start of break point case _WordWrapParseMode.atBreak: // at start of break point
...@@ -154,14 +157,16 @@ Iterable<String> debugWordWrap(String message, int width, { String wrapIndent = ...@@ -154,14 +157,16 @@ Iterable<String> debugWordWrap(String message, int width, { String wrapIndent =
wrapped.add(message.substring(start, lastWordEnd)); wrapped.add(message.substring(start, lastWordEnd));
addPrefix = true; addPrefix = true;
} }
if (lastWordEnd >= message.length) if (lastWordEnd >= message.length) {
return wrapped; return wrapped;
}
// just yielded a line // just yielded a line
if (lastWordEnd == index) { if (lastWordEnd == index) {
// we broke at current position // we broke at current position
// eat all the spaces, then set our start point // eat all the spaces, then set our start point
while ((index < message.length) && (message[index] == ' ')) while ((index < message.length) && (message[index] == ' ')) {
index += 1; index += 1;
}
start = index; start = index;
mode = _WordWrapParseMode.inWord; mode = _WordWrapParseMode.inWord;
} else { } else {
......
...@@ -262,7 +262,8 @@ class ReadBuffer { ...@@ -262,7 +262,8 @@ class ReadBuffer {
void _alignTo(int alignment) { void _alignTo(int alignment) {
final int mod = _position % alignment; final int mod = _position % alignment;
if (mod != 0) if (mod != 0) {
_position += alignment - mod; _position += alignment - mod;
}
} }
} }
...@@ -298,8 +298,9 @@ class StackFrame { ...@@ -298,8 +298,9 @@ class StackFrame {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is StackFrame return other is StackFrame
&& other.number == number && other.number == number
&& other.package == package && other.package == package
......
...@@ -39,8 +39,9 @@ class SynchronousFuture<T> implements Future<T> { ...@@ -39,8 +39,9 @@ class SynchronousFuture<T> implements Future<T> {
@override @override
Future<R> then<R>(FutureOr<R> Function(T value) onValue, { Function? onError }) { Future<R> then<R>(FutureOr<R> Function(T value) onValue, { Function? onError }) {
final dynamic result = onValue(_value); final dynamic result = onValue(_value);
if (result is Future<R>) if (result is Future<R>) {
return result; return result;
}
return SynchronousFuture<R>(result as R); return SynchronousFuture<R>(result as R);
} }
...@@ -53,8 +54,9 @@ class SynchronousFuture<T> implements Future<T> { ...@@ -53,8 +54,9 @@ class SynchronousFuture<T> implements Future<T> {
Future<T> whenComplete(FutureOr<dynamic> Function() action) { Future<T> whenComplete(FutureOr<dynamic> Function() action) {
try { try {
final FutureOr<dynamic> result = action(); final FutureOr<dynamic> result = action();
if (result is Future) if (result is Future) {
return result.then<T>((dynamic value) => _value); return result.then<T>((dynamic value) => _value);
}
return this; return this;
} catch (e, stack) { } catch (e, stack) {
return Future<T>.error(e, stack); return Future<T>.error(e, stack);
......
...@@ -78,17 +78,21 @@ class _GestureArena { ...@@ -78,17 +78,21 @@ class _GestureArena {
buffer.write('<empty>'); buffer.write('<empty>');
} else { } else {
buffer.write(members.map<String>((GestureArenaMember member) { buffer.write(members.map<String>((GestureArenaMember member) {
if (member == eagerWinner) if (member == eagerWinner) {
return '$member (eager winner)'; return '$member (eager winner)';
}
return '$member'; return '$member';
}).join(', ')); }).join(', '));
} }
if (isOpen) if (isOpen) {
buffer.write(' [open]'); buffer.write(' [open]');
if (isHeld) }
if (isHeld) {
buffer.write(' [held]'); buffer.write(' [held]');
if (hasPendingSweep) }
if (hasPendingSweep) {
buffer.write(' [hasPendingSweep]'); buffer.write(' [hasPendingSweep]');
}
return buffer.toString(); return buffer.toString();
} }
} }
...@@ -119,8 +123,9 @@ class GestureArenaManager { ...@@ -119,8 +123,9 @@ class GestureArenaManager {
/// Called after the framework has finished dispatching the pointer down event. /// Called after the framework has finished dispatching the pointer down event.
void close(int pointer) { void close(int pointer) {
final _GestureArena? state = _arenas[pointer]; final _GestureArena? state = _arenas[pointer];
if (state == null) if (state == null) {
return; // This arena either never existed or has been resolved. return; // This arena either never existed or has been resolved.
}
state.isOpen = false; state.isOpen = false;
assert(_debugLogDiagnostic(pointer, 'Closing', state)); assert(_debugLogDiagnostic(pointer, 'Closing', state));
_tryToResolveArena(pointer, state); _tryToResolveArena(pointer, state);
...@@ -141,8 +146,9 @@ class GestureArenaManager { ...@@ -141,8 +146,9 @@ class GestureArenaManager {
/// * [release] /// * [release]
void sweep(int pointer) { void sweep(int pointer) {
final _GestureArena? state = _arenas[pointer]; final _GestureArena? state = _arenas[pointer];
if (state == null) if (state == null) {
return; // This arena either never existed or has been resolved. return; // This arena either never existed or has been resolved.
}
assert(!state.isOpen); assert(!state.isOpen);
if (state.isHeld) { if (state.isHeld) {
state.hasPendingSweep = true; state.hasPendingSweep = true;
...@@ -156,8 +162,9 @@ class GestureArenaManager { ...@@ -156,8 +162,9 @@ class GestureArenaManager {
assert(_debugLogDiagnostic(pointer, 'Winner: ${state.members.first}')); assert(_debugLogDiagnostic(pointer, 'Winner: ${state.members.first}'));
state.members.first.acceptGesture(pointer); state.members.first.acceptGesture(pointer);
// Give all the other members the bad news. // Give all the other members the bad news.
for (int i = 1; i < state.members.length; i++) for (int i = 1; i < state.members.length; i++) {
state.members[i].rejectGesture(pointer); state.members[i].rejectGesture(pointer);
}
} }
} }
...@@ -175,8 +182,9 @@ class GestureArenaManager { ...@@ -175,8 +182,9 @@ class GestureArenaManager {
/// * [release] /// * [release]
void hold(int pointer) { void hold(int pointer) {
final _GestureArena? state = _arenas[pointer]; final _GestureArena? state = _arenas[pointer];
if (state == null) if (state == null) {
return; // This arena either never existed or has been resolved. return; // This arena either never existed or has been resolved.
}
state.isHeld = true; state.isHeld = true;
assert(_debugLogDiagnostic(pointer, 'Holding', state)); assert(_debugLogDiagnostic(pointer, 'Holding', state));
} }
...@@ -192,12 +200,14 @@ class GestureArenaManager { ...@@ -192,12 +200,14 @@ class GestureArenaManager {
/// * [hold] /// * [hold]
void release(int pointer) { void release(int pointer) {
final _GestureArena? state = _arenas[pointer]; final _GestureArena? state = _arenas[pointer];
if (state == null) if (state == null) {
return; // This arena either never existed or has been resolved. return; // This arena either never existed or has been resolved.
}
state.isHeld = false; state.isHeld = false;
assert(_debugLogDiagnostic(pointer, 'Releasing', state)); assert(_debugLogDiagnostic(pointer, 'Releasing', state));
if (state.hasPendingSweep) if (state.hasPendingSweep) {
sweep(pointer); sweep(pointer);
}
} }
/// Reject or accept a gesture recognizer. /// Reject or accept a gesture recognizer.
...@@ -205,15 +215,17 @@ class GestureArenaManager { ...@@ -205,15 +215,17 @@ class GestureArenaManager {
/// This is called by calling [GestureArenaEntry.resolve] on the object returned from [add]. /// This is called by calling [GestureArenaEntry.resolve] on the object returned from [add].
void _resolve(int pointer, GestureArenaMember member, GestureDisposition disposition) { void _resolve(int pointer, GestureArenaMember member, GestureDisposition disposition) {
final _GestureArena? state = _arenas[pointer]; final _GestureArena? state = _arenas[pointer];
if (state == null) if (state == null) {
return; // This arena has already resolved. return; // This arena has already resolved.
}
assert(_debugLogDiagnostic(pointer, '${ disposition == GestureDisposition.accepted ? "Accepting" : "Rejecting" }: $member')); assert(_debugLogDiagnostic(pointer, '${ disposition == GestureDisposition.accepted ? "Accepting" : "Rejecting" }: $member'));
assert(state.members.contains(member)); assert(state.members.contains(member));
if (disposition == GestureDisposition.rejected) { if (disposition == GestureDisposition.rejected) {
state.members.remove(member); state.members.remove(member);
member.rejectGesture(pointer); member.rejectGesture(pointer);
if (!state.isOpen) if (!state.isOpen) {
_tryToResolveArena(pointer, state); _tryToResolveArena(pointer, state);
}
} else { } else {
assert(disposition == GestureDisposition.accepted); assert(disposition == GestureDisposition.accepted);
if (state.isOpen) { if (state.isOpen) {
...@@ -240,8 +252,9 @@ class GestureArenaManager { ...@@ -240,8 +252,9 @@ class GestureArenaManager {
} }
void _resolveByDefault(int pointer, _GestureArena state) { void _resolveByDefault(int pointer, _GestureArena state) {
if (!_arenas.containsKey(pointer)) if (!_arenas.containsKey(pointer)) {
return; // Already resolved earlier. return; // This arena has already resolved.
}
assert(_arenas[pointer] == state); assert(_arenas[pointer] == state);
assert(!state.isOpen); assert(!state.isOpen);
final List<GestureArenaMember> members = state.members; final List<GestureArenaMember> members = state.members;
...@@ -258,8 +271,9 @@ class GestureArenaManager { ...@@ -258,8 +271,9 @@ class GestureArenaManager {
assert(!state.isOpen); assert(!state.isOpen);
_arenas.remove(pointer); _arenas.remove(pointer);
for (final GestureArenaMember rejectedMember in state.members) { for (final GestureArenaMember rejectedMember in state.members) {
if (rejectedMember != member) if (rejectedMember != member) {
rejectedMember.rejectGesture(pointer); rejectedMember.rejectGesture(pointer);
}
} }
member.acceptGesture(pointer); member.acceptGesture(pointer);
} }
......
...@@ -281,8 +281,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -281,8 +281,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
// We convert pointer data to logical pixels so that e.g. the touch slop can be // We convert pointer data to logical pixels so that e.g. the touch slop can be
// defined in a device-independent manner. // defined in a device-independent manner.
_pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, window.devicePixelRatio)); _pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, window.devicePixelRatio));
if (!locked) if (!locked) {
_flushPointerEventQueue(); _flushPointerEventQueue();
}
} }
/// Dispatch a [PointerCancelEvent] for the given pointer soon. /// Dispatch a [PointerCancelEvent] for the given pointer soon.
...@@ -290,16 +291,18 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -290,16 +291,18 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
/// The pointer event will be dispatched before the next pointer event and /// The pointer event will be dispatched before the next pointer event and
/// before the end of the microtask but not within this function call. /// before the end of the microtask but not within this function call.
void cancelPointer(int pointer) { void cancelPointer(int pointer) {
if (_pendingPointerEvents.isEmpty && !locked) if (_pendingPointerEvents.isEmpty && !locked) {
scheduleMicrotask(_flushPointerEventQueue); scheduleMicrotask(_flushPointerEventQueue);
}
_pendingPointerEvents.addFirst(PointerCancelEvent(pointer: pointer)); _pendingPointerEvents.addFirst(PointerCancelEvent(pointer: pointer));
} }
void _flushPointerEventQueue() { void _flushPointerEventQueue() {
assert(!locked); assert(!locked);
while (_pendingPointerEvents.isNotEmpty) while (_pendingPointerEvents.isNotEmpty) {
handlePointerEvent(_pendingPointerEvents.removeFirst()); handlePointerEvent(_pendingPointerEvents.removeFirst());
}
} }
/// A router that routes all pointer events received from the engine. /// A router that routes all pointer events received from the engine.
...@@ -354,8 +357,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -354,8 +357,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
_hitTests[event.pointer] = hitTestResult; _hitTests[event.pointer] = hitTestResult;
} }
assert(() { assert(() {
if (debugPrintHitTestResults) if (debugPrintHitTestResults) {
debugPrint('$event: $hitTestResult'); debugPrint('$event: $hitTestResult');
}
return true; return true;
}()); }());
} else if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) { } else if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) {
...@@ -369,8 +373,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -369,8 +373,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
hitTestResult = _hitTests[event.pointer]; hitTestResult = _hitTests[event.pointer];
} }
assert(() { assert(() {
if (debugPrintMouseHoverEvents && event is PointerHoverEvent) if (debugPrintMouseHoverEvents && event is PointerHoverEvent) {
debugPrint('$event'); debugPrint('$event');
}
return true; return true;
}()); }());
if (hitTestResult != null || if (hitTestResult != null ||
...@@ -483,8 +488,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -483,8 +488,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
SamplingClock value = SamplingClock(); SamplingClock value = SamplingClock();
assert(() { assert(() {
final SamplingClock? debugValue = debugSamplingClock; final SamplingClock? debugValue = debugSamplingClock;
if (debugValue != null) if (debugValue != null) {
value = debugValue; value = debugValue;
}
return true; return true;
}()); }());
return value; return value;
......
...@@ -76,8 +76,9 @@ bool debugAssertAllGesturesVarsUnset(String reason) { ...@@ -76,8 +76,9 @@ bool debugAssertAllGesturesVarsUnset(String reason) {
if (debugPrintHitTestResults || if (debugPrintHitTestResults ||
debugPrintGestureArenaDiagnostics || debugPrintGestureArenaDiagnostics ||
debugPrintRecognizerCallbacksTrace || debugPrintRecognizerCallbacksTrace ||
debugPrintResamplingMargin) debugPrintResamplingMargin) {
throw FlutterError(reason); throw FlutterError(reason);
}
return true; return true;
}()); }());
return true; return true;
......
...@@ -288,8 +288,9 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -288,8 +288,9 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
@override @override
void acceptGesture(int pointer) { void acceptGesture(int pointer) {
if (_state == _ForceState.possible) if (_state == _ForceState.possible) {
_state = _ForceState.accepted; _state = _ForceState.accepted;
}
if (onStart != null && _state == _ForceState.started) { if (onStart != null && _state == _ForceState.started) {
invokeCallback<void>('onStart', () => onStart!(ForcePressDetails( invokeCallback<void>('onStart', () => onStart!(ForcePressDetails(
...@@ -331,8 +332,9 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -331,8 +332,9 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
// If the device incorrectly reports a pressure outside of pressureMin // If the device incorrectly reports a pressure outside of pressureMin
// and pressureMax, we still want this recognizer to respond normally. // and pressureMax, we still want this recognizer to respond normally.
if (!value.isNaN) if (!value.isNaN) {
value = clampDouble(value, 0.0, 1.0); value = clampDouble(value, 0.0, 1.0);
}
return value; return value;
} }
......
...@@ -41,8 +41,9 @@ class DeviceGestureSettings { ...@@ -41,8 +41,9 @@ class DeviceGestureSettings {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is DeviceGestureSettings return other is DeviceGestureSettings
&& other.touchSlop == touchSlop; && other.touchSlop == touchSlop;
} }
......
...@@ -268,10 +268,11 @@ class HitTestResult { ...@@ -268,10 +268,11 @@ class HitTestResult {
/// function pair in more details. /// function pair in more details.
@protected @protected
void popTransform() { void popTransform() {
if (_localTransforms.isNotEmpty) if (_localTransforms.isNotEmpty) {
_localTransforms.removeLast(); _localTransforms.removeLast();
else } else {
_transforms.removeLast(); _transforms.removeLast();
}
assert(_transforms.isNotEmpty); assert(_transforms.isNotEmpty);
} }
......
...@@ -575,8 +575,9 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -575,8 +575,9 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
onLongPress == null && onLongPress == null &&
onLongPressMoveUpdate == null && onLongPressMoveUpdate == null &&
onLongPressEnd == null && onLongPressEnd == null &&
onLongPressUp == null) onLongPressUp == null) {
return false; return false;
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryLongPressDown == null && if (onSecondaryLongPressDown == null &&
...@@ -585,8 +586,9 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -585,8 +586,9 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
onSecondaryLongPress == null && onSecondaryLongPress == null &&
onSecondaryLongPressMoveUpdate == null && onSecondaryLongPressMoveUpdate == null &&
onSecondaryLongPressEnd == null && onSecondaryLongPressEnd == null &&
onSecondaryLongPressUp == null) onSecondaryLongPressUp == null) {
return false; return false;
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryLongPressDown == null && if (onTertiaryLongPressDown == null &&
...@@ -595,8 +597,9 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -595,8 +597,9 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
onTertiaryLongPress == null && onTertiaryLongPress == null &&
onTertiaryLongPressMoveUpdate == null && onTertiaryLongPressMoveUpdate == null &&
onTertiaryLongPressEnd == null && onTertiaryLongPressEnd == null &&
onTertiaryLongPressUp == null) onTertiaryLongPressUp == null) {
return false; return false;
}
break; break;
default: default:
return false; return false;
...@@ -661,16 +664,19 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -661,16 +664,19 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
); );
switch (_initialButtons) { switch (_initialButtons) {
case kPrimaryButton: case kPrimaryButton:
if (onLongPressDown != null) if (onLongPressDown != null) {
invokeCallback<void>('onLongPressDown', () => onLongPressDown!(details)); invokeCallback<void>('onLongPressDown', () => onLongPressDown!(details));
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryLongPressDown != null) if (onSecondaryLongPressDown != null) {
invokeCallback<void>('onSecondaryLongPressDown', () => onSecondaryLongPressDown!(details)); invokeCallback<void>('onSecondaryLongPressDown', () => onSecondaryLongPressDown!(details));
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryLongPressDown != null) if (onTertiaryLongPressDown != null) {
invokeCallback<void>('onTertiaryLongPressDown', () => onTertiaryLongPressDown!(details)); invokeCallback<void>('onTertiaryLongPressDown', () => onTertiaryLongPressDown!(details));
}
break; break;
default: default:
assert(false, 'Unhandled button $_initialButtons'); assert(false, 'Unhandled button $_initialButtons');
...@@ -681,16 +687,19 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -681,16 +687,19 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
if (state == GestureRecognizerState.possible) { if (state == GestureRecognizerState.possible) {
switch (_initialButtons) { switch (_initialButtons) {
case kPrimaryButton: case kPrimaryButton:
if (onLongPressCancel != null) if (onLongPressCancel != null) {
invokeCallback<void>('onLongPressCancel', onLongPressCancel!); invokeCallback<void>('onLongPressCancel', onLongPressCancel!);
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryLongPressCancel != null) if (onSecondaryLongPressCancel != null) {
invokeCallback<void>('onSecondaryLongPressCancel', onSecondaryLongPressCancel!); invokeCallback<void>('onSecondaryLongPressCancel', onSecondaryLongPressCancel!);
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryLongPressCancel != null) if (onTertiaryLongPressCancel != null) {
invokeCallback<void>('onTertiaryLongPressCancel', onTertiaryLongPressCancel!); invokeCallback<void>('onTertiaryLongPressCancel', onTertiaryLongPressCancel!);
}
break; break;
default: default:
assert(false, 'Unhandled button $_initialButtons'); assert(false, 'Unhandled button $_initialButtons');
......
...@@ -33,8 +33,9 @@ class _Vector { ...@@ -33,8 +33,9 @@ class _Vector {
double operator *(_Vector a) { double operator *(_Vector a) {
double result = 0.0; double result = 0.0;
for (int i = 0; i < _length; i += 1) for (int i = 0; i < _length; i += 1) {
result += this[i] * a[i]; result += this[i] * a[i];
}
return result; return result;
} }
...@@ -100,8 +101,10 @@ class LeastSquaresSolver { ...@@ -100,8 +101,10 @@ class LeastSquaresSolver {
/// ///
/// When there is not enough data to fit a curve null is returned. /// When there is not enough data to fit a curve null is returned.
PolynomialFit? solve(int degree) { PolynomialFit? solve(int degree) {
if (degree > x.length) // Not enough data to fit a curve. if (degree > x.length) {
// Not enough data to fit a curve.
return null; return null;
}
final PolynomialFit result = PolynomialFit(degree); final PolynomialFit result = PolynomialFit(degree);
...@@ -113,8 +116,9 @@ class LeastSquaresSolver { ...@@ -113,8 +116,9 @@ class LeastSquaresSolver {
final _Matrix a = _Matrix(n, m); final _Matrix a = _Matrix(n, m);
for (int h = 0; h < m; h += 1) { for (int h = 0; h < m; h += 1) {
a.set(0, h, w[h]); a.set(0, h, w[h]);
for (int i = 1; i < n; i += 1) for (int i = 1; i < n; i += 1) {
a.set(i, h, a.get(i - 1, h) * x[h]); a.set(i, h, a.get(i - 1, h) * x[h]);
}
} }
// Apply the Gram-Schmidt process to A to obtain its QR decomposition. // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
...@@ -124,12 +128,14 @@ class LeastSquaresSolver { ...@@ -124,12 +128,14 @@ class LeastSquaresSolver {
// Upper triangular matrix, row-major order. // Upper triangular matrix, row-major order.
final _Matrix r = _Matrix(n, n); final _Matrix r = _Matrix(n, n);
for (int j = 0; j < n; j += 1) { for (int j = 0; j < n; j += 1) {
for (int h = 0; h < m; h += 1) for (int h = 0; h < m; h += 1) {
q.set(j, h, a.get(j, h)); q.set(j, h, a.get(j, h));
}
for (int i = 0; i < j; i += 1) { for (int i = 0; i < j; i += 1) {
final double dot = q.getRow(j) * q.getRow(i); final double dot = q.getRow(j) * q.getRow(i);
for (int h = 0; h < m; h += 1) for (int h = 0; h < m; h += 1) {
q.set(j, h, q.get(j, h) - dot * q.get(i, h)); q.set(j, h, q.get(j, h) - dot * q.get(i, h));
}
} }
final double norm = q.getRow(j).norm(); final double norm = q.getRow(j).norm();
...@@ -139,21 +145,25 @@ class LeastSquaresSolver { ...@@ -139,21 +145,25 @@ class LeastSquaresSolver {
} }
final double inverseNorm = 1.0 / norm; final double inverseNorm = 1.0 / norm;
for (int h = 0; h < m; h += 1) for (int h = 0; h < m; h += 1) {
q.set(j, h, q.get(j, h) * inverseNorm); q.set(j, h, q.get(j, h) * inverseNorm);
for (int i = 0; i < n; i += 1) }
for (int i = 0; i < n; i += 1) {
r.set(j, i, i < j ? 0.0 : q.getRow(j) * a.getRow(i)); r.set(j, i, i < j ? 0.0 : q.getRow(j) * a.getRow(i));
}
} }
// Solve R B = Qt W Y to find B. This is easy because R is upper triangular. // Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
// We just work from bottom-right to top-left calculating B's coefficients. // We just work from bottom-right to top-left calculating B's coefficients.
final _Vector wy = _Vector(m); final _Vector wy = _Vector(m);
for (int h = 0; h < m; h += 1) for (int h = 0; h < m; h += 1) {
wy[h] = y[h] * w[h]; wy[h] = y[h] * w[h];
}
for (int i = n - 1; i >= 0; i -= 1) { for (int i = n - 1; i >= 0; i -= 1) {
result.coefficients[i] = q.getRow(i) * wy; result.coefficients[i] = q.getRow(i) * wy;
for (int j = n - 1; j > i; j -= 1) for (int j = n - 1; j > i; j -= 1) {
result.coefficients[i] -= r.get(i, j) * result.coefficients[j]; result.coefficients[i] -= r.get(i, j) * result.coefficients[j];
}
result.coefficients[i] /= r.get(i, i); result.coefficients[i] /= r.get(i, i);
} }
...@@ -163,8 +173,9 @@ class LeastSquaresSolver { ...@@ -163,8 +173,9 @@ class LeastSquaresSolver {
// error), and sumSquaredTotal is the total sum of squares (variance of the // error), and sumSquaredTotal is the total sum of squares (variance of the
// data) where each has been weighted. // data) where each has been weighted.
double yMean = 0.0; double yMean = 0.0;
for (int h = 0; h < m; h += 1) for (int h = 0; h < m; h += 1) {
yMean += y[h]; yMean += y[h];
}
yMean /= m; yMean /= m;
double sumSquaredError = 0.0; double sumSquaredError = 0.0;
......
...@@ -241,8 +241,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -241,8 +241,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
onStart == null && onStart == null &&
onUpdate == null && onUpdate == null &&
onEnd == null && onEnd == null &&
onCancel == null) onCancel == null) {
return false; return false;
}
break; break;
default: default:
return false; return false;
...@@ -336,8 +337,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -336,8 +337,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
untransformedDelta: movedLocally, untransformedDelta: movedLocally,
untransformedEndPosition: localPosition untransformedEndPosition: localPosition
).distance * (_getPrimaryValueFromOffset(movedLocally) ?? 1).sign; ).distance * (_getPrimaryValueFromOffset(movedLocally) ?? 1).sign;
if (_hasSufficientGlobalDistanceToAccept(event.kind, gestureSettings?.touchSlop)) if (_hasSufficientGlobalDistanceToAccept(event.kind, gestureSettings?.touchSlop)) {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
}
} }
} }
if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) { if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) {
...@@ -425,8 +427,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -425,8 +427,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
stopTrackingPointer(pointer); stopTrackingPointer(pointer);
// If we never accepted the pointer, we reject it since we are no longer // If we never accepted the pointer, we reject it since we are no longer
// interested in winning the gesture arena for it. // interested in winning the gesture arena for it.
if (!_acceptedActivePointers.remove(pointer)) if (!_acceptedActivePointers.remove(pointer)) {
resolvePointer(pointer, GestureDisposition.rejected); resolvePointer(pointer, GestureDisposition.rejected);
}
} }
void _checkDown() { void _checkDown() {
...@@ -475,8 +478,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -475,8 +478,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
void _checkEnd(int pointer) { void _checkEnd(int pointer) {
assert(_initialButtons == kPrimaryButton); assert(_initialButtons == kPrimaryButton);
if (onEnd == null) if (onEnd == null) {
return; return;
}
final VelocityTracker tracker = _velocityTrackers[pointer]!; final VelocityTracker tracker = _velocityTrackers[pointer]!;
assert(tracker != null); assert(tracker != null);
...@@ -500,8 +504,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -500,8 +504,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
primaryVelocity: 0.0, primaryVelocity: 0.0,
); );
debugReport = () { debugReport = () {
if (estimate == null) if (estimate == null) {
return 'Could not estimate velocity.'; return 'Could not estimate velocity.';
}
return '$estimate; judged to not be a fling.'; return '$estimate; judged to not be a fling.';
}; };
} }
...@@ -510,8 +515,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -510,8 +515,9 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
void _checkCancel() { void _checkCancel() {
assert(_initialButtons == kPrimaryButton); assert(_initialButtons == kPrimaryButton);
if (onCancel != null) if (onCancel != null) {
invokeCallback<void>('onCancel', onCancel!); invokeCallback<void>('onCancel', onCancel!);
}
} }
@override @override
......
...@@ -78,8 +78,9 @@ abstract class MultiDragPointerState { ...@@ -78,8 +78,9 @@ abstract class MultiDragPointerState {
void _move(PointerMoveEvent event) { void _move(PointerMoveEvent event) {
assert(_arenaEntry != null); assert(_arenaEntry != null);
if (!event.synthesized) if (!event.synthesized) {
_velocityTracker.addPosition(event.timeStamp, event.position); _velocityTracker.addPosition(event.timeStamp, event.position);
}
if (_client != null) { if (_client != null) {
assert(pendingDelta == null); assert(pendingDelta == null);
// Call client last to avoid reentrancy. // Call client last to avoid reentrancy.
...@@ -276,8 +277,9 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer { ...@@ -276,8 +277,9 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer {
void acceptGesture(int pointer) { void acceptGesture(int pointer) {
assert(_pointers != null); assert(_pointers != null);
final MultiDragPointerState? state = _pointers![pointer]; final MultiDragPointerState? state = _pointers![pointer];
if (state == null) if (state == null) {
return; // We might already have canceled this drag if the up comes before the accept. return; // We might already have canceled this drag if the up comes before the accept.
}
state.accepted((Offset initialPosition) => _startDrag(initialPosition, pointer)); state.accepted((Offset initialPosition) => _startDrag(initialPosition, pointer));
} }
...@@ -287,8 +289,9 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer { ...@@ -287,8 +289,9 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer {
assert(state != null); assert(state != null);
assert(state._pendingDelta != null); assert(state._pendingDelta != null);
Drag? drag; Drag? drag;
if (onStart != null) if (onStart != null) {
drag = invokeCallback<Drag?>('onStart', () => onStart!(initialPosition)); drag = invokeCallback<Drag?>('onStart', () => onStart!(initialPosition));
}
if (drag != null) { if (drag != null) {
state._startDrag(drag); state._startDrag(drag);
} else { } else {
...@@ -334,8 +337,9 @@ class _ImmediatePointerState extends MultiDragPointerState { ...@@ -334,8 +337,9 @@ class _ImmediatePointerState extends MultiDragPointerState {
@override @override
void checkForResolutionAfterMove() { void checkForResolutionAfterMove() {
assert(pendingDelta != null); assert(pendingDelta != null);
if (pendingDelta!.distance > computeHitSlop(kind, gestureSettings)) if (pendingDelta!.distance > computeHitSlop(kind, gestureSettings)) {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
}
} }
@override @override
...@@ -390,8 +394,9 @@ class _HorizontalPointerState extends MultiDragPointerState { ...@@ -390,8 +394,9 @@ class _HorizontalPointerState extends MultiDragPointerState {
@override @override
void checkForResolutionAfterMove() { void checkForResolutionAfterMove() {
assert(pendingDelta != null); assert(pendingDelta != null);
if (pendingDelta!.dx.abs() > computeHitSlop(kind, gestureSettings)) if (pendingDelta!.dx.abs() > computeHitSlop(kind, gestureSettings)) {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
}
} }
@override @override
...@@ -446,8 +451,9 @@ class _VerticalPointerState extends MultiDragPointerState { ...@@ -446,8 +451,9 @@ class _VerticalPointerState extends MultiDragPointerState {
@override @override
void checkForResolutionAfterMove() { void checkForResolutionAfterMove() {
assert(pendingDelta != null); assert(pendingDelta != null);
if (pendingDelta!.dy.abs() > computeHitSlop(kind, gestureSettings)) if (pendingDelta!.dy.abs() > computeHitSlop(kind, gestureSettings)) {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
}
} }
@override @override
...@@ -527,10 +533,11 @@ class _DelayedPointerState extends MultiDragPointerState { ...@@ -527,10 +533,11 @@ class _DelayedPointerState extends MultiDragPointerState {
@override @override
void accepted(GestureMultiDragStartCallback starter) { void accepted(GestureMultiDragStartCallback starter) {
assert(_starter == null); assert(_starter == null);
if (_timer == null) if (_timer == null) {
starter(initialPosition); starter(initialPosition);
else } else {
_starter = starter; _starter = starter;
}
} }
@override @override
......
...@@ -204,8 +204,9 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -204,8 +204,9 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
case kPrimaryButton: case kPrimaryButton:
if (onDoubleTapDown == null && if (onDoubleTapDown == null &&
onDoubleTap == null && onDoubleTap == null &&
onDoubleTapCancel == null) onDoubleTapCancel == null) {
return false; return false;
}
break; break;
default: default:
return false; return false;
...@@ -252,13 +253,15 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -252,13 +253,15 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
void _handleEvent(PointerEvent event) { void _handleEvent(PointerEvent event) {
final _TapTracker tracker = _trackers[event.pointer]!; final _TapTracker tracker = _trackers[event.pointer]!;
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
if (_firstTap == null) if (_firstTap == null) {
_registerFirstTap(tracker); _registerFirstTap(tracker);
else } else {
_registerSecondTap(tracker); _registerSecondTap(tracker);
}
} else if (event is PointerMoveEvent) { } else if (event is PointerMoveEvent) {
if (!tracker.isWithinGlobalTolerance(event, kDoubleTapTouchSlop)) if (!tracker.isWithinGlobalTolerance(event, kDoubleTapTouchSlop)) {
_reject(tracker); _reject(tracker);
}
} else if (event is PointerCancelEvent) { } else if (event is PointerCancelEvent) {
_reject(tracker); _reject(tracker);
} }
...@@ -273,11 +276,13 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -273,11 +276,13 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
// If tracker isn't in the list, check if this is the first tap tracker // If tracker isn't in the list, check if this is the first tap tracker
if (tracker == null && if (tracker == null &&
_firstTap != null && _firstTap != null &&
_firstTap!.pointer == pointer) _firstTap!.pointer == pointer) {
tracker = _firstTap; tracker = _firstTap;
}
// If tracker is still null, we rejected ourselves already // If tracker is still null, we rejected ourselves already
if (tracker != null) if (tracker != null) {
_reject(tracker); _reject(tracker);
}
} }
void _reject(_TapTracker tracker) { void _reject(_TapTracker tracker) {
...@@ -289,8 +294,9 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -289,8 +294,9 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
_reset(); _reset();
} else { } else {
_checkCancel(); _checkCancel();
if (_trackers.isEmpty) if (_trackers.isEmpty) {
_reset(); _reset();
}
} }
} }
} }
...@@ -304,8 +310,9 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -304,8 +310,9 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
void _reset() { void _reset() {
_stopDoubleTapTimer(); _stopDoubleTapTimer();
if (_firstTap != null) { if (_firstTap != null) {
if (_trackers.isNotEmpty) if (_trackers.isNotEmpty) {
_checkCancel(); _checkCancel();
}
// Note, order is important below in order for the resolve -> reject logic // Note, order is important below in order for the resolve -> reject logic
// to work properly. // to work properly.
final _TapTracker tracker = _firstTap!; final _TapTracker tracker = _firstTap!;
...@@ -358,13 +365,15 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -358,13 +365,15 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
void _checkUp(int buttons) { void _checkUp(int buttons) {
assert(buttons == kPrimaryButton); assert(buttons == kPrimaryButton);
if (onDoubleTap != null) if (onDoubleTap != null) {
invokeCallback<void>('onDoubleTap', onDoubleTap!); invokeCallback<void>('onDoubleTap', onDoubleTap!);
}
} }
void _checkCancel() { void _checkCancel() {
if (onDoubleTapCancel != null) if (onDoubleTapCancel != null) {
invokeCallback<void>('onDoubleTapCancel', onDoubleTapCancel!); invokeCallback<void>('onDoubleTapCancel', onDoubleTapCancel!);
}
} }
@override @override
...@@ -407,10 +416,11 @@ class _TapGesture extends _TapTracker { ...@@ -407,10 +416,11 @@ class _TapGesture extends _TapTracker {
void handleEvent(PointerEvent event) { void handleEvent(PointerEvent event) {
assert(event.pointer == pointer); assert(event.pointer == pointer);
if (event is PointerMoveEvent) { if (event is PointerMoveEvent) {
if (!isWithinGlobalTolerance(event, computeHitSlop(event.kind, gestureSettings))) if (!isWithinGlobalTolerance(event, computeHitSlop(event.kind, gestureSettings))) {
cancel(); cancel();
else } else {
_lastPosition = OffsetPair.fromEventPosition(event); _lastPosition = OffsetPair.fromEventPosition(event);
}
} else if (event is PointerCancelEvent) { } else if (event is PointerCancelEvent) {
cancel(); cancel();
} else if (event is PointerUpEvent) { } else if (event is PointerUpEvent) {
...@@ -440,15 +450,17 @@ class _TapGesture extends _TapTracker { ...@@ -440,15 +450,17 @@ class _TapGesture extends _TapTracker {
void cancel() { void cancel() {
// If we won the arena already, then entry is resolved, so resolving // If we won the arena already, then entry is resolved, so resolving
// again is a no-op. But we still need to clean up our own state. // again is a no-op. But we still need to clean up our own state.
if (_wonArena) if (_wonArena) {
reject(); reject();
else } else {
entry.resolve(GestureDisposition.rejected); // eventually calls reject() entry.resolve(GestureDisposition.rejected); // eventually calls reject()
}
} }
void _check() { void _check() {
if (_wonArena && _finalPosition != null) if (_wonArena && _finalPosition != null) {
gestureRecognizer._dispatchTap(pointer, _finalPosition!); gestureRecognizer._dispatchTap(pointer, _finalPosition!);
}
} }
} }
...@@ -512,7 +524,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer { ...@@ -512,7 +524,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
longTapDelay: longTapDelay, longTapDelay: longTapDelay,
gestureSettings: gestureSettings, gestureSettings: gestureSettings,
); );
if (onTapDown != null) if (onTapDown != null) {
invokeCallback<void>('onTapDown', () { invokeCallback<void>('onTapDown', () {
onTapDown!(event.pointer, TapDownDetails( onTapDown!(event.pointer, TapDownDetails(
globalPosition: event.position, globalPosition: event.position,
...@@ -520,6 +532,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer { ...@@ -520,6 +532,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
kind: event.kind, kind: event.kind,
)); ));
}); });
}
} }
@override @override
...@@ -538,14 +551,15 @@ class MultiTapGestureRecognizer extends GestureRecognizer { ...@@ -538,14 +551,15 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
void _dispatchCancel(int pointer) { void _dispatchCancel(int pointer) {
assert(_gestureMap.containsKey(pointer)); assert(_gestureMap.containsKey(pointer));
_gestureMap.remove(pointer); _gestureMap.remove(pointer);
if (onTapCancel != null) if (onTapCancel != null) {
invokeCallback<void>('onTapCancel', () => onTapCancel!(pointer)); invokeCallback<void>('onTapCancel', () => onTapCancel!(pointer));
}
} }
void _dispatchTap(int pointer, OffsetPair position) { void _dispatchTap(int pointer, OffsetPair position) {
assert(_gestureMap.containsKey(pointer)); assert(_gestureMap.containsKey(pointer));
_gestureMap.remove(pointer); _gestureMap.remove(pointer);
if (onTapUp != null) if (onTapUp != null) {
invokeCallback<void>('onTapUp', () { invokeCallback<void>('onTapUp', () {
onTapUp!(pointer, TapUpDetails( onTapUp!(pointer, TapUpDetails(
kind: getKindForPointer(pointer), kind: getKindForPointer(pointer),
...@@ -553,13 +567,15 @@ class MultiTapGestureRecognizer extends GestureRecognizer { ...@@ -553,13 +567,15 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
globalPosition: position.global, globalPosition: position.global,
)); ));
}); });
if (onTap != null) }
if (onTap != null) {
invokeCallback<void>('onTap', () => onTap!(pointer)); invokeCallback<void>('onTap', () => onTap!(pointer));
}
} }
void _dispatchLongTap(int pointer, OffsetPair lastPosition) { void _dispatchLongTap(int pointer, OffsetPair lastPosition) {
assert(_gestureMap.containsKey(pointer)); assert(_gestureMap.containsKey(pointer));
if (onLongTapDown != null) if (onLongTapDown != null) {
invokeCallback<void>('onLongTapDown', () { invokeCallback<void>('onLongTapDown', () {
onLongTapDown!( onLongTapDown!(
pointer, pointer,
...@@ -570,13 +586,15 @@ class MultiTapGestureRecognizer extends GestureRecognizer { ...@@ -570,13 +586,15 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
), ),
); );
}); });
}
} }
@override @override
void dispose() { void dispose() {
final List<_TapGesture> localGestures = List<_TapGesture>.of(_gestureMap.values); final List<_TapGesture> localGestures = List<_TapGesture>.of(_gestureMap.values);
for (final _TapGesture gesture in localGestures) for (final _TapGesture gesture in localGestures) {
gesture.cancel(); gesture.cancel();
}
// Rejection of each gesture should cause it to be removed from our map // Rejection of each gesture should cause it to be removed from our map
assert(_gestureMap.isEmpty); assert(_gestureMap.isEmpty);
super.dispose(); super.dispose();
......
...@@ -44,8 +44,9 @@ class PointerRouter { ...@@ -44,8 +44,9 @@ class PointerRouter {
final Map<PointerRoute, Matrix4?> routes = _routeMap[pointer]!; final Map<PointerRoute, Matrix4?> routes = _routeMap[pointer]!;
assert(routes.containsKey(route)); assert(routes.containsKey(route));
routes.remove(route); routes.remove(route);
if (routes.isEmpty) if (routes.isEmpty) {
_routeMap.remove(pointer); _routeMap.remove(pointer);
}
} }
/// Adds a route to the global entry in the routing table. /// Adds a route to the global entry in the routing table.
......
...@@ -347,8 +347,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -347,8 +347,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
void resolve(GestureDisposition disposition) { void resolve(GestureDisposition disposition) {
final List<GestureArenaEntry> localEntries = List<GestureArenaEntry>.of(_entries.values); final List<GestureArenaEntry> localEntries = List<GestureArenaEntry>.of(_entries.values);
_entries.clear(); _entries.clear();
for (final GestureArenaEntry entry in localEntries) for (final GestureArenaEntry entry in localEntries) {
entry.resolve(disposition); entry.resolve(disposition);
}
} }
/// Resolves this recognizer's participation in the given gesture arena with /// Resolves this recognizer's participation in the given gesture arena with
...@@ -366,8 +367,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -366,8 +367,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
@override @override
void dispose() { void dispose() {
resolve(GestureDisposition.rejected); resolve(GestureDisposition.rejected);
for (final int pointer in _trackedPointers) for (final int pointer in _trackedPointers) {
GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent); GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent);
}
_trackedPointers.clear(); _trackedPointers.clear();
assert(_entries.isEmpty); assert(_entries.isEmpty);
super.dispose(); super.dispose();
...@@ -395,8 +397,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -395,8 +397,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
} }
GestureArenaEntry _addPointerToArena(int pointer) { GestureArenaEntry _addPointerToArena(int pointer) {
if (_team != null) if (_team != null) {
return _team!.add(pointer, this); return _team!.add(pointer, this);
}
return GestureBinding.instance.gestureArena.add(pointer, this); return GestureBinding.instance.gestureArena.add(pointer, this);
} }
...@@ -433,8 +436,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -433,8 +436,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
if (_trackedPointers.contains(pointer)) { if (_trackedPointers.contains(pointer)) {
GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent); GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent);
_trackedPointers.remove(pointer); _trackedPointers.remove(pointer);
if (_trackedPointers.isEmpty) if (_trackedPointers.isEmpty) {
didStopTrackingLastPointer(pointer); didStopTrackingLastPointer(pointer);
}
} }
} }
...@@ -442,8 +446,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -442,8 +446,9 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
/// a [PointerUpEvent] or a [PointerCancelEvent] event. /// a [PointerUpEvent] or a [PointerCancelEvent] event.
@protected @protected
void stopTrackingIfPointerNoLongerDown(PointerEvent event) { void stopTrackingIfPointerNoLongerDown(PointerEvent event) {
if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) {
stopTrackingPointer(event.pointer); stopTrackingPointer(event.pointer);
}
} }
} }
...@@ -571,8 +576,9 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni ...@@ -571,8 +576,9 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
_state = GestureRecognizerState.possible; _state = GestureRecognizerState.possible;
_primaryPointer = event.pointer; _primaryPointer = event.pointer;
_initialPosition = OffsetPair(local: event.localPosition, global: event.position); _initialPosition = OffsetPair(local: event.localPosition, global: event.position);
if (deadline != null) if (deadline != null) {
_timer = Timer(deadline!, () => didExceedDeadlineWithEvent(event)); _timer = Timer(deadline!, () => didExceedDeadlineWithEvent(event));
}
} }
} }
......
...@@ -442,8 +442,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -442,8 +442,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
bool shouldStartIfAccepted = false; bool shouldStartIfAccepted = false;
if (event is PointerMoveEvent) { if (event is PointerMoveEvent) {
final VelocityTracker tracker = _velocityTrackers[event.pointer]!; final VelocityTracker tracker = _velocityTrackers[event.pointer]!;
if (!event.synthesized) if (!event.synthesized) {
tracker.addPosition(event.timeStamp, event.position); tracker.addPosition(event.timeStamp, event.position);
}
_pointerLocations[event.pointer] = event.position; _pointerLocations[event.pointer] = event.position;
shouldStartIfAccepted = true; shouldStartIfAccepted = true;
_lastTransform = event.transform; _lastTransform = event.transform;
...@@ -469,8 +470,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -469,8 +470,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
shouldStartIfAccepted = true; shouldStartIfAccepted = true;
} else if (event is PointerPanZoomUpdateEvent) { } else if (event is PointerPanZoomUpdateEvent) {
assert(_pointerPanZooms[event.pointer] != null); assert(_pointerPanZooms[event.pointer] != null);
if (!event.synthesized) if (!event.synthesized) {
_velocityTrackers[event.pointer]!.addPosition(event.timeStamp, event.pan); _velocityTrackers[event.pointer]!.addPosition(event.timeStamp, event.pan);
}
_pointerPanZooms[event.pointer] = _PointerPanZoomData( _pointerPanZooms[event.pointer] = _PointerPanZoomData(
focalPoint: event.position + event.pan, focalPoint: event.position + event.pan,
scale: event.scale, scale: event.scale,
...@@ -487,8 +489,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -487,8 +489,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
_updateLines(); _updateLines();
_update(); _update();
if (!didChangeConfiguration || _reconfigure(event.pointer)) if (!didChangeConfiguration || _reconfigure(event.pointer)) {
_advanceStateMachine(shouldStartIfAccepted, event.kind); _advanceStateMachine(shouldStartIfAccepted, event.kind);
}
stopTrackingIfPointerNoLongerDown(event); stopTrackingIfPointerNoLongerDown(event);
} }
...@@ -497,10 +500,12 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -497,10 +500,12 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
// Compute the focal point // Compute the focal point
Offset focalPoint = Offset.zero; Offset focalPoint = Offset.zero;
for (final int pointer in _pointerLocations.keys) for (final int pointer in _pointerLocations.keys) {
focalPoint += _pointerLocations[pointer]!; focalPoint += _pointerLocations[pointer]!;
for (final _PointerPanZoomData p in _pointerPanZooms.values) }
for (final _PointerPanZoomData p in _pointerPanZooms.values) {
focalPoint += p.focalPoint; focalPoint += p.focalPoint;
}
_currentFocalPoint = _pointerCount > 0 ? focalPoint / _pointerCount.toDouble() : Offset.zero; _currentFocalPoint = _pointerCount > 0 ? focalPoint / _pointerCount.toDouble() : Offset.zero;
if (previousFocalPoint == null) { if (previousFocalPoint == null) {
...@@ -521,10 +526,12 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -521,10 +526,12 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
final int count = _pointerLocations.keys.length; final int count = _pointerLocations.keys.length;
Offset pointerFocalPoint = Offset.zero; Offset pointerFocalPoint = Offset.zero;
for (final int pointer in _pointerLocations.keys) for (final int pointer in _pointerLocations.keys) {
pointerFocalPoint += _pointerLocations[pointer]!; pointerFocalPoint += _pointerLocations[pointer]!;
if (count > 0) }
if (count > 0) {
pointerFocalPoint = pointerFocalPoint / count.toDouble(); pointerFocalPoint = pointerFocalPoint / count.toDouble();
}
// Span is the average deviation from focal point. Horizontal and vertical // Span is the average deviation from focal point. Horizontal and vertical
// spans are the average deviations from the focal point's horizontal and // spans are the average deviations from the focal point's horizontal and
...@@ -592,8 +599,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -592,8 +599,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
Velocity velocity = tracker.getVelocity(); Velocity velocity = tracker.getVelocity();
if (_isFlingGesture(velocity)) { if (_isFlingGesture(velocity)) {
final Offset pixelsPerSecond = velocity.pixelsPerSecond; final Offset pixelsPerSecond = velocity.pixelsPerSecond;
if (pixelsPerSecond.distanceSquared > kMaxFlingVelocity * kMaxFlingVelocity) if (pixelsPerSecond.distanceSquared > kMaxFlingVelocity * kMaxFlingVelocity) {
velocity = Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * kMaxFlingVelocity); velocity = Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * kMaxFlingVelocity);
}
invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(velocity: velocity, pointerCount: _pointerCount))); invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(velocity: velocity, pointerCount: _pointerCount)));
} else { } else {
invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(pointerCount: _pointerCount))); invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(pointerCount: _pointerCount)));
...@@ -606,14 +614,16 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -606,14 +614,16 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
} }
void _advanceStateMachine(bool shouldStartIfAccepted, PointerDeviceKind pointerDeviceKind) { void _advanceStateMachine(bool shouldStartIfAccepted, PointerDeviceKind pointerDeviceKind) {
if (_state == _ScaleState.ready) if (_state == _ScaleState.ready) {
_state = _ScaleState.possible; _state = _ScaleState.possible;
}
if (_state == _ScaleState.possible) { if (_state == _ScaleState.possible) {
final double spanDelta = (_currentSpan - _initialSpan).abs(); final double spanDelta = (_currentSpan - _initialSpan).abs();
final double focalPointDelta = (_currentFocalPoint! - _initialFocalPoint).distance; final double focalPointDelta = (_currentFocalPoint! - _initialFocalPoint).distance;
if (spanDelta > computeScaleSlop(pointerDeviceKind) || focalPointDelta > computePanSlop(pointerDeviceKind, gestureSettings) || math.max(_scaleFactor / _pointerScaleFactor, _pointerScaleFactor / _scaleFactor) > 1.05) if (spanDelta > computeScaleSlop(pointerDeviceKind) || focalPointDelta > computePanSlop(pointerDeviceKind, gestureSettings) || math.max(_scaleFactor / _pointerScaleFactor, _pointerScaleFactor / _scaleFactor) > 1.05) {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
}
} else if (_state.index >= _ScaleState.accepted.index) { } else if (_state.index >= _ScaleState.accepted.index) {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
} }
...@@ -623,7 +633,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -623,7 +633,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
_dispatchOnStartCallbackIfNeeded(); _dispatchOnStartCallbackIfNeeded();
} }
if (_state == _ScaleState.started && onUpdate != null) if (_state == _ScaleState.started && onUpdate != null) {
invokeCallback<void>('onUpdate', () { invokeCallback<void>('onUpdate', () {
onUpdate!(ScaleUpdateDetails( onUpdate!(ScaleUpdateDetails(
scale: _scaleFactor, scale: _scaleFactor,
...@@ -636,11 +646,12 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -636,11 +646,12 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
focalPointDelta: _delta, focalPointDelta: _delta,
)); ));
}); });
}
} }
void _dispatchOnStartCallbackIfNeeded() { void _dispatchOnStartCallbackIfNeeded() {
assert(_state == _ScaleState.started); assert(_state == _ScaleState.started);
if (onStart != null) if (onStart != null) {
invokeCallback<void>('onStart', () { invokeCallback<void>('onStart', () {
onStart!(ScaleStartDetails( onStart!(ScaleStartDetails(
focalPoint: _currentFocalPoint!, focalPoint: _currentFocalPoint!,
...@@ -648,6 +659,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -648,6 +659,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
pointerCount: _pointerCount, pointerCount: _pointerCount,
)); ));
}); });
}
} }
@override @override
......
...@@ -276,8 +276,9 @@ abstract class BaseTapGestureRecognizer extends PrimaryPointerGestureRecognizer ...@@ -276,8 +276,9 @@ abstract class BaseTapGestureRecognizer extends PrimaryPointerGestureRecognizer
if (pointer == primaryPointer) { if (pointer == primaryPointer) {
// Another gesture won the arena. // Another gesture won the arena.
assert(state != GestureRecognizerState.possible); assert(state != GestureRecognizerState.possible);
if (_sentTapDown) if (_sentTapDown) {
_checkCancel(null, 'forced'); _checkCancel(null, 'forced');
}
_reset(); _reset();
} }
} }
...@@ -549,21 +550,24 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer { ...@@ -549,21 +550,24 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer {
if (onTapDown == null && if (onTapDown == null &&
onTap == null && onTap == null &&
onTapUp == null && onTapUp == null &&
onTapCancel == null) onTapCancel == null) {
return false; return false;
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryTap == null && if (onSecondaryTap == null &&
onSecondaryTapDown == null && onSecondaryTapDown == null &&
onSecondaryTapUp == null && onSecondaryTapUp == null &&
onSecondaryTapCancel == null) onSecondaryTapCancel == null) {
return false; return false;
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryTapDown == null && if (onTertiaryTapDown == null &&
onTertiaryTapUp == null && onTertiaryTapUp == null &&
onTertiaryTapCancel == null) onTertiaryTapCancel == null) {
return false; return false;
}
break; break;
default: default:
return false; return false;
...@@ -581,16 +585,19 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer { ...@@ -581,16 +585,19 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer {
); );
switch (down.buttons) { switch (down.buttons) {
case kPrimaryButton: case kPrimaryButton:
if (onTapDown != null) if (onTapDown != null) {
invokeCallback<void>('onTapDown', () => onTapDown!(details)); invokeCallback<void>('onTapDown', () => onTapDown!(details));
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryTapDown != null) if (onSecondaryTapDown != null) {
invokeCallback<void>('onSecondaryTapDown', () => onSecondaryTapDown!(details)); invokeCallback<void>('onSecondaryTapDown', () => onSecondaryTapDown!(details));
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryTapDown != null) if (onTertiaryTapDown != null) {
invokeCallback<void>('onTertiaryTapDown', () => onTertiaryTapDown!(details)); invokeCallback<void>('onTertiaryTapDown', () => onTertiaryTapDown!(details));
}
break; break;
default: default:
} }
...@@ -606,20 +613,25 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer { ...@@ -606,20 +613,25 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer {
); );
switch (down.buttons) { switch (down.buttons) {
case kPrimaryButton: case kPrimaryButton:
if (onTapUp != null) if (onTapUp != null) {
invokeCallback<void>('onTapUp', () => onTapUp!(details)); invokeCallback<void>('onTapUp', () => onTapUp!(details));
if (onTap != null) }
if (onTap != null) {
invokeCallback<void>('onTap', onTap!); invokeCallback<void>('onTap', onTap!);
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryTapUp != null) if (onSecondaryTapUp != null) {
invokeCallback<void>('onSecondaryTapUp', () => onSecondaryTapUp!(details)); invokeCallback<void>('onSecondaryTapUp', () => onSecondaryTapUp!(details));
if (onSecondaryTap != null) }
if (onSecondaryTap != null) {
invokeCallback<void>('onSecondaryTap', () => onSecondaryTap!()); invokeCallback<void>('onSecondaryTap', () => onSecondaryTap!());
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryTapUp != null) if (onTertiaryTapUp != null) {
invokeCallback<void>('onTertiaryTapUp', () => onTertiaryTapUp!(details)); invokeCallback<void>('onTertiaryTapUp', () => onTertiaryTapUp!(details));
}
break; break;
default: default:
} }
...@@ -631,16 +643,19 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer { ...@@ -631,16 +643,19 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer {
final String note = reason == '' ? reason : '$reason '; final String note = reason == '' ? reason : '$reason ';
switch (down.buttons) { switch (down.buttons) {
case kPrimaryButton: case kPrimaryButton:
if (onTapCancel != null) if (onTapCancel != null) {
invokeCallback<void>('${note}onTapCancel', onTapCancel!); invokeCallback<void>('${note}onTapCancel', onTapCancel!);
}
break; break;
case kSecondaryButton: case kSecondaryButton:
if (onSecondaryTapCancel != null) if (onSecondaryTapCancel != null) {
invokeCallback<void>('${note}onSecondaryTapCancel', onSecondaryTapCancel!); invokeCallback<void>('${note}onSecondaryTapCancel', onSecondaryTapCancel!);
}
break; break;
case kTertiaryButton: case kTertiaryButton:
if (onTertiaryTapCancel != null) if (onTertiaryTapCancel != null) {
invokeCallback<void>('${note}onTertiaryTapCancel', onTertiaryTapCancel!); invokeCallback<void>('${note}onTertiaryTapCancel', onTertiaryTapCancel!);
}
break; break;
default: default:
} }
......
...@@ -36,8 +36,9 @@ class _CombiningGestureArenaMember extends GestureArenaMember { ...@@ -36,8 +36,9 @@ class _CombiningGestureArenaMember extends GestureArenaMember {
_close(); _close();
_winner ??= _owner.captain ?? _members[0]; _winner ??= _owner.captain ?? _members[0];
for (final GestureArenaMember member in _members) { for (final GestureArenaMember member in _members) {
if (member != _winner) if (member != _winner) {
member.rejectGesture(pointer); member.rejectGesture(pointer);
}
} }
_winner!.acceptGesture(pointer); _winner!.acceptGesture(pointer);
} }
...@@ -46,8 +47,9 @@ class _CombiningGestureArenaMember extends GestureArenaMember { ...@@ -46,8 +47,9 @@ class _CombiningGestureArenaMember extends GestureArenaMember {
void rejectGesture(int pointer) { void rejectGesture(int pointer) {
assert(_pointer == pointer); assert(_pointer == pointer);
_close(); _close();
for (final GestureArenaMember member in _members) for (final GestureArenaMember member in _members) {
member.rejectGesture(pointer); member.rejectGesture(pointer);
}
} }
void _close() { void _close() {
...@@ -66,13 +68,15 @@ class _CombiningGestureArenaMember extends GestureArenaMember { ...@@ -66,13 +68,15 @@ class _CombiningGestureArenaMember extends GestureArenaMember {
} }
void _resolve(GestureArenaMember member, GestureDisposition disposition) { void _resolve(GestureArenaMember member, GestureDisposition disposition) {
if (_resolved) if (_resolved) {
return; return;
}
if (disposition == GestureDisposition.rejected) { if (disposition == GestureDisposition.rejected) {
_members.remove(member); _members.remove(member);
member.rejectGesture(_pointer); member.rejectGesture(_pointer);
if (_members.isEmpty) if (_members.isEmpty) {
_entry!.resolve(disposition); _entry!.resolve(disposition);
}
} else { } else {
assert(disposition == GestureDisposition.accepted); assert(disposition == GestureDisposition.accepted);
_winner ??= _owner.captain ?? member; _winner ??= _owner.captain ?? member;
......
...@@ -53,10 +53,12 @@ class Velocity { ...@@ -53,10 +53,12 @@ class Velocity {
assert(minValue != null && minValue >= 0.0); assert(minValue != null && minValue >= 0.0);
assert(maxValue != null && maxValue >= 0.0 && maxValue >= minValue); assert(maxValue != null && maxValue >= 0.0 && maxValue >= minValue);
final double valueSquared = pixelsPerSecond.distanceSquared; final double valueSquared = pixelsPerSecond.distanceSquared;
if (valueSquared > maxValue * maxValue) if (valueSquared > maxValue * maxValue) {
return Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * maxValue); return Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * maxValue);
if (valueSquared < minValue * minValue) }
if (valueSquared < minValue * minValue) {
return Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * minValue); return Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * minValue);
}
return this; return this;
} }
...@@ -163,8 +165,9 @@ class VelocityTracker { ...@@ -163,8 +165,9 @@ class VelocityTracker {
/// Adds a position as the given time to the tracker. /// Adds a position as the given time to the tracker.
void addPosition(Duration time, Offset position) { void addPosition(Duration time, Offset position) {
_index += 1; _index += 1;
if (_index == _historySize) if (_index == _historySize) {
_index = 0; _index = 0;
}
_samples[_index] = _PointAtTime(position, time); _samples[_index] = _PointAtTime(position, time);
} }
...@@ -183,8 +186,9 @@ class VelocityTracker { ...@@ -183,8 +186,9 @@ class VelocityTracker {
int index = _index; int index = _index;
final _PointAtTime? newestSample = _samples[index]; final _PointAtTime? newestSample = _samples[index];
if (newestSample == null) if (newestSample == null) {
return null; return null;
}
_PointAtTime previousSample = newestSample; _PointAtTime previousSample = newestSample;
_PointAtTime oldestSample = newestSample; _PointAtTime oldestSample = newestSample;
...@@ -193,14 +197,16 @@ class VelocityTracker { ...@@ -193,14 +197,16 @@ class VelocityTracker {
// the samples represent continuous motion. // the samples represent continuous motion.
do { do {
final _PointAtTime? sample = _samples[index]; final _PointAtTime? sample = _samples[index];
if (sample == null) if (sample == null) {
break; break;
}
final double age = (newestSample.time - sample.time).inMicroseconds.toDouble() / 1000; final double age = (newestSample.time - sample.time).inMicroseconds.toDouble() / 1000;
final double delta = (sample.time - previousSample.time).inMicroseconds.abs().toDouble() / 1000; final double delta = (sample.time - previousSample.time).inMicroseconds.abs().toDouble() / 1000;
previousSample = sample; previousSample = sample;
if (age > _horizonMilliseconds || delta > _assumePointerMoveStoppedMilliseconds) if (age > _horizonMilliseconds || delta > _assumePointerMoveStoppedMilliseconds) {
break; break;
}
oldestSample = sample; oldestSample = sample;
final Offset position = sample.point; final Offset position = sample.point;
...@@ -249,8 +255,9 @@ class VelocityTracker { ...@@ -249,8 +255,9 @@ class VelocityTracker {
/// estimate or if the estimated velocity is zero. /// estimate or if the estimated velocity is zero.
Velocity getVelocity() { Velocity getVelocity() {
final VelocityEstimate? estimate = getVelocityEstimate(); final VelocityEstimate? estimate = getVelocityEstimate();
if (estimate == null || estimate.pixelsPerSecond == Offset.zero) if (estimate == null || estimate.pixelsPerSecond == Offset.zero) {
return Velocity.zero; return Velocity.zero;
}
return Velocity(pixelsPerSecond: estimate.pixelsPerSecond); return Velocity(pixelsPerSecond: estimate.pixelsPerSecond);
} }
} }
...@@ -292,8 +299,9 @@ class IOSScrollViewFlingVelocityTracker extends VelocityTracker { ...@@ -292,8 +299,9 @@ class IOSScrollViewFlingVelocityTracker extends VelocityTracker {
void addPosition(Duration time, Offset position) { void addPosition(Duration time, Offset position) {
assert(() { assert(() {
final _PointAtTime? previousPoint = _touchSamples[_index]; final _PointAtTime? previousPoint = _touchSamples[_index];
if (previousPoint == null || previousPoint.time <= time) if (previousPoint == null || previousPoint.time <= time) {
return true; return true;
}
throw FlutterError( throw FlutterError(
'The position being added ($position) has a smaller timestamp ($time) ' 'The position being added ($position) has a smaller timestamp ($time) '
'than its predecessor: $previousPoint.', 'than its predecessor: $previousPoint.',
...@@ -342,8 +350,9 @@ class IOSScrollViewFlingVelocityTracker extends VelocityTracker { ...@@ -342,8 +350,9 @@ class IOSScrollViewFlingVelocityTracker extends VelocityTracker {
for (int i = 1; i <= _sampleSize; i += 1) { for (int i = 1; i <= _sampleSize; i += 1) {
oldestNonNullSample = _touchSamples[(_index + i) % _sampleSize]; oldestNonNullSample = _touchSamples[(_index + i) % _sampleSize];
if (oldestNonNullSample != null) if (oldestNonNullSample != null) {
break; break;
}
} }
if (oldestNonNullSample == null || newestSample == null) { if (oldestNonNullSample == null || newestSample == null) {
......
...@@ -66,8 +66,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -66,8 +66,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
static HttpClient get _httpClient { static HttpClient get _httpClient {
HttpClient client = _sharedHttpClient; HttpClient client = _sharedHttpClient;
assert(() { assert(() {
if (debugNetworkImageHttpClientProvider != null) if (debugNetworkImageHttpClientProvider != null) {
client = debugNetworkImageHttpClientProvider!(); client = debugNetworkImageHttpClientProvider!();
}
return true; return true;
}()); }());
return client; return client;
...@@ -106,8 +107,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -106,8 +107,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
)); ));
}, },
); );
if (bytes.lengthInBytes == 0) if (bytes.lengthInBytes == 0) {
throw Exception('NetworkImage is an empty file: $resolved'); throw Exception('NetworkImage is an empty file: $resolved');
}
return decode(bytes); return decode(bytes);
} catch (e) { } catch (e) {
...@@ -125,8 +127,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -125,8 +127,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is NetworkImage return other is NetworkImage
&& other.url == url && other.url == url
&& other.scale == scale; && other.scale == scale;
......
...@@ -139,9 +139,10 @@ class NetworkImage ...@@ -139,9 +139,10 @@ class NetworkImage
final Uint8List bytes = (request.response as ByteBuffer).asUint8List(); final Uint8List bytes = (request.response as ByteBuffer).asUint8List();
if (bytes.lengthInBytes == 0) if (bytes.lengthInBytes == 0) {
throw image_provider.NetworkImageLoadException( throw image_provider.NetworkImageLoadException(
statusCode: request.status!, uri: resolved); statusCode: request.status!, uri: resolved);
}
return decode(bytes); return decode(bytes);
} else { } else {
......
...@@ -88,16 +88,21 @@ abstract class AlignmentGeometry { ...@@ -88,16 +88,21 @@ abstract class AlignmentGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static AlignmentGeometry? lerp(AlignmentGeometry? a, AlignmentGeometry? b, double t) { static AlignmentGeometry? lerp(AlignmentGeometry? a, AlignmentGeometry? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b! * t; return b! * t;
if (b == null) }
if (b == null) {
return a * (1.0 - t); return a * (1.0 - t);
if (a is Alignment && b is Alignment) }
if (a is Alignment && b is Alignment) {
return Alignment.lerp(a, b, t); return Alignment.lerp(a, b, t);
if (a is AlignmentDirectional && b is AlignmentDirectional) }
if (a is AlignmentDirectional && b is AlignmentDirectional) {
return AlignmentDirectional.lerp(a, b, t); return AlignmentDirectional.lerp(a, b, t);
}
return _MixedAlignment( return _MixedAlignment(
ui.lerpDouble(a._x, b._x, t)!, ui.lerpDouble(a._x, b._x, t)!,
ui.lerpDouble(a._start, b._start, t)!, ui.lerpDouble(a._start, b._start, t)!,
...@@ -118,10 +123,12 @@ abstract class AlignmentGeometry { ...@@ -118,10 +123,12 @@ abstract class AlignmentGeometry {
@override @override
String toString() { String toString() {
if (_start == 0.0) if (_start == 0.0) {
return Alignment._stringify(_x, _y); return Alignment._stringify(_x, _y);
if (_x == 0.0) }
if (_x == 0.0) {
return AlignmentDirectional._stringify(_start, _y); return AlignmentDirectional._stringify(_start, _y);
}
return '${Alignment._stringify(_x, _y)} + ${AlignmentDirectional._stringify(_start, 0.0)}'; return '${Alignment._stringify(_x, _y)} + ${AlignmentDirectional._stringify(_start, 0.0)}';
} }
...@@ -240,8 +247,9 @@ class Alignment extends AlignmentGeometry { ...@@ -240,8 +247,9 @@ class Alignment extends AlignmentGeometry {
@override @override
AlignmentGeometry add(AlignmentGeometry other) { AlignmentGeometry add(AlignmentGeometry other) {
if (other is Alignment) if (other is Alignment) {
return this + other; return this + other;
}
return super.add(other); return super.add(other);
} }
...@@ -333,12 +341,15 @@ class Alignment extends AlignmentGeometry { ...@@ -333,12 +341,15 @@ class Alignment extends AlignmentGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static Alignment? lerp(Alignment? a, Alignment? b, double t) { static Alignment? lerp(Alignment? a, Alignment? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return Alignment(ui.lerpDouble(0.0, b!.x, t)!, ui.lerpDouble(0.0, b.y, t)!); return Alignment(ui.lerpDouble(0.0, b!.x, t)!, ui.lerpDouble(0.0, b.y, t)!);
if (b == null) }
if (b == null) {
return Alignment(ui.lerpDouble(a.x, 0.0, t)!, ui.lerpDouble(a.y, 0.0, t)!); return Alignment(ui.lerpDouble(a.x, 0.0, t)!, ui.lerpDouble(a.y, 0.0, t)!);
}
return Alignment(ui.lerpDouble(a.x, b.x, t)!, ui.lerpDouble(a.y, b.y, t)!); return Alignment(ui.lerpDouble(a.x, b.x, t)!, ui.lerpDouble(a.y, b.y, t)!);
} }
...@@ -346,24 +357,33 @@ class Alignment extends AlignmentGeometry { ...@@ -346,24 +357,33 @@ class Alignment extends AlignmentGeometry {
Alignment resolve(TextDirection? direction) => this; Alignment resolve(TextDirection? direction) => this;
static String _stringify(double x, double y) { static String _stringify(double x, double y) {
if (x == -1.0 && y == -1.0) if (x == -1.0 && y == -1.0) {
return 'Alignment.topLeft'; return 'Alignment.topLeft';
if (x == 0.0 && y == -1.0) }
if (x == 0.0 && y == -1.0) {
return 'Alignment.topCenter'; return 'Alignment.topCenter';
if (x == 1.0 && y == -1.0) }
if (x == 1.0 && y == -1.0) {
return 'Alignment.topRight'; return 'Alignment.topRight';
if (x == -1.0 && y == 0.0) }
if (x == -1.0 && y == 0.0) {
return 'Alignment.centerLeft'; return 'Alignment.centerLeft';
if (x == 0.0 && y == 0.0) }
if (x == 0.0 && y == 0.0) {
return 'Alignment.center'; return 'Alignment.center';
if (x == 1.0 && y == 0.0) }
if (x == 1.0 && y == 0.0) {
return 'Alignment.centerRight'; return 'Alignment.centerRight';
if (x == -1.0 && y == 1.0) }
if (x == -1.0 && y == 1.0) {
return 'Alignment.bottomLeft'; return 'Alignment.bottomLeft';
if (x == 0.0 && y == 1.0) }
if (x == 0.0 && y == 1.0) {
return 'Alignment.bottomCenter'; return 'Alignment.bottomCenter';
if (x == 1.0 && y == 1.0) }
if (x == 1.0 && y == 1.0) {
return 'Alignment.bottomRight'; return 'Alignment.bottomRight';
}
return 'Alignment(${x.toStringAsFixed(1)}, ' return 'Alignment(${x.toStringAsFixed(1)}, '
'${y.toStringAsFixed(1)})'; '${y.toStringAsFixed(1)})';
} }
...@@ -462,8 +482,9 @@ class AlignmentDirectional extends AlignmentGeometry { ...@@ -462,8 +482,9 @@ class AlignmentDirectional extends AlignmentGeometry {
@override @override
AlignmentGeometry add(AlignmentGeometry other) { AlignmentGeometry add(AlignmentGeometry other) {
if (other is AlignmentDirectional) if (other is AlignmentDirectional) {
return this + other; return this + other;
}
return super.add(other); return super.add(other);
} }
...@@ -514,12 +535,15 @@ class AlignmentDirectional extends AlignmentGeometry { ...@@ -514,12 +535,15 @@ class AlignmentDirectional extends AlignmentGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static AlignmentDirectional? lerp(AlignmentDirectional? a, AlignmentDirectional? b, double t) { static AlignmentDirectional? lerp(AlignmentDirectional? a, AlignmentDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return AlignmentDirectional(ui.lerpDouble(0.0, b!.start, t)!, ui.lerpDouble(0.0, b.y, t)!); return AlignmentDirectional(ui.lerpDouble(0.0, b!.start, t)!, ui.lerpDouble(0.0, b.y, t)!);
if (b == null) }
if (b == null) {
return AlignmentDirectional(ui.lerpDouble(a.start, 0.0, t)!, ui.lerpDouble(a.y, 0.0, t)!); return AlignmentDirectional(ui.lerpDouble(a.start, 0.0, t)!, ui.lerpDouble(a.y, 0.0, t)!);
}
return AlignmentDirectional(ui.lerpDouble(a.start, b.start, t)!, ui.lerpDouble(a.y, b.y, t)!); return AlignmentDirectional(ui.lerpDouble(a.start, b.start, t)!, ui.lerpDouble(a.y, b.y, t)!);
} }
...@@ -535,24 +559,33 @@ class AlignmentDirectional extends AlignmentGeometry { ...@@ -535,24 +559,33 @@ class AlignmentDirectional extends AlignmentGeometry {
} }
static String _stringify(double start, double y) { static String _stringify(double start, double y) {
if (start == -1.0 && y == -1.0) if (start == -1.0 && y == -1.0) {
return 'AlignmentDirectional.topStart'; return 'AlignmentDirectional.topStart';
if (start == 0.0 && y == -1.0) }
if (start == 0.0 && y == -1.0) {
return 'AlignmentDirectional.topCenter'; return 'AlignmentDirectional.topCenter';
if (start == 1.0 && y == -1.0) }
if (start == 1.0 && y == -1.0) {
return 'AlignmentDirectional.topEnd'; return 'AlignmentDirectional.topEnd';
if (start == -1.0 && y == 0.0) }
if (start == -1.0 && y == 0.0) {
return 'AlignmentDirectional.centerStart'; return 'AlignmentDirectional.centerStart';
if (start == 0.0 && y == 0.0) }
if (start == 0.0 && y == 0.0) {
return 'AlignmentDirectional.center'; return 'AlignmentDirectional.center';
if (start == 1.0 && y == 0.0) }
if (start == 1.0 && y == 0.0) {
return 'AlignmentDirectional.centerEnd'; return 'AlignmentDirectional.centerEnd';
if (start == -1.0 && y == 1.0) }
if (start == -1.0 && y == 1.0) {
return 'AlignmentDirectional.bottomStart'; return 'AlignmentDirectional.bottomStart';
if (start == 0.0 && y == 1.0) }
if (start == 0.0 && y == 1.0) {
return 'AlignmentDirectional.bottomCenter'; return 'AlignmentDirectional.bottomCenter';
if (start == 1.0 && y == 1.0) }
if (start == 1.0 && y == 1.0) {
return 'AlignmentDirectional.bottomEnd'; return 'AlignmentDirectional.bottomEnd';
}
return 'AlignmentDirectional(${start.toStringAsFixed(1)}, ' return 'AlignmentDirectional(${start.toStringAsFixed(1)}, '
'${y.toStringAsFixed(1)})'; '${y.toStringAsFixed(1)})';
} }
......
...@@ -149,8 +149,9 @@ class BeveledRectangleBorder extends OutlinedBorder { ...@@ -149,8 +149,9 @@ class BeveledRectangleBorder extends OutlinedBorder {
@override @override
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) { void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
if (rect.isEmpty) if (rect.isEmpty) {
return; return;
}
switch (side.style) { switch (side.style) {
case BorderStyle.none: case BorderStyle.none:
break; break;
...@@ -177,8 +178,9 @@ class BeveledRectangleBorder extends OutlinedBorder { ...@@ -177,8 +178,9 @@ class BeveledRectangleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is BeveledRectangleBorder return other is BeveledRectangleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius; && other.borderRadius == borderRadius;
......
...@@ -130,8 +130,9 @@ abstract class BorderRadiusGeometry { ...@@ -130,8 +130,9 @@ abstract class BorderRadiusGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadiusGeometry? lerp(BorderRadiusGeometry? a, BorderRadiusGeometry? b, double t) { static BorderRadiusGeometry? lerp(BorderRadiusGeometry? a, BorderRadiusGeometry? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
}
a ??= BorderRadius.zero; a ??= BorderRadius.zero;
b ??= BorderRadius.zero; b ??= BorderRadius.zero;
return a.add((b.subtract(a)) * t); return a.add((b.subtract(a)) * t);
...@@ -171,20 +172,23 @@ abstract class BorderRadiusGeometry { ...@@ -171,20 +172,23 @@ abstract class BorderRadiusGeometry {
comma = true; comma = true;
} }
if (_topRight != Radius.zero) { if (_topRight != Radius.zero) {
if (comma) if (comma) {
result.write(', '); result.write(', ');
}
result.write('topRight: $_topRight'); result.write('topRight: $_topRight');
comma = true; comma = true;
} }
if (_bottomLeft != Radius.zero) { if (_bottomLeft != Radius.zero) {
if (comma) if (comma) {
result.write(', '); result.write(', ');
}
result.write('bottomLeft: $_bottomLeft'); result.write('bottomLeft: $_bottomLeft');
comma = true; comma = true;
} }
if (_bottomRight != Radius.zero) { if (_bottomRight != Radius.zero) {
if (comma) if (comma) {
result.write(', '); result.write(', ');
}
result.write('bottomRight: $_bottomRight'); result.write('bottomRight: $_bottomRight');
} }
result.write(')'); result.write(')');
...@@ -210,40 +214,48 @@ abstract class BorderRadiusGeometry { ...@@ -210,40 +214,48 @@ abstract class BorderRadiusGeometry {
comma = true; comma = true;
} }
if (_topEnd != Radius.zero) { if (_topEnd != Radius.zero) {
if (comma) if (comma) {
result.write(', '); result.write(', ');
}
result.write('topEnd: $_topEnd'); result.write('topEnd: $_topEnd');
comma = true; comma = true;
} }
if (_bottomStart != Radius.zero) { if (_bottomStart != Radius.zero) {
if (comma) if (comma) {
result.write(', '); result.write(', ');
}
result.write('bottomStart: $_bottomStart'); result.write('bottomStart: $_bottomStart');
comma = true; comma = true;
} }
if (_bottomEnd != Radius.zero) { if (_bottomEnd != Radius.zero) {
if (comma) if (comma) {
result.write(', '); result.write(', ');
}
result.write('bottomEnd: $_bottomEnd'); result.write('bottomEnd: $_bottomEnd');
} }
result.write(')'); result.write(')');
logical = result.toString(); logical = result.toString();
} }
if (visual != null && logical != null) if (visual != null && logical != null) {
return '$visual + $logical'; return '$visual + $logical';
if (visual != null) }
if (visual != null) {
return visual; return visual;
if (logical != null) }
if (logical != null) {
return logical; return logical;
}
return 'BorderRadius.zero'; return 'BorderRadius.zero';
} }
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is BorderRadiusGeometry return other is BorderRadiusGeometry
&& other._topLeft == _topLeft && other._topLeft == _topLeft
&& other._topRight == _topRight && other._topRight == _topRight
...@@ -392,15 +404,17 @@ class BorderRadius extends BorderRadiusGeometry { ...@@ -392,15 +404,17 @@ class BorderRadius extends BorderRadiusGeometry {
@override @override
BorderRadiusGeometry subtract(BorderRadiusGeometry other) { BorderRadiusGeometry subtract(BorderRadiusGeometry other) {
if (other is BorderRadius) if (other is BorderRadius) {
return this - other; return this - other;
}
return super.subtract(other); return super.subtract(other);
} }
@override @override
BorderRadiusGeometry add(BorderRadiusGeometry other) { BorderRadiusGeometry add(BorderRadiusGeometry other) {
if (other is BorderRadius) if (other is BorderRadius) {
return this + other; return this + other;
}
return super.add(other); return super.add(other);
} }
...@@ -488,12 +502,15 @@ class BorderRadius extends BorderRadiusGeometry { ...@@ -488,12 +502,15 @@ class BorderRadius extends BorderRadiusGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadius? lerp(BorderRadius? a, BorderRadius? b, double t) { static BorderRadius? lerp(BorderRadius? a, BorderRadius? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b! * t; return b! * t;
if (b == null) }
if (b == null) {
return a * (1.0 - t); return a * (1.0 - t);
}
return BorderRadius.only( return BorderRadius.only(
topLeft: Radius.lerp(a.topLeft, b.topLeft, t)!, topLeft: Radius.lerp(a.topLeft, b.topLeft, t)!,
topRight: Radius.lerp(a.topRight, b.topRight, t)!, topRight: Radius.lerp(a.topRight, b.topRight, t)!,
...@@ -609,15 +626,17 @@ class BorderRadiusDirectional extends BorderRadiusGeometry { ...@@ -609,15 +626,17 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
@override @override
BorderRadiusGeometry subtract(BorderRadiusGeometry other) { BorderRadiusGeometry subtract(BorderRadiusGeometry other) {
if (other is BorderRadiusDirectional) if (other is BorderRadiusDirectional) {
return this - other; return this - other;
}
return super.subtract(other); return super.subtract(other);
} }
@override @override
BorderRadiusGeometry add(BorderRadiusGeometry other) { BorderRadiusGeometry add(BorderRadiusGeometry other) {
if (other is BorderRadiusDirectional) if (other is BorderRadiusDirectional) {
return this + other; return this + other;
}
return super.add(other); return super.add(other);
} }
...@@ -705,12 +724,15 @@ class BorderRadiusDirectional extends BorderRadiusGeometry { ...@@ -705,12 +724,15 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadiusDirectional? lerp(BorderRadiusDirectional? a, BorderRadiusDirectional? b, double t) { static BorderRadiusDirectional? lerp(BorderRadiusDirectional? a, BorderRadiusDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b! * t; return b! * t;
if (b == null) }
if (b == null) {
return a * (1.0 - t); return a * (1.0 - t);
}
return BorderRadiusDirectional.only( return BorderRadiusDirectional.only(
topStart: Radius.lerp(a.topStart, b.topStart, t)!, topStart: Radius.lerp(a.topStart, b.topStart, t)!,
topEnd: Radius.lerp(a.topEnd, b.topEnd, t)!, topEnd: Radius.lerp(a.topEnd, b.topEnd, t)!,
......
...@@ -110,12 +110,15 @@ class BorderSide { ...@@ -110,12 +110,15 @@ class BorderSide {
assert(canMerge(a, b)); assert(canMerge(a, b));
final bool aIsNone = a.style == BorderStyle.none && a.width == 0.0; final bool aIsNone = a.style == BorderStyle.none && a.width == 0.0;
final bool bIsNone = b.style == BorderStyle.none && b.width == 0.0; final bool bIsNone = b.style == BorderStyle.none && b.width == 0.0;
if (aIsNone && bIsNone) if (aIsNone && bIsNone) {
return BorderSide.none; return BorderSide.none;
if (aIsNone) }
if (aIsNone) {
return b; return b;
if (bIsNone) }
if (bIsNone) {
return a; return a;
}
assert(a.color == b.color); assert(a.color == b.color);
assert(a.style == b.style); assert(a.style == b.style);
return BorderSide( return BorderSide(
...@@ -222,8 +225,9 @@ class BorderSide { ...@@ -222,8 +225,9 @@ class BorderSide {
assert(a != null); assert(a != null);
assert(b != null); assert(b != null);
if ((a.style == BorderStyle.none && a.width == 0.0) || if ((a.style == BorderStyle.none && a.width == 0.0) ||
(b.style == BorderStyle.none && b.width == 0.0)) (b.style == BorderStyle.none && b.width == 0.0)) {
return true; return true;
}
return a.style == b.style return a.style == b.style
&& a.color == b.color && a.color == b.color
&& a.strokeAlign == b.strokeAlign; && a.strokeAlign == b.strokeAlign;
...@@ -238,13 +242,16 @@ class BorderSide { ...@@ -238,13 +242,16 @@ class BorderSide {
assert(a != null); assert(a != null);
assert(b != null); assert(b != null);
assert(t != null); assert(t != null);
if (t == 0.0) if (t == 0.0) {
return a; return a;
if (t == 1.0) }
if (t == 1.0) {
return b; return b;
}
final double width = ui.lerpDouble(a.width, b.width, t)!; final double width = ui.lerpDouble(a.width, b.width, t)!;
if (width < 0.0) if (width < 0.0) {
return BorderSide.none; return BorderSide.none;
}
if (a.style == b.style && a.strokeAlign == b.strokeAlign) { if (a.style == b.style && a.strokeAlign == b.strokeAlign) {
return BorderSide( return BorderSide(
color: Color.lerp(a.color, b.color, t)!, color: Color.lerp(a.color, b.color, t)!,
...@@ -289,10 +296,12 @@ class BorderSide { ...@@ -289,10 +296,12 @@ class BorderSide {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is BorderSide return other is BorderSide
&& other.color == color && other.color == color
&& other.width == width && other.width == width
...@@ -423,8 +432,9 @@ abstract class ShapeBorder { ...@@ -423,8 +432,9 @@ abstract class ShapeBorder {
/// Instead of calling this directly, use [ShapeBorder.lerp]. /// Instead of calling this directly, use [ShapeBorder.lerp].
@protected @protected
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a == null) if (a == null) {
return scale(t); return scale(t);
}
return null; return null;
} }
...@@ -455,8 +465,9 @@ abstract class ShapeBorder { ...@@ -455,8 +465,9 @@ abstract class ShapeBorder {
/// Instead of calling this directly, use [ShapeBorder.lerp]. /// Instead of calling this directly, use [ShapeBorder.lerp].
@protected @protected
ShapeBorder? lerpTo(ShapeBorder? b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b == null) if (b == null) {
return scale(1.0 - t); return scale(1.0 - t);
}
return null; return null;
} }
...@@ -471,10 +482,12 @@ abstract class ShapeBorder { ...@@ -471,10 +482,12 @@ abstract class ShapeBorder {
static ShapeBorder? lerp(ShapeBorder? a, ShapeBorder? b, double t) { static ShapeBorder? lerp(ShapeBorder? a, ShapeBorder? b, double t) {
assert(t != null); assert(t != null);
ShapeBorder? result; ShapeBorder? result;
if (b != null) if (b != null) {
result = b.lerpFrom(a, t); result = b.lerpFrom(a, t);
if (result == null && a != null) }
if (result == null && a != null) {
result = a.lerpTo(b, t); result = a.lerpTo(b, t);
}
return result ?? (t < 0.5 ? a : b); return result ?? (t < 0.5 ? a : b);
} }
...@@ -644,18 +657,21 @@ class _CompoundBorder extends ShapeBorder { ...@@ -644,18 +657,21 @@ class _CompoundBorder extends ShapeBorder {
// is inserted before the shape that is going away, so that the outer path changes to // is inserted before the shape that is going away, so that the outer path changes to
// the new border earlier rather than later. (This affects, among other things, where // the new border earlier rather than later. (This affects, among other things, where
// the ShapeDecoration class puts its background.) // the ShapeDecoration class puts its background.)
if (localB != null) if (localB != null) {
results.add(localB.scale(t)); results.add(localB.scale(t));
if (localA != null) }
if (localA != null) {
results.add(localA.scale(1.0 - t)); results.add(localA.scale(1.0 - t));
}
} }
return _CompoundBorder(results); return _CompoundBorder(results);
} }
@override @override
Path getInnerPath(Rect rect, { TextDirection? textDirection }) { Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
for (int index = 0; index < borders.length - 1; index += 1) for (int index = 0; index < borders.length - 1; index += 1) {
rect = borders[index].dimensions.resolve(textDirection).deflateRect(rect); rect = borders[index].dimensions.resolve(textDirection).deflateRect(rect);
}
return borders.last.getInnerPath(rect, textDirection: textDirection); return borders.last.getInnerPath(rect, textDirection: textDirection);
} }
...@@ -674,10 +690,12 @@ class _CompoundBorder extends ShapeBorder { ...@@ -674,10 +690,12 @@ class _CompoundBorder extends ShapeBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is _CompoundBorder return other is _CompoundBorder
&& listEquals<ShapeBorder>(other.borders, borders); && listEquals<ShapeBorder>(other.borders, borders);
} }
......
...@@ -104,10 +104,12 @@ abstract class BoxBorder extends ShapeBorder { ...@@ -104,10 +104,12 @@ abstract class BoxBorder extends ShapeBorder {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxBorder? lerp(BoxBorder? a, BoxBorder? b, double t) { static BoxBorder? lerp(BoxBorder? a, BoxBorder? b, double t) {
assert(t != null); assert(t != null);
if ((a is Border?) && (b is Border?)) if ((a is Border?) && (b is Border?)) {
return Border.lerp(a, b, t); return Border.lerp(a, b, t);
if ((a is BorderDirectional?) && (b is BorderDirectional?)) }
if ((a is BorderDirectional?) && (b is BorderDirectional?)) {
return BorderDirectional.lerp(a, b, t); return BorderDirectional.lerp(a, b, t);
}
if (b is Border && a is BorderDirectional) { if (b is Border && a is BorderDirectional) {
final BoxBorder c = b; final BoxBorder c = b;
b = a; b = a;
...@@ -490,15 +492,17 @@ class Border extends BoxBorder { ...@@ -490,15 +492,17 @@ class Border extends BoxBorder {
@override @override
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a is Border) if (a is Border) {
return Border.lerp(a, this, t); return Border.lerp(a, this, t);
}
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
ShapeBorder? lerpTo(ShapeBorder? b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is Border) if (b is Border) {
return Border.lerp(this, b, t); return Border.lerp(this, b, t);
}
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
...@@ -510,12 +514,15 @@ class Border extends BoxBorder { ...@@ -510,12 +514,15 @@ class Border extends BoxBorder {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static Border? lerp(Border? a, Border? b, double t) { static Border? lerp(Border? a, Border? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
}
return Border( return Border(
top: BorderSide.lerp(a.top, b.top, t), top: BorderSide.lerp(a.top, b.top, t),
right: BorderSide.lerp(a.right, b.right, t), right: BorderSide.lerp(a.right, b.right, t),
...@@ -613,10 +620,12 @@ class Border extends BoxBorder { ...@@ -613,10 +620,12 @@ class Border extends BoxBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is Border return other is Border
&& other.top == top && other.top == top
&& other.right == right && other.right == right
...@@ -629,8 +638,9 @@ class Border extends BoxBorder { ...@@ -629,8 +638,9 @@ class Border extends BoxBorder {
@override @override
String toString() { String toString() {
if (isUniform) if (isUniform) {
return '${objectRuntimeType(this, 'Border')}.all($top)'; return '${objectRuntimeType(this, 'Border')}.all($top)';
}
final List<String> arguments = <String>[ final List<String> arguments = <String>[
if (top != BorderSide.none) 'top: $top', if (top != BorderSide.none) 'top: $top',
if (right != BorderSide.none) 'right: $right', if (right != BorderSide.none) 'right: $right',
...@@ -748,23 +758,27 @@ class BorderDirectional extends BoxBorder { ...@@ -748,23 +758,27 @@ class BorderDirectional extends BoxBorder {
final Color topColor = top.color; final Color topColor = top.color;
if (start.color != topColor || if (start.color != topColor ||
end.color != topColor || end.color != topColor ||
bottom.color != topColor) bottom.color != topColor) {
return false; return false;
}
final double topWidth = top.width; final double topWidth = top.width;
if (start.width != topWidth || if (start.width != topWidth ||
end.width != topWidth || end.width != topWidth ||
bottom.width != topWidth) bottom.width != topWidth) {
return false; return false;
}
final BorderStyle topStyle = top.style; final BorderStyle topStyle = top.style;
if (start.style != topStyle || if (start.style != topStyle ||
end.style != topStyle || end.style != topStyle ||
bottom.style != topStyle) bottom.style != topStyle) {
return false; return false;
}
if (_strokeAlignIsUniform == false) if (_strokeAlignIsUniform == false) {
return false; return false;
}
return true; return true;
} }
...@@ -791,13 +805,15 @@ class BorderDirectional extends BoxBorder { ...@@ -791,13 +805,15 @@ class BorderDirectional extends BoxBorder {
if (other is Border) { if (other is Border) {
final Border typedOther = other; final Border typedOther = other;
if (!BorderSide.canMerge(typedOther.top, top) || if (!BorderSide.canMerge(typedOther.top, top) ||
!BorderSide.canMerge(typedOther.bottom, bottom)) !BorderSide.canMerge(typedOther.bottom, bottom)) {
return null; return null;
}
if (start != BorderSide.none || if (start != BorderSide.none ||
end != BorderSide.none) { end != BorderSide.none) {
if (typedOther.left != BorderSide.none || if (typedOther.left != BorderSide.none ||
typedOther.right != BorderSide.none) typedOther.right != BorderSide.none) {
return null; return null;
}
assert(typedOther.left == BorderSide.none); assert(typedOther.left == BorderSide.none);
assert(typedOther.right == BorderSide.none); assert(typedOther.right == BorderSide.none);
return BorderDirectional( return BorderDirectional(
...@@ -831,15 +847,17 @@ class BorderDirectional extends BoxBorder { ...@@ -831,15 +847,17 @@ class BorderDirectional extends BoxBorder {
@override @override
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a is BorderDirectional) if (a is BorderDirectional) {
return BorderDirectional.lerp(a, this, t); return BorderDirectional.lerp(a, this, t);
}
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
ShapeBorder? lerpTo(ShapeBorder? b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is BorderDirectional) if (b is BorderDirectional) {
return BorderDirectional.lerp(this, b, t); return BorderDirectional.lerp(this, b, t);
}
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
...@@ -851,12 +869,15 @@ class BorderDirectional extends BoxBorder { ...@@ -851,12 +869,15 @@ class BorderDirectional extends BoxBorder {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderDirectional? lerp(BorderDirectional? a, BorderDirectional? b, double t) { static BorderDirectional? lerp(BorderDirectional? a, BorderDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
}
return BorderDirectional( return BorderDirectional(
top: BorderSide.lerp(a.top, b.top, t), top: BorderSide.lerp(a.top, b.top, t),
end: BorderSide.lerp(a.end, b.end, t), end: BorderSide.lerp(a.end, b.end, t),
...@@ -938,10 +959,12 @@ class BorderDirectional extends BoxBorder { ...@@ -938,10 +959,12 @@ class BorderDirectional extends BoxBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is BorderDirectional return other is BorderDirectional
&& other.top == top && other.top == top
&& other.start == start && other.start == start
......
...@@ -220,8 +220,9 @@ class BoxDecoration extends Decoration { ...@@ -220,8 +220,9 @@ class BoxDecoration extends Decoration {
final Rect square = Rect.fromCircle(center: center, radius: radius); final Rect square = Rect.fromCircle(center: center, radius: radius);
return Path()..addOval(square); return Path()..addOval(square);
case BoxShape.rectangle: case BoxShape.rectangle:
if (borderRadius != null) if (borderRadius != null) {
return Path()..addRRect(borderRadius!.resolve(textDirection).toRRect(rect)); return Path()..addRRect(borderRadius!.resolve(textDirection).toRRect(rect));
}
return Path()..addRect(rect); return Path()..addRect(rect);
} }
} }
...@@ -244,19 +245,23 @@ class BoxDecoration extends Decoration { ...@@ -244,19 +245,23 @@ class BoxDecoration extends Decoration {
@override @override
BoxDecoration? lerpFrom(Decoration? a, double t) { BoxDecoration? lerpFrom(Decoration? a, double t) {
if (a == null) if (a == null) {
return scale(t); return scale(t);
if (a is BoxDecoration) }
if (a is BoxDecoration) {
return BoxDecoration.lerp(a, this, t); return BoxDecoration.lerp(a, this, t);
}
return super.lerpFrom(a, t) as BoxDecoration?; return super.lerpFrom(a, t) as BoxDecoration?;
} }
@override @override
BoxDecoration? lerpTo(Decoration? b, double t) { BoxDecoration? lerpTo(Decoration? b, double t) {
if (b == null) if (b == null) {
return scale(1.0 - t); return scale(1.0 - t);
if (b is BoxDecoration) }
if (b is BoxDecoration) {
return BoxDecoration.lerp(this, b, t); return BoxDecoration.lerp(this, b, t);
}
return super.lerpTo(b, t) as BoxDecoration?; return super.lerpTo(b, t) as BoxDecoration?;
} }
...@@ -285,16 +290,21 @@ class BoxDecoration extends Decoration { ...@@ -285,16 +290,21 @@ class BoxDecoration extends Decoration {
/// [BoxDecoration]s or a [BoxDecoration] to or from null. /// [BoxDecoration]s or a [BoxDecoration] to or from null.
static BoxDecoration? lerp(BoxDecoration? a, BoxDecoration? b, double t) { static BoxDecoration? lerp(BoxDecoration? a, BoxDecoration? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
if (t == 0.0) }
if (t == 0.0) {
return a; return a;
if (t == 1.0) }
if (t == 1.0) {
return b; return b;
}
return BoxDecoration( return BoxDecoration(
color: Color.lerp(a.color, b.color, t), color: Color.lerp(a.color, b.color, t),
image: t < 0.5 ? a.image : b.image, // TODO(ianh): cross-fade the image image: t < 0.5 ? a.image : b.image, // TODO(ianh): cross-fade the image
...@@ -308,10 +318,12 @@ class BoxDecoration extends Decoration { ...@@ -308,10 +318,12 @@ class BoxDecoration extends Decoration {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is BoxDecoration return other is BoxDecoration
&& other.color == color && other.color == color
&& other.image == image && other.image == image
...@@ -394,10 +406,12 @@ class _BoxDecorationPainter extends BoxPainter { ...@@ -394,10 +406,12 @@ class _BoxDecorationPainter extends BoxPainter {
if (_cachedBackgroundPaint == null || if (_cachedBackgroundPaint == null ||
(_decoration.gradient != null && _rectForCachedBackgroundPaint != rect)) { (_decoration.gradient != null && _rectForCachedBackgroundPaint != rect)) {
final Paint paint = Paint(); final Paint paint = Paint();
if (_decoration.backgroundBlendMode != null) if (_decoration.backgroundBlendMode != null) {
paint.blendMode = _decoration.backgroundBlendMode!; paint.blendMode = _decoration.backgroundBlendMode!;
if (_decoration.color != null) }
if (_decoration.color != null) {
paint.color = _decoration.color!; paint.color = _decoration.color!;
}
if (_decoration.gradient != null) { if (_decoration.gradient != null) {
paint.shader = _decoration.gradient!.createShader(rect, textDirection: textDirection); paint.shader = _decoration.gradient!.createShader(rect, textDirection: textDirection);
_rectForCachedBackgroundPaint = rect; _rectForCachedBackgroundPaint = rect;
...@@ -427,8 +441,9 @@ class _BoxDecorationPainter extends BoxPainter { ...@@ -427,8 +441,9 @@ class _BoxDecorationPainter extends BoxPainter {
} }
void _paintShadows(Canvas canvas, Rect rect, TextDirection? textDirection) { void _paintShadows(Canvas canvas, Rect rect, TextDirection? textDirection) {
if (_decoration.boxShadow == null) if (_decoration.boxShadow == null) {
return; return;
}
for (final BoxShadow boxShadow in _decoration.boxShadow!) { for (final BoxShadow boxShadow in _decoration.boxShadow!) {
final Paint paint = boxShadow.toPaint(); final Paint paint = boxShadow.toPaint();
final Rect bounds = rect.shift(boxShadow.offset).inflate(boxShadow.spreadRadius); final Rect bounds = rect.shift(boxShadow.offset).inflate(boxShadow.spreadRadius);
...@@ -437,14 +452,16 @@ class _BoxDecorationPainter extends BoxPainter { ...@@ -437,14 +452,16 @@ class _BoxDecorationPainter extends BoxPainter {
} }
void _paintBackgroundColor(Canvas canvas, Rect rect, TextDirection? textDirection) { void _paintBackgroundColor(Canvas canvas, Rect rect, TextDirection? textDirection) {
if (_decoration.color != null || _decoration.gradient != null) if (_decoration.color != null || _decoration.gradient != null) {
_paintBox(canvas, rect, _getBackgroundPaint(rect, textDirection), textDirection); _paintBox(canvas, rect, _getBackgroundPaint(rect, textDirection), textDirection);
}
} }
DecorationImagePainter? _imagePainter; DecorationImagePainter? _imagePainter;
void _paintBackgroundImage(Canvas canvas, Rect rect, ImageConfiguration configuration) { void _paintBackgroundImage(Canvas canvas, Rect rect, ImageConfiguration configuration) {
if (_decoration.image == null) if (_decoration.image == null) {
return; return;
}
_imagePainter ??= _decoration.image!.createPainter(onChanged!); _imagePainter ??= _decoration.image!.createPainter(onChanged!);
Path? clipPath; Path? clipPath;
switch (_decoration.shape) { switch (_decoration.shape) {
...@@ -456,8 +473,9 @@ class _BoxDecorationPainter extends BoxPainter { ...@@ -456,8 +473,9 @@ class _BoxDecorationPainter extends BoxPainter {
clipPath = Path()..addOval(square); clipPath = Path()..addOval(square);
break; break;
case BoxShape.rectangle: case BoxShape.rectangle:
if (_decoration.borderRadius != null) if (_decoration.borderRadius != null) {
clipPath = Path()..addRRect(_decoration.borderRadius!.resolve(configuration.textDirection).toRRect(rect)); clipPath = Path()..addRRect(_decoration.borderRadius!.resolve(configuration.textDirection).toRRect(rect));
}
break; break;
} }
_imagePainter!.paint(canvas, rect, clipPath, configuration); _imagePainter!.paint(canvas, rect, clipPath, configuration);
......
...@@ -139,8 +139,9 @@ class FittedSizes { ...@@ -139,8 +139,9 @@ class FittedSizes {
/// * [DecoratedBox], [BoxDecoration], and [DecorationImage], which together /// * [DecoratedBox], [BoxDecoration], and [DecorationImage], which together
/// provide access to [paintImage] at the widgets layer. /// provide access to [paintImage] at the widgets layer.
FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) { FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) {
if (inputSize.height <= 0.0 || inputSize.width <= 0.0 || outputSize.height <= 0.0 || outputSize.width <= 0.0) if (inputSize.height <= 0.0 || inputSize.width <= 0.0 || outputSize.height <= 0.0 || outputSize.width <= 0.0) {
return const FittedSizes(Size.zero, Size.zero); return const FittedSizes(Size.zero, Size.zero);
}
Size sourceSize, destinationSize; Size sourceSize, destinationSize;
switch (fit) { switch (fit) {
...@@ -150,10 +151,11 @@ FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) { ...@@ -150,10 +151,11 @@ FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) {
break; break;
case BoxFit.contain: case BoxFit.contain:
sourceSize = inputSize; sourceSize = inputSize;
if (outputSize.width / outputSize.height > sourceSize.width / sourceSize.height) if (outputSize.width / outputSize.height > sourceSize.width / sourceSize.height) {
destinationSize = Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height); destinationSize = Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height);
else } else {
destinationSize = Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width); destinationSize = Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width);
}
break; break;
case BoxFit.cover: case BoxFit.cover:
if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) { if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) {
...@@ -179,10 +181,12 @@ FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) { ...@@ -179,10 +181,12 @@ FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) {
sourceSize = inputSize; sourceSize = inputSize;
destinationSize = inputSize; destinationSize = inputSize;
final double aspectRatio = inputSize.width / inputSize.height; final double aspectRatio = inputSize.width / inputSize.height;
if (destinationSize.height > outputSize.height) if (destinationSize.height > outputSize.height) {
destinationSize = Size(outputSize.height * aspectRatio, outputSize.height); destinationSize = Size(outputSize.height * aspectRatio, outputSize.height);
if (destinationSize.width > outputSize.width) }
if (destinationSize.width > outputSize.width) {
destinationSize = Size(outputSize.width, outputSize.width / aspectRatio); destinationSize = Size(outputSize.width, outputSize.width / aspectRatio);
}
break; break;
} }
return FittedSizes(sourceSize, destinationSize); return FittedSizes(sourceSize, destinationSize);
......
...@@ -58,8 +58,9 @@ class BoxShadow extends ui.Shadow { ...@@ -58,8 +58,9 @@ class BoxShadow extends ui.Shadow {
..color = color ..color = color
..maskFilter = MaskFilter.blur(blurStyle, blurSigma); ..maskFilter = MaskFilter.blur(blurStyle, blurSigma);
assert(() { assert(() {
if (debugDisableShadows) if (debugDisableShadows) {
result.maskFilter = null; result.maskFilter = null;
}
return true; return true;
}()); }());
return result; return result;
...@@ -86,12 +87,15 @@ class BoxShadow extends ui.Shadow { ...@@ -86,12 +87,15 @@ class BoxShadow extends ui.Shadow {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxShadow? lerp(BoxShadow? a, BoxShadow? b, double t) { static BoxShadow? lerp(BoxShadow? a, BoxShadow? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
}
return BoxShadow( return BoxShadow(
color: Color.lerp(a.color, b.color, t)!, color: Color.lerp(a.color, b.color, t)!,
offset: Offset.lerp(a.offset, b.offset, t)!, offset: Offset.lerp(a.offset, b.offset, t)!,
...@@ -108,8 +112,9 @@ class BoxShadow extends ui.Shadow { ...@@ -108,8 +112,9 @@ class BoxShadow extends ui.Shadow {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static List<BoxShadow>? lerpList(List<BoxShadow>? a, List<BoxShadow>? b, double t) { static List<BoxShadow>? lerpList(List<BoxShadow>? a, List<BoxShadow>? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
}
a ??= <BoxShadow>[]; a ??= <BoxShadow>[];
b ??= <BoxShadow>[]; b ??= <BoxShadow>[];
final int commonLength = math.min(a.length, b.length); final int commonLength = math.min(a.length, b.length);
...@@ -122,10 +127,12 @@ class BoxShadow extends ui.Shadow { ...@@ -122,10 +127,12 @@ class BoxShadow extends ui.Shadow {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is BoxShadow return other is BoxShadow
&& other.color == color && other.color == color
&& other.offset == offset && other.offset == offset
......
...@@ -46,15 +46,17 @@ class CircleBorder extends OutlinedBorder { ...@@ -46,15 +46,17 @@ class CircleBorder extends OutlinedBorder {
@override @override
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a is CircleBorder) if (a is CircleBorder) {
return CircleBorder(side: BorderSide.lerp(a.side, side, t)); return CircleBorder(side: BorderSide.lerp(a.side, side, t));
}
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
ShapeBorder? lerpTo(ShapeBorder? b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is CircleBorder) if (b is CircleBorder) {
return CircleBorder(side: BorderSide.lerp(side, b.side, t)); return CircleBorder(side: BorderSide.lerp(side, b.side, t));
}
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
...@@ -118,8 +120,9 @@ class CircleBorder extends OutlinedBorder { ...@@ -118,8 +120,9 @@ class CircleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is CircleBorder return other is CircleBorder
&& other.side == side; && other.side == side;
} }
......
...@@ -199,12 +199,15 @@ class HSVColor { ...@@ -199,12 +199,15 @@ class HSVColor {
/// Values outside of the valid range for each channel will be clamped. /// Values outside of the valid range for each channel will be clamped.
static HSVColor? lerp(HSVColor? a, HSVColor? b, double t) { static HSVColor? lerp(HSVColor? a, HSVColor? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!._scaleAlpha(t); return b!._scaleAlpha(t);
if (b == null) }
if (b == null) {
return a._scaleAlpha(1.0 - t); return a._scaleAlpha(1.0 - t);
}
return HSVColor.fromAHSV( return HSVColor.fromAHSV(
clampDouble(lerpDouble(a.alpha, b.alpha, t)!, 0.0, 1.0), clampDouble(lerpDouble(a.alpha, b.alpha, t)!, 0.0, 1.0),
lerpDouble(a.hue, b.hue, t)! % 360.0, lerpDouble(a.hue, b.hue, t)! % 360.0,
...@@ -215,8 +218,9 @@ class HSVColor { ...@@ -215,8 +218,9 @@ class HSVColor {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
}
return other is HSVColor return other is HSVColor
&& other.alpha == alpha && other.alpha == alpha
&& other.hue == hue && other.hue == hue
...@@ -383,12 +387,15 @@ class HSLColor { ...@@ -383,12 +387,15 @@ class HSLColor {
/// an [AnimationController]. /// an [AnimationController].
static HSLColor? lerp(HSLColor? a, HSLColor? b, double t) { static HSLColor? lerp(HSLColor? a, HSLColor? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!._scaleAlpha(t); return b!._scaleAlpha(t);
if (b == null) }
if (b == null) {
return a._scaleAlpha(1.0 - t); return a._scaleAlpha(1.0 - t);
}
return HSLColor.fromAHSL( return HSLColor.fromAHSL(
clampDouble(lerpDouble(a.alpha, b.alpha, t)!, 0.0, 1.0), clampDouble(lerpDouble(a.alpha, b.alpha, t)!, 0.0, 1.0),
lerpDouble(a.hue, b.hue, t)! % 360.0, lerpDouble(a.hue, b.hue, t)! % 360.0,
...@@ -399,8 +406,9 @@ class HSLColor { ...@@ -399,8 +406,9 @@ class HSLColor {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
}
return other is HSLColor return other is HSLColor
&& other.alpha == alpha && other.alpha == alpha
&& other.hue == hue && other.hue == hue
...@@ -443,10 +451,12 @@ class ColorSwatch<T> extends Color { ...@@ -443,10 +451,12 @@ class ColorSwatch<T> extends Color {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return super == other return super == other
&& other is ColorSwatch<T> && other is ColorSwatch<T>
&& mapEquals<T, Color>(other._swatch, _swatch); && mapEquals<T, Color>(other._swatch, _swatch);
......
...@@ -141,8 +141,9 @@ class ContinuousRectangleBorder extends OutlinedBorder { ...@@ -141,8 +141,9 @@ class ContinuousRectangleBorder extends OutlinedBorder {
@override @override
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) { void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
if (rect.isEmpty) if (rect.isEmpty) {
return; return;
}
switch (side.style) { switch (side.style) {
case BorderStyle.none: case BorderStyle.none:
break; break;
...@@ -156,8 +157,9 @@ class ContinuousRectangleBorder extends OutlinedBorder { ...@@ -156,8 +157,9 @@ class ContinuousRectangleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ContinuousRectangleBorder return other is ContinuousRectangleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius; && other.borderRadius == borderRadius;
......
...@@ -127,16 +127,21 @@ abstract class Decoration with Diagnosticable { ...@@ -127,16 +127,21 @@ abstract class Decoration with Diagnosticable {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static Decoration? lerp(Decoration? a, Decoration? b, double t) { static Decoration? lerp(Decoration? a, Decoration? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.lerpFrom(null, t) ?? b; return b!.lerpFrom(null, t) ?? b;
if (b == null) }
if (b == null) {
return a.lerpTo(null, t) ?? a; return a.lerpTo(null, t) ?? a;
if (t == 0.0) }
if (t == 0.0) {
return a; return a;
if (t == 1.0) }
if (t == 1.0) {
return b; return b;
}
return b.lerpFrom(a, t) return b.lerpFrom(a, t)
?? a.lerpTo(b, t) ?? a.lerpTo(b, t)
?? (t < 0.5 ? (a.lerpTo(null, t * 2.0) ?? a) : (b.lerpFrom(null, (t - 0.5) * 2.0) ?? b)); ?? (t < 0.5 ? (a.lerpTo(null, t * 2.0) ?? a) : (b.lerpFrom(null, (t - 0.5) * 2.0) ?? b));
......
...@@ -186,10 +186,12 @@ class DecorationImage { ...@@ -186,10 +186,12 @@ class DecorationImage {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is DecorationImage return other is DecorationImage
&& other.image == image && other.image == image
&& other.colorFilter == colorFilter && other.colorFilter == colorFilter
...@@ -307,8 +309,9 @@ class DecorationImagePainter { ...@@ -307,8 +309,9 @@ class DecorationImagePainter {
} }
return true; return true;
}()); }());
if (configuration.textDirection == TextDirection.rtl) if (configuration.textDirection == TextDirection.rtl) {
flipHorizontally = true; flipHorizontally = true;
}
} }
final ImageStream newImageStream = _details.image.resolve(configuration); final ImageStream newImageStream = _details.image.resolve(configuration);
...@@ -321,8 +324,9 @@ class DecorationImagePainter { ...@@ -321,8 +324,9 @@ class DecorationImagePainter {
_imageStream = newImageStream; _imageStream = newImageStream;
_imageStream!.addListener(listener); _imageStream!.addListener(listener);
} }
if (_image == null) if (_image == null) {
return; return;
}
if (clipPath != null) { if (clipPath != null) {
canvas.save(); canvas.save();
...@@ -347,13 +351,15 @@ class DecorationImagePainter { ...@@ -347,13 +351,15 @@ class DecorationImagePainter {
isAntiAlias: _details.isAntiAlias, isAntiAlias: _details.isAntiAlias,
); );
if (clipPath != null) if (clipPath != null) {
canvas.restore(); canvas.restore();
}
} }
void _handleImage(ImageInfo value, bool synchronousCall) { void _handleImage(ImageInfo value, bool synchronousCall) {
if (_image == value) if (_image == value) {
return; return;
}
if (_image != null && _image!.isCloneOf(value)) { if (_image != null && _image!.isCloneOf(value)) {
value.dispose(); value.dispose();
return; return;
...@@ -361,8 +367,9 @@ class DecorationImagePainter { ...@@ -361,8 +367,9 @@ class DecorationImagePainter {
_image?.dispose(); _image?.dispose();
_image = value; _image = value;
assert(_onChanged != null); assert(_onChanged != null);
if (!synchronousCall) if (!synchronousCall) {
_onChanged(); _onChanged();
}
} }
/// Releases the resources used by this painter. /// Releases the resources used by this painter.
...@@ -504,8 +511,9 @@ void paintImage({ ...@@ -504,8 +511,9 @@ void paintImage({
'The caller of paintImage is expected to wait to dispose the image until ' 'The caller of paintImage is expected to wait to dispose the image until '
'after painting has completed.', 'after painting has completed.',
); );
if (rect.isEmpty) if (rect.isEmpty) {
return; return;
}
Size outputSize = rect.size; Size outputSize = rect.size;
Size inputSize = Size(image.width.toDouble(), image.height.toDouble()); Size inputSize = Size(image.width.toDouble(), image.height.toDouble());
Offset? sliceBorder; Offset? sliceBorder;
...@@ -533,8 +541,9 @@ void paintImage({ ...@@ -533,8 +541,9 @@ void paintImage({
repeat = ImageRepeat.noRepeat; repeat = ImageRepeat.noRepeat;
} }
final Paint paint = Paint()..isAntiAlias = isAntiAlias; final Paint paint = Paint()..isAntiAlias = isAntiAlias;
if (colorFilter != null) if (colorFilter != null) {
paint.colorFilter = colorFilter; paint.colorFilter = colorFilter;
}
paint.color = Color.fromRGBO(0, 0, 0, opacity); paint.color = Color.fromRGBO(0, 0, 0, opacity);
paint.filterQuality = filterQuality; paint.filterQuality = filterQuality;
paint.invertColors = invertColors; paint.invertColors = invertColors;
...@@ -618,10 +627,12 @@ void paintImage({ ...@@ -618,10 +627,12 @@ void paintImage({
} }
final bool needSave = centerSlice != null || repeat != ImageRepeat.noRepeat || flipHorizontally; final bool needSave = centerSlice != null || repeat != ImageRepeat.noRepeat || flipHorizontally;
if (needSave) if (needSave) {
canvas.save(); canvas.save();
if (repeat != ImageRepeat.noRepeat) }
if (repeat != ImageRepeat.noRepeat) {
canvas.clipRect(rect); canvas.clipRect(rect);
}
if (flipHorizontally) { if (flipHorizontally) {
final double dx = -(rect.left + rect.width / 2.0); final double dx = -(rect.left + rect.width / 2.0);
canvas.translate(-dx, 0.0); canvas.translate(-dx, 0.0);
...@@ -635,20 +646,23 @@ void paintImage({ ...@@ -635,20 +646,23 @@ void paintImage({
if (repeat == ImageRepeat.noRepeat) { if (repeat == ImageRepeat.noRepeat) {
canvas.drawImageRect(image, sourceRect, destinationRect, paint); canvas.drawImageRect(image, sourceRect, destinationRect, paint);
} else { } else {
for (final Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) for (final Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) {
canvas.drawImageRect(image, sourceRect, tileRect, paint); canvas.drawImageRect(image, sourceRect, tileRect, paint);
}
} }
} else { } else {
canvas.scale(1 / scale); canvas.scale(1 / scale);
if (repeat == ImageRepeat.noRepeat) { if (repeat == ImageRepeat.noRepeat) {
canvas.drawImageNine(image, _scaleRect(centerSlice, scale), _scaleRect(destinationRect, scale), paint); canvas.drawImageNine(image, _scaleRect(centerSlice, scale), _scaleRect(destinationRect, scale), paint);
} else { } else {
for (final Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) for (final Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) {
canvas.drawImageNine(image, _scaleRect(centerSlice, scale), _scaleRect(tileRect, scale), paint); canvas.drawImageNine(image, _scaleRect(centerSlice, scale), _scaleRect(tileRect, scale), paint);
}
} }
} }
if (needSave) if (needSave) {
canvas.restore(); canvas.restore();
}
if (invertedCanvas) { if (invertedCanvas) {
canvas.restore(); canvas.restore();
......
...@@ -217,16 +217,21 @@ abstract class EdgeInsetsGeometry { ...@@ -217,16 +217,21 @@ abstract class EdgeInsetsGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsetsGeometry? lerp(EdgeInsetsGeometry? a, EdgeInsetsGeometry? b, double t) { static EdgeInsetsGeometry? lerp(EdgeInsetsGeometry? a, EdgeInsetsGeometry? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b! * t; return b! * t;
if (b == null) }
if (b == null) {
return a * (1.0 - t); return a * (1.0 - t);
if (a is EdgeInsets && b is EdgeInsets) }
if (a is EdgeInsets && b is EdgeInsets) {
return EdgeInsets.lerp(a, b, t); return EdgeInsets.lerp(a, b, t);
if (a is EdgeInsetsDirectional && b is EdgeInsetsDirectional) }
if (a is EdgeInsetsDirectional && b is EdgeInsetsDirectional) {
return EdgeInsetsDirectional.lerp(a, b, t); return EdgeInsetsDirectional.lerp(a, b, t);
}
return _MixedEdgeInsets.fromLRSETB( return _MixedEdgeInsets.fromLRSETB(
ui.lerpDouble(a._left, b._left, t)!, ui.lerpDouble(a._left, b._left, t)!,
ui.lerpDouble(a._right, b._right, t)!, ui.lerpDouble(a._right, b._right, t)!,
...@@ -251,10 +256,12 @@ abstract class EdgeInsetsGeometry { ...@@ -251,10 +256,12 @@ abstract class EdgeInsetsGeometry {
@override @override
String toString() { String toString() {
if (_start == 0.0 && _end == 0.0) { if (_start == 0.0 && _end == 0.0) {
if (_left == 0.0 && _right == 0.0 && _top == 0.0 && _bottom == 0.0) if (_left == 0.0 && _right == 0.0 && _top == 0.0 && _bottom == 0.0) {
return 'EdgeInsets.zero'; return 'EdgeInsets.zero';
if (_left == _right && _right == _top && _top == _bottom) }
if (_left == _right && _right == _top && _top == _bottom) {
return 'EdgeInsets.all(${_left.toStringAsFixed(1)})'; return 'EdgeInsets.all(${_left.toStringAsFixed(1)})';
}
return 'EdgeInsets(${_left.toStringAsFixed(1)}, ' return 'EdgeInsets(${_left.toStringAsFixed(1)}, '
'${_top.toStringAsFixed(1)}, ' '${_top.toStringAsFixed(1)}, '
'${_right.toStringAsFixed(1)}, ' '${_right.toStringAsFixed(1)}, '
...@@ -490,15 +497,17 @@ class EdgeInsets extends EdgeInsetsGeometry { ...@@ -490,15 +497,17 @@ class EdgeInsets extends EdgeInsetsGeometry {
@override @override
EdgeInsetsGeometry subtract(EdgeInsetsGeometry other) { EdgeInsetsGeometry subtract(EdgeInsetsGeometry other) {
if (other is EdgeInsets) if (other is EdgeInsets) {
return this - other; return this - other;
}
return super.subtract(other); return super.subtract(other);
} }
@override @override
EdgeInsetsGeometry add(EdgeInsetsGeometry other) { EdgeInsetsGeometry add(EdgeInsetsGeometry other) {
if (other is EdgeInsets) if (other is EdgeInsets) {
return this + other; return this + other;
}
return super.add(other); return super.add(other);
} }
...@@ -596,12 +605,15 @@ class EdgeInsets extends EdgeInsetsGeometry { ...@@ -596,12 +605,15 @@ class EdgeInsets extends EdgeInsetsGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsets? lerp(EdgeInsets? a, EdgeInsets? b, double t) { static EdgeInsets? lerp(EdgeInsets? a, EdgeInsets? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b! * t; return b! * t;
if (b == null) }
if (b == null) {
return a * (1.0 - t); return a * (1.0 - t);
}
return EdgeInsets.fromLTRB( return EdgeInsets.fromLTRB(
ui.lerpDouble(a.left, b.left, t)!, ui.lerpDouble(a.left, b.left, t)!,
ui.lerpDouble(a.top, b.top, t)!, ui.lerpDouble(a.top, b.top, t)!,
...@@ -737,15 +749,17 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry { ...@@ -737,15 +749,17 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry {
@override @override
EdgeInsetsGeometry subtract(EdgeInsetsGeometry other) { EdgeInsetsGeometry subtract(EdgeInsetsGeometry other) {
if (other is EdgeInsetsDirectional) if (other is EdgeInsetsDirectional) {
return this - other; return this - other;
}
return super.subtract(other); return super.subtract(other);
} }
@override @override
EdgeInsetsGeometry add(EdgeInsetsGeometry other) { EdgeInsetsGeometry add(EdgeInsetsGeometry other) {
if (other is EdgeInsetsDirectional) if (other is EdgeInsetsDirectional) {
return this + other; return this + other;
}
return super.add(other); return super.add(other);
} }
...@@ -837,12 +851,15 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry { ...@@ -837,12 +851,15 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsetsDirectional? lerp(EdgeInsetsDirectional? a, EdgeInsetsDirectional? b, double t) { static EdgeInsetsDirectional? lerp(EdgeInsetsDirectional? a, EdgeInsetsDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b! * t; return b! * t;
if (b == null) }
if (b == null) {
return a * (1.0 - t); return a * (1.0 - t);
}
return EdgeInsetsDirectional.fromSTEB( return EdgeInsetsDirectional.fromSTEB(
ui.lerpDouble(a.start, b.start, t)!, ui.lerpDouble(a.start, b.start, t)!,
ui.lerpDouble(a.top, b.top, t)!, ui.lerpDouble(a.top, b.top, t)!,
......
...@@ -111,8 +111,9 @@ class FlutterLogoDecoration extends Decoration { ...@@ -111,8 +111,9 @@ class FlutterLogoDecoration extends Decoration {
assert(t != null); assert(t != null);
assert(a == null || a.debugAssertIsValid()); assert(a == null || a.debugAssertIsValid());
assert(b == null || b.debugAssertIsValid()); assert(b == null || b.debugAssertIsValid());
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
}
if (a == null) { if (a == null) {
return FlutterLogoDecoration._( return FlutterLogoDecoration._(
b!.textColor, b!.textColor,
...@@ -131,10 +132,12 @@ class FlutterLogoDecoration extends Decoration { ...@@ -131,10 +132,12 @@ class FlutterLogoDecoration extends Decoration {
a._opacity * clampDouble(1.0 - t, 0.0, 1.0), a._opacity * clampDouble(1.0 - t, 0.0, 1.0),
); );
} }
if (t == 0.0) if (t == 0.0) {
return a; return a;
if (t == 1.0) }
if (t == 1.0) {
return b; return b;
}
return FlutterLogoDecoration._( return FlutterLogoDecoration._(
Color.lerp(a.textColor, b.textColor, t)!, Color.lerp(a.textColor, b.textColor, t)!,
t < 0.5 ? a.style : b.style, t < 0.5 ? a.style : b.style,
...@@ -182,8 +185,9 @@ class FlutterLogoDecoration extends Decoration { ...@@ -182,8 +185,9 @@ class FlutterLogoDecoration extends Decoration {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
assert(debugAssertIsValid()); assert(debugAssertIsValid());
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
}
return other is FlutterLogoDecoration return other is FlutterLogoDecoration
&& other.textColor == textColor && other.textColor == textColor
&& other._position == _position && other._position == _position
...@@ -205,8 +209,9 @@ class FlutterLogoDecoration extends Decoration { ...@@ -205,8 +209,9 @@ class FlutterLogoDecoration extends Decoration {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(ColorProperty('textColor', textColor)); properties.add(ColorProperty('textColor', textColor));
properties.add(EnumProperty<FlutterLogoStyle>('style', style)); properties.add(EnumProperty<FlutterLogoStyle>('style', style));
if (_inTransition) if (_inTransition) {
properties.add(DiagnosticsNode.message('transition ${debugFormatDouble(_position)}:${debugFormatDouble(_opacity)}')); properties.add(DiagnosticsNode.message('transition ${debugFormatDouble(_position)}:${debugFormatDouble(_opacity)}'));
}
} }
} }
...@@ -329,8 +334,9 @@ class _FlutterLogoPainter extends BoxPainter { ...@@ -329,8 +334,9 @@ class _FlutterLogoPainter extends BoxPainter {
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
offset += _config.margin.topLeft; offset += _config.margin.topLeft;
final Size canvasSize = _config.margin.deflateSize(configuration.size!); final Size canvasSize = _config.margin.deflateSize(configuration.size!);
if (canvasSize.isEmpty) if (canvasSize.isEmpty) {
return; return;
}
final Size logoSize; final Size logoSize;
if (_config._position > 0.0) { if (_config._position > 0.0) {
// horizontal style // horizontal style
...@@ -441,7 +447,8 @@ class _FlutterLogoPainter extends BoxPainter { ...@@ -441,7 +447,8 @@ class _FlutterLogoPainter extends BoxPainter {
} }
} }
_paintLogo(canvas, logoSquare); _paintLogo(canvas, logoSquare);
if (_config._opacity < 1.0) if (_config._opacity < 1.0) {
canvas.restore(); canvas.restore();
}
} }
} }
...@@ -135,15 +135,17 @@ class FractionalOffset extends Alignment { ...@@ -135,15 +135,17 @@ class FractionalOffset extends Alignment {
@override @override
Alignment operator -(Alignment other) { Alignment operator -(Alignment other) {
if (other is! FractionalOffset) if (other is! FractionalOffset) {
return super - other; return super - other;
}
return FractionalOffset(dx - other.dx, dy - other.dy); return FractionalOffset(dx - other.dx, dy - other.dy);
} }
@override @override
Alignment operator +(Alignment other) { Alignment operator +(Alignment other) {
if (other is! FractionalOffset) if (other is! FractionalOffset) {
return super + other; return super + other;
}
return FractionalOffset(dx + other.dx, dy + other.dy); return FractionalOffset(dx + other.dx, dy + other.dy);
} }
...@@ -179,12 +181,15 @@ class FractionalOffset extends Alignment { ...@@ -179,12 +181,15 @@ class FractionalOffset extends Alignment {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static FractionalOffset? lerp(FractionalOffset? a, FractionalOffset? b, double t) { static FractionalOffset? lerp(FractionalOffset? a, FractionalOffset? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return FractionalOffset(ui.lerpDouble(0.5, b!.dx, t)!, ui.lerpDouble(0.5, b.dy, t)!); return FractionalOffset(ui.lerpDouble(0.5, b!.dx, t)!, ui.lerpDouble(0.5, b.dy, t)!);
if (b == null) }
if (b == null) {
return FractionalOffset(ui.lerpDouble(a.dx, 0.5, t)!, ui.lerpDouble(a.dy, 0.5, t)!); return FractionalOffset(ui.lerpDouble(a.dx, 0.5, t)!, ui.lerpDouble(a.dy, 0.5, t)!);
}
return FractionalOffset(ui.lerpDouble(a.dx, b.dx, t)!, ui.lerpDouble(a.dy, b.dy, t)!); return FractionalOffset(ui.lerpDouble(a.dx, b.dx, t)!, ui.lerpDouble(a.dy, b.dy, t)!);
} }
......
...@@ -56,10 +56,11 @@ Offset positionDependentBox({ ...@@ -56,10 +56,11 @@ Offset positionDependentBox({
final bool fitsAbove = target.dy - verticalOffset - childSize.height >= margin; final bool fitsAbove = target.dy - verticalOffset - childSize.height >= margin;
final bool tooltipBelow = preferBelow ? fitsBelow || !fitsAbove : !(fitsAbove || !fitsBelow); final bool tooltipBelow = preferBelow ? fitsBelow || !fitsAbove : !(fitsAbove || !fitsBelow);
double y; double y;
if (tooltipBelow) if (tooltipBelow) {
y = math.min(target.dy + verticalOffset, size.height - margin); y = math.min(target.dy + verticalOffset, size.height - margin);
else } else {
y = math.max(target.dy - verticalOffset - childSize.height, margin); y = math.max(target.dy - verticalOffset - childSize.height, margin);
}
// HORIZONTAL DIRECTION // HORIZONTAL DIRECTION
double x; double x;
if (size.width - margin * 2.0 < childSize.width) { if (size.width - margin * 2.0 < childSize.width) {
......
...@@ -26,10 +26,12 @@ Color _sample(List<Color> colors, List<double> stops, double t) { ...@@ -26,10 +26,12 @@ Color _sample(List<Color> colors, List<double> stops, double t) {
assert(stops != null); assert(stops != null);
assert(stops.isNotEmpty); assert(stops.isNotEmpty);
assert(t != null); assert(t != null);
if (t <= stops.first) if (t <= stops.first) {
return colors.first; return colors.first;
if (t >= stops.last) }
if (t >= stops.last) {
return colors.last; return colors.last;
}
final int index = stops.lastIndexWhere((double s) => s <= t); final int index = stops.lastIndexWhere((double s) => s <= t);
assert(index != -1); assert(index != -1);
return Color.lerp( return Color.lerp(
...@@ -120,10 +122,12 @@ class GradientRotation extends GradientTransform { ...@@ -120,10 +122,12 @@ class GradientRotation extends GradientTransform {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is GradientRotation return other is GradientRotation
&& other.radians == radians; && other.radians == radians;
} }
...@@ -202,8 +206,9 @@ abstract class Gradient { ...@@ -202,8 +206,9 @@ abstract class Gradient {
final GradientTransform? transform; final GradientTransform? transform;
List<double> _impliedStops() { List<double> _impliedStops() {
if (stops != null) if (stops != null) {
return stops!; return stops!;
}
assert(colors.length >= 2, 'colors list must have at least two colors'); assert(colors.length >= 2, 'colors list must have at least two colors');
final double separation = 1.0 / (colors.length - 1); final double separation = 1.0 / (colors.length - 1);
return List<double>.generate( return List<double>.generate(
...@@ -260,8 +265,9 @@ abstract class Gradient { ...@@ -260,8 +265,9 @@ abstract class Gradient {
/// Instead of calling this directly, use [Gradient.lerp]. /// Instead of calling this directly, use [Gradient.lerp].
@protected @protected
Gradient? lerpFrom(Gradient? a, double t) { Gradient? lerpFrom(Gradient? a, double t) {
if (a == null) if (a == null) {
return scale(t); return scale(t);
}
return null; return null;
} }
...@@ -291,8 +297,9 @@ abstract class Gradient { ...@@ -291,8 +297,9 @@ abstract class Gradient {
/// Instead of calling this directly, use [Gradient.lerp]. /// Instead of calling this directly, use [Gradient.lerp].
@protected @protected
Gradient? lerpTo(Gradient? b, double t) { Gradient? lerpTo(Gradient? b, double t) {
if (b == null) if (b == null) {
return scale(1.0 - t); return scale(1.0 - t);
}
return null; return null;
} }
...@@ -307,14 +314,18 @@ abstract class Gradient { ...@@ -307,14 +314,18 @@ abstract class Gradient {
static Gradient? lerp(Gradient? a, Gradient? b, double t) { static Gradient? lerp(Gradient? a, Gradient? b, double t) {
assert(t != null); assert(t != null);
Gradient? result; Gradient? result;
if (b != null) if (b != null) {
result = b.lerpFrom(a, t); // if a is null, this must return non-null result = b.lerpFrom(a, t); // if a is null, this must return non-null
if (result == null && a != null) }
if (result == null && a != null) {
result = a.lerpTo(b, t); // if b is null, this must return non-null result = a.lerpTo(b, t); // if b is null, this must return non-null
if (result != null) }
if (result != null) {
return result; return result;
if (a == null && b == null) }
if (a == null && b == null) {
return null; return null;
}
assert(a != null && b != null); assert(a != null && b != null);
return t < 0.5 ? a!.scale(1.0 - (t * 2.0)) : b!.scale((t - 0.5) * 2.0); return t < 0.5 ? a!.scale(1.0 - (t * 2.0)) : b!.scale((t - 0.5) * 2.0);
} }
...@@ -447,15 +458,17 @@ class LinearGradient extends Gradient { ...@@ -447,15 +458,17 @@ class LinearGradient extends Gradient {
@override @override
Gradient? lerpFrom(Gradient? a, double t) { Gradient? lerpFrom(Gradient? a, double t) {
if (a == null || (a is LinearGradient)) if (a == null || (a is LinearGradient)) {
return LinearGradient.lerp(a as LinearGradient?, this, t); return LinearGradient.lerp(a as LinearGradient?, this, t);
}
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
Gradient? lerpTo(Gradient? b, double t) { Gradient? lerpTo(Gradient? b, double t) {
if (b == null || (b is LinearGradient)) if (b == null || (b is LinearGradient)) {
return LinearGradient.lerp(this, b as LinearGradient?, t); return LinearGradient.lerp(this, b as LinearGradient?, t);
}
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
...@@ -480,12 +493,15 @@ class LinearGradient extends Gradient { ...@@ -480,12 +493,15 @@ class LinearGradient extends Gradient {
/// an [AnimationController]. /// an [AnimationController].
static LinearGradient? lerp(LinearGradient? a, LinearGradient? b, double t) { static LinearGradient? lerp(LinearGradient? a, LinearGradient? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
}
final _ColorsAndStops interpolated = _interpolateColorsAndStops( final _ColorsAndStops interpolated = _interpolateColorsAndStops(
a.colors, a.colors,
a._impliedStops(), a._impliedStops(),
...@@ -504,10 +520,12 @@ class LinearGradient extends Gradient { ...@@ -504,10 +520,12 @@ class LinearGradient extends Gradient {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is LinearGradient return other is LinearGradient
&& other.begin == begin && other.begin == begin
&& other.end == end && other.end == end
...@@ -723,15 +741,17 @@ class RadialGradient extends Gradient { ...@@ -723,15 +741,17 @@ class RadialGradient extends Gradient {
@override @override
Gradient? lerpFrom(Gradient? a, double t) { Gradient? lerpFrom(Gradient? a, double t) {
if (a == null || (a is RadialGradient)) if (a == null || (a is RadialGradient)) {
return RadialGradient.lerp(a as RadialGradient?, this, t); return RadialGradient.lerp(a as RadialGradient?, this, t);
}
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
Gradient? lerpTo(Gradient? b, double t) { Gradient? lerpTo(Gradient? b, double t) {
if (b == null || (b is RadialGradient)) if (b == null || (b is RadialGradient)) {
return RadialGradient.lerp(this, b as RadialGradient?, t); return RadialGradient.lerp(this, b as RadialGradient?, t);
}
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
...@@ -756,12 +776,15 @@ class RadialGradient extends Gradient { ...@@ -756,12 +776,15 @@ class RadialGradient extends Gradient {
/// an [AnimationController]. /// an [AnimationController].
static RadialGradient? lerp(RadialGradient? a, RadialGradient? b, double t) { static RadialGradient? lerp(RadialGradient? a, RadialGradient? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
}
final _ColorsAndStops interpolated = _interpolateColorsAndStops( final _ColorsAndStops interpolated = _interpolateColorsAndStops(
a.colors, a.colors,
a._impliedStops(), a._impliedStops(),
...@@ -782,10 +805,12 @@ class RadialGradient extends Gradient { ...@@ -782,10 +805,12 @@ class RadialGradient extends Gradient {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RadialGradient return other is RadialGradient
&& other.center == center && other.center == center
&& other.radius == radius && other.radius == radius
...@@ -988,15 +1013,17 @@ class SweepGradient extends Gradient { ...@@ -988,15 +1013,17 @@ class SweepGradient extends Gradient {
@override @override
Gradient? lerpFrom(Gradient? a, double t) { Gradient? lerpFrom(Gradient? a, double t) {
if (a == null || (a is SweepGradient)) if (a == null || (a is SweepGradient)) {
return SweepGradient.lerp(a as SweepGradient?, this, t); return SweepGradient.lerp(a as SweepGradient?, this, t);
}
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
Gradient? lerpTo(Gradient? b, double t) { Gradient? lerpTo(Gradient? b, double t) {
if (b == null || (b is SweepGradient)) if (b == null || (b is SweepGradient)) {
return SweepGradient.lerp(this, b as SweepGradient?, t); return SweepGradient.lerp(this, b as SweepGradient?, t);
}
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
...@@ -1020,12 +1047,15 @@ class SweepGradient extends Gradient { ...@@ -1020,12 +1047,15 @@ class SweepGradient extends Gradient {
/// an [AnimationController]. /// an [AnimationController].
static SweepGradient? lerp(SweepGradient? a, SweepGradient? b, double t) { static SweepGradient? lerp(SweepGradient? a, SweepGradient? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
if (a == null) }
if (a == null) {
return b!.scale(t); return b!.scale(t);
if (b == null) }
if (b == null) {
return a.scale(1.0 - t); return a.scale(1.0 - t);
}
final _ColorsAndStops interpolated = _interpolateColorsAndStops( final _ColorsAndStops interpolated = _interpolateColorsAndStops(
a.colors, a.colors,
a._impliedStops(), a._impliedStops(),
...@@ -1045,10 +1075,12 @@ class SweepGradient extends Gradient { ...@@ -1045,10 +1075,12 @@ class SweepGradient extends Gradient {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is SweepGradient return other is SweepGradient
&& other.center == center && other.center == center
&& other.startAngle == startAngle && other.startAngle == startAngle
......
...@@ -101,8 +101,9 @@ class ImageCache { ...@@ -101,8 +101,9 @@ class ImageCache {
set maximumSize(int value) { set maximumSize(int value) {
assert(value != null); assert(value != null);
assert(value >= 0); assert(value >= 0);
if (value == maximumSize) if (value == maximumSize) {
return; return;
}
TimelineTask? timelineTask; TimelineTask? timelineTask;
if (!kReleaseMode) { if (!kReleaseMode) {
timelineTask = TimelineTask()..start( timelineTask = TimelineTask()..start(
...@@ -140,8 +141,9 @@ class ImageCache { ...@@ -140,8 +141,9 @@ class ImageCache {
set maximumSizeBytes(int value) { set maximumSizeBytes(int value) {
assert(value != null); assert(value != null);
assert(value >= 0); assert(value >= 0);
if (value == _maximumSizeBytes) if (value == _maximumSizeBytes) {
return; return;
}
TimelineTask? timelineTask; TimelineTask? timelineTask;
if (!kReleaseMode) { if (!kReleaseMode) {
timelineTask = TimelineTask()..start( timelineTask = TimelineTask()..start(
......
...@@ -98,8 +98,9 @@ class ImageConfiguration { ...@@ -98,8 +98,9 @@ class ImageConfiguration {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ImageConfiguration return other is ImageConfiguration
&& other.bundle == bundle && other.bundle == bundle
&& other.devicePixelRatio == devicePixelRatio && other.devicePixelRatio == devicePixelRatio
...@@ -122,32 +123,37 @@ class ImageConfiguration { ...@@ -122,32 +123,37 @@ class ImageConfiguration {
hasArguments = true; hasArguments = true;
} }
if (devicePixelRatio != null) { if (devicePixelRatio != null) {
if (hasArguments) if (hasArguments) {
result.write(', '); result.write(', ');
}
result.write('devicePixelRatio: ${devicePixelRatio!.toStringAsFixed(1)}'); result.write('devicePixelRatio: ${devicePixelRatio!.toStringAsFixed(1)}');
hasArguments = true; hasArguments = true;
} }
if (locale != null) { if (locale != null) {
if (hasArguments) if (hasArguments) {
result.write(', '); result.write(', ');
}
result.write('locale: $locale'); result.write('locale: $locale');
hasArguments = true; hasArguments = true;
} }
if (textDirection != null) { if (textDirection != null) {
if (hasArguments) if (hasArguments) {
result.write(', '); result.write(', ');
}
result.write('textDirection: $textDirection'); result.write('textDirection: $textDirection');
hasArguments = true; hasArguments = true;
} }
if (size != null) { if (size != null) {
if (hasArguments) if (hasArguments) {
result.write(', '); result.write(', ');
}
result.write('size: $size'); result.write('size: $size');
hasArguments = true; hasArguments = true;
} }
if (platform != null) { if (platform != null) {
if (hasArguments) if (hasArguments) {
result.write(', '); result.write(', ');
}
result.write('platform: ${platform!.name}'); result.write('platform: ${platform!.name}');
hasArguments = true; hasArguments = true;
} }
...@@ -601,8 +607,9 @@ class AssetBundleImageKey { ...@@ -601,8 +607,9 @@ class AssetBundleImageKey {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is AssetBundleImageKey return other is AssetBundleImageKey
&& other.bundle == bundle && other.bundle == bundle
&& other.name == name && other.name == name
...@@ -683,8 +690,9 @@ class ResizeImageKey { ...@@ -683,8 +690,9 @@ class ResizeImageKey {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ResizeImageKey return other is ResizeImageKey
&& other._providerCacheKey == _providerCacheKey && other._providerCacheKey == _providerCacheKey
&& other._width == _width && other._width == _width
...@@ -883,8 +891,9 @@ class FileImage extends ImageProvider<FileImage> { ...@@ -883,8 +891,9 @@ class FileImage extends ImageProvider<FileImage> {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is FileImage return other is FileImage
&& other.file.path == file.path && other.file.path == file.path
&& other.scale == scale; && other.scale == scale;
...@@ -958,8 +967,9 @@ class MemoryImage extends ImageProvider<MemoryImage> { ...@@ -958,8 +967,9 @@ class MemoryImage extends ImageProvider<MemoryImage> {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is MemoryImage return other is MemoryImage
&& other.bytes == bytes && other.bytes == bytes
&& other.scale == scale; && other.scale == scale;
...@@ -1100,8 +1110,9 @@ class ExactAssetImage extends AssetBundleImageProvider { ...@@ -1100,8 +1110,9 @@ class ExactAssetImage extends AssetBundleImageProvider {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ExactAssetImage return other is ExactAssetImage
&& other.keyName == keyName && other.keyName == keyName
&& other.scale == scale && other.scale == scale
......
...@@ -336,8 +336,9 @@ class AssetImage extends AssetBundleImageProvider { ...@@ -336,8 +336,9 @@ class AssetImage extends AssetBundleImageProvider {
} }
static Future<Map<String, List<String>>?> _manifestParser(String? jsonData) { static Future<Map<String, List<String>>?> _manifestParser(String? jsonData) {
if (jsonData == null) if (jsonData == null) {
return SynchronousFuture<Map<String, List<String>>?>(null); return SynchronousFuture<Map<String, List<String>>?>(null);
}
// TODO(ianh): JSON decoding really shouldn't be on the main thread. // TODO(ianh): JSON decoding really shouldn't be on the main thread.
final Map<String, dynamic> parsedJson = json.decode(jsonData) as Map<String, dynamic>; final Map<String, dynamic> parsedJson = json.decode(jsonData) as Map<String, dynamic>;
final Iterable<String> keys = parsedJson.keys; final Iterable<String> keys = parsedJson.keys;
...@@ -349,12 +350,14 @@ class AssetImage extends AssetBundleImageProvider { ...@@ -349,12 +350,14 @@ class AssetImage extends AssetBundleImageProvider {
} }
String? _chooseVariant(String main, ImageConfiguration config, List<String>? candidates) { String? _chooseVariant(String main, ImageConfiguration config, List<String>? candidates) {
if (config.devicePixelRatio == null || candidates == null || candidates.isEmpty) if (config.devicePixelRatio == null || candidates == null || candidates.isEmpty) {
return main; return main;
}
// TODO(ianh): Consider moving this parsing logic into _manifestParser. // TODO(ianh): Consider moving this parsing logic into _manifestParser.
final SplayTreeMap<double, String> mapping = SplayTreeMap<double, String>(); final SplayTreeMap<double, String> mapping = SplayTreeMap<double, String>();
for (final String candidate in candidates) for (final String candidate in candidates) {
mapping[_parseScale(candidate)] = candidate; mapping[_parseScale(candidate)] = candidate;
}
// TODO(ianh): implement support for config.locale, config.textDirection, // TODO(ianh): implement support for config.locale, config.textDirection,
// config.size, config.platform (then document this over in the Image.asset // config.size, config.platform (then document this over in the Image.asset
// docs) // docs)
...@@ -374,23 +377,27 @@ class AssetImage extends AssetBundleImageProvider { ...@@ -374,23 +377,27 @@ class AssetImage extends AssetBundleImageProvider {
// - If the screen has high device pixel ratio, choose the variant with the // - If the screen has high device pixel ratio, choose the variant with the
// key nearest to `value`. // key nearest to `value`.
String? _findBestVariant(SplayTreeMap<double, String> candidates, double value) { String? _findBestVariant(SplayTreeMap<double, String> candidates, double value) {
if (candidates.containsKey(value)) if (candidates.containsKey(value)) {
return candidates[value]!; return candidates[value]!;
}
final double? lower = candidates.lastKeyBefore(value); final double? lower = candidates.lastKeyBefore(value);
final double? upper = candidates.firstKeyAfter(value); final double? upper = candidates.firstKeyAfter(value);
if (lower == null) if (lower == null) {
return candidates[upper]; return candidates[upper];
if (upper == null) }
if (upper == null) {
return candidates[lower]; return candidates[lower];
}
// On screens with low device-pixel ratios the artifacts from upscaling // On screens with low device-pixel ratios the artifacts from upscaling
// images are more visible than on screens with a higher device-pixel // images are more visible than on screens with a higher device-pixel
// ratios because the physical pixels are larger. Choose the higher // ratios because the physical pixels are larger. Choose the higher
// resolution image in that case instead of the nearest one. // resolution image in that case instead of the nearest one.
if (value < _kLowDprLimit || value > (lower + upper) / 2) if (value < _kLowDprLimit || value > (lower + upper) / 2) {
return candidates[upper]; return candidates[upper];
else } else {
return candidates[lower]; return candidates[lower];
}
} }
static final RegExp _extractRatioRegExp = RegExp(r'/?(\d+(\.\d*)?)x$'); static final RegExp _extractRatioRegExp = RegExp(r'/?(\d+(\.\d*)?)x$');
...@@ -407,15 +414,17 @@ class AssetImage extends AssetBundleImageProvider { ...@@ -407,15 +414,17 @@ class AssetImage extends AssetBundleImageProvider {
} }
final Match? match = _extractRatioRegExp.firstMatch(directoryPath); final Match? match = _extractRatioRegExp.firstMatch(directoryPath);
if (match != null && match.groupCount > 0) if (match != null && match.groupCount > 0) {
return double.parse(match.group(1)!); return double.parse(match.group(1)!);
}
return _naturalResolution; // i.e. default to 1.0x return _naturalResolution; // i.e. default to 1.0x
} }
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is AssetImage return other is AssetImage
&& other.keyName == keyName && other.keyName == keyName
&& other.bundle == bundle; && other.bundle == bundle;
......
...@@ -133,8 +133,9 @@ class ImageInfo { ...@@ -133,8 +133,9 @@ class ImageInfo {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ImageInfo return other is ImageInfo
&& other.image == image && other.image == image
&& other.scale == scale && other.scale == scale
...@@ -212,8 +213,9 @@ class ImageStreamListener { ...@@ -212,8 +213,9 @@ class ImageStreamListener {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ImageStreamListener return other is ImageStreamListener
&& other.onImage == onImage && other.onImage == onImage
&& other.onChunk == onChunk && other.onChunk == onChunk
...@@ -367,8 +369,9 @@ class ImageStream with Diagnosticable { ...@@ -367,8 +369,9 @@ class ImageStream with Diagnosticable {
/// responsible for disposing of the [ImageInfo.image]. /// responsible for disposing of the [ImageInfo.image].
/// {@endtemplate} /// {@endtemplate}
void addListener(ImageStreamListener listener) { void addListener(ImageStreamListener listener) {
if (_completer != null) if (_completer != null) {
return _completer!.addListener(listener); return _completer!.addListener(listener);
}
_listeners ??= <ImageStreamListener>[]; _listeners ??= <ImageStreamListener>[];
_listeners!.add(listener); _listeners!.add(listener);
} }
...@@ -378,8 +381,9 @@ class ImageStream with Diagnosticable { ...@@ -378,8 +381,9 @@ class ImageStream with Diagnosticable {
/// If [listener] has been added multiple times, this removes the _first_ /// If [listener] has been added multiple times, this removes the _first_
/// instance of the listener. /// instance of the listener.
void removeListener(ImageStreamListener listener) { void removeListener(ImageStreamListener listener) {
if (_completer != null) if (_completer != null) {
return _completer!.removeListener(listener); return _completer!.removeListener(listener);
}
assert(_listeners != null); assert(_listeners != null);
for (int i = 0; i < _listeners!.length; i += 1) { for (int i = 0; i < _listeners!.length; i += 1) {
if (_listeners![i] == listener) { if (_listeners![i] == listener) {
...@@ -635,8 +639,9 @@ abstract class ImageStreamCompleter with Diagnosticable { ...@@ -635,8 +639,9 @@ abstract class ImageStreamCompleter with Diagnosticable {
_currentImage?.dispose(); _currentImage?.dispose();
_currentImage = image; _currentImage = image;
if (_listeners.isEmpty) if (_listeners.isEmpty) {
return; return;
}
// Make a copy to allow for concurrent modification. // Make a copy to allow for concurrent modification.
final List<ImageStreamListener> localListeners = final List<ImageStreamListener> localListeners =
List<ImageStreamListener>.of(_listeners); List<ImageStreamListener>.of(_listeners);
...@@ -904,8 +909,9 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter { ...@@ -904,8 +909,9 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
void _handleAppFrame(Duration timestamp) { void _handleAppFrame(Duration timestamp) {
_frameCallbackScheduled = false; _frameCallbackScheduled = false;
if (!hasListeners) if (!hasListeners) {
return; return;
}
assert(_nextFrame != null); assert(_nextFrame != null);
if (_isFirstFrame() || _hasFrameDurationPassed(timestamp)) { if (_isFirstFrame() || _hasFrameDurationPassed(timestamp)) {
_emitFrame(ImageInfo( _emitFrame(ImageInfo(
...@@ -990,8 +996,9 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter { ...@@ -990,8 +996,9 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
@override @override
void addListener(ImageStreamListener listener) { void addListener(ImageStreamListener listener) {
if (!hasListeners && _codec != null && (_currentImage == null || _codec!.frameCount > 1)) if (!hasListeners && _codec != null && (_currentImage == null || _codec!.frameCount > 1)) {
_decodeNextFrameAndSchedule(); _decodeNextFrameAndSchedule();
}
super.addListener(listener); super.addListener(listener);
} }
......
...@@ -308,8 +308,9 @@ abstract class InlineSpan extends DiagnosticableTree { ...@@ -308,8 +308,9 @@ abstract class InlineSpan extends DiagnosticableTree {
/// ///
/// Returns null if the `index` is out of bounds. /// Returns null if the `index` is out of bounds.
int? codeUnitAt(int index) { int? codeUnitAt(int index) {
if (index < 0) if (index < 0) {
return null; return null;
}
final Accumulator offset = Accumulator(); final Accumulator offset = Accumulator();
int? result; int? result;
visitChildren((InlineSpan span) { visitChildren((InlineSpan span) {
...@@ -353,10 +354,12 @@ abstract class InlineSpan extends DiagnosticableTree { ...@@ -353,10 +354,12 @@ abstract class InlineSpan extends DiagnosticableTree {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is InlineSpan return other is InlineSpan
&& other.style == style; && other.style == style;
} }
......
...@@ -73,13 +73,16 @@ class MatrixUtils { ...@@ -73,13 +73,16 @@ class MatrixUtils {
/// Returns true if the given matrices are exactly equal, and false /// Returns true if the given matrices are exactly equal, and false
/// otherwise. Null values are assumed to be the identity matrix. /// otherwise. Null values are assumed to be the identity matrix.
static bool matrixEquals(Matrix4? a, Matrix4? b) { static bool matrixEquals(Matrix4? a, Matrix4? b) {
if (identical(a, b)) if (identical(a, b)) {
return true; return true;
}
assert(a != null || b != null); assert(a != null || b != null);
if (a == null) if (a == null) {
return isIdentity(b!); return isIdentity(b!);
if (b == null) }
if (b == null) {
return isIdentity(a); return isIdentity(a);
}
assert(a != null && b != null); assert(a != null && b != null);
return a.storage[0] == b.storage[0] return a.storage[0] == b.storage[0]
&& a.storage[1] == b.storage[1] && a.storage[1] == b.storage[1]
...@@ -441,8 +444,9 @@ class MatrixUtils { ...@@ -441,8 +444,9 @@ class MatrixUtils {
// Fixing it introduces a bunch of runtime failures; for more context see: // Fixing it introduces a bunch of runtime failures; for more context see:
// https://github.com/flutter/flutter/pull/31568 // https://github.com/flutter/flutter/pull/31568
// assert(transform.determinant != 0.0); // assert(transform.determinant != 0.0);
if (isIdentity(transform)) if (isIdentity(transform)) {
return rect; return rect;
}
transform = Matrix4.copy(transform)..invert(); transform = Matrix4.copy(transform)..invert();
return transformRect(transform, rect); return transformRect(transform, rect);
} }
...@@ -537,8 +541,9 @@ class MatrixUtils { ...@@ -537,8 +541,9 @@ class MatrixUtils {
/// ///
/// If the argument is null, returns a list with the single string "null". /// If the argument is null, returns a list with the single string "null".
List<String> debugDescribeTransform(Matrix4? transform) { List<String> debugDescribeTransform(Matrix4? transform) {
if (transform == null) if (transform == null) {
return const <String>['null']; return const <String>['null'];
}
return <String>[ return <String>[
'[0] ${debugFormatDouble(transform.entry(0, 0))},${debugFormatDouble(transform.entry(0, 1))},${debugFormatDouble(transform.entry(0, 2))},${debugFormatDouble(transform.entry(0, 3))}', '[0] ${debugFormatDouble(transform.entry(0, 0))},${debugFormatDouble(transform.entry(0, 1))},${debugFormatDouble(transform.entry(0, 2))},${debugFormatDouble(transform.entry(0, 3))}',
'[1] ${debugFormatDouble(transform.entry(1, 0))},${debugFormatDouble(transform.entry(1, 1))},${debugFormatDouble(transform.entry(1, 2))},${debugFormatDouble(transform.entry(1, 3))}', '[1] ${debugFormatDouble(transform.entry(1, 0))},${debugFormatDouble(transform.entry(1, 1))},${debugFormatDouble(transform.entry(1, 2))},${debugFormatDouble(transform.entry(1, 3))}',
......
...@@ -56,8 +56,9 @@ class CircularNotchedRectangle extends NotchedShape { ...@@ -56,8 +56,9 @@ class CircularNotchedRectangle extends NotchedShape {
// TODO(amirh): add an example diagram here. // TODO(amirh): add an example diagram here.
@override @override
Path getOuterPath(Rect host, Rect? guest) { Path getOuterPath(Rect host, Rect? guest) {
if (guest == null || !host.overlaps(guest)) if (guest == null || !host.overlaps(guest)) {
return Path()..addRect(host); return Path()..addRect(host);
}
// The guest's shape is a circle bounded by the guest rectangle. // The guest's shape is a circle bounded by the guest rectangle.
// So the guest's radius is half the guest width. // So the guest's radius is half the guest width.
...@@ -99,8 +100,9 @@ class CircularNotchedRectangle extends NotchedShape { ...@@ -99,8 +100,9 @@ class CircularNotchedRectangle extends NotchedShape {
p[5] = Offset(-1.0 * p[0]!.dx, p[0]!.dy); p[5] = Offset(-1.0 * p[0]!.dx, p[0]!.dy);
// translate all points back to the absolute coordinate system. // translate all points back to the absolute coordinate system.
for (int i = 0; i < p.length; i += 1) for (int i = 0; i < p.length; i += 1) {
p[i] = p[i]! + guest.center; p[i] = p[i]! + guest.center;
}
return Path() return Path()
..moveTo(host.left, host.top) ..moveTo(host.left, host.top)
......
...@@ -165,8 +165,9 @@ class RoundedRectangleBorder extends OutlinedBorder { ...@@ -165,8 +165,9 @@ class RoundedRectangleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RoundedRectangleBorder return other is RoundedRectangleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius; && other.borderRadius == borderRadius;
...@@ -262,8 +263,9 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -262,8 +263,9 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
} }
Rect _adjustRect(Rect rect) { Rect _adjustRect(Rect rect) {
if (circleness == 0.0 || rect.width == rect.height) if (circleness == 0.0 || rect.width == rect.height) {
return rect; return rect;
}
if (rect.width < rect.height) { if (rect.width < rect.height) {
final double delta = circleness * (rect.height - rect.width) / 2.0; final double delta = circleness * (rect.height - rect.width) / 2.0;
return Rect.fromLTRB( return Rect.fromLTRB(
...@@ -285,8 +287,9 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -285,8 +287,9 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
BorderRadius? _adjustBorderRadius(Rect rect, TextDirection? textDirection) { BorderRadius? _adjustBorderRadius(Rect rect, TextDirection? textDirection) {
final BorderRadius resolvedRadius = borderRadius.resolve(textDirection); final BorderRadius resolvedRadius = borderRadius.resolve(textDirection);
if (circleness == 0.0) if (circleness == 0.0) {
return resolvedRadius; return resolvedRadius;
}
return BorderRadius.lerp(resolvedRadius, BorderRadius.circular(rect.shortestSide / 2.0), circleness); return BorderRadius.lerp(resolvedRadius, BorderRadius.circular(rect.shortestSide / 2.0), circleness);
} }
...@@ -354,8 +357,9 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -354,8 +357,9 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is _RoundedRectangleToCircleBorder return other is _RoundedRectangleToCircleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius && other.borderRadius == borderRadius
......
...@@ -228,13 +228,16 @@ class ShapeDecoration extends Decoration { ...@@ -228,13 +228,16 @@ class ShapeDecoration extends Decoration {
/// [ShapeDecoration]s or a [ShapeDecoration] to or from null. /// [ShapeDecoration]s or a [ShapeDecoration] to or from null.
static ShapeDecoration? lerp(ShapeDecoration? a, ShapeDecoration? b, double t) { static ShapeDecoration? lerp(ShapeDecoration? a, ShapeDecoration? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null) {
return null; return null;
}
if (a != null && b != null) { if (a != null && b != null) {
if (t == 0.0) if (t == 0.0) {
return a; return a;
if (t == 1.0) }
if (t == 1.0) {
return b; return b;
}
} }
return ShapeDecoration( return ShapeDecoration(
color: Color.lerp(a?.color, b?.color, t), color: Color.lerp(a?.color, b?.color, t),
...@@ -247,10 +250,12 @@ class ShapeDecoration extends Decoration { ...@@ -247,10 +250,12 @@ class ShapeDecoration extends Decoration {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is ShapeDecoration return other is ShapeDecoration
&& other.color == color && other.color == color
&& other.gradient == gradient && other.gradient == gradient
...@@ -313,8 +318,9 @@ class _ShapeDecorationPainter extends BoxPainter { ...@@ -313,8 +318,9 @@ class _ShapeDecorationPainter extends BoxPainter {
void _precache(Rect rect, TextDirection? textDirection) { void _precache(Rect rect, TextDirection? textDirection) {
assert(rect != null); assert(rect != null);
if (rect == _lastRect && textDirection == _lastTextDirection) if (rect == _lastRect && textDirection == _lastTextDirection) {
return; return;
}
// We reach here in two cases: // We reach here in two cases:
// - the very first time we paint, in which case everything except _decoration is null // - the very first time we paint, in which case everything except _decoration is null
...@@ -322,11 +328,13 @@ class _ShapeDecorationPainter extends BoxPainter { ...@@ -322,11 +328,13 @@ class _ShapeDecorationPainter extends BoxPainter {
// the features that depend on the actual rect. // the features that depend on the actual rect.
if (_interiorPaint == null && (_decoration.color != null || _decoration.gradient != null)) { if (_interiorPaint == null && (_decoration.color != null || _decoration.gradient != null)) {
_interiorPaint = Paint(); _interiorPaint = Paint();
if (_decoration.color != null) if (_decoration.color != null) {
_interiorPaint!.color = _decoration.color!; _interiorPaint!.color = _decoration.color!;
}
} }
if (_decoration.gradient != null) if (_decoration.gradient != null) {
_interiorPaint!.shader = _decoration.gradient!.createShader(rect, textDirection: textDirection); _interiorPaint!.shader = _decoration.gradient!.createShader(rect, textDirection: textDirection);
}
if (_decoration.shadows != null) { if (_decoration.shadows != null) {
if (_shadowCount == null) { if (_shadowCount == null) {
_shadowCount = _decoration.shadows!.length; _shadowCount = _decoration.shadows!.length;
...@@ -340,10 +348,12 @@ class _ShapeDecorationPainter extends BoxPainter { ...@@ -340,10 +348,12 @@ class _ShapeDecorationPainter extends BoxPainter {
}), }),
]; ];
} }
if (_interiorPaint != null || _shadowCount != null) if (_interiorPaint != null || _shadowCount != null) {
_outerPath = _decoration.shape.getOuterPath(rect, textDirection: textDirection); _outerPath = _decoration.shape.getOuterPath(rect, textDirection: textDirection);
if (_decoration.image != null) }
if (_decoration.image != null) {
_innerPath = _decoration.shape.getInnerPath(rect, textDirection: textDirection); _innerPath = _decoration.shape.getInnerPath(rect, textDirection: textDirection);
}
_lastRect = rect; _lastRect = rect;
_lastTextDirection = textDirection; _lastTextDirection = textDirection;
...@@ -351,20 +361,23 @@ class _ShapeDecorationPainter extends BoxPainter { ...@@ -351,20 +361,23 @@ class _ShapeDecorationPainter extends BoxPainter {
void _paintShadows(Canvas canvas) { void _paintShadows(Canvas canvas) {
if (_shadowCount != null) { if (_shadowCount != null) {
for (int index = 0; index < _shadowCount!; index += 1) for (int index = 0; index < _shadowCount!; index += 1) {
canvas.drawPath(_shadowPaths[index], _shadowPaints[index]); canvas.drawPath(_shadowPaths[index], _shadowPaints[index]);
}
} }
} }
void _paintInterior(Canvas canvas) { void _paintInterior(Canvas canvas) {
if (_interiorPaint != null) if (_interiorPaint != null) {
canvas.drawPath(_outerPath, _interiorPaint!); canvas.drawPath(_outerPath, _interiorPaint!);
}
} }
DecorationImagePainter? _imagePainter; DecorationImagePainter? _imagePainter;
void _paintImage(Canvas canvas, ImageConfiguration configuration) { void _paintImage(Canvas canvas, ImageConfiguration configuration) {
if (_decoration.image == null) if (_decoration.image == null) {
return; return;
}
_imagePainter ??= _decoration.image!.createPainter(onChanged); _imagePainter ??= _decoration.image!.createPainter(onChanged);
_imagePainter!.paint(canvas, _lastRect!, _innerPath, configuration); _imagePainter!.paint(canvas, _lastRect!, _innerPath, configuration);
} }
......
...@@ -48,8 +48,9 @@ class StadiumBorder extends OutlinedBorder { ...@@ -48,8 +48,9 @@ class StadiumBorder extends OutlinedBorder {
@override @override
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null); assert(t != null);
if (a is StadiumBorder) if (a is StadiumBorder) {
return StadiumBorder(side: BorderSide.lerp(a.side, side, t)); return StadiumBorder(side: BorderSide.lerp(a.side, side, t));
}
if (a is CircleBorder) { if (a is CircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
...@@ -69,8 +70,9 @@ class StadiumBorder extends OutlinedBorder { ...@@ -69,8 +70,9 @@ class StadiumBorder extends OutlinedBorder {
@override @override
ShapeBorder? lerpTo(ShapeBorder? b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
assert(t != null); assert(t != null);
if (b is StadiumBorder) if (b is StadiumBorder) {
return StadiumBorder(side: BorderSide.lerp(side, b.side, t)); return StadiumBorder(side: BorderSide.lerp(side, b.side, t));
}
if (b is CircleBorder) { if (b is CircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
...@@ -148,8 +150,9 @@ class StadiumBorder extends OutlinedBorder { ...@@ -148,8 +150,9 @@ class StadiumBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is StadiumBorder return other is StadiumBorder
&& other.side == side; && other.side == side;
} }
...@@ -235,8 +238,9 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -235,8 +238,9 @@ class _StadiumToCircleBorder extends OutlinedBorder {
} }
Rect _adjustRect(Rect rect) { Rect _adjustRect(Rect rect) {
if (circleness == 0.0 || rect.width == rect.height) if (circleness == 0.0 || rect.width == rect.height) {
return rect; return rect;
}
if (rect.width < rect.height) { if (rect.width < rect.height) {
final double delta = circleness * (rect.height - rect.width) / 2.0; final double delta = circleness * (rect.height - rect.width) / 2.0;
return Rect.fromLTRB( return Rect.fromLTRB(
...@@ -310,8 +314,9 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -310,8 +314,9 @@ class _StadiumToCircleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is _StadiumToCircleBorder return other is _StadiumToCircleBorder
&& other.side == side && other.side == side
&& other.circleness == circleness; && other.circleness == circleness;
...@@ -482,8 +487,9 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -482,8 +487,9 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is _StadiumToRoundedRectangleBorder return other is _StadiumToRoundedRectangleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius && other.borderRadius == borderRadius
......
...@@ -405,8 +405,9 @@ class StrutStyle with Diagnosticable { ...@@ -405,8 +405,9 @@ class StrutStyle with Diagnosticable {
/// The package name should be provided by the `package` argument in the /// The package name should be provided by the `package` argument in the
/// constructor. /// constructor.
List<String>? get fontFamilyFallback { List<String>? get fontFamilyFallback {
if (_package != null && _fontFamilyFallback != null) if (_package != null && _fontFamilyFallback != null) {
return _fontFamilyFallback!.map((String family) => 'packages/$_package/$family').toList(); return _fontFamilyFallback!.map((String family) => 'packages/$_package/$family').toList();
}
return _fontFamilyFallback; return _fontFamilyFallback;
} }
final List<String>? _fontFamilyFallback; final List<String>? _fontFamilyFallback;
...@@ -518,8 +519,9 @@ class StrutStyle with Diagnosticable { ...@@ -518,8 +519,9 @@ class StrutStyle with Diagnosticable {
/// ///
/// * [TextSpan.compareTo], which does the same thing for entire [TextSpan]s. /// * [TextSpan.compareTo], which does the same thing for entire [TextSpan]s.
RenderComparison compareTo(StrutStyle other) { RenderComparison compareTo(StrutStyle other) {
if (identical(this, other)) if (identical(this, other)) {
return RenderComparison.identical; return RenderComparison.identical;
}
if (fontFamily != other.fontFamily || if (fontFamily != other.fontFamily ||
fontSize != other.fontSize || fontSize != other.fontSize ||
fontWeight != other.fontWeight || fontWeight != other.fontWeight ||
...@@ -527,8 +529,9 @@ class StrutStyle with Diagnosticable { ...@@ -527,8 +529,9 @@ class StrutStyle with Diagnosticable {
height != other.height || height != other.height ||
leading != other.leading || leading != other.leading ||
forceStrutHeight != other.forceStrutHeight || forceStrutHeight != other.forceStrutHeight ||
!listEquals(fontFamilyFallback, other.fontFamilyFallback)) !listEquals(fontFamilyFallback, other.fontFamilyFallback)) {
return RenderComparison.layout; return RenderComparison.layout;
}
return RenderComparison.identical; return RenderComparison.identical;
} }
...@@ -541,8 +544,9 @@ class StrutStyle with Diagnosticable { ...@@ -541,8 +544,9 @@ class StrutStyle with Diagnosticable {
/// ///
/// If the given text style is null, returns this strut style. /// If the given text style is null, returns this strut style.
StrutStyle inheritFromTextStyle(TextStyle? other) { StrutStyle inheritFromTextStyle(TextStyle? other) {
if (other == null) if (other == null) {
return this; return this;
}
return StrutStyle( return StrutStyle(
fontFamily: fontFamily ?? other.fontFamily, fontFamily: fontFamily ?? other.fontFamily,
...@@ -560,10 +564,12 @@ class StrutStyle with Diagnosticable { ...@@ -560,10 +564,12 @@ class StrutStyle with Diagnosticable {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is StrutStyle return other is StrutStyle
&& other.fontFamily == fontFamily && other.fontFamily == fontFamily
&& other.fontSize == fontSize && other.fontSize == fontSize
...@@ -592,8 +598,9 @@ class StrutStyle with Diagnosticable { ...@@ -592,8 +598,9 @@ class StrutStyle with Diagnosticable {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties, { String prefix = '' }) { void debugFillProperties(DiagnosticPropertiesBuilder properties, { String prefix = '' }) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
if (debugLabel != null) if (debugLabel != null) {
properties.add(MessageProperty('${prefix}debugLabel', debugLabel!)); properties.add(MessageProperty('${prefix}debugLabel', debugLabel!));
}
final List<DiagnosticsNode> styles = <DiagnosticsNode>[ final List<DiagnosticsNode> styles = <DiagnosticsNode>[
StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false), StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false),
IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null), IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null),
...@@ -619,7 +626,8 @@ class StrutStyle with Diagnosticable { ...@@ -619,7 +626,8 @@ class StrutStyle with Diagnosticable {
final bool styleSpecified = styles.any((DiagnosticsNode n) => !n.isFiltered(DiagnosticLevel.info)); final bool styleSpecified = styles.any((DiagnosticsNode n) => !n.isFiltered(DiagnosticLevel.info));
styles.forEach(properties.add); styles.forEach(properties.add);
if (!styleSpecified) if (!styleSpecified) {
properties.add(FlagProperty('forceStrutHeight', value: forceStrutHeight, ifTrue: '$prefix<strut height forced>', ifFalse: '$prefix<strut height normal>')); properties.add(FlagProperty('forceStrutHeight', value: forceStrutHeight, ifTrue: '$prefix<strut height forced>', ifFalse: '$prefix<strut height normal>'));
}
} }
} }
...@@ -225,10 +225,12 @@ class TextPainter { ...@@ -225,10 +225,12 @@ class TextPainter {
InlineSpan? _text; InlineSpan? _text;
set text(InlineSpan? value) { set text(InlineSpan? value) {
assert(value == null || value.debugAssertIsValid()); assert(value == null || value.debugAssertIsValid());
if (_text == value) if (_text == value) {
return; return;
if (_text?.style != value?.style) }
if (_text?.style != value?.style) {
_layoutTemplate = null; _layoutTemplate = null;
}
final RenderComparison comparison = value == null final RenderComparison comparison = value == null
? RenderComparison.layout ? RenderComparison.layout
...@@ -255,8 +257,9 @@ class TextPainter { ...@@ -255,8 +257,9 @@ class TextPainter {
TextAlign _textAlign; TextAlign _textAlign;
set textAlign(TextAlign value) { set textAlign(TextAlign value) {
assert(value != null); assert(value != null);
if (_textAlign == value) if (_textAlign == value) {
return; return;
}
_textAlign = value; _textAlign = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -279,8 +282,9 @@ class TextPainter { ...@@ -279,8 +282,9 @@ class TextPainter {
TextDirection? get textDirection => _textDirection; TextDirection? get textDirection => _textDirection;
TextDirection? _textDirection; TextDirection? _textDirection;
set textDirection(TextDirection? value) { set textDirection(TextDirection? value) {
if (_textDirection == value) if (_textDirection == value) {
return; return;
}
_textDirection = value; _textDirection = value;
markNeedsLayout(); markNeedsLayout();
_layoutTemplate = null; // Shouldn't really matter, but for strict correctness... _layoutTemplate = null; // Shouldn't really matter, but for strict correctness...
...@@ -296,8 +300,9 @@ class TextPainter { ...@@ -296,8 +300,9 @@ class TextPainter {
double _textScaleFactor; double _textScaleFactor;
set textScaleFactor(double value) { set textScaleFactor(double value) {
assert(value != null); assert(value != null);
if (_textScaleFactor == value) if (_textScaleFactor == value) {
return; return;
}
_textScaleFactor = value; _textScaleFactor = value;
markNeedsLayout(); markNeedsLayout();
_layoutTemplate = null; _layoutTemplate = null;
...@@ -323,8 +328,9 @@ class TextPainter { ...@@ -323,8 +328,9 @@ class TextPainter {
String? _ellipsis; String? _ellipsis;
set ellipsis(String? value) { set ellipsis(String? value) {
assert(value == null || value.isNotEmpty); assert(value == null || value.isNotEmpty);
if (_ellipsis == value) if (_ellipsis == value) {
return; return;
}
_ellipsis = value; _ellipsis = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -333,8 +339,9 @@ class TextPainter { ...@@ -333,8 +339,9 @@ class TextPainter {
Locale? get locale => _locale; Locale? get locale => _locale;
Locale? _locale; Locale? _locale;
set locale(Locale? value) { set locale(Locale? value) {
if (_locale == value) if (_locale == value) {
return; return;
}
_locale = value; _locale = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -351,8 +358,9 @@ class TextPainter { ...@@ -351,8 +358,9 @@ class TextPainter {
/// The value may be null. If it is not null, then it must be greater than zero. /// The value may be null. If it is not null, then it must be greater than zero.
set maxLines(int? value) { set maxLines(int? value) {
assert(value == null || value > 0); assert(value == null || value > 0);
if (_maxLines == value) if (_maxLines == value) {
return; return;
}
_maxLines = value; _maxLines = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -372,8 +380,9 @@ class TextPainter { ...@@ -372,8 +380,9 @@ class TextPainter {
StrutStyle? get strutStyle => _strutStyle; StrutStyle? get strutStyle => _strutStyle;
StrutStyle? _strutStyle; StrutStyle? _strutStyle;
set strutStyle(StrutStyle? value) { set strutStyle(StrutStyle? value) {
if (_strutStyle == value) if (_strutStyle == value) {
return; return;
}
_strutStyle = value; _strutStyle = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -385,8 +394,9 @@ class TextPainter { ...@@ -385,8 +394,9 @@ class TextPainter {
TextWidthBasis _textWidthBasis; TextWidthBasis _textWidthBasis;
set textWidthBasis(TextWidthBasis value) { set textWidthBasis(TextWidthBasis value) {
assert(value != null); assert(value != null);
if (_textWidthBasis == value) if (_textWidthBasis == value) {
return; return;
}
_textWidthBasis = value; _textWidthBasis = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -395,8 +405,9 @@ class TextPainter { ...@@ -395,8 +405,9 @@ class TextPainter {
ui.TextHeightBehavior? get textHeightBehavior => _textHeightBehavior; ui.TextHeightBehavior? get textHeightBehavior => _textHeightBehavior;
ui.TextHeightBehavior? _textHeightBehavior; ui.TextHeightBehavior? _textHeightBehavior;
set textHeightBehavior(ui.TextHeightBehavior? value) { set textHeightBehavior(ui.TextHeightBehavior? value) {
if (_textHeightBehavior == value) if (_textHeightBehavior == value) {
return; return;
}
_textHeightBehavior = value; _textHeightBehavior = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -481,8 +492,9 @@ class TextPainter { ...@@ -481,8 +492,9 @@ class TextPainter {
_createParagraphStyle(TextDirection.rtl), _createParagraphStyle(TextDirection.rtl),
); // direction doesn't matter, text is just a space ); // direction doesn't matter, text is just a space
final ui.TextStyle? textStyle = text?.style?.getTextStyle(textScaleFactor: textScaleFactor); final ui.TextStyle? textStyle = text?.style?.getTextStyle(textScaleFactor: textScaleFactor);
if (textStyle != null) if (textStyle != null) {
builder.pushStyle(textStyle); builder.pushStyle(textStyle);
}
builder.addText(' '); builder.addText(' ');
return builder.build() return builder.build()
..layout(const ui.ParagraphConstraints(width: double.infinity)); ..layout(const ui.ParagraphConstraints(width: double.infinity));
...@@ -642,11 +654,13 @@ class TextPainter { ...@@ -642,11 +654,13 @@ class TextPainter {
assert(textDirection != null, 'TextPainter.textDirection must be set to a non-null value before using the TextPainter.'); assert(textDirection != null, 'TextPainter.textDirection must be set to a non-null value before using the TextPainter.');
// Return early if the current layout information is not outdated, even if // Return early if the current layout information is not outdated, even if
// _needsPaint is true (in which case _paragraph will be rebuilt in paint). // _needsPaint is true (in which case _paragraph will be rebuilt in paint).
if (_paragraph != null && minWidth == _lastMinWidth && maxWidth == _lastMaxWidth) if (_paragraph != null && minWidth == _lastMinWidth && maxWidth == _lastMaxWidth) {
return; return;
}
if (_rebuildParagraphForPaint || _paragraph == null) if (_rebuildParagraphForPaint || _paragraph == null) {
_createParagraph(); _createParagraph();
}
_lastMinWidth = minWidth; _lastMinWidth = minWidth;
_lastMaxWidth = maxWidth; _lastMaxWidth = maxWidth;
// A change in layout invalidates the cached caret and line metrics as well. // A change in layout invalidates the cached caret and line metrics as well.
...@@ -718,8 +732,9 @@ class TextPainter { ...@@ -718,8 +732,9 @@ class TextPainter {
/// positioned. /// positioned.
int? getOffsetAfter(int offset) { int? getOffsetAfter(int offset) {
final int? nextCodeUnit = _text!.codeUnitAt(offset); final int? nextCodeUnit = _text!.codeUnitAt(offset);
if (nextCodeUnit == null) if (nextCodeUnit == null) {
return null; return null;
}
// TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404). // TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404).
return _isUtf16Surrogate(nextCodeUnit) ? offset + 2 : offset + 1; return _isUtf16Surrogate(nextCodeUnit) ? offset + 2 : offset + 1;
} }
...@@ -728,8 +743,9 @@ class TextPainter { ...@@ -728,8 +743,9 @@ class TextPainter {
/// be positioned. /// be positioned.
int? getOffsetBefore(int offset) { int? getOffsetBefore(int offset) {
final int? prevCodeUnit = _text!.codeUnitAt(offset - 1); final int? prevCodeUnit = _text!.codeUnitAt(offset - 1);
if (prevCodeUnit == null) if (prevCodeUnit == null) {
return null; return null;
}
// TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404). // TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404).
return _isUtf16Surrogate(prevCodeUnit) ? offset - 2 : offset - 1; return _isUtf16Surrogate(prevCodeUnit) ? offset - 2 : offset - 1;
} }
...@@ -742,8 +758,9 @@ class TextPainter { ...@@ -742,8 +758,9 @@ class TextPainter {
Rect? _getRectFromUpstream(int offset, Rect caretPrototype) { Rect? _getRectFromUpstream(int offset, Rect caretPrototype) {
final String flattenedText = _text!.toPlainText(includeSemanticsLabels: false); final String flattenedText = _text!.toPlainText(includeSemanticsLabels: false);
final int? prevCodeUnit = _text!.codeUnitAt(max(0, offset - 1)); final int? prevCodeUnit = _text!.codeUnitAt(max(0, offset - 1));
if (prevCodeUnit == null) if (prevCodeUnit == null) {
return null; return null;
}
// If the upstream character is a newline, cursor is at start of next line // If the upstream character is a newline, cursor is at start of next line
const int NEWLINE_CODE_UNIT = 10; const int NEWLINE_CODE_UNIT = 10;
...@@ -794,8 +811,9 @@ class TextPainter { ...@@ -794,8 +811,9 @@ class TextPainter {
final String flattenedText = _text!.toPlainText(includeSemanticsLabels: false); final String flattenedText = _text!.toPlainText(includeSemanticsLabels: false);
// We cap the offset at the final index of the _text. // We cap the offset at the final index of the _text.
final int? nextCodeUnit = _text!.codeUnitAt(min(offset, flattenedText.length - 1)); final int? nextCodeUnit = _text!.codeUnitAt(min(offset, flattenedText.length - 1));
if (nextCodeUnit == null) if (nextCodeUnit == null) {
return null; return null;
}
// Check for multi-code-unit glyphs such as emojis or zero width joiner // Check for multi-code-unit glyphs such as emojis or zero width joiner
final bool needsSearch = _isUtf16Surrogate(nextCodeUnit) || nextCodeUnit == _zwjUtf16 || _isUnicodeDirectionality(nextCodeUnit); final bool needsSearch = _isUtf16Surrogate(nextCodeUnit) || nextCodeUnit == _zwjUtf16 || _isUnicodeDirectionality(nextCodeUnit);
int graphemeClusterLength = needsSearch ? 2 : 1; int graphemeClusterLength = needsSearch ? 2 : 1;
...@@ -893,8 +911,9 @@ class TextPainter { ...@@ -893,8 +911,9 @@ class TextPainter {
// version and recomputes the metrics required to position the caret. // version and recomputes the metrics required to position the caret.
void _computeCaretMetrics(TextPosition position, Rect caretPrototype) { void _computeCaretMetrics(TextPosition position, Rect caretPrototype) {
assert(!_debugNeedsLayout); assert(!_debugNeedsLayout);
if (position == _previousCaretPosition && caretPrototype == _previousCaretPrototype) if (position == _previousCaretPosition && caretPrototype == _previousCaretPrototype) {
return; return;
}
final int offset = position.offset; final int offset = position.offset;
assert(position.affinity != null); assert(position.affinity != null);
Rect? rect; Rect? rect;
......
...@@ -249,8 +249,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -249,8 +249,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
@override @override
void handleEvent(PointerEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
if (event is PointerDownEvent) if (event is PointerDownEvent) {
recognizer?.addPointer(event); recognizer?.addPointer(event);
}
} }
/// Apply the [style], [text], and [children] of this object to the /// Apply the [style], [text], and [children] of this object to the
...@@ -268,8 +269,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -268,8 +269,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
}) { }) {
assert(debugAssertIsValid()); assert(debugAssertIsValid());
final bool hasStyle = style != null; final bool hasStyle = style != null;
if (hasStyle) if (hasStyle) {
builder.pushStyle(style!.getTextStyle(textScaleFactor: textScaleFactor)); builder.pushStyle(style!.getTextStyle(textScaleFactor: textScaleFactor));
}
if (text != null) { if (text != null) {
try { try {
builder.addText(text!); builder.addText(text!);
...@@ -294,8 +296,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -294,8 +296,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
); );
} }
} }
if (hasStyle) if (hasStyle) {
builder.pop(); builder.pop();
}
} }
/// Walks this [TextSpan] and its descendants in pre-order and calls [visitor] /// Walks this [TextSpan] and its descendants in pre-order and calls [visitor]
...@@ -306,13 +309,15 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -306,13 +309,15 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
@override @override
bool visitChildren(InlineSpanVisitor visitor) { bool visitChildren(InlineSpanVisitor visitor) {
if (text != null) { if (text != null) {
if (!visitor(this)) if (!visitor(this)) {
return false; return false;
}
} }
if (children != null) { if (children != null) {
for (final InlineSpan child in children!) { for (final InlineSpan child in children!) {
if (!child.visitChildren(visitor)) if (!child.visitChildren(visitor)) {
return false; return false;
}
} }
} }
return true; return true;
...@@ -466,32 +471,39 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -466,32 +471,39 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
@override @override
RenderComparison compareTo(InlineSpan other) { RenderComparison compareTo(InlineSpan other) {
if (identical(this, other)) if (identical(this, other)) {
return RenderComparison.identical; return RenderComparison.identical;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return RenderComparison.layout; return RenderComparison.layout;
}
final TextSpan textSpan = other as TextSpan; final TextSpan textSpan = other as TextSpan;
if (textSpan.text != text || if (textSpan.text != text ||
children?.length != textSpan.children?.length || children?.length != textSpan.children?.length ||
(style == null) != (textSpan.style == null)) (style == null) != (textSpan.style == null)) {
return RenderComparison.layout; return RenderComparison.layout;
}
RenderComparison result = recognizer == textSpan.recognizer ? RenderComparison result = recognizer == textSpan.recognizer ?
RenderComparison.identical : RenderComparison.identical :
RenderComparison.metadata; RenderComparison.metadata;
if (style != null) { if (style != null) {
final RenderComparison candidate = style!.compareTo(textSpan.style!); final RenderComparison candidate = style!.compareTo(textSpan.style!);
if (candidate.index > result.index) if (candidate.index > result.index) {
result = candidate; result = candidate;
if (result == RenderComparison.layout) }
if (result == RenderComparison.layout) {
return result; return result;
}
} }
if (children != null) { if (children != null) {
for (int index = 0; index < children!.length; index += 1) { for (int index = 0; index < children!.length; index += 1) {
final RenderComparison candidate = children![index].compareTo(textSpan.children![index]); final RenderComparison candidate = children![index].compareTo(textSpan.children![index]);
if (candidate.index > result.index) if (candidate.index > result.index) {
result = candidate; result = candidate;
if (result == RenderComparison.layout) }
if (result == RenderComparison.layout) {
return result; return result;
}
} }
} }
return result; return result;
...@@ -499,12 +511,15 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -499,12 +511,15 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
if (super != other) }
if (super != other) {
return false; return false;
}
return other is TextSpan return other is TextSpan
&& other.text == text && other.text == text
&& other.recognizer == recognizer && other.recognizer == recognizer
...@@ -542,8 +557,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -542,8 +557,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
defaultValue: null, defaultValue: null,
), ),
); );
if (style == null && text == null && children == null) if (style == null && text == null && children == null) {
properties.add(DiagnosticsNode.message('(empty)')); properties.add(DiagnosticsNode.message('(empty)'));
}
properties.add(DiagnosticsProperty<GestureRecognizer>( properties.add(DiagnosticsProperty<GestureRecognizer>(
'recognizer', recognizer, 'recognizer', recognizer,
...@@ -567,8 +583,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati ...@@ -567,8 +583,9 @@ class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotati
@override @override
List<DiagnosticsNode> debugDescribeChildren() { List<DiagnosticsNode> debugDescribeChildren() {
if (children == null) if (children == null) {
return const <DiagnosticsNode>[]; return const <DiagnosticsNode>[];
}
return children!.map<DiagnosticsNode>((InlineSpan child) { return children!.map<DiagnosticsNode>((InlineSpan child) {
// `child` has a non-nullable return type, but might be null when running // `child` has a non-nullable return type, but might be null when running
// with weak checking, so we need to null check it anyway (and ignore the // with weak checking, so we need to null check it anyway (and ignore the
......
...@@ -843,8 +843,9 @@ class TextStyle with Diagnosticable { ...@@ -843,8 +843,9 @@ class TextStyle with Diagnosticable {
assert(backgroundColor == null || background == null, _kColorBackgroundWarning); assert(backgroundColor == null || background == null, _kColorBackgroundWarning);
String? newDebugLabel; String? newDebugLabel;
assert(() { assert(() {
if (this.debugLabel != null) if (this.debugLabel != null) {
newDebugLabel = debugLabel ?? '(${this.debugLabel}).copyWith'; newDebugLabel = debugLabel ?? '(${this.debugLabel}).copyWith';
}
return true; return true;
}()); }());
...@@ -955,8 +956,9 @@ class TextStyle with Diagnosticable { ...@@ -955,8 +956,9 @@ class TextStyle with Diagnosticable {
String? modifiedDebugLabel; String? modifiedDebugLabel;
assert(() { assert(() {
if (debugLabel != null) if (debugLabel != null) {
modifiedDebugLabel = '($debugLabel).apply'; modifiedDebugLabel = '($debugLabel).apply';
}
return true; return true;
}()); }());
...@@ -1012,15 +1014,18 @@ class TextStyle with Diagnosticable { ...@@ -1012,15 +1014,18 @@ class TextStyle with Diagnosticable {
/// this or `other` has [background] specified it will be given preference /// this or `other` has [background] specified it will be given preference
/// over any backgroundColor parameter. /// over any backgroundColor parameter.
TextStyle merge(TextStyle? other) { TextStyle merge(TextStyle? other) {
if (other == null) if (other == null) {
return this; return this;
if (!other.inherit) }
if (!other.inherit) {
return other; return other;
}
String? mergedDebugLabel; String? mergedDebugLabel;
assert(() { assert(() {
if (other.debugLabel != null || debugLabel != null) if (other.debugLabel != null || debugLabel != null) {
mergedDebugLabel = '(${debugLabel ?? _kDefaultDebugLabel}).merge(${other.debugLabel ?? _kDefaultDebugLabel})'; mergedDebugLabel = '(${debugLabel ?? _kDefaultDebugLabel}).merge(${other.debugLabel ?? _kDefaultDebugLabel})';
}
return true; return true;
}()); }());
...@@ -1271,8 +1276,9 @@ class TextStyle with Diagnosticable { ...@@ -1271,8 +1276,9 @@ class TextStyle with Diagnosticable {
/// ///
/// * [TextSpan.compareTo], which does the same thing for entire [TextSpan]s. /// * [TextSpan.compareTo], which does the same thing for entire [TextSpan]s.
RenderComparison compareTo(TextStyle other) { RenderComparison compareTo(TextStyle other) {
if (identical(this, other)) if (identical(this, other)) {
return RenderComparison.identical; return RenderComparison.identical;
}
if (inherit != other.inherit || if (inherit != other.inherit ||
fontFamily != other.fontFamily || fontFamily != other.fontFamily ||
fontSize != other.fontSize || fontSize != other.fontSize ||
...@@ -1290,24 +1296,28 @@ class TextStyle with Diagnosticable { ...@@ -1290,24 +1296,28 @@ class TextStyle with Diagnosticable {
!listEquals(fontFeatures, other.fontFeatures) || !listEquals(fontFeatures, other.fontFeatures) ||
!listEquals(fontVariations, other.fontVariations) || !listEquals(fontVariations, other.fontVariations) ||
!listEquals(fontFamilyFallback, other.fontFamilyFallback) || !listEquals(fontFamilyFallback, other.fontFamilyFallback) ||
overflow != other.overflow) overflow != other.overflow) {
return RenderComparison.layout; return RenderComparison.layout;
}
if (color != other.color || if (color != other.color ||
backgroundColor != other.backgroundColor || backgroundColor != other.backgroundColor ||
decoration != other.decoration || decoration != other.decoration ||
decorationColor != other.decorationColor || decorationColor != other.decorationColor ||
decorationStyle != other.decorationStyle || decorationStyle != other.decorationStyle ||
decorationThickness != other.decorationThickness) decorationThickness != other.decorationThickness) {
return RenderComparison.paint; return RenderComparison.paint;
}
return RenderComparison.identical; return RenderComparison.identical;
} }
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is TextStyle return other is TextStyle
&& other.inherit == inherit && other.inherit == inherit
&& other.color == color && other.color == color
...@@ -1374,8 +1384,9 @@ class TextStyle with Diagnosticable { ...@@ -1374,8 +1384,9 @@ class TextStyle with Diagnosticable {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties, { String prefix = '' }) { void debugFillProperties(DiagnosticPropertiesBuilder properties, { String prefix = '' }) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
if (debugLabel != null) if (debugLabel != null) {
properties.add(MessageProperty('${prefix}debugLabel', debugLabel!)); properties.add(MessageProperty('${prefix}debugLabel', debugLabel!));
}
final List<DiagnosticsNode> styles = <DiagnosticsNode>[ final List<DiagnosticsNode> styles = <DiagnosticsNode>[
ColorProperty('${prefix}color', color, defaultValue: null), ColorProperty('${prefix}color', color, defaultValue: null),
ColorProperty('${prefix}backgroundColor', backgroundColor, defaultValue: null), ColorProperty('${prefix}backgroundColor', backgroundColor, defaultValue: null),
...@@ -1407,22 +1418,25 @@ class TextStyle with Diagnosticable { ...@@ -1407,22 +1418,25 @@ class TextStyle with Diagnosticable {
styles.add(DiagnosticsProperty<Paint>('${prefix}background', background, defaultValue: null)); styles.add(DiagnosticsProperty<Paint>('${prefix}background', background, defaultValue: null));
if (decoration != null || decorationColor != null || decorationStyle != null || decorationThickness != null) { if (decoration != null || decorationColor != null || decorationStyle != null || decorationThickness != null) {
final List<String> decorationDescription = <String>[]; final List<String> decorationDescription = <String>[];
if (decorationStyle != null) if (decorationStyle != null) {
decorationDescription.add(decorationStyle!.name); decorationDescription.add(decorationStyle!.name);
}
// Hide decorationColor from the default text view as it is shown in the // Hide decorationColor from the default text view as it is shown in the
// terse decoration summary as well. // terse decoration summary as well.
styles.add(ColorProperty('${prefix}decorationColor', decorationColor, defaultValue: null, level: DiagnosticLevel.fine)); styles.add(ColorProperty('${prefix}decorationColor', decorationColor, defaultValue: null, level: DiagnosticLevel.fine));
if (decorationColor != null) if (decorationColor != null) {
decorationDescription.add('$decorationColor'); decorationDescription.add('$decorationColor');
}
// Intentionally collide with the property 'decoration' added below. // Intentionally collide with the property 'decoration' added below.
// Tools that show hidden properties could choose the first property // Tools that show hidden properties could choose the first property
// matching the name to disambiguate. // matching the name to disambiguate.
styles.add(DiagnosticsProperty<TextDecoration>('${prefix}decoration', decoration, defaultValue: null, level: DiagnosticLevel.hidden)); styles.add(DiagnosticsProperty<TextDecoration>('${prefix}decoration', decoration, defaultValue: null, level: DiagnosticLevel.hidden));
if (decoration != null) if (decoration != null) {
decorationDescription.add('$decoration'); decorationDescription.add('$decoration');
}
assert(decorationDescription.isNotEmpty); assert(decorationDescription.isNotEmpty);
styles.add(MessageProperty('${prefix}decoration', decorationDescription.join(' '))); styles.add(MessageProperty('${prefix}decoration', decorationDescription.join(' ')));
styles.add(DoubleProperty('${prefix}decorationThickness', decorationThickness, unit: 'x', defaultValue: null)); styles.add(DoubleProperty('${prefix}decorationThickness', decorationThickness, unit: 'x', defaultValue: null));
...@@ -1432,8 +1446,9 @@ class TextStyle with Diagnosticable { ...@@ -1432,8 +1446,9 @@ class TextStyle with Diagnosticable {
properties.add(DiagnosticsProperty<bool>('${prefix}inherit', inherit, level: (!styleSpecified && inherit) ? DiagnosticLevel.fine : DiagnosticLevel.info)); properties.add(DiagnosticsProperty<bool>('${prefix}inherit', inherit, level: (!styleSpecified && inherit) ? DiagnosticLevel.fine : DiagnosticLevel.info));
styles.forEach(properties.add); styles.forEach(properties.add);
if (!styleSpecified) if (!styleSpecified) {
properties.add(FlagProperty('inherit', value: inherit, ifTrue: '$prefix<all styles inherited>', ifFalse: '$prefix<no style specified>')); properties.add(FlagProperty('inherit', value: inherit, ifTrue: '$prefix<all styles inherited>', ifFalse: '$prefix<no style specified>'));
}
styles.add(EnumProperty<TextOverflow>('${prefix}overflow', overflow, defaultValue: null)); styles.add(EnumProperty<TextOverflow>('${prefix}overflow', overflow, defaultValue: null));
} }
......
...@@ -82,10 +82,12 @@ class FrictionSimulation extends Simulation { ...@@ -82,10 +82,12 @@ class FrictionSimulation extends Simulation {
/// ///
/// Returns `double.infinity` if the simulation will never reach [x]. /// Returns `double.infinity` if the simulation will never reach [x].
double timeAtX(double x) { double timeAtX(double x) {
if (x == _x) if (x == _x) {
return 0.0; return 0.0;
if (_v == 0.0 || (_v > 0 ? (x < _x || x > finalX) : (x > _x || x < finalX))) }
if (_v == 0.0 || (_v > 0 ? (x < _x || x > finalX) : (x > _x || x < finalX))) {
return double.infinity; return double.infinity;
}
return math.log(_dragLog * (x - _x) / _v + 1.0) / _dragLog; return math.log(_dragLog * (x - _x) / _v + 1.0) / _dragLog;
} }
......
...@@ -158,10 +158,12 @@ abstract class _SpringSolution { ...@@ -158,10 +158,12 @@ abstract class _SpringSolution {
assert(initialPosition != null); assert(initialPosition != null);
assert(initialVelocity != null); assert(initialVelocity != null);
final double cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness; final double cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness;
if (cmk == 0.0) if (cmk == 0.0) {
return _CriticalSolution(spring, initialPosition, initialVelocity); return _CriticalSolution(spring, initialPosition, initialVelocity);
if (cmk > 0.0) }
if (cmk > 0.0) {
return _OverdampedSolution(spring, initialPosition, initialVelocity); return _OverdampedSolution(spring, initialPosition, initialVelocity);
}
return _UnderdampedSolution(spring, initialPosition, initialVelocity); return _UnderdampedSolution(spring, initialPosition, initialVelocity);
} }
......
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
bool nearEqual(double? a, double? b, double epsilon) { bool nearEqual(double? a, double? b, double epsilon) {
assert(epsilon != null); assert(epsilon != null);
assert(epsilon >= 0.0); assert(epsilon >= 0.0);
if (a == null || b == null) if (a == null || b == null) {
return a == b; return a == b;
}
return (a > (b - epsilon)) && (a < (b + epsilon)) || a == b; return (a > (b - epsilon)) && (a < (b + epsilon)) || a == b;
} }
......
...@@ -254,8 +254,9 @@ class TestTree extends Object with DiagnosticableTreeMixin { ...@@ -254,8 +254,9 @@ class TestTree extends Object with DiagnosticableTreeMixin {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
if (style != null) if (style != null) {
properties.defaultDiagnosticsTreeStyle = style!; properties.defaultDiagnosticsTreeStyle = style!;
}
this.properties.forEach(properties.add); this.properties.forEach(properties.add);
} }
......
...@@ -33,8 +33,9 @@ class TestTree extends Object with DiagnosticableTreeMixin { ...@@ -33,8 +33,9 @@ class TestTree extends Object with DiagnosticableTreeMixin {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
if (style != null) if (style != null) {
properties.defaultDiagnosticsTreeStyle = style!; properties.defaultDiagnosticsTreeStyle = style!;
}
this.properties.forEach(properties.add); this.properties.forEach(properties.add);
} }
} }
......
...@@ -21,8 +21,9 @@ class TestResampleEventFlutterBinding extends BindingBase with GestureBinding, S ...@@ -21,8 +21,9 @@ class TestResampleEventFlutterBinding extends BindingBase with GestureBinding, S
@override @override
void handleEvent(PointerEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
super.handleEvent(event, entry); super.handleEvent(event, entry);
if (callback != null) if (callback != null) {
callback?.call(event); callback?.call(event);
}
} }
@override @override
......
...@@ -40,8 +40,9 @@ class TestGestureFlutterBinding extends BindingBase with GestureBinding, Schedul ...@@ -40,8 +40,9 @@ class TestGestureFlutterBinding extends BindingBase with GestureBinding, Schedul
@override @override
void handleEvent(PointerEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
super.handleEvent(event, entry); super.handleEvent(event, entry);
if (callback != null) if (callback != null) {
callback?.call(event); callback?.call(event);
}
} }
} }
...@@ -144,8 +145,9 @@ void main() { ...@@ -144,8 +145,9 @@ void main() {
final List<PointerEvent> events = <PointerEvent>[]; final List<PointerEvent> events = <PointerEvent>[];
binding.callback = (PointerEvent event) { binding.callback = (PointerEvent event) {
events.add(event); events.add(event);
if (event is PointerDownEvent) if (event is PointerDownEvent) {
binding.cancelPointer(event.pointer); binding.cancelPointer(event.pointer);
}
}; };
GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet); GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet);
......
...@@ -15,8 +15,9 @@ class TestGestureFlutterBinding extends BindingBase with GestureBinding { ...@@ -15,8 +15,9 @@ class TestGestureFlutterBinding extends BindingBase with GestureBinding {
@override @override
void handleEvent(PointerEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
if (callback != null) if (callback != null) {
callback?.call(event); callback?.call(event);
}
super.handleEvent(event, entry); super.handleEvent(event, entry);
} }
......
...@@ -39,8 +39,9 @@ void main() { ...@@ -39,8 +39,9 @@ void main() {
final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch); final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
int i = 0; int i = 0;
for (final PointerEvent event in velocityEventData) { for (final PointerEvent event in velocityEventData) {
if (event is PointerDownEvent || event is PointerMoveEvent) if (event is PointerDownEvent || event is PointerMoveEvent) {
tracker.addPosition(event.timeStamp, event.position); tracker.addPosition(event.timeStamp, event.position);
}
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
_checkVelocity(tracker.getVelocity(), expected[i]); _checkVelocity(tracker.getVelocity(), expected[i]);
i += 1; i += 1;
...@@ -64,8 +65,9 @@ void main() { ...@@ -64,8 +65,9 @@ void main() {
// Regression test for https://github.com/flutter/flutter/pull/7510 // Regression test for https://github.com/flutter/flutter/pull/7510
final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch); final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
for (final PointerEvent event in interruptedVelocityEventData) { for (final PointerEvent event in interruptedVelocityEventData) {
if (event is PointerDownEvent || event is PointerMoveEvent) if (event is PointerDownEvent || event is PointerMoveEvent) {
tracker.addPosition(event.timeStamp, event.position); tracker.addPosition(event.timeStamp, event.position);
}
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
_checkVelocity(tracker.getVelocity(), const Offset(649.5, 3890.3)); _checkVelocity(tracker.getVelocity(), const Offset(649.5, 3890.3));
} }
......
...@@ -60,8 +60,9 @@ void main() { ...@@ -60,8 +60,9 @@ void main() {
for (final double n in numbers) { for (final double n in numbers) {
expect((topStart * n).add(topStart), topStart * (n + 1.0)); expect((topStart * n).add(topStart), topStart * (n + 1.0));
expect((topEnd * n).add(topEnd), topEnd * (n + 1.0)); expect((topEnd * n).add(topEnd), topEnd * (n + 1.0));
for (final double m in numbers) for (final double m in numbers) {
expect((topStart * n).add(topStart * m), topStart * (n + m)); expect((topStart * n).add(topStart * m), topStart * (n + m));
}
} }
expect(topStart + topStart + topStart, topStart * 3.0); // without using "add" expect(topStart + topStart + topStart, topStart * 3.0); // without using "add"
for (final TextDirection x in TextDirection.values) { for (final TextDirection x in TextDirection.values) {
......
...@@ -28,8 +28,9 @@ class FakeCodec implements ui.Codec { ...@@ -28,8 +28,9 @@ class FakeCodec implements ui.Codec {
final ui.Codec codec = await ui.instantiateImageCodec(data); final ui.Codec codec = await ui.instantiateImageCodec(data);
final int frameCount = codec.frameCount; final int frameCount = codec.frameCount;
final List<ui.FrameInfo> frameInfos = <ui.FrameInfo>[]; final List<ui.FrameInfo> frameInfos = <ui.FrameInfo>[];
for (int i = 0; i < frameCount; i += 1) for (int i = 0; i < frameCount; i += 1) {
frameInfos.add(await codec.getNextFrame()); frameInfos.add(await codec.getNextFrame());
}
return FakeCodec._(frameCount, codec.repetitionCount, frameInfos); return FakeCodec._(frameCount, codec.repetitionCount, frameInfos);
} }
......
...@@ -23,13 +23,15 @@ class TestAssetBundle extends CachingAssetBundle { ...@@ -23,13 +23,15 @@ class TestAssetBundle extends CachingAssetBundle {
@override @override
Future<ByteData> load(String key) async { Future<ByteData> load(String key) async {
if (key == 'AssetManifest.json') if (key == 'AssetManifest.json') {
return ByteData.view(Uint8List.fromList(const Utf8Encoder().convert(_assetBundleContents)).buffer); return ByteData.view(Uint8List.fromList(const Utf8Encoder().convert(_assetBundleContents)).buffer);
}
loadCallCount[key] = loadCallCount[key] ?? 0 + 1; loadCallCount[key] = loadCallCount[key] ?? 0 + 1;
if (key == 'one') if (key == 'one') {
return ByteData(1) return ByteData(1)
..setInt8(0, 49); ..setInt8(0, 49);
}
throw FlutterError('key not found'); throw FlutterError('key not found');
} }
} }
......
...@@ -30,8 +30,9 @@ class TestImageInfo extends ImageInfo { ...@@ -30,8 +30,9 @@ class TestImageInfo extends ImageInfo {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is TestImageInfo return other is TestImageInfo
&& other.value == value && other.value == value
&& other.image.isCloneOf(image) && other.image.isCloneOf(image)
......
...@@ -115,8 +115,9 @@ bool pathDoesNotContainCircle(Path path, Rect circleBounds) { ...@@ -115,8 +115,9 @@ bool pathDoesNotContainCircle(Path path, Rect circleBounds) {
for (double i = 0.0; i < 1; i += 0.01) { for (double i = 0.0; i < 1; i += 0.01) {
final double x = i * radius * math.cos(theta); final double x = i * radius * math.cos(theta);
final double y = i * radius * math.sin(theta); final double y = i * radius * math.sin(theta);
if (path.contains(Offset(x,y) + circleBounds.center)) if (path.contains(Offset(x,y) + circleBounds.center)) {
return false; return false;
}
} }
} }
return true; return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment