Merge remote-tracking branch 'remotes/origin/branches/issue123'

This commit is contained in:
Jakub Melka 2024-02-25 16:08:24 +01:00
commit 6c5b8b08a5
52 changed files with 1676 additions and 873 deletions

View File

@ -48,7 +48,7 @@ jobs:
- name: 'VCPKG: Install project dependencies' - name: 'VCPKG: Install project dependencies'
run: | run: |
./vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng ./vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng blend2d
working-directory: vcpkg working-directory: vcpkg
- name: Install Qt - name: Install Qt

View File

@ -36,7 +36,7 @@ jobs:
- name: 'VCPKG: Install project dependencies' - name: 'VCPKG: Install project dependencies'
run: | run: |
./vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng ./vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng blend2d
working-directory: vcpkg working-directory: vcpkg
- name: Install Qt - name: Install Qt
@ -101,7 +101,7 @@ jobs:
- name: 'VCPKG: Install project dependencies' - name: 'VCPKG: Install project dependencies'
run: | run: |
.\vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng --triplet x64-windows .\vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng blend2d --triplet x64-windows
working-directory: vcpkg working-directory: vcpkg
- name: Install Qt - name: Install Qt

View File

@ -33,7 +33,6 @@ if(WIN32 AND MSVC)
option(PDF4QT_INSTALL_PREPARE_WIX_INSTALLER "Prepare Wix installer for Windows" ON) option(PDF4QT_INSTALL_PREPARE_WIX_INSTALLER "Prepare Wix installer for Windows" ON)
endif() endif()
option(PDF4QT_ENABLE_OPENGL "Enable OpenGL" ON)
option(PDF4QT_BUILD_ONLY_CORE_LIBRARY "Build only core library" OFF) option(PDF4QT_BUILD_ONLY_CORE_LIBRARY "Build only core library" OFF)
set(PDF4QT_QT_ROOT "" CACHE PATH "Qt root directory") set(PDF4QT_QT_ROOT "" CACHE PATH "Qt root directory")
@ -49,18 +48,8 @@ include(GNUInstallDirs)
if(PDF4QT_BUILD_ONLY_CORE_LIBRARY) if(PDF4QT_BUILD_ONLY_CORE_LIBRARY)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Svg Xml) find_package(Qt6 REQUIRED COMPONENTS Core Gui Svg Xml)
if(PDF4QT_ENABLE_OPENGL)
add_compile_definitions(PDF4QT_ENABLE_OPENGL)
find_package(Qt6 REQUIRED COMPONENTS OpenGL)
endif()
else() else()
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Svg Xml PrintSupport TextToSpeech Test) find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Svg Xml PrintSupport TextToSpeech Test)
if(PDF4QT_ENABLE_OPENGL)
add_compile_definitions(PDF4QT_ENABLE_OPENGL)
find_package(Qt6 REQUIRED COMPONENTS OpenGL OpenGLWidgets)
endif()
endif() endif()
qt_standard_project_setup() qt_standard_project_setup()
@ -72,6 +61,7 @@ find_package(Freetype REQUIRED)
find_package(OpenJPEG CONFIG REQUIRED) find_package(OpenJPEG CONFIG REQUIRED)
find_package(JPEG REQUIRED) find_package(JPEG REQUIRED)
find_package(PNG REQUIRED) find_package(PNG REQUIRED)
find_package(blend2d CONFIG REQUIRED)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
@ -178,7 +168,7 @@ if(PDF4QT_INSTALL_DEPENDENCIES AND NOT PDF4QT_BUILD_ONLY_CORE_LIBRARY)
install(DIRECTORY ${PDF4QT_QT_ROOT}/bin/ install(DIRECTORY ${PDF4QT_QT_ROOT}/bin/
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/ RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/
FILES_MATCHING FILES_MATCHING
REGEX "(Qt6Core|Qt6Gui|Qt6PrintSupport|Qt6Svg|Qt6TextToSpeech|Qt6Widgets|Qt6Xml|Qt6OpenGL|Qt6OpenGLWidgets|Qt6Multimedia|Qt6Network)\\..*" REGEX "(Qt6Core|Qt6Gui|Qt6PrintSupport|Qt6Svg|Qt6TextToSpeech|Qt6Widgets|Qt6Xml|Qt6Multimedia|Qt6Network)\\..*"
PATTERN "Debug" EXCLUDE PATTERN "Debug" EXCLUDE
) )

View File

@ -35,10 +35,6 @@ add_executable(Pdf4QtDocDiff
icon.rc icon.rc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(Pdf4QtDocDiff PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(Pdf4QtDocDiff PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(Pdf4QtDocDiff PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(Pdf4QtDocDiff PROPERTIES set_target_properties(Pdf4QtDocDiff PROPERTIES

View File

@ -24,7 +24,6 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true); QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
QApplication application(argc, argv); QApplication application(argc, argv);
QCoreApplication::setOrganizationName("MelkaJ"); QCoreApplication::setOrganizationName("MelkaJ");

View File

@ -82,7 +82,7 @@ MainWindow::MainWindow(QWidget* parent) :
ui->documentFrame->setLayout(new QVBoxLayout); ui->documentFrame->setLayout(new QVBoxLayout);
m_cmsManager = new pdf::PDFCMSManager(this); m_cmsManager = new pdf::PDFCMSManager(this);
m_pdfWidget = new pdf::PDFWidget(m_cmsManager, pdf::RendererEngine::Software, 1, ui->documentFrame); m_pdfWidget = new pdf::PDFWidget(m_cmsManager, pdf::RendererEngine::QPainter, ui->documentFrame);
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress); m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
ui->documentFrame->layout()->addWidget(m_pdfWidget); ui->documentFrame->layout()->addWidget(m_pdfWidget);
m_pdfWidget->getDrawWidgetProxy()->registerDrawInterface(&m_drawInterface); m_pdfWidget->getDrawWidgetProxy()->registerDrawInterface(&m_drawInterface);

View File

@ -24,7 +24,6 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true); QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
QApplication application(argc, argv); QApplication application(argc, argv);
QCoreApplication::setOrganizationName("MelkaJ"); QCoreApplication::setOrganizationName("MelkaJ");

View File

@ -35,9 +35,7 @@ PageItemDelegate::PageItemDelegate(PageItemModel* model, QObject* parent) :
m_rasterizer(nullptr) m_rasterizer(nullptr)
{ {
m_rasterizer = new pdf::PDFRasterizer(this); m_rasterizer = new pdf::PDFRasterizer(this);
QSurfaceFormat format; m_rasterizer->reset(pdf::RendererEngine::Blend2D_SingleThread);
format.setSamples(16);
m_rasterizer->reset(false, format);
} }
PageItemDelegate::~PageItemDelegate() PageItemDelegate::~PageItemDelegate()

View File

@ -146,6 +146,8 @@ add_library(Pdf4QtLibCore SHARED
cmaps.qrc cmaps.qrc
sources/pdfcertificatestore.h sources/pdfcertificatestore.h
sources/pdfcertificatestore.cpp sources/pdfcertificatestore.cpp
sources/pdfblpainter.h
sources/pdfblpainter.cpp
) )
include(GenerateExportHeader) include(GenerateExportHeader)
@ -163,10 +165,6 @@ target_link_libraries(Pdf4QtLibCore PRIVATE Freetype::Freetype)
target_link_libraries(Pdf4QtLibCore PRIVATE openjp2) target_link_libraries(Pdf4QtLibCore PRIVATE openjp2)
target_link_libraries(Pdf4QtLibCore PRIVATE JPEG::JPEG) target_link_libraries(Pdf4QtLibCore PRIVATE JPEG::JPEG)
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(Pdf4QtLibCore PRIVATE Qt6::OpenGL)
endif()
if(LINUX_GCC) if(LINUX_GCC)
target_link_libraries(Pdf4QtLibCore PUBLIC TBB::tbb) target_link_libraries(Pdf4QtLibCore PUBLIC TBB::tbb)
endif() endif()
@ -178,6 +176,8 @@ endif()
target_include_directories(Pdf4QtLibCore INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/sources) target_include_directories(Pdf4QtLibCore INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/sources)
target_include_directories(Pdf4QtLibCore PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}) target_include_directories(Pdf4QtLibCore PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR})
target_link_libraries(Pdf4QtLibCore PRIVATE blend2d::blend2d)
set_target_properties(Pdf4QtLibCore PROPERTIES set_target_properties(Pdf4QtLibCore PROPERTIES
VERSION ${PDF4QT_VERSION} VERSION ${PDF4QT_VERSION}
SOVERSION ${PDF4QT_VERSION} SOVERSION ${PDF4QT_VERSION}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
// Copyright (C) 2024 Jakub Melka
//
// This file is part of PDF4QT.
//
// PDF4QT is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// with the written consent of the copyright owner, any later version.
//
// PDF4QT is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFBLPAINTER_H
#define PDFBLPAINTER_H
#include "pdfglobal.h"
#include <QImage>
#include <QPaintDevice>
namespace pdf
{
class PDFBLPaintEngine;
class PDF4QTLIBCORESHARED_EXPORT PDFBLPaintDevice : public QPaintDevice
{
public:
PDFBLPaintDevice(QImage& offscreenBuffer, bool isMultithreaded);
virtual ~PDFBLPaintDevice() override;
virtual int devType() const override;
virtual QPaintEngine* paintEngine() const override;
static uint32_t getVersion();
protected:
virtual int metric(PaintDeviceMetric metric) const override;
private:
QImage& m_offscreenBuffer;
PDFBLPaintEngine* m_paintEngine;
};
} // namespace pdf
#endif // PDFBLPAINTER_H

View File

@ -2685,4 +2685,16 @@ CharacterInfos PDFRealizedType3FontImpl::getCharacterInfos() const
return result; return result;
} }
QByteArray PDFSystemFont::getFontData(const QByteArray& fontName)
{
const PDFSystemFontInfoStorage* storage = PDFSystemFontInfoStorage::getInstance();
CIDSystemInfo systemInfo;
PDFRenderErrorReporterDummy reporter;
FontDescriptor descriptor;
descriptor.fontName = fontName;
return storage->loadFont(&systemInfo, &descriptor, StandardFontType::Invalid, &reporter);
}
} // namespace pdf } // namespace pdf

View File

@ -698,6 +698,12 @@ private:
std::map<QByteArray, QByteArray> m_cmaps; std::map<QByteArray, QByteArray> m_cmaps;
}; };
class PDF4QTLIBCORESHARED_EXPORT PDFSystemFont
{
public:
static QByteArray getFontData(const QByteArray& fontName);
};
} // namespace pdf } // namespace pdf
#endif // PDFFONT_H #endif // PDFFONT_H

View File

@ -187,8 +187,9 @@ private:
enum class RendererEngine enum class RendererEngine
{ {
Software, Blend2D_MultiThread,
OpenGL Blend2D_SingleThread,
QPainter,
}; };
enum class RenderingIntent enum class RenderingIntent

View File

@ -18,6 +18,7 @@
#include "pdfpainter.h" #include "pdfpainter.h"
#include "pdfpattern.h" #include "pdfpattern.h"
#include "pdfcms.h" #include "pdfcms.h"
#include "pdfpainterutils.h"
#include <QPainter> #include <QPainter>
#include <QCryptographicHash> #include <QCryptographicHash>

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021-2022 Jakub Melka // Copyright (C) 2021-2024 Jakub Melka
// //
// This file is part of PDF4QT. // This file is part of PDF4QT.
// //
@ -17,6 +17,7 @@
#include "pdfpainterutils.h" #include "pdfpainterutils.h"
#include <QPainterPath>
#include <QFontMetrics> #include <QFontMetrics>
#include "pdfdbgheap.h" #include "pdfdbgheap.h"
@ -63,4 +64,5 @@ QRect PDFPainterHelper::drawBubble(QPainter* painter, QPoint point, QColor color
return rectangle; return rectangle;
} }
} // namespace pdf } // namespace pdf

View File

@ -22,6 +22,7 @@
#include "pdfcolorspaces.h" #include "pdfcolorspaces.h"
#include "pdfexecutionpolicy.h" #include "pdfexecutionpolicy.h"
#include "pdfconstants.h" #include "pdfconstants.h"
#include "pdfpainterutils.h"
#include <QMutex> #include <QMutex>
#include <QPainter> #include <QPainter>

View File

