mirror of https://github.com/JakubMelka/PDF4QT.git
Finishing graphic state parameters
This commit is contained in:
parent
efef799c09
commit
2d29bebe30
|
@ -148,6 +148,15 @@ enum class RendererEngine
|
|||
OpenGL
|
||||
};
|
||||
|
||||
enum class RenderingIntent
|
||||
{
|
||||
Perceptual,
|
||||
AbsoluteColorimetric,
|
||||
RelativeColorimetric,
|
||||
Saturation,
|
||||
Unknown
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFGLOBAL_H
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue