• 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/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 
CPDF_Page(CPDF_Document * pDocument,CPDF_Dictionary * pPageDict,bool bPageCache)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 
~CPDF_Page()75 CPDF_Page::~CPDF_Page() {}
76 
IsPage() const77 bool CPDF_Page::IsPage() const {
78   return true;
79 }
80 
StartParse()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 
ParseContent()89 void CPDF_Page::ParseContent() {
90   StartParse();
91   ContinueParse(nullptr);
92 }
93 
SetRenderContext(std::unique_ptr<CPDF_PageRenderContext> pContext)94 void CPDF_Page::SetRenderContext(
95     std::unique_ptr<CPDF_PageRenderContext> pContext) {
96   m_pRenderContext = std::move(pContext);
97 }
98 
GetPageAttr(const ByteString & name) const99 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 
GetBox(const ByteString & name) const114 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 
GetDisplayMatrix(int xPos,int yPos,int xSize,int ySize,int iRotate) const124 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 
GetPageRotation() const180 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 
operator <(const GraphicsData & other) const186 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 
operator <(const FontData & other) const194 bool FontData::operator<(const FontData& other) const {
195   if (baseFont != other.baseFont)
196     return baseFont < other.baseFont;
197   return type < other.type;
198 }
199