@ -21,19 +21,12 @@
#include "pdfexecutionpolicy.h" #include "pdfexecutionpolicy.h"
#include "pdfprogress.h" #include "pdfprogress.h"
#include "pdfannotation.h" #include "pdfannotation.h"
#include "pdfblpainter.h"
#include <QDir> #include <QDir>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QtMath> #include <QtMath>
#ifdef PDF4QT_ENABLE_OPENGL
#include <QOpenGLContext>
#include <QOffscreenSurface>
#include <QOpenGLPaintDevice>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#endif
#include "pdfdbgheap.h" #include "pdfdbgheap.h"
namespace pdf namespace pdf
@ -227,54 +220,19 @@ void PDFRenderer::compile(PDFPrecompiledPage* precompiledPage, size_t pageIndex)
PDFRasterizer::PDFRasterizer(QObject* parent) : PDFRasterizer::PDFRasterizer(QObject* parent) :
BaseClass(parent), BaseClass(parent),
#ifdef PDF4QT_ENABLE_OPENGL m_rendererEngine(RendererEngine::Blend2D_SingleThread)
m_features(),
m_surfaceFormat(),
m_surface(nullptr),
m_context(nullptr),
m_fbo(nullptr)
#else
m_features()
#endif
{ {
} }
PDFRasterizer::~PDFRasterizer() PDFRasterizer::~PDFRasterizer()
{ {
#ifdef PDF4QT_ENABLE_OPENGL
releaseOpenGL();
#endif
} }
void PDFRasterizer::reset(bool useOpenGL, const QSurfaceFormat& surfaceFormat) void PDFRasterizer::reset(RendererEngine rendererEngine)
{ {
if (!PDFRendererInfo::isHardwareAccelerationSupported()) m_rendererEngine = rendererEngine;
{
m_features.setFlag(FailedOpenGL, true);
m_features.setFlag(ValidOpenGL, false);
}
#ifdef PDF4QT_ENABLE_OPENGL
if (useOpenGL != m_features.testFlag(UseOpenGL) || surfaceFormat != m_surfaceFormat)
{
// In either case, we must reset OpenGL
releaseOpenGL();
m_features.setFlag(UseOpenGL, useOpenGL);
m_surfaceFormat = surfaceFormat;
// We create new OpenGL renderer, but only if it hasn't failed (we do not try
// again to create new OpenGL renderer.
if (m_features.testFlag(UseOpenGL) && !m_features.testFlag(FailedOpenGL))
{
initializeOpenGL();
}
}
#else
Q_UNUSED(surfaceFormat);
m_features.setFlag(UseOpenGL, useOpenGL);
#endif
} }
QImage PDFRasterizer::render(PDFInteger pageIndex, QImage PDFRasterizer::render(PDFInteger pageIndex,
@ -285,70 +243,28 @@ QImage PDFRasterizer::render(PDFInteger pageIndex,
const PDFAnnotationManager* annotationManager, const PDFAnnotationManager* annotationManager,
PageRotation extraRotation) PageRotation extraRotation)
{ {
QImage image; QImage image(size, QImage::Format_ARGB32_Premultiplied);
QTransform matrix = PDFRenderer::createPagePointToDevicePointMatrix(page, QRect(QPoint(0, 0), size), extraRotation); QTransform matrix = PDFRenderer::createPagePointToDevicePointMatrix(page, QRect(QPoint(0, 0), size), extraRotation);
#ifdef PDF4QT_ENABLE_OPENGL if (m_rendererEngine == RendererEngine::Blend2D_MultiThread ||
if (m_features.testFlag(UseOpenGL) && m_features.testFlag(ValidOpenGL)) m_rendererEngine == RendererEngine::Blend2D_SingleThread)
{ {
// We have valid OpenGL context, try to select it and possibly create framebuffer object PDFBLPaintDevice blPaintDevice(image, false);
// for target image (to paint it using paint device).
Q_ASSERT(m_surface && m_context); QPainter painter(&blPaintDevice);
if (m_context->makeCurrent(m_surface)) compiledPage->draw(&painter, page->getCropBox(), matrix, features, 1.0);
if (annotationManager)
{ {
if (!m_fbo || m_fbo->width() != size.width() || m_fbo->height() != size.height()) QList<PDFRenderError> errors;
{ PDFTextLayoutGetter textLayoutGetter(nullptr, pageIndex);
// Delete old framebuffer object annotationManager->drawPage(&painter, pageIndex, compiledPage, textLayoutGetter, matrix, errors);
delete m_fbo;
// Create a new framebuffer object
QOpenGLFramebufferObjectFormat format;
format.setSamples(m_surfaceFormat.samples());
m_fbo = new QOpenGLFramebufferObject(size.width(), size.height(), format);
}
Q_ASSERT(m_fbo);
if (m_fbo->isValid() && m_fbo->bind())
{
// Now, we have bind the buffer. Due to bug in Qt's OpenGL drawing subsystem,
// we must render it two times, otherwise painter paths will be sometimes
// replaced by filled rectangles.
for (int i = 0; i < 2; ++i)
{
QOpenGLPaintDevice device(size);
QPainter painter(&device);
painter.fillRect(QRect(QPoint(0, 0), size), compiledPage->getPaperColor());
compiledPage->draw(&painter, page->getCropBox(), matrix, features, 1.0);
if (annotationManager)
{
QList<PDFRenderError> errors;
PDFTextLayoutGetter textLayoutGetter(nullptr, pageIndex);
annotationManager->drawPage(&painter, pageIndex, compiledPage, textLayoutGetter, matrix, errors);
}
}
m_fbo->release();
image = m_fbo->toImage();
}
else
{
m_features.setFlag(FailedOpenGL, true);
m_features.setFlag(ValidOpenGL, false);
}
m_context->doneCurrent();
} }
} }
#endif else
if (image.isNull())
{ {
// If we can't use OpenGL, or user doesn't want to use OpenGL, then fallback // Use standard software rasterizer.
// to standard software rasterizer.
image = QImage(size, QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::white); image.fill(Qt::white);
QPainter painter(&image); QPainter painter(&image);
@ -362,13 +278,6 @@ QImage PDFRasterizer::render(PDFInteger pageIndex,
} }
} }
// 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)
{
image.convertTo(QImage::Format_ARGB32_Premultiplied);
}
// Calculate image DPI // Calculate image DPI
QSizeF rotatedSizeInMeters = page->getRotatedMediaBoxMM().size() / 1000.0; QSizeF rotatedSizeInMeters = page->getRotatedMediaBoxMM().size() / 1000.0;
QSizeF rotatedSizeInPixels = image.size(); QSizeF rotatedSizeInPixels = image.size();
@ -380,87 +289,6 @@ QImage PDFRasterizer::render(PDFInteger pageIndex,
return image; return image;
} }
#ifdef PDF4QT_ENABLE_OPENGL
void PDFRasterizer::initializeOpenGL()
{
Q_ASSERT(!m_surface);
Q_ASSERT(!m_context);
Q_ASSERT(!m_fbo);
m_features.setFlag(ValidOpenGL, false);
m_features.setFlag(FailedOpenGL, false);
// Create context
m_context = new QOpenGLContext(this);
m_context->setFormat(m_surfaceFormat);
if (!m_context->create())
{
m_features.setFlag(FailedOpenGL, true);
delete m_context;
m_context = nullptr;
}
// Create surface
m_surface = new QOffscreenSurface(nullptr, this);
m_surface->setFormat(m_surfaceFormat);
m_surface->create();
if (!m_surface->isValid())
{
m_features.setFlag(FailedOpenGL, true);
delete m_context;
delete m_surface;
m_context = nullptr;
m_surface = nullptr;
}
// Check, if we can make it current
if (m_context->makeCurrent(m_surface))
{
m_features.setFlag(ValidOpenGL, true);
m_context->doneCurrent();
}
else
{
m_features.setFlag(FailedOpenGL, true);
releaseOpenGL();
}
}
#endif
#ifdef PDF4QT_ENABLE_OPENGL
void PDFRasterizer::releaseOpenGL()
{
if (m_surface)
{
Q_ASSERT(m_context);
// Delete framebuffer
if (m_fbo)
{
m_context->makeCurrent(m_surface);
delete m_fbo;
m_fbo = nullptr;
m_context->doneCurrent();
}
// Delete OpenGL context
delete m_context;
m_context = nullptr;
// Delete surface
m_surface->destroy();
delete m_surface;
m_surface = nullptr;
// Set flag, that we do not have valid OpenGL
m_features.setFlag(ValidOpenGL, false);
}
}
#endif
PDFRasterizer* PDFRasterizerPool::acquire() PDFRasterizer* PDFRasterizerPool::acquire()
{ {
m_semaphore.acquire(); m_semaphore.acquire();
@ -978,8 +806,7 @@ PDFRasterizerPool::PDFRasterizerPool(const PDFDocument* document,
PDFRenderer::Features features, PDFRenderer::Features features,
const PDFMeshQualitySettings& meshQualitySettings, const PDFMeshQualitySettings& meshQualitySettings,
int rasterizerCount, int rasterizerCount,
bool useOpenGL, RendererEngine rendererEngine,
const QSurfaceFormat& surfaceFormat,
QObject* parent) : QObject* parent) :
BaseClass(parent), BaseClass(parent),
m_document(document), m_document(document),
@ -994,96 +821,8 @@ PDFRasterizerPool::PDFRasterizerPool(const PDFDocument* document,
for (int i = 0; i < rasterizerCount; ++i) for (int i = 0; i < rasterizerCount; ++i)
{ {
m_rasterizers.push_back(new PDFRasterizer(this)); m_rasterizers.push_back(new PDFRasterizer(this));
m_rasterizers.back()->reset(useOpenGL, surfaceFormat); m_rasterizers.back()->reset(rendererEngine);
} }
} }
PDFCachedItem<PDFRendererInfo::Info> PDFRendererInfo::s_info;
const PDFRendererInfo::Info& PDFRendererInfo::getHardwareAccelerationSupportedInfo()
{
auto getInfo = []()
{
Info info;
#ifdef PDF4QT_ENABLE_OPENGL
QOffscreenSurface surface;
surface.create();
if (!surface.isValid())
{
info.renderer = PDFTranslationContext::tr("GDI Generic");
info.version = PDFTranslationContext::tr("1.1");
info.vendor = PDFTranslationContext::tr("System");
return info;
}
QOpenGLContext context;
if (!context.create())
{
info.renderer = PDFTranslationContext::tr("GDI Generic");
info.version = PDFTranslationContext::tr("1.1");
info.vendor = PDFTranslationContext::tr("System");
surface.destroy();
return info;
}
if (!context.makeCurrent(&surface))
{
info.renderer = PDFTranslationContext::tr("GDI Generic");
info.version = PDFTranslationContext::tr("1.1");
info.vendor = PDFTranslationContext::tr("System");
surface.destroy();
return info;
}
const char* versionStr = reinterpret_cast<const char*>(context.functions()->glGetString(GL_VERSION));
const char* vendorStr = reinterpret_cast<const char*>(context.functions()->glGetString(GL_VENDOR));
const char* rendererStr = reinterpret_cast<const char*>(context.functions()->glGetString(GL_RENDERER));
QString versionString = QString::fromLocal8Bit(versionStr, std::strlen(versionStr));
QString vendorString = QString::fromLocal8Bit(vendorStr, std::strlen(vendorStr));
QString rendererString = QString::fromLocal8Bit(rendererStr, std::strlen(rendererStr));
context.doneCurrent();
surface.destroy();
versionString = versionString.trimmed();
int spaceIndex = versionString.indexOf(QChar(QChar::Space));
if (spaceIndex != -1)
{
versionString = versionString.left(spaceIndex);
}
info.vendor = vendorString;
info.renderer = rendererString;
info.version = versionString;
QStringList versionStrSplitted = versionString.split('.', Qt::KeepEmptyParts);
if (versionStrSplitted.size() >= 2)
{
info.majorOpenGLVersion = versionStrSplitted[0].toInt();
info.minorOpenGLVersion = versionStrSplitted[1].toInt();
}
#endif
return info;
};
return s_info.get(getInfo);
}
bool PDFRendererInfo::isHardwareAccelerationSupported()
{
#ifdef PDF4QT_ENABLE_OPENGL
const Info& info = getHardwareAccelerationSupportedInfo();
return std::make_pair(info.majorOpenGLVersion, info.minorOpenGLVersion) >= std::make_pair(REQUIRED_OPENGL_MAJOR_VERSION, REQUIRED_OPENGL_MINOR_VERSION);
#else
return false;
#endif
}
} // namespace pdf } // namespace pdf

View File

