diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-01-09 18:11:05 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-01-27 13:55:09 +0000 |
commit | 9231d3444555945297857ee4aae05919083ea479 (patch) | |
tree | 7566488ff781e27f0e607cbf1c71a6d7594dc1ce | |
parent | a06650f819ef164e6ec83d69957bd60d77574a16 (diff) |
QPdfDocument: check first page in load(), current page in render()
When a viewer application is opened with a book-sized PDF, there's no
need to check hundreds of pages before we can render the first page.
Using it in QPdfIOHandler is even worse because this check needs to
be repeated each time we advance from one page to the next. But we
do need to ensure that the page we want to render is available.
Amends 945840bd067d9ca3179a667f48b451cc2087931b
Change-Id: Ib6576b1b91c63c2b57893d14b05632eff8cc4a15
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r-- | src/pdf/api/qpdfdocument_p.h | 1 | ||||
-rw-r--r-- | src/pdf/qpdfdocument.cpp | 49 |
2 files changed, 48 insertions, 2 deletions
diff --git a/src/pdf/api/qpdfdocument_p.h b/src/pdf/api/qpdfdocument_p.h index 928754210..15d8b8259 100644 --- a/src/pdf/api/qpdfdocument_p.h +++ b/src/pdf/api/qpdfdocument_p.h @@ -98,6 +98,7 @@ public: void _q_copyFromSequentialSourceDevice(); void tryLoadDocument(); void checkComplete(); + bool checkPageComplete(int page); void setStatus(QPdfDocument::Status status); static FPDF_BOOL fpdf_IsDataAvail(struct _FX_FILEAVAIL* pThis, size_t offset, size_t size); diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp index 690953691..4c4f8f24e 100644 --- a/src/pdf/qpdfdocument.cpp +++ b/src/pdf/qpdfdocument.cpp @@ -186,7 +186,35 @@ void QPdfDocumentPrivate::load(QIODevice *newDevice, bool transferDeviceOwnershi } else { device = newDevice; initiateAsyncLoadWithTotalSizeKnown(device->size()); - checkComplete(); + if (!avail) { + setStatus(QPdfDocument::Error); + return; + } + + if (!doc) + tryLoadDocument(); + + if (!doc) { + updateLastError(); + setStatus(QPdfDocument::Error); + return; + } + + QPdfMutexLocker lock; + const int newPageCount = FPDF_GetPageCount(doc); + lock.unlock(); + if (newPageCount != pageCount) { + pageCount = newPageCount; + emit q->pageCountChanged(pageCount); + } + + // If it's a local file, and the first page is available, probably the whole document is available. + if (checkPageComplete(0)) { + setStatus(QPdfDocument::Ready); + } else { + updateLastError(); + setStatus(QPdfDocument::Error); + } } } @@ -311,6 +339,23 @@ void QPdfDocumentPrivate::checkComplete() } } +bool QPdfDocumentPrivate::checkPageComplete(int page) +{ + if (loadComplete) + return true; + + QPdfMutexLocker lock; + int result = PDF_DATA_NOTAVAIL; + while (result == PDF_DATA_NOTAVAIL) + result = FPDFAvail_IsPageAvail(avail, page, this); + lock.unlock(); + + if (result == PDF_DATA_ERROR) + updateLastError(); + + return (result != PDF_DATA_ERROR); +} + void QPdfDocumentPrivate::setStatus(QPdfDocument::Status documentStatus) { if (status == documentStatus) @@ -581,7 +626,7 @@ QSizeF QPdfDocument::pageSize(int page) const */ QImage QPdfDocument::render(int page, QSize imageSize, QPdfDocumentRenderOptions renderOptions) { - if (!d->doc) + if (!d->doc || !d->checkPageComplete(page)) return QImage(); const QPdfMutexLocker lock; |