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/fpdfdoc/fpdf_doc.h"
8 #include "../../src/fxcrt/fx_safe_types.h"
9
~CPDF_LinkList()10 CPDF_LinkList::~CPDF_LinkList()
11 {
12 FX_POSITION pos = m_PageMap.GetStartPosition();
13 while (pos) {
14 FX_LPVOID key, value;
15 m_PageMap.GetNextAssoc(pos, key, value);
16 delete (CFX_PtrArray*)value;
17 }
18 }
GetPageLinks(CPDF_Page * pPage)19 CFX_PtrArray* CPDF_LinkList::GetPageLinks(CPDF_Page* pPage)
20 {
21 FX_DWORD objnum = pPage->m_pFormDict->GetObjNum();
22 if (objnum == 0) {
23 return NULL;
24 }
25 CFX_PtrArray* pPageLinkList = NULL;
26 if (!m_PageMap.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pPageLinkList)) {
27 pPageLinkList = new CFX_PtrArray;
28 m_PageMap.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pPageLinkList);
29 LoadPageLinks(pPage, pPageLinkList);
30 }
31 return pPageLinkList;
32 }
CountLinks(CPDF_Page * pPage)33 int CPDF_LinkList::CountLinks(CPDF_Page* pPage)
34 {
35 CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
36 if (pPageLinkList == NULL) {
37 return 0;
38 }
39 return pPageLinkList->GetSize();
40 }
GetLink(CPDF_Page * pPage,int index)41 CPDF_Link CPDF_LinkList::GetLink(CPDF_Page* pPage, int index)
42 {
43 CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
44 if (!pPageLinkList) {
45 return CPDF_Link();
46 }
47 return CPDF_Link((CPDF_Dictionary*)pPageLinkList->GetAt(index));
48 }
GetLinkAtPoint(CPDF_Page * pPage,FX_FLOAT pdf_x,FX_FLOAT pdf_y)49 CPDF_Link CPDF_LinkList::GetLinkAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y)
50 {
51 CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
52 if (!pPageLinkList) {
53 return CPDF_Link();
54 }
55 int size = pPageLinkList->GetSize();
56 for (int i = size - 1; i >= 0; --i) {
57 CPDF_Link link((CPDF_Dictionary*)pPageLinkList->GetAt(i));
58 CPDF_Rect rect = link.GetRect();
59 if (rect.Contains(pdf_x, pdf_y)) {
60 return link;
61 }
62 }
63 return CPDF_Link();
64 }
LoadPageLinks(CPDF_Page * pPage,CFX_PtrArray * pList)65 void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage, CFX_PtrArray* pList)
66 {
67 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
68 if (pAnnotList == NULL) {
69 return;
70 }
71 for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
72 CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
73 if (pAnnot == NULL) {
74 continue;
75 }
76 if (pAnnot->GetString("Subtype") != "Link") {
77 continue;
78 }
79 pList->Add(pAnnot);
80 }
81 }
GetRect()82 CPDF_Rect CPDF_Link::GetRect()
83 {
84 return m_pDict->GetRect("Rect");
85 }
GetDest(CPDF_Document * pDoc)86 CPDF_Dest CPDF_Link::GetDest(CPDF_Document* pDoc)
87 {
88 CPDF_Object* pDest = m_pDict->GetElementValue("Dest");
89 if (pDest == NULL) {
90 return CPDF_Dest();
91 }
92 if (pDest->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
93 CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
94 CFX_ByteStringC name = pDest->GetString();
95 return CPDF_Dest(name_tree.LookupNamedDest(pDoc, name));
96 }
97 if (pDest->GetType() == PDFOBJ_ARRAY) {
98 return CPDF_Dest((CPDF_Array*)pDest);
99 }
100 return CPDF_Dest();
101 }
GetAction()102 CPDF_Action CPDF_Link::GetAction()
103 {
104 return CPDF_Action(m_pDict->GetDict("A"));
105 }
106