mirror of https://github.com/JakubMelka/PDF4QT.git
Page prefetching, bugfixing
This commit is contained in:
parent
618f334e5d
commit
3cd2dd5104
|
@ -92,7 +92,7 @@ void PDFAsynchronousPageCompiler::reset()
|
|||
start();
|
||||
}
|
||||
|
||||
const PDFPrecompiledPage* PDFAsynchronousPageCompiler::getPrecompiledCache(PDFInteger pageIndex, bool compile)
|
||||
const PDFPrecompiledPage* PDFAsynchronousPageCompiler::getCompiledPage(PDFInteger pageIndex, bool compile)
|
||||
{
|
||||
if (m_state != State::Active || !m_proxy->getDocument())
|
||||
{
|
||||
|
@ -115,9 +115,8 @@ const PDFPrecompiledPage* PDFAsynchronousPageCompiler::getPrecompiledCache(PDFIn
|
|||
CompileTask& task = m_tasks[pageIndex];
|
||||
task.taskFuture = QtConcurrent::run(compilePage);
|
||||
task.taskWatcher = new QFutureWatcher<PDFPrecompiledPage>(this);
|
||||
task.taskWatcher->setFuture(task.taskFuture);
|
||||
connect(task.taskWatcher, &QFutureWatcher<PDFPrecompiledPage>::finished, this, &PDFAsynchronousPageCompiler::onPageCompiled);
|
||||
onPageCompiled();
|
||||
task.taskWatcher->setFuture(task.taskFuture);
|
||||
}
|
||||
|
||||
return page;
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
/// task is performed.
|
||||
/// \param pageIndex Index of page
|
||||
/// \param compile Compile the page, if it is not found in the cache
|
||||
const PDFPrecompiledPage* getPrecompiledCache(PDFInteger pageIndex, bool compile);
|
||||
const PDFPrecompiledPage* getCompiledPage(PDFInteger pageIndex, bool compile);
|
||||
|
||||
signals:
|
||||
void pageImageChanged(bool all, const std::vector<PDFInteger>& pages);
|
||||
|
|
|
@ -606,7 +606,7 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect)
|
|||
// Clear the page space by white color
|
||||
painter->fillRect(placedRect, Qt::white);
|
||||
|
||||
const PDFPrecompiledPage* compiledPage = m_compiler->getPrecompiledCache(item.pageIndex, true);
|
||||
const PDFPrecompiledPage* compiledPage = m_compiler->getCompiledPage(item.pageIndex, true);
|
||||
if (compiledPage && compiledPage->isValid())
|
||||
{
|
||||
QElapsedTimer timer;
|
||||
|
@ -676,7 +676,7 @@ QImage PDFDrawWidgetProxy::drawThumbnailImage(PDFInteger pageIndex, int pixelSiz
|
|||
|
||||
if (imageSize.isValid())
|
||||
{
|
||||
const PDFPrecompiledPage* compiledPage = m_compiler->getPrecompiledCache(pageIndex, true);
|
||||
const PDFPrecompiledPage* compiledPage = m_compiler->getCompiledPage(pageIndex, true);
|
||||
if (compiledPage && compiledPage->isValid())
|
||||
{
|
||||
// Rasterize the image.
|
||||
|
@ -957,6 +957,41 @@ void PDFDrawWidgetProxy::updateRenderer(bool useOpenGL, const QSurfaceFormat& su
|
|||
m_rasterizer->reset(useOpenGL, surfaceFormat);
|
||||
}
|
||||
|
||||
void PDFDrawWidgetProxy::prefetchPages(PDFInteger pageIndex)
|
||||
{
|
||||
// Determine number of pages, which should be prefetched. In case of two or more pages,
|
||||
// we need to prefetch more pages (for example, two for two columns/two pages display mode).
|
||||
int prefetchCount = 0;
|
||||
switch (m_controller->getPageLayout())
|
||||
{
|
||||
case PageLayout::OneColumn:
|
||||
case PageLayout::SinglePage:
|
||||
prefetchCount = 1;
|
||||
break;
|
||||
|
||||
case PageLayout::TwoPagesLeft:
|
||||
case PageLayout::TwoPagesRight:
|
||||
case PageLayout::TwoColumnLeft:
|
||||
case PageLayout::TwoColumnRight:
|
||||
prefetchCount = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (const PDFDocument* document = getDocument())
|
||||
{
|
||||
const PDFInteger pageCount = document->getCatalog()->getPageCount();
|
||||
const PDFInteger pageEnd = qMin(pageCount, pageIndex + prefetchCount + 1);
|
||||
for (PDFInteger i = pageIndex + 1; i < pageEnd; ++i)
|
||||
{
|
||||
m_compiler->getCompiledPage(i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFDrawWidgetProxy::onHorizontalScrollbarValueChanged(int value)
|
||||
{
|
||||
if (!m_updateDisabled && !m_horizontalScrollbar->isHidden())
|
||||
|
|
|
@ -260,6 +260,10 @@ public:
|
|||
/// \param surfaceFormat Surface format for OpenGL rendering
|
||||
void updateRenderer(bool useOpenGL, const QSurfaceFormat& surfaceFormat);
|
||||
|
||||
/// Prefetches (prerenders) pages after page with pageIndex, i.e., prepares
|
||||
/// for non-flickering scroll operation.
|
||||
void prefetchPages(PDFInteger pageIndex);
|
||||
|
||||
static constexpr PDFReal ZOOM_STEP = 1.2;
|
||||
|
||||
const PDFDocument* getDocument() const { return m_controller->getDocument(); }
|
||||
|
|
|
@ -241,7 +241,7 @@ QImage PDFRasterizer::render(const PDFPage* page, const PDFPrecompiledPage* comp
|
|||
compiledPage->draw(&painter, page->getCropBox(), matrix, features);
|
||||
}
|
||||
|
||||
// Convert the image into format Format_ARGB32_Premultiplied for fast drawing.
|
||||
// Jakub Melka: Convert the image into format Format_ARGB32_Premultiplied for fast drawing.
|
||||
// If this format is used, then no image conversion is performed while drawing.
|
||||
if (image.format() != QImage::Format_ARGB32_Premultiplied)
|
||||
{
|
||||
|
@ -304,13 +304,15 @@ void PDFRasterizer::releaseOpenGL()
|
|||
if (m_surface)
|
||||
{
|
||||
Q_ASSERT(m_context);
|
||||
Q_ASSERT(m_fbo);
|
||||
|
||||
// Delete framebuffer
|
||||
m_context->makeCurrent(m_surface);
|
||||
delete m_fbo;
|
||||
m_fbo = nullptr;
|
||||
m_context->doneCurrent();
|
||||
if (m_fbo)
|
||||
{
|
||||
m_context->makeCurrent(m_surface);
|
||||
delete m_fbo;
|
||||
m_fbo = nullptr;
|
||||
m_context->doneCurrent();
|
||||
}
|
||||
|
||||
// Delete OpenGL context
|
||||
delete m_context;
|
||||
|
|
|
@ -633,6 +633,12 @@ void PDFViewerMainWindow::updateUI(bool fullUpdate)
|
|||
if (!currentPages.empty())
|
||||
{
|
||||
m_pageNumberSpinBox->setValue(currentPages.front() + 1);
|
||||
|
||||
// Prefetch pages, if it is enabled
|
||||
if (m_settings->isPagePrefetchingEnabled())
|
||||
{
|
||||
m_pdfWidget->getDrawWidgetProxy()->prefetchPages(currentPages.back());
|
||||
}
|
||||
}
|
||||
|
||||
m_sidebarWidget->setCurrentPages(currentPages);
|
||||
|
|
|
@ -36,6 +36,7 @@ void PDFViewerSettings::readSettings(QSettings& settings)
|
|||
m_settings.m_rendererEngine = static_cast<pdf::RendererEngine>(settings.value("renderingEngine", static_cast<int>(pdf::RendererEngine::OpenGL)).toInt());
|
||||
m_settings.m_multisampleAntialiasing = settings.value("msaa", defaultSettings.m_multisampleAntialiasing).toBool();
|
||||
m_settings.m_rendererSamples = settings.value("rendererSamples", defaultSettings.m_rendererSamples).toInt();
|
||||
m_settings.m_prefetchPages = settings.value("prefetchPages", defaultSettings.m_prefetchPages).toBool();
|
||||
m_settings.m_preferredMeshResolutionRatio = settings.value("preferredMeshResolutionRatio", defaultSettings.m_preferredMeshResolutionRatio).toDouble();
|
||||
m_settings.m_minimalMeshResolutionRatio = settings.value("minimalMeshResolutionRatio", defaultSettings.m_minimalMeshResolutionRatio).toDouble();
|
||||
m_settings.m_colorTolerance = settings.value("colorTolerance", defaultSettings.m_colorTolerance).toDouble();
|
||||
|
@ -54,6 +55,7 @@ void PDFViewerSettings::writeSettings(QSettings& settings)
|
|||
settings.setValue("renderingEngine", static_cast<int>(m_settings.m_rendererEngine));
|
||||
settings.setValue("msaa", m_settings.m_multisampleAntialiasing);
|
||||
settings.setValue("rendererSamples", m_settings.m_rendererSamples);
|
||||
settings.setValue("prefetchPages", m_settings.m_prefetchPages);
|
||||
settings.setValue("preferredMeshResolutionRatio", m_settings.m_preferredMeshResolutionRatio);
|
||||
settings.setValue("minimalMeshResolutionRatio", m_settings.m_minimalMeshResolutionRatio);
|
||||
settings.setValue("colorTolerance", m_settings.m_colorTolerance);
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
m_rendererEngine(pdf::RendererEngine::OpenGL),
|
||||
m_multisampleAntialiasing(true),
|
||||
m_rendererSamples(16),
|
||||
m_prefetchPages(true),
|
||||
m_preferredMeshResolutionRatio(0.02),
|
||||
m_minimalMeshResolutionRatio(0.005),
|
||||
m_colorTolerance(0.01),
|
||||
|
@ -57,6 +58,7 @@ public:
|
|||
pdf::RendererEngine m_rendererEngine;
|
||||
bool m_multisampleAntialiasing;
|
||||
int m_rendererSamples;
|
||||
bool m_prefetchPages;
|
||||
pdf::PDFReal m_preferredMeshResolutionRatio;
|
||||
pdf::PDFReal m_minimalMeshResolutionRatio;
|
||||
pdf::PDFReal m_colorTolerance;
|
||||
|
@ -82,6 +84,7 @@ public:
|
|||
int getRendererSamples() const;
|
||||
void setRendererSamples(int rendererSamples);
|
||||
|
||||
bool isPagePrefetchingEnabled() const { return m_settings.m_prefetchPages; }
|
||||
bool isMultisampleAntialiasingEnabled() const { return m_settings.m_multisampleAntialiasing; }
|
||||
|
||||
pdf::PDFReal getPreferredMeshResolutionRatio() const { return m_settings.m_preferredMeshResolutionRatio; }
|
||||
|
|
|
@ -133,6 +133,7 @@ void PDFViewerSettingsDialog::loadData()
|
|||
ui->multisampleAntialiasingSamplesCountComboBox->setEnabled(false);
|
||||
ui->multisampleAntialiasingSamplesCountComboBox->setCurrentIndex(-1);
|
||||
}
|
||||
ui->prefetchPagesCheckBox->setChecked(m_settings.m_prefetchPages);
|
||||
|
||||
// Rendering
|
||||
ui->antialiasingCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::Antialiasing));
|
||||
|
@ -173,6 +174,10 @@ void PDFViewerSettingsDialog::saveData()
|
|||
{
|
||||
m_settings.m_rendererSamples = ui->multisampleAntialiasingSamplesCountComboBox->currentData().toInt();
|
||||
}
|
||||
else if (sender == ui->prefetchPagesCheckBox)
|
||||
{
|
||||
m_settings.m_prefetchPages = ui->prefetchPagesCheckBox->isChecked();
|
||||
}
|
||||
else if (sender == ui->antialiasingCheckBox)
|
||||
{
|
||||
m_settings.m_features.setFlag(pdf::PDFRenderer::Antialiasing, ui->antialiasingCheckBox->isChecked());
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="enginePage">
|
||||
<layout class="QVBoxLayout" name="enginePageLayout">
|
||||
|
@ -50,16 +50,6 @@
|
|||
<layout class="QVBoxLayout" name="engineSettingsGroupBoxLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="engineSettingsGridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="renderingEngineLabel">
|
||||
<property name="text">
|
||||
<string>Rendering engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="renderingEngineComboBox"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="multisampleAntialiasingCheckBox">
|
||||
<property name="text">
|
||||
|
@ -84,12 +74,36 @@
|
|||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="multisampleAntialiasingSamplesCountComboBox"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="renderingEngineComboBox"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="renderingEngineLabel">
|
||||
<property name="text">
|
||||
<string>Rendering engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="prefetchPagesLabel">
|
||||
<property name="text">
|
||||
<string>Prefetch pages</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="prefetchPagesCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="engineInfoLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Select rendering method according to your needs. <span style=" font-weight:600;">Software rendering</span> is much slower than hardware accelerated rendering using <span style=" font-weight:600;">OpenGL rendering</span>, but it works when OpenGL is not available at your platform. OpenGL rendering is selected as default and is recommended.</p><p>OpenGL rendering uses<span style=" font-weight:600;"> multisample antialiasing (MSAA)</span>, which provides good quality antialiasing. You can turn this feature on or off, but without antialiasing, bad quality image can occur. Samples count affect how much samples per pixel are considered to determine pixel color. It can be a value 1, 2, 4, 8, and 16. Most modern GPUs support at least value 8. Lower this value, if your GPU doesn't support the desired sample count.</p></body></html></string>
|
||||
<string><html><head/><body><p>Select rendering method according to your needs. <span style=" font-weight:600;">Software rendering</span> is much slower than hardware accelerated rendering using <span style=" font-weight:600;">OpenGL rendering</span>, but it works when OpenGL is not available at your platform. OpenGL rendering is selected as default and is recommended.</p><p>OpenGL rendering uses<span style=" font-weight:600;"> multisample antialiasing (MSAA)</span>, which provides good quality antialiasing. You can turn this feature on or off, but without antialiasing, bad quality image can occur. Samples count affect how much samples per pixel are considered to determine pixel color. It can be a value 1, 2, 4, 8, and 16. Most modern GPUs support at least value 8. Lower this value, if your GPU doesn't support the desired sample count.</p><p><span style=" font-weight:600;">Prefetch pages </span>prefetches (pre-renders) pages next to currently viewed pages, to avoid flickering during scrolling. Prefetched pages are stored in the page cache.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
|
Loading…
Reference in New Issue