blob: 5605325a12be184926a4a0a3335d3d305dc34e80 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
import 'dart:math' as math;
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('LinearGradient scale test', () {
const LinearGradient testGradient = LinearGradient(
begin: Alignment.bottomRight,
end: Alignment(0.7, 1.0),
colors: <Color>[
Color(0x00FFFFFF),
Color(0x11777777),
Color(0x44444444),
],
);
final LinearGradient? actual = LinearGradient.lerp(null, testGradient, 0.25);
expect(actual, const LinearGradient(
begin: Alignment.bottomRight,
end: Alignment(0.7, 1.0),
colors: <Color>[
Color(0x00FFFFFF),
Color(0x04777777),
Color(0x11444444),
],
));
});
test('LinearGradient lerp test', () {
const LinearGradient testGradient1 = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomLeft,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const LinearGradient testGradient2 = LinearGradient(
begin: Alignment.topRight,
end: Alignment.topLeft,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
);
final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.centerLeft,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x77777777),
],
stops: <double>[0, 1],
));
});
test('LinearGradient lerp test with stops', () {
const LinearGradient testGradient1 = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomLeft,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
0.5,
],
);
const LinearGradient testGradient2 = LinearGradient(
begin: Alignment.topRight,
end: Alignment.topLeft,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
stops: <double>[
0.5,
1.0,
],
);
final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.centerLeft,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x55555555),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
1.0,
],
));
});
test('LinearGradient lerp test with unequal number of colors', () {
const LinearGradient testGradient1 = LinearGradient(
colors: <Color>[
Color(0x22222222),
Color(0x66666666),
],
);
const LinearGradient testGradient2 = LinearGradient(
colors: <Color>[
Color(0x44444444),
Color(0x66666666),
Color(0x88888888),
],
);
final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const LinearGradient(
colors: <Color>[
Color(0x33333333),
Color(0x55555555),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
1.0,
],
));
});
test('LinearGradient lerp test with stops and unequal number of colors', () {
const LinearGradient testGradient1 = LinearGradient(
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
0.5,
],
);
const LinearGradient testGradient2 = LinearGradient(
colors: <Color>[
Color(0x44444444),
Color(0x48484848),
Color(0x88888888),
],
stops: <double>[
0.5,
0.7,
1.0,
],
);
final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const LinearGradient(
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x55555555),
Color(0x57575757),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
0.7,
1.0,
],
));
});
test('LinearGradient toString', () {
expect(
const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomLeft,
transform: GradientRotation(1.6),
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
).toString(),
equals(
'LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomLeft, colors: [Color(0x33333333), Color(0x66666666)], tileMode: TileMode.clamp, transform: GradientRotation(radians: 1.6))',
),
);
});
test('LinearGradient with different transforms', () {
const LinearGradient testGradient1 = LinearGradient(
transform: GradientRotation(math.pi/4),
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const LinearGradient testGradient1Copy = LinearGradient(
transform: GradientRotation(math.pi/4),
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const LinearGradient testGradient2 = LinearGradient(
transform: GradientRotation(math.pi/2),
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
expect(
testGradient1,
equals(testGradient1Copy),
);
expect(
testGradient1,
isNot(equals(testGradient2)),
);
});
test('LinearGradient with AlignmentDirectional', () {
expect(
() {
return const LinearGradient(
begin: AlignmentDirectional.topStart,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
},
throwsAssertionError,
);
expect(
() {
return const LinearGradient(
begin: AlignmentDirectional.topStart,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl);
},
returnsNormally,
);
expect(
() {
return const LinearGradient(
begin: AlignmentDirectional.topStart,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr);
},
returnsNormally,
);
expect(
() {
return const LinearGradient(
begin: Alignment.topLeft,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
},
returnsNormally,
);
});
test('RadialGradient with AlignmentDirectional', () {
expect(
() {
return const RadialGradient(
center: AlignmentDirectional.topStart,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
},
throwsAssertionError,
);
expect(
() {
return const RadialGradient(
center: AlignmentDirectional.topStart,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl);
},
returnsNormally,
);
expect(
() {
return const RadialGradient(
center: AlignmentDirectional.topStart,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr);
},
returnsNormally,
);
expect(
() {
return const RadialGradient(
center: Alignment.topLeft,
colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ],
).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
},
returnsNormally,
);
});
test('RadialGradient lerp test', () {
const RadialGradient testGradient1 = RadialGradient(
center: Alignment.topLeft,
radius: 20.0,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const RadialGradient testGradient2 = RadialGradient(
center: Alignment.topRight,
radius: 10.0,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
);
final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const RadialGradient(
center: Alignment.topCenter,
radius: 15.0,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x77777777),
],
stops: <double>[
0.0,
1.0,
],
));
});
test('RadialGradient lerp test with stops', () {
const RadialGradient testGradient1 = RadialGradient(
center: Alignment.topLeft,
radius: 20.0,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
0.5,
],
);
const RadialGradient testGradient2 = RadialGradient(
center: Alignment.topRight,
radius: 10.0,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
stops: <double>[
0.5,
1.0,
],
);
final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const RadialGradient(
center: Alignment.topCenter,
radius: 15.0,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x55555555),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
1.0,
],
));
expect(actual!.focal, isNull);
});
test('RadialGradient lerp test with unequal number of colors', () {
const RadialGradient testGradient1 = RadialGradient(
colors: <Color>[
Color(0x22222222),
Color(0x66666666),
],
);
const RadialGradient testGradient2 = RadialGradient(
colors: <Color>[
Color(0x44444444),
Color(0x66666666),
Color(0x88888888),
],
);
final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const RadialGradient(
colors: <Color>[
Color(0x33333333),
Color(0x55555555),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
1.0,
],
));
});
test('RadialGradient lerp test with stops and unequal number of colors', () {
const RadialGradient testGradient1 = RadialGradient(
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
0.5,
],
);
const RadialGradient testGradient2 = RadialGradient(
colors: <Color>[
Color(0x44444444),
Color(0x48484848),
Color(0x88888888),
],
stops: <double>[
0.5,
0.7,
1.0,
],
);
final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const RadialGradient(
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x55555555),
Color(0x57575757),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
0.7,
1.0,
],
));
});
test('RadialGradient lerp test with focal', () {
const RadialGradient testGradient1 = RadialGradient(
center: Alignment.topLeft,
focal: Alignment.centerLeft,
radius: 20.0,
focalRadius: 10.0,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const RadialGradient testGradient2 = RadialGradient(
center: Alignment.topRight,
focal: Alignment.centerRight,
radius: 10.0,
focalRadius: 5.0,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
);
const RadialGradient testGradient3 = RadialGradient(
center: Alignment.topRight,
radius: 10.0,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
);
final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const RadialGradient(
center: Alignment.topCenter,
focal: Alignment.center,
radius: 15.0,
focalRadius: 7.5,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x77777777),
],
stops: <double>[
0.0,
1.0,
],
));
final RadialGradient? actual2 = RadialGradient.lerp(testGradient1, testGradient3, 0.5);
expect(actual2, const RadialGradient(
center: Alignment.topCenter,
focal: Alignment(-0.5, 0.0),
radius: 15.0,
focalRadius: 5.0,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x77777777),
],
stops: <double>[
0.0,
1.0,
],
));
});
test('SweepGradient lerp test', () {
const SweepGradient testGradient1 = SweepGradient(
center: Alignment.topLeft,
endAngle: math.pi / 2,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const SweepGradient testGradient2 = SweepGradient(
center: Alignment.topRight,
startAngle: math.pi / 2,
endAngle: math.pi,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
);
final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const SweepGradient(
center: Alignment.topCenter,
startAngle: math.pi / 4,
endAngle: math.pi * 3/4,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x77777777),
],
stops: <double>[
0.0,
1.0,
],
));
});
test('SweepGradient lerp test with stops', () {
const SweepGradient testGradient1 = SweepGradient(
center: Alignment.topLeft,
endAngle: math.pi / 2,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
0.5,
],
);
const SweepGradient testGradient2 = SweepGradient(
center: Alignment.topRight,
startAngle: math.pi / 2,
endAngle: math.pi,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
stops: <double>[
0.5,
1.0,
],
);
final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const SweepGradient(
center: Alignment.topCenter,
startAngle: math.pi / 4,
endAngle: math.pi * 3/4,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x55555555),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
1.0,
],
));
});
test('SweepGradient lerp test with unequal number of colors', () {
const SweepGradient testGradient1 = SweepGradient(
colors: <Color>[
Color(0x22222222),
Color(0x66666666),
],
);
const SweepGradient testGradient2 = SweepGradient(
colors: <Color>[
Color(0x44444444),
Color(0x66666666),
Color(0x88888888),
],
);
final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const SweepGradient(
colors: <Color>[
Color(0x33333333),
Color(0x55555555),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
1.0,
],
));
});
test('SweepGradient lerp test with stops and unequal number of colors', () {
const SweepGradient testGradient1 = SweepGradient(
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
0.5,
],
);
const SweepGradient testGradient2 = SweepGradient(
colors: <Color>[
Color(0x44444444),
Color(0x48484848),
Color(0x88888888),
],
stops: <double>[
0.5,
0.7,
1.0,
],
);
final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
expect(actual, const SweepGradient(
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x55555555),
Color(0x57575757),
Color(0x77777777),
],
stops: <double>[
0.0,
0.5,
0.7,
1.0,
],
));
});
test('SweepGradient scale test)', () {
const SweepGradient testGradient = SweepGradient(
center: Alignment.topLeft,
endAngle: math.pi / 2,
colors: <Color>[
Color(0xff333333),
Color(0xff666666),
],
);
final SweepGradient actual = testGradient.scale(0.5);
expect(actual, const SweepGradient(
center: Alignment.topLeft,
endAngle: math.pi / 2,
colors: <Color>[
Color(0x80333333),
Color(0x80666666),
],
));
});
test('Gradient lerp test (with RadialGradient)', () {
const RadialGradient testGradient1 = RadialGradient(
center: Alignment.topLeft,
radius: 20.0,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
stops: <double>[
0.0,
1.0,
],
);
const RadialGradient testGradient2 = RadialGradient(
center: Alignment.topCenter,
radius: 15.0,
colors: <Color>[
Color(0x3B3B3B3B),
Color(0x77777777),
],
stops: <double>[
0.0,
1.0,
],
);
const RadialGradient testGradient3 = RadialGradient(
center: Alignment.topRight,
radius: 10.0,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
stops: <double>[
0.0,
1.0,
],
);
expect(Gradient.lerp(testGradient1, testGradient3, 0.0), testGradient1);
expect(Gradient.lerp(testGradient1, testGradient3, 0.5), testGradient2);
expect(Gradient.lerp(testGradient1, testGradient3, 1.0), testGradient3);
expect(Gradient.lerp(testGradient3, testGradient1, 0.0), testGradient3);
expect(Gradient.lerp(testGradient3, testGradient1, 0.5), testGradient2);
expect(Gradient.lerp(testGradient3, testGradient1, 1.0), testGradient1);
});
test('Gradient lerp test (LinearGradient to RadialGradient)', () {
const LinearGradient testGradient1 = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: <Color>[
Color(0x33333333),
Color(0x66666666),
],
);
const RadialGradient testGradient2 = RadialGradient(
radius: 20.0,
colors: <Color>[
Color(0x44444444),
Color(0x88888888),
],
);
expect(Gradient.lerp(testGradient1, testGradient2, 0.0), testGradient1);
expect(Gradient.lerp(testGradient1, testGradient2, 1.0), testGradient2);
expect(Gradient.lerp(testGradient1, testGradient2, 0.5), testGradient2.scale(0.0));
});
test('Gradients can handle missing stops and report mismatched stops', () {
const LinearGradient test1a = LinearGradient(
colors: <Color>[
Color(0x11111111),
Color(0x22222222),
Color(0x33333333),
],
);
const RadialGradient test1b = RadialGradient(
colors: <Color>[
Color(0x11111111),
Color(0x22222222),
Color(0x33333333),
],
);
const LinearGradient test2a = LinearGradient(
colors: <Color>[
Color(0x11111111),
Color(0x22222222),
Color(0x33333333),
],
stops: <double>[0.0, 1.0],
);
const RadialGradient test2b = RadialGradient(
colors: <Color>[
Color(0x11111111),
Color(0x22222222),
Color(0x33333333),
],
stops: <double>[0.0, 1.0],
);
const Rect rect = Rect.fromLTWH(1.0, 2.0, 3.0, 4.0);
expect(test1a.createShader(rect), isNotNull);
expect(test1b.createShader(rect), isNotNull);
expect(() { test2a.createShader(rect); }, throwsArgumentError);
expect(() { test2b.createShader(rect); }, throwsArgumentError);
});
group('Transforms', () {
const List<Color> colors = <Color>[Color(0xFFFFFFFF), Color(0xFF000088)];
const Rect rect = Rect.fromLTWH(0.0, 0.0, 300.0, 400.0);
const List<Gradient> gradients45 = <Gradient>[
LinearGradient(colors: colors, transform: GradientRotation(math.pi/4)),
// A radial gradient won't be interesting to rotate unless the center is changed.
RadialGradient(colors: colors, center: Alignment.topCenter, transform: GradientRotation(math.pi/4)),
SweepGradient(colors: colors, transform: GradientRotation(math.pi/4)),
];
const List<Gradient> gradients90 = <Gradient>[
LinearGradient(colors: colors, transform: GradientRotation(math.pi/2)),
// A radial gradient won't be interesting to rotate unless the center is changed.
RadialGradient(colors: colors, center: Alignment.topCenter, transform: GradientRotation(math.pi/2)),
SweepGradient(colors: colors, transform: GradientRotation(math.pi/2)),
];
const Map<Type, String> gradientSnakeCase = <Type, String> {
LinearGradient: 'linear_gradient',
RadialGradient: 'radial_gradient',
SweepGradient: 'sweep_gradient',
};
Future<void> runTest(WidgetTester tester, Gradient gradient, double degrees) async {
final String goldenName = '${gradientSnakeCase[gradient.runtimeType]}_$degrees.png';
final Shader shader = gradient.createShader(
rect,
);
final Key painterKey = UniqueKey();
await tester.pumpWidget(Center(
child: SizedBox.fromSize(
size: rect.size,
child: RepaintBoundary(
key: painterKey,
child: CustomPaint(
painter: GradientPainter(shader, rect),
),
),
),
));
await expectLater(
find.byKey(painterKey),
matchesGoldenFile(goldenName),
);
}
group('Gradients - 45 degrees', () {
for (final Gradient gradient in gradients45) {
testWidgets('$gradient', (WidgetTester tester) async {
await runTest(tester, gradient, 45);
});
}
});
group('Gradients - 90 degrees', () {
for (final Gradient gradient in gradients90) {
testWidgets('$gradient', (WidgetTester tester) async {
await runTest(tester, gradient, 90);
});
}
});
});
}
class GradientPainter extends CustomPainter {
const GradientPainter(this.shader, this.rect);
final Shader shader;
final Rect rect;
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(rect, Paint()..shader = shader);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}