• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • krita API Reference
  • KDE Home
  • Contact Us
 

KritaWidgets

  • sources
  • kfour-appscomplete
  • krita
  • libs
  • widgets
KisGradientSlider.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of Krita
3  *
4  * SPDX-FileCopyrightText: 2006 Frederic Coiffier <[email protected]>
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 // Local includes.
10 #include "KisGradientSlider.h"
11 
12 // C++ includes.
13 
14 #include <cmath>
15 #include <cstdlib>
16 
17 // Qt includes.
18 #include <kis_debug.h>
19 #include <QtGlobal>
20 #include <QPainter>
21 #include <QPoint>
22 #include <QPen>
23 #include <QMouseEvent>
24 #include <QBrush>
25 #include <QLinearGradient>
26 
27 #define MARGIN 5
28 #define HANDLE_SIZE 10
29 
30 KisGradientSlider::KisGradientSlider(QWidget *parent)
31  : QWidget(parent)
32  , m_leftmost(0)
33  , m_rightmost(0)
34  , m_scalingFactor(0)
35  , m_blackCursor(0)
36  , m_whiteCursor(0)
37  , m_gammaCursor(0)
38  , m_black(0)
39  , m_white(255)
40  , m_gamma(1.0)
41  , m_gammaEnabled(false)
42  , m_whiteEnabled(true)
43  , m_feedback(false)
44  , m_inverted(false)
45 {
46  m_grabCursor = None;
47 
48  setMouseTracking(true);
49  setFocusPolicy(Qt::StrongFocus);
50 }
51 
52 KisGradientSlider::~KisGradientSlider()
53 {
54 }
55 
56 int KisGradientSlider::black() const
57 {
58  return m_black;
59 }
60 
61 int KisGradientSlider::white() const
62 {
63  return m_white;
64 }
65 
66 void KisGradientSlider::paintEvent(QPaintEvent *e)
67 {
68  QWidget::paintEvent(e);
69 
70  int x = 0;
71  int y = 0;
72  int wWidth = width() - (2 * MARGIN);
73  int wHeight = height();
74 
75  const int gradientHeight = qRound((double)wHeight / 7.0 * 2);
76 
77  QPainter p1(this);
78  p1.fillRect(rect(), palette().window());
79  p1.setPen(Qt::black);
80  p1.drawRect(MARGIN, MARGIN, wWidth, height() - 2 * MARGIN - HANDLE_SIZE);
81 
82  // Draw first gradient
83  QLinearGradient grayGradient(MARGIN, y, wWidth, gradientHeight);
84  grayGradient.setColorAt(0, m_inverted ? Qt::white : Qt::black);
85  grayGradient.setColorAt(1, m_inverted ? Qt::black : Qt::white);
86  p1.fillRect(MARGIN, 0, wWidth, gradientHeight, QBrush(grayGradient));
87 
88  // Draw second gradient
89  y = gradientHeight;
90  p1.fillRect(MARGIN, y, wWidth, gradientHeight, Qt::white);
91 
92  if (m_blackCursor > 0 && !m_inverted) {
93  p1.fillRect(MARGIN, y, m_blackCursor, gradientHeight, Qt::black);
94  } else if (m_blackCursor < wWidth && m_inverted) {
95  p1.fillRect(MARGIN + m_blackCursor, y, wWidth - m_blackCursor, gradientHeight, Qt::black);
96  }
97 
98 
99  int left = qMin(m_blackCursor, m_whiteCursor);
100  int right = qMax(m_blackCursor, m_whiteCursor);
101  for (x = left; x <= right; ++x) {
102  double inten = (double)(x - m_blackCursor) /
103  (double)(m_whiteCursor - m_blackCursor);
104  inten = pow(inten, (1.0 / m_gamma));
105  int gray = (int)(255 * inten);
106  p1.setPen(QColor(gray, gray, gray));
107  p1.drawLine(x + MARGIN, y, x + MARGIN, y + gradientHeight - 1);
108  }
109 
110  // Draw cursors
111  y += gradientHeight;
112  QPoint a[3];
113  p1.setPen(Qt::darkGray);
114  p1.setRenderHint(QPainter::Antialiasing, true);
115 
116  const int cursorHalfBase = (int)(gradientHeight / 1.5);
117 
118  a[0] = QPoint(m_blackCursor + MARGIN, y);
119  a[1] = QPoint(m_blackCursor + MARGIN + cursorHalfBase, wHeight - 1);
120  a[2] = QPoint(m_blackCursor + MARGIN - cursorHalfBase, wHeight - 1);
121  p1.setBrush(Qt::black);
122  p1.drawPolygon(a, 3);
123 
124  p1.setPen(Qt::black);
125  if (m_gammaEnabled) {
126  a[0] = QPoint(m_gammaCursor + MARGIN, y);
127  a[1] = QPoint(m_gammaCursor + MARGIN + cursorHalfBase, wHeight - 1);
128  a[2] = QPoint(m_gammaCursor + MARGIN - cursorHalfBase, wHeight - 1);
129  p1.setBrush(Qt::gray);
130  p1.drawPolygon(a, 3);
131  }
132 
133  if (m_whiteEnabled) {
134  a[0] = QPoint(m_whiteCursor + MARGIN, y);
135  a[1] = QPoint(m_whiteCursor + MARGIN + cursorHalfBase, wHeight - 1);
136  a[2] = QPoint(m_whiteCursor + MARGIN - cursorHalfBase, wHeight - 1);
137  p1.setBrush(Qt::white);
138  p1.drawPolygon(a, 3);
139  }
140 }
141 
142 void KisGradientSlider::resizeEvent(QResizeEvent *)
143 {
144  m_scalingFactor = (double)(width() - 2 * MARGIN) / 255;
145  calculateCursorPositions();
146  update();
147 }
148 
149 void KisGradientSlider::mousePressEvent(QMouseEvent *e)
150 {
151  eCursor closest_cursor = KisGradientSlider::None;
152  int distance;
153 
154  if (e->button() != Qt::LeftButton)
155  return;
156 
157  unsigned int x = e->pos().x();
158  int xMinusMargin = x - MARGIN;
159 
160  distance = width() + 1; // just a big number
161 
162  if (abs((int)(xMinusMargin - m_blackCursor)) < distance) {
163  distance = abs((int)(xMinusMargin - m_blackCursor));
164  closest_cursor = BlackCursor;
165  }
166 
167  if (abs((int)(xMinusMargin - m_whiteCursor)) < distance) {
168  distance = abs((int)(xMinusMargin - m_whiteCursor));
169  closest_cursor = WhiteCursor;
170  }
171 
172  if (m_gammaEnabled) {
173  int gammaDistance = (int)xMinusMargin - m_gammaCursor;
174 
175  if (abs(gammaDistance) < distance) {
176  distance = abs((int)xMinusMargin - m_gammaCursor);
177  closest_cursor = GammaCursor;
178  } else if (abs(gammaDistance) == distance) {
179  if ((closest_cursor == BlackCursor) && (gammaDistance > 0)) {
180  distance = abs(gammaDistance);
181  closest_cursor = GammaCursor;
182  } else if ((closest_cursor == WhiteCursor) && (gammaDistance < 0)) {
183  distance = abs(gammaDistance);
184  closest_cursor = GammaCursor;
185  }
186  }
187  }
188 
189  if (distance > 20) {
190  m_grabCursor = None;
191  return;
192  }
193 
194  // Determine cursor values and the leftmost and rightmost points.
195 
196  switch (closest_cursor) {
197  case BlackCursor:
198  m_blackCursor = xMinusMargin;
199  m_grabCursor = closest_cursor;
200  if (m_inverted) {
201  m_leftmost = m_whiteCursor + 1;
202  m_rightmost = width() - 2 * MARGIN - 1;
203  } else {
204  m_leftmost = 0;
205  m_rightmost = m_whiteCursor - 1;
206  }
207  if (m_gammaEnabled)
208  m_gammaCursor = calculateGammaCursor();
209  break;
210  case WhiteCursor:
211  m_whiteCursor = xMinusMargin;
212  m_grabCursor = closest_cursor;
213  if (m_inverted) {
214  m_leftmost = 0;
215  m_rightmost = m_blackCursor - 1;
216  } else {
217  m_leftmost = m_blackCursor + 1;
218  m_rightmost = width() - 2 * MARGIN - 1;
219  }
220  if (m_gammaEnabled)
221  m_gammaCursor = calculateGammaCursor();
222  break;
223  case GammaCursor:
224  m_gammaCursor = x;
225  m_grabCursor = closest_cursor;
226  m_leftmost = qMin(m_blackCursor, m_whiteCursor);
227  m_rightmost = qMax(m_blackCursor, m_whiteCursor);
228  {
229  double delta = (double)(m_whiteCursor - m_blackCursor) / 2.0;
230  double mid = (double)m_blackCursor + delta + MARGIN;
231  double tmp = (xMinusMargin - mid) / delta;
232  m_gamma = 1.0 / pow(10, tmp);
233  }
234  break;
235  default:
236  break;
237  }
238  update();
239 }
240 
241 void KisGradientSlider::mouseReleaseEvent(QMouseEvent * e)
242 {
243  if (e->button() != Qt::LeftButton)
244  return;
245 
246  update();
247 
248  switch (m_grabCursor) {
249  case BlackCursor:
250  m_black = qRound(m_blackCursor / m_scalingFactor);
251  m_feedback = true;
252  emit sigModifiedBlack(m_black);
253  break;
254  case WhiteCursor:
255  m_white = qRound(m_whiteCursor / m_scalingFactor);
256  m_feedback = true;
257  emit sigModifiedWhite(m_white);
258  break;
259  case GammaCursor:
260  emit sigModifiedGamma(m_gamma);
261  break;
262  default:
263  break;
264  }
265 
266  m_grabCursor = None;
267  m_feedback = false;
268 }
269 
270 void KisGradientSlider::mouseMoveEvent(QMouseEvent * e)
271 {
272  int x = e->pos().x();
273  int xMinusMargin = x - MARGIN;
274  if (m_grabCursor != None) { // Else, drag the selected point
275  if (xMinusMargin <= m_leftmost)
276  xMinusMargin = m_leftmost;
277 
278  if (xMinusMargin >= m_rightmost)
279  xMinusMargin = m_rightmost;
280 
281  switch (m_grabCursor) {
282  case BlackCursor:
283  if (m_blackCursor != xMinusMargin) {
284  m_blackCursor = xMinusMargin;
285  if (m_gammaEnabled) {
286  m_gammaCursor = calculateGammaCursor();
287  }
288  }
289  break;
290  case WhiteCursor:
291  if (m_whiteCursor != xMinusMargin) {
292  m_whiteCursor = xMinusMargin;
293  if (m_gammaEnabled) {
294  m_gammaCursor = calculateGammaCursor();
295  }
296  }
297  break;
298  case GammaCursor:
299  if (m_gammaCursor != xMinusMargin) {
300  m_gammaCursor = xMinusMargin;
301  double delta = (double)(m_whiteCursor - m_blackCursor) / 2.0;
302  double mid = (double)m_blackCursor + delta;
303  double tmp = (xMinusMargin - mid) / delta;
304  m_gamma = 1.0 / pow(10, tmp);
305  }
306  break;
307  default:
308  break;
309  }
310  }
311 
312  update();
313 }
314 
315 void KisGradientSlider::calculateCursorPositions()
316 {
317  m_blackCursor = qRound(m_black * m_scalingFactor);
318  m_whiteCursor = qRound(m_white * m_scalingFactor);
319 
320  m_gammaCursor = calculateGammaCursor();
321 }
322 
323 unsigned int KisGradientSlider::calculateGammaCursor()
324 {
325  double delta = (double)(m_whiteCursor - m_blackCursor) / 2.0;
326  double mid = (double)m_blackCursor + delta;
327  double tmp = log10(1.0 / m_gamma);
328  return (unsigned int)qRound(mid + delta * tmp);
329 }
330 
331 
332 void KisGradientSlider::enableGamma(bool b)
333 {
334  m_gammaEnabled = b;
335  update();
336 }
337 
338 double KisGradientSlider::getGamma(void)
339 {
340  return m_gamma;
341 }
342 
343 
344 void KisGradientSlider::enableWhite(bool b)
345 {
346  m_whiteEnabled = b;
347  update();
348 }
349 
350 void KisGradientSlider::setInverted(bool b)
351 {
352  m_inverted = b;
353  update();
354 }
355 
356 void KisGradientSlider::slotModifyBlack(int v)
357 {
358  if ((m_inverted && (v < m_white || v > width())) ||
359  (!m_inverted && (v < 0 || v > m_white)) ||
360  m_feedback)
361  return;
362 
363  m_black = v;
364  m_blackCursor = qRound(m_black * m_scalingFactor);
365  m_gammaCursor = calculateGammaCursor();
366  update();
367 }
368 
369 void KisGradientSlider::slotModifyWhite(int v)
370 {
371  if ((m_inverted && (v < 0 || v > m_white)) ||
372  (!m_inverted && (v < m_black && v > width())) ||
373  m_feedback)
374  return;
375  m_white = v;
376  m_whiteCursor = qRound(m_white * m_scalingFactor);
377  m_gammaCursor = calculateGammaCursor();
378  update();
379 }
380 
381 void KisGradientSlider::slotModifyGamma(double v)
382 {
383  if (m_gamma != v) {
384  emit sigModifiedGamma(v);
385  }
386  m_gamma = v;
387  m_gammaCursor = calculateGammaCursor();
388  update();
389 }
390 
QGradient::setColorAt
void setColorAt(qreal position, const QColor &color)
QMouseEvent::pos
const QPoint & pos() const
QColor
QWidget::y
int y() const
KisGradientSlider::slotModifyGamma
void slotModifyGamma(double)
Definition: KisGradientSlider.cpp:381
KisGradientSlider::setInverted
void setInverted(bool b)
Definition: KisGradientSlider.cpp:350
KisGradientSlider::sigModifiedWhite
void sigModifiedWhite(int)
QWidget::window
QWidget * window() const
QPainter::setPen
void setPen(const QColor &color)
KisGradientSlider::enableWhite
void enableWhite(bool b)
Definition: KisGradientSlider.cpp:344
QWidget::setFocusPolicy
void setFocusPolicy(Qt::FocusPolicy policy)
KisGradientSlider::sigModifiedGamma
void sigModifiedGamma(double)
QWidget::paintEvent
virtual void paintEvent(QPaintEvent *event)
QWidget::palette
const QPalette & palette() const
QMouseEvent::button
Qt::MouseButton button() const
QPainter::drawRect
void drawRect(const QRectF &rectangle)
QWidget::rect
QRect rect() const
QWidget::update
void update()
KisGradientSlider::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e) override
Definition: KisGradientSlider.cpp:241
MARGIN
#define MARGIN
Definition: KisGradientSlider.cpp:27
QWidget
QWidget::x
int x() const
QPoint::x
int x() const
QPainter
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
KisGradientSlider::resizeEvent
void resizeEvent(QResizeEvent *) override
Definition: KisGradientSlider.cpp:142
QMouseEvent
QPainter::drawPolygon
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
KisGradientSlider::mousePressEvent
void mousePressEvent(QMouseEvent *e) override
Definition: KisGradientSlider.cpp:149
KisGradientSlider::sigModifiedBlack
void sigModifiedBlack(int)
KisGradientSlider::white
int white() const
Definition: KisGradientSlider.cpp:61
KisGradientSlider::getGamma
double getGamma(void)
Definition: KisGradientSlider.cpp:338
KisGradientSlider::slotModifyBlack
void slotModifyBlack(int)
Definition: KisGradientSlider.cpp:356
KisGradientSlider::paintEvent
void paintEvent(QPaintEvent *) override
Definition: KisGradientSlider.cpp:66
KisGradientSlider::black
int black() const
Definition: KisGradientSlider.cpp:56
KisGradientSlider::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e) override
Definition: KisGradientSlider.cpp:270
QBrush
KisGradientSlider::~KisGradientSlider
~KisGradientSlider() override
Definition: KisGradientSlider.cpp:52
QPainter::setBrush
void setBrush(const QBrush &brush)
KisGradientSlider::KisGradientSlider
KisGradientSlider(QWidget *parent=0)
Definition: KisGradientSlider.cpp:30
QWidget::setMouseTracking
void setMouseTracking(bool enable)
KisGradientSlider::enableGamma
void enableGamma(bool b)
Definition: KisGradientSlider.cpp:332
QWidget::height
int height() const
QLinearGradient
QResizeEvent
QPaintEvent
QPainter::drawLine
void drawLine(const QLineF &line)
KisGradientSlider.h
QPainter::setRenderHint
void setRenderHint(RenderHint hint, bool on)
QWidget::width
int width() const
KisGradientSlider::slotModifyWhite
void slotModifyWhite(int)
Definition: KisGradientSlider.cpp:369
QPoint
HANDLE_SIZE
#define HANDLE_SIZE
Definition: KisGradientSlider.cpp:28
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Jan 23 2021 11:48:22 by doxygen 1.8.16 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KritaWidgets

Skip menu "KritaWidgets"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

krita API Reference

Skip menu "krita API Reference"
  • libs
  •   KritaBasicFlakes
  •   brush
  •   KritaUndo2
  •   KritaFlake
  •   image
  •   KritaPlugin
  •   Krita
  •   KritaPigment
  •   KritaResources
  •   KritaStore
  •   ui
  •   KritaWidgets
  •   KritaWidgetUtils
  • plugins
  •   Assitants
  •   Extensions
  •   Filters
  •   Generators
  •   Formats
  •           src
  •   PaintOps
  •     libpaintop

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal