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 "pdfrenderer.h"
#include "pdfdrawspacecontroller.h" #include "pdfdrawspacecontroller.h"
#include <QCloseEvent>
#include <QtConcurrent/QtConcurrent>
namespace pdfplugin namespace pdfplugin
{ {
@ -30,7 +33,9 @@ OutputPreviewDialog::OutputPreviewDialog(const pdf::PDFDocument* document, pdf::
ui(new Ui::OutputPreviewDialog), ui(new Ui::OutputPreviewDialog),
m_inkMapper(document), m_inkMapper(document),
m_document(document), m_document(document),
m_widget(widget) m_widget(widget),
m_needUpdateImage(false),
m_futureWatcher(nullptr)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -39,7 +44,7 @@ OutputPreviewDialog::OutputPreviewDialog(const pdf::PDFDocument* document, pdf::
ui->pageIndexScrollBar->setMaximum(int(document->getCatalog()->getPageCount())); ui->pageIndexScrollBar->setMaximum(int(document->getCatalog()->getPageCount()));
m_inkMapper.createSpotColors(true); m_inkMapper.createSpotColors(true);
updateImage(); updatePageImage();
} }
OutputPreviewDialog::~OutputPreviewDialog() OutputPreviewDialog::~OutputPreviewDialog()
@ -50,25 +55,67 @@ OutputPreviewDialog::~OutputPreviewDialog()
void OutputPreviewDialog::resizeEvent(QResizeEvent* event) void OutputPreviewDialog::resizeEvent(QResizeEvent* event)
{ {
QDialog::resizeEvent(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); const pdf::PDFPage* page = m_document->getCatalog()->getPage(ui->pageIndexScrollBar->value() - 1);
if (!page) if (!page)
{ {
ui->imageLabel->setPixmap(QPixmap()); 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(); QRectF pageRect = page->getRotatedMediaBox();
QSizeF pageSize = pageRect.size(); 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(); QSize imageSize = pageSize.toSize();
if (!imageSize.isValid()) if (!imageSize.isValid())
{ {
ui->imageLabel->setPixmap(QPixmap()); return result;
} }
pdf::PDFTransparencyRendererSettings settings; pdf::PDFTransparencyRendererSettings settings;
@ -88,7 +135,31 @@ void OutputPreviewDialog::updateImage()
renderer.endPaint(); renderer.endPaint();
QImage image = renderer.toImage(false, true, pdf::PDFRGB{ 1.0f, 1.0f, 1.0f }); 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 } // namespace pdfplugin

View File

@ -23,6 +23,8 @@
#include "pdftransparencyrenderer.h" #include "pdftransparencyrenderer.h"
#include <QDialog> #include <QDialog>
#include <QFuture>
#include <QFutureWatcher>
namespace Ui namespace Ui
{ {
@ -41,14 +43,29 @@ public:
virtual ~OutputPreviewDialog() override; virtual ~OutputPreviewDialog() override;
virtual void resizeEvent(QResizeEvent* event) override; virtual void resizeEvent(QResizeEvent* event) override;
virtual void closeEvent(QCloseEvent* event) override;
virtual void showEvent(QShowEvent* event) override;
private: 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; Ui::OutputPreviewDialog* ui;
pdf::PDFInkMapper m_inkMapper; pdf::PDFInkMapper m_inkMapper;
const pdf::PDFDocument* m_document; const pdf::PDFDocument* m_document;
pdf::PDFWidget* m_widget; pdf::PDFWidget* m_widget;
bool m_needUpdateImage;
QFuture<RenderedImage> m_future;
QFutureWatcher<RenderedImage>* m_futureWatcher;
}; };
} // namespace pdf } // namespace pdf