[FXCRT] Add unit tests for CFX_FloatRect::GetInnerRect()
There were none before, now there can be some. This exposes an issue at
the edges of the integer range, where a float larger than the maximum
value of a signed 32 bit integer returns a value of the maximum negative
integer.
Similar to the unexpected behavior uncovered during debugging of Windows
print imaging issue in crbug.com/1019026. This is the GetInnerRect()
equivalent to the change in [1].
[1] https://pdfium-review.googlesource.com/c/pdfium/+/62130
Change-Id: Ic711dc3d8ee3a52098e6dfb07f6ee4aaf364938c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/63335
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Alan Screen <awscreen@chromium.org>
diff --git a/core/fxcrt/fx_coordinates_unittest.cpp b/core/fxcrt/fx_coordinates_unittest.cpp
index 627c45d..eaf431b 100644
--- a/core/fxcrt/fx_coordinates_unittest.cpp
+++ b/core/fxcrt/fx_coordinates_unittest.cpp
@@ -9,6 +9,16 @@
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+constexpr float kMinFloat = std::numeric_limits<float>::min();
+constexpr int kMaxInt = std::numeric_limits<int>::max();
+constexpr int kMinInt = std::numeric_limits<int>::min();
+constexpr float kMinIntAsFloat = static_cast<float>(kMinInt);
+constexpr float kMaxIntAsFloat = static_cast<float>(kMaxInt);
+
+} // namespace
+
TEST(CFX_FloatRect, FromFXRect) {
FX_RECT downwards(10, 20, 30, 40);
CFX_FloatRect rect(downwards);
@@ -74,14 +84,63 @@
EXPECT_FLOAT_EQ(6.3f, rect.top);
}
+TEST(CFX_FloatRect, GetInnerRect) {
+ FX_RECT inner_rect;
+ CFX_FloatRect rect;
+
+ inner_rect = rect.GetInnerRect();
+ EXPECT_EQ(0, inner_rect.left);
+ EXPECT_EQ(0, inner_rect.bottom);
+ EXPECT_EQ(0, inner_rect.right);
+ EXPECT_EQ(0, inner_rect.top);
+
+ // Function converts from float to int using floor() for top and right, and
+ // ceil() for left and bottom.
+ rect = CFX_FloatRect(-1.1f, 3.6f, 4.4f, -5.7f);
+ inner_rect = rect.GetInnerRect();
+ EXPECT_EQ(-1, inner_rect.left);
+ EXPECT_EQ(4, inner_rect.bottom);
+ EXPECT_EQ(4, inner_rect.right);
+ EXPECT_EQ(-6, inner_rect.top);
+
+ rect = CFX_FloatRect(kMinFloat, kMinFloat, kMinFloat, kMinFloat);
+ inner_rect = rect.GetInnerRect();
+ EXPECT_EQ(0, inner_rect.left);
+ EXPECT_EQ(1, inner_rect.bottom);
+ EXPECT_EQ(1, inner_rect.right);
+ EXPECT_EQ(0, inner_rect.top);
+
+ rect = CFX_FloatRect(-kMinFloat, -kMinFloat, -kMinFloat, -kMinFloat);
+ inner_rect = rect.GetInnerRect();
+ EXPECT_EQ(-1, inner_rect.left);
+ EXPECT_EQ(0, inner_rect.bottom);
+ EXPECT_EQ(0, inner_rect.right);
+ EXPECT_EQ(-1, inner_rect.top);
+
+ // Check at limits of integer range. When saturated would expect to get values
+ // that are clamped to the limits of integers, but instead it is returning all
+ // negative values that represent a rectangle as a dot in a far reach of the
+ // negative coordinate space. Related to crbug.com/1019026
+ rect = CFX_FloatRect(kMinIntAsFloat, kMinIntAsFloat, kMaxIntAsFloat,
+ kMaxIntAsFloat);
+ inner_rect = rect.GetInnerRect();
+ EXPECT_EQ(kMinInt, inner_rect.left);
+ EXPECT_EQ(kMinInt, inner_rect.bottom); // should be |kMaxInt|
+ EXPECT_EQ(kMinInt, inner_rect.right); // should be |kMaxInt|
+ EXPECT_EQ(kMinInt, inner_rect.top);
+
+ rect = CFX_FloatRect(kMinIntAsFloat - 1.0f, kMinIntAsFloat - 1.0f,
+ kMaxIntAsFloat + 1.0f, kMaxIntAsFloat + 1.0f);
+ inner_rect = rect.GetInnerRect();
+ EXPECT_EQ(kMinInt, inner_rect.left);
+ EXPECT_EQ(kMinInt, inner_rect.bottom); // should be |kMaxInt|
+ EXPECT_EQ(kMinInt, inner_rect.right); // should be |kMaxInt|
+ EXPECT_EQ(kMinInt, inner_rect.top);
+}
+
TEST(CFX_FloatRect, GetOuterRect) {
FX_RECT outer_rect;
CFX_FloatRect rect;
- constexpr float kMinFloat = std::numeric_limits<float>::min();
- constexpr int kMaxInt = std::numeric_limits<int>::max();
- constexpr int kMinInt = std::numeric_limits<int>::min();
- constexpr float kMinIntAsFloat = static_cast<float>(kMinInt);
- constexpr float kMaxIntAsFloat = static_cast<float>(kMaxInt);
outer_rect = rect.GetOuterRect();
EXPECT_EQ(0, outer_rect.left);
@@ -89,8 +148,8 @@
EXPECT_EQ(0, outer_rect.right);
EXPECT_EQ(0, outer_rect.top);
- // Function converts from float to int using floor() for left and top, and
- // ceil() for right and bottom.
+ // Function converts from float to int using floor() for left and bottom, and
+ // ceil() for right and top.
rect = CFX_FloatRect(-1.1f, 3.6f, 4.4f, -5.7f);
outer_rect = rect.GetOuterRect();
EXPECT_EQ(-2, outer_rect.left);