Unverified Commit 1ca2e0b5 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Fix `CastError` in `StadiumBorder.lerpTo` and `StadiumBorder.lerpFrom` when...

Fix `CastError` in `StadiumBorder.lerpTo` and  `StadiumBorder.lerpFrom` when using `BorderRadiusDirectional` (#114826)

* Fix casting in StadiumBorder lerp

* Add tests

* Fix made-up names
parent 585d4457
...@@ -57,7 +57,7 @@ class RoundedRectangleBorder extends OutlinedBorder { ...@@ -57,7 +57,7 @@ class RoundedRectangleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
circleness: 1.0 - t, circularity: 1.0 - t,
eccentricity: a.eccentricity, eccentricity: a.eccentricity,
); );
} }
...@@ -77,7 +77,7 @@ class RoundedRectangleBorder extends OutlinedBorder { ...@@ -77,7 +77,7 @@ class RoundedRectangleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
circleness: t, circularity: t,
eccentricity: b.eccentricity, eccentricity: b.eccentricity,
); );
} }
...@@ -163,14 +163,14 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -163,14 +163,14 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
const _RoundedRectangleToCircleBorder({ const _RoundedRectangleToCircleBorder({
super.side, super.side,
this.borderRadius = BorderRadius.zero, this.borderRadius = BorderRadius.zero,
required this.circleness, required this.circularity,
required this.eccentricity, required this.eccentricity,
}) : assert(side != null), }) : assert(side != null),
assert(borderRadius != null), assert(borderRadius != null),
assert(circleness != null); assert(circularity != null);
final BorderRadiusGeometry borderRadius; final BorderRadiusGeometry borderRadius;
final double circleness; final double circularity;
final double eccentricity; final double eccentricity;
@override @override
...@@ -178,7 +178,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -178,7 +178,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: side.scale(t), side: side.scale(t),
borderRadius: borderRadius * t, borderRadius: borderRadius * t,
circleness: t, circularity: t,
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
...@@ -190,7 +190,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -190,7 +190,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!, borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
circleness: circleness * t, circularity: circularity * t,
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
...@@ -198,7 +198,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -198,7 +198,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
circleness: circleness + (1.0 - circleness) * (1.0 - t), circularity: circularity + (1.0 - circularity) * (1.0 - t),
eccentricity: a.eccentricity, eccentricity: a.eccentricity,
); );
} }
...@@ -206,7 +206,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -206,7 +206,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!, borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
circleness: ui.lerpDouble(a.circleness, circleness, t)!, circularity: ui.lerpDouble(a.circularity, circularity, t)!,
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
...@@ -219,7 +219,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -219,7 +219,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!, borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
circleness: circleness * (1.0 - t), circularity: circularity * (1.0 - t),
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
...@@ -227,7 +227,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -227,7 +227,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
circleness: circleness + (1.0 - circleness) * t, circularity: circularity + (1.0 - circularity) * t,
eccentricity: b.eccentricity, eccentricity: b.eccentricity,
); );
} }
...@@ -235,7 +235,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -235,7 +235,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!, borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
circleness: ui.lerpDouble(circleness, b.circleness, t)!, circularity: ui.lerpDouble(circularity, b.circularity, t)!,
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
...@@ -243,12 +243,12 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -243,12 +243,12 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
} }
Rect _adjustRect(Rect rect) { Rect _adjustRect(Rect rect) {
if (circleness == 0.0 || rect.width == rect.height) { if (circularity == 0.0 || rect.width == rect.height) {
return rect; return rect;
} }
if (rect.width < rect.height) { if (rect.width < rect.height) {
final double partialDelta = (rect.height - rect.width) / 2; final double partialDelta = (rect.height - rect.width) / 2;
final double delta = circleness * partialDelta * (1.0 - eccentricity); final double delta = circularity * partialDelta * (1.0 - eccentricity);
return Rect.fromLTRB( return Rect.fromLTRB(
rect.left, rect.left,
rect.top + delta, rect.top + delta,
...@@ -257,7 +257,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -257,7 +257,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
); );
} else { } else {
final double partialDelta = (rect.width - rect.height) / 2; final double partialDelta = (rect.width - rect.height) / 2;
final double delta = circleness * partialDelta * (1.0 - eccentricity); final double delta = circularity * partialDelta * (1.0 - eccentricity);
return Rect.fromLTRB( return Rect.fromLTRB(
rect.left + delta, rect.left + delta,
rect.top, rect.top,
...@@ -269,7 +269,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -269,7 +269,7 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
BorderRadius? _adjustBorderRadius(Rect rect, TextDirection? textDirection) { BorderRadius? _adjustBorderRadius(Rect rect, TextDirection? textDirection) {
final BorderRadius resolvedRadius = borderRadius.resolve(textDirection); final BorderRadius resolvedRadius = borderRadius.resolve(textDirection);
if (circleness == 0.0) { if (circularity == 0.0) {
return resolvedRadius; return resolvedRadius;
} }
if (eccentricity != 0.0) { if (eccentricity != 0.0) {
...@@ -277,17 +277,17 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -277,17 +277,17 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return BorderRadius.lerp( return BorderRadius.lerp(
resolvedRadius, resolvedRadius,
BorderRadius.all(Radius.elliptical(rect.width / 2, (0.5 + eccentricity / 2) * rect.height / 2)), BorderRadius.all(Radius.elliptical(rect.width / 2, (0.5 + eccentricity / 2) * rect.height / 2)),
circleness, circularity,
)!; )!;
} else { } else {
return BorderRadius.lerp( return BorderRadius.lerp(
resolvedRadius, resolvedRadius,
BorderRadius.all(Radius.elliptical((0.5 + eccentricity / 2) * rect.width / 2, rect.height / 2)), BorderRadius.all(Radius.elliptical((0.5 + eccentricity / 2) * rect.width / 2, rect.height / 2)),
circleness, circularity,
)!; )!;
} }
} }
return BorderRadius.lerp(resolvedRadius, BorderRadius.circular(rect.shortestSide / 2), circleness); return BorderRadius.lerp(resolvedRadius, BorderRadius.circular(rect.shortestSide / 2), circularity);
} }
@override @override
...@@ -318,11 +318,11 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -318,11 +318,11 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
bool get preferPaintInterior => true; bool get preferPaintInterior => true;
@override @override
_RoundedRectangleToCircleBorder copyWith({ BorderSide? side, BorderRadiusGeometry? borderRadius, double? circleness, double? eccentricity }) { _RoundedRectangleToCircleBorder copyWith({ BorderSide? side, BorderRadiusGeometry? borderRadius, double? circularity, double? eccentricity }) {
return _RoundedRectangleToCircleBorder( return _RoundedRectangleToCircleBorder(
side: side ?? this.side, side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius, borderRadius: borderRadius ?? this.borderRadius,
circleness: circleness ?? this.circleness, circularity: circularity ?? this.circularity,
eccentricity: eccentricity ?? this.eccentricity, eccentricity: eccentricity ?? this.eccentricity,
); );
} }
...@@ -347,17 +347,17 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder { ...@@ -347,17 +347,17 @@ class _RoundedRectangleToCircleBorder extends OutlinedBorder {
return other is _RoundedRectangleToCircleBorder return other is _RoundedRectangleToCircleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius && other.borderRadius == borderRadius
&& other.circleness == circleness; && other.circularity == circularity;
} }
@override @override
int get hashCode => Object.hash(side, borderRadius, circleness); int get hashCode => Object.hash(side, borderRadius, circularity);
@override @override
String toString() { String toString() {
if (eccentricity != 0.0) { if (eccentricity != 0.0) {
return 'RoundedRectangleBorder($side, $borderRadius, ${(circleness * 100).toStringAsFixed(1)}% of the way to being a CircleBorder that is ${(eccentricity * 100).toStringAsFixed(1)}% oval)'; return 'RoundedRectangleBorder($side, $borderRadius, ${(circularity * 100).toStringAsFixed(1)}% of the way to being a CircleBorder that is ${(eccentricity * 100).toStringAsFixed(1)}% oval)';
} }
return 'RoundedRectangleBorder($side, $borderRadius, ${(circleness * 100).toStringAsFixed(1)}% of the way to being a CircleBorder)'; return 'RoundedRectangleBorder($side, $borderRadius, ${(circularity * 100).toStringAsFixed(1)}% of the way to being a CircleBorder)';
} }
} }
...@@ -41,15 +41,15 @@ class StadiumBorder extends OutlinedBorder { ...@@ -41,15 +41,15 @@ class StadiumBorder extends OutlinedBorder {
if (a is CircleBorder) { if (a is CircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
circleness: 1.0 - t, circularity: 1.0 - t,
eccentricity: a.eccentricity, eccentricity: a.eccentricity,
); );
} }
if (a is RoundedRectangleBorder) { if (a is RoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: a.borderRadius as BorderRadius, borderRadius: a.borderRadius,
rectness: 1.0 - t, rectilinearity: 1.0 - t,
); );
} }
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
...@@ -64,15 +64,15 @@ class StadiumBorder extends OutlinedBorder { ...@@ -64,15 +64,15 @@ class StadiumBorder extends OutlinedBorder {
if (b is CircleBorder) { if (b is CircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
circleness: t, circularity: t,
eccentricity: b.eccentricity, eccentricity: b.eccentricity,
); );
} }
if (b is RoundedRectangleBorder) { if (b is RoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: b.borderRadius as BorderRadius, borderRadius: b.borderRadius,
rectness: t, rectilinearity: t,
); );
} }
return super.lerpTo(b, t); return super.lerpTo(b, t);
...@@ -142,19 +142,19 @@ class StadiumBorder extends OutlinedBorder { ...@@ -142,19 +142,19 @@ class StadiumBorder extends OutlinedBorder {
class _StadiumToCircleBorder extends OutlinedBorder { class _StadiumToCircleBorder extends OutlinedBorder {
const _StadiumToCircleBorder({ const _StadiumToCircleBorder({
super.side, super.side,
this.circleness = 0.0, this.circularity = 0.0,
required this.eccentricity, required this.eccentricity,
}) : assert(side != null), }) : assert(side != null),
assert(circleness != null); assert(circularity != null);
final double circleness; final double circularity;
final double eccentricity; final double eccentricity;
@override @override
ShapeBorder scale(double t) { ShapeBorder scale(double t) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: side.scale(t), side: side.scale(t),
circleness: t, circularity: t,
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
...@@ -165,21 +165,21 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -165,21 +165,21 @@ class _StadiumToCircleBorder extends OutlinedBorder {
if (a is StadiumBorder) { if (a is StadiumBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
circleness: circleness * t, circularity: circularity * t,
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
if (a is CircleBorder) { if (a is CircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
circleness: circleness + (1.0 - circleness) * (1.0 - t), circularity: circularity + (1.0 - circularity) * (1.0 - t),
eccentricity: a.eccentricity, eccentricity: a.eccentricity,
); );
} }
if (a is _StadiumToCircleBorder) { if (a is _StadiumToCircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
circleness: ui.lerpDouble(a.circleness, circleness, t)!, circularity: ui.lerpDouble(a.circularity, circularity, t)!,
eccentricity: ui.lerpDouble(a.eccentricity, eccentricity, t)!, eccentricity: ui.lerpDouble(a.eccentricity, eccentricity, t)!,
); );
} }
...@@ -192,21 +192,21 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -192,21 +192,21 @@ class _StadiumToCircleBorder extends OutlinedBorder {
if (b is StadiumBorder) { if (b is StadiumBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
circleness: circleness * (1.0 - t), circularity: circularity * (1.0 - t),
eccentricity: eccentricity, eccentricity: eccentricity,
); );
} }
if (b is CircleBorder) { if (b is CircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
circleness: circleness + (1.0 - circleness) * t, circularity: circularity + (1.0 - circularity) * t,
eccentricity: b.eccentricity, eccentricity: b.eccentricity,
); );
} }
if (b is _StadiumToCircleBorder) { if (b is _StadiumToCircleBorder) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
circleness: ui.lerpDouble(circleness, b.circleness, t)!, circularity: ui.lerpDouble(circularity, b.circularity, t)!,
eccentricity: ui.lerpDouble(eccentricity, b.eccentricity, t)!, eccentricity: ui.lerpDouble(eccentricity, b.eccentricity, t)!,
); );
} }
...@@ -214,12 +214,12 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -214,12 +214,12 @@ class _StadiumToCircleBorder extends OutlinedBorder {
} }
Rect _adjustRect(Rect rect) { Rect _adjustRect(Rect rect) {
if (circleness == 0.0 || rect.width == rect.height) { if (circularity == 0.0 || rect.width == rect.height) {
return rect; return rect;
} }
if (rect.width < rect.height) { if (rect.width < rect.height) {
final double partialDelta = (rect.height - rect.width) / 2; final double partialDelta = (rect.height - rect.width) / 2;
final double delta = circleness * partialDelta * (1.0 - eccentricity); final double delta = circularity * partialDelta * (1.0 - eccentricity);
return Rect.fromLTRB( return Rect.fromLTRB(
rect.left, rect.left,
rect.top + delta, rect.top + delta,
...@@ -228,7 +228,7 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -228,7 +228,7 @@ class _StadiumToCircleBorder extends OutlinedBorder {
); );
} else { } else {
final double partialDelta = (rect.width - rect.height) / 2; final double partialDelta = (rect.width - rect.height) / 2;
final double delta = circleness * partialDelta * (1.0 - eccentricity); final double delta = circularity * partialDelta * (1.0 - eccentricity);
return Rect.fromLTRB( return Rect.fromLTRB(
rect.left + delta, rect.left + delta,
rect.top, rect.top,
...@@ -245,13 +245,13 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -245,13 +245,13 @@ class _StadiumToCircleBorder extends OutlinedBorder {
return BorderRadius.lerp( return BorderRadius.lerp(
circleRadius, circleRadius,
BorderRadius.all(Radius.elliptical(rect.width / 2, (0.5 + eccentricity / 2) * rect.height / 2)), BorderRadius.all(Radius.elliptical(rect.width / 2, (0.5 + eccentricity / 2) * rect.height / 2)),
circleness, circularity,
)!; )!;
} else { } else {
return BorderRadius.lerp( return BorderRadius.lerp(
circleRadius, circleRadius,
BorderRadius.all(Radius.elliptical((0.5 + eccentricity / 2) * rect.width / 2, rect.height / 2)), BorderRadius.all(Radius.elliptical((0.5 + eccentricity / 2) * rect.width / 2, rect.height / 2)),
circleness, circularity,
)!; )!;
} }
} }
...@@ -279,10 +279,10 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -279,10 +279,10 @@ class _StadiumToCircleBorder extends OutlinedBorder {
bool get preferPaintInterior => true; bool get preferPaintInterior => true;
@override @override
_StadiumToCircleBorder copyWith({ BorderSide? side, double? circleness, double? eccentricity }) { _StadiumToCircleBorder copyWith({ BorderSide? side, double? circularity, double? eccentricity }) {
return _StadiumToCircleBorder( return _StadiumToCircleBorder(
side: side ?? this.side, side: side ?? this.side,
circleness: circleness ?? this.circleness, circularity: circularity ?? this.circularity,
eccentricity: eccentricity ?? this.eccentricity, eccentricity: eccentricity ?? this.eccentricity,
); );
} }
...@@ -305,18 +305,18 @@ class _StadiumToCircleBorder extends OutlinedBorder { ...@@ -305,18 +305,18 @@ class _StadiumToCircleBorder extends OutlinedBorder {
} }
return other is _StadiumToCircleBorder return other is _StadiumToCircleBorder
&& other.side == side && other.side == side
&& other.circleness == circleness; && other.circularity == circularity;
} }
@override @override
int get hashCode => Object.hash(side, circleness); int get hashCode => Object.hash(side, circularity);
@override @override
String toString() { String toString() {
if (eccentricity != 0.0) { if (eccentricity != 0.0) {
return 'StadiumBorder($side, ${(circleness * 100).toStringAsFixed(1)}% of the way to being a CircleBorder that is ${(eccentricity * 100).toStringAsFixed(1)}% oval)'; return 'StadiumBorder($side, ${(circularity * 100).toStringAsFixed(1)}% of the way to being a CircleBorder that is ${(eccentricity * 100).toStringAsFixed(1)}% oval)';
} }
return 'StadiumBorder($side, ${(circleness * 100).toStringAsFixed(1)}% of the way to being a CircleBorder)'; return 'StadiumBorder($side, ${(circularity * 100).toStringAsFixed(1)}% of the way to being a CircleBorder)';
} }
} }
...@@ -325,21 +325,21 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -325,21 +325,21 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
const _StadiumToRoundedRectangleBorder({ const _StadiumToRoundedRectangleBorder({
super.side, super.side,
this.borderRadius = BorderRadius.zero, this.borderRadius = BorderRadius.zero,
this.rectness = 0.0, this.rectilinearity = 0.0,
}) : assert(side != null), }) : assert(side != null),
assert(borderRadius != null), assert(borderRadius != null),
assert(rectness != null); assert(rectilinearity != null);
final BorderRadius borderRadius; final BorderRadiusGeometry borderRadius;
final double rectness; final double rectilinearity;
@override @override
ShapeBorder scale(double t) { ShapeBorder scale(double t) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: side.scale(t), side: side.scale(t),
borderRadius: borderRadius * t, borderRadius: borderRadius * t,
rectness: t, rectilinearity: t,
); );
} }
...@@ -350,21 +350,21 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -350,21 +350,21 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
rectness: rectness * t, rectilinearity: rectilinearity * t,
); );
} }
if (a is RoundedRectangleBorder) { if (a is RoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
rectness: rectness + (1.0 - rectness) * (1.0 - t), rectilinearity: rectilinearity + (1.0 - rectilinearity) * (1.0 - t),
); );
} }
if (a is _StadiumToRoundedRectangleBorder) { if (a is _StadiumToRoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t)!, borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
rectness: ui.lerpDouble(a.rectness, rectness, t)!, rectilinearity: ui.lerpDouble(a.rectilinearity, rectilinearity, t)!,
); );
} }
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
...@@ -377,37 +377,37 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -377,37 +377,37 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
rectness: rectness * (1.0 - t), rectilinearity: rectilinearity * (1.0 - t),
); );
} }
if (b is RoundedRectangleBorder) { if (b is RoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: borderRadius, borderRadius: borderRadius,
rectness: rectness + (1.0 - rectness) * t, rectilinearity: rectilinearity + (1.0 - rectilinearity) * t,
); );
} }
if (b is _StadiumToRoundedRectangleBorder) { if (b is _StadiumToRoundedRectangleBorder) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t)!, borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
rectness: ui.lerpDouble(rectness, b.rectness, t)!, rectilinearity: ui.lerpDouble(rectilinearity, b.rectilinearity, t)!,
); );
} }
return super.lerpTo(b, t); return super.lerpTo(b, t);
} }
BorderRadius _adjustBorderRadius(Rect rect) { BorderRadiusGeometry _adjustBorderRadius(Rect rect) {
return BorderRadius.lerp( return BorderRadiusGeometry.lerp(
borderRadius, borderRadius,
BorderRadius.all(Radius.circular(rect.shortestSide / 2.0)), BorderRadius.all(Radius.circular(rect.shortestSide / 2.0)),
1.0 - rectness, 1.0 - rectilinearity,
)!; )!;
} }
@override @override
Path getInnerPath(Rect rect, { TextDirection? textDirection }) { Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
final RRect borderRect = _adjustBorderRadius(rect).toRRect(rect); final RRect borderRect = _adjustBorderRadius(rect).resolve(textDirection).toRRect(rect);
final RRect adjustedRect = borderRect.deflate(ui.lerpDouble(side.width, 0, side.strokeAlign)!); final RRect adjustedRect = borderRect.deflate(ui.lerpDouble(side.width, 0, side.strokeAlign)!);
return Path() return Path()
..addRRect(adjustedRect); ..addRRect(adjustedRect);
...@@ -416,16 +416,16 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -416,16 +416,16 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
@override @override
Path getOuterPath(Rect rect, { TextDirection? textDirection }) { Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return Path() return Path()
..addRRect(_adjustBorderRadius(rect).toRRect(rect)); ..addRRect(_adjustBorderRadius(rect).resolve(textDirection).toRRect(rect));
} }
@override @override
void paintInterior(Canvas canvas, Rect rect, Paint paint, { TextDirection? textDirection }) { void paintInterior(Canvas canvas, Rect rect, Paint paint, { TextDirection? textDirection }) {
final BorderRadius adjustedBorderRadius = _adjustBorderRadius(rect); final BorderRadiusGeometry adjustedBorderRadius = _adjustBorderRadius(rect);
if (adjustedBorderRadius == BorderRadius.zero) { if (adjustedBorderRadius == BorderRadius.zero) {
canvas.drawRect(rect, paint); canvas.drawRect(rect, paint);
} else { } else {
canvas.drawRRect(adjustedBorderRadius.toRRect(rect), paint); canvas.drawRRect(adjustedBorderRadius.resolve(textDirection).toRRect(rect), paint);
} }
} }
...@@ -433,11 +433,11 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -433,11 +433,11 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
bool get preferPaintInterior => true; bool get preferPaintInterior => true;
@override @override
_StadiumToRoundedRectangleBorder copyWith({ BorderSide? side, BorderRadius? borderRadius, double? rectness }) { _StadiumToRoundedRectangleBorder copyWith({ BorderSide? side, BorderRadiusGeometry? borderRadius, double? rectilinearity }) {
return _StadiumToRoundedRectangleBorder( return _StadiumToRoundedRectangleBorder(
side: side ?? this.side, side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius, borderRadius: borderRadius ?? this.borderRadius,
rectness: rectness ?? this.rectness, rectilinearity: rectilinearity ?? this.rectilinearity,
); );
} }
...@@ -447,7 +447,7 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -447,7 +447,7 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
case BorderStyle.none: case BorderStyle.none:
break; break;
case BorderStyle.solid: case BorderStyle.solid:
final BorderRadius adjustedBorderRadius = _adjustBorderRadius(rect); final BorderRadiusGeometry adjustedBorderRadius = _adjustBorderRadius(rect);
final RRect borderRect = adjustedBorderRadius.resolve(textDirection).toRRect(rect); final RRect borderRect = adjustedBorderRadius.resolve(textDirection).toRRect(rect);
canvas.drawRRect(borderRect.inflate(side.strokeOffset / 2), side.toPaint()); canvas.drawRRect(borderRect.inflate(side.strokeOffset / 2), side.toPaint());
} }
...@@ -461,16 +461,16 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder { ...@@ -461,16 +461,16 @@ class _StadiumToRoundedRectangleBorder extends OutlinedBorder {
return other is _StadiumToRoundedRectangleBorder return other is _StadiumToRoundedRectangleBorder
&& other.side == side && other.side == side
&& other.borderRadius == borderRadius && other.borderRadius == borderRadius
&& other.rectness == rectness; && other.rectilinearity == rectilinearity;
} }
@override @override
int get hashCode => Object.hash(side, borderRadius, rectness); int get hashCode => Object.hash(side, borderRadius, rectilinearity);
@override @override
String toString() { String toString() {
return 'StadiumBorder($side, $borderRadius, ' return 'StadiumBorder($side, $borderRadius, '
'${(rectness * 100).toStringAsFixed(1)}% of the way to being a ' '${(rectilinearity * 100).toStringAsFixed(1)}% of the way to being a '
'RoundedRectangleBorder)'; 'RoundedRectangleBorder)';
} }
} }
...@@ -137,7 +137,7 @@ void main() { ...@@ -137,7 +137,7 @@ void main() {
expect(direct50.toString(), indirect50.toString()); expect(direct50.toString(), indirect50.toString());
}); });
test('StadiumBorder and RoundedRectBorder', () { test('StadiumBorder and RoundedRectBorder with BorderRadius.zero', () {
const StadiumBorder stadium = StadiumBorder(); const StadiumBorder stadium = StadiumBorder();
const RoundedRectangleBorder rrect = RoundedRectangleBorder(); const RoundedRectangleBorder rrect = RoundedRectangleBorder();
const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 50.0); const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 50.0);
...@@ -221,4 +221,184 @@ void main() { ...@@ -221,4 +221,184 @@ void main() {
expect(direct50.hashCode, indirect50.hashCode); expect(direct50.hashCode, indirect50.hashCode);
expect(direct50.toString(), indirect50.toString()); expect(direct50.toString(), indirect50.toString());
}); });
test('StadiumBorder and RoundedRectBorder with circular BorderRadius', () {
const StadiumBorder stadium = StadiumBorder();
const RoundedRectangleBorder rrect = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10)));
const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 50.0);
final Matcher looksLikeS = isPathThat(
includes: const <Offset>[
Offset(25.0, 25.0),
Offset(50.0, 25.0),
Offset(7.33, 7.33),
],
excludes: const <Offset>[
Offset(0.001, 0.001),
Offset(99.999, 0.001),
Offset(99.999, 49.999),
Offset(0.001, 49.999),
],
);
final Matcher looksLikeR = isPathThat(
includes: const <Offset>[
Offset(25.0, 25.0),
Offset(50.0, 25.0),
Offset(7.33, 7.33),
Offset(4.0, 4.0),
Offset(96.0, 4.0),
Offset(96.0, 46.0),
Offset(4.0, 46.0),
],
);
expect(stadium.getOuterPath(rect), looksLikeS);
expect(rrect.getOuterPath(rect), looksLikeR);
expect(ShapeBorder.lerp(stadium, rrect, 0.1)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(stadium, rrect, 0.9)!.getOuterPath(rect), looksLikeR);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.9), stadium, 0.1)!.getOuterPath(rect), looksLikeR);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.9), stadium, 0.9)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), rrect, 0.1)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), rrect, 0.9)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.9), 0.1)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.9), 0.9)!.getOuterPath(rect), looksLikeR);
expect(ShapeBorder.lerp(stadium, ShapeBorder.lerp(stadium, rrect, 0.9), 0.1)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(stadium, ShapeBorder.lerp(stadium, rrect, 0.9), 0.9)!.getOuterPath(rect), looksLikeR);
expect(ShapeBorder.lerp(rrect, ShapeBorder.lerp(stadium, rrect, 0.1), 0.1)!.getOuterPath(rect), looksLikeS);
expect(ShapeBorder.lerp(rrect, ShapeBorder.lerp(stadium, rrect, 0.1), 0.9)!.getOuterPath(rect), looksLikeS);
expect(
ShapeBorder.lerp(stadium, rrect, 0.1).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadius.circular(10.0), 10.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(stadium, rrect, 0.2).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadius.circular(10.0), 20.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.9), 0.9).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadius.circular(10.0), 82.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(rrect, stadium, 0.9).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadius.circular(10.0), 10.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(rrect, stadium, 0.8).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadius.circular(10.0), 20.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.9), ShapeBorder.lerp(stadium, rrect, 0.1), 0.1).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadius.circular(10.0), 82.0% of the way to being a RoundedRectangleBorder)',
);
expect(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.1));
expect(ShapeBorder.lerp(stadium, rrect, 0.1).hashCode, ShapeBorder.lerp(stadium, rrect, 0.1).hashCode);
final ShapeBorder direct50 = ShapeBorder.lerp(stadium, rrect, 0.5)!;
final ShapeBorder indirect50 = ShapeBorder.lerp(ShapeBorder.lerp(rrect, stadium, 0.1), ShapeBorder.lerp(rrect, stadium, 0.9), 0.5)!;
expect(direct50, indirect50);
expect(direct50.hashCode, indirect50.hashCode);
expect(direct50.toString(), indirect50.toString());
});
test('StadiumBorder and RoundedRectBorder with BorderRadiusDirectional', () {
const StadiumBorder stadium = StadiumBorder();
const RoundedRectangleBorder rrect = RoundedRectangleBorder(
borderRadius: BorderRadiusDirectional.only(
topStart: Radius.circular(10),
bottomEnd: Radius.circular(10),
),
);
const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 50.0);
final Matcher looksLikeS = isPathThat(
includes: const <Offset>[
Offset(25.0, 25.0),
Offset(50.0, 25.0),
Offset(7.33, 7.33),
],
excludes: const <Offset>[
Offset(0.001, 0.001),
Offset(99.999, 0.001),
Offset(99.999, 49.999),
Offset(0.001, 49.999),
],
);
final Matcher looksLikeR = isPathThat(
includes: const <Offset>[
Offset(25.0, 25.0),
Offset(50.0, 25.0),
Offset(7.33, 7.33),
Offset(4.0, 4.0),
Offset(96.0, 4.0),
Offset(96.0, 46.0),
Offset(4.0, 46.0),
],
);
expect(stadium.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(rrect.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeR);
expect(ShapeBorder.lerp(stadium, rrect, 0.1)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(stadium, rrect, 0.9)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeR);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.9), stadium, 0.1)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeR);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.9), stadium, 0.9)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), rrect, 0.1)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), rrect, 0.9)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.9), 0.1)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.9), 0.9)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeR);
expect(ShapeBorder.lerp(stadium, ShapeBorder.lerp(stadium, rrect, 0.9), 0.1)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(stadium, ShapeBorder.lerp(stadium, rrect, 0.9), 0.9)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeR);
expect(ShapeBorder.lerp(rrect, ShapeBorder.lerp(stadium, rrect, 0.1), 0.1)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(ShapeBorder.lerp(rrect, ShapeBorder.lerp(stadium, rrect, 0.1), 0.9)!.getOuterPath(rect, textDirection: TextDirection.rtl), looksLikeS);
expect(
ShapeBorder.lerp(stadium, rrect, 0.1).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadiusDirectional.only(topStart: Radius.circular(10.0), '
'bottomEnd: Radius.circular(10.0)), 10.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(stadium, rrect, 0.2).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadiusDirectional.only(topStart: Radius.circular(10.0), '
'bottomEnd: Radius.circular(10.0)), 20.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.9), 0.9).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadiusDirectional.only(topStart: Radius.circular(10.0), '
'bottomEnd: Radius.circular(10.0)), 82.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(rrect, stadium, 0.9).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadiusDirectional.only(topStart: Radius.circular(10.0), '
'bottomEnd: Radius.circular(10.0)), 10.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(rrect, stadium, 0.8).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadiusDirectional.only(topStart: Radius.circular(10.0), '
'bottomEnd: Radius.circular(10.0)), 20.0% of the way to being a RoundedRectangleBorder)',
);
expect(
ShapeBorder.lerp(ShapeBorder.lerp(stadium, rrect, 0.9), ShapeBorder.lerp(stadium, rrect, 0.1), 0.1).toString(),
'StadiumBorder(BorderSide(width: 0.0, style: none), '
'BorderRadiusDirectional.only(topStart: Radius.circular(10.0), '
'bottomEnd: Radius.circular(10.0)), 82.0% of the way to being a RoundedRectangleBorder)',
);
expect(ShapeBorder.lerp(stadium, rrect, 0.1), ShapeBorder.lerp(stadium, rrect, 0.1));
expect(ShapeBorder.lerp(stadium, rrect, 0.1).hashCode, ShapeBorder.lerp(stadium, rrect, 0.1).hashCode);
final ShapeBorder direct50 = ShapeBorder.lerp(stadium, rrect, 0.5)!;
final ShapeBorder indirect50 = ShapeBorder.lerp(ShapeBorder.lerp(rrect, stadium, 0.1), ShapeBorder.lerp(rrect, stadium, 0.9), 0.5)!;
expect(direct50, indirect50);
expect(direct50.hashCode, indirect50.hashCode);
expect(direct50.toString(), indirect50.toString());
});
} }
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