• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "core/fpdfdoc/cpdf_linklist.h"
8 
9 #include "core/fpdfapi/page/cpdf_page.h"
10 #include "core/fpdfapi/parser/cpdf_array.h"
11 #include "core/fpdfapi/parser/cpdf_dictionary.h"
12 
13 CPDF_LinkList::CPDF_LinkList() = default;
14 
15 CPDF_LinkList::~CPDF_LinkList() = default;
16 
GetPageLinks(CPDF_Page * pPage)17 const std::vector<CPDF_Dictionary*>* CPDF_LinkList::GetPageLinks(
18     CPDF_Page* pPage) {
19   uint32_t objnum = pPage->GetDict()->GetObjNum();
20   if (objnum == 0)
21     return nullptr;
22 
23   auto it = m_PageMap.find(objnum);
24   if (it != m_PageMap.end())
25     return &it->second;
26 
27   // std::map::operator[] forces the creation of a map entry.
28   std::vector<CPDF_Dictionary*>& page_link_list = m_PageMap[objnum];
29   LoadPageLinks(pPage, &page_link_list);
30   return &page_link_list;
31 }
32 
GetLinkAtPoint(CPDF_Page * pPage,const CFX_PointF & point,int * z_order)33 CPDF_Link CPDF_LinkList::GetLinkAtPoint(CPDF_Page* pPage,
34                                         const CFX_PointF& point,
35                                         int* z_order) {
36   const std::vector<CPDF_Dictionary*>* pPageLinkList = GetPageLinks(pPage);
37   if (!pPageLinkList)
38     return CPDF_Link();
39 
40   for (size_t i = pPageLinkList->size(); i > 0; --i) {
41     size_t annot_index = i - 1;
42     CPDF_Dictionary* pAnnot = (*pPageLinkList)[annot_index];
43     if (!pAnnot)
44       continue;
45 
46     CPDF_Link link(pAnnot);
47     if (!link.GetRect().Contains(point))
48       continue;
49 
50     if (z_order)
51       *z_order = annot_index;
52     return link;
53   }
54   return CPDF_Link();
55 }
56 
LoadPageLinks(CPDF_Page * pPage,std::vector<CPDF_Dictionary * > * pList)57 void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage,
58                                   std::vector<CPDF_Dictionary*>* pList) {
59   CPDF_Array* pAnnotList = pPage->GetDict()->GetArrayFor("Annots");
60   if (!pAnnotList)
61     return;
62 
63   for (size_t i = 0; i < pAnnotList->size(); ++i) {
64     CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(i);
65     bool add_link = (pAnnot && pAnnot->GetStringFor("Subtype") == "Link");
66     // Add non-links as nullptrs to preserve z-order.
67     pList->push_back(add_link ? pAnnot : nullptr);
68   }
69 }
70