Unverified Commit bdc3dda5 authored by Gary Qian's avatar Gary Qian Committed by GitHub

Add support for text shadows and roll engine (26 commits) (#22449)

* Add support for shadows in text.

* Use dart:ui Shadow as base class for Shadows

* Update lerp definition

* Roll engine 3ffa3629523..84fe4a9f7e24e4 - Text Shadows and update goldens for skia roll.

git log 50c2e69daff4e207c54e463d2304139985c7511c..32f417db0d566d354605305cb29c251276fa65ee --oneline --no-merges
32f417db0 Roll tonic to 077be256142ede39a271385907faadf4fcc62a4d. (#6541)
4ee77256c Revert "Roll Dart to 1f4dfce179c8f05c9e48759300a15e671b88cc10 (#6515)" (#6537)
964acafeb Roll src/third_party/skia 646d917d3c71..c6a17104ad68 (1 commits) (#6536)
d4bae4ca4 Roll src/third_party/skia 2b2c00f6ec36..646d917d3c71 (1 commits) (#6535)
ff93ccf47 Roll src/third_party/skia 681692726fc0..2b2c00f6ec36 (1 commits) (#6534)
a4161c895 Roll src/third_party/skia 23775a2e9736..681692726fc0 (1 commits) (#6532)
116072e46 Roll src/third_party/skia 7435f2553f53..23775a2e9736 (1 commits) (#6531)
ef0b0f6e9 Roll src/third_party/skia bc7a51e79c5b..7435f2553f53 (1 commits) (#6530)
f46b7b971 Roll src/third_party/skia b28db529c866..bc7a51e79c5b (1 commits) (#6529)
9033c3902 Roll src/third_party/skia 7e67041a1428..b28db529c866 (1 commits) (#6528)
e6887a412 Add missing imports for unicode/utf16.h (#6524)
1242f6dfe Roll src/third_party/skia d38382d060ca..7e67041a1428 (2 commits) (#6527)
a1bbea77c Add a no-op platform view layer. (#6505)
2bb3afad8 Roll src/third_party/skia 21bd60daa3f3..d38382d060ca (10 commits) (#6526)
75e875240 Fix the Mac embedder build (#6525)
436f9707b Add version check for dismissable (#6522)
7767c785b Provide a default GL function resolver in the embedder (#6523)
32841dd89 Case-insensitive matching of family names for custom fonts (#6519)
a9076c7e6 Roll src/third_party/skia 419709dbb167..21bd60daa3f3 (11 commits) (#6520)
f2e7441b5 An API for loading fonts from a buffer provided by the application (#6508)
05aac0f27 fix ResourceExtractor npe. (#6461)
cf5a2a145 Roll src/third_party/skia b27a9cf2f4a8..419709dbb167 (16 commits) (#6517)
84fe4a9f7 Re-revert invalid line height tests (#6516)
5f529566c Add support for text shadows (#6385)
e44c10c96 Reland "Share engine layers with the framework" (#6412) (#6468)
ba0449971 Roll Dart to 1f4dfce179c8f05c9e48759300a15e671b88cc10 (#6515)
parent bf92d7f2
50c2e69daff4e207c54e463d2304139985c7511c 32f417db0d566d354605305cb29c251276fa65ee
fcb6a6cad08bd4a7d5c0157b9f83acadfa9be7e3 bf46dc6b05154649926392e0fc042289e6172ca7
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
/// painting boxes. /// painting boxes.
library painting; library painting;
export 'dart:ui' show Shadow;
export 'src/painting/alignment.dart'; export 'src/painting/alignment.dart';
export 'src/painting/basic_types.dart'; export 'src/painting/basic_types.dart';
export 'src/painting/beveled_rectangle_border.dart'; export 'src/painting/beveled_rectangle_border.dart';
......
...@@ -360,7 +360,7 @@ class ChipThemeData extends Diagnosticable { ...@@ -360,7 +360,7 @@ class ChipThemeData extends Diagnosticable {
/// ///
/// The arguments must not be null. /// The arguments must not be null.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static ChipThemeData lerp(ChipThemeData a, ChipThemeData b, double t) { static ChipThemeData lerp(ChipThemeData a, ChipThemeData b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -391,7 +391,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -391,7 +391,7 @@ class SliderThemeData extends Diagnosticable {
/// ///
/// The arguments must not be null. /// The arguments must not be null.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static SliderThemeData lerp(SliderThemeData a, SliderThemeData b, double t) { static SliderThemeData lerp(SliderThemeData a, SliderThemeData b, double t) {
assert(a != null); assert(a != null);
assert(b != null); assert(b != null);
......
...@@ -63,7 +63,7 @@ class TabBarTheme extends Diagnosticable { ...@@ -63,7 +63,7 @@ class TabBarTheme extends Diagnosticable {
/// ///
/// The arguments must not be null. /// The arguments must not be null.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static TabBarTheme lerp(TabBarTheme a, TabBarTheme b, double t) { static TabBarTheme lerp(TabBarTheme a, TabBarTheme b, double t) {
assert(a != null); assert(a != null);
assert(b != null); assert(b != null);
......
...@@ -787,7 +787,7 @@ class ThemeData extends Diagnosticable { ...@@ -787,7 +787,7 @@ class ThemeData extends Diagnosticable {
/// ///
/// The arguments must not be null. /// The arguments must not be null.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static ThemeData lerp(ThemeData a, ThemeData b, double t) { static ThemeData lerp(ThemeData a, ThemeData b, double t) {
assert(a != null); assert(a != null);
assert(b != null); assert(b != null);
......
...@@ -212,7 +212,7 @@ class Typography extends Diagnosticable { ...@@ -212,7 +212,7 @@ class Typography extends Diagnosticable {
/// Linearly interpolate between two [Typography] objects. /// Linearly interpolate between two [Typography] objects.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static Typography lerp(Typography a, Typography b, double t) { static Typography lerp(Typography a, Typography b, double t) {
return Typography( return Typography(
black: TextTheme.lerp(a.black, b.black, t), black: TextTheme.lerp(a.black, b.black, t),
......
...@@ -85,7 +85,7 @@ abstract class AlignmentGeometry { ...@@ -85,7 +85,7 @@ abstract class AlignmentGeometry {
/// representing a combination of both is returned. That object can be turned /// representing a combination of both is returned. That object can be turned
/// into a concrete [Alignment] using [resolve]. /// into a concrete [Alignment] using [resolve].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static AlignmentGeometry lerp(AlignmentGeometry a, AlignmentGeometry b, double t) { static AlignmentGeometry lerp(AlignmentGeometry a, AlignmentGeometry b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -324,7 +324,7 @@ class Alignment extends AlignmentGeometry { ...@@ -324,7 +324,7 @@ class Alignment extends AlignmentGeometry {
/// ///
/// If either is null, this function interpolates from [Alignment.center]. /// If either is null, this function interpolates from [Alignment.center].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static Alignment lerp(Alignment a, Alignment b, double t) { static Alignment lerp(Alignment a, Alignment b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -505,7 +505,7 @@ class AlignmentDirectional extends AlignmentGeometry { ...@@ -505,7 +505,7 @@ class AlignmentDirectional extends AlignmentGeometry {
/// ///
/// If either is null, this function interpolates from [AlignmentDirectional.center]. /// If either is null, this function interpolates from [AlignmentDirectional.center].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static AlignmentDirectional lerp(AlignmentDirectional a, AlignmentDirectional b, double t) { static AlignmentDirectional lerp(AlignmentDirectional a, AlignmentDirectional b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -127,7 +127,7 @@ abstract class BorderRadiusGeometry { ...@@ -127,7 +127,7 @@ abstract class BorderRadiusGeometry {
/// representing a combination of both is returned. That object can be turned /// representing a combination of both is returned. That object can be turned
/// into a concrete [BorderRadius] using [resolve]. /// into a concrete [BorderRadius] using [resolve].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadiusGeometry lerp(BorderRadiusGeometry a, BorderRadiusGeometry b, double t) { static BorderRadiusGeometry lerp(BorderRadiusGeometry a, BorderRadiusGeometry b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -471,7 +471,7 @@ class BorderRadius extends BorderRadiusGeometry { ...@@ -471,7 +471,7 @@ class BorderRadius extends BorderRadiusGeometry {
/// ///
/// If either is null, this function interpolates from [BorderRadius.zero]. /// If either is null, this function interpolates from [BorderRadius.zero].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadius lerp(BorderRadius a, BorderRadius b, double t) { static BorderRadius lerp(BorderRadius a, BorderRadius b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -688,7 +688,7 @@ class BorderRadiusDirectional extends BorderRadiusGeometry { ...@@ -688,7 +688,7 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
/// ///
/// If either is null, this function interpolates from [BorderRadiusDirectional.zero]. /// If either is null, this function interpolates from [BorderRadiusDirectional.zero].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadiusDirectional lerp(BorderRadiusDirectional a, BorderRadiusDirectional b, double t) { static BorderRadiusDirectional lerp(BorderRadiusDirectional a, BorderRadiusDirectional b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -198,7 +198,7 @@ class BorderSide { ...@@ -198,7 +198,7 @@ class BorderSide {
/// ///
/// The arguments must not be null. /// The arguments must not be null.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderSide lerp(BorderSide a, BorderSide b, double t) { static BorderSide lerp(BorderSide a, BorderSide b, double t) {
assert(a != null); assert(a != null);
assert(b != null); assert(b != null);
...@@ -404,7 +404,7 @@ abstract class ShapeBorder { ...@@ -404,7 +404,7 @@ abstract class ShapeBorder {
/// function instead. If both return null, it returns `a` before `t=0.5` /// function instead. If both return null, it returns `a` before `t=0.5`
/// and `b` after `t=0.5`. /// and `b` after `t=0.5`.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static ShapeBorder lerp(ShapeBorder a, ShapeBorder b, double t) { static ShapeBorder lerp(ShapeBorder a, ShapeBorder b, double t) {
assert(t != null); assert(t != null);
ShapeBorder result; ShapeBorder result;
......
...@@ -98,7 +98,7 @@ abstract class BoxBorder extends ShapeBorder { ...@@ -98,7 +98,7 @@ abstract class BoxBorder extends ShapeBorder {
/// For a more flexible approach, consider [ShapeBorder.lerp], which would /// For a more flexible approach, consider [ShapeBorder.lerp], which would
/// instead [add] the two sets of sides and interpolate them simultaneously. /// instead [add] the two sets of sides and interpolate them simultaneously.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxBorder lerp(BoxBorder a, BoxBorder b, double t) { static BoxBorder lerp(BoxBorder a, BoxBorder b, double t) {
assert(t != null); assert(t != null);
if ((a is Border || a == null) && (b is Border || b == null)) if ((a is Border || a == null) && (b is Border || b == null))
...@@ -421,7 +421,7 @@ class Border extends BoxBorder { ...@@ -421,7 +421,7 @@ class Border extends BoxBorder {
/// If a border is null, it is treated as having four [BorderSide.none] /// If a border is null, it is treated as having four [BorderSide.none]
/// borders. /// borders.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static Border lerp(Border a, Border b, double t) { static Border lerp(Border a, Border b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -711,7 +711,7 @@ class BorderDirectional extends BoxBorder { ...@@ -711,7 +711,7 @@ class BorderDirectional extends BoxBorder {
/// If a border is null, it is treated as having four [BorderSide.none] /// If a border is null, it is treated as having four [BorderSide.none]
/// borders. /// borders.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderDirectional lerp(BorderDirectional a, BorderDirectional b, double t) { static BorderDirectional lerp(BorderDirectional a, BorderDirectional b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -215,7 +215,7 @@ class BoxDecoration extends Decoration { ...@@ -215,7 +215,7 @@ class BoxDecoration extends Decoration {
/// unmodified. Otherwise, the values are computed by interpolating the /// unmodified. Otherwise, the values are computed by interpolating the
/// properties appropriately. /// properties appropriately.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
/// ///
/// See also: /// See also:
/// ///
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' as ui show lerpDouble; import 'dart:ui' as ui show Shadow, lerpDouble;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -12,6 +12,8 @@ import 'debug.dart'; ...@@ -12,6 +12,8 @@ import 'debug.dart';
/// A shadow cast by a box. /// A shadow cast by a box.
/// ///
/// Inherits from [Shadow]
///
/// [BoxShadow] can cast non-rectangular shadows if the box is non-rectangular /// [BoxShadow] can cast non-rectangular shadows if the box is non-rectangular
/// (e.g., has a border radius or a circular shape). /// (e.g., has a border radius or a circular shape).
/// ///
...@@ -20,52 +22,30 @@ import 'debug.dart'; ...@@ -20,52 +22,30 @@ import 'debug.dart';
/// See also: /// See also:
/// ///
/// * [Canvas.drawShadow], which is a more efficient way to draw shadows. /// * [Canvas.drawShadow], which is a more efficient way to draw shadows.
/// * [Shadow], which is the parent class that lacks [spreadRadius].
@immutable @immutable
class BoxShadow { class BoxShadow extends ui.Shadow {
/// Creates a box shadow. /// Creates a box shadow.
/// ///
/// By default, the shadow is solid black with zero [offset], [blurRadius], /// By default, the shadow is solid black with zero [offset], [blurRadius],
/// and [spreadRadius]. /// and [spreadRadius].
const BoxShadow({ const BoxShadow({
this.color = const Color(0xFF000000), Color color = const Color(0xFF000000),
this.offset = Offset.zero, Offset offset = Offset.zero,
this.blurRadius = 0.0, double blurRadius = 0.0,
this.spreadRadius = 0.0 this.spreadRadius = 0.0
}); }) : super(color: color, offset: offset, blurRadius: blurRadius);
/// The color of the shadow.
final Color color;
/// The displacement of the shadow from the box.
final Offset offset;
/// The standard deviation of the Gaussian to convolve with the box's shape.
final double blurRadius;
/// The amount the box should be inflated prior to applying the blur. /// The amount the box should be inflated prior to applying the blur.
final double spreadRadius; final double spreadRadius;
/// Converts a blur radius in pixels to sigmas.
///
/// See the sigma argument to [MaskFilter.blur].
//
// See SkBlurMask::ConvertRadiusToSigma().
// <https://github.com/google/skia/blob/bb5b77db51d2e149ee66db284903572a5aac09be/src/effects/SkBlurMask.cpp#L23>
static double convertRadiusToSigma(double radius) {
return radius * 0.57735 + 0.5;
}
/// The [blurRadius] in sigmas instead of logical pixels.
///
/// See the sigma argument to [MaskFilter.blur].
double get blurSigma => convertRadiusToSigma(blurRadius);
/// Create the [Paint] object that corresponds to this shadow description. /// Create the [Paint] object that corresponds to this shadow description.
/// ///
/// The [offset] and [spreadRadius] are not represented in the [Paint] object. /// The [offset] and [spreadRadius] are not represented in the [Paint] object.
/// To honor those as well, the shape should be inflated by [spreadRadius] pixels /// To honor those as well, the shape should be inflated by [spreadRadius] pixels
/// in every direction and then translated by [offset] before being filled using /// in every direction and then translated by [offset] before being filled using
/// this [Paint]. /// this [Paint].
@override
Paint toPaint() { Paint toPaint() {
final Paint result = Paint() final Paint result = Paint()
..color = color ..color = color
...@@ -79,6 +59,7 @@ class BoxShadow { ...@@ -79,6 +59,7 @@ class BoxShadow {
} }
/// Returns a new box shadow with its offset, blurRadius, and spreadRadius scaled by the given factor. /// Returns a new box shadow with its offset, blurRadius, and spreadRadius scaled by the given factor.
@override
BoxShadow scale(double factor) { BoxShadow scale(double factor) {
return BoxShadow( return BoxShadow(
color: color, color: color,
...@@ -94,7 +75,7 @@ class BoxShadow { ...@@ -94,7 +75,7 @@ class BoxShadow {
/// a box shadow that matches the other box shadow in color but has a zero /// a box shadow that matches the other box shadow in color but has a zero
/// offset and a zero blurRadius. /// offset and a zero blurRadius.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxShadow lerp(BoxShadow a, BoxShadow b, double t) { static BoxShadow lerp(BoxShadow a, BoxShadow b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -115,7 +96,7 @@ class BoxShadow { ...@@ -115,7 +96,7 @@ class BoxShadow {
/// ///
/// If the lists differ in length, excess items are lerped with null. /// If the lists differ in length, excess items are lerped with null.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static List<BoxShadow> lerpList(List<BoxShadow> a, List<BoxShadow> b, double t) { static List<BoxShadow> lerpList(List<BoxShadow> a, List<BoxShadow> b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -194,7 +194,7 @@ class HSVColor { ...@@ -194,7 +194,7 @@ class HSVColor {
/// that will interpolate from a transparent red and cycle through the hues to /// that will interpolate from a transparent red and cycle through the hues to
/// match the target color, regardless of what that color's hue is. /// match the target color, regardless of what that color's hue is.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
/// ///
/// Values outside of the valid range for each channel will be clamped. /// Values outside of the valid range for each channel will be clamped.
static HSVColor lerp(HSVColor a, HSVColor b, double t) { static HSVColor lerp(HSVColor a, HSVColor b, double t) {
......
...@@ -124,7 +124,7 @@ abstract class Decoration extends Diagnosticable { ...@@ -124,7 +124,7 @@ abstract class Decoration extends Diagnosticable {
/// respectively to find a solution. If the two values can't directly be /// respectively to find a solution. If the two values can't directly be
/// interpolated, then the interpolation is done via null (at `t == 0.5`). /// interpolated, then the interpolation is done via null (at `t == 0.5`).
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static Decoration lerp(Decoration a, Decoration b, double t) { static Decoration lerp(Decoration a, Decoration b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -190,7 +190,7 @@ abstract class EdgeInsetsGeometry { ...@@ -190,7 +190,7 @@ abstract class EdgeInsetsGeometry {
/// representing a combination of both is returned. That object can be turned /// representing a combination of both is returned. That object can be turned
/// into a concrete [EdgeInsets] using [resolve]. /// into a concrete [EdgeInsets] using [resolve].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsetsGeometry lerp(EdgeInsetsGeometry a, EdgeInsetsGeometry b, double t) { static EdgeInsetsGeometry lerp(EdgeInsetsGeometry a, EdgeInsetsGeometry b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -546,7 +546,7 @@ class EdgeInsets extends EdgeInsetsGeometry { ...@@ -546,7 +546,7 @@ class EdgeInsets extends EdgeInsetsGeometry {
/// ///
/// If either is null, this function interpolates from [EdgeInsets.zero]. /// If either is null, this function interpolates from [EdgeInsets.zero].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsets lerp(EdgeInsets a, EdgeInsets b, double t) { static EdgeInsets lerp(EdgeInsets a, EdgeInsets b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
...@@ -770,7 +770,7 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry { ...@@ -770,7 +770,7 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry {
/// (either [EdgeInsets] or [EdgeInsetsDirectional]), consider the /// (either [EdgeInsets] or [EdgeInsetsDirectional]), consider the
/// [EdgeInsetsGeometry.lerp] static method. /// [EdgeInsetsGeometry.lerp] static method.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsetsDirectional lerp(EdgeInsetsDirectional a, EdgeInsetsDirectional b, double t) { static EdgeInsetsDirectional lerp(EdgeInsetsDirectional a, EdgeInsetsDirectional b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -127,7 +127,7 @@ class FlutterLogoDecoration extends Decoration { ...@@ -127,7 +127,7 @@ class FlutterLogoDecoration extends Decoration {
/// non-null value. If one of the values is null, then the result is obtained /// non-null value. If one of the values is null, then the result is obtained
/// by scaling the other value's opacity and [margin]. /// by scaling the other value's opacity and [margin].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
/// ///
/// See also: /// See also:
/// ///
......
...@@ -178,7 +178,7 @@ class FractionalOffset extends Alignment { ...@@ -178,7 +178,7 @@ class FractionalOffset extends Alignment {
/// ///
/// If either is null, this function interpolates from [FractionalOffset.center]. /// If either is null, this function interpolates from [FractionalOffset.center].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static FractionalOffset lerp(FractionalOffset a, FractionalOffset b, double t) { static FractionalOffset lerp(FractionalOffset a, FractionalOffset b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -185,19 +185,7 @@ abstract class Gradient { ...@@ -185,19 +185,7 @@ abstract class Gradient {
/// function instead. If both return null, it returns `a` before `t == 0.5` /// function instead. If both return null, it returns `a` before `t == 0.5`
/// and `b` after `t == 0.5`. /// and `b` after `t == 0.5`.
/// ///
/// {@template flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
/// The `t` argument represents position on the timeline, with 0.0 meaning
/// that the interpolation has not started, returning `a` (or something
/// equivalent to `a`), 1.0 meaning that the interpolation has finished,
/// returning `b` (or something equivalent to `b`), and values in between
/// meaning that the interpolation is at the relevant point on the timeline
/// between `a` and `b`. The interpolation can be extrapolated beyond 0.0 and
/// 1.0, so negative values and values greater than 1.0 are valid (and can
/// easily be generated by curves such as [Curves.elasticInOut]).
///
/// Values for `t` are usually obtained from an [Animation<double>], such as
/// an [AnimationController].
/// {@endtemplate}
static Gradient lerp(Gradient a, Gradient b, double t) { static Gradient lerp(Gradient a, Gradient b, double t) {
assert(t != null); assert(t != null);
Gradient result; Gradient result;
......
...@@ -204,7 +204,7 @@ class ShapeDecoration extends Decoration { ...@@ -204,7 +204,7 @@ class ShapeDecoration extends Decoration {
/// fields are all null (including the [shape], which cannot normally be /// fields are all null (including the [shape], which cannot normally be
/// null). /// null).
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
/// ///
/// See also: /// See also:
/// ///
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui show ParagraphStyle, TextStyle, lerpDouble; import 'dart:ui' as ui show ParagraphStyle, TextStyle, lerpDouble, Shadow;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -238,6 +238,7 @@ class TextStyle extends Diagnosticable { ...@@ -238,6 +238,7 @@ class TextStyle extends Diagnosticable {
this.locale, this.locale,
this.foreground, this.foreground,
this.background, this.background,
this.shadows,
this.decoration, this.decoration,
this.decorationColor, this.decorationColor,
this.decorationStyle, this.decorationStyle,
...@@ -368,6 +369,15 @@ class TextStyle extends Diagnosticable { ...@@ -368,6 +369,15 @@ class TextStyle extends Diagnosticable {
/// [compareTo], and it does not affect [hashCode]. /// [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.
///
/// Multiple shadows are supported to replicate lighting from multiple light
/// sources.
///
/// Shadows must be in the same order for [TextStyle] to be considered as
/// equivalent as order produces differing transparency.
final List<ui.Shadow> shadows;
/// Creates a copy of this text style but with the given fields replaced with /// Creates a copy of this text style but with the given fields replaced with
/// the new values. /// the new values.
/// ///
...@@ -386,6 +396,7 @@ class TextStyle extends Diagnosticable { ...@@ -386,6 +396,7 @@ class TextStyle extends Diagnosticable {
Locale locale, Locale locale,
Paint foreground, Paint foreground,
Paint background, Paint background,
List<ui.Shadow> shadows,
TextDecoration decoration, TextDecoration decoration,
Color decorationColor, Color decorationColor,
TextDecorationStyle decorationStyle, TextDecorationStyle decorationStyle,
...@@ -412,6 +423,7 @@ class TextStyle extends Diagnosticable { ...@@ -412,6 +423,7 @@ class TextStyle extends Diagnosticable {
locale: locale ?? this.locale, locale: locale ?? this.locale,
foreground: foreground ?? this.foreground, foreground: foreground ?? this.foreground,
background: background ?? this.background, background: background ?? this.background,
shadows: shadows ?? this.shadows,
decoration: decoration ?? this.decoration, decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor, decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle, decorationStyle: decorationStyle ?? this.decorationStyle,
...@@ -497,6 +509,7 @@ class TextStyle extends Diagnosticable { ...@@ -497,6 +509,7 @@ class TextStyle extends Diagnosticable {
locale: locale, locale: locale,
foreground: foreground != null ? foreground : null, foreground: foreground != null ? foreground : null,
background: background, background: background,
shadows: shadows,
decoration: decoration ?? this.decoration, decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor, decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle, decorationStyle: decorationStyle ?? this.decorationStyle,
...@@ -547,6 +560,7 @@ class TextStyle extends Diagnosticable { ...@@ -547,6 +560,7 @@ class TextStyle extends Diagnosticable {
locale: other.locale, locale: other.locale,
foreground: other.foreground, foreground: other.foreground,
background: other.background, background: other.background,
shadows: other.shadows,
decoration: other.decoration, decoration: other.decoration,
decorationColor: other.decorationColor, decorationColor: other.decorationColor,
decorationStyle: other.decorationStyle, decorationStyle: other.decorationStyle,
...@@ -558,7 +572,7 @@ class TextStyle extends Diagnosticable { ...@@ -558,7 +572,7 @@ class TextStyle extends Diagnosticable {
/// ///
/// This will not work well if the styles don't set the same fields. /// This will not work well if the styles don't set the same fields.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
/// ///
/// If [foreground] is specified on either of `a` or `b`, both will be treated /// If [foreground] is specified on either of `a` or `b`, both will be treated
/// as if they have a [foreground] paint (creating a new [Paint] if necessary /// as if they have a [foreground] paint (creating a new [Paint] if necessary
...@@ -592,6 +606,7 @@ class TextStyle extends Diagnosticable { ...@@ -592,6 +606,7 @@ class TextStyle extends Diagnosticable {
foreground: t < 0.5 ? null : b.foreground, foreground: t < 0.5 ? null : b.foreground,
background: t < 0.5 ? null : b.background, background: t < 0.5 ? null : b.background,
decoration: t < 0.5 ? null : b.decoration, decoration: t < 0.5 ? null : b.decoration,
shadows: t < 0.5 ? null : b.shadows,
decorationColor: Color.lerp(null, b.decorationColor, t), decorationColor: Color.lerp(null, b.decorationColor, t),
decorationStyle: t < 0.5 ? null : b.decorationStyle, decorationStyle: t < 0.5 ? null : b.decorationStyle,
debugLabel: lerpDebugLabel, debugLabel: lerpDebugLabel,
...@@ -613,6 +628,7 @@ class TextStyle extends Diagnosticable { ...@@ -613,6 +628,7 @@ class TextStyle extends Diagnosticable {
locale: t < 0.5 ? a.locale : null, locale: t < 0.5 ? a.locale : null,
foreground: t < 0.5 ? a.foreground : null, foreground: t < 0.5 ? a.foreground : null,
background: t < 0.5 ? a.background : null, background: t < 0.5 ? a.background : null,
shadows: t < 0.5 ? a.shadows : null,
decoration: t < 0.5 ? a.decoration : null, decoration: t < 0.5 ? a.decoration : null,
decorationColor: Color.lerp(a.decorationColor, null, t), decorationColor: Color.lerp(a.decorationColor, null, t),
decorationStyle: t < 0.5 ? a.decorationStyle : null, decorationStyle: t < 0.5 ? a.decorationStyle : null,
...@@ -638,6 +654,7 @@ class TextStyle extends Diagnosticable { ...@@ -638,6 +654,7 @@ class TextStyle extends Diagnosticable {
: b.foreground ?? (Paint()..color = b.color) : b.foreground ?? (Paint()..color = b.color)
: null, : null,
background: t < 0.5 ? a.background : b.background, background: t < 0.5 ? a.background : b.background,
shadows: t < 0.5 ? a.shadows : b.shadows,
decoration: t < 0.5 ? a.decoration : b.decoration, decoration: t < 0.5 ? a.decoration : b.decoration,
decorationColor: Color.lerp(a.decorationColor, b.decorationColor, t), decorationColor: Color.lerp(a.decorationColor, b.decorationColor, t),
decorationStyle: t < 0.5 ? a.decorationStyle : b.decorationStyle, decorationStyle: t < 0.5 ? a.decorationStyle : b.decorationStyle,
...@@ -663,6 +680,7 @@ class TextStyle extends Diagnosticable { ...@@ -663,6 +680,7 @@ class TextStyle extends Diagnosticable {
locale: locale, locale: locale,
foreground: foreground, foreground: foreground,
background: background, background: background,
shadows: shadows,
); );
} }
...@@ -718,7 +736,8 @@ class TextStyle extends Diagnosticable { ...@@ -718,7 +736,8 @@ class TextStyle extends Diagnosticable {
height != other.height || height != other.height ||
locale != other.locale || locale != other.locale ||
foreground != other.foreground || foreground != other.foreground ||
background != other.background) background != other.background ||
!listEquals(shadows, other.shadows))
return RenderComparison.layout; return RenderComparison.layout;
if (color != other.color || if (color != other.color ||
decoration != other.decoration || decoration != other.decoration ||
...@@ -750,7 +769,8 @@ class TextStyle extends Diagnosticable { ...@@ -750,7 +769,8 @@ class TextStyle extends Diagnosticable {
background == typedOther.background && background == typedOther.background &&
decoration == typedOther.decoration && decoration == typedOther.decoration &&
decorationColor == typedOther.decorationColor && decorationColor == typedOther.decorationColor &&
decorationStyle == typedOther.decorationStyle; decorationStyle == typedOther.decorationStyle &&
listEquals(shadows, typedOther.shadows);
} }
@override @override
...@@ -771,7 +791,8 @@ class TextStyle extends Diagnosticable { ...@@ -771,7 +791,8 @@ class TextStyle extends Diagnosticable {
background, background,
decoration, decoration,
decorationColor, decorationColor,
decorationStyle decorationStyle,
shadows
); );
} }
......
...@@ -449,7 +449,7 @@ class BoxConstraints extends Constraints { ...@@ -449,7 +449,7 @@ class BoxConstraints extends Constraints {
/// If either is null, this function interpolates from a [BoxConstraints] /// If either is null, this function interpolates from a [BoxConstraints]
/// object whose fields are all set to 0.0. /// object whose fields are all set to 0.0.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxConstraints lerp(BoxConstraints a, BoxConstraints b, double t) { static BoxConstraints lerp(BoxConstraints a, BoxConstraints b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -131,7 +131,7 @@ class RelativeRect { ...@@ -131,7 +131,7 @@ class RelativeRect {
/// ///
/// If either rect is null, this function interpolates from [RelativeRect.fill]. /// If either rect is null, this function interpolates from [RelativeRect.fill].
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static RelativeRect lerp(RelativeRect a, RelativeRect b, double t) { static RelativeRect lerp(RelativeRect a, RelativeRect b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -147,7 +147,7 @@ class TableBorder { ...@@ -147,7 +147,7 @@ class TableBorder {
/// If a border is null, it is treated as having only [BorderSide.none] /// If a border is null, it is treated as having only [BorderSide.none]
/// borders. /// borders.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static TableBorder lerp(TableBorder a, TableBorder b, double t) { static TableBorder lerp(TableBorder a, TableBorder b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
......
...@@ -68,7 +68,7 @@ class IconThemeData extends Diagnosticable { ...@@ -68,7 +68,7 @@ class IconThemeData extends Diagnosticable {
/// Linearly interpolate between two icon theme data objects. /// Linearly interpolate between two icon theme data objects.
/// ///
/// {@macro flutter.painting.gradient.lerp} /// {@macro dart.ui.shadow.lerp}
static IconThemeData lerp(IconThemeData a, IconThemeData b, double t) { static IconThemeData lerp(IconThemeData a, IconThemeData b, double t) {
assert(t != null); assert(t != null);
return IconThemeData( return IconThemeData(
......
...@@ -460,6 +460,7 @@ class _TextStyleProxy implements TextStyle { ...@@ -460,6 +460,7 @@ class _TextStyleProxy implements TextStyle {
@override double get letterSpacing => _delegate.letterSpacing; @override double get letterSpacing => _delegate.letterSpacing;
@override TextBaseline get textBaseline => _delegate.textBaseline; @override TextBaseline get textBaseline => _delegate.textBaseline;
@override double get wordSpacing => _delegate.wordSpacing; @override double get wordSpacing => _delegate.wordSpacing;
@override List<Shadow> get shadows => _delegate.shadows;
@override @override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.debug}) => String toString({DiagnosticLevel minLevel = DiagnosticLevel.debug}) =>
...@@ -486,7 +487,7 @@ class _TextStyleProxy implements TextStyle { ...@@ -486,7 +487,7 @@ class _TextStyleProxy implements TextStyle {
} }
@override @override
TextStyle copyWith({Color color, String fontFamily, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, Locale locale, ui.Paint foreground, ui.Paint background, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel}) { TextStyle copyWith({Color color, String fontFamily, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, Locale locale, ui.Paint foreground, ui.Paint background, List<Shadow> shadows, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel}) {
throw UnimplementedError(); throw UnimplementedError();
} }
......
...@@ -163,10 +163,10 @@ void main() { ...@@ -163,10 +163,10 @@ void main() {
final ui.TextStyle ts5 = s5.getTextStyle(); final ui.TextStyle ts5 = s5.getTextStyle();
expect(ts5, equals(ui.TextStyle(fontWeight: FontWeight.w700, fontSize: 12.0, height: 123.0))); expect(ts5, equals(ui.TextStyle(fontWeight: FontWeight.w700, fontSize: 12.0, height: 123.0)));
expect(ts5.toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: FontWeight.w700, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontSize: 12.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 123.0x, locale: unspecified, background: unspecified, foreground: unspecified)'); expect(ts5.toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: FontWeight.w700, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontSize: 12.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 123.0x, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified)');
final ui.TextStyle ts2 = s2.getTextStyle(); final ui.TextStyle ts2 = s2.getTextStyle();
expect(ts2, equals(ui.TextStyle(color: const Color(0xFF00FF00), fontWeight: FontWeight.w800, fontSize: 10.0, height: 100.0))); expect(ts2, equals(ui.TextStyle(color: const Color(0xFF00FF00), fontWeight: FontWeight.w800, fontSize: 10.0, height: 100.0)));
expect(ts2.toString(), 'TextStyle(color: Color(0xff00ff00), decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: FontWeight.w800, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontSize: 10.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 100.0x, locale: unspecified, background: unspecified, foreground: unspecified)'); expect(ts2.toString(), 'TextStyle(color: Color(0xff00ff00), decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: FontWeight.w800, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontSize: 10.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 100.0x, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified)');
final ui.ParagraphStyle ps2 = s2.getParagraphStyle(textAlign: TextAlign.center); final ui.ParagraphStyle ps2 = s2.getParagraphStyle(textAlign: TextAlign.center);
expect(ps2, equals(ui.ParagraphStyle(textAlign: TextAlign.center, fontWeight: FontWeight.w800, fontSize: 10.0, lineHeight: 100.0))); expect(ps2, equals(ui.ParagraphStyle(textAlign: TextAlign.center, fontWeight: FontWeight.w800, fontSize: 10.0, lineHeight: 100.0)));
...@@ -189,11 +189,11 @@ void main() { ...@@ -189,11 +189,11 @@ void main() {
test('TextStyle using package font', () { test('TextStyle using package font', () {
const TextStyle s6 = TextStyle(fontFamily: 'test'); const TextStyle s6 = TextStyle(fontFamily: 'test');
expect(s6.fontFamily, 'test'); expect(s6.fontFamily, 'test');
expect(s6.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, locale: unspecified, background: unspecified, foreground: unspecified)'); expect(s6.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified)');
const TextStyle s7 = TextStyle(fontFamily: 'test', package: 'p'); const TextStyle s7 = TextStyle(fontFamily: 'test', package: 'p');
expect(s7.fontFamily, 'packages/p/test'); expect(s7.fontFamily, 'packages/p/test');
expect(s7.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: packages/p/test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, locale: unspecified, background: unspecified, foreground: unspecified)'); expect(s7.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: packages/p/test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified)');
}); });
test('TextStyle.debugLabel', () { test('TextStyle.debugLabel', () {
......
...@@ -57,7 +57,7 @@ void main() { ...@@ -57,7 +57,7 @@ void main() {
testWidgets('when image pixels do not match', (WidgetTester tester) async { testWidgets('when image pixels do not match', (WidgetTester tester) async {
expect( expect(
await matchesReferenceImage(createTestImage(100, 100, red)).matchAsync(createTestImage(100, 100, transparentRed)), await matchesReferenceImage(createTestImage(100, 100, red)).matchAsync(createTestImage(100, 100, transparentRed)),
equals('does not match on 53 pixels'), equals('does not match on 57 pixels'),
); );
expect( expect(
await matchesReferenceImage(createTestImage(100, 100, red)).matchAsync(createTestImage(100, 100, green)), await matchesReferenceImage(createTestImage(100, 100, red)).matchAsync(createTestImage(100, 100, green)),
......
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