blob: d3493de8a1b383c87f0204f68dc0f24eb20996f1 [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// Copyright 2016 The PDFium Authors
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -07002// 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
Haibo Huang49cc9302020-04-27 16:14:24 -070012#include "constants/page_object.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070013#include "core/fpdfapi/page/cpdf_contentparser.h"
kumarashishg826308d2023-06-23 13:21:22 +000014#include "core/fpdfapi/page/cpdf_pageimagecache.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070015#include "core/fpdfapi/page/cpdf_pageobject.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070016#include "core/fpdfapi/parser/cpdf_array.h"
17#include "core/fpdfapi/parser/cpdf_dictionary.h"
18#include "core/fpdfapi/parser/cpdf_object.h"
kumarashishg826308d2023-06-23 13:21:22 +000019#include "third_party/base/check.h"
20#include "third_party/base/check_op.h"
21#include "third_party/base/containers/contains.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070022
kumarashishg826308d2023-06-23 13:21:22 +000023CPDF_Page::CPDF_Page(CPDF_Document* pDocument,
24 RetainPtr<CPDF_Dictionary> pPageDict)
25 : CPDF_PageObjectHolder(pDocument, std::move(pPageDict), nullptr, nullptr),
Haibo Huang49cc9302020-04-27 16:14:24 -070026 m_PageSize(100, 100),
27 m_pPDFDocument(pDocument) {
Haibo Huang49cc9302020-04-27 16:14:24 -070028 // Cannot initialize |m_pResources| and |m_pPageResources| via the
29 // CPDF_PageObjectHolder ctor because GetPageAttr() requires
30 // CPDF_PageObjectHolder to finish initializing first.
kumarashishg826308d2023-06-23 13:21:22 +000031 RetainPtr<CPDF_Object> pPageAttr =
32 GetMutablePageAttr(pdfium::page_object::kResources);
33 m_pResources = pPageAttr ? pPageAttr->GetMutableDict() : nullptr;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070034 m_pPageResources = m_pResources;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070035
Haibo Huang49cc9302020-04-27 16:14:24 -070036 UpdateDimensions();
37 m_Transparency.SetIsolated();
38 LoadTransparencyInfo();
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070039}
40
kumarashishg826308d2023-06-23 13:21:22 +000041CPDF_Page::~CPDF_Page() = default;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070042
Haibo Huang49cc9302020-04-27 16:14:24 -070043CPDF_Page* CPDF_Page::AsPDFPage() {
44 return this;
45}
46
47CPDFXFA_Page* CPDF_Page::AsXFAPage() {
48 return nullptr;
49}
50
51CPDF_Document* CPDF_Page::GetDocument() const {
kumarashishg826308d2023-06-23 13:21:22 +000052 return m_pPDFDocument;
Haibo Huang49cc9302020-04-27 16:14:24 -070053}
54
55float CPDF_Page::GetPageWidth() const {
56 return m_PageSize.width;
57}
58
59float CPDF_Page::GetPageHeight() const {
60 return m_PageSize.height;
61}
62
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070063bool CPDF_Page::IsPage() const {
64 return true;
65}
66
Haibo Huang49cc9302020-04-27 16:14:24 -070067void CPDF_Page::ParseContent() {
68 if (GetParseState() == ParseState::kParsed)
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070069 return;
70
Haibo Huang49cc9302020-04-27 16:14:24 -070071 if (GetParseState() == ParseState::kNotParsed)
kumarashishg826308d2023-06-23 13:21:22 +000072 StartParse(std::make_unique<CPDF_ContentParser>(this));
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070073
kumarashishg826308d2023-06-23 13:21:22 +000074 DCHECK_EQ(GetParseState(), ParseState::kParsing);
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070075 ContinueParse(nullptr);
76}
77
kumarashishg826308d2023-06-23 13:21:22 +000078RetainPtr<CPDF_Object> CPDF_Page::GetMutablePageAttr(const ByteString& name) {
79 return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetPageAttr(name).Get()));
80}
81
82RetainPtr<const CPDF_Object> CPDF_Page::GetPageAttr(
83 const ByteString& name) const {
84 std::set<RetainPtr<const CPDF_Dictionary>> visited;
85 RetainPtr<const CPDF_Dictionary> pPageDict = GetDict();
86 while (pPageDict && !pdfium::Contains(visited, pPageDict)) {
87 RetainPtr<const CPDF_Object> pObj = pPageDict->GetDirectObjectFor(name);
88 if (pObj)
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070089 return pObj;
90
kumarashishg826308d2023-06-23 13:21:22 +000091 visited.insert(pPageDict);
Haibo Huang49cc9302020-04-27 16:14:24 -070092 pPageDict = pPageDict->GetDictFor(pdfium::page_object::kParent);
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070093 }
94 return nullptr;
95}
96
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070097CFX_FloatRect CPDF_Page::GetBox(const ByteString& name) const {
98 CFX_FloatRect box;
kumarashishg826308d2023-06-23 13:21:22 +000099 RetainPtr<const CPDF_Array> pBox = ToArray(GetPageAttr(name));
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700100 if (pBox) {
101 box = pBox->GetRect();
102 box.Normalize();
103 }
104 return box;
105}
106
kumarashishg826308d2023-06-23 13:21:22 +0000107absl::optional<CFX_PointF> CPDF_Page::DeviceToPage(
Haibo Huang49cc9302020-04-27 16:14:24 -0700108 const FX_RECT& rect,
109 int rotate,
110 const CFX_PointF& device_point) const {
111 CFX_Matrix page2device = GetDisplayMatrix(rect, rotate);
112 return page2device.GetInverse().Transform(device_point);
113}
114
kumarashishg826308d2023-06-23 13:21:22 +0000115absl::optional<CFX_PointF> CPDF_Page::PageToDevice(
Haibo Huang49cc9302020-04-27 16:14:24 -0700116 const FX_RECT& rect,
117 int rotate,
118 const CFX_PointF& page_point) const {
119 CFX_Matrix page2device = GetDisplayMatrix(rect, rotate);
120 return page2device.Transform(page_point);
121}
122
123CFX_Matrix CPDF_Page::GetDisplayMatrix(const FX_RECT& rect, int iRotate) const {
124 if (m_PageSize.width == 0 || m_PageSize.height == 0)
Philip P. Moltmann33357ca2017-05-11 09:25:13 -0700125 return CFX_Matrix();
126
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700127 float x0 = 0;
128 float y0 = 0;
129 float x1 = 0;
130 float y1 = 0;
131 float x2 = 0;
132 float y2 = 0;
133 iRotate %= 4;
Haibo Huang49cc9302020-04-27 16:14:24 -0700134 // This code implicitly inverts the y-axis to account for page coordinates
135 // pointing up and bitmap coordinates pointing down. (x0, y0) is the base
136 // point, (x1, y1) is that point translated on y and (x2, y2) is the point
137 // translated on x. On iRotate = 0, y0 is rect.bottom and the translation
138 // to get y1 is performed as negative. This results in the desired
139 // transformation.
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700140 switch (iRotate) {
141 case 0:
Haibo Huang49cc9302020-04-27 16:14:24 -0700142 x0 = rect.left;
143 y0 = rect.bottom;
144 x1 = rect.left;
145 y1 = rect.top;
146 x2 = rect.right;
147 y2 = rect.bottom;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700148 break;
149 case 1:
Haibo Huang49cc9302020-04-27 16:14:24 -0700150 x0 = rect.left;
151 y0 = rect.top;
152 x1 = rect.right;
153 y1 = rect.top;
154 x2 = rect.left;
155 y2 = rect.bottom;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700156 break;
157 case 2:
Haibo Huang49cc9302020-04-27 16:14:24 -0700158 x0 = rect.right;
159 y0 = rect.top;
160 x1 = rect.right;
161 y1 = rect.bottom;
162 x2 = rect.left;
163 y2 = rect.top;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700164 break;
165 case 3:
Haibo Huang49cc9302020-04-27 16:14:24 -0700166 x0 = rect.right;
167 y0 = rect.bottom;
168 x1 = rect.left;
169 y1 = rect.bottom;
170 x2 = rect.right;
171 y2 = rect.top;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700172 break;
173 }
Haibo Huang49cc9302020-04-27 16:14:24 -0700174 CFX_Matrix matrix((x2 - x0) / m_PageSize.width, (y2 - y0) / m_PageSize.width,
175 (x1 - x0) / m_PageSize.height,
176 (y1 - y0) / m_PageSize.height, x0, y0);
177 return m_PageMatrix * matrix;
Philip P. Moltmann33357ca2017-05-11 09:25:13 -0700178}
179
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700180int CPDF_Page::GetPageRotation() const {
kumarashishg826308d2023-06-23 13:21:22 +0000181 RetainPtr<const CPDF_Object> pRotate =
182 GetPageAttr(pdfium::page_object::kRotate);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700183 int rotate = pRotate ? (pRotate->GetInteger() / 90) % 4 : 0;
184 return (rotate < 0) ? (rotate + 4) : rotate;
185}
186
kumarashishg826308d2023-06-23 13:21:22 +0000187RetainPtr<CPDF_Array> CPDF_Page::GetOrCreateAnnotsArray() {
188 return GetMutableDict()->GetOrCreateArrayFor("Annots");
189}
190
191RetainPtr<CPDF_Array> CPDF_Page::GetMutableAnnotsArray() {
192 return GetMutableDict()->GetMutableArrayFor("Annots");
193}
194
195RetainPtr<const CPDF_Array> CPDF_Page::GetAnnotsArray() const {
196 return GetDict()->GetArrayFor("Annots");
197}
198
199void CPDF_Page::AddPageImageCache() {
200 m_pPageImageCache = std::make_unique<CPDF_PageImageCache>(this);
201}
202
203void CPDF_Page::SetRenderContext(std::unique_ptr<RenderContextIface> pContext) {
204 DCHECK(!m_pRenderContext);
205 DCHECK(pContext);
206 m_pRenderContext = std::move(pContext);
207}
208
209void CPDF_Page::ClearRenderContext() {
210 m_pRenderContext.reset();
211}
212
213void CPDF_Page::ClearView() {
214 if (m_pView)
215 m_pView->ClearPage(this);
216}
217
Haibo Huang49cc9302020-04-27 16:14:24 -0700218void CPDF_Page::UpdateDimensions() {
219 CFX_FloatRect mediabox = GetBox(pdfium::page_object::kMediaBox);
220 if (mediabox.IsEmpty())
221 mediabox = CFX_FloatRect(0, 0, 612, 792);
222
223 m_BBox = GetBox(pdfium::page_object::kCropBox);
224 if (m_BBox.IsEmpty())
225 m_BBox = mediabox;
226 else
227 m_BBox.Intersect(mediabox);
228
229 m_PageSize.width = m_BBox.Width();
230 m_PageSize.height = m_BBox.Height();
231
232 switch (GetPageRotation()) {
233 case 0:
234 m_PageMatrix = CFX_Matrix(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom);
235 break;
236 case 1:
237 std::swap(m_PageSize.width, m_PageSize.height);
238 m_PageMatrix =
239 CFX_Matrix(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right);
240 break;
241 case 2:
242 m_PageMatrix = CFX_Matrix(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top);
243 break;
244 case 3:
245 std::swap(m_PageSize.width, m_PageSize.height);
246 m_PageMatrix = CFX_Matrix(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left);
247 break;
248 }
Philip P. Moltmann33357ca2017-05-11 09:25:13 -0700249}
250
Haibo Huang49cc9302020-04-27 16:14:24 -0700251CPDF_Page::RenderContextClearer::RenderContextClearer(CPDF_Page* pPage)
252 : m_pPage(pPage) {}
253
254CPDF_Page::RenderContextClearer::~RenderContextClearer() {
kumarashishg826308d2023-06-23 13:21:22 +0000255 if (m_pPage)
256 m_pPage->ClearRenderContext();
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700257}