Commit 5db9a905 authored by Boudewijn Rempt's avatar Boudewijn Rempt

BUG:330661 Save multi-sensor configuration correctly

Big rewrite & cleanup of the sensors/libpaintop code...

The KisDynamicSensorList class is gone and KisCurveOption now tracks
all sensors. The KisMultiSensorModel doesn't own the data it is a model
for anymore everything is tracked by KisCurveOption.

Conflicts:
	krita/plugins/paintops/spray/kis_spray_paintop_settings_widget.cpp
	krita/plugins/paintops/spray/kis_sprayop_option.cpp
	krita/plugins/paintops/spray/spray_brush.cpp
	krita/plugins/paintops/spray/spray_brush.h
parent 8e8b35b9
......@@ -335,7 +335,8 @@ KisCubicCurve::KisCubicCurve(const QList<QPointF>& points) : d(new Private)
d->data->keepSorted();
}
KisCubicCurve::KisCubicCurve(const KisCubicCurve& curve) : d(new Private(*curve.d))
KisCubicCurve::KisCubicCurve(const KisCubicCurve& curve)
: d(new Private(*curve.d))
{
}
......
......@@ -19,7 +19,8 @@
#if defined(_WIN32) || defined(_WIN64)
#include <stdlib.h>
#define srand48 srand
inline double drand48() {
inline double drand48()
{
return double(rand()) / RAND_MAX;
}
#endif
......@@ -49,7 +50,7 @@ ChalkBrush::ChalkBrush(const ChalkProperties* properties, KoColorTransformation*
else {
m_saturationId = -1;
}
m_counter = 0;
m_properties = properties;
......@@ -79,10 +80,10 @@ void ChalkBrush::paint(KisPaintDeviceSP dev, qreal x, qreal y, const KoColor &co
if (m_properties->useSaturation) {
if (m_transfo) {
m_transfo->setParameter(m_saturationId,result);
m_transfo->setParameter(m_saturationId, result);
m_transfo->transform(m_inkColor.data(), m_inkColor.data(), 1);
}
}
if (m_properties->useOpacity) {
......@@ -90,16 +91,16 @@ void ChalkBrush::paint(KisPaintDeviceSP dev, qreal x, qreal y, const KoColor &co
m_inkColor.setOpacity(opacity);
}
}
int pixelX, pixelY;
int radiusSquared = m_properties->radius * m_properties->radius;
double dirtThreshold = 0.5;
for (int by = -m_properties->radius; by <= m_properties->radius; by++) {
int bySquared = by*by;
int bySquared = by * by;
for (int bx = -m_properties->radius; bx <= m_properties->radius; bx++) {
// let's call that noise from ground to chalk :)
if ( ((bx*bx + bySquared) > radiusSquared) || drand48() < dirtThreshold) {
if (((bx * bx + bySquared) > radiusSquared) || drand48() < dirtThreshold) {
continue;
}
......
......@@ -37,11 +37,11 @@ K_EXPORT_PLUGIN(ChalkPaintOpPluginFactory("krita"))
ChalkPaintOpPlugin::ChalkPaintOpPlugin(QObject *parent, const QVariantList &)
: QObject(parent)
: QObject(parent)
{
KisPaintOpRegistry *r = KisPaintOpRegistry::instance();
r->add(new KisSimplePaintOpFactory<KisChalkPaintOp, KisChalkPaintOpSettings, KisChalkPaintOpSettingsWidget>("chalkbrush", i18n("Chalk brush"),
KisPaintOpFactory::categoryExperimental(), "krita-chalk.png"));
r->add(new KisSimplePaintOpFactory<KisChalkPaintOp, KisChalkPaintOpSettings, KisChalkPaintOpSettingsWidget>("chalkbrush", i18n("Chalk brush"),
KisPaintOpFactory::categoryExperimental(), "krita-chalk.png"));
}
......
......@@ -38,19 +38,19 @@
#include <kis_pressure_opacity_option.h>
KisChalkPaintOp::KisChalkPaintOp(const KisChalkPaintOpSettings *settings, KisPainter * painter, KisImageWSP image)
: KisPaintOp(painter)
: KisPaintOp(painter)
{
Q_UNUSED(image);
m_opacityOption.readOptionSetting(settings);
m_opacityOption.sensor()->reset();
m_opacityOption.resetAllSensors();
m_properties.readOptionSetting(settings);
KoColorTransformation* transfo = 0;
if (m_properties.inkDepletion && m_properties.useSaturation){
if (m_properties.inkDepletion && m_properties.useSaturation) {
transfo = painter->device()->compositionSourceColorSpace()->createColorTransformation("hsv_adjustment", QHash<QString, QVariant>());
}
m_chalkBrush = new ChalkBrush( &m_properties, transfo );
m_chalkBrush = new ChalkBrush(&m_properties, transfo);
}
KisChalkPaintOp::~KisChalkPaintOp()
......@@ -64,7 +64,8 @@ KisSpacingInformation KisChalkPaintOp::paintAt(const KisPaintInformation& info)
if (!m_dab) {
m_dab = source()->createCompositionSourceDevice();
} else {
}
else {
m_dab->clear();
}
......@@ -79,7 +80,7 @@ KisSpacingInformation KisChalkPaintOp::paintAt(const KisPaintInformation& info)
QRect rc = m_dab->extent();
painter()->bitBlt(rc.x(), rc.y(), m_dab, rc.x(), rc.y(), rc.width(), rc.height());
painter()->renderMirrorMask(rc,m_dab);
painter()->renderMirrorMask(rc, m_dab);
painter()->setOpacity(origOpacity);
return 1.0;
}
......@@ -45,7 +45,7 @@ int KisChalkPaintOpSettings::rate() const
QPainterPath KisChalkPaintOpSettings::brushOutline(const KisPaintInformation &info, OutlineMode mode) const
{
QPainterPath path;
if (mode == CursorIsOutline){
if (mode == CursorIsOutline) {
qreal size = getInt(CHALK_RADIUS) * 2 + 1;
path = ellipseOutline(size, size, 1.0, 0.0);
path.translate(info.pos());
......
......@@ -29,7 +29,7 @@
#include <kis_airbrush_option.h>
KisChalkPaintOpSettingsWidget:: KisChalkPaintOpSettingsWidget(QWidget* parent)
: KisPaintOpOptionsWidget(parent)
: KisPaintOpOptionsWidget(parent)
{
m_chalkOption = new KisChalkOpOption();
......@@ -55,8 +55,8 @@ KisPropertiesConfiguration* KisChalkPaintOpSettingsWidget::configuration() cons
void KisChalkPaintOpSettingsWidget::changePaintOpSize(qreal x, qreal y)
{
// if the movement is more left<->right then up<->down
if (qAbs(x) > qAbs(y)){
m_chalkOption->setRadius( m_chalkOption->radius() + qRound(x) );
if (qAbs(x) > qAbs(y)) {
m_chalkOption->setRadius(m_chalkOption->radius() + qRound(x));
}
}
......
......@@ -23,13 +23,13 @@ class KisChalkOpOptionsWidget: public QWidget, public Ui::WdgChalkOptions
{
public:
KisChalkOpOptionsWidget(QWidget *parent = 0)
: QWidget(parent) {
: QWidget(parent) {
setupUi(this);
}
};
KisChalkOpOption::KisChalkOpOption()
: KisPaintOpOption(i18n("Brush size"), KisPaintOpOption::brushCategory(), false)
: KisPaintOpOption(i18n("Brush size"), KisPaintOpOption::brushCategory(), false)
{
m_checkable = false;
m_options = new KisChalkOpOptionsWidget();
......@@ -54,7 +54,7 @@ int KisChalkOpOption::radius() const
void KisChalkOpOption::setRadius(int radius) const
{
m_options->radiusSpinBox->setValue( radius );
m_options->radiusSpinBox->setValue(radius);
}
......
......@@ -37,10 +37,10 @@ public:
void setRadius(int radius) const;
int radius() const;
bool inkDepletion() const;
bool inkDepletion() const;
bool saturation() const;
bool opacity() const;
void writeOptionSetting(KisPropertiesConfiguration* setting) const;
void readOptionSetting(const KisPropertiesConfiguration* setting);
......@@ -51,18 +51,19 @@ private:
};
class ChalkProperties {
class ChalkProperties
{
public:
int radius;
bool inkDepletion;
bool useOpacity;
bool useSaturation;
void readOptionSetting(const KisPropertiesConfiguration* settings){
radius = settings->getInt(CHALK_RADIUS);
inkDepletion = settings->getBool(CHALK_INK_DEPLETION);
useOpacity = settings->getBool(CHALK_USE_OPACITY);
useSaturation = settings->getBool(CHALK_USE_SATURATION);
void readOptionSetting(const KisPropertiesConfiguration* settings) {
radius = settings->getInt(CHALK_RADIUS);
inkDepletion = settings->getBool(CHALK_INK_DEPLETION);
useOpacity = settings->getBool(CHALK_USE_OPACITY);
useSaturation = settings->getBool(CHALK_USE_SATURATION);
}
};
......
......@@ -41,8 +41,8 @@ ColorSmudgePaintOpPlugin::ColorSmudgePaintOpPlugin(QObject* parent, const QVaria
QObject(parent)
{
KisPaintOpRegistry::instance()->add(new KisSimplePaintOpFactory<KisColorSmudgeOp, KisBrushBasedPaintOpSettings, KisColorSmudgeOpSettingsWidget>(
"colorsmudge", i18n("Color Smudge Brush"), KisPaintOpFactory::categoryExperimental(), "krita-colorsmudge.png")
);
"colorsmudge", i18n("Color Smudge Brush"), KisPaintOpFactory::categoryExperimental(), "krita-colorsmudge.png")
);
}
ColorSmudgePaintOpPlugin::~ColorSmudgePaintOpPlugin() { }
......
......@@ -60,14 +60,14 @@ KisColorSmudgeOp::KisColorSmudgeOp(const KisBrushBasedPaintOpSettings* settings,
m_scatterOption.readOptionSetting(settings);
m_gradientOption.readOptionSetting(settings);
m_sizeOption.sensor()->reset();
m_opacityOption.sensor()->reset();
m_spacingOption.sensor()->reset();
m_smudgeRateOption.sensor()->reset();
m_colorRateOption.sensor()->reset();
m_rotationOption.sensor()->reset();
m_scatterOption.sensor()->reset();
m_gradientOption.sensor()->reset();
m_sizeOption.resetAllSensors();
m_opacityOption.resetAllSensors();
m_spacingOption.resetAllSensors();
m_smudgeRateOption.resetAllSensors();
m_colorRateOption.resetAllSensors();
m_rotationOption.resetAllSensors();
m_scatterOption.resetAllSensors();
m_gradientOption.resetAllSensors();
m_gradient = painter->gradient();
......@@ -127,7 +127,7 @@ KisSpacingInformation KisColorSmudgeOp::paintAt(const KisPaintInformation& info)
KisBrushSP brush = m_brush;
// Simple error catching
if(!painter()->device() || !brush || !brush->canPaintFor(info))
if (!painter()->device() || !brush || !brush->canPaintFor(info))
return 1.0;
// get the scaling factor calculated by the size option
......@@ -183,7 +183,7 @@ KisSpacingInformation KisColorSmudgeOp::paintAt(const KisPaintInformation& info)
QString oldModeId = painter()->compositeOp()->id();
qreal fpOpacity = (qreal(oldOpacity) / 255.0) * m_opacityOption.getOpacityf(info);
if(m_image && m_overlayModeOption.isChecked()) {
if (m_image && m_overlayModeOption.isChecked()) {
m_image->blockUpdates();
m_backgroundPainter->bitBlt(QPoint(), m_image->projection(), srcDabRect);
m_image->unblockUpdates();
......@@ -194,7 +194,7 @@ KisSpacingInformation KisColorSmudgeOp::paintAt(const KisPaintInformation& info)
m_tempDev->clear(QRect(QPoint(), m_dstDabRect.size()));
}
if(m_smudgeRateOption.getMode() == KisSmudgeOption::SMEARING_MODE) {
if (m_smudgeRateOption.getMode() == KisSmudgeOption::SMEARING_MODE) {
// cut out the area from the canvas under the brush
// and blit it to the temporary painting device
m_smudgePainter->bitBlt(QPoint(), painter()->device(), srcDabRect);
......@@ -214,10 +214,10 @@ KisSpacingInformation KisColorSmudgeOp::paintAt(const KisPaintInformation& info)
// if the user selected the color smudge option
// we will mix some color into the temporary painting device (m_tempDev)
if(m_colorRateOption.isChecked()) {
if (m_colorRateOption.isChecked()) {
// this will apply the opacy (selected by the user) to copyPainter
// (but fit the rate inbetween the range 0.0 to (1.0-SmudgeRate))
qreal maxColorRate = qMax<qreal>(1.0-m_smudgeRateOption.getRate(), 0.2);
qreal maxColorRate = qMax<qreal>(1.0 - m_smudgeRateOption.getRate(), 0.2);
m_colorRateOption.apply(*m_colorRatePainter, info, 0.0, maxColorRate, fpOpacity);
// paint a rectangle with the current color (foreground color)
......@@ -234,7 +234,7 @@ KisSpacingInformation KisColorSmudgeOp::paintAt(const KisPaintInformation& info)
// then first blit the region under the brush from the image projection
// to the painting device to prevent a rapid build up of alpha value
// if the color to be smudged is semi transparent
if(m_image && m_overlayModeOption.isChecked() && !m_colorRateOption.isChecked()) {
if (m_image && m_overlayModeOption.isChecked() && !m_colorRateOption.isChecked()) {
painter()->setCompositeOp(COMPOSITE_COPY);
painter()->setOpacity(OPACITY_OPAQUE_U8);
m_image->blockUpdates();
......
......@@ -28,7 +28,7 @@ class KisColorSmudgeOpSettingsWidget : public KisBrushBasedPaintopOptionWidget
Q_OBJECT
public:
KisColorSmudgeOpSettingsWidget(QWidget* parent = 0);
KisColorSmudgeOpSettingsWidget(QWidget* parent = 0);
~KisColorSmudgeOpSettingsWidget();
KisPropertiesConfiguration* configuration() const;
......
......@@ -29,12 +29,14 @@ public:
KisOverlayModeOption():
KisPaintOpOption(i18n("Overlay Mode"), KisPaintOpOption::brushCategory(), false) { }
virtual bool isCheckable() { return true; }
virtual bool isCheckable() {
return true;
}
virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const {
setting->setProperty("MergedPaint", isChecked());
}
virtual void readOptionSetting(const KisPropertiesConfiguration* setting) {
bool enabled = setting->getBool("MergedPaint");
setChecked(enabled);
......@@ -44,15 +46,14 @@ public:
class KisOverlayModeOptionWidget: public KisOverlayModeOption
{
public:
KisOverlayModeOptionWidget()
{
KisOverlayModeOptionWidget() {
QLabel* lable = new QLabel(
i18n("Paints on the current layer\n\
but uses all layers that are currently visible for smudge input\n\
NOTE: This mode is only able to work correctly with a fully opaque background")
);
lable->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter);
lable->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
setConfigurationPage(lable);
}
};
......
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......@@ -34,13 +34,13 @@ KisRateOption::KisRateOption(const QString& name, const QString& label, bool che
void KisRateOption::apply(KisPainter& painter, const KisPaintInformation& info, qreal scaleMin, qreal scaleMax, qreal multiplicator) const
{
if(!isChecked()) {
if (!isChecked()) {
painter.setOpacity((quint8)(scaleMax * 255.0));
return;
}
qreal rate = scaleMin + (scaleMax - scaleMin) * multiplicator * computeValue(info); // scale m_rate into the range scaleMin - scaleMax
quint8 opacity = qBound(OPACITY_TRANSPARENT_U8, (quint8)(rate * 255.0), OPACITY_OPAQUE_U8);
painter.setOpacity(opacity);
}
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......@@ -31,16 +31,20 @@ class KisPainter;
class KisRateOption: public KisCurveOption
{
public:
KisRateOption(const QString& name, const QString& label="", bool checked=true, const QString& category=KisPaintOpOption::brushCategory());
KisRateOption(const QString& name, const QString& label = "", bool checked = true, const QString& category = KisPaintOpOption::brushCategory());
/**
* Set the opacity of the painter based on the rate
* and the curve (if checked)
*/
void apply(KisPainter& painter, const KisPaintInformation& info, qreal scaleMin=0.0, qreal scaleMax=1.0, qreal multiplicator=1.0) const;
void setRate(qreal rate) { KisCurveOption::setValue(rate); }
qreal getRate() const { return KisCurveOption::value(); }
void apply(KisPainter& painter, const KisPaintInformation& info, qreal scaleMin = 0.0, qreal scaleMax = 1.0, qreal multiplicator = 1.0) const;
void setRate(qreal rate) {
KisCurveOption::setValue(rate);
}
qreal getRate() const {
return KisCurveOption::value();
}
};
#endif // KIS_RATE_OPTION_H
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......@@ -29,36 +29,36 @@
KisSmudgeOption::KisSmudgeOption(const QString& name, const QString& label, bool checked, const QString& category):
KisRateOption(name, label, checked, category),
mMode(SMEARING_MODE)
m_mode(SMEARING_MODE)
{
setValueRange(0.01, 1.0);
}
void KisSmudgeOption::apply(KisPainter& painter, const KisPaintInformation& info, qreal scaleMin, qreal scaleMax, qreal multiplicator) const
{
if(!isChecked()) {
if (!isChecked()) {
painter.setOpacity((quint8)(scaleMax * 255.0));
return;
}
qreal rate = scaleMin + (scaleMax - scaleMin) * multiplicator * computeValue(info); // scale m_rate into the range scaleMin - scaleMax
quint8 opacity = qBound(OPACITY_TRANSPARENT_U8, (quint8)(rate * 255.0), OPACITY_OPAQUE_U8);
painter.setOpacity(opacity);
}
void KisSmudgeOption::writeOptionSetting(KisPropertiesConfiguration* setting) const
{
KisRateOption::writeOptionSetting(setting);
setting->setProperty(name() + "Mode", mMode);
setting->setProperty(name() + "Mode", m_mode);
}
void KisSmudgeOption::readOptionSetting(const KisPropertiesConfiguration* setting)
{
KisRateOption::readOptionSetting(setting);
if(setting->hasProperty(name() + "Mode"))
mMode = (Mode)setting->getInt(name() + "Mode", mMode);
if (setting->hasProperty(name() + "Mode"))
m_mode = (Mode)setting->getInt(name() + "Mode", m_mode);
else
mMode = SMEARING_MODE;
m_mode = SMEARING_MODE;
}
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......@@ -33,24 +33,28 @@ class KisPainter;
class KisSmudgeOption: public KisRateOption
{
public:
KisSmudgeOption(const QString& name, const QString& label="", bool checked=true, const QString& category=KisPaintOpOption::brushCategory());
KisSmudgeOption(const QString& name, const QString& label = "", bool checked = true, const QString& category = KisPaintOpOption::brushCategory());
enum Mode { SMEARING_MODE, DULLING_MODE };
/**
* Set the opacity of the painter based on the rate
* and the curve (if checked)
*/
void apply(KisPainter& painter, const KisPaintInformation& info, qreal scaleMin=0.0, qreal scaleMax=1.0, qreal multiplicator=1.0) const;
Mode getMode() { return mMode; }
void setMode(Mode mode) { mMode = mode; }
void apply(KisPainter& painter, const KisPaintInformation& info, qreal scaleMin = 0.0, qreal scaleMax = 1.0, qreal multiplicator = 1.0) const;
Mode getMode() {
return m_mode;
}
void setMode(Mode mode) {
m_mode = mode;
}
virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const;
virtual void readOptionSetting(const KisPropertiesConfiguration* setting);
private:
Mode mMode;
Mode m_mode;
};
#endif // KIS_SMUDGE_OPTION_H
/* This file is part of the KDE project
*
*
* Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
......@@ -36,21 +36,21 @@ KisSmudgeOptionWidget::KisSmudgeOptionWidget(const QString& label, const QString
mCbSmudgeMode = new QComboBox();
mCbSmudgeMode->addItem(i18n("Smearing"), KisSmudgeOption::SMEARING_MODE);
mCbSmudgeMode->addItem(i18n("Dulling") , KisSmudgeOption::DULLING_MODE);
QHBoxLayout* h = new QHBoxLayout();
h->addWidget(new QLabel(i18n("Smudge mode:")));
h->addWidget(mCbSmudgeMode, 1);