/*
 * 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 (!poppler::page_renderer_private::conv_color_mode(d->image_format, colorMode) || !poppler::page_renderer_private::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;
}
