blob: b0a2324a32ad92adb0e478b41d97f628951cc538 [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>
Tom Sepezd524d322019-05-28 21:52:27 +000011#include <utility>
Wei Li0e2e5d72016-03-03 11:28:06 -080012
dsinclair41872fa2016-10-04 11:29:35 -070013#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070014#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000015#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070016#include "core/fpdfapi/parser/cpdf_document.h"
Ralf Sippl16381792018-04-12 21:20:26 +000017#include "core/fpdfapi/parser/cpdf_number.h"
dsinclair1727aee2016-09-29 13:12:56 -070018#include "core/fpdfdoc/cpdf_bookmark.h"
19#include "core/fpdfdoc/cpdf_bookmarktree.h"
dsinclairc59fa882016-11-08 06:55:40 -080020#include "core/fpdfdoc/cpdf_dest.h"
Tom Sepezd524d322019-05-28 21:52:27 +000021#include "core/fpdfdoc/cpdf_linklist.h"
thestig733e0682016-11-23 05:52:39 -080022#include "core/fpdfdoc/cpdf_pagelabel.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000023#include "fpdfsdk/cpdfsdk_helpers.h"
tsepeza9caab92016-12-14 05:57:10 -080024#include "third_party/base/ptr_util.h"
Wei Li0e2e5d72016-03-03 11:28:06 -080025#include "third_party/base/stl_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070026
Lei Zhangbdf72c32015-08-14 19:24:08 -070027namespace {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070028
Lei Zhangbdf72c32015-08-14 19:24:08 -070029CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree,
30 CPDF_Bookmark bookmark,
Ryan Harrison275e2602017-09-18 14:23:18 -040031 const WideString& title,
Lei Zhang5cee3f22018-05-25 21:48:49 +000032 std::set<const CPDF_Dictionary*>* visited) {
Wei Li0e2e5d72016-03-03 11:28:06 -080033 // Return if already checked to avoid circular calling.
34 if (pdfium::ContainsKey(*visited, bookmark.GetDict()))
35 return CPDF_Bookmark();
36 visited->insert(bookmark.GetDict());
37
Wei Li0fc6b252016-03-01 16:29:41 -080038 if (bookmark.GetDict() &&
39 bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
Wei Li0e2e5d72016-03-03 11:28:06 -080040 // First check this item.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070041 return bookmark;
42 }
Wei Li0e2e5d72016-03-03 11:28:06 -080043
44 // Go into children items.
Tom Sepez22923602019-07-15 21:33:35 +000045 CPDF_Bookmark child = tree.GetFirstChild(&bookmark);
Wei Li0e2e5d72016-03-03 11:28:06 -080046 while (child.GetDict() && !pdfium::ContainsKey(*visited, child.GetDict())) {
47 // Check this item and its children.
48 CPDF_Bookmark found = FindBookmark(tree, child, title, visited);
Wei Li0fc6b252016-03-01 16:29:41 -080049 if (found.GetDict())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070050 return found;
Tom Sepez22923602019-07-15 21:33:35 +000051 child = tree.GetNextSibling(&child);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070052 }
53 return CPDF_Bookmark();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070054}
55
Lei Zhangbdf72c32015-08-14 19:24:08 -070056CPDF_LinkList* GetLinkList(CPDF_Page* page) {
Lei Zhang8f637632018-05-07 23:36:26 +000057 CPDF_Document* pDoc = page->GetDocument();
Tom Sepezd524d322019-05-28 21:52:27 +000058 auto* pList = static_cast<CPDF_LinkList*>(pDoc->GetLinksContext());
59 if (pList)
60 return pList;
61
62 auto pNewList = pdfium::MakeUnique<CPDF_LinkList>();
63 pList = pNewList.get();
64 pDoc->SetLinksContext(std::move(pNewList));
65 return pList;
Lei Zhangbdf72c32015-08-14 19:24:08 -070066}
67
Dan Sinclair7aba4722018-03-28 17:04:16 +000068} // namespace
Lei Zhangaaed6982018-03-22 18:39:05 +000069
Dan Sinclair00d2ad12017-08-10 14:13:02 -040070FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000071FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -070072 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
73 if (!pDoc)
74 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075 CPDF_BookmarkTree tree(pDoc);
Andrew Weintraubfe111d92019-06-24 17:19:20 +000076 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
77 return FPDFBookmarkFromCPDFDictionary(
Tom Sepez22923602019-07-15 21:33:35 +000078 tree.GetFirstChild(&cBookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080079}
80
Dan Sinclair00d2ad12017-08-10 14:13:02 -040081FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000082FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -070083 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
84 if (!pDoc)
85 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +000086
Andrew Weintraubfe111d92019-06-24 17:19:20 +000087 if (!bookmark)
Tom Sepez8c628832018-10-09 21:02:15 +000088 return nullptr;
89
Nico Weber9d8ec5a2015-08-04 13:00:21 -070090 CPDF_BookmarkTree tree(pDoc);
Andrew Weintraubfe111d92019-06-24 17:19:20 +000091 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
Tom Sepez525147a2018-05-03 17:19:53 +000092 return FPDFBookmarkFromCPDFDictionary(
Tom Sepez22923602019-07-15 21:33:35 +000093 tree.GetNextSibling(&cBookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080094}
95
Dan Sinclair00d2ad12017-08-10 14:13:02 -040096FPDF_EXPORT unsigned long FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000097FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark,
98 void* buffer,
99 unsigned long buflen) {
100 if (!bookmark)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700101 return 0;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000102 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
103 WideString title = cBookmark.GetTitle();
thestig733e0682016-11-23 05:52:39 -0800104 return Utf16EncodeMaybeCopyAndReturnLength(title, buffer, buflen);
Bo Xu4d62b6b2015-01-10 22:52:59 -0800105}
106
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400107FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
108FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) {
Tom Sepez471a1032015-10-15 16:17:18 -0700109 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
110 if (!pDoc)
111 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000112
Lei Zhangb46a7632019-01-09 02:56:16 +0000113 WideString encodedTitle = WideStringFromFPDFWideString(title);
114 if (encodedTitle.IsEmpty())
Tom Sepez8c628832018-10-09 21:02:15 +0000115 return nullptr;
116
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700117 CPDF_BookmarkTree tree(pDoc);
Lei Zhang5cee3f22018-05-25 21:48:49 +0000118 std::set<const CPDF_Dictionary*> visited;
Tom Sepez525147a2018-05-03 17:19:53 +0000119 return FPDFBookmarkFromCPDFDictionary(
120 FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700121}
122
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000123FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
124FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -0700125 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
126 if (!pDoc)
127 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000128
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000129 if (!bookmark)
Tom Sepez8c628832018-10-09 21:02:15 +0000130 return nullptr;
131
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000132 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
133 CPDF_Dest dest = cBookmark.GetDest(pDoc);
Lei Zhang76525c42018-08-27 18:57:36 +0000134 if (dest.GetArray())
135 return FPDFDestFromCPDFArray(dest.GetArray());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136 // If this bookmark is not directly associated with a dest, we try to get
137 // action
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000138 CPDF_Action action = cBookmark.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800139 if (!action.GetDict())
Tom Sepez471a1032015-10-15 16:17:18 -0700140 return nullptr;
Lei Zhang76525c42018-08-27 18:57:36 +0000141 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700142}
143
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400144FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000145FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark) {
146 if (!bookmark)
thestig1cd352e2016-06-07 17:53:06 -0700147 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000148
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000149 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
150 return FPDFActionFromCPDFDictionary(cBookmark.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700151}
152
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000153FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION action) {
154 if (!action)
Lei Zhange0947b32015-09-17 14:51:48 -0700155 return PDFACTION_UNSUPPORTED;
156
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000157 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
158 CPDF_Action::ActionType type = cAction.GetType();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700159 switch (type) {
160 case CPDF_Action::GoTo:
161 return PDFACTION_GOTO;
162 case CPDF_Action::GoToR:
163 return PDFACTION_REMOTEGOTO;
164 case CPDF_Action::URI:
165 return PDFACTION_URI;
166 case CPDF_Action::Launch:
167 return PDFACTION_LAUNCH;
168 default:
169 return PDFACTION_UNSUPPORTED;
170 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700171}
172
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400173FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFAction_GetDest(FPDF_DOCUMENT document,
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000174 FPDF_ACTION action) {
Tom Sepez471a1032015-10-15 16:17:18 -0700175 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
176 if (!pDoc)
177 return nullptr;
Tom Sepez7bf81642018-10-10 17:27:33 +0000178
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000179 unsigned long type = FPDFAction_GetType(action);
Tom Sepez7bf81642018-10-10 17:27:33 +0000180 if (type != PDFACTION_GOTO && type != PDFACTION_REMOTEGOTO)
181 return nullptr;
182
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000183 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
184 return FPDFDestFromCPDFArray(cAction.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700185}
186
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400187FPDF_EXPORT unsigned long FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000188FPDFAction_GetFilePath(FPDF_ACTION action, void* buffer, unsigned long buflen) {
189 unsigned long type = FPDFAction_GetType(action);
Lei Zhange0947b32015-09-17 14:51:48 -0700190 if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_LAUNCH)
191 return 0;
192
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000193 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
194 ByteString path = cAction.GetFilePath().ToUTF8();
Lei Zhange0947b32015-09-17 14:51:48 -0700195 unsigned long len = path.GetLength() + 1;
thestig9067fd62016-11-23 14:10:06 -0800196 if (buffer && len <= buflen)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400197 memcpy(buffer, path.c_str(), len);
Lei Zhange0947b32015-09-17 14:51:48 -0700198 return len;
199}
200
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400201FPDF_EXPORT unsigned long FPDF_CALLCONV
202FPDFAction_GetURIPath(FPDF_DOCUMENT document,
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000203 FPDF_ACTION action,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400204 void* buffer,
205 unsigned long buflen) {
Tom Sepez471a1032015-10-15 16:17:18 -0700206 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
207 if (!pDoc)
208 return 0;
Tom Sepez7bf81642018-10-10 17:27:33 +0000209
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000210 unsigned long type = FPDFAction_GetType(action);
Tom Sepez7bf81642018-10-10 17:27:33 +0000211 if (type != PDFACTION_URI)
212 return 0;
213
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000214 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
215 ByteString path = cAction.GetURI(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216 unsigned long len = path.GetLength() + 1;
thestig9067fd62016-11-23 14:10:06 -0800217 if (buffer && len <= buflen)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400218 memcpy(buffer, path.c_str(), len);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700219 return len;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700220}
221
Henrique Nakashimae899dd72018-02-01 19:17:04 +0000222FPDF_EXPORT int FPDF_CALLCONV FPDFDest_GetDestPageIndex(FPDF_DOCUMENT document,
Lei Zhangaca3efc2018-03-16 20:27:04 +0000223 FPDF_DEST dest) {
Henrique Nakashima71a7d372018-02-01 17:07:13 +0000224 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
225 if (!pDoc)
226 return -1;
227
Tom Sepez69c32852018-10-09 21:42:39 +0000228 if (!dest)
229 return -1;
230
Tom Sepez525147a2018-05-03 17:19:53 +0000231 CPDF_Dest destination(CPDFArrayFromFPDFDest(dest));
Lei Zhangaca3efc2018-03-16 20:27:04 +0000232 return destination.GetDestPageIndex(pDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700233}
234
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500235FPDF_EXPORT unsigned long FPDF_CALLCONV
Lei Zhang537d3a62019-12-13 17:39:38 +0000236FPDFDest_GetView(FPDF_DEST dest, unsigned long* pNumParams, FS_FLOAT* pParams) {
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000237 if (!dest) {
Lei Zhang326c38c2018-01-10 20:10:05 +0000238 *pNumParams = 0;
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500239 return 0;
240 }
241
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000242 CPDF_Dest destination(CPDFArrayFromFPDFDest(dest));
Lei Zhang11767d32018-03-21 18:59:44 +0000243 unsigned long nParams = destination.GetNumParams();
Lei Zhang326c38c2018-01-10 20:10:05 +0000244 ASSERT(nParams <= 4);
245 *pNumParams = nParams;
246 for (unsigned long i = 0; i < nParams; ++i)
Lei Zhang11767d32018-03-21 18:59:44 +0000247 pParams[i] = destination.GetParam(i);
248 return destination.GetZoomMode();
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500249}
250
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400251FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000252FPDFDest_GetLocationInPage(FPDF_DEST dest,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400253 FPDF_BOOL* hasXVal,
254 FPDF_BOOL* hasYVal,
255 FPDF_BOOL* hasZoomVal,
256 FS_FLOAT* x,
257 FS_FLOAT* y,
258 FS_FLOAT* zoom) {
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000259 if (!dest)
dsinclairc59fa882016-11-08 06:55:40 -0800260 return false;
261
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000262 auto destination = pdfium::MakeUnique<CPDF_Dest>(CPDFArrayFromFPDFDest(dest));
dsinclairc59fa882016-11-08 06:55:40 -0800263
264 // FPDF_BOOL is an int, GetXYZ expects bools.
265 bool bHasX;
266 bool bHasY;
267 bool bHasZoom;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000268 if (!destination->GetXYZ(&bHasX, &bHasY, &bHasZoom, x, y, zoom))
dsinclairc59fa882016-11-08 06:55:40 -0800269 return false;
270
271 *hasXVal = bHasX;
272 *hasYVal = bHasY;
273 *hasZoomVal = bHasZoom;
274 return true;
275}
276
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400277FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFLink_GetLinkAtPoint(FPDF_PAGE page,
278 double x,
279 double y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700280 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700281 if (!pPage)
282 return nullptr;
283
284 CPDF_LinkList* pLinkList = GetLinkList(pPage);
285 if (!pLinkList)
286 return nullptr;
287
Tom Sepez525147a2018-05-03 17:19:53 +0000288 CPDF_Link link = pLinkList->GetLinkAtPoint(
289 pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)), nullptr);
290
291 return FPDFLinkFromCPDFDictionary(link.GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700292}
293
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400294FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page,
295 double x,
296 double y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700297 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700298 if (!pPage)
Lei Zhangbdf72c32015-08-14 19:24:08 -0700299 return -1;
300
301 CPDF_LinkList* pLinkList = GetLinkList(pPage);
302 if (!pLinkList)
303 return -1;
304
305 int z_order = -1;
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500306 pLinkList->GetLinkAtPoint(
Dan Sinclair05df0752017-03-14 14:43:42 -0400307 pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500308 &z_order);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700309 return z_order;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700310}
311
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400312FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFLink_GetDest(FPDF_DOCUMENT document,
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000313 FPDF_LINK link) {
314 if (!link)
Lei Zhange0947b32015-09-17 14:51:48 -0700315 return nullptr;
Tom Sepez471a1032015-10-15 16:17:18 -0700316 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
317 if (!pDoc)
318 return nullptr;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000319 CPDF_Link cLink(CPDFDictionaryFromFPDFLink(link));
320 FPDF_DEST dest = FPDFDestFromCPDFArray(cLink.GetDest(pDoc).GetArray());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700321 if (dest)
322 return dest;
323 // If this link is not directly associated with a dest, we try to get action
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000324 CPDF_Action action = cLink.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800325 if (!action.GetDict())
Lei Zhange0947b32015-09-17 14:51:48 -0700326 return nullptr;
Lei Zhang76525c42018-08-27 18:57:36 +0000327 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700328}
329
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000330FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDFLink_GetAction(FPDF_LINK link) {
331 if (!link)
Lei Zhange0947b32015-09-17 14:51:48 -0700332 return nullptr;
333
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000334 CPDF_Link cLink(CPDFDictionaryFromFPDFLink(link));
335 return FPDFActionFromCPDFDictionary(cLink.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700336}
337
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400338FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page,
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000339 int* start_pos,
340 FPDF_LINK* link_annot) {
341 if (!start_pos || !link_annot)
tsepez4cf55152016-11-02 14:37:54 -0700342 return false;
Tom Sepezdb0be962015-10-16 14:00:21 -0700343 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhang197d4982019-08-09 21:40:49 +0000344 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -0700345 return false;
Henrique Nakashima888af472018-06-07 19:43:42 +0000346 CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700347 if (!pAnnots)
tsepez4cf55152016-11-02 14:37:54 -0700348 return false;
Lei Zhangf40380f2018-10-12 18:31:51 +0000349 for (size_t i = *start_pos; i < pAnnots->size(); i++) {
Lei Zhang11767d32018-03-21 18:59:44 +0000350 CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i));
Dan Sinclairf1251c12015-10-20 16:24:45 -0400351 if (!pDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700352 continue;
dsinclair38fd8442016-09-15 10:15:32 -0700353 if (pDict->GetStringFor("Subtype") == "Link") {
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000354 *start_pos = static_cast<int>(i + 1);
Tom Sepez525147a2018-05-03 17:19:53 +0000355 *link_annot = FPDFLinkFromCPDFDictionary(pDict);
tsepez4cf55152016-11-02 14:37:54 -0700356 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357 }
358 }
tsepez4cf55152016-11-02 14:37:54 -0700359 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700360}
361
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000362FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK link_annot,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400363 FS_RECTF* rect) {
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000364 if (!link_annot || !rect)
tsepez4cf55152016-11-02 14:37:54 -0700365 return false;
Lei Zhang3567c612019-11-18 18:10:02 +0000366
Lei Zhang11767d32018-03-21 18:59:44 +0000367 CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFLink(link_annot);
Lei Zhang8da98232019-12-11 23:29:33 +0000368 *rect = FSRectFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"));
tsepez4cf55152016-11-02 14:37:54 -0700369 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370}
371
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000372FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK link_annot) {
Lei Zhangaaed6982018-03-22 18:39:05 +0000373 const CPDF_Array* pArray =
374 GetQuadPointsArrayFromDictionary(CPDFDictionaryFromFPDFLink(link_annot));
Lei Zhangf40380f2018-10-12 18:31:51 +0000375 return pArray ? static_cast<int>(pArray->size() / 8) : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376}
377
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400378FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000379FPDFLink_GetQuadPoints(FPDF_LINK link_annot,
380 int quad_index,
381 FS_QUADPOINTSF* quad_points) {
Lei Zhangaaed6982018-03-22 18:39:05 +0000382 if (!quad_points || quad_index < 0)
tsepez4cf55152016-11-02 14:37:54 -0700383 return false;
Ralf Sippl16381792018-04-12 21:20:26 +0000384
Lei Zhangeda4e7a2019-03-22 21:26:24 +0000385 const CPDF_Dictionary* pLinkDict = CPDFDictionaryFromFPDFLink(link_annot);
Ralf Sippl16381792018-04-12 21:20:26 +0000386 if (!pLinkDict)
387 return false;
388
389 const CPDF_Array* pArray = GetQuadPointsArrayFromDictionary(pLinkDict);
390 if (!pArray)
391 return false;
392
393 return GetQuadPointsAtIndex(pArray, static_cast<size_t>(quad_index),
394 quad_points);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700395}
396
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400397FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetMetaText(FPDF_DOCUMENT document,
398 FPDF_BYTESTRING tag,
399 void* buffer,
400 unsigned long buflen) {
Tom Sepez471a1032015-10-15 16:17:18 -0700401 if (!tag)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 return 0;
thestig733e0682016-11-23 05:52:39 -0800403 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700404 if (!pDoc)
405 return 0;
Artem Strygina3270302018-06-22 12:45:14 +0000406
Lei Zhang01581062017-08-30 14:19:26 -0700407 const CPDF_Dictionary* pInfo = pDoc->GetInfo();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700408 if (!pInfo)
409 return 0;
Ryan Harrison275e2602017-09-18 14:23:18 -0400410 WideString text = pInfo->GetUnicodeTextFor(tag);
thestig733e0682016-11-23 05:52:39 -0800411 return Utf16EncodeMaybeCopyAndReturnLength(text, buffer, buflen);
412}
413
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400414FPDF_EXPORT unsigned long FPDF_CALLCONV
415FPDF_GetPageLabel(FPDF_DOCUMENT document,
416 int page_index,
417 void* buffer,
418 unsigned long buflen) {
thestig733e0682016-11-23 05:52:39 -0800419 if (page_index < 0)
420 return 0;
421
422 // CPDF_PageLabel can deal with NULL |document|.
423 CPDF_PageLabel label(CPDFDocumentFromFPDFDocument(document));
Ryan Harrison8eeee772018-01-05 13:39:22 -0500424 Optional<WideString> str = label.GetLabel(page_index);
425 return str.has_value()
426 ? Utf16EncodeMaybeCopyAndReturnLength(str.value(), buffer, buflen)
427 : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700428}