Add functions to get/set ArtBox.

There are PDFs that use ArtBox.  In some use cases, user may scale
a page, scale up/down MediaBox and CropBox.  So if ArtBox exists,
it needs to be scaled as well.

Bug:409670
Change-Id: I78ac7afa66942352277f856514bdd9b15dda270b
Reviewed-on: https://pdfium-review.googlesource.com/c/43931
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Shirleen Lou <xlou@chromium.org>
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index d1f7fce..7595086 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -80,6 +80,15 @@
                  CFX_FloatRect(left, bottom, right, top));
 }
 
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetArtBox(FPDF_PAGE page,
+                                                  float left,
+                                                  float bottom,
+                                                  float right,
+                                                  float top) {
+  SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kArtBox,
+                 CFX_FloatRect(left, bottom, right, top));
+}
+
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetMediaBox(FPDF_PAGE page,
                                                          float* left,
                                                          float* bottom,
@@ -100,6 +109,15 @@
                         top);
 }
 
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetArtBox(FPDF_PAGE page,
+                                                       float* left,
+                                                       float* bottom,
+                                                       float* right,
+                                                       float* top) {
+  return GetBoundingBox(CPDFPageFromFPDFPage(page),
+                        pdfium::page_object::kArtBox, left, bottom, right, top);
+}
+
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
 FPDFPage_TransFormWithClip(FPDF_PAGE page,
                            FS_MATRIX* matrix,
diff --git a/fpdfsdk/fpdf_transformpage_embeddertest.cpp b/fpdfsdk/fpdf_transformpage_embeddertest.cpp
index 0a8e3e7..3904b0c 100644
--- a/fpdfsdk/fpdf_transformpage_embeddertest.cpp
+++ b/fpdfsdk/fpdf_transformpage_embeddertest.cpp
@@ -37,6 +37,17 @@
     EXPECT_EQ(150, cropbox_right);
     EXPECT_EQ(150, cropbox_top);
 
+    float artbox_left;
+    float artbox_bottom;
+    float artbox_right;
+    float artbox_top;
+    EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox_left, &artbox_bottom,
+                                   &artbox_right, &artbox_top));
+    EXPECT_EQ(50, artbox_left);
+    EXPECT_EQ(60, artbox_bottom);
+    EXPECT_EQ(135, artbox_right);
+    EXPECT_EQ(140, artbox_top);
+
     UnloadPage(page);
   }
 
@@ -76,6 +87,17 @@
                                      &cropbox_right, nullptr));
     EXPECT_FALSE(FPDFPage_GetCropBox(page, nullptr, nullptr, nullptr, nullptr));
 
+    float artbox_left;
+    float artbox_bottom;
+    float artbox_right;
+    float artbox_top;
+    EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox_left, &artbox_bottom,
+                                   &artbox_right, &artbox_top));
+    EXPECT_EQ(140, artbox_left);
+    EXPECT_EQ(145, artbox_bottom);
+    EXPECT_EQ(65, artbox_right);
+    EXPECT_EQ(70, artbox_top);
+
     UnloadPage(page);
   }
 }
@@ -120,3 +142,23 @@
   FPDF_DestroyClipPath(clip);
   UnloadPage(page);
 }
