Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
dl_image_filter_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
16#include "gtest/gtest.h"
17
18#include "include/core/SkMatrix.h"
19#include "third_party/skia/include/core/SkBlendMode.h"
20#include "third_party/skia/include/core/SkColorFilter.h"
21#include "third_party/skia/include/core/SkSamplingOptions.h"
22#include "third_party/skia/include/effects/SkImageFilters.h"
23
24namespace flutter {
25namespace testing {
26
27// DlRect::Contains treats the rect as a half-open interval which is
28// appropriate for so many operations. Unfortunately, we are using
29// it here to test containment of the corners of a transformed quad
30// so the corners of the quad that are measured against the right
31// and bottom edges are contained even if they are on the right or
32// bottom edge. This method does the "all sides inclusive" version
33// of DlRect::Contains.
34static bool containsInclusive(const DlRect rect, const DlPoint p) {
35 // Test with a slight offset of 1E-9 to "forgive" IEEE bit-rounding
36 // Ending up with bounds that are off by 1E-9 (these numbers are all
37 // being tested in device space with this method) will be off by a
38 // negligible amount of a pixel that wouldn't contribute to changing
39 // the color of a pixel.
40 return (p.x >= rect.GetLeft() - 1E-9 && //
41 p.x <= rect.GetRight() + 1E-9 && //
42 p.y >= rect.GetTop() - 1E-9 && //
43 p.y <= rect.GetBottom() + 1E-9);
44}
45
46static bool containsInclusive(const DlRect rect, const DlQuad quad) {
47 return (containsInclusive(rect, quad[0]) && //
48 containsInclusive(rect, quad[1]) && //
49 containsInclusive(rect, quad[2]) && //
50 containsInclusive(rect, quad[3]));
51}
52
53static bool containsInclusive(const DlIRect rect, const DlQuad quad) {
54 return containsInclusive(DlRect::Make(rect), quad);
55}
56
57static bool containsInclusive(const DlIRect rect, const DlRect bounds) {
58 return (bounds.GetLeft() >= rect.GetLeft() - 1E-9 &&
59 bounds.GetTop() >= rect.GetTop() - 1E-9 &&
60 bounds.GetRight() <= rect.GetRight() + 1E-9 &&
61 bounds.GetBottom() <= rect.GetBottom() + 1E-9);
62}
63
64// Used to verify that the expected output bounds and reverse-engineered
65// "input bounds for output bounds" rectangles are included in the rectangle
66// returned from the various bounds computation methods under the specified
67// matrix.
68static void TestBoundsWithMatrix(const DlImageFilter& filter,
69 const DlMatrix& matrix,
70 const DlRect& sourceBounds,
71 const DlQuad& expectedLocalOutputQuad) {
72 DlRect device_input_bounds = sourceBounds.TransformAndClipBounds(matrix);
73 DlQuad expected_output_quad = matrix.Transform(expectedLocalOutputQuad);
74
75 DlIRect device_filter_ibounds;
76 ASSERT_EQ(filter.map_device_bounds(DlIRect::RoundOut(device_input_bounds),
77 matrix, device_filter_ibounds),
78 &device_filter_ibounds);
79 EXPECT_TRUE(containsInclusive(device_filter_ibounds, expected_output_quad))
80 << filter << std::endl
81 << sourceBounds << ", {" << std::endl
82 << " " << expectedLocalOutputQuad[0] << ", " << std::endl
83 << " " << expectedLocalOutputQuad[1] << ", " << std::endl
84 << " " << expectedLocalOutputQuad[2] << ", " << std::endl
85 << " " << expectedLocalOutputQuad[3] << std::endl
86 << "}, " << matrix << ", " << std::endl
87 << device_filter_ibounds << std::endl
88 << device_input_bounds << ", {" << std::endl
89 << " " << expected_output_quad[0] << ", " << std::endl
90 << " " << expected_output_quad[1] << ", " << std::endl
91 << " " << expected_output_quad[2] << ", " << std::endl
92 << " " << expected_output_quad[3] << std::endl
93 << "}";
94
95 DlIRect reverse_input_ibounds;
96 ASSERT_EQ(filter.get_input_device_bounds(device_filter_ibounds, matrix,
97 reverse_input_ibounds),
98 &reverse_input_ibounds);
99 EXPECT_TRUE(containsInclusive(reverse_input_ibounds, device_input_bounds))
100 << filter << std::endl
101 << matrix << ", " << std::endl
102 << reverse_input_ibounds << ", " << std::endl
103 << device_input_bounds;
104}
105
106static void TestInvalidBounds(const DlImageFilter& filter,
107 const DlMatrix& matrix,
108 const DlRect& localInputBounds) {
109 DlIRect device_input_bounds =
110 DlIRect::RoundOut(localInputBounds.TransformBounds(matrix));
111
112 DlRect local_filter_bounds;
113 ASSERT_EQ(filter.map_local_bounds(localInputBounds, local_filter_bounds),
114 nullptr);
115 ASSERT_EQ(local_filter_bounds, localInputBounds);
116
117 DlIRect device_filter_ibounds;
118 ASSERT_EQ(filter.map_device_bounds(device_input_bounds, matrix,
119 device_filter_ibounds),
120 nullptr);
121 ASSERT_EQ(device_filter_ibounds, device_input_bounds);
122
123 DlIRect reverse_input_ibounds;
124 ASSERT_EQ(filter.get_input_device_bounds(device_input_bounds, matrix,
125 reverse_input_ibounds),
126 nullptr);
127 ASSERT_EQ(reverse_input_ibounds, device_input_bounds);
128}
129
130// localInputBounds is a sample bounds for testing as input to the filter.
131// localExpectOutputBounds is the theoretical output bounds for applying
132// the filter to the localInputBounds.
133// localExpectInputBounds is the theoretical input bounds required for the
134// filter to cover the localExpectOutputBounds
135// If either of the expected bounds are nullptr then the bounds methods will
136// be assumed to be unable to perform their computations for the given
137// image filter and will be returning null.
138static void TestBounds(const DlImageFilter& filter,
139 const DlRect& sourceBounds,
140 const DlQuad& expectedLocalOutputQuad) {
141 DlRect local_filter_bounds;
142 ASSERT_EQ(filter.map_local_bounds(sourceBounds, local_filter_bounds),
143 &local_filter_bounds);
144 ASSERT_TRUE(containsInclusive(local_filter_bounds, expectedLocalOutputQuad));
145
146 for (int i_scale = 1; i_scale <= 4; i_scale++) {
147 DlScalar scale = i_scale;
148 for (int skew_eighths = 0; skew_eighths < 7; skew_eighths++) {
149 DlScalar skew = skew_eighths / 8.0f;
150 for (int degrees = 0; degrees <= 360; degrees += 15) {
151 DlMatrix matrix;
152 matrix = matrix.Scale({scale, scale, 1});
153 matrix = DlMatrix::MakeSkew(skew, skew) * matrix;
154 matrix = DlMatrix::MakeRotationZ(DlDegrees(degrees)) * matrix;
155 ASSERT_TRUE(matrix.IsInvertible()) << matrix;
156 ASSERT_FALSE(matrix.HasPerspective2D()) << matrix;
157 TestBoundsWithMatrix(filter, matrix, sourceBounds,
158 expectedLocalOutputQuad);
159 matrix.m[3] = 0.001f;
160 matrix.m[7] = 0.001f;
161 ASSERT_TRUE(matrix.IsInvertible()) << matrix;
162 ASSERT_TRUE(matrix.HasPerspective2D()) << matrix;
163 TestBoundsWithMatrix(filter, matrix, sourceBounds,
164 expectedLocalOutputQuad);
165 }
166 }
167 }
168}
169
170static void TestBounds(const DlImageFilter& filter,
171 const DlRect& sourceBounds,
172 const DlRect& expectedLocalOutputBounds) {
173 DlQuad expected_local_output_quad = expectedLocalOutputBounds.GetPoints();
174 ASSERT_EQ(expected_local_output_quad.size(), 4u); // Only 0u when empty
175 TestBounds(filter, sourceBounds, expected_local_output_quad);
176}
177
178TEST(DisplayListImageFilter, BlurConstructor) {
179 DlBlurImageFilter filter(5.0, 6.0, DlTileMode::kMirror);
180}
181
182TEST(DisplayListImageFilter, BlurShared) {
183 DlBlurImageFilter filter(5.0, 6.0, DlTileMode::kMirror);
184
185 ASSERT_NE(filter.shared().get(), &filter);
186 ASSERT_EQ(*filter.shared(), filter);
187}
188
189TEST(DisplayListImageFilter, BlurAsBlur) {
190 DlBlurImageFilter filter(5.0, 6.0, DlTileMode::kMirror);
191
192 ASSERT_NE(filter.asBlur(), nullptr);
193 ASSERT_EQ(filter.asBlur(), &filter);
194}
195
196TEST(DisplayListImageFilter, BlurContents) {
197 DlBlurImageFilter filter(5.0, 6.0, DlTileMode::kMirror);
198
199 ASSERT_EQ(filter.sigma_x(), 5.0);
200 ASSERT_EQ(filter.sigma_y(), 6.0);
201 ASSERT_EQ(filter.tile_mode(), DlTileMode::kMirror);
202}
203
204TEST(DisplayListImageFilter, BlurEquals) {
205 DlBlurImageFilter filter1(5.0, 6.0, DlTileMode::kMirror);
206 DlBlurImageFilter filter2(5.0, 6.0, DlTileMode::kMirror);
207
208 TestEquals(filter1, filter2);
209
210 DlBlurImageFilter filter3(5.0, 6.0, DlTileMode::kMirror,
211 DlRect::MakeLTRB(1, 2, 3, 4));
212 DlBlurImageFilter filter4(5.0, 6.0, DlTileMode::kMirror,
213 DlRect::MakeLTRB(1, 2, 3, 4));
214
215 TestEquals(filter3, filter4);
216}
217
218TEST(DisplayListImageFilter, BlurWithLocalMatrixEquals) {
219 DlBlurImageFilter filter1(5.0, 6.0, DlTileMode::kMirror);
220 DlBlurImageFilter filter2(5.0, 6.0, DlTileMode::kMirror);
221
222 DlMatrix local_matrix = DlMatrix::MakeTranslation({10, 10});
223 TestEquals(*filter1.makeWithLocalMatrix(local_matrix),
224 *filter2.makeWithLocalMatrix(local_matrix));
225}
226
227TEST(DisplayListImageFilter, BlurNotEquals) {
228 DlBlurImageFilter filter1(5.0, 6.0, DlTileMode::kMirror);
229 DlBlurImageFilter filter2(7.0, 6.0, DlTileMode::kMirror);
230 DlBlurImageFilter filter3(5.0, 8.0, DlTileMode::kMirror);
231 DlBlurImageFilter filter4(5.0, 6.0, DlTileMode::kRepeat);
232 DlBlurImageFilter filter5(5.0, 6.0, DlTileMode::kRepeat,
233 DlRect::MakeLTRB(1, 2, 3, 4));
234 DlBlurImageFilter filter6(5.0, 6.0, DlTileMode::kRepeat,
235 DlRect::MakeLTRB(4, 2, 3, 4));
236
237 TestNotEquals(filter1, filter2, "Sigma X differs");
238 TestNotEquals(filter1, filter3, "Sigma Y differs");
239 TestNotEquals(filter1, filter4, "Tile Mode differs");
240 TestNotEquals(filter4, filter5, "Bounds differs");
241 TestNotEquals(filter5, filter6, "Bounds differs");
242}
243
244TEST(DisplayListImageFilter, BlurBounds) {
246 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
247 DlRect expected_output_bounds = input_bounds.Expand(15, 30);
248 TestBounds(filter, input_bounds, expected_output_bounds);
249}
250
251TEST(DisplayListImageFilter, BlurZeroSigma) {
252 std::shared_ptr<DlImageFilter> filter =
254 ASSERT_EQ(filter, nullptr);
255 filter = DlImageFilter::MakeBlur(3, SK_ScalarNaN, DlTileMode::kMirror);
256 ASSERT_EQ(filter, nullptr);
257 filter = DlImageFilter::MakeBlur(SK_ScalarNaN, 3, DlTileMode::kMirror);
258 ASSERT_EQ(filter, nullptr);
259 filter =
260 DlImageFilter::MakeBlur(SK_ScalarNaN, SK_ScalarNaN, DlTileMode::kMirror);
261 ASSERT_EQ(filter, nullptr);
263 ASSERT_NE(filter, nullptr);
265 ASSERT_NE(filter, nullptr);
266}
267
268TEST(DisplayListImageFilter, DilateConstructor) {
269 DlDilateImageFilter filter(5.0, 6.0);
270}
271
272TEST(DisplayListImageFilter, DilateShared) {
273 DlDilateImageFilter filter(5.0, 6.0);
274
275 ASSERT_NE(filter.shared().get(), &filter);
276 ASSERT_EQ(*filter.shared(), filter);
277}
278
279TEST(DisplayListImageFilter, DilateAsDilate) {
280 DlDilateImageFilter filter(5.0, 6.0);
281
282 ASSERT_NE(filter.asDilate(), nullptr);
283 ASSERT_EQ(filter.asDilate(), &filter);
284}
285
286TEST(DisplayListImageFilter, DilateContents) {
287 DlDilateImageFilter filter(5.0, 6.0);
288
289 ASSERT_EQ(filter.radius_x(), 5.0);
290 ASSERT_EQ(filter.radius_y(), 6.0);
291}
292
293TEST(DisplayListImageFilter, DilateEquals) {
294 DlDilateImageFilter filter1(5.0, 6.0);
295 DlDilateImageFilter filter2(5.0, 6.0);
296
297 TestEquals(filter1, filter2);
298}
299
300TEST(DisplayListImageFilter, DilateWithLocalMatrixEquals) {
301 DlDilateImageFilter filter1(5.0, 6.0);
302 DlDilateImageFilter filter2(5.0, 6.0);
303
304 DlMatrix local_matrix = DlMatrix::MakeTranslation({10, 10});
305 TestEquals(*filter1.makeWithLocalMatrix(local_matrix),
306 *filter2.makeWithLocalMatrix(local_matrix));
307}
308
309TEST(DisplayListImageFilter, DilateNotEquals) {
310 DlDilateImageFilter filter1(5.0, 6.0);
311 DlDilateImageFilter filter2(7.0, 6.0);
312 DlDilateImageFilter filter3(5.0, 8.0);
313
314 TestNotEquals(filter1, filter2, "Radius X differs");
315 TestNotEquals(filter1, filter3, "Radius Y differs");
316}
317
318TEST(DisplayListImageFilter, DilateBounds) {
320 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
321 DlRect expected_output_bounds = input_bounds.Expand(5, 10);
322 TestBounds(filter, input_bounds, expected_output_bounds);
323}
324
325TEST(DisplayListImageFilter, ErodeConstructor) {
326 DlErodeImageFilter filter(5.0, 6.0);
327}
328
329TEST(DisplayListImageFilter, ErodeShared) {
330 DlErodeImageFilter filter(5.0, 6.0);
331
332 ASSERT_NE(filter.shared().get(), &filter);
333 ASSERT_EQ(*filter.shared(), filter);
334}
335
336TEST(DisplayListImageFilter, ErodeAsErode) {
337 DlErodeImageFilter filter(5.0, 6.0);
338
339 ASSERT_NE(filter.asErode(), nullptr);
340 ASSERT_EQ(filter.asErode(), &filter);
341}
342
343TEST(DisplayListImageFilter, ErodeContents) {
344 DlErodeImageFilter filter(5.0, 6.0);
345
346 ASSERT_EQ(filter.radius_x(), 5.0);
347 ASSERT_EQ(filter.radius_y(), 6.0);
348}
349
350TEST(DisplayListImageFilter, ErodeEquals) {
351 DlErodeImageFilter filter1(5.0, 6.0);
352 DlErodeImageFilter filter2(5.0, 6.0);
353
354 TestEquals(filter1, filter2);
355}
356
357TEST(DisplayListImageFilter, ErodeWithLocalMatrixEquals) {
358 DlErodeImageFilter filter1(5.0, 6.0);
359 DlErodeImageFilter filter2(5.0, 6.0);
360
361 DlMatrix local_matrix = DlMatrix::MakeTranslation({10, 10});
362 TestEquals(*filter1.makeWithLocalMatrix(local_matrix),
363 *filter2.makeWithLocalMatrix(local_matrix));
364}
365
366TEST(DisplayListImageFilter, ErodeNotEquals) {
367 DlErodeImageFilter filter1(5.0, 6.0);
368 DlErodeImageFilter filter2(7.0, 6.0);
369 DlErodeImageFilter filter3(5.0, 8.0);
370
371 TestNotEquals(filter1, filter2, "Radius X differs");
372 TestNotEquals(filter1, filter3, "Radius Y differs");
373}
374
375TEST(DisplayListImageFilter, ErodeBounds) {
377 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
378 DlRect expected_output_bounds = input_bounds.Expand(-5, -10);
379 TestBounds(filter, input_bounds, expected_output_bounds);
380}
381
382TEST(DisplayListImageFilter, MatrixConstructor) {
383 DlMatrixImageFilter filter(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
384 0.5, 3.0, 0.0, 15, //
385 0.0, 0.0, 1.0, 0.0, //
386 0.0, 0.0, 0.0, 1.0),
388}
389
390TEST(DisplayListImageFilter, MatrixShared) {
391 DlMatrixImageFilter filter(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
392 0.5, 3.0, 0.0, 15, //
393 0.0, 0.0, 1.0, 0.0, //
394 0.0, 0.0, 0.0, 1.0),
396
397 ASSERT_NE(filter.shared().get(), &filter);
398 ASSERT_EQ(*filter.shared(), filter);
399}
400
401TEST(DisplayListImageFilter, MatrixAsMatrix) {
402 DlMatrixImageFilter filter(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
403 0.5, 3.0, 0.0, 15, //
404 0.0, 0.0, 1.0, 0.0, //
405 0.0, 0.0, 0.0, 1.0),
407
408 ASSERT_NE(filter.asMatrix(), nullptr);
409 ASSERT_EQ(filter.asMatrix(), &filter);
410}
411
412TEST(DisplayListImageFilter, MatrixContents) {
413 DlMatrix matrix = DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
414 0.5, 3.0, 0.0, 15, //
415 0.0, 0.0, 1.0, 0.0, //
416 0.0, 0.0, 0.0, 1.0);
418
419 ASSERT_EQ(filter.matrix(), matrix);
420 ASSERT_EQ(filter.sampling(), DlImageSampling::kLinear);
421}
422
423TEST(DisplayListImageFilter, MatrixEquals) {
424 DlMatrix matrix = DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
425 0.5, 3.0, 0.0, 15, //
426 0.0, 0.0, 1.0, 0.0, //
427 0.0, 0.0, 0.0, 1.0);
430
431 TestEquals(filter1, filter2);
432}
433
434TEST(DisplayListImageFilter, MatrixWithLocalMatrixEquals) {
435 DlMatrix matrix = DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
436 0.5, 3.0, 0.0, 15, //
437 0.0, 0.0, 1.0, 0.0, //
438 0.0, 0.0, 0.0, 1.0);
441
442 DlMatrix local_matrix = DlMatrix::MakeTranslation({10, 10});
443 TestEquals(*filter1.makeWithLocalMatrix(local_matrix),
444 *filter2.makeWithLocalMatrix(local_matrix));
445}
446
447TEST(DisplayListImageFilter, MatrixNotEquals) {
448 DlMatrix matrix1 = DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
449 0.5, 3.0, 0.0, 15, //
450 0.0, 0.0, 1.0, 0.0, //
451 0.0, 0.0, 0.0, 1.0);
452 DlMatrix matrix2 = DlMatrix::MakeRow(5.0, 0.0, 0.0, 10, //
453 0.5, 3.0, 0.0, 15, //
454 0.0, 0.0, 1.0, 0.0, //
455 0.0, 0.0, 0.0, 1.0);
459
460 TestNotEquals(filter1, filter2, "Matrix differs");
461 TestNotEquals(filter1, filter3, "Sampling differs");
462}
463
464TEST(DisplayListImageFilter, MatrixBounds) {
465 DlMatrix matrix = DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
466 0.5, 3.0, 0.0, 7, //
467 0.0, 0.0, 1.0, 0.0, //
468 0.0, 0.0, 0.0, 1.0);
469 EXPECT_TRUE(matrix.IsInvertible());
471 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
472 DlQuad expectedOutputQuad = {
473 DlPoint(50, 77), // == (20,20) => (20*2 + 10, 20/2 + 20*3 + 7)
474 DlPoint(50, 257), // == (20,80) => (20*2 + 10, 20/2 + 80*3 + 7)
475 DlPoint(170, 287), // == (80,80) => (80*2 + 10, 80/2 + 80*3 + 7)
476 DlPoint(170, 107), // == (80,20) => (80*2 + 10, 80/2 + 20*3 + 7)
477 };
478 TestBounds(filter, input_bounds, expectedOutputQuad);
479}
480
481TEST(DisplayListImageFilter, ComposeConstructor) {
482 DlMatrixImageFilter outer(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
483 0.5, 3.0, 0.0, 15, //
484 0.0, 0.0, 1.0, 0.0, //
485 0.0, 0.0, 0.0, 1.0),
487 DlBlurImageFilter inner(5.0, 6.0, DlTileMode::kMirror);
488 DlComposeImageFilter filter(outer, inner);
489}
490
491TEST(DisplayListImageFilter, ComposeShared) {
492 DlMatrixImageFilter outer(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
493 0.5, 3.0, 0.0, 15, //
494 0.0, 0.0, 1.0, 0.0, //
495 0.0, 0.0, 0.0, 1.0),
497 DlBlurImageFilter inner(5.0, 6.0, DlTileMode::kMirror);
498 DlComposeImageFilter filter(outer, inner);
499
500 ASSERT_NE(filter.shared().get(), &filter);
501 ASSERT_EQ(*filter.shared(), filter);
502}
503
504TEST(DisplayListImageFilter, ComposeAsCompose) {
505 DlMatrixImageFilter outer(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
506 0.5, 3.0, 0.0, 15, //
507 0.0, 0.0, 1.0, 0.0, //
508 0.0, 0.0, 0.0, 1.0),
510 DlBlurImageFilter inner(5.0, 6.0, DlTileMode::kMirror);
511 DlComposeImageFilter filter(outer, inner);
512
513 ASSERT_NE(filter.asCompose(), nullptr);
514 ASSERT_EQ(filter.asCompose(), &filter);
515}
516
517TEST(DisplayListImageFilter, ComposeContents) {
518 DlMatrixImageFilter outer(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
519 0.5, 3.0, 0.0, 15, //
520 0.0, 0.0, 1.0, 0.0, //
521 0.0, 0.0, 0.0, 1.0),
523 DlBlurImageFilter inner(5.0, 6.0, DlTileMode::kMirror);
524 DlComposeImageFilter filter(outer, inner);
525
526 ASSERT_EQ(*filter.outer().get(), outer);
527 ASSERT_EQ(*filter.inner().get(), inner);
528}
529
530TEST(DisplayListImageFilter, ComposeEquals) {
531 DlMatrixImageFilter outer1(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
532 0.5, 3.0, 0.0, 15, //
533 0.0, 0.0, 1.0, 0.0, //
534 0.0, 0.0, 0.0, 1.0),
536 DlBlurImageFilter inner1(5.0, 6.0, DlTileMode::kMirror);
537 DlComposeImageFilter filter1(outer1, inner1);
538
539 DlMatrixImageFilter outer2(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
540 0.5, 3.0, 0.0, 15, //
541 0.0, 0.0, 1.0, 0.0, //
542 0.0, 0.0, 0.0, 1.0),
544 DlBlurImageFilter inner2(5.0, 6.0, DlTileMode::kMirror);
545 DlComposeImageFilter filter2(outer1, inner1);
546
547 TestEquals(filter1, filter2);
548}
549
550TEST(DisplayListImageFilter, ComposeWithLocalMatrixEquals) {
551 DlMatrixImageFilter outer1(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
552 0.5, 3.0, 0.0, 15, //
553 0.0, 0.0, 1.0, 0.0, //
554 0.0, 0.0, 0.0, 1.0),
556 DlBlurImageFilter inner1(5.0, 6.0, DlTileMode::kMirror);
557 DlComposeImageFilter filter1(outer1, inner1);
558
559 DlMatrixImageFilter outer2(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
560 0.5, 3.0, 0.0, 15, //
561 0.0, 0.0, 1.0, 0.0, //
562 0.0, 0.0, 0.0, 1.0),
564 DlBlurImageFilter inner2(5.0, 6.0, DlTileMode::kMirror);
565 DlComposeImageFilter filter2(outer1, inner1);
566
567 DlMatrix local_matrix = DlMatrix::MakeTranslation({10, 10});
568 TestEquals(*filter1.makeWithLocalMatrix(local_matrix),
569 *filter2.makeWithLocalMatrix(local_matrix));
570}
571
572TEST(DisplayListImageFilter, ComposeNotEquals) {
573 DlMatrixImageFilter outer1(DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
574 0.5, 3.0, 0.0, 15, //
575 0.0, 0.0, 1.0, 0.0, //
576 0.0, 0.0, 0.0, 1.0),
578 DlBlurImageFilter inner1(5.0, 6.0, DlTileMode::kMirror);
579
580 DlMatrixImageFilter outer2(DlMatrix::MakeRow(5.0, 0.0, 0.0, 10, //
581 0.5, 3.0, 0.0, 15, //
582 0.0, 0.0, 1.0, 0.0, //
583 0.0, 0.0, 0.0, 1.0),
585 DlBlurImageFilter inner2(7.0, 6.0, DlTileMode::kMirror);
586
587 DlComposeImageFilter filter1(outer1, inner1);
588 DlComposeImageFilter filter2(outer2, inner1);
589 DlComposeImageFilter filter3(outer1, inner2);
590
591 TestNotEquals(filter1, filter2, "Outer differs");
592 TestNotEquals(filter1, filter3, "Inner differs");
593}
594
595TEST(DisplayListImageFilter, ComposeBounds) {
598 DlComposeImageFilter filter = DlComposeImageFilter(outer, inner);
599 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
600 DlRect expected_output_bounds = input_bounds.Expand(36, 15).Expand(5, 10);
601 TestBounds(filter, input_bounds, expected_output_bounds);
602}
603
605 const DlRect& sourceBounds,
606 const DlRect& expectedOutputBounds,
607 const DlRect& expectedInputBounds) {
608 DlRect bounds;
609 EXPECT_EQ(filter.map_local_bounds(sourceBounds, bounds), nullptr);
610 EXPECT_EQ(bounds, expectedOutputBounds);
611
612 DlIRect ibounds;
613 EXPECT_EQ(filter.map_device_bounds(DlIRect::RoundOut(sourceBounds),
614 DlMatrix(), ibounds),
615 nullptr);
616 EXPECT_EQ(ibounds, DlIRect::RoundOut(expectedOutputBounds));
617
618 EXPECT_EQ(filter.get_input_device_bounds(DlIRect::RoundOut(sourceBounds),
619 DlMatrix(), ibounds),
620 nullptr);
621 EXPECT_EQ(ibounds, DlIRect::RoundOut(expectedInputBounds));
622}
623
624TEST(DisplayListImageFilter, ComposeBoundsWithUnboundedInner) {
625 auto input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
626 auto expected_bounds = DlRect::MakeLTRB(5, 2, 95, 98);
627
628 DlBlendColorFilter color_filter(DlColor::kRed(), DlBlendMode::kSrcOver);
629 auto outer = DlBlurImageFilter(5.0, 6.0, DlTileMode::kRepeat);
630 auto inner = DlColorFilterImageFilter(color_filter.shared());
631 auto composed = DlComposeImageFilter(outer.shared(), inner.shared());
632
633 TestUnboundedBounds(composed, input_bounds, expected_bounds, expected_bounds);
634}
635
636TEST(DisplayListImageFilter, ComposeBoundsWithUnboundedOuter) {
637 auto input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
638 auto expected_bounds = DlRect::MakeLTRB(5, 2, 95, 98);
639
640 DlBlendColorFilter color_filter(DlColor::kRed(), DlBlendMode::kSrcOver);
641 auto outer = DlColorFilterImageFilter(color_filter.shared());
642 auto inner = DlBlurImageFilter(5.0, 6.0, DlTileMode::kRepeat);
643 auto composed = DlComposeImageFilter(outer.shared(), inner.shared());
644
645 TestUnboundedBounds(composed, input_bounds, expected_bounds, expected_bounds);
646}
647
648TEST(DisplayListImageFilter, ComposeBoundsWithUnboundedInnerAndOuter) {
649 auto input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
650 auto expected_bounds = input_bounds;
651
652 DlBlendColorFilter color_filter1(DlColor::kRed(), DlBlendMode::kSrcOver);
653 DlBlendColorFilter color_filter2(DlColor::kBlue(), DlBlendMode::kSrcOver);
654 auto outer = DlColorFilterImageFilter(color_filter1.shared());
655 auto inner = DlColorFilterImageFilter(color_filter2.shared());
656 auto composed = DlComposeImageFilter(outer.shared(), inner.shared());
657
658 TestUnboundedBounds(composed, input_bounds, expected_bounds, expected_bounds);
659}
660
661// See https://github.com/flutter/flutter/issues/108433
662TEST(DisplayListImageFilter, Issue108433) {
663 auto input_bounds = DlIRect::MakeLTRB(20, 20, 80, 80);
664 auto expected_bounds = DlIRect::MakeLTRB(5, 2, 95, 98);
665
666 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kSrcOver);
667 auto dl_outer = DlBlurImageFilter(5.0, 6.0, DlTileMode::kRepeat);
668 auto dl_inner = DlColorFilterImageFilter(dl_color_filter.shared());
669 auto dl_compose = DlComposeImageFilter(dl_outer, dl_inner);
670
671 DlIRect dl_bounds;
672 ASSERT_EQ(dl_compose.map_device_bounds(input_bounds, DlMatrix(), dl_bounds),
673 nullptr);
674 ASSERT_EQ(dl_bounds, expected_bounds);
675}
676
677TEST(DisplayListImageFilter, ColorFilterConstructor) {
678 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kLighten);
679 DlColorFilterImageFilter filter(dl_color_filter);
680}
681
682TEST(DisplayListImageFilter, ColorFilterShared) {
683 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kLighten);
684 DlColorFilterImageFilter filter(dl_color_filter);
685
686 ASSERT_EQ(*filter.shared(), filter);
687}
688
689TEST(DisplayListImageFilter, ColorFilterAsColorFilter) {
690 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kLighten);
691 DlColorFilterImageFilter filter(dl_color_filter);
692
693 ASSERT_NE(filter.asColorFilter(), nullptr);
694 ASSERT_EQ(filter.asColorFilter(), &filter);
695}
696
697TEST(DisplayListImageFilter, ColorFilterContents) {
698 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kLighten);
699 DlColorFilterImageFilter filter(dl_color_filter);
700
701 ASSERT_EQ(*filter.color_filter().get(), dl_color_filter);
702}
703
704TEST(DisplayListImageFilter, ColorFilterEquals) {
705 DlBlendColorFilter dl_color_filter1(DlColor::kRed(), DlBlendMode::kLighten);
706 DlColorFilterImageFilter filter1(dl_color_filter1);
707
708 DlBlendColorFilter dl_color_filter2(DlColor::kRed(), DlBlendMode::kLighten);
709 DlColorFilterImageFilter filter2(dl_color_filter2);
710
711 TestEquals(filter1, filter2);
712}
713
714TEST(DisplayListImageFilter, ColorFilterWithLocalMatrixEquals) {
715 DlBlendColorFilter dl_color_filter1(DlColor::kRed(), DlBlendMode::kLighten);
716 DlColorFilterImageFilter filter1(dl_color_filter1);
717
718 DlBlendColorFilter dl_color_filter2(DlColor::kRed(), DlBlendMode::kLighten);
719 DlColorFilterImageFilter filter2(dl_color_filter2);
720
721 DlMatrix local_matrix = DlMatrix::MakeTranslation({10, 10});
722 TestEquals(*filter1.makeWithLocalMatrix(local_matrix),
723 *filter2.makeWithLocalMatrix(local_matrix));
724}
725
726TEST(DisplayListImageFilter, ColorFilterNotEquals) {
727 DlBlendColorFilter dl_color_filter1(DlColor::kRed(), DlBlendMode::kLighten);
728 DlColorFilterImageFilter filter1(dl_color_filter1);
729
730 DlBlendColorFilter dl_color_filter2(DlColor::kBlue(), DlBlendMode::kLighten);
731 DlColorFilterImageFilter filter2(dl_color_filter2);
732
733 DlBlendColorFilter dl_color_filter3(DlColor::kRed(), DlBlendMode::kDarken);
734 DlColorFilterImageFilter filter3(dl_color_filter3);
735
736 TestNotEquals(filter1, filter2, "Color differs");
737 TestNotEquals(filter1, filter3, "Blend Mode differs");
738}
739
740TEST(DisplayListImageFilter, ColorFilterBounds) {
741 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kSrcIn);
742 DlColorFilterImageFilter filter(dl_color_filter);
743 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
744 TestBounds(filter, input_bounds, input_bounds);
745}
746
747TEST(DisplayListImageFilter, ColorFilterModifiesTransparencyBounds) {
748 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kSrcOver);
749 DlColorFilterImageFilter filter(dl_color_filter);
750 DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
751 TestInvalidBounds(filter, DlMatrix(), input_bounds);
752}
753
754TEST(DisplayListImageFilter, LocalImageFilterBounds) {
755 auto filter_matrix = DlMatrix::MakeRow(2.0, 0.0, 0.0, 10, //
756 0.5, 3.0, 0.0, 15, //
757 0.0, 0.0, 1.0, 0.0, //
758 0.0, 0.0, 0.0, 1.0);
759 std::vector<sk_sp<SkImageFilter>> sk_filters{
760 SkImageFilters::Blur(5.0, 6.0, SkTileMode::kRepeat, nullptr),
761 SkImageFilters::ColorFilter(
762 SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcOver), nullptr),
763 SkImageFilters::Dilate(5.0, 10.0, nullptr),
764 SkImageFilters::MatrixTransform(ToSkMatrix(filter_matrix),
765 SkSamplingOptions(SkFilterMode::kLinear),
766 nullptr),
767 SkImageFilters::Compose(
768 SkImageFilters::Blur(5.0, 6.0, SkTileMode::kRepeat, nullptr),
769 SkImageFilters::ColorFilter(
770 SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcOver),
771 nullptr))};
772
773 DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kSrcOver);
774 std::vector<std::shared_ptr<DlImageFilter>> dl_filters{
776 DlImageFilter::MakeColorFilter(dl_color_filter.shared()),
781 DlImageFilter::MakeColorFilter(dl_color_filter.shared())),
782 };
783
784 auto persp = SkMatrix::I();
785 persp.setPerspY(0.001);
786 std::vector<SkMatrix> sk_matrices = {
787 SkMatrix::Translate(10.0, 10.0),
788 SkMatrix::Scale(2.0, 2.0).preTranslate(10.0, 10.0),
789 SkMatrix::RotateDeg(45).preTranslate(5.0, 5.0), //
790 persp};
791 std::vector<DlMatrix> dl_matrices = {
792 DlMatrix::MakeTranslation({10.0, 10.0}),
793 DlMatrix::MakeScale({2.0, 2.0, 1.0}).Translate({10.0, 10.0}),
795 ToDlMatrix(persp)};
796 std::vector<SkMatrix> sk_bounds_matrices{
797 SkMatrix::Translate(5.0, 10.0),
798 SkMatrix::Scale(2.0, 2.0),
799 };
800 std::vector<DlMatrix> dl_bounds_matrices{
801 DlMatrix::MakeTranslation({5.0, 10.0}),
802 DlMatrix::MakeScale({2.0, 2.0, 1.0}),
803 };
804
805 for (unsigned j = 0; j < dl_matrices.size(); j++) {
806 DlLocalMatrixImageFilter filter(dl_matrices[j], nullptr);
807 {
808 const auto input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
809 DlRect output_bounds;
810 EXPECT_EQ(filter.map_local_bounds(input_bounds, output_bounds),
811 &output_bounds);
812 EXPECT_EQ(input_bounds, output_bounds);
813 }
814 for (unsigned k = 0; k < dl_bounds_matrices.size(); k++) {
815 auto& bounds_matrix = dl_bounds_matrices[k];
816 {
817 const auto input_bounds = DlIRect::MakeLTRB(20, 20, 80, 80);
818 DlIRect output_bounds;
819 EXPECT_EQ(filter.map_device_bounds(input_bounds, bounds_matrix,
820 output_bounds),
821 &output_bounds);
822 EXPECT_EQ(input_bounds, output_bounds);
823 }
824 {
825 const auto output_bounds = DlIRect::MakeLTRB(20, 20, 80, 80);
826 DlIRect input_bounds;
827 EXPECT_EQ(filter.get_input_device_bounds(output_bounds, bounds_matrix,
828 input_bounds),
829 &input_bounds);
830 EXPECT_EQ(input_bounds, output_bounds);
831 }
832 }
833 }
834
835 for (unsigned i = 0; i < sk_filters.size(); i++) {
836 for (unsigned j = 0; j < dl_matrices.size(); j++) {
837 for (unsigned k = 0; k < dl_bounds_matrices.size(); k++) {
838 auto desc = "filter " + std::to_string(i + 1) //
839 + ", filter matrix " + std::to_string(j + 1) //
840 + ", bounds matrix " + std::to_string(k + 1);
841 auto sk_local_filter =
842 sk_filters[i]->makeWithLocalMatrix(sk_matrices[j]);
843 auto dl_local_filter =
844 dl_filters[i]->makeWithLocalMatrix(dl_matrices[j]);
845 if (!sk_local_filter || !dl_local_filter) {
846 // Temporarily relax the equivalence testing to allow Skia to expand
847 // their behavior. Once the Skia fixes are rolled in, the
848 // DlImageFilter should adapt to the new rules.
849 // See https://github.com/flutter/flutter/issues/114723
850 ASSERT_TRUE(sk_local_filter || !dl_local_filter) << desc;
851 continue;
852 }
853 {
854 auto input_bounds = SkIRect::MakeLTRB(20, 20, 80, 80);
855 SkIRect sk_rect;
856 DlIRect dl_rect;
857 sk_rect = sk_local_filter->filterBounds(
858 input_bounds, sk_bounds_matrices[k],
859 SkImageFilter::MapDirection::kForward_MapDirection);
860 if (dl_local_filter->map_device_bounds(
861 ToDlIRect(input_bounds), dl_bounds_matrices[k], dl_rect)) {
862 ASSERT_EQ(sk_rect, ToSkIRect(dl_rect)) << desc;
863 } else {
864 ASSERT_TRUE(dl_local_filter->modifies_transparent_black()) << desc;
865 ASSERT_FALSE(sk_local_filter->canComputeFastBounds()) << desc;
866 }
867 }
868 {
869 // Test for: Know the outset bounds to get the inset bounds
870 // Skia have some bounds calculate error of DilateFilter and
871 // MatrixFilter
872 // Skia issue: https://bugs.chromium.org/p/skia/issues/detail?id=13444
873 // flutter issue: https://github.com/flutter/flutter/issues/108693
874 if (i == 2 || i == 3) {
875 continue;
876 }
877 auto outset_bounds = SkIRect::MakeLTRB(20, 20, 80, 80);
878 SkIRect sk_rect;
879 DlIRect dl_rect;
880 sk_rect = sk_local_filter->filterBounds(
881 outset_bounds, sk_bounds_matrices[k],
882 SkImageFilter::MapDirection::kReverse_MapDirection);
883 if (dl_local_filter->get_input_device_bounds(
884 ToDlIRect(outset_bounds), dl_bounds_matrices[k], dl_rect)) {
885 ASSERT_EQ(sk_rect, ToSkIRect(dl_rect)) << desc;
886 } else {
887 ASSERT_TRUE(dl_local_filter->modifies_transparent_black());
888 ASSERT_FALSE(sk_local_filter->canComputeFastBounds());
889 }
890 }
891 }
892 }
893 }
894}
895
896TEST(DisplayListImageFilter, RuntimeEffectEquality) {
897 DlRuntimeEffectImageFilter filter_a(nullptr, {nullptr},
898 std::make_shared<std::vector<uint8_t>>());
899 DlRuntimeEffectImageFilter filter_b(nullptr, {nullptr},
900 std::make_shared<std::vector<uint8_t>>());
901
902 EXPECT_EQ(filter_a, filter_b);
903
905 nullptr, {nullptr}, std::make_shared<std::vector<uint8_t>>(1));
906
907 EXPECT_NE(filter_a, filter_c);
908}
909
910TEST(DisplayListImageFilter, RuntimeEffectEqualityWithSamplers) {
911 auto image_a =
913 auto image_b =
915
916 DlRuntimeEffectImageFilter filter_a(nullptr, {nullptr, image_a},
917 std::make_shared<std::vector<uint8_t>>());
918 DlRuntimeEffectImageFilter filter_b(nullptr, {nullptr, image_a},
919 std::make_shared<std::vector<uint8_t>>());
920
921 EXPECT_EQ(filter_a, filter_b);
922
923 DlRuntimeEffectImageFilter filter_c(nullptr, {nullptr, image_b},
924 std::make_shared<std::vector<uint8_t>>());
925
926 EXPECT_NE(filter_a, filter_c);
927}
928
929TEST(DisplayListImageFilter, RuntimeEffectMapDeviceBounds) {
930 DlRuntimeEffectImageFilter filter_a(nullptr, {nullptr},
931 std::make_shared<std::vector<uint8_t>>());
932
933 auto input_bounds = DlIRect::MakeLTRB(0, 0, 100, 100);
934 DlMatrix identity;
935 DlIRect output_bounds;
936 DlIRect* result =
937 filter_a.map_device_bounds(input_bounds, identity, output_bounds);
938
939 EXPECT_NE(result, nullptr);
940 EXPECT_EQ(result, &output_bounds);
941 EXPECT_EQ(output_bounds, input_bounds);
942}
943
944TEST(DisplayListImageFilter, RuntimeEffectMapInputBounds) {
945 DlRuntimeEffectImageFilter filter_a(nullptr, {nullptr},
946 std::make_shared<std::vector<uint8_t>>());
947
948 auto input_bounds = DlRect::MakeLTRB(0, 0, 100, 100);
949
950 DlRect output_bounds;
951 DlRect* result = filter_a.map_local_bounds(input_bounds, output_bounds);
952
953 EXPECT_NE(result, nullptr);
954 EXPECT_EQ(result, &output_bounds);
955 EXPECT_EQ(output_bounds, input_bounds);
956}
957
958TEST(DisplayListImageFilter, RuntimeEffectGetInputDeviceBounds) {
959 DlRuntimeEffectImageFilter filter_a(nullptr, {nullptr},
960 std::make_shared<std::vector<uint8_t>>());
961
962 auto output_bounds = DlIRect::MakeLTRB(0, 0, 100, 100);
963
964 DlMatrix identity;
965 DlIRect input_bounds;
966 DlIRect* result =
967 filter_a.get_input_device_bounds(output_bounds, identity, input_bounds);
968
969 EXPECT_NE(result, nullptr);
970 EXPECT_EQ(result, &input_bounds);
971 EXPECT_EQ(output_bounds, input_bounds);
972}
973
974TEST(DisplayListImageFilter, RuntimeEffectModifiesTransparentBlack) {
975 DlRuntimeEffectImageFilter filter_a(nullptr, {nullptr},
976 std::make_shared<std::vector<uint8_t>>());
977
978 EXPECT_FALSE(filter_a.modifies_transparent_black());
979}
980
981} // namespace testing
982} // namespace flutter
std::shared_ptr< DlColorFilter > shared() const override
std::shared_ptr< DlImageFilter > shared() const override
const DlBlurImageFilter * asBlur() const override
const std::shared_ptr< const DlColorFilter > color_filter() const
const DlColorFilterImageFilter * asColorFilter() const override
std::shared_ptr< DlImageFilter > shared() const override
static std::shared_ptr< DlColorSource > MakeImage(const sk_sp< const DlImage > &image, DlTileMode horizontal_tile_mode, DlTileMode vertical_tile_mode, DlImageSampling sampling=DlImageSampling::kLinear, const DlMatrix *matrix=nullptr)
std::shared_ptr< DlImageFilter > shared() const override
std::shared_ptr< DlImageFilter > inner() const
std::shared_ptr< DlImageFilter > outer() const
const DlComposeImageFilter * asCompose() const override
const DlDilateImageFilter * asDilate() const override
std::shared_ptr< DlImageFilter > shared() const override
const DlErodeImageFilter * asErode() const override
std::shared_ptr< DlImageFilter > shared() const override
static std::shared_ptr< DlImageFilter > MakeDilate(DlScalar radius_x, DlScalar radius_y)
virtual std::shared_ptr< DlImageFilter > makeWithLocalMatrix(const DlMatrix &matrix) const
virtual DlIRect * map_device_bounds(const DlIRect &input_bounds, const DlMatrix &ctm, DlIRect &output_bounds) const =0
static std::shared_ptr< DlImageFilter > MakeBlur(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static std::shared_ptr< DlImageFilter > MakeColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
virtual DlRect * map_local_bounds(const DlRect &input_bounds, DlRect &output_bounds) const =0
static std::shared_ptr< DlImageFilter > MakeMatrix(const DlMatrix &matrix, DlImageSampling sampling)
static std::shared_ptr< DlImageFilter > MakeCompose(const std::shared_ptr< DlImageFilter > &outer, const std::shared_ptr< DlImageFilter > &inner)
virtual DlIRect * get_input_device_bounds(const DlIRect &output_bounds, const DlMatrix &ctm, DlIRect &input_bounds) const =0
DlIRect * map_device_bounds(const DlIRect &input_bounds, const DlMatrix &ctm, DlIRect &output_bounds) const override
DlIRect * get_input_device_bounds(const DlIRect &output_bounds, const DlMatrix &ctm, DlIRect &input_bounds) const override
DlRect * map_local_bounds(const DlRect &input_bounds, DlRect &output_bounds) const override
const DlMatrixImageFilter * asMatrix() const override
std::shared_ptr< DlImageFilter > shared() const override
const DlMatrix & matrix() const
DlIRect * map_device_bounds(const DlIRect &input_bounds, const DlMatrix &ctm, DlIRect &output_bounds) const override
DlRect * map_local_bounds(const DlRect &input_bounds, DlRect &output_bounds) const override
DlIRect * get_input_device_bounds(const DlIRect &output_bounds, const DlMatrix &ctm, DlIRect &input_bounds) const override
SkRect sk_rect
static void TestBoundsWithMatrix(const DlImageFilter &filter, const DlMatrix &matrix, const DlRect &sourceBounds, const DlQuad &expectedLocalOutputQuad)
static void TestBounds(const DlImageFilter &filter, const DlRect &sourceBounds, const DlQuad &expectedLocalOutputQuad)
static void TestEquals(const T &source1, const U &source2)
static void TestInvalidBounds(const DlImageFilter &filter, const DlMatrix &matrix, const DlRect &localInputBounds)
static void TestNotEquals(T &source1, U &source2, const std::string &label)
TEST(NativeAssetsManagerTest, NoAvailableAssets)
static void TestUnboundedBounds(DlImageFilter &filter, const DlRect &sourceBounds, const DlRect &expectedOutputBounds, const DlRect &expectedInputBounds)
static bool containsInclusive(const DlRect rect, const DlPoint p)
impeller::Scalar DlScalar
impeller::Matrix DlMatrix
impeller::Degrees DlDegrees
const SkIRect & ToSkIRect(const DlIRect &rect)
SkMatrix ToSkMatrix(const DlMatrix &matrix)
const DlIRect & ToDlIRect(const SkIRect &rect)
impeller::Quad DlQuad
DlMatrix ToDlMatrix(const SkMatrix &matrix)
impeller::Point DlPoint
static constexpr DlColor kBlue()
Definition dl_color.h:73
static constexpr DlColor kRed()
Definition dl_color.h:71
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
Scalar m[16]
Definition matrix.h:39
constexpr Matrix Translate(const Vector3 &t) const
Definition matrix.h:263
bool IsInvertible() const
Definition matrix.h:321
constexpr bool HasPerspective2D() const
Definition matrix.h:414
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:127
constexpr Quad Transform(const Quad &quad) const
Definition matrix.h:623
constexpr Matrix Scale(const Vector3 &s) const
Definition matrix.h:275
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:223
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
constexpr auto GetBottom() const
Definition rect.h:357
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition rect.h:472
constexpr auto GetTop() const
Definition rect.h:353
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
Definition rect.h:414
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
Definition rect.h:157
constexpr auto GetLeft() const
Definition rect.h:351
RoundOut(const TRect< U > &r)
Definition rect.h:679
constexpr auto GetRight() const
Definition rect.h:355
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
Definition rect.h:438
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:618
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129