File indexing completed on 2024-05-12 15:56:58

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_PAINTING_TWEAKS_H
0008 #define __KIS_PAINTING_TWEAKS_H
0009 
0010 #include "kritaglobal_export.h"
0011 
0012 #include <QPen>
0013 #include <QBrush>
0014 
0015 #include <QVector3D>
0016 #include <QVector2D>
0017 
0018 class QPainter;
0019 class QRegion;
0020 class QRect;
0021 class QPen;
0022 
0023 namespace KisPaintingTweaks {
0024 
0025     /**
0026      * This is a workaround for QPainter::clipRegion() bug. When zoom
0027      * is about 2000% and rotation is in a range[-5;5] degrees, the
0028      * generated region will have about 20k+ regtangles inside. Their
0029      * processing will be really slow. These functions fworkarounds
0030      * the issue.
0031      */
0032     KRITAGLOBAL_EXPORT QRegion safeClipRegion(const QPainter &painter);
0033 
0034     /**
0035      * \see safeClipRegion()
0036      */
0037     KRITAGLOBAL_EXPORT QRect safeClipBoundingRect(const QPainter &painter);
0038 
0039     KRITAGLOBAL_EXPORT void initAntsPen(QPen *antsPen, QPen *outlinePen,
0040                                         int antLength = 4, int antSpace = 4);
0041 
0042 
0043     /**
0044      * A special class to save painter->pen() and painter->brush() using RAII
0045      * principle.
0046      */
0047     class KRITAGLOBAL_EXPORT PenBrushSaver
0048     {
0049     public:
0050         struct allow_noop_t { explicit allow_noop_t() = default; };
0051         static constexpr allow_noop_t   allow_noop { };
0052 
0053         /**
0054          * Saves pen and brush state of the provided painter object. \p painter cannot be null.
0055          */
0056         PenBrushSaver(QPainter *painter);
0057 
0058         /**
0059          * Overrides pen and brush of \p painter with the provided values. \p painter cannot be null.
0060          */
0061         PenBrushSaver(QPainter *painter, const QPen &pen, const QBrush &brush);
0062 
0063         /**
0064          * Overrides pen and brush of \p painter with the provided values. \p painter cannot be null.
0065          */
0066         PenBrushSaver(QPainter *painter, const QPair<QPen, QBrush> &pair);
0067 
0068         /**
0069          * A special constructor of PenBrushSaver that allows \p painter to be null. Passing null
0070          * pointer will basically mean that the whole saver existence will be a noop.
0071          */
0072         PenBrushSaver(QPainter *painter, const QPair<QPen, QBrush> &pair, allow_noop_t);
0073 
0074         /**
0075          * Restores the state of the painter that has been saved during the construction of the saver
0076          */
0077         ~PenBrushSaver();
0078 
0079     private:
0080         PenBrushSaver(const PenBrushSaver &rhs) = delete;
0081         QPainter *m_painter;
0082         QPen m_pen;
0083         QBrush m_brush;
0084     };
0085 
0086     QColor KRITAGLOBAL_EXPORT blendColors(const QColor &c1, const QColor &c2, qreal r1);
0087 
0088     /**
0089      * \return an approximate difference between \p c1 and \p c2
0090      *         in a (nonlinear) range [0, 3]
0091      *
0092      * The colors are compared using the formula:
0093      *     difference = sqrt(2 * diff_R^2 + 4 * diff_G^2 + 3 * diff_B^2)
0094      */
0095     qreal KRITAGLOBAL_EXPORT colorDifference(const QColor &c1, const QColor &c2);
0096 
0097     /**
0098      * Make the color \p color differ from \p baseColor for at least \p threshold value
0099      */
0100     void KRITAGLOBAL_EXPORT dragColor(QColor *color, const QColor &baseColor, qreal threshold);
0101 
0102     inline void rectToVertices(QVector3D* vertices, const QRectF &rc)
0103     {
0104         vertices[0] = QVector3D(rc.left(),  rc.bottom(), 0.f);
0105         vertices[1] = QVector3D(rc.left(),  rc.top(),    0.f);
0106         vertices[2] = QVector3D(rc.right(), rc.bottom(), 0.f);
0107         vertices[3] = QVector3D(rc.left(),  rc.top(), 0.f);
0108         vertices[4] = QVector3D(rc.right(), rc.top(), 0.f);
0109         vertices[5] = QVector3D(rc.right(), rc.bottom(),    0.f);
0110     }
0111 
0112     inline void rectToTexCoords(QVector2D* texCoords, const QRectF &rc)
0113     {
0114         texCoords[0] = QVector2D(rc.left(), rc.bottom());
0115         texCoords[1] = QVector2D(rc.left(), rc.top());
0116         texCoords[2] = QVector2D(rc.right(), rc.bottom());
0117         texCoords[3] = QVector2D(rc.left(), rc.top());
0118         texCoords[4] = QVector2D(rc.right(), rc.top());
0119         texCoords[5] = QVector2D(rc.right(), rc.bottom());
0120     }
0121 }
0122 
0123 #endif /* __KIS_PAINTING_TWEAKS_H */