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']) |
8 | library; |
9 | |
10 | import 'dart:math' as math; |
11 | |
12 | import 'package:flutter/widgets.dart'; |
13 | import 'package:flutter_test/flutter_test.dart'; |
14 | |
15 | bool _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 | |
33 | bool _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 | |
49 | class _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 | |
71 | Matcher _matchesLinearGradient(LinearGradient target) => |
72 | _LinearGradientMatcher(target); |
73 | |
74 | class _RadialGradientMatcher extends Matcher { |
75 | _RadialGradientMatcher(this._target); |
76 | final RadialGradient _target; |
77 | |
78 | @override |
79 | Description describe(Description description) { |
80 | description.add('expected$_target '); |
81 | return description; |
82 | } |
83 | |
84 | @override |
85 | bool matches(dynamic item, Map<dynamic, dynamic> matchState) { |
86 | if (item is RadialGradient) { |
87 | return item.center == _target.center && |
88 | item.radius == _target.radius && |
89 | item.tileMode == _target.tileMode && |
90 | item.transform == _target.transform && |
91 | item.focal == _target.focal && |
92 | item.focalRadius == _target.focalRadius && |
93 | _listColorMatches(item.colors, _target.colors) && |
94 | _listDoubleMatches(item.stops, _target.stops); |
95 | } else { |
96 | return false; |
97 | } |
98 | } |
99 | } |
100 | |
101 | Matcher _matchesRadialGradient(RadialGradient target) => |
102 | _RadialGradientMatcher(target); |
103 | |
104 | |
105 | class _SweepGradientMatcher extends Matcher { |
106 | _SweepGradientMatcher(this._target); |
107 | final SweepGradient _target; |
108 | |
109 | @override |
110 | Description describe(Description description) { |
111 | description.add('expected$_target '); |
112 | return description; |
113 | } |
114 | |
115 | @override |
116 | bool matches(dynamic item, Map<dynamic, dynamic> matchState) { |
117 | if (item is SweepGradient) { |
118 | return item.center == _target.center && |
119 | item.startAngle == _target.startAngle && |
120 | item.endAngle == _target.endAngle && |
121 | item.tileMode == _target.tileMode && |
122 | item.transform == _target.transform && |
123 | _listColorMatches(item.colors, _target.colors) && |
124 | _listDoubleMatches(item.stops, _target.stops); |
125 | } else { |
126 | return false; |
127 | } |
128 | } |
129 | } |
130 | |
131 | Matcher _matchesSweepGradient(SweepGradient target) => |
132 | _SweepGradientMatcher(target); |
133 | |
134 | void main() { |
135 | test('LinearGradient scale test', () { |
136 | const LinearGradient testGradient = LinearGradient( |
137 | begin: Alignment.bottomRight, |
138 | end: Alignment(0.7, 1.0), |
139 | colors: <Color>[ |
140 | Color(0x00FFFFFF), |
141 | Color(0x11777777), |
142 | Color(0x44444444), |
143 | ], |
144 | ); |
145 | final LinearGradient? actual = LinearGradient.lerp(null, testGradient, 0.25); |
146 | |
147 | expect(actual, _matchesLinearGradient(const LinearGradient( |
148 | begin: Alignment.bottomRight, |
149 | end: Alignment(0.7, 1.0), |
150 | colors: <Color>[ |
151 | Color(0x00FFFFFF), |
152 | Color(0x04777777), |
153 | Color(0x11444444), |
154 | ], |
155 | ))); |
156 | }); |
157 | |
158 | test('LinearGradient lerp test', () { |
159 | const LinearGradient testGradient1 = LinearGradient( |
160 | begin: Alignment.topLeft, |
161 | end: Alignment.bottomLeft, |
162 | colors: <Color>[ |
163 | Color(0x33333333), |
164 | Color(0x66666666), |
165 | ], |
166 | ); |
167 | const LinearGradient testGradient2 = LinearGradient( |
168 | begin: Alignment.topRight, |
169 | end: Alignment.topLeft, |
170 | colors: <Color>[ |
171 | Color(0x44444444), |
172 | Color(0x88888888), |
173 | ], |
174 | ); |
175 | |
176 | final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5); |
177 | expect(actual, _matchesLinearGradient(const LinearGradient( |
178 | begin: Alignment.topCenter, |
179 | end: Alignment.centerLeft, |
180 | colors: <Color>[ |
181 | Color(0x3B3B3B3B), |
182 | Color(0x77777777), |
183 | ], |
184 | stops: <double>[0, 1], |
185 | ))); |
186 | }); |
187 | |
188 | test('LinearGradient.lerp identical a,b', () { |
189 | expect(LinearGradient.lerp(null, null, 0), null); |
190 | const LinearGradient gradient = LinearGradient( |
191 | colors: <Color>[ |
192 | Color(0x33333333), |
193 | Color(0x66666666), |
194 | ], |
195 | ); |
196 | expect(identical(LinearGradient.lerp(gradient, gradient, 0.5), gradient), true); |
197 | }); |
198 | |
199 | test('LinearGradient lerp test with stops', () { |
200 | const LinearGradient testGradient1 = LinearGradient( |
201 | begin: Alignment.topLeft, |
202 | end: Alignment.bottomLeft, |
203 | colors: <Color>[ |
204 | Color(0x33333333), |
205 | Color(0x66666666), |
206 | ], |
207 | stops: <double>[ |
208 | 0.0, |
209 | 0.5, |
210 | ], |
211 | ); |
212 | const LinearGradient testGradient2 = LinearGradient( |
213 | begin: Alignment.topRight, |
214 | end: Alignment.topLeft, |
215 | colors: <Color>[ |
216 | Color(0x44444444), |
217 | Color(0x88888888), |
218 | ], |
219 | stops: <double>[ |
220 | 0.5, |
221 | 1.0, |
222 | ], |
223 | ); |
224 | |
225 | final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5); |
226 | expect(actual, _matchesLinearGradient(const LinearGradient( |
227 | begin: Alignment.topCenter, |
228 | end: Alignment.centerLeft, |
229 | colors: <Color>[ |
230 | Color(0x3B3B3B3B), |
231 | Color(0x55555555), |
232 | Color(0x77777777), |
233 | ], |
234 | stops: <double>[ |
235 | 0.0, |
236 | 0.5, |
237 | 1.0, |
238 | ], |
239 | ))); |
240 | }); |
241 | |
242 | test('LinearGradient lerp test with unequal number of colors', () { |
243 | const LinearGradient testGradient1 = LinearGradient( |
244 | colors: <Color>[ |
245 | Color(0x22222222), |
246 | Color(0x66666666), |
247 | ], |
248 | ); |
249 | const LinearGradient testGradient2 = LinearGradient( |
250 | colors: <Color>[ |
251 | Color(0x44444444), |
252 | Color(0x66666666), |
253 | Color(0x88888888), |
254 | ], |
255 | ); |
256 | |
257 | final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5); |
258 | expect(actual, _matchesLinearGradient(const LinearGradient( |
259 | colors: <Color>[ |
260 | Color(0x33333333), |
261 | Color(0x55555555), |
262 | Color(0x77777777), |
263 | ], |
264 | stops: <double>[ |
265 | 0.0, |
266 | 0.5, |
267 | 1.0, |
268 | ], |
269 | ))); |
270 | }); |
271 | |
272 | test('LinearGradient lerp test with stops and unequal number of colors', () { |
273 | const LinearGradient testGradient1 = LinearGradient( |
274 | colors: <Color>[ |
275 | Color(0x33333333), |
276 | Color(0x66666666), |
277 | ], |
278 | stops: <double>[ |
279 | 0.0, |
280 | 0.5, |
281 | ], |
282 | ); |
283 | const LinearGradient testGradient2 = LinearGradient( |
284 | colors: <Color>[ |
285 | Color(0x44444444), |
286 | Color(0x48484848), |
287 | Color(0x88888888), |
288 | ], |
289 | stops: <double>[ |
290 | 0.5, |
291 | 0.7, |
292 | 1.0, |
293 | ], |
294 | ); |
295 | |
296 | final LinearGradient? actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5); |
297 | expect(actual, _matchesLinearGradient(const LinearGradient( |
298 | colors: <Color>[ |
299 | Color(0x3B3B3B3B), |
300 | Color(0x55555555), |
301 | Color(0x57575757), |
302 | Color(0x77777777), |
303 | ], |
304 | stops: <double>[ |
305 | 0.0, |
306 | 0.5, |
307 | 0.7, |
308 | 1.0, |
309 | ], |
310 | ))); |
311 | }); |
312 | |
313 | test('LinearGradient lerp test with transforms', () { |
314 | const LinearGradient testGradient1 = LinearGradient( |
315 | transform: GradientRotation(math.pi/4), |
316 | colors: <Color>[ |
317 | Color(0x33333333), |
318 | Color(0x66666666), |
319 | ], |
320 | stops: <double>[0, 1], |
321 | ); |
322 | const LinearGradient testGradient2 = LinearGradient( |
323 | transform: GradientRotation(math.pi/2), |
324 | colors: <Color>[ |
325 | Color(0x33333333), |
326 | Color(0x66666666), |
327 | ], |
328 | stops: <double>[0, 1], |
329 | ); |
330 | |
331 | final LinearGradient? actual0 = LinearGradient.lerp(testGradient1, testGradient2, 0.0); |
332 | final LinearGradient? actual1 = LinearGradient.lerp(testGradient1, testGradient2, 1.0); |
333 | final LinearGradient? actual2 = LinearGradient.lerp(testGradient1, testGradient2, 0.5); |
334 | expect(testGradient1, equals(actual0)); |
335 | expect(testGradient2, equals(actual1)); |
336 | expect(testGradient2, equals(actual2)); |
337 | }); |
338 | |
339 | test('LinearGradient toString', () { |
340 | expect( |
341 | const LinearGradient( |
342 | begin: Alignment.topLeft, |
343 | end: Alignment.bottomLeft, |
344 | transform: GradientRotation(1.6), |
345 | colors: <Color>[ |
346 | Color(0x33333333), |
347 | Color(0x66666666), |
348 | ], |
349 | ).toString(), |
350 | equals( |
351 | 'LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomLeft, colors: [${const Color(0x33333333)} ,${const Color(0x66666666)} ], tileMode: TileMode.clamp, transform: GradientRotation(radians: 1.6))', |
352 | ), |
353 | ); |
354 | }); |
355 | |
356 | test('LinearGradient with different transforms', () { |
357 | const LinearGradient testGradient1 = LinearGradient( |
358 | transform: GradientRotation(math.pi/4), |
359 | colors: <Color>[ |
360 | Color(0x33333333), |
361 | Color(0x66666666), |
362 | ], |
363 | ); |
364 | const LinearGradient testGradient1Copy = LinearGradient( |
365 | transform: GradientRotation(math.pi/4), |
366 | colors: <Color>[ |
367 | Color(0x33333333), |
368 | Color(0x66666666), |
369 | ], |
370 | ); |
371 | const LinearGradient testGradient2 = LinearGradient( |
372 | transform: GradientRotation(math.pi/2), |
373 | colors: <Color>[ |
374 | Color(0x33333333), |
375 | Color(0x66666666), |
376 | ], |
377 | ); |
378 | |
379 | expect( |
380 | testGradient1, |
381 | equals(testGradient1Copy), |
382 | ); |
383 | expect( |
384 | testGradient1, |
385 | isNot(equals(testGradient2)), |
386 | ); |
387 | }); |
388 | |
389 | test('LinearGradient with AlignmentDirectional', () { |
390 | expect( |
391 | () { |
392 | return const LinearGradient( |
393 | begin: AlignmentDirectional.topStart, |
394 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
395 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0)); |
396 | }, |
397 | throwsAssertionError, |
398 | ); |
399 | expect( |
400 | () { |
401 | return const LinearGradient( |
402 | begin: AlignmentDirectional.topStart, |
403 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
404 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl); |
405 | }, |
406 | returnsNormally, |
407 | ); |
408 | expect( |
409 | () { |
410 | return const LinearGradient( |
411 | begin: AlignmentDirectional.topStart, |
412 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
413 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr); |
414 | }, |
415 | returnsNormally, |
416 | ); |
417 | expect( |
418 | () { |
419 | return const LinearGradient( |
420 | begin: Alignment.topLeft, |
421 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
422 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0)); |
423 | }, |
424 | returnsNormally, |
425 | ); |
426 | }); |
427 | |
428 | test('LinearGradient withOpacity test', () { |
429 | const LinearGradient testGradient = LinearGradient( |
430 | begin: Alignment.bottomRight, |
431 | end: Alignment.topCenter, |
432 | colors: <Color>[ |
433 | Color(0xFFFFFFFF), |
434 | Color(0xAF777777), |
435 | Color(0x44444444), |
436 | ], |
437 | ); |
438 | final LinearGradient actual = testGradient.withOpacity(0.5); |
439 | |
440 | expect(actual, const LinearGradient( |
441 | begin: Alignment.bottomRight, |
442 | end: Alignment.topCenter, |
443 | colors: <Color>[ |
444 | Color(0x80FFFFFF), |
445 | Color(0x80777777), |
446 | Color(0x80444444), |
447 | ], |
448 | )); |
449 | }); |
450 | |
451 | test('LinearGradient withOpacity() preserves transform', () { |
452 | const LinearGradient testGradient = LinearGradient( |
453 | begin: Alignment.bottomRight, |
454 | end: Alignment.topCenter, |
455 | colors: <Color>[ |
456 | Color(0xFFFFFFFF), |
457 | Color(0xAF777777), |
458 | Color(0x44444444), |
459 | ], |
460 | transform: GradientRotation(1), |
461 | ); |
462 | final LinearGradient actual = testGradient.withOpacity(0.5); |
463 | |
464 | expect(actual, const LinearGradient( |
465 | begin: Alignment.bottomRight, |
466 | end: Alignment.topCenter, |
467 | colors: <Color>[ |
468 | Color(0x80FFFFFF), |
469 | Color(0x80777777), |
470 | Color(0x80444444), |
471 | ], |
472 | transform: GradientRotation(1), |
473 | )); |
474 | }); |
475 | |
476 | test('RadialGradient with AlignmentDirectional', () { |
477 | expect( |
478 | () { |
479 | return const RadialGradient( |
480 | center: AlignmentDirectional.topStart, |
481 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
482 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0)); |
483 | }, |
484 | throwsAssertionError, |
485 | ); |
486 | |
487 | expect( |
488 | () { |
489 | return const RadialGradient( |
490 | center: AlignmentDirectional.topStart, |
491 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
492 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.rtl); |
493 | }, |
494 | returnsNormally, |
495 | ); |
496 | expect( |
497 | () { |
498 | return const RadialGradient( |
499 | center: AlignmentDirectional.topStart, |
500 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
501 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0), textDirection: TextDirection.ltr); |
502 | }, |
503 | returnsNormally, |
504 | ); |
505 | expect( |
506 | () { |
507 | return const RadialGradient( |
508 | center: Alignment.topLeft, |
509 | colors: <Color>[ Color(0xFFFFFFFF), Color(0xFFFFFFFF) ], |
510 | ).createShader(const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0)); |
511 | }, |
512 | returnsNormally, |
513 | ); |
514 | }); |
515 | |
516 | test('RadialGradient lerp test', () { |
517 | const RadialGradient testGradient1 = RadialGradient( |
518 | center: Alignment.topLeft, |
519 | radius: 20.0, |
520 | colors: <Color>[ |
521 | Color(0x33333333), |
522 | Color(0x66666666), |
523 | ], |
524 | ); |
525 | const RadialGradient testGradient2 = RadialGradient( |
526 | center: Alignment.topRight, |
527 | radius: 10.0, |
528 | colors: <Color>[ |
529 | Color(0x44444444), |
530 | Color(0x88888888), |
531 | ], |
532 | ); |
533 | |
534 | final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5); |
535 | expect(actual, _matchesRadialGradient(const RadialGradient( |
536 | center: Alignment.topCenter, |
537 | radius: 15.0, |
538 | colors: <Color>[ |
539 | Color(0x3B3B3B3B), |
540 | Color(0x77777777), |
541 | ], |
542 | stops: <double>[ |
543 | 0.0, |
544 | 1.0, |
545 | ], |
546 | ))); |
547 | }); |
548 | |
549 | test('RadialGradient.lerp identical a,b', () { |
550 | expect(RadialGradient.lerp(null, null, 0), null); |
551 | const RadialGradient gradient = RadialGradient( |
552 | colors: <Color>[ |
553 | Color(0x33333333), |
554 | Color(0x66666666), |
555 | ], |
556 | ); |
557 | expect(identical(RadialGradient.lerp(gradient, gradient, 0.5), gradient), true); |
558 | }); |
559 | |
560 | test('RadialGradient lerp test with stops', () { |
561 | const RadialGradient testGradient1 = RadialGradient( |
562 | center: Alignment.topLeft, |
563 | radius: 20.0, |
564 | colors: <Color>[ |
565 | Color(0x33333333), |
566 | Color(0x66666666), |
567 | ], |
568 | stops: <double>[ |
569 | 0.0, |
570 | 0.5, |
571 | ], |
572 | ); |
573 | const RadialGradient testGradient2 = RadialGradient( |
574 | center: Alignment.topRight, |
575 | radius: 10.0, |
576 | colors: <Color>[ |
577 | Color(0x44444444), |
578 | Color(0x88888888), |
579 | ], |
580 | stops: <double>[ |
581 | 0.5, |
582 | 1.0, |
583 | ], |
584 | ); |
585 | |
586 | final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5); |
587 | |
588 | expect(actual, _matchesRadialGradient(const RadialGradient( |
589 | center: Alignment.topCenter, |
590 | radius: 15.0, |
591 | colors: <Color>[ |
592 | Color(0x3B3B3B3B), |
593 | Color(0x55555555), |
594 | Color(0x77777777), |
595 | ], |
596 | stops: <double>[ |
597 | 0.0, |
598 | 0.5, |
599 | 1.0, |
600 | ], |
601 | ))); |
602 | |
603 | expect(actual!.focal, isNull); |
604 | }); |
605 | |
606 | test('RadialGradient lerp test with unequal number of colors', () { |
607 | const RadialGradient testGradient1 = RadialGradient( |
608 | colors: <Color>[ |
609 | Color(0x22222222), |
610 | Color(0x66666666), |
611 | ], |
612 | ); |
613 | const RadialGradient testGradient2 = RadialGradient( |
614 | colors: <Color>[ |
615 | Color(0x44444444), |
616 | Color(0x66666666), |
617 | Color(0x88888888), |
618 | ], |
619 | ); |
620 | |
621 | final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5); |
622 | expect(actual, _matchesRadialGradient(const RadialGradient( |
623 | colors: <Color>[ |
624 | Color(0x33333333), |
625 | Color(0x55555555), |
626 | Color(0x77777777), |
627 | ], |
628 | stops: <double>[ |
629 | 0.0, |
630 | 0.5, |
631 | 1.0, |
632 | ], |
633 | ))); |
634 | }); |
635 | |
636 | test('RadialGradient lerp test with stops and unequal number of colors', () { |
637 | const RadialGradient testGradient1 = RadialGradient( |
638 | colors: <Color>[ |
639 | Color(0x33333333), |
640 | Color(0x66666666), |
641 | ], |
642 | stops: <double>[ |
643 | 0.0, |
644 | 0.5, |
645 | ], |
646 | ); |
647 | const RadialGradient testGradient2 = RadialGradient( |
648 | colors: <Color>[ |
649 | Color(0x44444444), |
650 | Color(0x48484848), |
651 | Color(0x88888888), |
652 | ], |
653 | stops: <double>[ |
654 | 0.5, |
655 | 0.7, |
656 | 1.0, |
657 | ], |
658 | ); |
659 | |
660 | final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5); |
661 | expect(actual, _matchesRadialGradient(const RadialGradient( |
662 | colors: <Color>[ |
663 | Color(0x3B3B3B3B), |
664 | Color(0x55555555), |
665 | Color(0x57575757), |
666 | Color(0x77777777), |
667 | ], |
668 | stops: <double>[ |
669 | 0.0, |
670 | 0.5, |
671 | 0.7, |
672 | 1.0, |
673 | ], |
674 | ))); |
675 | }); |
676 | |
677 | test('RadialGradient lerp test with transforms', () { |
678 | const RadialGradient testGradient1 = RadialGradient( |
679 | transform: GradientRotation(math.pi/4), |
680 | colors: <Color>[ |
681 | Color(0x33333333), |
682 | Color(0x66666666), |
683 | ], |
684 | stops: <double>[0, 1], |
685 | ); |
686 | const RadialGradient testGradient2 = RadialGradient( |
687 | transform: GradientRotation(math.pi/2), |
688 | colors: <Color>[ |
689 | Color(0x33333333), |
690 | Color(0x66666666), |
691 | ], |
692 | stops: <double>[0, 1], |
693 | ); |
694 | |
695 | final RadialGradient? actual0 = RadialGradient.lerp(testGradient1, testGradient2, 0.0); |
696 | final RadialGradient? actual1 = RadialGradient.lerp(testGradient1, testGradient2, 1.0); |
697 | final RadialGradient? actual2 = RadialGradient.lerp(testGradient1, testGradient2, 0.5); |
698 | expect(testGradient1, equals(actual0)); |
699 | expect(testGradient2, equals(actual1)); |
700 | expect(testGradient2, equals(actual2)); |
701 | }); |
702 | |
703 | test('RadialGradient lerp test with focal', () { |
704 | const RadialGradient testGradient1 = RadialGradient( |
705 | center: Alignment.topLeft, |
706 | focal: Alignment.centerLeft, |
707 | radius: 20.0, |
708 | focalRadius: 10.0, |
709 | colors: <Color>[ |
710 | Color(0x33333333), |
711 | Color(0x66666666), |
712 | ], |
713 | ); |
714 | const RadialGradient testGradient2 = RadialGradient( |
715 | center: Alignment.topRight, |
716 | focal: Alignment.centerRight, |
717 | radius: 10.0, |
718 | focalRadius: 5.0, |
719 | colors: <Color>[ |
720 | Color(0x44444444), |
721 | Color(0x88888888), |
722 | ], |
723 | ); |
724 | const RadialGradient testGradient3 = RadialGradient( |
725 | center: Alignment.topRight, |
726 | radius: 10.0, |
727 | colors: <Color>[ |
728 | Color(0x44444444), |
729 | Color(0x88888888), |
730 | ], |
731 | ); |
732 | |
733 | final RadialGradient? actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5); |
734 | expect(actual, _matchesRadialGradient(const RadialGradient( |
735 | center: Alignment.topCenter, |
736 | focal: Alignment.center, |
737 | radius: 15.0, |
738 | focalRadius: 7.5, |
739 | colors: <Color>[ |
740 | Color(0x3B3B3B3B), |
741 | Color(0x77777777), |
742 | ], |
743 | stops: <double>[ |
744 | 0.0, |
745 | 1.0, |
746 | ], |
747 | ))); |
748 | |
749 | final RadialGradient? actual2 = RadialGradient.lerp(testGradient1, testGradient3, 0.5); |
750 | expect(actual2, _matchesRadialGradient(const RadialGradient( |
751 | center: Alignment.topCenter, |
752 | focal: Alignment(-0.5, 0.0), |
753 | radius: 15.0, |
754 | focalRadius: 5.0, |
755 | colors: <Color>[ |
756 | Color(0x3B3B3B3B), |
757 | Color(0x77777777), |
758 | ], |
759 | stops: <double>[ |
760 | 0.0, |
761 | 1.0, |
762 | ], |
763 | ))); |
764 | }); |
765 | |
766 | |
767 | test('RadialGradient withOpacity test', () { |
768 | const RadialGradient testGradient = RadialGradient( |
769 | center: Alignment.topLeft, |
770 | focal: Alignment.centerLeft, |
771 | radius: 20.0, |
772 | focalRadius: 10.0, |
773 | colors: <Color>[ |
774 | Color(0xFFFFFFFF), |
775 | Color(0xAF777777), |
776 | Color(0x44444444), |
777 | ], |
778 | ); |
779 | final RadialGradient actual = testGradient.withOpacity(0.5); |
780 | |
781 | expect(actual, const RadialGradient( |
782 | center: Alignment.topLeft, |
783 | focal: Alignment.centerLeft, |
784 | radius: 20.0, |
785 | focalRadius: 10.0, |
786 | colors: <Color>[ |
787 | Color(0x80FFFFFF), |
788 | Color(0x80777777), |
789 | Color(0x80444444), |
790 | ], |
791 | )); |
792 | }); |
793 | |
794 | test('RadialGradient withOpacity() preserves transform', () { |
795 | const RadialGradient testGradient = RadialGradient( |
796 | center: Alignment.topLeft, |
797 | focal: Alignment.centerLeft, |
798 | radius: 20.0, |
799 | focalRadius: 10.0, |
800 | colors: <Color>[ |
801 | Color(0xFFFFFFFF), |
802 | Color(0xAF777777), |
803 | Color(0x44444444), |
804 | ], |
805 | transform: GradientRotation(1), |
806 | ); |
807 | final RadialGradient actual = testGradient.withOpacity(0.5); |
808 | |
809 | expect(actual, const RadialGradient( |
810 | center: Alignment.topLeft, |
811 | focal: Alignment.centerLeft, |
812 | radius: 20.0, |
813 | focalRadius: 10.0, |
814 | colors: <Color>[ |
815 | Color(0x80FFFFFF), |
816 | Color(0x80777777), |
817 | Color(0x80444444), |
818 | ], |
819 | transform: GradientRotation(1), |
820 | )); |
821 | }); |
822 | |
823 | test('SweepGradient lerp test', () { |
824 | const SweepGradient testGradient1 = SweepGradient( |
825 | center: Alignment.topLeft, |
826 | endAngle: math.pi / 2, |
827 | colors: <Color>[ |
828 | Color(0x33333333), |
829 | Color(0x66666666), |
830 | ], |
831 | ); |
832 | const SweepGradient testGradient2 = SweepGradient( |
833 | center: Alignment.topRight, |
834 | startAngle: math.pi / 2, |
835 | endAngle: math.pi, |
836 | colors: <Color>[ |
837 | Color(0x44444444), |
838 | Color(0x88888888), |
839 | ], |
840 | ); |
841 | |
842 | final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5); |
843 | expect(actual, _matchesSweepGradient(const SweepGradient( |
844 | center: Alignment.topCenter, |
845 | startAngle: math.pi / 4, |
846 | endAngle: math.pi * 3/4, |
847 | colors: <Color>[ |
848 | Color(0x3B3B3B3B), |
849 | Color(0x77777777), |
850 | ], |
851 | stops: <double>[ |
852 | 0.0, |
853 | 1.0, |
854 | ], |
855 | ))); |
856 | }); |
857 | |
858 | test('SweepGradient.lerp identical a,b', () { |
859 | expect(SweepGradient.lerp(null, null, 0), null); |
860 | const SweepGradient gradient = SweepGradient( |
861 | colors: <Color>[ |
862 | Color(0x33333333), |
863 | Color(0x66666666), |
864 | ], |
865 | ); |
866 | expect(identical(SweepGradient.lerp(gradient, gradient, 0.5), gradient), true); |
867 | }); |
868 | |
869 | test('SweepGradient lerp test with stops', () { |
870 | const SweepGradient testGradient1 = SweepGradient( |
871 | center: Alignment.topLeft, |
872 | endAngle: math.pi / 2, |
873 | colors: <Color>[ |
874 | Color(0x33333333), |
875 | Color(0x66666666), |
876 | ], |
877 | stops: <double>[ |
878 | 0.0, |
879 | 0.5, |
880 | ], |
881 | ); |
882 | const SweepGradient testGradient2 = SweepGradient( |
883 | center: Alignment.topRight, |
884 | startAngle: math.pi / 2, |
885 | endAngle: math.pi, |
886 | colors: <Color>[ |
887 | Color(0x44444444), |
888 | Color(0x88888888), |
889 | ], |
890 | stops: <double>[ |
891 | 0.5, |
892 | 1.0, |
893 | ], |
894 | ); |
895 | |
896 | final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5); |
897 | expect(actual, _matchesSweepGradient(const SweepGradient( |
898 | center: Alignment.topCenter, |
899 | startAngle: math.pi / 4, |
900 | endAngle: math.pi * 3/4, |
901 | colors: <Color>[ |
902 | Color(0x3B3B3B3B), |
903 | Color(0x55555555), |
904 | Color(0x77777777), |
905 | ], |
906 | stops: <double>[ |
907 | 0.0, |
908 | 0.5, |
909 | 1.0, |
910 | ], |
911 | ))); |
912 | }); |
913 | |
914 | test('SweepGradient lerp test with unequal number of colors', () { |
915 | const SweepGradient testGradient1 = SweepGradient( |
916 | colors: <Color>[ |
917 | Color(0x22222222), |
918 | Color(0x66666666), |
919 | ], |
920 | ); |
921 | const SweepGradient testGradient2 = SweepGradient( |
922 | colors: <Color>[ |
923 | Color(0x44444444), |
924 | Color(0x66666666), |
925 | Color(0x88888888), |
926 | ], |
927 | ); |
928 | |
929 | final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5); |
930 | expect(actual, _matchesSweepGradient(const SweepGradient( |
931 | colors: <Color>[ |
932 | Color(0x33333333), |
933 | Color(0x55555555), |
934 | Color(0x77777777), |
935 | ], |
936 | stops: <double>[ |
937 | 0.0, |
938 | 0.5, |
939 | 1.0, |
940 | ], |
941 | ))); |
942 | }); |
943 | |
944 | test('SweepGradient lerp test with stops and unequal number of colors', () { |
945 | const SweepGradient testGradient1 = SweepGradient( |
946 | colors: <Color>[ |
947 | Color(0x33333333), |
948 | Color(0x66666666), |
949 | ], |
950 | stops: <double>[ |
951 | 0.0, |
952 | 0.5, |
953 | ], |
954 | ); |
955 | const SweepGradient testGradient2 = SweepGradient( |
956 | colors: <Color>[ |
957 | Color(0x44444444), |
958 | Color(0x48484848), |
959 | Color(0x88888888), |
960 | ], |
961 | stops: <double>[ |
962 | 0.5, |
963 | 0.7, |
964 | 1.0, |
965 | ], |
966 | ); |
967 | |
968 | final SweepGradient? actual = SweepGradient.lerp(testGradient1, testGradient2, 0.5); |
969 | expect(actual, _matchesSweepGradient(const SweepGradient( |
970 | colors: <Color>[ |
971 | Color(0x3B3B3B3B), |
972 | Color(0x55555555), |
973 | Color(0x57575757), |
974 | Color(0x77777777), |
975 | ], |
976 | stops: <double>[ |
977 | 0.0, |
978 | 0.5, |
979 | 0.7, |
980 | 1.0, |
981 | ], |
982 | ))); |
983 | }); |
984 | |
985 | test('SweepGradient lerp test with transforms', () { |
986 | const SweepGradient testGradient1 = SweepGradient( |
987 | transform: GradientRotation(math.pi/4), |
988 | colors: <Color>[ |
989 | Color(0x33333333), |
990 | Color(0x66666666), |
991 | ], |
992 | stops: <double>[0, 1], |
993 | ); |
994 | const SweepGradient testGradient2 = SweepGradient( |
995 | transform: GradientRotation(math.pi/2), |
996 | colors: <Color>[ |
997 | Color(0x33333333), |
998 | Color(0x66666666), |
999 | ], |
1000 | stops: <double>[0, 1], |
1001 | ); |
1002 | |
1003 | final SweepGradient? actual0 = SweepGradient.lerp(testGradient1, testGradient2, 0.0); |
1004 | final SweepGradient? actual1 = SweepGradient.lerp(testGradient1, testGradient2, 1.0); |
1005 | final SweepGradient? actual2 = SweepGradient.lerp(testGradient1, testGradient2, 0.5); |
1006 | expect(testGradient1, equals(actual0)); |
1007 | expect(testGradient2, equals(actual1)); |
1008 | expect(testGradient2, equals(actual2)); |
1009 | }); |
1010 | |
1011 | test('SweepGradient scale test)', () { |
1012 | const SweepGradient testGradient = SweepGradient( |
1013 | center: Alignment.topLeft, |
1014 | endAngle: math.pi / 2, |
1015 | colors: <Color>[ |
1016 | Color(0xff333333), |
1017 | Color(0xff666666), |
1018 | ], |
1019 | ); |
1020 | |
1021 | final SweepGradient actual = testGradient.scale(0.5); |
1022 | |
1023 | expect(actual, _matchesSweepGradient(const SweepGradient( |
1024 | center: Alignment.topLeft, |
1025 | endAngle: math.pi / 2, |
1026 | colors: <Color>[ |
1027 | Color(0x80333333), |
1028 | Color(0x80666666), |
1029 | ], |
1030 | ))); |
1031 | }); |
1032 | |
1033 | test('SweepGradient withOpacity test', () { |
1034 | const SweepGradient testGradient = SweepGradient( |
1035 | center: Alignment.topLeft, |
1036 | endAngle: math.pi / 2, |
1037 | colors: <Color>[ |
1038 | Color(0xFFFFFFFF), |
1039 | Color(0xAF777777), |
1040 | Color(0x44444444), |
1041 | ], |
1042 | ); |
1043 | final SweepGradient actual = testGradient.withOpacity(0.5); |
1044 | |
1045 | expect(actual, const SweepGradient( |
1046 | center: Alignment.topLeft, |
1047 | endAngle: math.pi / 2, |
1048 | colors: <Color>[ |
1049 | Color(0x80FFFFFF), |
1050 | Color(0x80777777), |
1051 | Color(0x80444444), |
1052 | ], |
1053 | )); |
1054 | }); |
1055 | |
1056 | test('SweepGradient withOpacity() preserves transform', () { |
1057 | const SweepGradient testGradient = SweepGradient( |
1058 | center: Alignment.topLeft, |
1059 | endAngle: math.pi / 2, |
1060 | colors: <Color>[ |
1061 | Color(0xFFFFFFFF), |
1062 | Color(0xAF777777), |
1063 | Color(0x44444444), |
1064 | ], |
1065 | transform: GradientRotation(1), |
1066 | ); |
1067 | final SweepGradient actual = testGradient.withOpacity(0.5); |
1068 | |
1069 | expect(actual, const SweepGradient( |
1070 | center: Alignment.topLeft, |
1071 | endAngle: math.pi / 2, |
1072 | colors: <Color>[ |
1073 | Color(0x80FFFFFF), |
1074 | Color(0x80777777), |
1075 | Color(0x80444444), |
1076 | ], |
1077 | transform: GradientRotation(1), |
1078 | )); |
1079 | }); |
1080 | |
1081 | test('Gradient lerp test (with RadialGradient)', () { |
1082 | const RadialGradient testGradient1 = RadialGradient( |
1083 | center: Alignment.topLeft, |
1084 | radius: 20.0, |
1085 | colors: <Color>[ |
1086 | Color(0x33333333), |
1087 | Color(0x66666666), |
1088 | ], |
1089 | stops: <double>[ |
1090 | 0.0, |
1091 | 1.0, |
1092 | ], |
1093 | ); |
1094 | const RadialGradient testGradient2 = RadialGradient( |
1095 | center: Alignment.topCenter, |
1096 | radius: 15.0, |
1097 | colors: <Color>[ |
1098 | Color(0x3B3B3B3B), |
1099 | Color(0x77777777), |
1100 | ], |
1101 | stops: <double>[ |
1102 | 0.0, |
1103 | 1.0, |
1104 | ], |
1105 | ); |
1106 | const RadialGradient testGradient3 = RadialGradient( |
1107 | center: Alignment.topRight, |
1108 | radius: 10.0, |
1109 | colors: <Color>[ |
1110 | Color(0x44444444), |
1111 | Color(0x88888888), |
1112 | ], |
1113 | stops: <double>[ |
1114 | 0.0, |
1115 | 1.0, |
1116 | ], |
1117 | ); |
1118 | |
1119 | expect(Gradient.lerp(testGradient1, testGradient3, 0.0), _matchesRadialGradient(testGradient1)); |
1120 | expect(Gradient.lerp(testGradient1, testGradient3, 0.5), _matchesRadialGradient(testGradient2)); |
1121 | expect(Gradient.lerp(testGradient1, testGradient3, 1.0), _matchesRadialGradient(testGradient3)); |
1122 | expect(Gradient.lerp(testGradient3, testGradient1, 0.0), _matchesRadialGradient(testGradient3)); |
1123 | expect(Gradient.lerp(testGradient3, testGradient1, 0.5), _matchesRadialGradient(testGradient2)); |
1124 | expect(Gradient.lerp(testGradient3, testGradient1, 1.0), _matchesRadialGradient(testGradient1)); |
1125 | }); |
1126 | |
1127 | test('Gradient lerp test (LinearGradient to RadialGradient)', () { |
1128 | const LinearGradient testGradient1 = LinearGradient( |
1129 | begin: Alignment.topLeft, |
1130 | end: Alignment.bottomRight, |
1131 | colors: <Color>[ |
1132 | Color(0x33333333), |
1133 | Color(0x66666666), |
1134 | ], |
1135 | ); |
1136 | const RadialGradient testGradient2 = RadialGradient( |
1137 | radius: 20.0, |
1138 | colors: <Color>[ |
1139 | Color(0x44444444), |
1140 | Color(0x88888888), |
1141 | ], |
1142 | ); |
1143 | |
1144 | expect(Gradient.lerp(testGradient1, testGradient2, 0.0), testGradient1); |
1145 | expect(Gradient.lerp(testGradient1, testGradient2, 1.0), testGradient2); |
1146 | expect(Gradient.lerp(testGradient1, testGradient2, 0.5), testGradient2.scale(0.0)); |
1147 | }); |
1148 | |
1149 | test('Gradients can handle missing stops and report mismatched stops', () { |
1150 | const LinearGradient test1a = LinearGradient( |
1151 | colors: <Color>[ |
1152 | Color(0x11111111), |
1153 | Color(0x22222222), |
1154 | Color(0x33333333), |
1155 | ], |
1156 | ); |
1157 | const RadialGradient test1b = RadialGradient( |
1158 | colors: <Color>[ |
1159 | Color(0x11111111), |
1160 | Color(0x22222222), |
1161 | Color(0x33333333), |
1162 | ], |
1163 | ); |
1164 | const LinearGradient test2a = LinearGradient( |
1165 | colors: <Color>[ |
1166 | Color(0x11111111), |
1167 | Color(0x22222222), |
1168 | Color(0x33333333), |
1169 | ], |
1170 | stops: <double>[0.0, 1.0], |
1171 | ); |
1172 | const RadialGradient test2b = RadialGradient( |
1173 | colors: <Color>[ |
1174 | Color(0x11111111), |
1175 | Color(0x22222222), |
1176 | Color(0x33333333), |
1177 | ], |
1178 | stops: <double>[0.0, 1.0], |
1179 | ); |
1180 | const Rect rect = Rect.fromLTWH(1.0, 2.0, 3.0, 4.0); |
1181 | expect(test1a.createShader(rect), isNotNull); |
1182 | expect(test1b.createShader(rect), isNotNull); |
1183 | expect(() { test2a.createShader(rect); }, throwsArgumentError); |
1184 | expect(() { test2b.createShader(rect); }, throwsArgumentError); |
1185 | }); |
1186 | |
1187 | group('Transforms', () { |
1188 | const List<Color> colors = <Color>[Color(0xFFFFFFFF), Color(0xFF000088)]; |
1189 | const Rect rect = Rect.fromLTWH(0.0, 0.0, 300.0, 400.0); |
1190 | const List<Gradient> gradients45 = <Gradient>[ |
1191 | LinearGradient(colors: colors, transform: GradientRotation(math.pi/4)), |
1192 | // A radial gradient won't be interesting to rotate unless the center is changed. |
1193 | RadialGradient(colors: colors, center: Alignment.topCenter, transform: GradientRotation(math.pi/4)), |
1194 | SweepGradient(colors: colors, transform: GradientRotation(math.pi/4)), |
1195 | ]; |
1196 | const List<Gradient> gradients90 = <Gradient>[ |
1197 | LinearGradient(colors: colors, transform: GradientRotation(math.pi/2)), |
1198 | // A radial gradient won't be interesting to rotate unless the center is changed. |
1199 | RadialGradient(colors: colors, center: Alignment.topCenter, transform: GradientRotation(math.pi/2)), |
1200 | SweepGradient(colors: colors, transform: GradientRotation(math.pi/2)), |
1201 | ]; |
1202 | |
1203 | const Map<Type, String> gradientSnakeCase = <Type, String> { |
1204 | LinearGradient: 'linear_gradient', |
1205 | RadialGradient: 'radial_gradient', |
1206 | SweepGradient: 'sweep_gradient', |
1207 | }; |
1208 | |
1209 | Future<void> runTest(WidgetTester tester, Gradient gradient, double degrees) async { |
1210 | final String goldenName = '${gradientSnakeCase[gradient.runtimeType]} _$degrees .png'; |
1211 | final Shader shader = gradient.createShader( |
1212 | rect, |
1213 | ); |
1214 | final Key painterKey = UniqueKey(); |
1215 | await tester.pumpWidget(Center( |
1216 | child: SizedBox.fromSize( |
1217 | size: rect.size, |
1218 | child: RepaintBoundary( |
1219 | key: painterKey, |
1220 | child: CustomPaint( |
1221 | painter: GradientPainter(shader, rect), |
1222 | ), |
1223 | ), |
1224 | ), |
1225 | )); |
1226 | await expectLater( |
1227 | find.byKey(painterKey), |
1228 | matchesGoldenFile(goldenName), |
1229 | ); |
1230 | } |
1231 | |
1232 | group('Gradients - 45 degrees', () { |
1233 | for (final Gradient gradient in gradients45) { |
1234 | testWidgets('$gradient ', (WidgetTester tester) async { |
1235 | await runTest(tester, gradient, 45); |
1236 | }); |
1237 | } |
1238 | }); |
1239 | |
1240 | group('Gradients - 90 degrees', () { |
1241 | for (final Gradient gradient in gradients90) { |
1242 | testWidgets('$gradient ', (WidgetTester tester) async { |
1243 | await runTest(tester, gradient, 90); |
1244 | }); |
1245 | } |
1246 | }); |
1247 | }); |
1248 | } |
1249 | |
1250 | class GradientPainter extends CustomPainter { |
1251 | const GradientPainter(this.shader, this.rect); |
1252 | |
1253 | final Shader shader; |
1254 | final Rect rect; |
1255 | |
1256 | @override |
1257 | void paint(Canvas canvas, Size size) { |
1258 | canvas.drawRect(rect, Paint()..shader = shader); |
1259 | } |
1260 | |
1261 | @override |
1262 | bool shouldRepaint(CustomPainter oldDelegate) => true; |
1263 | |
1264 | } |
1265 |
Definitions
- _listDoubleMatches
- _listColorMatches
- _LinearGradientMatcher
- _LinearGradientMatcher
- describe
- matches
- _matchesLinearGradient
- _RadialGradientMatcher
- _RadialGradientMatcher
- describe
- matches
- _matchesRadialGradient
- _SweepGradientMatcher
- _SweepGradientMatcher
- describe
- matches
- _matchesSweepGradient
- main
- runTest
- GradientPainter
- GradientPainter
- paint
Learn more about Flutter for embedded and desktop on industrialflutter.com