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) => _LinearGradientMatcher(target); |
72 | |
73 | class _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 | |
100 | Matcher _matchesRadialGradient(RadialGradient target) => _RadialGradientMatcher(target); |
101 | |
102 | class _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 | |
128 | Matcher _matchesSweepGradient(SweepGradient target) => _SweepGradientMatcher(target); |
129 | |
130 | void 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 | |
963 | class 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 |
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