Create content mark APIs to get values by key.

Bug: pdfium:1037
Change-Id: Ie887c0bbf3e543676adec6d8411b0b3254677d3c
Reviewed-on: https://pdfium-review.googlesource.com/37170
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: Henrique Nakashima <hnakashima@chromium.org>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 445b0cc..a490162 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -573,6 +573,12 @@
                   FPDFPageObjMark_GetParamValueType(mark, 0));
         int square_root = FPDFPageObjMark_GetParamIntValue(mark, 0);
         EXPECT_EQ(i + 1, square_root * square_root);
+
+        EXPECT_EQ(FPDF_OBJECT_NUMBER,
+                  FPDFPageObjMark_GetParamValueTypeByKey(mark, "Factor"));
+        EXPECT_TRUE(FPDFPageObjMark_GetParamIntValueByKey(mark, "Factor",
+                                                          &square_root));
+        EXPECT_EQ(i + 1, square_root * square_root);
       } else if (name == L"GreaterThanTen") {
         greater_than_ten_count++;
         EXPECT_EQ(0, FPDFPageObjMark_CountParams(mark));
@@ -590,6 +596,15 @@
             GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
         EXPECT_EQ(L"Last", value);
         EXPECT_EQ(18, i);
+
+        EXPECT_EQ(FPDF_OBJECT_STRING,
+                  FPDFPageObjMark_GetParamValueTypeByKey(mark, "Position"));
+        unsigned long length;
+        EXPECT_TRUE(FPDFPageObjMark_GetParamStringValueByKey(
+            mark, "Position", buffer, 256, &length));
+        ASSERT_GT(length, 0u);
+        value = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
+        EXPECT_EQ(L"Last", value);
       } else {
         FAIL();
       }
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index d21b215..d275559 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -99,15 +99,19 @@
   }
 }
 
