1//========================================================================
2//
3// Page.h
4//
5// Copyright 1996-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
17// Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
18// Copyright (C) 2006 Pino Toscano <pino@kde.org>
19// Copyright (C) 2006, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
20// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
21// Copyright (C) 2008 Iñigo Martínez <inigomartinez@gmail.com>
22// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
23// Copyright (C) 2012, 2017, 2018, 2020, 2021, 2023 Albert Astals Cid <aacid@kde.org>
24// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
25// Copyright (C) 2013, 2017, 2023 Adrian Johnson <ajohnson@redneon.com>
26// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
27// Copyright (C) 2020 Oliver Sander <oliver.sander@tu-dresden.de>
28// Copyright (C) 2020, 2021 Nelson Benítez León <nbenitezl@gmail.com>
29//
30// To see a description of the changes please see the Changelog file that
31// came with your tarball or type make ChangeLog if you are building from git
32//
33//========================================================================
34
35#ifndef PAGE_H
36#define PAGE_H
37
38#include <memory>
39#include <mutex>
40
41#include "poppler-config.h"
42#include "Object.h"
43#include "poppler_private_export.h"
44
45class Dict;
46class PDFDoc;
47class XRef;
48class OutputDev;
49class Links;
50class LinkAction;
51class Annots;
52class Annot;
53class Gfx;
54class FormPageWidgets;
55class Form;
56class FormField;
57
58//------------------------------------------------------------------------
59
60class PDFRectangle
61{
62public:
63 double x1, y1, x2, y2;
64
65 PDFRectangle() { x1 = y1 = x2 = y2 = 0; }
66 PDFRectangle(double x1A, double y1A, double x2A, double y2A)
67 {
68 x1 = x1A;
69 y1 = y1A;
70 x2 = x2A;
71 y2 = y2A;
72 }
73 bool isValid() const { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
74 bool contains(double x, double y) const { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
75 void clipTo(PDFRectangle *rect);
76
77 bool operator==(const PDFRectangle &rect) const { return x1 == rect.x1 && y1 == rect.y1 && x2 == rect.x2 && y2 == rect.y2; }
78};
79
80//------------------------------------------------------------------------
81// PageAttrs
82//------------------------------------------------------------------------
83
84class PageAttrs
85{
86public:
87 // Construct a new PageAttrs object by merging a dictionary
88 // (of type Pages or Page) into another PageAttrs object. If
89 // <attrs> is nullptr, uses defaults.
90 PageAttrs(PageAttrs *attrs, Dict *dict);
91
92 // Destructor.
93 ~PageAttrs();
94
95 // Accessors.
96 const PDFRectangle *getMediaBox() const { return &mediaBox; }
97 const PDFRectangle *getCropBox() const { return &cropBox; }
98 bool isCropped() const { return haveCropBox; }
99 const PDFRectangle *getBleedBox() const { return &bleedBox; }
100 const PDFRectangle *getTrimBox() const { return &trimBox; }
101 const PDFRectangle *getArtBox() const { return &artBox; }
102 int getRotate() const { return rotate; }
103 const GooString *getLastModified() const { return lastModified.isString() ? lastModified.getString() : nullptr; }
104 Dict *getBoxColorInfo() { return boxColorInfo.isDict() ? boxColorInfo.getDict() : nullptr; }
105 Dict *getGroup() { return group.isDict() ? group.getDict() : nullptr; }
106 Stream *getMetadata() { return metadata.isStream() ? metadata.getStream() : nullptr; }
107 Dict *getPieceInfo() { return pieceInfo.isDict() ? pieceInfo.getDict() : nullptr; }
108 Dict *getSeparationInfo() { return separationInfo.isDict() ? separationInfo.getDict() : nullptr; }
109 Dict *getResourceDict() { return resources.isDict() ? resources.getDict() : nullptr; }
110 Object *getResourceDictObject() { return &resources; }
111 void replaceResource(Object &&obj1) { resources = std::move(obj1); }
112
113 // Clip all other boxes to the MediaBox.
114 void clipBoxes();
115
116private:
117 bool readBox(Dict *dict, const char *key, PDFRectangle *box);
118
119 PDFRectangle mediaBox;
120 PDFRectangle cropBox;
121 bool haveCropBox;
122 PDFRectangle bleedBox;
123 PDFRectangle trimBox;
124 PDFRectangle artBox;
125 int rotate;
126 Object lastModified;
127 Object boxColorInfo;
128 Object group;
129 Object metadata;
130 Object pieceInfo;
131 Object separationInfo;
132 Object resources;
133};
134
135//------------------------------------------------------------------------
136// Page
137//------------------------------------------------------------------------
138
139class POPPLER_PRIVATE_EXPORT Page
140{
141public:
142 // Constructor.
143 Page(PDFDoc *docA, int numA, Object &&pageDict, Ref pageRefA, PageAttrs *attrsA, Form *form);
144
145 // Destructor.
146 ~Page();
147
148 Page(const Page &) = delete;
149 Page &operator=(const Page &) = delete;
150
151 // Is page valid?
152 bool isOk() const { return ok; }
153
154 // Get page parameters.
155 int getNum() const { return num; }
156 const PDFRectangle *getMediaBox() const { return attrs->getMediaBox(); }
157 const PDFRectangle *getCropBox() const { return attrs->getCropBox(); }
158 bool isCropped() const { return attrs->isCropped(); }
159 double getMediaWidth() const { return attrs->getMediaBox()->x2 - attrs->getMediaBox()->x1; }
160 double getMediaHeight() const { return attrs->getMediaBox()->y2 - attrs->getMediaBox()->y1; }
161 double getCropWidth() const { return attrs->getCropBox()->x2 - attrs->getCropBox()->x1; }
162 double getCropHeight() const { return attrs->getCropBox()->y2 - attrs->getCropBox()->y1; }
163 const PDFRectangle *getBleedBox() const { return attrs->getBleedBox(); }
164 const PDFRectangle *getTrimBox() const { return attrs->getTrimBox(); }
165 const PDFRectangle *getArtBox() const { return attrs->getArtBox(); }
166 int getRotate() const { return attrs->getRotate(); }
167 const GooString *getLastModified() const { return attrs->getLastModified(); }
168 Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); }
169 Dict *getGroup() { return attrs->getGroup(); }
170 Stream *getMetadata() { return attrs->getMetadata(); }
171 Dict *getPieceInfo() { return attrs->getPieceInfo(); }
172 Dict *getSeparationInfo() { return attrs->getSeparationInfo(); }
173 PDFDoc *getDoc() { return doc; }
174 Ref getRef() { return pageRef; }
175
176 // Get resource dictionary.
177 Dict *getResourceDict();
178 Object *getResourceDictObject();
179 Dict *getResourceDictCopy(XRef *xrefA);
180
181 // Get annotations array.
182 Object getAnnotsObject(XRef *xrefA = nullptr) { return annotsObj.fetch(xref: xrefA ? xrefA : xref); }
183 // Add a new annotation to the page
184 bool addAnnot(Annot *annot);
185 // Remove an existing annotation from the page
186 void removeAnnot(Annot *annot);
187
188 // Return a list of links.
189 std::unique_ptr<Links> getLinks();
190
191 // Return a list of annots. It will be valid until the page is destroyed
192 Annots *getAnnots(XRef *xrefA = nullptr);
193
194 // Get contents.
195 Object getContents() { return contents.fetch(xref); }
196
197 // Get thumb.
198 Object getThumb() { return thumb.fetch(xref); }
199 bool loadThumb(unsigned char **data, int *width, int *height, int *rowstride);
200
201 // Get transition.
202 Object getTrans() { return trans.fetch(xref); }
203
204 // Get form.
205 std::unique_ptr<FormPageWidgets> getFormWidgets();
206
207 // Get duration, the maximum length of time, in seconds,
208 // that the page is displayed before the presentation automatically
209 // advances to the next page
210 double getDuration() { return duration; }
211
212 // Get actions
213 Object getActions() { return actions.fetch(xref); }
214
215 enum PageAdditionalActionsType
216 {
217 actionOpenPage, ///< Performed when opening the page
218 actionClosePage, ///< Performed when closing the page
219 };
220
221 std::unique_ptr<LinkAction> getAdditionalAction(PageAdditionalActionsType type);
222
223 Gfx *createGfx(OutputDev *out, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, int sliceX, int sliceY, int sliceW, int sliceH, bool printing, bool (*abortCheckCbk)(void *data), void *abortCheckCbkData,
224 XRef *xrefA = nullptr);
225
226 // Display a page.
227 void display(OutputDev *out, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, bool printing, bool (*abortCheckCbk)(void *data) = nullptr, void *abortCheckCbkData = nullptr,
228 bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr, void *annotDisplayDecideCbkData = nullptr, bool copyXRef = false);
229
230 // Display part of a page.
231 void displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, int sliceX, int sliceY, int sliceW, int sliceH, bool printing, bool (*abortCheckCbk)(void *data) = nullptr,
232 void *abortCheckCbkData = nullptr, bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr, void *annotDisplayDecideCbkData = nullptr, bool copyXRef = false);
233
234 void display(Gfx *gfx);
235
236 void makeBox(double hDPI, double vDPI, int rotate, bool useMediaBox, bool upsideDown, double sliceX, double sliceY, double sliceW, double sliceH, PDFRectangle *box, bool *crop);
237
238 void processLinks(OutputDev *out);
239
240 // Get the page's default CTM.
241 void getDefaultCTM(double *ctm, double hDPI, double vDPI, int rotate, bool useMediaBox, bool upsideDown);
242
243 bool hasStandaloneFields() const { return !standaloneFields.empty(); }
244
245 // Get the integer key of the page's entry in the structural parent tree.
246 // Returns -1 if the page dict does not contain a StructParents key.
247 int getStructParents() const { return structParents; }
248
249private:
250 // replace xref
251 void replaceXRef(XRef *xrefA);
252
253 PDFDoc *doc;
254 XRef *xref; // the xref table for this PDF file
255 Object pageObj; // page dictionary
256 const Ref pageRef; // page reference
257 int num; // page number
258 PageAttrs *attrs; // page attributes
259 Annots *annots; // annotations
260 Object annotsObj; // annotations array
261 Object contents; // page contents
262 Object thumb; // page thumbnail
263 Object trans; // page transition
264 Object actions; // page additional actions
265 double duration; // page duration
266 int structParents; // integer key of page in structure parent tree
267 bool ok; // true if page is valid
268 mutable std::recursive_mutex mutex;
269 // standalone widgets are special FormWidget's inside a Page that *are not*
270 // referenced from the Catalog's Field array. That means they are standlone,
271 // i.e. the PDF document does not have a FormField associated with them. We
272 // create standalone FormFields to contain those special FormWidgets, as
273 // they are 'de facto' being used to implement tooltips. See #34
274 std::vector<FormField *> standaloneFields;
275 void loadStandaloneFields(Annots *annotations, Form *form);
276};
277
278#endif
279

source code of poppler/poppler/Page.h