blob: 2c3d1afdd788652ec0664d5e6eb005d0a88dd9dc [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Tom Sepez1ed8a212015-05-11 15:25:39 -07007#include "../../public/fpdf_doc.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07008#include "../include/fsdk_define.h"
Bo Xufdc00a72014-10-28 23:03:33 -07009#include "../include/fpdfxfa/fpdfxfa_doc.h"
10#include "../include/fpdfxfa/fpdfxfa_page.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070011
Bo Xu5d9acf82015-01-05 12:39:36 -080012static int THISMODULE = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070013
Bo Xu5d9acf82015-01-05 12:39:36 -080014static CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, CPDF_Bookmark bookmark, const CFX_WideString& title)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070015{
Tom Sepez4f7bc042015-04-27 12:06:58 -070016 if (bookmark && bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070017 // First check this item
Bo Xu5d9acf82015-01-05 12:39:36 -080018 return bookmark;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070019 }
20 // go into children items
Bo Xu5d9acf82015-01-05 12:39:36 -080021 CPDF_Bookmark child = tree.GetFirstChild(bookmark);
22 while (child) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070023 // check if this item
Bo Xu5d9acf82015-01-05 12:39:36 -080024 CPDF_Bookmark found = FindBookmark(tree, child, title);
25 if (found)
26 return found;
27 child = tree.GetNextSibling(child);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070028 }
Bo Xu5d9acf82015-01-05 12:39:36 -080029 return CPDF_Bookmark();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070030}
31
Bo Xu4d62b6b2015-01-10 22:52:59 -080032DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict)
33{
34 if (!document || !pDict)
35 return NULL;
36 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
37 CPDF_BookmarkTree tree(pDoc);
38 CPDF_Bookmark bookmark = CPDF_Bookmark((CPDF_Dictionary*)pDict);
39 return tree.GetFirstChild(bookmark).GetDict();
40}
41
42DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict)
43{
44 if (!document || !pDict)
45 return NULL;
46 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
47 CPDF_BookmarkTree tree(pDoc);
48 CPDF_Bookmark bookmark = CPDF_Bookmark((CPDF_Dictionary*)pDict);
49 return tree.GetNextSibling(bookmark).GetDict();
50}
51
52DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict, void* buffer, unsigned long buflen)
53{
54 if (!pDict)
55 return 0;
56 CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
57 CFX_WideString title = bookmark.GetTitle();
Bo Xua6f95eb2015-01-21 12:17:23 -080058 CFX_ByteString encodedTitle = title.UTF16LE_Encode();
Bo Xu4d62b6b2015-01-10 22:52:59 -080059 unsigned long len = encodedTitle.GetLength();
Bo Xua6f95eb2015-01-21 12:17:23 -080060 if (buffer && buflen >= len) {
Bo Xu4d62b6b2015-01-10 22:52:59 -080061 FXSYS_memcpy(buffer, encodedTitle.c_str(), len);
Bo Xu4d62b6b2015-01-10 22:52:59 -080062 }
Bo Xua6f95eb2015-01-21 12:17:23 -080063 return len;
Bo Xu4d62b6b2015-01-10 22:52:59 -080064}
65
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070066DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title)
67{
Bo Xu5d9acf82015-01-05 12:39:36 -080068 if (!document)
69 return NULL;
70 if (!title || title[0] == 0)
71 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -070072 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070073 CPDF_BookmarkTree tree(pDoc);
Bo Xu8daab312014-07-14 12:13:53 -070074 FX_STRSIZE len = CFX_WideString::WStringLength(title);
Bo Xu5d9acf82015-01-05 12:39:36 -080075 CFX_WideString encodedTitle = CFX_WideString::FromUTF16LE(title, len);
76 return FindBookmark(tree, CPDF_Bookmark(), encodedTitle).GetDict();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070077}
78
Bo Xu5d9acf82015-01-05 12:39:36 -080079DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080{
Bo Xu5d9acf82015-01-05 12:39:36 -080081 if (!document)
82 return NULL;
83 if (!pDict)
84 return NULL;
85 CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
Bo Xufdc00a72014-10-28 23:03:33 -070086 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Bo Xu5d9acf82015-01-05 12:39:36 -080087 CPDF_Dest dest = bookmark.GetDest(pDoc);
88 if (dest)
Tom Sepezac8d1e72015-03-06 10:52:05 -080089 return dest.GetObject();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070090 // If this bookmark is not directly associated with a dest, we try to get action
Bo Xu5d9acf82015-01-05 12:39:36 -080091 CPDF_Action action = bookmark.GetAction();
92 if (!action)
93 return NULL;
Tom Sepezac8d1e72015-03-06 10:52:05 -080094 return action.GetDest(pDoc).GetObject();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070095}
96
Bo Xu5d9acf82015-01-05 12:39:36 -080097DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070098{
Bo Xu5d9acf82015-01-05 12:39:36 -080099 if (!pDict)
100 return NULL;
101 CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
Tom Sepez7b5bc262015-03-05 16:44:22 -0800102 return bookmark.GetAction().GetDict();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700103}
104
Bo Xu5d9acf82015-01-05 12:39:36 -0800105DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700106{
Bo Xu5d9acf82015-01-05 12:39:36 -0800107 if (!pDict)
108 return 0;
Tom Sepez7b5bc262015-03-05 16:44:22 -0800109 CPDF_Action action((CPDF_Dictionary*)pDict);
Bo Xu5d9acf82015-01-05 12:39:36 -0800110 CPDF_Action::ActionType type = action.GetType();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700111 switch (type) {
Bo Xu5d9acf82015-01-05 12:39:36 -0800112 case CPDF_Action::GoTo:
113 return PDFACTION_GOTO;
114 case CPDF_Action::GoToR:
115 return PDFACTION_REMOTEGOTO;
116 case CPDF_Action::URI:
117 return PDFACTION_URI;
118 case CPDF_Action::Launch:
119 return PDFACTION_LAUNCH;
120 default:
121 return PDFACTION_UNSUPPORTED;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700122 }
123 return PDFACTION_UNSUPPORTED;
124}
125
Bo Xu5d9acf82015-01-05 12:39:36 -0800126DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, FPDF_ACTION pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700127{
Bo Xu5d9acf82015-01-05 12:39:36 -0800128 if (!document)
129 return NULL;
130 if (!pDict)
131 return NULL;
Bo Xufdc00a72014-10-28 23:03:33 -0700132 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Tom Sepez7b5bc262015-03-05 16:44:22 -0800133 CPDF_Action action((CPDF_Dictionary*)pDict);
Tom Sepezac8d1e72015-03-06 10:52:05 -0800134 return action.GetDest(pDoc).GetObject();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700135}
136
Bo Xu5d9acf82015-01-05 12:39:36 -0800137DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, FPDF_ACTION pDict,
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700138 void* buffer, unsigned long buflen)
139{
Bo Xu5d9acf82015-01-05 12:39:36 -0800140 if (!document)
141 return 0;
142 if (!pDict)
143 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700144 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Tom Sepez7b5bc262015-03-05 16:44:22 -0800145 CPDF_Action action((CPDF_Dictionary*)pDict);
Bo Xu5d9acf82015-01-05 12:39:36 -0800146 CFX_ByteString path = action.GetURI(pDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700147 unsigned long len = path.GetLength() + 1;
148 if (buffer != NULL && buflen >= len)
Bo Xuc6164832014-12-30 16:56:12 -0800149 FXSYS_memcpy(buffer, path.c_str(), len);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700150 return len;
151}
152
Bo Xu5d9acf82015-01-05 12:39:36 -0800153DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700154{
Bo Xu5d9acf82015-01-05 12:39:36 -0800155 if (!document)
156 return 0;
157 if (!pDict)
158 return 0;
Bo Xufdc00a72014-10-28 23:03:33 -0700159 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
Tom Sepezac8d1e72015-03-06 10:52:05 -0800160 CPDF_Dest dest((CPDF_Array*)pDict);
Bo Xu5d9acf82015-01-05 12:39:36 -0800161 return dest.GetPageIndex(pDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700162}
163
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700164static void ReleaseLinkList(void* data)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700165{
166 delete (CPDF_LinkList*)data;
167}
168
169DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, double x, double y)
170{
Bo Xu5d9acf82015-01-05 12:39:36 -0800171 if (!page)
172 return NULL;
173 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
Bo Xu9f78c2a2015-01-13 17:02:12 -0800174 if (!pPage)
175 return NULL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700176 // Link list is stored with the document
177 CPDF_Document* pDoc = pPage->m_pDocument;
Bo Xu5d9acf82015-01-05 12:39:36 -0800178 CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&THISMODULE);
179 if (!pLinkList) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700180 pLinkList = FX_NEW CPDF_LinkList(pDoc);
Bo Xu5d9acf82015-01-05 12:39:36 -0800181 pDoc->SetPrivateData(&THISMODULE, pLinkList, ReleaseLinkList);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700182 }
Tom Sepez4cc9acb2015-03-06 12:37:13 -0800183 return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y).GetDict();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700184}
185
Bo Xu5d9acf82015-01-05 12:39:36 -0800186DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, FPDF_LINK pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700187{
Bo Xu5d9acf82015-01-05 12:39:36 -0800188 if (!document)
189 return NULL;
Bo Xu5d9acf82015-01-05 12:39:36 -0800190 if (!pDict)
191 return NULL;
Tom Sepez4cc9acb2015-03-06 12:37:13 -0800192 CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
193 CPDF_Link link((CPDF_Dictionary*)pDict);
Tom Sepezac8d1e72015-03-06 10:52:05 -0800194 FPDF_DEST dest = link.GetDest(pDoc).GetObject();
Bo Xu5d9acf82015-01-05 12:39:36 -0800195 if (dest)
196 return dest;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700197 // If this link is not directly associated with a dest, we try to get action
Bo Xu5d9acf82015-01-05 12:39:36 -0800198 CPDF_Action action = link.GetAction();
199 if (!action)
200 return NULL;
Tom Sepezac8d1e72015-03-06 10:52:05 -0800201 return action.GetDest(pDoc).GetObject();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700202}
203
Bo Xu5d9acf82015-01-05 12:39:36 -0800204DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK pDict)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700205{
Bo Xu5d9acf82015-01-05 12:39:36 -0800206 if (!pDict)
207 return NULL;
Tom Sepez4cc9acb2015-03-06 12:37:13 -0800208 CPDF_Link link((CPDF_Dictionary*)pDict);
Tom Sepez7b5bc262015-03-05 16:44:22 -0800209 return link.GetAction().GetDict();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
212DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, int* startPos, FPDF_LINK* linkAnnot)
213{
214 if(!page || !startPos || !linkAnnot)
215 return FALSE;
Bo Xu5d9acf82015-01-05 12:39:36 -0800216 CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
217 if(!pPage->m_pFormDict)
218 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700219 CPDF_Array* pAnnots = pPage->m_pFormDict->GetArray("Annots");
Bo Xu5d9acf82015-01-05 12:39:36 -0800220 if(!pAnnots)
221 return FALSE;
222 for (int i = *startPos; i < (int)pAnnots->GetCount(); i++) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700223 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i);
Bo Xu5d9acf82015-01-05 12:39:36 -0800224 if (!pDict || pDict->GetType() != PDFOBJ_DICTIONARY)
225 continue;
226 if(pDict->GetString(FX_BSTRC("Subtype")).Equal(FX_BSTRC("Link"))) {
227 *startPos = i + 1;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700228 *linkAnnot = (FPDF_LINK)pDict;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700229 return TRUE;
230 }
231 }
232 return FALSE;
233}
234
235DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, FS_RECTF* rect)
236{
237 if(!linkAnnot || !rect)
238 return FALSE;
239 CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
240 CPDF_Rect rt = pAnnotDict->GetRect(FX_BSTRC("Rect"));
241 rect->left = rt.left;
242 rect->bottom = rt.bottom;
243 rect->right = rt.right;
244 rect->top = rt.top;
245 return TRUE;
246}
247
248DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot)
249{
250 if(!linkAnnot)
251 return 0;
252 CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
253 CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
Bo Xu5d9acf82015-01-05 12:39:36 -0800254 if (!pArray)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700255 return 0;
256 else
257 return pArray->GetCount() / 8;
258}
259
260DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, int quadIndex, FS_QUADPOINTSF* quadPoints)
261{
262 if(!linkAnnot || !quadPoints)
263 return FALSE;
264 CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
265 CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
266 if (pArray) {
Bo Xu5d9acf82015-01-05 12:39:36 -0800267 if (quadIndex < 0 || quadIndex >= (int)pArray->GetCount()/8 || ((quadIndex*8+7) >= (int)pArray->GetCount()))
268 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700269 quadPoints->x1 = pArray->GetNumber(quadIndex*8);
270 quadPoints->y1 = pArray->GetNumber(quadIndex*8+1);
271 quadPoints->x2 = pArray->GetNumber(quadIndex*8+2);
272 quadPoints->y2 = pArray->GetNumber(quadIndex*8+3);
273 quadPoints->x3 = pArray->GetNumber(quadIndex*8+4);
274 quadPoints->y3 = pArray->GetNumber(quadIndex*8+5);
275 quadPoints->x4 = pArray->GetNumber(quadIndex*8+6);
276 quadPoints->y4 = pArray->GetNumber(quadIndex*8+7);
277 return TRUE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700278 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700279 return FALSE;
280}
281
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700282DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT doc, FPDF_BYTESTRING tag,
283 void* buffer, unsigned long buflen)
284{
Bo Xu5d9acf82015-01-05 12:39:36 -0800285 if (!doc || !tag)
286 return 0;
287 CPDF_Document* pDoc = ((CPDFXFA_Document*)doc)->GetPDFDoc();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700288 // Get info dictionary
289 CPDF_Dictionary* pInfo = pDoc->GetInfo();
Bo Xu5d9acf82015-01-05 12:39:36 -0800290 if (!pInfo)
291 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700292 CFX_WideString text = pInfo->GetUnicodeText(tag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700293 // Use UTF-16LE encoding
Bo Xu5d9acf82015-01-05 12:39:36 -0800294 CFX_ByteString encodedText = text.UTF16LE_Encode();
295 unsigned long len = encodedText.GetLength();
Bo Xua6f95eb2015-01-21 12:17:23 -0800296 if (buffer && buflen >= len) {
Bo Xu5d9acf82015-01-05 12:39:36 -0800297 FXSYS_memcpy(buffer, encodedText.c_str(), len);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700298 }
Bo Xua6f95eb2015-01-21 12:17:23 -0800299 return len;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700300}