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

Commit 3e3be5e

Browse files
authored
[Impeller] Make IsEmpty methods on Rect and Size NaN-aware (#47725)
Removes unused or redundant overloads and fixes the IsEmpty method on Size to be both simpler (2 comparisons vs. 4) and NaN-aware. Rect automatically uses the new code via delegation to the Size object.
1 parent f8961d2 commit 3e3be5e

File tree

9 files changed

+104
-13
lines changed

9 files changed

+104
-13
lines changed

ci/licenses_golden/excluded_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
../../../flutter/impeller/geometry/geometry_unittests.cc
151151
../../../flutter/impeller/geometry/matrix_unittests.cc
152152
../../../flutter/impeller/geometry/rect_unittests.cc
153+
../../../flutter/impeller/geometry/size_unittests.cc
153154
../../../flutter/impeller/golden_tests/README.md
154155
../../../flutter/impeller/golden_tests_harvester/.dart_tool
155156
../../../flutter/impeller/golden_tests_harvester/.gitignore

impeller/core/texture_descriptor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ struct TextureDescriptor {
8383

8484
constexpr bool IsValid() const {
8585
return format != PixelFormat::kUnknown && //
86-
size.IsPositive() && //
86+
!size.IsEmpty() && //
8787
mip_count >= 1u && //
8888
SamplingOptionsAreValid();
8989
}

impeller/geometry/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impeller_component("geometry_unittests") {
6363
"geometry_unittests.cc",
6464
"matrix_unittests.cc",
6565
"rect_unittests.cc",
66+
"size_unittests.cc",
6667
]
6768

6869
deps = [

impeller/geometry/rect.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ struct TRect {
123123
return Union(o).size == size;
124124
}
125125

126-
constexpr bool IsZero() const { return size.IsZero(); }
127-
126+
/// Returns true if either of the width or height are 0, negative, or NaN.
128127
constexpr bool IsEmpty() const { return size.IsEmpty(); }
129128

130129
constexpr bool IsMaximum() const { return *this == MakeMaximum(); }

impeller/geometry/rect_unittests.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,46 @@ TEST(RectTest, RectMakeSize) {
5555
}
5656
}
5757

58+
TEST(SizeTest, RectIsEmpty) {
59+
auto nan = std::numeric_limits<Scalar>::quiet_NaN();
60+
61+
// Non-empty
62+
EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
63+
64+
// Empty both width and height both 0 or negative, in all combinations
65+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
66+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
67+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
68+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
69+
70+
// Empty for 0 or negative width or height (but not both at the same time)
71+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
72+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
73+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
74+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
75+
76+
// Empty for NaN in width or height or both
77+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
78+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
79+
EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
80+
}
81+
82+
TEST(SizeTest, IRectIsEmpty) {
83+
// Non-empty
84+
EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
85+
86+
// Empty both width and height both 0 or negative, in all combinations
87+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
88+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
89+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
90+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
91+
92+
// Empty for 0 or negative width or height (but not both at the same time)
93+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
94+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
95+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
96+
EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
97+
}
98+
5899
} // namespace testing
59100
} // namespace impeller

