Home | History | Annotate | Download | only in page
      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/fpdfapi/page/cpdf_page.h"
      8 
      9 #include <set>
     10 #include <utility>
     11 
     12 #include "core/fpdfapi/cpdf_pagerendercontext.h"
     13 #include "core/fpdfapi/page/cpdf_contentparser.h"
     14 #include "core/fpdfapi/page/cpdf_pageobject.h"
     15 #include "core/fpdfapi/page/pageint.h"
     16 #include "core/fpdfapi/parser/cpdf_array.h"
     17 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     18 #include "core/fpdfapi/parser/cpdf_object.h"
     19 #include "core/fpdfapi/render/cpdf_pagerendercache.h"
     20 #include "third_party/base/ptr_util.h"
     21 #include "third_party/base/stl_util.h"
     22 
     23 CPDF_Page::CPDF_Page(CPDF_Document* pDocument,
     24                      CPDF_Dictionary* pPageDict,
     25                      bool bPageCache)
     26     : m_PageWidth(100),
     27       m_PageHeight(100),
     28       m_pView(nullptr),
     29       m_pPageRender(bPageCache ? new CPDF_PageRenderCache(this) : nullptr) {
     30   m_pFormDict = pPageDict;
     31   m_pDocument = pDocument;
     32   if (!pPageDict)
     33     return;
     34 
     35   CPDF_Object* pageAttr = GetPageAttr("Resources");
     36   m_pResources = pageAttr ? pageAttr->GetDict() : nullptr;
     37   m_pPageResources = m_pResources;
     38   CPDF_Object* pRotate = GetPageAttr("Rotate");
     39   int rotate = pRotate ? pRotate->GetInteger() / 90 % 4 : 0;
     40   if (rotate < 0)
     41     rotate += 4;
     42 
     43   CPDF_Array* pMediaBox = ToArray(GetPageAttr("MediaBox"));
     44   CFX_FloatRect mediabox;
     45   if (pMediaBox) {
     46     mediabox = pMediaBox->GetRect();
     47     mediabox.Normalize();
     48   }
     49   if (mediabox.IsEmpty())
     50     mediabox = CFX_FloatRect(0, 0, 612, 792);
     51 
     52   CPDF_Array* pCropBox = ToArray(GetPageAttr("CropBox"));
     53   if (pCropBox) {
     54     m_BBox = pCropBox->GetRect();
     55     m_BBox.Normalize();
     56   }
     57   if (m_BBox.IsEmpty())
     58     m_BBox = mediabox;
     59   else
     60     m_BBox.Intersect(mediabox);
     61 
     62   m_PageWidth = m_BBox.right - m_BBox.left;
     63   m_PageHeight = m_BBox.top - m_BBox.bottom;
     64   if (rotate % 2)
     65     std::swap(m_PageWidth, m_PageHeight);
     66 
     67   switch (rotate) {
     68     case 0:
     69       m_PageMatrix = CFX_Matrix(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom);
     70       break;
     71     case 1:
     72       m_PageMatrix =
     73           CFX_Matrix(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right);
     74       break;
     75     case 2:
     76       m_PageMatrix = CFX_Matrix(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top);
     77       break;
     78     case 3:
     79       m_PageMatrix = CFX_Matrix(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left);
     80       break;
     81   }
     82 
     83   m_Transparency = PDFTRANS_ISOLATED;
     84   LoadTransInfo();
     85 }
     86 
     87 CPDF_Page::~CPDF_Page() {}
     88 
     89 void CPDF_Page::StartParse() {
     90   if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING)
     91     return;
     92 
     93   m_pParser = pdfium::MakeUnique<CPDF_ContentParser>();
     94   m_pParser->Start(this);
     95   m_ParseState = CONTENT_PARSING;
     96 }
     97 
     98 void CPDF_Page::ParseContent() {
     99   StartParse();
    100   ContinueParse(nullptr);
    101 }
    102 
    103 void CPDF_Page::SetRenderContext(
    104     std::unique_ptr<CPDF_PageRenderContext> pContext) {
    105   m_pRenderContext = std::move(pContext);
    106 }
    107 
    108 CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteString& name) const {
    109   CPDF_Dictionary* pPageDict = m_pFormDict;
    110   std::set<CPDF_Dictionary*> visited;
    111   while (1) {
    112     visited.insert(pPageDict);
    113     if (CPDF_Object* pObj = pPageDict->GetDirectObjectFor(name))
    114       return pObj;
    115 
    116     pPageDict = pPageDict->GetDictFor("Parent");
    117     if (!pPageDict || pdfium::ContainsKey(visited, pPageDict))
    118       break;
    119   }
    120   return nullptr;
    121 }
    122 
    123 CFX_Matrix CPDF_Page::GetDisplayMatrix(int xPos,
    124                                        int yPos,
    125                                        int xSize,
    126                                        int ySize,
    127                                        int iRotate) const {
    128   if (m_PageWidth == 0 || m_PageHeight == 0)
    129     return CFX_Matrix();
    130 
    131   float x0 = 0;
    132   float y0 = 0;
    133   float x1 = 0;
    134   float y1 = 0;
    135   float x2 = 0;
    136   float y2 = 0;
    137   iRotate %= 4;
    138   switch (iRotate) {
    139     case 0:
    140       x0 = xPos;
    141       y0 = yPos + ySize;
    142       x1 = xPos;
    143       y1 = yPos;
    144       x2 = xPos + xSize;
    145       y2 = yPos + ySize;
    146       break;
    147     case 1:
    148       x0 = xPos;
    149       y0 = yPos;
    150       x1 = xPos + xSize;
    151       y1 = yPos;
    152       x2 = xPos;
    153       y2 = yPos + ySize;
    154       break;
    155     case 2:
    156       x0 = xPos + xSize;
    157       y0 = yPos;
    158       x1 = xPos + xSize;
    159       y1 = yPos + ySize;
    160       x2 = xPos;
    161       y2 = yPos;
    162       break;
    163     case 3:
    164       x0 = xPos + xSize;
    165       y0 = yPos + ySize;
    166       x1 = xPos;
    167       y1 = yPos + ySize;
    168       x2 = xPos + xSize;
    169       y2 = yPos;
    170       break;
    171   }
    172   CFX_Matrix matrix = m_PageMatrix;
    173   matrix.Concat(CFX_Matrix((x2 - x0) / m_PageWidth, (y2 - y0) / m_PageWidth,
    174                            (x1 - x0) / m_PageHeight, (y1 - y0) / m_PageHeight,
    175                            x0, y0));
    176   return matrix;
    177 }
    178 
    179 bool GraphicsData::operator<(const GraphicsData& other) const {
    180   if (fillAlpha != other.fillAlpha)
    181     return fillAlpha < other.fillAlpha;
    182   return strokeAlpha < other.strokeAlpha;
    183 }
    184 
    185 bool FontData::operator<(const FontData& other) const {
    186   return baseFont < other.baseFont;
    187 }
    188