1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file is run as part of a reduced test set in CI on Mac and Windows
6// machines.
7@Tags(<String>['reduced-test-set'])
8library;
9
10import 'dart:math' as math;
11
12import 'package:flutter/widgets.dart';
13import 'package:flutter_test/flutter_test.dart';
14
15bool _listDoubleMatches(List<double>? x, List<double>? y) {
16 if (x == null && y == null) {
17 return true;
18 }
19 if (x == null || y == null) {
20 return false;
21 }
22 if (x.length != y.length) {
23 return false;
24 }
25 for (int i = 0; i < x.length; i++) {
26 if ((x[i] - y[i]).abs() >= 0.0001) {
27 return false;
28 }
29 }
30 return true;
31}
32
33bool _listColorMatches(List<Color> x, List<Color> y) {
34 if (x.length != y.length) {
35 return false;
36 }
37 const double limit = 1 / 255;
38 for (int i = 0; i < x.length; i++) {
39 if ((x[i].a - y[i].a).abs() >= limit ||
40 (x[i].r - y[i].r).abs() >= limit ||
41 (x[i].g - y[i].g).abs() >= limit ||
42 (x[i].b - y[i].b).abs() >= limit) {
43 return false;
44 }
45 }
46 return true;
47}
48
49class _LinearGradientMatcher extends Matcher {
50 _LinearGradientMatcher(this._target);
51 final LinearGradient _target;
52
53 @override
54 Description describe(Description description) {
55 description.add('expected $_target');
56 return description;
57 }
58
59 @override
60 bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
61 return item is LinearGradient &&
62 item.begin == _target.begin &&
63 item.end == _target.end &&
64 item.tileMode == _target.tileMode &&
65 item.transform == _target.transform &&
66 _listColorMatches(item.colors, _target.colors) &&
67 _listDoubleMatches(item.stops, _target.stops);
68 }
69}
70
71Matcher _matchesLinearGradient(LinearGradient target) => _LinearGradientMatcher(target);
72
73class _RadialGradientMatcher extends Matcher {
74 _RadialGradientMatcher(this._target);
75 final RadialGradient _target;
76
77 @override
78 Description describe(Description description) {
79 description.add('expected $_target');
80 return description;
81 }
82
83 @override
84 bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
85 if (item is RadialGradient) {
86 return item.center == _target.center &&
87 item.radius == _target.radius &&
88 item.tileMode == _target.tileMode &&
89 item.transform == _target.transform &&
90 item.focal == _target.focal &&
91 item.focalRadius == _target.focalRadius &&
92 _listColorMatches(item.colors, _target.colors) &&
93 _listDoubleMatches(item.stops, _target.stops);
94 } else {
95 return false;
96 }
97 }
98}
99
100Matcher _matchesRadialGradient(RadialGradient target) => _RadialGradientMatcher(target);
101
102class _SweepGradientMatcher extends Matcher {
103 _SweepGradientMatcher(this._target);
104 final SweepGradient _target;
105
106 @override
107 Description describe(Description description) {
108 description.add('expected $_target');
109 return description;
110 }
111
112 @override
113 bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
114 if (item is SweepGradient) {
115 return item.center == _target.center &&
116 item.startAngle == _target.startAngle &&
117 item.endAngle == _target.endAngle &&
118 item.tileMode == _target.tileMode &&
119 item.transform == _target.transform &&
120 _listColorMatches(item.colors, _target.colors) &&
121 _listDoubleMatches(item.stops, _target.stops);
122 } else {
123 return false;
124 }
125 }
126}
127
128Matcher _matchesSweepGradient(SweepGradient target) => _SweepGradientMatcher(target);
129
130void main() {
131 test('LinearGradient scale test', () {
132 const LinearGradient testGradient = LinearGradient(
133 begin: Alignment.bottomRight,
134 end: Alignment(0.7, 1.0),
135 colors: <Color>[Color(0x00FFFFFF), Color(0x11777777), Color(0x44444444)],
136 );
137 final LinearGradient? actual = LinearGradient.lerp(null, testGradient, 0.25);
138
139 expect(
140 actual,
141 _matchesLinearGradient(
142 const LinearGradient(
143 begin: Alignment.bottomRight,
144 end: Alignment(0.7, 1.0),
145 colors: <Color>[Color(0x00FFFFFF), Color(0x04777777), Color(0x11444444)],
146 ),
147 ),
148 );
149 });
150
151 test('LinearGradient lerp test', () {
152 const LinearGradient testGradient1 = LinearGradient(
153 begin: Alignment.topLeft,
154 end: Alignment.bottomLeft,
155 colors: <Color>[Color(0x33333333), Color(0x66666666)],
156 );
157 const LinearGradient testGradient2 = LinearGradient(
158 begin: Alignment.topRight,
159 end: Alignment.topLeft,
160 colors: <Color>[Color(0x44444444), Color(0x88888888)],
161 );
162
163 final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
164 expect(
165 actual,
166 _matchesLinearGradient(
167 const LinearGradient(
168 begin: Alignment.topCenter,
169 end: Alignment.centerLeft,
170 colors: <Color>[Color(0x3B3B3B3B), Color(0x77777777)],
171 stops: <double>[0, 1],
172 ),
173 ),
174 );
175 });
176
177 test('LinearGradient.lerp identical a,b', () {
178 expect(LinearGradient.lerp(null, null, 0), null);
179 const LinearGradient gradient = LinearGradient(
180 colors: <Color>[Color(0x33333333), Color(0x66666666)],
181 );
182 expect(identical(LinearGradient.lerp(gradient, gradient, 0.5), gradient), true);
183 });
184
185 test('LinearGradient lerp test with stops', () {
186 const LinearGradient testGradient1 = LinearGradient(
187 begin: Alignment.topLeft,
188 end: Alignment.bottomLeft,
189 colors: <Color>[Color(0x33333333), Color(0x66666666)],
190 stops: <double>[0.0, 0.5],
191 );
192 const LinearGradient testGradient2 = LinearGradient(
193 begin: Alignment.topRight,
194 end: Alignment.topLeft,
195 colors: <Color>[Color(0x44444444), Color(0x88888888)],
196 stops: <double>[0.5, 1.0],
197 );
198
199 final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
200 expect(
201 actual,
202 _matchesLinearGradient(
203 const LinearGradient(
204 begin: Alignment.topCenter,
205 end: Alignment.centerLeft,
206 colors: <Color>[Color(0x3B3B3B3B), Color(0x55555555), Color(0x77777777)],
207 stops: <double>[0.0, 0.5, 1.0],
208 ),
209 ),
210 );
211 });
212
213 test('LinearGradient lerp test with unequal number of colors', () {
214 const LinearGradient testGradient1 = LinearGradient(
215 colors: <Color>[Color(0x22222222), Color(0x66666666)],
216 );
217 const LinearGradient testGradient2 = LinearGradient(
218 colors: <Color>[Color(0x44444444), Color(0x66666666), Color(0x88888888)],
219 );
220
221 final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
222 expect(
223 actual,
224 _matchesLinearGradient(
225 const LinearGradient(
226 colors: <Color>[Color(0x33333333), Color(0x55555555), Color(0x77777777)],
227 stops: <double>[0.0, 0.5, 1.0],
228 ),
229 ),
230 );
231 });
232
233 test('LinearGradient lerp test with stops and unequal number of colors', () {
234 const LinearGradient testGradient1 = LinearGradient(
235 colors: <Color>[Color(0x33333333), Color(0x66666666)],
236 stops: <double>[0.0, 0.5],
237 );
238 const LinearGradient testGradient2 = LinearGradient(
239 colors: <Color>[Color(0x44444444), Color(0x48484848), Color(0x88888888)],
240 stops: <double>[0.5, 0.7, 1.0],
241 );
242
243 final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
244 expect(
245 actual,
246 _matchesLinearGradient(
247 const LinearGradient(
248 colors: <Color>[
249 Color(0x3B3B3B3B),
250 Color(0x55555555),
251 Color(0x57575757),
252 Color(0x77777777),
253 ],
254 stops: <double>[0.0, 0.5, 0.7, 1.0],
255 ),
256 ),
257 );
258 });
259
260 test('LinearGradient lerp test with transforms', () {
261 const LinearGradient testGradient1 = LinearGradient(
262 transform: GradientRotation(math.pi / 4),
263 colors: <Color>[Color(0x33333333), Color(0x66666666)],
264 stops: <double>[0, 1],
265 );
266 const LinearGradient testGradient2 = LinearGradient(
267 transform: GradientRotation(math.pi / 2),
268 colors: <Color>[Color(0x33333333), Color(0x66666666)],
269 stops: <double>[0, 1],
270 );
271
272 final LinearGradient? actual0 = LinearGradient.lerp(testGradient1, testGradient2, 0.0);
273 final LinearGradient? actual1 = LinearGradient.lerp(testGradient1, testGradient2, 1.0);
274 final LinearGradient? actual2 = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
275 expect(testGradient1, equals(actual0));
276 expect(testGradient2, equals(actual1));
277 expect(testGradient2, equals(actual2));
278 });
279
280 test('LinearGradient toString', () {
281 expect(
282 const LinearGradient(
283 begin: Alignment.topLeft,
284 end: Alignment.bottomLeft,
285 transform: GradientRotation(1.6),
286 colors: <Color>[Color(0x33333333), Color(0x66666666)],
287 ).toString(),
288 equals(
289 'LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomLeft, colors: [${const Color(0x33333333)}, ${const Color(0x66666666)}], tileMode: TileMode.clamp, transform: GradientRotation(radians: 1.6))',
290 ),
291 );
292 });
293
294 test('LinearGradient with different transforms', () {
295 const LinearGradient testGradient1 = LinearGradient(
296 transform: GradientRotation(math.pi / 4),
297 colors: <Color>[Color(0x33333333), Color(0x66666666)],
298 );
299 const LinearGradient testGradient1Copy = LinearGradient(
300 transform: GradientRotation(math.pi / 4),
301 colors: <Color>[Color(0x33333333), Color(0x66666666)],
302 );
303 const LinearGradient testGradient2 = LinearGradient(
304 transform: GradientRotation(math.pi / 2),
305 colors: <Color>[Color(0x33333333), Color(0x66666666)],
306 );
307
308 expect(testGradient1, equals(testGradient1Copy));
309 expect(testGradient1, isNot(equals(testGradient2)));
310 });
311
312 test('LinearGradient with AlignmentDirectional', () {
313 expect(() {
314 return const LinearGradient(
315 begin: AlignmentDirectional.topStart,
316 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
317 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
318 }, throwsAssertionError);
319 expect(() {
320 return const LinearGradient(
321 begin: AlignmentDirectional.topStart,
322 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
323 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl);
324 }, returnsNormally);
325 expect(() {
326 return const LinearGradient(
327 begin: AlignmentDirectional.topStart,
328 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
329 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr);
330 }, returnsNormally);
331 expect(() {
332 return const LinearGradient(
333 begin: Alignment.topLeft,
334 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
335 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
336 }, returnsNormally);
337 });
338
339 test('LinearGradient withOpacity test', () {
340 const LinearGradient testGradient = LinearGradient(
341 begin: Alignment.bottomRight,
342 end: Alignment.topCenter,
343 colors: <Color>[Color(0xFFFFFFFF), Color(0xAF777777), Color(0x44444444)],
344 );
345 final LinearGradient actual = testGradient.withOpacity(0.5);
346
347 expect(
348 actual,
349 const LinearGradient(
350 begin: Alignment.bottomRight,
351 end: Alignment.topCenter,
352 colors: <Color>[Color(0x80FFFFFF), Color(0x80777777), Color(0x80444444)],
353 ),
354 );
355 });
356
357 test('LinearGradient withOpacity() preserves transform', () {
358 const LinearGradient testGradient = LinearGradient(
359 begin: Alignment.bottomRight,
360 end: Alignment.topCenter,
361 colors: <Color>[Color(0xFFFFFFFF), Color(0xAF777777), Color(0x44444444)],
362 transform: GradientRotation(1),
363 );
364 final LinearGradient actual = testGradient.withOpacity(0.5);
365
366 expect(
367 actual,
368 const LinearGradient(
369 begin: Alignment.bottomRight,
370 end: Alignment.topCenter,
371 colors: <Color>[Color(0x80FFFFFF), Color(0x80777777), Color(0x80444444)],
372 transform: GradientRotation(1),
373 ),
374 );
375 });
376
377 test('RadialGradient with AlignmentDirectional', () {
378 expect(() {
379 return const RadialGradient(
380 center: AlignmentDirectional.topStart,
381 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
382 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
383 }, throwsAssertionError);
384
385 expect(() {
386 return const RadialGradient(
387 center: AlignmentDirectional.topStart,
388 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
389 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl);
390 }, returnsNormally);
391 expect(() {
392 return const RadialGradient(
393 center: AlignmentDirectional.topStart,
394 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
395 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr);
396 }, returnsNormally);
397 expect(() {
398 return const RadialGradient(
399 center: Alignment.topLeft,
400 colors: <Color>[Color(0xFFFFFFFF), Color(0xFFFFFFFF)],
401 ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0));
402 }, returnsNormally);
403 });
404
405 test('RadialGradient lerp test', () {
406 const RadialGradient testGradient1 = RadialGradient(
407 center: Alignment.topLeft,
408 radius: 20.0,
409 colors: <Color>[Color(0x33333333), Color(0x66666666)],
410 );
411 const RadialGradient testGradient2 = RadialGradient(
412 center: Alignment.topRight,
413 radius: 10.0,
414 colors: <Color>[Color(0x44444444), Color(0x88888888)],
415 );
416
417 final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
418 expect(
419 actual,
420 _matchesRadialGradient(
421 const RadialGradient(
422 center: Alignment.topCenter,
423 radius: 15.0,
424 colors: <Color>[Color(0x3B3B3B3B), Color(0x77777777)],
425 stops: <double>[0.0, 1.0],
426 ),
427 ),
428 );
429 });
430
431 test('RadialGradient.lerp identical a,b', () {
432 expect(RadialGradient.lerp(null, null, 0), null);
433 const RadialGradient gradient = RadialGradient(
434 colors: <Color>[Color(0x33333333), Color(0x66666666)],
435 );
436 expect(identical(RadialGradient.lerp(gradient, gradient, 0.5), gradient), true);
437 });
438
439 test('RadialGradient lerp test with stops', () {
440 const RadialGradient testGradient1 = RadialGradient(
441 center: Alignment.topLeft,
442 radius: 20.0,
443 colors: <Color>[Color(0x33333333), Color(0x66666666)],
444 stops: <double>[0.0, 0.5],
445 );
446 const RadialGradient testGradient2 = RadialGradient(
447 center: Alignment.topRight,
448 radius: 10.0,
449 colors: <Color>[Color(0x44444444), Color(0x88888888)],
450 stops: <double>[0.5, 1.0],
451 );
452
453 final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
454
455 expect(
456 actual,
457 _matchesRadialGradient(
458 const RadialGradient(
459 center: Alignment.topCenter,
460 radius: 15.0,
461 colors: <Color>[Color(0x3B3B3B3B), Color(0x55555555), Color(0x77777777)],
462 stops: <double>[0.0, 0.5, 1.0],
463 ),
464 ),
465 );
466
467 expect(actual!.focal, isNull);
468 });
469
470 test('RadialGradient lerp test with unequal number of colors', () {
471 const RadialGradient testGradient1 = RadialGradient(
472 colors: <Color>[Color(0x22222222), Color(0x66666666)],
473 );
474 const RadialGradient testGradient2 = RadialGradient(
475 colors: <Color>[Color(0x44444444), Color(0x66666666), Color(0x88888888)],
476 );
477
478 final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
479 expect(
480 actual,
481 _matchesRadialGradient(
482 const RadialGradient(
483 colors: <Color>[Color(0x33333333), Color(0x55555555), Color(0x77777777)],
484 stops: <double>[0.0, 0.5, 1.0],
485 ),
486 ),
487 );
488 });
489
490 test('RadialGradient lerp test with stops and unequal number of colors', () {
491 const RadialGradient testGradient1 = RadialGradient(
492 colors: <Color>[Color(0x33333333), Color(0x66666666)],
493 stops: <double>[0.0, 0.5],
494 );
495 const RadialGradient testGradient2 = RadialGradient(
496 colors: <Color>[Color(0x44444444), Color(0x48484848), Color(0x88888888)],
497 stops: <double>[0.5, 0.7, 1.0],
498 );
499
500 final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
501 expect(
502 actual,
503 _matchesRadialGradient(
504 const RadialGradient(
505 colors: <Color>[
506 Color(0x3B3B3B3B),
507 Color(0x55555555),
508 Color(0x57575757),
509 Color(0x77777777),
510 ],
511 stops: <double>[0.0, 0.5, 0.7, 1.0],
512 ),
513 ),
514 );
515 });
516
517 test('RadialGradient lerp test with transforms', () {
518 const RadialGradient testGradient1 = RadialGradient(
519 transform: GradientRotation(math.pi / 4),
520 colors: <Color>[Color(0x33333333), Color(0x66666666)],
521 stops: <double>[0, 1],
522 );
523 const RadialGradient testGradient2 = RadialGradient(
524 transform: GradientRotation(math.pi / 2),
525 colors: <Color>[Color(0x33333333), Color(0x66666666)],
526 stops: <double>[0, 1],
527 );
528
529 final RadialGradient? actual0 = RadialGradient.lerp(testGradient1, testGradient2, 0.0);
530 final RadialGradient? actual1 = RadialGradient.lerp(testGradient1, testGradient2, 1.0);
531 final RadialGradient? actual2 = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
532 expect(testGradient1, equals(actual0));
533 expect(testGradient2, equals(actual1));
534 expect(testGradient2, equals(actual2));
535 });
536
537 test('RadialGradient lerp test with focal', () {
538 const RadialGradient testGradient1 = RadialGradient(
539 center: Alignment.topLeft,
540 focal: Alignment.centerLeft,
541 radius: 20.0,
542 focalRadius: 10.0,
543 colors: <Color>[Color(0x33333333), Color(0x66666666)],
544 );
545 const RadialGradient testGradient2 = RadialGradient(
546 center: Alignment.topRight,
547 focal: Alignment.centerRight,
548 radius: 10.0,
549 focalRadius: 5.0,
550 colors: <Color>[Color(0x44444444), Color(0x88888888)],
551 );
552 const RadialGradient testGradient3 = RadialGradient(
553 center: Alignment.topRight,
554 radius: 10.0,
555 colors: <Color>[Color(0x44444444), Color(0x88888888)],
556 );
557
558 final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
559 expect(
560 actual,
561 _matchesRadialGradient(
562 const RadialGradient(
563 center: Alignment.topCenter,
564 focal: Alignment.center,
565 radius: 15.0,
566 focalRadius: 7.5,
567 colors: <Color>[Color(0x3B3B3B3B), Color(0x77777777)],
568 stops: <double>[0.0, 1.0],
569 ),
570 ),
571 );
572
573 final RadialGradient? actual2 = RadialGradient.lerp(testGradient1, testGradient3, 0.5);
574 expect(
575 actual2,
576 _matchesRadialGradient(
577 const RadialGradient(
578 center: Alignment.topCenter,
579 focal: Alignment(-0.5, 0.0),
580 radius: 15.0,
581 focalRadius: 5.0,
582 colors: <Color>[Color(0x3B3B3B3B), Color(0x77777777)],
583 stops: <double>[0.0, 1.0],
584 ),
585 ),
586 );
587 });
588
589 test('RadialGradient withOpacity test', () {
590 const RadialGradient testGradient = RadialGradient(
591 center: Alignment.topLeft,
592 focal: Alignment.centerLeft,
593 radius: 20.0,
594 focalRadius: 10.0,
595 colors: <Color>[Color(0xFFFFFFFF), Color(0xAF777777), Color(0x44444444)],
596 );
597 final RadialGradient actual = testGradient.withOpacity(0.5);
598
599 expect(
600 actual,
601 const RadialGradient(
602 center: Alignment.topLeft,
603 focal: Alignment.centerLeft,
604 radius: 20.0,
605 focalRadius: 10.0,
606 colors: <Color>[Color(0x80FFFFFF), Color(0x80777777), Color(0x80444444)],
607 ),
608 );
609 });
610
611 test('RadialGradient withOpacity() preserves transform', () {
612 const RadialGradient testGradient = RadialGradient(
613 center: Alignment.topLeft,
614 focal: Alignment.centerLeft,
615 radius: 20.0,
616 focalRadius: 10.0,
617 colors: <Color>[Color(0xFFFFFFFF), Color(0xAF777777), Color(0x44444444)],
618 transform: GradientRotation(1),
619 );
620 final RadialGradient actual = testGradient.withOpacity(0.5);
621
622 expect(
623 actual,
624 const RadialGradient(
625 center: Alignment.topLeft,
626 focal: Alignment.centerLeft,
627 radius: 20.0,
628 focalRadius: 10.0,
629 colors: <Color>[Color(0x80FFFFFF), Color(0x80777777), Color(0x80444444)],
630 transform: GradientRotation(1),
631 ),
632 );
633 });
634
635 test('SweepGradient lerp test', () {
636 const SweepGradient testGradient1 = SweepGradient(
637 center: Alignment.topLeft,
638 endAngle: math.pi / 2,
639 colors: <Color>[Color(0x33333333), Color(0x66666666)],
640 );
641 const SweepGradient testGradient2 = SweepGradient(
642 center: Alignment.topRight,
643 startAngle: math.pi / 2,
644 endAngle: math.pi,
645 colors: <Color>[Color(0x44444444), Color(0x88888888)],
646 );
647
648 final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
649 expect(
650 actual,
651 _matchesSweepGradient(
652 const SweepGradient(
653 center: Alignment.topCenter,
654 startAngle: math.pi / 4,
655 endAngle: math.pi * 3 / 4,
656 colors: <Color>[Color(0x3B3B3B3B), Color(0x77777777)],
657 stops: <double>[0.0, 1.0],
658 ),
659 ),
660 );
661 });
662
663 test('SweepGradient.lerp identical a,b', () {
664 expect(SweepGradient.lerp(null, null, 0), null);
665 const SweepGradient gradient = SweepGradient(
666 colors: <Color>[Color(0x33333333), Color(0x66666666)],
667 );
668 expect(identical(SweepGradient.lerp(gradient, gradient, 0.5), gradient), true);
669 });
670
671 test('SweepGradient lerp test with stops', () {
672 const SweepGradient testGradient1 = SweepGradient(
673 center: Alignment.topLeft,
674 endAngle: math.pi / 2,
675 colors: <Color>[Color(0x33333333), Color(0x66666666)],
676 stops: <double>[0.0, 0.5],
677 );
678 const SweepGradient testGradient2 = SweepGradient(
679 center: Alignment.topRight,
680 startAngle: math.pi / 2,
681 endAngle: math.pi,
682 colors: <Color>[Color(0x44444444), Color(0x88888888)],
683 stops: <double>[0.5, 1.0],
684 );
685
686 final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
687 expect(
688 actual,
689 _matchesSweepGradient(
690 const SweepGradient(
691 center: Alignment.topCenter,
692 startAngle: math.pi / 4,
693 endAngle: math.pi * 3 / 4,
694 colors: <Color>[Color(0x3B3B3B3B), Color(0x55555555), Color(0x77777777)],
695 stops: <double>[0.0, 0.5, 1.0],
696 ),
697 ),
698 );
699 });
700
701 test('SweepGradient lerp test with unequal number of colors', () {
702 const SweepGradient testGradient1 = SweepGradient(
703 colors: <Color>[Color(0x22222222), Color(0x66666666)],
704 );
705 const SweepGradient testGradient2 = SweepGradient(
706 colors: <Color>[Color(0x44444444), Color(0x66666666), Color(0x88888888)],
707 );
708
709 final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
710 expect(
711 actual,
712 _matchesSweepGradient(
713 const SweepGradient(
714 colors: <Color>[Color(0x33333333), Color(0x55555555), Color(0x77777777)],
715 stops: <double>[0.0, 0.5, 1.0],
716 ),
717 ),
718 );
719 });
720
721 test('SweepGradient lerp test with stops and unequal number of colors', () {
722 const SweepGradient testGradient1 = SweepGradient(
723 colors: <Color>[Color(0x33333333), Color(0x66666666)],
724 stops: <double>[0.0, 0.5],
725 );
726 const SweepGradient testGradient2 = SweepGradient(
727 colors: <Color>[Color(0x44444444), Color(0x48484848), Color(0x88888888)],
728 stops: <double>[0.5, 0.7, 1.0],
729 );
730
731 final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
732 expect(
733 actual,
734 _matchesSweepGradient(
735 const SweepGradient(
736 colors: <Color>[
737 Color(0x3B3B3B3B),
738 Color(0x55555555),
739 Color(0x57575757),
740 Color(0x77777777),
741 ],
742 stops: <double>[0.0, 0.5, 0.7, 1.0],
743 ),
744 ),
745 );
746 });
747
748 test('SweepGradient lerp test with transforms', () {
749 const SweepGradient testGradient1 = SweepGradient(
750 transform: GradientRotation(math.pi / 4),
751 colors: <Color>[Color(0x33333333), Color(0x66666666)],
752 stops: <double>[0, 1],
753 );
754 const SweepGradient testGradient2 = SweepGradient(
755 transform: GradientRotation(math.pi / 2),
756 colors: <Color>[Color(0x33333333), Color(0x66666666)],
757 stops: <double>[0, 1],
758 );
759
760 final SweepGradient? actual0 = SweepGradient.lerp(testGradient1, testGradient2, 0.0);
761 final SweepGradient? actual1 = SweepGradient.lerp(testGradient1, testGradient2, 1.0);
762 final SweepGradient? actual2 = SweepGradient.lerp(testGradient1, testGradient2, 0.5);
763 expect(testGradient1, equals(actual0));
764 expect(testGradient2, equals(actual1));
765 expect(testGradient2, equals(actual2));
766 });
767
768 test('SweepGradient scale test)', () {
769 const SweepGradient testGradient = SweepGradient(
770 center: Alignment.topLeft,
771 endAngle: math.pi / 2,
772 colors: <Color>[Color(0xff333333), Color(0xff666666)],
773 );
774
775 final SweepGradient actual = testGradient.scale(0.5);
776
777 expect(
778 actual,
779 _matchesSweepGradient(
780 const SweepGradient(
781 center: Alignment.topLeft,
782 endAngle: math.pi / 2,
783 colors: <Color>[Color(0x80333333), Color(0x80666666)],
784 ),
785 ),
786 );
787 });
788
789 test('SweepGradient withOpacity test', () {
790 const SweepGradient testGradient = SweepGradient(
791 center: Alignment.topLeft,
792 endAngle: math.pi / 2,
793 colors: <Color>[Color(0xFFFFFFFF), Color(0xAF777777), Color(0x44444444)],
794 );
795 final SweepGradient actual = testGradient.withOpacity(0.5);
796
797 expect(
798 actual,
799 const SweepGradient(
800 center: Alignment.topLeft,
801 endAngle: math.pi / 2,
802 colors: <Color>[Color(0x80FFFFFF), Color(0x80777777), Color(0x80444444)],
803 ),
804 );
805 });
806
807 test('SweepGradient withOpacity() preserves transform', () {
808 const SweepGradient testGradient = SweepGradient(
809 center: Alignment.topLeft,
810 endAngle: math.pi / 2,
811 colors: <Color>[Color(0xFFFFFFFF), Color(0xAF777777), Color(0x44444444)],
812 transform: GradientRotation(1),
813 );
814 final SweepGradient actual = testGradient.withOpacity(0.5);
815
816 expect(
817 actual,
818 const SweepGradient(
819 center: Alignment.topLeft,
820 endAngle: math.pi / 2,
821 colors: <Color>[Color(0x80FFFFFF), Color(0x80777777), Color(0x80444444)],
822 transform: GradientRotation(1),
823 ),
824 );
825 });
826
827 test('Gradient lerp test (with RadialGradient)', () {
828 const RadialGradient testGradient1 = RadialGradient(
829 center: Alignment.topLeft,
830 radius: 20.0,
831 colors: <Color>[Color(0x33333333), Color(0x66666666)],
832 stops: <double>[0.0, 1.0],
833 );
834 const RadialGradient testGradient2 = RadialGradient(
835 center: Alignment.topCenter,
836 radius: 15.0,
837 colors: <Color>[Color(0x3B3B3B3B), Color(0x77777777)],
838 stops: <double>[0.0, 1.0],
839 );
840 const RadialGradient testGradient3 = RadialGradient(
841 center: Alignment.topRight,
842 radius: 10.0,
843 colors: <Color>[Color(0x44444444), Color(0x88888888)],
844 stops: <double>[0.0, 1.0],
845 );
846
847 expect(Gradient.lerp(testGradient1, testGradient3, 0.0), _matchesRadialGradient(testGradient1));
848 expect(Gradient.lerp(testGradient1, testGradient3, 0.5), _matchesRadialGradient(testGradient2));
849 expect(Gradient.lerp(testGradient1, testGradient3, 1.0), _matchesRadialGradient(testGradient3));
850 expect(Gradient.lerp(testGradient3, testGradient1, 0.0), _matchesRadialGradient(testGradient3));
851 expect(Gradient.lerp(testGradient3, testGradient1, 0.5), _matchesRadialGradient(testGradient2));
852 expect(Gradient.lerp(testGradient3, testGradient1, 1.0), _matchesRadialGradient(testGradient1));
853 });
854
855 test('Gradient lerp test (LinearGradient to RadialGradient)', () {
856 const LinearGradient testGradient1 = LinearGradient(
857 begin: Alignment.topLeft,
858 end: Alignment.bottomRight,
859 colors: <Color>[Color(0x33333333), Color(0x66666666)],
860 );
861 const RadialGradient testGradient2 = RadialGradient(
862 radius: 20.0,
863 colors: <Color>[Color(0x44444444), Color(0x88888888)],
864 );
865
866 expect(Gradient.lerp(testGradient1, testGradient2, 0.0), testGradient1);
867 expect(Gradient.lerp(testGradient1, testGradient2, 1.0), testGradient2);
868 expect(Gradient.lerp(testGradient1, testGradient2, 0.5), testGradient2.scale(0.0));
869 });
870
871 test('Gradients can handle missing stops and report mismatched stops', () {
872 const LinearGradient test1a = LinearGradient(
873 colors: <Color>[Color(0x11111111), Color(0x22222222), Color(0x33333333)],
874 );
875 const RadialGradient test1b = RadialGradient(
876 colors: <Color>[Color(0x11111111), Color(0x22222222), Color(0x33333333)],
877 );
878 const LinearGradient test2a = LinearGradient(
879 colors: <Color>[Color(0x11111111), Color(0x22222222), Color(0x33333333)],
880 stops: <double>[0.0, 1.0],
881 );
882 const RadialGradient test2b = RadialGradient(
883 colors: <Color>[Color(0x11111111), Color(0x22222222), Color(0x33333333)],
884 stops: <double>[0.0, 1.0],
885 );
886 const Rect rect = Rect.fromLTWH(1.0, 2.0, 3.0, 4.0);
887 expect(test1a.createShader(rect), isNotNull);
888 expect(test1b.createShader(rect), isNotNull);
889 expect(() {
890 test2a.createShader(rect);
891 }, throwsArgumentError);
892 expect(() {
893 test2b.createShader(rect);
894 }, throwsArgumentError);
895 });
896
897 group('Transforms', () {
898 const List<Color> colors = <Color>[Color(0xFFFFFFFF), Color(0xFF000088)];
899 const Rect rect = Rect.fromLTWH(0.0, 0.0, 300.0, 400.0);
900 const List<Gradient> gradients45 = <Gradient>[
901 LinearGradient(colors: colors, transform: GradientRotation(math.pi / 4)),
902 // A radial gradient won't be interesting to rotate unless the center is changed.
903 RadialGradient(
904 colors: colors,
905 center: Alignment.topCenter,
906 transform: GradientRotation(math.pi / 4),
907 ),
908 SweepGradient(colors: colors, transform: GradientRotation(math.pi / 4)),
909 ];
910 const List<Gradient> gradients90 = <Gradient>[
911 LinearGradient(colors: colors, transform: GradientRotation(math.pi / 2)),
912 // A radial gradient won't be interesting to rotate unless the center is changed.
913 RadialGradient(
914 colors: colors,
915 center: Alignment.topCenter,
916 transform: GradientRotation(math.pi / 2),
917 ),
918 SweepGradient(colors: colors, transform: GradientRotation(math.pi / 2)),
919 ];
920
921 const Map<Type, String> gradientSnakeCase = <Type, String>{
922 LinearGradient: 'linear_gradient',
923 RadialGradient: 'radial_gradient',
924 SweepGradient: 'sweep_gradient',
925 };
926
927 Future<void> runTest(WidgetTester tester, Gradient gradient, double degrees) async {
928 final String goldenName = '${gradientSnakeCase[gradient.runtimeType]}_$degrees.png';
929 final Shader shader = gradient.createShader(rect);
930 final Key painterKey = UniqueKey();
931 await tester.pumpWidget(
932 Center(
933 child: SizedBox.fromSize(
934 size: rect.size,
935 child: RepaintBoundary(
936 key: painterKey,
937 child: CustomPaint(painter: GradientPainter(shader, rect)),
938 ),
939 ),
940 ),
941 );
942 await expectLater(find.byKey(painterKey), matchesGoldenFile(goldenName));
943 }
944
945 group('Gradients - 45 degrees', () {
946 for (final Gradient gradient in gradients45) {
947 testWidgets('$gradient', (WidgetTester tester) async {
948 await runTest(tester, gradient, 45);
949 });
950 }
951 });
952
953 group('Gradients - 90 degrees', () {
954 for (final Gradient gradient in gradients90) {
955 testWidgets('$gradient', (WidgetTester tester) async {
956 await runTest(tester, gradient, 90);
957 });
958 }
959 });
960 });
961}
962
963class GradientPainter extends CustomPainter {
964 const GradientPainter(this.shader, this.rect);
965
966 final Shader shader;
967 final Rect rect;
968
969 @override
970 void paint(Canvas canvas, Size size) {
971 canvas.drawRect(rect, Paint()..shader = shader);
972 }
973
974 @override
975 bool shouldRepaint(CustomPainter oldDelegate) => true;
976}
977

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com