impeller/geometry/size.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,8 @@ struct TSize {
9696

9797
constexpr Type Area() const { return width * height; }
9898

99-
constexpr bool IsPositive() const { return width > 0 && height > 0; }
100-
101-
constexpr bool IsNegative() const { return width < 0 || height < 0; }
102-
103-
constexpr bool IsZero() const { return width == 0 || height == 0; }
104-
105-
constexpr bool IsEmpty() const { return IsNegative() || IsZero(); }
99+
/// Returns true if either of the width or height are 0, negative, or NaN.
100+
constexpr bool IsEmpty() const { return !(width > 0 && height > 0); }
106101

107102
template <class U>
108103
static constexpr TSize Ceil(const TSize<U>& other) {
@@ -112,7 +107,7 @@ struct TSize {
112107

113108
constexpr size_t MipCount() const {
114109
constexpr size_t minimum_mip = 1u;
115-
if (!IsPositive()) {
110+
if (IsEmpty()) {
116111
return minimum_mip;
117112
}
118113
size_t result = std::max(ceil(log2(width)), ceil(log2(height)));
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 "gtest/gtest.h"
6+
7+
#include "flutter/impeller/geometry/size.h"
8+
9+
namespace impeller {
10+
namespace testing {
11+
12+
TEST(SizeTest, SizeIsEmpty) {
13+
auto nan = std::numeric_limits<Scalar>::quiet_NaN();
14+
15+
// Non-empty
16+
EXPECT_FALSE(Size(10.5, 7.2).IsEmpty());
17+
18+
// Empty both width and height both 0 or negative, in all combinations
19+
EXPECT_TRUE(Size(0.0, 0.0).IsEmpty());
20+
EXPECT_TRUE(Size(-1.0, -1.0).IsEmpty());
21+
EXPECT_TRUE(Size(-1.0, 0.0).IsEmpty());
22+
EXPECT_TRUE(Size(0.0, -1.0).IsEmpty());
23+
24+
// Empty for 0 or negative width or height (but not both at the same time)
25+
EXPECT_TRUE(Size(10.5, 0.0).IsEmpty());
26+
EXPECT_TRUE(Size(10.5, -1.0).IsEmpty());
27+
EXPECT_TRUE(Size(0.0, 7.2).IsEmpty());
28+
EXPECT_TRUE(Size(-1.0, 7.2).IsEmpty());
29+
30+
// Empty for NaN in width or height or both
31+
EXPECT_TRUE(Size(10.5, nan).IsEmpty());
32+
EXPECT_TRUE(Size(nan, 7.2).IsEmpty());
33+
EXPECT_TRUE(Size(nan, nan).IsEmpty());
34+
}
35+
36+
TEST(SizeTest, ISizeIsEmpty) {
37+
// Non-empty
38+
EXPECT_FALSE(ISize(10, 7).IsEmpty());
39+
40+
// Empty both width and height both 0 or negative, in all combinations
41+
EXPECT_TRUE(ISize(0, 0).IsEmpty());
42+
EXPECT_TRUE(ISize(-1, -1).IsEmpty());
43+
EXPECT_TRUE(ISize(-1, 0).IsEmpty());
44+
EXPECT_TRUE(ISize(0, -1).IsEmpty());
45+
46+
// Empty for 0 or negative width or height (but not both at the same time)
47+
EXPECT_TRUE(ISize(10, 0).IsEmpty());
48+
EXPECT_TRUE(ISize(10, -1).IsEmpty());
49+
EXPECT_TRUE(ISize(0, 7).IsEmpty());
50+
EXPECT_TRUE(ISize(-1, 7).IsEmpty());
51+
}
52+
53+
} // namespace testing
54+
} // namespace impeller

impeller/image/decompressed_image.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ DecompressedImage::DecompressedImage(
1818
Format format,
1919
std::shared_ptr<const fml::Mapping> allocation)
2020
: size_(size), format_(format), allocation_(std::move(allocation)) {
21-
if (!allocation_ || !size.IsPositive() || format_ == Format::kInvalid) {
21+
if (!allocation_ || size.IsEmpty() || format_ == Format::kInvalid) {
2222
return;
2323
}
2424
is_valid_ = true;

impeller/renderer/snapshot.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ std::optional<Rect> Snapshot::GetCoverage() const {
1616
}
1717

1818
std::optional<Matrix> Snapshot::GetUVTransform() const {
19-
if (!texture || texture->GetSize().IsZero()) {
19+
if (!texture || texture->GetSize().IsEmpty()) {
2020
return std::nullopt;
2121
}
2222
return Matrix::MakeScale(1 / Vector2(texture->GetSize())) *

0 commit comments

Comments
 (0)