diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2014-12-15 16:13:52 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2014-12-15 16:13:52 +0100 |
commit | 233896bae4ecf86583d2ded590581b86c1f75b4d (patch) | |
tree | c2cb88ff317202f42297b8ddbf3e5d5ff9817a16 | |
parent | 92f9acff9db4ae299024d4640a4840d8f7c32b2d (diff) |
Allow loading documents synchronously from a QIODevice
-rw-r--r-- | src/pdf/qpdfdocument.cpp | 85 | ||||
-rw-r--r-- | src/pdf/qpdfdocument.h | 1 | ||||
-rw-r--r-- | src/pdf/qpdfdocument_p.h | 13 | ||||
-rw-r--r-- | tests/auto/qpdfdocument/tst_qpdfdocument.cpp | 49 |
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) |