mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			747 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			747 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//    Copyright (C) 2019-2021 Jakub Melka
 | 
						|
//
 | 
						|
//    This file is part of PDF4QT.
 | 
						|
//
 | 
						|
//    PDF4QT is free software: you can redistribute it and/or modify
 | 
						|
//    it under the terms of the GNU Lesser General Public License as published by
 | 
						|
//    the Free Software Foundation, either version 3 of the License, or
 | 
						|
//    with the written consent of the copyright owner, any later version.
 | 
						|
//
 | 
						|
//    PDF4QT is distributed in the hope that it will be useful,
 | 
						|
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
//    GNU Lesser General Public License for more details.
 | 
						|
//
 | 
						|
//    You should have received a copy of the GNU Lesser General Public License
 | 
						|
//    along with PDF4QT.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
#ifndef PDFPATTERN_H
 | 
						|
#define PDFPATTERN_H
 | 
						|
 | 
						|
#include "pdfobject.h"
 | 
						|
#include "pdffunction.h"
 | 
						|
#include "pdfcolorspaces.h"
 | 
						|
#include "pdfmeshqualitysettings.h"
 | 
						|
 | 
						|
#include <QMatrix>
 | 
						|
#include <QPainterPath>
 | 
						|
 | 
						|
#include <memory>
 | 
						|
 | 
						|
