diff options
-rw-r--r-- | core/fpdfdoc/cpdf_dest.cpp | 26 | ||||
-rw-r--r-- | core/fpdfdoc/cpdf_dest.h | 4 | ||||
-rw-r--r-- | fpdfsdk/fpdfdoc.cpp | 24 | ||||
-rw-r--r-- | fpdfsdk/fpdfdoc_embeddertest.cpp | 59 | ||||
-rw-r--r-- | fpdfsdk/fpdfview_c_api_test.c | 1 | ||||
-rw-r--r-- | public/fpdf_doc.h | 27 |
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. // |