Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_painting_tweaks.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include <kis_global.h>
9
10#include <QPen>
11#include <QRegion>
12#include <QPainter>
13#include <QTransform>
14
15#include "kis_debug.h"
16
17
19
20QRegion safeClipRegion(const QPainter &painter)
21{
22 const QTransform t = painter.transform();
23
24 QRegion region = t.type() <= QTransform::TxScale ?
25 painter.clipRegion() :
26 QRegion(painter.clipBoundingRect().toAlignedRect());
27
28 if (region.rectCount() > 1000) {
29 qWarning() << "WARNING: KisPaintingTweaks::safeClipRegion: too many rectangles in the region!" << ppVar(region.rectCount());
30 region = QRegion(painter.clipBoundingRect().toAlignedRect());
31 }
32
33 return region;
34}
35
36QRect safeClipBoundingRect(const QPainter &painter)
37{
38 return painter.clipBoundingRect().toAlignedRect();
39}
40
41void initAntsPen(QPen *antsPen, QPen *outlinePen,
42 int antLength, int antSpace)
43{
44 QVector<qreal> antDashPattern;
45 antDashPattern << antLength << antSpace;
46
47 *antsPen = QPen(Qt::CustomDashLine);
48 antsPen->setDashPattern(antDashPattern);
49 antsPen->setCosmetic(true);
50 antsPen->setColor(Qt::black);
51
52 *outlinePen = QPen(Qt::SolidLine);
53 outlinePen->setCosmetic(true);
54 outlinePen->setColor(Qt::white);
55}
56
58 : m_painter(painter),
59 m_pen(painter->pen()),
60 m_brush(painter->brush())
61{
62}
63
64PenBrushSaver::PenBrushSaver(QPainter *painter, const QPen &pen, const QBrush &brush)
65 : PenBrushSaver(painter)
66{
67 m_painter->setPen(pen);
68 m_painter->setBrush(brush);
69}
70
71PenBrushSaver::PenBrushSaver(QPainter *painter, const QPair<QPen, QBrush> &pair)
72 : PenBrushSaver(painter)
73{
74 m_painter->setPen(pair.first);
75 m_painter->setBrush(pair.second);
76}
77
78PenBrushSaver::PenBrushSaver(QPainter *painter, const QPair<QPen, QBrush> &pair, allow_noop_t)
79 : m_painter(painter)
80{
81 if (m_painter) {
82 m_pen = m_painter->pen();
83 m_brush = m_painter->brush();
84 m_painter->setPen(pair.first);
85 m_painter->setBrush(pair.second);
86 }
87}
88
90{
91 if (m_painter) {
92 m_painter->setPen(m_pen);
93 m_painter->setBrush(m_brush);
94 }
95}
96
97QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)
98{
99 const qreal r2 = 1.0 - r1;
100
101 return QColor::fromRgbF(
102 c1.redF() * r1 + c2.redF() * r2,
103 c1.greenF() * r1 + c2.greenF() * r2,
104 c1.blueF() * r1 + c2.blueF() * r2);
105}
106
107qreal colorDifference(const QColor &c1, const QColor &c2)
108{
109 const qreal dr = c1.redF() - c2.redF();
110 const qreal dg = c1.greenF() - c2.greenF();
111 const qreal db = c1.blueF() - c2.blueF();
112
113 return std::sqrt(2 * pow2(dr) + 4 * pow2(dg) + 3 * pow2(db));
114}
115
116void dragColor(QColor *color, const QColor &baseColor, qreal threshold)
117{
118 while (colorDifference(*color, baseColor) < threshold) {
119
120 QColor newColor = *color;
121
122 if (newColor.lightnessF() > baseColor.lightnessF()) {
123 newColor = newColor.lighter(120);
124 } else {
125 newColor = newColor.darker(120);
126 }
127
128 if (newColor == *color) {
129 break;
130 }
131
132 *color = newColor;
133 }
134}
135
136// This does a simplified linearization and calculates the luma.
137// Krita has the ability to precisely calculate this value,
138// but that seems overkill when all we want to know is whether
139// it passes a certain gray threshold.
140static QMap<qreal, qreal> sRgbTRCToLinear {
141 {0.0, 0.0},
142 {0.1, 0.01002},
143 {0.2, 0.0331},
144 {0.3, 0.07324},
145 {0.4, 0.13287},
146 {0.5, 0.21404},
147 {0.6, 0.31855},
148 {0.7, 0.44799},
149 {0.8, 0.60383},
150 {0.9, 0.78741},
151 {1.0, 1.0}
152};
153
154static QMap<qreal, qreal> linearToSRGBTRC {
155 {0.0, 0.0},
156 {0.01002, 0.1},
157 {0.0331, 0.2},
158 {0.07324, 0.3},
159 {0.13287, 0.4},
160 {0.21404, 0.5},
161 {0.31855, 0.6},
162 {0.44799, 0.7},
163 {0.60383, 0.8},
164 {0.78741, 0.9},
165 {1.0, 1.0}
166};
167
168qreal luminosityCoarse(const QColor &c, bool sRGBtrc)
169{
170 qreal r = c.redF();
171 qreal g = c.greenF();
172 qreal b = c.blueF();
173 if (sRGBtrc) {
174 if (r < 1.0) {
175 r = sRgbTRCToLinear.upperBound(r).value();
176 }
177 if (g < 1.0) {
178 g = sRgbTRCToLinear.upperBound(g).value();
179 }
180 if (b < 1.0) {
181 b = sRgbTRCToLinear.upperBound(b).value();
182 }
183 }
184 qreal lumi = (r * .2126) + (g * .7152) + (b * .0722);
185 if (sRGBtrc && lumi < 1.0) {
186 lumi = linearToSRGBTRC.lowerBound(lumi).value();
187 }
188 return lumi;
189}
190
191}
QPointF r2
QPointF r1
#define ppVar(var)
Definition kis_debug.h:155
T pow2(const T &x)
Definition kis_global.h:166
static QMap< qreal, qreal > linearToSRGBTRC
qreal luminosityCoarse(const QColor &c, bool sRGBtrc)
luminosityCoarse This calculates the luminosity of the given QColor. It uses a very coarse (10 step) ...
void initAntsPen(QPen *antsPen, QPen *outlinePen, int antLength, int antSpace)
QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)
qreal colorDifference(const QColor &c1, const QColor &c2)
QRegion safeClipRegion(const QPainter &painter)
void dragColor(QColor *color, const QColor &baseColor, qreal threshold)
QRect safeClipBoundingRect(const QPainter &painter)
static QMap< qreal, qreal > sRgbTRCToLinear