namespace pdf
 | 
						|
{
 | 
						|
class PDFPattern;
 | 
						|
class PDFTilingPattern;
 | 
						|
class PDFShadingPattern;
 | 
						|
 | 
						|
using PDFPatternPtr = std::shared_ptr<PDFPattern>;
 | 
						|
 | 
						|
enum class PatternType
 | 
						|
{
 | 
						|
    Invalid = 0,
 | 
						|
    Tiling = 1,
 | 
						|
    Shading = 2,
 | 
						|
};
 | 
						|
 | 
						|
enum class ShadingType
 | 
						|
{
 | 
						|
    Invalid = 0,
 | 
						|
    Function = 1,
 | 
						|
    Axial = 2,
 | 
						|
    Radial = 3,
 | 
						|
    FreeFormGouradTriangle = 4,
 | 
						|
    LatticeFormGouradTriangle = 5,
 | 
						|
    CoonsPatchMesh = 6,
 | 
						|
    TensorProductPatchMesh = 7
 | 
						|
};
 | 
						|
 | 
						|
/// Mesh consisting of triangles
 | 
						|
class PDFMesh
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFMesh() = default;
 | 
						|
 | 
						|
    struct Triangle
 | 
						|
    {
 | 
						|
        uint32_t v1 = 0;
 | 
						|
        uint32_t v2 = 0;
 | 
						|
        uint32_t v3 = 0;
 | 
						|
 | 
						|
        QRgb color;
 | 
						|
    };
 | 
						|
 | 
						|
    /// Adds vertex. Returns index of added vertex.
 | 
						|
    /// \param vertex Vertex to be added
 | 
						|
    /// \returns Index of the added vertex
 | 
						|
    inline uint32_t addVertex(const QPointF& vertex) { const size_t index = m_vertices.size(); m_vertices.emplace_back(vertex); return static_cast<uint32_t>(index); }
 | 
						|
 | 
						|
    /// Adds triangle. Returns index of added triangle.
 | 
						|
    /// \param triangle Triangle to be added
 | 
						|
    /// \returns Index of the added vertex
 | 
						|
    inline uint32_t addTriangle(const Triangle& triangle) { const size_t index = m_triangles.size(); m_triangles.emplace_back(triangle); return static_cast<uint32_t>(index); }
 | 
						|
 | 
						|
    /// Adds quad. Vertices are in clockwise order (so, we have edges v1-v2, v2-v3, v3-v4, v4-v1).
 | 
						|
    /// \param v1 First vertex (for example, topleft)
 | 
						|
    /// \param v2 Second vertex (for example, topright)
 | 
						|
    /// \param v3 Third vertex (for example, bottomright)
 | 
						|
    /// \param v4 Fourth vertex (for example, bottomleft)
 | 
						|
    /// \param color Color of the quad.
 | 
						|
    inline void addQuad(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t v4, QRgb color) { addTriangle({v1, v2, v3, color}); addTriangle({ v1, v3, v4, color}); }
 | 
						|
 | 
						|
    /// Paints the mesh on the painter
 | 
						|
    /// \param painter Painter, onto which is mesh drawn
 | 
						|
    /// \param alpha Opacity factor
 | 
						|
    void paint(QPainter* painter, PDFReal alpha) const;
 | 
						|
 | 
						|
    /// Transforms the mesh according to the matrix transform
 | 
						|
    /// \param matrix Matrix transform to be performed
 | 
						|
    void transform(const QMatrix& matrix);
 | 
						|
 | 
						|
    /// Reserves memory for meshing - both number of vertices and triangles.
 | 
						|
    /// Use this function, if number of vertices and triangles is known.
 | 
						|
    /// \param vertexCount Vertex count
 | 
						|
    /// \param triangleCount Triangle count
 | 
						|
    void reserve(size_t vertexCount, size_t triangleCount) { m_vertices.reserve(vertexCount); m_triangles.reserve(triangleCount); }
 | 
						|
 | 
						|
    const QPainterPath& getBoundingPath() const { return m_boundingPath; }
 | 
						|
    void setBoundingPath(const QPainterPath& path) { m_boundingPath = path; }
 | 
						|
 | 
						|
    /// Sets the vertex array to the mesh
 | 
						|
    /// \param vertices New vertex array
 | 
						|
    void setVertices(std::vector<QPointF>&& vertices) { m_vertices = qMove(vertices); }
 | 
						|
 | 
						|
    /// Sets the triangle array to the mesh
 | 
						|
    /// \param triangles New triangle array
 | 
						|
    void setTriangles(std::vector<Triangle>&& triangles) { m_triangles = qMove(triangles); }
 | 
						|
 | 
						|
    /// Merges the vertices/triangles (renumbers triangle indices) to this mesh.
 | 
						|
    /// Algorithm assumes that vertices/triangles are numbered from zero.
 | 
						|
    /// \param vertices Added vertex array
 | 
						|
    /// \param triangles Added triangle array
 | 
						|
    void addMesh(std::vector<QPointF>&& vertices, std::vector<Triangle>&& triangles);
 | 
						|
 | 
						|
    /// Returns vertex at given index
 | 
						|
    /// \param index Index of the vertex
 | 
						|
    const QPointF& getVertex(size_t index) const { return m_vertices[index]; }
 | 
						|
 | 
						|
    /// Returns triangle center. Triangles vertice indices must be valid.
 | 
						|
    /// \param triangle Triangle
 | 
						|
    QPointF getTriangleCenter(const Triangle& triangle) const;
 | 
						|
 | 
						|
    /// Sets the background path. In order to draw background properly, the background
 | 
						|
    /// color must be set to a valid color.
 | 
						|
    /// \param path Background path
 | 
						|
    void setBackgroundPath(QPainterPath path) { m_backgroundPath = qMove(path); }
 | 
						|
 | 
						|
    /// Sets the background color (background path is then painted with this color, if it is not
 | 
						|
    /// empty), if color is invalid, it turns off background painting.
 | 
						|
    /// \param backgroundColor Background color
 | 
						|
    void setBackgroundColor(QColor backgroundColor) { m_backgroundColor = backgroundColor; }
 | 
						|
 | 
						|
    /// Returns true, if mesh is empty
 | 
						|
    bool isEmpty() const { return m_vertices.empty(); }
 | 
						|
 | 
						|
    /// Returns estimate of number of bytes, which this mesh occupies in memory
 | 
						|
    qint64 getMemoryConsumptionEstimate() const;
 | 
						|
 | 
						|
    /// Invert colors
 | 
						|
    void invertColors();
 | 
						|
 | 
						|
private:
 | 
						|
    std::vector<QPointF> m_vertices;
 | 
						|
    std::vector<Triangle> m_triangles;
 | 
						|
    QPainterPath m_boundingPath;
 | 
						|
    QPainterPath m_backgroundPath;
 | 
						|
    QColor m_backgroundColor;
 | 
						|
};
 | 
						|
 | 
						|
/// Represents tiling/shading pattern
 | 
						|
class PDFPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFPattern() = default;
 | 
						|
    virtual ~PDFPattern() = default;
 | 
						|
 | 
						|
    virtual PatternType getType() const = 0;
 | 
						|
    virtual const PDFShadingPattern* getShadingPattern() const = 0;
 | 
						|
    virtual const PDFTilingPattern* getTilingPattern() const = 0;
 | 
						|
 | 
						|
    /// Returns bounding box in the shadings target coordinate system (not in
 | 
						|
    /// pattern coordinate system).
 | 
						|
    const QRectF& getBoundingBox() const { return m_boundingBox; }
 | 
						|
 | 
						|
    /// Returns transformation matrix from pattern space to the default
 | 
						|
    /// target space.
 | 
						|
    const QMatrix& getMatrix() const { return m_matrix; }
 | 
						|
 | 
						|
    /// Create pattern from the object. If error occurs, exception is thrown
 | 
						|
    /// \param colorSpaceDictionary Color space dictionary
 | 
						|
    /// \param document Document, owning the pdf object
 | 
						|
    /// \param object Object defining the pattern
 | 
						|
    /// \param cms Color management system
 | 
						|
    /// \param intent Rendering intent
 | 
						|
    /// \param reporter Error reporter
 | 
						|
    static PDFPatternPtr createPattern(const PDFDictionary* colorSpaceDictionary,
 | 
						|
                                       const PDFDocument* document,
 | 
						|
                                       const PDFObject& object,
 | 
						|
                                       const PDFCMS* cms,
 | 
						|
                                       RenderingIntent intent,
 | 
						|
                                       PDFRenderErrorReporter* reporter);
 | 
						|
 | 
						|
    /// Create shading pattern from the object. If error occurs, exception is thrown
 | 
						|
    /// \param colorSpaceDictionary Color space dictionary
 | 
						|
    /// \param document Document, owning the pdf object
 | 
						|
    /// \param object Object defining the shading
 | 
						|
    /// \param matrix Matrix converting reference coordinate system to the device coordinate system
 | 
						|
    /// \param patternGraphicState Pattern graphic state
 | 
						|
    /// \param cms Color management system
 | 
						|
    /// \param intent Rendering intent
 | 
						|
    /// \param reporter Error reporter
 | 
						|
    /// \param ignoreBackgroundColor If set, then ignores background color, even if it is present
 | 
						|
    static PDFPatternPtr createShadingPattern(const PDFDictionary* colorSpaceDictionary,
 | 
						|
                                              const PDFDocument* document,
 | 
						|
                                              const PDFObject& shadingObject,
 | 
						|
                                              const QMatrix& matrix,
 | 
						|
                                              const PDFObject& patternGraphicState,
 | 
						|
                                              const PDFCMS* cms,
 | 
						|
                                              RenderingIntent intent,
 | 
						|
                                              PDFRenderErrorReporter* reporter,
 | 
						|
                                              bool ignoreBackgroundColor);
 | 
						|
 | 
						|
protected:
 | 
						|
    QRectF m_boundingBox;
 | 
						|
    QMatrix m_matrix;
 | 
						|
};
 | 
						|
 | 
						|
class PDFInvalidPattern : public PDFPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFInvalidPattern() = default;
 | 
						|
 | 
						|
    virtual PatternType getType() const override { return PatternType::Invalid; }
 | 
						|
    virtual const PDFShadingPattern* getShadingPattern() const override { return nullptr; }
 | 
						|
    virtual const PDFTilingPattern* getTilingPattern() const override { return nullptr; }
 | 
						|
};
 | 
						|
 | 
						|
class PDFTilingPattern : public PDFPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFTilingPattern() = default;
 | 
						|
 | 
						|
    virtual PatternType getType() const override { return PatternType::Tiling; }
 | 
						|
    virtual const PDFShadingPattern* getShadingPattern() const override { return nullptr; }
 | 
						|
    virtual const PDFTilingPattern* getTilingPattern() const override { return this; }
 | 
						|
 | 
						|
    enum class PaintType
 | 
						|
    {
 | 
						|
        Colored = 1,
 | 
						|
        Uncolored = 2,
 | 
						|
        Invalid = 3
 | 
						|
    };
 | 
						|
 | 
						|
    enum class TilingType
 | 
						|
    {
 | 
						|
        ConstantSpacing = 1,
 | 
						|
        NoDistortion = 2,
 | 
						|
        ConstantSpacingAndFasterTiling = 3,
 | 
						|
        Invalid
 | 
						|
    };
 | 
						|
 | 
						|
    PaintType getPaintingType() const { return m_paintType; }
 | 
						|
    TilingType getTilingType() const { return m_tilingType; }
 | 
						|
    PDFReal getXStep() const { return m_xStep; }
 | 
						|
    PDFReal getYStep() const { return m_yStep; }
 | 
						|
    const PDFObject& getResources() const { return m_resources; }
 | 
						|
    const QByteArray& getContent() const { return m_content; }
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    PaintType m_paintType = PaintType::Colored;
 | 
						|
    TilingType m_tilingType = TilingType::ConstantSpacing;
 | 
						|
    PDFReal m_xStep = 0.0;
 | 
						|
    PDFReal m_yStep = 0.0;
 | 
						|
    PDFObject m_resources;
 | 
						|
    QByteArray m_content;
 | 
						|
};
 | 
						|
 | 
						|
