Bugfix: invalid pattern matrix

This commit is contained in:
Jakub Melka 2019-09-16 19:42:14 +02:00
parent 41a6ddbc40
commit 64ae2c7fea
2 changed files with 28 additions and 14 deletions

View File

@ -33,6 +33,11 @@ PatternType PDFShadingPattern::getType() const
return PatternType::Shading; return PatternType::Shading;
} }
QMatrix PDFShadingPattern::getPatternSpaceToDeviceSpaceMatrix(const PDFMeshQualitySettings& settings) const
{
return m_matrix * settings.userSpaceToDeviceSpaceMatrix;
}
ShadingType PDFAxialShading::getShadingType() const ShadingType PDFAxialShading::getShadingType() const
{ {
return ShadingType::Axial; return ShadingType::Axial;
@ -340,6 +345,7 @@ PDFPatternPtr PDFPattern::createShadingPattern(const PDFDictionary* colorSpaceDi
gouradTriangleShading->m_antiAlias = antialias; gouradTriangleShading->m_antiAlias = antialias;
gouradTriangleShading->m_backgroundColor = backgroundColor; gouradTriangleShading->m_backgroundColor = backgroundColor;
gouradTriangleShading->m_colorSpace = colorSpace; gouradTriangleShading->m_colorSpace = colorSpace;
gouradTriangleShading->m_matrix = matrix;
gouradTriangleShading->m_patternGraphicState = patternGraphicState; gouradTriangleShading->m_patternGraphicState = patternGraphicState;
gouradTriangleShading->m_bitsPerCoordinate = static_cast<uint8_t>(bitsPerCoordinate); gouradTriangleShading->m_bitsPerCoordinate = static_cast<uint8_t>(bitsPerCoordinate);
gouradTriangleShading->m_bitsPerComponent = static_cast<uint8_t>(bitsPerComponent); gouradTriangleShading->m_bitsPerComponent = static_cast<uint8_t>(bitsPerComponent);
@ -393,7 +399,8 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings) c
{ {
PDFMesh mesh; PDFMesh mesh;
QMatrix domainToDeviceSpaceMatrix = m_domainToTargetTransform * settings.userSpaceToDeviceSpaceMatrix; QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(settings);
QMatrix domainToDeviceSpaceMatrix = m_domainToTargetTransform * patternSpaceToDeviceSpaceMatrix;
QLineF topLine(m_domain.topLeft(), m_domain.topRight()); QLineF topLine(m_domain.topLeft(), m_domain.topRight());
QLineF leftLine(m_domain.topLeft(), m_domain.bottomLeft()); QLineF leftLine(m_domain.topLeft(), m_domain.bottomLeft());
@ -684,7 +691,7 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings) c
if (m_boundingBox.isValid()) if (m_boundingBox.isValid())
{ {
QPainterPath boundingPath; QPainterPath boundingPath;
boundingPath.addPolygon(settings.userSpaceToDeviceSpaceMatrix.map(m_boundingBox)); boundingPath.addPolygon(patternSpaceToDeviceSpaceMatrix.map(m_boundingBox));
mesh.setBoundingPath(boundingPath); mesh.setBoundingPath(boundingPath);
} }
@ -695,8 +702,9 @@ PDFMesh PDFAxialShading::createMesh(const PDFMeshQualitySettings& settings) cons
{ {
PDFMesh mesh; PDFMesh mesh;
QPointF p1 = settings.userSpaceToDeviceSpaceMatrix.map(m_startPoint); QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(settings);
QPointF p2 = settings.userSpaceToDeviceSpaceMatrix.map(m_endPoint); QPointF p1 = patternSpaceToDeviceSpaceMatrix.map(m_startPoint);
QPointF p2 = patternSpaceToDeviceSpaceMatrix.map(m_endPoint);
// Strategy: for simplification, we rotate the line clockwise so we will // Strategy: for simplification, we rotate the line clockwise so we will
// get the shading axis equal to the x-axis. Then we will determine the shading // get the shading axis equal to the x-axis. Then we will determine the shading
@ -908,7 +916,7 @@ PDFMesh PDFAxialShading::createMesh(const PDFMeshQualitySettings& settings) cons
if (m_boundingBox.isValid()) if (m_boundingBox.isValid())
{ {
QPainterPath boundingPath; QPainterPath boundingPath;
boundingPath.addPolygon(settings.userSpaceToDeviceSpaceMatrix.map(m_boundingBox)); boundingPath.addPolygon(patternSpaceToDeviceSpaceMatrix.map(m_boundingBox));
mesh.setBoundingPath(boundingPath); mesh.setBoundingPath(boundingPath);
} }
@ -993,11 +1001,12 @@ PDFMesh PDFRadialShading::createMesh(const PDFMeshQualitySettings& settings) con
{ {
PDFMesh mesh; PDFMesh mesh;
QPointF p1 = settings.userSpaceToDeviceSpaceMatrix.map(m_startPoint); QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(settings);
QPointF p2 = settings.userSpaceToDeviceSpaceMatrix.map(m_endPoint); QPointF p1 = patternSpaceToDeviceSpaceMatrix.map(m_startPoint);
QPointF p2 = patternSpaceToDeviceSpaceMatrix.map(m_endPoint);
QPointF r1TestPoint = settings.userSpaceToDeviceSpaceMatrix.map(QPointF(m_startPoint.x(), m_startPoint.y() + m_r0)); QPointF r1TestPoint = patternSpaceToDeviceSpaceMatrix.map(QPointF(m_startPoint.x(), m_startPoint.y() + m_r0));
QPointF r2TestPoint = settings.userSpaceToDeviceSpaceMatrix.map(QPointF(m_endPoint.x(), m_endPoint.y() + m_r1)); QPointF r2TestPoint = patternSpaceToDeviceSpaceMatrix.map(QPointF(m_endPoint.x(), m_endPoint.y() + m_r1));
const PDFReal r1 = QLineF(p1, r1TestPoint).length(); const PDFReal r1 = QLineF(p1, r1TestPoint).length();
const PDFReal r2 = QLineF(p2, r2TestPoint).length(); const PDFReal r2 = QLineF(p2, r2TestPoint).length();
@ -1266,7 +1275,7 @@ PDFMesh PDFRadialShading::createMesh(const PDFMeshQualitySettings& settings) con
if (m_boundingBox.isValid()) if (m_boundingBox.isValid())
{ {
QPainterPath boundingPath; QPainterPath boundingPath;
boundingPath.addPolygon(settings.userSpaceToDeviceSpaceMatrix.map(m_boundingBox)); boundingPath.addPolygon(patternSpaceToDeviceSpaceMatrix.map(m_boundingBox));
mesh.setBoundingPath(boundingPath); mesh.setBoundingPath(boundingPath);
} }
@ -1282,6 +1291,7 @@ PDFMesh PDFFreeFormGouradTriangleShading::createMesh(const PDFMeshQualitySetting
{ {
PDFMesh mesh; PDFMesh mesh;
QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(settings);
size_t bitsPerVertex = m_bitsPerFlag + 2 * m_bitsPerCoordinate + m_colorComponentCount * m_bitsPerComponent; size_t bitsPerVertex = m_bitsPerFlag + 2 * m_bitsPerCoordinate + m_colorComponentCount * m_bitsPerComponent;
size_t remainder = (8 - (bitsPerVertex % 8)) % 8; size_t remainder = (8 - (bitsPerVertex % 8)) % 8;
bitsPerVertex += remainder; bitsPerVertex += remainder;
@ -1319,7 +1329,7 @@ PDFMesh PDFFreeFormGouradTriangleShading::createMesh(const PDFMeshQualitySetting
std::vector<QPointF> meshVertices; std::vector<QPointF> meshVertices;
meshVertices.resize(vertexCount); meshVertices.resize(vertexCount);
auto readVertex = [this, &vertices, &settings, &meshVertices, bytesPerVertex, xScaleRatio, yScaleRatio, colorScaleRatio](size_t index) auto readVertex = [this, &vertices, &patternSpaceToDeviceSpaceMatrix, &meshVertices, bytesPerVertex, xScaleRatio, yScaleRatio, colorScaleRatio](size_t index)
{ {
PDFBitReader reader(&m_data, 8); PDFBitReader reader(&m_data, 8);
reader.seek(index * bytesPerVertex); reader.seek(index * bytesPerVertex);
@ -1329,7 +1339,7 @@ PDFMesh PDFFreeFormGouradTriangleShading::createMesh(const PDFMeshQualitySetting
data.flags = reader.read(m_bitsPerFlag); data.flags = reader.read(m_bitsPerFlag);
const PDFReal x = m_xmin + (reader.read(m_bitsPerCoordinate)) * xScaleRatio; const PDFReal x = m_xmin + (reader.read(m_bitsPerCoordinate)) * xScaleRatio;
const PDFReal y = m_ymin + (reader.read(m_bitsPerCoordinate)) * yScaleRatio; const PDFReal y = m_ymin + (reader.read(m_bitsPerCoordinate)) * yScaleRatio;
data.position = settings.userSpaceToDeviceSpaceMatrix.map(QPointF(x, y)); data.position = patternSpaceToDeviceSpaceMatrix.map(QPointF(x, y));
data.color.resize(m_colorComponentCount); data.color.resize(m_colorComponentCount);
meshVertices[index] = data.position; meshVertices[index] = data.position;
@ -1457,6 +1467,7 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
{ {
PDFMesh mesh; PDFMesh mesh;
QMatrix patternSpaceToDeviceSpaceMatrix = getPatternSpaceToDeviceSpaceMatrix(settings);
size_t bitsPerVertex = 2 * m_bitsPerCoordinate + m_colorComponentCount * m_bitsPerComponent; size_t bitsPerVertex = 2 * m_bitsPerCoordinate + m_colorComponentCount * m_bitsPerComponent;
size_t remainder = (8 - (bitsPerVertex % 8)) % 8; size_t remainder = (8 - (bitsPerVertex % 8)) % 8;
bitsPerVertex += remainder; bitsPerVertex += remainder;
@ -1495,7 +1506,7 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
std::vector<QPointF> meshVertices; std::vector<QPointF> meshVertices;
meshVertices.resize(vertexCount); meshVertices.resize(vertexCount);
auto readVertex = [this, &vertices, &settings, &meshVertices, bytesPerVertex, xScaleRatio, yScaleRatio, colorScaleRatio](size_t index) auto readVertex = [this, &vertices, &patternSpaceToDeviceSpaceMatrix, &meshVertices, bytesPerVertex, xScaleRatio, yScaleRatio, colorScaleRatio](size_t index)
{ {
PDFBitReader reader(&m_data, 8); PDFBitReader reader(&m_data, 8);
reader.seek(index * bytesPerVertex); reader.seek(index * bytesPerVertex);
@ -1504,7 +1515,7 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett
data.index = static_cast<uint32_t>(index); data.index = static_cast<uint32_t>(index);
const PDFReal x = m_xmin + (reader.read(m_bitsPerCoordinate)) * xScaleRatio; const PDFReal x = m_xmin + (reader.read(m_bitsPerCoordinate)) * xScaleRatio;
const PDFReal y = m_ymin + (reader.read(m_bitsPerCoordinate)) * yScaleRatio; const PDFReal y = m_ymin + (reader.read(m_bitsPerCoordinate)) * yScaleRatio;
data.position = settings.userSpaceToDeviceSpaceMatrix.map(QPointF(x, y)); data.position = patternSpaceToDeviceSpaceMatrix.map(QPointF(x, y));
data.color.resize(m_colorComponentCount); data.color.resize(m_colorComponentCount);
meshVertices[index] = data.position; meshVertices[index] = data.position;

View File

@ -243,6 +243,9 @@ public:
/// Returns true, if shading pattern should be anti-aliased /// Returns true, if shading pattern should be anti-aliased
bool isAntialiasing() const { return m_antiAlias; } bool isAntialiasing() const { return m_antiAlias; }
/// Returns matrix transforming pattern space to device space
QMatrix getPatternSpaceToDeviceSpaceMatrix(const PDFMeshQualitySettings& settings) const;
protected: protected:
friend class PDFPattern; friend class PDFPattern;