Avoid a case of float-int-float conversion in CPDF_Page

Currently, 2 CPDF_Page::GetDisplayMatrixForRect() callers do the
following:

1) Gets the page size as floats.
2) Constructs an int rectangle and passes that to
   GetDisplayMatrixForRect().
3) GetDisplayMatrixForRect() converts the int values back to float.

Add a GetDisplayMatrixForRect() variant that takes a float rectangle to
avoid the int conversion. For now, keep the new method private, and only
expose a GetDisplayMatrix() method, which is what those 2 callers
really want.

Bug: 413582795
Change-Id: Ifb616092bd4f498969388892102d1236019fe8c3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/132213
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp
index f62cd4f..0d56bfc 100644
--- a/core/fpdfapi/page/cpdf_page.cpp
+++ b/core/fpdfapi/page/cpdf_page.cpp
@@ -124,6 +124,11 @@
 
 CFX_Matrix CPDF_Page::GetDisplayMatrixForRect(const FX_RECT& rect,
                                               int rotation) const {
+  return GetDisplayMatrixForFloatRect(CFX_FloatRect(rect), rotation);
+}
+
+CFX_Matrix CPDF_Page::GetDisplayMatrixForFloatRect(const CFX_FloatRect& rect,
+                                                   int rotation) const {
   if (page_size_.width == 0 || page_size_.height == 0) {
     return CFX_Matrix();
   }
@@ -137,41 +142,40 @@
   // This code implicitly inverts the y-axis to account for page coordinates
   // pointing up and bitmap coordinates pointing down. (x0, y0) is the base
   // point, (x1, y1) is that point translated on y and (x2, y2) is the point
-  // translated on x. On rotation = 0, y0 is rect.bottom and the translation
-  // to get y1 is performed as negative. This results in the desired
-  // transformation.
+  // translated on x. On rotation = 0, y0 is rect.top and the translation to get
+  // y1 is performed as negative. This results in the desired transformation.
   switch (rotation % 4) {
     case 0:
       x0 = rect.left;
-      y0 = rect.bottom;
+      y0 = rect.top;
       x1 = rect.left;
-      y1 = rect.top;
+      y1 = rect.bottom;
       x2 = rect.right;
-      y2 = rect.bottom;
+      y2 = rect.top;
       break;
     case 1:
       x0 = rect.left;
-      y0 = rect.top;
+      y0 = rect.bottom;
+      x1 = rect.right;
+      y1 = rect.bottom;
+      x2 = rect.left;
+      y2 = rect.top;
+      break;
+    case 2:
+      x0 = rect.right;
+      y0 = rect.bottom;
       x1 = rect.right;
       y1 = rect.top;
       x2 = rect.left;
       y2 = rect.bottom;
       break;
-    case 2:
-      x0 = rect.right;
-      y0 = rect.top;
-      x1 = rect.right;
-      y1 = rect.bottom;
-      x2 = rect.left;
-      y2 = rect.top;
-      break;
     case 3:
       x0 = rect.right;
-      y0 = rect.bottom;
+      y0 = rect.top;
       x1 = rect.left;
-      y1 = rect.bottom;
+      y1 = rect.top;
       x2 = rect.right;
-      y2 = rect.top;
+      y2 = rect.bottom;
       break;
     default:
       CHECK_LT(rotation, 0);
@@ -185,6 +189,11 @@
   return page_matrix_ * matrix;
 }
 
+CFX_Matrix CPDF_Page::GetDisplayMatrix() const {
+  const CFX_FloatRect rect(0, 0, GetPageWidth(), GetPageHeight());
+  return GetDisplayMatrixForFloatRect(rect, 0);
+}
+
 int CPDF_Page::GetPageRotation() const {
   RetainPtr<const CPDF_Object> pRotate =
       GetPageAttr(pdfium::page_object::kRotate);
diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h
index 8b87b84..3421ad9 100644
--- a/core/fpdfapi/page/cpdf_page.h
+++ b/core/fpdfapi/page/cpdf_page.h
@@ -74,6 +74,7 @@
   void ParseContent();
   const CFX_SizeF& GetPageSize() const { return page_size_; }
   const CFX_Matrix& GetPageMatrix() const { return page_matrix_; }
+  CFX_Matrix GetDisplayMatrix() const;
   int GetPageRotation() const;
 
   RetainPtr<CPDF_Array> GetOrCreateAnnotsArray();
@@ -101,6 +102,8 @@
   RetainPtr<CPDF_Object> GetMutablePageAttr(ByteStringView name);
   RetainPtr<const CPDF_Object> GetPageAttr(ByteStringView name) const;
   CFX_FloatRect GetBox(ByteStringView name) const;
+  CFX_Matrix GetDisplayMatrixForFloatRect(const CFX_FloatRect& rect,
+                                          int rotation) const;
 
   CFX_SizeF page_size_;
   CFX_Matrix page_matrix_;
diff --git a/core/fpdftext/cpdf_textpage.cpp b/core/fpdftext/cpdf_textpage.cpp
index c1fde9d..9fb7d24 100644
--- a/core/fpdftext/cpdf_textpage.cpp
+++ b/core/fpdftext/cpdf_textpage.cpp
@@ -272,12 +272,6 @@
   return right <= left;
 }
 
-CFX_Matrix GetPageMatrix(const CPDF_Page* pPage) {
-  const FX_RECT rect(0, 0, static_cast<int>(pPage->GetPageWidth()),
-                     static_cast<int>(pPage->GetPageHeight()));
-  return pPage->GetDisplayMatrixForRect(rect, 0);
-}
-
 float GetFontSize(const CPDF_TextObject* text_object) {
   bool has_font = text_object && text_object->GetFont();
   return has_font ? text_object->GetFontSize() : kDefaultFontSize;
@@ -369,7 +363,7 @@
 CPDF_TextPage::CharInfo::~CharInfo() = default;
 
 CPDF_TextPage::CPDF_TextPage(const CPDF_Page* pPage, bool rtl)
-    : page_(pPage), rtl_(rtl), display_matrix_(GetPageMatrix(pPage)) {
+    : page_(pPage), rtl_(rtl), display_matrix_(page_->GetDisplayMatrix()) {
   Init();
 }
 
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 34abfae..efd9467 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -820,8 +820,7 @@
   }
   FX_RECT clip_rect = clipping_rect.ToFxRect();
 
-  const FX_RECT rect(0, 0, pPage->GetPageWidth(), pPage->GetPageHeight());
-  CFX_Matrix transform_matrix = pPage->GetDisplayMatrixForRect(rect, 0);
+  CFX_Matrix transform_matrix = pPage->GetDisplayMatrix();
   if (matrix) {
     transform_matrix *= CFXMatrixFromFSMatrix(*matrix);
   }