/// Compute color of sample points from shading pattern. Some sampler implementation
 | 
						|
/// uses numerical algorithms (such as Newton-Raphson method for type 6/7 shading), so
 | 
						|
/// calculation can be very slow for some types of shadings.
 | 
						|
class PDFShadingSampler
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit inline PDFShadingSampler(const PDFShadingPattern* pattern) :
 | 
						|
        m_pattern(pattern)
 | 
						|
    {
 | 
						|
 | 
						|
    }
 | 
						|
    virtual ~PDFShadingSampler() = default;
 | 
						|
 | 
						|
    /// Try to compute color of the point in device space coordinates in the shading. If color
 | 
						|
    /// can't be computed, then false is returned, otherwise true is returned.
 | 
						|
    /// \param devicePoint Point in device space coordinates
 | 
						|
    /// \param outputBuffer Color output buffer (where computed color is stored)
 | 
						|
    /// \param limit Maximal number of the steps of numerical calculation algorithms (for type 6/7 shading only)
 | 
						|
    virtual bool sample(const QPointF& devicePoint, PDFColorBuffer outputBuffer, int limit) const = 0;
 | 
						|
 | 
						|
    /// Fill background color to the output buffer. If the background color is not filled,
 | 
						|
    /// or is invalid, then false is returned, otherwise true is returned.
 | 
						|
    bool fillBackgroundColor(PDFColorBuffer outputBuffer) const;
 | 
						|
 | 
						|
protected:
 | 
						|
    const PDFShadingPattern* m_pattern;
 | 
						|
};
 | 
						|
 | 
						|
/// Shading pattern - smooth color distribution along the pattern's space
 | 
						|
class PDFShadingPattern : public PDFPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFShadingPattern() = default;
 | 
						|
 | 
						|
    virtual PatternType getType() const override;
 | 
						|
    virtual ShadingType getShadingType() const = 0;
 | 
						|
    virtual const PDFShadingPattern* getShadingPattern() const override { return this; }
 | 
						|
    virtual const PDFTilingPattern* getTilingPattern() const override { return nullptr; }
 | 
						|
 | 
						|
    /// Creates a colored mesh using settings. Mesh is generated in device space
 | 
						|
    /// coordinate system. You must transform the mesh, if you want to
 | 
						|
    /// use it in another coordinate system.
 | 
						|
    /// \param settings Meshing settings
 | 
						|
    /// \param cms Color management system
 | 
						|
    /// \param intent Rendering intent
 | 
						|
    /// \param reporter Error reporter
 | 
						|
    /// \param operationControl Operation control
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms, RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const = 0;
 | 
						|
 | 
						|
    /// Returns patterns graphic state. This state must be applied before
 | 
						|
    /// the shading pattern is painted to the target device.
 | 
						|
    const PDFObject& getPatternGraphicState() const { return m_patternGraphicState; }
 | 
						|
 | 
						|
    /// Returns color space of the pattern.
 | 
						|
    const PDFAbstractColorSpace* getColorSpace() const;
 | 
						|
 | 
						|
    /// Returns color space pointer
 | 
						|
    const PDFColorSpacePointer& getColorSpacePtr() const { return m_colorSpace; }
 | 
						|
 | 
						|
    /// Returns patterns background color (if pattern has background color).
 | 
						|
    /// If pattern has not background color, then invalid color is returned.
 | 
						|
    const QColor& getBackgroundColor() const { return m_backgroundColor; }
 | 
						|
 | 
						|
    /// Returns original background color (in color space of the shading pattern)
 | 
						|
    const PDFColor& getOriginalBackgroundColor() const { return m_originalBackgroundColor; }
 | 
						|
 | 
						|
    /// Returns true, if shading pattern should be anti-aliased
 | 
						|
    bool isAntialiasing() const { return m_antiAlias; }
 | 
						|
 | 
						|
    /// Returns matrix transforming pattern space to device space
 | 
						|
    QMatrix getPatternSpaceToDeviceSpaceMatrix(const PDFMeshQualitySettings& settings) const;
 | 
						|
 | 
						|
    /// Returns matrix transforming pattern space to device space
 | 
						|
    QMatrix getPatternSpaceToDeviceSpaceMatrix(const QMatrix& userSpaceToDeviceSpaceMatrix) const;
 | 
						|
 | 
						|
    /// Create sampler which can compute shading colors in device space coordinates. If sampler can't
 | 
						|
    /// be created (or shading is invalid), then nullptr is returned.
 | 
						|
    /// \param userSpaceToDeviceSpaceMatrix Matrix, which transforms user space points
 | 
						|
    ///        (user space is target space of the shading) to the device space of the paint device.
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const;
 | 
						|
 | 
						|
