mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Function type shading - finish
This commit is contained in:
@ -99,6 +99,12 @@ PDFPatternPtr PDFPattern::createShadingPattern(const PDFDictionary* colorSpaceDi
|
|||||||
|
|
||||||
// Parse common data for all shadings
|
// Parse common data for all shadings
|
||||||
PDFColorSpacePointer colorSpace = PDFAbstractColorSpace::createColorSpace(colorSpaceDictionary, document, shadingDictionary->get("ColorSpace"));
|
PDFColorSpacePointer colorSpace = PDFAbstractColorSpace::createColorSpace(colorSpaceDictionary, document, shadingDictionary->get("ColorSpace"));
|
||||||
|
|
||||||
|
if (colorSpace->getPattern())
|
||||||
|
{
|
||||||
|
throw PDFParserException(PDFTranslationContext::tr("Pattern color space is not valid for shading patterns."));
|
||||||
|
}
|
||||||
|
|
||||||
QColor backgroundColor;
|
QColor backgroundColor;
|
||||||
if (!ignoreBackgroundColor)
|
if (!ignoreBackgroundColor)
|
||||||
{
|
{
|
||||||
@ -255,8 +261,15 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings) c
|
|||||||
QLineF leftLineDS = domainToDeviceSpaceMatrix.map(leftLine);
|
QLineF leftLineDS = domainToDeviceSpaceMatrix.map(leftLine);
|
||||||
|
|
||||||
const size_t colorComponents = m_colorSpace->getColorComponentCount();
|
const size_t colorComponents = m_colorSpace->getColorComponentCount();
|
||||||
const PDFReal resolution = settings.preferredMeshResolution;
|
auto resolutions = { settings.preferredMeshResolution,
|
||||||
|
interpolate(0.25, 0.0, 1.0, settings.preferredMeshResolution, settings.minimalMeshResolution),
|
||||||
|
interpolate(0.50, 0.0, 1.0, settings.preferredMeshResolution, settings.minimalMeshResolution),
|
||||||
|
interpolate(0.75, 0.0, 1.0, settings.preferredMeshResolution, settings.minimalMeshResolution),
|
||||||
|
settings.minimalMeshResolution
|
||||||
|
};
|
||||||
|
|
||||||
|
for (PDFReal resolution : resolutions)
|
||||||
|
{
|
||||||
const PDFReal xSteps = qMax(std::floor(topLineDS.length() / resolution), 2.0);
|
const PDFReal xSteps = qMax(std::floor(topLineDS.length() / resolution), 2.0);
|
||||||
const PDFReal ySteps = qMax(std::floor(leftLineDS.length() / resolution), 2.0);
|
const PDFReal ySteps = qMax(std::floor(leftLineDS.length() / resolution), 2.0);
|
||||||
const PDFReal xStep = 1.0 / xSteps;
|
const PDFReal xStep = 1.0 / xSteps;
|
||||||
@ -375,6 +388,52 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings) c
|
|||||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Error occured during mesh generation of shading: %1").arg(functionError.errorMessage));
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Error occured during mesh generation of shading: %1").arg(functionError.errorMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the colors, if mesh is bad, then refine it
|
||||||
|
std::atomic_bool isMeshOK = true;
|
||||||
|
auto validateMesh = [&](size_t index)
|
||||||
|
{
|
||||||
|
if (!isMeshOK.load(std::memory_order_relaxed))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [row, column] = indexToRowColumn(index);
|
||||||
|
const size_t colorComponentIndex = rowColumnToFirstColorComponent(row, column);
|
||||||
|
|
||||||
|
// Check, if color left doesn't differ too much
|
||||||
|
if (column > 0)
|
||||||
|
{
|
||||||
|
const size_t colorOtherComponentIndex = rowColumnToFirstColorComponent(row, column - 1);
|
||||||
|
for (size_t i = 0; i < colorComponents; ++i)
|
||||||
|
{
|
||||||
|
if (std::fabs(sourceColorBuffer[colorComponentIndex + i] - sourceColorBuffer[colorOtherComponentIndex + i]) > settings.tolerance)
|
||||||
|
{
|
||||||
|
isMeshOK.store(std::memory_order_relaxed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row > 0)
|
||||||
|
{
|
||||||
|
const size_t colorOtherComponentIndex = rowColumnToFirstColorComponent(row - 1, column);
|
||||||
|
for (size_t i = 0; i < colorComponents; ++i)
|
||||||
|
{
|
||||||
|
if (std::fabs(sourceColorBuffer[colorComponentIndex + i] - sourceColorBuffer[colorOtherComponentIndex + i]) > settings.tolerance)
|
||||||
|
{
|
||||||
|
isMeshOK.store(std::memory_order_relaxed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::for_each(std::execution::parallel_policy(), indices.cbegin(), indices.cend(), validateMesh);
|
||||||
|
if (!isMeshOK && resolution != settings.minimalMeshResolution)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, we are ready to generate the mesh
|
||||||
std::vector<QRgb> colors;
|
std::vector<QRgb> colors;
|
||||||
colors.resize(rowCount * columnCount, QRgb());
|
colors.resize(rowCount * columnCount, QRgb());
|
||||||
|
|
||||||
@ -462,6 +521,22 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings) c
|
|||||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Error occured during mesh generation of shading: %1").arg(functionError.errorMessage));
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Error occured during mesh generation of shading: %1").arg(functionError.errorMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_backgroundColor.isValid())
|
||||||
|
{
|
||||||
|
QPainterPath backgroundPath;
|
||||||
|
backgroundPath.addRect(settings.deviceSpaceMeshingArea);
|
||||||
|
|
||||||
|
QPainterPath paintedPath;
|
||||||
|
paintedPath.addPolygon(domainToDeviceSpaceMatrix.map(m_domain));
|
||||||
|
|
||||||
|
backgroundPath = backgroundPath.subtracted(paintedPath);
|
||||||
|
mesh.setBackgroundPath(backgroundPath);
|
||||||
|
mesh.setBackgroundColor(m_backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
// Create bounding path
|
// Create bounding path
|
||||||
if (m_boundingBox.isValid())
|
if (m_boundingBox.isValid())
|
||||||
{
|
{
|
||||||
@ -714,6 +789,12 @@ void PDFMesh::paint(QPainter* painter) const
|
|||||||
painter->setClipPath(m_boundingPath, Qt::IntersectClip);
|
painter->setClipPath(m_boundingPath, Qt::IntersectClip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_backgroundPath.isEmpty() && m_backgroundColor.isValid())
|
||||||
|
{
|
||||||
|
painter->setBrush(QBrush(m_backgroundColor, Qt::SolidPattern));
|
||||||
|
painter->drawPath(m_backgroundPath);
|
||||||
|
}
|
||||||
|
|
||||||
QColor color;
|
QColor color;
|
||||||
|
|
||||||
// Draw all triangles
|
// Draw all triangles
|
||||||
@ -741,6 +822,7 @@ void PDFMesh::transform(const QMatrix& matrix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_boundingPath = matrix.map(m_boundingPath);
|
m_boundingPath = matrix.map(m_boundingPath);
|
||||||
|
m_backgroundPath = matrix.map(m_backgroundPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF PDFMesh::getTriangleCenter(const PDFMesh::Triangle& triangle) const
|
QPointF PDFMesh::getTriangleCenter(const PDFMesh::Triangle& triangle) const
|
||||||
|
@ -127,7 +127,12 @@ public:
|
|||||||
const QPainterPath& getBoundingPath() const { return m_boundingPath; }
|
const QPainterPath& getBoundingPath() const { return m_boundingPath; }
|
||||||
void setBoundingPath(const QPainterPath& path) { m_boundingPath = path; }
|
void setBoundingPath(const QPainterPath& path) { m_boundingPath = path; }
|
||||||
|
|
||||||
|
/// Sets the vertex array to the mesh
|
||||||
|
/// \param vertices New vertex array
|
||||||
void setVertices(std::vector<QPointF>&& vertices) { m_vertices = qMove(vertices); }
|
void setVertices(std::vector<QPointF>&& vertices) { m_vertices = qMove(vertices); }
|
||||||
|
|
||||||
|
/// Sets the triangle array to the mesh
|
||||||
|
/// \param triangles New triangle array
|
||||||
void setTriangles(std::vector<Triangle>&& triangles) { m_triangles = qMove(triangles); }
|
void setTriangles(std::vector<Triangle>&& triangles) { m_triangles = qMove(triangles); }
|
||||||
|
|
||||||
/// Returns vertex at given index
|
/// Returns vertex at given index
|
||||||
@ -138,10 +143,22 @@ public:
|
|||||||
/// \param triangle Triangle
|
/// \param triangle Triangle
|
||||||
QPointF getTriangleCenter(const Triangle& triangle) const;
|
QPointF getTriangleCenter(const Triangle& triangle) const;
|
||||||
|
|
||||||
|
/// Sets the background path. In order to draw background properly, the background
|
||||||
|
/// color must be set to a valid color.
|
||||||
|
/// \param path Background path
|
||||||
|
void setBackgroundPath(QPainterPath path) { m_backgroundPath = qMove(path); }
|
||||||
|
|
||||||
|
/// Sets the background color (background path is then painted with this color, if it is not
|
||||||
|
/// empty), if color is invalid, it turns off background painting.
|
||||||
|
/// \param backgroundColor Background color
|
||||||
|
void setBackgroundColor(QColor backgroundColor) { m_backgroundColor = backgroundColor; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<QPointF> m_vertices;
|
std::vector<QPointF> m_vertices;
|
||||||
std::vector<Triangle> m_triangles;
|
std::vector<Triangle> m_triangles;
|
||||||
QPainterPath m_boundingPath;
|
QPainterPath m_boundingPath;
|
||||||
|
QPainterPath m_backgroundPath;
|
||||||
|
QColor m_backgroundColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents tiling/shading pattern
|
/// Represents tiling/shading pattern
|
||||||
|
Reference in New Issue
Block a user