Unverified Commit be868397 authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

migrate part of painting to nullsafety (#63495)

parent 72619b86
......@@ -510,7 +510,7 @@ abstract class OutlinedBorder extends ShapeBorder {
/// Returns a copy of this OutlinedBorder that draws its outline with the
/// specified [side], if [side] is non-null.
OutlinedBorder copyWith({ BorderSide side });
OutlinedBorder copyWith({ BorderSide? side });
}
/// Represents the addition of two otherwise-incompatible borders.
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
......@@ -40,21 +39,21 @@ class CircleBorder extends OutlinedBorder {
ShapeBorder scale(double t) => CircleBorder(side: side.scale(t));
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a is CircleBorder)
return CircleBorder(side: BorderSide.lerp(a.side, side, t));
return super.lerpFrom(a, t);
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is CircleBorder)
return CircleBorder(side: BorderSide.lerp(side, b.side, t));
return super.lerpTo(b, t);
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addOval(Rect.fromCircle(
center: rect.center,
......@@ -63,7 +62,7 @@ class CircleBorder extends OutlinedBorder {
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addOval(Rect.fromCircle(
center: rect.center,
......@@ -72,12 +71,12 @@ class CircleBorder extends OutlinedBorder {
}
@override
CircleBorder copyWith({ BorderSide side }) {
CircleBorder copyWith({ BorderSide? side }) {
return CircleBorder(side: side ?? this.side);
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
switch (side.style) {
case BorderStyle.none:
break;
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show Canvas, Clip, Path, Paint, Rect, RRect;
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
......@@ -61,24 +60,24 @@ class ContinuousRectangleBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null);
if (a is ContinuousRectangleBorder) {
return ContinuousRectangleBorder(
side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
);
}
return super.lerpFrom(a, t);
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
assert(t != null);
if (b is ContinuousRectangleBorder) {
return ContinuousRectangleBorder(
side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
);
}
return super.lerpTo(b, t);
......@@ -125,17 +124,17 @@ class ContinuousRectangleBorder extends OutlinedBorder {
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return _getPath(borderRadius.resolve(textDirection).toRRect(rect).deflate(side.width));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return _getPath(borderRadius.resolve(textDirection).toRRect(rect));
}
@override
ContinuousRectangleBorder copyWith({ BorderSide side, BorderRadius borderRadius }) {
ContinuousRectangleBorder copyWith({ BorderSide? side, BorderRadius? borderRadius }) {
return ContinuousRectangleBorder(
side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius,
......@@ -143,7 +142,7 @@ class ContinuousRectangleBorder extends OutlinedBorder {
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
if (rect.isEmpty)
return;
switch (side.style) {
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
......@@ -58,7 +57,7 @@ abstract class Decoration with Diagnosticable {
/// [EdgeInsetsGeometry.resolve] to obtain an absolute [EdgeInsets]. (For
/// example, [BorderDirectional] will return an [EdgeInsetsDirectional] for
/// its [padding].)
EdgeInsetsGeometry get padding => EdgeInsets.zero;
EdgeInsetsGeometry? get padding => EdgeInsets.zero;
/// Whether this decoration is complex enough to benefit from caching its painting.
bool get isComplex => false;
......@@ -89,7 +88,7 @@ abstract class Decoration with Diagnosticable {
///
/// Instead of calling this directly, use [Decoration.lerp].
@protected
Decoration lerpFrom(Decoration a, double t) => null;
Decoration? lerpFrom(Decoration? a, double t) => null;
/// Linearly interpolates from `this` to another [Decoration] (which may be of
/// a different class).
......@@ -118,7 +117,7 @@ abstract class Decoration with Diagnosticable {
///
/// Instead of calling this directly, use [Decoration.lerp].
@protected
Decoration lerpTo(Decoration b, double t) => null;
Decoration? lerpTo(Decoration? b, double t) => null;
/// Linearly interpolates between two [Decoration]s.
///
......@@ -127,12 +126,12 @@ abstract class Decoration with Diagnosticable {
/// interpolated, then the interpolation is done via null (at `t == 0.5`).
///
/// {@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);
if (a == null && b == null)
return null;
if (a == null)
return b.lerpFrom(null, t) ?? b;
return b!.lerpFrom(null, t) ?? b;
if (b == null)
return a.lerpTo(null, t) ?? a;
if (t == 0.0)
......@@ -159,7 +158,7 @@ abstract class Decoration with Diagnosticable {
/// is what [Container] uses), the `textDirection` parameter will be populated
/// based on the ambient [Directionality] (by way of the [RenderDecoratedBox]
/// renderer).
bool hitTest(Size size, Offset position, { TextDirection textDirection }) => true;
bool hitTest(Size size, Offset position, { TextDirection? textDirection }) => true;
/// Returns a [BoxPainter] that will paint this decoration.
///
......@@ -170,7 +169,7 @@ abstract class Decoration with Diagnosticable {
BoxPainter createBoxPainter([ VoidCallback onChanged ]);
/// Returns a closed [Path] that describes the outer edge of this decoration.
Path getClipPath(Rect rect, TextDirection textDirection) => null;
Path? getClipPath(Rect rect, TextDirection textDirection) => null;
}
/// A stateful class that can paint a particular [Decoration].
......@@ -220,7 +219,7 @@ abstract class BoxPainter {
///
/// Resources might not start to load until after [paint] has been called,
/// because they might depend on the configuration.
final VoidCallback onChanged;
final VoidCallback? onChanged;
/// Discard any resources being held by the object.
///
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:developer' as developer;
import 'dart:ui' as ui show Image;
......@@ -44,7 +43,7 @@ class DecorationImage {
/// The [image], [alignment], [repeat], and [matchTextDirection] arguments
/// must not be null.
const DecorationImage({
@required this.image,
required this.image,
this.onError,
this.colorFilter,
this.fit,
......@@ -66,10 +65,10 @@ class DecorationImage {
final ImageProvider image;
/// An optional error callback for errors emitted when loading [image].
final ImageErrorListener onError;
final ImageErrorListener? onError;
/// A color filter to apply to the image before painting it.
final ColorFilter colorFilter;
final ColorFilter? colorFilter;
/// How the image should be inscribed into the box.
///
......@@ -77,7 +76,7 @@ class DecorationImage {
/// [BoxFit.fill] if [centerSlice] is not null.
///
/// See the discussion at [paintImage] for more details.
final BoxFit fit;
final BoxFit? fit;
/// How to align the image within its bounds.
///
......@@ -121,7 +120,7 @@ class DecorationImage {
/// destination image size will result in [centerSlice] having no effect
/// (since the nine regions of the image will be rendered with the same
/// scaling, as if it wasn't specified).
final Rect centerSlice;
final Rect? centerSlice;
/// How to paint any portions of the box that would not otherwise be covered
/// by the image.
......@@ -212,8 +211,8 @@ class DecorationImagePainter {
final DecorationImage _details;
final VoidCallback _onChanged;
ImageStream _imageStream;
ImageInfo _image;
ImageStream? _imageStream;
ImageInfo? _image;
/// Draw the image onto the given canvas.
///
......@@ -229,7 +228,7 @@ class DecorationImagePainter {
/// because it had not yet been loaded the first time this method was called,
/// then the `onChanged` callback passed to [DecorationImage.createPainter]
/// will be called.
void paint(Canvas canvas, Rect rect, Path clipPath, ImageConfiguration configuration) {
void paint(Canvas canvas, Rect rect, Path? clipPath, ImageConfiguration configuration) {
assert(canvas != null);
assert(rect != null);
assert(configuration != null);
......@@ -264,7 +263,7 @@ class DecorationImagePainter {
);
_imageStream?.removeListener(listener);
_imageStream = newImageStream;
_imageStream.addListener(listener);
_imageStream!.addListener(listener);
}
if (_image == null)
return;
......@@ -277,9 +276,9 @@ class DecorationImagePainter {
paintImage(
canvas: canvas,
rect: rect,
image: _image.image,
debugImageLabel: _image.debugLabel,
scale: _details.scale * _image.scale,
image: _image!.image,
debugImageLabel: _image!.debugLabel,
scale: _details.scale * _image!.scale,
colorFilter: _details.colorFilter,
fit: _details.fit,
alignment: _details.alignment.resolve(configuration.textDirection),
......@@ -409,15 +408,15 @@ void debugFlushLastFrameImageSizeInfo() {
/// * [DecorationImage], which holds a configuration for calling this function.
/// * [BoxDecoration], which uses this function to paint a [DecorationImage].
void paintImage({
@required Canvas canvas,
@required Rect rect,
@required ui.Image image,
String debugImageLabel,
required Canvas canvas,
required Rect rect,
required ui.Image image,
String? debugImageLabel,
double scale = 1.0,
ColorFilter colorFilter,
BoxFit fit,
ColorFilter? colorFilter,
BoxFit? fit,
Alignment alignment = Alignment.center,
Rect centerSlice,
Rect? centerSlice,
ImageRepeat repeat = ImageRepeat.noRepeat,
bool flipHorizontally = false,
bool invertColors = false,
......@@ -434,7 +433,7 @@ void paintImage({
return;
Size outputSize = rect.size;
Size inputSize = Size(image.width.toDouble(), image.height.toDouble());
Offset sliceBorder;
Offset? sliceBorder;
if (centerSlice != null) {
sliceBorder = Offset(
centerSlice.left + inputSize.width - centerSlice.right,
......@@ -449,7 +448,7 @@ void paintImage({
final Size sourceSize = fittedSizes.source * scale;
Size destinationSize = fittedSizes.destination;
if (centerSlice != null) {
outputSize += sliceBorder;
outputSize += sliceBorder!;
destinationSize += sliceBorder;
// We don't have the ability to draw a subset of the image at the same time
// as we apply a nine-patch stretch.
......@@ -523,23 +522,23 @@ void paintImage({
}());
// Avoid emitting events that are the same as those emitted in the last frame.
if (!_lastFrameImageSizeInfo.contains(sizeInfo)) {
final ImageSizeInfo existingSizeInfo = _pendingImageSizeInfo[sizeInfo.source];
final ImageSizeInfo? existingSizeInfo = _pendingImageSizeInfo[sizeInfo.source];
if (existingSizeInfo == null || existingSizeInfo.displaySizeInBytes < sizeInfo.displaySizeInBytes) {
_pendingImageSizeInfo[sizeInfo.source] = sizeInfo;
_pendingImageSizeInfo[sizeInfo.source!] = sizeInfo;
}
if (debugOnPaintImage != null) {
debugOnPaintImage(sizeInfo);
debugOnPaintImage!(sizeInfo);
}
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
_lastFrameImageSizeInfo = _pendingImageSizeInfo.values.toSet();
if (_pendingImageSizeInfo.isEmpty) {
return;
}
developer.postEvent(
'Flutter.ImageSizesForFrame',
<Object, Object>{
<String, Object>{
for (ImageSizeInfo imageSizeInfo in _pendingImageSizeInfo.values)
imageSizeInfo.source: imageSizeInfo.toJson()
imageSizeInfo.source!: imageSizeInfo.toJson()
},
);
_pendingImageSizeInfo = <String, ImageSizeInfo>{};
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show lerpDouble;
......@@ -139,16 +138,14 @@ class FractionalOffset extends Alignment {
Alignment operator -(Alignment other) {
if (other is! FractionalOffset)
return super - other;
final FractionalOffset typedOther = other as FractionalOffset;
return FractionalOffset(dx - typedOther.dx, dy - typedOther.dy);
return FractionalOffset(dx - other.dx, dy - other.dy);
}
@override
Alignment operator +(Alignment other) {
if (other is! FractionalOffset)
return super + other;
final FractionalOffset typedOther = other as FractionalOffset;
return FractionalOffset(dx + typedOther.dx, dy + typedOther.dy);
return FractionalOffset(dx + other.dx, dy + other.dy);
}
@override
......@@ -181,15 +178,15 @@ class FractionalOffset extends Alignment {
/// If either is null, this function interpolates from [FractionalOffset.center].
///
/// {@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);
if (a == null && b == null)
return 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)
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, 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)!);
}
@override
......
......@@ -2,12 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'basic_types.dart';
/// Position a child box within a container box, either above or below a target
......@@ -41,10 +38,10 @@ import 'basic_types.dart';
///
/// The arguments must not be null.
Offset positionDependentBox({
@required Size size,
@required Size childSize,
@required Offset target,
@required bool preferBelow,
required Size size,
required Size childSize,
required Offset target,
required bool preferBelow,
double verticalOffset = 0.0,
double margin = 10.0,
}) {
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:typed_data';
......@@ -23,7 +22,7 @@ import 'binding.dart';
/// [PaintingBinding.instantiateImageCodec], and therefore can be mocked in
/// tests.
Future<ui.Image> decodeImageFromList(Uint8List bytes) async {
final ui.Codec codec = await PaintingBinding.instance.instantiateImageCodec(bytes);
final ui.Codec codec = await PaintingBinding.instance!.instantiateImageCodec(bytes);
final ui.FrameInfo frameInfo = await codec.getNextFrame();
return frameInfo.image;
}
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:collection';
......@@ -153,11 +152,11 @@ class AssetImage extends AssetBundleImageProvider {
///
/// The image is obtained by calling [AssetBundle.load] on the given [bundle]
/// using the key given by [keyName].
final AssetBundle bundle;
final AssetBundle? bundle;
/// The name of the package from which the image is included. See the
/// documentation for the [AssetImage] class itself for details.
final String package;
final String? package;
// We assume the main asset is designed for a device pixel ratio of 1.0
static const double _naturalResolution = 1.0;
......@@ -171,16 +170,16 @@ class AssetImage extends AssetBundleImageProvider {
// that we resolve each future in a new call frame, and thus not in this
// build/layout/paint sequence.)
final AssetBundle chosenBundle = bundle ?? configuration.bundle ?? rootBundle;
Completer<AssetBundleImageKey> completer;
Future<AssetBundleImageKey> result;
Completer<AssetBundleImageKey>? completer;
Future<AssetBundleImageKey>? result;
chosenBundle.loadStructuredData<Map<String, List<String>>>(_kAssetManifestFileName, _manifestParser).then<void>(
(Map<String, List<String>> manifest) {
chosenBundle.loadStructuredData<Map<String, List<String>>?>(_kAssetManifestFileName, _manifestParser).then<void>(
(Map<String, List<String>>? manifest) {
final String chosenName = _chooseVariant(
keyName,
configuration,
manifest == null ? null : manifest[keyName],
);
)!;
final double chosenScale = _parseScale(chosenName);
final AssetBundleImageKey key = AssetBundleImageKey(
bundle: chosenBundle,
......@@ -200,17 +199,17 @@ class AssetImage extends AssetBundleImageProvider {
result = SynchronousFuture<AssetBundleImageKey>(key);
}
}
).catchError((dynamic error, StackTrace stack) {
).catchError((Object error, StackTrace stack) {
// We had an error. (This guarantees we weren't called synchronously.)
// Forward the error to the caller.
assert(completer != null);
assert(result == null);
completer.completeError(error, stack);
completer!.completeError(error, stack);
});
if (result != null) {
// The code above ran synchronously, and came up with an answer.
// Return the SynchronousFuture that we created above.
return result;
return result!;
}
// The code above hasn't yet run its "then" handler yet. Let's prepare a
// completer for it to use when it does run.
......@@ -218,9 +217,9 @@ class AssetImage extends AssetBundleImageProvider {
return completer.future;
}
static Future<Map<String, List<String>>> _manifestParser(String jsonData) {
static Future<Map<String, List<String>>?> _manifestParser(String? jsonData) {
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.
final Map<String, dynamic> parsedJson = json.decode(jsonData) as Map<String, dynamic>;
final Iterable<String> keys = parsedJson.keys;
......@@ -228,10 +227,10 @@ class AssetImage extends AssetBundleImageProvider {
Map<String, List<String>>.fromIterables(keys,
keys.map<List<String>>((String key) => List<String>.from(parsedJson[key] as List<dynamic>)));
// TODO(ianh): convert that data structure to the right types.
return SynchronousFuture<Map<String, List<String>>>(parsedManifest);
return SynchronousFuture<Map<String, List<String>>?>(parsedManifest);
}
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)
return main;
// TODO(ianh): Consider moving this parsing logic into _manifestParser.
......@@ -241,15 +240,15 @@ class AssetImage extends AssetBundleImageProvider {
// TODO(ianh): implement support for config.locale, config.textDirection,
// config.size, config.platform (then document this over in the Image.asset
// docs)
return _findNearest(mapping, config.devicePixelRatio);
return _findNearest(mapping, config.devicePixelRatio!);
}
// Return the value for the key in a [SplayTreeMap] nearest the provided key.
String _findNearest(SplayTreeMap<double, String> candidates, double value) {
String? _findNearest(SplayTreeMap<double, String> candidates, double value) {
if (candidates.containsKey(value))
return candidates[value];
final double lower = candidates.lastKeyBefore(value);
final double upper = candidates.firstKeyAfter(value);
return candidates[value]!;
final double? lower = candidates.lastKeyBefore(value);
final double? upper = candidates.firstKeyAfter(value);
if (lower == null)
return candidates[upper];
if (upper == null)
......@@ -273,9 +272,9 @@ class AssetImage extends AssetBundleImageProvider {
directoryPath = assetUri.pathSegments[assetUri.pathSegments.length - 2];
}
final Match match = _extractRatioRegExp.firstMatch(directoryPath);
final Match? match = _extractRatioRegExp.firstMatch(directoryPath);
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
}
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:typed_data';
......@@ -22,7 +21,7 @@ class MatrixUtils {
/// nothing but a 2D translation.
///
/// Otherwise, returns null.
static Offset getAsTranslation(Matrix4 transform) {
static Offset? getAsTranslation(Matrix4 transform) {
assert(transform != null);
final Float64List values = transform.storage;
// Values are stored in column-major order.
......@@ -49,7 +48,7 @@ class MatrixUtils {
/// scale, if the matrix is nothing but a symmetric 2D scale transform.
///
/// Otherwise, returns null.
static double getAsScale(Matrix4 transform) {
static double? getAsScale(Matrix4 transform) {
assert(transform != null);
final Float64List values = transform.storage;
// Values are stored in column-major order.
......@@ -75,12 +74,12 @@ class MatrixUtils {
/// Returns true if the given matrices are exactly equal, and false
/// 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))
return true;
assert(a != null || b != null);
if (a == null)
return isIdentity(b);
return isIdentity(b!);
if (b == null)
return isIdentity(a);
assert(a != null && b != null);
......@@ -165,8 +164,6 @@ class MatrixUtils {
storage[7] == 0.0 &&
storage[15] == 1.0;
_minMax ??= Float64List(4);
_accumulate(storage, rect.left, rect.top, true, isAffine);
_accumulate(storage, rect.right, rect.top, false, isAffine);
_accumulate(storage, rect.left, rect.bottom, false, isAffine);
......@@ -175,7 +172,7 @@ class MatrixUtils {
return Rect.fromLTRB(_minMax[0], _minMax[1], _minMax[2], _minMax[3]);
}
static Float64List _minMax;
static late final Float64List _minMax = Float64List(4);
static void _accumulate(Float64List m, double x, double y, bool first, bool isAffine) {
final double w = isAffine ? 1.0 : 1.0 / (m[3] * x + m[7] * y + m[15]);
final double tx = (m[0] * x + m[4] * y + m[12]) * w;
......@@ -485,8 +482,8 @@ class MatrixUtils {
/// almost always possible to end up seeing the inner side of the cylinder
/// or the back side of the transformed plane before π / 2 when perspective > 0.
static Matrix4 createCylindricalProjectionTransform({
@required double radius,
@required double angle,
required double radius,
required double angle,
double perspective = 0.001,
Axis orientation = Axis.vertical,
}) {
......@@ -541,7 +538,7 @@ class MatrixUtils {
/// useful for [TransformProperty].
///
/// 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)
return const <String>['null'];
return <String>[
......@@ -559,9 +556,9 @@ class TransformProperty extends DiagnosticsProperty<Matrix4> {
/// The [showName] and [level] arguments must not be null.
TransformProperty(
String name,
Matrix4 value, {
Matrix4? value, {
bool showName = true,
Object defaultValue = kNoDefaultValue,
Object? defaultValue = kNoDefaultValue,
DiagnosticLevel level = DiagnosticLevel.info,
}) : assert(showName != null),
assert(level != null),
......@@ -574,15 +571,15 @@ class TransformProperty extends DiagnosticsProperty<Matrix4> {
);
@override
String valueToString({ TextTreeConfiguration parentConfiguration }) {
String valueToString({ TextTreeConfiguration? parentConfiguration }) {
if (parentConfiguration != null && !parentConfiguration.lineBreakProperties) {
// Format the value on a single line to be compatible with the parent's
// style.
final List<String> values = <String>[
'${debugFormatDouble(value.entry(0, 0))},${debugFormatDouble(value.entry(0, 1))},${debugFormatDouble(value.entry(0, 2))},${debugFormatDouble(value.entry(0, 3))}',
'${debugFormatDouble(value.entry(1, 0))},${debugFormatDouble(value.entry(1, 1))},${debugFormatDouble(value.entry(1, 2))},${debugFormatDouble(value.entry(1, 3))}',
'${debugFormatDouble(value.entry(2, 0))},${debugFormatDouble(value.entry(2, 1))},${debugFormatDouble(value.entry(2, 2))},${debugFormatDouble(value.entry(2, 3))}',
'${debugFormatDouble(value.entry(3, 0))},${debugFormatDouble(value.entry(3, 1))},${debugFormatDouble(value.entry(3, 2))},${debugFormatDouble(value.entry(3, 3))}',
'${debugFormatDouble(value!.entry(0, 0))},${debugFormatDouble(value!.entry(0, 1))},${debugFormatDouble(value!.entry(0, 2))},${debugFormatDouble(value!.entry(0, 3))}',
'${debugFormatDouble(value!.entry(1, 0))},${debugFormatDouble(value!.entry(1, 1))},${debugFormatDouble(value!.entry(1, 2))},${debugFormatDouble(value!.entry(1, 3))}',
'${debugFormatDouble(value!.entry(2, 0))},${debugFormatDouble(value!.entry(2, 1))},${debugFormatDouble(value!.entry(2, 2))},${debugFormatDouble(value!.entry(2, 3))}',
'${debugFormatDouble(value!.entry(3, 0))},${debugFormatDouble(value!.entry(3, 1))},${debugFormatDouble(value!.entry(3, 2))},${debugFormatDouble(value!.entry(3, 3))}',
];
return '[${values.join('; ')}]';
}
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show lerpDouble;
......@@ -54,12 +53,12 @@ class RoundedRectangleBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null);
if (a is RoundedRectangleBorder) {
return RoundedRectangleBorder(
side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
);
}
if (a is CircleBorder) {
......@@ -73,12 +72,12 @@ class RoundedRectangleBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
assert(t != null);
if (b is RoundedRectangleBorder) {
return RoundedRectangleBorder(
side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
);
}
if (b is CircleBorder) {
......@@ -94,7 +93,7 @@ class RoundedRectangleBorder extends OutlinedBorder {
/// Returns a copy of this RoundedRectangleBorder with the given fields
/// replaced with the new values.
@override
RoundedRectangleBorder copyWith({ BorderSide side, BorderRadius borderRadius }) {
RoundedRectangleBorder copyWith({ BorderSide? side, BorderRadius? borderRadius }) {
return RoundedRectangleBorder(
side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius,
......@@ -102,19 +101,19 @@ class RoundedRectangleBorder extends OutlinedBorder {
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(borderRadius.resolve(textDirection).toRRect(rect).deflate(side.width));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
switch (side.style) {
case BorderStyle.none:
break;
......@@ -154,7 +153,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
const _RoundedRectangleToCircleBorder({
BorderSide side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
@required this.circleness,
required this.circleness,
}) : assert(side != null),
assert(borderRadius != null),
assert(circleness != null),
......@@ -179,12 +178,12 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null);
if (a is RoundedRectangleBorder) {
return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
circleness: circleness * t,
);
}
......@@ -198,19 +197,19 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
if (a is _RoundedRectangleToCircleBorder) {
return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t),
circleness: ui.lerpDouble(a.circleness, circleness, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
circleness: ui.lerpDouble(a.circleness, circleness, t)!,
);
}
return super.lerpFrom(a, t);
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is RoundedRectangleBorder) {
return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
circleness: circleness * (1.0 - t),
);
}
......@@ -224,8 +223,8 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
if (b is _RoundedRectangleToCircleBorder) {
return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t),
circleness: ui.lerpDouble(circleness, b.circleness, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
circleness: ui.lerpDouble(circleness, b.circleness, t)!,
);
}
return super.lerpTo(b, t);
......@@ -253,7 +252,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
}
}
BorderRadius _adjustBorderRadius(Rect rect, TextDirection textDirection) {
BorderRadius? _adjustBorderRadius(Rect rect, TextDirection? textDirection) {
final BorderRadius resolvedRadius = borderRadius.resolve(textDirection);
if (circleness == 0.0)
return resolvedRadius;
......@@ -261,19 +260,19 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(_adjustBorderRadius(rect, textDirection).toRRect(_adjustRect(rect)).deflate(side.width));
..addRRect(_adjustBorderRadius(rect, textDirection)!.toRRect(_adjustRect(rect)).deflate(side.width));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(_adjustBorderRadius(rect, textDirection).toRRect(_adjustRect(rect)));
..addRRect(_adjustBorderRadius(rect, textDirection)!.toRRect(_adjustRect(rect)));
}
@override
_RoundedRectangleToCircleBorder copyWith({ BorderSide side, BorderRadius borderRadius, double circleness }) {
_RoundedRectangleToCircleBorder copyWith({ BorderSide? side, BorderRadius? borderRadius, double? circleness }) {
return _RoundedRectangleToCircleBorder(
side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius,
......@@ -282,16 +281,16 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
switch (side.style) {
case BorderStyle.none:
break;
case BorderStyle.solid:
final double width = side.width;
if (width == 0.0) {
canvas.drawRRect(_adjustBorderRadius(rect, textDirection).toRRect(_adjustRect(rect)), side.toPaint());
canvas.drawRRect(_adjustBorderRadius(rect, textDirection)!.toRRect(_adjustRect(rect)), side.toPaint());
} else {
final RRect outer = _adjustBorderRadius(rect, textDirection).toRRect(_adjustRect(rect));
final RRect outer = _adjustBorderRadius(rect, textDirection)!.toRRect(_adjustRect(rect));
final RRect inner = outer.deflate(width);
final Paint paint = Paint()
..color = side.color;
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
......@@ -77,7 +76,7 @@ class ShapeDecoration extends Decoration {
this.image,
this.gradient,
this.shadows,
@required this.shape,
required this.shape,
}) : assert(!(color != null && gradient != null)),
assert(shape != null);
......@@ -97,18 +96,18 @@ class ShapeDecoration extends Decoration {
switch (source.shape) {
case BoxShape.circle:
if (source.border != null) {
assert(source.border.isUniform);
shape = CircleBorder(side: source.border.top);
assert(source.border!.isUniform);
shape = CircleBorder(side: source.border!.top);
} else {
shape = const CircleBorder();
}
break;
case BoxShape.rectangle:
if (source.borderRadius != null) {
assert(source.border == null || source.border.isUniform);
assert(source.border == null || source.border!.isUniform);
shape = RoundedRectangleBorder(
side: source.border?.top ?? BorderSide.none,
borderRadius: source.borderRadius,
borderRadius: source.borderRadius!,
);
} else {
shape = source.border ?? const Border();
......@@ -134,19 +133,19 @@ class ShapeDecoration extends Decoration {
/// The color is under the [image].
///
/// If a [gradient] is specified, [color] must be null.
final Color color;
final Color? color;
/// A gradient to use when filling the shape.
///
/// The gradient is under the [image].
///
/// If a [color] is specified, [gradient] must be null.
final Gradient gradient;
final Gradient? gradient;
/// An image to paint inside the shape (clipped to its outline).
///
/// The image is drawn over the [color] or [gradient].
final DecorationImage image;
final DecorationImage? image;
/// A list of shadows cast by the [shape].
///
......@@ -155,7 +154,7 @@ class ShapeDecoration extends Decoration {
/// * [kElevationToShadow], for some predefined shadows used in Material
/// Design.
/// * [PhysicalModel], a widget for showing shadows.
final List<BoxShadow> shadows;
final List<BoxShadow>? shadows;
/// The shape to fill the [color], [gradient], and [image] into and to cast as
/// the [shadows].
......@@ -191,23 +190,23 @@ class ShapeDecoration extends Decoration {
bool get isComplex => shadows != null;
@override
ShapeDecoration lerpFrom(Decoration a, double t) {
ShapeDecoration? lerpFrom(Decoration? a, double t) {
if (a is BoxDecoration) {
return ShapeDecoration.lerp(ShapeDecoration.fromBoxDecoration(a), this, t);
} else if (a == null || a is ShapeDecoration) {
return ShapeDecoration.lerp(a as ShapeDecoration, this, t);
}
return super.lerpFrom(a, t) as ShapeDecoration;
return super.lerpFrom(a, t) as ShapeDecoration?;
}
@override
ShapeDecoration lerpTo(Decoration b, double t) {
ShapeDecoration? lerpTo(Decoration? b, double t) {
if (b is BoxDecoration) {
return ShapeDecoration.lerp(this, ShapeDecoration.fromBoxDecoration(b), t);
} else if (b == null || b is ShapeDecoration) {
return ShapeDecoration.lerp(this, b as ShapeDecoration, t);
}
return super.lerpTo(b, t) as ShapeDecoration;
return super.lerpTo(b, t) as ShapeDecoration?;
}
/// Linearly interpolate between two shapes.
......@@ -228,7 +227,7 @@ class ShapeDecoration extends Decoration {
/// * [lerpFrom] and [lerpTo], which are used to implement [Decoration.lerp]
/// and which use [ShapeDecoration.lerp] when interpolating two
/// [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);
if (a == null && b == null)
return null;
......@@ -241,9 +240,9 @@ class ShapeDecoration extends Decoration {
return ShapeDecoration(
color: Color.lerp(a?.color, b?.color, t),
gradient: Gradient.lerp(a?.gradient, b?.gradient, 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
shadows: BoxShadow.lerpList(a?.shadows, b?.shadows, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t)!,
);
}
......@@ -284,14 +283,14 @@ class ShapeDecoration extends Decoration {
}
@override
bool hitTest(Size size, Offset position, { TextDirection textDirection }) {
bool hitTest(Size size, Offset position, { TextDirection? textDirection }) {
return shape.getOuterPath(Offset.zero & size, textDirection: textDirection).contains(position);
}
@override
_ShapeDecorationPainter createBoxPainter([ VoidCallback onChanged ]) {
_ShapeDecorationPainter createBoxPainter([ VoidCallback? onChanged ]) {
assert(onChanged != null || image == null);
return _ShapeDecorationPainter(this, onChanged);
return _ShapeDecorationPainter(this, onChanged!);
}
}
......@@ -303,16 +302,19 @@ class _ShapeDecorationPainter extends BoxPainter {
final ShapeDecoration _decoration;
Rect _lastRect;
TextDirection _lastTextDirection;
Path _outerPath;
Path _innerPath;
Paint _interiorPaint;
int _shadowCount;
List<Path> _shadowPaths;
List<Paint> _shadowPaints;
Rect? _lastRect;
TextDirection? _lastTextDirection;
late Path _outerPath;
Path? _innerPath;
Paint? _interiorPaint;
int? _shadowCount;
late List<Path> _shadowPaths;
late List<Paint> _shadowPaints;
void _precache(Rect rect, TextDirection textDirection) {
@override
VoidCallback get onChanged => super.onChanged!;
void _precache(Rect rect, TextDirection? textDirection) {
assert(rect != null);
if (rect == _lastRect && textDirection == _lastTextDirection)
return;
......@@ -324,22 +326,22 @@ class _ShapeDecorationPainter extends BoxPainter {
if (_interiorPaint == null && (_decoration.color != null || _decoration.gradient != null)) {
_interiorPaint = Paint();
if (_decoration.color != null)
_interiorPaint.color = _decoration.color;
_interiorPaint!.color = _decoration.color!;
}
if (_decoration.gradient != null)
_interiorPaint.shader = _decoration.gradient.createShader(rect);
_interiorPaint!.shader = _decoration.gradient!.createShader(rect);
if (_decoration.shadows != null) {
if (_shadowCount == null) {
_shadowCount = _decoration.shadows.length;
_shadowPaths = List<Path>(_shadowCount);
_shadowPaints = List<Paint>(_shadowCount);
for (int index = 0; index < _shadowCount; index += 1)
_shadowPaints[index] = _decoration.shadows[index].toPaint();
}
for (int index = 0; index < _shadowCount; index += 1) {
final BoxShadow shadow = _decoration.shadows[index];
_shadowPaths[index] = _decoration.shape.getOuterPath(rect.shift(shadow.offset).inflate(shadow.spreadRadius), textDirection: textDirection);
_shadowCount = _decoration.shadows!.length;
_shadowPaints = <Paint>[
..._decoration.shadows!.map((BoxShadow shadow) => shadow.toPaint()),
];
}
_shadowPaths = <Path>[
..._decoration.shadows!.map((BoxShadow shadow) {
return _decoration.shape.getOuterPath(rect.shift(shadow.offset).inflate(shadow.spreadRadius), textDirection: textDirection);
}),
];
}
if (_interiorPaint != null || _shadowCount != null)
_outerPath = _decoration.shape.getOuterPath(rect, textDirection: textDirection);
......@@ -352,22 +354,22 @@ class _ShapeDecorationPainter extends BoxPainter {
void _paintShadows(Canvas canvas) {
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]);
}
}
void _paintInterior(Canvas canvas) {
if (_interiorPaint != null)
canvas.drawPath(_outerPath, _interiorPaint);
canvas.drawPath(_outerPath, _interiorPaint!);
}
DecorationImagePainter _imagePainter;
DecorationImagePainter? _imagePainter;
void _paintImage(Canvas canvas, ImageConfiguration configuration) {
if (_decoration.image == null)
return;
_imagePainter ??= _decoration.image.createPainter(onChanged);
_imagePainter.paint(canvas, _lastRect, _innerPath, configuration);
_imagePainter ??= _decoration.image!.createPainter(onChanged);
_imagePainter!.paint(canvas, _lastRect!, _innerPath, configuration);
}
@override
......@@ -380,8 +382,8 @@ class _ShapeDecorationPainter extends BoxPainter {
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration != null);
assert(configuration.size != null);
final Rect rect = offset & configuration.size;
final TextDirection textDirection = configuration.textDirection;
final Rect rect = offset & configuration.size!;
final TextDirection? textDirection = configuration.textDirection;
_precache(rect, textDirection);
_paintShadows(canvas);
_paintInterior(canvas);
......
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