protected:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    PDFObject m_patternGraphicState;
 | 
						|
    PDFColorSpacePointer m_colorSpace;
 | 
						|
    QColor m_backgroundColor;
 | 
						|
    PDFColor m_originalBackgroundColor;
 | 
						|
    bool m_antiAlias = false;
 | 
						|
};
 | 
						|
 | 
						|
class PDFSingleDimensionShading : public PDFShadingPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFSingleDimensionShading() = default;
 | 
						|
 | 
						|
    const std::vector<PDFFunctionPtr>& getFunctions() const { return m_functions; }
 | 
						|
    const QPointF& getStartPoint() const { return m_startPoint; }
 | 
						|
    const QPointF& getEndPoint() const { return m_endPoint; }
 | 
						|
    PDFReal getDomainStart() const { return m_domainStart; }
 | 
						|
    PDFReal getDomainEnd() const { return m_domainEnd; }
 | 
						|
    bool isExtendStart() const { return m_extendStart; }
 | 
						|
    bool isExtendEnd() const { return m_extendEnd; }
 | 
						|
 | 
						|
protected:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    std::vector<PDFFunctionPtr> m_functions;
 | 
						|
    QPointF m_startPoint;
 | 
						|
    QPointF m_endPoint;
 | 
						|
    PDFReal m_domainStart = 0.0;
 | 
						|
    PDFReal m_domainEnd = 1.0;
 | 
						|
    bool m_extendStart = false;
 | 
						|
    bool m_extendEnd = false;
 | 
						|
};
 | 
						|
 | 
						|
class PDFFunctionShading : public PDFShadingPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFFunctionShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
 | 
						|
 | 
						|
    const QRectF& getDomain() const { return m_domain; }
 | 
						|
    const QMatrix& getDomainToTargetTransform() const { return m_domainToTargetTransform; }
 | 
						|
    const std::vector<PDFFunctionPtr>& getFunctions() const { return m_functions; }
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    QRectF m_domain; ///< Domain of the color function
 | 
						|
    QMatrix m_domainToTargetTransform; ///< Transformation mapping from domain to shading coordinate space
 | 
						|
    std::vector<PDFFunctionPtr> m_functions; ///< Color functions
 | 
						|
};
 | 
						|
 | 
						|
class PDFAxialShading : public PDFSingleDimensionShading
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFAxialShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
};
 | 
						|
 | 
						|
class PDFRadialShading : public PDFSingleDimensionShading
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFRadialShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
 | 
						|
 | 
						|
    PDFReal getR0() const { return m_r0; }
 | 
						|
    PDFReal getR1() const { return m_r1; }
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    PDFReal m_r0 = 0.0;
 | 
						|
    PDFReal m_r1 = 0.0;
 | 
						|
};
 | 
						|
 | 
						|
class PDFType4567Shading : public PDFShadingPattern
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFType4567Shading() = default;
 | 
						|
 | 
						|
    /// Returns color for given color or function parameter
 | 
						|
    PDFColor getColor(PDFColor colorOrFunctionParameter) const;
 | 
						|
 | 
						|
