mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Sampler for lattice form gourad triangle shading
This commit is contained in:
@ -2307,11 +2307,12 @@ ShadingType PDFLatticeFormGouradTriangleShading::getShadingType() const
|
|||||||
return ShadingType::LatticeFormGouradTriangle;
|
return ShadingType::LatticeFormGouradTriangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySettings& settings, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
bool PDFLatticeFormGouradTriangleShading::processTriangles(InitializeFunction initializeMeshFunction,
|
||||||
|
AddTriangleFunction addTriangle,
|
||||||
|
const QMatrix& userSpaceToDeviceSpaceMatrix,
|
||||||
|
bool convertColors) const
|
||||||
{
|
{
|
||||||
PDFMesh mesh;
|
QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(userSpaceToDeviceSpaceMatrix);
|
||||||
|
|
||||||
QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(settings);
|
|
||||||
size_t bitsPerVertex = 2 * m_bitsPerCoordinate + m_colorComponentCount * m_bitsPerComponent;
|
size_t bitsPerVertex = 2 * m_bitsPerCoordinate + m_colorComponentCount * m_bitsPerComponent;
|
||||||
size_t remainder = (8 - (bitsPerVertex % 8)) % 8;
|
size_t remainder = (8 - (bitsPerVertex % 8)) % 8;
|
||||||
bitsPerVertex += remainder;
|
bitsPerVertex += remainder;
|
||||||
@ -2323,20 +2324,12 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
|
|||||||
if (rowCount < 2)
|
if (rowCount < 2)
|
||||||
{
|
{
|
||||||
// No mesh produced
|
// No mesh produced
|
||||||
return mesh;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have 2 triangles for each quad. We have (columnCount - 1) quads
|
// We have 2 triangles for each quad. We have (columnCount - 1) quads
|
||||||
// in single line and we have (rowCount - 1) lines.
|
// in single line and we have (rowCount - 1) lines.
|
||||||
size_t triangleCount = (rowCount - 1) * (columnCount - 1) * 2;
|
size_t triangleCount = (rowCount - 1) * (columnCount - 1) * 2;
|
||||||
mesh.reserve(0, triangleCount);
|
|
||||||
|
|
||||||
struct VertexData
|
|
||||||
{
|
|
||||||
uint32_t index = 0;
|
|
||||||
QPointF position;
|
|
||||||
PDFColor color;
|
|
||||||
};
|
|
||||||
|
|
||||||
const PDFReal vertexScaleRatio = 1.0 / double((static_cast<uint64_t>(1) << m_bitsPerCoordinate) - 1);
|
const PDFReal vertexScaleRatio = 1.0 / double((static_cast<uint64_t>(1) << m_bitsPerCoordinate) - 1);
|
||||||
const PDFReal xScaleRatio = (m_xmax - m_xmin) * vertexScaleRatio;
|
const PDFReal xScaleRatio = (m_xmax - m_xmin) * vertexScaleRatio;
|
||||||
@ -2348,7 +2341,7 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
|
|||||||
std::vector<QPointF> meshVertices;
|
std::vector<QPointF> meshVertices;
|
||||||
meshVertices.resize(vertexCount);
|
meshVertices.resize(vertexCount);
|
||||||
|
|
||||||
auto readVertex = [this, &vertices, &patternSpaceToDeviceSpaceMatrix, &meshVertices, bytesPerVertex, xScaleRatio, yScaleRatio, colorScaleRatio](size_t index)
|
auto readVertex = [this, &vertices, &patternSpaceToDeviceSpaceMatrix, &meshVertices, bytesPerVertex, xScaleRatio, yScaleRatio, colorScaleRatio, convertColors](size_t index)
|
||||||
{
|
{
|
||||||
PDFBitReader reader(&m_data, 8);
|
PDFBitReader reader(&m_data, 8);
|
||||||
reader.seek(index * bytesPerVertex);
|
reader.seek(index * bytesPerVertex);
|
||||||
@ -2368,14 +2361,17 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
|
|||||||
data.color[i] = cMin + (reader.read(m_bitsPerComponent)) * (cMax - cMin) * colorScaleRatio;
|
data.color[i] = cMin + (reader.read(m_bitsPerComponent)) * (cMax - cMin) * colorScaleRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.color = getColor(data.color);
|
if (convertColors)
|
||||||
|
{
|
||||||
|
data.color = getColor(data.color);
|
||||||
|
}
|
||||||
|
|
||||||
vertices[index] = qMove(data);
|
vertices[index] = qMove(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
PDFIntegerRange indices(size_t(0), vertexCount);
|
PDFIntegerRange indices(size_t(0), vertexCount);
|
||||||
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.begin(), indices.end(), readVertex);
|
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.begin(), indices.end(), readVertex);
|
||||||
mesh.setVertices(qMove(meshVertices));
|
initializeMeshFunction(qMove(meshVertices), triangleCount);
|
||||||
|
|
||||||
auto getVertexIndex = [columnCount](size_t row, size_t column) -> size_t
|
auto getVertexIndex = [columnCount](size_t row, size_t column) -> size_t
|
||||||
{
|
{
|
||||||
@ -2396,11 +2392,38 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
|
|||||||
const VertexData& vertexBottomRight = vertices[vBottomRight];
|
const VertexData& vertexBottomRight = vertices[vBottomRight];
|
||||||
const VertexData& vertexBottomLeft = vertices[vBottomLeft];
|
const VertexData& vertexBottomLeft = vertices[vBottomLeft];
|
||||||
|
|
||||||
addSubdividedTriangles(settings, mesh, vertexTopLeft.index, vertexTopRight.index, vertexBottomRight.index, vertexTopLeft.color, vertexTopRight.color, vertexBottomRight.color, cms, intent, reporter);
|
addTriangle(&vertexTopLeft, &vertexTopRight, &vertexBottomRight);
|
||||||
addSubdividedTriangles(settings, mesh, vertexBottomRight.index, vertexBottomLeft.index, vertexTopLeft.index, vertexBottomRight.color, vertexBottomLeft.color, vertexTopLeft.color, cms, intent, reporter);
|
addTriangle(&vertexBottomRight, &vertexBottomLeft, &vertexTopLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySettings& settings, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||||
|
{
|
||||||
|
PDFMesh mesh;
|
||||||
|
|
||||||
|
auto addTriangle = [this, &settings, &mesh, cms, intent, reporter](const VertexData* va, const VertexData* vb, const VertexData* vc)
|
||||||
|
{
|
||||||
|
const uint32_t via = va->index;
|
||||||
|
const uint32_t vib = vb->index;
|
||||||
|
const uint32_t vic = vc->index;
|
||||||
|
|
||||||
|
addSubdividedTriangles(settings, mesh, via, vib, vic, va->color, vb->color, vc->color, cms, intent, reporter);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto initializeMeshFunction = [&mesh](std::vector<QPointF>&& vertices, size_t triangleCount)
|
||||||
|
{
|
||||||
|
mesh.reserve(0, triangleCount);
|
||||||
|
mesh.setVertices(qMove(vertices));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!processTriangles(initializeMeshFunction, addTriangle, settings.userSpaceToDeviceSpaceMatrix, true))
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid lattice form gourad triangle data stream."));
|
||||||
|
}
|
||||||
|
|
||||||
if (m_backgroundColor.isValid())
|
if (m_backgroundColor.isValid())
|
||||||
{
|
{
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
@ -2412,6 +2435,35 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
|
|||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFShadingSampler* PDFLatticeFormGouradTriangleShading::createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const
|
||||||
|
{
|
||||||
|
PDFTriangleShadingSampler* sampler = new PDFTriangleShadingSampler(this, userSpaceToDeviceSpaceMatrix);
|
||||||
|
|
||||||
|
auto addTriangle = [sampler](const VertexData* va, const VertexData* vb, const VertexData* vc)
|
||||||
|
{
|
||||||
|
const uint32_t via = va->index;
|
||||||
|
const uint32_t vib = vb->index;
|
||||||
|
const uint32_t vic = vc->index;
|
||||||
|
|
||||||
|
sampler->addTriangle({ via, vib, vic }, { va->color, vb->color, vc->color });
|
||||||
|
};
|
||||||
|
|
||||||
|
auto initializeMeshFunction = [sampler](std::vector<QPointF>&& vertices, size_t triangleCount)
|
||||||
|
{
|
||||||
|
sampler->setVertexArray(qMove(vertices));
|
||||||
|
sampler->reserveSpaceForTriangles(triangleCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!processTriangles(initializeMeshFunction, addTriangle, userSpaceToDeviceSpaceMatrix, false))
|
||||||
|
{
|
||||||
|
// Just delete the sampler, data are invalid
|
||||||
|
delete sampler;
|
||||||
|
sampler = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampler;
|
||||||
|
}
|
||||||
|
|
||||||
PDFColor PDFType4567Shading::getColor(PDFColor colorOrFunctionParameter) const
|
PDFColor PDFType4567Shading::getColor(PDFColor colorOrFunctionParameter) const
|
||||||
{
|
{
|
||||||
if (!m_functions.empty())
|
if (!m_functions.empty())
|
||||||
|
@ -509,10 +509,26 @@ public:
|
|||||||
|
|
||||||
virtual ShadingType getShadingType() const override;
|
virtual ShadingType getShadingType() const override;
|
||||||
virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||||
|
virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class PDFPattern;
|
friend class PDFPattern;
|
||||||
|
|
||||||
|
struct VertexData
|
||||||
|
{
|
||||||
|
uint32_t index = 0;
|
||||||
|
QPointF position;
|
||||||
|
PDFColor color;
|
||||||
|
};
|
||||||
|
|
||||||
|
using InitializeFunction = std::function<void(std::vector<QPointF>&&, size_t)>;
|
||||||
|
using AddTriangleFunction = std::function<void(const VertexData*, const VertexData*, const VertexData*)>;
|
||||||
|
|
||||||
|
bool processTriangles(InitializeFunction initializeMeshFunction,
|
||||||
|
AddTriangleFunction addTriangle,
|
||||||
|
const QMatrix& userSpaceToDeviceSpaceMatrix,
|
||||||
|
bool convertColors) const;
|
||||||
|
|
||||||
PDFInteger m_verticesPerRow = 0;
|
PDFInteger m_verticesPerRow = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user