Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_color_selector_wheel.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Adam Celarek <kdedev at xibo dot at>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QImage>
10#include <QPainter>
11#include <QColor>
12#include <cmath>
13#include <kconfig.h>
14#include <kconfiggroup.h>
15#include <ksharedconfig.h>
16
19
20
23 m_lastClickPos(-1,-1),
24 m_renderAreaSize(1,1),
25 m_renderAreaOffsetX(0.0),
26 m_renderAreaOffsetY(0.0),
27 m_toRenderArea(QTransform())
28{
29}
30
32{
33 int xWheel = x-width()/2;
34 int yWheel = y-height()/2;
35
36 qreal radius = sqrt((double)xWheel*xWheel+yWheel*yWheel);
37 radius/=qMin(width(), height());
38 if(radius>0.5)
39 radius=0.5;
40
41 radius*=2.;
42
43 qreal angle = std::atan2((qreal)yWheel, (qreal)xWheel);
44 angle+=M_PI;
45 angle/=2*M_PI;
46
47 switch (m_parameter) {
49 Q_EMIT paramChanged(angle, radius, -1, -1, -1, -1, -1, -1, -1);
50 break;
52 Q_EMIT paramChanged(angle, -1, -1, radius, -1, -1, -1, -1, -1);
53 break;
55 Q_EMIT paramChanged(angle, -1, -1, -1, -1, radius, -1, -1, -1);
56 break;
58 Q_EMIT paramChanged(angle, -1, -1, -1, -1, -1, -1, radius, -1);
59 break;
61 Q_EMIT paramChanged(angle, -1, radius, -1, -1, -1, -1, -1, -1);
62 break;
64 Q_EMIT paramChanged(angle, -1, -1, -1, radius, -1, -1, -1, -1);
65 break;
67 Q_EMIT paramChanged(angle, -1, -1, -1, -1, -1, radius, -1, -1);
68 break;
70 Q_EMIT paramChanged(angle, -1, -1, -1, -1, -1, -1, -1, radius);
71 break;
72 default:
73 Q_ASSERT(false);
74 break;
75 }
76
77 Q_EMIT update();
78
79 angle *= 2. * M_PI;
80 angle -= M_PI;
81 radius*=0.5;
82 m_lastClickPos.setX(cos(angle)*radius+0.5);
83 m_lastClickPos.setY(sin(angle)*radius+0.5);
84
85 return colorAt(x, y, true);
86}
87
89{
90 qreal hsvH, hsvS, hsvV;
91 qreal hslH, hslS, hslL;
92 qreal hsiH, hsiS, hsiI;
93 qreal hsyH, hsyS, hsyY;
94 KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector");
95 R = cfg.readEntry("lumaR", 0.2126);
96 G = cfg.readEntry("lumaG", 0.7152);
97 B = cfg.readEntry("lumaB", 0.0722);
98 Gamma = cfg.readEntry("gamma", 2.2);
99 m_parent->converter()->getHsvF(color, &hsvH, &hsvS, &hsvV);
100 m_parent->converter()->getHslF(color, &hslH, &hslS, &hslL);
101 m_parent->converter()->getHsiF(color, &hsiH, &hsiS, &hsiI);
102 m_parent->converter()->getHsyF(color, &hsyH, &hsyS, &hsyY, R, G, B, Gamma);
103
104 qreal angle = 0.0, radius = 0.0;
105 switch (m_parameter) {
107 Q_EMIT paramChanged(hslH, -1, -1, -1, hslL, -1, -1, -1, -1);
108 angle = hslH;
109 radius = hslL;
110 break;
112 Q_EMIT paramChanged(hsvH, -1, hsvV, -1, -1, -1, -1, -1, -1);
113 angle = hsvH;
114 radius = hsvV;
115 break;
117 Q_EMIT paramChanged(hslH, -1, -1, -1, -1, -1, hsiI, -1, -1);
118 angle = hsiH;
119 radius = hsiI;
120 break;
122 Q_EMIT paramChanged(hsyH, -1, -1, -1, -1, -1, -1, -1, hsyY);
123 angle = hsyH;
124 radius = hsyY;
125 break;
127 Q_EMIT paramChanged(hsvH, hsvS, -1, -1, -1, -1, -1, -1, -1);
128 angle = hsvH;
129 radius = hsvS;
130 break;
132 Q_EMIT paramChanged(hslH, -1, -1, hslS, -1, -1, -1, -1, -1);
133 angle = hslH;
134 radius = hslS;
135 break;
137 Q_EMIT paramChanged(hsiH, -1, -1, -1, -1, hsiS, -1, -1, -1);
138 angle = hsiH;
139 radius = hsiS;
140 break;
142 Q_EMIT paramChanged(hsyH, -1, -1, -1, -1, -1, -1, hsyS, -1);
143 angle = hsyH;
144 radius = hsyS;
145 break;
146 default:
147 Q_ASSERT(false);
148 break;
149 }
150 angle *= 2. * M_PI;
151 angle -= M_PI;
152 radius *= 0.5;
153
154 m_lastClickPos.setX(cos(angle)*radius+0.5);
155 m_lastClickPos.setY(sin(angle)*radius+0.5);
156
157 //workaround for bug 279500
158
159 if(m_lastClickPos!=QPoint(-1,-1) && m_parent->displayBlip()) {
160 QPoint pos = (m_lastClickPos*qMin(width(), height())).toPoint();
161 if(width() < height()) {
162 pos.setY(pos.y()+height()/2-width()/2);
163 } else {
164 pos.setX(pos.x()+width()/2-height()/2);
165 }
166
167 setLastMousePosition(pos.x(), pos.y());
168 }
169
171}
172
173void KisColorSelectorWheel::paint(QPainter* painter)
174{
175
176 if(isDirty()) {
177 KisPaintDeviceSP realPixelCache;
178 Acs::PixelCacheRenderer::render(this, m_parent->converter(), QRect(0, 0, width(), height()), realPixelCache,
179 m_pixelCache, m_pixelCacheOffset, painter->device()->devicePixelRatioF());
180
181 //antialiasing for wheel
182 QPainter tmpPainter(&m_pixelCache);
183 tmpPainter.setRenderHint(QPainter::Antialiasing);
184 tmpPainter.setPen(QPen(QColor(0,0,0,0), 2.5));
185 tmpPainter.setCompositionMode(QPainter::CompositionMode_Clear);
186 int size=qMin(width(), height());
187
188 m_renderAreaSize = QSize(size,size);
189 m_renderAreaOffsetX = ((qreal)width()-(qreal)m_renderAreaSize.width())*0.5;
190 m_renderAreaOffsetY = ((qreal)height()-(qreal)m_renderAreaSize.height())*0.5;
191 m_toRenderArea.reset();
193
194 QPoint ellipseCenter(width() / 2 - size / 2, height() / 2 - size / 2);
195 ellipseCenter -= m_pixelCacheOffset;
196
197 tmpPainter.drawEllipse(ellipseCenter.x(), ellipseCenter.y(), size, size);
198 }
199
200 painter->drawImage(m_pixelCacheOffset.x(),m_pixelCacheOffset.y(), m_pixelCache);
201
202 // draw gamut mask
204 QImage maskBuffer = QImage(m_renderAreaSize*painter->device()->devicePixelRatioF(), QImage::Format_ARGB32_Premultiplied);
205 maskBuffer.setDevicePixelRatio(painter->device()->devicePixelRatioF());
206 maskBuffer.fill(0);
207 QPainter maskPainter(&maskBuffer);
208
209 QRect rect = QRect(0, 0, m_renderAreaSize.width(), m_renderAreaSize.height());
210 maskPainter.setRenderHint(QPainter::Antialiasing, true);
211
212 maskPainter.resetTransform();
213 maskPainter.translate(rect.width()*0.5, rect.height()*0.5);
214 maskPainter.scale(rect.width()*0.5, rect.height()*0.5);
215
216 maskPainter.setPen(QPen(QBrush(Qt::white), 0.002));
217 maskPainter.setBrush(QColor(128,128,128,255)); // middle gray
218
219 maskPainter.drawEllipse(QPointF(0,0), 1.0, 1.0);
220
221 maskPainter.resetTransform();
222 maskPainter.setTransform(m_currentGamutMask->maskToViewTransform(m_renderAreaSize.width()));
223
224 maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
225 m_currentGamutMask->paint(maskPainter, m_maskPreviewActive);
226
227 maskPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
228 m_currentGamutMask->paintStroke(maskPainter, m_maskPreviewActive);
229
230 painter->drawImage(m_renderAreaOffsetX, m_renderAreaOffsetY, maskBuffer);
231 }
232
233 // draw blips
234
235 if(m_lastClickPos!=QPoint(-1,-1) && m_parent->displayBlip()) {
236 QPoint pos = (m_lastClickPos*qMin(width(), height())).toPoint();
237 if(width()<height())
238 pos.setY(pos.y()+height()/2-width()/2);
239 else
240 pos.setX(pos.x()+width()/2-height()/2);
241
242 painter->setPen(QColor(0,0,0));
243 painter->drawEllipse(pos, 5, 5);
244 painter->setPen(QColor(255,255,255));
245 painter->drawEllipse(pos, 4, 4);
246 }
247}
248
249KoColor KisColorSelectorWheel::colorAt(float x, float y, bool forceValid)
250{
252
253 Q_ASSERT(x>=0 && x<=width());
254 Q_ASSERT(y>=0 && y<=height());
255
256 const qreal xRel = x - 0.5 * width();
257 const qreal yRel = y - 0.5 * height();
258 const qreal minDimension = qMin(width(), height());
259
260 qreal radius = sqrt(xRel*xRel+yRel*yRel);
261 if (radius > 0.5 * minDimension) {
262 if (!forceValid) {
263 return color;
264 } else {
265 radius = 0.5 * minDimension;
266 }
267 }
268 radius /= 0.5 * minDimension;
269
270 qreal angle = std::atan2(yRel, xRel);
271 angle += M_PI;
272 angle /= 2 * M_PI;
273
274 switch(m_parameter) {
276 color = m_parent->converter()->fromHsvF(angle, radius, m_value);
277 break;
279 color = m_parent->converter()->fromHslF(angle, radius, m_lightness);
280 break;
282 color = m_parent->converter()->fromHsiF(angle, radius, m_intensity);
283 break;
285 color = m_parent->converter()->fromHsyF(angle, radius, m_luma, R, G, B, Gamma);
286 break;
288 color = m_parent->converter()->fromHsvF(angle, m_hsvSaturation, radius);
289 break;
291 color = m_parent->converter()->fromHslF(angle, m_hslSaturation, radius);
292 break;
294 color = m_parent->converter()->fromHsiF(angle, m_hsiSaturation, radius);
295 break;
297 color = m_parent->converter()->fromHsyF(angle, m_hsySaturation, radius, R, G, B, Gamma);
298 break;
299 default:
300 Q_ASSERT(false);
301
302 return color;
303 }
304 return color;
305}
306
308{
310 return true;
311 }
312
313 QPointF colorCoord = m_toRenderArea.map(QPointF(pt));
314 QPointF translatedPoint = m_currentGamutMask->viewToMaskTransform(m_renderAreaSize.width()).map(colorCoord);
315 bool isClear = m_currentGamutMask->coordIsClear(translatedPoint, m_maskPreviewActive);
316
317 return isClear;
318}
static void render(Sampler *sampler, const KisDisplayColorConverter *converter, const QRect &sampleRect, KisPaintDeviceSP &realPixelCache, QImage &pixelCache, QPoint &pixelCacheOffset, qreal devicePixelRatioF)
KisDisplayColorConverter * converter() const
const KoColorSpace * colorSpace() const
void update()
request for repaint, for instance, if the hue changes.
bool isDirty() const
returns true, if ether the color space, the size or the parameters have changed since the last paint ...
virtual void setColor(const KoColor &color)
set the color, blibs etc
void paramChanged(qreal hue, qreal hsvSaturation, qreal value, qreal hslSaturation, qreal lightness, qreal hsiSaturation, qreal intensity, qreal hsySaturation, qreal luma)
-1, if unaffected
KoColor selectColor(int x, int y) override
this method must be overloaded to return the color at position x/y and draw a marker on that position
KisColorSelectorWheel(KisColorSelector *parent)
void paint(QPainter *) override
KoColor colorAt(float x, float y, bool forceValid=false)
bool allowsColorSelectionAtPoint(const QPoint &pt) const override
void setColor(const KoColor &color) override
set the color, blibs etc
bool displayBlip() const
void getHslF(const KoColor &srcColor, qreal *h, qreal *s, qreal *l, qreal *a=0)
KoColor fromHsiF(qreal h, qreal s, qreal i)
void getHsiF(const KoColor &srcColor, qreal *h, qreal *s, qreal *i)
void getHsyF(const KoColor &srcColor, qreal *h, qreal *s, qreal *y, qreal R=0.2126, qreal G=0.7152, qreal B=0.0722, qreal gamma=2.2)
KoColor fromHslF(qreal h, qreal s, qreal l, qreal a=1.0)
void getHsvF(const KoColor &srcColor, qreal *h, qreal *s, qreal *v, qreal *a=0)
KoColor fromHsyF(qreal h, qreal s, qreal y, qreal R=0.2126, qreal G=0.7152, qreal B=0.0722, qreal gamma=2.2)
KoColor fromHsvF(qreal h, qreal s, qreal v, qreal a=1.0)
static KoColor createTransparent(const KoColorSpace *cs)
Definition KoColor.cpp:681
#define M_PI
Definition kis_global.h:111