1 | /* |
2 | * Copyright (C) 2010, Pino Toscano <pino@kde.org> |
3 | * Copyright (C) 2015 William Bader <williambader@hotmail.com> |
4 | * Copyright (C) 2018, Zsombor Hollay-Horvath <hollay.horvath@gmail.com> |
5 | * Copyright (C) 2019, Julián Unrrein <junrrein@gmail.com> |
6 | * Copyright (C) 2020, Albert Astals Cid <aacid@kde.org> |
7 | * Copyright (C) 2021, Hubert Figuiere <hub@figuiere.net> |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2, or (at your option) |
12 | * any later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. |
22 | */ |
23 | |
24 | /** |
25 | \file poppler-page-renderer.h |
26 | */ |
27 | #include "poppler-page-renderer.h" |
28 | |
29 | #include "poppler-document-private.h" |
30 | #include "poppler-page-private.h" |
31 | #include "poppler-image.h" |
32 | |
33 | #include <config.h> |
34 | #include <poppler-config.h> |
35 | |
36 | #include "PDFDoc.h" |
37 | #include "SplashOutputDev.h" |
38 | #include "splash/SplashBitmap.h" |
39 | |
40 | using namespace poppler; |
41 | |
42 | class poppler::page_renderer_private |
43 | { |
44 | public: |
45 | page_renderer_private() : paper_color(0xffffffff), hints(0), image_format(image::format_enum::format_argb32), line_mode(page_renderer::line_mode_enum::line_default) { } |
46 | |
47 | static bool conv_color_mode(image::format_enum mode, SplashColorMode &splash_mode); |
48 | static bool conv_line_mode(page_renderer::line_mode_enum mode, SplashThinLineMode &splash_mode); |
49 | |
50 | argb paper_color; |
51 | unsigned int hints; |
52 | image::format_enum image_format; |
53 | page_renderer::line_mode_enum line_mode; |
54 | }; |
55 | |
56 | bool page_renderer_private::conv_color_mode(image::format_enum mode, SplashColorMode &splash_mode) |
57 | { |
58 | switch (mode) { |
59 | case image::format_enum::format_mono: |
60 | splash_mode = splashModeMono1; |
61 | break; |
62 | case image::format_enum::format_gray8: |
63 | splash_mode = splashModeMono8; |
64 | break; |
65 | case image::format_enum::format_rgb24: |
66 | splash_mode = splashModeRGB8; |
67 | break; |
68 | case image::format_enum::format_bgr24: |
69 | splash_mode = splashModeBGR8; |
70 | break; |
71 | case image::format_enum::format_argb32: |
72 | splash_mode = splashModeXBGR8; |
73 | break; |
74 | default: |
75 | return false; |
76 | } |
77 | return true; |
78 | } |
79 | |
80 | bool page_renderer_private::conv_line_mode(page_renderer::line_mode_enum mode, SplashThinLineMode &splash_mode) |
81 | { |
82 | switch (mode) { |
83 | case page_renderer::line_mode_enum::line_default: |
84 | splash_mode = splashThinLineDefault; |
85 | break; |
86 | case page_renderer::line_mode_enum::line_solid: |
87 | splash_mode = splashThinLineSolid; |
88 | break; |
89 | case page_renderer::line_mode_enum::line_shape: |
90 | splash_mode = splashThinLineShape; |
91 | break; |
92 | default: |
93 | return false; |
94 | } |
95 | return true; |
96 | } |
97 | |
98 | /** |
99 | \class poppler::page_renderer poppler-page-renderer.h "poppler/cpp/poppler-renderer.h" |
100 | |
101 | Simple way to render a page of a PDF %document. |
102 | |
103 | \since 0.16 |
104 | */ |
105 | |
106 | /** |
107 | \enum poppler::page_renderer::render_hint |
108 | |
109 | A flag of an option taken into account when rendering |
110 | */ |
111 | |
112 | /** |
113 | Constructs a new %page renderer. |
114 | */ |
115 | page_renderer::page_renderer() : d(new page_renderer_private()) { } |
116 | |
117 | /** |
118 | Destructor. |
119 | */ |
120 | page_renderer::~page_renderer() |
121 | { |
122 | delete d; |
123 | } |
124 | |
125 | /** |
126 | The color used for the "paper" of the pages. |
127 | |
128 | The default color is opaque solid white (0xffffffff). |
129 | |
130 | \returns the paper color |
131 | */ |
132 | argb page_renderer::paper_color() const |
133 | { |
134 | return d->paper_color; |
135 | } |
136 | |
137 | /** |
138 | Set a new color for the "paper". |
139 | |
140 | \param c the new color |
141 | */ |
142 | void page_renderer::set_paper_color(argb c) |
143 | { |
144 | d->paper_color = c; |
145 | } |
146 | |
147 | /** |
148 | The hints used when rendering. |
149 | |
150 | By default no hint is set. |
151 | |
152 | \returns the render hints set |
153 | */ |
154 | unsigned int page_renderer::render_hints() const |
155 | { |
156 | return d->hints; |
157 | } |
158 | |
159 | /** |
160 | Enable or disable a single render %hint. |
161 | |
162 | \param hint the hint to modify |
163 | \param on whether enable it or not |
164 | */ |
165 | void page_renderer::set_render_hint(page_renderer::render_hint hint, bool on) |
166 | { |
167 | if (on) { |
168 | d->hints |= hint; |
169 | } else { |
170 | d->hints &= ~(int)hint; |
171 | } |
172 | } |
173 | |
174 | /** |
175 | Set new render %hints at once. |
176 | |
177 | \param hints the new set of render hints |
178 | */ |
179 | void page_renderer::set_render_hints(unsigned int hints) |
180 | { |
181 | d->hints = hints; |
182 | } |
183 | |
184 | /** |
185 | The image format used when rendering. |
186 | |
187 | By default ARGB32 is set. |
188 | |
189 | \returns the image format |
190 | |
191 | \since 0.65 |
192 | */ |
193 | image::format_enum page_renderer::image_format() const |
194 | { |
195 | return d->image_format; |
196 | } |
197 | |
198 | /** |
199 | Set new image format used when rendering. |
200 | |
201 | \param format the new image format |
202 | |
203 | \since 0.65 |
204 | */ |
205 | void page_renderer::set_image_format(image::format_enum format) |
206 | { |
207 | d->image_format = format; |
208 | } |
209 | |
210 | /** |
211 | The line mode used when rendering. |
212 | |
213 | By default default mode is set. |
214 | |
215 | \returns the line mode |
216 | |
217 | \since 0.65 |
218 | */ |
219 | page_renderer::line_mode_enum page_renderer::line_mode() const |
220 | { |
221 | return d->line_mode; |
222 | } |
223 | |
224 | /** |
225 | Set new line mode used when rendering. |
226 | |
227 | \param mode the new line mode |
228 | |
229 | \since 0.65 |
230 | */ |
231 | void page_renderer::set_line_mode(page_renderer::line_mode_enum mode) |
232 | { |
233 | d->line_mode = mode; |
234 | } |
235 | |
236 | /** |
237 | Render the specified page. |
238 | |
239 | This functions renders the specified page on an image following the specified |
240 | parameters, returning it. |
241 | |
242 | \param p the page to render |
243 | \param xres the X resolution, in dot per inch (DPI) |
244 | \param yres the Y resolution, in dot per inch (DPI) |
245 | \param x the X top-right coordinate, in pixels |
246 | \param y the Y top-right coordinate, in pixels |
247 | \param w the width in pixels of the area to render |
248 | \param h the height in pixels of the area to render |
249 | \param rotate the rotation to apply when rendering the page |
250 | |
251 | \returns the rendered image, or a null one in case of errors |
252 | |
253 | \see can_render |
254 | */ |
255 | image page_renderer::render_page(const page *p, double xres, double yres, int x, int y, int w, int h, rotation_enum rotate) const |
256 | { |
257 | if (!p) { |
258 | return image(); |
259 | } |
260 | |
261 | page_private *pp = page_private::get(p); |
262 | PDFDoc *pdfdoc = pp->doc->doc; |
263 | |
264 | SplashColorMode colorMode; |
265 | SplashThinLineMode lineMode; |
266 | |
267 | if (!d->conv_color_mode(mode: d->image_format, splash_mode&: colorMode) || !d->conv_line_mode(mode: d->line_mode, splash_mode&: lineMode)) { |
268 | return image(); |
269 | } |
270 | |
271 | SplashColor bgColor; |
272 | bgColor[0] = d->paper_color & 0xff; |
273 | bgColor[1] = (d->paper_color >> 8) & 0xff; |
274 | bgColor[2] = (d->paper_color >> 16) & 0xff; |
275 | SplashOutputDev splashOutputDev(colorMode, 4, false, bgColor, true, lineMode); |
276 | splashOutputDev.setFontAntialias(d->hints & text_antialiasing ? true : false); |
277 | splashOutputDev.setVectorAntialias(d->hints & antialiasing ? true : false); |
278 | splashOutputDev.setFreeTypeHinting(enable: d->hints & text_hinting ? true : false, enableSlightHinting: false); |
279 | splashOutputDev.startDoc(docA: pdfdoc); |
280 | pdfdoc->displayPageSlice(out: &splashOutputDev, page: pp->index + 1, hDPI: xres, vDPI: yres, rotate: int(rotate) * 90, useMediaBox: false, crop: true, printing: false, sliceX: x, sliceY: y, sliceW: w, sliceH: h, abortCheckCbk: nullptr, abortCheckCbkData: nullptr, annotDisplayDecideCbk: nullptr, annotDisplayDecideCbkData: nullptr, copyXRef: true); |
281 | |
282 | SplashBitmap *bitmap = splashOutputDev.getBitmap(); |
283 | const int bw = bitmap->getWidth(); |
284 | const int bh = bitmap->getHeight(); |
285 | |
286 | SplashColorPtr data_ptr = bitmap->getDataPtr(); |
287 | |
288 | const image img(reinterpret_cast<char *>(data_ptr), bw, bh, d->image_format); |
289 | return img.copy(); |
290 | } |
291 | |
292 | /** |
293 | Rendering capability test. |
294 | |
295 | page_renderer can render only if a render backend ('Splash') is compiled in |
296 | Poppler. |
297 | |
298 | \returns whether page_renderer can render |
299 | */ |
300 | bool page_renderer::can_render() |
301 | { |
302 | return true; |
303 | } |
304 | |