1
0
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:
Duan Yao 2014-06-07 02:01:10 +08:00 committed by Lu Wang
parent a36c612744
commit 85a7c43f83
6 changed files with 92 additions and 34 deletions

View File

@ -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

View File

@ -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;
}; };
} }

View File

@ -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";

View File

@ -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

View File

@ -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;

View File

@ -190,7 +190,8 @@ void parse_options (int argc, char **argv)
// background image // background image
.add("bg-format", &param.bg_format, "png", "specify background image format") .add("bg-format", &param.bg_format, "png", "specify background image format")
.add("svg-nodes-limit", &param.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", &param.owner_password, "", "owner password (for encrypted files)", true) .add("owner-password,o", &param.owner_password, "", "owner password (for encrypted files)", true)
.add("user-password,u", &param.user_password, "", "user password (for encrypted files)", true) .add("user-password,u", &param.user_password, "", "user password (for encrypted files)", true)