[poppler] glib/poppler-input-stream.cc glib/poppler-input-stream.h poppler/Stream.cc poppler/Stream.h qt5/src qt5/tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Jan 12 23:50:20 UTC 2020


 glib/poppler-input-stream.cc                |   98 +------------------------
 glib/poppler-input-stream.h                 |   33 +-------
 poppler/Stream.cc                           |  107 ++++++++++++++++++++++++++++
 poppler/Stream.h                            |   58 +++++++++++++++
 qt5/src/CMakeLists.txt                      |    1 
 qt5/src/poppler-document.cc                 |   17 ++++
 qt5/src/poppler-private.h                   |   16 ++++
 qt5/src/poppler-qiodeviceinstream-private.h |   49 ++++++++++++
 qt5/src/poppler-qiodeviceinstream.cc        |   63 ++++++++++++++++
 qt5/src/poppler-qt5.h                       |   29 +++++++
 qt5/tests/check_actualtext.cpp              |   30 ++++++-
 11 files changed, 376 insertions(+), 125 deletions(-)

New commits:
commit a047dea62d28402e819d8ecacdaca95a18f2e3f1
Author: Alexander Volkov <a.volkov at rusbitech.ru>
Date:   Thu Sep 12 00:04:20 2019 +0300

    qt5: Allow to load document from QIODevice
    
    Extract BaseSeekInputStream class from PopplerInputStream class
    and inherit an introduced Poppler::QIODeviceInStream from it.
    This allows to implement Poppler::Document::load(QIODevice *, ...)
    overload.