@ -28,13 +28,9 @@
#include <QMutex> #include <QMutex>
#include <QSemaphore> #include <QSemaphore>
#include <QImageWriter> #include <QImageWriter>
#include <QSurfaceFormat>
#include <QImage> #include <QImage>
class QPainter; class QPainter;
class QOpenGLContext;
class QOffscreenSurface;
class QOpenGLFramebufferObject;
namespace pdf namespace pdf
{ {
@ -46,30 +42,6 @@ class PDFPrecompiledPage;
class PDFAnnotationManager; class PDFAnnotationManager;
class PDFOptionalContentActivity; class PDFOptionalContentActivity;
class PDF4QTLIBCORESHARED_EXPORT PDFRendererInfo
{
public:
PDFRendererInfo() = delete;
struct Info
{
QString vendor;
QString renderer;
QString version;
int majorOpenGLVersion = 0;
int minorOpenGLVersion = 0;
};
static const Info& getHardwareAccelerationSupportedInfo();
static bool isHardwareAccelerationSupported();
static constexpr int REQUIRED_OPENGL_MAJOR_VERSION = 3;
static constexpr int REQUIRED_OPENGL_MINOR_VERSION = 2;
private:
static PDFCachedItem<Info> s_info;
};
/// Renders the PDF page on the painter, or onto an image. /// Renders the PDF page on the painter, or onto an image.
class PDF4QTLIBCORESHARED_EXPORT PDFRenderer class PDF4QTLIBCORESHARED_EXPORT PDFRenderer
{ {
@ -165,9 +137,7 @@ private:
PDFMeshQualitySettings m_meshQualitySettings; PDFMeshQualitySettings m_meshQualitySettings;
}; };
/// Renders PDF pages to bitmap images (QImage). It can use OpenGL for painting, /// Renders PDF pages to bitmap images (QImage).
/// if it is enabled, if this is the case, offscreen rendering to framebuffer
/// is used.
/// \note Construct this object only in main GUI thread /// \note Construct this object only in main GUI thread
class PDF4QTLIBCORESHARED_EXPORT PDFRasterizer : public QObject class PDF4QTLIBCORESHARED_EXPORT PDFRasterizer : public QObject
{ {
@ -180,22 +150,9 @@ public:
explicit PDFRasterizer(QObject* parent); explicit PDFRasterizer(QObject* parent);
virtual ~PDFRasterizer() override; virtual ~PDFRasterizer() override;
/// Resets the renderer. This function must be called from main GUI thread, /// Resets the renderer.
/// it cannot be called from deferred threads, because it can create hidden /// \param rendererEngine Renderer engine type
/// window (offscreen surface). If hardware renderer is required, and void reset(RendererEngine rendererEngine);
/// none is available, then software renderer is used.
/// \param useOpenGL Use OpenGL for rendering (ignored if not available)
/// \param surfaceFormat Surface format to render
void reset(bool useOpenGL, const QSurfaceFormat& surfaceFormat);
enum Feature
{
UseOpenGL = 0x0001, ///< Use OpenGL for rendering
ValidOpenGL = 0x0002, ///< OpenGL is initialized and valid
FailedOpenGL = 0x0004, ///< OpenGL creation has failed
};
Q_DECLARE_FLAGS(Features, Feature)
/// Renders page to the image of given size. If some error occurs, then /// Renders page to the image of given size. If some error occurs, then
/// empty image is returned. Warning: this function can modify this object, /// empty image is returned. Warning: this function can modify this object,
@ -217,18 +174,7 @@ public:
PageRotation extraRotation); PageRotation extraRotation);
private: private:
#ifdef PDF4QT_ENABLE_OPENGL RendererEngine m_rendererEngine;
void initializeOpenGL();
void releaseOpenGL();
#endif
Features m_features;
#ifdef PDF4QT_ENABLE_OPENGL
QSurfaceFormat m_surfaceFormat;
QOffscreenSurface* m_surface;
QOpenGLContext* m_context;
QOpenGLFramebufferObject* m_fbo;
#endif
}; };
/// Simple structure for storing rendered page images /// Simple structure for storing rendered page images
@ -267,8 +213,7 @@ public:
/// \param features Renderer features /// \param features Renderer features
/// \param meshQualitySettings Mesh quality settings /// \param meshQualitySettings Mesh quality settings
/// \param rasterizerCount Number of rasterizers /// \param rasterizerCount Number of rasterizers
/// \param useOpenGL Use OpenGL for rendering? /// \param rendererEngine Renderer engine
/// \param surfaceFormat Surface format
/// \param parent Parent object /// \param parent Parent object
explicit PDFRasterizerPool(const PDFDocument* document, explicit PDFRasterizerPool(const PDFDocument* document,
PDFFontCache* fontCache, PDFFontCache* fontCache,
@ -277,8 +222,7 @@ public:
PDFRenderer::Features features, PDFRenderer::Features features,
const PDFMeshQualitySettings& meshQualitySettings, const PDFMeshQualitySettings& meshQualitySettings,
int rasterizerCount, int rasterizerCount,
bool useOpenGL, RendererEngine rendererEngine,
const QSurfaceFormat& surfaceFormat,
QObject* parent); QObject* parent);
/// Acquire rasterizer. This function is thread safe. /// Acquire rasterizer. This function is thread safe.

View File

@ -17,6 +17,7 @@
#include "pdfutils.h" #include "pdfutils.h"
#include "pdfexception.h" #include "pdfexception.h"
#include "pdfblpainter.h"
#include <QtGlobal> #include <QtGlobal>
#include <QtMath> #include <QtMath>
@ -315,6 +316,18 @@ std::vector<PDFDependentLibraryInfo> PDFDependentLibraryInfo::getLibraryInfo()
zlibInfo.url = tr("https://zlib.net/"); zlibInfo.url = tr("https://zlib.net/");
result.emplace_back(qMove(zlibInfo)); result.emplace_back(qMove(zlibInfo));
// blend2d
const uint32_t blend2dVersion = PDFBLPaintDevice::getVersion();
const int blend2dMajor = (blend2dVersion >> 16) & 0xFF;
const int blend2dMinor = (blend2dVersion >> 8) & 0xFF;
const int blend2dPatch = (blend2dVersion) & 0xFF;
PDFDependentLibraryInfo blend2dInfo;
blend2dInfo.library = tr("Blend2D");
blend2dInfo.license = tr("zlib specific");
blend2dInfo.version = QString("%1.%2.%3").arg(blend2dMajor).arg(blend2dMinor).arg(blend2dPatch);
blend2dInfo.url = tr("https://blend2d.com/");
result.emplace_back(qMove(blend2dInfo));
return result; return result;
} }

View File

@ -74,10 +74,6 @@ GENERATE_EXPORT_HEADER(Pdf4QtLibWidgets
PDF4QTLIBWIDGETSSHARED_EXPORT PDF4QTLIBWIDGETSSHARED_EXPORT
EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/pdf4qtlibwidgets_export.h") EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/pdf4qtlibwidgets_export.h")
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(Pdf4QtLibWidgets PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(Pdf4QtLibWidgets PRIVATE Pdf4QtLibCore Qt6::Core Qt6::Gui Qt6::Xml Qt6::Svg Qt6::Widgets) target_link_libraries(Pdf4QtLibWidgets PRIVATE Pdf4QtLibCore Qt6::Core Qt6::Gui Qt6::Xml Qt6::Svg Qt6::Widgets)
if(LINUX_GCC) if(LINUX_GCC)
@ -88,6 +84,8 @@ if(MINGW)
target_link_libraries(Pdf4QtLibWidgets PRIVATE Secur32 Mscms Gdi32 User32 crypt32) target_link_libraries(Pdf4QtLibWidgets PRIVATE Secur32 Mscms Gdi32 User32 crypt32)
endif() endif()
target_link_libraries(Pdf4QtLibWidgets PRIVATE blend2d::blend2d)
target_include_directories(Pdf4QtLibWidgets INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/sources) target_include_directories(Pdf4QtLibWidgets INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/sources)
target_include_directories(Pdf4QtLibWidgets PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}) target_include_directories(Pdf4QtLibWidgets PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR})

View File

@ -24,6 +24,7 @@
#include "pdfannotation.h" #include "pdfannotation.h"
#include "pdfdrawwidget.h" #include "pdfdrawwidget.h"
#include "pdfwidgetannotation.h" #include "pdfwidgetannotation.h"
#include "pdfpainterutils.h"
#include <QTimer> #include <QTimer>
#include <QPainter> #include <QPainter>
@ -469,7 +470,7 @@ PDFDrawWidgetProxy::PDFDrawWidgetProxy(QObject* parent) :
m_rasterizer(new PDFRasterizer(this)), m_rasterizer(new PDFRasterizer(this)),
m_progress(nullptr), m_progress(nullptr),
m_cacheClearTimer(new QTimer(this)), m_cacheClearTimer(new QTimer(this)),
m_useOpenGL(false) m_rendererEngine(RendererEngine::Blend2D_MultiThread)
{ {
m_controller = new PDFDrawSpaceController(this); m_controller = new PDFDrawSpaceController(this);
connect(m_controller, &PDFDrawSpaceController::drawSpaceChanged, this, &PDFDrawWidgetProxy::update); connect(m_controller, &PDFDrawSpaceController::drawSpaceChanged, this, &PDFDrawWidgetProxy::update);
@ -1403,11 +1404,10 @@ bool PDFDrawWidgetProxy::isBlockMode() const
return false; return false;
} }
void PDFDrawWidgetProxy::updateRenderer(bool useOpenGL, const QSurfaceFormat& surfaceFormat) void PDFDrawWidgetProxy::updateRenderer(RendererEngine rendererEngine)
{ {
m_useOpenGL = useOpenGL; m_rendererEngine = rendererEngine;
m_surfaceFormat = surfaceFormat; m_rasterizer->reset(m_rendererEngine);
m_rasterizer->reset(useOpenGL && ENABLE_OPENGL_FOR_THUMBNAILS, surfaceFormat);
} }
void PDFDrawWidgetProxy::prefetchPages(PDFInteger pageIndex) void PDFDrawWidgetProxy::prefetchPages(PDFInteger pageIndex)

View File

@ -317,9 +317,8 @@ public:
/// Updates renderer (in current implementation, renderer for page thumbnails) /// Updates renderer (in current implementation, renderer for page thumbnails)
/// using given parameters. /// using given parameters.
/// \param useOpenGL Use OpenGL for rendering? /// \param rendererEngine Renderer engine
/// \param surfaceFormat Surface format for OpenGL rendering void updateRenderer(RendererEngine rendererEngine);
void updateRenderer(bool useOpenGL, const QSurfaceFormat& surfaceFormat);
/// Prefetches (prerenders) pages after page with pageIndex, i.e., prepares /// Prefetches (prerenders) pages after page with pageIndex, i.e., prepares
/// for non-flickering scroll operation. /// for non-flickering scroll operation.
@ -338,8 +337,7 @@ public:
void setProgress(PDFProgress* progress) { m_progress = progress; } void setProgress(PDFProgress* progress) { m_progress = progress; }
PDFAsynchronousTextLayoutCompiler* getTextLayoutCompiler() const { return m_textLayoutCompiler; } PDFAsynchronousTextLayoutCompiler* getTextLayoutCompiler() const { return m_textLayoutCompiler; }
PDFWidget* getWidget() const { return m_widget; } PDFWidget* getWidget() const { return m_widget; }
bool isUsingOpenGL() const { return m_useOpenGL; } RendererEngine getRendererEngine() const { return m_rendererEngine; }
const QSurfaceFormat& getSurfaceFormat() const { return m_surfaceFormat; }
PageRotation getPageRotation() const { return m_controller->getPageRotation(); } PageRotation getPageRotation() const { return m_controller->getPageRotation(); }
void setFeatures(PDFRenderer::Features features); void setFeatures(PDFRenderer::Features features);
@ -461,8 +459,6 @@ private:
constexpr inline T bound(T value) { return qBound(min, value, max); } constexpr inline T bound(T value) { return qBound(min, value, max); }
}; };
static constexpr bool ENABLE_OPENGL_FOR_THUMBNAILS = false;
/// Flag, disables the update /// Flag, disables the update
bool m_updateDisabled; bool m_updateDisabled;
@ -536,11 +532,8 @@ private:
/// Additional drawing interfaces /// Additional drawing interfaces
std::set<IDocumentDrawInterface*> m_drawInterfaces; std::set<IDocumentDrawInterface*> m_drawInterfaces;
/// Use OpenGL for rendering? /// Renderer engine
bool m_useOpenGL; RendererEngine m_rendererEngine;
/// Surface format for OpenGL
QSurfaceFormat m_surfaceFormat;
/// Page group info for rendering. Group of pages /// Page group info for rendering. Group of pages
/// can be rendered with transparency or without paper /// can be rendered with transparency or without paper

View File

