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