mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Transparency groups
This commit is contained in:
@ -374,6 +374,18 @@ void PDFPageContentProcessor::performSetCacheDevice(PDFReal wx, PDFReal wy, PDFR
|
|||||||
Q_UNUSED(ury);
|
Q_UNUSED(ury);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFPageContentProcessor::performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup)
|
||||||
|
{
|
||||||
|
Q_UNUSED(order);
|
||||||
|
Q_UNUSED(transparencyGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFPageContentProcessor::performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup)
|
||||||
|
{
|
||||||
|
Q_UNUSED(order);
|
||||||
|
Q_UNUSED(transparencyGroup);
|
||||||
|
}
|
||||||
|
|
||||||
bool PDFPageContentProcessor::isContentSuppressed() const
|
bool PDFPageContentProcessor::isContentSuppressed() const
|
||||||
{
|
{
|
||||||
return std::any_of(m_markedContentStack.cbegin(), m_markedContentStack.cend(), [](const MarkedContentState& state) { return state.contentSuppressed; });
|
return std::any_of(m_markedContentStack.cbegin(), m_markedContentStack.cend(), [](const MarkedContentState& state) { return state.contentSuppressed; });
|
||||||
@ -554,10 +566,38 @@ void PDFPageContentProcessor::processContentStream(const PDFStream* stream)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::processForm(const QMatrix& matrix, const QRectF& boundingBox, const PDFObject& resources, const QByteArray& content)
|
void PDFPageContentProcessor::processForm(const QMatrix& matrix,
|
||||||
|
const QRectF& boundingBox,
|
||||||
|
const PDFObject& resources,
|
||||||
|
const PDFObject& transparencyGroup,
|
||||||
|
const QByteArray& content)
|
||||||
{
|
{
|
||||||
PDFPageContentProcessorStateGuard guard(this);
|
PDFPageContentProcessorStateGuard guard(this);
|
||||||
|
|
||||||
|
std::unique_ptr<PDFTransparencyGroupGuard> guard2;
|
||||||
|
if (transparencyGroup.isDictionary())
|
||||||
|
{
|
||||||
|
// Parse the transparency group
|
||||||
|
const PDFDictionary* transparencyDictionary = transparencyGroup.getDictionary();
|
||||||
|
PDFDocumentDataLoaderDecorator loader(m_document);
|
||||||
|
PDFTransparencyGroup group;
|
||||||
|
|
||||||
|
const PDFObject& colorSpaceObject = m_document->getObject(transparencyDictionary->get("CS"));
|
||||||
|
if (!colorSpaceObject.isNull())
|
||||||
|
{
|
||||||
|
group.colorSpacePointer = PDFAbstractColorSpace::createColorSpace(m_colorSpaceDictionary, m_document, colorSpaceObject);
|
||||||
|
}
|
||||||
|
group.isolated = loader.readBooleanFromDictionary(transparencyDictionary, "I", false);
|
||||||
|
group.knockout = loader.readBooleanFromDictionary(transparencyDictionary, "K", false);
|
||||||
|
guard2.reset(new PDFTransparencyGroupGuard(this, qMove(group)));
|
||||||
|
|
||||||
|
// If we are in transparency group, we must reset transparency settings in the graphic state.
|
||||||
|
// Graphic state is then updated in the lines below.
|
||||||
|
m_graphicState.setBlendMode(BlendMode::Normal);
|
||||||
|
m_graphicState.setAlphaFilling(1.0);
|
||||||
|
m_graphicState.setAlphaStroking(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
QMatrix formMatrix = matrix * m_graphicState.getCurrentTransformationMatrix();
|
QMatrix formMatrix = matrix * m_graphicState.getCurrentTransformationMatrix();
|
||||||
m_graphicState.setCurrentTransformationMatrix(formMatrix);
|
m_graphicState.setCurrentTransformationMatrix(formMatrix);
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
@ -2640,7 +2680,10 @@ void PDFPageContentProcessor::operatorPaintXObject(PDFPageContentProcessor::PDFO
|
|||||||
// Read resources
|
// Read resources
|
||||||
PDFObject resources = m_document->getObject(streamDictionary->get("Resources"));
|
PDFObject resources = m_document->getObject(streamDictionary->get("Resources"));
|
||||||
|
|
||||||
processForm(transformationMatrix, boundingBox, resources, content);
|
// Transparency group
|
||||||
|
PDFObject transparencyGroup = m_document->getObject(streamDictionary->get("Group"));
|
||||||
|
|
||||||
|
processForm(transformationMatrix, boundingBox, resources, transparencyGroup, content);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3298,4 +3341,20 @@ PDFPageContentProcessor::PDFPageContentProcessorStateGuard::~PDFPageContentProce
|
|||||||
m_processor->operatorRestoreGraphicState();
|
m_processor->operatorRestoreGraphicState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFPageContentProcessor::PDFTransparencyGroupGuard::PDFTransparencyGroupGuard(PDFPageContentProcessor* processor, PDFTransparencyGroup&& group) :
|
||||||
|
m_processor(processor)
|
||||||
|
{
|
||||||
|
m_processor->performBeginTransparencyGroup(ProcessOrder::BeforeOperation, group);
|
||||||
|
m_processor->m_transparencyGroupStack.push(qMove(group));
|
||||||
|
m_processor->performBeginTransparencyGroup(ProcessOrder::AfterOperation, m_processor->m_transparencyGroupStack.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFPageContentProcessor::PDFTransparencyGroupGuard::~PDFTransparencyGroupGuard()
|
||||||
|
{
|
||||||
|
m_processor->performEndTransparencyGroup(ProcessOrder::BeforeOperation, m_processor->m_transparencyGroupStack.top());
|
||||||
|
PDFTransparencyGroup group = qMove(m_processor->m_transparencyGroupStack.top());
|
||||||
|
m_processor->m_transparencyGroupStack.pop();
|
||||||
|
m_processor->performEndTransparencyGroup(ProcessOrder::AfterOperation, group);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -198,6 +198,13 @@ protected:
|
|||||||
PDFReal m_dashOffset = 0.0;
|
PDFReal m_dashOffset = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PDFTransparencyGroup
|
||||||
|
{
|
||||||
|
PDFColorSpacePointer colorSpacePointer;
|
||||||
|
bool isolated = false;
|
||||||
|
bool knockout = false;
|
||||||
|
};
|
||||||
|
|
||||||
/// Represents graphic state of the PDF (holding current graphic state parameters).
|
/// Represents graphic state of the PDF (holding current graphic state parameters).
|
||||||
/// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State"
|
/// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State"
|
||||||
class PDFPageContentProcessorState
|
class PDFPageContentProcessorState
|
||||||
@ -435,6 +442,16 @@ protected:
|
|||||||
/// Implement to react on set cache device request
|
/// Implement to react on set cache device request
|
||||||
virtual void performSetCacheDevice(PDFReal wx, PDFReal wy, PDFReal llx, PDFReal lly, PDFReal urx, PDFReal ury);
|
virtual void performSetCacheDevice(PDFReal wx, PDFReal wy, PDFReal llx, PDFReal lly, PDFReal urx, PDFReal ury);
|
||||||
|
|
||||||
|
/// Implement to begin new transparency group
|
||||||
|
/// \param Order, in which is function called (before/after setting new transparency group)
|
||||||
|
/// \param transparencyGroup Transparency group
|
||||||
|
virtual void performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup);
|
||||||
|
|
||||||
|
/// Implement to end current transparency group
|
||||||
|
/// \param Order, in which is function called (before/after setting new transparency group)
|
||||||
|
/// \param transparencyGroup Transparency group
|
||||||
|
virtual void performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup);
|
||||||
|
|
||||||
/// Returns current graphic state
|
/// Returns current graphic state
|
||||||
const PDFPageContentProcessorState* getGraphicState() const { return &m_graphicState; }
|
const PDFPageContentProcessorState* getGraphicState() const { return &m_graphicState; }
|
||||||
|
|
||||||
@ -478,8 +495,9 @@ private:
|
|||||||
/// \param Matrix Transformation matrix from form coordinate system to page coordinate system
|
/// \param Matrix Transformation matrix from form coordinate system to page coordinate system
|
||||||
/// \param boundingBox Bounding box, to which is drawed content clipped
|
/// \param boundingBox Bounding box, to which is drawed content clipped
|
||||||
/// \param resources Resources, assigned to the form
|
/// \param resources Resources, assigned to the form
|
||||||
|
/// \param transparencyGroup Transparency group object
|
||||||
/// \param content Content stream of the form
|
/// \param content Content stream of the form
|
||||||
void processForm(const QMatrix& matrix, const QRectF& boundingBox, const PDFObject& resources, const QByteArray& content);
|
void processForm(const QMatrix& matrix, const QRectF& boundingBox, const PDFObject& resources, const PDFObject& transparencyGroup, const QByteArray& content);
|
||||||
|
|
||||||
/// Performs path painting
|
/// Performs path painting
|
||||||
/// \param path Path, which should be drawn (can be emtpy - in that case nothing happens)
|
/// \param path Path, which should be drawn (can be emtpy - in that case nothing happens)
|
||||||
@ -525,7 +543,7 @@ private:
|
|||||||
bool contentSuppressed = false;
|
bool contentSuppressed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PDFPageContentProcessorStateGuard
|
class PDFPageContentProcessorStateGuard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFPageContentProcessorStateGuard(PDFPageContentProcessor* processor);
|
explicit PDFPageContentProcessorStateGuard(PDFPageContentProcessor* processor);
|
||||||
@ -544,7 +562,7 @@ private:
|
|||||||
const PDFDictionary* m_patternDictionary;
|
const PDFDictionary* m_patternDictionary;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PDFPageContentProcessorGraphicStateSaveRestoreGuard
|
class PDFPageContentProcessorGraphicStateSaveRestoreGuard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline explicit PDFPageContentProcessorGraphicStateSaveRestoreGuard(PDFPageContentProcessor* processor) :
|
inline explicit PDFPageContentProcessorGraphicStateSaveRestoreGuard(PDFPageContentProcessor* processor) :
|
||||||
@ -561,6 +579,16 @@ private:
|
|||||||
PDFPageContentProcessor* m_processor;
|
PDFPageContentProcessor* m_processor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PDFTransparencyGroupGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PDFTransparencyGroupGuard(PDFPageContentProcessor* processor, PDFTransparencyGroup&& group);
|
||||||
|
~PDFTransparencyGroupGuard();
|
||||||
|
|
||||||
|
private:
|
||||||
|
PDFPageContentProcessor* m_processor;
|
||||||
|
};
|
||||||
|
|
||||||
/// Wrapper for PDF Name
|
/// Wrapper for PDF Name
|
||||||
struct PDFOperandName
|
struct PDFOperandName
|
||||||
{
|
{
|
||||||
@ -797,6 +825,9 @@ private:
|
|||||||
/// Stack with saved graphic states
|
/// Stack with saved graphic states
|
||||||
std::stack<PDFPageContentProcessorState> m_stack;
|
std::stack<PDFPageContentProcessorState> m_stack;
|
||||||
|
|
||||||
|
/// Stack with transparency groups
|
||||||
|
std::stack<PDFTransparencyGroup> m_transparencyGroupStack;
|
||||||
|
|
||||||
/// Stack with marked content
|
/// Stack with marked content
|
||||||
std::vector<MarkedContentState> m_markedContentStack;
|
std::vector<MarkedContentState> m_markedContentStack;
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ void PDFPainter::performMeshPainting(const PDFMesh& mesh)
|
|||||||
{
|
{
|
||||||
m_painter->save();
|
m_painter->save();
|
||||||
m_painter->setWorldMatrix(QMatrix());
|
m_painter->setWorldMatrix(QMatrix());
|
||||||
mesh.paint(m_painter, getGraphicState()->getAlphaFilling());
|
mesh.paint(m_painter, getEffectiveFillingAlpha());
|
||||||
m_painter->restore();
|
m_painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,15 +188,26 @@ void PDFPainter::performUpdateGraphicsState(const PDFPageContentProcessorState&
|
|||||||
// If current blend mode has changed, then update it
|
// If current blend mode has changed, then update it
|
||||||
if (flags.testFlag(PDFPageContentProcessorState::StateBlendMode))
|
if (flags.testFlag(PDFPageContentProcessorState::StateBlendMode))
|
||||||
{
|
{
|
||||||
|
// Try to simulate transparency groups. Use only first composition mode,
|
||||||
|
// outside the transparency groups (so we are on pages main transparency
|
||||||
|
// groups).
|
||||||
|
|
||||||
const BlendMode blendMode = state.getBlendMode();
|
const BlendMode blendMode = state.getBlendMode();
|
||||||
const QPainter::CompositionMode compositionMode = PDFBlendModeInfo::getCompositionModeFromBlendMode(blendMode);
|
if (canSetBlendMode(blendMode))
|
||||||
|
|
||||||
if (!PDFBlendModeInfo::isSupportedByQt(blendMode))
|
|
||||||
{
|
{
|
||||||
reportRenderError(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Blend mode '%1' not supported.").arg(PDFBlendModeInfo::getBlendModeName(blendMode)));
|
const QPainter::CompositionMode compositionMode = PDFBlendModeInfo::getCompositionModeFromBlendMode(blendMode);
|
||||||
}
|
|
||||||
|
|
||||||
m_painter->setCompositionMode(compositionMode);
|
if (!PDFBlendModeInfo::isSupportedByQt(blendMode))
|
||||||
|
{
|
||||||
|
reportRenderError(RenderErrorType::NotSupported, PDFTranslationContext::tr("Blend mode '%1' not supported.").arg(PDFBlendModeInfo::getBlendModeName(blendMode)));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_painter->setCompositionMode(compositionMode);
|
||||||
|
}
|
||||||
|
else if (blendMode != BlendMode::Normal && blendMode != BlendMode::Compatible)
|
||||||
|
{
|
||||||
|
reportRenderError(RenderErrorType::NotSupported, PDFTranslationContext::tr("Blend mode '%1' is in transparency group, which is not supported.").arg(PDFBlendModeInfo::getBlendModeName(blendMode)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFPageContentProcessor::performUpdateGraphicsState(state);
|
PDFPageContentProcessor::performUpdateGraphicsState(state);
|
||||||
@ -218,6 +229,29 @@ void PDFPainter::performRestoreGraphicState(ProcessOrder order)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFPainter::performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup)
|
||||||
|
{
|
||||||
|
if (order == ProcessOrder::BeforeOperation)
|
||||||
|
{
|
||||||
|
PDFTransparencyGroupPainterData data;
|
||||||
|
data.group = transparencyGroup;
|
||||||
|
data.alphaFill = getGraphicState()->getAlphaFilling();
|
||||||
|
data.alphaStroke = getGraphicState()->getAlphaStroking();
|
||||||
|
data.blendMode = getGraphicState()->getBlendMode();
|
||||||
|
m_transparencyGroupDataStack.emplace_back(qMove(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFPainter::performEndTransparencyGroup(PDFPageContentProcessor::ProcessOrder order, const PDFPageContentProcessor::PDFTransparencyGroup& transparencyGroup)
|
||||||
|
{
|
||||||
|
Q_UNUSED(transparencyGroup);
|
||||||
|
|
||||||
|
if (order == ProcessOrder::AfterOperation)
|
||||||
|
{
|
||||||
|
m_transparencyGroupDataStack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool PDFPainter::isContentSuppressedByOC(PDFObjectReference ocgOrOcmd)
|
bool PDFPainter::isContentSuppressedByOC(PDFObjectReference ocgOrOcmd)
|
||||||
{
|
{
|
||||||
if (m_features.testFlag(PDFRenderer::IgnoreOptionalContent))
|
if (m_features.testFlag(PDFRenderer::IgnoreOptionalContent))
|
||||||
@ -231,9 +265,10 @@ bool PDFPainter::isContentSuppressedByOC(PDFObjectReference ocgOrOcmd)
|
|||||||
QPen PDFPainter::getCurrentPenImpl() const
|
QPen PDFPainter::getCurrentPenImpl() const
|
||||||
{
|
{
|
||||||
const PDFPageContentProcessorState* graphicState = getGraphicState();
|
const PDFPageContentProcessorState* graphicState = getGraphicState();
|
||||||
const QColor& color = graphicState->getStrokeColorWithAlpha();
|
QColor color = graphicState->getStrokeColor();
|
||||||
if (color.isValid())
|
if (color.isValid())
|
||||||
{
|
{
|
||||||
|
color.setAlphaF(getEffectiveStrokingAlpha());
|
||||||
const PDFReal lineWidth = graphicState->getLineWidth();
|
const PDFReal lineWidth = graphicState->getLineWidth();
|
||||||
Qt::PenCapStyle penCapStyle = graphicState->getLineCapStyle();
|
Qt::PenCapStyle penCapStyle = graphicState->getLineCapStyle();
|
||||||
Qt::PenJoinStyle penJoinStyle = graphicState->getLineJoinStyle();
|
Qt::PenJoinStyle penJoinStyle = graphicState->getLineJoinStyle();
|
||||||
@ -269,9 +304,10 @@ QPen PDFPainter::getCurrentPenImpl() const
|
|||||||
QBrush PDFPainter::getCurrentBrushImpl() const
|
QBrush PDFPainter::getCurrentBrushImpl() const
|
||||||
{
|
{
|
||||||
const PDFPageContentProcessorState* graphicState = getGraphicState();
|
const PDFPageContentProcessorState* graphicState = getGraphicState();
|
||||||
const QColor& color = graphicState->getFillColorWithAlpha();
|
QColor color = graphicState->getFillColor();
|
||||||
if (color.isValid())
|
if (color.isValid())
|
||||||
{
|
{
|
||||||
|
color.setAlphaF(getEffectiveFillingAlpha());
|
||||||
return QBrush(color, Qt::SolidPattern);
|
return QBrush(color, Qt::SolidPattern);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -280,4 +316,54 @@ QBrush PDFPainter::getCurrentBrushImpl() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFReal PDFPainter::getEffectiveStrokingAlpha() const
|
||||||
|
{
|
||||||
|
PDFReal alpha = getGraphicState()->getAlphaStroking();
|
||||||
|
|
||||||
|
auto it = m_transparencyGroupDataStack.crbegin();
|
||||||
|
auto itEnd = m_transparencyGroupDataStack.crend();
|
||||||
|
for (; it != itEnd; ++it)
|
||||||
|
{
|
||||||
|
const PDFTransparencyGroupPainterData& transparencyGroup = *it;
|
||||||
|
alpha *= transparencyGroup.alphaStroke;
|
||||||
|
|
||||||
|
if (transparencyGroup.group.isolated)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFReal PDFPainter::getEffectiveFillingAlpha() const
|
||||||
|
{
|
||||||
|
PDFReal alpha = getGraphicState()->getAlphaFilling();
|
||||||
|
|
||||||
|
auto it = m_transparencyGroupDataStack.crbegin();
|
||||||
|
auto itEnd = m_transparencyGroupDataStack.crend();
|
||||||
|
for (; it != itEnd; ++it)
|
||||||
|
{
|
||||||
|
const PDFTransparencyGroupPainterData& transparencyGroup = *it;
|
||||||
|
alpha *= transparencyGroup.alphaFill;
|
||||||
|
|
||||||
|
if (transparencyGroup.group.isolated)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFPainter::canSetBlendMode(BlendMode mode) const
|
||||||
|
{
|
||||||
|
// We will assume, that we can set blend mode, when
|
||||||
|
// all other blend modes on transparency stack are normal,
|
||||||
|
// or compatible. It should work.
|
||||||
|
|
||||||
|
Q_UNUSED(mode);
|
||||||
|
return std::all_of(m_transparencyGroupDataStack.cbegin(), m_transparencyGroupDataStack.cend(), [](const PDFTransparencyGroupPainterData& group) { return group.blendMode == BlendMode::Normal || group.blendMode == BlendMode::Compatible; });
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -30,6 +30,8 @@ namespace pdf
|
|||||||
|
|
||||||
/// Processor, which processes PDF's page commands on the QPainter. It works with QPainter
|
/// Processor, which processes PDF's page commands on the QPainter. It works with QPainter
|
||||||
/// and with transformation matrix, which translates page points to the device points.
|
/// and with transformation matrix, which translates page points to the device points.
|
||||||
|
/// Only basic transparency is supported, advanced transparency, such as transparency groups,
|
||||||
|
/// are not supported. Painter will try to emulate them so painting will not fail completely.
|
||||||
class PDFPainter : public PDFPageContentProcessor
|
class PDFPainter : public PDFPageContentProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -60,6 +62,8 @@ protected:
|
|||||||
virtual void performUpdateGraphicsState(const PDFPageContentProcessorState& state) override;
|
virtual void performUpdateGraphicsState(const PDFPageContentProcessorState& state) override;
|
||||||
virtual void performSaveGraphicState(ProcessOrder order) override;
|
virtual void performSaveGraphicState(ProcessOrder order) override;
|
||||||
virtual void performRestoreGraphicState(ProcessOrder order) override;
|
virtual void performRestoreGraphicState(ProcessOrder order) override;
|
||||||
|
virtual void performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup);
|
||||||
|
virtual void performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup);
|
||||||
virtual bool isContentSuppressedByOC(PDFObjectReference ocgOrOcmd) override;
|
virtual bool isContentSuppressedByOC(PDFObjectReference ocgOrOcmd) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -75,10 +79,28 @@ private:
|
|||||||
/// Returns current brush (implementation)
|
/// Returns current brush (implementation)
|
||||||
QBrush getCurrentBrushImpl() const;
|
QBrush getCurrentBrushImpl() const;
|
||||||
|
|
||||||
|
/// Returns effective stroking alpha from transparency groups and current graphic state
|
||||||
|
PDFReal getEffectiveStrokingAlpha() const;
|
||||||
|
|
||||||
|
/// Returns effective filling alpha from transparency groups and current graphic state
|
||||||
|
PDFReal getEffectiveFillingAlpha() const;
|
||||||
|
|
||||||
|
/// Returns true, if blend mode can be set according the transparency group stack
|
||||||
|
bool canSetBlendMode(BlendMode mode) const;
|
||||||
|
|
||||||
|
struct PDFTransparencyGroupPainterData
|
||||||
|
{
|
||||||
|
PDFTransparencyGroup group;
|
||||||
|
PDFReal alphaStroke = 1.0;
|
||||||
|
PDFReal alphaFill = 1.0;
|
||||||
|
BlendMode blendMode = BlendMode::Normal;
|
||||||
|
};
|
||||||
|
|
||||||
QPainter* m_painter;
|
QPainter* m_painter;
|
||||||
PDFRenderer::Features m_features;
|
PDFRenderer::Features m_features;
|
||||||
PDFCachedItem<QPen> m_currentPen;
|
PDFCachedItem<QPen> m_currentPen;
|
||||||
PDFCachedItem<QBrush> m_currentBrush;
|
PDFCachedItem<QBrush> m_currentBrush;
|
||||||
|
std::vector<PDFTransparencyGroupPainterData> m_transparencyGroupDataStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
Reference in New Issue
Block a user