@ -22,6 +22,7 @@
#include "pdfannotation.h" #include "pdfannotation.h"
#include "pdfwidgetannotation.h" #include "pdfwidgetannotation.h"
#include "pdfwidgetformmanager.h" #include "pdfwidgetformmanager.h"
#include "pdfblpainter.h"
#include <QPainter> #include <QPainter>
#include <QGridLayout> #include <QGridLayout>
@ -35,7 +36,7 @@
namespace pdf namespace pdf
{ {
PDFWidget::PDFWidget(const PDFCMSManager* cmsManager, RendererEngine engine, int samplesCount, QWidget* parent) : PDFWidget::PDFWidget(const PDFCMSManager* cmsManager, RendererEngine engine, QWidget* parent) :
QWidget(parent), QWidget(parent),
m_cmsManager(cmsManager), m_cmsManager(cmsManager),
m_toolManager(nullptr), m_toolManager(nullptr),
@ -44,9 +45,10 @@ PDFWidget::PDFWidget(const PDFCMSManager* cmsManager, RendererEngine engine, int
m_drawWidget(nullptr), m_drawWidget(nullptr),
m_horizontalScrollBar(nullptr), m_horizontalScrollBar(nullptr),
m_verticalScrollBar(nullptr), m_verticalScrollBar(nullptr),
m_proxy(nullptr) m_proxy(nullptr),
m_rendererEngine(engine)
{ {
m_drawWidget = createDrawWidget(getEffectiveRenderer(engine), samplesCount); m_drawWidget = new PDFDrawWidget(this, this);
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this); m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this); m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
@ -62,10 +64,10 @@ PDFWidget::PDFWidget(const PDFCMSManager* cmsManager, RendererEngine engine, int
m_proxy = new PDFDrawWidgetProxy(this); m_proxy = new PDFDrawWidgetProxy(this);
m_proxy->init(this); m_proxy->init(this);
m_proxy->updateRenderer(m_rendererEngine);
connect(m_proxy, &PDFDrawWidgetProxy::renderingError, this, &PDFWidget::onRenderingError); connect(m_proxy, &PDFDrawWidgetProxy::renderingError, this, &PDFWidget::onRenderingError);
connect(m_proxy, &PDFDrawWidgetProxy::repaintNeeded, m_drawWidget->getWidget(), QOverload<>::of(&QWidget::update)); connect(m_proxy, &PDFDrawWidgetProxy::repaintNeeded, m_drawWidget->getWidget(), QOverload<>::of(&QWidget::update));
connect(m_proxy, &PDFDrawWidgetProxy::pageImageChanged, this, &PDFWidget::onPageImageChanged); connect(m_proxy, &PDFDrawWidgetProxy::pageImageChanged, this, &PDFWidget::onPageImageChanged);
updateRendererImpl();
} }
PDFWidget::~PDFWidget() PDFWidget::~PDFWidget()
@ -90,39 +92,10 @@ void PDFWidget::setDocument(const PDFModifiedDocument& document)
m_drawWidget->getWidget()->update(); m_drawWidget->getWidget()->update();
} }
void PDFWidget::updateRenderer(RendererEngine engine, int samplesCount) void PDFWidget::updateRenderer(RendererEngine engine)
{ {
engine = getEffectiveRenderer(engine); m_rendererEngine = engine;
m_proxy->updateRenderer(m_rendererEngine);
PDFOpenGLDrawWidget* openglDrawWidget = qobject_cast<PDFOpenGLDrawWidget*>(m_drawWidget->getWidget());
PDFDrawWidget* softwareDrawWidget = qobject_cast<PDFDrawWidget*>(m_drawWidget->getWidget());
// Do we need to change renderer?
if ((openglDrawWidget && engine != RendererEngine::OpenGL) || (softwareDrawWidget && engine != RendererEngine::Software))
{
QGridLayout* layout = qobject_cast<QGridLayout*>(this->layout());
layout->removeWidget(m_drawWidget->getWidget());
delete m_drawWidget->getWidget();
m_drawWidget = createDrawWidget(engine, samplesCount);
layout->addWidget(m_drawWidget->getWidget(), 0, 0);
setFocusProxy(m_drawWidget->getWidget());
connect(m_proxy, &PDFDrawWidgetProxy::repaintNeeded, m_drawWidget->getWidget(), QOverload<>::of(&QWidget::update));
}
#ifdef PDF4QT_ENABLE_OPENGL
else if (openglDrawWidget)
{
// Just check the samples count
QSurfaceFormat format = openglDrawWidget->format();
if (format.samples() != samplesCount)
{
format.setSamples(samplesCount);
openglDrawWidget->setFormat(format);
}
}
#endif
updateRendererImpl();
} }
void PDFWidget::updateCacheLimits(int compiledPageCacheLimit, int thumbnailsCacheLimit, int fontCacheLimit, int instancedFontCacheLimit) void PDFWidget::updateCacheLimits(int compiledPageCacheLimit, int thumbnailsCacheLimit, int fontCacheLimit, int instancedFontCacheLimit)
@ -142,16 +115,6 @@ int PDFWidget::getPageRenderingErrorCount() const
return count; return count;
} }
void PDFWidget::updateRendererImpl()
{
#ifdef PDF4QT_ENABLE_OPENGL
PDFOpenGLDrawWidget* openglDrawWidget = qobject_cast<PDFOpenGLDrawWidget*>(m_drawWidget->getWidget());
m_proxy->updateRenderer(openglDrawWidget != nullptr, openglDrawWidget ? openglDrawWidget->format() : QSurfaceFormat::defaultFormat());
#else
m_proxy->updateRenderer(false, QSurfaceFormat::defaultFormat());
#endif
}
void PDFWidget::onRenderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors) void PDFWidget::onRenderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors)
{ {
// Empty list of error should not be reported! // Empty list of error should not be reported!
@ -182,29 +145,6 @@ void PDFWidget::onPageImageChanged(bool all, const std::vector<PDFInteger>& page
} }
} }
IDrawWidget* PDFWidget::createDrawWidget(RendererEngine rendererEngine, int samplesCount)
{
switch (rendererEngine)
{
case RendererEngine::Software:
return new PDFDrawWidget(this, this);
case RendererEngine::OpenGL:
#ifdef PDF4QT_ENABLE_OPENGL
return new PDFOpenGLDrawWidget(this, samplesCount, this);
#else
Q_UNUSED(samplesCount);
return new PDFDrawWidget(this, this);
#endif
default:
Q_ASSERT(false);
break;
}
return nullptr;
}
void PDFWidget::removeInputInterface(IDrawWidgetInputInterface* inputInterface) void PDFWidget::removeInputInterface(IDrawWidgetInputInterface* inputInterface)
{ {
auto it = std::find(m_inputInterfaces.begin(), m_inputInterfaces.end(), inputInterface); auto it = std::find(m_inputInterfaces.begin(), m_inputInterfaces.end(), inputInterface);
@ -223,16 +163,6 @@ void PDFWidget::addInputInterface(IDrawWidgetInputInterface* inputInterface)
} }
} }
RendererEngine PDFWidget::getEffectiveRenderer(RendererEngine rendererEngine)
{
if (rendererEngine == RendererEngine::OpenGL && !pdf::PDFRendererInfo::isHardwareAccelerationSupported())
{
return RendererEngine::Software;
}
return rendererEngine;
}
PDFWidgetFormManager* PDFWidget::getFormManager() const PDFWidgetFormManager* PDFWidget::getFormManager() const
{ {
return m_formManager; return m_formManager;
@ -259,43 +189,38 @@ void PDFWidget::setAnnotationManager(PDFWidgetAnnotationManager* annotationManag
addInputInterface(m_annotationManager); addInputInterface(m_annotationManager);
} }
template<typename BaseWidget> PDFDrawWidget::PDFDrawWidget(PDFWidget* widget, QWidget* parent) :
PDFDrawWidgetBase<BaseWidget>::PDFDrawWidgetBase(PDFWidget* widget, QWidget* parent) : BaseClass(parent),
BaseWidget(parent),
m_widget(widget), m_widget(widget),
m_mouseOperation(MouseOperation::None) m_mouseOperation(MouseOperation::None)
{ {
this->setFocusPolicy(Qt::StrongFocus); this->setFocusPolicy(Qt::StrongFocus);
this->setMouseTracking(true); this->setMouseTracking(true);
QObject::connect(&m_autoScrollTimer, &QTimer::timeout, this, &PDFDrawWidgetBase::onAutoScrollTimeout); QObject::connect(&m_autoScrollTimer, &QTimer::timeout, this, &PDFDrawWidget::onAutoScrollTimeout);
} }
template<typename BaseWidget> std::vector<PDFInteger> PDFDrawWidget::getCurrentPages() const
std::vector<PDFInteger> PDFDrawWidgetBase<BaseWidget>::getCurrentPages() const
{ {
return this->m_widget->getDrawWidgetProxy()->getPagesIntersectingRect(this->rect()); return this->m_widget->getDrawWidgetProxy()->getPagesIntersectingRect(this->rect());
} }
template<typename BaseWidget> QSize PDFDrawWidget::minimumSizeHint() const
QSize PDFDrawWidgetBase<BaseWidget>::minimumSizeHint() const
{ {
return QSize(200, 200); return QSize(200, 200);
} }
template<typename BaseWidget> bool PDFDrawWidget::event(QEvent* event)
bool PDFDrawWidgetBase<BaseWidget>::event(QEvent* event)
{ {
if (event->type() == QEvent::ShortcutOverride) if (event->type() == QEvent::ShortcutOverride)
{ {
return processEvent<QKeyEvent, &IDrawWidgetInputInterface::shortcutOverrideEvent>(static_cast<QKeyEvent*>(event)); return processEvent<QKeyEvent, &IDrawWidgetInputInterface::shortcutOverrideEvent>(static_cast<QKeyEvent*>(event));
} }
return BaseWidget::event(event); return BaseClass::event(event);
} }
template<typename BaseWidget> void PDFDrawWidget::performMouseOperation(QPoint currentMousePosition)
void PDFDrawWidgetBase<BaseWidget>::performMouseOperation(QPoint currentMousePosition)
{ {
switch (m_mouseOperation) switch (m_mouseOperation)
{ {
@ -323,9 +248,8 @@ void PDFDrawWidgetBase<BaseWidget>::performMouseOperation(QPoint currentMousePos
} }
} }
template<typename BaseWidget>
template<typename Event, void (IDrawWidgetInputInterface::* Function)(QWidget*, Event*)> template<typename Event, void (IDrawWidgetInputInterface::* Function)(QWidget*, Event*)>
bool PDFDrawWidgetBase<BaseWidget>::processEvent(Event* event) bool PDFDrawWidget::processEvent(Event* event)
{ {
QString tooltip; QString tooltip;
for (IDrawWidgetInputInterface* inputInterface : m_widget->getInputInterfaces()) for (IDrawWidgetInputInterface* inputInterface : m_widget->getInputInterfaces())
@ -351,8 +275,7 @@ bool PDFDrawWidgetBase<BaseWidget>::processEvent(Event* event)
return false; return false;
} }
template<typename BaseWidget> void PDFDrawWidget::keyPressEvent(QKeyEvent* event)
void PDFDrawWidgetBase<BaseWidget>::keyPressEvent(QKeyEvent* event)
{ {
event->ignore(); event->ignore();
@ -388,8 +311,7 @@ void PDFDrawWidgetBase<BaseWidget>::keyPressEvent(QKeyEvent* event)
updateCursor(); updateCursor();
} }
template<typename BaseWidget> void PDFDrawWidget::keyReleaseEvent(QKeyEvent* event)
void PDFDrawWidgetBase<BaseWidget>::keyReleaseEvent(QKeyEvent* event)
{ {
event->ignore(); event->ignore();
@ -401,8 +323,7 @@ void PDFDrawWidgetBase<BaseWidget>::keyReleaseEvent(QKeyEvent* event)
event->accept(); event->accept();
} }
template<typename BaseWidget> void PDFDrawWidget::mousePressEvent(QMouseEvent* event)
void PDFDrawWidgetBase<BaseWidget>::mousePressEvent(QMouseEvent* event)
{ {
event->ignore(); event->ignore();
@ -442,8 +363,7 @@ void PDFDrawWidgetBase<BaseWidget>::mousePressEvent(QMouseEvent* event)
event->accept(); event->accept();
} }
template<typename BaseWidget> void PDFDrawWidget::mouseDoubleClickEvent(QMouseEvent* event)
void PDFDrawWidgetBase<BaseWidget>::mouseDoubleClickEvent(QMouseEvent* event)
{ {
event->ignore(); event->ignore();
@ -453,8 +373,7 @@ void PDFDrawWidgetBase<BaseWidget>::mouseDoubleClickEvent(QMouseEvent* event)
} }
} }
template<typename BaseWidget> void PDFDrawWidget::mouseReleaseEvent(QMouseEvent* event)
void PDFDrawWidgetBase<BaseWidget>::mouseReleaseEvent(QMouseEvent* event)
{ {
event->ignore(); event->ignore();
@ -491,8 +410,7 @@ void PDFDrawWidgetBase<BaseWidget>::mouseReleaseEvent(QMouseEvent* event)
event->accept(); event->accept();
} }
template<typename BaseWidget> void PDFDrawWidget::mouseMoveEvent(QMouseEvent* event)
void PDFDrawWidgetBase<BaseWidget>::mouseMoveEvent(QMouseEvent* event)
{ {
event->ignore(); event->ignore();
@ -506,8 +424,7 @@ void PDFDrawWidgetBase<BaseWidget>::mouseMoveEvent(QMouseEvent* event)
event->accept(); event->accept();
} }
template<typename BaseWidget> void PDFDrawWidget::updateCursor()
void PDFDrawWidgetBase<BaseWidget>::updateCursor()
{ {
std::optional<QCursor> cursor; std::optional<QCursor> cursor;
@ -554,8 +471,7 @@ void PDFDrawWidgetBase<BaseWidget>::updateCursor()
} }
} }
template<typename BaseWidget> void PDFDrawWidget::onAutoScrollTimeout()
void PDFDrawWidgetBase<BaseWidget>::onAutoScrollTimeout()
{ {
if (m_mouseOperation != MouseOperation::AutoScroll) if (m_mouseOperation != MouseOperation::AutoScroll)
{ {
@ -579,8 +495,7 @@ void PDFDrawWidgetBase<BaseWidget>::onAutoScrollTimeout()
proxy->scrollByPixels(QPoint(scrollX, scrollY)); proxy->scrollByPixels(QPoint(scrollX, scrollY));
} }
template<typename BaseWidget> void PDFDrawWidget::wheelEvent(QWheelEvent* event)
void PDFDrawWidgetBase<BaseWidget>::wheelEvent(QWheelEvent* event)
{ {
event->ignore(); event->ignore();
@ -659,62 +574,59 @@ void PDFDrawWidgetBase<BaseWidget>::wheelEvent(QWheelEvent* event)
event->accept(); event->accept();
} }
#ifdef PDF4QT_ENABLE_OPENGL
PDFOpenGLDrawWidget::PDFOpenGLDrawWidget(PDFWidget* widget, int samplesCount, QWidget* parent) :
BaseClass(widget, parent)
{
QSurfaceFormat format = this->format();
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSamples(samplesCount);
format.setColorSpace(QColorSpace(QColorSpace::SRgb));
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
setFormat(format);
}
PDFOpenGLDrawWidget::~PDFOpenGLDrawWidget()
{
}
void PDFOpenGLDrawWidget::resizeGL(int w, int h)
{
QOpenGLWidget::resizeGL(w, h);
getPDFWidget()->getDrawWidgetProxy()->update();
}
void PDFOpenGLDrawWidget::initializeGL()
{
QOpenGLWidget::initializeGL();
}
void PDFOpenGLDrawWidget::paintGL()
{
if (this->isValid())
{
QPainter painter(this);
getPDFWidget()->getDrawWidgetProxy()->draw(&painter, this->rect());
}
}
#endif
PDFDrawWidget::PDFDrawWidget(PDFWidget* widget, QWidget* parent) :
BaseClass(widget, parent)
{
}
PDFDrawWidget::~PDFDrawWidget()
{
}
void PDFDrawWidget::paintEvent(QPaintEvent* event) void PDFDrawWidget::paintEvent(QPaintEvent* event)
{ {
Q_UNUSED(event); Q_UNUSED(event);
QPainter painter(this); RendererEngine rendererEngine = getPDFWidget()->getDrawWidgetProxy()->getRendererEngine();
getPDFWidget()->getDrawWidgetProxy()->draw(&painter, this->rect()); switch (rendererEngine)
{
case RendererEngine::Blend2D_MultiThread:
case RendererEngine::Blend2D_SingleThread:
{
QRect rect = this->rect();
qreal devicePixelRatio = devicePixelRatioF();
m_blend2DframeBuffer.setDevicePixelRatio(devicePixelRatio);
qreal dpmX = logicalDpiX() / 0.0254;
qreal dpmY = logicalDpiY() / 0.0254;
m_blend2DframeBuffer.setDotsPerMeterX(qCeil(dpmX));
m_blend2DframeBuffer.setDotsPerMeterY(qCeil(dpmY));
QSize requiredSize = rect.size() * devicePixelRatio;
if (m_blend2DframeBuffer.size() != requiredSize)
{
m_blend2DframeBuffer = QImage(requiredSize, QImage::Format_ARGB32_Premultiplied);
}
const bool multithreaded = rendererEngine == RendererEngine::Blend2D_MultiThread;
PDFBLPaintDevice blPaintDevice(m_blend2DframeBuffer, multithreaded);
QPainter blPainter;
if (blPainter.begin(&blPaintDevice))
{
getPDFWidget()->getDrawWidgetProxy()->draw(&blPainter, rect);
blPainter.end();
}
QPainter painter(this);
painter.drawImage(QPoint(0, 0), m_blend2DframeBuffer);
break;
}
case RendererEngine::QPainter:
{
QPainter painter(this);
getPDFWidget()->getDrawWidgetProxy()->draw(&painter, this->rect());
m_blend2DframeBuffer = QImage();
break;
}
default:
Q_ASSERT(false);
break;
}
} }
void PDFDrawWidget::resizeEvent(QResizeEvent* event) void PDFDrawWidget::resizeEvent(QResizeEvent* event)
@ -724,9 +636,4 @@ void PDFDrawWidget::resizeEvent(QResizeEvent* event)
getPDFWidget()->getDrawWidgetProxy()->update(); getPDFWidget()->getDrawWidgetProxy()->update();
} }
#ifdef PDF4QT_ENABLE_OPENGL
template class PDFDrawWidgetBase<QOpenGLWidget>;
#endif
template class PDFDrawWidgetBase<QWidget>;
} // namespace pdf } // namespace pdf

