File indexing completed on 2024-05-19 04:25:04
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+ rectangles inside. Their 0029 * processing will be really slow. These functions work around 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 /** 0090 * @brief luminosityCoarse 0091 * This calculates the luminosity of the given QColor. 0092 * It uses a very coarse (10 step) lut to linearize the sRGB trc, and then 0093 * uses rec709 values to calculate the luminosity. Because of the effect of 0094 * linearization, this is still more precise than one that just calculates 0095 * based on coefficients. 0096 * @param c the color to calculate the luminosity of. 0097 * @param sRGBtrc whether to linearize the sRGB trc. 0098 * @return a delinearized luminosity value, quantized to steps of 0.1. 0099 */ 0100 qreal KRITAGLOBAL_EXPORT luminosityCoarse(const QColor &c, bool sRGBtrc = true); 0101 0102 /** 0103 * \return an approximate difference between \p c1 and \p c2 0104 * in a (nonlinear) range [0, 3] 0105 * 0106 * The colors are compared using the formula: 0107 * difference = sqrt(2 * diff_R^2 + 4 * diff_G^2 + 3 * diff_B^2) 0108 */ 0109 qreal KRITAGLOBAL_EXPORT colorDifference(const QColor &c1, const QColor &c2); 0110 0111 /** 0112 * Make the color \p color differ from \p baseColor for at least \p threshold value 0113 */ 0114 void KRITAGLOBAL_EXPORT dragColor(QColor *color, const QColor &baseColor, qreal threshold); 0115 0116 inline void rectToVertices(QVector3D* vertices, const QRectF &rc) 0117 { 0118 vertices[0] = QVector3D(rc.left(), rc.bottom(), 0.f); 0119 vertices[1] = QVector3D(rc.left(), rc.top(), 0.f); 0120 vertices[2] = QVector3D(rc.right(), rc.bottom(), 0.f); 0121 vertices[3] = QVector3D(rc.left(), rc.top(), 0.f); 0122 vertices[4] = QVector3D(rc.right(), rc.top(), 0.f); 0123 vertices[5] = QVector3D(rc.right(), rc.bottom(), 0.f); 0124 } 0125 0126 inline void rectToTexCoords(QVector2D* texCoords, const QRectF &rc) 0127 { 0128 texCoords[0] = QVector2D(rc.left(), rc.bottom()); 0129 texCoords[1] = QVector2D(rc.left(), rc.top()); 0130 texCoords[2] = QVector2D(rc.right(), rc.bottom()); 0131 texCoords[3] = QVector2D(rc.left(), rc.top()); 0132 texCoords[4] = QVector2D(rc.right(), rc.top()); 0133 texCoords[5] = QVector2D(rc.right(), rc.bottom()); 0134 } 0135 } 0136 0137 #endif /* __KIS_PAINTING_TWEAKS_H */