@@ -124,6 +124,95 @@ class DisplayListTestBase : public BaseT {
124
124
EXPECT_EQ (builder.GetSaveCount (), 1 );
125
125
}
126
126
127
+ typedef const std::function<void (DlCanvas&)> DlSetup;
128
+ typedef const std::function<void (DlCanvas&, DlPaint&, SkRect& rect)>
129
+ DlRenderer;
130
+
131
+ static void verify_inverted_bounds (DlSetup& setup,
132
+ DlRenderer& renderer,
133
+ DlPaint paint,
134
+ SkRect render_rect,
135
+ SkRect expected_bounds,
136
+ const std::string& desc) {
137
+ DisplayListBuilder builder;
138
+ setup (builder);
139
+ renderer (builder, paint, render_rect);
140
+ auto dl = builder.Build ();
141
+ EXPECT_EQ (dl->op_count (), 1u ) << desc;
142
+ EXPECT_EQ (dl->bounds (), expected_bounds) << desc;
143
+ }
144
+
145
+ static void check_inverted_bounds (DlRenderer& renderer,
146
+ const std::string& desc) {
147
+ SkRect rect = SkRect::MakeLTRB (0 .0f , 0 .0f , 10 .0f , 10 .0f );
148
+ SkRect invertedLR = SkRect::MakeLTRB (rect.fRight , rect.fTop , //
149
+ rect.fLeft , rect.fBottom );
150
+ SkRect invertedTB = SkRect::MakeLTRB (rect.fLeft , rect.fBottom , //
151
+ rect.fRight , rect.fTop );
152
+ SkRect invertedLTRB = SkRect::MakeLTRB (rect.fRight , rect.fBottom , //
153
+ rect.fLeft , rect.fTop );
154
+ auto empty_setup = [](DlCanvas&) {};
155
+
156
+ ASSERT_TRUE (rect.fLeft < rect.fRight );
157
+ ASSERT_TRUE (rect.fTop < rect.fBottom );
158
+ ASSERT_FALSE (rect.isEmpty ());
159
+ ASSERT_TRUE (invertedLR.fLeft > invertedLR.fRight );
160
+ ASSERT_TRUE (invertedLR.isEmpty ());
161
+ ASSERT_TRUE (invertedTB.fTop > invertedTB.fBottom );
162
+ ASSERT_TRUE (invertedTB.isEmpty ());
163
+ ASSERT_TRUE (invertedLTRB.fLeft > invertedLTRB.fRight );
164
+ ASSERT_TRUE (invertedLTRB.fTop > invertedLTRB.fBottom );
165
+ ASSERT_TRUE (invertedLTRB.isEmpty ());
166
+
167
+ DlPaint ref_paint = DlPaint ();
168
+ SkRect ref_bounds = rect;
169
+ verify_inverted_bounds (empty_setup, renderer, ref_paint, invertedLR,
170
+ ref_bounds, desc + " LR swapped" );
171
+ verify_inverted_bounds (empty_setup, renderer, ref_paint, invertedTB,
172
+ ref_bounds, desc + " TB swapped" );
173
+ verify_inverted_bounds (empty_setup, renderer, ref_paint, invertedLTRB,
174
+ ref_bounds, desc + " LR&TB swapped" );
175
+
176
+ // Round joins are used because miter joins greatly pad the bounds,
177
+ // but only on paths. So we use round joins for consistency there.
178
+ // We aren't fully testing all stroke-related bounds computations here,
179
+ // those are more fully tested in the render tests. We are simply
180
+ // checking that they are applied to the ordered bounds.
181
+ DlPaint stroke_paint = DlPaint () //
182
+ .setDrawStyle (DlDrawStyle::kStroke ) //
183
+ .setStrokeJoin (DlStrokeJoin::kRound ) //
184
+ .setStrokeWidth (2 .0f );
185
+ SkRect stroke_bounds = rect.makeOutset (1 .0f , 1 .0f );
186
+ verify_inverted_bounds (empty_setup, renderer, stroke_paint, invertedLR,
187
+ stroke_bounds, desc + " LR swapped, sw 2" );
188
+ verify_inverted_bounds (empty_setup, renderer, stroke_paint, invertedTB,
189
+ stroke_bounds, desc + " TB swapped, sw 2" );
190
+ verify_inverted_bounds (empty_setup, renderer, stroke_paint, invertedLTRB,
191
+ stroke_bounds, desc + " LR&TB swapped, sw 2" );
192
+
193
+ DlBlurMaskFilter mask_filter (DlBlurStyle::kNormal , 2 .0f );
194
+ DlPaint maskblur_paint = DlPaint () //
195
+ .setMaskFilter (&mask_filter);
196
+ SkRect maskblur_bounds = rect.makeOutset (6 .0f , 6 .0f );
197
+ verify_inverted_bounds (empty_setup, renderer, maskblur_paint, invertedLR,
198
+ maskblur_bounds, desc + " LR swapped, mask 2" );
199
+ verify_inverted_bounds (empty_setup, renderer, maskblur_paint, invertedTB,
200
+ maskblur_bounds, desc + " TB swapped, mask 2" );
201
+ verify_inverted_bounds (empty_setup, renderer, maskblur_paint, invertedLTRB,
202
+ maskblur_bounds, desc + " LR&TB swapped, mask 2" );
203
+
204
+ DlErodeImageFilter erode_filter (2 .0f , 2 .0f );
205
+ DlPaint erode_paint = DlPaint () //
206
+ .setImageFilter (&erode_filter);
207
+ SkRect erode_bounds = rect.makeInset (2 .0f , 2 .0f );
208
+ verify_inverted_bounds (empty_setup, renderer, erode_paint, invertedLR,
209
+ erode_bounds, desc + " LR swapped, erode 2" );
210
+ verify_inverted_bounds (empty_setup, renderer, erode_paint, invertedTB,
211
+ erode_bounds, desc + " TB swapped, erode 2" );
212
+ verify_inverted_bounds (empty_setup, renderer, erode_paint, invertedLTRB,
213
+ erode_bounds, desc + " LR&TB swapped, erode 2" );
214
+ }
215
+
127
216
private:
128
217
FML_DISALLOW_COPY_AND_ASSIGN (DisplayListTestBase);
129
218
};
@@ -2874,5 +2963,58 @@ TEST_F(DisplayListTest, DrawSaveDrawCannotInheritOpacity) {
2874
2963
ASSERT_FALSE (display_list->can_apply_group_opacity ());
2875
2964
}
2876
2965
2966
+ TEST_F (DisplayListTest, DrawUnorderedRect) {
2967
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
2968
+ canvas.DrawRect (rect, paint);
2969
+ };
2970
+ check_inverted_bounds (renderer, " DrawRect" );
2971
+ }
2972
+
2973
+ TEST_F (DisplayListTest, DrawUnorderedRoundRect) {
2974
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
2975
+ canvas.DrawRRect (SkRRect::MakeRectXY (rect, 2 .0f , 2 .0f ), paint);
2976
+ };
2977
+ check_inverted_bounds (renderer, " DrawRoundRect" );
2978
+ }
2979
+
2980
+ TEST_F (DisplayListTest, DrawUnorderedOval) {
2981
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
2982
+ canvas.DrawOval (rect, paint);
2983
+ };
2984
+ check_inverted_bounds (renderer, " DrawOval" );
2985
+ }
2986
+
2987
+ TEST_F (DisplayListTest, DrawUnorderedRectangularPath) {
2988
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
2989
+ canvas.DrawPath (SkPath ().addRect (rect), paint);
2990
+ };
2991
+ check_inverted_bounds (renderer, " DrawRectangularPath" );
2992
+ }
2993
+
2994
+ TEST_F (DisplayListTest, DrawUnorderedOvalPath) {
2995
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
2996
+ canvas.DrawPath (SkPath ().addOval (rect), paint);
2997
+ };
2998
+ check_inverted_bounds (renderer, " DrawOvalPath" );
2999
+ }
3000
+
3001
+ TEST_F (DisplayListTest, DrawUnorderedRoundRectPathCW) {
3002
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
3003
+ SkPath path = SkPath () //
3004
+ .addRoundRect (rect, 2 .0f , 2 .0f , SkPathDirection::kCW );
3005
+ canvas.DrawPath (path, paint);
3006
+ };
3007
+ check_inverted_bounds (renderer, " DrawRoundRectPath Clockwise" );
3008
+ }
3009
+
3010
+ TEST_F (DisplayListTest, DrawUnorderedRoundRectPathCCW) {
3011
+ auto renderer = [](DlCanvas& canvas, DlPaint& paint, SkRect& rect) {
3012
+ SkPath path = SkPath () //
3013
+ .addRoundRect (rect, 2 .0f , 2 .0f , SkPathDirection::kCCW );
3014
+ canvas.DrawPath (path, paint);
3015
+ };
3016
+ check_inverted_bounds (renderer, " DrawRoundRectPath Counter-Clockwise" );
3017
+ }
3018
+
2877
3019
} // namespace testing
2878
3020
} // namespace flutter
0 commit comments