diff --git a/qt5/src/CMakeLists.txt b/qt5/src/CMakeLists.txt index 5ae42f52..1c1a7fad 100644 --- a/qt5/src/CMakeLists.txt +++ b/qt5/src/CMakeLists.txt @@ -10,41 +10,41 @@ include_directories( set(poppler_qt5_SRCS poppler-annotation.cc poppler-document.cc poppler-embeddedfile.cc poppler-fontinfo.cc poppler-form.cc poppler-link.cc poppler-link-extractor.cc poppler-movie.cc poppler-optcontent.cc poppler-page.cc poppler-base-converter.cc poppler-pdf-converter.cc poppler-private.cc poppler-ps-converter.cc poppler-qiodeviceoutstream.cc poppler-sound.cc poppler-textbox.cc poppler-page-transition.cc poppler-media.cc - ArthurOutputDev.cc + Qt5OutputDevices.cc ) add_library(poppler-qt5 ${poppler_qt5_SRCS}) set_target_properties(poppler-qt5 PROPERTIES VERSION 1.13.0 SOVERSION 1) if(MINGW) get_target_property(POPPLER_QT5_SOVERSION poppler-qt5 SOVERSION) set_target_properties(poppler-qt5 PROPERTIES SUFFIX "-${POPPLER_QT5_SOVERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") endif() target_link_libraries(poppler-qt5 poppler ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Xml_LIBRARIES}) if(MSVC) target_link_libraries(poppler-qt5 poppler ${poppler_LIBS}) endif() install(TARGETS poppler-qt5 RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES poppler-qt5.h poppler-link.h poppler-annotation.h poppler-form.h poppler-optcontent.h poppler-export.h diff --git a/qt5/src/ArthurOutputDev.cc b/qt5/src/Qt5OutputDevices.cc similarity index 91% rename from qt5/src/ArthurOutputDev.cc rename to qt5/src/Qt5OutputDevices.cc index 9af32ae5..0ca83de4 100644 --- a/qt5/src/ArthurOutputDev.cc +++ b/qt5/src/Qt5OutputDevices.cc @@ -1,23 +1,23 @@ //======================================================================== // -// ArthurOutputDev.cc +// Qt5OutputDevices.cc // // Copyright 2003 Glyph & Cog, LLC // //======================================================================== //======================================================================== // // Modified under the Poppler project - http://poppler.freedesktop.org // // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // // Copyright (C) 2005 Brad Hards // Copyright (C) 2005-2009, 2011, 2012, 2014, 2015, 2018 Albert Astals Cid // Copyright (C) 2008, 2010 Pino Toscano // Copyright (C) 2009, 2011 Carlos Garcia Campos // Copyright (C) 2009 Petr Gajdos // Copyright (C) 2010 Matthias Fauconneau // Copyright (C) 2011 Andreas Hartmetz // Copyright (C) 2013 Thomas Freitag @@ -31,78 +31,95 @@ // //======================================================================== #include #ifdef USE_GCC_PRAGMAS #pragma implementation #endif #include #include #include "goo/gfile.h" #include "GlobalParams.h" #include "Error.h" #include "Object.h" #include "GfxState.h" #include "GfxFont.h" #include "Link.h" #include "FontEncodingTables.h" +#include "Qt5OutputDevices.h" + #include -#include "ArthurOutputDev.h" +#if defined(HAVE_SPLASH) +#include +#include +#endif #include #include #include #include #include //------------------------------------------------------------------------ #ifdef HAVE_SPLASH #include "splash/SplashFontFileID.h" #include "splash/SplashFTFontFile.h" #include "splash/SplashFontEngine.h" //------------------------------------------------------------------------ // SplashOutFontFileID //------------------------------------------------------------------------ class SplashOutFontFileID: public SplashFontFileID { public: SplashOutFontFileID(Ref *rA) { r = *rA; } ~SplashOutFontFileID() {} GBool matches(SplashFontFileID *id) override { return ((SplashOutFontFileID *)id)->r.num == r.num && ((SplashOutFontFileID *)id)->r.gen == r.gen; } private: Ref r; }; #endif +//------------------------------------------------------------------------ +// OutputDevCallbackHelper +//------------------------------------------------------------------------ + +void OutputDevCallbackHelper::setCallbacks(Poppler::Page::RenderToImagePartialUpdateFunc callback, Poppler::Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, Poppler::Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA) +{ + partialUpdateCallback = callback; + shouldDoPartialUpdateCallback = shouldDoCallback; + shouldAbortRenderCallback = shouldAbortCallback; + payload = payloadA; +} + //------------------------------------------------------------------------ // ArthurOutputDev //------------------------------------------------------------------------ ArthurOutputDev::ArthurOutputDev(QPainter *painter): m_lastTransparencyGroupPicture(nullptr), m_fontHinting(NoHinting) { m_painter.push(painter); m_currentBrush = QBrush(Qt::SolidPattern); m_fontEngine = nullptr; } ArthurOutputDev::~ArthurOutputDev() { #ifdef HAVE_SPLASH delete m_fontEngine; #endif } @@ -1144,20 +1161,102 @@ void ArthurOutputDev::endTransparencyGroup(GfxState * /*state*/) // 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; } +//------------------------------------------------------------------------ +// QImageDumpingArthurOutputDev +//------------------------------------------------------------------------ + +QImageDumpingArthurOutputDev::QImageDumpingArthurOutputDev(QPainter *painter, QImage *i) + : ArthurOutputDev(painter) + , image(i) +{ +} + +void QImageDumpingArthurOutputDev::dump() +{ + if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) { + partialUpdateCallback(*image, payload); + } +} + +//------------------------------------------------------------------------ +// Qt5SplashOutputDev +//------------------------------------------------------------------------ + +#if defined(HAVE_SPLASH) +Qt5SplashOutputDev::Qt5SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, bool ignorePaperColorA, SplashColorPtr paperColorA, + GBool bitmapTopDownA, SplashThinLineMode thinLineMode, + GBool overprintPreviewA) + : SplashOutputDev(colorModeA, bitmapRowPadA, reverseVideoA, paperColorA, bitmapTopDownA, thinLineMode, overprintPreviewA) + , ignorePaperColor(ignorePaperColorA) +{ +} + +void Qt5SplashOutputDev::dump() +{ + if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) { + partialUpdateCallback(getXBGRImage( false /* takeImageData */), payload); + } +} + +QImage Qt5SplashOutputDev::getXBGRImage(bool takeImageData) +{ + SplashBitmap *b = getBitmap(); + + const int bw = b->getWidth(); + const int bh = b->getHeight(); + const int brs = b->getRowSize(); + + // If we use DeviceN8, convert to XBGR8. + // If requested, also transfer Splash's internal alpha channel. + const SplashBitmap::ConversionMode mode = ignorePaperColor + ? SplashBitmap::conversionAlphaPremultiplied + : SplashBitmap::conversionOpaque; + + const QImage::Format format = ignorePaperColor + ? QImage::Format_ARGB32_Premultiplied + : QImage::Format_RGB32; + + if (b->convertToXBGR(mode)) { + SplashColorPtr data = takeImageData ? b->takeData() : b->getDataPtr(); + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + // Convert byte order from RGBX to XBGR. + for (int i = 0; i < bh; ++i) { + for (int j = 0; j < bw; ++j) { + SplashColorPtr pixel = &data[i * brs + j]; + + qSwap(pixel[0], pixel[3]); + qSwap(pixel[1], pixel[2]); + } + } + } + + if (takeImageData) { + // Construct a Qt image holding (and also owning) the raw bitmap data. + return QImage(data, bw, bh, brs, format, gfree, data); + } else { + return QImage(data, bw, bh, brs, format).copy(); + } + } + + return QImage(); +} +#endif diff --git a/qt5/src/ArthurOutputDev.h b/qt5/src/Qt5OutputDevices.h similarity index 79% rename from qt5/src/ArthurOutputDev.h rename to qt5/src/Qt5OutputDevices.h index 701a883a..595848ff 100644 --- a/qt5/src/ArthurOutputDev.h +++ b/qt5/src/Qt5OutputDevices.h @@ -1,72 +1,93 @@ //======================================================================== // -// ArthurOutputDev.h +// Qt5OutputDevices.h // // Copyright 2003 Glyph & Cog, LLC // //======================================================================== //======================================================================== // // Modified under the Poppler project - http://poppler.freedesktop.org // // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // // Copyright (C) 2005 Brad Hards // Copyright (C) 2005 Albert Astals Cid // Copyright (C) 2009, 2011 Carlos Garcia Campos // Copyright (C) 2010 Pino Toscano // Copyright (C) 2011 Andreas Hartmetz // Copyright (C) 2013 Thomas Freitag // Copyright (C) 2013 Mihai Niculescu // Copyright (C) 2017, 2018 Oliver Sander // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git // //======================================================================== -#ifndef ARTHUROUTPUTDEV_H -#define ARTHUROUTPUTDEV_H +#ifndef QT5OUTPUTDEVICES_H +#define QT5OUTPUTDEVICES_H #ifdef USE_GCC_PRAGMAS #pragma interface #endif #include #include #include +#if defined(HAVE_SPLASH) +#include +#endif + +#include "poppler-qt5.h" #include "goo/gtypes.h" #include "OutputDev.h" #include "GfxState.h" #include +#include class GfxState; class SplashFontEngine; class QRawFont; +//------------------------------------------------------------------------ +// OutputDevCallbackHelper - Extend OutputDevs with callback handling +//------------------------------------------------------------------------ + +class OutputDevCallbackHelper +{ +public: + void setCallbacks(Poppler::Page::RenderToImagePartialUpdateFunc callback, Poppler::Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, Poppler::Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA); + + Poppler::Page::RenderToImagePartialUpdateFunc partialUpdateCallback = nullptr; + Poppler::Page::ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback = nullptr; + Poppler::Page::ShouldAbortQueryFunc shouldAbortRenderCallback = nullptr; + QVariant payload; +}; + //------------------------------------------------------------------------ // ArthurOutputDev - Qt 5 QPainter renderer //------------------------------------------------------------------------ class ArthurOutputDev: public OutputDev { public: /** * Describes how fonts are distorted (aka hinted) to fit the pixel grid. * More hinting means sharper edges and less adherence to the true letter shapes. */ enum FontHinting { NoHinting = 0, ///< Font shapes are left unchanged SlightHinting, ///< Font shapes are distorted vertically only FullHinting ///< Font shapes are distorted horizontally and vertically }; // Constructor. ArthurOutputDev(QPainter *painter ); // Destructor. @@ -221,21 +242,58 @@ private: struct ArthurFontID { Ref ref; double fontSize; bool operator<(const ArthurFontID& other) const { return (ref.num < other.ref.num) || ((ref.num == other.ref.num) && (fontSize < other.fontSize)); } }; // Cache all fonts std::map > m_rawFontCache; // The table that maps character codes to glyph indexes int* m_codeToGID; std::stack m_codeToGIDStack; }; +//------------------------------------------------------------------------ +// QImageDumpingArthurOutputDev - ArthurOutputDev for QT5 frontend +//------------------------------------------------------------------------ + +class QImageDumpingArthurOutputDev : public ArthurOutputDev, public OutputDevCallbackHelper +{ +public: + QImageDumpingArthurOutputDev(QPainter *painter, QImage *i); + + void dump() override; + +private: + QImage *image; +}; + +//------------------------------------------------------------------------ +// Qt5SplashOutputDev - SplashOutputDev for QT5 frontend +//------------------------------------------------------------------------ + +#if defined(HAVE_SPLASH) +class Qt5SplashOutputDev : public SplashOutputDev, public OutputDevCallbackHelper +{ +public: + Qt5SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, bool ignorePaperColorA, SplashColorPtr paperColorA, + GBool bitmapTopDownA, SplashThinLineMode thinLineMode, + GBool overprintPreviewA); + + void dump() override; + + QImage getXBGRImage(bool takeImageData); + +private: + bool ignorePaperColor; +}; +#endif + #endif diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 381a608b..a53bc31f 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -35,178 +35,71 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include #include #if defined(HAVE_SPLASH) #include #include #endif #include "poppler-private.h" #include "poppler-page-transition-private.h" #include "poppler-page-private.h" #include "poppler-link-extractor-private.h" #include "poppler-link-private.h" #include "poppler-annotation-private.h" #include "poppler-form.h" #include "poppler-media.h" namespace Poppler { class TextExtractionAbortHelper { public: TextExtractionAbortHelper(Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA) { shouldAbortExtractionCallback = shouldAbortCallback; payload = payloadA; } Page::ShouldAbortQueryFunc shouldAbortExtractionCallback = nullptr; QVariant payload; }; -class OutputDevCallbackHelper -{ -public: - void setCallbacks(Page::RenderToImagePartialUpdateFunc callback, Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA) - { - partialUpdateCallback = callback; - shouldDoPartialUpdateCallback = shouldDoCallback; - shouldAbortRenderCallback = shouldAbortCallback; - payload = payloadA; - } - - Page::RenderToImagePartialUpdateFunc partialUpdateCallback = nullptr; - Page::ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback = nullptr; - Page::ShouldAbortQueryFunc shouldAbortRenderCallback = nullptr; - QVariant payload; -}; - -class Qt5SplashOutputDev : public SplashOutputDev, public OutputDevCallbackHelper -{ -public: - Qt5SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, - GBool reverseVideoA, bool ignorePaperColorA, SplashColorPtr paperColorA, - GBool bitmapTopDownA, SplashThinLineMode thinLineMode, - GBool overprintPreviewA) - : SplashOutputDev(colorModeA, bitmapRowPadA, reverseVideoA, paperColorA, bitmapTopDownA, thinLineMode, overprintPreviewA) - , ignorePaperColor(ignorePaperColorA) - { - } - - void dump() override - { - if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) { - partialUpdateCallback(getXBGRImage( false /* takeImageData */), payload); - } - } - - QImage getXBGRImage(bool takeImageData) - { - SplashBitmap *b = getBitmap(); - - const int bw = b->getWidth(); - const int bh = b->getHeight(); - const int brs = b->getRowSize(); - - // If we use DeviceN8, convert to XBGR8. - // If requested, also transfer Splash's internal alpha channel. - const SplashBitmap::ConversionMode mode = ignorePaperColor - ? SplashBitmap::conversionAlphaPremultiplied - : SplashBitmap::conversionOpaque; - - const QImage::Format format = ignorePaperColor - ? QImage::Format_ARGB32_Premultiplied - : QImage::Format_RGB32; - - if (b->convertToXBGR(mode)) { - SplashColorPtr data = takeImageData ? b->takeData() : b->getDataPtr(); - - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { - // Convert byte order from RGBX to XBGR. - for (int i = 0; i < bh; ++i) { - for (int j = 0; j < bw; ++j) { - SplashColorPtr pixel = &data[i * brs + j]; - - qSwap(pixel[0], pixel[3]); - qSwap(pixel[1], pixel[2]); - } - } - } - - if (takeImageData) { - // Construct a Qt image holding (and also owning) the raw bitmap data. - return QImage(data, bw, bh, brs, format, gfree, data); - } else { - return QImage(data, bw, bh, brs, format).copy(); - } - } - - return QImage(); - } - -private: - bool ignorePaperColor; -}; - - -class QImageDumpingArthurOutputDev : public ArthurOutputDev, public OutputDevCallbackHelper -{ -public: - QImageDumpingArthurOutputDev(QPainter *painter, QImage *i) - : ArthurOutputDev(painter) - , image(i) - { - } - - void dump() override - { - if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) { - partialUpdateCallback(*image, payload); - } - } - -private: - QImage *image; -}; - - - Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea) { return convertLinkActionToLink(a, parentDoc, linkArea); } Link* PageData::convertLinkActionToLink(::LinkAction * a, DocumentData *parentDoc, const QRectF &linkArea) { if ( !a ) return nullptr; Link * popplerLink = nullptr; switch ( a->getKind() ) { case actionGoTo: { LinkGoTo * g = (LinkGoTo *) a; const LinkDestinationData ldd( g->getDest(), g->getNamedDest(), parentDoc, false ); // create link: no ext file, namedDest, object pointer popplerLink = new LinkGoto( linkArea, QString::null, LinkDestination( ldd ) ); }