forked from firka/flutter
migrate part of painting to nullsafety (#63495)
This commit is contained in:
committed by
GitHub
parent
72619b8642
commit
be868397be
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user