[poppler] qt5/src
Albert Astals Cid
aacid at kemper.freedesktop.org
Thu Feb 1 21:47:08 UTC 2018
qt5/src/poppler-page.cc | 148 ++++++++++++++++++++++++++++--------------------
qt5/src/poppler-qt5.h | 98 +++++++++++++++++++++++++++++++
2 files changed, 185 insertions(+), 61 deletions(-)
New commits:
commit b1016f574ac63fa269ca5125827895220e1df883
Author: Albert Astals Cid <albert.astals.cid at kdab.com>
Date: Thu Feb 1 22:46:33 2018 +0100
Qt5: Add cancellation support to renderToImage and textList
diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc
index 174d5857..f4c88de3 100644
--- a/qt5/src/poppler-page.cc
+++ b/qt5/src/poppler-page.cc
@@ -19,7 +19,7 @@
* Copyright (C) 2016, Hanno Meyer-Thurow <h.mth at web.de>
* Copyright (C) 2017, Oliver Sander <oliver.sander at tu-dresden.de>
* Copyright (C) 2017 Adrian Johnson <ajohnson at redneon.com>
- * Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by the LiMux project of the city of Munich
+ * Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by the LiMux project of the city of Munich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -70,27 +70,48 @@
namespace Poppler {
-class Qt5SplashOutputDev : public SplashOutputDev
+class TextExtractionAbortHelper
{
public:
- Qt5SplashOutputDev(SplashColorMode colorMode, int bitmapRowPad,
- GBool reverseVideo, bool ignorePaperColorA, SplashColorPtr paperColor,
- GBool bitmapTopDown, SplashThinLineMode thinLineMode,
- GBool overprintPreview)
- : SplashOutputDev(colorMode, bitmapRowPad, reverseVideo, paperColor, bitmapTopDown, thinLineMode, overprintPreview)
- , partialUpdateCallback(nullptr)
- , shouldDoPartialUpdateCallback(nullptr)
- , ignorePaperColor(ignorePaperColorA)
+ TextExtractionAbortHelper(Page::ShouldAbortQueryFunc shouldAbortCallback, const QVariant &payloadA)
{
+ shouldAbortExtractionCallback = shouldAbortCallback;
+ payload = payloadA;
}
- void setPartialUpdateCallbackData(Page::RenderToImagePartialUpdateFunc callback, Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, const QVariant &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 colorMode, int bitmapRowPad,
+ GBool reverseVideo, bool ignorePaperColorA, SplashColorPtr paperColor,
+ GBool bitmapTopDown, SplashThinLineMode thinLineMode,
+ GBool overprintPreview)
+ : SplashOutputDev(colorMode, bitmapRowPad, reverseVideo, paperColor, bitmapTopDown, thinLineMode, overprintPreview)
+ , ignorePaperColor(ignorePaperColorA)
+ {
+ }
+
void dump() override
{
if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) {
@@ -143,31 +164,19 @@ public:
}
private:
- Page::RenderToImagePartialUpdateFunc partialUpdateCallback;
- Page::ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback;
- QVariant payload;
bool ignorePaperColor;
};
-class QImageDumpingArthurOutputDev : public ArthurOutputDev
+class QImageDumpingArthurOutputDev : public ArthurOutputDev, public OutputDevCallbackHelper
{
public:
QImageDumpingArthurOutputDev(QPainter *painter, QImage *i)
: ArthurOutputDev(painter)
- , partialUpdateCallback(nullptr)
- , shouldDoPartialUpdateCallback(nullptr)
, image(i)
{
}
- void setPartialUpdateCallbackData(Page::RenderToImagePartialUpdateFunc callback, Page::ShouldRenderToImagePartialQueryFunc shouldDoCallback, const QVariant &payloadA)
- {
- partialUpdateCallback = callback;
- shouldDoPartialUpdateCallback = shouldDoCallback;
- payload = payloadA;
- }
-
void dump() override
{
if (partialUpdateCallback && shouldDoPartialUpdateCallback && shouldDoPartialUpdateCallback(payload)) {
@@ -176,9 +185,6 @@ public:
}
private:
- Page::RenderToImagePartialUpdateFunc partialUpdateCallback;
- Page::ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback;
- QVariant payload;
QImage *image;
};
@@ -412,7 +418,34 @@ Page::~Page()
delete m_page;
}
-static bool renderToArthur(ArthurOutputDev *arthur_output, QPainter *painter, PageData *page, double xres, double yres, int x, int y, int w, int h, Page::Rotation rotate, Page::PainterFlags flags)
+// Callback that filters out everything but form fields
+static auto annotDisplayDecideCbk = [](Annot *annot, void *user_data)
+{
+ // Hide everything but forms
+ return (annot->getType() == Annot::typeWidget);
+};
+
+// A nullptr, but with the type of a function pointer
+// Needed to make the ternary operator happy.
+static GBool (*nullAnnotCallBack)(Annot *annot, void *user_data) = nullptr;
+
+static auto shouldAbortRenderInternalCallback = [](void *user_data)
+{
+ OutputDevCallbackHelper *helper = reinterpret_cast<OutputDevCallbackHelper*>(user_data);
+ return helper->shouldAbortRenderCallback(helper->payload);
+};
+
+static auto shouldAbortExtractionInternalCallback = [](void *user_data)
+{
+ TextExtractionAbortHelper *helper = reinterpret_cast<TextExtractionAbortHelper*>(user_data);
+ return helper->shouldAbortExtractionCallback(helper->payload);
+};
+
+// A nullptr, but with the type of a function pointer
+// Needed to make the ternary operator happy.
+static GBool (*nullAbortCallBack)(void *user_data) = nullptr;
+
+static bool renderToArthur(QImageDumpingArthurOutputDev *arthur_output, QPainter *painter, PageData *page, double xres, double yres, int x, int y, int w, int h, Page::Rotation rotate, Page::PainterFlags flags)
{
const bool savePainter = !(flags & Page:: DontSaveAndRestore);
if (savePainter)
@@ -427,17 +460,7 @@ static bool renderToArthur(ArthurOutputDev *arthur_output, QPainter *painter, Pa
const GBool hideAnnotations = page->parentDoc->m_hints & Document::HideAnnotations;
- // Callback that filters out everything but form fields
- auto annotDisplayDecideCbk = [](Annot *annot, void *user_data)
- {
- // Hide everything but forms
- return (annot->getType() == Annot::typeWidget);
- };
-
- // A nullptr, but with the type of a function pointer
- // Needed to make the ternary operator below happy.
- GBool (*nullCallBack)(Annot *annot, void *user_data) = nullptr;
-
+ OutputDevCallbackHelper *abortHelper = arthur_output;
page->parentDoc->doc->displayPageSlice(arthur_output,
page->index + 1,
xres,
@@ -450,9 +473,9 @@ static bool renderToArthur(ArthurOutputDev *arthur_output, QPainter *painter, Pa
y,
w,
h,
- nullptr,
- nullptr,
- (hideAnnotations) ? annotDisplayDecideCbk : nullCallBack);
+ abortHelper->shouldAbortRenderCallback ? shouldAbortRenderInternalCallback : nullAbortCallBack,
+ abortHelper,
+ (hideAnnotations) ? annotDisplayDecideCbk : nullAnnotCallBack);
if (savePainter)
painter->restore();
return true;
@@ -465,6 +488,11 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, Rotation rotate, RenderToImagePartialUpdateFunc partialUpdateCallback, ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback, const QVariant &payload) const
{
+ return renderToImage(xres, yres, x, y, w, h, rotate, partialUpdateCallback, shouldDoPartialUpdateCallback, nullptr, payload);
+}
+
+QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, Rotation rotate, RenderToImagePartialUpdateFunc partialUpdateCallback, ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback, ShouldAbortQueryFunc shouldAbortRenderCallback, const QVariant &payload) const
+{
int rotation = (int)rotate * 90;
QImage img;
switch(m_page->parentDoc->m_backend)
@@ -526,7 +554,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
thinLineMode,
overprintPreview);
- splash_output.setPartialUpdateCallbackData(partialUpdateCallback, shouldDoPartialUpdateCallback, payload);
+ splash_output.setCallbacks(partialUpdateCallback, shouldDoPartialUpdateCallback, shouldAbortRenderCallback, payload);
splash_output.setFontAntialias(m_page->parentDoc->m_hints & Document::TextAntialiasing ? gTrue : gFalse);
splash_output.setVectorAntialias(m_page->parentDoc->m_hints & Document::Antialiasing ? gTrue : gFalse);
@@ -537,21 +565,11 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
const GBool hideAnnotations = m_page->parentDoc->m_hints & Document::HideAnnotations;
- // Callback that filters out everything but form fields
- auto annotDisplayDecideCbk = [](Annot *annot, void *user_data)
- {
- // Hide everything but forms
- return (annot->getType() == Annot::typeWidget);
- };
-
- // A nullptr, but with the type of a function pointer
- // Needed to make the ternary operator below happy.
- GBool (*nullCallBack)(Annot *annot, void *user_data) = nullptr;
-
+ OutputDevCallbackHelper *abortHelper = &splash_output;
m_page->parentDoc->doc->displayPageSlice(&splash_output, m_page->index + 1, xres, yres,
rotation, false, true, false, x, y, w, h,
- nullptr, nullptr,
- (hideAnnotations) ? annotDisplayDecideCbk : nullCallBack,
+ shouldAbortRenderCallback ? shouldAbortRenderInternalCallback : nullAbortCallBack, abortHelper,
+ (hideAnnotations) ? annotDisplayDecideCbk : nullAnnotCallBack,
nullptr, gTrue);
img = splash_output.getXBGRImage( true /* takeImageData */);
@@ -572,7 +590,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
QPainter painter(&tmpimg);
QImageDumpingArthurOutputDev arthur_output(&painter, &tmpimg);
- arthur_output.setPartialUpdateCallbackData(partialUpdateCallback, shouldDoPartialUpdateCallback, payload);
+ arthur_output.setCallbacks(partialUpdateCallback, shouldDoPartialUpdateCallback, shouldAbortRenderCallback, payload);
renderToArthur(&arthur_output, &painter, m_page, xres, yres, x, y, w, h, rotate, DontSaveAndRestore);
painter.end();
img = tmpimg;
@@ -580,6 +598,9 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
}
}
+ if (shouldAbortRenderCallback && shouldAbortRenderCallback(payload))
+ return QImage();
+
return img;
}
@@ -594,7 +615,7 @@ bool Page::renderToPainter(QPainter* painter, double xres, double yres, int x, i
return false;
case Poppler::Document::ArthurBackend:
{
- ArthurOutputDev arthur_output(painter);
+ QImageDumpingArthurOutputDev arthur_output(painter, nullptr);
return renderToArthur(&arthur_output, painter, m_page, xres, yres, x, y, w, h, rotate, flags);
}
}
@@ -713,6 +734,11 @@ QList<QRectF> Page::search(const QString &text, SearchFlags flags, Rotation rota
QList<TextBox*> Page::textList(Rotation rotate) const
{
+ return textList(rotate, nullptr, QVariant());
+}
+
+QList<TextBox*> Page::textList(Rotation rotate, ShouldAbortQueryFunc shouldAbortExtractionCallback, const QVariant &closure) const
+{
TextOutputDev *output_dev;
QList<TextBox*> output_list;
@@ -721,13 +747,15 @@ QList<TextBox*> Page::textList(Rotation rotate) const
int rotation = (int)rotate * 90;
+ TextExtractionAbortHelper abortHelper(shouldAbortExtractionCallback, closure);
m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72,
rotation, false, false, false, -1, -1, -1, -1,
- nullptr, nullptr, nullptr, nullptr, gTrue);
+ shouldAbortExtractionCallback ? shouldAbortExtractionInternalCallback : nullAbortCallBack, &abortHelper,
+ nullptr, nullptr, gTrue);
TextWordList *word_list = output_dev->makeWordList();
- if (!word_list) {
+ if (!word_list || (shouldAbortExtractionCallback && shouldAbortExtractionCallback(closure))) {
delete output_dev;
return output_list;
}
diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h
index 2c30e5ec..3adbf02f 100644
--- a/qt5/src/poppler-qt5.h
+++ b/qt5/src/poppler-qt5.h
@@ -17,7 +17,7 @@
* Copyright (C) 2013 Anthony Granger <grangeranthony at gmail.com>
* Copyright (C) 2016 Jakub Alba <jakubalba at gmail.com>
* Copyright (C) 2017 Oliver Sander <oliver.sander at tu-dresden.de>
- * Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by the LiMux project of the city of Munich
+ * Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by the LiMux project of the city of Munich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -571,6 +571,76 @@ delete it;
const QVariant &closure
) const;
+ /**
+ Abort query function callback.
+
+ This function type is used for query if the current rendering/text extraction should be cancelled.
+
+ \since 0.63
+ */
+ typedef bool (*ShouldAbortQueryFunc)(const QVariant & /*closure*/);
+
+ /**
+ Render the page to a QImage using the current
+ \link Document::renderBackend() Document renderer\endlink.
+
+ If \p x = \p y = \p w = \p h = -1, the method will automatically
+ compute the size of the image from the horizontal and vertical
+ resolutions specified in \p xres and \p yres. Otherwise, the
+ method renders only a part of the page, specified by the
+ parameters (\p x, \p y, \p w, \p h) in pixel coordinates. The returned
+ QImage then has size (\p w, \p h), independent of the page
+ size.
+
+ \param x specifies the left x-coordinate of the box, in
+ pixels.
+
+ \param y specifies the top y-coordinate of the box, in
+ pixels.
+
+ \param w specifies the width of the box, in pixels.
+
+ \param h specifies the height of the box, in pixels.
+
+ \param xres horizontal resolution of the graphics device,
+ in dots per inch
+
+ \param yres vertical resolution of the graphics device, in
+ dots per inch
+
+ \param rotate how to rotate the page
+
+ \param partialUpdateCallback callback that will be called to
+ report a partial rendering update
+
+ \param shouldDoPartialUpdateCallback callback that will be called
+ to ask if a partial rendering update is wanted. This exists
+ because doing a partial rendering update needs to copy the image
+ buffer so if it is not wanted it is better skipped early.
+
+ \param shouldAbortRenderCallback callback that will be called
+ to ask if the rendering should be cancelled.
+
+ \param closure opaque structure that will be passed
+ back to partialUpdateCallback, shouldDoPartialUpdateCallback
+ and shouldAbortRenderCallback.
+
+ \warning The parameter (\p x, \p y, \p w, \p h) are not
+ well-tested. Unusual or meaningless parameters may lead to
+ rather unexpected results.
+
+ \returns a QImage of the page, or a null image on failure.
+
+ \since 0.63
+ */
+ QImage renderToImage(double xres, double yres,
+ int x, int y, int w, int h, Rotation rotate,
+ RenderToImagePartialUpdateFunc partialUpdateCallback,
+ ShouldRenderToImagePartialQueryFunc shouldDoPartialUpdateCallback,
+ ShouldAbortQueryFunc shouldAbortRenderCallback,
+ const QVariant &closure
+ ) const;
+
/**
Render the page to the specified QPainter using the current
\link Document::renderBackend() Document renderer\endlink.
@@ -745,6 +815,32 @@ delete it;
QList<TextBox*> textList(Rotation rotate = Rotate0) const;
/**
+ Returns a list of text of the page
+
+ This method returns a QList of TextBoxes that contain all
+ the text of the page, with roughly one text word of text
+ per TextBox item.
+
+ For text written in western languages (left-to-right and
+ up-to-down), the QList contains the text in the proper
+ order.
+
+ \param shouldAbortExtractionCallback callback that will be called
+ to ask if the text extraction should be cancelled.
+
+ \param closure opaque structure that will be passed
+ back to shouldAbortExtractionCallback.
+
+ \note The caller owns the text boxes and they should
+ be deleted when no longer required.
+
+ \warning This method is not tested with Asian scripts
+
+ // \since 0.63
+ */
+ QList<TextBox*> textList(Rotation rotate, ShouldAbortQueryFunc shouldAbortExtractionCallback, const QVariant &closure) const;
+
+ /**
\return The dimensions (cropbox) of the page, in points (i.e. 1/72th of an inch)
*/
QSizeF pageSizeF() const;
More information about the poppler
mailing list