summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fpdfdoc/cpdf_dest.cpp26
-rw-r--r--core/fpdfdoc/cpdf_dest.h4
-rw-r--r--fpdfsdk/fpdfdoc.cpp24
-rw-r--r--fpdfsdk/fpdfdoc_embeddertest.cpp59
-rw-r--r--fpdfsdk/fpdfview_c_api_test.c1
-rw-r--r--public/fpdf_doc.h27
6 files changed, 137 insertions, 4 deletions
diff --git a/core/fpdfdoc/cpdf_dest.cpp b/core/fpdfdoc/cpdf_dest.cpp
index ebe3834e91..cb15bf1c33 100644
--- a/core/fpdfdoc/cpdf_dest.cpp
+++ b/core/fpdfdoc/cpdf_dest.cpp
@@ -6,6 +6,8 @@
#include "core/fpdfdoc/cpdf_dest.h"
+#include <algorithm>
+
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_name.h"
@@ -13,8 +15,14 @@
namespace {
-const char* const g_sZoomModes[] = {"XYZ", "Fit", "FitH", "FitV", "FitR",
- "FitB", "FitBH", "FitBV", nullptr};
+// These arrays are indexed by the PDFDEST_VIEW_* constants.
+
+// Last element is a sentinel.
+const char* const g_sZoomModes[] = {"Unknown", "XYZ", "Fit", "FitH",
+ "FitV", "FitR", "FitB", "FitBH",
+ "FitBV", nullptr};
+
+const int g_sZoomModeMaxParamCount[] = {0, 3, 0, 1, 1, 4, 0, 1, 1, 0};
} // namespace
@@ -66,9 +74,9 @@ int CPDF_Dest::GetZoomMode() {
return 0;
ByteString mode = pObj->GetString();
- for (int i = 0; g_sZoomModes[i]; ++i) {
+ for (int i = 1; g_sZoomModes[i]; ++i) {
if (mode == g_sZoomModes[i])
- return i + 1;
+ return i;
}
return 0;
@@ -121,6 +129,16 @@ bool CPDF_Dest::GetXYZ(bool* pHasX,
return true;
}
+unsigned int CPDF_Dest::GetNumParams() {
+ CPDF_Array* pArray = ToArray(m_pObj.Get());
+ if (!pArray || pArray->GetCount() < 2)
+ return 0;
+
+ size_t maxParamsForFitType = g_sZoomModeMaxParamCount[GetZoomMode()];
+ size_t numParamsInArray = pArray->GetCount() - 2;
+ return std::min(maxParamsForFitType, numParamsInArray);
+}
+
float CPDF_Dest::GetParam(int index) {
CPDF_Array* pArray = ToArray(m_pObj.Get());
return pArray ? pArray->GetNumberAt(2 + index) : 0;
diff --git a/core/fpdfdoc/cpdf_dest.h b/core/fpdfdoc/cpdf_dest.h
index 2836ebb471..4959901972 100644
--- a/core/fpdfdoc/cpdf_dest.h
+++ b/core/fpdfdoc/cpdf_dest.h
@@ -25,7 +25,11 @@ class CPDF_Dest {
ByteString GetRemoteName();
int GetPageIndex(CPDF_Document* pDoc);
uint32_t GetPageObjNum();
+
+ // Returns the zoom mode, as one of the PDFDEST_VIEW_* values in fpdf_doc.h.
int GetZoomMode();
+
+ unsigned int GetNumParams();
float GetParam(int index);
bool GetXYZ(bool* pHasX,
diff --git a/fpdfsdk/fpdfdoc.cpp b/fpdfsdk/fpdfdoc.cpp
index 4d2942fb31..51a1c61e77 100644
--- a/fpdfsdk/fpdfdoc.cpp
+++ b/fpdfsdk/fpdfdoc.cpp
@@ -210,6 +210,30 @@ FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST pDict) {
return dest.GetPageIndex(pDoc);
}
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFDest_GetView(FPDF_DOCUMENT document,
+ FPDF_DEST pDict,
+ unsigned long* outNumParams,
+ FS_FLOAT* outParams) {
+ if (!pDict) {
+ *outNumParams = 0;
+ return 0;
+ }
+
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc) {
+ *outNumParams = 0;
+ return 0;
+ }
+
+ CPDF_Dest dest(static_cast<CPDF_Array*>(pDict));
+
+ *outNumParams = dest.GetNumParams();
+ for (unsigned long i = 0; i < *outNumParams; ++i)
+ outParams[i] = dest.GetParam(i);
+ return dest.GetZoomMode();
+}
+
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFDest_GetLocationInPage(FPDF_DEST pDict,
FPDF_BOOL* hasXVal,
diff --git a/fpdfsdk/fpdfdoc_embeddertest.cpp b/fpdfsdk/fpdfdoc_embeddertest.cpp
index c691a17a11..24414a1c33 100644
--- a/fpdfsdk/fpdfdoc_embeddertest.cpp
+++ b/fpdfsdk/fpdfdoc_embeddertest.cpp
@@ -42,6 +42,65 @@ TEST_F(FPDFDocEmbeddertest, DestGetPageIndex) {
EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), dest));
}
+TEST_F(FPDFDocEmbeddertest, DestGetView) {
+ EXPECT_TRUE(OpenDocument("named_dests.pdf"));
+
+ unsigned long numParams;
+ FS_FLOAT params[4];
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_UNKNOWN_MODE),
+ FPDFDest_GetView(document(), nullptr, &numParams, params));
+ EXPECT_EQ(0U, numParams);
+ EXPECT_FLOAT_EQ(42.4242f, params[0]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
+ FPDFDest_GetView(document(), dest, &numParams, params));
+ EXPECT_EQ(3U, numParams);
+ EXPECT_FLOAT_EQ(0, params[0]);
+ EXPECT_FLOAT_EQ(0, params[1]);
+ EXPECT_FLOAT_EQ(1, params[2]);
+ EXPECT_FLOAT_EQ(42.4242f, params[3]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ dest = FPDF_GetNamedDestByName(document(), "Next");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_FIT),
+ FPDFDest_GetView(document(), dest, &numParams, params));
+ EXPECT_EQ(0U, numParams);
+ EXPECT_FLOAT_EQ(42.4242f, params[0]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
+ FPDFDest_GetView(document(), dest, &numParams, params));
+ EXPECT_EQ(3U, numParams);
+ EXPECT_FLOAT_EQ(200, params[0]);
+ EXPECT_FLOAT_EQ(400, params[1]);
+ EXPECT_FLOAT_EQ(800, params[2]);
+ EXPECT_FLOAT_EQ(42.4242f, params[3]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
+ FPDFDest_GetView(document(), dest, &numParams, params));
+ EXPECT_EQ(3U, numParams);
+ EXPECT_FLOAT_EQ(0, params[0]);
+ EXPECT_FLOAT_EQ(0, params[1]);
+ EXPECT_FLOAT_EQ(-200, params[2]);
+ EXPECT_FLOAT_EQ(42.4242f, params[3]);
+}
+
TEST_F(FPDFDocEmbeddertest, DestGetLocationInPage) {
EXPECT_TRUE(OpenDocument("named_dests.pdf"));
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index de4fa1c564..199c383ae5 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -107,6 +107,7 @@ int CheckPDFiumCApi() {
CHK(FPDFAction_GetURIPath);
CHK(FPDFDest_GetPageIndex);
CHK(FPDFDest_GetLocationInPage);
+ CHK(FPDFDest_GetView);
CHK(FPDFLink_GetLinkAtPoint);
CHK(FPDFLink_GetLinkZOrderAtPoint);
CHK(FPDFLink_GetDest);
diff --git a/public/fpdf_doc.h b/public/fpdf_doc.h
index 0f87361b38..93efa7ae98 100644
--- a/public/fpdf_doc.h
+++ b/public/fpdf_doc.h
@@ -25,6 +25,17 @@ extern "C" {
// Launch an application or open a file.
#define PDFACTION_LAUNCH 4
+// View destination fit types. See pdfmark reference v9, page 48.
+#define PDFDEST_VIEW_UNKNOWN_MODE 0
+#define PDFDEST_VIEW_XYZ 1
+#define PDFDEST_VIEW_FIT 2
+#define PDFDEST_VIEW_FITH 3
+#define PDFDEST_VIEW_FITV 4
+#define PDFDEST_VIEW_FITR 5
+#define PDFDEST_VIEW_FITB 6
+#define PDFDEST_VIEW_FITBH 7
+#define PDFDEST_VIEW_FITBV 8
+
typedef struct _FS_QUADPOINTSF {
FS_FLOAT x1;
FS_FLOAT y1;
@@ -175,6 +186,22 @@ FPDFAction_GetURIPath(FPDF_DOCUMENT document,
FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST dest);
+// Get the view (fit type) specified by |dest|.
+// Experimental API. Subject to change.
+//
+// document - handle to the document.
+// dest - handle to the destination.
+// outNumParams - buffer to write the number of view parameters.
+// outParams - buffer to write the view parameters. Must be at least 4
+// FS_FLOATs long.
+// Returns one of the PDFDEST_VIEW_* constants, PDFDEST_VIEW_UNKNOWN_MODE if
+// |dest| does not specify a view.
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFDest_GetView(FPDF_DOCUMENT document,
+ FPDF_DEST dest,
+ unsigned long* outNumParams,
+ FS_FLOAT* outParams);
+
// Get the (x, y, zoom) location of |dest| in the destination page, if the
// destination is in [page /XYZ x y zoom] syntax.
//