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