[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-kimageshop
Subject: Patch: Smudge Brush fixes
From: Silvio Heinrich <plassy () web ! de>
Date: 2011-01-04 0:20:34
Message-ID: 4D2267D2.6010303 () web ! de
[Download RAW message or body]
Now it should work pretty similar to the smudge tool in gimp.
But I still need to do some tweaks to how the rate values (color and
smudge rates) are used.
It only smudges/paints correctly in a certain region of the rates.
But the transparency issues should be solved by now, so no black color
should be introduced anymore (hopefully :P).
["SmudgeBrush.patch" (text/x-diff)]
From db2c5f5cc5aee64ff8af4c6470fe879e09981a18 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich <plassy@web.de>
Date: Fri, 31 Dec 2010 00:23:07 +0100
Subject: [PATCH 1/6] Fixed (reprogrammed) smudge brush
Reprogrammed the smudge brush with a simpler algorithm.
An option to mix color into the smudge process is also introduced.
---
.../defaultpaintops/smudge/kis_smudgeop.cpp | 107 ++++++++++++++++----
.../paintops/defaultpaintops/smudge/kis_smudgeop.h | 3 +-
.../smudge/kis_smudgeop_settings_widget.cpp | 10 +-
krita/plugins/paintops/libpaintop/CMakeLists.txt | 2 +
.../libpaintop/kis_pressure_composite_option.cpp | 76 ++++++++++++++
.../libpaintop/kis_pressure_composite_option.h | 58 +++++++++++
.../kis_pressure_composite_option_widget.cpp | 104 +++++++++++++++++++
.../kis_pressure_composite_option_widget.h | 46 +++++++++
8 files changed, 380 insertions(+), 26 deletions(-)
create mode 100644 krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
create mode 100644 \
krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h create mode 100644 \
krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp create \
mode 100644 krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp index \
ee7927f..c8dde6d 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
@@ -58,11 +58,11 @@ KisSmudgeOp::KisSmudgeOp(const KisBrushBasedPaintOpSettings \
*settings, KisPainte Q_ASSERT(settings);
Q_ASSERT(painter);
m_sizeOption.readOptionSetting(settings);
- m_opacityOption.readOptionSetting(settings);
m_rateOption.readOptionSetting(settings);
+ m_compositeOption.readOptionSetting(settings);
m_sizeOption.sensor()->reset();
- m_opacityOption.sensor()->reset();
m_rateOption.sensor()->reset();
+ m_compositeOption.sensor()->reset();
m_tempDev = new KisPaintDevice(painter->device()->colorSpace());
@@ -76,9 +76,77 @@ KisSmudgeOp::~KisSmudgeOp()
{
}
-/* To smudge, one does the following:
- 1.- First step: initialize a temporary paint device (m_tempDev) with a copy of the \
colors below the mouse pointer. +
+qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
+{
+ // Simple error catching
+ if (!painter()->device())
+ return 1.0;
+
+ KisBrushSP brush = m_brush;
+
+ if(!brush || !brush->canPaintFor(info))
+ return 1.0;
+
+ double scale = m_sizeOption.apply(info);
+
+ if((scale*brush->width()) <= 0.01 || (scale*brush->height()) <= 0.01)
+ return 1.0;
+
+ setCurrentScale(scale);
+
+ QPointF point = info.pos() - brush->hotSpot(scale, scale);
+
+ qint32 x, y;
+ qreal xFraction, yFraction;
+ splitCoordinate(point.x(), &x, &xFraction);
+ splitCoordinate(point.y(), &y, &yFraction);
+
+ KisFixedPaintDeviceSP maskDab = cachedDab(painter()->device()->colorSpace());
+
+ // Extract the brush mask (maskDab) from brush, and turn it into a transparency \
mask (alpha8). + if(brush->brushType() == IMAGE || brush->brushType() == \
PIPE_IMAGE) { + // This is for bitmap brushes
+ maskDab = brush->paintDevice(painter()->device()->colorSpace(), scale, 0.0, \
info, xFraction, yFraction); + } else {
+ // This is for parametric brushes, those created in the Autobrush popup \
config dialogue + maskDab = cachedDab();
+ brush->mask(maskDab, painter()->paintColor(), scale, scale, 0.0, info, \
xFraction, yFraction); + }
+
+ maskDab->convertTo(KoColorSpaceRegistry::instance()->alpha8());
+
+ KisPainter copyPainter(m_tempDev);
+
+ if(m_compositeOption.isChecked()) {
+ m_compositeOption.apply(©Painter, OPACITY_OPAQUE_U8, info);
+
+ copyPainter.setFillStyle(KisPainter::FillStyleForegroundColor);
+ copyPainter.setPaintColor(painter()->paintColor());
+ copyPainter.paintRect(maskDab->bounds());
+ }
+
+ quint8 newOpacity = m_rateOption.apply(OPACITY_OPAQUE_U8, info);
+
+ painter()->setOpacity(newOpacity);
+ painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, \
maskDab->bounds().width(), maskDab->bounds().height()); + \
//painter()->bitBlt(QPoint(x,y), m_tempDev, dab->bounds()); +
+ m_tempDev->clear(maskDab->bounds());
+
+ copyPainter.setCompositeOp(COMPOSITE_OVER);
+ copyPainter.setOpacity(OPACITY_OPAQUE_U8);
+ copyPainter.bitBlt(0, 0, painter()->device(), x, y, maskDab->bounds().width(), \
maskDab->bounds().height()); + copyPainter.end();
+
+ return spacing(scale);
+}
+
+
+/* To smudge, one does the following:
+ *
+ 1 *.- First step: initialize a temporary paint device (m_tempDev) with a copy of \
the colors below the mouse pointer. All other times:
2.- Vanishing step: Reduce the transparency of the temporary paint device so as to \
let it mix gradually. 3.- Combine: Combine the temporary device with the piece the \
brush currently is 'painting', according to a ratio: @@ -93,8 +161,7 @@ \
KisSmudgeOp::~KisSmudgeOp() temporary device is cached such that only the colored \
areas are considered. TODO: Make this cached value dump colors that have faded \
nearly completely and lie outside of the rectangle (dab) of the current iteration.
-*/
-
+ *
qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
{
KisBrushSP brush = m_brush;
@@ -109,14 +176,14 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
if ((scale * brush->width()) <= 0.01 || (scale * brush->height()) <= 0.01) \
return 1.0; setCurrentScale(scale);
- /* Align a point that represents the top-left corner of the \
brush-stroke-rendering
- with the mouse pointer and take into account the brush mask size */
+ // Align a point that represents the top-left corner of the \
brush-stroke-rendering + // with the mouse pointer and take into account the brush \
mask size QPointF hotSpot = brush->hotSpot(scale, scale);
QPointF pt = info.pos() - hotSpot;
- /* Split the coordinates into integer plus fractional parts. The integer
- is where the dab will be positioned and the fractional part determines
- the sub-pixel positioning. */
+ // Split the coordinates into integer plus fractional parts. The integer
+ //is where the dab will be positioned and the fractional part determines
+ // the sub-pixel positioning.
qint32 x, y;
qreal xFraction, yFraction;
@@ -141,17 +208,17 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
qint32 sw = maskDab->bounds().width();
qint32 sh = maskDab->bounds().height();
- /* Prepare the top left corner of the temporary paint device where the extracted \
color will be drawn */ + // Prepare the top left corner of the temporary paint \
device where the extracted color will be drawn QPoint extractionTopLeft = \
QPoint(ANCHOR_POINT.x() - sw / 2, ANCHOR_POINT.y() - sh / 2);
- /* In the block below, the opacity of the colors stored in m_tempDev
- is reduced in opacity. Nothing of the color present inside it is left out */
+ // In the block below, the opacity of the colors stored in m_tempDev
+ // is reduced in opacity. Nothing of the color present inside it is left out
quint8 opacity = OPACITY_OPAQUE_U8;
if (!m_firstRun) {
opacity = m_rateOption.apply(opacity, info);
- /* Without those limits, the smudge brush doesn't smudge anymore, it either \
makes a single
- dropplet of color, or drags a frame indefinitely over the canvas. */
+ // Without those limits, the smudge brush doesn't smudge anymore, it either \
makes a single + // dropplet of color, or drags a frame indefinitely over the \
canvas.
opacity = qBound(MIXABLE_LOWER_LIMIT, opacity, MIXABLE_UPPER_LIMIT);
// Invert the opacity value for color absorption in the next lines \
(copyPainter) @@ -162,9 +229,9 @@ qreal KisSmudgeOp::paintAt(const \
KisPaintInformation& info) m_firstRun = false;
m_wholeTempData = QRect(extractionTopLeft, maskDab->bounds().size());
}
- /* copyPainter will extract the piece of color (image) to be duplicated to \
generate the smudge effect,
- it extracts a simple unmasked rectangle and adds it to what was extracted before \
in this same block of code,
- this sometimes shows artifacts when the brush is used with stylus and high \
spacing */ + // copyPainter will extract the piece of color (image) to be \
duplicated to generate the smudge effect, + // it extracts a simple unmasked \
rectangle and adds it to what was extracted before in this same block of code, + \
// this sometimes shows artifacts when the brush is used with stylus and high spacing \
KisPainter copyPainter(m_tempDev); copyPainter.setCompositeOp(COMPOSITE_COPY);
copyPainter.setOpacity(opacity);
@@ -179,4 +246,4 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
renderMirrorMask(QRect(QPoint(x,y),QSize(sw,sh)),m_tempDev,extractionTopLeft.x(), \
extractionTopLeft.y(),maskDab);
return spacing(scale);
-}
+}//*/
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h index 6e3e63f..35a5b64 \
100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
@@ -31,6 +31,7 @@
#include <kis_pressure_opacity_option.h>
#include <kis_pressure_size_option.h>
#include <kis_pressure_rate_option.h>
+#include <kis_pressure_composite_option.h>
class KisBrushBasedPaintOpSettings;
@@ -56,8 +57,8 @@ private:
KoColor m_color;
KisPressureSizeOption m_sizeOption;
- KisPressureOpacityOption m_opacityOption;
KisPressureRateOption m_rateOption;
+ KisPressureCompositeOption m_compositeOption;
};
#endif // KIS_SMUDGEOP_H_
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp \
index 07a70ca..3f01533 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp
@@ -24,12 +24,13 @@
#include "kis_brush_based_paintop_settings.h"
#include <kis_properties_configuration.h>
#include <kis_paintop_options_widget.h>
-#include <kis_pressure_darken_option.h>
-#include <kis_pressure_opacity_option.h>
#include <kis_pressure_size_option.h>
+#include <kis_pressure_composite_option.h>
#include <kis_pressure_rate_option.h>
#include <kis_curve_option_widget.h>
#include <kis_pressure_rate_option_widget.h>
+#include <kis_pressure_composite_option_widget.h>
+
KisSmudgeOpSettingsWidget::KisSmudgeOpSettingsWidget(QWidget* parent)
: KisBrushBasedPaintopOptionWidget(parent)
@@ -37,9 +38,8 @@ KisSmudgeOpSettingsWidget::KisSmudgeOpSettingsWidget(QWidget* \
parent) setObjectName("brush option widget");
addPaintOpOption(new KisCurveOptionWidget(new KisPressureSizeOption()));
- addPaintOpOption(new KisCurveOptionWidget(new KisPressureOpacityOption()));
- addPaintOpOption(new KisCurveOptionWidget(new KisPressureDarkenOption));
addPaintOpOption(new KisPressureRateOptionWidget());
+ addPaintOpOption(new KisPressureCompositeOptionWidget());
}
@@ -51,7 +51,7 @@ KisPropertiesConfiguration* \
KisSmudgeOpSettingsWidget::configuration() const {
KisBrushBasedPaintOpSettings *config = new KisBrushBasedPaintOpSettings();
config->setOptionsWidget(const_cast<KisSmudgeOpSettingsWidget*>(this));
- config->setProperty("paintop", "smudge"); // XXX: make this a const id string
+ config->setProperty("paintop", "smudge"); // TODO: make this a const id string
writeConfiguration(config);
return config;
}
diff --git a/krita/plugins/paintops/libpaintop/CMakeLists.txt \
b/krita/plugins/paintops/libpaintop/CMakeLists.txt index 996cafc..b0bc55d 100644
--- a/krita/plugins/paintops/libpaintop/CMakeLists.txt
+++ b/krita/plugins/paintops/libpaintop/CMakeLists.txt
@@ -38,6 +38,8 @@ set(kritalibpaintop_LIB_SRCS
kis_pressure_size_option.cpp
kis_pressure_softness_option.cpp
kis_pressure_mix_option.cpp
+ kis_pressure_composite_option.cpp
+ kis_pressure_composite_option_widget.cpp
kis_sensor_selector.cc
kis_text_brush_chooser.cpp
kis_brush_based_paintop_options_widget.cpp
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp new file mode \
100644 index 0000000..18a9882
--- /dev/null
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project
+ * Copyright (C) Boudewijn Rempt <boud@valdyas.org>, (C) 2008
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_pressure_composite_option.h"
+
+
+#include <klocale.h>
+
+#include <kis_painter.h>
+#include <widgets/kis_curve_widget.h>
+
+#include <KoColor.h>
+#include <KoColorSpace.h>
+#include <KoCompositeOp.h>
+
+KisPressureCompositeOption::KisPressureCompositeOption()
+ : KisCurveOption(i18n("Color"), "Color", KisPaintOpOption::brushCategory(), \
false) +{
+ setMinimumLabel(i18n("Full Color"));
+ setMaximumLabel(i18n("No Color"));
+}
+
+void KisPressureCompositeOption::writeOptionSetting(KisPropertiesConfiguration* \
setting) const +{
+ KisCurveOption::writeOptionSetting(setting);
+ setting->setProperty("CompositeOp", m_compositeOp);
+ setting->setProperty("CompositeRateValue", m_rate);
+}
+
+void KisPressureCompositeOption::readOptionSetting(const KisPropertiesConfiguration* \
setting) +{
+ KisCurveOption::readOptionSetting(setting);
+ m_compositeOp = setting->getString("CompositeOp");
+ m_rate = setting->getInt("CompositeRateValue");
+
+ if(m_compositeOp == "") //TODO: test if compositeOp is valid instead of just \
testing for an empty string + m_compositeOp = COMPOSITE_OVER;
+}
+
+QString KisPressureCompositeOption::apply(KisPainter* painter, qint8 opacity, const \
KisPaintInformation& info) const +{
+ if(!isChecked())
+ return painter->compositeOp()->id();
+
+ QString oldCompositeOp = painter->compositeOp()->id();
+
+ opacity = (m_rate * 255) / 100;
+ opacity = qBound((qint32)OPACITY_TRANSPARENT_U8,
+ (qint32)(double(opacity) * computeValue(info) / \
PRESSURE_DEFAULT), + (qint32)OPACITY_OPAQUE_U8);
+
+ //qreal opacity1 = (qreal)(painter->opacity() * computeValue(info));
+ //quint8 opacity2 = (quint8)qRound(qBound<qreal>(OPACITY_TRANSPARENT_U8, \
opacity1, OPACITY_OPAQUE_U8)); +
+ painter->setCompositeOp(m_compositeOp);
+ painter->setOpacity(opacity);
+
+ return oldCompositeOp;
+}
+
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h new file mode \
100644 index 0000000..f05642a
--- /dev/null
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ * Copyright (C) Boudewijn Rempt <boud@valdyas.org>, (C) 2008
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KIS_PRESSURE_COMPOSITE_OPTION_H
+#define KIS_PRESSURE_COMPOSITE_OPTION_H
+
+#include "kis_curve_option.h"
+#include <kis_paint_information.h>
+#include <krita_export.h>
+#include <kis_types.h>
+
+class QSlider;
+class KisPropertiesConfiguration;
+class KisPainter;
+
+class PAINTOP_EXPORT KisPressureCompositeOption : public KisCurveOption
+{
+public:
+ KisPressureCompositeOption();
+
+ /**
+ * Set the composite mode and opacity of the painter based on the pressure
+ * and the curve (if checked) and return the old composite mode
+ * of the painter.
+ */
+ QString apply(KisPainter* painter, qint8 opacity, const KisPaintInformation& \
info) const; +
+ void writeOptionSetting(KisPropertiesConfiguration* setting) const;
+ void readOptionSetting(const KisPropertiesConfiguration* setting);
+
+ void setCompositeOp(const QString& compositeOp) { m_compositeOp = compositeOp; }
+ QString getCompositeOp() { return m_compositeOp; }
+
+ void setRate(int rate) { m_rate = rate; }
+ int getRate() { return m_rate; }
+
+private:
+ QString m_compositeOp;
+ int m_rate;
+};
+
+#endif // KIS_PRESSURE_COMPOSITE_OPTION_H
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp new file \
mode 100644 index 0000000..140c628
--- /dev/null
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp
@@ -0,0 +1,104 @@
+/* This file is part of the KDE project
+ * Copyright (C) Boudewijn Rempt <boud@valdyas.org>, (C) 2008
+ * Copyright (C) Sven Langkamp <sven.langkamp@gmail.com>, (C) 2009
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_pressure_composite_option_widget.h"
+#include "kis_pressure_composite_option.h"
+
+#include <KoCompositeOp.h>
+
+#include <QWidget>
+#include <QCheckBox>
+#include <QLabel>
+#include <QComboBox>
+#include <QSlider>
+#include <QVBoxLayout>
+#include <QGridLayout>
+
+#include <klocale.h>
+
+KisPressureCompositeOptionWidget::KisPressureCompositeOptionWidget()
+ : KisCurveOptionWidget(new KisPressureCompositeOption())
+{
+ QWidget* widget = new QWidget;
+ QLabel* modeLabel = new QLabel(i18n("Mode: "));
+ QLabel* rateLabel = new QLabel(i18n("Rate: "));
+
+ m_compositeOpBox = new QComboBox();
+ m_compositeOpBox->addItem(COMPOSITE_OVER);
+ m_compositeOpBox->addItem(COMPOSITE_OVERLAY);
+ m_compositeOpBox->addItem(COMPOSITE_SCREEN);
+ m_compositeOpBox->addItem(COMPOSITE_ADD);
+ m_compositeOpBox->addItem(COMPOSITE_SUBTRACT);
+
+ m_rateSlider = new QSlider();
+ m_rateSlider->setMinimum(0);
+ m_rateSlider->setMaximum(100);
+ m_rateSlider->setPageStep(1);
+ m_rateSlider->setValue(90);
+ m_rateSlider->setOrientation(Qt::Horizontal);
+
+ connect(m_compositeOpBox, SIGNAL(activated(QString)), this, \
SLOT(compositeOpChanged(QString))); + connect(m_rateSlider, \
SIGNAL(valueChanged(int)), this, SLOT(rateChanged(int))); +
+ QGridLayout* gridLayout = new QGridLayout();
+ gridLayout->addWidget(modeLabel, 0, 0);
+ gridLayout->addWidget(m_compositeOpBox, 0, 1);
+ gridLayout->addWidget(rateLabel, 1, 0);
+ gridLayout->addWidget(m_rateSlider, 1, 1);
+
+ QVBoxLayout* vBoxLayout = new QVBoxLayout;
+ vBoxLayout->addLayout(gridLayout);
+ vBoxLayout->addWidget(curveWidget());
+
+ widget->setLayout(vBoxLayout);
+
+ setConfigurationPage(widget);
+
+ compositeOpChanged(COMPOSITE_OVER);
+ rateChanged(m_rateSlider->value());
+}
+
+void KisPressureCompositeOptionWidget::readOptionSetting(const \
KisPropertiesConfiguration* setting) +{
+ KisCurveOptionWidget::readOptionSetting(setting);
+
+ QString compositeOp = \
static_cast<KisPressureCompositeOption*>(curveOption())->getCompositeOp(); +
+ for(int i=0; i<m_compositeOpBox->count(); ++i) {
+ if(m_compositeOpBox->itemText(i) == compositeOp) {
+ m_compositeOpBox->setCurrentIndex(i);
+ break;
+ }
+ }
+
+ m_rateSlider->setValue(static_cast<KisPressureCompositeOption*>(curveOption())->getRate());
+}
+
+void KisPressureCompositeOptionWidget::compositeOpChanged(const QString& \
compositeOp) +{
+ static_cast<KisPressureCompositeOption*>(curveOption())->setCompositeOp(compositeOp);
+ emit sigSettingChanged();
+}
+
+void KisPressureCompositeOptionWidget::rateChanged(int rate)
+{
+ static_cast<KisPressureCompositeOption*>(curveOption())->setRate(rate);
+ emit sigSettingChanged();
+}
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h new file \
mode 100644 index 0000000..6660f72
--- /dev/null
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h
@@ -0,0 +1,46 @@
+/* This file is part of the KDE project
+ * Copyright (C) Sven Langkamp <sven.langkamp@gmail.com>, (C) 2009
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KIS_PRESSURE_COMPOSITE_OPTION_WIDGET_H
+#define KIS_PRESSURE_COMPOSITE_OPTION_WIDGET_H
+
+#include "kis_curve_option_widget.h"
+
+class QComboBox;
+class QSlider;
+
+class PAINTOP_EXPORT KisPressureCompositeOptionWidget : public KisCurveOptionWidget
+{
+ Q_OBJECT
+
+public:
+ KisPressureCompositeOptionWidget();
+
+ void readOptionSetting(const KisPropertiesConfiguration* setting);
+
+private slots:
+ void compositeOpChanged(const QString& compositeOp);
+ void rateChanged(int rate);
+
+private:
+ QComboBox* m_compositeOpBox;
+ QSlider* m_rateSlider;
+};
+
+#endif // KIS_PRESSURE_COMPOSITE_OPTION_WIDGET_H
--
1.7.1
From 11e99bf63e2cff5667b3a2314eaa7e724ac8de37 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich <plassy@web.de>
Date: Fri, 31 Dec 2010 21:28:09 +0100
Subject: [PATCH 2/6] Some cleanup and documentation and added more composite modes to \
KisPressureCompositeOptionWidget.
---
.../defaultpaintops/smudge/kis_smudgeop.cpp | 163 ++++----------------
.../paintops/defaultpaintops/smudge/kis_smudgeop.h | 8 +-
.../libpaintop/kis_pressure_composite_option.cpp | 7 +-
.../libpaintop/kis_pressure_composite_option.h | 7 +-
.../kis_pressure_composite_option_widget.cpp | 6 +
5 files changed, 42 insertions(+), 149 deletions(-)
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp index \
c8dde6d..372a1b7 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
@@ -40,19 +40,8 @@
#include <kis_selection.h>
#include <kis_brush_based_paintop_settings.h>
-
-// Both limits defined to be 15 units away from the min (0) or max (255) to allow \
actual mixing of colors
-const quint8 MIXABLE_UPPER_LIMIT = 240;
-const quint8 MIXABLE_LOWER_LIMIT = 15;
-
-// All pieces of color extracted from the canvas will be centered around \
ANCHOR_POINT
-const QPoint ANCHOR_POINT = QPoint(0, 0);
-
-
KisSmudgeOp::KisSmudgeOp(const KisBrushBasedPaintOpSettings *settings, KisPainter \
*painter, KisImageWSP image)
- : KisBrushBasedPaintOp(settings, painter)
- , m_firstRun(true)
- , m_tempDev(0)
+ : KisBrushBasedPaintOp(settings, painter), m_tempDev(0)
{
Q_UNUSED(image);
Q_ASSERT(settings);
@@ -65,11 +54,6 @@ KisSmudgeOp::KisSmudgeOp(const KisBrushBasedPaintOpSettings \
*settings, KisPainte m_compositeOption.sensor()->reset();
m_tempDev = new KisPaintDevice(painter->device()->colorSpace());
-
- // Initializing to a valid value to avoid weird errors during modifications
- m_wholeTempData = QRect(0, 0, 0, 0);
-
- m_color = painter->paintColor();
}
KisSmudgeOp::~KisSmudgeOp()
@@ -89,8 +73,10 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
if(!brush || !brush->canPaintFor(info))
return 1.0;
+ // get the scaling factor calculated by the size option
double scale = m_sizeOption.apply(info);
+ // don't paint anything if the brush is too samll
if((scale*brush->width()) <= 0.01 || (scale*brush->height()) <= 0.01)
return 1.0;
@@ -105,7 +91,7 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
KisFixedPaintDeviceSP maskDab = cachedDab(painter()->device()->colorSpace());
- // Extract the brush mask (maskDab) from brush, and turn it into a transparency \
mask (alpha8). + // Extract the brush mask (maskDab) from brush with the correct \
scaled size if(brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
// This is for bitmap brushes
maskDab = brush->paintDevice(painter()->device()->colorSpace(), scale, 0.0, \
info, xFraction, yFraction); @@ -115,135 +101,46 @@ qreal KisSmudgeOp::paintAt(const \
KisPaintInformation& info)
brush->mask(maskDab, painter()->paintColor(), scale, scale, 0.0, info, \
xFraction, yFraction); }
+ // transforms the fixed paint device with the current brush to alpha color space \
(to use it as alpha/transparency mask) \
maskDab->convertTo(KoColorSpaceRegistry::instance()->alpha8());
- KisPainter copyPainter(m_tempDev);
-
- if(m_compositeOption.isChecked()) {
- m_compositeOption.apply(©Painter, OPACITY_OPAQUE_U8, info);
-
- copyPainter.setFillStyle(KisPainter::FillStyleForegroundColor);
- copyPainter.setPaintColor(painter()->paintColor());
- copyPainter.paintRect(maskDab->bounds());
- }
-
+ // GET the opacy calculated by the rate option (apply is misleading because the \
opacy will not be applied) quint8 newOpacity = m_rateOption.apply(OPACITY_OPAQUE_U8, \
info);
+ // set opacity calculated by the rate option
+ // then blit the temporary painting device on the canvas at the current brush \
position + // the alpha mask (maskDab) will be used here to only blit the pixels \
that lie in the area (shape) of the brush painter()->setOpacity(newOpacity);
painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, \
maskDab->bounds().width(), maskDab->bounds().height());
- //painter()->bitBlt(QPoint(x,y), m_tempDev, dab->bounds());
+ // IMPORTANT: clear the temporary painting device to color black with zero \
opacity + // it will only clear the extents of the brush
m_tempDev->clear(maskDab->bounds());
+ KisPainter copyPainter(m_tempDev);
+
+ // reset composite mode and opacity
+ // then cut out the area from the canvas under the brush
+ // and blit it to the temporary painting device
copyPainter.setCompositeOp(COMPOSITE_OVER);
copyPainter.setOpacity(OPACITY_OPAQUE_U8);
copyPainter.bitBlt(0, 0, painter()->device(), x, y, maskDab->bounds().width(), \
maskDab->bounds().height());
- copyPainter.end();
-
- return spacing(scale);
-}
-
-
-/* To smudge, one does the following:
- *
- 1 *.- First step: initialize a temporary paint device (m_tempDev) with a copy of \
the colors below the mouse pointer.
- All other times:
- 2.- Vanishing step: Reduce the transparency of the temporary paint device so as to \
let it mix gradually.
- 3.- Combine: Combine the temporary device with the piece the brush currently is \
'painting', according to a ratio:
- in this case, opacity. (This is what in the first step does the copying of the \
data).
- 4.- Blit to screen: This combination is then composited upon the actual image.
- 5.- Special case: If the size of the dab (brush mask) changes during the stroke \
(for example, when
- using a stylus sensitive to pressure), align the colors extracted to the center of \
the previously absorbed colors,
- and in the vanishing step, ensure that all the colors have their opacity slowly \
reduced, not just the ones below
- the current brush mask.
-
- For the sake of speed optimization, the extent of the largest area of color \
contained in the
- temporary device is cached such that only the colored areas are considered.
- TODO: Make this cached value dump colors that have faded nearly completely and lie \
outside of the rectangle (dab)
- of the current iteration.
- *
-qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
-{
- KisBrushSP brush = m_brush;
- // Simple error catching
- if (!painter()->device()) return 1.0;
- if (!brush) return 1.0;
- if (!brush->canPaintFor(info)) return 1.0;
-
- // Grow the brush (this includes the mask) according to pressure or other \
parameters
- double scale = m_sizeOption.apply(info);
- if ((scale * brush->width()) <= 0.01 || (scale * brush->height()) <= 0.01) \
return 1.0;
- setCurrentScale(scale);
-
- // Align a point that represents the top-left corner of the \
brush-stroke-rendering
- // with the mouse pointer and take into account the brush mask size
- QPointF hotSpot = brush->hotSpot(scale, scale);
- QPointF pt = info.pos() - hotSpot;
-
- // Split the coordinates into integer plus fractional parts. The integer
- //is where the dab will be positioned and the fractional part determines
- // the sub-pixel positioning.
- qint32 x, y;
- qreal xFraction, yFraction;
-
- splitCoordinate(pt.x(), &x, &xFraction);
- splitCoordinate(pt.y(), &y, &yFraction);
-
- KisFixedPaintDeviceSP maskDab = 0;
-
- // Extract the brush mask (maskDab) from brush, and turn it into a transparency \
mask (alpha8).
- if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
- // This is for bitmap brushes
- maskDab = brush->paintDevice(painter()->device()->colorSpace(), scale, 0.0, \
info, xFraction, yFraction);
- maskDab->convertTo(KoColorSpaceRegistry::instance()->alpha8());
- } else {
- // This is for parametric brushes, those created in the Autobrush popup \
config dialogue
- maskDab = cachedDab();
- brush->mask(maskDab, m_color, scale, scale, 0.0, info, xFraction, \
yFraction);
- maskDab->convertTo(KoColorSpaceRegistry::instance()->alpha8());
- }
-
- // Convenient renaming for the limits of the maskDab
- qint32 sw = maskDab->bounds().width();
- qint32 sh = maskDab->bounds().height();
-
- // Prepare the top left corner of the temporary paint device where the extracted \
color will be drawn
- QPoint extractionTopLeft = QPoint(ANCHOR_POINT.x() - sw / 2,
- ANCHOR_POINT.y() - sh / 2);
-
- // In the block below, the opacity of the colors stored in m_tempDev
- // is reduced in opacity. Nothing of the color present inside it is left out
- quint8 opacity = OPACITY_OPAQUE_U8;
- if (!m_firstRun) {
- opacity = m_rateOption.apply(opacity, info);
- // Without those limits, the smudge brush doesn't smudge anymore, it either \
makes a single
- // dropplet of color, or drags a frame indefinitely over the canvas.
- opacity = qBound(MIXABLE_LOWER_LIMIT, opacity, MIXABLE_UPPER_LIMIT);
-
- // Invert the opacity value for color absorption in the next lines \
(copyPainter)
- opacity = OPACITY_OPAQUE_U8 - opacity;
- m_wholeTempData |= QRect(extractionTopLeft, maskDab->bounds().size());
- }
- else {
- m_firstRun = false;
- m_wholeTempData = QRect(extractionTopLeft, maskDab->bounds().size());
+ // if the user selected the color smudge option
+ // we will mix some color into the temorary painting device (m_tempDev)
+ if(m_compositeOption.isChecked()) {
+ // this will apply the composite mode and the opacy (selected by the user)
+ // to copyPainter
+ m_compositeOption.apply(©Painter, OPACITY_OPAQUE_U8, info);
+
+ // paint a rectangle with the current color (foreground color)
+ // into the temporary painting device
+ copyPainter.setFillStyle(KisPainter::FillStyleForegroundColor);
+ copyPainter.setPaintColor(painter()->paintColor());
+ copyPainter.paintRect(maskDab->bounds());
}
- // copyPainter will extract the piece of color (image) to be duplicated to \
generate the smudge effect,
- // it extracts a simple unmasked rectangle and adds it to what was extracted \
before in this same block of code,
- // this sometimes shows artifacts when the brush is used with stylus and high \
spacing
- KisPainter copyPainter(m_tempDev);
- copyPainter.setCompositeOp(COMPOSITE_COPY);
- copyPainter.setOpacity(opacity);
- copyPainter.bitBlt(m_wholeTempData.x(), m_wholeTempData.y(), \
painter()->device(),
- x - m_wholeTempData.x() + extractionTopLeft.x(),
- y - m_wholeTempData.y() + extractionTopLeft.y(),
- m_wholeTempData.width(), m_wholeTempData.height());
- copyPainter.end();
- // This is the line that renders the extracted colors to the screen, with \
maskDab giving it the brush shape
- painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, 0, 0, \
extractionTopLeft.x(), extractionTopLeft.y(), sw, sh);
- renderMirrorMask(QRect(QPoint(x,y),QSize(sw,sh)),m_tempDev,extractionTopLeft.x(), \
extractionTopLeft.y(),maskDab); + copyPainter.end();
return spacing(scale);
-}//*/
+}
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h index 35a5b64..5948e04 \
100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
@@ -49,13 +49,7 @@ public:
qreal paintAt(const KisPaintInformation& info);
private:
- bool m_firstRun;
- // The "temporary paint device"
- KisPaintDeviceSP m_tempDev;
- // The size of the rectangle encompassing the whole data in the temporary device \
needs to be cached for speed
- QRect m_wholeTempData;
- KoColor m_color;
-
+ KisPaintDeviceSP m_tempDev; // The temporary paint device
KisPressureSizeOption m_sizeOption;
KisPressureRateOption m_rateOption;
KisPressureCompositeOption m_compositeOption;
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp index \
18a9882..ca09eb6 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
@@ -30,7 +30,7 @@
#include <KoCompositeOp.h>
KisPressureCompositeOption::KisPressureCompositeOption()
- : KisCurveOption(i18n("Color"), "Color", KisPaintOpOption::brushCategory(), \
false) + : KisCurveOption(i18n("Color"), "Color", \
KisPaintOpOption::brushCategory(), false) {
setMinimumLabel(i18n("Full Color"));
setMaximumLabel(i18n("No Color"));
@@ -53,7 +53,7 @@ void KisPressureCompositeOption::readOptionSetting(const \
KisPropertiesConfigurat m_compositeOp = COMPOSITE_OVER;
}
-QString KisPressureCompositeOption::apply(KisPainter* painter, qint8 opacity, const \
KisPaintInformation& info) const +void KisPressureCompositeOption::apply(KisPainter* \
painter, qint8 opacity, const KisPaintInformation& info) const {
if(!isChecked())
return painter->compositeOp()->id();
@@ -65,9 +65,6 @@ QString KisPressureCompositeOption::apply(KisPainter* painter, \
qint8 opacity, co
(qint32)(double(opacity) * computeValue(info) / \
PRESSURE_DEFAULT), (qint32)OPACITY_OPAQUE_U8);
- //qreal opacity1 = (qreal)(painter->opacity() * computeValue(info));
- //quint8 opacity2 = (quint8)qRound(qBound<qreal>(OPACITY_TRANSPARENT_U8, \
opacity1, OPACITY_OPAQUE_U8));
-
painter->setCompositeOp(m_compositeOp);
painter->setOpacity(opacity);
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h index \
f05642a..2ba3d8b 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h
@@ -35,11 +35,10 @@ public:
KisPressureCompositeOption();
/**
- * Set the composite mode and opacity of the painter based on the pressure
- * and the curve (if checked) and return the old composite mode
- * of the painter.
+ * Set the composite mode and opacity of the painter based on the user selection
+ * and the pressure curve (if checked)
*/
- QString apply(KisPainter* painter, qint8 opacity, const KisPaintInformation& \
info) const; + void apply(KisPainter* painter, qint8 opacity, const \
KisPaintInformation& info) const;
void writeOptionSetting(KisPropertiesConfiguration* setting) const;
void readOptionSetting(const KisPropertiesConfiguration* setting);
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp index \
140c628..6f17544 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp
@@ -46,6 +46,12 @@ KisPressureCompositeOptionWidget::KisPressureCompositeOptionWidget()
m_compositeOpBox->addItem(COMPOSITE_SCREEN);
m_compositeOpBox->addItem(COMPOSITE_ADD);
m_compositeOpBox->addItem(COMPOSITE_SUBTRACT);
+ m_compositeOpBox->addItem(COMPOSITE_DIVIDE);
+ m_compositeOpBox->addItem(COMPOSITE_BURN);
+ m_compositeOpBox->addItem(COMPOSITE_DODGE);
+ m_compositeOpBox->addItem(COMPOSITE_COLOR);
+ m_compositeOpBox->addItem(COMPOSITE_HARD_LIGHT);
+ m_compositeOpBox->addItem(COMPOSITE_SOFT_LIGHT);
m_rateSlider = new QSlider();
m_rateSlider->setMinimum(0);
--
1.7.1
From aa6eb274013a01d46d97d05a6a45f4f3ff9bc2e5 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich <plassy@web.de>
Date: Mon, 3 Jan 2011 00:43:51 +0100
Subject: [PATCH 3/6] Fixed the handling of transparency for the smudge brush.
Implemented the COMPOSITE_COPY_OPACY mode to fix it
---
.../defaultpaintops/smudge/kis_smudgeop.cpp | 28 +++--
.../paintops/defaultpaintops/smudge/kis_smudgeop.h | 2 +
.../smudge/kis_smudgeop_settings_widget.cpp | 1 +
.../libpaintop/kis_pressure_composite_option.cpp | 10 +-
.../libpaintop/kis_pressure_composite_option.h | 2 +-
.../kis_pressure_composite_option_widget.cpp | 3 +-
.../kis_pressure_composite_option_widget.h | 2 +-
libs/pigment/compositeops/KoCompositeOpCopyOpacy.h | 133 ++++++++++++++++++++
libs/pigment/compositeops/KoCompositeOps.h | 5 +-
9 files changed, 165 insertions(+), 21 deletions(-)
create mode 100644 libs/pigment/compositeops/KoCompositeOpCopyOpacy.h
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp index \
372a1b7..0dabf9a 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
@@ -6,6 +6,7 @@
* Copyright (c) 2004,2010 Cyrille Berger <cberger@cberger.net>
* Copyright (c) 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
* Copyright (c) 2010 José Luis Vergara Toloza <pentalis@gmail.com>
+ * Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -53,7 +54,8 @@ KisSmudgeOp::KisSmudgeOp(const KisBrushBasedPaintOpSettings \
*settings, KisPainte m_rateOption.sensor()->reset();
m_compositeOption.sensor()->reset();
- m_tempDev = new KisPaintDevice(painter->device()->colorSpace());
+ m_tempDev = new KisPaintDevice(painter->device()->colorSpace());
+ m_firstRun = true;
}
KisSmudgeOp::~KisSmudgeOp()
@@ -89,7 +91,7 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
splitCoordinate(point.x(), &x, &xFraction);
splitCoordinate(point.y(), &y, &yFraction);
- KisFixedPaintDeviceSP maskDab = cachedDab(painter()->device()->colorSpace());
+ KisFixedPaintDeviceSP maskDab = 0;
// Extract the brush mask (maskDab) from brush with the correct scaled size
if(brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
@@ -107,15 +109,22 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
// GET the opacy calculated by the rate option (apply is misleading because the \
opacy will not be applied) quint8 newOpacity = m_rateOption.apply(OPACITY_OPAQUE_U8, \
info);
- // set opacity calculated by the rate option
- // then blit the temporary painting device on the canvas at the current brush \
position
- // the alpha mask (maskDab) will be used here to only blit the pixels that lie \
in the area (shape) of the brush
- painter()->setOpacity(newOpacity);
- painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, \
maskDab->bounds().width(), maskDab->bounds().height()); + if(!m_firstRun) {
+ // set opacity calculated by the rate option
+ // then blit the temporary painting device on the canvas at the current \
brush position + // the alpha mask (maskDab) will be used here to only blit \
the pixels that lie in the area (shape) of the brush + \
painter()->setOpacity(newOpacity / 2); + \
painter()->setCompositeOp(COMPOSITE_OVER); + \
painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, \
maskDab->bounds().width(), maskDab->bounds().height()); + \
painter()->setOpacity(newOpacity); + \
painter()->setCompositeOp(COMPOSITE_COPY_OPACITY); + \
painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, \
maskDab->bounds().width(), maskDab->bounds().height()); + }
+ else m_firstRun = false;
// IMPORTANT: clear the temporary painting device to color black with zero \
opacity // it will only clear the extents of the brush
- m_tempDev->clear(maskDab->bounds());
+ m_tempDev->clear(QRect(0, 0, brush->width(), brush->height()));
KisPainter copyPainter(m_tempDev);
@@ -124,7 +133,7 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
// and blit it to the temporary painting device
copyPainter.setCompositeOp(COMPOSITE_OVER);
copyPainter.setOpacity(OPACITY_OPAQUE_U8);
- copyPainter.bitBlt(0, 0, painter()->device(), x, y, maskDab->bounds().width(), \
maskDab->bounds().height()); + copyPainter.bitBlt(0, 0, painter()->device(), x, y, \
brush->width(), brush->width());
// if the user selected the color smudge option
// we will mix some color into the temorary painting device (m_tempDev)
@@ -141,6 +150,5 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
}
copyPainter.end();
-
return spacing(scale);
}
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h index 5948e04..333df09 \
100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
@@ -5,6 +5,7 @@
* Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
* Copyright (c) 2010 José Luis Vergara Toloza <pentalis@gmail.com>
+ * Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -49,6 +50,7 @@ public:
qreal paintAt(const KisPaintInformation& info);
private:
+ bool m_firstRun;
KisPaintDeviceSP m_tempDev; // The temporary paint device
KisPressureSizeOption m_sizeOption;
KisPressureRateOption m_rateOption;
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp \
index 3f01533..a07d7f4 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop_settings_widget.cpp
@@ -4,6 +4,7 @@
* Copyright (c) 2004 Clarence Dang <dang@kde.org>
* Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ * Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp index \
ca09eb6..6d82865 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
@@ -1,5 +1,5 @@
/* This file is part of the KDE project
- * Copyright (C) Boudewijn Rempt <boud@valdyas.org>, (C) 2008
+ * Copyright (C) Silvio Heinrich <plassy@web.de>, (C) 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -32,8 +32,8 @@
KisPressureCompositeOption::KisPressureCompositeOption()
: KisCurveOption(i18n("Color"), "Color", KisPaintOpOption::brushCategory(), \
false) {
- setMinimumLabel(i18n("Full Color"));
- setMaximumLabel(i18n("No Color"));
+ setMinimumLabel(i18n("No Color"));
+ setMaximumLabel(i18n("Full Color"));
}
void KisPressureCompositeOption::writeOptionSetting(KisPropertiesConfiguration* \
setting) const @@ -56,7 +56,7 @@ void \
KisPressureCompositeOption::readOptionSetting(const KisPropertiesConfigurat void \
KisPressureCompositeOption::apply(KisPainter* painter, qint8 opacity, const \
KisPaintInformation& info) const {
if(!isChecked())
- return painter->compositeOp()->id();
+ return;
QString oldCompositeOp = painter->compositeOp()->id();
@@ -67,7 +67,5 @@ void KisPressureCompositeOption::apply(KisPainter* painter, qint8 \
opacity, const
painter->setCompositeOp(m_compositeOp);
painter->setOpacity(opacity);
-
- return oldCompositeOp;
}
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h index \
2ba3d8b..1ed6ff7 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.h
@@ -1,5 +1,5 @@
/* This file is part of the KDE project
- * Copyright (C) Boudewijn Rempt <boud@valdyas.org>, (C) 2008
+ * Copyright (C) Silvio Heinrich <plassy@web.de>, (C) 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp index \
6f17544..f075a3c 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.cpp
@@ -1,6 +1,5 @@
/* This file is part of the KDE project
- * Copyright (C) Boudewijn Rempt <boud@valdyas.org>, (C) 2008
- * Copyright (C) Sven Langkamp <sven.langkamp@gmail.com>, (C) 2009
+ * Copyright (C) Silvio Heinrich <plassy@web.de>, (C) 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h \
b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h index \
6660f72..30c09ce 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option_widget.h
@@ -1,5 +1,5 @@
/* This file is part of the KDE project
- * Copyright (C) Sven Langkamp <sven.langkamp@gmail.com>, (C) 2009
+ * Copyright (C) Silvio Heinrich <plassy@web.de>, (C) 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
diff --git a/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h \
b/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h new file mode 100644
index 0000000..97dcbfd
--- /dev/null
+++ b/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2008 Silvio Heinrich <plassy@web.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KOCOMPOSITEOPCOPYOPACY_H_
+#define KOCOMPOSITEOPCOPYOPACY_H_
+
+#include <KoColorSpaceMaths.h>
+#include <KoCompositeOp.h>
+#include <KoColorSpaceConstants.h>
+
+/**
+ * A template version of the copy opacy composite operation to use in colorspaces.
+ */
+template<class _CSTraits>
+class KoCompositeOpCopyOpacy : public KoCompositeOp
+{
+ typedef typename _CSTraits::channels_type channels_type;
+ static const qint32 channels_nb = _CSTraits::channels_nb;
+ static const qint32 alpha_pos = _CSTraits::alpha_pos;
+ static const qint32 pixelSize = _CSTraits::pixelSize;
+
+public:
+ KoCompositeOpCopyOpacy(const KoColorSpace * cs)
+ : KoCompositeOp(cs, COMPOSITE_COPY_OPACITY, i18n("Copy Opacy"), \
KoCompositeOp::categoryArithmetic(), true) { + }
+
+public:
+ inline static channels_type selectAlpha(channels_type srcAlpha, channels_type \
dstAlpha) { + return qMin(srcAlpha, dstAlpha);
+ }
+
+ void composite(quint8 *dstRowStart,
+ qint32 dstRowStride,
+ const quint8 *srcRowStart,
+ qint32 srcRowStride,
+ const quint8 *maskRowStart,
+ qint32 maskRowStride,
+ qint32 rows,
+ qint32 cols,
+ quint8 U8_opacity,
+ const QBitArray & channelFlags) const
+ {
+ bool useMask = maskRowStart != 0;
+ channels_type opacity = \
KoColorSpaceMaths<quint8,channels_type>::scaleToA(U8_opacity); +
+ if(srcRowStride != 0) {
+ for(; rows>0; --rows) {
+ const quint8* mskRowItr = maskRowStart;
+ const channels_type* srcRowItr = reinterpret_cast<const \
channels_type*>(srcRowStart) + alpha_pos; + channels_type* \
dstRowItr = reinterpret_cast<channels_type*>(dstRowStart) + alpha_pos; + \
+ for(qint32 c=cols; c>0; --c) {
+ channels_type value = 0;
+
+ switch(U8_opacity)
+ {
+ case OPACITY_TRANSPARENT_U8: { value = *dstRowItr; } break;
+ case OPACITY_OPAQUE_U8: { value = *srcRowItr; } break;
+ default: { value = \
KoColorSpaceMaths<channels_type>::blend(*srcRowItr, *dstRowItr, opacity); } break; + \
} +
+ if(useMask) {
+ channels_type blend = \
KoColorSpaceMaths<quint8,channels_type>::scaleToA(*mskRowItr); + \
value = KoColorSpaceMaths<channels_type>::blend(value, *dstRowItr, blend); + \
value = (value > *dstRowItr) ? (value-1) : value; + \
++mskRowItr; + }
+
+ *dstRowItr = value;
+ srcRowItr += channels_nb;
+ dstRowItr += channels_nb;
+
+ }
+
+ srcRowStart += srcRowStride;
+ dstRowStart += dstRowStride;
+ maskRowStart += maskRowStride;
+ }
+ }
+ else {
+ channels_type srcValue = *(reinterpret_cast<const \
channels_type*>(srcRowStart) + alpha_pos); +
+ for(; rows>0; --rows) {
+ const quint8* mskRowItr = maskRowStart;
+ channels_type* dstRowItr = \
reinterpret_cast<channels_type*>(dstRowStart) + alpha_pos; +
+ for(qint32 c=cols; c>0; --c) {
+ channels_type value = 0;
+
+ switch(U8_opacity)
+ {
+ case OPACITY_TRANSPARENT_U8: { value = *dstRowItr; } break;
+ case OPACITY_OPAQUE_U8: { value = srcValue; } break;
+ default: { value = \
KoColorSpaceMaths<channels_type>::blend(srcValue, *dstRowItr, opacity); } break; + \
} +
+ if(useMask) {
+ channels_type blend = \
KoColorSpaceMaths<quint8,channels_type>::scaleToA(*mskRowItr); + \
value = KoColorSpaceMaths<channels_type>::blend(value, *dstRowItr, blend); + \
value = (value > *dstRowItr) ? (value-1) : value; + \
++mskRowItr; + }
+
+ *dstRowItr = value;
+ dstRowItr += channels_nb;
+ }
+
+ srcRowStart += srcRowStride;
+ dstRowStart += dstRowStride;
+ maskRowStart += maskRowStride;
+ }
+ }
+ }
+
+};
+
+#endif // KOCOMPOSITEOPCOPYOPACY_H_
diff --git a/libs/pigment/compositeops/KoCompositeOps.h \
b/libs/pigment/compositeops/KoCompositeOps.h index d278234..b222f32 100644
--- a/libs/pigment/compositeops/KoCompositeOps.h
+++ b/libs/pigment/compositeops/KoCompositeOps.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2007 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2007 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -37,6 +38,7 @@
#include "compositeops/KoCompositeOpSoftlight.h"
#include "compositeops/KoCompositeOpHardlight.h"
#include "compositeops/KoCompositeOpCopy2.h"
+#include "compositeops/KoCompositeOpCopyOpacy.h"
/**
* This function add to the colorspace all the composite ops defined by
@@ -59,6 +61,7 @@ void addStandardCompositeOps(KoColorSpace* cs)
cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+ cs->addCompositeOp(new KoCompositeOpCopyOpacy<_Traits_>(cs));
}
#endif
--
1.7.1
From bf5ed07167a9bd844c5c0aa608488a26b0d6367b Mon Sep 17 00:00:00 2001
From: Silvio Heinrich <plassy@web.de>
Date: Mon, 3 Jan 2011 21:34:41 +0100
Subject: [PATCH 4/6] Fixed some gliches introducing transparency and black color \
where it should not be.
---
.../defaultpaintops/smudge/kis_smudgeop.cpp | 6 +++---
libs/pigment/compositeops/KoCompositeOpCopyOpacy.h | 7 +++----
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp index \
0dabf9a..ef48e1f 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
@@ -87,7 +87,7 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
QPointF point = info.pos() - brush->hotSpot(scale, scale);
qint32 x, y;
- qreal xFraction, yFraction;
+ qreal xFraction, yFraction; // will not be used
splitCoordinate(point.x(), &x, &xFraction);
splitCoordinate(point.y(), &y, &yFraction);
@@ -96,11 +96,11 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
// Extract the brush mask (maskDab) from brush with the correct scaled size
if(brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
// This is for bitmap brushes
- maskDab = brush->paintDevice(painter()->device()->colorSpace(), scale, 0.0, \
info, xFraction, yFraction); + maskDab = \
brush->paintDevice(painter()->device()->colorSpace(), scale, 0.0, info, 0.0, 0.0); } \
else {
// This is for parametric brushes, those created in the Autobrush popup \
config dialogue maskDab = cachedDab();
- brush->mask(maskDab, painter()->paintColor(), scale, scale, 0.0, info, \
xFraction, yFraction); + brush->mask(maskDab, painter()->paintColor(), scale, \
scale, 0.0, info, 0.0, 0.0); }
// transforms the fixed paint device with the current brush to alpha color space \
(to use it as alpha/transparency mask)
diff --git a/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h \
b/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h index 97dcbfd..48f63ce 100644
--- a/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h
+++ b/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h
@@ -78,14 +78,13 @@ public:
if(useMask) {
channels_type blend = \
KoColorSpaceMaths<quint8,channels_type>::scaleToA(*mskRowItr);
value = KoColorSpaceMaths<channels_type>::blend(value, \
*dstRowItr, blend);
- value = (value > *dstRowItr) ? (value-1) : value;
++mskRowItr;
}
+ value = (value > *dstRowItr) ? (value-1) : value;
*dstRowItr = value;
srcRowItr += channels_nb;
dstRowItr += channels_nb;
-
}
srcRowStart += srcRowStride;
@@ -113,10 +112,10 @@ public:
if(useMask) {
channels_type blend = \
KoColorSpaceMaths<quint8,channels_type>::scaleToA(*mskRowItr);
value = KoColorSpaceMaths<channels_type>::blend(value, \
*dstRowItr, blend);
- value = (value > *dstRowItr) ? (value-1) : value;
++mskRowItr;
}
+ value = (value > *dstRowItr) ? (value-1) : value;
*dstRowItr = value;
dstRowItr += channels_nb;
}
@@ -127,7 +126,7 @@ public:
}
}
}
-
+
};
#endif // KOCOMPOSITEOPCOPYOPACY_H_
--
1.7.1
From f72641b0df5016f8e11085365110e808aeb1edae Mon Sep 17 00:00:00 2001
From: Silvio Heinrich <plassy@web.de>
Date: Tue, 4 Jan 2011 00:49:28 +0100
Subject: [PATCH 5/6] Opacity adjustment.
---
.../defaultpaintops/smudge/kis_smudgeop.cpp | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp \
b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp index \
ef48e1f..e03121f 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
@@ -112,8 +112,8 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
if(!m_firstRun) {
// set opacity calculated by the rate option
// then blit the temporary painting device on the canvas at the current \
brush position
- // the alpha mask (maskDab) will be used here to only blit the pixels that \
lie in the area (shape) of the brush
- painter()->setOpacity(newOpacity / 2);
+ // the alpha mask (maskDab) will be used here to only blit the pixels that \
are in the area (shape) of the brush + painter()->setOpacity(newOpacity);
painter()->setCompositeOp(COMPOSITE_OVER);
painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, \
maskDab->bounds().width(), maskDab->bounds().height()); \
painter()->setOpacity(newOpacity);
--
1.7.1
From 1f43c1c7113a98f3f4d42b58932a0679736d7706 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich <plassy@web.de>
Date: Tue, 4 Jan 2011 00:55:43 +0100
Subject: [PATCH 6/6] Fixed copyright/author information
---
libs/pigment/compositeops/KoCompositeOpCopyOpacy.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h \
b/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h index 48f63ce..03a43d2 100644
--- a/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h
+++ b/libs/pigment/compositeops/KoCompositeOpCopyOpacy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008 Silvio Heinrich <plassy@web.de>
+ * Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
--
1.7.1
_______________________________________________
kimageshop mailing list
kimageshop@kde.org
https://mail.kde.org/mailman/listinfo/kimageshop
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic