mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-03-18 04:10:23 +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())
|
||||
{
|
||||
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);
|
||||
@ -352,7 +352,13 @@ PDFColorSpacePointer PDFAbstractColorSpace::createColorSpaceImpl(const PDFDictio
|
||||
|
||||
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)
|
||||
@ -413,7 +419,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con
|
||||
|
||||
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)
|
||||
|
@ -34,6 +34,7 @@ class PDFPattern;
|
||||
class PDFDocument;
|
||||
class PDFDictionary;
|
||||
class PDFAbstractColorSpace;
|
||||
class PDFPatternColorSpace;
|
||||
|
||||
using PDFColorComponent = float;
|
||||
using PDFColor = PDFFlatArray<PDFColorComponent, 4>;
|
||||
@ -211,7 +212,7 @@ public:
|
||||
virtual QColor getColor(const PDFColor& color) const = 0;
|
||||
virtual size_t getColorComponentCount() const = 0;
|
||||
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.
|
||||
/// If they are not OK, exception is thrown.
|
||||
@ -592,17 +593,29 @@ private:
|
||||
class PDFPatternColorSpace : public PDFAbstractColorSpace
|
||||
{
|
||||
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 QColor getDefaultColor() const override;
|
||||
virtual QColor getColor(const PDFColor& color) 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:
|
||||
std::shared_ptr<PDFPattern> m_pattern;
|
||||
PDFColorSpacePointer m_uncoloredPatternColorSpace;
|
||||
PDFColor m_uncoloredPatternColor;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -594,15 +594,15 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
||||
|
||||
if (fill)
|
||||
{
|
||||
const PDFPattern* pattern = getGraphicState()->getFillColorSpace()->getPattern();
|
||||
if (pattern)
|
||||
if (const PDFPatternColorSpace* patternColorSpace = getGraphicState()->getFillColorSpace()->asPatternColorSpace())
|
||||
{
|
||||
const PDFPattern* pattern = patternColorSpace->getPattern();
|
||||
switch (pattern->getType())
|
||||
{
|
||||
case PatternType::Tiling:
|
||||
{
|
||||
const PDFTilingPattern* tilingPattern = pattern->getTilingPattern();
|
||||
processTillingPatternPainting(tilingPattern, path);
|
||||
processTillingPatternPainting(tilingPattern, path, patternColorSpace->getUncoloredPatternColorSpace(), patternColorSpace->getUncoloredPatternColor());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -653,9 +653,9 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
const PDFPattern* pattern = getGraphicState()->getStrokeColorSpace()->getPattern();
|
||||
if (pattern)
|
||||
if (const PDFPatternColorSpace* patternColorSpace = getGraphicState()->getFillColorSpace()->asPatternColorSpace())
|
||||
{
|
||||
const PDFPattern* pattern = patternColorSpace->getPattern();
|
||||
switch (pattern->getType())
|
||||
{
|
||||
case PatternType::Tiling:
|
||||
@ -676,7 +676,7 @@ void PDFPageContentProcessor::processPathPainting(const QPainterPath& path, bool
|
||||
stroker.setDashOffset(lineDashPattern.getDashOffset());
|
||||
}
|
||||
QPainterPath strokedPath = stroker.createStroke(path);
|
||||
processTillingPatternPainting(tilingPattern, strokedPath);
|
||||
processTillingPatternPainting(tilingPattern, strokedPath, patternColorSpace->getUncoloredPatternColorSpace(), patternColorSpace->getUncoloredPatternColor());
|
||||
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);
|
||||
performClipping(path, path.fillRule());
|
||||
@ -764,6 +767,33 @@ void PDFPageContentProcessor::processTillingPatternPainting(const PDFTilingPatte
|
||||
QMatrix matrix = patternMatrix * m_pagePointToDevicePointMatrix.inverted();
|
||||
QMatrix pathTransformationMatrix = m_graphicState.getCurrentTransformationMatrix() * matrix.inverted();
|
||||
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();
|
||||
|
||||
// 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,
|
||||
// we treat this differently.
|
||||
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
|
||||
PDFOperandName name = readOperand<PDFOperandName>(m_operands.size() - 1);
|
||||
PDFColorSpacePointer uncoloredColorSpace = patternColorSpace->getUncoloredPatternColorSpace();
|
||||
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))
|
||||
{
|
||||
// Create the pattern
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -2009,17 +2047,25 @@ void PDFPageContentProcessor::operatorColorSetFillingColorN()
|
||||
// but default operator can use them (with exception of Pattern color space). For pattern color space,
|
||||
// we treat this differently.
|
||||
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
|
||||
PDFOperandName name = readOperand<PDFOperandName>(m_operands.size() - 1);
|
||||
PDFColorSpacePointer uncoloredColorSpace = patternColorSpace->getUncoloredPatternColorSpace();
|
||||
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))
|
||||
{
|
||||
// Create the pattern
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -2359,7 +2405,7 @@ void PDFPageContentProcessor::operatorShadingPaintShape(PDFPageContentProcessor:
|
||||
|
||||
// We will do a trick: we will set current fill color space, and then paint
|
||||
// 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();
|
||||
|
||||
Q_ASSERT(matrix.isInvertible());
|
||||
|
@ -468,7 +468,12 @@ private:
|
||||
/// Performs tiling pattern painting
|
||||
/// \param tilingPattern Tiling pattern to be painted
|
||||
/// \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
|
||||
{
|
||||
|
@ -50,6 +50,8 @@ PDFPainter::PDFPainter(QPainter* painter,
|
||||
m_painter->setClipPath(path, Qt::IntersectClip);
|
||||
}
|
||||
}
|
||||
|
||||
m_painter->setRenderHint(QPainter::SmoothPixmapTransform, features.testFlag(PDFRenderer::SmoothImages));
|
||||
}
|
||||
|
||||
PDFPainter::~PDFPainter()
|
||||
|
@ -156,7 +156,7 @@ PDFPatternPtr PDFPattern::createShadingPattern(const PDFDictionary* colorSpaceDi
|
||||
// Parse common data for all shadings
|
||||
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."));
|
||||
}
|
||||
|
@ -250,16 +250,16 @@ public:
|
||||
|
||||
enum class PaintType
|
||||
{
|
||||
Colored,
|
||||
Uncolored,
|
||||
Invalid
|
||||
Colored = 1,
|
||||
Uncolored = 2,
|
||||
Invalid = 3
|
||||
};
|
||||
|
||||
enum class TilingType
|
||||
{
|
||||
ConstantSpacing,
|
||||
NoDistortion,
|
||||
ConstantSpacingAndFasterTiling,
|
||||
ConstantSpacing = 1,
|
||||
NoDistortion = 2,
|
||||
ConstantSpacingAndFasterTiling = 3,
|
||||
Invalid
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user