Mesh quality settings

This commit is contained in:
Jakub Melka 2019-09-28 18:26:31 +02:00
parent 9941438e99
commit b09f9eff21
17 changed files with 335 additions and 68 deletions

View File

@ -65,6 +65,7 @@ SOURCES += \
HEADERS += \
sources/pdfitemmodels.h \
sources/pdfmeshqualitysettings.h \
sources/pdfobject.h \
sources/pdfoptionalcontent.h \
sources/pdfparser.h \

View File

@ -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<PDFRenderError> 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

View File

@ -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

View File

@ -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 <https://www.gnu.org/licenses/>.
#ifndef PDFMESHQUALITYSETTINGS_H
#define PDFMESHQUALITYSETTINGS_H
#include "pdfglobal.h"
#include <QMatrix>
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

View File

@ -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);

View File

@ -23,6 +23,7 @@
#include "pdfparser.h"
#include "pdffont.h"
#include "pdfutils.h"
#include "pdfmeshqualitysettings.h"
#include <QMatrix>
#include <QPainterPath>
@ -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

View File

@ -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)
{

View File

@ -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:

View File

@ -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

View File

@ -21,6 +21,7 @@
#include "pdfobject.h"
#include "pdffunction.h"
#include "pdfcolorspaces.h"
#include "pdfmeshqualitysettings.h"
#include <QMatrix>
@ -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
{

View File

@ -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<PDFRenderError> 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<PDFRenderError> 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();
}

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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<pdf::PDFRenderer::Features>(settings.value("rendererFeatures", 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_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<int>(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

View File

@ -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();

View File

@ -4,6 +4,7 @@
#include "pdfglobal.h"
#include "pdfutils.h"
#include <QMessageBox>
#include <QListWidgetItem>
namespace pdfviewer
@ -42,6 +43,10 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
{
connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFViewerSettingsDialog::saveData);
}
for (QDoubleSpinBox* spinBox : { ui->preferredMeshResolutionEdit, ui->minimalMeshResolutionEdit, ui->colorToleranceEdit })
{
connect(spinBox, QOverload<double>::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<int>(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();
}

View File

@ -255,6 +255,113 @@
<property name="title">
<string>Shading Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="preferredMeshResolutionLabel">
<property name="text">
<string>Preferred mesh resolution ratio</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="colorToleranceLabel">
<property name="text">
<string>Color tolerance</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="minimalMeshResolutionLabel">
<property name="text">
<string>Minimal mesh resolution ratio</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="preferredMeshResolutionEdit">
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>0.100000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="minimalMeshResolutionEdit">
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>0.100000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="colorToleranceEdit">
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>0.100000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="shadingInfoLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Shading is meshed according the mesh quality criteria. It involves &lt;span style=&quot; font-weight:600;&quot;&gt;color tolerance&lt;/span&gt; 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 &lt;span style=&quot; font-style:italic;&quot;&gt;Coons patch shading &lt;/span&gt;or &lt;span style=&quot; font-style:italic;&quot;&gt;Tensor product patch shading&lt;/span&gt;), which is also considered in meshing.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Preferred mesh resolution ratio&lt;/span&gt; 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.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Minimal mesh resolution ratio&lt;/span&gt; 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 &amp;lt; 1mm). But it also affect performance, because too much triangles can be generated.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Color tolerance&lt;/span&gt; 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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="shadingVerticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>91</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>