Kill JS_TIMER_MAPARRAY
[pdfium.git] / fpdfsdk / src / fpdfdoc.cpp
1 // 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.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../include/fsdk_define.h"
8 #include "../../public/fpdf_doc.h"
9
10 static int THISMODULE = 0;
11
12 static CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree,
13                                   CPDF_Bookmark bookmark,
14                                   const CFX_WideString& title) {
15   if (bookmark && bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
16     // First check this item
17     return bookmark;
18   }
19   // go into children items
20   CPDF_Bookmark child = tree.GetFirstChild(bookmark);
21   while (child) {
22     // check if this item
23     CPDF_Bookmark found = FindBookmark(tree, child, title);
24     if (found)
25       return found;
26     child = tree.GetNextSibling(child);
27   }
28   return CPDF_Bookmark();
29 }
30
31 DLLEXPORT FPDF_BOOKMARK STDCALL
32 FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) {
33   if (!document)
34     return NULL;
35   CPDF_Document* pDoc = (CPDF_Document*)document;
36   CPDF_BookmarkTree tree(pDoc);
37   CPDF_Bookmark bookmark = CPDF_Bookmark((CPDF_Dictionary*)pDict);
38   return tree.GetFirstChild(bookmark).GetDict();
39 }
40
41 DLLEXPORT FPDF_BOOKMARK STDCALL
42 FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) {
43   if (!document || !pDict)
44     return NULL;
45   CPDF_Document* pDoc = (CPDF_Document*)document;
46   CPDF_BookmarkTree tree(pDoc);
47   CPDF_Bookmark bookmark = CPDF_Bookmark((CPDF_Dictionary*)pDict);
48   return tree.GetNextSibling(bookmark).GetDict();
49 }
50
51 DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict,
52                                                       void* buffer,
53                                                       unsigned long buflen) {
54   if (!pDict)
55     return 0;
56   CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
57   CFX_WideString title = bookmark.GetTitle();
58   CFX_ByteString encodedTitle = title.UTF16LE_Encode();
59   unsigned long len = encodedTitle.GetLength();
60   if (buffer && buflen >= len) {
61     FXSYS_memcpy(buffer, encodedTitle.c_str(), len);
62   }
63   return len;
64 }
65
66 DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document,
67                                                   FPDF_WIDESTRING title) {
68   if (!document)
69     return NULL;
70   if (!title || title[0] == 0)
71     return NULL;
72   CPDF_Document* pDoc = (CPDF_Document*)document;
73   CPDF_BookmarkTree tree(pDoc);
74   FX_STRSIZE len = CFX_WideString::WStringLength(title);
75   CFX_WideString encodedTitle = CFX_WideString::FromUTF16LE(title, len);
76   return FindBookmark(tree, CPDF_Bookmark(), encodedTitle).GetDict();
77 }
78
79 DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document,
80                                                  FPDF_BOOKMARK pDict) {
81   if (!document)
82     return NULL;
83   if (!pDict)
84     return NULL;
85   CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
86   CPDF_Document* pDoc = (CPDF_Document*)document;
87   CPDF_Dest dest = bookmark.GetDest(pDoc);
88   if (dest)
89     return dest.GetObject();
90   // If this bookmark is not directly associated with a dest, we try to get
91   // action
92   CPDF_Action action = bookmark.GetAction();
93   if (!action)
94     return NULL;
95   return action.GetDest(pDoc).GetObject();
96 }
97
98 DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK pDict) {
99   if (!pDict)
100     return NULL;
101   CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
102   return bookmark.GetAction().GetDict();
103 }
104
105 DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION pDict) {
106   if (!pDict)
107     return 0;
108   CPDF_Action action((CPDF_Dictionary*)pDict);
109   CPDF_Action::ActionType type = action.GetType();
110   switch (type) {
111     case CPDF_Action::GoTo:
112       return PDFACTION_GOTO;
113     case CPDF_Action::GoToR:
114       return PDFACTION_REMOTEGOTO;
115     case CPDF_Action::URI:
116       return PDFACTION_URI;
117     case CPDF_Action::Launch:
118       return PDFACTION_LAUNCH;
119     default:
120       return PDFACTION_UNSUPPORTED;
121   }
122   return PDFACTION_UNSUPPORTED;
123 }
124
125 DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document,
126                                                FPDF_ACTION pDict) {
127   if (!document)
128     return NULL;
129   if (!pDict)
130     return NULL;
131   CPDF_Document* pDoc = (CPDF_Document*)document;
132   CPDF_Action action((CPDF_Dictionary*)pDict);
133   return action.GetDest(pDoc).GetObject();
134 }
135
136 DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document,
137                                                       FPDF_ACTION pDict,
138                                                       void* buffer,
139                                                       unsigned long buflen) {
140   if (!document)
141     return 0;
142   if (!pDict)
143     return 0;
144   CPDF_Document* pDoc = (CPDF_Document*)document;
145   CPDF_Action action((CPDF_Dictionary*)pDict);
146   CFX_ByteString path = action.GetURI(pDoc);
147   unsigned long len = path.GetLength() + 1;
148   if (buffer != NULL && buflen >= len)
149     FXSYS_memcpy(buffer, path.c_str(), len);
150   return len;
151 }
152
153 DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document,
154                                                       FPDF_DEST pDict) {
155   if (!document)
156     return 0;
157   if (!pDict)
158     return 0;
159   CPDF_Document* pDoc = (CPDF_Document*)document;
160   CPDF_Dest dest((CPDF_Array*)pDict);
161   return dest.GetPageIndex(pDoc);
162 }
163
164 static void ReleaseLinkList(void* data) {
165   delete (CPDF_LinkList*)data;
166 }
167
168 DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page,
169                                                     double x,
170                                                     double y) {
171   if (!page)
172     return NULL;
173   CPDF_Page* pPage = (CPDF_Page*)page;
174   // Link list is stored with the document
175   CPDF_Document* pDoc = pPage->m_pDocument;
176   CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&THISMODULE);
177   if (!pLinkList) {
178     pLinkList = new CPDF_LinkList(pDoc);
179     pDoc->SetPrivateData(&THISMODULE, pLinkList, ReleaseLinkList);
180   }
181   return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y).GetDict();
182 }
183
184 DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document,
185                                              FPDF_LINK pDict) {
186   if (!document)
187     return NULL;
188   if (!pDict)
189     return NULL;
190   CPDF_Document* pDoc = (CPDF_Document*)document;
191   CPDF_Link link((CPDF_Dictionary*)pDict);
192   FPDF_DEST dest = link.GetDest(pDoc).GetObject();
193   if (dest)
194     return dest;
195   // If this link is not directly associated with a dest, we try to get action
196   CPDF_Action action = link.GetAction();
197   if (!action)
198     return NULL;
199   return action.GetDest(pDoc).GetObject();
200 }
201
202 DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK pDict) {
203   if (!pDict)
204     return NULL;
205   CPDF_Link link((CPDF_Dictionary*)pDict);
206   return link.GetAction().GetDict();
207 }
208
209 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page,
210                                                int* startPos,
211                                                FPDF_LINK* linkAnnot) {
212   if (!page || !startPos || !linkAnnot)
213     return FALSE;
214   CPDF_Page* pPage = (CPDF_Page*)page;
215   if (!pPage->m_pFormDict)
216     return FALSE;
217   CPDF_Array* pAnnots = pPage->m_pFormDict->GetArray("Annots");
218   if (!pAnnots)
219     return FALSE;
220   for (int i = *startPos; i < (int)pAnnots->GetCount(); i++) {
221     CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i);
222     if (!pDict || pDict->GetType() != PDFOBJ_DICTIONARY)
223       continue;
224     if (pDict->GetString(FX_BSTRC("Subtype")).Equal(FX_BSTRC("Link"))) {
225       *startPos = i + 1;
226       *linkAnnot = (FPDF_LINK)pDict;
227       return TRUE;
228     }
229   }
230   return FALSE;
231 }
232
233 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot,
234                                                   FS_RECTF* rect) {
235   if (!linkAnnot || !rect)
236     return FALSE;
237   CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
238   CPDF_Rect rt = pAnnotDict->GetRect(FX_BSTRC("Rect"));
239   rect->left = rt.left;
240   rect->bottom = rt.bottom;
241   rect->right = rt.right;
242   rect->top = rt.top;
243   return TRUE;
244 }
245
246 DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) {
247   if (!linkAnnot)
248     return 0;
249   CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
250   CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
251   if (!pArray)
252     return 0;
253   return pArray->GetCount() / 8;
254 }
255
256 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot,
257                                                    int quadIndex,
258                                                    FS_QUADPOINTSF* quadPoints) {
259   if (!linkAnnot || !quadPoints)
260     return FALSE;
261   CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
262   CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
263   if (pArray) {
264     if (quadIndex < 0 || quadIndex >= (int)pArray->GetCount() / 8 ||
265         ((quadIndex * 8 + 7) >= (int)pArray->GetCount()))
266       return FALSE;
267     quadPoints->x1 = pArray->GetNumber(quadIndex * 8);
268     quadPoints->y1 = pArray->GetNumber(quadIndex * 8 + 1);
269     quadPoints->x2 = pArray->GetNumber(quadIndex * 8 + 2);
270     quadPoints->y2 = pArray->GetNumber(quadIndex * 8 + 3);
271     quadPoints->x3 = pArray->GetNumber(quadIndex * 8 + 4);
272     quadPoints->y3 = pArray->GetNumber(quadIndex * 8 + 5);
273     quadPoints->x4 = pArray->GetNumber(quadIndex * 8 + 6);
274     quadPoints->y4 = pArray->GetNumber(quadIndex * 8 + 7);
275     return TRUE;
276   }
277   return FALSE;
278 }
279
280 DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT doc,
281                                                  FPDF_BYTESTRING tag,
282                                                  void* buffer,
283                                                  unsigned long buflen) {
284   if (!doc || !tag)
285     return 0;
286   CPDF_Document* pDoc = (CPDF_Document*)doc;
287   // Get info dictionary
288   CPDF_Dictionary* pInfo = pDoc->GetInfo();
289   if (!pInfo)
290     return 0;
291   CFX_WideString text = pInfo->GetUnicodeText(tag);
292   // Use UTF-16LE encoding
293   CFX_ByteString encodedText = text.UTF16LE_Encode();
294   unsigned long len = encodedText.GetLength();
295   if (buffer && buflen >= len) {
296     FXSYS_memcpy(buffer, encodedText.c_str(), len);
297   }
298   return len;
299 }