-const std::pair<const ByteString, std::unique_ptr<CPDF_Object>>*
-GetMarkParamPairAtIndex(FPDF_PAGEOBJECTMARK mark, unsigned long index) {
+const CPDF_Dictionary* GetMarkParamDict(FPDF_PAGEOBJECTMARK mark) {
   if (!mark)
     return nullptr;
 
   const CPDF_ContentMarkItem* pMarkItem =
       CPDFContentMarkItemFromFPDFPageObjectMark(mark);
 
-  const CPDF_Dictionary* pParams = pMarkItem->GetParam();
+  return pMarkItem->GetParam();
+}
+
+const std::pair<const ByteString, std::unique_ptr<CPDF_Object>>*
+GetMarkParamPairAtIndex(FPDF_PAGEOBJECTMARK mark, unsigned long index) {
+  const CPDF_Dictionary* pParams = GetMarkParamDict(mark);
   if (!pParams)
     return nullptr;
 
@@ -345,6 +349,20 @@
   return param_pair->second->GetType();
 }
 
+FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
+FPDFPageObjMark_GetParamValueTypeByKey(FPDF_PAGEOBJECTMARK mark,
+                                       FPDF_BYTESTRING key) {
+  const CPDF_Dictionary* pParams = GetMarkParamDict(mark);
+  if (!pParams)
+    return FPDF_OBJECT_UNKNOWN;
+
+  const CPDF_Object* pObject = pParams->GetObjectFor(key);
+  if (!pObject)
+    return FPDF_OBJECT_UNKNOWN;
+
+  return pObject->GetType();
+}
+
 FPDF_EXPORT int FPDF_CALLCONV
 FPDFPageObjMark_GetParamIntValue(FPDF_PAGEOBJECTMARK mark,
                                  unsigned long index) {
@@ -355,6 +373,22 @@
   return param_pair->second->GetInteger();
 }
 
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPageObjMark_GetParamIntValueByKey(FPDF_PAGEOBJECTMARK mark,
+                                      FPDF_BYTESTRING key,
+                                      int* out_value) {
+  const CPDF_Dictionary* pParams = GetMarkParamDict(mark);
+  if (!pParams)
+    return false;
+
+  const CPDF_Object* pObj = pParams->GetObjectFor(key);
+  if (!pObj || !pObj->IsNumber())
+    return false;
+
+  *out_value = pObj->GetInteger();
+  return true;
+}
+
 FPDF_EXPORT unsigned long FPDF_CALLCONV
 FPDFPageObjMark_GetParamStringValue(FPDF_PAGEOBJECTMARK mark,
                                     unsigned long index,
@@ -370,6 +404,25 @@
 }
 
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPageObjMark_GetParamStringValueByKey(FPDF_PAGEOBJECTMARK mark,
+                                         FPDF_BYTESTRING key,
+                                         void* buffer,
+                                         unsigned long buflen,
+                                         unsigned long* out_buflen) {
+  const CPDF_Dictionary* pParams = GetMarkParamDict(mark);
+  if (!pParams)
+    return false;
+
+  const CPDF_Object* pObj = pParams->GetObjectFor(key);
+  if (!pObj || !pObj->IsString())
+    return false;
+
+  *out_buflen = Utf16EncodeMaybeCopyAndReturnLength(
+      WideString::FromUTF8(pObj->GetString().AsStringView()), buffer, buflen);
+  return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
 FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) {
   if (!pageObject)
     return false;
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 1837b58..51b5884 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -139,9 +139,12 @@
     CHK(FPDFPageObjMark_CountParams);
     CHK(FPDFPageObjMark_GetName);
     CHK(FPDFPageObjMark_GetParamIntValue);
+    CHK(FPDFPageObjMark_GetParamIntValueByKey);
     CHK(FPDFPageObjMark_GetParamKey);
     CHK(FPDFPageObjMark_GetParamStringValue);
+    CHK(FPDFPageObjMark_GetParamStringValueByKey);
     CHK(FPDFPageObjMark_GetParamValueType);
+    CHK(FPDFPageObjMark_GetParamValueTypeByKey);
     CHK(FPDFPageObj_CountMarks);
     CHK(FPDFPageObj_CreateNewPath);
     CHK(FPDFPageObj_CreateNewRect);
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 6490c18..380a0a2 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -368,7 +368,18 @@
                                   unsigned long index);
 
 // Experimental API.
-// Get the value of an int property in a content mark.
+// Get the type of the value of a property in a content mark by key.
+//
+//   mark   - handle to a content mark.
+//   key    - string key of the property.
+//
+// Returns the type of the value, or FPDF_OBJECT_UNKNOWN in case of failure.
+FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
+FPDFPageObjMark_GetParamValueTypeByKey(FPDF_PAGEOBJECTMARK mark,
+                                       FPDF_BYTESTRING key);
+
+// Experimental API.
+// Get the value of a number property in a content mark as int.
 // FPDFPageObjMark_GetParamValueType() should have returned FPDF_OBJECT_NUMBER
 // for this property.
 //
@@ -380,12 +391,28 @@
 FPDFPageObjMark_GetParamIntValue(FPDF_PAGEOBJECTMARK mark, unsigned long index);
 
 // Experimental API.
+// Get the value of a number property in a content mark by key as int.
+// FPDFPageObjMark_GetParamValueType() should have returned FPDF_OBJECT_NUMBER
+// for this property.
+//
+//   mark      - handle to a content mark.
+//   key       - string key of the property.
+//   out_value - pointer to variable that will receive the value. Not filled if
+//               false is returned.
+//
+// Returns TRUE if the key maps to a number value, FALSE otherwise.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPageObjMark_GetParamIntValueByKey(FPDF_PAGEOBJECTMARK mark,
+                                      FPDF_BYTESTRING key,
+                                      int* out_value);
+
+// Experimental API.
 // Get the value of a string property in a content mark.
-// |buffer| is only modified if |buflen| is longer than the length of the key.
+// |buffer| is only modified if |buflen| is longer than the length of the value.
 //
 //   mark   - handle to a content mark.
 //   index  - index of the property.
-//   buffer - buffer for holding the returned key in UTF16-LE.
+//   buffer - buffer for holding the returned value in UTF16-LE.
 //   buflen - length of the buffer.
 //
 // Returns the length of the value.
@@ -395,6 +422,25 @@
                                     void* buffer,
                                     unsigned long buflen);
 
+// Experimental API.
+// Get the value of a string property in a content mark by key.
+// |buffer| is only modified if |buflen| is longer than the length of the value.
+//
+//   mark       - handle to a content mark.
+//   key        - string key of the property.
+//   buffer     - buffer for holding the returned value in UTF16-LE.
+//   buflen     - length of the buffer.
+//   out_buflen - pointer to variable that will receive the length of the value.
+//                Not filled if false is returned.
+//
+// Returns TRUE if the key maps to a string value, FALSE otherwise.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPageObjMark_GetParamStringValueByKey(FPDF_PAGEOBJECTMARK mark,
+                                         FPDF_BYTESTRING key,
+                                         void* buffer,
+                                         unsigned long buflen,
+                                         unsigned long* out_buflen);
+
 // Load an image from a JPEG image file and then set it into |image_object|.
 //
 //   pages        - pointer to the start of all loaded pages, may be NULL.