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
40using namespace poppler;
41
42class poppler::page_renderer_private
43{
44public:
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
56bool 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
80bool 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 */
115page_renderer::page_renderer() : d(new page_renderer_private()) { }
116
117/**
118 Destructor.
119 */
120page_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 */
132argb 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 */
142void 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 */
154unsigned 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 */
165void 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 */
179void 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 */
193image::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 */
205void 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 */
219page_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 */
231void 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 */
255image 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 */
300bool page_renderer::can_render()
301{
302 return true;
303}
304

source code of poppler/cpp/poppler-page-renderer.cpp