mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-03-24 23:30:25 +01:00
Uncolored tiling patterns, tiling patterns colors
This commit is contained in:
parent
40f3f9f9b4
commit
59ad9afadd
@ -241,7 +241,7 @@ QColor PDFAbstractColorSpace::getCheckedColor(const PDFColor& color) const
|
|||||||
{
|
{
|
||||||
if (getColorComponentCount() != color.size())
|
if (getColorComponentCount() != color.size())
|
||||||
{
|
{
|
||||||
throw PDFParserException(PDFTranslationContext::tr("Invalid number of color components. Expected number is %1, actual number is %2.").arg(static_cast<int>(getColorComponentCount()), static_cast<int>(color.size())));
|
throw PDFParserException(PDFTranslationContext::tr("Invalid number of color components. Expected number is %1, actual number is %2.").arg(static_cast<int>(getColorComponentCount())).arg(static_cast<int>(color.size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return getColor(color);
|
return getColor(color);
|
||||||
@ -352,7 +352,13 @@ PDFColorSpacePointer PDFAbstractColorSpace::createColorSpaceImpl(const PDFDictio
|
|||||||
|
|
||||||
if (name == COLOR_SPACE_NAME_PATTERN)
|
if (name == COLOR_SPACE_NAME_PATTERN)
|
||||||
{
|
{
|
||||||
return PDFColorSpacePointer(new PDFPatternColorSpace(std::make_shared<PDFInvalidPattern>()));
|
PDFColorSpacePointer uncoloredPatternColorSpace;
|
||||||
|
if (count == 2)
|
||||||
|
{
|
||||||
|
uncoloredPatternColorSpace = createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(array->getItem(1)), recursion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PDFColorSpacePointer(new PDFPatternColorSpace(std::make_shared<PDFInvalidPattern>(), qMove(uncoloredPatternColorSpace), PDFColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dictionary)
|
if (dictionary)
|
||||||
@ -413,7 +419,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con
|
|||||||
|
|
||||||
if (name == COLOR_SPACE_NAME_PATTERN)
|
if (name == COLOR_SPACE_NAME_PATTERN)
|
||||||
{
|
{
|
||||||
return PDFColorSpacePointer(new PDFPatternColorSpace(std::make_shared<PDFInvalidPattern>()));
|
return PDFColorSpacePointer(new PDFPatternColorSpace(std::make_shared<PDFInvalidPattern>(), nullptr, PDFColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == COLOR_SPACE_NAME_DEVICE_GRAY || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_GRAY)
|
if (name == COLOR_SPACE_NAME_DEVICE_GRAY || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_GRAY)
|
||||||
|
@ -34,6 +34,7 @@ class PDFPattern;
|
|||||||
class PDFDocument;
|
class PDFDocument;
|
||||||
class PDFDictionary;
|
class PDFDictionary;
|
||||||
class PDFAbstractColorSpace;
|
class PDFAbstractColorSpace;
|
||||||
|
class PDFPatternColorSpace;
|
||||||
|
|
||||||
using PDFColorComponent = float;
|
using PDFColorComponent = float;
|
||||||
using PDFColor = PDFFlatArray<PDFColorComponent, 4>;
|
using PDFColor = PDFFlatArray<PDFColorComponent, 4>;
|
||||||
@ -211,7 +212,7 @@ public:
|
|||||||
virtual QColor getColor(const PDFColor& color) const = 0;
|
virtual QColor getColor(const PDFColor& color) const = 0;
|
||||||
virtual size_t getColorComponentCount() const = 0;
|
virtual size_t getColorComponentCount() const = 0;
|
||||||
virtual QImage getImage(const PDFImageData& imageData) const;
|
virtual QImage getImage(const PDFImageData& imageData) const;
|
||||||
virtual const PDFPattern* getPattern() const { return nullptr; }
|
virtual const PDFPatternColorSpace* asPatternColorSpace() const { return nullptr; }
|
||||||
|
|
||||||
/// Checks, if number of color components is OK, and if yes, converts them to the QColor value.
|
/// Checks, if number of color components is OK, and if yes, converts them to the QColor value.
|
||||||
/// If they are not OK, exception is thrown.
|
/// If they are not OK, exception is thrown.
|
||||||
@ -592,17 +593,29 @@ private:
|
|||||||
class PDFPatternColorSpace : public PDFAbstractColorSpace
|
class PDFPatternColorSpace : public PDFAbstractColorSpace
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFPatternColorSpace(std::shared_ptr<PDFPattern>&& pattern) : m_pattern(qMove(pattern)) { }
|
explicit PDFPatternColorSpace(std::shared_ptr<PDFPattern>&& pattern, PDFColorSpacePointer&& uncoloredPatternColorSpace, PDFColor uncoloredPatternColor) :
|
||||||
|
m_pattern(qMove(pattern)),
|
||||||
|
m_uncoloredPatternColorSpace(qMove(uncoloredPatternColorSpace)),
|
||||||
|
m_uncoloredPatternColor(qMove(uncoloredPatternColor))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~PDFPatternColorSpace() override = default;
|
virtual ~PDFPatternColorSpace() override = default;
|
||||||
|
|
||||||
virtual QColor getDefaultColor() const override;
|
virtual QColor getDefaultColor() const override;
|
||||||
virtual QColor getColor(const PDFColor& color) const override;
|
virtual QColor getColor(const PDFColor& color) const override;
|
||||||
virtual size_t getColorComponentCount() const override;
|
virtual size_t getColorComponentCount() const override;
|
||||||
|
virtual const PDFPatternColorSpace* asPatternColorSpace() const override { return this; }
|
||||||
|
|
||||||
virtual const PDFPattern* getPattern() const override { return m_pattern.get(); }
|
const PDFPattern* getPattern() const { return m_pattern.get(); }
|
||||||
|
PDFColorSpacePointer getUncoloredPatternColorSpace() const { return m_uncoloredPatternColorSpace; }
|
||||||
|
PDFColor getUncoloredPatternColor() const { return m_uncoloredPatternColor; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<PDFPattern> m_pattern;
|
std::shared_ptr<PDFPattern> m_pattern;
|
||||||
|
PDFColorSpacePointer m_uncoloredPatternColorSpace;
|
||||||
|
PDFColor m_uncoloredPatternColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -594,15 +594,15 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
|||||||
|
|
||||||
if (fill)
|
if (fill)
|
||||||
{
|
{
|
||||||
const PDFPattern* pattern = getGraphicState()->getFillColorSpace()->getPattern();
|
if (const PDFPatternColorSpace* patternColorSpace = getGraphicState()->getFillColorSpace()->asPatternColorSpace())
|
||||||
if (pattern)
|
|
||||||
{
|
{
|
||||||
|
const PDFPattern* pattern = patternColorSpace->getPattern();
|
||||||
switch (pattern->getType())
|
switch (pattern->getType())
|
||||||
{
|
{
|
||||||
case PatternType::Tiling:
|
case PatternType::Tiling:
|
||||||
{
|
{
|
||||||
const PDFTilingPattern* tilingPattern = pattern->getTilingPattern();
|
const PDFTilingPattern* tilingPattern = pattern->getTilingPattern();
|
||||||
processTillingPatternPainting(tilingPattern, path);
|
processTillingPatternPainting(tilingPattern, path, patternColorSpace->getUncoloredPatternColorSpace(), patternColorSpace->getUncoloredPatternColor());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,9 +653,9 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
|||||||
|
|
||||||
if (stroke)
|
if (stroke)
|
||||||
{
|
{
|
||||||
const PDFPattern* pattern = getGraphicState()->getStrokeColorSpace()->getPattern();
|
if (const PDFPatternColorSpace* patternColorSpace = getGraphicState()->getFillColorSpace()->asPatternColorSpace())
|
||||||
if (pattern)
|
|
||||||
{
|
{
|
||||||
|
const PDFPattern* pattern = patternColorSpace->getPattern();
|
||||||
switch (pattern->getType())
|
switch (pattern->getType())
|
||||||
{
|
{
|
||||||
case PatternType::Tiling:
|
case PatternType::Tiling:
|
||||||
@ -676,7 +676,7 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
|||||||
stroker.setDashOffset(lineDashPattern.getDashOffset());
|
stroker.setDashOffset(lineDashPattern.getDashOffset());
|
||||||
}
|
}
|
||||||
QPainterPath strokedPath = stroker.createStroke(path);
|
QPainterPath strokedPath = stroker.createStroke(path);
|
||||||
processTillingPatternPainting(tilingPattern, strokedPath);
|
processTillingPatternPainting(tilingPattern, strokedPath, patternColorSpace->getUncoloredPatternColorSpace(), patternColorSpace->getUncoloredPatternColor());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +745,10 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::processTillingPatternPainting(const PDFTilingPattern* tilingPattern, const QPainterPath& path)
|
void PDFPageContentProcessor::processTillingPatternPainting(const PDFTilingPattern* tilingPattern,
|
||||||
|
const QPainterPath& path,
|
||||||
|
PDFColorSpacePointer uncoloredPatternColorSpace,
|
||||||
|
PDFColor uncoloredPatternColor)
|
||||||
{
|
{
|
||||||
PDFPageContentProcessorStateGuard guard(this);
|
PDFPageContentProcessorStateGuard guard(this);
|
||||||
performClipping(path, path.fillRule());
|
performClipping(path, path.fillRule());
|
||||||
@ -764,6 +767,33 @@ void PDFPageContentProcessor::processTillingPatternPainting(const PDFTilingPatte
|
|||||||
QMatrix matrix = patternMatrix * m_pagePointToDevicePointMatrix.inverted();
|
QMatrix matrix = patternMatrix * m_pagePointToDevicePointMatrix.inverted();
|
||||||
QMatrix pathTransformationMatrix = m_graphicState.getCurrentTransformationMatrix() * matrix.inverted();
|
QMatrix pathTransformationMatrix = m_graphicState.getCurrentTransformationMatrix() * matrix.inverted();
|
||||||
m_graphicState.setCurrentTransformationMatrix(matrix);
|
m_graphicState.setCurrentTransformationMatrix(matrix);
|
||||||
|
|
||||||
|
// Initialize colors for uncolored color space pattern
|
||||||
|
if (tilingPattern->getPaintingType() == PDFTilingPattern::PaintType::Uncolored)
|
||||||
|
{
|
||||||
|
if (!uncoloredPatternColorSpace)
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Uncolored tiling pattern has not underlying color space."));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_graphicState.setStrokeColorSpace(uncoloredPatternColorSpace);
|
||||||
|
m_graphicState.setFillColorSpace(uncoloredPatternColorSpace);
|
||||||
|
|
||||||
|
QColor color = uncoloredPatternColorSpace->getCheckedColor(uncoloredPatternColor);
|
||||||
|
m_graphicState.setStrokeColor(color);
|
||||||
|
m_graphicState.setFillColor(color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Jakub Melka: According the specification, we set default color space and default color
|
||||||
|
m_graphicState.setStrokeColorSpace(m_deviceGrayColorSpace);
|
||||||
|
m_graphicState.setFillColorSpace(m_deviceGrayColorSpace);
|
||||||
|
|
||||||
|
QColor color = m_deviceGrayColorSpace->getDefaultColor();
|
||||||
|
m_graphicState.setStrokeColor(color);
|
||||||
|
m_graphicState.setFillColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
|
|
||||||
// Tiling parameters
|
// Tiling parameters
|
||||||
@ -1951,17 +1981,25 @@ void PDFPageContentProcessor::operatorColorSetStrokingColorN()
|
|||||||
// but default operator can use them (with exception of Pattern color space). For pattern color space,
|
// but default operator can use them (with exception of Pattern color space). For pattern color space,
|
||||||
// we treat this differently.
|
// we treat this differently.
|
||||||
const PDFAbstractColorSpace* colorSpace = m_graphicState.getStrokeColorSpace();
|
const PDFAbstractColorSpace* colorSpace = m_graphicState.getStrokeColorSpace();
|
||||||
if (colorSpace->getPattern())
|
if (const PDFPatternColorSpace* patternColorSpace = colorSpace->asPatternColorSpace())
|
||||||
{
|
{
|
||||||
if (m_operands.size() > 0)
|
const size_t operandCount = m_operands.size();
|
||||||
|
if (operandCount > 0)
|
||||||
{
|
{
|
||||||
// TODO: Implement tiling pattern colors
|
PDFColorSpacePointer uncoloredColorSpace = patternColorSpace->getUncoloredPatternColorSpace();
|
||||||
PDFOperandName name = readOperand<PDFOperandName>(m_operands.size() - 1);
|
PDFColor uncoloredPatternColor;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < operandCount - 1; ++i)
|
||||||
|
{
|
||||||
|
uncoloredPatternColor.push_back(readOperand<PDFReal>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFOperandName name = readOperand<PDFOperandName>(operandCount - 1);
|
||||||
if (m_patternDictionary && m_patternDictionary->hasKey(name.name))
|
if (m_patternDictionary && m_patternDictionary->hasKey(name.name))
|
||||||
{
|
{
|
||||||
// Create the pattern
|
// Create the pattern
|
||||||
PDFPatternPtr pattern = PDFPattern::createPattern(m_colorSpaceDictionary, m_document, m_patternDictionary->get(name.name));
|
PDFPatternPtr pattern = PDFPattern::createPattern(m_colorSpaceDictionary, m_document, m_patternDictionary->get(name.name));
|
||||||
m_graphicState.setStrokeColorSpace(QSharedPointer<PDFAbstractColorSpace>(new PDFPatternColorSpace(qMove(pattern))));
|
m_graphicState.setStrokeColorSpace(PDFColorSpacePointer(new PDFPatternColorSpace(qMove(pattern), qMove(uncoloredColorSpace), qMove(uncoloredPatternColor))));
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2009,17 +2047,25 @@ void PDFPageContentProcessor::operatorColorSetFillingColorN()
|
|||||||
// but default operator can use them (with exception of Pattern color space). For pattern color space,
|
// but default operator can use them (with exception of Pattern color space). For pattern color space,
|
||||||
// we treat this differently.
|
// we treat this differently.
|
||||||
const PDFAbstractColorSpace* colorSpace = m_graphicState.getFillColorSpace();
|
const PDFAbstractColorSpace* colorSpace = m_graphicState.getFillColorSpace();
|
||||||
if (colorSpace->getPattern())
|
if (const PDFPatternColorSpace* patternColorSpace = colorSpace->asPatternColorSpace())
|
||||||
{
|
{
|
||||||
if (m_operands.size() > 0)
|
const size_t operandCount = m_operands.size();
|
||||||
|
if (operandCount > 0)
|
||||||
{
|
{
|
||||||
// TODO: Implement tiling pattern colors
|
PDFColorSpacePointer uncoloredColorSpace = patternColorSpace->getUncoloredPatternColorSpace();
|
||||||
PDFOperandName name = readOperand<PDFOperandName>(m_operands.size() - 1);
|
PDFColor uncoloredPatternColor;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < operandCount - 1; ++i)
|
||||||
|
{
|
||||||
|
uncoloredPatternColor.push_back(readOperand<PDFReal>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFOperandName name = readOperand<PDFOperandName>(operandCount - 1);
|
||||||
if (m_patternDictionary && m_patternDictionary->hasKey(name.name))
|
if (m_patternDictionary && m_patternDictionary->hasKey(name.name))
|
||||||
{
|
{
|
||||||
// Create the pattern
|
// Create the pattern
|
||||||
PDFPatternPtr pattern = PDFPattern::createPattern(m_colorSpaceDictionary, m_document, m_patternDictionary->get(name.name));
|
PDFPatternPtr pattern = PDFPattern::createPattern(m_colorSpaceDictionary, m_document, m_patternDictionary->get(name.name));
|
||||||
m_graphicState.setFillColorSpace(QSharedPointer<PDFAbstractColorSpace>(new PDFPatternColorSpace(qMove(pattern))));
|
m_graphicState.setFillColorSpace(QSharedPointer<PDFAbstractColorSpace>(new PDFPatternColorSpace(qMove(pattern), qMove(uncoloredColorSpace), qMove(uncoloredPatternColor))));
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2359,7 +2405,7 @@ void PDFPageContentProcessor::operatorShadingPaintShape(PDFPageContentProcessor:
|
|||||||
|
|
||||||
// We will do a trick: we will set current fill color space, and then paint
|
// We will do a trick: we will set current fill color space, and then paint
|
||||||
// bounding rectangle in the color pattern.
|
// bounding rectangle in the color pattern.
|
||||||
m_graphicState.setFillColorSpace(PDFColorSpacePointer(new PDFPatternColorSpace(qMove(pattern))));
|
m_graphicState.setFillColorSpace(PDFColorSpacePointer(new PDFPatternColorSpace(qMove(pattern), nullptr, PDFColor())));
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
|
|
||||||
Q_ASSERT(matrix.isInvertible());
|
Q_ASSERT(matrix.isInvertible());
|
||||||
|
@ -468,7 +468,12 @@ private:
|
|||||||
/// Performs tiling pattern painting
|
/// Performs tiling pattern painting
|
||||||
/// \param tilingPattern Tiling pattern to be painted
|
/// \param tilingPattern Tiling pattern to be painted
|
||||||
/// \param path Clipping path
|
/// \param path Clipping path
|
||||||
void processTillingPatternPainting(const PDFTilingPattern* tilingPattern, const QPainterPath& path);
|
/// \param uncoloredPatternColorSpace Color space for uncolored color patterns
|
||||||
|
/// \param uncoloredPatternColor Uncolored color pattern color
|
||||||
|
void processTillingPatternPainting(const PDFTilingPattern* tilingPattern,
|
||||||
|
const QPainterPath& path,
|
||||||
|
PDFColorSpacePointer uncoloredPatternColorSpace,
|
||||||
|
PDFColor uncoloredPatternColor);
|
||||||
|
|
||||||
enum class MarkedContentKind
|
enum class MarkedContentKind
|
||||||
{
|
{
|
||||||
|
@ -50,6 +50,8 @@ PDFPainter::PDFPainter(QPainter* painter,
|
|||||||
m_painter->setClipPath(path, Qt::IntersectClip);
|
m_painter->setClipPath(path, Qt::IntersectClip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_painter->setRenderHint(QPainter::SmoothPixmapTransform, features.testFlag(PDFRenderer::SmoothImages));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFPainter::~PDFPainter()
|
PDFPainter::~PDFPainter()
|
||||||
|
@ -156,7 +156,7 @@ PDFPatternPtr PDFPattern::createShadingPattern(const PDFDictionary* colorSpaceDi
|
|||||||
// Parse common data for all shadings
|
// Parse common data for all shadings
|
||||||
PDFColorSpacePointer colorSpace = PDFAbstractColorSpace::createColorSpace(colorSpaceDictionary, document, document->getObject(shadingDictionary->get("ColorSpace")));
|
PDFColorSpacePointer colorSpace = PDFAbstractColorSpace::createColorSpace(colorSpaceDictionary, document, document->getObject(shadingDictionary->get("ColorSpace")));
|
||||||
|
|
||||||
if (colorSpace->getPattern())
|
if (colorSpace->asPatternColorSpace())
|
||||||
{
|
{
|
||||||
throw PDFParserException(PDFTranslationContext::tr("Pattern color space is not valid for shading patterns."));
|
throw PDFParserException(PDFTranslationContext::tr("Pattern color space is not valid for shading patterns."));
|
||||||
}
|
}
|
||||||
|
@ -250,16 +250,16 @@ public:
|
|||||||
|
|
||||||
enum class PaintType
|
enum class PaintType
|
||||||
{
|
{
|
||||||
Colored,
|
Colored = 1,
|
||||||
Uncolored,
|
Uncolored = 2,
|
||||||
Invalid
|
Invalid = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TilingType
|
enum class TilingType
|
||||||
{
|
{
|
||||||
ConstantSpacing,
|
ConstantSpacing = 1,
|
||||||
NoDistortion,
|
NoDistortion = 2,
|
||||||
ConstantSpacingAndFasterTiling,
|
ConstantSpacingAndFasterTiling = 3,
|
||||||
Invalid
|
Invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user