[PATCH 3/6] 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