summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-01-09 18:11:05 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-01-27 13:55:09 +0000
commit9231d3444555945297857ee4aae05919083ea479 (patch)
tree7566488ff781e27f0e607cbf1c71a6d7594dc1ce
parenta06650f819ef164e6ec83d69957bd60d77574a16 (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.h1
-rw-r--r--src/pdf/qpdfdocument.cpp49
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;