summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2014-12-15 16:13:52 +0100
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2014-12-15 16:13:52 +0100
commit233896bae4ecf86583d2ded590581b86c1f75b4d (patch)
treec2cb88ff317202f42297b8ddbf3e5d5ff9817a16
parent92f9acff9db4ae299024d4640a4840d8f7c32b2d (diff)
Allow loading documents synchronously from a QIODevice
-rw-r--r--src/pdf/qpdfdocument.cpp85
-rw-r--r--src/pdf/qpdfdocument.h1
-rw-r--r--src/pdf/qpdfdocument_p.h13
-rw-r--r--tests/auto/qpdfdocument/tst_qpdfdocument.cpp49
4 files changed, 95 insertions, 53 deletions
diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp
index 738f896..394182e 100644
--- a/src/pdf/qpdfdocument.cpp
+++ b/src/pdf/qpdfdocument.cpp
@@ -23,6 +23,10 @@ QPdfDocumentPrivate::QPdfDocumentPrivate()
FPDF_InitLibrary();
++libraryRefCount;
}
+
+ // FPDF_FILEACCESS setup
+ m_Param = this;
+ m_GetBlock = fpdf_GetBlock;
}
QPdfDocumentPrivate::~QPdfDocumentPrivate()
@@ -38,6 +42,49 @@ QPdfDocumentPrivate::~QPdfDocumentPrivate()
}
}
+QPdfDocument::Error QPdfDocumentPrivate::load(QIODevice *newDevice, bool transferDeviceOwnership, const QString &documentPassword)
+{
+ if (doc)
+ FPDF_CloseDocument(doc);
+
+ if (transferDeviceOwnership)
+ ownDevice.reset(newDevice);
+ else
+ ownDevice.reset();
+ device = newDevice;
+
+ if (!device->isOpen() && !device->open(QIODevice::ReadOnly))
+ return QPdfDocument::FileNotFoundError;
+
+ // FPDF_FILEACCESS setup
+ m_FileLen = device->size();
+
+ password = documentPassword.toUtf8();
+
+ QMutexLocker loadLocker(&documentLoadMutex);
+
+ doc = FPDF_LoadCustomDocument(this, password.constData());
+ switch (FPDF_GetLastError()) {
+ case FPDF_ERR_SUCCESS: return QPdfDocument::NoError;
+ case FPDF_ERR_UNKNOWN: return QPdfDocument::UnknownError;
+ case FPDF_ERR_FILE: return QPdfDocument::FileNotFoundError;
+ case FPDF_ERR_FORMAT: return QPdfDocument::InvalidFileFormatError;
+ case FPDF_ERR_PASSWORD: return QPdfDocument::IncorrectPasswordError;
+ case FPDF_ERR_SECURITY: return QPdfDocument::UnsupportedSecuritySchemeError;
+ default:
+ Q_UNREACHABLE();
+ }
+ return QPdfDocument::UnknownError;
+}
+
+int QPdfDocumentPrivate::fpdf_GetBlock(void *param, unsigned long position, unsigned char *pBuf, unsigned long size)
+{
+ QPdfDocumentPrivate *d = static_cast<QPdfDocumentPrivate*>(reinterpret_cast<FPDF_FILEACCESS*>(param));
+ d->device->seek(position);
+ return qMax(qint64(0), d->device->read(reinterpret_cast<char *>(pBuf), size));
+
+}
+
QPdfDocument::QPdfDocument(QObject *parent)
: QObject(parent)
, d(new QPdfDocumentPrivate)
@@ -48,44 +95,14 @@ QPdfDocument::~QPdfDocument()
{
}
-static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size)
+QPdfDocument::Error QPdfDocument::load(const QString &fileName, const QString &password)
{
- QIODevice *dev = reinterpret_cast<QIODevice*>(param);
- dev->seek(position);
- return dev->read(reinterpret_cast<char *>(pBuf), size);
+ return d->load(new QFile(fileName), /*transfer ownership*/true, password);
}
-QPdfDocument::Error QPdfDocument::load(const QString &fileName, const QString &password)
+QPdfDocument::Error QPdfDocument::load(QIODevice *device, const QString &password)
{
- if (d->doc)
- FPDF_CloseDocument(d->doc);
-
- QFile *file = new QFile(fileName);
- d->device.reset(file);
-
- if (!d->device->open(QIODevice::ReadOnly))
- return FileNotFoundError;
-
- FPDF_FILEACCESS access;
- access.m_FileLen = file->size();
- access.m_GetBlock = fpdf_GetBlock;
- access.m_Param = d->device.data();
-
- d->password = password.toUtf8();
-
- QMutexLocker loadLocker(&documentLoadMutex);
- d->doc = FPDF_LoadCustomDocument(&access, d->password.constData());
- switch (FPDF_GetLastError()) {
- case FPDF_ERR_SUCCESS: return NoError;
- case FPDF_ERR_UNKNOWN: return UnknownError;
- case FPDF_ERR_FILE: return FileNotFoundError;
- case FPDF_ERR_FORMAT: return InvalidFileFormatError;
- case FPDF_ERR_PASSWORD: return IncorrectPasswordError;
- case FPDF_ERR_SECURITY: return UnsupportedSecuritySchemeError;
- default:
- Q_UNREACHABLE();
- }
- return UnknownError;
+ return d->load(device, /*transfer ownership*/false, password);
}
int QPdfDocument::pageCount() const
diff --git a/src/pdf/qpdfdocument.h b/src/pdf/qpdfdocument.h
index c389ab5..b33f0fe 100644
--- a/src/pdf/qpdfdocument.h
+++ b/src/pdf/qpdfdocument.h
@@ -26,6 +26,7 @@ public:
~QPdfDocument();
Error load(const QString &fileName, const QString &password = QString());
+ Error load(QIODevice *device, const QString &password = QString());
int pageCount() const;
diff --git a/src/pdf/qpdfdocument_p.h b/src/pdf/qpdfdocument_p.h
index 5a30b1f..7f9b102 100644
--- a/src/pdf/qpdfdocument_p.h
+++ b/src/pdf/qpdfdocument_p.h
@@ -2,18 +2,27 @@
#define QPDFDOCUMENT_P_H
#include "fpdfview.h"
+#include "fpdf_dataavail.h"
+#include "qpdfdocument.h"
#include <qiodevice.h>
-class QPdfDocumentPrivate
+class QPdfDocumentPrivate: public FPDF_FILEACCESS
{
public:
QPdfDocumentPrivate();
~QPdfDocumentPrivate();
FPDF_DOCUMENT doc;
- QScopedPointer<QIODevice> device;
+
+ QIODevice *device;
+ QScopedPointer<QIODevice> ownDevice;
QByteArray password;
+
+ QPdfDocument::Error load(QIODevice *device, bool ownDevice, const QString &documentPassword);
+
+ static bool fpdf_IsDataAvail(struct _FX_FILEAVAIL* pThis, size_t offset, size_t size);
+ static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size);
};
#endif // QPDFDOCUMENT_P_H
diff --git a/tests/auto/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/qpdfdocument/tst_qpdfdocument.cpp
index f91b407..a51c172 100644
--- a/tests/auto/qpdfdocument/tst_qpdfdocument.cpp
+++ b/tests/auto/qpdfdocument/tst_qpdfdocument.cpp
@@ -13,37 +13,52 @@ public:
private slots:
void pageCount();
+ void loadFromIODevice();
};
+struct TemporaryPdf: public QTemporaryFile
+{
+ TemporaryPdf();
+ QPageLayout pageLayout;
+};
-void tst_QPdfDocument::pageCount()
+
+TemporaryPdf::TemporaryPdf()
{
- QTemporaryFile tempPdf;
- tempPdf.setAutoRemove(true);
- QVERIFY(tempPdf.open());
+ open();
+ pageLayout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF());
- QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF());
+ QPrinter printer;
+ printer.setOutputFormat(QPrinter::PdfFormat);
+ printer.setOutputFileName(fileName());
+ printer.setPageLayout(pageLayout);
{
- QPrinter printer;
- printer.setOutputFormat(QPrinter::PdfFormat);
- printer.setOutputFileName(tempPdf.fileName());
- printer.setPageLayout(layout);
-
- {
- QPainter painter(&printer);
- painter.drawText(100, 100, QStringLiteral("Hello Page 1"));
- printer.newPage();
- painter.drawText(100, 100, QStringLiteral("Hello Page 2"));
- }
+ QPainter painter(&printer);
+ painter.drawText(100, 100, QStringLiteral("Hello Page 1"));
+ printer.newPage();
+ painter.drawText(100, 100, QStringLiteral("Hello Page 2"));
}
+}
+
+void tst_QPdfDocument::pageCount()
+{
+ TemporaryPdf tempPdf;
QPdfDocument doc;
QCOMPARE(doc.pageCount(), 0);
QCOMPARE(doc.load(tempPdf.fileName()), QPdfDocument::NoError);
QCOMPARE(doc.pageCount(), 2);
- QCOMPARE(doc.pageSize(0).toSize(), layout.fullRectPoints().size());
+ QCOMPARE(doc.pageSize(0).toSize(), tempPdf.pageLayout.fullRectPoints().size());
+}
+
+void tst_QPdfDocument::loadFromIODevice()
+{
+ TemporaryPdf tempPdf;
+ QPdfDocument doc;
+ QCOMPARE(doc.load(&tempPdf), QPdfDocument::NoError);
+ QCOMPARE(doc.pageCount(), 2);
}
QTEST_MAIN(tst_QPdfDocument)