protected:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    void addSubdividedTriangles(const PDFMeshQualitySettings& settings,
 | 
						|
                                PDFMesh& mesh,
 | 
						|
                                uint32_t v1,
 | 
						|
                                uint32_t v2,
 | 
						|
                                uint32_t v3,
 | 
						|
                                PDFColor c1,
 | 
						|
                                PDFColor c2,
 | 
						|
                                PDFColor c3,
 | 
						|
                                const PDFCMS* cms,
 | 
						|
                                RenderingIntent intent,
 | 
						|
                                PDFRenderErrorReporter* reporter) const;
 | 
						|
 | 
						|
    uint8_t m_bitsPerCoordinate = 0;
 | 
						|
    uint8_t m_bitsPerComponent = 0;
 | 
						|
    uint8_t m_bitsPerFlag = 0;
 | 
						|
    PDFReal m_xmin = 0.0;
 | 
						|
    PDFReal m_xmax = 0.0;
 | 
						|
    PDFReal m_ymin = 0.0;
 | 
						|
    PDFReal m_ymax = 0.0;
 | 
						|
    std::vector<PDFReal> m_limits;
 | 
						|
    size_t m_colorComponentCount = 0;
 | 
						|
 | 
						|
    /// Color functions. This array can be empty. If it is empty,
 | 
						|
    /// then colors should be determined directly from color space.
 | 
						|
    std::vector<PDFFunctionPtr> m_functions;
 | 
						|
 | 
						|
    /// Data of the shading, containing triangles and colors
 | 
						|
    QByteArray m_data;
 | 
						|
};
 | 
						|
 | 
						|
class PDFFreeFormGouradTriangleShading : public PDFType4567Shading
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFFreeFormGouradTriangleShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
 | 
						|
 | 
						|
private:
 | 
						|
    struct VertexData
 | 
						|
    {
 | 
						|
        uint32_t index = 0;
 | 
						|
        uint8_t flags = 0;
 | 
						|
        QPointF position;
 | 
						|
        PDFColor color;
 | 
						|
    };
 | 
						|
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    using InitializeFunction = std::function<void(std::vector<QPointF>&&, size_t)>;
 | 
						|
    using AddTriangleFunction = std::function<void(const VertexData*, const VertexData*, const VertexData*)>;
 | 
						|
 | 
						|
    bool processTriangles(InitializeFunction initializeMeshFunction,
 | 
						|
                          AddTriangleFunction addTriangle,
 | 
						|
                          const QMatrix& userSpaceToDeviceSpaceMatrix,
 | 
						|
                          bool convertColors) const;
 | 
						|
};
 | 
						|
 | 
						|
class PDFLatticeFormGouradTriangleShading : public PDFType4567Shading
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFLatticeFormGouradTriangleShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
 | 
						|
    struct VertexData
 | 
						|
    {
 | 
						|
        uint32_t index = 0;
 | 
						|
        QPointF position;
 | 
						|
        PDFColor color;
 | 
						|
    };
 | 
						|
 | 
						|
    using InitializeFunction = std::function<void(std::vector<QPointF>&&, size_t)>;
 | 
						|
    using AddTriangleFunction = std::function<void(const VertexData*, const VertexData*, const VertexData*)>;
 | 
						|
 | 
						|
    bool processTriangles(InitializeFunction initializeMeshFunction,
 | 
						|
                          AddTriangleFunction addTriangle,
 | 
						|
                          const QMatrix& userSpaceToDeviceSpaceMatrix,
 | 
						|
                          bool convertColors) const;
 | 
						|
 | 
						|
    PDFInteger m_verticesPerRow = 0;
 | 
						|
};
 | 
						|
 | 
						|
