From a4ad6d778036af05aa0287fe9e434a9f96e8fdf9 Mon Sep 17 00:00:00 2001 From: Oliver Sander Date: Sat, 28 Oct 2017 21:16:55 +0200 Subject: [PATCH 4/4] [Arthur] Rudimentary support for transparency groups This patch adds minimal support for transparency groups. With it, the Arthur backend can render highlight annotations. --- qt5/src/ArthurOutputDev.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++++ qt5/src/ArthurOutputDev.h | 15 +++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/qt5/src/ArthurOutputDev.cc b/qt5/src/ArthurOutputDev.cc index 5a4202f0..427bbf2e 100644 --- a/qt5/src/ArthurOutputDev.cc +++ b/qt5/src/ArthurOutputDev.cc @@ -54,6 +54,8 @@ #include #include #include +#include + //------------------------------------------------------------------------ #ifdef HAVE_SPLASH @@ -88,6 +90,7 @@ private: //------------------------------------------------------------------------ ArthurOutputDev::ArthurOutputDev(QPainter *painter): + m_lastTransparencyGroupPicture(nullptr), m_fontHinting(NoHinting) { m_painter.push(painter); @@ -986,3 +989,46 @@ void ArthurOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream * m_painter.top()->drawImage( QRect(0,0,1,1), image ); } +void ArthurOutputDev::beginTransparencyGroup(GfxState * /*state*/, double * /*bbox*/, + GfxColorSpace * /*blendingColorSpace*/, + GBool /*isolated*/, GBool /*knockout*/, + GBool /*forSoftMask*/) +{ + // The entire transparency group will be painted into a + // freshly created QPicture object. Since an existing painter + // cannot change its paint device, we need to construct a + // new QPainter object as well. + m_qpictures.push(new QPicture); + m_painter.push(new QPainter(m_qpictures.top())); +} + +void ArthurOutputDev::endTransparencyGroup(GfxState * /*state*/) +{ + // Stop painting into the group + m_painter.top()->end(); + + // Kill the painter that has been used for the transparency group + delete(m_painter.top()); + m_painter.pop(); + + // Store the QPicture object that holds the result of the transparency group + // painting. It will be painted and deleted in the method paintTransparencyGroup. + if (m_lastTransparencyGroupPicture) + { + qDebug() << "Found a transparency group that has not been painted"; + delete(m_lastTransparencyGroupPicture); + } + m_lastTransparencyGroupPicture = m_qpictures.top(); + m_qpictures.pop(); +} + +void ArthurOutputDev::paintTransparencyGroup(GfxState * /*state*/, double * /*bbox*/) +{ + // Actually draw the transparency group + m_painter.top()->drawPicture(0,0,*m_lastTransparencyGroupPicture); + + // And delete it + delete(m_lastTransparencyGroupPicture); + m_lastTransparencyGroupPicture = nullptr; +} + diff --git a/qt5/src/ArthurOutputDev.h b/qt5/src/ArthurOutputDev.h index 4fae0a5c..b4ab3d7e 100644 --- a/qt5/src/ArthurOutputDev.h +++ b/qt5/src/ArthurOutputDev.h @@ -164,6 +164,14 @@ public: void type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) override; + //----- transparency groups and soft masks + virtual void beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) override; + virtual void endTransparencyGroup(GfxState *state) override; + virtual void paintTransparencyGroup(GfxState *state, double *bbox) override; + //----- special access // Called to indicate that a new PDF document has been loaded. @@ -178,6 +186,13 @@ private: // It is popped again when the transparency group ends. std::stack m_painter; + // This is the corresponding stack of QPicture objects + std::stack m_qpictures; + + // endTransparencyGroup removes a QPicture from the stack, but stores + // it here for later use in paintTransparencyGroup. + QPicture* m_lastTransparencyGroupPicture; + FontHinting m_fontHinting; QPen m_currentPen; -- 2.14.2