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 QColor black, QColor white)
44{
45 QVector<qreal> antDashPattern;
46 antDashPattern << antLength << antSpace;
47
48 *antsPen = QPen(Qt::CustomDashLine);
49 antsPen->setDashPattern(antDashPattern);
50 antsPen->setCosmetic(true);
51 antsPen->setColor(black);
52
53 *outlinePen = QPen(Qt::SolidLine);
54 outlinePen->setCosmetic(true);
55 outlinePen->setColor(white);
56}
57
59 : m_painter(painter),
60 m_pen(painter->pen()),
61 m_brush(painter->brush())
62{
63}
64
65PenBrushSaver::PenBrushSaver(QPainter *painter, const QPen &pen, const QBrush &brush)
66 : PenBrushSaver(painter)
67{
68 m_painter->setPen(pen);
69 m_painter->setBrush(brush);
70}
71
72PenBrushSaver::PenBrushSaver(QPainter *painter, const QPair<QPen, QBrush> &pair)
73 : PenBrushSaver(painter)
74{
75 m_painter->setPen(pair.first);
76 m_painter->setBrush(pair.second);
77}
78
79PenBrushSaver::PenBrushSaver(QPainter *painter, const QPair<QPen, QBrush> &pair, allow_noop_t)
80 : m_painter(painter)
81{
82 if (m_painter) {
83 m_pen = m_painter->pen();
84 m_brush = m_painter->brush();
85 m_painter->setPen(pair.first);
86 m_painter->setBrush(pair.second);
87 }
88}
89
91{
92 if (m_painter) {
93 m_painter->setPen(m_pen);
94 m_painter->setBrush(m_brush);
95 }
96}
97
98QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)
99{
100 const qreal r2 = 1.0 - r1;
101
102 return QColor::fromRgbF(
103 c1.redF() * r1 + c2.redF() * r2,
104 c1.greenF() * r1 + c2.greenF() * r2,
105 c1.blueF() * r1 + c2.blueF() * r2);
106}
107
108qreal colorDifference(const QColor &c1, const QColor &c2)
109{
110 const qreal dr = c1.redF() - c2.redF();
111 const qreal dg = c1.greenF() - c2.greenF();
112 const qreal db = c1.blueF() - c2.blueF();
113
114 return std::sqrt(2 * pow2(dr) + 4 * pow2(dg) + 3 * pow2(db));
115}
116
117void dragColor(QColor *color, const QColor &baseColor, qreal threshold)
118{
119 while (colorDifference(*color, baseColor) < threshold) {
120
121 QColor newColor = *color;
122
123 if (newColor.lightnessF() > baseColor.lightnessF()) {
124 newColor = newColor.lighter(120);
125 } else {
126 newColor = newColor.darker(120);
127 }
128
129 if (newColor == *color) {
130 break;
131 }
132
133 *color = newColor;
134 }
135}
136
137// This does a simplified linearization and calculates the luma.
138// Krita has the ability to precisely calculate this value,
139// but that seems overkill when all we want to know is whether
140// it passes a certain gray threshold.
141static QMap<qreal, qreal> sRgbTRCToLinear {
142 {0.0, 0.0},
143 {0.1, 0.01002},
144 {0.2, 0.0331},
145 {0.3, 0.07324},
146 {0.4, 0.13287},
147 {0.5, 0.21404},
148 {0.6, 0.31855},
149 {0.7, 0.44799},
150 {0.8, 0.60383},
151 {0.9, 0.78741},
152 {1.0, 1.0}
153};
154
155static QMap<qreal, qreal> linearToSRGBTRC {
156 {0.0, 0.0},
157 {0.01002, 0.1},
158 {0.0331, 0.2},
159 {0.07324, 0.3},
160 {0.13287, 0.4},
161 {0.21404, 0.5},
162 {0.31855, 0.6},
163 {0.44799, 0.7},
164 {0.60383, 0.8},
165 {0.78741, 0.9},
166 {1.0, 1.0}
167};
168
169qreal luminosityCoarse(const QColor &c, bool sRGBtrc)
170{
171 qreal r = c.redF();
172 qreal g = c.greenF();
173 qreal b = c.blueF();
174 if (sRGBtrc) {
175 if (r < 1.0) {
176 r = sRgbTRCToLinear.upperBound(r).value();
177 }
178 if (g < 1.0) {
179 g = sRgbTRCToLinear.upperBound(g).value();
180 }
181 if (b < 1.0) {
182 b = sRgbTRCToLinear.upperBound(b).value();
183 }
184 }
185 qreal lumi = (r * .2126) + (g * .7152) + (b * .0722);
186 if (sRGBtrc && lumi < 1.0) {
187 lumi = linearToSRGBTRC.lowerBound(lumi).value();
188 }
189 return lumi;
190}
191
192}
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) ...
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
void initAntsPen(QPen *antsPen, QPen *outlinePen, int antLength, int antSpace, QColor black, QColor white)