@@ -557,6 +557,95 @@ void main() async {
557
557
expect (tabToTofuComparison, isFalse);
558
558
});
559
559
560
+ test ('drawRect, drawOval, and clipRect render with unsorted rectangles' , () async {
561
+ final PictureRecorder recorder = PictureRecorder ();
562
+ final Canvas canvas = Canvas (recorder);
563
+
564
+ canvas.drawColor (const Color (0xFFE0E0E0 ), BlendMode .src);
565
+
566
+ void draw (Rect rect, double x, double y, Color color) {
567
+ final Paint paint = Paint ()
568
+ ..color = color
569
+ ..strokeWidth = 5.0 ;
570
+
571
+ final Rect tallThin = Rect .fromLTRB (
572
+ min (rect.left, rect.right) - 10 ,
573
+ rect.top,
574
+ min (rect.left, rect.right) - 10 ,
575
+ rect.bottom,
576
+ );
577
+ final Rect wideThin = Rect .fromLTRB (
578
+ rect.left,
579
+ min (rect.top, rect.bottom) - 10 ,
580
+ rect.right,
581
+ min (rect.top, rect.bottom) - 10 ,
582
+ );
583
+
584
+ canvas.save ();
585
+ canvas.translate (x, y);
586
+
587
+ paint.style = PaintingStyle .fill;
588
+ canvas.drawRect (rect, paint);
589
+ canvas.drawRect (tallThin, paint);
590
+ canvas.drawRect (wideThin, paint);
591
+
592
+ canvas.save ();
593
+ canvas.translate (0 , 100 );
594
+ paint.style = PaintingStyle .stroke;
595
+ canvas.drawRect (rect, paint);
596
+ canvas.drawRect (tallThin, paint);
597
+ canvas.drawRect (wideThin, paint);
598
+ canvas.restore ();
599
+
600
+ canvas.save ();
601
+ canvas.translate (100 , 0 );
602
+ paint.style = PaintingStyle .fill;
603
+ canvas.drawOval (rect, paint);
604
+ canvas.drawOval (tallThin, paint);
605
+ canvas.drawOval (wideThin, paint);
606
+ canvas.restore ();
607
+
608
+ canvas.save ();
609
+ canvas.translate (100 , 100 );
610
+ paint.style = PaintingStyle .stroke;
611
+ canvas.drawOval (rect, paint);
612
+ canvas.drawOval (tallThin, paint);
613
+ canvas.drawOval (wideThin, paint);
614
+ canvas.restore ();
615
+
616
+ canvas.save ();
617
+ canvas.translate (50 , 50 );
618
+
619
+ canvas.save ();
620
+ canvas.clipRect (rect);
621
+ canvas.drawPaint (paint);
622
+ canvas.restore ();
623
+
624
+ canvas.save ();
625
+ canvas.clipRect (tallThin);
626
+ canvas.drawPaint (paint);
627
+ canvas.restore ();
628
+
629
+ canvas.save ();
630
+ canvas.clipRect (wideThin);
631
+ canvas.drawPaint (paint);
632
+ canvas.restore ();
633
+
634
+ canvas.restore ();
635
+
636
+ canvas.restore ();
637
+ }
638
+
639
+ draw (const Rect .fromLTRB (10 , 10 , 40 , 40 ), 50 , 50 , const Color (0xFF2196F3 ));
640
+ draw (const Rect .fromLTRB (40 , 10 , 10 , 40 ), 250 , 50 , const Color (0xFF4CAF50 ));
641
+ draw (const Rect .fromLTRB (10 , 40 , 40 , 10 ), 50 , 250 , const Color (0xFF9C27B0 ));
642
+ draw (const Rect .fromLTRB (40 , 40 , 10 , 10 ), 250 , 250 , const Color (0xFFFF9800 ));
643
+
644
+ final Picture picture = recorder.endRecording ();
645
+ final Image image = await picture.toImage (450 , 450 );
646
+ await comparer.addGoldenImage (image, 'render_unordered_rects.png' );
647
+ });
648
+
560
649
Matcher closeToTransform (Float64List expected) => (dynamic v) {
561
650
Expect .type <Float64List >(v);
562
651
final Float64List value = v as Float64List ;
@@ -676,83 +765,82 @@ void main() async {
676
765
Expect .fail ('$value is too close to $expected ' );
677
766
};
678
767
679
- test ('Canvas.clipRect(doAA=true) affects canvas.getClipBounds' , () async {
680
- final PictureRecorder recorder = PictureRecorder ();
681
- final Canvas canvas = Canvas (recorder);
682
- const Rect clipBounds = Rect .fromLTRB (10.2 , 11.3 , 20.4 , 25.7 );
683
- const Rect clipExpandedBounds = Rect .fromLTRB (10 , 11 , 21 , 26 );
684
- canvas.clipRect (clipBounds);
685
-
686
- // Save initial return values for testing restored values
687
- final Rect initialLocalBounds = canvas.getLocalClipBounds ();
688
- final Rect initialDestinationBounds = canvas.getDestinationClipBounds ();
689
- expect (initialLocalBounds, closeToRect (clipExpandedBounds));
690
- expect (initialDestinationBounds, closeToRect (clipExpandedBounds));
691
-
692
- canvas.save ();
693
- canvas.clipRect (const Rect .fromLTRB (0 , 0 , 15 , 15 ));
694
- // Both clip bounds have changed
695
- expect (canvas.getLocalClipBounds (), notCloseToRect (clipExpandedBounds));
696
- expect (canvas.getDestinationClipBounds (), notCloseToRect (clipExpandedBounds));
697
- // Previous return values have not changed
698
- expect (initialLocalBounds, closeToRect (clipExpandedBounds));
699
- expect (initialDestinationBounds, closeToRect (clipExpandedBounds));
700
- canvas.restore ();
701
-
702
- // save/restore returned the values to their original values
703
- expect (canvas.getLocalClipBounds (), initialLocalBounds);
704
- expect (canvas.getDestinationClipBounds (), initialDestinationBounds);
705
-
706
- canvas.save ();
707
- canvas.scale (2 , 2 );
708
- const Rect scaledExpandedBounds = Rect .fromLTRB (5 , 5.5 , 10.5 , 13 );
709
- expect (canvas.getLocalClipBounds (), closeToRect (scaledExpandedBounds));
710
- // Destination bounds are unaffected by transform
711
- expect (canvas.getDestinationClipBounds (), closeToRect (clipExpandedBounds));
712
- canvas.restore ();
713
-
714
- // save/restore returned the values to their original values
715
- expect (canvas.getLocalClipBounds (), initialLocalBounds);
716
- expect (canvas.getDestinationClipBounds (), initialDestinationBounds);
717
- });
718
-
719
- test ('Canvas.clipRect(doAA=false) affects canvas.getClipBounds' , () async {
720
- final PictureRecorder recorder = PictureRecorder ();
721
- final Canvas canvas = Canvas (recorder);
722
- const Rect clipBounds = Rect .fromLTRB (10.2 , 11.3 , 20.4 , 25.7 );
723
- canvas.clipRect (clipBounds, doAntiAlias: false );
768
+ test ('Canvas.clipRect affects canvas.getClipBounds' , () async {
769
+ void testRect (Rect clipRect, bool doAA) {
770
+ final PictureRecorder recorder = PictureRecorder ();
771
+ final Canvas canvas = Canvas (recorder);
772
+ canvas.clipRect (clipRect, doAntiAlias: doAA);
773
+
774
+ final Rect clipSortedBounds = Rect .fromLTRB (
775
+ min (clipRect.left, clipRect.right),
776
+ min (clipRect.top, clipRect.bottom),
777
+ max (clipRect.left, clipRect.right),
778
+ max (clipRect.top, clipRect.bottom),
779
+ );
780
+ Rect clipExpandedBounds;
781
+ if (doAA) {
782
+ clipExpandedBounds = Rect .fromLTRB (
783
+ clipSortedBounds.left.floorToDouble (),
784
+ clipSortedBounds.top.floorToDouble (),
785
+ clipSortedBounds.right.ceilToDouble (),
786
+ clipSortedBounds.bottom.ceilToDouble (),
787
+ );
788
+ } else {
789
+ clipExpandedBounds = clipSortedBounds;
790
+ }
724
791
725
- // Save initial return values for testing restored values
726
- final Rect initialLocalBounds = canvas.getLocalClipBounds ();
727
- final Rect initialDestinationBounds = canvas.getDestinationClipBounds ();
728
- expect (initialLocalBounds, closeToRect (clipBounds));
729
- expect (initialDestinationBounds, closeToRect (clipBounds));
792
+ // Save initial return values for testing restored values
793
+ final Rect initialLocalBounds = canvas.getLocalClipBounds ();
794
+ final Rect initialDestinationBounds = canvas.getDestinationClipBounds ();
795
+ expect (initialLocalBounds, closeToRect (clipExpandedBounds));
796
+ expect (initialDestinationBounds, closeToRect (clipExpandedBounds));
797
+
798
+ canvas.save ();
799
+ canvas.clipRect (const Rect .fromLTRB (0 , 0 , 15 , 15 ));
800
+ // Both clip bounds have changed
801
+ expect (canvas.getLocalClipBounds (), notCloseToRect (clipExpandedBounds));
802
+ expect (canvas.getDestinationClipBounds (), notCloseToRect (clipExpandedBounds));
803
+ // Previous return values have not changed
804
+ expect (initialLocalBounds, closeToRect (clipExpandedBounds));
805
+ expect (initialDestinationBounds, closeToRect (clipExpandedBounds));
806
+ canvas.restore ();
807
+
808
+ // save/restore returned the values to their original values
809
+ expect (canvas.getLocalClipBounds (), initialLocalBounds);
810
+ expect (canvas.getDestinationClipBounds (), initialDestinationBounds);
811
+
812
+ canvas.save ();
813
+ canvas.scale (2 , 2 );
814
+ final Rect scaledExpandedBounds = Rect .fromLTRB (
815
+ clipExpandedBounds.left / 2.0 ,
816
+ clipExpandedBounds.top / 2.0 ,
817
+ clipExpandedBounds.right / 2.0 ,
818
+ clipExpandedBounds.bottom / 2.0 ,
819
+ );
820
+ expect (canvas.getLocalClipBounds (), closeToRect (scaledExpandedBounds));
821
+ // Destination bounds are unaffected by transform
822
+ expect (canvas.getDestinationClipBounds (), closeToRect (clipExpandedBounds));
823
+ canvas.restore ();
824
+
825
+ // save/restore returned the values to their original values
826
+ expect (canvas.getLocalClipBounds (), initialLocalBounds);
827
+ expect (canvas.getDestinationClipBounds (), initialDestinationBounds);
828
+ }
730
829
731
- canvas.save ();
732
- canvas.clipRect (const Rect .fromLTRB (0 , 0 , 15 , 15 ));
733
- // Both clip bounds have changed
734
- expect (canvas.getLocalClipBounds (), notCloseToRect (clipBounds));
735
- expect (canvas.getDestinationClipBounds (), notCloseToRect (clipBounds));
736
- // Previous return values have not changed
737
- expect (initialLocalBounds, closeToRect (clipBounds));
738
- expect (initialDestinationBounds, closeToRect (clipBounds));
739
- canvas.restore ();
830
+ testRect (const Rect .fromLTRB (10.2 , 11.3 , 20.4 , 25.7 ), false );
831
+ testRect (const Rect .fromLTRB (10.2 , 11.3 , 20.4 , 25.7 ), true );
740
832
741
- // save/restore returned the values to their original values
742
- expect (canvas. getLocalClipBounds ( ), initialLocalBounds );
743
- expect (canvas. getDestinationClipBounds ( ), initialDestinationBounds );
833
+ // LR swapped
834
+ testRect ( const Rect . fromLTRB ( 20.4 , 11.3 , 10.2 , 25.7 ), false );
835
+ testRect ( const Rect . fromLTRB ( 20.4 , 11.3 , 10.2 , 25.7 ), true );
744
836
745
- canvas.save ();
746
- canvas.scale (2 , 2 );
747
- const Rect scaledClipBounds = Rect .fromLTRB (5.1 , 5.65 , 10.2 , 12.85 );
748
- expect (canvas.getLocalClipBounds (), closeToRect (scaledClipBounds));
749
- // Destination bounds are unaffected by transform
750
- expect (canvas.getDestinationClipBounds (), closeToRect (clipBounds));
751
- canvas.restore ();
837
+ // TB swapped
838
+ testRect (const Rect .fromLTRB (10.2 , 25.7 , 20.4 , 11.3 ), false );
839
+ testRect (const Rect .fromLTRB (10.2 , 25.7 , 20.4 , 11.3 ), true );
752
840
753
- // save/restore returned the values to their original values
754
- expect (canvas. getLocalClipBounds ( ), initialLocalBounds );
755
- expect (canvas. getDestinationClipBounds ( ), initialDestinationBounds );
841
+ // LR and TB swapped
842
+ testRect ( const Rect . fromLTRB ( 20.4 , 25.7 , 10.2 , 11.3 ), false );
843
+ testRect ( const Rect . fromLTRB ( 20.4 , 25.7 , 10.2 , 11.3 ), true );
756
844
});
757
845
758
846
test ('Canvas.clipRect with matrix affects canvas.getClipBounds' , () async {
0 commit comments