Add SweepGradient (#17368)
This PR adds a SweepGradient class, extending Gradient to expose the engine's ui.Gradient.sweep shader. Similar to LinearGradient and RadialGradient - SweepGradients can be used in a BoxDecoration or passed to a Paint's shader.
This commit is contained in:
parent
6fc7199dcc
commit
d57cc44f05
1
AUTHORS
1
AUTHORS
@ -23,3 +23,4 @@ Ali Bitek <alibitek@protonmail.ch>
|
|||||||
Tetsuhiro Ueda <najeira@gmail.com>
|
Tetsuhiro Ueda <najeira@gmail.com>
|
||||||
Dan Field <dfield@gmail.com>
|
Dan Field <dfield@gmail.com>
|
||||||
Noah Groß <gross@ngsger.de>
|
Noah Groß <gross@ngsger.de>
|
||||||
|
Victor Choueiri <victor@ctrlanddev.com>
|
||||||
|
@ -37,8 +37,8 @@ _ColorsAndStops _interpolateColorsAndStops(List<Color> aColors, List<double> aSt
|
|||||||
|
|
||||||
/// A 2D gradient.
|
/// A 2D gradient.
|
||||||
///
|
///
|
||||||
/// This is an interface that allows [LinearGradient] and [RadialGradient]
|
/// This is an interface that allows [LinearGradient], [RadialGradient], and
|
||||||
/// classes to be used interchangeably in [BoxDecoration]s.
|
/// [SweepGradient] classes to be used interchangeably in [BoxDecoration]s.
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
@ -214,9 +214,9 @@ abstract class Gradient {
|
|||||||
|
|
||||||
/// A 2D linear gradient.
|
/// A 2D linear gradient.
|
||||||
///
|
///
|
||||||
/// This class is used by [BoxDecoration] to represent gradients. This abstracts
|
/// This class is used by [BoxDecoration] to represent linear gradients. This
|
||||||
/// out the arguments to the [new ui.Gradient.linear] constructor from the
|
/// abstracts out the arguments to the [new ui.Gradient.linear] constructor from
|
||||||
/// `dart:ui` library.
|
/// the `dart:ui` library.
|
||||||
///
|
///
|
||||||
/// A gradient has two anchor points, [begin] and [end]. The [begin] point
|
/// A gradient has two anchor points, [begin] and [end]. The [begin] point
|
||||||
/// corresponds to 0.0, and the [end] point corresponds to 1.0. These points are
|
/// corresponds to 0.0, and the [end] point corresponds to 1.0. These points are
|
||||||
@ -258,6 +258,8 @@ abstract class Gradient {
|
|||||||
///
|
///
|
||||||
/// * [RadialGradient], which displays a gradient in concentric circles, and
|
/// * [RadialGradient], which displays a gradient in concentric circles, and
|
||||||
/// has an example which shows a different way to use [Gradient] objects.
|
/// has an example which shows a different way to use [Gradient] objects.
|
||||||
|
/// * [SweepGradient], which displays a gradient in a sweeping arc around a
|
||||||
|
/// center point.
|
||||||
/// * [BoxDecoration], which can take a [LinearGradient] in its
|
/// * [BoxDecoration], which can take a [LinearGradient] in its
|
||||||
/// [BoxDecoration.gradient] property.
|
/// [BoxDecoration.gradient] property.
|
||||||
class LinearGradient extends Gradient {
|
class LinearGradient extends Gradient {
|
||||||
@ -278,14 +280,14 @@ class LinearGradient extends Gradient {
|
|||||||
|
|
||||||
/// The offset at which stop 0.0 of the gradient is placed.
|
/// The offset at which stop 0.0 of the gradient is placed.
|
||||||
///
|
///
|
||||||
/// If this is a [Alignment], then it is expressed as a vector from
|
/// If this is an [Alignment], then it is expressed as a vector from
|
||||||
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
||||||
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
||||||
///
|
///
|
||||||
/// For example, a begin offset of (-1.0, 0.0) is half way down the
|
/// For example, a begin offset of (-1.0, 0.0) is half way down the
|
||||||
/// left side of the box.
|
/// left side of the box.
|
||||||
///
|
///
|
||||||
/// It can also be a [AlignmentDirectional], where the start is the
|
/// It can also be an [AlignmentDirectional], where the start is the
|
||||||
/// left in left-to-right contexts and the right in right-to-left contexts. If
|
/// left in left-to-right contexts and the right in right-to-left contexts. If
|
||||||
/// a text-direction-dependent value is provided here, then the [createShader]
|
/// a text-direction-dependent value is provided here, then the [createShader]
|
||||||
/// method will need to be given a [TextDirection].
|
/// method will need to be given a [TextDirection].
|
||||||
@ -293,14 +295,14 @@ class LinearGradient extends Gradient {
|
|||||||
|
|
||||||
/// The offset at which stop 1.0 of the gradient is placed.
|
/// The offset at which stop 1.0 of the gradient is placed.
|
||||||
///
|
///
|
||||||
/// If this is a [Alignment], then it is expressed as a vector from
|
/// If this is an [Alignment], then it is expressed as a vector from
|
||||||
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
||||||
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
||||||
///
|
///
|
||||||
/// For example, a begin offset of (1.0, 0.0) is half way down the
|
/// For example, a begin offset of (1.0, 0.0) is half way down the
|
||||||
/// right side of the box.
|
/// right side of the box.
|
||||||
///
|
///
|
||||||
/// It can also be a [AlignmentDirectional], where the start is the left in
|
/// It can also be an [AlignmentDirectional], where the start is the left in
|
||||||
/// left-to-right contexts and the right in right-to-left contexts. If a
|
/// left-to-right contexts and the right in right-to-left contexts. If a
|
||||||
/// text-direction-dependent value is provided here, then the [createShader]
|
/// text-direction-dependent value is provided here, then the [createShader]
|
||||||
/// method will need to be given a [TextDirection].
|
/// method will need to be given a [TextDirection].
|
||||||
@ -325,10 +327,10 @@ class LinearGradient extends Gradient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new [LinearGradient] with its properties (in particular the
|
/// Returns a new [LinearGradient] with its colors scaled by the given factor.
|
||||||
/// colors) scaled by the given factor.
|
|
||||||
///
|
///
|
||||||
/// If the factor is 0.0 or less, then the gradient is fully transparent.
|
/// Since the alpha component of the Color is what is scaled, a factor
|
||||||
|
/// of 0.0 or less results in a gradient that is fully transparent.
|
||||||
@override
|
@override
|
||||||
LinearGradient scale(double factor) {
|
LinearGradient scale(double factor) {
|
||||||
return new LinearGradient(
|
return new LinearGradient(
|
||||||
@ -362,7 +364,7 @@ class LinearGradient extends Gradient {
|
|||||||
///
|
///
|
||||||
/// If neither gradient is null, they must have the same number of [colors].
|
/// If neither gradient is null, they must have the same number of [colors].
|
||||||
///
|
///
|
||||||
/// The `t` argument represents position on the timeline, with 0.0 meaning
|
/// The `t` argument represents a position on the timeline, with 0.0 meaning
|
||||||
/// that the interpolation has not started, returning `a` (or something
|
/// that the interpolation has not started, returning `a` (or something
|
||||||
/// equivalent to `a`), 1.0 meaning that the interpolation has finished,
|
/// equivalent to `a`), 1.0 meaning that the interpolation has finished,
|
||||||
/// returning `b` (or something equivalent to `b`), and values in between
|
/// returning `b` (or something equivalent to `b`), and values in between
|
||||||
@ -434,9 +436,9 @@ class LinearGradient extends Gradient {
|
|||||||
|
|
||||||
/// A 2D radial gradient.
|
/// A 2D radial gradient.
|
||||||
///
|
///
|
||||||
/// This class is used by [BoxDecoration] to represent gradients. This abstracts
|
/// This class is used by [BoxDecoration] to represent radial gradients. This
|
||||||
/// out the arguments to the [new ui.Gradient.radial] constructor from the
|
/// abstracts out the arguments to the [new ui.Gradient.radial] constructor from
|
||||||
/// `dart:ui` library.
|
/// the `dart:ui` library.
|
||||||
///
|
///
|
||||||
/// A gradient has a [center] and a [radius]. The [center] point corresponds to
|
/// A gradient has a [center] and a [radius]. The [center] point corresponds to
|
||||||
/// 0.0, and the ring at [radius] from the center corresponds to 1.0. These
|
/// 0.0, and the ring at [radius] from the center corresponds to 1.0. These
|
||||||
@ -483,6 +485,8 @@ class LinearGradient extends Gradient {
|
|||||||
///
|
///
|
||||||
/// * [LinearGradient], which displays a gradient in parallel lines, and has an
|
/// * [LinearGradient], which displays a gradient in parallel lines, and has an
|
||||||
/// example which shows a different way to use [Gradient] objects.
|
/// example which shows a different way to use [Gradient] objects.
|
||||||
|
/// * [SweepGradient], which displays a gradient in a sweeping arc around a
|
||||||
|
/// center point.
|
||||||
/// * [BoxDecoration], which can take a [RadialGradient] in its
|
/// * [BoxDecoration], which can take a [RadialGradient] in its
|
||||||
/// [BoxDecoration.gradient] property.
|
/// [BoxDecoration.gradient] property.
|
||||||
/// * [CustomPainter], which shows how to use the above sample code in a custom
|
/// * [CustomPainter], which shows how to use the above sample code in a custom
|
||||||
@ -509,11 +513,11 @@ class RadialGradient extends Gradient {
|
|||||||
/// For example, an alignment of (0.0, 0.0) will place the radial
|
/// For example, an alignment of (0.0, 0.0) will place the radial
|
||||||
/// gradient in the center of the box.
|
/// gradient in the center of the box.
|
||||||
///
|
///
|
||||||
/// If this is a [Alignment], then it is expressed as a vector from
|
/// If this is an [Alignment], then it is expressed as a vector from
|
||||||
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
||||||
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
||||||
///
|
///
|
||||||
/// It can also be a [AlignmentDirectional], where the start is the left in
|
/// It can also be an [AlignmentDirectional], where the start is the left in
|
||||||
/// left-to-right contexts and the right in right-to-left contexts. If a
|
/// left-to-right contexts and the right in right-to-left contexts. If a
|
||||||
/// text-direction-dependent value is provided here, then the [createShader]
|
/// text-direction-dependent value is provided here, then the [createShader]
|
||||||
/// method will need to be given a [TextDirection].
|
/// method will need to be given a [TextDirection].
|
||||||
@ -548,7 +552,8 @@ class RadialGradient extends Gradient {
|
|||||||
|
|
||||||
/// Returns a new [RadialGradient] with its colors scaled by the given factor.
|
/// Returns a new [RadialGradient] with its colors scaled by the given factor.
|
||||||
///
|
///
|
||||||
/// If the factor is 0.0 or less, then the gradient is fully transparent.
|
/// Since the alpha component of the Color is what is scaled, a factor
|
||||||
|
/// of 0.0 or less results in a gradient that is fully transparent.
|
||||||
@override
|
@override
|
||||||
RadialGradient scale(double factor) {
|
RadialGradient scale(double factor) {
|
||||||
return new RadialGradient(
|
return new RadialGradient(
|
||||||
@ -582,7 +587,7 @@ class RadialGradient extends Gradient {
|
|||||||
///
|
///
|
||||||
/// If neither gradient is null, they must have the same number of [colors].
|
/// If neither gradient is null, they must have the same number of [colors].
|
||||||
///
|
///
|
||||||
/// The `t` argument represents position on the timeline, with 0.0 meaning
|
/// The `t` argument represents a position on the timeline, with 0.0 meaning
|
||||||
/// that the interpolation has not started, returning `a` (or something
|
/// that the interpolation has not started, returning `a` (or something
|
||||||
/// equivalent to `a`), 1.0 meaning that the interpolation has finished,
|
/// equivalent to `a`), 1.0 meaning that the interpolation has finished,
|
||||||
/// returning `b` (or something equivalent to `b`), and values in between
|
/// returning `b` (or something equivalent to `b`), and values in between
|
||||||
@ -651,3 +656,230 @@ class RadialGradient extends Gradient {
|
|||||||
return '$runtimeType($center, $radius, $colors, $stops, $tileMode)';
|
return '$runtimeType($center, $radius, $colors, $stops, $tileMode)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A 2D sweep gradient.
|
||||||
|
///
|
||||||
|
/// This class is used by [BoxDecoration] to represent sweep gradients. This
|
||||||
|
/// abstracts out the arguments to the [new ui.Gradient.sweep] constructor from
|
||||||
|
/// the `dart:ui` library.
|
||||||
|
///
|
||||||
|
/// A gradient has a [center], a [startAngle], and an [endAngle]. The [startAngle]
|
||||||
|
/// corresponds to 0.0, and the [endAngle] corresponds to 1.0. These angles are
|
||||||
|
/// expressed in radians.
|
||||||
|
///
|
||||||
|
/// The [colors] are described by a list of [Color] objects. There must be at
|
||||||
|
/// least two colors. The [stops] list, if specified, must have the same length
|
||||||
|
/// as [colors]. It specifies fractions of the vector from start to end, between
|
||||||
|
/// 0.0 and 1.0, for each color. If it is null, a uniform distribution is
|
||||||
|
/// assumed.
|
||||||
|
///
|
||||||
|
/// The region of the canvas before [startAngle] and after [endAngle] is colored
|
||||||
|
/// according to [tileMode].
|
||||||
|
///
|
||||||
|
/// Typically this class is used with [BoxDecoration], which does the painting.
|
||||||
|
/// To use a [SweepGradient] to paint on a canvas directly, see [createShader].
|
||||||
|
///
|
||||||
|
/// ## Sample code
|
||||||
|
///
|
||||||
|
/// This sample draws a different color in each quadrant.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// new Container(
|
||||||
|
/// decoration: new BoxDecoration(
|
||||||
|
/// gradient: new SweepGradient(
|
||||||
|
/// center: FractionalOffset.center,
|
||||||
|
/// startAngle: 0.0,
|
||||||
|
/// endAngle: math.pi * 2,
|
||||||
|
/// colors: const <Color>[
|
||||||
|
/// const Color(0xFF4285F4), // blue
|
||||||
|
/// const Color(0xFF34A853), // green
|
||||||
|
/// const Color(0xFFFBBC05), // yellow
|
||||||
|
/// const Color(0xFFEA4335), // red
|
||||||
|
/// const Color(0xFF4285F4), // blue again to seamlessly transition to the start
|
||||||
|
/// ],
|
||||||
|
/// stops: const <double>[0.0, 0.25, 0.5, 0.75, 1.0],
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [LinearGradient], which displays a gradient in parallel lines, and has an
|
||||||
|
/// example which shows a different way to use [Gradient] objects.
|
||||||
|
/// * [RadialGradient], which displays a gradient in concentric circles, and
|
||||||
|
/// has an example which shows a different way to use [Gradient] objects.
|
||||||
|
/// * [BoxDecoration], which can take a [SweepGradient] in its
|
||||||
|
/// [BoxDecoration.gradient] property.
|
||||||
|
class SweepGradient extends Gradient {
|
||||||
|
/// Creates a sweep gradient.
|
||||||
|
///
|
||||||
|
/// The [colors] argument must not be null. If [stops] is non-null, it must
|
||||||
|
/// have the same length as [colors].
|
||||||
|
const SweepGradient({
|
||||||
|
this.center: Alignment.center,
|
||||||
|
this.startAngle: 0.0,
|
||||||
|
this.endAngle: math.pi * 2,
|
||||||
|
@required List<Color> colors,
|
||||||
|
List<double> stops,
|
||||||
|
this.tileMode: TileMode.clamp,
|
||||||
|
}) : assert(center != null),
|
||||||
|
assert(startAngle != null),
|
||||||
|
assert(endAngle != null),
|
||||||
|
assert(tileMode != null),
|
||||||
|
super(colors: colors, stops: stops);
|
||||||
|
|
||||||
|
/// The center of the gradient, as an offset into the (-1.0, -1.0) x (1.0, 1.0)
|
||||||
|
/// square describing the gradient which will be mapped onto the paint box.
|
||||||
|
///
|
||||||
|
/// For example, an alignment of (0.0, 0.0) will place the sweep
|
||||||
|
/// gradient in the center of the box.
|
||||||
|
///
|
||||||
|
/// If this is an [Alignment], then it is expressed as a vector from
|
||||||
|
/// coordinate (0.0, 0.0), in a coordinate space that maps the center of the
|
||||||
|
/// paint box at (0.0, 0.0) and the bottom right at (1.0, 1.0).
|
||||||
|
///
|
||||||
|
/// It can also be an [AlignmentDirectional], where the start is the left in
|
||||||
|
/// left-to-right contexts and the right in right-to-left contexts. If a
|
||||||
|
/// text-direction-dependent value is provided here, then the [createShader]
|
||||||
|
/// method will need to be given a [TextDirection].
|
||||||
|
final AlignmentGeometry center;
|
||||||
|
|
||||||
|
/// The angle in radians at which stop 0.0 of the gradient is placed.
|
||||||
|
///
|
||||||
|
/// Defaults to 0.0.
|
||||||
|
final double startAngle;
|
||||||
|
|
||||||
|
/// The angle in radians at which stop 1.0 of the gradient is placed.
|
||||||
|
///
|
||||||
|
/// Defaults to math.pi * 2.
|
||||||
|
final double endAngle;
|
||||||
|
|
||||||
|
/// How this gradient should tile the plane beyond in the region before
|
||||||
|
/// [startAngle] and after [endAngle].
|
||||||
|
///
|
||||||
|
/// For details, see [TileMode].
|
||||||
|
///
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
final TileMode tileMode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Shader createShader(Rect rect, { TextDirection textDirection }) {
|
||||||
|
return new ui.Gradient.sweep(
|
||||||
|
center.resolve(textDirection).withinRect(rect),
|
||||||
|
colors, _impliedStops(), tileMode,
|
||||||
|
startAngle,
|
||||||
|
endAngle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [SweepGradient] with its colors scaled by the given factor.
|
||||||
|
///
|
||||||
|
/// Since the alpha component of the Color is what is scaled, a factor
|
||||||
|
/// of 0.0 or less results in a gradient that is fully transparent.
|
||||||
|
@override
|
||||||
|
SweepGradient scale(double factor) {
|
||||||
|
return new SweepGradient(
|
||||||
|
center: center,
|
||||||
|
startAngle: startAngle,
|
||||||
|
endAngle: endAngle,
|
||||||
|
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)).toList(),
|
||||||
|
stops: stops,
|
||||||
|
tileMode: tileMode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Gradient lerpFrom(Gradient a, double t) {
|
||||||
|
if (a == null || (a is SweepGradient && a.colors.length == colors.length)) // TODO(ianh): remove limitation
|
||||||
|
return SweepGradient.lerp(a, this, t);
|
||||||
|
return super.lerpFrom(a, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Gradient lerpTo(Gradient b, double t) {
|
||||||
|
if (b == null || (b is SweepGradient && b.colors.length == colors.length)) // TODO(ianh): remove limitation
|
||||||
|
return SweepGradient.lerp(this, b, t);
|
||||||
|
return super.lerpTo(b, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Linearly interpolate between two [SweepGradient]s.
|
||||||
|
///
|
||||||
|
/// If either gradient is null, then the non-null gradient is returned with
|
||||||
|
/// its color scaled in the same way as the [scale] function.
|
||||||
|
///
|
||||||
|
/// If neither gradient is null, they must have the same number of [colors].
|
||||||
|
///
|
||||||
|
/// The `t` argument represents a 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].
|
||||||
|
static SweepGradient lerp(SweepGradient a, SweepGradient b, double t) {
|
||||||
|
assert(t != null);
|
||||||
|
if (a == null && b == null)
|
||||||
|
return null;
|
||||||
|
if (a == null)
|
||||||
|
return b.scale(t);
|
||||||
|
if (b == null)
|
||||||
|
return a.scale(1.0 - t);
|
||||||
|
final _ColorsAndStops interpolated = _interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t);
|
||||||
|
return new SweepGradient(
|
||||||
|
center: AlignmentGeometry.lerp(a.center, b.center, t),
|
||||||
|
startAngle: math.max(0.0, ui.lerpDouble(a.startAngle, b.startAngle, t)),
|
||||||
|
endAngle: math.max(0.0, ui.lerpDouble(a.endAngle, b.endAngle, t)),
|
||||||
|
colors: interpolated.colors,
|
||||||
|
stops: interpolated.stops,
|
||||||
|
tileMode: t < 0.5 ? a.tileMode : b.tileMode, // TODO(ianh): interpolate tile mode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
if (identical(this, other))
|
||||||
|
return true;
|
||||||
|
if (runtimeType != other.runtimeType)
|
||||||
|
return false;
|
||||||
|
final SweepGradient typedOther = other;
|
||||||
|
if (center != typedOther.center ||
|
||||||
|
startAngle != typedOther.startAngle ||
|
||||||
|
endAngle != typedOther.endAngle ||
|
||||||
|
tileMode != typedOther.tileMode ||
|
||||||
|
colors?.length != typedOther.colors?.length ||
|
||||||
|
stops?.length != typedOther.stops?.length)
|
||||||
|
return false;
|
||||||
|
if (colors != null) {
|
||||||
|
assert(typedOther.colors != null);
|
||||||
|
assert(colors.length == typedOther.colors.length);
|
||||||
|
for (int i = 0; i < colors.length; i += 1) {
|
||||||
|
if (colors[i] != typedOther.colors[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stops != null) {
|
||||||
|
assert(typedOther.stops != null);
|
||||||
|
assert(stops.length == typedOther.stops.length);
|
||||||
|
for (int i = 0; i < stops.length; i += 1) {
|
||||||
|
if (stops[i] != typedOther.stops[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => hashValues(center, startAngle, endAngle, tileMode, hashList(colors), hashList(stops));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return '$runtimeType($center, $startAngle, $endAngle, $colors, $stops, $tileMode)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -233,9 +233,9 @@ class ShaderMask extends SingleChildRenderObjectWidget {
|
|||||||
/// The shader callback is called with the current size of the child so that
|
/// The shader callback is called with the current size of the child so that
|
||||||
/// it can customize the shader to the size and location of the child.
|
/// it can customize the shader to the size and location of the child.
|
||||||
///
|
///
|
||||||
/// Typically this will use a [LinearGradient] or [RadialGradient] to create
|
/// Typically this will use a [LinearGradient], [RadialGradient], or
|
||||||
/// the [dart:ui.Shader], though the [dart:ui.ImageShader] class could also be
|
/// [SweepGradient] to create the [dart:ui.Shader], though the
|
||||||
/// used.
|
/// [dart:ui.ImageShader] class could also be used.
|
||||||
final ShaderCallback shaderCallback;
|
final ShaderCallback shaderCallback;
|
||||||
|
|
||||||
/// The [BlendMode] to use when applying the shader to the child.
|
/// The [BlendMode] to use when applying the shader to the child.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
// 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:math' as math;
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
@ -193,6 +194,45 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('SweepGradient with AlignmentDirectional', () {
|
||||||
|
expect(
|
||||||
|
() {
|
||||||
|
return const SweepGradient(
|
||||||
|
center: AlignmentDirectional.topStart,
|
||||||
|
colors: const <Color>[ const Color(0xFFFFFFFF), const Color(0xFFFFFFFF) ]
|
||||||
|
).createShader(new Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
|
||||||
|
},
|
||||||
|
throwsAssertionError,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
() {
|
||||||
|
return const SweepGradient(
|
||||||
|
center: AlignmentDirectional.topStart,
|
||||||
|
colors: const <Color>[ const Color(0xFFFFFFFF), const Color(0xFFFFFFFF) ]
|
||||||
|
).createShader(new Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl);
|
||||||
|
},
|
||||||
|
returnsNormally,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
() {
|
||||||
|
return const SweepGradient(
|
||||||
|
center: AlignmentDirectional.topStart,
|
||||||
|
colors: const <Color>[ const Color(0xFFFFFFFF), const Color(0xFFFFFFFF) ]
|
||||||
|
).createShader(new Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr);
|
||||||
|
},
|
||||||
|
returnsNormally,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
() {
|
||||||
|
return const SweepGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
colors: const <Color>[ const Color(0xFFFFFFFF), const Color(0xFFFFFFFF) ]
|
||||||
|
).createShader(new Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
|
||||||
|
},
|
||||||
|
returnsNormally,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('RadialGradient lerp test', () {
|
test('RadialGradient lerp test', () {
|
||||||
const RadialGradient testGradient1 = const RadialGradient(
|
const RadialGradient testGradient1 = const RadialGradient(
|
||||||
center: Alignment.topLeft,
|
center: Alignment.topLeft,
|
||||||
@ -263,6 +303,106 @@ void main() {
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('SweepGradient lerp test', () {
|
||||||
|
const SweepGradient testGradient1 = const SweepGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
startAngle: 0.0,
|
||||||
|
endAngle: math.pi / 2,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x33333333),
|
||||||
|
const Color(0x66666666),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
const SweepGradient testGradient2 = const SweepGradient(
|
||||||
|
center: Alignment.topRight,
|
||||||
|
startAngle: math.pi / 2,
|
||||||
|
endAngle: math.pi,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x44444444),
|
||||||
|
const Color(0x88888888),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final SweepGradient actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
|
||||||
|
expect(actual, const SweepGradient(
|
||||||
|
center: const Alignment(0.0, -1.0),
|
||||||
|
startAngle: math.pi / 4,
|
||||||
|
endAngle: math.pi * 3/4,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x3B3B3B3B),
|
||||||
|
const Color(0x77777777),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('SweepGradient lerp test with stops', () {
|
||||||
|
const SweepGradient testGradient1 = const SweepGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
startAngle: 0.0,
|
||||||
|
endAngle: math.pi / 2,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x33333333),
|
||||||
|
const Color(0x66666666),
|
||||||
|
],
|
||||||
|
stops: const <double>[
|
||||||
|
0.0,
|
||||||
|
0.5,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
const SweepGradient testGradient2 = const SweepGradient(
|
||||||
|
center: Alignment.topRight,
|
||||||
|
startAngle: math.pi / 2,
|
||||||
|
endAngle: math.pi,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x44444444),
|
||||||
|
const Color(0x88888888),
|
||||||
|
],
|
||||||
|
stops: const <double>[
|
||||||
|
0.5,
|
||||||
|
1.0,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final SweepGradient actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
|
||||||
|
expect(actual, const SweepGradient(
|
||||||
|
center: const Alignment(0.0, -1.0),
|
||||||
|
startAngle: math.pi / 4,
|
||||||
|
endAngle: math.pi * 3/4,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x3B3B3B3B),
|
||||||
|
const Color(0x77777777),
|
||||||
|
],
|
||||||
|
stops: const <double>[
|
||||||
|
0.25,
|
||||||
|
0.75,
|
||||||
|
],
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('SweepGradient scale test)', () {
|
||||||
|
const SweepGradient testGradient = const SweepGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
startAngle: 0.0,
|
||||||
|
endAngle: math.pi / 2,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0xff333333),
|
||||||
|
const Color(0xff666666),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final SweepGradient actual = testGradient.scale(0.5);
|
||||||
|
|
||||||
|
expect(actual, const SweepGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
startAngle: 0.0,
|
||||||
|
endAngle: math.pi / 2,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x80333333),
|
||||||
|
const Color(0x80666666),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
test('Gradient lerp test (with RadialGradient)', () {
|
test('Gradient lerp test (with RadialGradient)', () {
|
||||||
const RadialGradient testGradient1 = const RadialGradient(
|
const RadialGradient testGradient1 = const RadialGradient(
|
||||||
center: Alignment.topLeft,
|
center: Alignment.topLeft,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user