blob: 17cfce0b2448cca74077e1d197b734b7bd58189c [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
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdf_doc.h"
8
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009#include <memory>
Wei Li0e2e5d72016-03-03 11:28:06 -080010#include <set>
11
dsinclair41872fa2016-10-04 11:29:35 -070012#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070013#include "core/fpdfapi/parser/cpdf_array.h"
14#include "core/fpdfapi/parser/cpdf_document.h"
Ralf Sippl16381792018-04-12 21:20:26 +000015#include "core/fpdfapi/parser/cpdf_number.h"
dsinclair1727aee2016-09-29 13:12:56 -070016#include "core/fpdfdoc/cpdf_bookmark.h"
17#include "core/fpdfdoc/cpdf_bookmarktree.h"
dsinclairc59fa882016-11-08 06:55:40 -080018#include "core/fpdfdoc/cpdf_dest.h"
thestig733e0682016-11-23 05:52:39 -080019#include "core/fpdfdoc/cpdf_pagelabel.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000020#include "fpdfsdk/cpdfsdk_helpers.h"
tsepeza9caab92016-12-14 05:57:10 -080021#include "third_party/base/ptr_util.h"
Wei Li0e2e5d72016-03-03 11:28:06 -080022#include "third_party/base/stl_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070023
Lei Zhangbdf72c32015-08-14 19:24:08 -070024namespace {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070025
Lei Zhangbdf72c32015-08-14 19:24:08 -070026CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree,
27 CPDF_Bookmark bookmark,
Ryan Harrison275e2602017-09-18 14:23:18 -040028 const WideString& title,
Wei Li0e2e5d72016-03-03 11:28:06 -080029 std::set<CPDF_Dictionary*>* visited) {
30 // Return if already checked to avoid circular calling.
31 if (pdfium::ContainsKey(*visited, bookmark.GetDict()))
32 return CPDF_Bookmark();
33 visited->insert(bookmark.GetDict());
34
Wei Li0fc6b252016-03-01 16:29:41 -080035 if (bookmark.GetDict() &&
36 bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
Wei Li0e2e5d72016-03-03 11:28:06 -080037 // First check this item.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038 return bookmark;
39 }
Wei Li0e2e5d72016-03-03 11:28:06 -080040
41 // Go into children items.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070042 CPDF_Bookmark child = tree.GetFirstChild(bookmark);
Wei Li0e2e5d72016-03-03 11:28:06 -080043 while (child.GetDict() && !pdfium::ContainsKey(*visited, child.GetDict())) {
44 // Check this item and its children.
45 CPDF_Bookmark found = FindBookmark(tree, child, title, visited);
Wei Li0fc6b252016-03-01 16:29:41 -080046 if (found.GetDict())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 return found;
48 child = tree.GetNextSibling(child);
49 }
50 return CPDF_Bookmark();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070051}
52
Lei Zhangbdf72c32015-08-14 19:24:08 -070053CPDF_LinkList* GetLinkList(CPDF_Page* page) {
54 if (!page)
55 return nullptr;
56
Tom Sepez4cb82ee2017-05-22 15:15:30 -070057 CPDF_Document* pDoc = page->m_pDocument.Get();
tsepez5ce09682016-05-25 16:16:32 -070058 std::unique_ptr<CPDF_LinkList>* pHolder = pDoc->LinksContext();
59 if (!pHolder->get())
tsepeza9caab92016-12-14 05:57:10 -080060 *pHolder = pdfium::MakeUnique<CPDF_LinkList>();
tsepez5ce09682016-05-25 16:16:32 -070061 return pHolder->get();
Lei Zhangbdf72c32015-08-14 19:24:08 -070062}
63
Dan Sinclair7aba4722018-03-28 17:04:16 +000064} // namespace
Lei Zhangaaed6982018-03-22 18:39:05 +000065
Dan Sinclair00d2ad12017-08-10 14:13:02 -040066FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) {
Tom Sepez471a1032015-10-15 16:17:18 -070068 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
69 if (!pDoc)
70 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071 CPDF_BookmarkTree tree(pDoc);
Lei Zhang11767d32018-03-21 18:59:44 +000072 CPDF_Bookmark bookmark(CPDFDictionaryFromFPDFBookmark(pDict));
Tom Sepez525147a2018-05-03 17:19:53 +000073 return FPDFBookmarkFromCPDFDictionary(tree.GetFirstChild(bookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080074}
75
Dan Sinclair00d2ad12017-08-10 14:13:02 -040076FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Nico Weber9d8ec5a2015-08-04 13:00:21 -070077FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) {
Tom Sepez471a1032015-10-15 16:17:18 -070078 if (!pDict)
79 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +000080
Tom Sepez471a1032015-10-15 16:17:18 -070081 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
82 if (!pDoc)
83 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +000084
Nico Weber9d8ec5a2015-08-04 13:00:21 -070085 CPDF_BookmarkTree tree(pDoc);
Lei Zhang11767d32018-03-21 18:59:44 +000086 CPDF_Bookmark bookmark(CPDFDictionaryFromFPDFBookmark(pDict));
Tom Sepez525147a2018-05-03 17:19:53 +000087 return FPDFBookmarkFromCPDFDictionary(
88 tree.GetNextSibling(bookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080089}
90
Dan Sinclair00d2ad12017-08-10 14:13:02 -040091FPDF_EXPORT unsigned long FPDF_CALLCONV
92FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict, void* buffer, unsigned long buflen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 if (!pDict)
94 return 0;
Lei Zhang11767d32018-03-21 18:59:44 +000095 CPDF_Bookmark bookmark(CPDFDictionaryFromFPDFBookmark(pDict));
Ryan Harrison275e2602017-09-18 14:23:18 -040096 WideString title = bookmark.GetTitle();
thestig733e0682016-11-23 05:52:39 -080097 return Utf16EncodeMaybeCopyAndReturnLength(title, buffer, buflen);
Bo Xu4d62b6b2015-01-10 22:52:59 -080098}
99
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400100FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
101FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700102 if (!title || title[0] == 0)
Tom Sepez471a1032015-10-15 16:17:18 -0700103 return nullptr;
104 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
105 if (!pDoc)
106 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700107 CPDF_BookmarkTree tree(pDoc);
Ryan Harrison875e98c2017-09-27 10:53:11 -0400108 size_t len = WideString::WStringLength(title);
Ryan Harrison275e2602017-09-18 14:23:18 -0400109 WideString encodedTitle = WideString::FromUTF16LE(title, len);
Wei Li0e2e5d72016-03-03 11:28:06 -0800110 std::set<CPDF_Dictionary*> visited;
Tom Sepez525147a2018-05-03 17:19:53 +0000111 return FPDFBookmarkFromCPDFDictionary(
112 FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700113}
114
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400115FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFBookmark_GetDest(FPDF_DOCUMENT document,
116 FPDF_BOOKMARK pDict) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700117 if (!pDict)
Tom Sepez471a1032015-10-15 16:17:18 -0700118 return nullptr;
119 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
120 if (!pDoc)
121 return nullptr;
Lei Zhang11767d32018-03-21 18:59:44 +0000122 CPDF_Bookmark bookmark(CPDFDictionaryFromFPDFBookmark(pDict));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700123 CPDF_Dest dest = bookmark.GetDest(pDoc);
Wei Li0fc6b252016-03-01 16:29:41 -0800124 if (dest.GetObject())
Tom Sepez525147a2018-05-03 17:19:53 +0000125 return FPDFDestFromCPDFArray(dest.GetObject());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126 // If this bookmark is not directly associated with a dest, we try to get
127 // action
128 CPDF_Action action = bookmark.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800129 if (!action.GetDict())
Tom Sepez471a1032015-10-15 16:17:18 -0700130 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +0000131 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetObject());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700132}
133
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400134FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV
135FPDFBookmark_GetAction(FPDF_BOOKMARK pDict) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136 if (!pDict)
thestig1cd352e2016-06-07 17:53:06 -0700137 return nullptr;
Lei Zhang11767d32018-03-21 18:59:44 +0000138 CPDF_Bookmark bookmark(CPDFDictionaryFromFPDFBookmark(pDict));
Tom Sepez525147a2018-05-03 17:19:53 +0000139 return FPDFActionFromCPDFDictionary(bookmark.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700140}
141
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400142FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION pDict) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700143 if (!pDict)
Lei Zhange0947b32015-09-17 14:51:48 -0700144 return PDFACTION_UNSUPPORTED;
145
Lei Zhang11767d32018-03-21 18:59:44 +0000146 CPDF_Action action(CPDFDictionaryFromFPDFAction(pDict));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147 CPDF_Action::ActionType type = action.GetType();
148 switch (type) {
149 case CPDF_Action::GoTo:
150 return PDFACTION_GOTO;
151 case CPDF_Action::GoToR:
152 return PDFACTION_REMOTEGOTO;
153 case CPDF_Action::URI:
154 return PDFACTION_URI;
155 case CPDF_Action::Launch:
156 return PDFACTION_LAUNCH;
157 default:
158 return PDFACTION_UNSUPPORTED;
159 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700160}
161
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400162FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFAction_GetDest(FPDF_DOCUMENT document,
163 FPDF_ACTION pDict) {
Tom Sepez471a1032015-10-15 16:17:18 -0700164 if (!pDict)
Lei Zhange0947b32015-09-17 14:51:48 -0700165 return nullptr;
Tom Sepez471a1032015-10-15 16:17:18 -0700166 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
167 if (!pDoc)
168 return nullptr;
Lei Zhang11767d32018-03-21 18:59:44 +0000169 CPDF_Action action(CPDFDictionaryFromFPDFAction(pDict));
Tom Sepez525147a2018-05-03 17:19:53 +0000170 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetObject());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700171}
172
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400173FPDF_EXPORT unsigned long FPDF_CALLCONV
174FPDFAction_GetFilePath(FPDF_ACTION pDict, void* buffer, unsigned long buflen) {
Lei Zhange0947b32015-09-17 14:51:48 -0700175 unsigned long type = FPDFAction_GetType(pDict);
176 if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_LAUNCH)
177 return 0;
178
Lei Zhang11767d32018-03-21 18:59:44 +0000179 CPDF_Action action(CPDFDictionaryFromFPDFAction(pDict));
Ryan Harrison275e2602017-09-18 14:23:18 -0400180 ByteString path = action.GetFilePath().UTF8Encode();
Lei Zhange0947b32015-09-17 14:51:48 -0700181 unsigned long len = path.GetLength() + 1;
thestig9067fd62016-11-23 14:10:06 -0800182 if (buffer && len <= buflen)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400183 memcpy(buffer, path.c_str(), len);
Lei Zhange0947b32015-09-17 14:51:48 -0700184 return len;
185}
186
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400187FPDF_EXPORT unsigned long FPDF_CALLCONV
188FPDFAction_GetURIPath(FPDF_DOCUMENT document,
189 FPDF_ACTION pDict,
190 void* buffer,
191 unsigned long buflen) {
Tom Sepez471a1032015-10-15 16:17:18 -0700192 if (!pDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 return 0;
Tom Sepez471a1032015-10-15 16:17:18 -0700194 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
195 if (!pDoc)
196 return 0;
Lei Zhang11767d32018-03-21 18:59:44 +0000197 CPDF_Action action(CPDFDictionaryFromFPDFAction(pDict));
Ryan Harrison275e2602017-09-18 14:23:18 -0400198 ByteString path = action.GetURI(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 unsigned long len = path.GetLength() + 1;
thestig9067fd62016-11-23 14:10:06 -0800200 if (buffer && len <= buflen)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400201 memcpy(buffer, path.c_str(), len);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202 return len;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700203}
204
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400205FPDF_EXPORT unsigned long FPDF_CALLCONV
Lei Zhangaca3efc2018-03-16 20:27:04 +0000206FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST dest) {
207 if (!dest)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700208 return 0;
Henrique Nakashima71a7d372018-02-01 17:07:13 +0000209
Tom Sepez471a1032015-10-15 16:17:18 -0700210 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
211 if (!pDoc)
212 return 0;
Henrique Nakashima71a7d372018-02-01 17:07:13 +0000213
Tom Sepez525147a2018-05-03 17:19:53 +0000214 CPDF_Dest destination(CPDFArrayFromFPDFDest(dest));
Lei Zhangaca3efc2018-03-16 20:27:04 +0000215 return destination.GetPageIndexDeprecated(pDoc);
Henrique Nakashima71a7d372018-02-01 17:07:13 +0000216}
217
Henrique Nakashimae899dd72018-02-01 19:17:04 +0000218FPDF_EXPORT int FPDF_CALLCONV FPDFDest_GetDestPageIndex(FPDF_DOCUMENT document,
Lei Zhangaca3efc2018-03-16 20:27:04 +0000219 FPDF_DEST dest) {
220 if (!dest)
Henrique Nakashima71a7d372018-02-01 17:07:13 +0000221 return -1;
222
223 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
224 if (!pDoc)
225 return -1;
226
Tom Sepez525147a2018-05-03 17:19:53 +0000227 CPDF_Dest destination(CPDFArrayFromFPDFDest(dest));
Lei Zhangaca3efc2018-03-16 20:27:04 +0000228 return destination.GetDestPageIndex(pDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700229}
230
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500231FPDF_EXPORT unsigned long FPDF_CALLCONV
Lei Zhang326c38c2018-01-10 20:10:05 +0000232FPDFDest_GetView(FPDF_DEST pDict,
233 unsigned long* pNumParams,
234 FS_FLOAT* pParams) {
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500235 if (!pDict) {
Lei Zhang326c38c2018-01-10 20:10:05 +0000236 *pNumParams = 0;
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500237 return 0;
238 }
239
Tom Sepez525147a2018-05-03 17:19:53 +0000240 CPDF_Dest destination(CPDFArrayFromFPDFDest(pDict));
Lei Zhang11767d32018-03-21 18:59:44 +0000241 unsigned long nParams = destination.GetNumParams();
Lei Zhang326c38c2018-01-10 20:10:05 +0000242 ASSERT(nParams <= 4);
243 *pNumParams = nParams;
244 for (unsigned long i = 0; i < nParams; ++i)
Lei Zhang11767d32018-03-21 18:59:44 +0000245 pParams[i] = destination.GetParam(i);
246 return destination.GetZoomMode();
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500247}
248
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400249FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
250FPDFDest_GetLocationInPage(FPDF_DEST pDict,
251 FPDF_BOOL* hasXVal,
252 FPDF_BOOL* hasYVal,
253 FPDF_BOOL* hasZoomVal,
254 FS_FLOAT* x,
255 FS_FLOAT* y,
256 FS_FLOAT* zoom) {
dsinclairc59fa882016-11-08 06:55:40 -0800257 if (!pDict)
258 return false;
259
Tom Sepez525147a2018-05-03 17:19:53 +0000260 auto dest = pdfium::MakeUnique<CPDF_Dest>(CPDFArrayFromFPDFDest(pDict));
dsinclairc59fa882016-11-08 06:55:40 -0800261
262 // FPDF_BOOL is an int, GetXYZ expects bools.
263 bool bHasX;
264 bool bHasY;
265 bool bHasZoom;
266 if (!dest->GetXYZ(&bHasX, &bHasY, &bHasZoom, x, y, zoom))
267 return false;
268
269 *hasXVal = bHasX;
270 *hasYVal = bHasY;
271 *hasZoomVal = bHasZoom;
272 return true;
273}
274
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400275FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFLink_GetLinkAtPoint(FPDF_PAGE page,
276 double x,
277 double y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700278 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700279 if (!pPage)
280 return nullptr;
281
282 CPDF_LinkList* pLinkList = GetLinkList(pPage);
283 if (!pLinkList)
284 return nullptr;
285
Tom Sepez525147a2018-05-03 17:19:53 +0000286 CPDF_Link link = pLinkList->GetLinkAtPoint(
287 pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)), nullptr);
288
289 return FPDFLinkFromCPDFDictionary(link.GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700290}
291
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400292FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page,
293 double x,
294 double y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700295 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296 if (!pPage)
Lei Zhangbdf72c32015-08-14 19:24:08 -0700297 return -1;
298
299 CPDF_LinkList* pLinkList = GetLinkList(pPage);
300 if (!pLinkList)
301 return -1;
302
303 int z_order = -1;
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500304 pLinkList->GetLinkAtPoint(
Dan Sinclair05df0752017-03-14 14:43:42 -0400305 pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500306 &z_order);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700307 return z_order;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700308}
309
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400310FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFLink_GetDest(FPDF_DOCUMENT document,
311 FPDF_LINK pDict) {
Tom Sepez471a1032015-10-15 16:17:18 -0700312 if (!pDict)
Lei Zhange0947b32015-09-17 14:51:48 -0700313 return nullptr;
Tom Sepez471a1032015-10-15 16:17:18 -0700314 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
315 if (!pDoc)
316 return nullptr;
Lei Zhang11767d32018-03-21 18:59:44 +0000317 CPDF_Link link(CPDFDictionaryFromFPDFLink(pDict));
Tom Sepez525147a2018-05-03 17:19:53 +0000318 FPDF_DEST dest = FPDFDestFromCPDFArray(link.GetDest(pDoc).GetObject());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 if (dest)
320 return dest;
321 // If this link is not directly associated with a dest, we try to get action
322 CPDF_Action action = link.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800323 if (!action.GetDict())
Lei Zhange0947b32015-09-17 14:51:48 -0700324 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +0000325 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetObject());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700326}
327
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400328FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDFLink_GetAction(FPDF_LINK pDict) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329 if (!pDict)
Lei Zhange0947b32015-09-17 14:51:48 -0700330 return nullptr;
331
Lei Zhang11767d32018-03-21 18:59:44 +0000332 CPDF_Link link(CPDFDictionaryFromFPDFLink(pDict));
Tom Sepez525147a2018-05-03 17:19:53 +0000333 return FPDFActionFromCPDFDictionary(link.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700334}
335
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400336FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page,
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000337 int* start_pos,
338 FPDF_LINK* link_annot) {
339 if (!start_pos || !link_annot)
tsepez4cf55152016-11-02 14:37:54 -0700340 return false;
Tom Sepezdb0be962015-10-16 14:00:21 -0700341 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
342 if (!pPage || !pPage->m_pFormDict)
tsepez4cf55152016-11-02 14:37:54 -0700343 return false;
dsinclair38fd8442016-09-15 10:15:32 -0700344 CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345 if (!pAnnots)
tsepez4cf55152016-11-02 14:37:54 -0700346 return false;
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000347 for (size_t i = *start_pos; i < pAnnots->GetCount(); i++) {
Lei Zhang11767d32018-03-21 18:59:44 +0000348 CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i));
Dan Sinclairf1251c12015-10-20 16:24:45 -0400349 if (!pDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350 continue;
dsinclair38fd8442016-09-15 10:15:32 -0700351 if (pDict->GetStringFor("Subtype") == "Link") {
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000352 *start_pos = static_cast<int>(i + 1);
Tom Sepez525147a2018-05-03 17:19:53 +0000353 *link_annot = FPDFLinkFromCPDFDictionary(pDict);
tsepez4cf55152016-11-02 14:37:54 -0700354 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 }
356 }
tsepez4cf55152016-11-02 14:37:54 -0700357 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700358}
359
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000360FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK link_annot,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400361 FS_RECTF* rect) {
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000362 if (!link_annot || !rect)
tsepez4cf55152016-11-02 14:37:54 -0700363 return false;
Lei Zhang11767d32018-03-21 18:59:44 +0000364 CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFLink(link_annot);
Lei Zhang367e7de2017-10-31 13:32:17 +0000365 FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"), rect);
tsepez4cf55152016-11-02 14:37:54 -0700366 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367}
368
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000369FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK link_annot) {
Lei Zhangaaed6982018-03-22 18:39:05 +0000370 const CPDF_Array* pArray =
371 GetQuadPointsArrayFromDictionary(CPDFDictionaryFromFPDFLink(link_annot));
372 return pArray ? static_cast<int>(pArray->GetCount() / 8) : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700373}
374
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400375FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000376FPDFLink_GetQuadPoints(FPDF_LINK link_annot,
377 int quad_index,
378 FS_QUADPOINTSF* quad_points) {
Lei Zhangaaed6982018-03-22 18:39:05 +0000379 if (!quad_points || quad_index < 0)
tsepez4cf55152016-11-02 14:37:54 -0700380 return false;
Ralf Sippl16381792018-04-12 21:20:26 +0000381
382 CPDF_Dictionary* pLinkDict = CPDFDictionaryFromFPDFLink(link_annot);
383 if (!pLinkDict)
384 return false;
385
386 const CPDF_Array* pArray = GetQuadPointsArrayFromDictionary(pLinkDict);
387 if (!pArray)
388 return false;
389
390 return GetQuadPointsAtIndex(pArray, static_cast<size_t>(quad_index),
391 quad_points);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700392}
393
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400394FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetMetaText(FPDF_DOCUMENT document,
395 FPDF_BYTESTRING tag,
396 void* buffer,
397 unsigned long buflen) {
Tom Sepez471a1032015-10-15 16:17:18 -0700398 if (!tag)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700399 return 0;
thestig733e0682016-11-23 05:52:39 -0800400 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700401 if (!pDoc)
402 return 0;
Henrique Nakashimab73ce7b2017-06-19 16:04:34 -0400403 pDoc->LoadDocumentInfo();
Lei Zhang01581062017-08-30 14:19:26 -0700404 const CPDF_Dictionary* pInfo = pDoc->GetInfo();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405 if (!pInfo)
406 return 0;
Ryan Harrison275e2602017-09-18 14:23:18 -0400407 WideString text = pInfo->GetUnicodeTextFor(tag);
thestig733e0682016-11-23 05:52:39 -0800408 return Utf16EncodeMaybeCopyAndReturnLength(text, buffer, buflen);
409}
410
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400411FPDF_EXPORT unsigned long FPDF_CALLCONV
412FPDF_GetPageLabel(FPDF_DOCUMENT document,
413 int page_index,
414 void* buffer,
415 unsigned long buflen) {
thestig733e0682016-11-23 05:52:39 -0800416 if (page_index < 0)
417 return 0;
418
419 // CPDF_PageLabel can deal with NULL |document|.
420 CPDF_PageLabel label(CPDFDocumentFromFPDFDocument(document));
Ryan Harrison8eeee772018-01-05 13:39:22 -0500421 Optional<WideString> str = label.GetLabel(page_index);
422 return str.has_value()
423 ? Utf16EncodeMaybeCopyAndReturnLength(str.value(), buffer, buflen)
424 : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700425}