xref: /aosp_15_r20/external/pdfium/core/fpdfdoc/cpdf_linklist.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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)20 CPDF_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)45 const 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