Fix rotations

Normalize rotations read from PDF documents. Make FPDFPage_GetRotation
always return a value 0 to 3 as specified in fpdf_edit.h instead of
returning the page rotation / 90 (page rotation may be negative for some
PDFs).

BUG=chromium:713197

Change-Id: Ie477803f7d298b777a3ace89b21cfda8b7f6808b
Reviewed-on: https://pdfium-review.googlesource.com/4532
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp
index 496ed7c..5ea575e 100644
--- a/core/fpdfapi/page/cpdf_page.cpp
+++ b/core/fpdfapi/page/cpdf_page.cpp
@@ -35,10 +35,7 @@
   CPDF_Object* pageAttr = GetPageAttr("Resources");
   m_pResources = pageAttr ? pageAttr->GetDict() : nullptr;
   m_pPageResources = m_pResources;
-  CPDF_Object* pRotate = GetPageAttr("Rotate");
-  int rotate = pRotate ? pRotate->GetInteger() / 90 % 4 : 0;
-  if (rotate < 0)
-    rotate += 4;
+  int rotate = GetPageRotation();
 
   CPDF_Array* pMediaBox = ToArray(GetPageAttr("MediaBox"));
   CFX_FloatRect mediabox;
@@ -176,6 +173,12 @@
   return matrix;
 }
 
+int CPDF_Page::GetPageRotation() const {
+  CPDF_Object* pRotate = GetPageAttr("Rotate");
+  int rotate = pRotate ? (pRotate->GetInteger() / 90) % 4 : 0;
+  return (rotate < 0) ? (rotate + 4) : rotate;
+}
+
 bool GraphicsData::operator<(const GraphicsData& other) const {
   if (fillAlpha != other.fillAlpha)
     return fillAlpha < other.fillAlpha;
diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h
index 076ab3f..b0dfa26 100644
--- a/core/fpdfapi/page/cpdf_page.h
+++ b/core/fpdfapi/page/cpdf_page.h
@@ -56,6 +56,7 @@
   float GetPageHeight() const { return m_PageHeight; }
   CFX_FloatRect GetPageBBox() const { return m_BBox; }
   const CFX_Matrix& GetPageMatrix() const { return m_PageMatrix; }
+  int GetPageRotation() const;
   CPDF_Object* GetPageAttr(const CFX_ByteString& name) const;
   CPDF_PageRenderCache* GetRenderCache() const { return m_pPageRender.get(); }
 
diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp
index 952564d..d62f5ca 100644
--- a/fpdfsdk/fpdfedit_embeddertest.cpp
+++ b/fpdfsdk/fpdfedit_embeddertest.cpp
@@ -694,3 +694,13 @@
   ASSERT_TRUE(widths_array);
   CheckCompositeFontWidths(widths_array, typed_font);
 }
+
+TEST_F(FPDFEditEmbeddertest, NormalizeNegativeRotation) {
+  // Load document with a -90 degree rotation
+  EXPECT_TRUE(OpenDocument("bug_713197.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  EXPECT_NE(nullptr, page);
+
+  EXPECT_EQ(3, FPDFPage_GetRotation(page));
+  UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index 511b7f5..739723f 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -133,20 +133,7 @@
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
   if (!IsPageObject(pPage))
     return -1;
-
-  CPDF_Dictionary* pDict = pPage->m_pFormDict;
-  while (pDict) {
-    if (pDict->KeyExist("Rotate")) {
-      CPDF_Object* pRotateObj = pDict->GetObjectFor("Rotate")->GetDirect();
-      return pRotateObj ? pRotateObj->GetInteger() / 90 : 0;
-    }
-    if (!pDict->KeyExist("Parent"))
-      break;
-
-    pDict = ToDictionary(pDict->GetObjectFor("Parent")->GetDirect());
-  }
-
-  return 0;
+  return pPage->GetPageRotation();
 }
 
 DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page,
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index 4fea392..c928ebe 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -740,19 +740,7 @@
                   static_cast<int>(mask_box.bottom * scale_y);
 
   // Get page rotation
-  int page_rotation = 0;
-  CPDF_Dictionary* pDict = pPage->m_pFormDict;
-  while (pDict) {
-    if (pDict->KeyExist("Rotate")) {
-      CPDF_Object* pRotateObj = pDict->GetObjectFor("Rotate")->GetDirect();
-      page_rotation = pRotateObj ? pRotateObj->GetInteger() / 90 : 0;
-      break;
-    }
-    if (!pDict->KeyExist("Parent"))
-      break;
-
-    pDict = ToDictionary(pDict->GetObjectFor("Parent")->GetDirect());
-  }
+  int page_rotation = pPage->GetPageRotation();
 
   // Compute offsets
   int offset_x = 0;
diff --git a/testing/resources/bug_713197.in b/testing/resources/bug_713197.in
new file mode 100644
index 0000000..49eaee2
--- /dev/null
+++ b/testing/resources/bug_713197.in
@@ -0,0 +1,27 @@
+{{header}}

+{{object 1 0}} <<

+  /Type /Catalog

+  /Pages 2 0 R

+>>

+endobj

+{{object 2 0}}<<

+  /Type /Pages

+  /MediaBox [0 0 600 800]

+  /Count 1

+  /Kids [ 3 0 R ]

+>>

+endobj

+{{object 3 0}}<<

+  /Type /Page

+  /Parent 2 0 R

+  /Resources <<>>

+  /Rotate -90

+>>

+endobj

+{{xref}}

+trailer <<

+  /Size 4

+  /Root 1 0 R

+>>

+{{startxref}}

+%%EOF

diff --git a/testing/resources/bug_713197.pdf b/testing/resources/bug_713197.pdf
new file mode 100644
index 0000000..571cde9
--- /dev/null
+++ b/testing/resources/bug_713197.pdf
@@ -0,0 +1,34 @@
+%PDF-1.7
+% ò¤ô

+1 0 obj <<

+  /Type /Catalog

+  /Pages 2 0 R

+>>

+endobj

+2 0 obj<<

+  /Type /Pages

+  /MediaBox [0 0 600 800]

+  /Count 1

+  /Kids [ 3 0 R ]

+>>

+endobj

+3 0 obj<<

+  /Type /Page

+  /Parent 2 0 R

+  /Resources <<>>

+  /Rotate -90

+>>

+endobj

+xref
+0 4
+0000000000 65535 f 
+0000000016 00000 n 
+0000000074 00000 n 
+0000000171 00000 n 
+trailer <<

+  /Size 4

+  /Root 1 0 R

+>>

+startxref
+260

+%%EOF