@@ -9,6 +9,7 @@ import 'package:fake_async/fake_async.dart';
99import 'package:flutter/foundation.dart' ;
1010import 'package:flutter/painting.dart' ;
1111import 'package:flutter_test/flutter_test.dart' ;
12+ import 'package:vector_math/vector_math_64.dart' ;
1213
1314import '../image_data.dart' ;
1415import '../painting/mocks_for_image_cache.dart' ;
@@ -672,7 +673,8 @@ void main() {
672673 final TestCanvas canvas = TestCanvas ();
673674
674675 // Paint a square image into an output rect that is twice as wide as it is
675- // tall. Two copies of the image should be painted, one next to the other.
676+ // tall. One copy of the image should be painted, aligned so that a repeating
677+ // tile mode causes it to appear twice.
676678 const Rect outputRect = Rect .fromLTWH (30.0 , 30.0 , 400.0 , 200.0 );
677679 final ui.Image image = await createTestImage (width: 100 , height: 100 );
678680
@@ -685,34 +687,29 @@ void main() {
685687 repeat: ImageRepeat .repeatX,
686688 );
687689
688- const Size imageSize = Size (100.0 , 100.0 );
689-
690- final List <Invocation > calls = canvas.invocations.where ((Invocation call) => call.memberName == #drawImageRect).toList ();
691- final Set <Rect > tileRects = < Rect > {};
692-
693- expect (calls, hasLength (2 ));
694- for (final Invocation call in calls) {
695- expect (call.isMethod, isTrue);
696- expect (call.positionalArguments, hasLength (4 ));
690+ final List <Invocation > calls = canvas.invocations.where ((Invocation call) => call.memberName == #drawRect).toList ();
697691
698- expect (call.positionalArguments[ 0 ], isA < ui. Image > ( ));
699-
700- // sourceRect should contain all pixels of the source image
701- expect (call.positionalArguments[ 1 ], Offset .zero & imageSize );
692+ expect (calls, hasLength ( 1 ));
693+ final Invocation call = calls[ 0 ];
694+ expect (call.isMethod, isTrue);
695+ expect (call.positionalArguments, hasLength ( 2 ) );
702696
703- tileRects.add (call.positionalArguments[2 ] as Rect );
697+ // A tiled image is drawn as a rect with a shader.
698+ expect (call.positionalArguments[0 ], isA <Rect >());
699+ expect (call.positionalArguments[1 ], isA <Paint >());
704700
705- expect (call.positionalArguments[3 ], isA <Paint >());
706- }
701+ final Paint paint = call.positionalArguments[1 ] as Paint ;
707702
708- expect (tileRects, < Rect > {const Rect .fromLTWH (30.0 , 30.0 , 200.0 , 200.0 ), const Rect .fromLTWH (230.0 , 30.0 , 200.0 , 200.0 )});
703+ expect (paint.shader, isA <ImageShader >());
704+ expect (call.positionalArguments[0 ], outputRect);
709705 });
710706
711707 test ('paintImage with repeatY and fitWidth' , () async {
712708 final TestCanvas canvas = TestCanvas ();
713709
714710 // Paint a square image into an output rect that is twice as tall as it is
715- // wide. Two copies of the image should be painted, one above the other.
711+ // wide. One copy of the image should be painted, aligned so that a repeating
712+ // tile mode causes it to appear twice.
716713 const Rect outputRect = Rect .fromLTWH (30.0 , 30.0 , 200.0 , 400.0 );
717714 final ui.Image image = await createTestImage (width: 100 , height: 100 );
718715
@@ -724,28 +721,21 @@ void main() {
724721 fit: BoxFit .fitWidth,
725722 repeat: ImageRepeat .repeatY,
726723 );
724+ final List <Invocation > calls = canvas.invocations.where ((Invocation call) => call.memberName == #drawRect).toList ();
727725
728- const Size imageSize = Size (100.0 , 100.0 );
729-
730- final List <Invocation > calls = canvas.invocations.where ((Invocation call) => call.memberName == #drawImageRect).toList ();
731- final Set <Rect > tileRects = < Rect > {};
732-
733- expect (calls, hasLength (2 ));
734- for (final Invocation call in calls) {
735- expect (call.isMethod, isTrue);
736- expect (call.positionalArguments, hasLength (4 ));
737-
738- expect (call.positionalArguments[0 ], isA< ui.Image > ());
739-
740- // sourceRect should contain all pixels of the source image
741- expect (call.positionalArguments[1 ], Offset .zero & imageSize);
726+ expect (calls, hasLength (1 ));
727+ final Invocation call = calls[0 ];
728+ expect (call.isMethod, isTrue);
729+ expect (call.positionalArguments, hasLength (2 ));
742730
743- tileRects.add (call.positionalArguments[2 ] as Rect );
731+ // A tiled image is drawn as a rect with a shader.
732+ expect (call.positionalArguments[0 ], isA <Rect >());
733+ expect (call.positionalArguments[1 ], isA <Paint >());
744734
745- expect (call.positionalArguments[3 ], isA <Paint >());
746- }
735+ final Paint paint = call.positionalArguments[1 ] as Paint ;
747736
748- expect (tileRects, < Rect > {const Rect .fromLTWH (30.0 , 30.0 , 200.0 , 200.0 ), const Rect .fromLTWH (30.0 , 230.0 , 200.0 , 200.0 )});
737+ expect (paint.shader, isA <ImageShader >());
738+ expect (call.positionalArguments[0 ], outputRect);
749739 });
750740
751741 test ('DecorationImage scale test' , () async {
@@ -794,4 +784,52 @@ void main() {
794784
795785 info.dispose ();
796786 }, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87442
787+
788+ test ('Compute image tiling' , () {
789+ expect (() => createTilingInfo (ImageRepeat .noRepeat, Rect .zero, Rect .zero, Rect .zero), throwsAssertionError);
790+
791+ // These tests draw a 16x9 image into a 100x50 container with a destination
792+ // size of and make assertions based on observed behavior and the original
793+ // rectangles from https://github.com/flutter/flutter/pull/119495/
794+
795+ final ImageTilingInfo repeatX = createTilingInfo (
796+ ImageRepeat .repeatX,
797+ const Rect .fromLTRB (0.0 , 0.0 , 100.0 , 50.0 ),
798+ const Rect .fromLTRB (84.0 , 0.0 , 100.0 , 9.0 ),
799+ const Rect .fromLTRB (0.0 , 0.0 , 16.0 , 9.0 ),
800+ );
801+
802+ expect (repeatX.tmx, TileMode .repeated);
803+ expect (repeatX.tmy, TileMode .decal);
804+ expect (repeatX.transform, matrixMoreOrLessEquals (Matrix4 .identity ()
805+ ..scale (1.0 , 1.0 )
806+ ..setTranslationRaw (- 12.0 , 0.0 , 0.0 )
807+ ));
808+
809+ final ImageTilingInfo repeatY = createTilingInfo (
810+ ImageRepeat .repeatY,
811+ const Rect .fromLTRB (0.0 , 0.0 , 100.0 , 50.0 ),
812+ const Rect .fromLTRB (84.0 , 0.0 , 100.0 , 9.0 ),
813+ const Rect .fromLTRB (0.0 , 0.0 , 16.0 , 9.0 ),
814+ );
815+ expect (repeatY.tmx, TileMode .decal);
816+ expect (repeatY.tmy, TileMode .repeated);
817+ expect (repeatY.transform, matrixMoreOrLessEquals (Matrix4 .identity ()
818+ ..scale (1.0 , 1.0 )
819+ ..setTranslationRaw (84.0 , 0.0 , 0.0 )
820+ ));
821+
822+ final ImageTilingInfo repeat = createTilingInfo (
823+ ImageRepeat .repeat,
824+ const Rect .fromLTRB (0.0 , 0.0 , 100.0 , 50.0 ),
825+ const Rect .fromLTRB (84.0 , 0.0 , 100.0 , 9.0 ),
826+ const Rect .fromLTRB (0.0 , 0.0 , 16.0 , 9.0 ),
827+ );
828+ expect (repeat.tmx, TileMode .repeated);
829+ expect (repeat.tmy, TileMode .repeated);
830+ expect (repeat.transform, matrixMoreOrLessEquals (Matrix4 .identity ()
831+ ..scale (1.0 , 1.0 )
832+ ..setTranslationRaw (- 12.0 , 0.0 , 0.0 )
833+ ));
834+ });
797835}
0 commit comments