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 "core/include/fpdfdoc/fpdf_doc.h" 8 9CPDF_LinkList::CPDF_LinkList() { 10} 11 12CPDF_LinkList::~CPDF_LinkList() { 13} 14 15const std::vector<CPDF_Dictionary*>* CPDF_LinkList::GetPageLinks( 16 CPDF_Page* pPage) { 17 FX_DWORD objnum = pPage->m_pFormDict->GetObjNum(); 18 if (objnum == 0) 19 return nullptr; 20 21 auto it = m_PageMap.find(objnum); 22 if (it != m_PageMap.end()) 23 return &it->second; 24 25 // std::map::operator[] forces the creation of a map entry. 26 std::vector<CPDF_Dictionary*>& page_link_list = m_PageMap[objnum]; 27 LoadPageLinks(pPage, &page_link_list); 28 return &page_link_list; 29} 30 31CPDF_Link CPDF_LinkList::GetLinkAtPoint(CPDF_Page* pPage, 32 FX_FLOAT pdf_x, 33 FX_FLOAT pdf_y, 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 CPDF_Rect rect = link.GetRect(); 47 if (!rect.Contains(pdf_x, pdf_y)) 48 continue; 49 50 if (z_order) 51 *z_order = annot_index; 52 return link; 53 } 54 return CPDF_Link(); 55} 56 57void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage, 58 std::vector<CPDF_Dictionary*>* pList) { 59 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); 60 if (!pAnnotList) 61 return; 62 63 for (FX_DWORD i = 0; i < pAnnotList->GetCount(); ++i) { 64 CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i); 65 bool add_link = (pAnnot && pAnnot->GetString("Subtype") == "Link"); 66 // Add non-links as nullptrs to preserve z-order. 67 pList->push_back(add_link ? pAnnot : nullptr); 68 } 69} 70 71CPDF_Rect CPDF_Link::GetRect() { 72 return m_pDict->GetRect("Rect"); 73} 74CPDF_Dest CPDF_Link::GetDest(CPDF_Document* pDoc) { 75 CPDF_Object* pDest = m_pDict->GetElementValue("Dest"); 76 if (!pDest) 77 return CPDF_Dest(); 78 79 if (pDest->IsString() || pDest->IsName()) { 80 CPDF_NameTree name_tree(pDoc, "Dests"); 81 CFX_ByteStringC name = pDest->GetString(); 82 return CPDF_Dest(name_tree.LookupNamedDest(pDoc, name)); 83 } 84 if (CPDF_Array* pArray = pDest->AsArray()) 85 return CPDF_Dest(pArray); 86 return CPDF_Dest(); 87} 88CPDF_Action CPDF_Link::GetAction() { 89 return CPDF_Action(m_pDict->GetDict("A")); 90} 91