• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dest.h"
8 
9 #include <algorithm>
10 #include <iterator>
11 #include <utility>
12 
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_document.h"
15 #include "core/fpdfapi/parser/cpdf_name.h"
16 #include "core/fpdfapi/parser/cpdf_number.h"
17 #include "core/fpdfdoc/cpdf_nametree.h"
18 #include "core/fxcrt/stl_util.h"
19 
20 namespace {
21 
22 // These arrays are indexed by the PDFDEST_VIEW_* constants.
23 
24 constexpr auto kZoomModes =
25     fxcrt::ToArray<const char*>({"Unknown", "XYZ", "Fit", "FitH", "FitV",
26                                  "FitR", "FitB", "FitBH", "FitBV"});
27 
28 constexpr auto kZoomModeMaxParamCount =
29     fxcrt::ToArray<const uint8_t>({0, 3, 0, 1, 1, 4, 0, 1, 1});
30 
31 }  // namespace
32 
CPDF_Dest(RetainPtr<const CPDF_Array> pArray)33 CPDF_Dest::CPDF_Dest(RetainPtr<const CPDF_Array> pArray)
34     : m_pArray(std::move(pArray)) {}
35 
36 CPDF_Dest::CPDF_Dest(const CPDF_Dest& that) = default;
37 
38 CPDF_Dest::~CPDF_Dest() = default;
39 
40 // static
Create(CPDF_Document * pDoc,RetainPtr<const CPDF_Object> pDest)41 CPDF_Dest CPDF_Dest::Create(CPDF_Document* pDoc,
42                             RetainPtr<const CPDF_Object> pDest) {
43   if (!pDest)
44     return CPDF_Dest(nullptr);
45 
46   if (pDest->IsString() || pDest->IsName())
47     return CPDF_Dest(CPDF_NameTree::LookupNamedDest(pDoc, pDest->GetString()));
48 
49   return CPDF_Dest(ToArray(pDest));
50 }
51 
GetDestPageIndex(CPDF_Document * pDoc) const52 int CPDF_Dest::GetDestPageIndex(CPDF_Document* pDoc) const {
53   if (!m_pArray)
54     return -1;
55 
56   RetainPtr<const CPDF_Object> pPage = m_pArray->GetDirectObjectAt(0);
57   if (!pPage)
58     return -1;
59 
60   if (pPage->IsNumber())
61     return pPage->GetInteger();
62 
63   if (!pPage->IsDictionary())
64     return -1;
65 
66   return pDoc->GetPageIndex(pPage->GetObjNum());
67 }
68 
GetScrollPositionArray() const69 std::vector<float> CPDF_Dest::GetScrollPositionArray() const {
70   std::vector<float> result;
71   if (m_pArray) {
72     // Skip over index 0 which contains destination page details, and index 1
73     // which contains a parameter that describes the rest of the array.
74     for (size_t i = 2; i < m_pArray->size(); i++)
75       result.push_back(m_pArray->GetFloatAt(i));
76   }
77   return result;
78 }
79 
GetZoomMode() const80 int CPDF_Dest::GetZoomMode() const {
81   if (!m_pArray) {
82     return 0;
83   }
84   RetainPtr<const CPDF_Object> pArray = m_pArray->GetDirectObjectAt(1);
85   if (!pArray) {
86     return 0;
87   }
88   ByteString mode = pArray->GetString();
89   for (size_t i = 1; i < std::size(kZoomModes); ++i) {
90     if (mode == kZoomModes[i]) {
91       return static_cast<int>(i);
92     }
93   }
94   return 0;
95 }
96 
GetXYZ(bool * pHasX,bool * pHasY,bool * pHasZoom,float * pX,float * pY,float * pZoom) const97 bool CPDF_Dest::GetXYZ(bool* pHasX,
98                        bool* pHasY,
99                        bool* pHasZoom,
100                        float* pX,
101                        float* pY,
102                        float* pZoom) const {
103   *pHasX = false;
104   *pHasY = false;
105   *pHasZoom = false;
106 
107   if (!m_pArray)
108     return false;
109 
110   if (m_pArray->size() < 5)
111     return false;
112 
113   RetainPtr<const CPDF_Name> xyz = ToName(m_pArray->GetDirectObjectAt(1));
114   if (!xyz || xyz->GetString() != "XYZ")
115     return false;
116 
117   RetainPtr<const CPDF_Number> numX = ToNumber(m_pArray->GetDirectObjectAt(2));
118   RetainPtr<const CPDF_Number> numY = ToNumber(m_pArray->GetDirectObjectAt(3));
119   RetainPtr<const CPDF_Number> numZoom =
120       ToNumber(m_pArray->GetDirectObjectAt(4));
121 
122   // If the value is a CPDF_Null then ToNumber will return nullptr.
123   *pHasX = !!numX;
124   *pHasY = !!numY;
125   *pHasZoom = !!numZoom;
126 
127   if (numX)
128     *pX = numX->GetNumber();
129   if (numY)
130     *pY = numY->GetNumber();
131 
132   // A zoom value of 0 is equivalent to a null value, so treat it as a null.
133   if (numZoom) {
134     float num = numZoom->GetNumber();
135     if (num == 0.0)
136       *pHasZoom = false;
137     else
138       *pZoom = num;
139   }
140 
141   return true;
142 }
143 
GetNumParams() const144 size_t CPDF_Dest::GetNumParams() const {
145   if (!m_pArray || m_pArray->size() < 2)
146     return 0;
147 
148   size_t maxParamsForFitType = kZoomModeMaxParamCount[GetZoomMode()];
149   size_t numParamsInArray = m_pArray->size() - 2;
150   return std::min(maxParamsForFitType, numParamsInArray);
151 }
152 
GetParam(size_t index) const153 float CPDF_Dest::GetParam(size_t index) const {
154   return m_pArray ? m_pArray->GetFloatAt(2 + index) : 0;
155 }
156