diff --git a/glib/poppler-input-stream.cc b/glib/poppler-input-stream.cc
index 2365be87..2c75cc0c 100644
--- a/glib/poppler-input-stream.cc
+++ b/glib/poppler-input-stream.cc
@@ -22,17 +22,10 @@
 
 PopplerInputStream::PopplerInputStream(GInputStream *inputStreamA, GCancellable *cancellableA,
                                        Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
-  : BaseStream(std::move(dictA), lengthA)
+  : BaseSeekInputStream(startA, limitedA, lengthA, std::move(dictA))
 {
   inputStream = (GInputStream *)g_object_ref(inputStreamA);
   cancellable = cancellableA ? (GCancellable *)g_object_ref(cancellableA) : nullptr;
-  start = startA;
-  limited = limitedA;
-  length = lengthA;
-  bufPtr = bufEnd = buf;
-  bufPos = start;
-  savePos = 0;
-  saved = false;
 }
 
 PopplerInputStream::~PopplerInputStream()
@@ -53,96 +46,19 @@ Stream *PopplerInputStream::makeSubStream(Goffset startA, bool limitedA,
   return new PopplerInputStream(inputStream, cancellable, startA, limitedA, lengthA, std::move(dictA));
 }
 
-void PopplerInputStream::reset()
+Goffset PopplerInputStream::currentPos() const
 {
   GSeekable *seekable = G_SEEKABLE(inputStream);
-
-  savePos = (unsigned int)g_seekable_tell(seekable);
-  g_seekable_seek(seekable, start, G_SEEK_SET, cancellable, nullptr);
-  saved = true;
-  bufPtr = bufEnd = buf;
-  bufPos = start;
+  return g_seekable_tell(seekable);
 }
 
-void PopplerInputStream::close()
+void PopplerInputStream::setCurrentPos(Goffset offset)
 {
-  if (!saved)
-    return;
-  g_seekable_seek(G_SEEKABLE(inputStream), savePos, G_SEEK_SET, cancellable, nullptr);
-  saved = false;
-}
-
-void PopplerInputStream::setPos(Goffset pos, int dir)
-{
-  unsigned int size;
   GSeekable *seekable = G_SEEKABLE(inputStream);
-
-  if (dir >= 0) {
-    g_seekable_seek(seekable, pos, G_SEEK_SET, cancellable, nullptr);
-    bufPos = pos;
-  } else {
-    g_seekable_seek(seekable, 0, G_SEEK_END, cancellable, nullptr);
-    size = (unsigned int)g_seekable_tell(seekable);
-
-    if (pos > size)
-      pos = size;
-
-    g_seekable_seek(seekable, -(goffset)pos, G_SEEK_END, cancellable, nullptr);
-    bufPos = (unsigned int)g_seekable_tell(seekable);
-  }
-  bufPtr = bufEnd = buf;
-}
-
-void PopplerInputStream::moveStart(Goffset delta)
-{
-  start += delta;
-  bufPtr = bufEnd = buf;
-  bufPos = start;
+  g_seekable_seek(seekable, offset, G_SEEK_SET, cancellable, nullptr);
 }
 
-bool PopplerInputStream::fillBuf()
+Goffset PopplerInputStream::read(char *buffer, Goffset count)
 {
-  int n;
-
-  bufPos += bufEnd - buf;
-  bufPtr = bufEnd = buf;
-  if (limited && bufPos >= start + length) {
-    return false;
-  }
-
-  if (limited && bufPos + inputStreamBufSize > start + length) {
-    n = start + length - bufPos;
-  } else {
-    n = inputStreamBufSize - (bufPos % inputStreamBufSize);
-  }
-
-  n = g_input_stream_read(inputStream, buf, n, cancellable, nullptr);
-  bufEnd = buf + n;
-  if (bufPtr >= bufEnd) {
-    return false;
-  }
-
-  return true;
-}
-
-int PopplerInputStream::getChars(int nChars, unsigned char *buffer)
-{
-  int n, m;
-
-  n = 0;
-  while (n < nChars) {
-    if (bufPtr >= bufEnd) {
-      if (!fillBuf()) {
-        break;
-      }
-    }
-    m = (int)(bufEnd - bufPtr);
-    if (m > nChars - n) {
-      m = nChars - n;
-    }
-    memcpy(buffer + n, bufPtr, m);
-    bufPtr += m;
-    n += m;
-  }
-  return n;
+  return g_input_stream_read(inputStream, buffer, count, cancellable, nullptr);
 }
diff --git a/glib/poppler-input-stream.h b/glib/poppler-input-stream.h
index 799d752e..1c6011f8 100644
--- a/glib/poppler-input-stream.h
+++ b/glib/poppler-input-stream.h
@@ -26,9 +26,7 @@
 #include <Object.h>
 #include <Stream.h>
 
-#define inputStreamBufSize 1024
-
-class PopplerInputStream: public BaseStream {
+class PopplerInputStream: public BaseSeekInputStream {
 public:
 
   PopplerInputStream(GInputStream *inputStream, GCancellable *cancellableA,
@@ -37,38 +35,15 @@ public:
   BaseStream *copy() override;
   Stream *makeSubStream(Goffset start, bool limited,
                         Goffset lengthA, Object &&dictA) override;
-  StreamKind getKind() const override { return strWeird; }
-  void reset() override;
-  void close() override;
-  int getChar() override
-    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
-  int lookChar() override
-    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  Goffset getPos() override { return bufPos + (bufPtr - buf); }
-  void setPos(Goffset pos, int dir = 0) override;
-  Goffset getStart() override { return start; }
-  void moveStart(Goffset delta) override;
-
-  int getUnfilteredChar() override { return getChar(); }
-  void unfilteredReset() override { reset(); }
 
 private:
 
-  bool fillBuf();
-
-  bool hasGetChars() override { return true; }
-  int getChars(int nChars, unsigned char *buffer) override;
+  Goffset currentPos() const override;
+  void setCurrentPos(Goffset offset) override;
+  Goffset read(char *buffer, Goffset count) override;
 
   GInputStream *inputStream;
   GCancellable *cancellable;
-  Goffset start;
-  bool limited;
-  char buf[inputStreamBufSize];
-  char *bufPtr;
-  char *bufEnd;
-  Goffset bufPos;
-  int savePos;
-  bool saved;
 };
 
 #endif /* __GI_SCANNER__ */
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 76a542af..fa89fc5c 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -37,6 +37,7 @@
 // Copyright (C) 2019 Christian Persch <chpe at src.gnome.org>
 // Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent at gmail.com>
 // Copyright (C) 2019 Volker Krause <vkrause at kde.org>
+// Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
 //
 // 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
@@ -408,6 +409,112 @@ BaseStream::BaseStream(Object &&dictA, Goffset lengthA) {
 BaseStream::~BaseStream() {
 }
 
+//------------------------------------------------------------------------
+// BaseStream
+//------------------------------------------------------------------------
+
+BaseSeekInputStream::BaseSeekInputStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
+  : BaseStream(std::move(dictA), lengthA)
+  , start(startA)
+  , limited(limitedA)
+  , bufPtr(buf)
+  , bufEnd(buf)
+  , bufPos(start)
+  , savePos(0)
+  , saved(false)
+{
+}
+
+BaseSeekInputStream::~BaseSeekInputStream()
+{
+}
+
+void BaseSeekInputStream::reset()
+{
+  savePos = currentPos();
+  setCurrentPos(start);
+  saved = true;
+  bufPtr = bufEnd = buf;
+  bufPos = start;
+}
+
+void BaseSeekInputStream::close()
+{
+  if (!saved)
+    return;
+  setCurrentPos(savePos);
+  saved = false;
+}
+
+void BaseSeekInputStream::setPos(Goffset pos, int dir)
+{
+  if (dir >= 0) {
+    setCurrentPos(pos);
+    bufPos = pos;
+  } else {
+    if (pos > length)
+      pos = length;
+
+    bufPos = length - pos;
+    setCurrentPos(bufPos);
+  }
+  bufPtr = bufEnd = buf;
+}
+
+void BaseSeekInputStream::moveStart(Goffset delta)
+{
+  start += delta;
+  bufPtr = bufEnd = buf;
+  bufPos = start;
+}
+
+bool BaseSeekInputStream::fillBuf()
+{
+  Goffset n;
+
+  bufPos += bufEnd - buf;
+  bufPtr = bufEnd = buf;
+  if (limited && bufPos >= start + length) {
+    return false;
+  }
+
+  if (limited && bufPos + seekInputStreamBufSize > start + length) {
+    n = start + length - bufPos;
+  } else {
+    n = seekInputStreamBufSize - (bufPos % seekInputStreamBufSize);
+  }
+
+  n = read(buf, n);
+  bufEnd = buf + n;
+  if (bufPtr >= bufEnd) {
+    return false;
+  }
+
+  return true;
+}
+
+int BaseSeekInputStream::getChars(int nChars, unsigned char *buffer)
+{
+  int n, m;
+
+  n = 0;
+  while (n < nChars) {
+    if (bufPtr >= bufEnd) {
+      if (!fillBuf()) {
+        break;
+      }
+    }
+    m = (int)(bufEnd - bufPtr);
+    if (m > nChars - n) {
+      m = nChars - n;
+    }
+    memcpy(buffer + n, bufPtr, m);
+    bufPtr += m;
+    n += m;
+  }
+  return n;
+}
+
 //------------------------------------------------------------------------
 // FilterStream
 //------------------------------------------------------------------------
diff --git a/poppler/Stream.h b/poppler/Stream.h
index 46f2b375..b675bcc6 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -27,6 +27,7 @@
 // Copyright (C) 2013, 2018 Adam Reichold <adamreichold at myopera.com>
 // Copyright (C) 2013 Pino Toscano <pino at kde.org>
 // Copyright (C) 2019 Volker Krause <vkrause at kde.org>
+// Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
 //
 // 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
@@ -326,6 +327,63 @@ protected:
   Object dict;
 };
 
+//------------------------------------------------------------------------
+// BaseInputStream
+//------------------------------------------------------------------------
+
+class BaseSeekInputStream: public BaseStream {
+public:
+
+  // This enum is used to tell the seek() method how it must reposition
+  // the stream offset.
+  enum SeekType {
+    SeekSet, // the offset is set to offset bytes
+    SeekCur, // the offset is set to its current location plus offset bytes
+    SeekEnd  // the offset is set to the size of the stream plus offset bytes
+  };
+
+  BaseSeekInputStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA);
+  ~BaseSeekInputStream() override;
+  StreamKind getKind() const override { return strWeird; }
+  void reset() override;
+  void close() override;
+  int getChar() override
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+  int lookChar() override
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+  Goffset getPos() override { return bufPos + (bufPtr - buf); }
+  void setPos(Goffset pos, int dir = 0) override;
+  Goffset getStart() override { return start; }
+  void moveStart(Goffset delta) override;
+
+  int getUnfilteredChar() override { return getChar(); }
+  void unfilteredReset() override { reset(); }
+
+protected:
+
+  Goffset start;
+  bool limited;
+
+private:
+
+  bool fillBuf();
+
+  bool hasGetChars() override { return true; }
+  int getChars(int nChars, unsigned char *buffer) override;
+
+  virtual Goffset currentPos() const = 0;
+  virtual void setCurrentPos(Goffset offset) = 0;
+  virtual Goffset read(char *buf, Goffset size) = 0;
+
+  static constexpr int seekInputStreamBufSize = 1024;
+  char buf[seekInputStreamBufSize];
+  char *bufPtr;
+  char *bufEnd;
+  Goffset bufPos;
+  Goffset savePos;
+  bool saved;
+};
+
 //------------------------------------------------------------------------
 // FilterStream
 //
diff --git a/qt5/src/CMakeLists.txt b/qt5/src/CMakeLists.txt
index 643f56a1..b22bd40d 100644
--- a/qt5/src/CMakeLists.txt
+++ b/qt5/src/CMakeLists.txt
@@ -29,6 +29,7 @@ set(poppler_qt5_SRCS
   poppler-pdf-converter.cc
   poppler-private.cc
   poppler-ps-converter.cc
+  poppler-qiodeviceinstream.cc
   poppler-qiodeviceoutstream.cc
   poppler-sound.cc
   poppler-textbox.cc
diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc
index fd525e62..bff01205 100644
--- a/qt5/src/poppler-document.cc
+++ b/qt5/src/poppler-document.cc
@@ -14,6 +14,7 @@
  * Copyright (C) 2017 Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
  * Copyright (C) 2018 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) 2019 Oliver Sander <oliver.sander at tu-dresden.de>
+ * Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
  *
  * 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
@@ -66,6 +67,15 @@ namespace Poppler {
 	return DocumentData::checkDocument(doc);
     }
 
+	Document *Document::load(QIODevice *device, const QByteArray &ownerPassword,
+			   const QByteArray &userPassword)
+    {
+	DocumentData *doc = new DocumentData(device,
+					     new GooString(ownerPassword.data()),
+					     new GooString(userPassword.data()));
+	return DocumentData::checkDocument(doc);
+    }
+
     Document *Document::loadFromData(const QByteArray &fileContents,
 			      const QByteArray &ownerPassword,
 			      const QByteArray &userPassword)
@@ -136,7 +146,12 @@ namespace Poppler {
 					new GooString(ownerPassword.data()),
 					new GooString(userPassword.data()));
 	    }
-	    else
+	    else if (m_doc->m_device)
+	    {
+		doc2 = new DocumentData(m_doc->m_device,
+					new GooString(ownerPassword.data()),
+					new GooString(userPassword.data()));
+	    }
 	    {
 		doc2 = new DocumentData(m_doc->m_filePath,
 					new GooString(ownerPassword.data()),
diff --git a/qt5/src/poppler-private.h b/qt5/src/poppler-private.h
index 0b09d30e..9131dba6 100644
--- a/qt5/src/poppler-private.h
+++ b/qt5/src/poppler-private.h
@@ -16,6 +16,7 @@
  * Copyright (C) 2019 Oliver Sander <oliver.sander at tu-dresden.de>
  * Copyright (C) 2019 João Netto <joaonetto901 at gmail.com>
  * Copyright (C) 2019 Jan Grulich <jgrulich at redhat.com>
+ * Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -57,6 +58,7 @@
 
 #include "poppler-qt5.h"
 #include "poppler-embeddedfile-private.h"
+#include "poppler-qiodeviceinstream-private.h"
 
 class LinkDest;
 class FormWidget;
@@ -99,6 +101,7 @@ namespace Poppler {
 	GlobalParamsIniter(qt5ErrorFunction)
 	    {
 		init();
+		m_device = nullptr;
 		m_filePath = filePath;	
 
 #ifdef _WIN32
@@ -112,9 +115,21 @@ namespace Poppler {
 		delete userPassword;
 	    }
 	
+	DocumentData(QIODevice *device, GooString *ownerPassword, GooString *userPassword) :
+	GlobalParamsIniter(qt5ErrorFunction)
+	    {
+		m_device = device;
+		QIODeviceInStream *str = new QIODeviceInStream(device, 0, false, device->size(), Object(objNull));
+		init();
+		doc = new PDFDoc(str, ownerPassword, userPassword);
+		delete ownerPassword;
+		delete userPassword;
+	    }
+
 	DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword) :
 	GlobalParamsIniter(qt5ErrorFunction)
 	    {
+		m_device = nullptr;
 		fileContents = data;
 		MemStream *str = new MemStream((char*)fileContents.data(), 0, fileContents.length(), Object(objNull));
 		init();
@@ -153,6 +168,7 @@ namespace Poppler {
 
 	PDFDoc *doc;
 	QString m_filePath;
+	QIODevice *m_device;
 	QByteArray fileContents;
 	bool locked;
 	Document::RenderBackend m_backend;
diff --git a/qt5/src/poppler-qiodeviceinstream-private.h b/qt5/src/poppler-qiodeviceinstream-private.h
new file mode 100644
index 00000000..13aa5128
--- /dev/null
+++ b/qt5/src/poppler-qiodeviceinstream-private.h
@@ -0,0 +1,49 @@
+/* poppler-qiodeviceinstream-private.h: Qt5 interface to poppler
+ * Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
+ *
+ * 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
+ * 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.
+ */
+
+#ifndef POPPLER_QIODEVICEINSTREAM_PRIVATE_H
+#define POPPLER_QIODEVICEINSTREAM_PRIVATE_H
+
+#include "Object.h"
+#include "Stream.h"
+
+class QIODevice;
+
+namespace Poppler {
+
+class QIODeviceInStream : public BaseSeekInputStream
+{
+  public:
+    QIODeviceInStream(QIODevice* device, Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA);
+    ~QIODeviceInStream() override;
+
+    BaseStream *copy() override;
+    Stream *makeSubStream(Goffset startA, bool limitedA,
+                          Goffset lengthA, Object &&dictA) override;
+
+  private:
+    Goffset currentPos() const override;
+    void setCurrentPos(Goffset offset) override;
+    Goffset read(char *buffer, Goffset count) override;
+
+    QIODevice *m_device;
+};
+
+}
+
+#endif
diff --git a/qt5/src/poppler-qiodeviceinstream.cc b/qt5/src/poppler-qiodeviceinstream.cc
new file mode 100644
index 00000000..d1cd433c
--- /dev/null
+++ b/qt5/src/poppler-qiodeviceinstream.cc
@@ -0,0 +1,63 @@
+/* poppler-qiodeviceinstream.cc: Qt5 interface to poppler
+ * Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
+ *
+ * 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
+ * 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-qiodeviceinstream-private.h"
+
+#include <QtCore/QIODevice>
+
+#include <cstdio>
+
+namespace Poppler {
+
+QIODeviceInStream::QIODeviceInStream(QIODevice *device, Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
+  : BaseSeekInputStream(startA, limitedA, lengthA, std::move(dictA))
+  , m_device(device)
+{
+}
+
+QIODeviceInStream::~QIODeviceInStream()
+{
+  close();
+}
+
+BaseStream *QIODeviceInStream::copy()
+{
+  return new QIODeviceInStream(m_device, start, limited, length, dict.copy());
+}
+
+Stream *QIODeviceInStream::makeSubStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
+{
+  return new QIODeviceInStream(m_device, startA, limitedA, lengthA, std::move(dictA));
+}
+
+Goffset QIODeviceInStream::currentPos() const
+{
+  return m_device->pos();
+}
+
+void QIODeviceInStream::setCurrentPos(Goffset offset)
+{
+  m_device->seek(offset);
+}
+
+Goffset QIODeviceInStream::read(char *buffer, Goffset count)
+{
+  return m_device->read(buffer, count);
+}
+
+}
diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h
index c501f67f..d32ffa3b 100644
--- a/qt5/src/poppler-qt5.h
+++ b/qt5/src/poppler-qt5.h
@@ -20,6 +20,7 @@
  * 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
  * Copyright (C) 2018 Nelson Benítez León <nbenitezl at gmail.com>
  * Copyright (C) 2019 Jan Grulich <jgrulich at redhat.com>
+ * Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
  *
  * 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
@@ -1241,6 +1242,34 @@ delete it;
 			      const QByteArray &ownerPassword=QByteArray(),
 			      const QByteArray &userPassword=QByteArray());
 	
+	/**
+	   Load the document from a device
+
+	   \param device the device of the data to load
+	   \param ownerPassword the Latin1-encoded owner password to use in
+	   loading the file
+	   \param userPassword the Latin1-encoded user ("open") password
+	   to use in loading the file
+
+	   \return the loaded document, or NULL on error
+
+	   \note The caller owns the pointer to Document, and this should
+	   be deleted when no longer required.
+
+	   \note The ownership of the device stays with the caller.
+
+	   \note if the file is on disk it is recommended to use the other load overload
+	   since it is less resource intensive
+
+	   \warning The returning document may be locked if a password is required
+	   to open the file, and one is not provided (as the userPassword).
+
+	   \since 0.85
+	*/
+	static Document *load(QIODevice *device,
+			      const QByteArray &ownerPassword=QByteArray(),
+			      const QByteArray &userPassword=QByteArray());
+
 	/**
 	   Load the document from memory
 
diff --git a/qt5/tests/check_actualtext.cpp b/qt5/tests/check_actualtext.cpp
index 29865665..09bf3156 100644
--- a/qt5/tests/check_actualtext.cpp
+++ b/qt5/tests/check_actualtext.cpp
@@ -11,20 +11,42 @@ public:
     TestActualText(QObject *parent = nullptr) : QObject(parent) { }
 private slots:
     void checkActualText1();
+    void checkActualText2();
+private:
+    void checkActualText(Poppler::Document *doc);
 };
 
+void TestActualText::checkActualText(Poppler::Document *doc)
+{
+    Poppler::Page *page = doc->page(0);
+    QVERIFY( page );
+
+    QCOMPARE( page->text(QRectF()), QLatin1String("The slow brown fox jumps over the black dog.") );
+
+    delete page;
+}
+
 void TestActualText::checkActualText1()
 {
     Poppler::Document *doc;
     doc = Poppler::Document::load(TESTDATADIR "/unittestcases/WithActualText.pdf");
     QVERIFY( doc );
 
-    Poppler::Page *page = doc->page(0);
-    QVERIFY( page );
+    checkActualText(doc);
 
-    QCOMPARE( page->text(QRectF()), QLatin1String("The slow brown fox jumps over the black dog.") );
+    delete doc;
+}
 
-    delete page;
+void TestActualText::checkActualText2()
+{
+    QFile file(TESTDATADIR "/unittestcases/WithActualText.pdf");
+    QVERIFY(file.open(QIODevice::ReadOnly));
+
+    Poppler::Document *doc;
+    doc = Poppler::Document::load(&file);
+    QVERIFY( doc );
+
+    checkActualText(doc);
 
     delete doc;
 }


More information about the poppler mailing list