Commit 052935bf authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fixed three bugs and add a feature to KisFilterOp

1) Fixed painting on semi-transparent images. Now COMPOSITE_COPY is the
   default mode and it works nicely!
2) Added a feature: Smudge Mode for the Filter Op. The temporary device is
   not cleared every time, which creates really nice effects.
3) Fixed loading of the default filter configuration for the Filter Op
4) Fixed an offset bug when painting with Gaussian Blur.

BUG:252882
parent 1e0ef81f
......@@ -24,6 +24,7 @@
#include <kis_debug.h>
#include <KoColorSpaceRegistry.h>
#include <KoColorTransformation.h>
#include <KoColor.h>
#include <KoInputDevice.h>
......@@ -54,10 +55,12 @@ KisFilterOp::KisFilterOp(const KisFilterOpSettings *settings, KisPainter *painte
Q_ASSERT(painter);
m_tmpDevice = source()->createCompositionSourceDevice();
m_sizeOption.readOptionSetting(settings);
m_rotationOption.readOptionSetting(settings);
m_sizeOption.sensor()->reset();
m_rotationOption.sensor()->reset();
m_filter = KisFilterRegistry::instance()->get(settings->getString(FILTER_ID));
m_filterConfiguration = settings->filterConfig();
m_ignoreAlpha = settings->getBool(FILTER_IGNORE_ALPHA);
m_smudgeMode = settings->getBool(FILTER_SMUDGE_MODE);
}
KisFilterOp::~KisFilterOp()
......@@ -89,7 +92,8 @@ qreal KisFilterOp::paintAt(const KisPaintInformation& info)
setCurrentScale(scale);
QPointF hotSpot = brush->hotSpot(scale, scale, 0, info);
qreal rotation = m_rotationOption.apply(info);
QPointF hotSpot = brush->hotSpot(scale, scale, rotation, info);
QPointF pt = info.pos() - hotSpot;
......@@ -104,43 +108,32 @@ qreal KisFilterOp::paintAt(const KisPaintInformation& info)
splitCoordinate(pt.x(), &x, &xFraction);
splitCoordinate(pt.y(), &y, &yFraction);
qint32 maskWidth = brush->maskWidth(scale, 0.0, info);
qint32 maskHeight = brush->maskHeight(scale, 0.0, info);
qint32 maskWidth = brush->maskWidth(scale, rotation, info);
qint32 maskHeight = brush->maskHeight(scale, rotation, info);
// Filter the paint device
QRect rect = QRect(0, 0, maskWidth, maskHeight);
QRect neededRect = m_filter->neededRect(rect.translated(x, y), m_filterConfiguration);
KisPainter p(m_tmpDevice);
p.bitBltOldData(QPoint(x-neededRect.x(), y-neededRect.y()), source(), neededRect);
if (!m_smudgeMode) {
m_tmpDevice->clear();
}
KisPainter p(m_tmpDevice);
p.bitBltOldData(QPoint(neededRect.x()-x, neededRect.y()-y), source(), neededRect);
m_filter->process(m_tmpDevice, rect, m_filterConfiguration, 0);
// Apply the mask on the paint device (filter before mask because edge pixels may be important)
KisFixedPaintDeviceSP fixedDab = source()->createCompositionSourceDeviceFixed();
fixedDab->setRect(rect);
fixedDab->initialize();
m_tmpDevice->readBytes(fixedDab->data(), fixedDab->bounds());
brush->mask(fixedDab, scale, scale, 0.0, info, xFraction, yFraction);
m_tmpDevice->writeBytes(fixedDab->data(), fixedDab->bounds());
const KoColorSpace* tmpCS = m_tmpDevice->colorSpace();
const KoColorSpace* srcCS = source()->colorSpace();
if (!m_ignoreAlpha && srcCS->id() != "ALPHA") {
KisHLineIteratorSP itTmpDev = m_tmpDevice->createHLineIteratorNG(0, 0, maskWidth);
KisHLineConstIteratorSP itSrc = source()->createHLineConstIteratorNG(x, y, maskWidth);
for (int y = 0; y < maskHeight; ++y) {
do {
quint8 alphaTmpDev = tmpCS->opacityU8(itTmpDev->rawData());
quint8 alphaSrc = srcCS->opacityU8(itSrc->oldRawData());
tmpCS->setOpacity(itTmpDev->rawData(), qMin(alphaTmpDev, alphaSrc), 1);
} while (itTmpDev->nextPixel() && itSrc->nextPixel());
itTmpDev->nextRow();
itSrc->nextRow();
}
}
// Fetch the mask
static const KoColorSpace *cs = KoColorSpaceRegistry::instance()->alpha8();
static KoColor color(Qt::black, cs);
KisFixedPaintDeviceSP fixedDab = m_dabCache->fetchDab(cs,
color,
scale, scale,
rotation,
info,
xFraction,
yFraction);
// Blit the paint device onto the layer
QRect dabRect = QRect(0, 0, maskWidth, maskHeight);
......@@ -148,11 +141,12 @@ qreal KisFilterOp::paintAt(const KisPaintInformation& info)
if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return 1.0;
qint32 sx = dstRect.x() - x;
qint32 sy = dstRect.y() - y;
qint32 sw = dstRect.width();
qint32 sh = dstRect.height();
painter()->
bitBltWithFixedSelection(dstRect.x(), dstRect.y(),
m_tmpDevice, fixedDab,
0,0,
0,0,
maskWidth, maskHeight);
painter()->bitBlt(dstRect.x(), dstRect.y(), m_tmpDevice, sx, sy, sw, sh);
return spacing(scale);
}
......@@ -26,6 +26,7 @@
#include "kis_brush_based_paintop.h"
#include <KoColorSpace.h>
#include <kis_pressure_size_option.h>
#include <kis_pressure_rotation_option.h>
class KisFilterConfiguration;
class KisFilterOpSettings;
......@@ -47,9 +48,10 @@ private:
const KisFilterOpSettings * settings;
KisPaintDeviceSP m_tmpDevice;
KisPressureSizeOption m_sizeOption;
KisPressureRotationOption m_rotationOption;
KisFilterSP m_filter;
KisFilterConfiguration* m_filterConfiguration;
bool m_ignoreAlpha;
bool m_smudgeMode;
};
#endif // KIS_FILTEROP_H_
......@@ -31,6 +31,7 @@
#include <kis_paintop_options_widget.h>
#include <kis_pressure_size_option.h>
#include <kis_pressure_opacity_option.h>
#include <kis_pressure_rotation_option.h>
#include <kis_curve_option_widget.h>
#include <kis_compositeop_option.h>
#include <kis_filter_option.h>
......@@ -39,13 +40,15 @@ KisFilterOpSettingsWidget::KisFilterOpSettingsWidget(QWidget* parent)
: KisBrushBasedPaintopOptionWidget(parent)
{
setObjectName("filter option widget");
setPrecisionEnabled(true);
m_filterOption = new KisFilterOption();
addPaintOpOption(new KisCompositeOpOption(true));
addPaintOpOption(new KisCurveOptionWidget(new KisPressureSizeOption()));
addPaintOpOption(new KisCurveOptionWidget(new KisPressureOpacityOption()));
addPaintOpOption(m_filterOption);
addPaintOpOption(new KisCurveOptionWidget(new KisPressureSizeOption()));
addPaintOpOption(new KisCurveOptionWidget(new KisPressureRotationOption()));
m_filterOption = new KisFilterOption();
addPaintOpOption(m_filterOption);
}
KisFilterOpSettingsWidget::~KisFilterOpSettingsWidget()
......
......@@ -38,9 +38,9 @@
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxIgnoreAlpha">
<widget class="QCheckBox" name="checkBoxSmudgeMode">
<property name="text">
<string>Ignore Alpha</string>
<string>Smudge Mode</string>
</property>
</widget>
</item>
......
......@@ -75,7 +75,7 @@ KisFilterOption::KisFilterOption()
setCurrentFilter(l2.first());
}
connect(m_options->checkBoxSmudgeMode, SIGNAL(stateChanged(int)), this, SIGNAL(sigSettingChanged()));
}
const KisFilterSP KisFilterOption::filter() const
......@@ -89,13 +89,11 @@ KisFilterConfiguration* KisFilterOption::filterConfig() const
return static_cast<KisFilterConfiguration*>(m_currentFilterConfigWidget->configuration());
}
bool KisFilterOption::ignoreAlpha() const
bool KisFilterOption::smudgeMode() const
{
return m_options->checkBoxIgnoreAlpha->isChecked();
return m_options->checkBoxSmudgeMode->isChecked();
}
void KisFilterOption::setNode(KisNodeSP node)
{
if (node && node->paintDevice()) {
......@@ -171,7 +169,7 @@ void KisFilterOption::writeOptionSetting(KisPropertiesConfiguration* setting) co
if (!m_currentFilter) return;
setting->setProperty(FILTER_ID, m_currentFilter->id());
setting->setProperty(FILTER_IGNORE_ALPHA, ignoreAlpha());
setting->setProperty(FILTER_SMUDGE_MODE, smudgeMode());
if(filterConfig()) {
setting->setProperty(FILTER_CONFIGURATION, filterConfig()->toXML());
}
......@@ -181,7 +179,7 @@ void KisFilterOption::readOptionSetting(const KisPropertiesConfiguration* settin
{
KoID id(setting->getString(FILTER_ID), "");
setCurrentFilter(id);
m_options->checkBoxIgnoreAlpha->setChecked(setting->getBool(FILTER_IGNORE_ALPHA));
m_options->checkBoxSmudgeMode->setChecked(setting->getBool(FILTER_SMUDGE_MODE));
KisFilterConfiguration* configuration = filterConfig();
if(configuration) {
configuration->fromXML(setting->getString(FILTER_CONFIGURATION));
......
......@@ -31,7 +31,7 @@ class KisFilterConfiguration;
class KisFilterOptionWidget;
const QString FILTER_ID = "Filter/id";
const QString FILTER_IGNORE_ALPHA = "Filter/ignoreAlpha";
const QString FILTER_SMUDGE_MODE = "Filter/smudgeMode";
const QString FILTER_CONFIGURATION = "Filter/configuration";
/**
......@@ -57,10 +57,7 @@ public:
*/
KisFilterConfiguration* filterConfig() const;
/**
* XXX
*/
bool ignoreAlpha() const;
bool smudgeMode() const;
/**
* XXX
......
......@@ -362,12 +362,14 @@ void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP pr
m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createSettingsWidget(this);
m_optionWidget = m_paintopOptionWidgets[paintop];
m_optionWidget->setImage(m_view->image());
m_optionWidget->setConfiguration(preset->settings());
// the node should be initialized before the configuration (see KisFilterOp)
preset->settings()->setOptionsWidget(m_optionWidget);
preset->settings()->setNode(m_resourceProvider->currentNode());
m_optionWidget->setImage(m_view->image());
m_optionWidget->setConfiguration(preset->settings());
m_presetsPopup->setPaintOpSettingsWidget(m_optionWidget);
m_presetsChooserPopup->setPresetFilter(paintop);
......
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