Flutter Engine
The Flutter Engine
dl_matrix_clip_tracker_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 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#include "flutter/display_list/utils/dl_matrix_clip_tracker.h"
6#include "flutter/testing/assertions_skia.h"
7#include "gtest/gtest.h"
8
9namespace flutter {
10namespace testing {
11
13 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
14 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
15 const SkMatrix matrix = SkMatrix::Scale(4, 4);
16 const SkM44 m44 = SkM44::Scale(4, 4);
17 const DlMatrix dl_matrix = DlMatrix::MakeScale({4.0, 4.0, 1.0});
18 const SkRect local_cull_rect = SkRect::MakeLTRB(5, 10, 15, 20);
19
20 DisplayListMatrixClipState state1(cull_rect, matrix);
21 DisplayListMatrixClipState state2(cull_rect, m44);
22 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
23
24 EXPECT_FALSE(state1.using_4x4_matrix());
25 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
26 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
27 EXPECT_EQ(state1.matrix_3x3(), matrix);
28 EXPECT_EQ(state1.matrix_4x4(), m44);
29 EXPECT_EQ(state1.matrix(), dl_matrix);
30
31 EXPECT_FALSE(state2.using_4x4_matrix());
32 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
33 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
34 EXPECT_EQ(state2.matrix_3x3(), matrix);
35 EXPECT_EQ(state2.matrix_4x4(), m44);
36 EXPECT_EQ(state2.matrix(), dl_matrix);
37
38 EXPECT_FALSE(state3.using_4x4_matrix());
39 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
40 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
41 EXPECT_EQ(state3.matrix_3x3(), matrix);
42 EXPECT_EQ(state3.matrix_4x4(), m44);
43 EXPECT_EQ(state3.matrix(), dl_matrix);
44}
45
47 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
48 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
49 // clang-format off
50 const SkM44 m44 = SkM44(4, 0, 0.5, 0,
51 0, 4, 0.5, 0,
52 0, 0, 4.0, 0,
53 0, 0, 0.0, 1);
54 const DlMatrix dl_matrix = DlMatrix::MakeRow(4, 0, 0.5, 0,
55 0, 4, 0.5, 0,
56 0, 0, 4.0, 0,
57 0, 0, 0.0, 1);
58 // clang-format on
59 const SkRect local_cull_rect = SkRect::MakeLTRB(5, 10, 15, 20);
60
61 DisplayListMatrixClipState state1(cull_rect, m44);
62 DisplayListMatrixClipState state2(dl_cull_rect, dl_matrix);
63
65 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
66 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
67 EXPECT_EQ(state1.matrix_4x4(), m44);
68 EXPECT_EQ(state1.matrix(), dl_matrix);
69
71 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
72 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
73 EXPECT_EQ(state2.matrix_4x4(), m44);
74 EXPECT_EQ(state2.matrix(), dl_matrix);
75}
76
78 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
79 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
80 // clang-format off
81 const SkM44 m44 = SkM44(4, 0, 0.5, 0,
82 0, 4, 0.5, 0,
83 0, 0, 4.0, 0,
84 0, 0, 0.0, 1);
85 const DlMatrix dl_matrix = DlMatrix::MakeRow(4, 0, 0.5, 0,
86 0, 4, 0.5, 0,
87 0, 0, 4.0, 0,
88 0, 0, 0.0, 1);
89 // clang-format on
90 const SkRect local_cull_rect = SkRect::MakeLTRB(5, 10, 15, 20);
91
92 DisplayListMatrixClipState state1(cull_rect, SkMatrix::I());
93 DisplayListMatrixClipState state2(dl_cull_rect, DlMatrix());
94 EXPECT_FALSE(state1.using_4x4_matrix());
95 EXPECT_FALSE(state2.using_4x4_matrix());
96
97 state1.transform(m44);
99 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
100 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
101 EXPECT_EQ(state1.matrix_4x4(), m44);
102 EXPECT_EQ(state1.matrix(), dl_matrix);
103
104 state2.transform(dl_matrix);
106 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
107 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
108 EXPECT_EQ(state2.matrix_4x4(), m44);
109 EXPECT_EQ(state2.matrix(), dl_matrix);
110}
111
113 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
114 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
115 // clang-format off
116 const SkM44 m44 = SkM44(4, 0, 0.5, 0,
117 0, 4, 0.5, 0,
118 0, 0, 4.0, 0,
119 0, 0, 0.0, 1);
120 const DlMatrix dl_matrix = DlMatrix::MakeRow(4, 0, 0.5, 0,
121 0, 4, 0.5, 0,
122 0, 0, 4.0, 0,
123 0, 0, 0.0, 1);
124 // clang-format on
125 const SkRect local_cull_rect = SkRect::MakeLTRB(5, 10, 15, 20);
126
127 DisplayListMatrixClipState state1(cull_rect, SkMatrix::I());
128 DisplayListMatrixClipState state2(dl_cull_rect, DlMatrix());
129 EXPECT_FALSE(state1.using_4x4_matrix());
130 EXPECT_FALSE(state2.using_4x4_matrix());
131
132 state1.setTransform(m44);
134 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
135 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
136 EXPECT_EQ(state1.matrix_4x4(), m44);
137 EXPECT_EQ(state1.matrix(), dl_matrix);
138
139 state2.setTransform(dl_matrix);
141 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
142 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
143 EXPECT_EQ(state2.matrix_4x4(), m44);
144 EXPECT_EQ(state2.matrix(), dl_matrix);
145}
146
148 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
149 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
150 const SkMatrix matrix = SkMatrix::Scale(4, 4);
151 const SkM44 m44 = SkM44::Scale(4, 4);
152 const DlMatrix dl_matrix = DlMatrix::MakeScale({4.0, 4.0, 1.0});
153 const SkMatrix translated_matrix =
155 const SkM44 translated_m44 = SkM44(translated_matrix);
156 const DlMatrix dl_translated_matrix =
157 dl_matrix * DlMatrix::MakeTranslation({5.0, 1.0});
158 const SkRect local_cull_rect = SkRect::MakeLTRB(0, 9, 10, 19);
159
160 DisplayListMatrixClipState state1(cull_rect, matrix);
161 DisplayListMatrixClipState state2(cull_rect, m44);
162 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
163 state1.translate(5, 1);
164 state2.translate(5, 1);
165 state3.translate(5, 1);
166
167 EXPECT_FALSE(state1.using_4x4_matrix());
168 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
169 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
170 EXPECT_EQ(state1.matrix_3x3(), translated_matrix);
171 EXPECT_EQ(state1.matrix_4x4(), translated_m44);
172 EXPECT_EQ(state1.matrix(), dl_translated_matrix);
173
174 EXPECT_FALSE(state2.using_4x4_matrix());
175 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
176 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
177 EXPECT_EQ(state2.matrix_3x3(), translated_matrix);
178 EXPECT_EQ(state2.matrix_4x4(), translated_m44);
179 EXPECT_EQ(state2.matrix(), dl_translated_matrix);
180
181 EXPECT_FALSE(state3.using_4x4_matrix());
182 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
183 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
184 EXPECT_EQ(state3.matrix_3x3(), translated_matrix);
185 EXPECT_EQ(state3.matrix_4x4(), translated_m44);
186 EXPECT_EQ(state3.matrix(), dl_translated_matrix);
187}
188
190 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
191 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
192 const SkMatrix matrix = SkMatrix::Scale(4, 4);
193 const SkM44 m44 = SkM44::Scale(4, 4);
194 const DlMatrix dl_matrix = DlMatrix::MakeScale({4.0, 4.0, 1.0});
195 // Scale factor carefully chosen to multiply cleanly and invert
196 // without any non-binary-power-of-2 approximation errors.
197 const SkMatrix scaled_matrix =
199 const SkM44 scaled_m44 = SkM44(scaled_matrix);
200 const DlMatrix scaled_dl_matrix = dl_matrix.Scale({0.5, 2, 1});
201 const SkRect local_cull_rect = SkRect::MakeLTRB(10, 5, 30, 10);
202
203 DisplayListMatrixClipState state1(cull_rect, matrix);
204 DisplayListMatrixClipState state2(cull_rect, m44);
205 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
206 state1.scale(0.5, 2);
207 state2.scale(0.5, 2);
208 state3.scale(0.5, 2);
209
210 EXPECT_FALSE(state1.using_4x4_matrix());
211 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
212 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
213 EXPECT_EQ(state1.matrix_3x3(), scaled_matrix);
214 EXPECT_EQ(state1.matrix_4x4(), scaled_m44);
215 EXPECT_EQ(state1.matrix(), scaled_dl_matrix);
216
217 EXPECT_FALSE(state2.using_4x4_matrix());
218 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
219 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
220 EXPECT_EQ(state2.matrix_3x3(), scaled_matrix);
221 EXPECT_EQ(state2.matrix_4x4(), scaled_m44);
222 EXPECT_EQ(state2.matrix(), scaled_dl_matrix);
223
224 EXPECT_FALSE(state3.using_4x4_matrix());
225 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
226 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
227 EXPECT_EQ(state3.matrix_3x3(), scaled_matrix);
228 EXPECT_EQ(state3.matrix_4x4(), scaled_m44);
229 EXPECT_EQ(state3.matrix(), scaled_dl_matrix);
230}
231
233 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
234 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
235 const SkMatrix matrix = SkMatrix::Scale(4, 4);
236 const SkM44 m44 = SkM44::Scale(4, 4);
237 const DlMatrix dl_matrix = DlMatrix::MakeScale({4, 4, 1});
238 const SkMatrix skewed_matrix =
240 const SkM44 skewed_m44 = SkM44(skewed_matrix);
241 const DlMatrix skewed_dl_matrix = dl_matrix * DlMatrix::MakeSkew(0.25, 0);
242 const SkRect local_cull_rect = SkRect::MakeLTRB(0, 10, 12.5, 20);
243
244 DisplayListMatrixClipState state1(cull_rect, matrix);
245 DisplayListMatrixClipState state2(cull_rect, m44);
246 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
247 state1.skew(.25, 0);
248 state2.skew(.25, 0);
249 state3.skew(.25, 0);
250
251 EXPECT_FALSE(state1.using_4x4_matrix());
252 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
253 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
254 EXPECT_EQ(state1.matrix_3x3(), skewed_matrix);
255 EXPECT_EQ(state1.matrix_4x4(), skewed_m44);
256 EXPECT_EQ(state1.matrix(), skewed_dl_matrix);
257
258 EXPECT_FALSE(state2.using_4x4_matrix());
259 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
260 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
261 EXPECT_EQ(state2.matrix_3x3(), skewed_matrix);
262 EXPECT_EQ(state2.matrix_4x4(), skewed_m44);
263 EXPECT_EQ(state2.matrix(), skewed_dl_matrix);
264
265 EXPECT_FALSE(state3.using_4x4_matrix());
266 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
267 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
268 EXPECT_EQ(state3.matrix_3x3(), skewed_matrix);
269 EXPECT_EQ(state3.matrix_4x4(), skewed_m44);
270 EXPECT_EQ(state3.matrix(), skewed_dl_matrix);
271}
272
274 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
275 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
276 const SkMatrix matrix = SkMatrix::Scale(4, 4);
277 const SkM44 m44 = SkM44::Scale(4, 4);
278 const DlMatrix dl_matrix = DlMatrix::MakeScale({4, 4, 1});
279 const SkMatrix rotated_matrix =
281 const SkM44 rotated_m44 = SkM44(rotated_matrix);
282 const DlMatrix rotated_dl_matrix =
283 dl_matrix * DlMatrix::MakeRotationZ(DlDegrees(90));
284 const SkRect local_cull_rect = SkRect::MakeLTRB(10, -15, 20, -5);
285
286 DisplayListMatrixClipState state1(cull_rect, matrix);
287 DisplayListMatrixClipState state2(cull_rect, m44);
288 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
289 state1.rotate(90);
290 state2.rotate(90);
291 state3.rotate(90);
292
293 EXPECT_FALSE(state1.using_4x4_matrix());
294 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
295 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
296 EXPECT_EQ(state1.matrix_3x3(), rotated_matrix);
297 EXPECT_EQ(state1.matrix_4x4(), rotated_m44);
298 EXPECT_EQ(state1.matrix(), rotated_dl_matrix);
299
300 EXPECT_FALSE(state2.using_4x4_matrix());
301 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
302 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
303 EXPECT_EQ(state2.matrix_3x3(), rotated_matrix);
304 EXPECT_EQ(state2.matrix_4x4(), rotated_m44);
305 EXPECT_EQ(state2.matrix(), rotated_dl_matrix);
306
307 EXPECT_FALSE(state3.using_4x4_matrix());
308 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
309 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
310 EXPECT_EQ(state3.matrix_3x3(), rotated_matrix);
311 EXPECT_EQ(state3.matrix_4x4(), rotated_m44);
312 EXPECT_EQ(state3.matrix(), rotated_dl_matrix);
313}
314
315TEST(DisplayListMatrixClipState, Transform2DAffine) {
316 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
317 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
318 const SkMatrix matrix = SkMatrix::Scale(4, 4);
319 const SkM44 m44 = SkM44::Scale(4, 4);
320 const DlMatrix dl_matrix = DlMatrix::MakeScale({4, 4, 1});
321
322 const SkMatrix transformed_matrix =
324 0, 2, 6, //
325 0, 0, 1));
326 const SkM44 transformed_m44 = SkM44(transformed_matrix);
327 const DlMatrix transformed_dl_matrix =
328 dl_matrix * DlMatrix::MakeRow(2, 0, 0, 5, //
329 0, 2, 0, 6, //
330 0, 0, 1, 0, //
331 0, 0, 0, 1);
332 const SkRect local_cull_rect = SkRect::MakeLTRB(0, 2, 5, 7);
333
334 DisplayListMatrixClipState state1(cull_rect, matrix);
335 DisplayListMatrixClipState state2(cull_rect, m44);
336 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
337 state1.transform2DAffine(2, 0, 5, //
338 0, 2, 6);
339 state2.transform2DAffine(2, 0, 5, //
340 0, 2, 6);
341 state3.transform2DAffine(2, 0, 5, //
342 0, 2, 6);
343
344 EXPECT_FALSE(state1.using_4x4_matrix());
345 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
346 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
347 EXPECT_EQ(state1.matrix_3x3(), transformed_matrix);
348 EXPECT_EQ(state1.matrix_4x4(), transformed_m44);
349 EXPECT_EQ(state1.matrix(), transformed_dl_matrix);
350
351 EXPECT_FALSE(state2.using_4x4_matrix());
352 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
353 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
354 EXPECT_EQ(state2.matrix_3x3(), transformed_matrix);
355 EXPECT_EQ(state2.matrix_4x4(), transformed_m44);
356 EXPECT_EQ(state2.matrix(), transformed_dl_matrix);
357
358 EXPECT_FALSE(state3.using_4x4_matrix());
359 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
360 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
361 EXPECT_EQ(state3.matrix_3x3(), transformed_matrix);
362 EXPECT_EQ(state3.matrix_4x4(), transformed_m44);
363 EXPECT_EQ(state3.matrix(), transformed_dl_matrix);
364}
365
366TEST(DisplayListMatrixClipState, TransformFullPerspectiveUsing3x3Matrix) {
367 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
368 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
369 const SkMatrix matrix = SkMatrix::Scale(4, 4);
370 const SkM44 m44 = SkM44::Scale(4, 4);
371 const DlMatrix dl_matrix = DlMatrix::MakeScale({4, 4, 1});
372
373 const SkMatrix transformed_matrix =
375 0, 2, 6, //
376 0, 0, 1));
377 const SkM44 transformed_m44 = SkM44(transformed_matrix);
378 const DlMatrix transformed_dl_matrix =
379 dl_matrix * DlMatrix::MakeRow(2, 0, 0, 5, //
380 0, 2, 0, 6, //
381 0, 0, 1, 0, //
382 0, 0, 0, 1);
383 const SkRect local_cull_rect = SkRect::MakeLTRB(0, 2, 5, 7);
384
385 DisplayListMatrixClipState state1(cull_rect, matrix);
386 DisplayListMatrixClipState state2(cull_rect, m44);
387 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
388 state1.transformFullPerspective(2, 0, 0, 5, //
389 0, 2, 0, 6, //
390 0, 0, 1, 0, //
391 0, 0, 0, 1);
392 state2.transformFullPerspective(2, 0, 0, 5, //
393 0, 2, 0, 6, //
394 0, 0, 1, 0, //
395 0, 0, 0, 1);
396 state3.transformFullPerspective(2, 0, 0, 5, //
397 0, 2, 0, 6, //
398 0, 0, 1, 0, //
399 0, 0, 0, 1);
400
401 EXPECT_FALSE(state1.using_4x4_matrix());
402 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
403 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
404 EXPECT_EQ(state1.matrix_3x3(), transformed_matrix);
405 EXPECT_EQ(state1.matrix_4x4(), transformed_m44);
406 EXPECT_EQ(state1.matrix(), transformed_dl_matrix);
407
408 EXPECT_FALSE(state2.using_4x4_matrix());
409 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
410 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
411 EXPECT_EQ(state2.matrix_3x3(), transformed_matrix);
412 EXPECT_EQ(state2.matrix_4x4(), transformed_m44);
413 EXPECT_EQ(state2.matrix(), transformed_dl_matrix);
414
415 EXPECT_FALSE(state3.using_4x4_matrix());
416 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
417 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
418 EXPECT_EQ(state3.matrix_3x3(), transformed_matrix);
419 EXPECT_EQ(state3.matrix_4x4(), transformed_m44);
420 EXPECT_EQ(state3.matrix(), transformed_dl_matrix);
421}
422
423TEST(DisplayListMatrixClipState, TransformFullPerspectiveUsing4x4Matrix) {
424 const SkRect cull_rect = SkRect::MakeLTRB(20, 40, 60, 80);
425 const DlRect dl_cull_rect = DlRect::MakeLTRB(20, 40, 60, 80);
426 const SkMatrix matrix = SkMatrix::Scale(4, 4);
427 const SkM44 m44 = SkM44::Scale(4, 4);
428 const DlMatrix dl_matrix = DlMatrix::MakeScale({4, 4, 1});
429
430 const SkM44 transformed_m44 = SkM44(m44, SkM44(2, 0, 0, 5, //
431 0, 2, 0, 6, //
432 0, 0, 1, 7, //
433 0, 0, 0, 1));
434 const DlMatrix transformed_dl_matrix =
435 dl_matrix * DlMatrix::MakeRow(2, 0, 0, 5, //
436 0, 2, 0, 6, //
437 0, 0, 1, 7, //
438 0, 0, 0, 1);
439 const SkRect local_cull_rect = SkRect::MakeLTRB(0, 2, 5, 7);
440
441 DisplayListMatrixClipState state1(cull_rect, matrix);
442 DisplayListMatrixClipState state2(cull_rect, m44);
443 DisplayListMatrixClipState state3(dl_cull_rect, dl_matrix);
444 state1.transformFullPerspective(2, 0, 0, 5, //
445 0, 2, 0, 6, //
446 0, 0, 1, 7, //
447 0, 0, 0, 1);
448 state2.transformFullPerspective(2, 0, 0, 5, //
449 0, 2, 0, 6, //
450 0, 0, 1, 7, //
451 0, 0, 0, 1);
452 state3.transformFullPerspective(2, 0, 0, 5, //
453 0, 2, 0, 6, //
454 0, 0, 1, 7, //
455 0, 0, 0, 1);
456
458 EXPECT_EQ(state1.device_cull_rect(), cull_rect);
459 EXPECT_EQ(state1.local_cull_rect(), local_cull_rect);
460 EXPECT_EQ(state1.matrix_4x4(), transformed_m44);
461 EXPECT_EQ(state1.matrix(), transformed_dl_matrix);
462
464 EXPECT_EQ(state2.device_cull_rect(), cull_rect);
465 EXPECT_EQ(state2.local_cull_rect(), local_cull_rect);
466 EXPECT_EQ(state2.matrix_4x4(), transformed_m44);
467 EXPECT_EQ(state2.matrix(), transformed_dl_matrix);
468
470 EXPECT_EQ(state3.device_cull_rect(), cull_rect);
471 EXPECT_EQ(state3.local_cull_rect(), local_cull_rect);
472 EXPECT_EQ(state3.matrix_4x4(), transformed_m44);
473 EXPECT_EQ(state3.matrix(), transformed_dl_matrix);
474}
475
477 SkRect cull_rect = SkRect::MakeLTRB(20, 20, 40, 40);
478
479 auto non_reducing = [&cull_rect](const SkRect& diff_rect,
480 const std::string& label) {
481 {
483 state.clipRect(diff_rect, DlCanvas::ClipOp::kDifference, false);
484 EXPECT_EQ(state.device_cull_rect(), cull_rect) << label;
485 }
486 {
488 const SkRRect diff_rrect = SkRRect::MakeRect(diff_rect);
489 state.clipRRect(diff_rrect, DlCanvas::ClipOp::kDifference, false);
490 EXPECT_EQ(state.device_cull_rect(), cull_rect) << label << " (RRect)";
491 }
492 {
494 const SkPath diff_path = SkPath().addRect(diff_rect);
495 state.clipPath(diff_path, DlCanvas::ClipOp::kDifference, false);
496 EXPECT_EQ(state.device_cull_rect(), cull_rect) << label << " (RRect)";
497 }
498 };
499
500 auto reducing = [&cull_rect](const SkRect& diff_rect,
501 const SkRect& result_rect,
502 const std::string& label) {
503 EXPECT_TRUE(result_rect.isEmpty() || cull_rect.contains(result_rect));
504 {
506 state.clipRect(diff_rect, DlCanvas::ClipOp::kDifference, false);
507 EXPECT_EQ(state.device_cull_rect(), result_rect) << label;
508 }
509 {
511 const SkRRect diff_rrect = SkRRect::MakeRect(diff_rect);
512 state.clipRRect(diff_rrect, DlCanvas::ClipOp::kDifference, false);
513 EXPECT_EQ(state.device_cull_rect(), result_rect) << label << " (RRect)";
514 }
515 {
517 const SkPath diff_path = SkPath().addRect(diff_rect);
518 state.clipPath(diff_path, DlCanvas::ClipOp::kDifference, false);
519 EXPECT_EQ(state.device_cull_rect(), result_rect) << label << " (RRect)";
520 }
521 };
522
523 // Skim the corners and edge
524 non_reducing(SkRect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
525 non_reducing(SkRect::MakeLTRB(20, 10, 40, 20), "Above");
526 non_reducing(SkRect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
527 non_reducing(SkRect::MakeLTRB(40, 20, 50, 40), "Right");
528 non_reducing(SkRect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
529 non_reducing(SkRect::MakeLTRB(20, 40, 40, 50), "Below");
530 non_reducing(SkRect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
531 non_reducing(SkRect::MakeLTRB(10, 20, 20, 40), "Left");
532
533 // Overlap corners
534 non_reducing(SkRect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
535 non_reducing(SkRect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
536 non_reducing(SkRect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
537 non_reducing(SkRect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
538
539 // Overlap edges, but not across an entire side
540 non_reducing(SkRect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
541 non_reducing(SkRect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
542 non_reducing(SkRect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
543 non_reducing(SkRect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
544 non_reducing(SkRect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
545 non_reducing(SkRect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
546 non_reducing(SkRect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
547 non_reducing(SkRect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
548
549 // Slice all the way through the middle
550 non_reducing(SkRect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
551 non_reducing(SkRect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
552
553 // Slice off each edge
554 reducing(SkRect::MakeLTRB(20, 15, 40, 25), //
555 SkRect::MakeLTRB(20, 25, 40, 40), //
556 "Slice off top");
557 reducing(SkRect::MakeLTRB(35, 20, 45, 40), //
558 SkRect::MakeLTRB(20, 20, 35, 40), //
559 "Slice off right");
560 reducing(SkRect::MakeLTRB(20, 35, 40, 45), //
561 SkRect::MakeLTRB(20, 20, 40, 35), //
562 "Slice off bottom");
563 reducing(SkRect::MakeLTRB(15, 20, 25, 40), //
564 SkRect::MakeLTRB(25, 20, 40, 40), //
565 "Slice off left");
566
567 // cull rect contains diff rect
568 non_reducing(SkRect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
569
570 // cull rect equals diff rect
571 reducing(cull_rect, SkRect::MakeEmpty(), "Perfectly covering");
572
573 // diff rect contains cull rect
574 reducing(SkRect::MakeLTRB(15, 15, 45, 45), SkRect::MakeEmpty(), "Smothering");
575}
576
577TEST(DisplayListMatrixClipState, ClipPathWithInvertFillType) {
578 SkRect cull_rect = SkRect::MakeLTRB(0, 0, 100.0, 100.0);
580 SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
582 state.clipPath(clip, DlCanvas::ClipOp::kIntersect, false);
583
584 EXPECT_EQ(state.local_cull_rect(), cull_rect);
585 EXPECT_EQ(state.device_cull_rect(), cull_rect);
586}
587
588TEST(DisplayListMatrixClipState, DiffClipPathWithInvertFillType) {
589 SkRect cull_rect = SkRect::MakeLTRB(0, 0, 100.0, 100.0);
591
592 SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
594 SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7);
595 state.clipPath(clip, DlCanvas::ClipOp::kDifference, false);
596
597 EXPECT_EQ(state.local_cull_rect(), clip_bounds);
598 EXPECT_EQ(state.device_cull_rect(), clip_bounds);
599}
600
601TEST(DisplayListMatrixClipState, MapAndClipRectTranslation) {
602 DlRect cull_rect = DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
603 DlMatrix matrix = DlMatrix::MakeTranslation({10.0f, 20.0f, 1.0f});
605
606 {
607 // Empty width in src rect (before and after translation)
608 SkRect rect = SkRect::MakeLTRB(150.0f, 150.0f, 150.0f, 160.0f);
609 EXPECT_FALSE(state.mapAndClipRect(&rect));
610 EXPECT_TRUE(rect.isEmpty());
611 }
612
613 {
614 // Empty height in src rect (before and after translation)
615 SkRect rect = SkRect::MakeLTRB(150.0f, 150.0f, 160.0f, 150.0f);
616 EXPECT_FALSE(state.mapAndClipRect(&rect));
617 EXPECT_TRUE(rect.isEmpty());
618 }
619
620 {
621 // rect far outside of clip, even after translation
622 SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f);
623 EXPECT_FALSE(state.mapAndClipRect(&rect));
624 EXPECT_TRUE(rect.isEmpty());
625 }
626
627 {
628 // Rect abuts clip left side after translation
629 SkRect rect = SkRect::MakeLTRB(80.0f, 100.0f, 90.0f, 110.0f);
630 EXPECT_FALSE(state.mapAndClipRect(&rect));
631 EXPECT_TRUE(rect.isEmpty());
632 }
633
634 {
635 // Rect barely grazes clip left side after translation
636 SkRect rect = SkRect::MakeLTRB(80.0f, 100.0f, 91.0f, 110.0f);
637 EXPECT_TRUE(state.mapAndClipRect(&rect));
638 EXPECT_EQ(rect, SkRect::MakeLTRB(100.0f, 120.0f, 101.0f, 130.0f));
639 }
640
641 {
642 // Rect abuts clip top after translation
643 SkRect rect = SkRect::MakeLTRB(100.0f, 70.0f, 110.0f, 80.0f);
644 EXPECT_FALSE(state.mapAndClipRect(&rect));
645 EXPECT_TRUE(rect.isEmpty());
646 }
647
648 {
649 // Rect barely grazes clip top after translation
650 SkRect rect = SkRect::MakeLTRB(100.0f, 70.0f, 110.0f, 81.0f);
651 EXPECT_TRUE(state.mapAndClipRect(&rect));
652 EXPECT_EQ(rect, SkRect::MakeLTRB(110.0f, 100.0f, 120.0f, 101.0f));
653 }
654
655 {
656 // Rect abuts clip right side after translation
657 SkRect rect = SkRect::MakeLTRB(190.0f, 100.0f, 200.0f, 110.0f);
658 EXPECT_FALSE(state.mapAndClipRect(&rect));
659 EXPECT_TRUE(rect.isEmpty());
660 }
661
662 {
663 // Rect barely grazes clip right side after translation
664 SkRect rect = SkRect::MakeLTRB(189.0f, 100.0f, 200.0f, 110.0f);
665 EXPECT_TRUE(state.mapAndClipRect(&rect));
666 EXPECT_EQ(rect, SkRect::MakeLTRB(199.0f, 120.0f, 200.0f, 130.0f));
667 }
668
669 {
670 // Rect abuts clip bottom after translation
671 SkRect rect = SkRect::MakeLTRB(100.0f, 180.0f, 110.0f, 190.0f);
672 EXPECT_FALSE(state.mapAndClipRect(&rect));
673 EXPECT_TRUE(rect.isEmpty());
674 }
675
676 {
677 // Rect barely grazes clip bottom after translation
678 SkRect rect = SkRect::MakeLTRB(100.0f, 179.0f, 110.0f, 190.0f);
679 EXPECT_TRUE(state.mapAndClipRect(&rect));
680 EXPECT_EQ(rect, SkRect::MakeLTRB(110.0f, 199.0f, 120.0f, 200.0f));
681 }
682}
683
684TEST(DisplayListMatrixClipState, MapAndClipRectScale) {
685 DlRect cull_rect = DlRect::MakeLTRB(100.0f, 100.0f, 500.0f, 500.0f);
686 DlMatrix matrix = DlMatrix::MakeScale({2.0f, 4.0f, 1.0f});
688
689 {
690 // Empty width in src rect (before and after scaling)
691 SkRect rect = SkRect::MakeLTRB(100.0f, 100.0f, 100.0f, 110.0f);
692 EXPECT_FALSE(state.mapAndClipRect(&rect));
693 EXPECT_TRUE(rect.isEmpty());
694 }
695
696 {
697 // Empty height in src rect (before and after scaling)
698 SkRect rect = SkRect::MakeLTRB(100.0f, 100.0f, 110.0f, 100.0f);
699 EXPECT_FALSE(state.mapAndClipRect(&rect));
700 EXPECT_TRUE(rect.isEmpty());
701 }
702
703 {
704 // rect far outside of clip, even after scaling
705 SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f);
706 EXPECT_FALSE(state.mapAndClipRect(&rect));
707 EXPECT_TRUE(rect.isEmpty());
708 }
709
710 {
711 // Rect abuts clip left side after scaling
712 SkRect rect = SkRect::MakeLTRB(40.0f, 100.0f, 50.0f, 110.0f);
713 EXPECT_FALSE(state.mapAndClipRect(&rect));
714 EXPECT_TRUE(rect.isEmpty());
715 }
716
717 {
718 // Rect barely grazes clip left side after scaling
719 SkRect rect = SkRect::MakeLTRB(40.0f, 100.0f, 51.0f, 110.0f);
720 EXPECT_TRUE(state.mapAndClipRect(&rect));
721 EXPECT_EQ(rect, SkRect::MakeLTRB(100.0f, 400.0f, 102.0f, 440.0f));
722 }
723
724 {
725 // Rect abuts clip top after scaling
726 SkRect rect = SkRect::MakeLTRB(100.0f, 15.0f, 110.0f, 25.0f);
727 EXPECT_FALSE(state.mapAndClipRect(&rect));
728 EXPECT_TRUE(rect.isEmpty());
729 }
730
731 {
732 // Rect barely grazes clip top after scaling
733 SkRect rect = SkRect::MakeLTRB(100.0f, 15.0f, 110.0f, 26.0f);
734 EXPECT_TRUE(state.mapAndClipRect(&rect));
735 EXPECT_EQ(rect, SkRect::MakeLTRB(200.0f, 100.0f, 220.0f, 104.0f));
736 }
737
738 {
739 // Rect abuts clip right side after scaling
740 SkRect rect = SkRect::MakeLTRB(250.0f, 100.0f, 260.0f, 110.0f);
741 EXPECT_FALSE(state.mapAndClipRect(&rect));
742 EXPECT_TRUE(rect.isEmpty());
743 }
744
745 {
746 // Rect barely grazes clip right side after scaling
747 SkRect rect = SkRect::MakeLTRB(249.0f, 100.0f, 260.0f, 110.0f);
748 EXPECT_TRUE(state.mapAndClipRect(&rect));
749 EXPECT_EQ(rect, SkRect::MakeLTRB(498.0f, 400.0f, 500.0f, 440.0f));
750 }
751
752 {
753 // Rect abuts clip bottom after scaling
754 SkRect rect = SkRect::MakeLTRB(100.0f, 125.0f, 110.0f, 135.0f);
755 EXPECT_FALSE(state.mapAndClipRect(&rect));
756 EXPECT_TRUE(rect.isEmpty());
757 }
758
759 {
760 // Rect barely grazes clip bottom after scaling
761 SkRect rect = SkRect::MakeLTRB(100.0f, 124.0f, 110.0f, 135.0f);
762 EXPECT_TRUE(state.mapAndClipRect(&rect));
763 EXPECT_EQ(rect, SkRect::MakeLTRB(200.0f, 496.0f, 220.0f, 500.0f));
764 }
765}
766
768 DlRect rect = DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
770
771 EXPECT_TRUE(state.rect_covers_cull(rect));
772 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
773 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
774 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
775 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
776 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
777 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, -0.1f, 0.0f, 0.0f)));
778 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
779 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, -0.1f)));
780}
781
782TEST(DisplayListMatrixClipState, RectCoverageAccuracy) {
783 // These particular values create bit errors if we use the path that
784 // tests for inclusion in local space, but work OK if we use a forward
785 // path that tests for inclusion in device space, due to the fact that
786 // the extra matrix inversion is just enough math to cause the transform
787 // to place the local space cull corners just outside the original rect.
788 // The test in device space only works under a simple scale, such as we
789 // use for DPR adjustments (and which are not always inversion friendly).
790
791 DlRect cull = DlRect::MakeLTRB(0.0f, 0.0f, 1080.0f, 2400.0f);
792 DlScalar DPR = 2.625;
793 DlRect rect = DlRect::MakeLTRB(0.0f, 0.0f, 1080.0f / DPR, 2400.0f / DPR);
794
796 state.scale(DPR, DPR);
797
798 EXPECT_TRUE(state.rect_covers_cull(rect));
799 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
800 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
801 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
802 EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
803 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
804 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, -0.1f, 0.0f, 0.0f)));
805 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
806 EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, -0.1f)));
807}
808
809TEST(DisplayListMatrixClipState, RectCoverageUnderScale) {
810 DlRect rect = DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
812 state.scale(2.0f, 2.0f);
813
814 EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(100, 100, 200, 200)));
815 EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 100)));
816 EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(49, 50, 100, 100)));
817 EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 49, 100, 100)));
818 EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 101, 100)));
819 EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 101)));
820 EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(51, 50, 100, 100)));
821 EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 51, 100, 100)));
822 EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 99, 100)));
823 EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 99)));
824}
825
826TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
827 DlRect rect = DlRect::MakeLTRB(-1.0f, -1.0f, 1.0f, 1.0f);
828 DlRect cull = rect.Scale(impeller::kSqrt2 * 25);
829 DlRect test = rect.Scale(50.0f);
830 DlRect test_true = test.Expand(0.002f);
831 DlRect test_false = test.Expand(-0.002f);
832
833 for (int i = 0; i <= 360; i++) {
835 state.rotate(i);
836 EXPECT_TRUE(state.rect_covers_cull(test_true))
837 << " testing " << test_true << std::endl
838 << " contains " << state.local_cull_rect() << std::endl
839 << " at " << i << " degrees";
840 if ((i % 90) == 45) {
841 // The cull rect is largest when viewed at multiples of 45
842 // degrees so we will fail to contain it at those angles
843 EXPECT_FALSE(state.rect_covers_cull(test_false))
844 << " testing " << test_false << std::endl
845 << " contains " << state.local_cull_rect() << std::endl
846 << " at " << i << " degrees";
847 } else {
848 // At other angles, the cull rect is not quite so big as to encroach
849 // upon the expanded test rectangle.
850 EXPECT_TRUE(state.rect_covers_cull(test_false))
851 << " testing " << test_false << std::endl
852 << " contains " << state.local_cull_rect() << std::endl
853 << " at " << i << " degrees";
854 }
855 }
856}
857
859 DlRect cull = DlRect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
861 // The cull rect corners will be at (50, 50) so the oval needs to have
862 // a radius large enough to cover that - sqrt(2*50*50) == sqrt(2) * 50
863 // We pad by an ever so slight 0.02f to account for round off error and
864 // then use larger expansion/contractions of 0.1f to cover/not-cover it.
865 DlRect test = cull.Scale(impeller::kSqrt2).Expand(0.02f);
866
867 EXPECT_TRUE(state.oval_covers_cull(test));
868 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
869 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
870 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
871 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
872 EXPECT_FALSE(state.oval_covers_cull(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
873 EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, -0.1f, 0.0f, 0.0f)));
874 EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
875 EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, -0.1f)));
876}
877
878TEST(DisplayListMatrixClipState, OvalCoverageUnderScale) {
879 DlRect cull = DlRect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
881 state.scale(2.0f, 2.0f);
882 // The cull rect corners will be at (50, 50) so the oval needs to have
883 // a radius large enough to cover that - sqrt(2*50*50) == sqrt(2) * 50
884 // We pad by an ever so slight 0.02f to account for round off error and
885 // then use larger expansion/contractions of 0.1f to cover/not-cover it.
886 // We combine that with an additional scale 0.5f since we are viewing
887 // the cull rect under a 2.0 scale.
888 DlRect test = cull.Scale(0.5f * impeller::kSqrt2).Expand(0.02f);
889
890 EXPECT_TRUE(state.oval_covers_cull(test));
891 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
892 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
893 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
894 EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
895 EXPECT_FALSE(state.oval_covers_cull(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
896 EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, -0.1f, 0.0f, 0.0f)));
897 EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
898 EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, -0.1f)));
899}
900
901TEST(DisplayListMatrixClipState, OvalCoverageUnderRotation) {
902 DlRect unit = DlRect::MakeLTRB(-1.0f, -1.0f, 1.0f, 1.0f);
903 DlRect cull = unit.Scale(50.0f);
904 // See above, test bounds need to be sqrt(2) larger for the inscribed
905 // oval to contain the cull rect. These tests are simpler than the scaled
906 // rectangle coverage tests because this expanded test oval will
907 // precisely cover the cull rect at all angles.
909 DlRect test_true = test.Expand(0.002f);
910 DlRect test_false = test.Expand(-0.002f);
911
912 for (int i = 0; i <= 360; i++) {
914 state.rotate(i);
915 EXPECT_TRUE(state.oval_covers_cull(test_true))
916 << " testing " << test_true << std::endl
917 << " contains " << state.local_cull_rect() << std::endl
918 << " at " << i << " degrees";
919 EXPECT_FALSE(state.oval_covers_cull(test_false))
920 << " testing " << test_false << std::endl
921 << " contains " << state.local_cull_rect() << std::endl
922 << " at " << i << " degrees";
923 }
924}
925
927 SkRect cull = SkRect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
929 // test_bounds need to contain
930 SkRect test = cull.makeOutset(2.0f, 2.0f);
931
932 // RRect of cull with no corners covers
933 EXPECT_TRUE(state.rrect_covers_cull(SkRRect::MakeRectXY(cull, 0.0f, 0.0f)));
934 // RRect of cull with even the tiniest corners does not cover
935 EXPECT_FALSE(
936 state.rrect_covers_cull(SkRRect::MakeRectXY(cull, 0.01f, 0.01f)));
937
938 // Expanded by 2.0 and then with a corner of 2.0 obviously still covers
939 EXPECT_TRUE(state.rrect_covers_cull(SkRRect::MakeRectXY(test, 2.0f, 2.0f)));
940 // The corner point of the cull rect is at (c-2, c-2) relative to the
941 // corner of the rrect bounds so we compute its disance to the center
942 // of the circular part and compare it to the radius of the corner (c)
943 // to find the corner radius where it will start to leave the rounded
944 // rectangle:
945 //
946 // +----------- +
947 // | __---^^ |
948 // | +/------- + |
949 // | / \ | c
950 // | /| \ c-2 |
951 // |/ | \ | |
952 // || | * + +
953 //
954 // sqrt(2*(c-2)*(c-2)) > c
955 // 2*(c-2)*(c-2) > c*c
956 // 2*(cc - 4c + 4) > cc
957 // 2cc - 8c + 8 > cc
958 // cc - 8c + 8 > 0
959 // c > 8 +/- sqrt(64 - 32) / 2
960 // c > ~6.828
961 // corners set to 6.82 should still cover the cull rect
962 EXPECT_TRUE(state.rrect_covers_cull(SkRRect::MakeRectXY(test, 6.82f, 6.82f)));
963 // but corners set to 6.83 should not cover the cull rect
964 EXPECT_FALSE(
965 state.rrect_covers_cull(SkRRect::MakeRectXY(test, 6.84f, 6.84f)));
966}
967
968} // namespace testing
969} // namespace flutter
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
Definition: SkM44.h:150
static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z=1)
Definition: SkM44.h:232
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix RotateDeg(SkScalar deg)
Definition: SkMatrix.h:104
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
Definition: SkMatrix.h:179
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition: SkMatrix.h:1775
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
static SkMatrix Skew(SkScalar kx, SkScalar ky)
Definition: SkMatrix.h:124
Definition: SkPath.h:59
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1213
void setFillType(SkPathFillType ft)
Definition: SkPath.h:235
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition: SkPath.cpp:864
static SkRRect MakeRect(const SkRect &r)
Definition: SkRRect.h:149
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
void scale(SkScalar sx, SkScalar sy)
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt)
void setTransform(const DlMatrix &matrix)
void transformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt)
void skew(SkScalar skx, SkScalar sky)
void transform(const DlMatrix &matrix)
void translate(SkScalar tx, SkScalar ty)
AtkStateType state
Definition: dart.idl:629
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
TEST(DisplayListComplexity, EmptyDisplayList)
impeller::Scalar DlScalar
impeller::Matrix DlMatrix
impeller::Degrees DlDegrees
constexpr float kSqrt2
Definition: constants.h:47
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
SkRect makeOutset(float dx, float dy) const
Definition: SkRect.h:1002
bool contains(SkScalar x, SkScalar y) const
Definition: extension.cpp:19
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:83
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition: matrix.h:117
constexpr Matrix Scale(const Vector3 &s) const
Definition: matrix.h:252
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:213
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr TRect Scale(Type scale) const
Definition: rect.h:192
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:605
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678