Merge to XFA: Make conversion between CPDF_Action and its dictionary explicit.
[pdfium.git] / core / src / fpdfdoc / doc_link.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/fpdfdoc/fpdf_doc.h"
8 #include "../../src/fxcrt/fx_safe_types.h"
9
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 }
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 = FX_NEW CFX_PtrArray;
28         if (pPageLinkList == NULL) {
29             return NULL;
30         }
31         m_PageMap.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pPageLinkList);
32         LoadPageLinks(pPage, pPageLinkList);
33     }
34     return pPageLinkList;
35 }
36 int CPDF_LinkList::CountLinks(CPDF_Page* pPage)
37 {
38     CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
39     if (pPageLinkList == NULL) {
40         return 0;
41     }
42     return pPageLinkList->GetSize();
43 }
44 CPDF_Link CPDF_LinkList::GetLink(CPDF_Page* pPage, int index)
45 {
46     CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
47     if (pPageLinkList == NULL) {
48         return NULL;
49     }
50     return (CPDF_Dictionary*)pPageLinkList->GetAt(index);
51 }
52 CPDF_Link CPDF_LinkList::GetLinkAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y)
53 {
54     CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
55     if (pPageLinkList == NULL) {
56         return NULL;
57     }
58     int size = pPageLinkList->GetSize();
59     for (int i = size - 1; i >= 0; --i) {
60         CPDF_Link Link = (CPDF_Dictionary*)pPageLinkList->GetAt(i);
61         CPDF_Rect rect = Link.GetRect();
62         if (rect.Contains(pdf_x, pdf_y)) {
63             return Link;
64         }
65     }
66     return NULL;
67 }
68 void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage, CFX_PtrArray* pList)
69 {
70     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
71     if (pAnnotList == NULL) {
72         return;
73     }
74     for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
75         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
76         if (pAnnot == NULL) {
77             continue;
78         }
79         if (pAnnot->GetString("Subtype") != "Link") {
80             continue;
81         }
82         pList->Add(pAnnot);
83     }
84 }
85 CPDF_Rect CPDF_Link::GetRect()
86 {
87     return m_pDict->GetRect("Rect");
88 }
89 CPDF_Dest CPDF_Link::GetDest(CPDF_Document* pDoc)
90 {
91     CPDF_Object* pDest = m_pDict->GetElementValue("Dest");
92     if (pDest == NULL) {
93         return NULL;
94     }
95     if (pDest->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
96         CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
97         CFX_ByteStringC name = pDest->GetString();
98         return name_tree.LookupNamedDest(pDoc, name);
99     } else if (pDest->GetType() == PDFOBJ_ARRAY) {
100         return (CPDF_Array*)pDest;
101     }
102     return NULL;
103 }
104 CPDF_Action CPDF_Link::GetAction()
105 {
106     return CPDF_Action(m_pDict->GetDict("A"));
107 }