mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Function shading sampler
This commit is contained in:
@ -502,6 +502,101 @@ PDFPatternPtr PDFPattern::createShadingPattern(const PDFDictionary* colorSpaceDi
|
|||||||
return PDFPatternPtr();
|
return PDFPatternPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PDFFunctionShadingSampler : public PDFShadingSampler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PDFFunctionShadingSampler(const PDFFunctionShading* functionShadingPattern, QMatrix userSpaceToDeviceSpaceMatrix) :
|
||||||
|
PDFShadingSampler(functionShadingPattern),
|
||||||
|
m_functionShadingPattern(functionShadingPattern),
|
||||||
|
m_domain(functionShadingPattern->getDomain())
|
||||||
|
{
|
||||||
|
QMatrix patternSpaceToDeviceSpaceMatrix = functionShadingPattern->getMatrix() * userSpaceToDeviceSpaceMatrix;
|
||||||
|
QMatrix domainToDeviceSpaceMatrix = functionShadingPattern->getDomainToTargetTransform() * patternSpaceToDeviceSpaceMatrix;
|
||||||
|
|
||||||
|
if (domainToDeviceSpaceMatrix.isInvertible())
|
||||||
|
{
|
||||||
|
m_deviceSpaceToDomainMatrix = domainToDeviceSpaceMatrix.inverted();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_deviceSpaceToDomainMatrix = QMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool sample(const QPointF& devicePoint, PDFColorBuffer outputBuffer, int limit) const override
|
||||||
|
{
|
||||||
|
Q_UNUSED(limit);
|
||||||
|
|
||||||
|
if (!m_pattern->getColorSpace() || m_pattern->getColorSpace()->getColorComponentCount() != outputBuffer.size())
|
||||||
|
{
|
||||||
|
// Invalid color space, or invalid color buffer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF domainPoint = m_deviceSpaceToDomainMatrix.map(devicePoint);
|
||||||
|
|
||||||
|
if (!m_domain.contains(domainPoint))
|
||||||
|
{
|
||||||
|
return fillBackgroundColor(outputBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& functions = m_functionShadingPattern->getFunctions();
|
||||||
|
std::array<PDFReal, PDF_MAX_COLOR_COMPONENTS> colorBuffer = { };
|
||||||
|
|
||||||
|
if (colorBuffer.size() < outputBuffer.size())
|
||||||
|
{
|
||||||
|
// Jakub Melka: Too much colors - we cant process it
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<PDFReal, 2> input = { domainPoint.x(), domainPoint.y() };
|
||||||
|
|
||||||
|
if (functions.size() == 1)
|
||||||
|
{
|
||||||
|
Q_ASSERT(outputBuffer.size() <= colorBuffer.size());
|
||||||
|
PDFFunction::FunctionResult result = functions.front()->apply(input.data(), input.data() + input.size(), colorBuffer.data(), colorBuffer.data() + outputBuffer.size());
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
// Function call failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (functions.size() != outputBuffer.size())
|
||||||
|
{
|
||||||
|
// Invalid number of functions
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(outputBuffer.size() <= colorBuffer.size());
|
||||||
|
for (size_t i = 0, count = outputBuffer.size(); i < count; ++i)
|
||||||
|
{
|
||||||
|
PDFFunction::FunctionResult result = functions[i]->apply(input.data(), input.data() + input.size(), colorBuffer.data() + i, colorBuffer.data() + i + 1);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
// Function call failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0, count = outputBuffer.size(); i < count; ++i)
|
||||||
|
{
|
||||||
|
outputBuffer[i] = colorBuffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const PDFFunctionShading* m_functionShadingPattern;
|
||||||
|
QRectF m_domain;
|
||||||
|
QMatrix m_deviceSpaceToDomainMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
ShadingType PDFFunctionShading::getShadingType() const
|
ShadingType PDFFunctionShading::getShadingType() const
|
||||||
{
|
{
|
||||||
return ShadingType::Function;
|
return ShadingType::Function;
|
||||||
@ -810,6 +905,11 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings, c
|
|||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFShadingSampler* PDFFunctionShading::createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const
|
||||||
|
{
|
||||||
|
return new PDFFunctionShadingSampler(this, userSpaceToDeviceSpaceMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
PDFMesh PDFAxialShading::createMesh(const PDFMeshQualitySettings& settings, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
PDFMesh PDFAxialShading::createMesh(const PDFMeshQualitySettings& settings, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||||
{
|
{
|
||||||
PDFMesh mesh;
|
PDFMesh mesh;
|
||||||
|
@ -383,6 +383,11 @@ 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;
|
||||||
|
|
||||||
|
const QRectF& getDomain() const { return m_domain; }
|
||||||
|
const QMatrix& getDomainToTargetTransform() const { return m_domainToTargetTransform; }
|
||||||
|
const std::vector<PDFFunctionPtr>& getFunctions() const { return m_functions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class PDFPattern;
|
friend class PDFPattern;
|
||||||
|
Reference in New Issue
Block a user