Dear Poppler developers, I have the task to render PDF documents and to trace back each output pixel to the object(s) that were rendered at this place. To achieve this, Poppler is a great help, so I'd like to contribute something back. Attached is the second smallest patch (see below) I came up with.
Do you think it makes sense to include this feature in Poppler? Usage: A. Use the private poppler API to render a PDF onto a custom OutputDev. B. Derive that custom OutputDev from SplashOutputDev. C. Set your tracePixel() callback, which is called for each rendered pixel. It may be part of the same custom OutputDev class. D. Keep track of which object is rendered right now (overwriting drawImage(), etc.), and use that information within tracePixel(). To get the discussion started, these are the things I think I could have done differently: 1. Currently, tracePixel() is called in addition to the "pipe run". However, it could also be called instead of the "pipe run". This would result in an even smaller patch, but it would suppress the PDF output while the tracer is run, which could possibly cause side effects on anti aliasing and other things. Also, since I need the rendered image as well, I would have to run the renderer twice - with and without pixel tracer. 2. The tracePixel() callback only gets the pixel coordinates (x, y), which is sufficient for my task. However, one could also think of providing the actual pixel value to that callback. The drawback is the additional complexity of handling different types of pixels. (RGB, Mono, etc.) 3. I could have used a more C++-like interface, using templates, std::function and other nice stuff. However, that would not fit well in the current coding style of Poppler, thus requiring a lot more changes. On the positive side, this would allow for a completely transparent tracing mechanism, where e.g. the compiler is able to optimize an empty tracer function completely away. Also, that could restructure the current "pipe" mechanism in a way that is as flexible as now, but would enable the compiler to inline the complete "pipe run" code without any function call. 4. I could have added the whole code for the object tracing to Poppler, rather than just the ability to add custom callbacks. However, this would be less flexible, and it is probably not a good idea to overload the Poppler project with too much specialized code that is useful for just one or two applications. Regards, Volker -- Volker Grabsch ---<<(())>>---
commit 526ae2f973d6ff7d4453c17101958f89b13c1d02 Author: Volker Grabsch <[email protected]> Date: Fri Nov 14 14:54:58 2014 +0100 Add support for pixel tracer in SplashOutputDev diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index 0eaeb79..ee1d7dd 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -1733,6 +1733,10 @@ void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace, #endif } +void SplashOutputDev::setPixelTracer(SplashPixelTracer *pixelTracer) { + splash->setPixelTracer(pixelTracer); +} + void SplashOutputDev::updateBlendMode(GfxState *state) { splash->setBlendFunc(splashOutBlendFuncs[state->getBlendMode()]); } diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h index efbb865..2f72089 100644 --- a/poppler/SplashOutputDev.h +++ b/poppler/SplashOutputDev.h @@ -52,6 +52,7 @@ class SplashFont; class T3FontCache; struct T3FontCacheTag; struct T3GlyphStack; +struct SplashPixelTracer; struct SplashTransparencyGroup; //------------------------------------------------------------------------ @@ -361,6 +362,8 @@ public: void setFreeTypeHinting(GBool enable, GBool enableSlightHinting); + void setPixelTracer(SplashPixelTracer *pixelTracer); + protected: void doUpdateFont(GfxState *state); diff --git a/splash/Splash.cc b/splash/Splash.cc index fde272a..3500b41 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -163,6 +163,9 @@ struct SplashPipe { // the "run" function void (Splash::*run)(SplashPipe *pipe); + + // the original "run" function if pixel tracer is present + void (Splash::*origRun)(SplashPipe *pipe); }; SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = { @@ -339,6 +342,12 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y, #endif } } + + // inject pixel tracer if present + if (pixelTracer != NULL) { + pipe->origRun = pipe->run; + pipe->run = &Splash::pipeRunPixelTracer; + } } // general case @@ -1320,6 +1329,12 @@ void Splash::pipeRunAADeviceN8(SplashPipe *pipe) { } #endif +// run pixel tracer, then call original "run" function +void Splash::pipeRunPixelTracer(SplashPipe *pipe) { + pixelTracer->tracePixel(pipe->x, pipe->y); + (this->*pipe->run)(pipe); +} + inline void Splash::pipeSetXY(SplashPipe *pipe, int x, int y) { pipe->x = x; pipe->y = y; @@ -1606,6 +1621,7 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, clearModRegion(); debugMode = gFalse; alpha0Bitmap = NULL; + pixelTracer = NULL; } Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, @@ -1634,6 +1650,7 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, clearModRegion(); debugMode = gFalse; alpha0Bitmap = NULL; + pixelTracer = NULL; } Splash::~Splash() { diff --git a/splash/Splash.h b/splash/Splash.h index cf98e6c..4b6bb5d 100644 --- a/splash/Splash.h +++ b/splash/Splash.h @@ -81,6 +81,15 @@ enum SplashPipeResultColorCtrl { }; //------------------------------------------------------------------------ + +class SplashPixelTracer { +public: + SplashPixelTracer() {} + virtual ~SplashPixelTracer() {} + virtual void tracePixel(int x, int y) = 0; +}; + +//------------------------------------------------------------------------ // Splash //------------------------------------------------------------------------ @@ -280,6 +289,9 @@ public: // Draw a gouraud triangle shading. GBool gouraudTriangleShadedFill(SplashGouraudColor *shading); + // Set pixel tracer + void setPixelTracer(SplashPixelTracer *pixelTracerA) { pixelTracer = pixelTracerA; } + private: void pipeInit(SplashPipe *pipe, int x, int y, @@ -306,6 +318,7 @@ private: void pipeRunAACMYK8(SplashPipe *pipe); void pipeRunAADeviceN8(SplashPipe *pipe); #endif + void pipeRunPixelTracer(SplashPipe *pipe); void pipeSetXY(SplashPipe *pipe, int x, int y); void pipeIncX(SplashPipe *pipe); void drawPixel(SplashPipe *pipe, int x, int y, GBool noClip); @@ -421,6 +434,7 @@ private: GBool vectorAntialias; GBool inShading; GBool debugMode; + SplashPixelTracer *pixelTracer; }; #endif
_______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
