summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthestig <thestig@chromium.org>2016-11-04 16:07:25 -0700
committerCommit bot <commit-bot@chromium.org>2016-11-04 16:07:25 -0700
commit04bebfe590d6d27a825b881fd234e31501843edc (patch)
tree127477b084005457579c599b2ec9eef0668a1479
parent931d087b991a986cc8bfa72131fe8eda0d987fc4 (diff)
downloadpdfium-04bebfe590d6d27a825b881fd234e31501843edc.tar.xz
Implement FPDF_VIEWERREF_GetName() API.chromium/2910
This is a generic API function to retrieve any viewer preference of type name. BUG=pdfium:414 Review-Url: https://codereview.chromium.org/2475923003
-rw-r--r--core/fpdfdoc/cpdf_viewerpreferences.cpp16
-rw-r--r--core/fpdfdoc/cpdf_viewerpreferences.h5
-rw-r--r--fpdfsdk/fpdfview.cpp19
-rw-r--r--fpdfsdk/fpdfview_c_api_test.c1
-rw-r--r--fpdfsdk/fpdfview_embeddertest.cpp48
-rw-r--r--public/fpdf_doc.h2
-rw-r--r--public/fpdfview.h19
-rw-r--r--testing/resources/viewer_ref.in57
-rw-r--r--testing/resources/viewer_ref.pdf82
9 files changed, 247 insertions, 2 deletions
diff --git a/core/fpdfdoc/cpdf_viewerpreferences.cpp b/core/fpdfdoc/cpdf_viewerpreferences.cpp
index 799f2d5814..f1fc4b0347 100644
--- a/core/fpdfdoc/cpdf_viewerpreferences.cpp
+++ b/core/fpdfdoc/cpdf_viewerpreferences.cpp
@@ -7,6 +7,7 @@
#include "core/fpdfdoc/cpdf_viewerpreferences.h"
#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/parser/cpdf_name.h"
CPDF_ViewerPreferences::CPDF_ViewerPreferences(CPDF_Document* pDoc)
: m_pDoc(pDoc) {}
@@ -38,6 +39,21 @@ CFX_ByteString CPDF_ViewerPreferences::Duplex() const {
return pDict ? pDict->GetStringFor("Duplex") : CFX_ByteString("None");
}
+bool CPDF_ViewerPreferences::GenericName(const CFX_ByteString& bsKey,
+ CFX_ByteString* bsVal) const {
+ ASSERT(bsVal);
+ CPDF_Dictionary* pDict = GetViewerPreferences();
+ if (!pDict)
+ return false;
+
+ const CPDF_Name* pName = ToName(pDict->GetObjectFor(bsKey));
+ if (!pName)
+ return false;
+
+ *bsVal = pName->GetString();
+ return true;
+}
+
CPDF_Dictionary* CPDF_ViewerPreferences::GetViewerPreferences() const {
CPDF_Dictionary* pDict = m_pDoc->GetRoot();
return pDict ? pDict->GetDictFor("ViewerPreferences") : nullptr;
diff --git a/core/fpdfdoc/cpdf_viewerpreferences.h b/core/fpdfdoc/cpdf_viewerpreferences.h
index c64292d9f9..c7e9112380 100644
--- a/core/fpdfdoc/cpdf_viewerpreferences.h
+++ b/core/fpdfdoc/cpdf_viewerpreferences.h
@@ -25,6 +25,11 @@ class CPDF_ViewerPreferences {
CPDF_Array* PrintPageRange() const;
CFX_ByteString Duplex() const;
+ // Gets the entry for |bsKey|. If the entry exists and it is of type name,
+ // then this method writes the value into |bsVal| and returns true. Otherwise
+ // returns false and |bsVal| is untouched. |bsVal| must not be NULL.
+ bool GenericName(const CFX_ByteString& bsKey, CFX_ByteString* bsVal) const;
+
private:
CPDF_Dictionary* GetViewerPreferences() const;
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index cde15dff9b..9142dc78c9 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -942,6 +942,25 @@ FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
return DuplexUndefined;
}
+DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
+ FPDF_BYTESTRING key,
+ char* buffer,
+ unsigned long length) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return 0;
+
+ CPDF_ViewerPreferences viewRef(pDoc);
+ CFX_ByteString bsVal;
+ if (!viewRef.GenericName(key, &bsVal))
+ return 0;
+
+ unsigned long dwStringLen = bsVal.GetLength() + 1;
+ if (buffer && length >= dwStringLen)
+ memcpy(buffer, bsVal.c_str(), dwStringLen);
+ return dwStringLen;
+}
+
DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index 2f0cb49fc2..4847180e46 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -228,6 +228,7 @@ int CheckPDFiumCApi() {
CHK(FPDF_VIEWERREF_GetNumCopies);
CHK(FPDF_VIEWERREF_GetPrintPageRange);
CHK(FPDF_VIEWERREF_GetDuplex);
+ CHK(FPDF_VIEWERREF_GetName);
CHK(FPDF_CountNamedDests);
CHK(FPDF_GetNamedDestByName);
CHK(FPDF_GetNamedDest);
diff --git a/fpdfsdk/fpdfview_embeddertest.cpp b/fpdfsdk/fpdfview_embeddertest.cpp
index 820d496bdc..e712edb89a 100644
--- a/fpdfsdk/fpdfview_embeddertest.cpp
+++ b/fpdfsdk/fpdfview_embeddertest.cpp
@@ -56,6 +56,10 @@ TEST_F(FPDFViewEmbeddertest, EmptyDocument) {
EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document()));
EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
+ char buf[100];
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", nullptr, 0));
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", buf, sizeof(buf)));
+
EXPECT_EQ(0u, FPDF_CountNamedDests(document()));
}
@@ -69,11 +73,53 @@ TEST_F(FPDFViewEmbeddertest, Page) {
EXPECT_EQ(nullptr, LoadPage(1));
}
-TEST_F(FPDFViewEmbeddertest, ViewerRef) {
+TEST_F(FPDFViewEmbeddertest, ViewerRefDummy) {
EXPECT_TRUE(OpenDocument("about_blank.pdf"));
EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document()));
EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
+
+ char buf[100];
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", nullptr, 0));
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", buf, sizeof(buf)));
+}
+
+TEST_F(FPDFViewEmbeddertest, ViewerRef) {
+ EXPECT_TRUE(OpenDocument("viewer_ref.pdf"));
+ EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
+ EXPECT_EQ(5, FPDF_VIEWERREF_GetNumCopies(document()));
+ EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
+
+ // Test some corner cases.
+ char buf[100];
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "", buf, sizeof(buf)));
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", nullptr, 0));
+ EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", buf, sizeof(buf)));
+
+ // Make sure |buf| does not get written into when it appears to be too small.
+ strcpy(buf, "ABCD");
+ EXPECT_EQ(4U, FPDF_VIEWERREF_GetName(document(), "Foo", buf, 1));
+ EXPECT_STREQ("ABCD", buf);
+
+ // Note "Foo" is a different key from "foo".
+ EXPECT_EQ(4U,
+ FPDF_VIEWERREF_GetName(document(), "Foo", nullptr, sizeof(buf)));
+ ASSERT_EQ(4U, FPDF_VIEWERREF_GetName(document(), "Foo", buf, sizeof(buf)));
+ EXPECT_STREQ("foo", buf);
+
+ // Try to retrieve a boolean and an integer.
+ EXPECT_EQ(
+ 0U, FPDF_VIEWERREF_GetName(document(), "HideToolbar", buf, sizeof(buf)));
+ EXPECT_EQ(0U,
+ FPDF_VIEWERREF_GetName(document(), "NumCopies", buf, sizeof(buf)));
+
+ // Try more valid cases.
+ ASSERT_EQ(4U,
+ FPDF_VIEWERREF_GetName(document(), "Direction", buf, sizeof(buf)));
+ EXPECT_STREQ("R2L", buf);
+ ASSERT_EQ(8U,
+ FPDF_VIEWERREF_GetName(document(), "ViewArea", buf, sizeof(buf)));
+ EXPECT_STREQ("CropBox", buf);
}
TEST_F(FPDFViewEmbeddertest, NamedDests) {
diff --git a/public/fpdf_doc.h b/public/fpdf_doc.h
index 0b78743259..c3be0e0598 100644
--- a/public/fpdf_doc.h
+++ b/public/fpdf_doc.h
@@ -271,7 +271,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot,
// Returns the number of bytes in the title, including trailing zeros.
//
// The |buffer| is always encoded in UTF-16LE. The |buffer| is followed by two
-// bytes of zeros indicating the end of the string. If |buflen| is less then
+// bytes of zeros indicating the end of the string. If |buflen| is less than
// the returned length, or |buffer| is NULL, |buffer| will not be modified.
DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT doc,
FPDF_BYTESTRING tag,
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 499124d6e8..469053c4e8 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -914,6 +914,25 @@ FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document);
DLLEXPORT FPDF_DUPLEXTYPE STDCALL
FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document);
+// Function: FPDF_VIEWERREF_GetName
+// Gets the contents for a viewer ref, with a given key. The value must
+// be of type "name".
+// Parameters:
+// document - Handle to the loaded document.
+// key - Name of the key in the viewer pref dictionary.
+// buffer - A string to write the contents of the key to.
+// length - Length of the buffer.
+// Return value:
+// The number of bytes in the contents, including the NULL terminator.
+// Thus if the return value is 0, then that indicates an error, such
+// as when |document| is invalid or |buffer| is NULL. If |length| is
+// less than the returned length, or |buffer| is NULL, |buffer| will
+// not be modified.
+DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
+ FPDF_BYTESTRING key,
+ char* buffer,
+ unsigned long length);
+
// Function: FPDF_CountNamedDests
// Get the count of named destinations in the PDF document.
// Parameters:
diff --git a/testing/resources/viewer_ref.in b/testing/resources/viewer_ref.in
new file mode 100644
index 0000000000..62ae372dfe
--- /dev/null
+++ b/testing/resources/viewer_ref.in
@@ -0,0 +1,57 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /ViewerPreferences <<
+ /Foo /foo
+ /HideToolbar true
+ /Direction /R2L
+ /ViewArea /CropBox
+ /NumCopies 5
+ >>
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+>>
+endobj
+% Page number 0.
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <</F1 15 0 R>>
+ >>
+ /Contents [21 0 R]
+ /MediaBox [0 0 612 792]
+>>
+endobj
+% Font resource.
+{{object 15 0}} <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Arial
+>>
+endobj
+% Content for page 0.
+{{object 21 0}} <<
+ /Length 0
+>>
+stream
+BT
+/F1 20 Tf
+100 600 TD (Page1)Tj
+ET
+endstream
+endobj
+{{xref}}
+trailer <<
+ /Size 6
+ /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/viewer_ref.pdf b/testing/resources/viewer_ref.pdf
new file mode 100644
index 0000000000..fb72107b5b
--- /dev/null
+++ b/testing/resources/viewer_ref.pdf
@@ -0,0 +1,82 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /ViewerPreferences <<
+ /Foo /foo
+ /HideToolbar true
+ /Direction /R2L
+ /ViewArea /CropBox
+ /NumCopies 5
+ >>
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+>>
+endobj
+% Page number 0.
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <</F1 15 0 R>>
+ >>
+ /Contents [21 0 R]
+ /MediaBox [0 0 612 792]
+>>
+endobj
+% Font resource.
+15 0 obj <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Arial
+>>
+endobj
+% Content for page 0.
+21 0 obj <<
+ /Length 0
+>>
+stream
+BT
+/F1 20 Tf
+100 600 TD (Page1)Tj
+ET
+endstream
+endobj
+xref
+0 22
+0000000000 65535 f
+0000000015 00000 n
+0000000193 00000 n
+0000000281 00000 n
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000442 00000 n
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000537 00000 n
+trailer <<
+ /Size 6
+ /Root 1 0 R
+>>
+startxref
+625
+%%EOF