@@ -9,6 +9,7 @@ import 'package:fake_async/fake_async.dart';
9
9
import 'package:flutter/foundation.dart' ;
10
10
import 'package:flutter/painting.dart' ;
11
11
import 'package:flutter_test/flutter_test.dart' ;
12
+ import 'package:vector_math/vector_math_64.dart' ;
12
13
13
14
import '../image_data.dart' ;
14
15
import '../painting/mocks_for_image_cache.dart' ;
@@ -672,7 +673,8 @@ void main() {
672
673
final TestCanvas canvas = TestCanvas ();
673
674
674
675
// 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.
676
678
const Rect outputRect = Rect .fromLTWH (30.0 , 30.0 , 400.0 , 200.0 );
677
679
final ui.Image image = await createTestImage (width: 100 , height: 100 );
678
680
@@ -685,34 +687,29 @@ void main() {
685
687
repeat: ImageRepeat .repeatX,
686
688
);
687
689
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 ();
697
691
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 ) );
702
696
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 >());
704
700
705
- expect (call.positionalArguments[3 ], isA <Paint >());
706
- }
701
+ final Paint paint = call.positionalArguments[1 ] as Paint ;
707
702
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);
709
705
});
710
706
711
707
test ('paintImage with repeatY and fitWidth' , () async {
712
708
final TestCanvas canvas = TestCanvas ();
713
709
714
710
// 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.
716
713
const Rect outputRect = Rect .fromLTWH (30.0 , 30.0 , 200.0 , 400.0 );
717
714
final ui.Image image = await createTestImage (width: 100 , height: 100 );
718
715
@@ -724,28 +721,21 @@ void main() {
724
721
fit: BoxFit .fitWidth,
725
722
repeat: ImageRepeat .repeatY,
726
723
);
724
+ final List <Invocation > calls = canvas.invocations.where ((Invocation call) => call.memberName == #drawRect).toList ();
727
725
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 ));
742
730
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 >());
744
734
745
- expect (call.positionalArguments[3 ], isA <Paint >());
746
- }
735
+ final Paint paint = call.positionalArguments[1 ] as Paint ;
747
736
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);
749
739
});
750
740
751
741
test ('DecorationImage scale test' , () async {
@@ -794,4 +784,52 @@ void main() {
794
784
795
785
info.dispose ();
796
786
}, 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
+ });
797
835
}
0 commit comments