1 // Copyright 2014 PDFium Authors. All rights reserved.
\r
2 // Use of this source code is governed by a BSD-style license that can be
\r
3 // found in the LICENSE file.
\r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
\r
7 #include "../include/fsdk_define.h"
\r
8 #include "../include/fpdfdoc.h"
\r
10 static int this_module = 0;
\r
12 static CPDF_Bookmark FindBookmark(CPDF_BookmarkTree& tree, CPDF_Bookmark This, const CFX_WideString& title)
\r
15 // First check this item
\r
16 CFX_WideString this_title = This.GetTitle();
\r
17 if (this_title.CompareNoCase(title) == 0)
\r
20 // go into children items
\r
21 CPDF_Bookmark Child = tree.GetFirstChild(This);
\r
22 while (Child != NULL) {
\r
23 // check if this item
\r
24 CPDF_Bookmark Found = FindBookmark(tree, Child, title);
\r
25 if (Found) return Found;
\r
26 Child = tree.GetNextSibling(Child);
\r
31 DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title)
\r
33 if (document == NULL) return NULL;
\r
34 if (title == NULL || title[0] == 0) return NULL;
\r
36 CPDF_Document* pDoc = (CPDF_Document*)document;
\r
37 CPDF_BookmarkTree tree(pDoc);
\r
39 CFX_WideString wstr = CFX_WideString::FromUTF16LE(title);
\r
40 return FindBookmark(tree, NULL, wstr);
\r
43 DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark)
\r
45 if (document == NULL) return NULL;
\r
46 if (bookmark == NULL) return NULL;
\r
48 CPDF_Bookmark Bookmark = (CPDF_Dictionary*)bookmark;
\r
49 CPDF_Document* pDoc = (CPDF_Document*)document;
\r
50 CPDF_Dest dest = Bookmark.GetDest(pDoc);
\r
51 if (dest != NULL) return dest;
\r
53 // If this bookmark is not directly associated with a dest, we try to get action
\r
54 CPDF_Action Action = Bookmark.GetAction();
\r
55 if (Action == NULL) return NULL;
\r
56 return Action.GetDest(pDoc);
\r
59 DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark)
\r
61 if (bookmark == NULL) return NULL;
\r
63 CPDF_Bookmark Bookmark = (CPDF_Dictionary*)bookmark;
\r
64 return Bookmark.GetAction();
\r
67 DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION action)
\r
69 if (action == NULL) return 0;
\r
71 CPDF_Action Action = (CPDF_Dictionary*)action;
\r
72 CPDF_Action::ActionType type = Action.GetType();
\r
74 case CPDF_Action::GoTo:
\r
75 return PDFACTION_GOTO;
\r
76 case CPDF_Action::GoToR:
\r
77 return PDFACTION_REMOTEGOTO;
\r
78 case CPDF_Action::URI:
\r
79 return PDFACTION_URI;
\r
80 case CPDF_Action::Launch:
\r
81 return PDFACTION_LAUNCH;
\r
83 return PDFACTION_UNSUPPORTED;
\r
85 return PDFACTION_UNSUPPORTED;
\r
88 DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, FPDF_ACTION action)
\r
90 if (document == NULL) return NULL;
\r
91 if (action == NULL) return NULL;
\r
92 CPDF_Document* pDoc = (CPDF_Document*)document;
\r
93 CPDF_Action Action = (CPDF_Dictionary*)action;
\r
95 return Action.GetDest(pDoc);
\r
98 DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, FPDF_ACTION action,
\r
99 void* buffer, unsigned long buflen)
\r
101 if (document == NULL) return 0;
\r
102 if (action == NULL) return 0;
\r
103 CPDF_Document* pDoc = (CPDF_Document*)document;
\r
104 CPDF_Action Action = (CPDF_Dictionary*)action;
\r
106 CFX_ByteString path = Action.GetURI(pDoc);
\r
107 unsigned long len = path.GetLength() + 1;
\r
108 if (buffer != NULL && buflen >= len)
\r
109 FXSYS_memcpy(buffer, (FX_LPCSTR)path, len);
\r
113 DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST dest)
\r
115 if (document == NULL) return 0;
\r
116 if (dest == NULL) return 0;
\r
117 CPDF_Document* pDoc = (CPDF_Document*)document;
\r
118 CPDF_Dest Dest = (CPDF_Array*)dest;
\r
120 return Dest.GetPageIndex(pDoc);
\r
123 static void ReleaseLinkList(FX_LPVOID data)
\r
125 delete (CPDF_LinkList*)data;
\r
128 DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, double x, double y)
\r
130 if (page == NULL) return NULL;
\r
131 CPDF_Page* pPage = (CPDF_Page*)page;
\r
133 // Link list is stored with the document
\r
134 CPDF_Document* pDoc = pPage->m_pDocument;
\r
135 CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&this_module);
\r
136 if (pLinkList == NULL) {
\r
137 pLinkList = FX_NEW CPDF_LinkList(pDoc);
\r
138 pDoc->SetPrivateData(&this_module, pLinkList, ReleaseLinkList);
\r
141 return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y);
\r
144 DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, FPDF_LINK link)
\r
146 if (document == NULL) return NULL;
\r
147 CPDF_Document* pDoc = (CPDF_Document*)document;
\r
148 if (link == NULL) return NULL;
\r
149 CPDF_Link Link = (CPDF_Dictionary*)link;
\r
151 FPDF_DEST dest = Link.GetDest(pDoc);
\r
152 if (dest) return dest;
\r
154 // If this link is not directly associated with a dest, we try to get action
\r
155 CPDF_Action Action = Link.GetAction();
\r
156 if (Action == NULL) return NULL;
\r
157 return Action.GetDest(pDoc);
\r
160 DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK link)
\r
162 if (link == NULL) return NULL;
\r
163 CPDF_Link Link = (CPDF_Dictionary*)link;
\r
165 return Link.GetAction();
\r
168 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, int* startPos, FPDF_LINK* linkAnnot)
\r
170 if(!page || !startPos || !linkAnnot)
\r
172 CPDF_Page* pPage = (CPDF_Page*)page;
\r
173 if(!pPage->m_pFormDict) return FALSE;
\r
174 CPDF_Array* pAnnots = pPage->m_pFormDict->GetArray("Annots");
\r
175 if(!pAnnots) return FALSE;
\r
176 for (int i = *startPos; i < (int)pAnnots->GetCount(); i ++) {
\r
177 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i);
\r
178 if (pDict == NULL || pDict->GetType() != PDFOBJ_DICTIONARY) continue;
\r
179 if(pDict->GetString(FX_BSTRC("Subtype")).Equal(FX_BSTRC("Link")))
\r
182 *linkAnnot = (FPDF_LINK)pDict;
\r
189 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, FS_RECTF* rect)
\r
191 if(!linkAnnot || !rect)
\r
193 CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
\r
194 CPDF_Rect rt = pAnnotDict->GetRect(FX_BSTRC("Rect"));
\r
195 rect->left = rt.left;
\r
196 rect->bottom = rt.bottom;
\r
197 rect->right = rt.right;
\r
198 rect->top = rt.top;
\r
202 DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot)
\r
206 CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
\r
207 CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
\r
208 if (pArray == NULL)
\r
211 return pArray->GetCount() / 8;
\r
214 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, int quadIndex, FS_QUADPOINTSF* quadPoints)
\r
216 if(!linkAnnot || !quadPoints)
\r
218 CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
\r
219 CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
\r
221 if (0 > quadIndex || quadIndex >= (int)pArray->GetCount()/8 ||
\r
222 ((quadIndex*8+7) >= (int)pArray->GetCount())) return FALSE;
\r
223 quadPoints->x1 = pArray->GetNumber(quadIndex*8);
\r
224 quadPoints->y1 = pArray->GetNumber(quadIndex*8+1);
\r
225 quadPoints->x2 = pArray->GetNumber(quadIndex*8+2);
\r
226 quadPoints->y2 = pArray->GetNumber(quadIndex*8+3);
\r
227 quadPoints->x3 = pArray->GetNumber(quadIndex*8+4);
\r
228 quadPoints->y3 = pArray->GetNumber(quadIndex*8+5);
\r
229 quadPoints->x4 = pArray->GetNumber(quadIndex*8+6);
\r
230 quadPoints->y4 = pArray->GetNumber(quadIndex*8+7);
\r
237 DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT doc, FPDF_BYTESTRING tag,
\r
238 void* buffer, unsigned long buflen)
\r
240 if (doc == NULL || tag == NULL) return 0;
\r
242 CPDF_Document* pDoc = (CPDF_Document*)doc;
\r
243 // Get info dictionary
\r
244 CPDF_Dictionary* pInfo = pDoc->GetInfo();
\r
245 if (pInfo == NULL) return 0;
\r
247 CFX_WideString text = pInfo->GetUnicodeText(tag);
\r
249 // Use UTF-16LE encoding
\r
250 CFX_ByteString bstr = text.UTF16LE_Encode();
\r
251 unsigned long len = bstr.GetLength();
\r
252 if (buffer != NULL || buflen >= len+2) {
\r
253 FXSYS_memcpy(buffer, (FX_LPCSTR)bstr, len);
\r
254 // use double zero as trailer
\r
255 ((FX_BYTE*)buffer)[len] = ((FX_BYTE*)buffer)[len+1] = 0;
\r