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