diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp index 7ecc625..d907821 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp @@ -1743,6 +1743,20 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap QByteArray blendModeName = loader.readNameFromDictionary(graphicStateDictionary, "BM"); QByteArray renderingIntentName = loader.readNameFromDictionary(graphicStateDictionary, "RI"); const bool alphaIsShape = loader.readBooleanFromDictionary(graphicStateDictionary, "AIS", m_graphicState.getAlphaIsShape()); + const bool strokeAdjustment = loader.readBooleanFromDictionary(graphicStateDictionary, "SA", m_graphicState.getStrokeAdjustment()); + const PDFDictionary* softMask = m_document->getDictionaryFromObject(graphicStateDictionary->get("SMask")); + + // We will try to get blend mode name from the array (if BM is array). First supported blend mode should + // be used. In PDF 2.0, array is deprecated, so for backward compatibility, we extract first blend mode + // name from the array and try to use it. + if (blendModeName.isEmpty()) + { + std::vector blendModeNames = loader.readNameArrayFromDictionary(graphicStateDictionary, "BM"); + if (!blendModeNames.empty()) + { + blendModeName = qMove(blendModeNames.front()); + } + } if (!blendModeName.isEmpty()) { @@ -1781,6 +1795,8 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap m_graphicState.setAlphaFilling(fillingAlpha); m_graphicState.setOverprintMode(overprintMode); m_graphicState.setAlphaIsShape(alphaIsShape); + m_graphicState.setStrokeAdjustment(strokeAdjustment); + m_graphicState.setSoftMask(softMask); updateGraphicState(); if (graphicStateDictionary->hasKey("Font")) @@ -1797,17 +1813,6 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap } } } - - if (graphicStateDictionary->hasKey("SMask")) - { - const PDFObject& softMaskObject = m_document->getObject(graphicStateDictionary->get("SMask")); - - bool isNone = (softMaskObject.isName() && softMaskObject.getString() == "None"); - if (!isNone) - { - reportRenderErrorOnce(RenderErrorType::NotSupported, PDFTranslationContext::tr("Soft masks not supported.")); - } - } } void PDFPageContentProcessor::operatorSetGraphicState(PDFOperandName dictionaryName) @@ -3201,6 +3206,8 @@ PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorSt m_renderingIntent(RenderingIntent::Perceptual), m_overprintMode(), m_alphaIsShape(false), + m_strokeAdjustment(false), + m_softMask(nullptr), m_stateFlags(StateUnchanged) { m_fillColorSpace.reset(new PDFDeviceGrayColorSpace); @@ -3244,6 +3251,8 @@ PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor:: setRenderingIntent(other.getRenderingIntent()); setOverprintMode(other.getOverprintMode()); setAlphaIsShape(other.getAlphaIsShape()); + setStrokeAdjustment(other.getStrokeAdjustment()); + setSoftMask(other.getSoftMask()); return *this; } @@ -3468,6 +3477,34 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaIsShape(bool } } +bool PDFPageContentProcessor::PDFPageContentProcessorState::getStrokeAdjustment() const +{ + return m_strokeAdjustment; +} + +void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeAdjustment(bool strokeAdjustment) +{ + if (m_strokeAdjustment != strokeAdjustment) + { + m_strokeAdjustment = strokeAdjustment; + m_stateFlags |= StateStrokeAdjustment; + } +} + +const PDFDictionary* PDFPageContentProcessor::PDFPageContentProcessorState::getSoftMask() const +{ + return m_softMask; +} + +void PDFPageContentProcessor::PDFPageContentProcessorState::setSoftMask(const PDFDictionary* softMask) +{ + if (m_softMask != softMask) + { + m_softMask = softMask; + m_stateFlags |= StateSoftMask; + } +} + void PDFPageContentProcessor::PDFPageContentProcessorState::setTextMatrix(const QMatrix& textMatrix) { if (m_textMatrix != textMatrix) diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.h b/PdfForQtLib/sources/pdfpagecontentprocessor.h index c333ae0..c2d3f7b 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.h +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.h @@ -306,6 +306,8 @@ protected: StateRenderingIntent = 0x08000000, StateOverprint = 0x10000000, StateAlphaIsShape = 0x20000000, + StateStrokeAdjustment = 0x40000000, + StateSoftMask = 0x80000000, StateAll = 0xFFFFFFFF }; @@ -410,6 +412,12 @@ protected: bool getAlphaIsShape() const { return m_alphaIsShape; } void setAlphaIsShape(bool alphaIsShape); + bool getStrokeAdjustment() const; + void setStrokeAdjustment(bool strokeAdjustment); + + const PDFDictionary* getSoftMask() const; + void setSoftMask(const PDFDictionary* softMask); + private: QMatrix m_currentTransformationMatrix; PDFColorSpacePointer m_strokeColorSpace; @@ -441,6 +449,8 @@ protected: RenderingIntent m_renderingIntent; PDFOverprintMode m_overprintMode; bool m_alphaIsShape; + bool m_strokeAdjustment; + const PDFDictionary* m_softMask; StateFlags m_stateFlags; }; diff --git a/PdfForQtLib/sources/pdfpainter.cpp b/PdfForQtLib/sources/pdfpainter.cpp index 3db4700..878e89c 100644 --- a/PdfForQtLib/sources/pdfpainter.cpp +++ b/PdfForQtLib/sources/pdfpainter.cpp @@ -89,6 +89,11 @@ void PDFPainterBase::performUpdateGraphicsState(const PDFPageContentProcessorSta } } + if (flags.testFlag(PDFPageContentProcessorState::StateSoftMask) && state.getSoftMask()) + { + reportRenderErrorOnce(RenderErrorType::NotSupported, PDFTranslationContext::tr("Soft masks not supported.")); + } + BaseClass::performUpdateGraphicsState(state); }