[PATCH 03/15] Added KoCompositeOpGeneric class to easily create new composite modes by just defining a composition function.

Silvio Heinrich plassy at web.de
Sat Jan 8 03:46:10 CET 2011


The KoCompositeOpGeneric class is a template that takes a function pointer
to a composition function as a second template parameter.
So for the most composition modes it is not needed anymore
to derive a new class from KoCompositionOp (or from one of its derivates)
---
 libs/pigment/KoCompositeOp.h                       |    2 +
 libs/pigment/compositeops/KoCompositeOpBurn.h      |    2 +-
 libs/pigment/compositeops/KoCompositeOpDodge.h     |    2 +-
 libs/pigment/compositeops/KoCompositeOpFunctions.h |   64 +++++++++++++++++---
 libs/pigment/compositeops/KoCompositeOpGeneric.h   |   65 ++++++++++++++++++++
 libs/pigment/compositeops/KoCompositeOps.h         |   56 +++++++++++------
 6 files changed, 162 insertions(+), 29 deletions(-)
 create mode 100644 libs/pigment/compositeops/KoCompositeOpGeneric.h

diff --git a/libs/pigment/KoCompositeOp.h b/libs/pigment/KoCompositeOp.h
index f6fb236..73c923e 100644
--- a/libs/pigment/KoCompositeOp.h
+++ b/libs/pigment/KoCompositeOp.h
@@ -43,7 +43,9 @@ const QString COMPOSITE_DIFF = "diff";
 const QString COMPOSITE_MULT = "multiply";
 const QString COMPOSITE_DIVIDE = "divide";
 const QString COMPOSITE_DODGE = "dodge";
+const QString COMPOSITE_LINEAR_DODGE = "linear_dodge";
 const QString COMPOSITE_BURN = "burn";
+const QString COMPOSITE_LINEAR_BURN = "linear_burn";
 const QString COMPOSITE_BUMPMAP = "bumpmap";
 const QString COMPOSITE_CLEAR = "clear";
 const QString COMPOSITE_DISSOLVE = "dissolve";
diff --git a/libs/pigment/compositeops/KoCompositeOpBurn.h b/libs/pigment/compositeops/KoCompositeOpBurn.h
index 3315373..857efea 100644
--- a/libs/pigment/compositeops/KoCompositeOpBurn.h
+++ b/libs/pigment/compositeops/KoCompositeOpBurn.h
@@ -35,7 +35,7 @@ class KoCompositeOpBurn : public KoCompositeOpBase< _CSTraits, KoCompositeOpBurn
     
 public:
     KoCompositeOpBurn(const KoColorSpace* cs)
-        : KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight()) { }
+        : KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight(), true) { }
 
 public:
     inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
diff --git a/libs/pigment/compositeops/KoCompositeOpDodge.h b/libs/pigment/compositeops/KoCompositeOpDodge.h
index 019695a..815d273 100644
--- a/libs/pigment/compositeops/KoCompositeOpDodge.h
+++ b/libs/pigment/compositeops/KoCompositeOpDodge.h
@@ -35,7 +35,7 @@ class KoCompositeOpDodge : public KoCompositeOpBase< _CSTraits, KoCompositeOpDod
     static const qint32 alpha_pos   = _CSTraits::alpha_pos;
 public:
     KoCompositeOpDodge(const KoColorSpace * cs)
-        : KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight()) { }
+        : KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight(), true) { }
 
 public:
     inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