View File

@ -27,10 +27,6 @@
#include <QTimer> #include <QTimer>
#include <QElapsedTimer> #include <QElapsedTimer>
#ifdef PDF4QT_ENABLE_OPENGL
#include <QOpenGLWidget>
#endif
namespace pdf namespace pdf
{ {
class PDFDocument; class PDFDocument;
@ -65,8 +61,7 @@ public:
/// Constructs new PDFWidget. /// Constructs new PDFWidget.
/// \param cmsManager Color management system manager /// \param cmsManager Color management system manager
/// \param engine Rendering engine type /// \param engine Rendering engine type
/// \param samplesCount Samples count for rendering engine MSAA antialiasing explicit PDFWidget(const PDFCMSManager* cmsManager, RendererEngine engine, QWidget* parent);
explicit PDFWidget(const PDFCMSManager* cmsManager, RendererEngine engine, int samplesCount, QWidget* parent);
virtual ~PDFWidget() override; virtual ~PDFWidget() override;
virtual bool focusNextPrevChild(bool next) override; virtual bool focusNextPrevChild(bool next) override;
@ -81,8 +76,7 @@ public:
/// Update rendering engine according the settings /// Update rendering engine according the settings
/// \param engine Engine type /// \param engine Engine type
/// \param samplesCount Samples count for rendering engine MSAA antialiasing void updateRenderer(RendererEngine engine);
void updateRenderer(RendererEngine engine, int samplesCount);
/// Updates cache limits /// Updates cache limits
/// \param compiledPageCacheLimit Compiled page cache limit [bytes] /// \param compiledPageCacheLimit Compiled page cache limit [bytes]
@ -115,14 +109,9 @@ signals:
void pageRenderingErrorsChanged(pdf::PDFInteger pageIndex, int errorsCount); void pageRenderingErrorsChanged(pdf::PDFInteger pageIndex, int errorsCount);
private: private:
RendererEngine getEffectiveRenderer(RendererEngine rendererEngine);
void updateRendererImpl();
void onRenderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors); void onRenderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors);
void onPageImageChanged(bool all, const std::vector<PDFInteger>& pages); void onPageImageChanged(bool all, const std::vector<PDFInteger>& pages);
IDrawWidget* createDrawWidget(RendererEngine rendererEngine, int samplesCount);
const PDFCMSManager* m_cmsManager; const PDFCMSManager* m_cmsManager;
PDFToolManager* m_toolManager; PDFToolManager* m_toolManager;
PDFWidgetAnnotationManager* m_annotationManager; PDFWidgetAnnotationManager* m_annotationManager;
@ -133,14 +122,19 @@ private:
PDFDrawWidgetProxy* m_proxy; PDFDrawWidgetProxy* m_proxy;
PageRenderingErrors m_pageRenderingErrors; PageRenderingErrors m_pageRenderingErrors;
std::vector<IDrawWidgetInputInterface*> m_inputInterfaces; std::vector<IDrawWidgetInputInterface*> m_inputInterfaces;
RendererEngine m_rendererEngine;
}; };
template<typename BaseWidget> class PDFDrawWidget : public QWidget, public IDrawWidget
class PDFDrawWidgetBase : public BaseWidget, public IDrawWidget
{ {
Q_OBJECT
private:
using BaseClass = QWidget;
public: public:
explicit PDFDrawWidgetBase(PDFWidget* widget, QWidget* parent); explicit PDFDrawWidget(PDFWidget* widget, QWidget* parent);
virtual ~PDFDrawWidgetBase() override = default; virtual ~PDFDrawWidget() override = default;
/// Returns page indices, which are currently displayed in the widget /// Returns page indices, which are currently displayed in the widget
virtual std::vector<PDFInteger> getCurrentPages() const override; virtual std::vector<PDFInteger> getCurrentPages() const override;
@ -158,6 +152,8 @@ protected:
virtual void mouseReleaseEvent(QMouseEvent* event) override; virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override; virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void wheelEvent(QWheelEvent* event) override; virtual void wheelEvent(QWheelEvent* event) override;
virtual void paintEvent(QPaintEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
PDFWidget* getPDFWidget() const { return m_widget; } PDFWidget* getPDFWidget() const { return m_widget; }
@ -186,50 +182,9 @@ private:
QTimer m_autoScrollTimer; QTimer m_autoScrollTimer;
QPointF m_autoScrollOffset; QPointF m_autoScrollOffset;
QElapsedTimer m_autoScrollLastElapsedTimer; QElapsedTimer m_autoScrollLastElapsedTimer;
QImage m_blend2DframeBuffer;
}; };
class PDFDrawWidget : public PDFDrawWidgetBase<QWidget>
{
Q_OBJECT
private:
using BaseClass = PDFDrawWidgetBase<QWidget>;
public:
explicit PDFDrawWidget(PDFWidget* widget, QWidget* parent);
virtual ~PDFDrawWidget() override;
protected:
virtual void paintEvent(QPaintEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
};
#ifdef PDF4QT_ENABLE_OPENGL
class PDFOpenGLDrawWidget : public PDFDrawWidgetBase<QOpenGLWidget>
{
Q_OBJECT
private:
using BaseClass = PDFDrawWidgetBase<QOpenGLWidget>;
public:
explicit PDFOpenGLDrawWidget(PDFWidget* widget, int samplesCount, QWidget* parent);
virtual ~PDFOpenGLDrawWidget() override;
protected:
virtual void resizeGL(int w, int h) override;
virtual void initializeGL() override;
virtual void paintGL() override;
};
#else
using PDFOpenGLDrawWidget = PDFDrawWidget;
#endif
#ifdef PDF4QT_ENABLE_OPENGL
extern template class PDFDrawWidgetBase<QOpenGLWidget>;
#endif
extern template class PDFDrawWidgetBase<QWidget>;
} // namespace pdf } // namespace pdf
#endif // PDFDRAWWIDGET_H #endif // PDFDRAWWIDGET_H

View File

@ -1197,7 +1197,7 @@ void PDFMagnifierTool::mouseMoveEvent(QWidget* widget, QMouseEvent* event)
if (m_mousePos != mousePos) if (m_mousePos != mousePos)
{ {
m_mousePos = mousePos; m_mousePos = mousePos;
getProxy()->repaintNeeded(); Q_EMIT getProxy()->repaintNeeded();
} }
} }

View File

