mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Path sampling, painting paths
This commit is contained in:
@ -444,7 +444,17 @@ void PDFPageContentProcessor::performOutputCharacter(const PDFTextCharacterInfo&
|
|||||||
Q_UNUSED(info);
|
Q_UNUSED(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PDFPageContentProcessor::isContentKindSuppressed(PDFPageContentProcessor::ContentKind kind) const
|
void PDFPageContentProcessor::performTextBegin(ProcessOrder order)
|
||||||
|
{
|
||||||
|
Q_UNUSED(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFPageContentProcessor::performTextEnd(ProcessOrder order)
|
||||||
|
{
|
||||||
|
Q_UNUSED(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFPageContentProcessor::isContentKindSuppressed(ContentKind kind) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(kind);
|
Q_UNUSED(kind);
|
||||||
return false;
|
return false;
|
||||||
@ -2580,11 +2590,13 @@ void PDFPageContentProcessor::operatorColorSetDeviceCMYKFilling(PDFReal c, PDFRe
|
|||||||
|
|
||||||
void PDFPageContentProcessor::operatorTextBegin()
|
void PDFPageContentProcessor::operatorTextBegin()
|
||||||
{
|
{
|
||||||
|
performTextBegin(ProcessOrder::BeforeOperation);
|
||||||
m_graphicState.setTextMatrix(QMatrix());
|
m_graphicState.setTextMatrix(QMatrix());
|
||||||
m_graphicState.setTextLineMatrix(QMatrix());
|
m_graphicState.setTextLineMatrix(QMatrix());
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
|
|
||||||
++m_textBeginEndState;
|
++m_textBeginEndState;
|
||||||
|
performTextBegin(ProcessOrder::AfterOperation);
|
||||||
|
|
||||||
if (m_textBeginEndState > 1)
|
if (m_textBeginEndState > 1)
|
||||||
{
|
{
|
||||||
@ -2599,12 +2611,14 @@ void PDFPageContentProcessor::operatorTextEnd()
|
|||||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Text object ended more than once."));
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Text object ended more than once."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
performTextEnd(ProcessOrder::BeforeOperation);
|
||||||
if (!m_textClippingPath.isEmpty())
|
if (!m_textClippingPath.isEmpty())
|
||||||
{
|
{
|
||||||
QPainterPath clippingPath = m_graphicState.getCurrentTransformationMatrix().inverted().map(m_textClippingPath);
|
QPainterPath clippingPath = m_graphicState.getCurrentTransformationMatrix().inverted().map(m_textClippingPath);
|
||||||
performClipping(clippingPath, clippingPath.fillRule());
|
performClipping(clippingPath, clippingPath.fillRule());
|
||||||
m_textClippingPath = QPainterPath();
|
m_textClippingPath = QPainterPath();
|
||||||
}
|
}
|
||||||
|
performTextEnd(ProcessOrder::AfterOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::operatorTextSetCharacterSpacing(PDFReal charSpacing)
|
void PDFPageContentProcessor::operatorTextSetCharacterSpacing(PDFReal charSpacing)
|
||||||
|
@ -569,6 +569,12 @@ protected:
|
|||||||
/// Implement to react on character printing
|
/// Implement to react on character printing
|
||||||
virtual void performOutputCharacter(const PDFTextCharacterInfo& info);
|
virtual void performOutputCharacter(const PDFTextCharacterInfo& info);
|
||||||
|
|
||||||
|
/// Implement to respond to text begin operator
|
||||||
|
virtual void performTextBegin(ProcessOrder order);
|
||||||
|
|
||||||
|
/// Implement to respond to text end operator
|
||||||
|
virtual void performTextEnd(ProcessOrder order);
|
||||||
|
|
||||||
enum class ContentKind
|
enum class ContentKind
|
||||||
{
|
{
|
||||||
Shapes, ///< General shapes (they can be also shaded / tiled)
|
Shapes, ///< General shapes (they can be also shaded / tiled)
|
||||||
|
@ -719,7 +719,129 @@ QImage PDFTransparencyRenderer::toImage(bool use16Bit) const
|
|||||||
|
|
||||||
void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
|
void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
|
||||||
{
|
{
|
||||||
|
PDFPainterPathSampler clipSampler(m_painterStateStack.top().clipPath, m_settings.samplesCount, 1.0f);
|
||||||
|
|
||||||
|
QMatrix worldMatrix = getCurrentWorldMatrix();
|
||||||
|
|
||||||
|
const PDFReal shapeStroking = getShapeStroking();
|
||||||
|
const PDFReal opacityStroking = getOpacityStroking();
|
||||||
|
const PDFReal shapeFilling = getShapeFilling();
|
||||||
|
const PDFReal opacityFilling = getOpacityFilling();
|
||||||
|
|
||||||
|
PDFPixelFormat format = m_drawBuffer.getPixelFormat();
|
||||||
|
Q_ASSERT(format.hasShapeChannel());
|
||||||
|
Q_ASSERT(format.hasOpacityChannel());
|
||||||
|
|
||||||
|
const uint8_t shapeChannel = format.getShapeChannelIndex();
|
||||||
|
const uint8_t opacityChannel = format.getOpacityChannelIndex();
|
||||||
|
const uint8_t colorChannelStart = format.getColorChannelIndexStart();
|
||||||
|
const uint8_t colorChannelEnd = format.getColorChannelIndexEnd();
|
||||||
|
|
||||||
|
if (fill)
|
||||||
|
{
|
||||||
|
QPainterPath worldPath = worldMatrix.map(path);
|
||||||
|
QRect fillRect = getActualFillRect(worldPath.controlPointRect());
|
||||||
|
|
||||||
|
// Fill rect may be, or may not be valid. It depends on the painter path
|
||||||
|
// and world matrix. Path can be translated outside of the paint area.
|
||||||
|
if (fillRect.isValid())
|
||||||
|
{
|
||||||
|
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f);
|
||||||
|
const PDFMappedColor& fillColor = getMappedFillColor();
|
||||||
|
|
||||||
|
for (int x = fillRect.left(); x < fillRect.right(); ++x)
|
||||||
|
{
|
||||||
|
for (int y = fillRect.top(); y < fillRect.bottom(); ++y)
|
||||||
|
{
|
||||||
|
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
|
||||||
|
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
|
||||||
|
const PDFColorComponent shapeValue = objectShapeValue * clipValue * shapeFilling;
|
||||||
|
|
||||||
|
if (shapeValue > 0.0f)
|
||||||
|
{
|
||||||
|
// We consider old object shape - we use Union function to
|
||||||
|
// set shape channel value.
|
||||||
|
|
||||||
|
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
|
||||||
|
pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]);
|
||||||
|
pixel[opacityChannel] = pixel[shapeChannel] * opacityFilling;
|
||||||
|
|
||||||
|
// Copy color
|
||||||
|
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
|
||||||
|
{
|
||||||
|
pixel[colorChannelIndex] = fillColor.mappedColor[colorChannelIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_drawBuffer.markActiveColors(fillColor.activeChannels);
|
||||||
|
m_drawBuffer.modify(fillRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stroke)
|
||||||
|
{
|
||||||
|
// We must stroke the path.
|
||||||
|
QPainterPathStroker stroker;
|
||||||
|
stroker.setCapStyle(m_graphicState.getLineCapStyle());
|
||||||
|
stroker.setWidth(m_graphicState.getLineWidth());
|
||||||
|
stroker.setMiterLimit(m_graphicState.getMitterLimit());
|
||||||
|
stroker.setJoinStyle(m_graphicState.getLineJoinStyle());
|
||||||
|
|
||||||
|
const PDFLineDashPattern& lineDashPattern = m_graphicState.getLineDashPattern();
|
||||||
|
if (!lineDashPattern.isSolid())
|
||||||
|
{
|
||||||
|
stroker.setDashPattern(QVector<PDFReal>::fromStdVector(lineDashPattern.getDashArray()));
|
||||||
|
stroker.setDashOffset(lineDashPattern.getDashOffset());
|
||||||
|
}
|
||||||
|
QPainterPath strokedPath = stroker.createStroke(path);
|
||||||
|
|
||||||
|
QPainterPath worldPath = worldMatrix.map(strokedPath);
|
||||||
|
QRect strokeRect = getActualFillRect(worldPath.controlPointRect());
|
||||||
|
|
||||||
|
// Fill rect may be, or may not be valid. It depends on the painter path
|
||||||
|
// and world matrix. Path can be translated outside of the paint area.
|
||||||
|
if (strokeRect.isValid())
|
||||||
|
{
|
||||||
|
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f);
|
||||||
|
const PDFMappedColor& strokeColor = getMappedStrokeColor();
|
||||||
|
|
||||||
|
for (int x = strokeRect.left(); x < strokeRect.right(); ++x)
|
||||||
|
{
|
||||||
|
for (int y = strokeRect.top(); y < strokeRect.bottom(); ++y)
|
||||||
|
{
|
||||||
|
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
|
||||||
|
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
|
||||||
|
const PDFColorComponent shapeValue = objectShapeValue * clipValue * shapeFilling;
|
||||||
|
|
||||||
|
if (shapeValue > 0.0f)
|
||||||
|
{
|
||||||
|
// We consider old object shape - we use Union function to
|
||||||
|
// set shape channel value.
|
||||||
|
|
||||||
|
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
|
||||||
|
pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]);
|
||||||
|
pixel[opacityChannel] = pixel[shapeChannel] * opacityFilling;
|
||||||
|
|
||||||
|
// Copy color
|
||||||
|
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
|
||||||
|
{
|
||||||
|
pixel[colorChannelIndex] = strokeColor.mappedColor[colorChannelIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_drawBuffer.markActiveColors(strokeColor.activeChannels);
|
||||||
|
m_drawBuffer.modify(strokeRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!text || !getGraphicState()->getTextKnockout())
|
||||||
|
{
|
||||||
|
flushDrawBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFTransparencyRenderer::performClipping(const QPainterPath& path, Qt::FillRule fillRule)
|
void PDFTransparencyRenderer::performClipping(const QPainterPath& path, Qt::FillRule fillRule)
|
||||||
@ -837,6 +959,9 @@ void PDFTransparencyRenderer::performBeginTransparencyGroup(ProcessOrder order,
|
|||||||
// in the immediate backdrop, so we will make it transparent.
|
// in the immediate backdrop, so we will make it transparent.
|
||||||
data.immediateBackdrop.makeTransparent();
|
data.immediateBackdrop.makeTransparent();
|
||||||
|
|
||||||
|
// Create draw buffer
|
||||||
|
m_drawBuffer = PDFDrawBuffer(data.immediateBackdrop.getWidth(), data.immediateBackdrop.getHeight(), data.immediateBackdrop.getPixelFormat());
|
||||||
|
|
||||||
m_transparencyGroupDataStack.emplace_back(qMove(data));
|
m_transparencyGroupDataStack.emplace_back(qMove(data));
|
||||||
invalidateCachedItems();
|
invalidateCachedItems();
|
||||||
}
|
}
|
||||||
@ -860,10 +985,22 @@ void PDFTransparencyRenderer::performEndTransparencyGroup(ProcessOrder order, co
|
|||||||
PDFFloatBitmap::blend(sourceData.immediateBackdrop, targetData.immediateBackdrop, *getBackdrop(), *getInitialBackdrop(), sourceData.softMask,
|
PDFFloatBitmap::blend(sourceData.immediateBackdrop, targetData.immediateBackdrop, *getBackdrop(), *getInitialBackdrop(), sourceData.softMask,
|
||||||
sourceData.alphaIsShape, sourceData.alphaFill, BlendMode::Normal, targetData.group.knockout, 0xFFFF, PDFFloatBitmap::OverprintMode::NoOveprint);
|
sourceData.alphaIsShape, sourceData.alphaFill, BlendMode::Normal, targetData.group.knockout, 0xFFFF, PDFFloatBitmap::OverprintMode::NoOveprint);
|
||||||
|
|
||||||
|
// Create draw buffer
|
||||||
|
PDFFloatBitmapWithColorSpace* backdrop = getImmediateBackdrop();
|
||||||
|
m_drawBuffer = PDFDrawBuffer(backdrop->getWidth(), backdrop->getHeight(), backdrop->getPixelFormat());
|
||||||
|
|
||||||
invalidateCachedItems();
|
invalidateCachedItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFTransparencyRenderer::performTextEnd(ProcessOrder order)
|
||||||
|
{
|
||||||
|
if (order == ProcessOrder::AfterOperation)
|
||||||
|
{
|
||||||
|
flushDrawBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PDFReal PDFTransparencyRenderer::getShapeStroking() const
|
PDFReal PDFTransparencyRenderer::getShapeStroking() const
|
||||||
{
|
{
|
||||||
return getGraphicState()->getAlphaIsShape() ? getGraphicState()->getAlphaStroking() : 1.0;
|
return getGraphicState()->getAlphaIsShape() ? getGraphicState()->getAlphaStroking() : 1.0;
|
||||||
@ -1085,6 +1222,30 @@ PDFTransparencyRenderer::PDFMappedColor PDFTransparencyRenderer::getMappedFillCo
|
|||||||
return createMappedColor(sourceColor, sourceColorSpace);
|
return createMappedColor(sourceColor, sourceColorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect PDFTransparencyRenderer::getPaintRect() const
|
||||||
|
{
|
||||||
|
return QRect(0, 0, getBackdrop()->getWidth(), getBackdrop()->getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect PDFTransparencyRenderer::getActualFillRect(QRectF& fillRect) const
|
||||||
|
{
|
||||||
|
int xLeft = qFloor(fillRect.left()) - 1;
|
||||||
|
int xRight = qCeil(fillRect.right()) + 1;
|
||||||
|
int yTop = qFloor(fillRect.top()) - 1;
|
||||||
|
int yBottom = qCeil(fillRect.bottom()) + 1;
|
||||||
|
|
||||||
|
QRect drawRect(xLeft, yTop, xRight - xLeft, yBottom - yTop);
|
||||||
|
return getPaintRect().intersected(drawRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFTransparencyRenderer::flushDrawBuffer()
|
||||||
|
{
|
||||||
|
if (m_drawBuffer.isModified())
|
||||||
|
{
|
||||||
|
m_drawBuffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PDFInkMapper::PDFInkMapper(const PDFDocument* document) :
|
PDFInkMapper::PDFInkMapper(const PDFDocument* document) :
|
||||||
m_document(document)
|
m_document(document)
|
||||||
{
|
{
|
||||||
@ -1289,4 +1450,109 @@ PDFInkMapping PDFInkMapper::createMapping(const PDFAbstractColorSpace* sourceCol
|
|||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFPainterPathSampler::PDFPainterPathSampler(QPainterPath path, int samplesCount, PDFColorComponent defaultShape) :
|
||||||
|
m_defaultShape(defaultShape),
|
||||||
|
m_samplesCount(samplesCount),
|
||||||
|
m_path(qMove(path))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFColorComponent PDFPainterPathSampler::sample(QPoint point) const
|
||||||
|
{
|
||||||
|
if (m_path.isEmpty())
|
||||||
|
{
|
||||||
|
return m_defaultShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qreal coordX1 = point.x();
|
||||||
|
const qreal coordX2 = coordX1 + 1.0;
|
||||||
|
const qreal coordY1 = point.x();
|
||||||
|
const qreal coordY2 = coordX1 + 1.0;
|
||||||
|
|
||||||
|
const qreal centerX = (coordX1 + coordX2) * 0.5;
|
||||||
|
const qreal centerY = (coordY1 + coordY2) * 0.5;
|
||||||
|
|
||||||
|
const QPointF topLeft(coordX1, coordY1);
|
||||||
|
const QPointF topRight(coordX2, coordY1);
|
||||||
|
const QPointF bottomLeft(coordX1, coordY2);
|
||||||
|
const QPointF bottomRight(coordX2, coordY2);
|
||||||
|
|
||||||
|
if (m_samplesCount <= 1)
|
||||||
|
{
|
||||||
|
// Jakub Melka: Just one sample
|
||||||
|
return m_path.contains(QPointF(centerX, centerY)) ? 1.0f : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cornerHits = 0;
|
||||||
|
|
||||||
|
cornerHits += m_path.contains(topLeft) ? 1 : 0;
|
||||||
|
cornerHits += m_path.contains(topRight) ? 1 : 0;
|
||||||
|
cornerHits += m_path.contains(bottomLeft) ? 1 : 0;
|
||||||
|
cornerHits += m_path.contains(bottomRight) ? 1 : 0;
|
||||||
|
|
||||||
|
if (cornerHits == 4)
|
||||||
|
{
|
||||||
|
// Completely inside
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cornerHits == 0)
|
||||||
|
{
|
||||||
|
// Completely outside
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we must use regular sample grid
|
||||||
|
const qreal offset = 1.0f / PDFColorComponent(m_samplesCount + 1);
|
||||||
|
PDFColorComponent sampleValue = 0.0f;
|
||||||
|
const PDFColorComponent sampleGain = 1.0f / PDFColorComponent(m_samplesCount * m_samplesCount);
|
||||||
|
for (int ix = 0; ix < m_samplesCount; ++ix)
|
||||||
|
{
|
||||||
|
const qreal x = offset * (ix + 1) + coordX1;
|
||||||
|
|
||||||
|
for (int iy = 0; iy < m_samplesCount; ++iy)
|
||||||
|
{
|
||||||
|
const qreal y = offset * (iy + 1) + coordY1;
|
||||||
|
|
||||||
|
if (m_path.contains(QPointF(x, y)))
|
||||||
|
{
|
||||||
|
sampleValue += sampleGain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFDrawBuffer::markActiveColors(uint32_t activeColors)
|
||||||
|
{
|
||||||
|
m_activeColors |= activeColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFDrawBuffer::clear()
|
||||||
|
{
|
||||||
|
if (!m_modifiedRect.isValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = m_modifiedRect.left(); x <= m_modifiedRect.right(); ++x)
|
||||||
|
{
|
||||||
|
for (int y = m_modifiedRect.top(); y <= m_modifiedRect.bottom(); ++y)
|
||||||
|
{
|
||||||
|
PDFColorBuffer buffer = getPixel(x, y);
|
||||||
|
std::fill(buffer.begin(), buffer.end(), 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_activeColors = 0;
|
||||||
|
m_modifiedRect = QRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFDrawBuffer::modify(QRect rect)
|
||||||
|
{
|
||||||
|
m_modifiedRect = m_modifiedRect.united(rect);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -320,6 +320,56 @@ private:
|
|||||||
size_t m_activeSpotColors = 0;
|
size_t m_activeSpotColors = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Painter path sampler. Returns shape value of pixel. This sampler
|
||||||
|
/// uses MSAA with regular grid.
|
||||||
|
class PDFPainterPathSampler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Creates new painter path sampler, using given painter path,
|
||||||
|
/// sample count (in one direction) and default shape used, when painter path is empty.
|
||||||
|
/// \param path Sampled path
|
||||||
|
/// \param samplesCount Samples count in one direction
|
||||||
|
/// \param defaultShape Default shape returned, if path is empty
|
||||||
|
PDFPainterPathSampler(QPainterPath path, int samplesCount, PDFColorComponent defaultShape);
|
||||||
|
|
||||||
|
/// Return sample value for a given pixel
|
||||||
|
PDFColorComponent sample(QPoint point) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PDFColorComponent m_defaultShape = 0.0;
|
||||||
|
int m_samplesCount; ///< Samples count in one direction
|
||||||
|
QPainterPath m_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Represents draw buffer, into which is current graphics drawn
|
||||||
|
class PDFDrawBuffer : public PDFFloatBitmap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PDFFloatBitmap::PDFFloatBitmap;
|
||||||
|
|
||||||
|
/// Marks color channels as active
|
||||||
|
void markActiveColors(uint32_t activeColors);
|
||||||
|
|
||||||
|
/// Clears the draw buffer
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Marks given area as modified
|
||||||
|
void modify(QRect rect);
|
||||||
|
|
||||||
|
/// Returns true, if draw buffer is modified and needs to be flushed
|
||||||
|
bool isModified() const { return m_modifiedRect.isValid(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t m_activeColors = 0;
|
||||||
|
QRect m_modifiedRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PDFTransparencyRendererSettings
|
||||||
|
{
|
||||||
|
/// Sample count for MSAA antialiasing
|
||||||
|
int samplesCount = 16;
|
||||||
|
};
|
||||||
|
|
||||||
/// Renders PDF pages with transparency, using 32-bit floating point precision.
|
/// Renders PDF pages with transparency, using 32-bit floating point precision.
|
||||||
/// Both device color space and blending color space can be defined. It implements
|
/// Both device color space and blending color space can be defined. It implements
|
||||||
/// page blending space and device blending space. So, painted graphics is being
|
/// page blending space and device blending space. So, painted graphics is being
|
||||||
@ -374,6 +424,7 @@ public:
|
|||||||
virtual void performRestoreGraphicState(ProcessOrder order) override;
|
virtual void performRestoreGraphicState(ProcessOrder order) override;
|
||||||
virtual void performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
|
virtual void performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
|
||||||
virtual void performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
|
virtual void performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
|
||||||
|
virtual void performTextEnd(ProcessOrder order) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -382,7 +433,6 @@ private:
|
|||||||
PDFReal getShapeFilling() const;
|
PDFReal getShapeFilling() const;
|
||||||
PDFReal getOpacityFilling() const;
|
PDFReal getOpacityFilling() const;
|
||||||
|
|
||||||
|
|
||||||
struct PDFTransparencyGroupPainterData
|
struct PDFTransparencyGroupPainterData
|
||||||
{
|
{
|
||||||
PDFTransparencyGroup group;
|
PDFTransparencyGroup group;
|
||||||
@ -436,6 +486,17 @@ private:
|
|||||||
PDFMappedColor getMappedStrokeColorImpl();
|
PDFMappedColor getMappedStrokeColorImpl();
|
||||||
PDFMappedColor getMappedFillColorImpl();
|
PDFMappedColor getMappedFillColorImpl();
|
||||||
|
|
||||||
|
/// Returns painting rectangle (i.e. rectangle, which has topleft coordinate 0,0
|
||||||
|
/// and has width/height equal to bitmap width/height)
|
||||||
|
QRect getPaintRect() const;
|
||||||
|
|
||||||
|
/// Returns fill area from fill rectangle
|
||||||
|
/// \param fillRect Fill rectangle
|
||||||
|
QRect getActualFillRect(QRectF& fillRect) const;
|
||||||
|
|
||||||
|
/// Flushes draw buffer
|
||||||
|
void flushDrawBuffer();
|
||||||
|
|
||||||
PDFColorSpacePointer m_deviceColorSpace; ///< Device color space (color space for final result)
|
PDFColorSpacePointer m_deviceColorSpace; ///< Device color space (color space for final result)
|
||||||
PDFColorSpacePointer m_processColorSpace; ///< Process color space (color space, in which is page graphic's blended)
|
PDFColorSpacePointer m_processColorSpace; ///< Process color space (color space, in which is page graphic's blended)
|
||||||
std::unique_ptr<PDFTransparencyGroupGuard> m_pageTransparencyGroupGuard;
|
std::unique_ptr<PDFTransparencyGroupGuard> m_pageTransparencyGroupGuard;
|
||||||
@ -445,6 +506,8 @@ private:
|
|||||||
bool m_active;
|
bool m_active;
|
||||||
PDFCachedItem<PDFMappedColor> m_mappedStrokeColor;
|
PDFCachedItem<PDFMappedColor> m_mappedStrokeColor;
|
||||||
PDFCachedItem<PDFMappedColor> m_mappedFillColor;
|
PDFCachedItem<PDFMappedColor> m_mappedFillColor;
|
||||||
|
PDFTransparencyRendererSettings m_settings;
|
||||||
|
PDFDrawBuffer m_drawBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
Reference in New Issue
Block a user