Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 981ba0f

Browse files
committed
workaround perspective math failures in ImageFilter bounds unit tests
1 parent 007f8b0 commit 981ba0f

File tree

2 files changed

+37
-33
lines changed

2 files changed

+37
-33
lines changed

display_list/effects/dl_image_filter.cc

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,21 @@ DlIRect* DlImageFilter::inset_device_bounds(const DlIRect& input_bounds,
4646
DlIRect& output_bounds) {
4747
if (ctm.IsFinite() && ctm.IsInvertible()) {
4848
if (ctm.HasPerspective2D()) {
49-
DlRect local_bounds = DlRect::Make(input_bounds)
50-
.TransformAndClipBounds(ctm.Invert())
51-
.Expand(-radius_x, -radius_y);
52-
output_bounds =
53-
DlIRect::RoundOut(local_bounds.TransformAndClipBounds(ctm));
54-
return &output_bounds;
49+
// Ideally this code would use Impeller classes to do the math, see:
50+
// https://github.com/flutter/flutter/issues/159175
51+
SkMatrix sk_ctm = ToSkMatrix(ctm);
52+
FML_DCHECK(sk_ctm.hasPerspective());
53+
SkIRect sk_input_bounds =
54+
SkIRect::MakeLTRB(input_bounds.GetLeft(), input_bounds.GetTop(),
55+
input_bounds.GetRight(), input_bounds.GetBottom());
56+
57+
SkMatrix inverse;
58+
if (sk_ctm.invert(&inverse)) {
59+
SkRect local_bounds = inverse.mapRect(SkRect::Make(sk_input_bounds));
60+
local_bounds.inset(radius_x, radius_y);
61+
output_bounds = ToDlIRect(sk_ctm.mapRect(local_bounds).roundOut());
62+
return &output_bounds;
63+
}
5564
} else {
5665
DlVector2 device_radius = map_vectors_affine(ctm, radius_x, radius_y);
5766
output_bounds =
@@ -70,12 +79,21 @@ DlIRect* DlImageFilter::outset_device_bounds(const DlIRect& input_bounds,
7079
DlIRect& output_bounds) {
7180
if (ctm.IsFinite() && ctm.IsInvertible()) {
7281
if (ctm.HasPerspective2D()) {
73-
DlRect local_bounds = DlRect::Make(input_bounds)
74-
.TransformAndClipBounds(ctm.Invert())
75-
.Expand(radius_x, radius_y);
76-
output_bounds =
77-
DlIRect::RoundOut(local_bounds.TransformAndClipBounds(ctm));
78-
return &output_bounds;
82+
// Ideally this code would use Impeller classes to do the math, see:
83+
// https://github.com/flutter/flutter/issues/159175
84+
SkMatrix sk_ctm = ToSkMatrix(ctm);
85+
FML_DCHECK(sk_ctm.hasPerspective());
86+
SkIRect sk_input_bounds =
87+
SkIRect::MakeLTRB(input_bounds.GetLeft(), input_bounds.GetTop(),
88+
input_bounds.GetRight(), input_bounds.GetBottom());
89+
90+
SkMatrix inverse;
91+
if (sk_ctm.invert(&inverse)) {
92+
SkRect local_bounds = inverse.mapRect(SkRect::Make(sk_input_bounds));
93+
local_bounds.outset(radius_x, radius_y);
94+
output_bounds = ToDlIRect(sk_ctm.mapRect(local_bounds).roundOut());
95+
return &output_bounds;
96+
}
7997
} else {
8098
DlVector2 device_radius = map_vectors_affine(ctm, radius_x, radius_y);
8199
output_bounds =

display_list/effects/dl_image_filter_unittests.cc

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -156,29 +156,15 @@ static void TestBounds(const DlImageFilter& filter,
156156
ASSERT_FALSE(matrix.HasPerspective2D()) << matrix;
157157
TestBoundsWithMatrix(filter, matrix, sourceBounds,
158158
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);
159165
}
160166
}
161167
}
162-
163-
{
164-
// Just test once with a reasonable perspective transform. Combining
165-
// perspective with all of the abusively scaled and skewed transforms
166-
// created in the loop above tends to lead to coordinates growing out
167-
// of any reasonable scale.
168-
DlMatrix matrix;
169-
matrix = matrix.Scale({2.0f, 2.0f, 1});
170-
matrix = matrix.Translate({1000, 1000, 500});
171-
// matrix = DlMatrix::MakeSkew(0.125f, 0.125f) * matrix;
172-
matrix = DlMatrix::MakeRotationX(DlDegrees(5)) * matrix;
173-
// matrix = DlMatrix::MakeRotationY(DlDegrees(5)) * matrix;
174-
// matrix = DlMatrix::MakeTranslation({0, 0, 5});
175-
matrix = DlMatrix::MakePerspective(DlDegrees(60), 0.5, -500, 1000) * matrix;
176-
// matrix = DlMatrix::MakeLookAt({0, 0, -10}, {0, 0, 10}, {0, 1, 0})
177-
// * matrix;
178-
ASSERT_TRUE(matrix.IsInvertible()) << matrix;
179-
ASSERT_TRUE(matrix.HasPerspective2D()) << matrix;
180-
TestBoundsWithMatrix(filter, matrix, sourceBounds, expectedLocalOutputQuad);
181-
}
182168
}
183169

184170
static void TestBounds(const DlImageFilter& filter,
@@ -375,7 +361,7 @@ TEST(DisplayListImageFilter, ErodeNotEquals) {
375361

376362
TEST(DisplayListImageFilter, ErodeBounds) {
377363
DlErodeImageFilter filter = DlErodeImageFilter(5, 10);
378-
DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80).Shift(100, 100);
364+
DlRect input_bounds = DlRect::MakeLTRB(20, 20, 80, 80);
379365
DlRect expected_output_bounds = input_bounds.Expand(-5, -10);
380366
TestBounds(filter, input_bounds, expected_output_bounds);
381367
}

0 commit comments

Comments
 (0)