class PDFTensorPatch
 | 
						|
{
 | 
						|
public:
 | 
						|
    enum ColorIndex
 | 
						|
    {
 | 
						|
        C_00 = 0,
 | 
						|
        C_03 = 1,
 | 
						|
        C_33 = 2,
 | 
						|
        C_30 = 3
 | 
						|
    };
 | 
						|
 | 
						|
    using PointMatrix = std::array<std::array<QPointF, 4>, 4>;
 | 
						|
    using Colors = std::array<PDFColor, 4>;
 | 
						|
 | 
						|
    explicit inline PDFTensorPatch(PointMatrix P, Colors colors) : m_P(P), m_colors(colors) { computeBoundingRectangle(); }
 | 
						|
 | 
						|
    /// Calculates value at point in the patch.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    QPointF getValue(PDFReal u, PDFReal v) const;
 | 
						|
 | 
						|
    /// Calculates value at point in the patch, possibly derivation, if derivation
 | 
						|
    /// variables are positive.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param derivativeOrderU Derivation order in direction u (0 means no derivation)
 | 
						|
    /// \param derivativeOrderV Derivation order in direction v (0 means no derivation)
 | 
						|
    QPointF getValue(PDFReal u, PDFReal v, int derivativeOrderU, int derivativeOrderV) const;
 | 
						|
 | 
						|
    /// Tries to find value (u,v) using Newton-Raphson numerical algorithm method.
 | 
						|
    /// This can fail and when it fails, false is returned. As initial point, input uv
 | 
						|
    /// is considered. Also, if maximal number of steps is reached, false is returned.
 | 
						|
    /// \param[in,out] u Output value of u (passed value is used as a seed)
 | 
						|
    /// \param[in,out] v Output value of v (passed value is used as a seed)
 | 
						|
    /// \param x Input x coordinate, for which we want to compute (u, v)
 | 
						|
    /// \param y Input y coordinate, for which we want to compute (u, v)
 | 
						|
    /// \param epsilon Epsilon, when distance from the getValue(u, v) and (x, y)
 | 
						|
    ///                is less than epsilon, convergence is reached
 | 
						|
    /// \param maximalNumberOfSteps Maximal number of steps of Newton-Raphson algorithm
 | 
						|
    bool getUV(PDFReal& u, PDFReal& v, PDFReal x, PDFReal y, PDFReal epsilon, int maximalNumberOfSteps) const;
 | 
						|
 | 
						|
    /// Calculates first derivate in the surface, in the direction of variable u.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    QPointF getDerivative_u(PDFReal u, PDFReal v) const { return getValue(u, v, 1, 0); }
 | 
						|
 | 
						|
    /// Calculates second derivate in the surface, in the direction of variable u.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    QPointF getDerivative_uu(PDFReal u, PDFReal v) const { return getValue(u, v, 2, 0); }
 | 
						|
 | 
						|
    /// Calculates first derivate in the surface, in the direction of variable v.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    QPointF getDerivative_v(PDFReal u, PDFReal v) const { return getValue(u, v, 0, 1); }
 | 
						|
 | 
						|
    /// Calculates second derivate in the surface, in the direction of variable v.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    QPointF getDerivative_vv(PDFReal u, PDFReal v) const { return getValue(u, v, 0, 2); }
 | 
						|
 | 
						|
    /// Calculates curvature of the given point in the surface, in the direction of u.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    PDFReal getCurvature_u(PDFReal u, PDFReal v) const;
 | 
						|
 | 
						|
    /// Calculates curvature of the given point in the surface, in the direction of v.
 | 
						|
    /// \param u Horizontal coordinate of the patch, must be in range [0, 1]
 | 
						|
    /// \param v Vertical coordinate of the patch, must be in range [0, 1]
 | 
						|
    PDFReal getCurvature_v(PDFReal u, PDFReal v) const;
 | 
						|
 | 
						|
    /// Returns matrix of control points
 | 
						|
    const PointMatrix& getP() const { return m_P; }
 | 
						|
 | 
						|
    /// Returns colors of corner points
 | 
						|
    const Colors& getColors() const { return m_colors; }
 | 
						|
 | 
						|
private:
 | 
						|
    /// Computes Bernstein polynomial B0, B1, B2, B3, for parameter t.
 | 
						|
    /// If \p derivative is zero, then it evaluates polynomial's value,
 | 
						|
    /// otherwise it computes value of the derivation of Bx, up to degree 3
 | 
						|
    /// derivation.
 | 
						|
    /// \param index Index of polynomial, from 0 to 3 (B0, B1, B2, B3)
 | 
						|
    /// \param t Parameter of polynomial function
 | 
						|
    /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation)
 | 
						|
    static constexpr PDFReal B(int index, PDFReal t, int derivativeOrder);
 | 
						|
 | 
						|
    /// Computes Bernstein polynomial B0 for parameter t.
 | 
						|
    /// If \p derivative is zero, then it evaluates polynomial's value,
 | 
						|
    /// otherwise it computes value of the derivation of B0, up to degree 3
 | 
						|
    /// derivation.
 | 
						|
    /// \param t Parameter of polynomial function
 | 
						|
    /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation)
 | 
						|
    static constexpr PDFReal B0(PDFReal t, int derivative);
 | 
						|
 | 
						|
    /// Computes Bernstein polynomial B1 for parameter t.
 | 
						|
    /// If \p derivative is zero, then it evaluates polynomial's value,
 | 
						|
    /// otherwise it computes value of the derivation of B1, up to degree 3
 | 
						|
    /// derivation.
 | 
						|
    /// \param t Parameter of polynomial function
 | 
						|
    /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation)
 | 
						|
    static constexpr PDFReal B1(PDFReal t, int derivative);
 | 
						|
 | 
						|
    /// Computes Bernstein polynomial B2 for parameter t.
 | 
						|
    /// If \p derivative is zero, then it evaluates polynomial's value,
 | 
						|
    /// otherwise it computes value of the derivation of B2, up to degree 3
 | 
						|
    /// derivation.
 | 
						|
    /// \param t Parameter of polynomial function
 | 
						|
    /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation)
 | 
						|
    static constexpr PDFReal B2(PDFReal t, int derivative);
 | 
						|
 | 
						|
    /// Computes Bernstein polynomial B3 for parameter t.
 | 
						|
    /// If \p derivative is zero, then it evaluates polynomial's value,
 | 
						|
    /// otherwise it computes value of the derivation of B3, up to degree 3
 | 
						|
    /// derivation.
 | 
						|
    /// \param t Parameter of polynomial function
 | 
						|
    /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation)
 | 
						|
    static constexpr PDFReal B3(PDFReal t, int derivative);
 | 
						|
 | 
						|
    static constexpr PDFReal pow2(PDFReal x) { return x * x; }
 | 
						|
    static constexpr PDFReal pow3(PDFReal x) { return x * x * x; }
 | 
						|
 | 
						|
    void computeBoundingRectangle();
 | 
						|
 | 
						|
    PointMatrix m_P = { };
 | 
						|
    Colors m_colors = { };
 | 
						|
    QRectF m_boundingBox; ///< Bounding box of the tensor product patch
 | 
						|
};
 | 
						|
 | 
						|
