diff --git qt5/src/poppler-page.cc qt5/src/poppler-page.cc index b48ee959..4b30d9da 100644 --- qt5/src/poppler-page.cc +++ qt5/src/poppler-page.cc @@ -67,147 +67,40 @@ #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 ) ); } diff --git qt5/src/poppler-private.cc qt5/src/poppler-private.cc index 78751f8e..b3628b41 100644 --- qt5/src/poppler-private.cc +++ qt5/src/poppler-private.cc @@ -14,43 +14,50 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "poppler-private.h" #include #include #include +#include +#include + #include #include #include +#if defined(HAVE_SPLASH) +#include +#include +#endif #include namespace Poppler { namespace Debug { static void qDebugDebugFunction(const QString &message, const QVariant & /*closure*/) { qDebug() << message; } PopplerDebugFunc debugFunction = qDebugDebugFunction; QVariant debugClosure; } static UnicodeMap *utf8Map = nullptr; void setDebugErrorFunction(PopplerDebugFunc function, const QVariant &closure) { @@ -275,21 +282,103 @@ namespace Debug { if ( name.isEmpty() ) continue; QDomElement item = docSyn->createElement( name ); parent->appendChild( item ); // 2. find the page the link refers to const ::LinkAction * a = outlineItem->getAction(); linkActionToTocItem( a, this, &item ); item.setAttribute( QStringLiteral("Open"), QVariant( (bool)outlineItem->isOpen() ).toString() ); // 3. recursively descend over children outlineItem->open(); const GooList * children = outlineItem->getKids(); if ( children ) addTocChildren( docSyn, &item, children ); } } + void OutputDevCallbackHelper::setCallbacks(Page::RenderToImagePartialUpdateFunc callback, Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA) + { + partialUpdateCallback = callback; + shouldDoPartialUpdateCallback = shouldDoCallback; + shouldAbortRenderCallback = shouldAbortCallback; + payload = payloadA; + } + + QImageDumpingArthurOutputDev::QImageDumpingArthurOutputDev(QPainter *painter, QImage *i) + : ArthurOutputDev(painter) + , image(i) + { + } + + void QImageDumpingArthurOutputDev::dump() + { + if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) { + partialUpdateCallback(*image, payload); + } + } + + #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 qt5/src/poppler-private.h qt5/src/poppler-private.h index 52715179..58031be1 100644 --- qt5/src/poppler-private.h +++ qt5/src/poppler-private.h @@ -34,40 +34,41 @@ #ifndef _POPPLER_PRIVATE_H_ #define _POPPLER_PRIVATE_H_ #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_SPLASH) #include #endif #include "poppler-qt5.h" #include "poppler-embeddedfile-private.h" +#include "ArthurOutputDev.h" class LinkDest; class FormWidget; namespace Poppler { /* borrowed from kpdf */ QString unicodeToQString(const Unicode* u, int len); QString UnicodeParsedString(const GooString *s1); GooString *QStringToUnicodeGooString(const QString &s); GooString *QStringToGooString(const QString &s); GooString *QDateTimeToUnicodeGooString(const QDateTime &dt); void qt5ErrorFunction(int pos, char *msg, va_list args); class LinkDestinationData @@ -214,23 +215,62 @@ namespace Poppler { QRectF bBox; TextBox *nextWord; QVector charBBoxes; // the boundingRect of each character bool hasSpaceAfter; }; class FormFieldData { public: FormFieldData(DocumentData *_doc, ::Page *p, ::FormWidget *w) : doc(_doc), page(p), fm(w) { } DocumentData *doc; ::Page *page; ::FormWidget *fm; QRectF box; }; + class OutputDevCallbackHelper + { + public: + void setCallbacks(Page::RenderToImagePartialUpdateFunc callback, Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA); + + Page::RenderToImagePartialUpdateFunc partialUpdateCallback = nullptr; + Page::ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback = nullptr; + Page::ShouldAbortQueryFunc shouldAbortRenderCallback = nullptr; + QVariant payload; + }; + + class QImageDumpingArthurOutputDev : public ArthurOutputDev, public OutputDevCallbackHelper + { + public: + QImageDumpingArthurOutputDev(QPainter *painter, QImage *i); + + void dump() override; + + private: + QImage *image; + }; + + #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