Finishing graphic state parameters

This commit is contained in:
Jakub Melka 2019-10-04 17:21:26 +02:00
parent efef799c09
commit 2d29bebe30
3 changed files with 155 additions and 17 deletions

View File

@ -148,6 +148,15 @@ enum class RendererEngine
OpenGL
};
enum class RenderingIntent
{
Perceptual,
AbsoluteColorimetric,
RelativeColorimetric,
Saturation,
Unknown
};
} // namespace pdf
#endif // PDFGLOBAL_H

View File

@ -1593,7 +1593,7 @@ void PDFPageContentProcessor::operatorSetLineDashPattern()
void PDFPageContentProcessor::operatorSetRenderingIntent(PDFOperandName intent)
{
m_graphicState.setRenderingIntent(intent.name);
setRenderingIntentByName(intent.name);
updateGraphicState();
}
@ -1604,6 +1604,30 @@ void PDFPageContentProcessor::operatorSetFlatness(PDFReal flatness)
updateGraphicState();
}
void PDFPageContentProcessor::setRenderingIntentByName(QByteArray renderingIntentName)
{
RenderingIntent renderingIntent = RenderingIntent::Unknown;
if (renderingIntentName == "Perceptual")
{
renderingIntent = RenderingIntent::Perceptual;
}
else if (renderingIntentName == "AbsoluteColorimetric")
{
renderingIntent = RenderingIntent::AbsoluteColorimetric;
}
else if (renderingIntentName == "RelativeColorimetric")
{
renderingIntent = RenderingIntent::RelativeColorimetric;
}
else if (renderingIntentName == "Saturation")
{
renderingIntent = RenderingIntent::Saturation;
}
m_graphicState.setRenderingIntent(renderingIntent);
m_graphicState.setRenderingIntentName(renderingIntentName);
}
void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* graphicStateDictionary)
{
PDFDocumentDataLoaderDecorator loader(m_document);
@ -1623,18 +1647,14 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
}
}
const PDFObject& renderingIntentObject = m_document->getObject(graphicStateDictionary->get("RI"));
if (renderingIntentObject.isName())
{
m_graphicState.setRenderingIntent(renderingIntentObject.getString());
}
const PDFReal flatness = loader.readNumberFromDictionary(graphicStateDictionary, "FL", m_graphicState.getFlatness());
const PDFReal smoothness = loader.readNumberFromDictionary(graphicStateDictionary, "SM", m_graphicState.getSmoothness());
const bool textKnockout = loader.readBooleanFromDictionary(graphicStateDictionary, "TK", m_graphicState.getTextKnockout());
const PDFReal strokingAlpha = loader.readNumberFromDictionary(graphicStateDictionary, "CA", m_graphicState.getAlphaStroking());
const PDFReal fillingAlpha = loader.readNumberFromDictionary(graphicStateDictionary, "ca", m_graphicState.getAlphaFilling());
QByteArray blendModeName = loader.readNameFromDictionary(graphicStateDictionary, "BM");
QByteArray renderingIntentName = loader.readNameFromDictionary(graphicStateDictionary, "RI");
const bool alphaIsShape = loader.readBooleanFromDictionary(graphicStateDictionary, "AIS", m_graphicState.getAlphaIsShape());
if (!blendModeName.isEmpty())
{
@ -1648,6 +1668,20 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
m_graphicState.setBlendMode(blendMode);
}
if (!renderingIntentName.isEmpty())
{
setRenderingIntentByName(renderingIntentName);
}
PDFOverprintMode overprintMode = m_graphicState.getOverprintMode();
overprintMode.overprintMode = loader.readIntegerFromDictionary(graphicStateDictionary, "OPM", overprintMode.overprintMode);
if (graphicStateDictionary->hasKey("OP"))
{
// Overprint for filling is ruled by overprint for stroking, if "op" is not present, according to the specification
overprintMode.overprintStroking = loader.readBooleanFromDictionary(graphicStateDictionary, "OP", overprintMode.overprintStroking);
overprintMode.overprintFilling = loader.readBooleanFromDictionary(graphicStateDictionary, "op", overprintMode.overprintStroking);
}
m_graphicState.setLineWidth(lineWidth);
m_graphicState.setLineCapStyle(penCapStyle);
m_graphicState.setLineJoinStyle(penJoinStyle);
@ -1657,7 +1691,35 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
m_graphicState.setTextKnockout(textKnockout);
m_graphicState.setAlphaStroking(strokingAlpha);
m_graphicState.setAlphaFilling(fillingAlpha);
m_graphicState.setOverprintMode(overprintMode);
m_graphicState.setAlphaIsShape(alphaIsShape);
updateGraphicState();
if (graphicStateDictionary->hasKey("Font"))
{
const PDFObject& fontObject = m_document->getObject(graphicStateDictionary->get("Font"));
if (fontObject.isArray())
{
const PDFArray* fontObjectArray = fontObject.getArray();
if (fontObjectArray->getCount() == 2)
{
PDFOperandName operandName;
operandName.name = loader.readName(fontObjectArray->getItem(0));
operatorTextSetFontAndFontSize(operandName, loader.readNumber(fontObjectArray->getItem(1), 1.0));
}
}
}
if (graphicStateDictionary->hasKey("SMask"))
{
const PDFObject& softMaskObject = m_document->getObject(graphicStateDictionary->get("SMask"));
bool isNone = (softMaskObject.isName() && softMaskObject.getString() == "None");
if (!isNone)
{
reportRenderError(RenderErrorType::NotSupported, PDFTranslationContext::tr("Soft masks not supported."));
}
}
}
void PDFPageContentProcessor::operatorSetGraphicState(PDFOperandName dictionaryName)
@ -3000,7 +3062,7 @@ PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorSt
m_lineCapStyle(Qt::FlatCap),
m_lineJoinStyle(Qt::MiterJoin),
m_mitterLimit(10.0),
m_renderingIntent(),
m_renderingIntentName(),
m_flatness(1.0),
m_smoothness(0.01),
m_textCharacterSpacing(0.0),
@ -3014,6 +3076,9 @@ PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorSt
m_alphaStroking(1.0),
m_alphaFilling(1.0),
m_blendMode(BlendMode::Normal),
m_renderingIntent(RenderingIntent::Perceptual),
m_overprintMode(),
m_alphaIsShape(false),
m_stateFlags(StateUnchanged)
{
m_fillColorSpace.reset(new PDFDeviceGrayColorSpace);
@ -3037,7 +3102,7 @@ PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor::
setLineJoinStyle(other.getLineJoinStyle());
setMitterLimit(other.getMitterLimit());
setLineDashPattern(other.getLineDashPattern());
setRenderingIntent(other.getRenderingIntent());
setRenderingIntentName(other.getRenderingIntentName());
setFlatness(other.getFlatness());
setSmoothness(other.getSmoothness());
setTextCharacterSpacing(other.getTextCharacterSpacing());
@ -3054,6 +3119,9 @@ PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor::
setAlphaStroking(other.getAlphaStroking());
setAlphaFilling(other.getAlphaFilling());
setBlendMode(other.getBlendMode());
setRenderingIntent(other.getRenderingIntent());
setOverprintMode(other.getOverprintMode());
setAlphaIsShape(other.getAlphaIsShape());
return *this;
}
@ -3147,12 +3215,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setLineDashPattern(P
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntent(const QByteArray& renderingIntent)
void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntentName(const QByteArray& renderingIntentName)
{
if (m_renderingIntent != renderingIntent)
if (m_renderingIntentName != renderingIntentName)
{
m_renderingIntent = renderingIntent;
m_stateFlags |= StateRenderingIntent;
m_renderingIntentName = renderingIntentName;
m_stateFlags |= StateRenderingIntentName;
}
}
@ -3237,6 +3305,15 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setBlendMode(BlendMo
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntent(RenderingIntent renderingIntent)
{
if (m_renderingIntent != renderingIntent)
{
m_renderingIntent = renderingIntent;
m_stateFlags |= StateRenderingIntent;
}
}
QColor PDFPageContentProcessor::PDFPageContentProcessorState::getStrokeColorWithAlpha() const
{
QColor color = getStrokeColor();
@ -3251,6 +3328,24 @@ QColor PDFPageContentProcessor::PDFPageContentProcessorState::getFillColorWithAl
return color;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setOverprintMode(PDFOverprintMode overprintMode)
{
if (m_overprintMode != overprintMode)
{
m_overprintMode = overprintMode;
m_stateFlags |= StateOverprint;
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaIsShape(bool alphaIsShape)
{
if (m_alphaIsShape != alphaIsShape)
{
m_alphaIsShape = alphaIsShape;
m_stateFlags |= StateAlphaIsShape;
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextMatrix(const QMatrix& textMatrix)
{
if (m_textMatrix != textMatrix)

View File

@ -205,6 +205,22 @@ protected:
bool knockout = false;
};
struct PDFOverprintMode
{
bool overprintStroking = false;
bool overprintFilling = false;
int overprintMode = 0;
inline bool operator==(const PDFOverprintMode& other) const
{
return std::tie(overprintStroking, overprintFilling, overprintMode) == std::tie(other.overprintStroking, other.overprintFilling, other.overprintMode);
}
inline bool operator!=(const PDFOverprintMode& other) const
{
return !(*this == other);
}
};
/// Represents graphic state of the PDF (holding current graphic state parameters).
/// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State"
class PDFPageContentProcessorState
@ -232,7 +248,7 @@ protected:
StateLineJoinStyle = 0x00000080,
StateMitterLimit = 0x00000100,
StateLineDashPattern = 0x00000200,
StateRenderingIntent = 0x00000400,
StateRenderingIntentName = 0x00000400,
StateFlatness = 0x00000800,
StateSmoothness = 0x00001000,
StateTextMatrix = 0x00002000,
@ -249,6 +265,9 @@ protected:
StateAlphaStroking = 0x01000000,
StateAlphaFilling = 0x02000000,
StateBlendMode = 0x04000000,
StateRenderingIntent = 0x08000000,
StateOverprint = 0x10000000,
StateAlphaIsShape = 0x20000000,
StateAll = 0xFFFFFFFF
};
@ -284,8 +303,8 @@ protected:
const PDFLineDashPattern& getLineDashPattern() const { return m_lineDashPattern; }
void setLineDashPattern(PDFLineDashPattern pattern);
const QByteArray& getRenderingIntent() const { return m_renderingIntent; }
void setRenderingIntent(const QByteArray& renderingIntent);
const QByteArray& getRenderingIntentName() const { return m_renderingIntentName; }
void setRenderingIntentName(const QByteArray& renderingIntentName);
PDFReal getFlatness() const { return m_flatness; }
void setFlatness(PDFReal flatness);
@ -338,12 +357,21 @@ protected:
BlendMode getBlendMode() const { return m_blendMode; }
void setBlendMode(BlendMode mode);
RenderingIntent getRenderingIntent() const { return m_renderingIntent; }
void setRenderingIntent(RenderingIntent renderingIntent);
/// Returns stroke color with alpha channel
QColor getStrokeColorWithAlpha() const;
/// Returns fill color with alpha channel
QColor getFillColorWithAlpha() const;
PDFOverprintMode getOverprintMode() const { return m_overprintMode; }
void setOverprintMode(PDFOverprintMode overprintMode);
bool getAlphaIsShape() const { return m_alphaIsShape; }
void setAlphaIsShape(bool alphaIsShape);
private:
QMatrix m_currentTransformationMatrix;
PDFColorSpacePointer m_strokeColorSpace;
@ -355,7 +383,7 @@ protected:
Qt::PenJoinStyle m_lineJoinStyle;
PDFReal m_mitterLimit;
PDFLineDashPattern m_lineDashPattern;
QByteArray m_renderingIntent;
QByteArray m_renderingIntentName;
PDFReal m_flatness;
PDFReal m_smoothness;
PDFReal m_textCharacterSpacing; // T_c
@ -372,6 +400,9 @@ protected:
PDFReal m_alphaStroking;
PDFReal m_alphaFilling;
BlendMode m_blendMode;
RenderingIntent m_renderingIntent;
PDFOverprintMode m_overprintMode;
bool m_alphaIsShape;
StateFlags m_stateFlags;
};
@ -802,6 +833,9 @@ private:
/// Report warning about color operators in uncolored tiling pattern
void reportWarningAboutColorOperatorsInUTP();
/// Set rendering intent by name
void setRenderingIntentByName(QByteArray renderingIntentName);
const PDFPage* m_page;
const PDFDocument* m_document;
const PDFFontCache* m_fontCache;