using PDFTensorPatches = std::vector<PDFTensorPatch>;
 | 
						|
 | 
						|
class PDFTensorProductPatchShadingBase : public PDFType4567Shading
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit inline PDFTensorProductPatchShadingBase() = default;
 | 
						|
 | 
						|
    virtual PDFShadingSampler* createSampler(QMatrix userSpaceToDeviceSpaceMatrix) const override;
 | 
						|
    virtual PDFTensorPatches createPatches(QMatrix userSpaceToDeviceSpaceMatrix, bool transformColor) const = 0;
 | 
						|
 | 
						|
protected:
 | 
						|
    struct Triangle;
 | 
						|
 | 
						|
    void fillMesh(PDFMesh& mesh, const PDFMeshQualitySettings& settings, const PDFTensorPatch& patch, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool fastAlgorithm, const PDFOperationControl* operationControl) const;
 | 
						|
    void fillMesh(PDFMesh& mesh, const QMatrix& patternSpaceToDeviceSpaceMatrix, const PDFMeshQualitySettings& settings, const PDFTensorPatches& patches, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, const PDFOperationControl* operationControl) const;
 | 
						|
    static void addTriangle(std::vector<Triangle>& triangles, const PDFTensorPatch& patch, std::array<QPointF, 3> uvCoordinates);
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
};
 | 
						|
 | 
						|
class PDFCoonsPatchShading : public PDFTensorProductPatchShadingBase
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFCoonsPatchShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFTensorPatches createPatches(QMatrix userSpaceToDeviceSpaceMatrix, bool transformColor) const override;
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
};
 | 
						|
 | 
						|
class PDFTensorProductPatchShading : public PDFTensorProductPatchShadingBase
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFTensorProductPatchShading() = default;
 | 
						|
 | 
						|
    virtual ShadingType getShadingType() const override;
 | 
						|
    virtual PDFMesh createMesh(const PDFMeshQualitySettings& settings,
 | 
						|
                               const PDFCMS* cms,
 | 
						|
                               RenderingIntent intent,
 | 
						|
                               PDFRenderErrorReporter* reporter,
 | 
						|
                               const PDFOperationControl* operationControl) const override;
 | 
						|
    virtual PDFTensorPatches createPatches(QMatrix userSpaceToDeviceSpaceMatrix, bool transformColor) const override;
 | 
						|
 | 
						|
private:
 | 
						|
    friend class PDFPattern;
 | 
						|
};
 | 
						|
 | 
						|
}   // namespace pdf
 | 
						|
 | 
						|
#endif // PDFPATTERN_H
 |