+
+TEST_F(FPDFTransformEmbedderTest, NoArtBox) {
+  ASSERT_TRUE(OpenDocument("hello_world.pdf"));
+  ASSERT_EQ(1, FPDF_GetPageCount(document()));
+
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+
+  float left = -1.0f;
+  float bottom = -1.0f;
+  float right = 3.0f;
+  float top = 0.0f;
+  EXPECT_FALSE(FPDFPage_GetArtBox(page, &left, &bottom, &right, &top));
+  EXPECT_EQ(-1.0f, left);
+  EXPECT_EQ(-1.0f, bottom);
+  EXPECT_EQ(3.0f, right);
+  EXPECT_EQ(0.0f, top);
+
+  UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 0fc28c3..3aa40ca 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -332,9 +332,11 @@
 
     // fpdf_transformpage.h
     CHK(FPDFPageObj_TransformClipPath);
+    CHK(FPDFPage_GetArtBox);
     CHK(FPDFPage_GetCropBox);
     CHK(FPDFPage_GetMediaBox);
     CHK(FPDFPage_InsertClipPath);
+    CHK(FPDFPage_SetArtBox);
     CHK(FPDFPage_SetCropBox);
     CHK(FPDFPage_SetMediaBox);
     CHK(FPDFPage_TransFormWithClip);
diff --git a/public/fpdf_transformpage.h b/public/fpdf_transformpage.h
index 742da49..c1abe76 100644
--- a/public/fpdf_transformpage.h
+++ b/public/fpdf_transformpage.h
@@ -45,6 +45,21 @@
                                                    float top);
 
 /**
+ * Set "ArtBox" entry to the page dictionary.
+ *
+ * page   - Handle to a page.
+ * left   - The left of the rectangle.
+ * bottom - The bottom of the rectangle.
+ * right  - The right of the rectangle.
+ * top    - The top of the rectangle.
+ */
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetArtBox(FPDF_PAGE page,
+                                                  float left,
+                                                  float bottom,
+                                                  float right,
+                                                  float top);
+
+/**
  * Get "MediaBox" entry from the page dictionary.
  *
  * page   - Handle to a page.
@@ -81,6 +96,24 @@
                                                         float* top);
 
 /**
+ * Get "ArtBox" entry from the page dictionary.
+ *
+ * page   - Handle to a page.
+ * left   - Pointer to a float value receiving the left of the rectangle.
+ * bottom - Pointer to a float value receiving the bottom of the rectangle.
+ * right  - Pointer to a float value receiving the right of the rectangle.
+ * top    - Pointer to a float value receiving the top of the rectangle.
+ *
+ * On success, return true and write to the out parameters. Otherwise return
+ * false and leave the out parameters unmodified.
+ */
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetArtBox(FPDF_PAGE page,
+                                                       float* left,
+                                                       float* bottom,
+                                                       float* right,
+                                                       float* top);
+
+/**
  * Apply transforms to |page|.
  *
  * If |matrix| is provided it will be applied to transform the page.
diff --git a/testing/resources/cropped_text.in b/testing/resources/cropped_text.in
index c8632de..d3812dc 100644
--- a/testing/resources/cropped_text.in
+++ b/testing/resources/cropped_text.in
@@ -41,6 +41,7 @@
   /Parent 2 0 R
   /MediaBox [ 0 0 200 200 ]
   /CropBox [ 50 50 150 150 ]
+  /ArtBox [ 55 65 140 145 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -55,6 +56,7 @@
   /Parent 2 0 R
   /MediaBox [ -50 -50 200 200 ]
   /CropBox [ 50 50 150 150 ]
+  /ArtBox [ 50 60 135 140 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -69,6 +71,7 @@
   /Parent 2 0 R
   /MediaBox [ 0 0 200 200 ]
   /CropBox [ 60 60 150 150 ]
+  /ArtBox [ 65 75 140 148 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -83,6 +86,7 @@
   /Parent 2 0 R
   /MediaBox [ 0 0 200 200 ]
   /CropBox [ 150 150 60 60 ]
+  /ArtBox [ 140 145 65 70 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
diff --git a/testing/resources/cropped_text.pdf b/testing/resources/cropped_text.pdf
index 02d50c6..676d44b 100644
--- a/testing/resources/cropped_text.pdf
+++ b/testing/resources/cropped_text.pdf
@@ -42,6 +42,7 @@
   /Parent 2 0 R
   /MediaBox [ 0 0 200 200 ]
   /CropBox [ 50 50 150 150 ]
+  /ArtBox [ 55 65 140 145 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -56,6 +57,7 @@
   /Parent 2 0 R
   /MediaBox [ -50 -50 200 200 ]
   /CropBox [ 50 50 150 150 ]
+  /ArtBox [ 50 60 135 140 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -70,6 +72,7 @@
   /Parent 2 0 R
   /MediaBox [ 0 0 200 200 ]
   /CropBox [ 60 60 150 150 ]
+  /ArtBox [ 65 75 140 148 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -84,6 +87,7 @@
   /Parent 2 0 R
   /MediaBox [ 0 0 200 200 ]
   /CropBox [ 150 150 60 60 ]
+  /ArtBox [ 140 145 65 70 ]
   /Resources <<
     /Font <<
       /F1 3 0 R
@@ -102,13 +106,13 @@
 0000000229 00000 n 
 0000000305 00000 n 
 0000000439 00000 n 
-0000000638 00000 n 
-0000000841 00000 n 
-0000001040 00000 n 
+0000000666 00000 n 
+0000000897 00000 n 
+0000001124 00000 n 
 trailer <<
   /Root 1 0 R
   /Size 10
 >>
 startxref
-1239
+1351
 %%EOF