Make PSOP_ROUND round according to PLRM definiton
Add a function `RoundHalfUp()` to cpdf_psengine.cpp to handle rounding
according to the PLRM definition of half up rounding. Half up rounding
of a number `x` is defined as `floor(x + 0.5)`. Support rounding for
all floats, and not only floats within the range of INTs, as before.
This bug is related to pdfium:1314.
Bug: pdfium:1321
Change-Id: I1c071e8ac4bb718a08722159faee6326f82d17ed
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/56236
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_psengine.cpp b/core/fpdfapi/page/cpdf_psengine.cpp
index 7eb437b..98f5c47 100644
--- a/core/fpdfapi/page/cpdf_psengine.cpp
+++ b/core/fpdfapi/page/cpdf_psengine.cpp
@@ -7,6 +7,8 @@
#include "core/fpdfapi/page/cpdf_psengine.h"
#include <algorithm>
+#include <cmath>
+#include <limits>
#include <utility>
#include "core/fpdfapi/parser/cpdf_simple_parser.h"
@@ -67,6 +69,16 @@
{"xor", PSOP_XOR},
};
+// Round half up is a nearest integer round with half-way numbers always rounded
+// up. Example: -5.5 rounds to -5.
+float RoundHalfUp(float f) {
+ if (std::isnan(f))
+ return 0;
+ if (f > std::numeric_limits<float>::max() - 0.5f)
+ return std::numeric_limits<float>::max();
+ return floor(f + 0.5f);
+}
+
} // namespace
CPDF_PSOP::CPDF_PSOP()
@@ -262,7 +274,7 @@
break;
case PSOP_ROUND:
d1 = Pop();
- Push(FXSYS_round(d1));
+ Push(RoundHalfUp(d1));
break;
case PSOP_TRUNCATE:
i1 = PopInt();
diff --git a/core/fpdfapi/page/cpdf_psengine_unittest.cpp b/core/fpdfapi/page/cpdf_psengine_unittest.cpp
index babbb7f..03e096d 100644
--- a/core/fpdfapi/page/cpdf_psengine_unittest.cpp
+++ b/core/fpdfapi/page/cpdf_psengine_unittest.cpp
@@ -151,14 +151,18 @@
EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_ROUND));
// Smallest positive float value.
float min_float = std::numeric_limits<float>::min();
+ // Largest positive float value.
+ float max_float = std::numeric_limits<float>::max();
EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_ROUND));
EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_ROUND));
+ EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_ROUND));
+ EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_ROUND));
EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_ROUND));
EXPECT_FLOAT_EQ(4.0f, DoOperator1(&engine, 3.8f, PSOP_ROUND));
EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.5f, PSOP_ROUND));
EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_ROUND));
EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -3.8f, PSOP_ROUND));
- EXPECT_FLOAT_EQ(-6.0f, DoOperator1(&engine, -5.5f, PSOP_ROUND));
+ EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_ROUND));
}
TEST(CPDF_PSEngine, Truncate) {
diff --git a/testing/SUPPRESSIONS b/testing/SUPPRESSIONS
index c492ec5..fe49416 100644
--- a/testing/SUPPRESSIONS
+++ b/testing/SUPPRESSIONS
@@ -328,9 +328,6 @@
# TODO(pdfium:632): Remove after associated bug is fixed
bug_632.in * * *
-# TODO(pdfium:1321): Remove after associated bug is fixed
-bug_1321.in * * *
-
# xfa_specific
# TODO(pdfium:1107): Remove after associated bug is fixed