summaryrefslogtreecommitdiff
path: root/cpp/poppler-page-renderer.cpp
blob: fd28d9b1717777a7f9cb0a129b1468e371980301 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/*
 * Copyright (C) 2010, Pino Toscano <pino@kde.org>
 * Copyright (C) 2015 William Bader <williambader@hotmail.com>
 * Copyright (C) 2018, Zsombor Hollay-Horvath <hollay.horvath@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "poppler-page-renderer.h"

#include "poppler-document-private.h"
#include "poppler-page-private.h"
#include "poppler-image.h"

#include <config.h>

#include "PDFDoc.h"
#if defined(HAVE_SPLASH)
#include "SplashOutputDev.h"
#include "splash/SplashBitmap.h"
#endif

using namespace poppler;

class poppler::page_renderer_private
{
public:
    page_renderer_private()
        : paper_color(0xffffffff)
        , hints(0)
        , image_format(image::format_enum::format_argb32)
        , line_mode(page_renderer::line_mode_enum::line_default)
    {
    }

#if defined(HAVE_SPLASH)
    static bool conv_color_mode(image::format_enum mode,
                                SplashColorMode &splash_mode);
    static bool conv_line_mode(page_renderer::line_mode_enum mode,
                               SplashThinLineMode &splash_mode);
#endif

    argb paper_color;
    unsigned int hints;
    image::format_enum image_format;
    page_renderer::line_mode_enum line_mode;

};


#if defined(HAVE_SPLASH)
bool page_renderer_private::conv_color_mode(image::format_enum mode,
                                            SplashColorMode &splash_mode)
{
    switch (mode) {
        case image::format_enum::format_mono:
            splash_mode = splashModeMono1;
            break;
        case image::format_enum::format_gray8:
            splash_mode = splashModeMono8;
            break;
        case image::format_enum::format_rgb24:
            splash_mode = splashModeRGB8;
            break;
        case image::format_enum::format_bgr24:
            splash_mode = splashModeBGR8;
            break;
        case image::format_enum::format_argb32:
            splash_mode = splashModeXBGR8;
            break;
        default:
            return false;
    }
    return true;
}

bool page_renderer_private::conv_line_mode(page_renderer::line_mode_enum mode,
                                           SplashThinLineMode &splash_mode)
{
    switch (mode) {
        case page_renderer::line_mode_enum::line_default:
            splash_mode = splashThinLineDefault;
            break;
        case page_renderer::line_mode_enum::line_solid:
            splash_mode = splashThinLineSolid;
            break;
        case page_renderer::line_mode_enum::line_shape:
            splash_mode = splashThinLineShape;
            break;
        default:
            return false;
    }
    return true;
}
#endif

/**
 \class poppler::page_renderer poppler-page-renderer.h "poppler/cpp/poppler-renderer.h"

 Simple way to render a page of a PDF %document.

 \since 0.16
 */

/**
 \enum poppler::page_renderer::render_hint

 A flag of an option taken into account when rendering
*/


/**
 Constructs a new %page renderer.
 */
page_renderer::page_renderer()
    : d(new page_renderer_private())
{
}

/**
 Destructor.
 */
page_renderer::~page_renderer()
{
    delete d;
}

/**
 The color used for the "paper" of the pages.

 The default color is opaque solid white (0xffffffff).

 \returns the paper color
 */
argb page_renderer::paper_color() const
{
    return d->paper_color;
}

/**
 Set a new color for the "paper".

 \param c the new color
 */
void page_renderer::set_paper_color(argb c)
{
    d->paper_color = c;
}

/**
 The hints used when rendering.

 By default no hint is set.

 \returns the render hints set
 */
unsigned int page_renderer::render_hints() const
{
    return d->hints;
}

/**
 Enable or disable a single render %hint.

 \param hint the hint to modify
 \param on whether enable it or not
 */
void page_renderer::set_render_hint(page_renderer::render_hint hint, bool on)
{
    if (on) {
        d->hints |= hint;
    } else {
        d->hints &= ~(int)hint;
    }
}

/**
 Set new render %hints at once.

 \param hints the new set of render hints
 */
void page_renderer::set_render_hints(unsigned int hints)
{
    d->hints = hints;
}

/**
 The image format used when rendering.

 By default ARGB32 is set.

 \returns the image format

 \since 0.65
 */
image::format_enum page_renderer::image_format() const
{
    return d->image_format;
}

/**
 Set new image format used when rendering.

 \param format the new image format

 \since 0.65
 */
void page_renderer::set_image_format(image::format_enum format)
{
    d->image_format = format;
}

/**
 The line mode used when rendering.

 By default default mode is set.

 \returns the line mode

 \since 0.65
 */
page_renderer::line_mode_enum page_renderer::line_mode() const
{
    return d->line_mode;
}

/**
 Set new line mode used when rendering.

 \param mode the new line mode

 \since 0.65
 */
void page_renderer::set_line_mode(page_renderer::line_mode_enum mode)
{
    d->line_mode = mode;
}

/**
 Render the specified page.

 This functions renders the specified page on an image following the specified
 parameters, returning it.

 \param p the page to render
 \param xres the X resolution, in dot per inch (DPI)
 \param yres the Y resolution, in dot per inch (DPI)
 \param x the X top-right coordinate, in pixels
 \param y the Y top-right coordinate, in pixels
 \param w the width in pixels of the area to render
 \param h the height in pixels of the area to render
 \param rotate the rotation to apply when rendering the page

 \returns the rendered image, or a null one in case of errors

 \see can_render
 */
image page_renderer::render_page(const page *p,
                                 double xres, double yres,
                                 int x, int y, int w, int h,
                                 rotation_enum rotate) const
{
    if (!p) {
        return image();
    }

#if defined(HAVE_SPLASH)
    page_private *pp = page_private::get(p);
    PDFDoc *pdfdoc = pp->doc->doc;

    SplashColorMode colorMode;
    SplashThinLineMode lineMode;

    if (!d->conv_color_mode(d->image_format, colorMode) ||
        !d->conv_line_mode(d->line_mode, lineMode)) {
        return image();
    }

    SplashColor bgColor;
    bgColor[0] = d->paper_color & 0xff;
    bgColor[1] = (d->paper_color >> 8) & 0xff;
    bgColor[2] = (d->paper_color >> 16) & 0xff;
    SplashOutputDev splashOutputDev(colorMode, 4, gFalse, bgColor, gTrue, lineMode);
    splashOutputDev.setFontAntialias(d->hints & text_antialiasing ? gTrue : gFalse);
    splashOutputDev.setVectorAntialias(d->hints & antialiasing ? gTrue : gFalse);
    splashOutputDev.setFreeTypeHinting(d->hints & text_hinting ? gTrue : gFalse, gFalse);
    splashOutputDev.startDoc(pdfdoc);
    pdfdoc->displayPageSlice(&splashOutputDev, pp->index + 1,
                             xres, yres, int(rotate) * 90,
                             gFalse, gTrue, gFalse,
                             x, y, w, h);

    SplashBitmap *bitmap = splashOutputDev.getBitmap();
    const int bw = bitmap->getWidth();
    const int bh = bitmap->getHeight();

    SplashColorPtr data_ptr = bitmap->getDataPtr();

    const image img(reinterpret_cast<char *>(data_ptr), bw, bh, d->image_format);
    return img.copy();
#else
    return image();
#endif
}

/**
 Rendering capability test.

 page_renderer can render only if a render backend ('Splash') is compiled in
 Poppler.

 \returns whether page_renderer can render
 */
bool page_renderer::can_render()
{
#if defined(HAVE_SPLASH)
    return true;
#else
    return false;
#endif
}