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:math' show min, max;
import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphConstraints, ParagraphStyle, PlaceholderAlignment, LineMetrics, TextHeightBehavior, BoxHeightStyle, BoxWidthStyle;
......@@ -39,8 +38,8 @@ class PlaceholderDimensions {
/// The `size` and `alignment` are required as a placeholder's dimensions
/// require at least `size` and `alignment` to be fully defined.
const PlaceholderDimensions({
@required this.size,
@required this.alignment,
required this.size,
required this.alignment,
this.baseline,
this.baselineOffset,
}) : assert(size != null),
......@@ -64,7 +63,7 @@ class PlaceholderDimensions {
/// Distance of the [baseline] from the upper edge of the placeholder.
///
/// Only used when [alignment] is [ui.PlaceholderAlignment.baseline].
final double baselineOffset;
final double? baselineOffset;
/// The [TextBaseline] to align to. Used with:
///
......@@ -72,7 +71,7 @@ class PlaceholderDimensions {
/// * [ui.PlaceholderAlignment.aboveBaseline]
/// * [ui.PlaceholderAlignment.belowBaseline]
/// * [ui.PlaceholderAlignment.middle]
final TextBaseline baseline;
final TextBaseline? baseline;
@override
String toString() {
......@@ -99,13 +98,13 @@ enum TextWidthBasis {
/// caret's size and position. This is preferred due to the expensive
/// nature of the calculation.
class _CaretMetrics {
const _CaretMetrics({this.offset, this.fullHeight});
const _CaretMetrics({required this.offset, this.fullHeight});
/// The offset of the top left corner of the caret from the top left
/// corner of the paragraph.
final Offset offset;
/// The full height of the glyph at the caret position.
final double fullHeight;
final double? fullHeight;
}
/// An object that paints a [TextSpan] tree into a [Canvas].
......@@ -135,16 +134,16 @@ class TextPainter {
///
/// The [maxLines] property, if non-null, must be greater than zero.
TextPainter({
InlineSpan text,
InlineSpan? text,
TextAlign textAlign = TextAlign.start,
TextDirection textDirection,
TextDirection? textDirection,
double textScaleFactor = 1.0,
int maxLines,
String ellipsis,
Locale locale,
StrutStyle strutStyle,
int? maxLines,
String? ellipsis,
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior textHeightBehavior,
ui.TextHeightBehavior? textHeightBehavior,
}) : assert(text == null || text.debugAssertIsValid()),
assert(textAlign != null),
assert(textScaleFactor != null),
......@@ -161,7 +160,7 @@ class TextPainter {
_textWidthBasis = textWidthBasis,
_textHeightBehavior = textHeightBehavior;
ui.Paragraph _paragraph;
ui.Paragraph? _paragraph;
bool _needsLayout = true;
/// Marks this text painter's layout information as dirty and removes cached
......@@ -187,9 +186,9 @@ class TextPainter {
/// representation of the contents of this [TextPainter], use [InlineSpan.toPlainText]
/// to get the full contents of all nodes in the tree. [TextSpan.text] will
/// only provide the contents of the first node in the tree.
InlineSpan get text => _text;
InlineSpan _text;
set text(InlineSpan value) {
InlineSpan? get text => _text;
InlineSpan? _text;
set text(InlineSpan? value) {
assert(value == null || value.debugAssertIsValid());
if (_text == value)
return;
......@@ -229,9 +228,9 @@ class TextPainter {
/// After this is set, you must call [layout] before the next call to [paint].
///
/// This and [text] must be non-null before you call [layout].
TextDirection get textDirection => _textDirection;
TextDirection _textDirection;
set textDirection(TextDirection value) {
TextDirection? get textDirection => _textDirection;
TextDirection? _textDirection;
set textDirection(TextDirection? value) {
if (_textDirection == value)
return;
_textDirection = value;
......@@ -272,9 +271,9 @@ class TextPainter {
/// overflow effects using the [TextOverflow] enum. The
/// [TextOverflow.ellipsis] value corresponds to setting this property to
/// U+2026 HORIZONTAL ELLIPSIS (…).
String get ellipsis => _ellipsis;
String _ellipsis;
set ellipsis(String value) {
String? get ellipsis => _ellipsis;
String? _ellipsis;
set ellipsis(String? value) {
assert(value == null || value.isNotEmpty);
if (_ellipsis == value)
return;
......@@ -283,9 +282,9 @@ class TextPainter {
}
/// The locale used to select region-specific glyphs.
Locale get locale => _locale;
Locale _locale;
set locale(Locale value) {
Locale? get locale => _locale;
Locale? _locale;
set locale(Locale? value) {
if (_locale == value)
return;
_locale = value;
......@@ -299,10 +298,10 @@ class TextPainter {
/// subsequent lines are dropped.
///
/// After this is set, you must call [layout] before the next call to [paint].
int get maxLines => _maxLines;
int _maxLines;
int? get maxLines => _maxLines;
int? _maxLines;
/// The value may be null. If it is not null, then it must be greater than zero.
set maxLines(int value) {
set maxLines(int? value) {
assert(value == null || value > 0);
if (_maxLines == value)
return;
......@@ -322,9 +321,9 @@ class TextPainter {
///
/// See [StrutStyle] for details.
/// {@endtemplate}
StrutStyle get strutStyle => _strutStyle;
StrutStyle _strutStyle;
set strutStyle(StrutStyle value) {
StrutStyle? get strutStyle => _strutStyle;
StrutStyle? _strutStyle;
set strutStyle(StrutStyle? value) {
if (_strutStyle == value)
return;
_strutStyle = value;
......@@ -345,24 +344,24 @@ class TextPainter {
}
/// {@macro flutter.dart:ui.textHeightBehavior}
ui.TextHeightBehavior get textHeightBehavior => _textHeightBehavior;
ui.TextHeightBehavior _textHeightBehavior;
set textHeightBehavior(ui.TextHeightBehavior value) {
ui.TextHeightBehavior? get textHeightBehavior => _textHeightBehavior;
ui.TextHeightBehavior? _textHeightBehavior;
set textHeightBehavior(ui.TextHeightBehavior? value) {
if (_textHeightBehavior == value)
return;
_textHeightBehavior = value;
markNeedsLayout();
}
ui.Paragraph _layoutTemplate;
ui.Paragraph? _layoutTemplate;
/// An ordered list of [TextBox]es that bound the positions of the placeholders
/// in the paragraph.
///
/// Each box corresponds to a [PlaceholderSpan] in the order they were defined
/// in the [InlineSpan] tree.
List<TextBox> get inlinePlaceholderBoxes => _inlinePlaceholderBoxes;
List<TextBox> _inlinePlaceholderBoxes;
List<TextBox>? get inlinePlaceholderBoxes => _inlinePlaceholderBoxes;
List<TextBox>? _inlinePlaceholderBoxes;
/// An ordered list of scales for each placeholder in the paragraph.
///
......@@ -371,8 +370,8 @@ class TextPainter {
///
/// Each scale corresponds to a [PlaceholderSpan] in the order they were defined
/// in the [InlineSpan] tree.
List<double> get inlinePlaceholderScales => _inlinePlaceholderScales;
List<double> _inlinePlaceholderScales;
List<double>? get inlinePlaceholderScales => _inlinePlaceholderScales;
List<double>? _inlinePlaceholderScales;
/// Sets the dimensions of each placeholder in [text].
///
......@@ -383,13 +382,13 @@ class TextPainter {
/// If [layout] is attempted without setting the placeholder dimensions, the
/// placeholders will be ignored in the text layout and no valid
/// [inlinePlaceholderBoxes] will be returned.
void setPlaceholderDimensions(List<PlaceholderDimensions> value) {
void setPlaceholderDimensions(List<PlaceholderDimensions>? value) {
if (value == null || value.isEmpty || listEquals(value, _placeholderDimensions)) {
return;
}
assert(() {
int placeholderCount = 0;
text.visitChildren((InlineSpan span) {
text!.visitChildren((InlineSpan span) {
if (span is PlaceholderSpan) {
placeholderCount += 1;
}
......@@ -400,14 +399,14 @@ class TextPainter {
_placeholderDimensions = value;
markNeedsLayout();
}
List<PlaceholderDimensions> _placeholderDimensions;
List<PlaceholderDimensions>? _placeholderDimensions;
ui.ParagraphStyle _createParagraphStyle([ TextDirection defaultTextDirection ]) {
ui.ParagraphStyle _createParagraphStyle([ TextDirection? defaultTextDirection ]) {
// The defaultTextDirection argument is used for preferredLineHeight in case
// textDirection hasn't yet been set.
assert(textAlign != null);
assert(textDirection != null || defaultTextDirection != null, 'TextPainter.textDirection must be set to a non-null value before using the TextPainter.');
return _text.style?.getParagraphStyle(
return _text!.style?.getParagraphStyle(
textAlign: textAlign,
textDirection: textDirection ?? defaultTextDirection,
textScaleFactor: textScaleFactor,
......@@ -444,12 +443,12 @@ class TextPainter {
_createParagraphStyle(TextDirection.rtl),
); // direction doesn't matter, text is just a space
if (text?.style != null)
builder.pushStyle(text.style.getTextStyle(textScaleFactor: textScaleFactor));
builder.pushStyle(text!.style!.getTextStyle(textScaleFactor: textScaleFactor));
builder.addText(' ');
_layoutTemplate = builder.build()
..layout(const ui.ParagraphConstraints(width: double.infinity));
}
return _layoutTemplate.height;
return _layoutTemplate!.height;
}
// Unfortunately, using full precision floating point here causes bad layouts
......@@ -469,7 +468,7 @@ class TextPainter {
/// Valid only after [layout] has been called.
double get minIntrinsicWidth {
assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.minIntrinsicWidth);
return _applyFloatingPointHack(_paragraph!.minIntrinsicWidth);
}
/// The width at which increasing the width of the text no longer decreases the height.
......@@ -477,7 +476,7 @@ class TextPainter {
/// Valid only after [layout] has been called.
double get maxIntrinsicWidth {
assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.maxIntrinsicWidth);
return _applyFloatingPointHack(_paragraph!.maxIntrinsicWidth);
}
/// The horizontal space required to paint this text.
......@@ -486,7 +485,7 @@ class TextPainter {
double get width {
assert(!_needsLayout);
return _applyFloatingPointHack(
textWidthBasis == TextWidthBasis.longestLine ? _paragraph.longestLine : _paragraph.width,
textWidthBasis == TextWidthBasis.longestLine ? _paragraph!.longestLine : _paragraph!.width,
);
}
......@@ -495,7 +494,7 @@ class TextPainter {
/// Valid only after [layout] has been called.
double get height {
assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.height);
return _applyFloatingPointHack(_paragraph!.height);
}
/// The amount of space required to paint this text.
......@@ -515,11 +514,10 @@ class TextPainter {
assert(baseline != null);
switch (baseline) {
case TextBaseline.alphabetic:
return _paragraph.alphabeticBaseline;
return _paragraph!.alphabeticBaseline;
case TextBaseline.ideographic:
return _paragraph.ideographicBaseline;
return _paragraph!.ideographicBaseline;
}
return null;
}
/// Whether any text was truncated or ellipsized.
......@@ -535,11 +533,11 @@ class TextPainter {
/// Valid only after [layout] has been called.
bool get didExceedMaxLines {
assert(!_needsLayout);
return _paragraph.didExceedMaxLines;
return _paragraph!.didExceedMaxLines;
}
double _lastMinWidth;
double _lastMaxWidth;
double? _lastMinWidth;
double? _lastMaxWidth;
/// Computes the visual position of the glyphs for painting the text.
///
......@@ -557,7 +555,7 @@ class TextPainter {
_needsLayout = false;
if (_paragraph == null) {
final ui.ParagraphBuilder builder = ui.ParagraphBuilder(_createParagraphStyle());
_text.build(builder, textScaleFactor: textScaleFactor, dimensions: _placeholderDimensions);
_text!.build(builder, textScaleFactor: textScaleFactor, dimensions: _placeholderDimensions);
_inlinePlaceholderScales = builder.placeholderScales;
_paragraph = builder.build();
}
......@@ -566,7 +564,7 @@ class TextPainter {
// A change in layout invalidates the cached caret metrics as well.
_previousCaretPosition = null;
_previousCaretPrototype = null;
_paragraph.layout(ui.ParagraphConstraints(width: maxWidth));
_paragraph!.layout(ui.ParagraphConstraints(width: maxWidth));
if (minWidth != maxWidth) {
double newWidth;
switch (textWidthBasis) {
......@@ -576,18 +574,18 @@ class TextPainter {
// it gave to the TextPainter. So when `textWidthBasis` is longestLine,
// the paragraph's width needs to be as close to the width of its
// longest line as possible.
newWidth = _applyFloatingPointHack(_paragraph.longestLine);
newWidth = _applyFloatingPointHack(_paragraph!.longestLine);
break;
case TextWidthBasis.parent:
newWidth = maxIntrinsicWidth;
break;
}
newWidth = newWidth.clamp(minWidth, maxWidth) as double;
if (newWidth != _applyFloatingPointHack(_paragraph.width)) {
_paragraph.layout(ui.ParagraphConstraints(width: newWidth));
if (newWidth != _applyFloatingPointHack(_paragraph!.width)) {
_paragraph!.layout(ui.ParagraphConstraints(width: newWidth));
}
}
_inlinePlaceholderBoxes = _paragraph.getBoxesForPlaceholders();
_inlinePlaceholderBoxes = _paragraph!.getBoxesForPlaceholders();
}
/// Paints the text onto the given canvas at the given offset.
......@@ -612,7 +610,7 @@ class TextPainter {
}
return true;
}());
canvas.drawParagraph(_paragraph, offset);
canvas.drawParagraph(_paragraph!, offset);
}
// Returns true iff the given value is a valid UTF-16 surrogate. The value
......@@ -634,8 +632,8 @@ class TextPainter {
/// Returns the closest offset after `offset` at which the input cursor can be
/// positioned.
int getOffsetAfter(int offset) {
final int nextCodeUnit = _text.codeUnitAt(offset);
int? getOffsetAfter(int offset) {
final int? nextCodeUnit = _text!.codeUnitAt(offset);
if (nextCodeUnit == null)
return null;
// TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404).
......@@ -644,8 +642,8 @@ class TextPainter {
/// Returns the closest offset before `offset` at which the input cursor can
/// be positioned.
int getOffsetBefore(int offset) {
final int prevCodeUnit = _text.codeUnitAt(offset - 1);
int? getOffsetBefore(int offset) {
final int? prevCodeUnit = _text!.codeUnitAt(offset - 1);
if (prevCodeUnit == null)
return null;
// TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404).
......@@ -657,21 +655,21 @@ class TextPainter {
// Get the Rect of the cursor (in logical pixels) based off the near edge
// of the character upstream from the given string offset.
Rect _getRectFromUpstream(int offset, Rect caretPrototype) {
final String flattenedText = _text.toPlainText(includePlaceholders: false);
final int prevCodeUnit = _text.codeUnitAt(max(0, offset - 1));
Rect? _getRectFromUpstream(int offset, Rect caretPrototype) {
final String flattenedText = _text!.toPlainText(includePlaceholders: false);
final int? prevCodeUnit = _text!.codeUnitAt(max(0, offset - 1));
if (prevCodeUnit == null)
return null;
// Check for multi-code-unit glyphs such as emojis or zero width joiner.
final bool needsSearch = _isUtf16Surrogate(prevCodeUnit) || _text.codeUnitAt(offset) == _zwjUtf16 || _isUnicodeDirectionality(prevCodeUnit);
final bool needsSearch = _isUtf16Surrogate(prevCodeUnit) || _text!.codeUnitAt(offset) == _zwjUtf16 || _isUnicodeDirectionality(prevCodeUnit);
int graphemeClusterLength = needsSearch ? 2 : 1;
List<TextBox> boxes = <TextBox>[];
while (boxes.isEmpty && flattenedText != null) {
while (boxes.isEmpty) {
final int prevRuneOffset = offset - graphemeClusterLength;
// Use BoxHeightStyle.strut to ensure that the caret's height fits within
// the line's height and is consistent throughout the line.
boxes = _paragraph.getBoxesForRange(prevRuneOffset, offset, boxHeightStyle: ui.BoxHeightStyle.strut);
boxes = _paragraph!.getBoxesForRange(prevRuneOffset, offset, boxHeightStyle: ui.BoxHeightStyle.strut);
// When the range does not include a full cluster, no boxes will be returned.
if (boxes.isEmpty) {
// When we are at the beginning of the line, a non-surrogate position will
......@@ -699,28 +697,28 @@ class TextPainter {
final double caretEnd = box.end;
final double dx = box.direction == TextDirection.rtl ? caretEnd - caretPrototype.width : caretEnd;
return Rect.fromLTRB(min(dx, _paragraph.width), box.top, min(dx, _paragraph.width), box.bottom);
return Rect.fromLTRB(min(dx, _paragraph!.width), box.top, min(dx, _paragraph!.width), box.bottom);
}
return null;
}
// Get the Rect of the cursor (in logical pixels) based off the near edge
// of the character downstream from the given string offset.
Rect _getRectFromDownstream(int offset, Rect caretPrototype) {
final String flattenedText = _text.toPlainText(includePlaceholders: false);
Rect? _getRectFromDownstream(int offset, Rect caretPrototype) {
final String flattenedText = _text!.toPlainText(includePlaceholders: false);
// We cap the offset at the final index of the _text.
final int nextCodeUnit = _text.codeUnitAt(min(offset, flattenedText == null ? 0 : flattenedText.length - 1));
final int? nextCodeUnit = _text!.codeUnitAt(min(offset, flattenedText.length - 1));
if (nextCodeUnit == null)
return null;
// Check for multi-code-unit glyphs such as emojis or zero width joiner
final bool needsSearch = _isUtf16Surrogate(nextCodeUnit) || nextCodeUnit == _zwjUtf16 || _isUnicodeDirectionality(nextCodeUnit);
int graphemeClusterLength = needsSearch ? 2 : 1;
List<TextBox> boxes = <TextBox>[];
while (boxes.isEmpty && flattenedText != null) {
while (boxes.isEmpty) {
final int nextRuneOffset = offset + graphemeClusterLength;
// Use BoxHeightStyle.strut to ensure that the caret's height fits within
// the line's height and is consistent throughout the line.
boxes = _paragraph.getBoxesForRange(offset, nextRuneOffset, boxHeightStyle: ui.BoxHeightStyle.strut);
boxes = _paragraph!.getBoxesForRange(offset, nextRuneOffset, boxHeightStyle: ui.BoxHeightStyle.strut);
// When the range does not include a full cluster, no boxes will be returned.
if (boxes.isEmpty) {
// When we are at the end of the line, a non-surrogate position will
......@@ -741,7 +739,7 @@ class TextPainter {
final TextBox box = boxes.last;
final double caretStart = box.start;
final double dx = box.direction == TextDirection.rtl ? caretStart - caretPrototype.width : caretStart;
return Rect.fromLTRB(min(dx, _paragraph.width), box.top, min(dx, _paragraph.width), box.bottom);
return Rect.fromLTRB(min(dx, _paragraph!.width), box.top, min(dx, _paragraph!.width), box.bottom);
}
return null;
}
......@@ -759,24 +757,21 @@ class TextPainter {
case TextAlign.justify:
case TextAlign.start:
assert(textDirection != null);
switch (textDirection) {
switch (textDirection!) {
case TextDirection.rtl:
return Offset(width, 0.0);
case TextDirection.ltr:
return Offset.zero;
}
return null;
case TextAlign.end:
assert(textDirection != null);
switch (textDirection) {
switch (textDirection!) {
case TextDirection.rtl:
return Offset.zero;
case TextDirection.ltr:
return Offset(width, 0.0);
}
return null;
}
return null;
}
/// Returns the offset at which to paint the caret.
......@@ -790,7 +785,7 @@ class TextPainter {
/// Returns the tight bounded height of the glyph at the given [position].
///
/// Valid only after [layout] has been called.
double getFullHeightForCaret(TextPosition position, Rect caretPrototype) {
double? getFullHeightForCaret(TextPosition position, Rect caretPrototype) {
_computeCaretMetrics(position, caretPrototype);
return _caretMetrics.fullHeight;
}
......@@ -798,13 +793,13 @@ class TextPainter {
// Cached caret metrics. This allows multiple invokes of [getOffsetForCaret] and
// [getFullHeightForCaret] in a row without performing redundant and expensive
// get rect calls to the paragraph.
_CaretMetrics _caretMetrics;
late _CaretMetrics _caretMetrics;
// Holds the TextPosition and caretPrototype the last caret metrics were
// computed with. When new values are passed in, we recompute the caret metrics.
// only as necessary.
TextPosition _previousCaretPosition;
Rect _previousCaretPrototype;
TextPosition? _previousCaretPosition;
Rect? _previousCaretPrototype;
// Checks if the [position] and [caretPrototype] have changed from the cached
// version and recomputes the metrics required to position the caret.
......@@ -814,7 +809,7 @@ class TextPainter {
return;
final int offset = position.offset;
assert(position.affinity != null);
Rect rect;
Rect? rect;
switch (position.affinity) {
case TextAffinity.upstream: {
rect = _getRectFromUpstream(offset, caretPrototype) ?? _getRectFromDownstream(offset, caretPrototype);
......@@ -853,7 +848,7 @@ class TextPainter {
assert(!_needsLayout);
assert(boxHeightStyle != null);
assert(boxWidthStyle != null);
return _paragraph.getBoxesForRange(
return _paragraph!.getBoxesForRange(
selection.start,
selection.end,
boxHeightStyle: boxHeightStyle,
......@@ -864,7 +859,7 @@ class TextPainter {
/// Returns the position within the text for the given pixel offset.
TextPosition getPositionForOffset(Offset offset) {
assert(!_needsLayout);
return _paragraph.getPositionForOffset(offset);
return _paragraph!.getPositionForOffset(offset);
}
/// Returns the text range of the word at the given offset. Characters not
......@@ -876,7 +871,7 @@ class TextPainter {
/// <http://www.unicode.org/reports/tr29/#Word_Boundaries>.
TextRange getWordBoundary(TextPosition position) {
assert(!_needsLayout);
return _paragraph.getWordBoundary(position);
return _paragraph!.getWordBoundary(position);
}
/// Returns the text range of the line at the given offset.
......@@ -884,7 +879,7 @@ class TextPainter {
/// The newline, if any, is included in the range.
TextRange getLineBoundary(TextPosition position) {
assert(!_needsLayout);
return _paragraph.getLineBoundary(position);
return _paragraph!.getLineBoundary(position);
}
/// Returns the full list of [LineMetrics] that describe in detail the various
......@@ -904,6 +899,6 @@ class TextPainter {
/// should be invalidated upon the next successful [layout].
List<ui.LineMetrics> computeLineMetrics() {
assert(!_needsLayout);
return _paragraph.computeLineMetrics();
return _paragraph!.computeLineMetrics();
}
}
......@@ -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 {
......
......@@ -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 ParagraphStyle, TextStyle, StrutStyle, lerpDouble, Shadow, FontFeature, TextHeightBehavior;
......@@ -421,9 +420,9 @@ class TextStyle with Diagnosticable {
this.decorationStyle,
this.decorationThickness,
this.debugLabel,
String fontFamily,
List<String> fontFamilyFallback,
String package,
String? fontFamily,
List<String>? fontFamilyFallback,
String? package,
}) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily',
_fontFamilyFallback = fontFamilyFallback,
_package = package,
......@@ -448,7 +447,7 @@ class TextStyle with Diagnosticable {
/// In [merge], [apply], and [lerp], conflicts between [color] and [foreground]
/// specification are resolved in [foreground]'s favor - i.e. if [foreground] is
/// specified in one place, it will dominate [color] in another.
final Color color;
final Color? color;
/// The color to use as the background for the text.
///
......@@ -459,7 +458,7 @@ class TextStyle with Diagnosticable {
/// In [merge], [apply], and [lerp], conflicts between [backgroundColor] and [background]
/// specification are resolved in [background]'s favor - i.e. if [background] is
/// specified in one place, it will dominate [color] in another.
final Color backgroundColor;
final Color? backgroundColor;
/// The name of the font to use when painting the text (e.g., Roboto). If the
/// font is defined in a package, this will be prefixed with
......@@ -473,7 +472,7 @@ class TextStyle with Diagnosticable {
/// first value in [fontFamilyFallback] acts as the preferred/first font
/// family. When neither is provided, then the default platform font will
/// be used.
final String fontFamily;
final String? fontFamily;
/// The ordered list of font families to fall back on when a glyph cannot be
/// found in a higher priority font family.
......@@ -496,12 +495,12 @@ class TextStyle 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 => _package != null && _fontFamilyFallback != null ? _fontFamilyFallback.map((String str) => 'packages/$_package/$str').toList() : _fontFamilyFallback;
final List<String> _fontFamilyFallback;
List<String>? get fontFamilyFallback => _package != null && _fontFamilyFallback != null ? _fontFamilyFallback!.map((String str) => 'packages/$_package/$str').toList() : _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 glyphs (in logical pixels) to use when painting the text.
///
......@@ -511,29 +510,29 @@ class TextStyle with Diagnosticable {
///
/// [getParagraphStyle] will default to 14 logical pixels if the font size
/// isn't specified here.
final double fontSize;
final double? fontSize;
// The default font size if none is specified.
static const double _defaultFontSize = 14.0;
/// The typeface thickness to use when painting the text (e.g., bold).
final FontWeight fontWeight;
final FontWeight? fontWeight;
/// The typeface variant to use when drawing the letters (e.g., italics).
final FontStyle fontStyle;
final FontStyle? fontStyle;
/// The amount of space (in logical pixels) to add between each letter.
/// A negative value can be used to bring the letters closer.
final double letterSpacing;
final double? letterSpacing;
/// The amount of space (in logical pixels) to add at each sequence of
/// white-space (i.e. between each word). A negative value can be used to
/// bring the words closer.
final double wordSpacing;
final double? wordSpacing;
/// The common baseline that should be aligned between this text span and its
/// parent text span, or, for the root text spans, with the line box.
final TextBaseline textBaseline;
final TextBaseline? textBaseline;
/// The height of this text span, as a multiple of the font size.
///
......@@ -557,7 +556,7 @@ class TextStyle with Diagnosticable {
/// ![Text height comparison diagram](https://flutter.github.io/assets-for-api-docs/assets/painting/text_height_comparison_diagram.png)
///
/// See [StrutStyle] for further control of line height at the paragraph level.
final double height;
final double? height;
/// The locale used to select region-specific glyphs.
///
......@@ -567,7 +566,7 @@ class TextStyle with Diagnosticable {
/// its locale this way. However, a rich text widget's [TextSpan]s could
/// specify text styles with different explicit locales in order to select
/// different region-specific glyphs for each text span.
final Locale locale;
final Locale? locale;
/// The paint drawn as a foreground for the text.
///
......@@ -582,7 +581,7 @@ class TextStyle with Diagnosticable {
/// In [merge], [apply], and [lerp], conflicts between [color] and [foreground]
/// specification are resolved in [foreground]'s favor - i.e. if [foreground] is
/// specified in one place, it will dominate [color] in another.
final Paint foreground;
final Paint? foreground;
/// The paint drawn as a background for the text.
///
......@@ -599,18 +598,18 @@ class TextStyle with Diagnosticable {
/// [background] specification are resolved in [background]'s favor - i.e. if
/// [background] is specified in one place, it will dominate [backgroundColor]
/// in another.
final Paint background;
final Paint? background;
/// The decorations to paint near the text (e.g., an underline).
///
/// Multiple decorations can be applied using [TextDecoration.combine].
final TextDecoration decoration;
final TextDecoration? decoration;
/// The color in which to paint the text decorations.
final Color decorationColor;
final Color? decorationColor;
/// The style in which to paint the text decorations (e.g., dashed).
final TextDecorationStyle decorationStyle;
final TextDecorationStyle? decorationStyle;
/// The thickness of the decoration stroke as a multiplier of the thickness
/// defined by the font.
......@@ -655,7 +654,7 @@ class TextStyle with Diagnosticable {
///
/// The default [decorationThickness] is 1.0, which will use the font's base
/// stroke thickness/width.
final double decorationThickness;
final double? decorationThickness;
/// A human-readable description of this text style.
///
......@@ -668,7 +667,7 @@ class TextStyle with Diagnosticable {
///
/// This property is not considered when comparing text styles using `==` or
/// [compareTo], and it does not affect [hashCode].
final String debugLabel;
final String? debugLabel;
/// A list of [Shadow]s that will be painted underneath the text.
///
......@@ -677,7 +676,7 @@ class TextStyle with Diagnosticable {
///
/// Shadows must be in the same order for [TextStyle] to be considered as
/// equivalent as order produces differing transparency.
final List<ui.Shadow> shadows;
final List<ui.Shadow>? shadows;
/// A list of [FontFeature]s that affect how the font selects glyphs.
///
......@@ -686,7 +685,7 @@ class TextStyle with Diagnosticable {
/// tabular numbers, or it might offer versions of the zero digit with
/// and without slashes. [FontFeature]s can be used to select which of
/// these variants will be used for rendering.
final List<ui.FontFeature> fontFeatures;
final List<ui.FontFeature>? fontFeatures;
/// Creates a copy of this text style but with the given fields replaced with
/// the new values.
......@@ -698,32 +697,32 @@ class TextStyle with Diagnosticable {
/// [background] specified it will be given preference over any
/// backgroundColor parameter.
TextStyle copyWith({
bool inherit,
Color color,
Color backgroundColor,
String fontFamily,
List<String> fontFamilyFallback,
double fontSize,
FontWeight fontWeight,
FontStyle fontStyle,
double letterSpacing,
double wordSpacing,
TextBaseline textBaseline,
double height,
Locale locale,
Paint foreground,
Paint background,
List<ui.Shadow> shadows,
List<ui.FontFeature> fontFeatures,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
double decorationThickness,
String debugLabel,
bool? inherit,
Color? color,
Color? backgroundColor,
String? fontFamily,
List<String>? fontFamilyFallback,
double? fontSize,
FontWeight? fontWeight,
FontStyle? fontStyle,
double? letterSpacing,
double? wordSpacing,
TextBaseline? textBaseline,
double? height,
Locale? locale,
Paint? foreground,
Paint? background,
List<ui.Shadow>? shadows,
List<ui.FontFeature>? fontFeatures,
TextDecoration? decoration,
Color? decorationColor,
TextDecorationStyle? decorationStyle,
double? decorationThickness,
String? debugLabel,
}) {
assert(color == null || foreground == null, _kColorForegroundWarning);
assert(backgroundColor == null || background == null, _kColorBackgroundWarning);
String newDebugLabel;
String? newDebugLabel;
assert(() {
if (this.debugLabel != null)
newDebugLabel = debugLabel ?? '(${this.debugLabel}).copyWith';
......@@ -785,29 +784,29 @@ class TextStyle with Diagnosticable {
/// will have no effect and if [background] is specified on this object, then
/// applying [backgroundColor] here will have no effect either.
TextStyle apply({
Color color,
Color backgroundColor,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
Color? color,
Color? backgroundColor,
TextDecoration? decoration,
Color? decorationColor,
TextDecorationStyle? decorationStyle,
double decorationThicknessFactor = 1.0,
double decorationThicknessDelta = 0.0,
String fontFamily,
List<String> fontFamilyFallback,
String? fontFamily,
List<String>? fontFamilyFallback,
double fontSizeFactor = 1.0,
double fontSizeDelta = 0.0,
int fontWeightDelta = 0,
FontStyle fontStyle,
FontStyle? fontStyle,
double letterSpacingFactor = 1.0,
double letterSpacingDelta = 0.0,
double wordSpacingFactor = 1.0,
double wordSpacingDelta = 0.0,
double heightFactor = 1.0,
double heightDelta = 0.0,
TextBaseline textBaseline,
Locale locale,
List<ui.Shadow> shadows,
List<ui.FontFeature> fontFeatures,
TextBaseline? textBaseline,
Locale? locale,
List<ui.Shadow>? shadows,
List<ui.FontFeature>? fontFeatures,
}) {
assert(fontSizeFactor != null);
assert(fontSizeDelta != null);
......@@ -827,7 +826,7 @@ class TextStyle with Diagnosticable {
assert(decorationThicknessDelta != null);
assert(decorationThickness != null || (decorationThicknessFactor == 1.0 && decorationThicknessDelta == 0.0));
String modifiedDebugLabel;
String? modifiedDebugLabel;
assert(() {
if (debugLabel != null)
modifiedDebugLabel = '($debugLabel).apply';
......@@ -840,13 +839,13 @@ class TextStyle with Diagnosticable {
backgroundColor: background == null ? backgroundColor ?? this.backgroundColor : null,
fontFamily: fontFamily ?? this.fontFamily,
fontFamilyFallback: fontFamilyFallback ?? this.fontFamilyFallback,
fontSize: fontSize == null ? null : fontSize * fontSizeFactor + fontSizeDelta,
fontWeight: fontWeight == null ? null : FontWeight.values[(fontWeight.index + fontWeightDelta).clamp(0, FontWeight.values.length - 1) as int],
fontSize: fontSize == null ? null : fontSize! * fontSizeFactor + fontSizeDelta,
fontWeight: fontWeight == null ? null : FontWeight.values[(fontWeight!.index + fontWeightDelta).clamp(0, FontWeight.values.length - 1) as int],
fontStyle: fontStyle ?? this.fontStyle,
letterSpacing: letterSpacing == null ? null : letterSpacing * letterSpacingFactor + letterSpacingDelta,
wordSpacing: wordSpacing == null ? null : wordSpacing * wordSpacingFactor + wordSpacingDelta,
letterSpacing: letterSpacing == null ? null : letterSpacing! * letterSpacingFactor + letterSpacingDelta,
wordSpacing: wordSpacing == null ? null : wordSpacing! * wordSpacingFactor + wordSpacingDelta,
textBaseline: textBaseline ?? this.textBaseline,
height: height == null ? null : height * heightFactor + heightDelta,
height: height == null ? null : height! * heightFactor + heightDelta,
locale: locale ?? this.locale,
foreground: foreground,
background: background,
......@@ -855,7 +854,7 @@ class TextStyle with Diagnosticable {
decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle,
decorationThickness: decorationThickness == null ? null : decorationThickness * decorationThicknessFactor + decorationThicknessDelta,
decorationThickness: decorationThickness == null ? null : decorationThickness! * decorationThicknessFactor + decorationThicknessDelta,
debugLabel: modifiedDebugLabel,
);
}
......@@ -881,13 +880,13 @@ class TextStyle with Diagnosticable {
/// Similarly, One of [backgroundColor] or [background] must be null, and if
/// this or `other` has [background] specified it will be given preference
/// over any backgroundColor parameter.
TextStyle merge(TextStyle other) {
TextStyle merge(TextStyle? other) {
if (other == null)
return this;
if (!other.inherit)
return other;
String mergedDebugLabel;
String? mergedDebugLabel;
assert(() {
if (other.debugLabel != null || debugLabel != null)
mergedDebugLabel = '(${debugLabel ?? _kDefaultDebugLabel}).merge(${other.debugLabel ?? _kDefaultDebugLabel})';
......@@ -932,14 +931,14 @@ class TextStyle with Diagnosticable {
/// If [background] is specified on either of `a` or `b`, both will be treated
/// as if they have a [background] paint (creating a new [Paint] if necessary
/// based on the [backgroundColor] property).
static TextStyle lerp(TextStyle a, TextStyle b, double t) {
static TextStyle? lerp(TextStyle? a, TextStyle? b, double t) {
assert(t != null);
assert(a == null || b == null || a.inherit == b.inherit);
if (a == null && b == null) {
return null;
}
String lerpDebugLabel;
String? lerpDebugLabel;
assert(() {
lerpDebugLabel = 'lerp(${a?.debugLabel ?? _kDefaultDebugLabel}${t.toStringAsFixed(1)}${b?.debugLabel ?? _kDefaultDebugLabel})';
return true;
......@@ -947,7 +946,7 @@ class TextStyle with Diagnosticable {
if (a == null) {
return TextStyle(
inherit: b.inherit,
inherit: b!.inherit,
color: Color.lerp(null, b.color, t),
backgroundColor: Color.lerp(null, b.backgroundColor, t),
fontFamily: t < 0.5 ? null : b.fontFamily,
......@@ -1015,13 +1014,13 @@ class TextStyle with Diagnosticable {
locale: t < 0.5 ? a.locale : b.locale,
foreground: (a.foreground != null || b.foreground != null)
? t < 0.5
? a.foreground ?? (Paint()..color = a.color)
: b.foreground ?? (Paint()..color = b.color)
? a.foreground ?? (Paint()..color = a.color!)
: b.foreground ?? (Paint()..color = b.color!)
: null,
background: (a.background != null || b.background != null)
? t < 0.5
? a.background ?? (Paint()..color = a.backgroundColor)
: b.background ?? (Paint()..color = b.backgroundColor)
? a.background ?? (Paint()..color = a.backgroundColor!)
: b.background ?? (Paint()..color = b.backgroundColor!)
: null,
shadows: t < 0.5 ? a.shadows : b.shadows,
fontFeatures: t < 0.5 ? a.fontFeatures : b.fontFeatures,
......@@ -1046,14 +1045,14 @@ class TextStyle with Diagnosticable {
textBaseline: textBaseline,
fontFamily: fontFamily,
fontFamilyFallback: fontFamilyFallback,
fontSize: fontSize == null ? null : fontSize * textScaleFactor,
fontSize: fontSize == null ? null : fontSize! * textScaleFactor,
letterSpacing: letterSpacing,
wordSpacing: wordSpacing,
height: height,
locale: locale,
foreground: foreground,
background: background ?? (backgroundColor != null
? (Paint()..color = backgroundColor)
? (Paint()..color = backgroundColor!)
: null
),
shadows: shadows,
......@@ -1070,19 +1069,19 @@ class TextStyle with Diagnosticable {
/// If the font size on this style isn't set, it will default to 14 logical
/// pixels.
ui.ParagraphStyle getParagraphStyle({
TextAlign textAlign,
TextDirection textDirection,
TextAlign? textAlign,
TextDirection? textDirection,
double textScaleFactor = 1.0,
String ellipsis,
int maxLines,
ui.TextHeightBehavior textHeightBehavior,
Locale locale,
String fontFamily,
double fontSize,
FontWeight fontWeight,
FontStyle fontStyle,
double height,
StrutStyle strutStyle,
String? ellipsis,
int? maxLines,
ui.TextHeightBehavior? textHeightBehavior,
Locale? locale,
String? fontFamily,
double? fontSize,
FontWeight? fontWeight,
FontStyle? fontStyle,
double? height,
StrutStyle? strutStyle,
}) {
assert(textScaleFactor != null);
assert(maxLines == null || maxLines > 0);
......@@ -1100,7 +1099,7 @@ class TextStyle with Diagnosticable {
strutStyle: strutStyle == null ? null : ui.StrutStyle(
fontFamily: strutStyle.fontFamily,
fontFamilyFallback: strutStyle.fontFamilyFallback,
fontSize: strutStyle.fontSize == null ? null : strutStyle.fontSize * textScaleFactor,
fontSize: strutStyle.fontSize == null ? null : strutStyle.fontSize! * textScaleFactor,
height: strutStyle.height,
leading: strutStyle.leading,
fontWeight: strutStyle.fontWeight,
......@@ -1212,7 +1211,7 @@ class TextStyle 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>[
ColorProperty('${prefix}color', color, defaultValue: null),
ColorProperty('${prefix}backgroundColor', backgroundColor, defaultValue: null),
......@@ -1220,9 +1219,9 @@ class TextStyle with Diagnosticable {
IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null),
DoubleProperty('${prefix}size', fontSize, defaultValue: null),
];
String weightDescription;
String? weightDescription;
if (fontWeight != null) {
weightDescription = '${fontWeight.index + 1}00';
weightDescription = '${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
......@@ -1244,7 +1243,7 @@ class TextStyle with Diagnosticable {
if (decoration != null || decorationColor != null || decorationStyle != null || decorationThickness != null) {
final List<String> decorationDescription = <String>[];
if (decorationStyle != null)
decorationDescription.add(describeEnum(decorationStyle));
decorationDescription.add(describeEnum(decorationStyle!));
// Hide decorationColor from the default text view as it is shown in the
// terse decoration summary as well.
......
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