diff --git a/pdf2htmlEX.1.in b/pdf2htmlEX.1.in
index b63b1d9..026e88b 100644
--- a/pdf2htmlEX.1.in
+++ b/pdf2htmlEX.1.in
@@ -296,6 +296,11 @@ Experimental and unsupported CSS drawing
.B --debug <0|1> (Default: 0)
Print debug information.
+.TP
+.B --proof <0|1|2> (Default: 0)
+Output a proof version. If a positive value is specified, texts are drawn on both text layer and background image for comparision.
+If 2 is specified, texts on background are in different colors, usually red for filling, blue for stroking.
+
.SS Meta
.TP
diff --git a/src/BackgroundRenderer/BackgroundRenderer.cc b/src/BackgroundRenderer/BackgroundRenderer.cc
index 1ae298c..ba1e832 100644
--- a/src/BackgroundRenderer/BackgroundRenderer.cc
+++ b/src/BackgroundRenderer/BackgroundRenderer.cc
@@ -49,4 +49,57 @@ BackgroundRenderer * BackgroundRenderer::getFallbackBackgroundRenderer(HTMLRende
return nullptr;
}
+BackgroundRenderer::~BackgroundRenderer()
+{
+ //delete proof_state
+ if (proof_state)
+ delete proof_state;
+}
+
+void BackgroundRenderer::proof_begin_string(GfxState *state)
+{
+ auto dev = (OutputDev*) dynamic_cast(this);
+ if (!dev)
+ dev = (OutputDev*) dynamic_cast(this);
+
+ if (!proof_state)
+ {
+ PDFRectangle rect(0, 0, state->getPageWidth(), state->getPageHeight());
+ proof_state = new GfxState(state->getHDPI(), state->getVDPI(), &rect, state->getRotate(), dev->upsideDown());
+ proof_state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+ proof_state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+ }
+
+ Color fc, sc, red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), yellow(1, 1, 0);
+ state->getFillRGB(&fc.rgb);
+ state->getStrokeRGB(&sc.rgb);
+
+ fc = fc.distance(red) > 0.4 ? red : green;
+ sc = sc.distance(blue) > 0.4 ? blue : yellow;
+
+ if (state->getFillColorSpace()->getMode() != csDeviceRGB)
+ dev->updateFillColorSpace(proof_state);
+ if (state->getStrokeColorSpace()->getMode() != csDeviceRGB)
+ dev->updateStrokeColorSpace(proof_state);
+ GfxColor gfc, gsc;
+ fc.get_gfx_color(gfc);
+ sc.get_gfx_color(gsc);
+ proof_state->setFillColor(&gfc);
+ proof_state->setStrokeColor(&gsc);
+ dev->updateFillColor(proof_state);
+ dev->updateStrokeColor(proof_state);
+}
+
+void BackgroundRenderer::proof_end_text_object(GfxState *state)
+{
+ auto dev = (OutputDev*) dynamic_cast(this);
+ if (!dev)
+ dev = (OutputDev*) dynamic_cast(this);
+
+ dev->updateFillColorSpace(state);
+ dev->updateStrokeColorSpace(state);
+ dev->updateFillColor(state);
+ dev->updateStrokeColor(state);
+}
+
} // namespace pdf2htmlEX
diff --git a/src/BackgroundRenderer/BackgroundRenderer.h b/src/BackgroundRenderer/BackgroundRenderer.h
index 29e03b6..e1c6179 100644
--- a/src/BackgroundRenderer/BackgroundRenderer.h
+++ b/src/BackgroundRenderer/BackgroundRenderer.h
@@ -12,6 +12,7 @@
#include
class PDFDoc;
+class GfxState;
namespace pdf2htmlEX {
@@ -26,14 +27,20 @@ public:
// Currently only svg bg format might need a bitmap fallback.
static BackgroundRenderer * getFallbackBackgroundRenderer(HTMLRenderer * html_renderer, const Param & param);
- BackgroundRenderer() {}
- virtual ~BackgroundRenderer() {}
+ BackgroundRenderer(): proof_state(nullptr) {}
+ virtual ~BackgroundRenderer();
virtual void init(PDFDoc * doc) = 0;
//return true on success, false otherwise (e.g. need a fallback)
virtual bool render_page(PDFDoc * doc, int pageno) = 0;
virtual void embed_image(int pageno) = 0;
+ // for proof output
+protected:
+ void proof_begin_string(GfxState *state);
+ void proof_end_text_object(GfxState *state);
+private:
+ GfxState * proof_state;
};
} // namespace pdf2htmlEX
diff --git a/src/BackgroundRenderer/CairoBackgroundRenderer.cc b/src/BackgroundRenderer/CairoBackgroundRenderer.cc
index 63a6a81..1e9eabd 100644
--- a/src/BackgroundRenderer/CairoBackgroundRenderer.cc
+++ b/src/BackgroundRenderer/CairoBackgroundRenderer.cc
@@ -53,8 +53,8 @@ void CairoBackgroundRenderer::drawChar(GfxState *state, double x, double y,
// - OR there is special filling method
// - OR using a writing mode font
// - OR using a Type 3 font while param.process_type3 is not enabled
- if((param.fallback)
- || ( (state->getFont())
+ if((param.fallback || param.proof)
+ || ( (state->getFont())
&& ( (state->getFont()->getWMode())
|| ((state->getFont()->getType() == fontType3) && (!param.process_type3))
)
@@ -65,6 +65,20 @@ void CairoBackgroundRenderer::drawChar(GfxState *state, double x, double y,
}
}
+void CairoBackgroundRenderer::beginString(GfxState *state, GooString * str)
+{
+ if (param.proof == 2)
+ proof_begin_string(state);
+ CairoOutputDev::beginString(state, str);
+}
+
+void CairoBackgroundRenderer::endTextObject(GfxState *state)
+{
+ if (param.proof == 2)
+ proof_end_text_object(state);
+ CairoOutputDev::endTextObject(state);
+}
+
void CairoBackgroundRenderer::init(PDFDoc * doc)
{
startDoc(doc);
diff --git a/src/BackgroundRenderer/CairoBackgroundRenderer.h b/src/BackgroundRenderer/CairoBackgroundRenderer.h
index 8abe5f3..68d9123 100644
--- a/src/BackgroundRenderer/CairoBackgroundRenderer.h
+++ b/src/BackgroundRenderer/CairoBackgroundRenderer.h
@@ -44,6 +44,10 @@ public:
double originX, double originY,
CharCode code, int nBytes, Unicode *u, int uLen);
+ //for proof
+ void beginString(GfxState *state, GooString * str);
+ void endTextObject(GfxState *state);
+
protected:
virtual void setMimeData(Stream *str, Object *ref, cairo_surface_t *image);
diff --git a/src/BackgroundRenderer/SplashBackgroundRenderer.cc b/src/BackgroundRenderer/SplashBackgroundRenderer.cc
index c596508..7feb043 100644
--- a/src/BackgroundRenderer/SplashBackgroundRenderer.cc
+++ b/src/BackgroundRenderer/SplashBackgroundRenderer.cc
@@ -78,7 +78,7 @@ void SplashBackgroundRenderer::drawChar(GfxState *state, double x, double y,
// - OR there is special filling method
// - OR using a writing mode font
// - OR using a Type 3 font while param.process_type3 is not enabled
- if((param.fallback)
+ if((param.fallback || param.proof)
|| ( (state->getFont())
&& ( (state->getFont()->getWMode())
|| ((state->getFont()->getType() == fontType3) && (!param.process_type3))
@@ -90,6 +90,20 @@ void SplashBackgroundRenderer::drawChar(GfxState *state, double x, double y,
}
}
+void SplashBackgroundRenderer::beginString(GfxState *state, GooString * str)
+{
+ if (param.proof == 2)
+ proof_begin_string(state);
+ SplashOutputDev::beginString(state, str);
+}
+
+void SplashBackgroundRenderer::endTextObject(GfxState *state)
+{
+ if (param.proof == 2)
+ proof_end_text_object(state);
+ SplashOutputDev::endTextObject(state);
+}
+
void SplashBackgroundRenderer::init(PDFDoc * doc)
{
startDoc(doc);
diff --git a/src/BackgroundRenderer/SplashBackgroundRenderer.h b/src/BackgroundRenderer/SplashBackgroundRenderer.h
index 9ec8de9..205c201 100644
--- a/src/BackgroundRenderer/SplashBackgroundRenderer.h
+++ b/src/BackgroundRenderer/SplashBackgroundRenderer.h
@@ -60,6 +60,10 @@ public:
SplashOutputDev::fill(state);
}
+ //for proof
+ void beginString(GfxState *state, GooString * str);
+ void endTextObject(GfxState *state);
+
protected:
void dump_image(const char * filename, int x1, int y1, int x2, int y2);
HTMLRenderer * html_renderer;
diff --git a/src/Color.cc b/src/Color.cc
index 3c06fca..07781a7 100644
--- a/src/Color.cc
+++ b/src/Color.cc
@@ -1,3 +1,5 @@
+#include
+
#include "Color.h"
#include "util/misc.h"
@@ -6,6 +8,22 @@ namespace pdf2htmlEX {
using std::ostream;
+Color::Color()
+{
+ memset(this, 0, sizeof(Color));
+}
+
+Color::Color(double r, double g, double b, bool transparent)
+ :transparent(transparent)
+{
+ rgb.r = (GfxColorComp)(r * gfxColorComp1);
+ rgb.g = (GfxColorComp)(g * gfxColorComp1);
+ rgb.b = (GfxColorComp)(b * gfxColorComp1);
+}
+
+Color::Color(const GfxRGB& rgb)
+ :transparent(false), rgb(rgb) { }
+
ostream & operator << (ostream & out, const Color & color)
{
if(color.transparent)
@@ -15,4 +33,19 @@ ostream & operator << (ostream & out, const Color & color)
return out;
}
+void Color::get_gfx_color(GfxColor & gc)
+{
+ gc.c[0] = rgb.r;
+ gc.c[1] = rgb.g;
+ gc.c[2] = rgb.b;
+}
+
+double Color::distance(const Color & other)
+{
+ double dr = (double)rgb.r - other.rgb.r,
+ dg = (double)rgb.g - other.rgb.g,
+ db = (double)rgb.b - other.rgb.b;
+ return sqrt((dr * dr + dg * dg + db * db) / (3.0 * gfxColorComp1 * gfxColorComp1));
+}
+
} // namespace pdf2htmlEX
diff --git a/src/Color.h b/src/Color.h
index 5c54559..2e8c7d8 100644
--- a/src/Color.h
+++ b/src/Color.h
@@ -16,6 +16,9 @@ struct Color
{
bool transparent;
GfxRGB rgb;
+ Color();
+ Color(double r, double g, double b, bool transparent = false);
+ Color(const GfxRGB& rgb);
bool operator == (const Color & c) const {
if(transparent != c.transparent)
return false;
@@ -23,6 +26,9 @@ struct Color
return true;
return ((rgb.r == c.rgb.r) && (rgb.g == c.rgb.g) && (rgb.b == c.rgb.b));
}
+ void get_gfx_color(GfxColor & gc);
+ // Color distance, [0,1].
+ double distance(const Color & other);
};
std::ostream & operator << (std::ostream & out, const Color & color);
diff --git a/src/Param.h b/src/Param.h
index 8c16802..84a2f55 100644
--- a/src/Param.h
+++ b/src/Param.h
@@ -76,6 +76,7 @@ struct Param
std::string tmp_dir;
int css_draw;
int debug;
+ int proof;
std::string input_filename, output_filename;
};
diff --git a/src/pdf2htmlEX.cc b/src/pdf2htmlEX.cc
index f20dc2b..cd1ae46 100644
--- a/src/pdf2htmlEX.cc
+++ b/src/pdf2htmlEX.cc
@@ -206,6 +206,7 @@ void parse_options (int argc, char **argv)
// TODO: css drawings are hidden on print, for annot links, need to fix it for other drawings
// .add("css-draw", ¶m.css_draw, 0, "[experimental and unsupported] CSS drawing")
.add("debug", ¶m.debug, 0, "print debugging information")
+ .add("proof", ¶m.proof, 0, "texts are drawn on both text layer and background for proof.")
// meta
.add("version,v", "print copyright and version info", &show_version_and_exit)