mirror of https://github.com/JakubMelka/PDF4QT.git
Adjust graphic state according to the PDF 2.0 specification
This commit is contained in:
parent
8262654b0e
commit
c033de6917
|
@ -79,6 +79,13 @@ static constexpr const char* ICCBASED_ALTERNATE = "Alternate";
|
|||
static constexpr const char* ICCBASED_N = "N";
|
||||
static constexpr const char* ICCBASED_RANGE = "Range";
|
||||
|
||||
enum class BlackPointCompensationMode
|
||||
{
|
||||
Default,
|
||||
ON,
|
||||
OFF
|
||||
};
|
||||
|
||||
/// Image raw data - containing data for image. Image data are row-ordered, and by components.
|
||||
/// So the row can be for 3-components RGB like 'RGBRGBRGB...RGB', where size of row in bytes is 3 * width of image.
|
||||
class PDFImageData
|
||||
|
|
|
@ -1722,7 +1722,7 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
|
|||
const PDFReal lineWidth = loader.readNumberFromDictionary(graphicStateDictionary, "LW", m_graphicState.getLineWidth());
|
||||
const Qt::PenCapStyle penCapStyle = convertLineCapToPenCapStyle(loader.readNumberFromDictionary(graphicStateDictionary, "LC", convertPenCapStyleToLineCap(m_graphicState.getLineCapStyle())));
|
||||
const Qt::PenJoinStyle penJoinStyle = convertLineJoinToPenJoinStyle(loader.readNumberFromDictionary(graphicStateDictionary, "LJ", convertPenJoinStyleToLineJoin(m_graphicState.getLineJoinStyle())));
|
||||
const PDFReal mitterLimit = loader.readNumberFromDictionary(graphicStateDictionary, "MT", m_graphicState.getMitterLimit());
|
||||
const PDFReal mitterLimit = loader.readNumberFromDictionary(graphicStateDictionary, "ML", m_graphicState.getMitterLimit());
|
||||
|
||||
const PDFObject& lineDashPatternObject = m_document->getObject(graphicStateDictionary->get("D"));
|
||||
if (lineDashPatternObject.isArray())
|
||||
|
@ -1731,6 +1731,7 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
|
|||
if (lineDashPatternDefinitionArray->getCount() == 2)
|
||||
{
|
||||
PDFLineDashPattern pattern(loader.readNumberArray(lineDashPatternDefinitionArray->getItem(0)), loader.readNumber(lineDashPatternDefinitionArray->getItem(1), 0.0));
|
||||
pattern.fix();
|
||||
m_graphicState.setLineDashPattern(pattern);
|
||||
}
|
||||
}
|
||||
|
@ -1744,7 +1745,7 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
|
|||
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"));
|
||||
const PDFDictionary* softMask = graphicStateDictionary->hasKey("SMask") ? m_document->getDictionaryFromObject(graphicStateDictionary->get("SMask")) : m_graphicState.getSoftMask();
|
||||
|
||||
// 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
|
||||
|
@ -1777,11 +1778,63 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
|
|||
|
||||
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);
|
||||
|
||||
constexpr std::array blackPointCompensationModes = {
|
||||
std::pair<const char*, BlackPointCompensationMode>{ "Default", BlackPointCompensationMode::Default },
|
||||
std::pair<const char*, BlackPointCompensationMode>{ "ON", BlackPointCompensationMode::ON },
|
||||
std::pair<const char*, BlackPointCompensationMode>{ "OFF", BlackPointCompensationMode::OFF },
|
||||
};
|
||||
|
||||
BlackPointCompensationMode blackPointCompensationMode = m_graphicState.getBlackPointCompensationMode();
|
||||
if (graphicStateDictionary->hasKey("UseBlackPtComp"))
|
||||
{
|
||||
// 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);
|
||||
blackPointCompensationMode = loader.readEnumByName(graphicStateDictionary->get("UseBlackPtComp"), blackPointCompensationModes.cbegin(), blackPointCompensationModes.cend(), BlackPointCompensationMode::Default);
|
||||
}
|
||||
|
||||
PDFObject blackGenerationFunctionObject = m_graphicState.getBlackGenerationFunction();
|
||||
if (graphicStateDictionary->hasKey("BG") || graphicStateDictionary->hasKey("BG2"))
|
||||
{
|
||||
blackGenerationFunctionObject = m_document->getObject(graphicStateDictionary->get("BG2"));
|
||||
if (blackGenerationFunctionObject.isNull())
|
||||
{
|
||||
blackGenerationFunctionObject = m_document->getObject(graphicStateDictionary->get("BG"));
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject undercolorRemovalFunctionObject = m_graphicState.getUndercolorRemovalFunction();
|
||||
if (graphicStateDictionary->hasKey("UCR") || graphicStateDictionary->hasKey("UCR2"))
|
||||
{
|
||||
undercolorRemovalFunctionObject = m_document->getObject(graphicStateDictionary->get("UCR2"));
|
||||
if (undercolorRemovalFunctionObject.isNull())
|
||||
{
|
||||
undercolorRemovalFunctionObject = m_document->getObject(graphicStateDictionary->get("UCR"));
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject transferFunctionObject = m_graphicState.getTransferFunction();
|
||||
if (graphicStateDictionary->hasKey("TR") || graphicStateDictionary->hasKey("TR2"))
|
||||
{
|
||||
transferFunctionObject = m_document->getObject(graphicStateDictionary->get("TR2"));
|
||||
if (transferFunctionObject.isNull())
|
||||
{
|
||||
transferFunctionObject = m_document->getObject(graphicStateDictionary->get("TR"));
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject halftoneObject = graphicStateDictionary->hasKey("HT") ? m_document->getObject(graphicStateDictionary->get("HT")) : m_graphicState.getHalftone();
|
||||
|
||||
QPointF halftoneOrigin = m_graphicState.getHalftoneOrigin();
|
||||
if (graphicStateDictionary->hasKey("HTO"))
|
||||
{
|
||||
std::vector<PDFReal> halftoneOriginArray = loader.readNumberArrayFromDictionary(graphicStateDictionary, "HTO");
|
||||
if (halftoneOriginArray.size() >= 2)
|
||||
{
|
||||
halftoneOrigin = QPointF(halftoneOriginArray[0], halftoneOriginArray[1]);
|
||||
}
|
||||
}
|
||||
|
||||
m_graphicState.setLineWidth(lineWidth);
|
||||
|
@ -1797,6 +1850,12 @@ void PDFPageContentProcessor::processApplyGraphicState(const PDFDictionary* grap
|
|||
m_graphicState.setAlphaIsShape(alphaIsShape);
|
||||
m_graphicState.setStrokeAdjustment(strokeAdjustment);
|
||||
m_graphicState.setSoftMask(softMask);
|
||||
m_graphicState.setBlackPointCompensationMode(blackPointCompensationMode);
|
||||
m_graphicState.setBlackGenerationFunction(qMove(blackGenerationFunctionObject));
|
||||
m_graphicState.setUndercolorRemovalFunction(qMove(undercolorRemovalFunctionObject));
|
||||
m_graphicState.setTransferFunction(qMove(transferFunctionObject));
|
||||
m_graphicState.setHalftone(qMove(halftoneObject));
|
||||
m_graphicState.setHalftoneOrigin(halftoneOrigin);
|
||||
updateGraphicState();
|
||||
|
||||
if (graphicStateDictionary->hasKey("Font"))
|
||||
|
@ -3208,6 +3267,7 @@ PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorSt
|
|||
m_alphaIsShape(false),
|
||||
m_strokeAdjustment(false),
|
||||
m_softMask(nullptr),
|
||||
m_blackPointCompensationMode(BlackPointCompensationMode::Default),
|
||||
m_stateFlags(StateUnchanged)
|
||||
{
|
||||
m_fillColorSpace.reset(new PDFDeviceGrayColorSpace);
|
||||
|
@ -3253,6 +3313,12 @@ PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor::
|
|||
setAlphaIsShape(other.getAlphaIsShape());
|
||||
setStrokeAdjustment(other.getStrokeAdjustment());
|
||||
setSoftMask(other.getSoftMask());
|
||||
setBlackPointCompensationMode(other.getBlackPointCompensationMode());
|
||||
setBlackGenerationFunction(other.getBlackGenerationFunction());
|
||||
setUndercolorRemovalFunction(other.getUndercolorRemovalFunction());
|
||||
setTransferFunction(other.getTransferFunction());
|
||||
setHalftone(other.getHalftone());
|
||||
setHalftoneOrigin(other.getHalftoneOrigin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -3505,6 +3571,90 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setSoftMask(const PD
|
|||
}
|
||||
}
|
||||
|
||||
BlackPointCompensationMode PDFPageContentProcessor::PDFPageContentProcessorState::getBlackPointCompensationMode() const
|
||||
{
|
||||
return m_blackPointCompensationMode;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setBlackPointCompensationMode(BlackPointCompensationMode blackPointCompensationMode)
|
||||
{
|
||||
if (m_blackPointCompensationMode != blackPointCompensationMode)
|
||||
{
|
||||
m_blackPointCompensationMode = blackPointCompensationMode;
|
||||
m_stateFlags |= StateBlackPointCompensation;
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getHalftone() const
|
||||
{
|
||||
return m_halftone;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setHalftone(const PDFObject& halftone)
|
||||
{
|
||||
if (m_halftone != halftone)
|
||||
{
|
||||
m_halftone = halftone;
|
||||
m_stateFlags |= StateHalftone;
|
||||
}
|
||||
}
|
||||
|
||||
QPointF PDFPageContentProcessor::PDFPageContentProcessorState::getHalftoneOrigin() const
|
||||
{
|
||||
return m_halftoneOrigin;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setHalftoneOrigin(const QPointF& halftoneOrigin)
|
||||
{
|
||||
if (m_halftoneOrigin != halftoneOrigin)
|
||||
{
|
||||
m_halftoneOrigin = halftoneOrigin;
|
||||
m_stateFlags |= StateHalftoneOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getTransferFunction() const
|
||||
{
|
||||
return m_transferFunction;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTransferFunction(const PDFObject& transferFunction)
|
||||
{
|
||||
if (m_transferFunction != transferFunction)
|
||||
{
|
||||
m_transferFunction = transferFunction;
|
||||
m_stateFlags |= StateTransferFunction;
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getUndercolorRemovalFunction() const
|
||||
{
|
||||
return m_undercolorRemovalFunction;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setUndercolorRemovalFunction(const PDFObject& undercolorRemovalFunction)
|
||||
{
|
||||
if (m_undercolorRemovalFunction != undercolorRemovalFunction)
|
||||
{
|
||||
m_undercolorRemovalFunction = undercolorRemovalFunction;
|
||||
m_stateFlags |= StateUndercolorRemovalFunction;
|
||||
}
|
||||
}
|
||||
|
||||
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getBlackGenerationFunction() const
|
||||
{
|
||||
return m_blackGenerationFunction;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setBlackGenerationFunction(const PDFObject& blackGenerationFunction)
|
||||
{
|
||||
if (m_blackGenerationFunction != blackGenerationFunction)
|
||||
{
|
||||
m_blackGenerationFunction = blackGenerationFunction;
|
||||
m_stateFlags |= StateBlackGenerationFunction;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextMatrix(const QMatrix& textMatrix)
|
||||
{
|
||||
if (m_textMatrix != textMatrix)
|
||||
|
@ -3613,4 +3763,35 @@ PDFPageContentProcessor::PDFTransparencyGroupGuard::~PDFTransparencyGroupGuard()
|
|||
m_processor->performEndTransparencyGroup(ProcessOrder::AfterOperation, group);
|
||||
}
|
||||
|
||||
PDFLineDashPattern::PDFLineDashPattern(const std::vector<PDFReal>& dashArray, PDFReal dashOffset) :
|
||||
m_dashArray(dashArray),
|
||||
m_dashOffset(dashOffset)
|
||||
{
|
||||
if (m_dashArray.size() % 2 == 1)
|
||||
{
|
||||
m_dashArray.push_back(m_dashArray.back());
|
||||
}
|
||||
}
|
||||
|
||||
void PDFLineDashPattern::fix()
|
||||
{
|
||||
if (m_dashOffset < 0.0)
|
||||
{
|
||||
// According to the PDF 2.0 specification, if dash offset is negative,
|
||||
// then twice of sum of lengths in the dash array should be added
|
||||
// so dash offset will become positive.
|
||||
|
||||
const PDFReal totalLength = 2 * std::accumulate(m_dashArray.cbegin(), m_dashArray.cend(), 0.0);
|
||||
if (totalLength > 0.0)
|
||||
{
|
||||
m_dashOffset += (std::floor(std::abs(m_dashOffset / totalLength)) + 1.0) * totalLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset to default solid line, dash pattern is invalid
|
||||
*this = PDFLineDashPattern();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
|
|
@ -48,15 +48,7 @@ class PDFLineDashPattern
|
|||
{
|
||||
public:
|
||||
explicit inline PDFLineDashPattern() = default;
|
||||
explicit inline PDFLineDashPattern(const std::vector<PDFReal>& dashArray, PDFReal dashOffset) :
|
||||
m_dashArray(dashArray),
|
||||
m_dashOffset(dashOffset)
|
||||
{
|
||||
if (m_dashArray.size() % 2 == 1)
|
||||
{
|
||||
m_dashArray.push_back(m_dashArray.back());
|
||||
}
|
||||
}
|
||||
explicit PDFLineDashPattern(const std::vector<PDFReal>& dashArray, PDFReal dashOffset);
|
||||
|
||||
inline const std::vector<PDFReal>& getDashArray() const { return m_dashArray; }
|
||||
inline void setDashArray(const std::vector<PDFReal>& dashArray) { m_dashArray = dashArray; }
|
||||
|
@ -70,6 +62,9 @@ public:
|
|||
/// Is line solid? Function returns true, if yes.
|
||||
bool isSolid() const { return m_dashArray.empty(); }
|
||||
|
||||
/// Fix line dash pattern according to the specification
|
||||
void fix();
|
||||
|
||||
private:
|
||||
std::vector<PDFReal> m_dashArray;
|
||||
PDFReal m_dashOffset = 0.0;
|
||||
|
@ -273,45 +268,51 @@ protected:
|
|||
PDFPageContentProcessorState& operator=(PDFPageContentProcessorState&&) = delete;
|
||||
PDFPageContentProcessorState& operator=(const PDFPageContentProcessorState& other);
|
||||
|
||||
enum StateFlag : uint32_t
|
||||
enum StateFlag : uint64_t
|
||||
{
|
||||
StateUnchanged = 0x00000000,
|
||||
StateCurrentTransformationMatrix = 0x00000001,
|
||||
StateStrokeColorSpace = 0x00000002,
|
||||
StateFillColorSpace = 0x00000004,
|
||||
StateStrokeColor = 0x00000008,
|
||||
StateFillColor = 0x00000010,
|
||||
StateLineWidth = 0x00000020,
|
||||
StateLineCapStyle = 0x00000040,
|
||||
StateLineJoinStyle = 0x00000080,
|
||||
StateMitterLimit = 0x00000100,
|
||||
StateLineDashPattern = 0x00000200,
|
||||
StateRenderingIntentName = 0x00000400,
|
||||
StateFlatness = 0x00000800,
|
||||
StateSmoothness = 0x00001000,
|
||||
StateTextMatrix = 0x00002000,
|
||||
StateTextLineMatrix = 0x00004000,
|
||||
StateTextCharacterSpacing = 0x00008000,
|
||||
StateTextWordSpacing = 0x00010000,
|
||||
StateTextHorizontalScaling = 0x00020000,
|
||||
StateTextLeading = 0x00040000,
|
||||
StateTextFont = 0x00080000,
|
||||
StateTextFontSize = 0x00100000,
|
||||
StateTextRenderingMode = 0x00200000,
|
||||
StateTextRise = 0x00400000,
|
||||
StateTextKnockout = 0x00800000,
|
||||
StateAlphaStroking = 0x01000000,
|
||||
StateAlphaFilling = 0x02000000,
|
||||
StateBlendMode = 0x04000000,
|
||||
StateRenderingIntent = 0x08000000,
|
||||
StateOverprint = 0x10000000,
|
||||
StateAlphaIsShape = 0x20000000,
|
||||
StateStrokeAdjustment = 0x40000000,
|
||||
StateSoftMask = 0x80000000,
|
||||
StateAll = 0xFFFFFFFF
|
||||
StateUnchanged = 0x0000000000000000,
|
||||
StateCurrentTransformationMatrix = 0x0000000000000001,
|
||||
StateStrokeColorSpace = 0x0000000000000002,
|
||||
StateFillColorSpace = 0x0000000000000004,
|
||||
StateStrokeColor = 0x0000000000000008,
|
||||
StateFillColor = 0x0000000000000010,
|
||||
StateLineWidth = 0x0000000000000020,
|
||||
StateLineCapStyle = 0x0000000000000040,
|
||||
StateLineJoinStyle = 0x0000000000000080,
|
||||
StateMitterLimit = 0x0000000000000100,
|
||||
StateLineDashPattern = 0x0000000000000200,
|
||||
StateRenderingIntentName = 0x0000000000000400,
|
||||
StateFlatness = 0x0000000000000800,
|
||||
StateSmoothness = 0x0000000000001000,
|
||||
StateTextMatrix = 0x0000000000002000,
|
||||
StateTextLineMatrix = 0x0000000000004000,
|
||||
StateTextCharacterSpacing = 0x0000000000008000,
|
||||
StateTextWordSpacing = 0x0000000000010000,
|
||||
StateTextHorizontalScaling = 0x0000000000020000,
|
||||
StateTextLeading = 0x0000000000040000,
|
||||
StateTextFont = 0x0000000000080000,
|
||||
StateTextFontSize = 0x0000000000100000,
|
||||
StateTextRenderingMode = 0x0000000000200000,
|
||||
StateTextRise = 0x0000000000400000,
|
||||
StateTextKnockout = 0x0000000000800000,
|
||||
StateAlphaStroking = 0x0000000001000000,
|
||||
StateAlphaFilling = 0x0000000002000000,
|
||||
StateBlendMode = 0x0000000004000000,
|
||||
StateRenderingIntent = 0x0000000008000000,
|
||||
StateOverprint = 0x0000000010000000,
|
||||
StateAlphaIsShape = 0x0000000020000000,
|
||||
StateStrokeAdjustment = 0x0000000040000000,
|
||||
StateSoftMask = 0x0000000080000000,
|
||||
StateBlackPointCompensation = 0x0000000100000000,
|
||||
StateBlackGenerationFunction = 0x0000000200000000,
|
||||
StateUndercolorRemovalFunction = 0x0000000400000000,
|
||||
StateTransferFunction = 0x0000000800000000,
|
||||
StateHalftone = 0x0000001000000000,
|
||||
StateHalftoneOrigin = 0x0000002000000000,
|
||||
StateAll = 0xFFFFFFFFFFFFFFFF
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(StateFlags, StateFlag)
|
||||
using StateFlags = PDFFlags<StateFlag>;
|
||||
|
||||
const QMatrix& getCurrentTransformationMatrix() const { return m_currentTransformationMatrix; }
|
||||
void setCurrentTransformationMatrix(const QMatrix& currentTransformationMatrix);
|
||||
|
@ -418,6 +419,24 @@ protected:
|
|||
const PDFDictionary* getSoftMask() const;
|
||||
void setSoftMask(const PDFDictionary* softMask);
|
||||
|
||||
BlackPointCompensationMode getBlackPointCompensationMode() const;
|
||||
void setBlackPointCompensationMode(BlackPointCompensationMode blackPointCompensationMode);
|
||||
|
||||
PDFObject getBlackGenerationFunction() const;
|
||||
void setBlackGenerationFunction(const PDFObject& blackGenerationFunction);
|
||||
|
||||
PDFObject getUndercolorRemovalFunction() const;
|
||||
void setUndercolorRemovalFunction(const PDFObject& undercolorRemovalFunction);
|
||||
|
||||
PDFObject getTransferFunction() const;
|
||||
void setTransferFunction(const PDFObject& transferFunction);
|
||||
|
||||
PDFObject getHalftone() const;
|
||||
void setHalftone(const PDFObject& halftone);
|
||||
|
||||
QPointF getHalftoneOrigin() const;
|
||||
void setHalftoneOrigin(const QPointF& halftoneOrigin);
|
||||
|
||||
private:
|
||||
QMatrix m_currentTransformationMatrix;
|
||||
PDFColorSpacePointer m_strokeColorSpace;
|
||||
|
@ -451,6 +470,12 @@ protected:
|
|||
bool m_alphaIsShape;
|
||||
bool m_strokeAdjustment;
|
||||
const PDFDictionary* m_softMask;
|
||||
BlackPointCompensationMode m_blackPointCompensationMode;
|
||||
PDFObject m_blackGenerationFunction;
|
||||
PDFObject m_undercolorRemovalFunction;
|
||||
PDFObject m_transferFunction;
|
||||
PDFObject m_halftone;
|
||||
QPointF m_halftoneOrigin;
|
||||
StateFlags m_stateFlags;
|
||||
};
|
||||
|
||||
|
|
|
@ -527,6 +527,61 @@ private:
|
|||
QString m_errorMessage;
|
||||
};
|
||||
|
||||
template<typename Enum>
|
||||
class PDFFlags
|
||||
{
|
||||
public:
|
||||
using Integer = typename std::underlying_type<Enum>::type;
|
||||
|
||||
constexpr inline PDFFlags() noexcept = default;
|
||||
constexpr inline PDFFlags(Integer flags) noexcept : m_flags(flags) { }
|
||||
constexpr inline PDFFlags(Enum flag) noexcept : m_flags(flag) { }
|
||||
|
||||
constexpr inline PDFFlags& operator|=(Integer flags) { m_flags |= flags; return *this; }
|
||||
constexpr inline PDFFlags& operator|=(PDFFlags flags) { m_flags |= flags.m_flags; return *this; }
|
||||
constexpr inline PDFFlags& operator|=(Enum flag) { m_flags |= flag; return *this; }
|
||||
constexpr inline PDFFlags& operator&=(Integer flags) { m_flags &= flags; return *this; }
|
||||
constexpr inline PDFFlags& operator&=(PDFFlags flags) { m_flags &= flags.m_flags; return *this; }
|
||||
constexpr inline PDFFlags& operator&=(Enum flag) { m_flags &= flag; return *this; }
|
||||
constexpr inline PDFFlags& operator^=(Integer flags) { m_flags ^= flags; return *this; }
|
||||
constexpr inline PDFFlags& operator^=(PDFFlags flags) { m_flags ^= flags.m_flags; return *this; }
|
||||
constexpr inline PDFFlags& operator^=(Enum flag) { m_flags ^= flag; return *this; }
|
||||
|
||||
constexpr inline operator Integer() const { return m_flags; }
|
||||
|
||||
constexpr inline PDFFlags operator|(Integer flags) const { return PDFFlags(m_flags | flags); }
|
||||
constexpr inline PDFFlags operator|(PDFFlags flags) const { return PDFFlags(m_flags | flags.m_flags); }
|
||||
constexpr inline PDFFlags operator|(Enum flag) const { return PDFFlags(m_flags | flag); }
|
||||
constexpr inline PDFFlags operator&(Integer flags) const { return PDFFlags(m_flags & flags); }
|
||||
constexpr inline PDFFlags operator&(PDFFlags flags) const { return PDFFlags(m_flags & flags.m_flags); }
|
||||
constexpr inline PDFFlags operator&(Enum flag) const { return PDFFlags(m_flags & flag); }
|
||||
constexpr inline PDFFlags operator^(Integer flags) const { return PDFFlags(m_flags ^ flags); }
|
||||
constexpr inline PDFFlags operator^(PDFFlags flags) const { return PDFFlags(m_flags ^ flags.m_flags); }
|
||||
constexpr inline PDFFlags operator^(Enum flag) const { return PDFFlags(m_flags ^ flag); }
|
||||
constexpr inline PDFFlags operator~() const { return PDFFlags(~m_flags); }
|
||||
|
||||
// Explicit bool operator to disallow implicit conversion
|
||||
constexpr inline explicit operator bool() const { return m_flags != 0; }
|
||||
constexpr inline bool operator!() const { return m_flags == 0; }
|
||||
|
||||
constexpr inline bool testFlag(Enum flag) const { return (m_flags & flag) == flag; }
|
||||
constexpr inline PDFFlags& setFlag(Enum flag, bool on = true)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
m_flags |= Integer(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flags &= ~Integer(flag);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Integer m_flags = Integer();
|
||||
};
|
||||
|
||||
/// Set of closed intervals
|
||||
class PDFClosedIntervalSet
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue