Home | History | Annotate | Download | only in fpdfdoc
      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 
     33 CPDF_Dest::CPDF_Dest() {}
     34 
     35 CPDF_Dest::CPDF_Dest(const CPDF_Dest& pObj) = default;
     36 
     37 CPDF_Dest::CPDF_Dest(CPDF_Object* pObj) : m_pObj(pObj) {}
     38 
     39 CPDF_Dest::~CPDF_Dest() {}
     40 
     41 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 
     56 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 
     71 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 
     89 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 
    136 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 
    146 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 
    151 ByteString CPDF_Dest::GetRemoteName() const {
    152   return m_pObj ? m_pObj->GetString() : ByteString();
    153 }
    154