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;
......@@ -106,14 +105,14 @@ class BoxDecoration extends Decoration {
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
BoxDecoration copyWith({
Color color,
DecorationImage image,
BoxBorder border,
BorderRadiusGeometry borderRadius,
List<BoxShadow> boxShadow,
Gradient gradient,
BlendMode backgroundBlendMode,
BoxShape shape,
Color? color,
DecorationImage? image,
BoxBorder? border,
BorderRadiusGeometry? borderRadius,
List<BoxShadow>? boxShadow,
Gradient? gradient,
BlendMode? backgroundBlendMode,
BoxShape? shape,
}) {
return BoxDecoration(
color: color ?? this.color,
......@@ -142,14 +141,14 @@ class BoxDecoration extends Decoration {
/// This is ignored if [gradient] is non-null.
///
/// The [color] is drawn under the [image].
final Color color;
final Color? color;
/// An image to paint above the background [color] or [gradient].
///
/// If [shape] is [BoxShape.circle] then the image is clipped to the circle's
/// boundary; if [borderRadius] is non-null then the image is clipped to the
/// given radii.
final DecorationImage image;
final DecorationImage? image;
/// A border to draw above the background [color], [gradient], or [image].
///
......@@ -161,7 +160,7 @@ class BoxDecoration extends Decoration {
/// Use [BoxBorder] objects to describe borders that should flip their left
/// and right edges based on whether the text is being read left-to-right or
/// right-to-left.
final BoxBorder border;
final BoxBorder? border;
/// If non-null, the corners of this box are rounded by this [BorderRadius].
///
......@@ -169,7 +168,7 @@ class BoxDecoration extends Decoration {
/// [BoxShape.rectangle].
///
/// {@macro flutter.painting.boxDecoration.clip}
final BorderRadiusGeometry borderRadius;
final BorderRadiusGeometry? borderRadius;
/// A list of shadows cast by this box behind the box.
///
......@@ -180,14 +179,14 @@ class BoxDecoration extends Decoration {
/// * [kElevationToShadow], for some predefined shadows used in Material
/// Design.
/// * [PhysicalModel], a widget for showing shadows.
final List<BoxShadow> boxShadow;
final List<BoxShadow>? boxShadow;
/// A gradient to use when filling the box.
///
/// If this is specified, [color] has no effect.
///
/// The [gradient] is drawn under the [image].
final Gradient gradient;
final Gradient? gradient;
/// The blend mode applied to the [color] or [gradient] background of the box.
///
......@@ -195,7 +194,7 @@ class BoxDecoration extends Decoration {
/// mode is used.
///
/// If no [color] or [gradient] is provided then the blend mode has no impact.
final BlendMode backgroundBlendMode;
final BlendMode? backgroundBlendMode;
/// The shape to fill the background [color], [gradient], and [image] into and
/// to cast as the [boxShadow].
......@@ -213,18 +212,18 @@ class BoxDecoration extends Decoration {
final BoxShape shape;
@override
EdgeInsetsGeometry get padding => border?.dimensions;
EdgeInsetsGeometry? get padding => border?.dimensions;
@override
Path getClipPath(Rect rect, TextDirection textDirection) {
Path clipPath;
Path? getClipPath(Rect rect, TextDirection textDirection) {
Path? clipPath;
switch (shape) {
case BoxShape.circle:
clipPath = Path()..addOval(rect);
break;
case BoxShape.rectangle:
if (borderRadius != null)
clipPath = Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
clipPath = Path()..addRRect(borderRadius!.resolve(textDirection).toRRect(rect));
break;
}
return clipPath;
......@@ -247,7 +246,7 @@ class BoxDecoration extends Decoration {
bool get isComplex => boxShadow != null;
@override
BoxDecoration lerpFrom(Decoration a, double t) {
BoxDecoration? lerpFrom(Decoration? a, double t) {
if (a == null)
return scale(t);
if (a is BoxDecoration)
......@@ -256,7 +255,7 @@ class BoxDecoration extends Decoration {
}
@override
BoxDecoration lerpTo(Decoration b, double t) {
BoxDecoration? lerpTo(Decoration? b, double t) {
if (b == null)
return scale(1.0 - t);
if (b is BoxDecoration)
......@@ -287,12 +286,12 @@ class BoxDecoration extends Decoration {
/// * [lerpFrom] and [lerpTo], which are used to implement [Decoration.lerp]
/// and which use [BoxDecoration.lerp] when interpolating two
/// [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);
if (a == null && b == null)
return null;
if (a == null)
return b.scale(t);
return b!.scale(t);
if (b == null)
return a.scale(1.0 - t);
if (t == 0.0)
......@@ -356,13 +355,13 @@ class BoxDecoration extends Decoration {
}
@override
bool hitTest(Size size, Offset position, { TextDirection textDirection }) {
bool hitTest(Size size, Offset position, { TextDirection? textDirection }) {
assert(shape != null);
assert((Offset.zero & size).contains(position));
switch (shape) {
case BoxShape.rectangle:
if (borderRadius != null) {
final RRect bounds = borderRadius.resolve(textDirection).toRRect(Offset.zero & size);
final RRect bounds = borderRadius!.resolve(textDirection).toRRect(Offset.zero & size);
return bounds.contains(position);
}
return true;
......@@ -372,12 +371,10 @@ class BoxDecoration extends Decoration {
final double distance = (position - center).distance;
return distance <= math.min(size.width, size.height) / 2.0;
}
assert(shape != null);
return null;
}
@override
_BoxDecorationPainter createBoxPainter([ VoidCallback onChanged ]) {
_BoxDecorationPainter createBoxPainter([ VoidCallback? onChanged ]) {
assert(onChanged != null || image == null);
return _BoxDecorationPainter(this, onChanged);
}
......@@ -385,15 +382,15 @@ class BoxDecoration extends Decoration {
/// An object that paints a [BoxDecoration] into a canvas.
class _BoxDecorationPainter extends BoxPainter {
_BoxDecorationPainter(this._decoration, VoidCallback onChanged)
_BoxDecorationPainter(this._decoration, VoidCallback? onChanged)
: assert(_decoration != null),
super(onChanged);
final BoxDecoration _decoration;
Paint _cachedBackgroundPaint;
Rect _rectForCachedBackgroundPaint;
Paint _getBackgroundPaint(Rect rect, TextDirection textDirection) {
Paint? _cachedBackgroundPaint;
Rect? _rectForCachedBackgroundPaint;
Paint _getBackgroundPaint(Rect rect, TextDirection? textDirection) {
assert(rect != null);
assert(_decoration.gradient != null || _rectForCachedBackgroundPaint == null);
......@@ -401,20 +398,20 @@ class _BoxDecorationPainter extends BoxPainter {
(_decoration.gradient != null && _rectForCachedBackgroundPaint != rect)) {
final Paint paint = Paint();
if (_decoration.backgroundBlendMode != null)
paint.blendMode = _decoration.backgroundBlendMode;
paint.blendMode = _decoration.backgroundBlendMode!;
if (_decoration.color != null)
paint.color = _decoration.color;
paint.color = _decoration.color!;
if (_decoration.gradient != null) {
paint.shader = _decoration.gradient.createShader(rect, textDirection: textDirection);
paint.shader = _decoration.gradient!.createShader(rect, textDirection: textDirection);
_rectForCachedBackgroundPaint = rect;
}
_cachedBackgroundPaint = paint;
}
return _cachedBackgroundPaint;
return _cachedBackgroundPaint!;
}
void _paintBox(Canvas canvas, Rect rect, Paint paint, TextDirection textDirection) {
void _paintBox(Canvas canvas, Rect rect, Paint paint, TextDirection? textDirection) {
switch (_decoration.shape) {
case BoxShape.circle:
assert(_decoration.borderRadius == null);
......@@ -426,43 +423,43 @@ class _BoxDecorationPainter extends BoxPainter {
if (_decoration.borderRadius == null) {
canvas.drawRect(rect, paint);
} else {
canvas.drawRRect(_decoration.borderRadius.resolve(textDirection).toRRect(rect), paint);
canvas.drawRRect(_decoration.borderRadius!.resolve(textDirection).toRRect(rect), paint);
}
break;
}
}
void _paintShadows(Canvas canvas, Rect rect, TextDirection textDirection) {
void _paintShadows(Canvas canvas, Rect rect, TextDirection? textDirection) {
if (_decoration.boxShadow == null)
return;
for (final BoxShadow boxShadow in _decoration.boxShadow) {
for (final BoxShadow boxShadow in _decoration.boxShadow!) {
final Paint paint = boxShadow.toPaint();
final Rect bounds = rect.shift(boxShadow.offset).inflate(boxShadow.spreadRadius);
_paintBox(canvas, bounds, paint, textDirection);
}
}
void _paintBackgroundColor(Canvas canvas, Rect rect, TextDirection textDirection) {
void _paintBackgroundColor(Canvas canvas, Rect rect, TextDirection? textDirection) {
if (_decoration.color != null || _decoration.gradient != null)
_paintBox(canvas, rect, _getBackgroundPaint(rect, textDirection), textDirection);
}
DecorationImagePainter _imagePainter;
DecorationImagePainter? _imagePainter;
void _paintBackgroundImage(Canvas canvas, Rect rect, ImageConfiguration configuration) {
if (_decoration.image == null)
return;
_imagePainter ??= _decoration.image.createPainter(onChanged);
Path clipPath;
_imagePainter ??= _decoration.image!.createPainter(onChanged!);
Path? clipPath;
switch (_decoration.shape) {
case BoxShape.circle:
clipPath = Path()..addOval(rect);
break;
case BoxShape.rectangle:
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;
}
_imagePainter.paint(canvas, rect, clipPath, configuration);
_imagePainter!.paint(canvas, rect, clipPath, configuration);
}
@override
......@@ -476,8 +473,8 @@ class _BoxDecorationPainter 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;
_paintShadows(canvas, rect, textDirection);
_paintBackgroundColor(canvas, rect, textDirection);
_paintBackgroundImage(canvas, rect, configuration);
......
......@@ -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:collection';
import 'dart:math' as math;
......@@ -37,7 +36,7 @@ Color _sample(List<Color> colors, List<double> stops, double t) {
return Color.lerp(
colors[index], colors[index + 1],
(t - stops[index]) / (stops[index + 1] - stops[index]),
);
)!;
}
_ColorsAndStops _interpolateColorsAndStops(
......@@ -56,7 +55,7 @@ _ColorsAndStops _interpolateColorsAndStops(
..addAll(bStops);
final List<double> interpolatedStops = stops.toList(growable: false);
final List<Color> interpolatedColors = interpolatedStops.map<Color>(
(double stop) => Color.lerp(_sample(aColors, aStops, stop), _sample(bColors, bStops, stop), t)
(double stop) => Color.lerp(_sample(aColors, aStops, stop), _sample(bColors, bStops, stop), t)!
).toList(growable: false);
return _ColorsAndStops(interpolatedColors, interpolatedStops);
}
......@@ -78,7 +77,7 @@ abstract class GradientTransform {
///
/// Implementers may return null from this method, which achieves the same
/// final effect as returning [Matrix4.identity].
Matrix4 transform(Rect bounds, {TextDirection textDirection});
Matrix4? transform(Rect bounds, {TextDirection? textDirection});
}
/// A [GradientTransform] that rotates the gradient around the center-point of
......@@ -106,7 +105,7 @@ class GradientRotation extends GradientTransform {
final double radians;
@override
Matrix4 transform(Rect bounds, {TextDirection textDirection}) {
Matrix4 transform(Rect bounds, {TextDirection? textDirection}) {
assert(bounds != null);
final double sinRadians = math.sin(radians);
final double oneMinusCosRadians = 1 - math.cos(radians);
......@@ -147,7 +146,7 @@ abstract class Gradient {
/// no other rotation or perspective transformations have been applied to the
/// [Canvas]. If null, no transformation is applied.
const Gradient({
@required this.colors,
required this.colors,
this.stops,
this.transform,
}) : assert(colors != null);
......@@ -176,17 +175,17 @@ abstract class Gradient {
///
/// If stops is null, then a set of uniformly distributed stops is implied,
/// with the first stop at 0.0 and the last stop at 1.0.
final List<double> stops;
final List<double>? stops;
/// The transform, if any, to apply to the gradient.
///
/// This transform is in addition to any other transformations applied to the
/// canvas, but does not add any transformations to the canvas.
final GradientTransform transform;
final GradientTransform? transform;
List<double> _impliedStops() {
if (stops != null)
return stops;
return stops!;
assert(colors.length >= 2, 'colors list must have at least two colors');
final double separation = 1.0 / (colors.length - 1);
return List<double>.generate(
......@@ -205,7 +204,7 @@ abstract class Gradient {
/// The shader's transform will be resolved from the [transform] of this
/// gradient.
@factory
Shader createShader(Rect rect, { TextDirection textDirection });
Shader createShader(Rect rect, { TextDirection? textDirection });
/// Returns a new gradient with its properties scaled by the given factor.
///
......@@ -242,7 +241,7 @@ abstract class Gradient {
///
/// Instead of calling this directly, use [Gradient.lerp].
@protected
Gradient lerpFrom(Gradient a, double t) {
Gradient? lerpFrom(Gradient? a, double t) {
if (a == null)
return scale(t);
return null;
......@@ -273,7 +272,7 @@ abstract class Gradient {
///
/// Instead of calling this directly, use [Gradient.lerp].
@protected
Gradient lerpTo(Gradient b, double t) {
Gradient? lerpTo(Gradient? b, double t) {
if (b == null)
return scale(1.0 - t);
return null;
......@@ -287,9 +286,9 @@ abstract class Gradient {
/// and `b` after `t == 0.5`.
///
/// {@macro dart.ui.shadow.lerp}
static Gradient lerp(Gradient a, Gradient b, double t) {
static Gradient? lerp(Gradient? a, Gradient? b, double t) {
assert(t != null);
Gradient result;
Gradient? result;
if (b != null)
result = b.lerpFrom(a, t); // if a is null, this must return non-null
if (result == null && a != null)
......@@ -299,10 +298,10 @@ abstract class Gradient {
if (a == null && b == null)
return 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);
}
Float64List _resolveTransform(Rect bounds, TextDirection textDirection) {
Float64List? _resolveTransform(Rect bounds, TextDirection? textDirection) {
return transform?.transform(bounds, textDirection: textDirection)?.storage;
}
}
......@@ -366,10 +365,10 @@ class LinearGradient extends Gradient {
const LinearGradient({
this.begin = Alignment.centerLeft,
this.end = Alignment.centerRight,
@required List<Color> colors,
List<double> stops,
required List<Color> colors,
List<double>? stops,
this.tileMode = TileMode.clamp,
GradientTransform transform,
GradientTransform? transform,
}) : assert(begin != null),
assert(end != null),
assert(tileMode != null),
......@@ -416,7 +415,7 @@ class LinearGradient extends Gradient {
final TileMode tileMode;
@override
Shader createShader(Rect rect, { TextDirection textDirection }) {
Shader createShader(Rect rect, { TextDirection? textDirection }) {
return ui.Gradient.linear(
begin.resolve(textDirection).withinRect(rect),
end.resolve(textDirection).withinRect(rect),
......@@ -433,21 +432,21 @@ class LinearGradient extends Gradient {
return LinearGradient(
begin: begin,
end: end,
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)).toList(),
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)!).toList(),
stops: stops,
tileMode: tileMode,
);
}
@override
Gradient lerpFrom(Gradient a, double t) {
Gradient? lerpFrom(Gradient? a, double t) {
if (a == null || (a is LinearGradient))
return LinearGradient.lerp(a as LinearGradient, this, t);
return super.lerpFrom(a, t);
}
@override
Gradient lerpTo(Gradient b, double t) {
Gradient? lerpTo(Gradient? b, double t) {
if (b == null || (b is LinearGradient))
return LinearGradient.lerp(this, b as LinearGradient, t);
return super.lerpTo(b, t);
......@@ -472,12 +471,12 @@ class LinearGradient extends Gradient {
///
/// Values for `t` are usually obtained from an [Animation<double>], such as
/// an [AnimationController].
static LinearGradient lerp(LinearGradient a, LinearGradient b, double t) {
static LinearGradient? lerp(LinearGradient? a, LinearGradient? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b.scale(t);
return b!.scale(t);
if (b == null)
return a.scale(1.0 - t);
final _ColorsAndStops interpolated = _interpolateColorsAndStops(
......@@ -488,8 +487,8 @@ class LinearGradient extends Gradient {
t,
);
return LinearGradient(
begin: AlignmentGeometry.lerp(a.begin, b.begin, t),
end: AlignmentGeometry.lerp(a.end, b.end, t),
begin: AlignmentGeometry.lerp(a.begin, b.begin, t)!,
end: AlignmentGeometry.lerp(a.end, b.end, t)!,
colors: interpolated.colors,
stops: interpolated.stops,
tileMode: t < 0.5 ? a.tileMode : b.tileMode, // TODO(ianh): interpolate tile mode
......@@ -596,12 +595,12 @@ class RadialGradient extends Gradient {
const RadialGradient({
this.center = Alignment.center,
this.radius = 0.5,
@required List<Color> colors,
List<double> stops,
required List<Color> colors,
List<double>? stops,
this.tileMode = TileMode.clamp,
this.focal,
this.focalRadius = 0.0,
GradientTransform transform,
GradientTransform? transform,
}) : assert(center != null),
assert(radius != null),
assert(tileMode != null),
......@@ -654,7 +653,7 @@ class RadialGradient extends Gradient {
/// If this value is specified and [focalRadius] > 0.0, care should be taken
/// to ensure that either this value or [center] will not both resolve to
/// [Offset.zero], which would fail to create a valid gradient.
final AlignmentGeometry focal;
final AlignmentGeometry? focal;
/// The radius of the focal point of gradient, as a fraction of the shortest
/// side of the paint box.
......@@ -669,13 +668,13 @@ class RadialGradient extends Gradient {
final double focalRadius;
@override
Shader createShader(Rect rect, { TextDirection textDirection }) {
Shader createShader(Rect rect, { TextDirection? textDirection }) {
return ui.Gradient.radial(
center.resolve(textDirection).withinRect(rect),
radius * rect.shortestSide,
colors, _impliedStops(), tileMode,
_resolveTransform(rect, textDirection),
focal == null ? null : focal.resolve(textDirection).withinRect(rect),
focal == null ? null : focal!.resolve(textDirection).withinRect(rect),
focalRadius * rect.shortestSide,
);
}
......@@ -689,7 +688,7 @@ class RadialGradient extends Gradient {
return RadialGradient(
center: center,
radius: radius,
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)).toList(),
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)!).toList(),
stops: stops,
tileMode: tileMode,
focal: focal,
......@@ -698,14 +697,14 @@ class RadialGradient extends Gradient {
}
@override
Gradient lerpFrom(Gradient a, double t) {
Gradient? lerpFrom(Gradient? a, double t) {
if (a == null || (a is RadialGradient))
return RadialGradient.lerp(a as RadialGradient, this, t);
return super.lerpFrom(a, t);
}
@override
Gradient lerpTo(Gradient b, double t) {
Gradient? lerpTo(Gradient? b, double t) {
if (b == null || (b is RadialGradient))
return RadialGradient.lerp(this, b as RadialGradient, t);
return super.lerpTo(b, t);
......@@ -730,12 +729,12 @@ class RadialGradient extends Gradient {
///
/// Values for `t` are usually obtained from an [Animation<double>], such as
/// an [AnimationController].
static RadialGradient lerp(RadialGradient a, RadialGradient b, double t) {
static RadialGradient? lerp(RadialGradient? a, RadialGradient? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b.scale(t);
return b!.scale(t);
if (b == null)
return a.scale(1.0 - t);
final _ColorsAndStops interpolated = _interpolateColorsAndStops(
......@@ -746,13 +745,13 @@ class RadialGradient extends Gradient {
t,
);
return RadialGradient(
center: AlignmentGeometry.lerp(a.center, b.center, t),
radius: math.max(0.0, ui.lerpDouble(a.radius, b.radius, t)),
center: AlignmentGeometry.lerp(a.center, b.center, t)!,
radius: math.max(0.0, ui.lerpDouble(a.radius, b.radius, t)!),
colors: interpolated.colors,
stops: interpolated.stops,
tileMode: t < 0.5 ? a.tileMode : b.tileMode, // TODO(ianh): interpolate tile mode
focal: AlignmentGeometry.lerp(a.focal, b.focal, t),
focalRadius: math.max(0.0, ui.lerpDouble(a.focalRadius, b.focalRadius, t)),
focalRadius: math.max(0.0, ui.lerpDouble(a.focalRadius, b.focalRadius, t)!),
);
}
......@@ -872,10 +871,10 @@ class SweepGradient extends Gradient {
this.center = Alignment.center,
this.startAngle = 0.0,
this.endAngle = math.pi * 2,
@required List<Color> colors,
List<double> stops,
required List<Color> colors,
List<double>? stops,
this.tileMode = TileMode.clamp,
GradientTransform transform,
GradientTransform? transform,
}) : assert(center != null),
assert(startAngle != null),
assert(endAngle != null),
......@@ -919,7 +918,7 @@ class SweepGradient extends Gradient {
final TileMode tileMode;
@override
Shader createShader(Rect rect, { TextDirection textDirection }) {
Shader createShader(Rect rect, { TextDirection? textDirection }) {
return ui.Gradient.sweep(
center.resolve(textDirection).withinRect(rect),
colors, _impliedStops(), tileMode,
......@@ -939,21 +938,21 @@ class SweepGradient extends Gradient {
center: center,
startAngle: startAngle,
endAngle: endAngle,
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)).toList(),
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)!).toList(),
stops: stops,
tileMode: tileMode,
);
}
@override
Gradient lerpFrom(Gradient a, double t) {
Gradient? lerpFrom(Gradient? a, double t) {
if (a == null || (a is SweepGradient))
return SweepGradient.lerp(a as SweepGradient, this, t);
return super.lerpFrom(a, t);
}
@override
Gradient lerpTo(Gradient b, double t) {
Gradient? lerpTo(Gradient? b, double t) {
if (b == null || (b is SweepGradient))
return SweepGradient.lerp(this, b as SweepGradient, t);
return super.lerpTo(b, t);
......@@ -977,12 +976,12 @@ class SweepGradient extends Gradient {
///
/// Values for `t` are usually obtained from an [Animation<double>], such as
/// an [AnimationController].
static SweepGradient lerp(SweepGradient a, SweepGradient b, double t) {
static SweepGradient? lerp(SweepGradient? a, SweepGradient? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b.scale(t);
return b!.scale(t);
if (b == null)
return a.scale(1.0 - t);
final _ColorsAndStops interpolated = _interpolateColorsAndStops(
......@@ -993,9 +992,9 @@ class SweepGradient extends Gradient {
t,
);
return SweepGradient(
center: AlignmentGeometry.lerp(a.center, b.center, t),
startAngle: math.max(0.0, ui.lerpDouble(a.startAngle, b.startAngle, t)),
endAngle: math.max(0.0, ui.lerpDouble(a.endAngle, b.endAngle, t)),
center: AlignmentGeometry.lerp(a.center, b.center, t)!,
startAngle: math.max(0.0, ui.lerpDouble(a.startAngle, b.startAngle, t)!),
endAngle: math.max(0.0, ui.lerpDouble(a.endAngle, b.endAngle, t)!),
colors: interpolated.colors,
stops: interpolated.stops,
tileMode: t < 0.5 ? a.tileMode : b.tileMode, // TODO(ianh): interpolate tile mode
......
......@@ -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