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