[PATCH 03/10] Fixed the handling of transparency for the smudge brush.
Silvio Heinrich
plassy at web.de
Mon Jan 3 00:43:51 CET 2011
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 at cberger.net>
* Copyright (c) 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
* Copyright (c) 2010 José Luis Vergara Toloza <pentalis at gmail.com>
+ * Copyright (C) 2011 Silvio Heinrich <plassy at 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 at pagenet.plus.com>
* Copyright (c) 2004 Cyrille Berger <cberger at cberger.net>
* Copyright (c) 2010 José Luis Vergara Toloza <pentalis at gmail.com>
+ * Copyright (C) 2011 Silvio Heinrich <plassy at 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 at kde.org>
* Copyright (c) 2004 Adrian Page <adrian at pagenet.plus.com>
* Copyright (c) 2004 Cyrille Berger <cberger at cberger.net>
+ * Copyright (C) 2011 Silvio Heinrich <plassy at 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 at valdyas.org>, (C) 2008
+ * Copyright (C) Silvio Heinrich <plassy at 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 at valdyas.org>, (C) 2008
+ * Copyright (C) Silvio Heinrich <plassy at 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 at valdyas.org>, (C) 2008
- * Copyright (C) Sven Langkamp <sven.langkamp at gmail.com>, (C) 2009
+ * Copyright (C) Silvio Heinrich <plassy at 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 at gmail.com>, (C) 2009
+ * Copyright (C) Silvio Heinrich <plassy at 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 at 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 at cberger.net>
+ * Copyright (c) 2007 Cyrille Berger <cberger at cberger.net>
+ * Copyright (c) 2011 Silvio Heinrich <plassy at 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
More information about the kimageshop
mailing list