From b09f9eff213ea283226bdc6896c0136cda77a0aa Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sat, 28 Sep 2019 18:26:31 +0200 Subject: [PATCH] Mesh quality settings --- PdfForQtLib/PdfForQtLib.pro | 1 + .../sources/pdfdrawspacecontroller.cpp | 29 ++++- PdfForQtLib/sources/pdfdrawspacecontroller.h | 6 + PdfForQtLib/sources/pdfmeshqualitysettings.h | 75 ++++++++++++ .../sources/pdfpagecontentprocessor.cpp | 14 ++- PdfForQtLib/sources/pdfpagecontentprocessor.h | 7 +- PdfForQtLib/sources/pdfpainter.cpp | 5 +- PdfForQtLib/sources/pdfpainter.h | 4 +- PdfForQtLib/sources/pdfpattern.cpp | 15 +-- PdfForQtLib/sources/pdfpattern.h | 40 +------ PdfForQtLib/sources/pdfrenderer.cpp | 13 ++- PdfForQtLib/sources/pdfrenderer.h | 4 +- PdfForQtViewer/pdfviewermainwindow.cpp | 3 + PdfForQtViewer/pdfviewersettings.cpp | 39 ++++++- PdfForQtViewer/pdfviewersettings.h | 17 ++- PdfForQtViewer/pdfviewersettingsdialog.cpp | 24 ++++ PdfForQtViewer/pdfviewersettingsdialog.ui | 107 ++++++++++++++++++ 17 files changed, 335 insertions(+), 68 deletions(-) create mode 100644 PdfForQtLib/sources/pdfmeshqualitysettings.h diff --git a/PdfForQtLib/PdfForQtLib.pro b/PdfForQtLib/PdfForQtLib.pro index c36b4e0..073b377 100644 --- a/PdfForQtLib/PdfForQtLib.pro +++ b/PdfForQtLib/PdfForQtLib.pro @@ -65,6 +65,7 @@ SOURCES += \ HEADERS += \ sources/pdfitemmodels.h \ + sources/pdfmeshqualitysettings.h \ sources/pdfobject.h \ sources/pdfoptionalcontent.h \ sources/pdfparser.h \ diff --git a/PdfForQtLib/sources/pdfdrawspacecontroller.cpp b/PdfForQtLib/sources/pdfdrawspacecontroller.cpp index 63eb9d1..aa67b70 100644 --- a/PdfForQtLib/sources/pdfdrawspacecontroller.cpp +++ b/PdfForQtLib/sources/pdfdrawspacecontroller.cpp @@ -552,7 +552,7 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect) // Clear the page space by white color painter->fillRect(placedRect, Qt::white); - PDFRenderer renderer(m_controller->getDocument(), m_controller->getFontCache(), m_controller->getOptionalContentActivity(), m_features); + PDFRenderer renderer(m_controller->getDocument(), m_controller->getFontCache(), m_controller->getOptionalContentActivity(), m_features, m_meshQualitySettings); QList errors = renderer.render(painter, placedRect, item.pageIndex); if (!errors.empty()) @@ -827,4 +827,31 @@ void PDFDrawWidgetProxy::setFeatures(PDFRenderer::Features features) } } +void PDFDrawWidgetProxy::setPreferredMeshResolutionRatio(PDFReal ratio) +{ + if (m_meshQualitySettings.preferredMeshResolutionRatio != ratio) + { + m_meshQualitySettings.preferredMeshResolutionRatio = ratio; + emit repaintNeeded(); + } +} + +void PDFDrawWidgetProxy::setMinimalMeshResolutionRatio(PDFReal ratio) +{ + if (m_meshQualitySettings.minimalMeshResolutionRatio != ratio) + { + m_meshQualitySettings.minimalMeshResolutionRatio = ratio; + emit repaintNeeded(); + } +} + +void PDFDrawWidgetProxy::setColorTolerance(PDFReal colorTolerance) +{ + if (m_meshQualitySettings.tolerance != colorTolerance) + { + m_meshQualitySettings.tolerance = colorTolerance; + emit repaintNeeded(); + } +} + } // namespace pdf diff --git a/PdfForQtLib/sources/pdfdrawspacecontroller.h b/PdfForQtLib/sources/pdfdrawspacecontroller.h index 32b1d71..06009bd 100644 --- a/PdfForQtLib/sources/pdfdrawspacecontroller.h +++ b/PdfForQtLib/sources/pdfdrawspacecontroller.h @@ -215,6 +215,9 @@ public: PDFRenderer::Features getFeatures() const; void setFeatures(PDFRenderer::Features features); + void setPreferredMeshResolutionRatio(PDFReal ratio); + void setMinimalMeshResolutionRatio(PDFReal ratio); + void setColorTolerance(PDFReal colorTolerance); signals: void drawSpaceChanged(); @@ -332,6 +335,9 @@ private: /// Renderer features PDFRenderer::Features m_features; + + /// Mesh quality settings + PDFMeshQualitySettings m_meshQualitySettings; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdfmeshqualitysettings.h b/PdfForQtLib/sources/pdfmeshqualitysettings.h new file mode 100644 index 0000000..31b4eba --- /dev/null +++ b/PdfForQtLib/sources/pdfmeshqualitysettings.h @@ -0,0 +1,75 @@ +// Copyright (C) 2019 Jakub Melka +// +// This file is part of PdfForQt. +// +// PdfForQt 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 +// (at your option) any later version. +// +// PdfForQt 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 PDFForQt. If not, see . + +#ifndef PDFMESHQUALITYSETTINGS_H +#define PDFMESHQUALITYSETTINGS_H + +#include "pdfglobal.h" + +#include + +namespace pdf +{ + +struct PDFMeshQualitySettings +{ + /// Initializes default resolution + void initResolution(); + + /// Value used to compute minimal pxiel size resolution (it is multiplied by whole shading area size) + PDFReal minimalMeshResolutionRatio = 0.005; + + /// Value used to compute pixel size resolution (it is multiplied by whole shading area size) + PDFReal preferredMeshResolutionRatio = 0.02; + + /// Matrix, which transforms user space points (user space is target space of the shading) + /// to the device space of the paint device. + QMatrix userSpaceToDeviceSpaceMatrix; + + /// Rectangle in device space coordinate system, onto which is area meshed. + QRectF deviceSpaceMeshingArea; + + /// Preferred mesh resolution in device space pixels. Mesh will be created in this + /// resolution, if it is smooth enough (no jumps in colors occurs). + PDFReal preferredMeshResolution = 1.0; + + /// Minimal mesh resolution in device space pixels. If jumps in colors occurs (jump + /// is two colors, that differ more than \p color tolerance), then mesh is meshed to + /// minimal mesh resolution. + PDFReal minimalMeshResolution = 1.0; + + /// Color tolerance - 1% by default + PDFReal tolerance = 0.01; + + /// Test points to determine maximal curvature of the tensor product patch meshes + PDFInteger patchTestPoints = 64; + + /// Lower value of the surface curvature meshing resolution mapping. When ratio between + /// current curvature at the center of meshed triangle and maximal curvature is below + /// this value, then prefered mesh resolution is used. If ratio is higher than this value + /// and lower than \p patchResolutionMappingRatioHigh, then target length is linearly mapped. + /// If value is higher, than \p patchResolutionMappingRatioHigh, then minimal mesh resolution + /// is used when generating triangles on the patch. + PDFReal patchResolutionMappingRatioLow = 0.3; + + /// Highter value of the surface curvature meshing resolution mapping. \sa patchResolutionMappingRatioLow + PDFReal patchResolutionMappingRatioHigh = 0.9; +}; + +} // namespace pdf + +#endif // PDFMESHQUALITYSETTINGS_H diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp index 7951775..e2d2e17 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp @@ -184,7 +184,8 @@ PDFPageContentProcessor::PDFPageContentProcessor(const PDFPage* page, const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, - QMatrix pagePointToDevicePointMatrix) : + QMatrix pagePointToDevicePointMatrix, + const PDFMeshQualitySettings& meshQualitySettings) : m_page(page), m_document(document), m_fontCache(fontCache), @@ -201,7 +202,8 @@ PDFPageContentProcessor::PDFPageContentProcessor(const PDFPage* page, m_drawingUncoloredTilingPatternState(0), m_isWarningColorOperatorsInUncoloredTilingPatternReported(false), m_patternBaseMatrix(pagePointToDevicePointMatrix), - m_pagePointToDevicePointMatrix(pagePointToDevicePointMatrix) + m_pagePointToDevicePointMatrix(pagePointToDevicePointMatrix), + m_meshQualitySettings(meshQualitySettings) { Q_ASSERT(page); Q_ASSERT(document); @@ -628,10 +630,10 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool } // We must create a mesh and then draw pattern - PDFMeshQualitySettings settings; + PDFMeshQualitySettings settings = m_meshQualitySettings; settings.deviceSpaceMeshingArea = getPageBoundingRectDeviceSpace(); settings.userSpaceToDeviceSpaceMatrix = getPatternBaseMatrix(); - settings.initDefaultResolution(); + settings.initResolution(); PDFMesh mesh = shadingPattern->createMesh(settings); @@ -717,10 +719,10 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool } // We must create a mesh and then draw pattern - PDFMeshQualitySettings settings; + PDFMeshQualitySettings settings = m_meshQualitySettings; settings.deviceSpaceMeshingArea = getPageBoundingRectDeviceSpace(); settings.userSpaceToDeviceSpaceMatrix = getPatternBaseMatrix(); - settings.initDefaultResolution(); + settings.initResolution(); PDFMesh mesh = shadingPattern->createMesh(settings); diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.h b/PdfForQtLib/sources/pdfpagecontentprocessor.h index 1e0ac7b..352bcdb 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.h +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.h @@ -23,6 +23,7 @@ #include "pdfparser.h" #include "pdffont.h" #include "pdfutils.h" +#include "pdfmeshqualitysettings.h" #include #include @@ -48,7 +49,8 @@ public: const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, - QMatrix pagePointToDevicePointMatrix); + QMatrix pagePointToDevicePointMatrix, + const PDFMeshQualitySettings& meshQualitySettings); virtual ~PDFPageContentProcessor(); enum class Operator @@ -814,6 +816,9 @@ private: /// Bounding rectangle of pages media box in device space coordinates. If drawing rotation /// is zero, then it corresponds to the scaled media box of the page. QRectF m_pageBoundingRectDeviceSpace; + + /// Mesh quality settings + PDFMeshQualitySettings m_meshQualitySettings; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdfpainter.cpp b/PdfForQtLib/sources/pdfpainter.cpp index 08c280e..72aa8fa 100644 --- a/PdfForQtLib/sources/pdfpainter.cpp +++ b/PdfForQtLib/sources/pdfpainter.cpp @@ -29,8 +29,9 @@ PDFPainter::PDFPainter(QPainter* painter, const PDFPage* page, const PDFDocument* document, const PDFFontCache* fontCache, - const PDFOptionalContentActivity* optionalContentActivity) : - PDFPageContentProcessor(page, document, fontCache, optionalContentActivity, pagePointToDevicePointMatrix), + const PDFOptionalContentActivity* optionalContentActivity, + const PDFMeshQualitySettings& meshQualitySettings) : + PDFPageContentProcessor(page, document, fontCache, optionalContentActivity, pagePointToDevicePointMatrix, meshQualitySettings), m_painter(painter), m_features(features) { diff --git a/PdfForQtLib/sources/pdfpainter.h b/PdfForQtLib/sources/pdfpainter.h index 565bf94..ca0141b 100644 --- a/PdfForQtLib/sources/pdfpainter.h +++ b/PdfForQtLib/sources/pdfpainter.h @@ -41,13 +41,15 @@ public: /// \param document Document owning the page /// \param fontCache Font cache /// \param optionalContentActivity Activity of optional content + /// \param meshQualitySettings Mesh quality settings explicit PDFPainter(QPainter* painter, PDFRenderer::Features features, QMatrix pagePointToDevicePointMatrix, const PDFPage* page, const PDFDocument* document, const PDFFontCache* fontCache, - const PDFOptionalContentActivity* optionalContentActivity); + const PDFOptionalContentActivity* optionalContentActivity, + const PDFMeshQualitySettings& meshQualitySettings); virtual ~PDFPainter() override; protected: diff --git a/PdfForQtLib/sources/pdfpattern.cpp b/PdfForQtLib/sources/pdfpattern.cpp index 8951ca7..c04b4c1 100644 --- a/PdfForQtLib/sources/pdfpattern.cpp +++ b/PdfForQtLib/sources/pdfpattern.cpp @@ -903,7 +903,7 @@ PDFMesh PDFAxialShading::createMesh(const PDFMeshQualitySettings& settings) cons { // We will skip this coordinate, if both of meshing criteria have been met: // 1) Color difference is small (lesser than tolerance) - // 2) Distance from previous and next point is less than preffered meshing resolution OR colors are equal + // 2) Distance from previous and next point is less than preferred meshing resolution OR colors are equal if (it != coloredCoordinates.cbegin() && std::next(it) != coloredCoordinates.cend()) { @@ -1083,15 +1083,12 @@ QPointF PDFMesh::getTriangleCenter(const PDFMesh::Triangle& triangle) const return (m_vertices[triangle.v1] + m_vertices[triangle.v2] + m_vertices[triangle.v3]) / 3.0; } -void PDFMeshQualitySettings::initDefaultResolution() +void PDFMeshQualitySettings::initResolution() { - // We will take 0.5% percent of device space meshing area as minimal resolution (it is ~1.5 mm for - // A4 page) and default resolution 4x number of that. - Q_ASSERT(deviceSpaceMeshingArea.isValid()); PDFReal size = qMax(deviceSpaceMeshingArea.width(), deviceSpaceMeshingArea.height()); - minimalMeshResolution = size * 0.005; - preferredMeshResolution = minimalMeshResolution * 4; + minimalMeshResolution = size * minimalMeshResolutionRatio; + preferredMeshResolution = size * qMax(preferredMeshResolutionRatio, minimalMeshResolutionRatio); } ShadingType PDFRadialShading::getShadingType() const @@ -1272,7 +1269,7 @@ PDFMesh PDFRadialShading::createMesh(const PDFMeshQualitySettings& settings) con { // We will skip this coordinate, if both of meshing criteria have been met: // 1) Color difference is small (lesser than tolerance) - // 2) Distance from previous and next point is less than preffered meshing resolution OR colors are equal + // 2) Distance from previous and next point is less than preferred meshing resolution OR colors are equal if (it != coloredCoordinates.cbegin() && std::next(it) != coloredCoordinates.cend()) { @@ -2610,6 +2607,4 @@ PDFMesh PDFCoonsPatchShading::createMesh(const PDFMeshQualitySettings& settings) return mesh; } -// TODO: Implement settings of meshing in the settings dialog - } // namespace pdf diff --git a/PdfForQtLib/sources/pdfpattern.h b/PdfForQtLib/sources/pdfpattern.h index ddf0ae7..699b891 100644 --- a/PdfForQtLib/sources/pdfpattern.h +++ b/PdfForQtLib/sources/pdfpattern.h @@ -21,6 +21,7 @@ #include "pdfobject.h" #include "pdffunction.h" #include "pdfcolorspaces.h" +#include "pdfmeshqualitysettings.h" #include @@ -53,45 +54,6 @@ enum class ShadingType TensorProductPatchMesh = 7 }; -struct PDFMeshQualitySettings -{ - /// Initializes default resolution - void initDefaultResolution(); - - /// Matrix, which transforms user space points (user space is target space of the shading) - /// to the device space of the paint device. - QMatrix userSpaceToDeviceSpaceMatrix; - - /// Rectangle in device space coordinate system, onto which is area meshed. - QRectF deviceSpaceMeshingArea; - - /// Preferred mesh resolution in device space pixels. Mesh will be created in this - /// resolution, if it is smooth enough (no jumps in colors occurs). - PDFReal preferredMeshResolution = 1.0; - - /// Minimal mesh resolution in device space pixels. If jumps in colors occurs (jump - /// is two colors, that differ more than \p color tolerance), then mesh is meshed to - /// minimal mesh resolution. - PDFReal minimalMeshResolution = 1.0; - - /// Color tolerance - 1% by default - PDFReal tolerance = 0.01; - - /// Test points to determine maximal curvature of the tensor product patch meshes - PDFInteger patchTestPoints = 64; - - /// Lower value of the surface curvature meshing resolution mapping. When ratio between - /// current curvature at the center of meshed triangle and maximal curvature is below - /// this value, then prefered mesh resolution is used. If ratio is higher than this value - /// and lower than \p patchResolutionMappingRatioHigh, then target length is linearly mapped. - /// If value is higher, than \p patchResolutionMappingRatioHigh, then minimal mesh resolution - /// is used when generating triangles on the patch. - PDFReal patchResolutionMappingRatioLow = 0.3; - - /// Highter value of the surface curvature meshing resolution mapping. \sa patchResolutionMappingRatioLow - PDFReal patchResolutionMappingRatioHigh = 0.9; -}; - /// Mesh consisting of triangles class PDFMesh { diff --git a/PdfForQtLib/sources/pdfrenderer.cpp b/PdfForQtLib/sources/pdfrenderer.cpp index bea5f34..ff5dcef 100644 --- a/PdfForQtLib/sources/pdfrenderer.cpp +++ b/PdfForQtLib/sources/pdfrenderer.cpp @@ -22,11 +22,16 @@ namespace pdf { -PDFRenderer::PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, Features features) : +PDFRenderer::PDFRenderer(const PDFDocument* document, + const PDFFontCache* fontCache, + const PDFOptionalContentActivity* optionalContentActivity, + Features features, + const PDFMeshQualitySettings& meshQualitySettings) : m_document(document), m_fontCache(fontCache), m_optionalContentActivity(optionalContentActivity), - m_features(features) + m_features(features), + m_meshQualitySettings(meshQualitySettings) { Q_ASSERT(document); } @@ -88,7 +93,7 @@ QList PDFRenderer::render(QPainter* painter, const QRectF& recta } } - PDFPainter processor(painter, m_features, matrix, page, m_document, m_fontCache, m_optionalContentActivity); + PDFPainter processor(painter, m_features, matrix, page, m_document, m_fontCache, m_optionalContentActivity, m_meshQualitySettings); return processor.processContents(); } @@ -106,7 +111,7 @@ QList PDFRenderer::render(QPainter* painter, const QMatrix& matr const PDFPage* page = catalog->getPage(pageIndex); Q_ASSERT(page); - PDFPainter processor(painter, m_features, matrix, page, m_document, m_fontCache, m_optionalContentActivity); + PDFPainter processor(painter, m_features, matrix, page, m_document, m_fontCache, m_optionalContentActivity, m_meshQualitySettings); return processor.processContents(); } diff --git a/PdfForQtLib/sources/pdfrenderer.h b/PdfForQtLib/sources/pdfrenderer.h index 1bde704..6fbfc3b 100644 --- a/PdfForQtLib/sources/pdfrenderer.h +++ b/PdfForQtLib/sources/pdfrenderer.h @@ -20,6 +20,7 @@ #include "pdfpage.h" #include "pdfexception.h" +#include "pdfmeshqualitysettings.h" class QPainter; @@ -44,7 +45,7 @@ public: Q_DECLARE_FLAGS(Features, Feature) - explicit PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, Features features); + explicit PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, Features features, const PDFMeshQualitySettings& meshQualitySettings); /// Paints desired page onto the painter. Page is painted in the rectangle using best-fit method. /// If the page doesn't exist, then error is returned. No exception is thrown. Rendering errors @@ -67,6 +68,7 @@ private: const PDFFontCache* m_fontCache; const PDFOptionalContentActivity* m_optionalContentActivity; Features m_features; + PDFMeshQualitySettings m_meshQualitySettings; }; diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp index 58388f1..2874e19 100644 --- a/PdfForQtViewer/pdfviewermainwindow.cpp +++ b/PdfForQtViewer/pdfviewermainwindow.cpp @@ -255,6 +255,9 @@ void PDFViewerMainWindow::onViewerSettingsChanged() { m_pdfWidget->updateRenderer(m_settings->getRendererEngine(), m_settings->isMultisampleAntialiasingEnabled() ? m_settings->getRendererSamples() : -1); m_pdfWidget->getDrawWidgetProxy()->setFeatures(m_settings->getFeatures()); + m_pdfWidget->getDrawWidgetProxy()->setPreferredMeshResolutionRatio(m_settings->getPreferredMeshResolutionRatio()); + m_pdfWidget->getDrawWidgetProxy()->setMinimalMeshResolutionRatio(m_settings->getMinimalMeshResolutionRatio()); + m_pdfWidget->getDrawWidgetProxy()->setColorTolerance(m_settings->getColorTolerance()); updateRenderingOptionActions(); } diff --git a/PdfForQtViewer/pdfviewersettings.cpp b/PdfForQtViewer/pdfviewersettings.cpp index 3ffd771..8f66c69 100644 --- a/PdfForQtViewer/pdfviewersettings.cpp +++ b/PdfForQtViewer/pdfviewersettings.cpp @@ -11,12 +11,17 @@ void PDFViewerSettings::setSettings(const PDFViewerSettings::Settings& settings) void PDFViewerSettings::readSettings(QSettings& settings) { + Settings defaultSettings; + settings.beginGroup("ViewerSettings"); m_settings.m_directory = settings.value("defaultDirectory", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).toString(); m_settings.m_features = static_cast(settings.value("rendererFeatures", static_cast(pdf::PDFRenderer::getDefaultFeatures())).toInt()); m_settings.m_rendererEngine = static_cast(settings.value("renderingEngine", static_cast(pdf::RendererEngine::OpenGL)).toInt()); - m_settings.m_multisampleAntialiasing = settings.value("msaa", true).toBool(); - m_settings.m_rendererSamples = settings.value("rendererSamples", 16).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_preferredMeshResolutionRatio = settings.value("preferredMeshResolutionRatio", defaultSettings.m_preferredMeshResolutionRatio).toDouble(); + m_settings.m_minimalMeshResolutionRatio = settings.value("minimalMeshResolutionRatio", defaultSettings.m_minimalMeshResolutionRatio).toDouble(); + m_settings.m_colorTolerance = settings.value("colorTolerance", defaultSettings.m_colorTolerance).toDouble(); settings.endGroup(); emit settingsChanged(); @@ -30,6 +35,9 @@ void PDFViewerSettings::writeSettings(QSettings& settings) settings.setValue("renderingEngine", static_cast(m_settings.m_rendererEngine)); settings.setValue("msaa", m_settings.m_multisampleAntialiasing); settings.setValue("rendererSamples", m_settings.m_rendererSamples); + settings.setValue("preferredMeshResolutionRatio", m_settings.m_preferredMeshResolutionRatio); + settings.setValue("minimalMeshResolutionRatio", m_settings.m_minimalMeshResolutionRatio); + settings.setValue("colorTolerance", m_settings.m_colorTolerance); settings.endGroup(); } @@ -89,4 +97,31 @@ void PDFViewerSettings::setRendererSamples(int rendererSamples) } } +void PDFViewerSettings::setPreferredMeshResolutionRatio(pdf::PDFReal preferredMeshResolutionRatio) +{ + if (m_settings.m_preferredMeshResolutionRatio != preferredMeshResolutionRatio) + { + m_settings.m_preferredMeshResolutionRatio = preferredMeshResolutionRatio; + emit settingsChanged(); + } +} + +void PDFViewerSettings::setMinimalMeshResolutionRatio(pdf::PDFReal minimalMeshResolutionRatio) +{ + if (m_settings.m_minimalMeshResolutionRatio != minimalMeshResolutionRatio) + { + m_settings.m_minimalMeshResolutionRatio = minimalMeshResolutionRatio; + emit settingsChanged(); + } +} + +void PDFViewerSettings::setColorTolerance(pdf::PDFReal colorTolerance) +{ + if (m_settings.m_colorTolerance != colorTolerance) + { + m_settings.m_colorTolerance = colorTolerance; + emit settingsChanged(); + } +} + } // namespace pdfviewer diff --git a/PdfForQtViewer/pdfviewersettings.h b/PdfForQtViewer/pdfviewersettings.h index 98a85f2..1f8fd3e 100644 --- a/PdfForQtViewer/pdfviewersettings.h +++ b/PdfForQtViewer/pdfviewersettings.h @@ -25,7 +25,10 @@ public: m_features(pdf::PDFRenderer::getDefaultFeatures()), m_rendererEngine(pdf::RendererEngine::OpenGL), m_multisampleAntialiasing(true), - m_rendererSamples(16) + m_rendererSamples(16), + m_preferredMeshResolutionRatio(0.02), + m_minimalMeshResolutionRatio(0.005), + m_colorTolerance(0.01) { } @@ -35,6 +38,9 @@ public: pdf::RendererEngine m_rendererEngine; bool m_multisampleAntialiasing; int m_rendererSamples; + pdf::PDFReal m_preferredMeshResolutionRatio; + pdf::PDFReal m_minimalMeshResolutionRatio; + pdf::PDFReal m_colorTolerance; }; const Settings& getSettings() const { return m_settings; } @@ -57,6 +63,15 @@ public: bool isMultisampleAntialiasingEnabled() const { return m_settings.m_multisampleAntialiasing; } + pdf::PDFReal getPreferredMeshResolutionRatio() const { return m_settings.m_preferredMeshResolutionRatio; } + void setPreferredMeshResolutionRatio(pdf::PDFReal preferredMeshResolutionRatio); + + pdf::PDFReal getMinimalMeshResolutionRatio() const { return m_settings.m_minimalMeshResolutionRatio; } + void setMinimalMeshResolutionRatio(pdf::PDFReal minimalMeshResolutionRatio); + + pdf::PDFReal getColorTolerance() const { return m_settings.m_colorTolerance; } + void setColorTolerance(pdf::PDFReal colorTolerance); + signals: void settingsChanged(); diff --git a/PdfForQtViewer/pdfviewersettingsdialog.cpp b/PdfForQtViewer/pdfviewersettingsdialog.cpp index 64c2595..5668a0e 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.cpp +++ b/PdfForQtViewer/pdfviewersettingsdialog.cpp @@ -4,6 +4,7 @@ #include "pdfglobal.h" #include "pdfutils.h" +#include #include namespace pdfviewer @@ -42,6 +43,10 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin { connect(comboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &PDFViewerSettingsDialog::saveData); } + for (QDoubleSpinBox* spinBox : { ui->preferredMeshResolutionEdit, ui->minimalMeshResolutionEdit, ui->colorToleranceEdit }) + { + connect(spinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &PDFViewerSettingsDialog::saveData); + } ui->optionsPagesWidget->setCurrentRow(0); adjustSize(); @@ -82,6 +87,7 @@ void PDFViewerSettingsDialog::loadData() pdf::PDFTemporaryValueChange guard(&m_isLoadingData, true); ui->renderingEngineComboBox->setCurrentIndex(ui->renderingEngineComboBox->findData(static_cast(m_settings.m_rendererEngine))); + // Engine if (m_settings.m_rendererEngine == pdf::RendererEngine::OpenGL) { ui->multisampleAntialiasingCheckBox->setEnabled(true); @@ -106,11 +112,17 @@ void PDFViewerSettingsDialog::loadData() ui->multisampleAntialiasingSamplesCountComboBox->setCurrentIndex(-1); } + // Rendering ui->antialiasingCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::Antialiasing)); ui->textAntialiasingCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::TextAntialiasing)); ui->smoothPicturesCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::SmoothImages)); ui->ignoreOptionalContentCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::IgnoreOptionalContent)); ui->clipToCropBoxCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::ClipToCropBox)); + + // Shading + ui->preferredMeshResolutionEdit->setValue(m_settings.m_preferredMeshResolutionRatio); + ui->minimalMeshResolutionEdit->setValue(m_settings.m_minimalMeshResolutionRatio); + ui->colorToleranceEdit->setValue(m_settings.m_colorTolerance); } void PDFViewerSettingsDialog::saveData() @@ -154,6 +166,18 @@ void PDFViewerSettingsDialog::saveData() { m_settings.m_features.setFlag(pdf::PDFRenderer::ClipToCropBox, ui->clipToCropBoxCheckBox->isChecked()); } + else if (sender == ui->preferredMeshResolutionEdit) + { + m_settings.m_preferredMeshResolutionRatio = ui->preferredMeshResolutionEdit->value(); + } + else if (sender == ui->minimalMeshResolutionEdit) + { + m_settings.m_minimalMeshResolutionRatio = ui->minimalMeshResolutionEdit->value(); + } + else if (sender == ui->colorToleranceEdit) + { + m_settings.m_colorTolerance = ui->colorToleranceEdit->value(); + } loadData(); } diff --git a/PdfForQtViewer/pdfviewersettingsdialog.ui b/PdfForQtViewer/pdfviewersettingsdialog.ui index 393dfa8..b979e6b 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.ui +++ b/PdfForQtViewer/pdfviewersettingsdialog.ui @@ -255,6 +255,113 @@ Shading Settings + + + + + + + Preferred mesh resolution ratio + + + + + + + Color tolerance + + + + + + + Minimal mesh resolution ratio + + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.001000000000000 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.001000000000000 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.001000000000000 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + + + + + <html><head/><body><p>Shading is meshed according the mesh quality criteria. It involves <span style=" font-weight:600;">color tolerance</span> and shape tolerance. If color of vertices of triangle in the mesh is too different (it differs more than color tolerance) then mesh is refined and triangle is subdivided. Some shadings are defined by patterns (such as <span style=" font-style:italic;">Coons patch shading </span>or <span style=" font-style:italic;">Tensor product patch shading</span>), which is also considered in meshing.</p><p><span style=" font-weight:600;">Preferred mesh resolution ratio</span> should be set to optimal balance between performance of mesh generation and quality of the mesh. Optimal triangle size will be computed in the following way: total meshing area (typically a page) will be multiplied with this ratio and that will determine the triangle size. So, if we have A4 page (210 mm x 297mm), and ratio is set to 0,01, then we will get optimal triangle size as 297 * 0.01 = ~3mm.</p><p><span style=" font-weight:600;">Minimal mesh resolution ratio</span> is ratio, which will determine triangle minimal size. At this bound, no triangles are subdivided, even if color is different or shape is not good. This should be set to a value, at which user barely can recognize patterns on the screen (for example, the size of triangle should be &lt; 1mm). But it also affect performance, because too much triangles can be generated.</p><p><span style=" font-weight:600;">Color tolerance</span> is threshold, at which is two colors recognized as different. The comparation is done component-wise, so if at least one of color components is greater than this parameter, then colors are treated as different.</p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 20 + 91 + + + + +