Commit dedcbc77 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

[FEATURE] Added a Scalable Distance option to Weighted Smoothing

Now if you activate "Scalable Distance" option for a brush tool,
the distance will be corrected to your current zoom level. It means
that your stylus will be "stabilized" the same way at any zoom level
you choose.

BUG:335834
CCMAIL:kimageshop@kde.org
parent d5abb82d
......@@ -74,12 +74,14 @@ void KisToolBrush::slotSetSmoothingType(int index)
m_sliderSmoothnessDistance->setEnabled(false);
m_sliderTailAggressiveness->setEnabled(false);
m_chkSmoothPressure->setEnabled(false);
m_chkUseScalableDistance->setEnabled(false);
break;
case 1:
m_smoothingOptions.setSmoothingType(KisSmoothingOptions::SIMPLE_SMOOTHING);
m_sliderSmoothnessDistance->setEnabled(false);
m_sliderTailAggressiveness->setEnabled(false);
m_chkSmoothPressure->setEnabled(false);
m_chkUseScalableDistance->setEnabled(false);
break;
case 2:
default:
......@@ -87,6 +89,7 @@ void KisToolBrush::slotSetSmoothingType(int index)
m_sliderSmoothnessDistance->setEnabled(true);
m_sliderTailAggressiveness->setEnabled(true);
m_chkSmoothPressure->setEnabled(true);
m_chkUseScalableDistance->setEnabled(true);
}
emit smoothingTypeChanged();
}
......@@ -113,6 +116,17 @@ void KisToolBrush::slotSetMagnetism(int magnetism)
m_magnetism = expf(magnetism / (double)MAXIMUM_MAGNETISM) / expf(1.0);
}
bool KisToolBrush::useScalableDistance() const
{
return m_smoothingOptions.useScalableDistance();
}
void KisToolBrush::setUseScalableDistance(bool value)
{
m_smoothingOptions.setUseScalableDistance(value);
emit useScalableDistanceChanged();
}
QWidget * KisToolBrush::createOptionWidget()
{
QWidget *optionsWidget = KisToolFreehand::createOptionWidget();
......@@ -177,6 +191,11 @@ QWidget * KisToolBrush::createOptionWidget()
connect(m_chkSmoothPressure, SIGNAL(toggled(bool)), this, SLOT(setSmoothPressure(bool)));
addOptionWidgetOption(m_chkSmoothPressure, new QLabel(i18n("Smooth Pressure")));
m_chkUseScalableDistance = new QCheckBox("", optionsWidget);
m_chkUseScalableDistance->setChecked(m_smoothingOptions.useScalableDistance());
connect(m_chkUseScalableDistance, SIGNAL(toggled(bool)), this, SLOT(setUseScalableDistance(bool)));
addOptionWidgetOption(m_chkUseScalableDistance, new QLabel(i18n("Scalable Distance")));
m_buttonGroup->button((int)m_smoothingOptions.smoothingType())->setChecked(true);
slotSetSmoothingType((int)m_smoothingOptions.smoothingType());
......
......@@ -41,6 +41,7 @@ class KisToolBrush : public KisToolFreehand
Q_PROPERTY(qreal smoothnessFactor READ smoothnessFactor WRITE slotSetTailAgressiveness NOTIFY smoothnessFactorChanged)
Q_PROPERTY(bool smoothPressure READ smoothPressure WRITE setSmoothPressure NOTIFY smoothPressureChanged)
Q_PROPERTY(int smoothingType READ smoothingType WRITE slotSetSmoothingType NOTIFY smoothingTypeChanged)
Q_PROPERTY(bool useScalableDistance READ useScalableDistance WRITE setUseScalableDistance NOTIFY useScalableDistanceChanged)
public:
KisToolBrush(KoCanvasBase * canvas);
......@@ -52,6 +53,7 @@ public:
qreal smoothnessFactor() const;
bool smoothPressure() const;
int smoothingType() const;
bool useScalableDistance() const;
public slots:
void slotSetSmoothnessDistance(qreal distance);
......@@ -59,12 +61,14 @@ public slots:
void slotSetSmoothingType(int index);
void slotSetTailAgressiveness(qreal argh_rhhrr);
void setSmoothPressure(bool value);
void setUseScalableDistance(bool value);
Q_SIGNALS:
void smoothnessQualityChanged();
void smoothnessFactorChanged();
void smoothPressureChanged();
void smoothingTypeChanged();
void useScalableDistanceChanged();
private:
QGridLayout *m_optionLayout;
......@@ -74,6 +78,7 @@ private:
KisDoubleSliderSpinBox *m_sliderSmoothnessDistance;
KisDoubleSliderSpinBox *m_sliderTailAggressiveness;
QCheckBox *m_chkSmoothPressure;
QCheckBox *m_chkUseScalableDistance;
QButtonGroup * m_buttonGroup;
};
......
......@@ -415,6 +415,12 @@ QPointF KisCoordinatesConverter::widgetCenterPoint() const
void KisCoordinatesConverter::imageScale(qreal *scaleX, qreal *scaleY) const
{
if(!m_d->image) {
*scaleX = 1.0;
*scaleY = 1.0;
return;
}
// get the x and y zoom level of the canvas
qreal zoomX, zoomY;
KoZoomHandler::zoom(&zoomX, &zoomY);
......
......@@ -79,6 +79,7 @@ void KisCanvasResourceProvider::setResourceManager(KoCanvasResourceManager *reso
m_resourceManager->setResource(HdrExposure, 0.0);
m_resourceManager->setResource(HdrGamma, 1.0);
m_resourceManager->setResource(EffectiveZoom, 1.0);
connect(m_resourceManager, SIGNAL(canvasResourceChanged(int,QVariant)),
this, SLOT(slotCanvasResourceChanged(int,QVariant)));
......
......@@ -66,7 +66,8 @@ public:
Opacity,
HdrGamma,
GlobalAlphaLock,
PreviousPaintOpPreset
PreviousPaintOpPreset,
EffectiveZoom ///<-Used only by painting tools for non-displaying purposes
};
......
......@@ -1125,6 +1125,16 @@ void KisConfig::setLineSmoothingSmoothPressure(bool value)
m_cfg.writeEntry("LineSmoothingSmoothPressure", value);
}
bool KisConfig::lineSmoothingScalableDistance() const
{
return m_cfg.readEntry("LineSmoothingScalableDistance", true);
}
void KisConfig::setLineSmoothingScalableDistance(bool value)
{
m_cfg.writeEntry("LineSmoothingScalableDistance", value);
}
int KisConfig::paletteDockerPaletteViewSectionSize() const
{
return m_cfg.readEntry("paletteDockerPaletteViewSectionSize", 12);
......
......@@ -342,6 +342,9 @@ public:
bool lineSmoothingSmoothPressure() const;
void setLineSmoothingSmoothPressure(bool value);
bool lineSmoothingScalableDistance() const;
void setLineSmoothingScalableDistance(bool value);
int paletteDockerPaletteViewSectionSize() const;
void setPaletteDockerPaletteViewSectionSize(int value) const;
......
......@@ -49,6 +49,8 @@
#include "kis_statusbar.h"
#include "kis_config.h"
#include "krita_utils.h"
#include "kis_canvas_resource_provider.h"
class KisZoomController : public KoZoomController
{
......@@ -230,6 +232,10 @@ void KisZoomManager::slotZoomChanged(KoZoomMode::Mode mode, qreal zoom)
KritaUtils::prettyFormatReal(humanZoom)),
QIcon(), 500, KisFloatingMessage::Low);
qreal scaleX, scaleY;
m_view->canvasBase()->coordinatesConverter()->imageScale(&scaleX, &scaleY);
KIS_ASSERT_RECOVER_NOOP(scaleX == scaleY && "Zoom is not isotropic!");
m_view->canvasBase()->resourceManager()->setResource(KisCanvasResourceProvider::EffectiveZoom, scaleX);
}
void KisZoomManager::slotScrollAreaSizeChanged()
......
......@@ -67,6 +67,7 @@ struct KisResourcesSnapshot::Private {
KisPainter::FillStyle fillStyle;
bool globalAlphaLock;
qreal effectiveZoom;
};
KisResourcesSnapshot::KisResourcesSnapshot(KisImageWSP image, KisPostExecutionUndoAdapter *undoAdapter, KoCanvasResourceManager *resourceManager, KisDefaultBoundsBaseSP bounds)
......@@ -118,6 +119,7 @@ KisResourcesSnapshot::KisResourcesSnapshot(KisImageWSP image, KisPostExecutionUn
m_d->fillStyle = KisPainter::FillStyleNone;
m_d->globalAlphaLock = resourceManager->resource(KisCanvasResourceProvider::GlobalAlphaLock).toBool();
m_d->effectiveZoom = resourceManager->resource(KisCanvasResourceProvider::EffectiveZoom).toDouble();
}
KisResourcesSnapshot::~KisResourcesSnapshot()
......@@ -282,3 +284,7 @@ QBitArray KisResourcesSnapshot::channelLockFlags() const
return channelFlags;
}
qreal KisResourcesSnapshot::effectiveZoom() const
{
return m_d->effectiveZoom;
}
......@@ -69,6 +69,8 @@ public:
/// @return the channel lock flags of the current node with the global override applied
QBitArray channelLockFlags() const;
qreal effectiveZoom() const;
private:
struct Private;
Private * const m_d;
......
......@@ -24,12 +24,14 @@ KisSmoothingOptions::KisSmoothingOptions()
, m_smoothnessDistance(55.0)
, m_tailAggressiveness(0.15)
, m_smoothPressure(false)
, m_useScalableDistance(true)
{
KisConfig cfg;
m_smoothingType = (SmoothingType)cfg.lineSmoothingType();
m_smoothnessDistance = cfg.lineSmoothingDistance();
m_tailAggressiveness = cfg.lineSmoothingTailAggressiveness();
m_smoothPressure = cfg.lineSmoothingSmoothPressure();
m_useScalableDistance = cfg.lineSmoothingScalableDistance();
}
KisSmoothingOptions::SmoothingType KisSmoothingOptions::smoothingType() const
......@@ -80,4 +82,14 @@ void KisSmoothingOptions::setSmoothPressure(bool value)
m_smoothPressure = value;
}
bool KisSmoothingOptions::useScalableDistance() const
{
return m_useScalableDistance;
}
void KisSmoothingOptions::setUseScalableDistance(bool value)
{
KisConfig cfg;
cfg.setLineSmoothingScalableDistance(value);
m_useScalableDistance = value;
}
......@@ -46,12 +46,15 @@ public:
bool smoothPressure() const;
void setSmoothPressure(bool value);
bool useScalableDistance() const;
void setUseScalableDistance(bool value);
private:
SmoothingType m_smoothingType;
qreal m_smoothnessDistance;
qreal m_tailAggressiveness;
bool m_smoothPressure;
bool m_useScalableDistance;
};
#endif // KIS_SMOOTHING_OPTIONS_H
......@@ -350,7 +350,13 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
qreal y = 0.0;
if (m_d->history.size() > 3) {
const qreal sigma = m_d->smoothingOptions.smoothnessDistance() / 3.0; // '3.0' for (3 * sigma) range
const qreal effectiveSmoothnessDistance =
!m_d->smoothingOptions.useScalableDistance() ?
m_d->smoothingOptions.smoothnessDistance() :
m_d->smoothingOptions.smoothnessDistance() /
m_d->resources->effectiveZoom();
const qreal sigma = effectiveSmoothnessDistance / 3.0; // '3.0' for (3 * sigma) range
qreal gaussianWeight = 1 / (sqrt(2 * M_PI) * sigma);
qreal gaussianWeight2 = sigma * sigma;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment