mirror of https://github.com/JakubMelka/PDF4QT.git
Separation color space, some bugfixing
This commit is contained in:
parent
2964637949
commit
8c417b2afb
|
@ -168,6 +168,11 @@ PDFColorSpacePointer PDFAbstractColorSpace::createColorSpaceImpl(const PDFDictio
|
|||
return PDFIndexedColorSpace::createIndexedColorSpace(colorSpaceDictionary, document, array, recursion);
|
||||
}
|
||||
|
||||
if (name == COLOR_SPACE_NAME_SEPARATION && count == 4)
|
||||
{
|
||||
return PDFSeparationColorSpace::createSeparationColorSpace(colorSpaceDictionary, document, array, recursion);
|
||||
}
|
||||
|
||||
// Try to just load by standard way - we can have "standard" color space stored in array
|
||||
return createColorSpaceImpl(colorSpaceDictionary, document, colorSpaceIdentifier, recursion);
|
||||
}
|
||||
|
@ -628,4 +633,79 @@ PDFColorSpacePointer PDFIndexedColorSpace::createIndexedColorSpace(const PDFDict
|
|||
return PDFColorSpacePointer(new PDFIndexedColorSpace(qMove(baseColorSpace), qMove(colors), maxValue));
|
||||
}
|
||||
|
||||
PDFSeparationColorSpace::PDFSeparationColorSpace(QByteArray&& colorName, PDFColorSpacePointer alternateColorSpace, PDFFunctionPtr tintTransform) :
|
||||
m_colorName(qMove(colorName)),
|
||||
m_alternateColorSpace(qMove(alternateColorSpace)),
|
||||
m_tintTransform(qMove(tintTransform))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QColor PDFSeparationColorSpace::getDefaultColor() const
|
||||
{
|
||||
return getColor(PDFColor(0.0f));
|
||||
}
|
||||
|
||||
QColor PDFSeparationColorSpace::getColor(const PDFColor& color) const
|
||||
{
|
||||
// Separation color space value must have exactly one component!
|
||||
Q_ASSERT(color.size() == 1);
|
||||
|
||||
// Input value
|
||||
double tint = color.back();
|
||||
|
||||
// Output values
|
||||
std::vector<double> outputColor;
|
||||
outputColor.resize(m_alternateColorSpace->getColorComponentCount(), 0.0);
|
||||
PDFFunction::FunctionResult result = m_tintTransform->apply(&tint, &tint + 1, outputColor.data(), outputColor.data() + outputColor.size());
|
||||
|
||||
if (result)
|
||||
{
|
||||
PDFColor color;
|
||||
std::for_each(outputColor.cbegin(), outputColor.cend(), [&color](double value) { color.push_back(static_cast<float>(value)); });
|
||||
return m_alternateColorSpace->getColor(color);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return invalid color
|
||||
return QColor();
|
||||
}
|
||||
}
|
||||
|
||||
size_t PDFSeparationColorSpace::getColorComponentCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
PDFColorSpacePointer PDFSeparationColorSpace::createSeparationColorSpace(const PDFDictionary* colorSpaceDictionary,
|
||||
const PDFDocument* document,
|
||||
const PDFArray* array,
|
||||
int recursion)
|
||||
{
|
||||
Q_ASSERT(array->getCount() == 4);
|
||||
|
||||
// Read color name
|
||||
const PDFObject& colorNameObject = document->getObject(array->getItem(1));
|
||||
if (!colorNameObject.isName())
|
||||
{
|
||||
throw PDFParserException(PDFTranslationContext::tr("Can't determine color name for separation color space."));
|
||||
}
|
||||
QByteArray colorName = colorNameObject.getString();
|
||||
|
||||
// Read alternate color space
|
||||
PDFColorSpacePointer alternateColorSpace = PDFAbstractColorSpace::createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(array->getItem(2)), recursion);
|
||||
if (!alternateColorSpace)
|
||||
{
|
||||
throw PDFParserException(PDFTranslationContext::tr("Can't determine alternate color space for separation color space."));
|
||||
}
|
||||
|
||||
PDFFunctionPtr tintTransform = PDFFunction::createFunction(document, array->getItem(3));
|
||||
if (!tintTransform)
|
||||
{
|
||||
throw PDFParserException(PDFTranslationContext::tr("Can't determine tint transform for separation color space."));
|
||||
}
|
||||
|
||||
return PDFColorSpacePointer(new PDFSeparationColorSpace(qMove(colorName), qMove(alternateColorSpace), qMove(tintTransform)));
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define PDFCOLORSPACES_H
|
||||
|
||||
#include "pdfflatarray.h"
|
||||
#include "pdffunction.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QSharedPointer>
|
||||
|
@ -57,6 +58,7 @@ static constexpr const char* COLOR_SPACE_NAME_CAL_RGB = "CalRGB";
|
|||
static constexpr const char* COLOR_SPACE_NAME_LAB = "Lab";
|
||||
static constexpr const char* COLOR_SPACE_NAME_ICCBASED = "ICCBased";
|
||||
static constexpr const char* COLOR_SPACE_NAME_INDEXED = "Indexed";
|
||||
static constexpr const char* COLOR_SPACE_NAME_SEPARATION = "Separation";
|
||||
|
||||
static constexpr const char* CAL_WHITE_POINT = "WhitePoint";
|
||||
static constexpr const char* CAL_BLACK_POINT = "BlackPoint";
|
||||
|
@ -284,7 +286,7 @@ protected:
|
|||
class PDFCalGrayColorSpace : public PDFXYZColorSpace
|
||||
{
|
||||
public:
|
||||
explicit inline PDFCalGrayColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColorComponent gamma);
|
||||
explicit PDFCalGrayColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColorComponent gamma);
|
||||
virtual ~PDFCalGrayColorSpace() = default;
|
||||
|
||||
virtual QColor getColor(const PDFColor& color) const override;
|
||||
|
@ -303,7 +305,7 @@ private:
|
|||
class PDFCalRGBColorSpace : public PDFXYZColorSpace
|
||||
{
|
||||
public:
|
||||
explicit inline PDFCalRGBColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColor3 gamma, PDFColorComponentMatrix_3x3 matrix);
|
||||
explicit PDFCalRGBColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColor3 gamma, PDFColorComponentMatrix_3x3 matrix);
|
||||
virtual ~PDFCalRGBColorSpace() = default;
|
||||
|
||||
virtual QColor getColor(const PDFColor& color) const override;
|
||||
|
@ -323,7 +325,7 @@ private:
|
|||
class PDFLabColorSpace : public PDFXYZColorSpace
|
||||
{
|
||||
public:
|
||||
explicit inline PDFLabColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColorComponent aMin, PDFColorComponent aMax, PDFColorComponent bMin, PDFColorComponent bMax);
|
||||
explicit PDFLabColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColorComponent aMin, PDFColorComponent aMax, PDFColorComponent bMin, PDFColorComponent bMax);
|
||||
virtual ~PDFLabColorSpace() = default;
|
||||
|
||||
virtual QColor getColor(const PDFColor& color) const override;
|
||||
|
@ -349,7 +351,7 @@ private:
|
|||
using Ranges = std::array<PDFColorComponent, MAX_COLOR_COMPONENTS * 2>;
|
||||
|
||||
public:
|
||||
explicit inline PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range);
|
||||
explicit PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range);
|
||||
virtual ~PDFICCBasedColorSpace() = default;
|
||||
|
||||
virtual QColor getDefaultColor() const override;
|
||||
|
@ -371,7 +373,7 @@ private:
|
|||
class PDFIndexedColorSpace : public PDFAbstractColorSpace
|
||||
{
|
||||
public:
|
||||
explicit inline PDFIndexedColorSpace(PDFColorSpacePointer baseColorSpace, QByteArray&& colors, int maxValue);
|
||||
explicit PDFIndexedColorSpace(PDFColorSpacePointer baseColorSpace, QByteArray&& colors, int maxValue);
|
||||
virtual ~PDFIndexedColorSpace() = default;
|
||||
|
||||
virtual QColor getDefaultColor() const override;
|
||||
|
@ -394,7 +396,29 @@ private:
|
|||
int m_maxValue;
|
||||
};
|
||||
|
||||
// TODO: Implement Separation color space
|
||||
class PDFSeparationColorSpace : public PDFAbstractColorSpace
|
||||
{
|
||||
public:
|
||||
explicit PDFSeparationColorSpace(QByteArray&& colorName, PDFColorSpacePointer alternateColorSpace, PDFFunctionPtr tintTransform);
|
||||
virtual ~PDFSeparationColorSpace() = default;
|
||||
|
||||
virtual QColor getDefaultColor() const override;
|
||||
virtual QColor getColor(const PDFColor& color) const override;
|
||||
virtual size_t getColorComponentCount() const override;
|
||||
|
||||
/// Creates separation color space from provided values.
|
||||
/// \param colorSpaceDictionary Color space dictionary
|
||||
/// \param document Document
|
||||
/// \param array Array with separation color space definition
|
||||
/// \param recursion Recursion guard
|
||||
static PDFColorSpacePointer createSeparationColorSpace(const PDFDictionary* colorSpaceDictionary, const PDFDocument* document, const PDFArray* array, int recursion);
|
||||
|
||||
private:
|
||||
QByteArray m_colorName;
|
||||
PDFColorSpacePointer m_alternateColorSpace;
|
||||
PDFFunctionPtr m_tintTransform;
|
||||
};
|
||||
|
||||
// TODO: Implement DeviceN color space
|
||||
// TODO: Implement Pattern color space
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
|
||||
}
|
||||
|
||||
using value_type = T;
|
||||
|
||||
/// Returns the size of the array
|
||||
size_t size() const { return getFlatBlockSize() + m_variableBlock.size(); }
|
||||
|
||||
|
|
|
@ -311,10 +311,12 @@ void PDFPageContentProcessor::processContentStream(const PDFStream* stream)
|
|||
}
|
||||
catch (PDFParserException exception)
|
||||
{
|
||||
m_operands.clear();
|
||||
m_errorList.append(PDFRenderError(RenderErrorType::Error, exception.getMessage()));
|
||||
}
|
||||
catch (PDFRendererException exception)
|
||||
{
|
||||
m_operands.clear();
|
||||
m_errorList.append(exception.getError());
|
||||
}
|
||||
}
|
||||
|
@ -1061,12 +1063,14 @@ void PDFPageContentProcessor::operatorEndSubpath()
|
|||
|
||||
void PDFPageContentProcessor::operatorRectangle(PDFReal x, PDFReal y, PDFReal width, PDFReal height)
|
||||
{
|
||||
if (width < 0 || height < 0)
|
||||
{
|
||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid size of rectangle (%1 x %2).").arg(width).arg(height));
|
||||
}
|
||||
const PDFReal xMin = qMin(x, x + width);
|
||||
const PDFReal xMax = qMax(x, x + width);
|
||||
const PDFReal yMin = qMin(y, y + height);
|
||||
const PDFReal yMax = qMax(y, y + height);
|
||||
const PDFReal correctedWidth = xMax - xMin;
|
||||
const PDFReal correctedHeight = yMax - yMin;
|
||||
|
||||
m_currentPath.addRect(QRectF(x, y, width, height));
|
||||
m_currentPath.addRect(QRectF(xMin, yMin, correctedWidth, correctedHeight));
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorPathStroke()
|
||||
|
@ -1233,8 +1237,10 @@ void PDFPageContentProcessor::operatorColorSetStrokingColor()
|
|||
|
||||
void PDFPageContentProcessor::operatorColorSetStrokingColorN()
|
||||
{
|
||||
// TODO: Implement operator SCN
|
||||
throw PDFRendererException(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Not implemented!"));
|
||||
// In our implementation, operator 'SC' can also set color using all color spaces
|
||||
// PDF reference 1.7 allows here Pattern, Separation, DeviceN and ICCBased color spaces here,
|
||||
// but default operator can use them (with exception of Pattern color space).
|
||||
operatorColorSetStrokingColor();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorColorSetFillingColor()
|
||||
|
@ -1261,8 +1267,10 @@ void PDFPageContentProcessor::operatorColorSetFillingColor()
|
|||
|
||||
void PDFPageContentProcessor::operatorColorSetFillingColorN()
|
||||
{
|
||||
// TODO: Implement operator scn
|
||||
throw PDFRendererException(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Not implemented!"));
|
||||
// In our implementation, operator 'sc' can also set color using all color spaces
|
||||
// PDF reference 1.7 allows here Pattern, Separation, DeviceN and ICCBased color spaces here,
|
||||
// but default operator can use them (with exception of Pattern color space).
|
||||
operatorColorSetFillingColor();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorColorSetDeviceGrayStroking(PDFReal gray)
|
||||
|
|
|
@ -75,14 +75,7 @@ void PDFPainter::performPathPainting(const QPainterPath& path, bool stroke, bool
|
|||
void PDFPainter::performClipping(const QPainterPath& path, Qt::FillRule fillRule)
|
||||
{
|
||||
Q_ASSERT(path.fillRule() == fillRule);
|
||||
if (m_painter->hasClipping())
|
||||
{
|
||||
m_painter->setClipPath(path, Qt::IntersectClip);
|
||||
}
|
||||
else
|
||||
{
|
||||
addError(PDFTranslationContext::tr("The paint device doesn't support clipping. Path was not clipped."));
|
||||
}
|
||||
m_painter->setClipPath(path, Qt::IntersectClip);
|
||||
}
|
||||
|
||||
void PDFPainter::performUpdateGraphicsState(const PDFPageContentProcessorState& state)
|
||||
|
|
Loading…
Reference in New Issue