Unverified Commit 96f36450 authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

migrate painting to nullsafety (#63703)

* migrate painting to nullsafety

* address review comments
parent 48b9c3d3
......@@ -2,8 +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
/// The Flutter painting library.
///
/// To use, import `package:flutter/painting.dart`.
......
......@@ -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;
import 'dart:typed_data';
......@@ -107,7 +106,7 @@ class FlutterLogoDecoration extends Decoration {
/// See also:
///
/// * [Decoration.lerp], which interpolates between arbitrary decorations.
static FlutterLogoDecoration lerp(FlutterLogoDecoration a, FlutterLogoDecoration b, double t) {
static FlutterLogoDecoration? lerp(FlutterLogoDecoration? a, FlutterLogoDecoration? b, double t) {
assert(t != null);
assert(a == null || a.debugAssertIsValid());
assert(b == null || b.debugAssertIsValid());
......@@ -115,7 +114,7 @@ class FlutterLogoDecoration extends Decoration {
return null;
if (a == null) {
return FlutterLogoDecoration._(
b.textColor,
b!.textColor,
b.style,
b.margin * t,
b._position,
......@@ -136,40 +135,40 @@ class FlutterLogoDecoration extends Decoration {
if (t == 1.0)
return b;
return FlutterLogoDecoration._(
Color.lerp(a.textColor, b.textColor, t),
Color.lerp(a.textColor, b.textColor, t)!,
t < 0.5 ? a.style : b.style,
EdgeInsets.lerp(a.margin, b.margin, t),
EdgeInsets.lerp(a.margin, b.margin, t)!,
a._position + (b._position - a._position) * t,
(a._opacity + (b._opacity - a._opacity) * t).clamp(0.0, 1.0) as double,
);
}
@override
FlutterLogoDecoration lerpFrom(Decoration a, double t) {
FlutterLogoDecoration? lerpFrom(Decoration? a, double t) {
assert(debugAssertIsValid());
if (a == null || a is FlutterLogoDecoration) {
assert(a == null || a.debugAssertIsValid());
return FlutterLogoDecoration.lerp(a as FlutterLogoDecoration, this, t);
}
return super.lerpFrom(a, t) as FlutterLogoDecoration;
return super.lerpFrom(a, t) as FlutterLogoDecoration?;
}
@override
FlutterLogoDecoration lerpTo(Decoration b, double t) {
FlutterLogoDecoration? lerpTo(Decoration? b, double t) {
assert(debugAssertIsValid());
if (b == null || b is FlutterLogoDecoration) {
assert(b == null || b.debugAssertIsValid());
return FlutterLogoDecoration.lerp(this, b as FlutterLogoDecoration, t);
}
return super.lerpTo(b, t) as FlutterLogoDecoration;
return super.lerpTo(b, t) as FlutterLogoDecoration?;
}
@override
// TODO(ianh): better hit testing
bool hitTest(Size size, Offset position, { TextDirection textDirection }) => true;
bool hitTest(Size size, Offset position, { TextDirection? textDirection }) => true;
@override
BoxPainter createBoxPainter([ VoidCallback onChanged ]) {
BoxPainter createBoxPainter([ VoidCallback? onChanged ]) {
assert(debugAssertIsValid());
return _FlutterLogoPainter(this);
}
......@@ -218,8 +217,8 @@ class _FlutterLogoPainter extends BoxPainter {
final FlutterLogoDecoration _config;
// these are configured assuming a font size of 100.0.
TextPainter _textPainter;
Rect _textBoundingRect;
late TextPainter _textPainter;
late Rect _textBoundingRect;
void _prepareText() {
const String kLabel = 'Flutter';
......@@ -323,7 +322,7 @@ class _FlutterLogoPainter extends BoxPainter {
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
offset += _config.margin.topLeft;
final Size canvasSize = _config.margin.deflateSize(configuration.size);
final Size canvasSize = _config.margin.deflateSize(configuration.size!);
if (canvasSize.isEmpty)
return;
Size logoSize;
......@@ -365,7 +364,7 @@ class _FlutterLogoPainter extends BoxPainter {
// only the mark
logoTargetSquare = centerSquare;
}
final Rect logoSquare = Rect.lerp(centerSquare, logoTargetSquare, _config._position.abs());
final Rect logoSquare = Rect.lerp(centerSquare, logoTargetSquare, _config._position.abs())!;
if (_config._opacity < 1.0) {
canvas.saveLayer(
......@@ -388,7 +387,7 @@ class _FlutterLogoPainter extends BoxPainter {
final double initialLeftTextPosition = // position of text when just starting the animation
rect.width / 2.0 - _textBoundingRect.width * scale;
final Offset textOffset = Offset(
rect.left + ui.lerpDouble(initialLeftTextPosition, finalLeftTextPosition, _config._position),
rect.left + ui.lerpDouble(initialLeftTextPosition, finalLeftTextPosition, _config._position)!,
rect.top + (rect.height - _textBoundingRect.height * scale) / 2.0,
);
canvas.save();
......
......@@ -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 ParagraphBuilder;
......@@ -71,10 +70,10 @@ class InlineSpanSemanticsInformation {
final String text;
/// The semanticsLabel, if any.
final String semanticsLabel;
final String? semanticsLabel;
/// The gesture recognizer, if any, for this span.
final GestureRecognizer recognizer;
final GestureRecognizer? recognizer;
/// Whether this is for a placeholder span.
final bool isPlaceholder;
......@@ -155,7 +154,7 @@ abstract class InlineSpan extends DiagnosticableTree {
///
/// The [style] is also applied to any child spans when this is an instance
/// of [TextSpan].
final TextStyle style;
final TextStyle? style;
// TODO(garyq): Remove the deprecated visitTextSpan, text, and children.
/// Returns the text associated with this span if this is an instance of [TextSpan],
......@@ -164,7 +163,7 @@ abstract class InlineSpan extends DiagnosticableTree {
'InlineSpan does not innately have text. Use TextSpan.text instead. '
'This feature was deprecated after v1.7.3.'
)
String get text => null;
String? get text => null;
// TODO(garyq): Remove the deprecated visitTextSpan, text, and children.
/// Returns the [InlineSpan] children list associated with this span if this is an
......@@ -173,7 +172,7 @@ abstract class InlineSpan extends DiagnosticableTree {
'InlineSpan does not innately have children. Use TextSpan.children instead. '
'This feature was deprecated after v1.7.3.'
)
List<InlineSpan> get children => null;
List<InlineSpan>? get children => null;
/// Returns the [GestureRecognizer] associated with this span if this is an
/// instance of [TextSpan], otherwise returns null.
......@@ -181,7 +180,7 @@ abstract class InlineSpan extends DiagnosticableTree {
'InlineSpan does not innately have a recognizer. Use TextSpan.recognizer instead. '
'This feature was deprecated after v1.7.3.'
)
GestureRecognizer get recognizer => null;
GestureRecognizer? get recognizer => null;
/// Apply the properties of this object to the given [ParagraphBuilder], from
/// which a [Paragraph] can be obtained.
......@@ -195,7 +194,7 @@ abstract class InlineSpan extends DiagnosticableTree {
/// in the same order as defined in the [InlineSpan] tree.
///
/// [Paragraph] objects can be drawn on [Canvas] objects.
void build(ui.ParagraphBuilder builder, { double textScaleFactor = 1.0, List<PlaceholderDimensions> dimensions });
void build(ui.ParagraphBuilder builder, { double textScaleFactor = 1.0, List<PlaceholderDimensions>? dimensions });
// TODO(garyq): Remove the deprecated visitTextSpan, text, and children.
/// Walks this [TextSpan] and any descendants in pre-order and calls `visitor`
......@@ -217,10 +216,10 @@ abstract class InlineSpan extends DiagnosticableTree {
bool visitChildren(InlineSpanVisitor visitor);
/// Returns the [InlineSpan] that contains the given position in the text.
InlineSpan getSpanForPosition(TextPosition position) {
InlineSpan? getSpanForPosition(TextPosition position) {
assert(debugAssertIsValid());
final Accumulator offset = Accumulator();
InlineSpan result;
InlineSpan? result;
visitChildren((InlineSpan span) {
result = span.getSpanForPositionVisitor(position, offset);
return result == null;
......@@ -237,7 +236,7 @@ abstract class InlineSpan extends DiagnosticableTree {
///
/// This method should not be directly called. Use [getSpanForPosition] instead.
@protected
InlineSpan getSpanForPositionVisitor(TextPosition position, Accumulator offset);
InlineSpan? getSpanForPositionVisitor(TextPosition position, Accumulator offset);
/// Flattens the [InlineSpan] tree into a single string.
///
......@@ -297,11 +296,11 @@ abstract class InlineSpan extends DiagnosticableTree {
/// This only accounts for the [TextSpan.text] values and ignores [PlaceholderSpan]s.
///
/// Returns null if the `index` is out of bounds.
int codeUnitAt(int index) {
int? codeUnitAt(int index) {
if (index < 0)
return null;
final Accumulator offset = Accumulator();
int result;
int? result;
visitChildren((InlineSpan span) {
result = span.codeUnitAtVisitor(index, offset);
return result == null;
......@@ -318,7 +317,7 @@ abstract class InlineSpan extends DiagnosticableTree {
///
/// This method should not be directly called. Use [codeUnitAt] instead.
@protected
int codeUnitAtVisitor(int index, Accumulator offset);
int? codeUnitAtVisitor(int index, Accumulator offset);
/// Populates the `semanticsOffsets` and `semanticsElements` with the appropriate data
/// to be able to construct a [SemanticsNode].
......@@ -375,7 +374,7 @@ abstract class InlineSpan extends DiagnosticableTree {
properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.whitespace;
if (style != null) {
style.debugFillProperties(properties);
style!.debugFillProperties(properties);
}
}
}
......@@ -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;
......@@ -30,7 +29,7 @@ abstract class NotchedShape {
///
/// The `guest` is the bounding rectangle of the shape for which a notch will
/// be made. It is null when there is no guest.
Path getOuterPath(Rect host, Rect guest);
Path getOuterPath(Rect host, Rect? guest);
}
/// A rectangle with a smooth circular notch.
......@@ -57,7 +56,7 @@ class CircularNotchedRectangle extends NotchedShape {
/// the guest circle.
// TODO(amirh): add an example diagram here.
@override
Path getOuterPath(Rect host, Rect guest) {
Path getOuterPath(Rect host, Rect? guest) {
if (guest == null || !host.overlaps(guest))
return Path()..addRect(host);
......@@ -86,7 +85,7 @@ class CircularNotchedRectangle extends NotchedShape {
final double p2yA = math.sqrt(r * r - p2xA * p2xA);
final double p2yB = math.sqrt(r * r - p2xB * p2xB);
final List<Offset> p = List<Offset>(6);
final List<Offset?> p = List<Offset?>.filled(6, null, growable: false);
// p0, p1, and p2 are the control points for segment A.
p[0] = Offset(a - s1, b);
......@@ -96,24 +95,24 @@ class CircularNotchedRectangle extends NotchedShape {
// p3, p4, and p5 are the control points for segment B, which is a mirror
// of segment A around the y axis.
p[3] = Offset(-1.0 * p[2].dx, p[2].dy);
p[4] = Offset(-1.0 * p[1].dx, p[1].dy);
p[5] = Offset(-1.0 * p[0].dx, p[0].dy);
p[3] = Offset(-1.0 * p[2]!.dx, p[2]!.dy);
p[4] = Offset(-1.0 * p[1]!.dx, p[1]!.dy);
p[5] = Offset(-1.0 * p[0]!.dx, p[0]!.dy);
// translate all points back to the absolute coordinate system.
for (int i = 0; i < p.length; i += 1)
p[i] += guest.center;
p[i] = p[i]! + guest.center;
return Path()
..moveTo(host.left, host.top)
..lineTo(p[0].dx, p[0].dy)
..quadraticBezierTo(p[1].dx, p[1].dy, p[2].dx, p[2].dy)
..lineTo(p[0]!.dx, p[0]!.dy)
..quadraticBezierTo(p[1]!.dx, p[1]!.dy, p[2]!.dx, p[2]!.dy)
..arcToPoint(
p[3],
p[3]!,
radius: Radius.circular(notchRadius),
clockwise: false,
)
..quadraticBezierTo(p[4].dx, p[4].dy, p[5].dx, p[5].dy)
..quadraticBezierTo(p[4]!.dx, p[4]!.dy, p[5]!.dx, p[5]!.dy)
..lineTo(host.right, host.top)
..lineTo(host.right, host.bottom)
..lineTo(host.left, host.bottom)
......@@ -149,16 +148,16 @@ class AutomaticNotchedShape extends NotchedShape {
/// is available to [NotchedShape]s.
///
/// If this is null, [getOuterPath] ignores the guest rectangle.
final ShapeBorder guest;
final ShapeBorder? guest;
@override
Path getOuterPath(Rect hostRect, Rect guestRect) { // ignore: avoid_renaming_method_parameters, the
Path getOuterPath(Rect hostRect, Rect? guestRect) { // ignore: avoid_renaming_method_parameters, the
// parameters are renamed over the baseclass because they would clash
// with properties of this object, and the use of all four of them in
// the code below is really confusing if they have the same names.
final Path hostPath = host.getOuterPath(hostRect);
if (guest != null && guestRect != null) {
final Path guestPath = guest.getOuterPath(guestRect);
final Path guestPath = guest!.getOuterPath(guestRect);
return Path.combine(PathOperation.difference, hostPath, guestPath);
}
return hostPath;
......
......@@ -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;
......
......@@ -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 PlaceholderAlignment;
......@@ -39,7 +38,7 @@ abstract class PlaceholderSpan extends InlineSpan {
const PlaceholderSpan({
this.alignment = ui.PlaceholderAlignment.bottom,
this.baseline,
TextStyle style,
TextStyle? style,
}) : super(style: style,);
/// How the placeholder aligns vertically with the text.
......@@ -51,7 +50,7 @@ abstract class PlaceholderSpan extends InlineSpan {
/// [ui.PlaceholderAlignment.aboveBaseline], and [ui.PlaceholderAlignment.belowBaseline].
///
/// This is ignored when using other alignment modes.
final TextBaseline baseline;
final TextBaseline? baseline;
/// [PlaceholderSpan]s are flattened to a `0xFFFC` object replacement character in the
/// plain text representation when `includePlaceholders` is true.
......
......@@ -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;
......@@ -41,7 +40,7 @@ class StadiumBorder extends OutlinedBorder {
ShapeBorder scale(double t) => StadiumBorder(side: side.scale(t));
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null);
if (a is StadiumBorder)
return StadiumBorder(side: BorderSide.lerp(a.side, side, t));
......@@ -62,7 +61,7 @@ class StadiumBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
assert(t != null);
if (b is StadiumBorder)
return StadiumBorder(side: BorderSide.lerp(side, b.side, t));
......@@ -83,26 +82,26 @@ class StadiumBorder extends OutlinedBorder {
}
@override
StadiumBorder copyWith({ BorderSide side }) {
StadiumBorder copyWith({ BorderSide? side }) {
return StadiumBorder(side: side ?? this.side);
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
final Radius radius = Radius.circular(rect.shortestSide / 2.0);
return Path()
..addRRect(RRect.fromRectAndRadius(rect, radius).deflate(side.width));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
final Radius radius = Radius.circular(rect.shortestSide / 2.0);
return Path()
..addRRect(RRect.fromRectAndRadius(rect, radius));
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
switch (side.style) {
case BorderStyle.none:
break;
......@@ -157,7 +156,7 @@ class _StadiumToCircleBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null);
if (a is StadiumBorder) {
return _StadiumToCircleBorder(
......@@ -174,14 +173,14 @@ class _StadiumToCircleBorder extends OutlinedBorder {
if (a is _StadiumToCircleBorder) {
return _StadiumToCircleBorder(
side: BorderSide.lerp(a.side, side, t),
circleness: ui.lerpDouble(a.circleness, circleness, 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) {
assert(t != null);
if (b is StadiumBorder) {
return _StadiumToCircleBorder(
......@@ -198,7 +197,7 @@ class _StadiumToCircleBorder extends OutlinedBorder {
if (b is _StadiumToCircleBorder) {
return _StadiumToCircleBorder(
side: BorderSide.lerp(side, b.side, t),
circleness: ui.lerpDouble(circleness, b.circleness, t),
circleness: ui.lerpDouble(circleness, b.circleness, t)!,
);
}
return super.lerpTo(b, t);
......@@ -231,19 +230,19 @@ class _StadiumToCircleBorder extends OutlinedBorder {
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(_adjustBorderRadius(rect).toRRect(_adjustRect(rect)).deflate(side.width));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(_adjustBorderRadius(rect).toRRect(_adjustRect(rect)));
}
@override
_StadiumToCircleBorder copyWith({ BorderSide side, double circleness }) {
_StadiumToCircleBorder copyWith({ BorderSide? side, double? circleness }) {
return _StadiumToCircleBorder(
side: side ?? this.side,
circleness: circleness ?? this.circleness,
......@@ -251,7 +250,7 @@ class _StadiumToCircleBorder 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;
......@@ -318,7 +317,7 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null);
if (a is StadiumBorder) {
return _StadiumToRoundedRectangleBorder(
......@@ -337,15 +336,15 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
if (a is _StadiumToRoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t),
rectness: ui.lerpDouble(a.rectness, rectness, t),
borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t)!,
rectness: ui.lerpDouble(a.rectness, rectness, 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 StadiumBorder) {
return _StadiumToRoundedRectangleBorder(
......@@ -364,8 +363,8 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
if (b is _StadiumToRoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t),
rectness: ui.lerpDouble(rectness, b.rectness, t),
borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t)!,
rectness: ui.lerpDouble(rectness, b.rectness, t)!,
);
}
return super.lerpTo(b, t);
......@@ -376,23 +375,23 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
borderRadius,
BorderRadius.all(Radius.circular(rect.shortestSide / 2.0)),
1.0 - rectness,
);
)!;
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(_adjustBorderRadius(rect).toRRect(rect).deflate(side.width));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return Path()
..addRRect(_adjustBorderRadius(rect).toRRect(rect));
}
@override
_StadiumToRoundedRectangleBorder copyWith({ BorderSide side, BorderRadius borderRadius, double rectness }) {
_StadiumToRoundedRectangleBorder copyWith({ BorderSide? side, BorderRadius? borderRadius, double? rectness }) {
return _StadiumToRoundedRectangleBorder(
side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius,
......@@ -401,7 +400,7 @@ class _StadiumToRoundedRectangleBorder 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;
......
......@@ -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';
......@@ -297,8 +296,8 @@ class StrutStyle with Diagnosticable {
/// If provided, fontSize must be positive and non-zero, leading must be
/// zero or positive.
const StrutStyle({
String fontFamily,
List<String> fontFamilyFallback,
String? fontFamily,
List<String>? fontFamilyFallback,
this.fontSize,
this.height,
this.leading,
......@@ -306,13 +305,13 @@ class StrutStyle with Diagnosticable {
this.fontStyle,
this.forceStrutHeight,
this.debugLabel,
String package,
String? package,
}) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily',
_fontFamilyFallback = fontFamilyFallback,
_package = package,
assert(fontSize == null || fontSize > 0),
assert(leading == null || leading >= 0),
assert(package == null || (package != null && (fontFamily != null || fontFamilyFallback != null)));
assert(package == null || (fontFamily != null || fontFamilyFallback != null));
/// Builds a StrutStyle that contains values of the equivalent properties in
/// the provided [textStyle].
......@@ -335,20 +334,20 @@ class StrutStyle with Diagnosticable {
/// from being prepended twice.
StrutStyle.fromTextStyle(
TextStyle textStyle, {
String fontFamily,
List<String> fontFamilyFallback,
double fontSize,
double height,
String? fontFamily,
List<String>? fontFamilyFallback,
double? fontSize,
double? height,
this.leading, // TextStyle does not have an equivalent (yet).
FontWeight fontWeight,
FontStyle fontStyle,
FontWeight? fontWeight,
FontStyle? fontStyle,
this.forceStrutHeight,
String debugLabel,
String package,
String? debugLabel,
String? package,
}) : assert(textStyle != null),
assert(fontSize == null || fontSize > 0),
assert(leading == null || leading >= 0),
assert(package == null || (package != null && (fontFamily != null || fontFamilyFallback != null))),
assert(package == null || fontFamily != null || fontFamilyFallback != null),
fontFamily = fontFamily != null ? (package == null ? fontFamily : 'packages/$package/$fontFamily') : textStyle.fontFamily,
_fontFamilyFallback = fontFamilyFallback ?? textStyle.fontFamilyFallback,
height = height ?? textStyle.height,
......@@ -380,7 +379,7 @@ class StrutStyle with Diagnosticable {
/// was found, the default platform font family will be used instead. Unlike
/// [TextStyle.fontFamilyFallback], the font does not need to contain the
/// desired glyphs to match.
final String fontFamily;
final String? fontFamily;
/// The ordered list of font families to fall back on when a higher priority
/// font family cannot be found.
......@@ -401,16 +400,16 @@ class StrutStyle with Diagnosticable {
/// prefixed with 'packages/package_name/' (e.g. 'packages/cool_fonts/Roboto').
/// The package name should be provided by the `package` argument in the
/// constructor.
List<String> get fontFamilyFallback {
List<String>? get fontFamilyFallback {
if (_package != null && _fontFamilyFallback != null)
return _fontFamilyFallback.map((String family) => 'packages/$_package/$family').toList();
return _fontFamilyFallback!.map((String family) => 'packages/$_package/$family').toList();
return _fontFamilyFallback;
}
final List<String> _fontFamilyFallback;
final List<String>? _fontFamilyFallback;
// This is stored in order to prefix the fontFamilies in _fontFamilyFallback
// in the [fontFamilyFallback] getter.
final String _package;
final String? _package;
/// The size of text (in logical pixels) to use when obtaining metrics from the font.
///
......@@ -419,7 +418,7 @@ class StrutStyle with Diagnosticable {
/// [fontSize].
///
/// The default fontSize is 14 logical pixels.
final double fontSize;
final double? fontSize;
/// The multiple of [fontSize] to multiply the ascent and descent by where
/// `ascent + descent = fontSize`.
......@@ -447,17 +446,17 @@ class StrutStyle with Diagnosticable {
/// See [TextStyle.height], which works in a similar manner.
///
/// The default height is null.
final double height;
final double? height;
/// The typeface thickness to use when calculating the strut (e.g., bold).
///
/// The default fontWeight is [FontWeight.w400].
final FontWeight fontWeight;
final FontWeight? fontWeight;
/// The typeface variant to use when calculating the strut (e.g., italics).
///
/// The default fontStyle is [FontStyle.normal].
final FontStyle fontStyle;
final FontStyle? fontStyle;
/// The custom leading to apply to the strut as a multiple of [fontSize].
///
......@@ -467,7 +466,7 @@ class StrutStyle with Diagnosticable {
/// baseline.
///
/// The default leading is null, which will use the font-specified leading.
final double leading;
final double? leading;
/// Whether the strut height should be forced.
///
......@@ -486,7 +485,7 @@ class StrutStyle with Diagnosticable {
/// of the strut.
///
/// The default is false.
final bool forceStrutHeight;
final bool? forceStrutHeight;
/// A human-readable description of this strut style.
///
......@@ -494,7 +493,7 @@ class StrutStyle with Diagnosticable {
///
/// This property is not considered when comparing strut styles using `==` or
/// [compareTo], and it does not affect [hashCode].
final String debugLabel;
final String? debugLabel;
/// Describe the difference between this style and another, in terms of how
/// much damage it will make to the rendering.
......@@ -525,7 +524,7 @@ class StrutStyle with Diagnosticable {
/// [StrutStyle] shares many of the same basic properties as [TextStyle].
///
/// If the given text style is null, returns this strut style.
StrutStyle inheritFromTextStyle(TextStyle other) {
StrutStyle inheritFromTextStyle(TextStyle? other) {
if (other == null)
return this;
......@@ -580,15 +579,15 @@ class StrutStyle with Diagnosticable {
void debugFillProperties(DiagnosticPropertiesBuilder properties, { String prefix = '' }) {
super.debugFillProperties(properties);
if (debugLabel != null)
properties.add(MessageProperty('${prefix}debugLabel', debugLabel));
properties.add(MessageProperty('${prefix}debugLabel', debugLabel!));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[
StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false),
IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null),
DoubleProperty('${prefix}size', fontSize, defaultValue: null),
];
String weightDescription;
String? weightDescription;
if (fontWeight != null) {
weightDescription = 'w${fontWeight.index + 1}00';
weightDescription = 'w${fontWeight!.index + 1}00';
}
// TODO(jacobr): switch this to use enumProperty which will either cause the
// weight description to change to w600 from 600 or require existing
......
......@@ -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 ParagraphBuilder;
......@@ -70,10 +69,10 @@ class TextSpan extends InlineSpan {
const TextSpan({
this.text,
this.children,
TextStyle style,
TextStyle? style,
this.recognizer,
this.semanticsLabel,
}) : super(style: style,);
}) : super(style: style);
/// The text contained in this span.
///
......@@ -82,7 +81,7 @@ class TextSpan extends InlineSpan {
///
/// This getter does not include the contents of its children.
@override
final String text;
final String? text;
/// Additional spans to include as children.
......@@ -95,7 +94,7 @@ class TextSpan extends InlineSpan {
///
/// The list must not contain any nulls.
@override
final List<InlineSpan> children;
final List<InlineSpan>? children;
/// A gesture recognizer that will receive events that hit this span.
///
......@@ -173,7 +172,7 @@ class TextSpan extends InlineSpan {
/// ```
/// {@end-tool}
@override
final GestureRecognizer recognizer;
final GestureRecognizer? recognizer;
/// An alternative semantics label for this [TextSpan].
///
......@@ -186,7 +185,7 @@ class TextSpan extends InlineSpan {
/// ```dart
/// TextSpan(text: r'$$', semanticsLabel: 'Double dollars')
/// ```
final String semanticsLabel;
final String? semanticsLabel;
/// Apply the [style], [text], and [children] of this object to the
/// given [ParagraphBuilder], from which a [Paragraph] can be obtained.
......@@ -199,16 +198,16 @@ class TextSpan extends InlineSpan {
void build(
ui.ParagraphBuilder builder, {
double textScaleFactor = 1.0,
List<PlaceholderDimensions> dimensions,
List<PlaceholderDimensions>? dimensions,
}) {
assert(debugAssertIsValid());
final bool hasStyle = style != null;
if (hasStyle)
builder.pushStyle(style.getTextStyle(textScaleFactor: textScaleFactor));
builder.pushStyle(style!.getTextStyle(textScaleFactor: textScaleFactor));
if (text != null)
builder.addText(text);
builder.addText(text!);
if (children != null) {
for (final InlineSpan child in children) {
for (final InlineSpan child in children!) {
assert(child != null);
child.build(
builder,
......@@ -233,7 +232,7 @@ class TextSpan extends InlineSpan {
return false;
}
if (children != null) {
for (final InlineSpan child in children) {
for (final InlineSpan child in children!) {
if (!child.visitChildren(visitor))
return false;
}
......@@ -258,7 +257,7 @@ class TextSpan extends InlineSpan {
return false;
}
if (children != null) {
for (final InlineSpan child in children) {
for (final InlineSpan child in children!) {
assert(
child is TextSpan,
'visitTextSpan is deprecated. Use visitChildren to support InlineSpans',
......@@ -273,19 +272,19 @@ class TextSpan extends InlineSpan {
/// Returns the text span that contains the given position in the text.
@override
InlineSpan getSpanForPositionVisitor(TextPosition position, Accumulator offset) {
InlineSpan? getSpanForPositionVisitor(TextPosition position, Accumulator offset) {
if (text == null) {
return null;
}
final TextAffinity affinity = position.affinity;
final int targetOffset = position.offset;
final int endOffset = offset.value + text.length;
final int endOffset = offset.value + text!.length;
if (offset.value == targetOffset && affinity == TextAffinity.downstream ||
offset.value < targetOffset && targetOffset < endOffset ||
endOffset == targetOffset && affinity == TextAffinity.upstream) {
return this;
}
offset.increment(text.length);
offset.increment(text!.length);
return null;
}
......@@ -302,7 +301,7 @@ class TextSpan extends InlineSpan {
buffer.write(text);
}
if (children != null) {
for (final InlineSpan child in children) {
for (final InlineSpan child in children!) {
child.computeToPlainText(buffer,
includeSemanticsLabels: includeSemanticsLabels,
includePlaceholders: includePlaceholders,
......@@ -316,27 +315,27 @@ class TextSpan extends InlineSpan {
assert(debugAssertIsValid());
if (text != null || semanticsLabel != null) {
collector.add(InlineSpanSemanticsInformation(
text,
text!,
semanticsLabel: semanticsLabel,
recognizer: recognizer,
));
}
if (children != null) {
for (final InlineSpan child in children) {
for (final InlineSpan child in children!) {
child.computeSemanticsInformation(collector);
}
}
}
@override
int codeUnitAtVisitor(int index, Accumulator offset) {
int? codeUnitAtVisitor(int index, Accumulator offset) {
if (text == null) {
return null;
}
if (index - offset.value < text.length) {
return text.codeUnitAt(index - offset.value);
if (index - offset.value < text!.length) {
return text!.codeUnitAt(index - offset.value);
}
offset.increment(text.length);
offset.increment(text!.length);
return null;
}
......@@ -346,12 +345,12 @@ class TextSpan extends InlineSpan {
recognizer != null &&
(recognizer is TapGestureRecognizer || recognizer is LongPressGestureRecognizer)
) {
final int length = semanticsLabel?.length ?? text.length;
final int length = semanticsLabel?.length ?? text!.length;
semanticsOffsets.add(offset.value);
semanticsOffsets.add(offset.value + length);
semanticsElements.add(recognizer);
}
offset.increment(text != null ? text.length : 0);
offset.increment(text != null ? text!.length : 0);
}
/// In checked mode, throws an exception if the object is not in a valid
......@@ -366,7 +365,7 @@ class TextSpan extends InlineSpan {
bool debugAssertIsValid() {
assert(() {
if (children != null) {
for (final InlineSpan child in children) {
for (final InlineSpan child in children!) {
if (child == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('TextSpan contains a null child.'),
......@@ -399,15 +398,15 @@ class TextSpan extends InlineSpan {
RenderComparison.identical :
RenderComparison.metadata;
if (style != null) {
final RenderComparison candidate = style.compareTo(textSpan.style);
final RenderComparison candidate = style!.compareTo(textSpan.style!);
if (candidate.index > result.index)
result = candidate;
if (result == RenderComparison.layout)
return result;
}
if (children != null) {
for (int index = 0; index < children.length; index += 1) {
final RenderComparison candidate = children[index].compareTo(textSpan.children[index]);
for (int index = 0; index < children!.length; index += 1) {
final RenderComparison candidate = children![index].compareTo(textSpan.children![index]);
if (candidate.index > result.index)
result = candidate;
if (result == RenderComparison.layout)
......@@ -461,7 +460,7 @@ class TextSpan extends InlineSpan {
properties.add(DiagnosticsProperty<GestureRecognizer>(
'recognizer', recognizer,
description: recognizer?.runtimeType?.toString(),
description: recognizer?.runtimeType.toString(),
defaultValue: null,
));
......@@ -474,7 +473,7 @@ class TextSpan extends InlineSpan {
List<DiagnosticsNode> debugDescribeChildren() {
if (children == null)
return const <DiagnosticsNode>[];
return children.map<DiagnosticsNode>((InlineSpan child) {
return children!.map<DiagnosticsNode>((InlineSpan child) {
if (child != null) {
return child.toDiagnosticsNode();
} else {
......
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