diff --git a/libs/pigment/compositeops/KoCompositeOpFunctions.h b/libs/pigment/compositeops/KoCompositeOpFunctions.h
index bdd3af7..0656fa5 100644
--- a/libs/pigment/compositeops/KoCompositeOpFunctions.h
+++ b/libs/pigment/compositeops/KoCompositeOpFunctions.h
@@ -56,7 +56,8 @@ inline T inv(T a) {
 
 template<class T>
 inline T clamp(typename KoColorSpaceMathsTraits<T>::compositetype a) {
-    return (a > KoColorSpaceMathsTraits<T>::unitValue) ? KoColorSpaceMathsTraits<T>::unitValue : T(a);
+    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
+    return qBound<composite_type>(KoColorSpaceMathsTraits<T>::zeroValue, a, KoColorSpaceMathsTraits<T>::unitValue);
 }
 
 template<class T>
@@ -89,24 +90,69 @@ inline T blend(T src, T srcAlpha, T dst, T dstAlpha, TFunc blendFunc) {
 
 template<class T>
 inline T cfColorBurn(T src, T dst) {
-    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
-    
     if(src != KoColorSpaceMathsTraits<T>::zeroValue)
         return inv(clamp<T>(div(inv(dst), src)));
-    
     return KoColorSpaceMathsTraits<T>::zeroValue;
 }
 
 template<class T>
-inline T cfColorDodge(T src, T dst) {
+inline T cfLinearBurn(T src, T dst) {
     typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
-    
+    return clamp<T>(composite_type(src) + dst - KoColorSpaceMathsTraits<T>::unitValue);
+}
+
+template<class T>
+inline T cfColorDodge(T src, T dst) {
     if(src != KoColorSpaceMathsTraits<T>::unitValue)
         return clamp<T>(div(dst, inv(src)));
-    
     return KoColorSpaceMathsTraits<T>::unitValue;
 }
 
+template<class T>
+inline T cfAddition(T src, T dst) {
+    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
+    return clamp<T>(composite_type(src) + dst);
+}
+
+template<class T>
+inline T cfSubtract(T src, T dst) {
+    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
+    return clamp<T>(composite_type(dst) - src);
+}
+
+template<class T>
+inline T cfExclusion(T src, T dst) {
+    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
+    composite_type x = mul(src, dst);
+    return clamp<T>(composite_type(dst) + src - (x + x));
+}
+
+template<class T>
+inline T cfDivide(T src, T dst) {
+    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;
+    if(src == KoColorSpaceMathsTraits<T>::zeroValue)
+        return dst;
+    return clamp<T>(div(dst, src));
+}
+
+template<class T>
+inline T cfOver(T src, T dst) { Q_UNUSED(dst); return src; }
+
+template<class T>
+inline T cfMultiply(T src, T dst) { return mul(src, dst); }
+
+template<class T>
+inline T cfDifference(T src, T dst) { return qMax(src,dst) - qMin(src,dst); }
+
+template<class T>
+inline T cfScreen(T src, T dst) { return unionShapeOpacy(src, dst); }
+
+template<class T>
+inline T cfDarkenOnly(T src, T dst) { return qMin(src, dst); }
+
+template<class T>
+inline T cfLightenOnly(T src, T dst) { return qMax(src, dst); }
+
 /**
  * A template base class that can be used for most composite modes/ops
  *
@@ -132,8 +178,8 @@ class KoCompositeOpBase : public KoCompositeOp
     
 public:
     
-    KoCompositeOpBase(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category)
-        : KoCompositeOp(cs, id, description, category) { }
+    KoCompositeOpBase(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category, bool userVisible)
+        : KoCompositeOp(cs, id, description, category, userVisible) { }
     
 private:
     template<bool alphaLocked>
diff --git a/libs/pigment/compositeops/KoCompositeOpGeneric.h b/libs/pigment/compositeops/KoCompositeOpGeneric.h
new file mode 100644
index 0000000..805b017
--- /dev/null
+++ b/libs/pigment/compositeops/KoCompositeOpGeneric.h
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * 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 _KOCOMPOSITEO_GENERIC_H_
+#define _KOCOMPOSITEO_GENERIC_H_
+
+#include "KoCompositeOpFunctions.h"
+
+/**
+ * A template version of the burn composite operation to use in colorspaces.
+ */
+template<
+    class Traits,
+    typename Traits::channels_type compositeFunc(typename Traits::channels_type, typename Traits::channels_type)
+>
+class KoCompositeOpGeneric : public KoCompositeOpBase< Traits, KoCompositeOpGeneric<Traits,compositeFunc> >
+{
+    typedef KoCompositeOpBase< Traits, KoCompositeOpGeneric<Traits,compositeFunc> > base_class;
+    typedef typename Traits::channels_type                                          channels_type;
+    typedef typename KoColorSpaceMathsTraits<channels_type>::compositetype          composite_type;
+    
+    static const qint32 channels_nb = Traits::channels_nb;
+    static const qint32 alpha_pos   = Traits::alpha_pos;
+    
+public:
+    KoCompositeOpGeneric(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category, bool userVisible=true)
+        : base_class(cs, id, description, category, userVisible) { }
+
+public:
+    inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
+                                                     channels_type*       dst, channels_type dstAlpha,
+                                                     channels_type opacity, const QBitArray& channelFlags) {
+        srcAlpha = mul(srcAlpha, opacity);
+        channels_type newDstAlpha = unionShapeOpacy(srcAlpha, dstAlpha);
+        
+        if(newDstAlpha != KoColorSpaceMathsTraits<channels_type>::zeroValue) {
+            for(qint32 i=0; i <channels_nb; i++) {
+                if(i != alpha_pos && channelFlags.testBit(i)) {
+                    channels_type result = blend(src[i], srcAlpha, dst[i], dstAlpha, compositeFunc);
+                    dst[i] = div(result, newDstAlpha);
+                }
+            }
+        }
+        
+        return newDstAlpha;
+    }
+};
+
+#endif // _KOCOMPOSITEO_GENERIC_H_
diff --git a/libs/pigment/compositeops/KoCompositeOps.h b/libs/pigment/compositeops/KoCompositeOps.h
index d278234..7949865 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) 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
@@ -22,21 +23,22 @@
 
 #include "KoColorSpace.h"
 
-#include "compositeops/KoCompositeOpAdd.h"
+// #include "compositeops/KoCompositeOpAdd.h"
 #include "compositeops/KoCompositeOpAlphaDarken.h"
-#include "compositeops/KoCompositeOpBurn.h"
+// #include "compositeops/KoCompositeOpBurn.h"
 #include "compositeops/KoCompositeOpDivide.h"
-#include "compositeops/KoCompositeOpDodge.h"
+// #include "compositeops/KoCompositeOpDodge.h"
 #include "compositeops/KoCompositeOpErase.h"
-#include "compositeops/KoCompositeOpMultiply.h"
-#include "compositeops/KoCompositeOpOver.h"
+// #include "compositeops/KoCompositeOpMultiply.h"
+// #include "compositeops/KoCompositeOpOver.h"
 #include "compositeops/KoCompositeOpOverlay.h"
-#include "compositeops/KoCompositeOpScreen.h"
-#include "compositeops/KoCompositeOpSubtract.h"
+// #include "compositeops/KoCompositeOpScreen.h"
+// #include "compositeops/KoCompositeOpSubtract.h"
 #include "compositeops/KoCompositeOpInversedSubtract.h"
 #include "compositeops/KoCompositeOpSoftlight.h"
 #include "compositeops/KoCompositeOpHardlight.h"
 #include "compositeops/KoCompositeOpCopy2.h"
+#include "compositeops/KoCompositeOpGeneric.h"
 
 /**
  * This function add to the colorspace all the composite ops defined by
@@ -45,20 +47,38 @@
 template<class _Traits_>
 void addStandardCompositeOps(KoColorSpace* cs)
 {
-    cs->addCompositeOp(new KoCompositeOpAdd<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpAdd<_Traits_>(cs));
     cs->addCompositeOp(new KoCompositeOpAlphaDarken<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpBurn<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpBurn<_Traits_>(cs));
     cs->addCompositeOp(new KoCompositeOpCopy2<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpDivide<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpDodge<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpDivide<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpDodge<_Traits_>(cs));
     cs->addCompositeOp(new KoCompositeOpErase<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpMultiply<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpOver<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpOverlay<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpScreen<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
-    cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpMultiply<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpOver<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpOverlay<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpScreen<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
+    //cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+    
+    typedef typename _Traits_::channels_type type;
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfOver <type> >(cs, COMPOSITE_OVER, i18n("Normal"), KoCompositeOp::categoryMix()));
+    
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorBurn  <type> >(cs, COMPOSITE_BURN        , i18n("Color Burn"), KoCompositeOp::categoryLight()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorDodge <type> >(cs, COMPOSITE_DODGE       , i18n("Color Dodge"), KoCompositeOp::categoryLight()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLinearBurn <type> >(cs, COMPOSITE_LINEAR_BURN , i18n("Linear Burn"), KoCompositeOp::categoryLight()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition   <type> >(cs, COMPOSITE_LINEAR_DODGE, i18n("Linear Dodge"), KoCompositeOp::categoryLight()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDarkenOnly <type> >(cs, COMPOSITE_DARKEN      , i18n("Darken"), KoCompositeOp::categoryLight()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLightenOnly<type> >(cs, COMPOSITE_LIGHTEN     , i18n("Lighten"), KoCompositeOp::categoryLight()));
+    
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition  <type> >(cs, COMPOSITE_ADD      , i18n("Addition"), KoCompositeOp::categoryArithmetic()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfSubtract  <type> >(cs, COMPOSITE_SUBTRACT , i18n("Subtract"), KoCompositeOp::categoryArithmetic()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDifference<type> >(cs, COMPOSITE_DIFF     , i18n("Difference"), KoCompositeOp::categoryArithmetic()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfMultiply  <type> >(cs, COMPOSITE_MULT     , i18n("Multiply"), KoCompositeOp::categoryArithmetic()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDivide    <type> >(cs, COMPOSITE_DIVIDE   , i18n("Divide"), KoCompositeOp::categoryArithmetic()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfExclusion <type> >(cs, COMPOSITE_EXCLUSION, i18n("Exclusion"), KoCompositeOp::categoryArithmetic()));
+    cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfScreen    <type> >(cs, COMPOSITE_SCREEN   , i18n("Screen"), KoCompositeOp::categoryArithmetic()));
 }
 
 #endif
-- 
1.7.1




More information about the kimageshop mailing list