[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