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