diff --git a/libs/pigment/KoCompositeOp.h b/libs/pigment/KoCompositeOp.h --- a/libs/pigment/KoCompositeOp.h +++ b/libs/pigment/KoCompositeOp.h @@ -51,6 +51,7 @@ static QString categoryHSV(); static QString categoryMix(); static QString categoryMisc(); + static QString categoryQuadratic(); struct KRITAPIGMENT_EXPORT ParameterInfo { diff --git a/libs/pigment/KoCompositeOp.cpp b/libs/pigment/KoCompositeOp.cpp --- a/libs/pigment/KoCompositeOp.cpp +++ b/libs/pigment/KoCompositeOp.cpp @@ -41,6 +41,7 @@ QString KoCompositeOp::categoryHSV() { return i18n("HSV"); } QString KoCompositeOp::categoryMix() { return i18n("Mix"); } QString KoCompositeOp::categoryMisc() { return i18n("Misc"); } +QString KoCompositeOp::categoryQuadratic() { return i18n("Quadratic"); } KoCompositeOp::ParameterInfo::ParameterInfo() : opacity(1.0f), diff --git a/libs/pigment/KoCompositeOpRegistry.h b/libs/pigment/KoCompositeOpRegistry.h --- a/libs/pigment/KoCompositeOpRegistry.h +++ b/libs/pigment/KoCompositeOpRegistry.h @@ -138,6 +138,12 @@ const QString COMPOSITE_LIGHTER_COLOR = "lighter color"; const QString COMPOSITE_UNDEF = "undefined"; +const QString COMPOSITE_REFLECT = "reflect"; +const QString COMPOSITE_GLOW = "glow"; +const QString COMPOSITE_FREEZE = "freeze"; +const QString COMPOSITE_HEAT = "heat"; + + class KRITAPIGMENT_EXPORT KoCompositeOpRegistry { diff --git a/libs/pigment/KoCompositeOpRegistry.cpp b/libs/pigment/KoCompositeOpRegistry.cpp --- a/libs/pigment/KoCompositeOpRegistry.cpp +++ b/libs/pigment/KoCompositeOpRegistry.cpp @@ -43,7 +43,8 @@ << KoID("hsy" , i18n("HSY")) << KoID("hsi" , i18n("HSI")) << KoID("hsl" , i18n("HSL")) - << KoID("hsv" , i18n("HSV")); + << KoID("hsv" , i18n("HSV")) + << KoID("quadratic" , i18n("Quadratic")); m_map.insert(m_categories[0], KoID(COMPOSITE_ADD , i18n("Addition"))); m_map.insert(m_categories[0], KoID(COMPOSITE_SUBTRACT , i18n("Subtract"))); @@ -137,6 +138,11 @@ m_map.insert(m_categories[9], KoID(COMPOSITE_INC_SATURATION_HSV, i18n("Increase Saturation HSV"))); m_map.insert(m_categories[9], KoID(COMPOSITE_DEC_VALUE , i18n("Decrease Value"))); m_map.insert(m_categories[9], KoID(COMPOSITE_INC_VALUE , i18n("Increase Value"))); + + m_map.insert(m_categories[10], KoID(COMPOSITE_REFLECT , i18n("Reflect"))); + m_map.insert(m_categories[10], KoID(COMPOSITE_GLOW , i18n("Glow"))); + m_map.insert(m_categories[10], KoID(COMPOSITE_FREEZE , i18n("Freeze"))); + m_map.insert(m_categories[10], KoID(COMPOSITE_HEAT , i18n("Heat"))); } const KoCompositeOpRegistry& KoCompositeOpRegistry::instance() diff --git a/libs/pigment/compositeops/KoCompositeOpFunctions.h b/libs/pigment/compositeops/KoCompositeOpFunctions.h --- a/libs/pigment/compositeops/KoCompositeOpFunctions.h +++ b/libs/pigment/compositeops/KoCompositeOpFunctions.h @@ -453,4 +453,51 @@ template inline T cfLightenOnly(T src, T dst) { return qMax(src, dst); } +template +inline T cfGlow(T src, T dst) { + using namespace Arithmetic; + // see http://www.pegtop.net/delphi/articles/blendmodes/quadratic.htm for formulas of Quadratic Blending Modes like Glow, Reflect, Freeze, and Heat + + if(dst == unitValue()) { + return unitValue(); + } + + if(src == zeroValue()) { + return zeroValue(); + } + + return clamp(div(mul(src, src), inv(dst))); +} + +template +inline T cfReflect(T src, T dst) { + using namespace Arithmetic; + + return (cfGlow(dst,src)); +} + +template +inline T cfHeat(T src, T dst) { + using namespace Arithmetic; + // Heat, and Freeze only works properly on 8-bit images. It does not work properly on any other color depth. For now, if Heat and Freeze are proven useful for 8-bit painting, then there should be some way of solving this issue. + + if(dst == zeroValue()) { + return zeroValue(); + } + + if(src == unitValue()) { + return unitValue(); + } + + return inv(clamp(div(mul(inv(src), inv(src)),dst))); +} + +template +inline T cfFreeze(T src, T dst) { + using namespace Arithmetic; + + return clamp(cfHeat(dst,src)); +} + + #endif // KOCOMPOSITEOP_FUNCTIONS_H_ diff --git a/libs/pigment/compositeops/KoCompositeOps.h b/libs/pigment/compositeops/KoCompositeOps.h --- a/libs/pigment/compositeops/KoCompositeOps.h +++ b/libs/pigment/compositeops/KoCompositeOps.h @@ -153,6 +153,11 @@ add<&cfExclusion >(cs, COMPOSITE_EXCLUSION , i18n("Exclusion") , KoCompositeOp::categoryNegative()); add<&cfEquivalence >(cs, COMPOSITE_EQUIVALENCE , i18n("Equivalence") , KoCompositeOp::categoryNegative()); add<&cfAdditiveSubtractive >(cs, COMPOSITE_ADDITIVE_SUBTRACTIVE , i18n("Additive-Subtractive") , KoCompositeOp::categoryNegative()); + + add<&cfReflect >(cs, COMPOSITE_REFLECT , i18n("Reflect") , KoCompositeOp::categoryQuadratic()); + add<&cfGlow >(cs, COMPOSITE_GLOW , i18n("Glow") , KoCompositeOp::categoryQuadratic()); + add<&cfFreeze >(cs, COMPOSITE_FREEZE , i18n("Freeze") , KoCompositeOp::categoryQuadratic()); + add<&cfHeat >(cs, COMPOSITE_HEAT , i18n("Heat") , KoCompositeOp::categoryQuadratic()); cs->addCompositeOp(new KoCompositeOpDissolve(cs, KoCompositeOp::categoryMisc())); }