1 /*
2  * Copyright (C) 2019, Masamichi Hosoda <trueroad@trueroad.jp>
3  * Copyright (C) 2019 Albert Astals Cid <aacid@kde.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  \file poppler-destination.h
22  */
23 #include "poppler-destination.h"
24 
25 #include "poppler-destination-private.h"
26 
27 #include "PDFDoc.h"
28 #include "Link.h"
29 
30 #include <utility>
31 
32 using namespace poppler;
33 
destination_private(const LinkDest * ld,PDFDoc * doc)34 destination_private::destination_private(const LinkDest *ld, PDFDoc *doc) : pdf_doc(doc)
35 {
36     if (!ld) {
37         type = destination::unknown;
38         return;
39     }
40 
41     switch (ld->getKind()) {
42     case ::destXYZ:
43         type = destination::xyz;
44         break;
45     case ::destFit:
46         type = destination::fit;
47         break;
48     case ::destFitH:
49         type = destination::fit_h;
50         break;
51     case ::destFitV:
52         type = destination::fit_v;
53         break;
54     case ::destFitR:
55         type = destination::fit_r;
56         break;
57     case ::destFitB:
58         type = destination::fit_b;
59         break;
60     case ::destFitBH:
61         type = destination::fit_b_h;
62         break;
63     case ::destFitBV:
64         type = destination::fit_b_v;
65         break;
66     default:
67         type = destination::unknown;
68         break;
69     }
70 
71     if (!ld->isPageRef()) {
72         // The page number has been resolved.
73         page_number_unresolved = false;
74         page_number = ld->getPageNum();
75     } else if (doc) {
76         // It is necessary to resolve the page number by its accessor.
77         page_number_unresolved = true;
78         page_ref = ld->getPageRef();
79     } else {
80         // The page number cannot be resolved because there is no PDFDoc.
81         page_number_unresolved = false;
82         page_number = 0;
83     }
84 
85     left = ld->getLeft();
86     bottom = ld->getBottom();
87     right = ld->getRight();
88     top = ld->getTop();
89     zoom = ld->getZoom();
90     change_left = ld->getChangeLeft();
91     change_top = ld->getChangeTop();
92     change_zoom = ld->getChangeZoom();
93 }
94 
95 /**
96  \class poppler::destination poppler-destination.h "poppler/cpp/poppler-destination.h"
97 
98  The information about a destination used in a PDF %document.
99  */
100 
101 /**
102  \enum poppler::destination::type_enum
103 
104  The various types of destinations available in a PDF %document.
105 */
106 /**
107  \var poppler::destination::type_enum poppler::destination::unknown
108 
109  unknown destination
110 */
111 /**
112  \var poppler::destination::type_enum poppler::destination::xyz
113 
114  go to page with coordinates (left, top) positioned at the upper-left
115  corner of the window and the contents of the page magnified
116  by the factor zoom
117 */
118 /**
119  \var poppler::destination::type_enum poppler::destination::fit
120 
121  go to page with its contents magnified just enough to fit the entire page
122  within the window both horizontally and vertically
123 */
124 /**
125  \var poppler::destination::type_enum poppler::destination::fit_h
126 
127  go to page with the vertical coordinate top positioned at the top edge
128  of the window and the contents of the page magnified just enough to fit
129  the entire width of the page within the window
130 */
131 /**
132  \var poppler::destination::type_enum poppler::destination::fit_v
133 
134  go to page with the horizontal coordinate left positioned at the left edge
135  of the window and the contents of the page magnified just enough to fit
136  the entire height of the page within the window
137 */
138 /**
139  \var poppler::destination::type_enum poppler::destination::fit_r
140 
141  go to page with its contents magnified just enough to fit the rectangle
142  specified by the coordinates left, bottom, right, and top entirely
143  within the window both horizontally and vertically
144 */
145 /**
146  \var poppler::destination::type_enum poppler::destination::fit_b
147 
148  go to page with its contents magnified just enough to fit its bounding box
149  entirely within the window both horizontally and vertically
150 */
151 /**
152  \var poppler::destination::type_enum poppler::destination::fit_b_h
153 
154  go to page with the vertical coordinate top positioned at the top edge
155  of the window and the contents of the page magnified just enough to fit
156  the entire width of its bounding box within the window
157 */
158 /**
159  \var poppler::destination::type_enum poppler::destination::fit_b_v
160 
161  go to page with the horizontal coordinate left positioned at the left edge
162  of the window and the contents of the page magnified just enough to fit
163  the entire height of its bounding box within the window
164 */
165 
destination(destination_private * dd)166 destination::destination(destination_private *dd) : d(dd) { }
167 
168 /**
169  Move constructor.
170  */
destination(destination && other)171 destination::destination(destination &&other) noexcept
172 {
173     *this = std::move(other);
174 }
175 
176 /**
177  \returns the type of the destination
178  */
type() const179 destination::type_enum destination::type() const
180 {
181     return d->type;
182 }
183 
184 /**
185  \note It is necessary not to destruct parent poppler::document
186  before calling this function for the first time.
187 
188  \returns the page number of the destination
189  */
page_number() const190 int destination::page_number() const
191 {
192     if (d->page_number_unresolved) {
193         d->page_number_unresolved = false;
194         d->page_number = d->pdf_doc->findPage(d->page_ref);
195     }
196 
197     return d->page_number;
198 }
199 
200 /**
201  \returns the left coordinate of the destination
202  */
left() const203 double destination::left() const
204 {
205     return d->left;
206 }
207 
208 /**
209  \returns the bottom coordinate of the destination
210  */
bottom() const211 double destination::bottom() const
212 {
213     return d->bottom;
214 }
215 
216 /**
217  \returns the right coordinate of the destination
218  */
right() const219 double destination::right() const
220 {
221     return d->right;
222 }
223 
224 /**
225  \returns the top coordinate of the destination
226  */
top() const227 double destination::top() const
228 {
229     return d->top;
230 }
231 
232 /**
233  \returns the scale factor of the destination
234  */
zoom() const235 double destination::zoom() const
236 {
237     return d->zoom;
238 }
239 
240 /**
241  \returns whether left coordinate should be changed
242  */
is_change_left() const243 bool destination::is_change_left() const
244 {
245     return d->change_left;
246 }
247 
248 /**
249  \returns whether top coordinate should be changed
250  */
is_change_top() const251 bool destination::is_change_top() const
252 {
253     return d->change_top;
254 }
255 
256 /**
257  \returns whether scale factor should be changed
258  */
is_change_zoom() const259 bool destination::is_change_zoom() const
260 {
261     return d->change_zoom;
262 }
263 
264 /**
265  Move assignment operator.
266  */
operator =(destination && other)267 destination &destination::operator=(destination &&other) noexcept
268 {
269     if (this != &other) {
270         d = other.d;
271         other.d = nullptr;
272     }
273 
274     return *this;
275 }
276 
277 /**
278  Destructor.
279  */
~destination()280 destination::~destination()
281 {
282     delete d;
283 }
284