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

plugins/paintops/libpaintop

  • sources
  • kfour-appscomplete
  • krita
  • plugins
  • paintops
  • libpaintop
kis_auto_brush_widget.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2004, 2007, 2009 Cyrille Berger <[email protected]>
3  * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <[email protected]>
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  */
7 
8 
9 #include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
10 #include "kis_auto_brush_widget.h"
11 
12 #include <kconfig.h>
13 #include <ksharedconfig.h>
14 #include <kconfiggroup.h>
15 
16 #include <math.h>
17 #include <kis_debug.h>
18 #include <QSpinBox>
19 #include <QToolButton>
20 #include <QImage>
21 #include <QComboBox>
22 #include <QLabel>
23 #include <QPixmap>
24 #include <QResizeEvent>
25 
26 #include <kis_fixed_paint_device.h>
27 #include <kis_mask_generator.h>
28 #include <kis_slider_spin_box.h>
29 #include "kis_signals_blocker.h"
30 #include "kis_signal_compressor.h"
31 #include "kis_aspect_ratio_locker.h"
32 #include <KisAngleSelector.h>
33 
34 
35 #define showSlider(input, step) input->setRange(input->minimum(), input->maximum(), step)
36 #include <kis_cubic_curve.h>
37 
38 KisAutoBrushWidget::KisAutoBrushWidget(QWidget *parent, const char* name)
39  : KisWdgAutoBrush(parent, name)
40  , m_autoBrush(0)
41  , m_updateCompressor(new KisSignalCompressor(100, KisSignalCompressor::FIRST_ACTIVE))
42  , m_fadeAspectLocker(new KisAspectRatioLocker())
43 {
44  connect(m_updateCompressor.data(), SIGNAL(timeout()), SLOT(paramChanged()));
45 
46  connect((QObject*)comboBoxShape, SIGNAL(activated(int)), m_updateCompressor.data(), SLOT(start()));
47 
48  inputRadius->setRange(0.01, KSharedConfig::openConfig()->group("").readEntry("maximumBrushSize", 1000), 2);
49  inputRadius->setExponentRatio(3.0);
50  inputRadius->setSingleStep(1);
51  inputRadius->setValue(5);
52  inputRadius->setSuffix(i18n(" px"));
53  inputRadius->setBlockUpdateSignalOnDrag(true);
54  connect(inputRadius, SIGNAL(valueChanged(qreal)), m_updateCompressor.data(), SLOT(start()));
55 
56  inputRatio->setRange(0.01, 1.0, 2);
57  inputRatio->setSingleStep(0.1);
58  inputRatio->setValue(1.0);
59  inputRatio->setBlockUpdateSignalOnDrag(true);
60  connect(inputRatio, SIGNAL(valueChanged(qreal)), m_updateCompressor.data(), SLOT(start()));
61 
62  inputHFade->setRange(0.0, 1.0, 2);
63  inputHFade->setSingleStep(0.1);
64  inputHFade->setValue(0.5);
65 
66  inputVFade->setRange(0.0, 1.0, 2);
67  inputVFade->setSingleStep(0.1);
68  inputVFade->setValue(0.5);
69 
70  aspectButton->setKeepAspectRatio(true);
71 
72  m_fadeAspectLocker->connectSpinBoxes(inputHFade, inputVFade, aspectButton);
73  m_fadeAspectLocker->setBlockUpdateSignalOnDrag(true);
74  connect(m_fadeAspectLocker.data(), SIGNAL(sliderValueChanged()), m_updateCompressor.data(), SLOT(start()));
75  connect(m_fadeAspectLocker.data(), SIGNAL(aspectButtonChanged()), m_updateCompressor.data(), SLOT(start()));
76 
77  inputSpikes->setRange(2, 20);
78  inputSpikes->setValue(2);
79  inputSpikes->setBlockUpdateSignalOnDrag(true);
80  connect(inputSpikes, SIGNAL(valueChanged(int)), m_updateCompressor.data(), SLOT(start()));
81 
82  inputRandomness->setRange(0, 100);
83  inputRandomness->setValue(0);
84  inputRandomness->setBlockUpdateSignalOnDrag(true);
85  connect(inputRandomness, SIGNAL(valueChanged(qreal)), m_updateCompressor.data(), SLOT(start()));
86 
87  inputAngle->setDecimals(0);
88  connect(inputAngle, SIGNAL(angleChanged(qreal)), m_updateCompressor.data(), SLOT(start()));
89 
90  connect(spacingWidget, SIGNAL(sigSpacingChanged()), m_updateCompressor.data(), SLOT(start()));
91 
92  density->setRange(0, 100, 0);
93  density->setSingleStep(1);
94  density->setValue(100);
95  density->setSuffix(i18n("%"));
96  density->setBlockUpdateSignalOnDrag(true);
97  connect(density, SIGNAL(valueChanged(qreal)), m_updateCompressor.data(), SLOT(start()));
98 
99  KisCubicCurve topLeftBottomRightLinearCurve;
100  topLeftBottomRightLinearCurve.setPoint(0, QPointF(0.0, 1.0));
101  topLeftBottomRightLinearCurve.setPoint(1, QPointF(1.0, 0.0));
102 
103  bool blockedBefore = softnessCurve->blockSignals(true);
104  softnessCurve->setCurve(topLeftBottomRightLinearCurve);
105  softnessCurve->blockSignals(blockedBefore);
106 
107  connect(softnessCurve, SIGNAL(modified()), m_updateCompressor.data(), SLOT(start()));
108 
109  m_brush = QImage(1, 1, QImage::Format_RGB32);
110 
111  connect(brushPreview, SIGNAL(clicked()), m_updateCompressor.data(), SLOT(start()));
112 
113  QList<KoID> ids = KisMaskGenerator::maskGeneratorIds();
114  for (int i = 0; i < ids.size(); i++) {
115  comboBoxMaskType->insertItem(i, ids[i].name());
116  }
117 
118  connect(comboBoxMaskType, SIGNAL(activated(int)), m_updateCompressor.data(), SLOT(start()));
119  connect(comboBoxMaskType, SIGNAL(currentIndexChanged(int)), SLOT(setStackedWidget(int)));
120  setStackedWidget(comboBoxMaskType->currentIndex());
121 
122  brushPreview->setIconSize(QSize(100, 100));
123 
124  connect(btnAntialiasing, SIGNAL(toggled(bool)), m_updateCompressor.data(), SLOT(start()));
125 
126  m_updateCompressor->start();
127 
128 }
129 
130 KisAutoBrushWidget::~KisAutoBrushWidget()
131 {
132 }
133 
134 void KisAutoBrushWidget::resizeEvent(QResizeEvent *)
135 {
136  brushPreview->setMinimumHeight(brushPreview->width()); // dirty hack !
137  brushPreview->setMaximumHeight(brushPreview->width()); // dirty hack !
138 }
139 
140 void KisAutoBrushWidget::activate()
141 {
142  m_updateCompressor->start();
143 }
144 
145 void KisAutoBrushWidget::paramChanged()
146 {
147  KisMaskGenerator* kas;
148 
149  bool antialiasEdges = btnAntialiasing->isChecked();
150 
151  if (comboBoxMaskType->currentIndex() == 2) { // gaussian brush
152  if (comboBoxShape->currentIndex() == 0) {
153  kas = new KisGaussCircleMaskGenerator(inputRadius->value(), inputRatio->value(), inputHFade->value(), inputVFade->value(), inputSpikes->value(), antialiasEdges);
154  }
155  else {
156  kas = new KisGaussRectangleMaskGenerator(inputRadius->value(), inputRatio->value(), inputHFade->value(), inputVFade->value(), inputSpikes->value(), antialiasEdges);
157  }
158  }
159  else if (comboBoxMaskType->currentIndex() == 1) { // soft brush
160  if (comboBoxShape->currentIndex() == 0) {
161  kas = new KisCurveCircleMaskGenerator(inputRadius->value(), inputRatio->value(), inputHFade->value(), inputVFade->value(), inputSpikes->value(), softnessCurve->curve(), antialiasEdges);
162  }
163  else {
164  kas = new KisCurveRectangleMaskGenerator(inputRadius->value(), inputRatio->value(), inputHFade->value(), inputVFade->value(), inputSpikes->value(), softnessCurve->curve(), antialiasEdges);
165  }
166  }
167  else {// default == 0 or any other
168  if (comboBoxShape->currentIndex() == 0) { // use index compare instead of comparing a translatable string
169  kas = new KisCircleMaskGenerator(inputRadius->value(), inputRatio->value(), inputHFade->value(), inputVFade->value(), inputSpikes->value(), antialiasEdges);
170  }
171  else {
172  kas = new KisRectangleMaskGenerator(inputRadius->value(), inputRatio->value(), inputHFade->value(), inputVFade->value(), inputSpikes->value(), antialiasEdges);
173  }
174  }
175  Q_CHECK_PTR(kas);
176 
177  m_autoBrush = KisBrushSP(new KisAutoBrush(kas, inputAngle->angle() / 180.0 * M_PI, inputRandomness->value() / 100.0, density->value() / 100.0));
178  m_autoBrush->setSpacing(spacingWidget->spacing());
179  m_autoBrush->setAutoSpacing(spacingWidget->autoSpacingActive(), spacingWidget->autoSpacingCoeff());
180  m_brush = m_autoBrush->image();
181 
182  drawBrushPreviewArea();
183 
184  emit sigBrushChanged();
185 }
186 
187 void KisAutoBrushWidget::drawBrushPreviewArea() {
188  QImage pi(m_brush);
189  double coeff = 1.0;
190  int bPw = brushPreview->width() - 3;
191  if (pi.width() > bPw) {
192  coeff = bPw / (double)pi.width();
193  }
194  int bPh = brushPreview->height() - 3;
195  if (pi.height() > coeff * bPh) {
196  coeff = bPh / (double)pi.height();
197  }
198  if (coeff < 1.0) {
199  pi = pi.scaled((int)(coeff * pi.width()) , (int)(coeff * pi.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
200  }
201 
202  QPixmap p = QPixmap::fromImage(pi);
203  brushPreview->setIcon(QIcon(p));
204 }
205 
206 void KisAutoBrushWidget::setStackedWidget(int index)
207 {
208  if (index == 1) {
209  stackedWidget->setCurrentIndex(1);
210  }
211  else {
212  stackedWidget->setCurrentIndex(0);
213  }
214 }
215 
216 KisBrushSP KisAutoBrushWidget::brush()
217 {
218  return m_autoBrush;
219 }
220 
221 void KisAutoBrushWidget::setBrush(KisBrushSP brush)
222 {
223  m_autoBrush = brush;
224  m_brush = brush->image();
225  // XXX: lock, set and unlock the widgets.
226  KisAutoBrush* aBrush = dynamic_cast<KisAutoBrush*>(brush.data());
227 
228  KisSignalsBlocker b1(comboBoxShape, comboBoxMaskType);
229  KisSignalsBlocker b2(inputRadius, inputRatio, inputHFade, inputVFade, inputAngle, inputSpikes);
230  KisSignalsBlocker b3(spacingWidget, inputRandomness, density, softnessCurve, btnAntialiasing);
231 
232  if (aBrush->maskGenerator()->type() == KisMaskGenerator::CIRCLE) {
233  comboBoxShape->setCurrentIndex(0);
234  }
235  else if (aBrush->maskGenerator()->type() == KisMaskGenerator::RECTANGLE) {
236  comboBoxShape->setCurrentIndex(1);
237  }
238  else {
239  comboBoxShape->setCurrentIndex(2);
240  }
241 
242  const int mastTypeIndex = comboBoxMaskType->findText(aBrush->maskGenerator()->name());
243  comboBoxMaskType->setCurrentIndex(mastTypeIndex);
244  setStackedWidget(mastTypeIndex); // adjusting manually because the signals are blocked
245 
246  inputRadius->setValue(aBrush->maskGenerator()->diameter());
247  inputRatio->setValue(aBrush->maskGenerator()->ratio());
248  inputHFade->setValue(aBrush->maskGenerator()->horizontalFade());
249  inputVFade->setValue(aBrush->maskGenerator()->verticalFade());
250  inputAngle->setAngle(aBrush->angle() * 180 / M_PI);
251  inputSpikes->setValue(aBrush->maskGenerator()->spikes());
252  spacingWidget->setSpacing(aBrush->autoSpacingActive(),
253  aBrush->autoSpacingActive() ?
254  aBrush->autoSpacingCoeff() : aBrush->spacing());
255  inputRandomness->setValue(aBrush->randomness() * 100);
256  density->setValue(aBrush->density() * 100);
257 
258  if (!aBrush->maskGenerator()->curveString().isEmpty()) {
259  KisCubicCurve curve;
260  curve.fromString(aBrush->maskGenerator()->curveString());
261  softnessCurve->setCurve(curve);
262  }
263 
264  btnAntialiasing->setChecked(aBrush->maskGenerator()->antialiasEdges());
265 
266  drawBrushPreviewArea(); // sync up what the brush preview area looks like
267 }
268 
269 
270 void KisAutoBrushWidget::setBrushSize(qreal dxPixels, qreal dyPixels)
271 {
272  Q_UNUSED(dyPixels);
273 
274  qreal newWidth = inputRadius->value() + dxPixels;
275  newWidth = qMax(newWidth, qreal(0.1));
276 
277  inputRadius->setValue(newWidth);
278 }
279 
280 QSizeF KisAutoBrushWidget::brushSize() const
281 {
282  return QSizeF(inputRadius->value(), inputRadius->value() * inputRatio->value());
283 }
284 
285 #include "moc_kis_auto_brush_widget.cpp"
KisAutoBrushWidget::drawBrushPreviewArea
void drawBrushPreviewArea()
Definition: kis_auto_brush_widget.cpp:187
QSharedPointer::data
T * data() const
QPixmap::fromImage
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
KisAutoBrushWidget::resizeEvent
void resizeEvent(QResizeEvent *) override
Definition: kis_auto_brush_widget.cpp:134
QImage::height
int height() const
KisAutoBrushWidget::sigBrushChanged
void sigBrushChanged()
KisAutoBrushWidget::brush
KisBrushSP brush()
Definition: kis_auto_brush_widget.cpp:216
QWidget
QImage::scaled
QImage scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const
QSize
KisAutoBrushWidget::activate
void activate()
Definition: kis_auto_brush_widget.cpp:140
QSharedPointer< KisBrush >
QList
QPointF
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QPixmap
QScopedPointer::data
T * data() const
QObject
QIcon
kis_auto_brush_widget.h
KisAutoBrushWidget::setBrush
void setBrush(KisBrushSP brush)
Definition: kis_auto_brush_widget.cpp:221
QResizeEvent
QSizeF
QObject::name
const char * name() const
KisWdgAutoBrush
Definition: kis_auto_brush_widget.h:20
KisAutoBrushWidget::setBrushSize
void setBrushSize(qreal dxPixels, qreal dyPixels)
Definition: kis_auto_brush_widget.cpp:270
KisAutoBrushWidget::brushSize
QSizeF brushSize() const
Definition: kis_auto_brush_widget.cpp:280
QImage
KisBrushSP
QSharedPointer< KisBrush > KisBrushSP
Definition: KisDabCacheUtils.h:21
KisAutoBrushWidget::~KisAutoBrushWidget
~KisAutoBrushWidget() override
Definition: kis_auto_brush_widget.cpp:130
KisAutoBrushWidget::KisAutoBrushWidget
KisAutoBrushWidget(QWidget *parent, const char *name)
Definition: kis_auto_brush_widget.cpp:38
QImage::width
int width() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Apr 17 2021 23:38:22 by doxygen 1.8.16 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

plugins/paintops/libpaintop

Skip menu "plugins/paintops/libpaintop"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

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