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:
page_renderer_private()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
conv_color_mode(image::format_enum mode,SplashColorMode & splash_mode)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
conv_line_mode(page_renderer::line_mode_enum mode,SplashThinLineMode & splash_mode)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 */
page_renderer()115 page_renderer::page_renderer() : d(new page_renderer_private()) { }
116
117 /**
118 Destructor.
119 */
~page_renderer()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 */
paper_color() const132 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 */
set_paper_color(argb c)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 */
render_hints() const154 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 */
set_render_hint(page_renderer::render_hint hint,bool on)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 */
set_render_hints(unsigned int hints)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 */
image_format() const193 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 */
set_image_format(image::format_enum format)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 */
line_mode() const219 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 */
set_line_mode(page_renderer::line_mode_enum mode)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 */
render_page(const page * p,double xres,double yres,int x,int y,int w,int h,rotation_enum rotate) const255 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(d->image_format, colorMode) || !d->conv_line_mode(d->line_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(d->hints & text_hinting ? true : false, false);
279 splashOutputDev.startDoc(pdfdoc);
280 pdfdoc->displayPageSlice(&splashOutputDev, pp->index + 1, xres, yres, int(rotate) * 90, false, true, false, x, y, w, h, nullptr, nullptr, nullptr, nullptr, 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 */
can_render()300 bool page_renderer::can_render()
301 {
302 return true;
303 }
304