Sampler bugfixing

This commit is contained in:
Jakub Melka 2021-02-08 19:18:09 +01:00
parent f0b1707d12
commit 3f7ddacdc0
2 changed files with 66 additions and 16 deletions

View File

@ -727,7 +727,8 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
{ {
Q_UNUSED(fillRule); Q_UNUSED(fillRule);
PDFPainterPathSampler clipSampler(m_painterStateStack.top().clipPath, m_settings.samplesCount, 1.0f); PDFPainterPathSampler clipSampler(m_painterStateStack.top().clipPath, m_settings.samplesCount, 1.0f,
m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
QMatrix worldMatrix = getCurrentWorldMatrix(); QMatrix worldMatrix = getCurrentWorldMatrix();
@ -754,7 +755,7 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
// and world matrix. Path can be translated outside of the paint area. // and world matrix. Path can be translated outside of the paint area.
if (fillRect.isValid()) if (fillRect.isValid())
{ {
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f); PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
const PDFMappedColor& fillColor = getMappedFillColor(); const PDFMappedColor& fillColor = getMappedFillColor();
for (int x = fillRect.left(); x < fillRect.right(); ++x) for (int x = fillRect.left(); x < fillRect.right(); ++x)
@ -812,7 +813,7 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
// and world matrix. Path can be translated outside of the paint area. // and world matrix. Path can be translated outside of the paint area.
if (strokeRect.isValid()) if (strokeRect.isValid())
{ {
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f); PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
const PDFMappedColor& strokeColor = getMappedStrokeColor(); const PDFMappedColor& strokeColor = getMappedStrokeColor();
for (int x = strokeRect.left(); x < strokeRect.right(); ++x) for (int x = strokeRect.left(); x < strokeRect.right(); ++x)
@ -821,7 +822,7 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
{ {
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y)); const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y)); const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
const PDFColorComponent shapeValue = objectShapeValue * clipValue * shapeFilling; const PDFColorComponent shapeValue = objectShapeValue * clipValue * shapeStroking;
if (shapeValue > 0.0f) if (shapeValue > 0.0f)
{ {
@ -830,7 +831,7 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y); PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]); pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]);
pixel[opacityChannel] = pixel[shapeChannel] * opacityFilling; pixel[opacityChannel] = pixel[shapeChannel] * opacityStroking;
// Copy color // Copy color
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex) for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
@ -1497,12 +1498,16 @@ PDFInkMapping PDFInkMapper::createMapping(const PDFAbstractColorSpace* sourceCol
return mapping; return mapping;
} }
PDFPainterPathSampler::PDFPainterPathSampler(QPainterPath path, int samplesCount, PDFColorComponent defaultShape) : PDFPainterPathSampler::PDFPainterPathSampler(QPainterPath path, int samplesCount, PDFColorComponent defaultShape, bool precise) :
m_defaultShape(defaultShape), m_defaultShape(defaultShape),
m_samplesCount(samplesCount), m_samplesCount(samplesCount),
m_precise(precise),
m_path(qMove(path)) m_path(qMove(path))
{ {
if (!precise)
{
m_fillPolygon = m_path.toFillPolygon();
}
} }
PDFColorComponent PDFPainterPathSampler::sample(QPoint point) const PDFColorComponent PDFPainterPathSampler::sample(QPoint point) const
@ -1528,15 +1533,33 @@ PDFColorComponent PDFPainterPathSampler::sample(QPoint point) const
if (m_samplesCount <= 1) if (m_samplesCount <= 1)
{ {
// Jakub Melka: Just one sample // Jakub Melka: Just one sample
return m_path.contains(QPointF(centerX, centerY)) ? 1.0f : 0.0f; if (m_precise)
{
return m_path.contains(QPointF(centerX, centerY)) ? 1.0f : 0.0f;
}
else
{
return m_fillPolygon.contains(QPointF(centerX, centerY)) ? 1.0f : 0.0f;
}
} }
int cornerHits = 0; int cornerHits = 0;
Qt::FillRule fillRule = m_path.fillRule();
cornerHits += m_path.contains(topLeft) ? 1 : 0; if (m_precise)
cornerHits += m_path.contains(topRight) ? 1 : 0; {
cornerHits += m_path.contains(bottomLeft) ? 1 : 0; cornerHits += m_path.contains(topLeft) ? 1 : 0;
cornerHits += m_path.contains(bottomRight) ? 1 : 0; cornerHits += m_path.contains(topRight) ? 1 : 0;
cornerHits += m_path.contains(bottomLeft) ? 1 : 0;
cornerHits += m_path.contains(bottomRight) ? 1 : 0;
}
else
{
cornerHits += m_fillPolygon.containsPoint(topLeft, fillRule) ? 1 : 0;
cornerHits += m_fillPolygon.containsPoint(topRight, fillRule) ? 1 : 0;
cornerHits += m_fillPolygon.containsPoint(bottomLeft, fillRule) ? 1 : 0;
cornerHits += m_fillPolygon.containsPoint(bottomRight, fillRule) ? 1 : 0;
}
if (cornerHits == 4) if (cornerHits == 4)
{ {
@ -1562,9 +1585,19 @@ PDFColorComponent PDFPainterPathSampler::sample(QPoint point) const
{ {
const qreal y = offset * (iy + 1) + coordY1; const qreal y = offset * (iy + 1) + coordY1;
if (m_path.contains(QPointF(x, y))) if (m_precise)
{ {
sampleValue += sampleGain; if (m_path.contains(QPointF(x, y)))
{
sampleValue += sampleGain;
}
}
else
{
if (m_fillPolygon.containsPoint(QPointF(x, y), fillRule))
{
sampleValue += sampleGain;
}
} }
} }
} }

View File

@ -332,15 +332,18 @@ public:
/// \param path Sampled path /// \param path Sampled path
/// \param samplesCount Samples count in one direction /// \param samplesCount Samples count in one direction
/// \param defaultShape Default shape returned, if path is empty /// \param defaultShape Default shape returned, if path is empty
PDFPainterPathSampler(QPainterPath path, int samplesCount, PDFColorComponent defaultShape); /// \param precise Use precise sampling (using spline curves), or fill polygon (fast, but not too precise)
PDFPainterPathSampler(QPainterPath path, int samplesCount, PDFColorComponent defaultShape, bool precise);
/// Return sample value for a given pixel /// Return sample value for a given pixel
PDFColorComponent sample(QPoint point) const; PDFColorComponent sample(QPoint point) const;
private: private:
PDFColorComponent m_defaultShape = 0.0; PDFColorComponent m_defaultShape = 0.0;
int m_samplesCount; ///< Samples count in one direction int m_samplesCount = 0; ///< Samples count in one direction
bool m_precise = false;
QPainterPath m_path; QPainterPath m_path;
QPolygonF m_fillPolygon;
}; };
/// Represents draw buffer, into which is current graphics drawn /// Represents draw buffer, into which is current graphics drawn
@ -381,6 +384,20 @@ struct PDFTransparencyRendererSettings
{ {
/// Sample count for MSAA antialiasing /// Sample count for MSAA antialiasing
int samplesCount = 16; int samplesCount = 16;
enum Flag
{
None = 0x0000,
/// Use precise path sampler, which uses paths instead
/// of filling polygon.
PrecisePathSampler = 0x0001
};
Q_DECLARE_FLAGS(Flags, Flag)
/// Flags
Flags flags = None;
}; };
/// Renders PDF pages with transparency, using 32-bit floating point precision. /// Renders PDF pages with transparency, using 32-bit floating point precision.