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
CPDF_Page(CPDF_Document * pDocument,CPDF_Dictionary * pPageDict,bool bPageCache)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
~CPDF_Page()87 CPDF_Page::~CPDF_Page() {}
88
StartParse()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
ParseContent()98 void CPDF_Page::ParseContent() {
99 StartParse();
100 ContinueParse(nullptr);
101 }
102
SetRenderContext(std::unique_ptr<CPDF_PageRenderContext> pContext)103 void CPDF_Page::SetRenderContext(
104 std::unique_ptr<CPDF_PageRenderContext> pContext) {
105 m_pRenderContext = std::move(pContext);
106 }
107
GetPageAttr(const CFX_ByteString & name) const108 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
GetDisplayMatrix(int xPos,int yPos,int xSize,int ySize,int iRotate) const123 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
operator <(const GraphicsData & other) const179 bool GraphicsData::operator<(const GraphicsData& other) const {
180 if (fillAlpha != other.fillAlpha)
181 return fillAlpha < other.fillAlpha;
182 return strokeAlpha < other.strokeAlpha;
183 }
184
operator <(const FontData & other) const185 bool FontData::operator<(const FontData& other) const {
186 return baseFont < other.baseFont;
187 }
188