mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-12-22 13:00:08 +00:00
Add svg-nodes-limit option to avoid overly complicated svg background.
This commit is contained in:
parent
4865d3aa5c
commit
82b0569c06
@ -15,12 +15,28 @@
|
|||||||
#if ENABLE_SVG
|
#if ENABLE_SVG
|
||||||
|
|
||||||
#include "CairoBackgroundRenderer.h"
|
#include "CairoBackgroundRenderer.h"
|
||||||
|
#include "SplashBackgroundRenderer.h"
|
||||||
|
|
||||||
namespace pdf2htmlEX {
|
namespace pdf2htmlEX {
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::ifstream;
|
using std::ifstream;
|
||||||
|
|
||||||
|
CairoBackgroundRenderer::CairoBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param)
|
||||||
|
: CairoOutputDev()
|
||||||
|
, html_renderer(html_renderer)
|
||||||
|
, param(param)
|
||||||
|
, surface(nullptr)
|
||||||
|
, use_bitmap(false)
|
||||||
|
{
|
||||||
|
if (param.svg_nodes_limit > 0)
|
||||||
|
{
|
||||||
|
this->bitmap_renderer = new SplashBackgroundRenderer(html_renderer, param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->bitmap_renderer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void CairoBackgroundRenderer::drawChar(GfxState *state, double x, double y,
|
void CairoBackgroundRenderer::drawChar(GfxState *state, double x, double y,
|
||||||
double dx, double dy,
|
double dx, double dy,
|
||||||
double originX, double originY,
|
double originX, double originY,
|
||||||
@ -46,6 +62,8 @@ void CairoBackgroundRenderer::drawChar(GfxState *state, double x, double y,
|
|||||||
void CairoBackgroundRenderer::init(PDFDoc * doc)
|
void CairoBackgroundRenderer::init(PDFDoc * doc)
|
||||||
{
|
{
|
||||||
startDoc(doc);
|
startDoc(doc);
|
||||||
|
if (this->bitmap_renderer != nullptr)
|
||||||
|
this->bitmap_renderer->init(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GBool annot_cb(Annot *, void * pflag) {
|
static GBool annot_cb(Annot *, void * pflag) {
|
||||||
@ -67,13 +85,11 @@ void CairoBackgroundRenderer::render_page(PDFDoc * doc, int pageno)
|
|||||||
page_height = doc->getPageMediaHeight(pageno);
|
page_height = doc->getPageMediaHeight(pageno);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
auto fn = html_renderer->str_fmt("%s/bg%x.svg", (param.embed_image ? param.tmp_dir : param.dest_dir).c_str(), pageno);
|
||||||
auto fn = html_renderer->str_fmt("%s/bg%x.svg", (param.embed_image ? param.tmp_dir : param.dest_dir).c_str(), pageno);
|
if(param.embed_image)
|
||||||
if(param.embed_image)
|
html_renderer->tmp_files.add((char*)fn);
|
||||||
html_renderer->tmp_files.add((char*)fn);
|
|
||||||
|
|
||||||
surface = cairo_svg_surface_create((char*)fn, page_width * param.h_dpi / DEFAULT_DPI, page_height * param.v_dpi / DEFAULT_DPI);
|
surface = cairo_svg_surface_create((char*)fn, page_width * param.h_dpi / DEFAULT_DPI, page_height * param.v_dpi / DEFAULT_DPI);
|
||||||
}
|
|
||||||
cairo_svg_surface_restrict_to_version(surface, CAIRO_SVG_VERSION_1_2);
|
cairo_svg_surface_restrict_to_version(surface, CAIRO_SVG_VERSION_1_2);
|
||||||
cairo_surface_set_fallback_resolution(surface, param.h_dpi, param.v_dpi);
|
cairo_surface_set_fallback_resolution(surface, param.h_dpi, param.v_dpi);
|
||||||
|
|
||||||
@ -105,10 +121,39 @@ void CairoBackgroundRenderer::render_page(PDFDoc * doc, int pageno)
|
|||||||
if(status)
|
if(status)
|
||||||
throw string("Error in cairo: ") + cairo_status_to_string(status);
|
throw string("Error in cairo: ") + cairo_status_to_string(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check node count in the svg file, fall back to bitmap_renderer if necessary.
|
||||||
|
if (param.svg_nodes_limit > 0)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
char c;
|
||||||
|
ifstream svgfile((char*)fn);
|
||||||
|
//count of '<' in the file should be an approximation of node count.
|
||||||
|
while(svgfile >> c)
|
||||||
|
{
|
||||||
|
if (c == '<')
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
svgfile.close();
|
||||||
|
if (n > param.svg_nodes_limit)
|
||||||
|
{
|
||||||
|
html_renderer->tmp_files.add((char*)fn);
|
||||||
|
use_bitmap = true;
|
||||||
|
bitmap_renderer->render_page(doc, pageno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
use_bitmap = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CairoBackgroundRenderer::embed_image(int pageno)
|
void CairoBackgroundRenderer::embed_image(int pageno)
|
||||||
{
|
{
|
||||||
|
if (use_bitmap)
|
||||||
|
{
|
||||||
|
bitmap_renderer->embed_image(pageno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto & f_page = *(html_renderer->f_curpage);
|
auto & f_page = *(html_renderer->f_curpage);
|
||||||
|
|
||||||
f_page << "<img class=\"" << CSS::FULL_BACKGROUND_IMAGE_CN
|
f_page << "<img class=\"" << CSS::FULL_BACKGROUND_IMAGE_CN
|
||||||
|
@ -20,16 +20,13 @@
|
|||||||
|
|
||||||
namespace pdf2htmlEX {
|
namespace pdf2htmlEX {
|
||||||
|
|
||||||
|
class SplashBackgroundRenderer;
|
||||||
|
|
||||||
// Based on BackgroundRenderer from poppler
|
// Based on BackgroundRenderer from poppler
|
||||||
class CairoBackgroundRenderer : public BackgroundRenderer, CairoOutputDev
|
class CairoBackgroundRenderer : public BackgroundRenderer, CairoOutputDev
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CairoBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param)
|
CairoBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param);
|
||||||
: CairoOutputDev()
|
|
||||||
, html_renderer(html_renderer)
|
|
||||||
, param(param)
|
|
||||||
, surface(nullptr)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual ~CairoBackgroundRenderer() { }
|
virtual ~CairoBackgroundRenderer() { }
|
||||||
|
|
||||||
@ -50,6 +47,8 @@ protected:
|
|||||||
HTMLRenderer * html_renderer;
|
HTMLRenderer * html_renderer;
|
||||||
const Param & param;
|
const Param & param;
|
||||||
cairo_surface_t * surface;
|
cairo_surface_t * surface;
|
||||||
|
SplashBackgroundRenderer * bitmap_renderer;
|
||||||
|
bool use_bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,30 @@ using std::unique_ptr;
|
|||||||
|
|
||||||
const SplashColor SplashBackgroundRenderer::white = {255,255,255};
|
const SplashColor SplashBackgroundRenderer::white = {255,255,255};
|
||||||
|
|
||||||
|
SplashBackgroundRenderer::SplashBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param)
|
||||||
|
: SplashOutputDev(splashModeRGB8, 4, gFalse, (SplashColorPtr)(&white), gTrue, gTrue)
|
||||||
|
, html_renderer(html_renderer)
|
||||||
|
, param(param)
|
||||||
|
{
|
||||||
|
if(false) { }
|
||||||
|
#ifdef ENABLE_LIBPNG
|
||||||
|
else if(param.bg_format == "png" || param.bg_format == "svg")
|
||||||
|
{
|
||||||
|
format = "png";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_LIBJPEG
|
||||||
|
else if(param.bg_format == "jpg" || param.bg_format == "svg")
|
||||||
|
{
|
||||||
|
format = "jpg";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw string("Image format not supported: ") + param.bg_format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SplashOutputDev::startPage would paint the whole page with the background color
|
* SplashOutputDev::startPage would paint the whole page with the background color
|
||||||
* And thus have modified region set to the whole page area
|
* And thus have modified region set to the whole page area
|
||||||
@ -96,7 +120,7 @@ void SplashBackgroundRenderer::embed_image(int pageno)
|
|||||||
if((xmin <= xmax) && (ymin <= ymax))
|
if((xmin <= xmax) && (ymin <= ymax))
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto fn = html_renderer->str_fmt("%s/bg%x.%s", (param.embed_image ? param.tmp_dir : param.dest_dir).c_str(), pageno, param.bg_format.c_str());
|
auto fn = html_renderer->str_fmt("%s/bg%x.%s", (param.embed_image ? param.tmp_dir : param.dest_dir).c_str(), pageno, format.c_str());
|
||||||
if(param.embed_image)
|
if(param.embed_image)
|
||||||
html_renderer->tmp_files.add((char*)fn);
|
html_renderer->tmp_files.add((char*)fn);
|
||||||
|
|
||||||
@ -118,21 +142,21 @@ void SplashBackgroundRenderer::embed_image(int pageno)
|
|||||||
|
|
||||||
if(param.embed_image)
|
if(param.embed_image)
|
||||||
{
|
{
|
||||||
auto path = html_renderer->str_fmt("%s/bg%x.%s", param.tmp_dir.c_str(), pageno, param.bg_format.c_str());
|
auto path = html_renderer->str_fmt("%s/bg%x.%s", param.tmp_dir.c_str(), pageno, format.c_str());
|
||||||
ifstream fin((char*)path, ifstream::binary);
|
ifstream fin((char*)path, ifstream::binary);
|
||||||
if(!fin)
|
if(!fin)
|
||||||
throw string("Cannot read background image ") + (char*)path;
|
throw string("Cannot read background image ") + (char*)path;
|
||||||
|
|
||||||
auto iter = FORMAT_MIME_TYPE_MAP.find(param.bg_format);
|
auto iter = FORMAT_MIME_TYPE_MAP.find(format);
|
||||||
if(iter == FORMAT_MIME_TYPE_MAP.end())
|
if(iter == FORMAT_MIME_TYPE_MAP.end())
|
||||||
throw string("Image format not supported: ") + param.bg_format;
|
throw string("Image format not supported: ") + format;
|
||||||
|
|
||||||
string mime_type = iter->second;
|
string mime_type = iter->second;
|
||||||
f_page << "data:" << mime_type << ";base64," << Base64Stream(fin);
|
f_page << "data:" << mime_type << ";base64," << Base64Stream(fin);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
f_page << (char*)html_renderer->str_fmt("bg%x.%s", pageno, param.bg_format.c_str());
|
f_page << (char*)html_renderer->str_fmt("bg%x.%s", pageno, format.c_str());
|
||||||
}
|
}
|
||||||
f_page << "\"/>";
|
f_page << "\"/>";
|
||||||
}
|
}
|
||||||
@ -153,23 +177,14 @@ void SplashBackgroundRenderer::dump_image(const char * filename, int x1, int y1,
|
|||||||
// use unique_ptr to auto delete the object upon exception
|
// use unique_ptr to auto delete the object upon exception
|
||||||
unique_ptr<ImgWriter> writer;
|
unique_ptr<ImgWriter> writer;
|
||||||
|
|
||||||
if(false) { }
|
if(format == "png")
|
||||||
#ifdef ENABLE_LIBPNG
|
|
||||||
else if(param.bg_format == "png")
|
|
||||||
{
|
{
|
||||||
writer = unique_ptr<ImgWriter>(new PNGWriter);
|
writer = unique_ptr<ImgWriter>(new PNGWriter);
|
||||||
}
|
}
|
||||||
#endif
|
else if(format == "jpg")
|
||||||
#ifdef ENABLE_LIBJPEG
|
|
||||||
else if(param.bg_format == "jpg")
|
|
||||||
{
|
{
|
||||||
writer = unique_ptr<ImgWriter>(new JpegWriter);
|
writer = unique_ptr<ImgWriter>(new JpegWriter);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw string("Image format not supported: ") + param.bg_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!writer->init(f, width, height, param.h_dpi, param.v_dpi))
|
if(!writer->init(f, width, height, param.h_dpi, param.v_dpi))
|
||||||
throw "Cannot initialize PNGWriter";
|
throw "Cannot initialize PNGWriter";
|
||||||
|
@ -27,11 +27,7 @@ class SplashBackgroundRenderer : public BackgroundRenderer, SplashOutputDev
|
|||||||
public:
|
public:
|
||||||
static const SplashColor white;
|
static const SplashColor white;
|
||||||
|
|
||||||
SplashBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param)
|
SplashBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param);
|
||||||
: SplashOutputDev(splashModeRGB8, 4, gFalse, (SplashColorPtr)(&white), gTrue, gTrue)
|
|
||||||
, html_renderer(html_renderer)
|
|
||||||
, param(param)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual ~SplashBackgroundRenderer() { }
|
virtual ~SplashBackgroundRenderer() { }
|
||||||
|
|
||||||
@ -68,6 +64,7 @@ protected:
|
|||||||
void dump_image(const char * filename, int x1, int y1, int x2, int y2);
|
void dump_image(const char * filename, int x1, int y1, int x2, int y2);
|
||||||
HTMLRenderer * html_renderer;
|
HTMLRenderer * html_renderer;
|
||||||
const Param & param;
|
const Param & param;
|
||||||
|
std::string format;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf2htmlEX
|
} // namespace pdf2htmlEX
|
||||||
|
@ -63,6 +63,7 @@ struct Param
|
|||||||
|
|
||||||
// background image
|
// background image
|
||||||
std::string bg_format;
|
std::string bg_format;
|
||||||
|
int svg_nodes_limit = 0;
|
||||||
|
|
||||||
// encryption
|
// encryption
|
||||||
std::string owner_password, user_password;
|
std::string owner_password, user_password;
|
||||||
|
@ -190,7 +190,8 @@ void parse_options (int argc, char **argv)
|
|||||||
|
|
||||||
// background image
|
// background image
|
||||||
.add("bg-format", ¶m.bg_format, "png", "specify background image format")
|
.add("bg-format", ¶m.bg_format, "png", "specify background image format")
|
||||||
|
.add("svg-nodes-limit", ¶m.svg_nodes_limit, 0, "if node count in a svg background image exceeds this limit,"
|
||||||
|
" fall back to bitmap background. 0 or negative means no limit.")
|
||||||
// encryption
|
// encryption
|
||||||
.add("owner-password,o", ¶m.owner_password, "", "owner password (for encrypted files)", true)
|
.add("owner-password,o", ¶m.owner_password, "", "owner password (for encrypted files)", true)
|
||||||
.add("user-password,u", ¶m.user_password, "", "user password (for encrypted files)", true)
|
.add("user-password,u", ¶m.user_password, "", "user password (for encrypted files)", true)
|
||||||
|
Loading…
Reference in New Issue
Block a user