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