Asynchronous image redraw

This commit is contained in:
Jakub Melka 2021-02-13 19:20:05 +01:00
parent f020098435
commit 9da1efe4ef
2 changed files with 96 additions and 8 deletions

View File

@ -22,6 +22,9 @@
#include "pdfrenderer.h"
#include "pdfdrawspacecontroller.h"
#include <QCloseEvent>
#include <QtConcurrent/QtConcurrent>
namespace pdfplugin
{
@ -30,7 +33,9 @@ OutputPreviewDialog::OutputPreviewDialog(const pdf::PDFDocument* document, pdf::
ui(new Ui::OutputPreviewDialog),
m_inkMapper(document),
m_document(document),
m_widget(widget)
m_widget(widget),
m_needUpdateImage(false),
m_futureWatcher(nullptr)
{
ui->setupUi(this);
@ -39,7 +44,7 @@ OutputPreviewDialog::OutputPreviewDialog(const pdf::PDFDocument* document, pdf::
ui->pageIndexScrollBar->setMaximum(int(document->getCatalog()->getPageCount()));
m_inkMapper.createSpotColors(true);
updateImage();
updatePageImage();
}
OutputPreviewDialog::~OutputPreviewDialog()
@ -50,25 +55,67 @@ OutputPreviewDialog::~OutputPreviewDialog()
void OutputPreviewDialog::resizeEvent(QResizeEvent* event)
{
QDialog::resizeEvent(event);
updateImage();
updatePageImage();
}
void OutputPreviewDialog::updateImage()
void OutputPreviewDialog::closeEvent(QCloseEvent* event)
{
if (!isRenderingDone())
{
event->ignore();
}
}
void OutputPreviewDialog::showEvent(QShowEvent* event)
{
Q_UNUSED(event);
updatePageImage();
}
void OutputPreviewDialog::updatePageImage()
{
if (!isRenderingDone())
{
m_needUpdateImage = true;
return;
}
m_needUpdateImage = false;
const pdf::PDFPage* page = m_document->getCatalog()->getPage(ui->pageIndexScrollBar->value() - 1);
if (!page)
{
ui->imageLabel->setPixmap(QPixmap());
return;
}
QApplication::setOverrideCursor(Qt::WaitCursor);
QSize renderSize = ui->imageLabel->size();
auto renderImage = [this, page, renderSize]() -> RenderedImage
{
return renderPage(page, renderSize);
};
m_future = QtConcurrent::run(renderImage);
m_futureWatcher = new QFutureWatcher<RenderedImage>();
connect(m_futureWatcher, &QFutureWatcher<RenderedImage>::finished, this, &OutputPreviewDialog::onPageImageRendered);
m_futureWatcher->setFuture(m_future);
}
OutputPreviewDialog::RenderedImage OutputPreviewDialog::renderPage(const pdf::PDFPage* page, QSize renderSize)
{
RenderedImage result;
QRectF pageRect = page->getRotatedMediaBox();
QSizeF pageSize = pageRect.size();
pageSize.scale(ui->imageLabel->width(), ui->imageLabel->height(), Qt::KeepAspectRatio);
pageSize.scale(renderSize.width(), renderSize.height(), Qt::KeepAspectRatio);
QSize imageSize = pageSize.toSize();
if (!imageSize.isValid())
{
ui->imageLabel->setPixmap(QPixmap());
return result;
}
pdf::PDFTransparencyRendererSettings settings;
@ -88,7 +135,31 @@ void OutputPreviewDialog::updateImage()
renderer.endPaint();
QImage image = renderer.toImage(false, true, pdf::PDFRGB{ 1.0f, 1.0f, 1.0f });
ui->imageLabel->setPixmap(QPixmap::fromImage(image));
result.image = qMove(image);
return result;
}
void OutputPreviewDialog::onPageImageRendered()
{
QApplication::restoreOverrideCursor();
RenderedImage result = m_future.result();
m_future = QFuture<RenderedImage>();
m_futureWatcher->deleteLater();
m_futureWatcher = nullptr;
ui->imageLabel->setPixmap(QPixmap::fromImage(result.image));
if (m_needUpdateImage)
{
updatePageImage();
}
}
bool OutputPreviewDialog::isRenderingDone() const
{
return !(m_futureWatcher && m_futureWatcher->isRunning());
}
} // namespace pdfplugin

View File

@ -23,6 +23,8 @@
#include "pdftransparencyrenderer.h"
#include <QDialog>
#include <QFuture>
#include <QFutureWatcher>
namespace Ui
{
@ -41,14 +43,29 @@ public:
virtual ~OutputPreviewDialog() override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void closeEvent(QCloseEvent* event) override;
virtual void showEvent(QShowEvent* event) override;
private:
void updateImage();
struct RenderedImage
{
QImage image;
};
void updatePageImage();
void onPageImageRendered();
RenderedImage renderPage(const pdf::PDFPage* page, QSize renderSize);
bool isRenderingDone() const;
Ui::OutputPreviewDialog* ui;
pdf::PDFInkMapper m_inkMapper;
const pdf::PDFDocument* m_document;
pdf::PDFWidget* m_widget;
bool m_needUpdateImage;
QFuture<RenderedImage> m_future;
QFutureWatcher<RenderedImage>* m_futureWatcher;
};
} // namespace pdf