@ -86,10 +86,6 @@ GENERATE_EXPORT_HEADER(Pdf4QtViewer
PDF4QTVIEWERLIBSHARED_EXPORT PDF4QTVIEWERLIBSHARED_EXPORT
EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/pdf4qtviewer_export.h") EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/pdf4qtviewer_export.h")
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(Pdf4QtViewer PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(Pdf4QtViewer PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets Qt6::PrintSupport Qt6::TextToSpeech Qt6::Xml Qt6::Svg) target_link_libraries(Pdf4QtViewer PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets Qt6::PrintSupport Qt6::TextToSpeech Qt6::Xml Qt6::Svg)
target_include_directories(Pdf4QtViewer INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(Pdf4QtViewer INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(Pdf4QtViewer PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}) target_include_directories(Pdf4QtViewer PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR})

View File

@ -150,6 +150,7 @@ std::vector<QAction*> PDFActionManager::getRenderingOptionActions() const
RenderOptionTextAntialiasing, RenderOptionTextAntialiasing,
RenderOptionSmoothPictures, RenderOptionSmoothPictures,
RenderOptionIgnoreOptionalContentSettings, RenderOptionIgnoreOptionalContentSettings,
RenderOptionDisplayRenderTimes,
RenderOptionDisplayAnnotations, RenderOptionDisplayAnnotations,
RenderOptionInvertColors, RenderOptionInvertColors,
RenderOptionGrayscale, RenderOptionGrayscale,
@ -157,8 +158,7 @@ std::vector<QAction*> PDFActionManager::getRenderingOptionActions() const
RenderOptionHighContrast, RenderOptionHighContrast,
RenderOptionCustomColors, RenderOptionCustomColors,
RenderOptionShowTextBlocks, RenderOptionShowTextBlocks,
RenderOptionShowTextLines RenderOptionShowTextLines});
});
} }
std::vector<QAction*> PDFActionManager::getActions() const std::vector<QAction*> PDFActionManager::getActions() const
@ -266,6 +266,7 @@ void PDFActionManager::initActions(QSize iconSize, bool initializeStampActions)
setUserData(RenderOptionTextAntialiasing, pdf::PDFRenderer::TextAntialiasing); setUserData(RenderOptionTextAntialiasing, pdf::PDFRenderer::TextAntialiasing);
setUserData(RenderOptionSmoothPictures, pdf::PDFRenderer::SmoothImages); setUserData(RenderOptionSmoothPictures, pdf::PDFRenderer::SmoothImages);
setUserData(RenderOptionIgnoreOptionalContentSettings, pdf::PDFRenderer::IgnoreOptionalContent); setUserData(RenderOptionIgnoreOptionalContentSettings, pdf::PDFRenderer::IgnoreOptionalContent);
setUserData(RenderOptionDisplayRenderTimes, pdf::PDFRenderer::DisplayTimes);
setUserData(RenderOptionDisplayAnnotations, pdf::PDFRenderer::DisplayAnnotations); setUserData(RenderOptionDisplayAnnotations, pdf::PDFRenderer::DisplayAnnotations);
setUserData(RenderOptionInvertColors, pdf::PDFRenderer::ColorAdjust_Invert); setUserData(RenderOptionInvertColors, pdf::PDFRenderer::ColorAdjust_Invert);
setUserData(RenderOptionGrayscale, pdf::PDFRenderer::ColorAdjust_Grayscale); setUserData(RenderOptionGrayscale, pdf::PDFRenderer::ColorAdjust_Grayscale);
@ -624,7 +625,7 @@ void PDFProgramController::initialize(Features features,
readSettings(Settings(GeneralSettings | PluginsSettings | RecentFileSettings | CertificateSettings)); readSettings(Settings(GeneralSettings | PluginsSettings | RecentFileSettings | CertificateSettings));
m_pdfWidget = new pdf::PDFWidget(m_CMSManager, m_settings->getRendererEngine(), m_settings->isMultisampleAntialiasingEnabled() ? m_settings->getRendererSamples() : -1, m_mainWindow); m_pdfWidget = new pdf::PDFWidget(m_CMSManager, m_settings->getRendererEngine(), m_mainWindow);
m_pdfWidget->setObjectName("pdfWidget"); m_pdfWidget->setObjectName("pdfWidget");
m_pdfWidget->updateCacheLimits(m_settings->getCompiledPageCacheLimit() * 1024, m_settings->getThumbnailsCacheLimit(), m_settings->getFontCacheLimit(), m_settings->getInstancedFontCacheLimit()); m_pdfWidget->updateCacheLimits(m_settings->getCompiledPageCacheLimit() * 1024, m_settings->getThumbnailsCacheLimit(), m_settings->getFontCacheLimit(), m_settings->getInstancedFontCacheLimit());
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress); m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
@ -1697,7 +1698,7 @@ void PDFProgramController::updateActionsAvailability()
void PDFProgramController::onViewerSettingsChanged() void PDFProgramController::onViewerSettingsChanged()
{ {
m_pdfWidget->updateRenderer(m_settings->getRendererEngine(), m_settings->isMultisampleAntialiasingEnabled() ? m_settings->getRendererSamples() : -1); m_pdfWidget->updateRenderer(m_settings->getRendererEngine());
m_pdfWidget->updateCacheLimits(m_settings->getCompiledPageCacheLimit() * 1024, m_settings->getThumbnailsCacheLimit(), m_settings->getFontCacheLimit(), m_settings->getInstancedFontCacheLimit()); m_pdfWidget->updateCacheLimits(m_settings->getCompiledPageCacheLimit() * 1024, m_settings->getThumbnailsCacheLimit(), m_settings->getFontCacheLimit(), m_settings->getInstancedFontCacheLimit());
m_pdfWidget->getDrawWidgetProxy()->setFeatures(m_settings->getFeatures()); m_pdfWidget->getDrawWidgetProxy()->setFeatures(m_settings->getFeatures());
m_pdfWidget->getDrawWidgetProxy()->setPreferredMeshResolutionRatio(m_settings->getPreferredMeshResolutionRatio()); m_pdfWidget->getDrawWidgetProxy()->setPreferredMeshResolutionRatio(m_settings->getPreferredMeshResolutionRatio());
@ -2298,24 +2299,6 @@ void PDFProgramController::resetSettings()
} }
} }
void PDFProgramController::checkHardwareOpenGLAvailability()
{
if (m_settings->getRendererEngine() == pdf::RendererEngine::OpenGL &&
!pdf::PDFRendererInfo::isHardwareAccelerationSupported())
{
#ifdef PDF4QT_ENABLE_OPENGL
pdf::PDFRendererInfo::Info info = pdf::PDFRendererInfo::getHardwareAccelerationSupportedInfo();
QMessageBox::warning(m_mainWindow, tr("Warning"),
tr("Hardware acceleration is not supported on this device. "
"OpenGL version at least 3.2 is required. Software rendering is used instead. "
"Available OpenGL is %1 using %2. You can turn off hardware acceleration "
"in 'Tools' menu using 'Options' item to stop displaying this message.").arg(info.version, info.renderer));
#else
QMessageBox::warning(m_mainWindow, tr("Warning"), tr("Hardware acceleration is not enabled in this build."));
#endif
}
}
void PDFProgramController::onActionOptionsTriggered() void PDFProgramController::onActionOptionsTriggered()
{ {
PDFViewerSettingsDialog::OtherSettings otherSettings; PDFViewerSettingsDialog::OtherSettings otherSettings;

View File

@ -161,6 +161,7 @@ public:
RenderOptionTextAntialiasing, RenderOptionTextAntialiasing,
RenderOptionSmoothPictures, RenderOptionSmoothPictures,
RenderOptionIgnoreOptionalContentSettings, RenderOptionIgnoreOptionalContentSettings,
RenderOptionDisplayRenderTimes,
RenderOptionDisplayAnnotations, RenderOptionDisplayAnnotations,
RenderOptionInvertColors, RenderOptionInvertColors,
RenderOptionGrayscale, RenderOptionGrayscale,
@ -297,8 +298,6 @@ public:
void writeSettings(); void writeSettings();
void resetSettings(); void resetSettings();
void checkHardwareOpenGLAvailability();
void performPrint(); void performPrint();
void performSave(); void performSave();
void performSaveAs(); void performSaveAs();

View File

@ -299,7 +299,7 @@ void PDFRenderToImagesDialog::on_buttonBox_clicked(QAbstractButton* button)
m_cms = m_proxy->getCMSManager()->getCurrentCMS(); m_cms = m_proxy->getCMSManager()->getCurrentCMS();
m_rasterizerPool = new pdf::PDFRasterizerPool(m_document, m_proxy->getFontCache(), m_proxy->getCMSManager(), m_rasterizerPool = new pdf::PDFRasterizerPool(m_document, m_proxy->getFontCache(), m_proxy->getCMSManager(),
m_optionalContentActivity, m_proxy->getFeatures(), m_proxy->getMeshQualitySettings(), m_optionalContentActivity, m_proxy->getFeatures(), m_proxy->getMeshQualitySettings(),
pdf::PDFRasterizerPool::getDefaultRasterizerCount(), m_proxy->isUsingOpenGL(), m_proxy->getSurfaceFormat(), this); pdf::PDFRasterizerPool::getDefaultRasterizerCount(), m_proxy->getRendererEngine(), this);
connect(m_rasterizerPool, &pdf::PDFRasterizerPool::renderError, this, &PDFRenderToImagesDialog::onRenderError); connect(m_rasterizerPool, &pdf::PDFRasterizerPool::renderError, this, &PDFRenderToImagesDialog::onRenderError);
auto process = [this]() auto process = [this]()

View File

@ -160,6 +160,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_actionManager->setAction(PDFActionManager::RenderOptionTextAntialiasing, ui->actionRenderOptionTextAntialiasing); m_actionManager->setAction(PDFActionManager::RenderOptionTextAntialiasing, ui->actionRenderOptionTextAntialiasing);
m_actionManager->setAction(PDFActionManager::RenderOptionSmoothPictures, ui->actionRenderOptionSmoothPictures); m_actionManager->setAction(PDFActionManager::RenderOptionSmoothPictures, ui->actionRenderOptionSmoothPictures);
m_actionManager->setAction(PDFActionManager::RenderOptionIgnoreOptionalContentSettings, ui->actionRenderOptionIgnoreOptionalContentSettings); m_actionManager->setAction(PDFActionManager::RenderOptionIgnoreOptionalContentSettings, ui->actionRenderOptionIgnoreOptionalContentSettings);
m_actionManager->setAction(PDFActionManager::RenderOptionDisplayRenderTimes, ui->actionRenderOptionDisplayRenderTimes);
m_actionManager->setAction(PDFActionManager::RenderOptionDisplayAnnotations, ui->actionRenderOptionDisplayAnnotations); m_actionManager->setAction(PDFActionManager::RenderOptionDisplayAnnotations, ui->actionRenderOptionDisplayAnnotations);
m_actionManager->setAction(PDFActionManager::RenderOptionInvertColors, ui->actionColorInvert); m_actionManager->setAction(PDFActionManager::RenderOptionInvertColors, ui->actionColorInvert);
m_actionManager->setAction(PDFActionManager::RenderOptionGrayscale, ui->actionColorGrayscale); m_actionManager->setAction(PDFActionManager::RenderOptionGrayscale, ui->actionColorGrayscale);
@ -543,7 +544,6 @@ void PDFViewerMainWindow::showEvent(QShowEvent* event)
{ {
QMainWindow::showEvent(event); QMainWindow::showEvent(event);
m_progressTaskbarIndicator->setWindow(windowHandle()); m_progressTaskbarIndicator->setWindow(windowHandle());
QTimer::singleShot(0, this, [this] { m_programController->checkHardwareOpenGLAvailability(); });
} }
void PDFViewerMainWindow::dragEnterEvent(QDragEnterEvent* event) void PDFViewerMainWindow::dragEnterEvent(QDragEnterEvent* event)

View File

@ -90,6 +90,7 @@
<addaction name="actionRenderOptionSmoothPictures"/> <addaction name="actionRenderOptionSmoothPictures"/>
<addaction name="actionRenderOptionIgnoreOptionalContentSettings"/> <addaction name="actionRenderOptionIgnoreOptionalContentSettings"/>
<addaction name="actionRenderOptionDisplayAnnotations"/> <addaction name="actionRenderOptionDisplayAnnotations"/>
<addaction name="actionRenderOptionDisplayRenderTimes"/>
</widget> </widget>
<addaction name="menuPage_Layout"/> <addaction name="menuPage_Layout"/>
<addaction name="menuRendering_Options"/> <addaction name="menuRendering_Options"/>
@ -1153,6 +1154,17 @@
<string>If checked, bookmarks for main document chapters are generated automatically.</string> <string>If checked, bookmarks for main document chapters are generated automatically.</string>
</property> </property>
</action> </action>
<action name="actionRenderOptionDisplayRenderTimes">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Display Render Times</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources> <resources>

View File

@ -130,6 +130,7 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) :
m_actionManager->setAction(PDFActionManager::RenderOptionTextAntialiasing, ui->actionRenderOptionTextAntialiasing); m_actionManager->setAction(PDFActionManager::RenderOptionTextAntialiasing, ui->actionRenderOptionTextAntialiasing);
m_actionManager->setAction(PDFActionManager::RenderOptionSmoothPictures, ui->actionRenderOptionSmoothPictures); m_actionManager->setAction(PDFActionManager::RenderOptionSmoothPictures, ui->actionRenderOptionSmoothPictures);
m_actionManager->setAction(PDFActionManager::RenderOptionIgnoreOptionalContentSettings, ui->actionRenderOptionIgnoreOptionalContentSettings); m_actionManager->setAction(PDFActionManager::RenderOptionIgnoreOptionalContentSettings, ui->actionRenderOptionIgnoreOptionalContentSettings);
m_actionManager->setAction(PDFActionManager::RenderOptionDisplayRenderTimes, ui->actionRenderOptionDisplayRenderTimes);
m_actionManager->setAction(PDFActionManager::RenderOptionDisplayAnnotations, ui->actionRenderOptionDisplayAnnotations); m_actionManager->setAction(PDFActionManager::RenderOptionDisplayAnnotations, ui->actionRenderOptionDisplayAnnotations);
m_actionManager->setAction(PDFActionManager::RenderOptionInvertColors, ui->actionColorInvert); m_actionManager->setAction(PDFActionManager::RenderOptionInvertColors, ui->actionColorInvert);
m_actionManager->setAction(PDFActionManager::RenderOptionGrayscale, ui->actionColorGrayscale); m_actionManager->setAction(PDFActionManager::RenderOptionGrayscale, ui->actionColorGrayscale);
@ -432,7 +433,6 @@ void PDFViewerMainWindowLite::showEvent(QShowEvent* event)
{ {
QMainWindow::showEvent(event); QMainWindow::showEvent(event);
m_progressTaskbarIndicator->setWindow(windowHandle()); m_progressTaskbarIndicator->setWindow(windowHandle());
QTimer::singleShot(0, this, [this] { m_programController->checkHardwareOpenGLAvailability(); });
} }
void PDFViewerMainWindowLite::dragEnterEvent(QDragEnterEvent* event) void PDFViewerMainWindowLite::dragEnterEvent(QDragEnterEvent* event)

View File

@ -42,7 +42,7 @@
<property name="title"> <property name="title">
<string>Go To</string> <string>Go To</string>
</property> </property>
<widget class="QMenu" name="menuBookmarkSettings"> <widget class="QMenu" name="menuBookmarkSettings">
<property name="title"> <property name="title">
<string>Bookmark Settings</string> <string>Bookmark Settings</string>
</property> </property>
@ -56,7 +56,6 @@
<addaction name="actionGoToNextPage"/> <addaction name="actionGoToNextPage"/>
<addaction name="actionGoToPreviousLine"/> <addaction name="actionGoToPreviousLine"/>
<addaction name="actionGoToNextLine"/> <addaction name="actionGoToNextLine"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionBookmarkPage"/> <addaction name="actionBookmarkPage"/>
<addaction name="actionGotoPreviousBookmark"/> <addaction name="actionGotoPreviousBookmark"/>
@ -87,6 +86,7 @@
<addaction name="actionRenderOptionSmoothPictures"/> <addaction name="actionRenderOptionSmoothPictures"/>
<addaction name="actionRenderOptionIgnoreOptionalContentSettings"/> <addaction name="actionRenderOptionIgnoreOptionalContentSettings"/>
<addaction name="actionRenderOptionDisplayAnnotations"/> <addaction name="actionRenderOptionDisplayAnnotations"/>
<addaction name="actionRenderOptionDisplayRenderTimes"/>
</widget> </widget>
<addaction name="menuPage_Layout"/> <addaction name="menuPage_Layout"/>
<addaction name="menuRendering_Options"/> <addaction name="menuRendering_Options"/>
@ -368,65 +368,65 @@
</property> </property>
</action> </action>
<action name="actionColorInvert"> <action name="actionColorInvert">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset> <normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Color | Inverted</string> <string>Color | Inverted</string>
</property> </property>
</action> </action>
<action name="actionColorGrayscale"> <action name="actionColorGrayscale">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset> <normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Color | Grayscale</string> <string>Color | Grayscale</string>
</property> </property>
</action> </action>
<action name="actionColorHighContrast"> <action name="actionColorHighContrast">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset> <normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Color | High Contrast</string> <string>Color | High Contrast</string>
</property> </property>
</action> </action>
<action name="actionColorBitonal"> <action name="actionColorBitonal">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset> <normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Color | Monochromatic</string> <string>Color | Monochromatic</string>
</property> </property>
</action> </action>
<action name="actionColorCustom"> <action name="actionColorCustom">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset> <normaloff>:/resources/invert-colors.svg</normaloff>:/resources/invert-colors.svg</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Color | Custom</string> <string>Color | Custom</string>
</property> </property>
</action> </action>
<action name="actionRotateRight"> <action name="actionRotateRight">
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
@ -557,7 +557,6 @@
<string>Become a Sponsor</string> <string>Become a Sponsor</string>
</property> </property>
</action> </action>
<action name="actionBookmarkPage"> <action name="actionBookmarkPage">
<property name="icon"> <property name="icon">
<iconset resource="pdf4qtviewer.qrc"> <iconset resource="pdf4qtviewer.qrc">
@ -651,6 +650,17 @@
<string>If checked, bookmarks for main document chapters are generated automatically.</string> <string>If checked, bookmarks for main document chapters are generated automatically.</string>
</property> </property>
</action> </action>
<action name="actionRenderOptionDisplayRenderTimes">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Display Render Times</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources> <resources>

View File

@ -43,9 +43,7 @@ void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSetti
settings.beginGroup("ViewerSettings"); settings.beginGroup("ViewerSettings");
m_settings.m_directory = settings.value("defaultDirectory", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).toString(); m_settings.m_directory = settings.value("defaultDirectory", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).toString();
m_settings.m_features = static_cast<pdf::PDFRenderer::Features>(settings.value("rendererFeaturesv2", static_cast<int>(pdf::PDFRenderer::getDefaultFeatures())).toInt()); m_settings.m_features = static_cast<pdf::PDFRenderer::Features>(settings.value("rendererFeaturesv2", static_cast<int>(pdf::PDFRenderer::getDefaultFeatures())).toInt());
m_settings.m_rendererEngine = static_cast<pdf::RendererEngine>(settings.value("renderingEngine", static_cast<int>(pdf::RendererEngine::OpenGL)).toInt()); m_settings.m_rendererEngine = static_cast<pdf::RendererEngine>(settings.value("renderingEngine", static_cast<int>(pdf::RendererEngine::Blend2D_MultiThread)).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_prefetchPages = settings.value("prefetchPages", defaultSettings.m_prefetchPages).toBool();
m_settings.m_preferredMeshResolutionRatio = settings.value("preferredMeshResolutionRatio", defaultSettings.m_preferredMeshResolutionRatio).toDouble(); 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_minimalMeshResolutionRatio = settings.value("minimalMeshResolutionRatio", defaultSettings.m_minimalMeshResolutionRatio).toDouble();
@ -119,8 +117,6 @@ void PDFViewerSettings::writeSettings(QSettings& settings)
settings.setValue("defaultDirectory", m_settings.m_directory); settings.setValue("defaultDirectory", m_settings.m_directory);
settings.setValue("rendererFeaturesv2", static_cast<int>(m_settings.m_features)); settings.setValue("rendererFeaturesv2", static_cast<int>(m_settings.m_features));
settings.setValue("renderingEngine", static_cast<int>(m_settings.m_rendererEngine)); 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("prefetchPages", m_settings.m_prefetchPages);
settings.setValue("preferredMeshResolutionRatio", m_settings.m_preferredMeshResolutionRatio); settings.setValue("preferredMeshResolutionRatio", m_settings.m_preferredMeshResolutionRatio);
settings.setValue("minimalMeshResolutionRatio", m_settings.m_minimalMeshResolutionRatio); settings.setValue("minimalMeshResolutionRatio", m_settings.m_minimalMeshResolutionRatio);
@ -228,20 +224,6 @@ void PDFViewerSettings::setRendererEngine(pdf::RendererEngine rendererEngine)
} }
} }
int PDFViewerSettings::getRendererSamples() const
{
return m_settings.m_rendererSamples;
}
void PDFViewerSettings::setRendererSamples(int rendererSamples)
{
if (m_settings.m_rendererSamples != rendererSamples)
{
m_settings.m_rendererSamples = rendererSamples;
Q_EMIT settingsChanged();
}
}
void PDFViewerSettings::setPreferredMeshResolutionRatio(pdf::PDFReal preferredMeshResolutionRatio) void PDFViewerSettings::setPreferredMeshResolutionRatio(pdf::PDFReal preferredMeshResolutionRatio)
{ {
if (m_settings.m_preferredMeshResolutionRatio != preferredMeshResolutionRatio) if (m_settings.m_preferredMeshResolutionRatio != preferredMeshResolutionRatio)
@ -271,9 +253,7 @@ void PDFViewerSettings::setColorTolerance(pdf::PDFReal colorTolerance)
PDFViewerSettings::Settings::Settings() : PDFViewerSettings::Settings::Settings() :
m_features(pdf::PDFRenderer::getDefaultFeatures()), m_features(pdf::PDFRenderer::getDefaultFeatures()),
m_rendererEngine(pdf::RendererEngine::OpenGL), m_rendererEngine(pdf::RendererEngine::Blend2D_MultiThread),
m_multisampleAntialiasing(true),
m_rendererSamples(16),
m_prefetchPages(true), m_prefetchPages(true),
m_preferredMeshResolutionRatio(0.02), m_preferredMeshResolutionRatio(0.02),
m_minimalMeshResolutionRatio(0.005), m_minimalMeshResolutionRatio(0.005),

View File

@ -52,8 +52,6 @@ public:
pdf::PDFRenderer::Features m_features; pdf::PDFRenderer::Features m_features;
QString m_directory; QString m_directory;
pdf::RendererEngine m_rendererEngine; pdf::RendererEngine m_rendererEngine;
bool m_multisampleAntialiasing;
int m_rendererSamples;
bool m_prefetchPages; bool m_prefetchPages;
pdf::PDFReal m_preferredMeshResolutionRatio; pdf::PDFReal m_preferredMeshResolutionRatio;
pdf::PDFReal m_minimalMeshResolutionRatio; pdf::PDFReal m_minimalMeshResolutionRatio;
@ -113,11 +111,7 @@ public:
pdf::RendererEngine getRendererEngine() const; pdf::RendererEngine getRendererEngine() const;
void setRendererEngine(pdf::RendererEngine rendererEngine); void setRendererEngine(pdf::RendererEngine rendererEngine);
int getRendererSamples() const;
void setRendererSamples(int rendererSamples);
bool isPagePrefetchingEnabled() const { return m_settings.m_prefetchPages; } 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; } pdf::PDFReal getPreferredMeshResolutionRatio() const { return m_settings.m_preferredMeshResolutionRatio; }
void setPreferredMeshResolutionRatio(pdf::PDFReal preferredMeshResolutionRatio); void setPreferredMeshResolutionRatio(pdf::PDFReal preferredMeshResolutionRatio);

View File

@ -102,13 +102,9 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
font.setPointSize(font.pointSize() * 1.5); font.setPointSize(font.pointSize() * 1.5);
ui->optionsPagesWidget->setFont(font); ui->optionsPagesWidget->setFont(font);
ui->renderingEngineComboBox->addItem(tr("Software"), static_cast<int>(pdf::RendererEngine::Software)); ui->renderingEngineComboBox->addItem(tr("Software | QPainter"), static_cast<int>(pdf::RendererEngine::QPainter));
ui->renderingEngineComboBox->addItem(tr("Hardware accelerated (OpenGL)"), static_cast<int>(pdf::RendererEngine::OpenGL)); ui->renderingEngineComboBox->addItem(tr("Software | Blend2D | Parallel"), static_cast<int>(pdf::RendererEngine::Blend2D_MultiThread));
ui->renderingEngineComboBox->addItem(tr("Software | Blend2D | Sequential"), static_cast<int>(pdf::RendererEngine::Blend2D_SingleThread));
for (int i : { 1, 2, 4, 8, 16 })
{
ui->multisampleAntialiasingSamplesCountComboBox->addItem(QString::number(i), i);
}
ui->multithreadingComboBox->addItem(tr("Single thread"), static_cast<int>(pdf::PDFExecutionPolicy::Strategy::SingleThreaded)); ui->multithreadingComboBox->addItem(tr("Single thread"), static_cast<int>(pdf::PDFExecutionPolicy::Strategy::SingleThreaded));
ui->multithreadingComboBox->addItem(tr("Multithreading (load balanced)"), static_cast<int>(pdf::PDFExecutionPolicy::Strategy::PageMultithreaded)); ui->multithreadingComboBox->addItem(tr("Multithreading (load balanced)"), static_cast<int>(pdf::PDFExecutionPolicy::Strategy::PageMultithreaded));
@ -279,29 +275,6 @@ void PDFViewerSettingsDialog::loadData()
ui->renderingEngineComboBox->setCurrentIndex(ui->renderingEngineComboBox->findData(static_cast<int>(m_settings.m_rendererEngine))); ui->renderingEngineComboBox->setCurrentIndex(ui->renderingEngineComboBox->findData(static_cast<int>(m_settings.m_rendererEngine)));
// Engine // Engine
if (m_settings.m_rendererEngine == pdf::RendererEngine::OpenGL)
{
ui->multisampleAntialiasingCheckBox->setEnabled(true);
ui->multisampleAntialiasingCheckBox->setChecked(m_settings.m_multisampleAntialiasing);
if (m_settings.m_multisampleAntialiasing)
{
ui->multisampleAntialiasingSamplesCountComboBox->setEnabled(true);
ui->multisampleAntialiasingSamplesCountComboBox->setCurrentIndex(ui->multisampleAntialiasingSamplesCountComboBox->findData(m_settings.m_rendererSamples));
}
else
{
ui->multisampleAntialiasingSamplesCountComboBox->setEnabled(false);
ui->multisampleAntialiasingSamplesCountComboBox->setCurrentIndex(-1);
}
}
else
{
ui->multisampleAntialiasingCheckBox->setEnabled(false);
ui->multisampleAntialiasingCheckBox->setChecked(false);
ui->multisampleAntialiasingSamplesCountComboBox->setEnabled(false);
ui->multisampleAntialiasingSamplesCountComboBox->setCurrentIndex(-1);
}
ui->prefetchPagesCheckBox->setChecked(m_settings.m_prefetchPages); ui->prefetchPagesCheckBox->setChecked(m_settings.m_prefetchPages);
ui->multithreadingComboBox->setCurrentIndex(ui->multithreadingComboBox->findData(static_cast<int>(m_settings.m_multithreadingStrategy))); ui->multithreadingComboBox->setCurrentIndex(ui->multithreadingComboBox->findData(static_cast<int>(m_settings.m_multithreadingStrategy)));
@ -432,14 +405,6 @@ void PDFViewerSettingsDialog::saveData()
{ {
m_settings.m_rendererEngine = static_cast<pdf::RendererEngine>(ui->renderingEngineComboBox->currentData().toInt()); m_settings.m_rendererEngine = static_cast<pdf::RendererEngine>(ui->renderingEngineComboBox->currentData().toInt());
} }
else if (sender == ui->multisampleAntialiasingCheckBox)
{
m_settings.m_multisampleAntialiasing = ui->multisampleAntialiasingCheckBox->isChecked();
}
else if (sender == ui->multisampleAntialiasingSamplesCountComboBox)
{
m_settings.m_rendererSamples = ui->multisampleAntialiasingSamplesCountComboBox->currentData().toInt();
}
else if (sender == ui->prefetchPagesCheckBox) else if (sender == ui->prefetchPagesCheckBox)
{ {
m_settings.m_prefetchPages = ui->prefetchPagesCheckBox->isChecked(); m_settings.m_prefetchPages = ui->prefetchPagesCheckBox->isChecked();

View File

@ -35,7 +35,7 @@
<item> <item>
<widget class="QStackedWidget" name="stackedWidget"> <widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>6</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="enginePage"> <widget class="QWidget" name="enginePage">
<layout class="QVBoxLayout" name="enginePageLayout"> <layout class="QVBoxLayout" name="enginePageLayout">
@ -59,47 +59,16 @@
<layout class="QVBoxLayout" name="engineSettingsGroupBoxLayout"> <layout class="QVBoxLayout" name="engineSettingsGroupBoxLayout">
<item> <item>
<layout class="QGridLayout" name="engineSettingsGridLayout"> <layout class="QGridLayout" name="engineSettingsGridLayout">
<item row="1" column="1"> <item row="2" column="0">
<widget class="QCheckBox" name="multisampleAntialiasingCheckBox"> <widget class="QLabel" name="multithreadingLabel">
<property name="text"> <property name="text">
<string>Enable</string> <string>Multithreading strategy</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="renderingEngineComboBox"/> <widget class="QComboBox" name="renderingEngineComboBox"/>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="multisampleAntialiasingLabel">
<property name="text">
<string>Multisample antialiasing (MSAA)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multisampleAntialiasingSamplesCountComboBox"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="prefetchPagesLabel">
<property name="text">
<string>Prefetch pages</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="multisampleAntiailasingSamplesLabel">
<property name="text">
<string>MSAA Samples count</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="prefetchPagesCheckBox">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="renderingEngineLabel"> <widget class="QLabel" name="renderingEngineLabel">
<property name="text"> <property name="text">
@ -107,22 +76,29 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="1" column="0">
<widget class="QLabel" name="multithreadingLabel"> <widget class="QLabel" name="prefetchPagesLabel">
<property name="text"> <property name="text">
<string>Multithreading strategy</string> <string>Prefetch pages</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="2" column="1">
<widget class="QComboBox" name="multithreadingComboBox"/> <widget class="QComboBox" name="multithreadingComboBox"/>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="prefetchPagesCheckBox">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="engineInfoLabel"> <widget class="QLabel" name="engineInfoLabel">
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Choose a rendering method based on your needs. Although &lt;span style=&quot; font-weight:600;&quot;&gt;Software Rendering&lt;/span&gt; is slower than the hardware-accelerated &lt;span style=&quot; font-weight:600;&quot;&gt;OpenGL Rendering&lt;/span&gt;, it can be utilized when OpenGL is not available on your platform. The default (and recommended) method is OpenGL Rendering. &lt;/p&gt;&lt;p&gt;OpenGL rendering employs &lt;span style=&quot; font-weight:600;&quot;&gt;Multisample Antialiasing (MSAA)&lt;/span&gt;, ensuring high-quality image rendering. You have the option to enable or disable this feature. However, disabling it might lead to inferior image quality. The Samples Count sets the number of samples per pixel used to determine pixel color. It can be set to 1, 2, 4, 8, or 16. Most modern GPUs support at least a value of 8. If your GPU doesn't support the desired sample count, lower this value. &lt;/p&gt;&lt;p&gt;The &lt;span style=&quot; font-weight:600;&quot;&gt;Prefetch Pages&lt;/span&gt; feature pre-renders pages adjacent to the currently viewed pages, minimizing flickering during scrolling. Prefetched pages are stored in the page cache. &lt;/p&gt;&lt;p&gt;The &lt;span style=&quot; font-weight:600;&quot;&gt;Multithreading Strategy&lt;/span&gt; determines how the program will utilize CPU cores. With the &lt;span style=&quot; font-weight:600;&quot;&gt;Single Thread&lt;/span&gt; strategy, only one CPU core is used for rendering a page. This results in longer processing times, but each page is independently compiled/drawn in its own thread. Alternatively, there are two multithreading strategies: Load Balanced and Maximum Threads. Load Balanced only parallelizes pages without processing individual page content. In contrast, the Maximum Threads strategy spawns as many threads as possible for operations to achieve optimal performance. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select a rendering method tailored to your application's requirements. Software Rendering, utilizing QPainter, is a versatile choice that guarantees compatibility across all platforms. It's particularly useful in scenarios where direct access to hardware acceleration isn't crucial. QPainter, part of the Qt framework, excels in rendering 2D graphics with support for various painting styles, image processing, and intricate graphical transformations, making it an excellent tool for applications that require detailed and sophisticated 2D graphics without relying on hardware acceleration.&lt;/p&gt;&lt;p&gt;On the other hand, for applications that demand high-performance rendering, leveraging the Blend2D library offers a compelling alternative. Blend2D is a high-performance 2D vector graphics engine that utilizes multi-threading to accelerate the rendering process. It does not rely on QPainter or hardware acceleration but instead offers a software-based rendering solution optimized for speed and quality. Blend2D's advanced anti-aliasing techniques ensure crisp and clear image quality, making it suitable for applications where rendering performance and image quality are paramount.&lt;/p&gt;&lt;p&gt;The Prefetch Pages feature is a strategy that can be applied regardless of the rendering method chosen. By pre-rendering pages adjacent to the currently viewed content, this approach minimizes flickering and enhances the smoothness of transitions during scrolling, improving the overall user experience.&lt;/p&gt;&lt;p&gt;When it comes to optimizing the rendering process, the choice of multithreading strategy plays a crucial role. A Single Thread strategy, where rendering tasks are executed sequentially on a single CPU core, might be preferable in environments where simplicity and predictability are key. For more demanding applications, employing a Multi-threading strategy can significantly improve rendering times. Strategies like Load Balanced distribute the workload evenly across CPU cores without delving into content-specific processing, offering a good performance boost. The Maximum Threads strategy takes full advantage of available CPU resources by allocating as many threads as possible to the rendering tasks, achieving optimal performance and minimizing rendering times.&lt;/p&gt;&lt;p&gt;This delineation between using QPainter for software rendering and Blend2D for high-performance, multi-threaded rendering allows developers to choose the most appropriate rendering pathway based on their specific performance requirements and the graphical complexity of their application.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>

View File

@ -24,7 +24,6 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true); QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
QApplication application(argc, argv); QApplication application(argc, argv);
QCoreApplication::setOrganizationName("MelkaJ"); QCoreApplication::setOrganizationName("MelkaJ");

View File

@ -23,10 +23,6 @@ add_library(AudioBookPlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(AudioBookPlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(AudioBookPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(AudioBookPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
if(MINGW) if(MINGW)

View File

@ -23,10 +23,6 @@ add_library(DimensionsPlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(DimensionsPlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(DimensionsPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(DimensionsPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(DimensionsPlugin PROPERTIES set_target_properties(DimensionsPlugin PROPERTIES

View File

@ -29,10 +29,6 @@ add_library(ObjectInspectorPlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(ObjectInspectorPlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(ObjectInspectorPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(ObjectInspectorPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(ObjectInspectorPlugin PROPERTIES set_target_properties(ObjectInspectorPlugin PROPERTIES

View File

@ -25,10 +25,6 @@ add_library(OutputPreviewPlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(OutputPreviewPlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(OutputPreviewPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(OutputPreviewPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(OutputPreviewPlugin PROPERTIES set_target_properties(OutputPreviewPlugin PROPERTIES

View File

@ -22,10 +22,6 @@ add_library(RedactPlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(RedactPlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(RedactPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(RedactPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(RedactPlugin PROPERTIES set_target_properties(RedactPlugin PROPERTIES

View File

@ -22,10 +22,6 @@ add_library(SignaturePlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(SignaturePlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(SignaturePlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(SignaturePlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
target_link_libraries(SignaturePlugin PRIVATE OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(SignaturePlugin PRIVATE OpenSSL::SSL OpenSSL::Crypto)

View File

@ -22,10 +22,6 @@ add_library(SoftProofingPlugin SHARED
icons.qrc icons.qrc
) )
if(PDF4QT_ENABLE_OPENGL)
target_link_libraries(SoftProofingPlugin PRIVATE Qt6::OpenGLWidgets)
endif()
target_link_libraries(SoftProofingPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets) target_link_libraries(SoftProofingPlugin PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(SoftProofingPlugin PROPERTIES set_target_properties(SoftProofingPlugin PROPERTIES

View File

@ -30,7 +30,6 @@ int main(int argc, char *argv[])
#endif #endif
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true); QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
QApplication application(argc, argv); QApplication application(argc, argv);
QCoreApplication::setOrganizationName("MelkaJ"); QCoreApplication::setOrganizationName("MelkaJ");

View File

@ -24,7 +24,6 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QGuiApplication a(argc, argv); QGuiApplication a(argc, argv);
QGuiApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
QCoreApplication::setOrganizationName("MelkaJ"); QCoreApplication::setOrganizationName("MelkaJ");
QCoreApplication::setApplicationName("PdfTool"); QCoreApplication::setApplicationName("PdfTool");
QCoreApplication::setApplicationVersion(pdf::PDF_LIBRARY_VERSION); QCoreApplication::setApplicationVersion(pdf::PDF_LIBRARY_VERSION);

View File

@ -847,12 +847,12 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
} }
} }
QString textValue = parser->value("render-hw-accel"); QString textValue = parser->value("render-software");
bool ok = false; bool ok = false;
bool value = textValue.toInt(&ok); bool value = textValue.toInt(&ok);
if (ok) if (ok)
{ {
options.renderUseHardwareRendering = value; options.renderUseSoftwareRendering = value;
} }
else else
{ {

View File

@ -135,7 +135,7 @@ struct PDFToolOptions
// For option 'RenderFlags' // For option 'RenderFlags'
pdf::PDFRenderer::Features renderFeatures = pdf::PDFRenderer::getDefaultFeatures(); pdf::PDFRenderer::Features renderFeatures = pdf::PDFRenderer::getDefaultFeatures();
bool renderUseHardwareRendering = true; bool renderUseSoftwareRendering = true;
bool renderShowPageStatistics = false; bool renderShowPageStatistics = false;
int renderMSAAsamples = 4; int renderMSAAsamples = 4;
int renderRasterizerCount = pdf::PDFRasterizerPool::getDefaultRasterizerCount(); int renderRasterizerCount = pdf::PDFRasterizerPool::getDefaultRasterizerCount();

View File

@ -180,21 +180,11 @@ int PDFToolRenderBase::execute(const PDFToolOptions& options)
fontCache.setDocument(md); fontCache.setDocument(md);
fontCache.setCacheShrinkEnabled(nullptr, false); fontCache.setCacheShrinkEnabled(nullptr, false);
QSurfaceFormat surfaceFormat;
if (options.renderUseHardwareRendering)
{
surfaceFormat = QSurfaceFormat::defaultFormat();
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
surfaceFormat.setSamples(options.renderMSAAsamples);
surfaceFormat.setColorSpace(QColorSpace(QColorSpace::SRgb));
surfaceFormat.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior);
}
m_pageInfo.resize(document.getCatalog()->getPageCount()); m_pageInfo.resize(document.getCatalog()->getPageCount());
pdf::PDFRasterizerPool rasterizerPool(&document, &fontCache, &cmsManager, pdf::PDFRasterizerPool rasterizerPool(&document, &fontCache, &cmsManager,
&optionalContentActivity, options.renderFeatures, meshQualitySettings, &optionalContentActivity, options.renderFeatures, meshQualitySettings,
pdf::PDFRasterizerPool::getCorrectedRasterizerCount(options.renderRasterizerCount), pdf::PDFRasterizerPool::getCorrectedRasterizerCount(options.renderRasterizerCount),
options.renderUseHardwareRendering, surfaceFormat, nullptr); options.renderUseSoftwareRendering ? pdf::RendererEngine::QPainter : pdf::RendererEngine::Blend2D_SingleThread, nullptr);
auto onRenderError = [this](pdf::PDFInteger pageIndex, pdf::PDFRenderError error) auto onRenderError = [this](pdf::PDFInteger pageIndex, pdf::PDFRenderError error)
{ {

View File

@ -1,5 +1,5 @@
{ {
"name": "pdf4qt", "name": "pdf4qt",
"version-string": "1.3.6", "version-string": "1.3.7",
"dependencies": [ "tbb", "openssl", "lcms", "zlib", "openjpeg", "freetype", "ijg-libjpeg", "libpng" ] "dependencies": [ "tbb", "openssl", "lcms", "zlib", "openjpeg", "freetype", "ijg-libjpeg", "libpng", "blend2d" ]
} }