• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dest.h"
8 
9 #include <algorithm>
10 
11 #include "core/fpdfapi/parser/cpdf_array.h"
12 #include "core/fpdfapi/parser/cpdf_document.h"
13 #include "core/fpdfapi/parser/cpdf_name.h"
14 #include "core/fpdfapi/parser/cpdf_number.h"
15 
16 namespace {
17 
18 // These arrays are indexed by the PDFDEST_VIEW_* constants.
19 
20 // Last element is a sentinel.
21 const char* const g_sZoomModes[] = {"Unknown", "XYZ",  "Fit",  "FitH",
22                                     "FitV",    "FitR", "FitB", "FitBH",
23                                     "FitBV",   nullptr};
24 
25 const uint8_t g_sZoomModeMaxParamCount[] = {0, 3, 0, 1, 1, 4, 0, 1, 1, 0};
26 
27 static_assert(FX_ArraySize(g_sZoomModes) ==
28                   FX_ArraySize(g_sZoomModeMaxParamCount),
29               "Zoom mode count Mismatch");
30 
31 }  // namespace
32 
CPDF_Dest()33 CPDF_Dest::CPDF_Dest() {}
34 
35 CPDF_Dest::CPDF_Dest(const CPDF_Dest& pObj) = default;
36 
CPDF_Dest(CPDF_Object * pObj)37 CPDF_Dest::CPDF_Dest(CPDF_Object* pObj) : m_pObj(pObj) {}
38 
~CPDF_Dest()39 CPDF_Dest::~CPDF_Dest() {}
40 
GetPageIndex(CPDF_Document * pDoc) const41 int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc) const {
42   CPDF_Array* pArray = ToArray(m_pObj.Get());
43   if (!pArray)
44     return 0;
45 
46   CPDF_Object* pPage = pArray->GetDirectObjectAt(0);
47   if (!pPage)
48     return 0;
49   if (pPage->IsNumber())
50     return pPage->GetInteger();
51   if (!pPage->IsDictionary())
52     return 0;
53   return pDoc->GetPageIndex(pPage->GetObjNum());
54 }
55 
GetPageObjNum() const56 uint32_t CPDF_Dest::GetPageObjNum() const {
57   CPDF_Array* pArray = ToArray(m_pObj.Get());
58   if (!pArray)
59     return 0;
60 
61   CPDF_Object* pPage = pArray->GetDirectObjectAt(0);
62   if (!pPage)
63     return 0;
64   if (pPage->IsNumber())
65     return pPage->GetInteger();
66   if (pPage->IsDictionary())
67     return pPage->GetObjNum();
68   return 0;
69 }
70 
GetZoomMode() const71 int CPDF_Dest::GetZoomMode() const {
72   CPDF_Array* pArray = ToArray(m_pObj.Get());
73   if (!pArray)
74     return 0;
75 
76   CPDF_Object* pObj = pArray->GetDirectObjectAt(1);
77   if (!pObj)
78     return 0;
79 
80   ByteString mode = pObj->GetString();
81   for (int i = 1; g_sZoomModes[i]; ++i) {
82     if (mode == g_sZoomModes[i])
83       return i;
84   }
85 
86   return 0;
87 }
88 
GetXYZ(bool * pHasX,bool * pHasY,bool * pHasZoom,float * pX,float * pY,float * pZoom) const89 bool CPDF_Dest::GetXYZ(bool* pHasX,
90                        bool* pHasY,
91                        bool* pHasZoom,
92                        float* pX,
93                        float* pY,
94                        float* pZoom) const {
95   *pHasX = false;
96   *pHasY = false;
97   *pHasZoom = false;
98 
99   CPDF_Array* pArray = ToArray(m_pObj.Get());
100   if (!pArray)
101     return false;
102 
103   if (pArray->GetCount() < 5)
104     return false;
105 
106   const CPDF_Name* xyz = ToName(pArray->GetDirectObjectAt(1));
107   if (!xyz || xyz->GetString() != "XYZ")
108     return false;
109 
110   const CPDF_Number* numX = ToNumber(pArray->GetDirectObjectAt(2));
111   const CPDF_Number* numY = ToNumber(pArray->GetDirectObjectAt(3));
112   const CPDF_Number* numZoom = ToNumber(pArray->GetDirectObjectAt(4));
113 
114   // If the value is a CPDF_Null then ToNumber will return nullptr.
115   *pHasX = !!numX;
116   *pHasY = !!numY;
117   *pHasZoom = !!numZoom;
118 
119   if (numX)
120     *pX = numX->GetNumber();
121   if (numY)
122     *pY = numY->GetNumber();
123 
124   // A zoom value of 0 is equivalent to a null value, so treat it as a null.
125   if (numZoom) {
126     float num = numZoom->GetNumber();
127     if (num == 0.0)
128       *pHasZoom = false;
129     else
130       *pZoom = num;
131   }
132 
133   return true;
134 }
135 
GetNumParams() const136 unsigned long CPDF_Dest::GetNumParams() const {
137   CPDF_Array* pArray = ToArray(m_pObj.Get());
138   if (!pArray || pArray->GetCount() < 2)
139     return 0;
140 
141   unsigned long maxParamsForFitType = g_sZoomModeMaxParamCount[GetZoomMode()];
142   unsigned long numParamsInArray = pArray->GetCount() - 2;
143   return std::min(maxParamsForFitType, numParamsInArray);
144 }
145 
GetParam(int index) const146 float CPDF_Dest::GetParam(int index) const {
147   CPDF_Array* pArray = ToArray(m_pObj.Get());
148   return pArray ? pArray->GetNumberAt(2 + index) : 0;
149 }
150 
GetRemoteName() const151 ByteString CPDF_Dest::GetRemoteName() const {
152   return m_pObj ? m_pObj->GetString() : ByteString();
153 }
154