blob: 4b07e7692751af18eaf54bd79d73b21c8ae39e67 [file] [log] [blame]
/*
* 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>
* Copyright (C) 2019, Julián Unrrein <junrrein@gmail.com>
* Copyright (C) 2020, Albert Astals Cid <aacid@kde.org>
* Copyright (C) 2021, Hubert Figuiere <hub@figuiere.net>
*
* 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.
*/
/**
\file poppler-page-renderer.h
*/
#include "poppler-page-renderer.h"
#include "poppler-document-private.h"
#include "poppler-page-private.h"
#include "poppler-image.h"
#include <config.h>
#include <poppler-config.h>
#include "PDFDoc.h"
#include "SplashOutputDev.h"
#include "splash/SplashBitmap.h"
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) { }
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);
argb paper_color;
unsigned int hints;
image::format_enum image_format;
page_renderer::line_mode_enum line_mode;
};
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;
}
/**
\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();
}
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, false, bgColor, true, lineMode);
splashOutputDev.setFontAntialias(d->hints & text_antialiasing ? true : false);
splashOutputDev.setVectorAntialias(d->hints & antialiasing ? true : false);
splashOutputDev.setFreeTypeHinting(d->hints & text_hinting ? true : false, false);
splashOutputDev.startDoc(pdfdoc);
pdfdoc->displayPageSlice(&splashOutputDev, pp->index + 1, xres, yres, int(rotate) * 90, false, true, false, x, y, w, h, nullptr, nullptr, nullptr, nullptr, true);
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();
}
/**
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()
{
return true;
}