Commit b8d64d3d authored by Miguel Lopez's avatar Miguel Lopez Committed by Boudewijn Rempt

Final Series of IMBLEND blending modes, and including modulo modes.

Differential revision: https://phabricator.kde.org/D15584
parent b46ee111
......@@ -249,6 +249,22 @@ public:
return (dst_compositetype(a) * KoColorSpaceMathsTraits<_Tdst>::unitValue) / b;
}
inline static dst_compositetype modulus(_T a, _Tdst b) {
return (dst_compositetype(a) - floor(dst_compositetype(a)/((b != (KoColorSpaceMathsTraits<_T>::zeroValue - traits::epsilon) ? b : KoColorSpaceMathsTraits<_T>::zeroValue) + traits::epsilon))*(b + traits::epsilon));
}
inline static dst_compositetype xor(_T a, _Tdst b) {
return (int (a * std::numeric_limits<int>::max() - traits::epsilon) ^ int (b * std::numeric_limits<int>::max() - traits::epsilon));
}
inline static dst_compositetype and(_T a, _Tdst b) {
return (int (a * std::numeric_limits<int>::max() - traits::epsilon) & int (b * std::numeric_limits<int>::max() - traits::epsilon));
}
inline static dst_compositetype or(_T a, _Tdst b) {
return (int (a * std::numeric_limits<int>::max() - traits::epsilon) | int (b * std::numeric_limits<int>::max() - traits::epsilon));
}
/**
* Inversion : unitValue - a
* @param a
......@@ -576,6 +592,18 @@ namespace Arithmetic
inline typename KoColorSpaceMathsTraits<T>::compositetype
div(T a, T b) { return KoColorSpaceMaths<T>::divide(a, b); }
template<class T>
inline typename KoColorSpaceMathsTraits<T>::compositetype
xor(T a, T b) { return KoColorSpaceMaths<T>::xor(a, b); }
template<class T>
inline typename KoColorSpaceMathsTraits<T>::compositetype
and(T a, T b) { return KoColorSpaceMaths<T>::and(a, b); }
template<class T>
inline typename KoColorSpaceMathsTraits<T>::compositetype
or(T a, T b) { return KoColorSpaceMaths<T>::or(a, b); }
template<class T>
inline T clamp(typename KoColorSpaceMathsTraits<T>::compositetype a) {
return KoColorSpaceMaths<T>::clamp(a);
......@@ -612,6 +640,13 @@ namespace Arithmetic
inline T blend(T src, T srcAlpha, T dst, T dstAlpha, T cfValue) {
return mul(inv(srcAlpha), dstAlpha, dst) + mul(inv(dstAlpha), srcAlpha, src) + mul(dstAlpha, srcAlpha, cfValue);
}
template<class T>
inline T epsilon() { return KoColorSpaceMathsTraits<T>::epsilon; }
template<class T>
inline typename KoColorSpaceMathsTraits<T>::compositetype
mod(T a, T b) { return KoColorSpaceMaths<T>::modulus(a, b); }
}
struct HSYType
......
......@@ -32,6 +32,8 @@ QString KoCompositeOp::categoryColor()
}
QString KoCompositeOp::categoryArithmetic() { return i18n("Arithmetic"); }
QString KoCompositeOp::categoryBinary() { return i18n("Binary"); }
QString KoCompositeOp::categoryModulo() { return i18n("Modulo"); }
QString KoCompositeOp::categoryNegative() { return i18n("Negative"); }
QString KoCompositeOp::categoryLight() { return i18n("Lighten"); }
QString KoCompositeOp::categoryDark() { return i18n("Darken"); }
......
......@@ -42,6 +42,8 @@ public:
static QString categoryColor();
static QString categoryArithmetic();
static QString categoryBinary();
static QString categoryModulo();
static QString categoryNegative();
static QString categoryLight();
static QString categoryDark();
......
......@@ -35,8 +35,10 @@ KoCompositeOpRegistry::KoCompositeOpRegistry()
{
m_categories
<< KoID("arithmetic", i18n("Arithmetic"))
<< KoID("binary" , i18n("Binary"))
<< KoID("dark" , i18n("Darken"))
<< KoID("light" , i18n("Lighten"))
<< KoID("modulo" , i18n("Modulo"))
<< KoID("negative" , i18n("Negative"))
<< KoID("mix" , i18n("Mix"))
<< KoID("misc" , i18n("Misc"))
......@@ -52,97 +54,142 @@ KoCompositeOpRegistry::KoCompositeOpRegistry()
m_map.insert(m_categories[0], KoID(COMPOSITE_DIVIDE , i18n("Divide")));
m_map.insert(m_categories[0], KoID(COMPOSITE_INVERSE_SUBTRACT, i18n("Inverse Subtract")));
m_map.insert(m_categories[1], KoID(COMPOSITE_BURN , i18n("Burn")));
m_map.insert(m_categories[1], KoID(COMPOSITE_LINEAR_BURN, i18n("Linear Burn")));
m_map.insert(m_categories[1], KoID(COMPOSITE_DARKEN , i18n("Darken")));
m_map.insert(m_categories[1], KoID(COMPOSITE_GAMMA_DARK , i18n("Gamma Dark")));
m_map.insert(m_categories[1], KoID(COMPOSITE_DARKER_COLOR , i18n("Darker Color")));
m_map.insert(m_categories[2], KoID(COMPOSITE_DODGE , i18n("Color Dodge")));
m_map.insert(m_categories[2], KoID(COMPOSITE_LINEAR_DODGE, i18n("Linear Dodge")));
m_map.insert(m_categories[2], KoID(COMPOSITE_LIGHTEN , i18n("Lighten")));
m_map.insert(m_categories[2], KoID(COMPOSITE_LINEAR_LIGHT, i18n("Linear Light")));
m_map.insert(m_categories[2], KoID(COMPOSITE_SCREEN , i18n("Screen")));
m_map.insert(m_categories[2], KoID(COMPOSITE_PIN_LIGHT , i18n("Pin Light")));
m_map.insert(m_categories[2], KoID(COMPOSITE_VIVID_LIGHT , i18n("Vivid Light")));
m_map.insert(m_categories[2], KoID(COMPOSITE_HARD_LIGHT , i18n("Hard Light")));
m_map.insert(m_categories[2], KoID(COMPOSITE_SOFT_LIGHT_PHOTOSHOP, i18n("Soft Light (Photoshop)")));
m_map.insert(m_categories[2], KoID(COMPOSITE_SOFT_LIGHT_SVG, i18n("Soft Light (SVG)")));
m_map.insert(m_categories[2], KoID(COMPOSITE_GAMMA_LIGHT , i18n("Gamma Light")));
m_map.insert(m_categories[2], KoID(COMPOSITE_LIGHTER_COLOR , i18n("Lighter Color")));
m_map.insert(m_categories[3], KoID(COMPOSITE_DIFF , i18n("Difference")));
m_map.insert(m_categories[3], KoID(COMPOSITE_EQUIVALENCE , i18n("Equivalence")));
m_map.insert(m_categories[3], KoID(COMPOSITE_ADDITIVE_SUBTRACTIVE, i18n("Additive Subtractive")));
m_map.insert(m_categories[3], KoID(COMPOSITE_EXCLUSION , i18n("Exclusion")));
m_map.insert(m_categories[3], KoID(COMPOSITE_ARC_TANGENT , i18n("Arcus Tangent")));
m_map.insert(m_categories[4], KoID(COMPOSITE_OVER , i18n("Normal")));
m_map.insert(m_categories[4], KoID(COMPOSITE_BEHIND , i18n("Behind")));
m_map.insert(m_categories[4], KoID(COMPOSITE_GREATER , i18n("Greater")));
m_map.insert(m_categories[4], KoID(COMPOSITE_OVERLAY , i18n("Overlay")));
m_map.insert(m_categories[4], KoID(COMPOSITE_ERASE , i18n("Erase")));
m_map.insert(m_categories[4], KoID(COMPOSITE_ALPHA_DARKEN , i18n("Alpha Darken")));
m_map.insert(m_categories[4], KoID(COMPOSITE_HARD_MIX , i18n("Hard Mix")));
m_map.insert(m_categories[4], KoID(COMPOSITE_HARD_MIX_PHOTOSHOP, i18n("Hard Mix (Photoshop)")));
m_map.insert(m_categories[4], KoID(COMPOSITE_GRAIN_MERGE , i18n("Grain Merge")));
m_map.insert(m_categories[4], KoID(COMPOSITE_GRAIN_EXTRACT , i18n("Grain Extract")));
m_map.insert(m_categories[4], KoID(COMPOSITE_PARALLEL , i18n("Parallel")));
m_map.insert(m_categories[4], KoID(COMPOSITE_ALLANON , i18n("Allanon")));
m_map.insert(m_categories[4], KoID(COMPOSITE_GEOMETRIC_MEAN , i18n("Geometric Mean")));
m_map.insert(m_categories[4], KoID(COMPOSITE_DESTINATION_ATOP, i18n("Destination Atop")));
m_map.insert(m_categories[4], KoID(COMPOSITE_DESTINATION_IN , i18n("Destination In")));
m_map.insert(m_categories[4], KoID(COMPOSITE_HARD_OVERLAY , i18n("Hard Overlay")));
m_map.insert(m_categories[5], KoID(COMPOSITE_BUMPMAP , i18n("Bumpmap")));
m_map.insert(m_categories[5], KoID(COMPOSITE_COMBINE_NORMAL, i18n("Combine Normal Map")));
m_map.insert(m_categories[5], KoID(COMPOSITE_DISSOLVE , i18n("Dissolve")));
m_map.insert(m_categories[5], KoID(COMPOSITE_COPY_RED , i18n("Copy Red")));
m_map.insert(m_categories[5], KoID(COMPOSITE_COPY_GREEN, i18n("Copy Green")));
m_map.insert(m_categories[5], KoID(COMPOSITE_COPY_BLUE , i18n("Copy Blue")));
m_map.insert(m_categories[5], KoID(COMPOSITE_COPY , i18n("Copy")));
m_map.insert(m_categories[5], KoID(COMPOSITE_TANGENT_NORMALMAP, i18n("Tangent Normalmap")));
m_map.insert(m_categories[6], KoID(COMPOSITE_COLOR , i18n("Color")));
m_map.insert(m_categories[6], KoID(COMPOSITE_HUE , i18n("Hue")));
m_map.insert(m_categories[6], KoID(COMPOSITE_SATURATION , i18n("Saturation")));
m_map.insert(m_categories[6], KoID(COMPOSITE_LUMINIZE , i18n("Luminosity")));
m_map.insert(m_categories[6], KoID(COMPOSITE_DEC_SATURATION, i18n("Decrease Saturation")));
m_map.insert(m_categories[6], KoID(COMPOSITE_INC_SATURATION, i18n("Increase Saturation")));
m_map.insert(m_categories[6], KoID(COMPOSITE_DEC_LUMINOSITY, i18n("Decrease Luminosity")));
m_map.insert(m_categories[6], KoID(COMPOSITE_INC_LUMINOSITY, i18n("Increase Luminosity")));
m_map.insert(m_categories[7], KoID(COMPOSITE_COLOR_HSI , i18n("Color HSI")));
m_map.insert(m_categories[7], KoID(COMPOSITE_HUE_HSI , i18n("Hue HSI")));
m_map.insert(m_categories[7], KoID(COMPOSITE_SATURATION_HSI , i18n("Saturation HSI")));
m_map.insert(m_categories[7], KoID(COMPOSITE_INTENSITY , i18n("Intensity")));
m_map.insert(m_categories[7], KoID(COMPOSITE_DEC_SATURATION_HSI, i18n("Decrease Saturation HSI")));
m_map.insert(m_categories[7], KoID(COMPOSITE_INC_SATURATION_HSI, i18n("Increase Saturation HSI")));
m_map.insert(m_categories[7], KoID(COMPOSITE_DEC_INTENSITY , i18n("Decrease Intensity")));
m_map.insert(m_categories[7], KoID(COMPOSITE_INC_INTENSITY , i18n("Increase Intensity")));
m_map.insert(m_categories[8], KoID(COMPOSITE_COLOR_HSL , i18n("Color HSL")));
m_map.insert(m_categories[8], KoID(COMPOSITE_HUE_HSL , i18n("Hue HSL")));
m_map.insert(m_categories[8], KoID(COMPOSITE_SATURATION_HSL , i18n("Saturation HSL")));
m_map.insert(m_categories[8], KoID(COMPOSITE_LIGHTNESS , i18n("Lightness")));
m_map.insert(m_categories[8], KoID(COMPOSITE_DEC_SATURATION_HSL, i18n("Decrease Saturation HSL")));
m_map.insert(m_categories[8], KoID(COMPOSITE_INC_SATURATION_HSL, i18n("Increase Saturation HSL")));
m_map.insert(m_categories[8], KoID(COMPOSITE_DEC_LIGHTNESS , i18n("Decrease Lightness")));
m_map.insert(m_categories[8], KoID(COMPOSITE_INC_LIGHTNESS , i18n("Increase Lightness")));
m_map.insert(m_categories[9], KoID(COMPOSITE_COLOR_HSV , i18n("Color HSV")));
m_map.insert(m_categories[9], KoID(COMPOSITE_HUE_HSV , i18n("Hue HSV")));
m_map.insert(m_categories[9], KoID(COMPOSITE_SATURATION_HSV , i18n("Saturation HSV")));
m_map.insert(m_categories[9], KoID(COMPOSITE_VALUE , i18nc("HSV Value", "Value")));
m_map.insert(m_categories[9], KoID(COMPOSITE_DEC_SATURATION_HSV, i18n("Decrease Saturation HSV")));
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")));
m_map.insert(m_categories[1], KoID(COMPOSITE_XOR , i18n("XOR")));
m_map.insert(m_categories[1], KoID(COMPOSITE_OR , i18n("OR")));
m_map.insert(m_categories[1], KoID(COMPOSITE_AND , i18n("AND")));
m_map.insert(m_categories[1], KoID(COMPOSITE_NAND , i18n("NAND")));
m_map.insert(m_categories[1], KoID(COMPOSITE_NOR , i18n("NOR")));
m_map.insert(m_categories[1], KoID(COMPOSITE_XNOR , i18n("XNOR")));
m_map.insert(m_categories[1], KoID(COMPOSITE_IMPLICATION , i18n("IMPLICATION")));
m_map.insert(m_categories[1], KoID(COMPOSITE_NOT_IMPLICATION , i18n("NOT IMPLICATION")));
m_map.insert(m_categories[1], KoID(COMPOSITE_CONVERSE , i18n("CONVERSE")));
m_map.insert(m_categories[1], KoID(COMPOSITE_NOT_CONVERSE , i18n("NOT CONVERSE")));
m_map.insert(m_categories[2], KoID(COMPOSITE_BURN , i18n("Burn")));
m_map.insert(m_categories[2], KoID(COMPOSITE_BURN_LOGARITHMIC , i18n("Burn - Logarithmic")));
m_map.insert(m_categories[2], KoID(COMPOSITE_LINEAR_BURN, i18n("Linear Burn")));
m_map.insert(m_categories[2], KoID(COMPOSITE_DARKEN , i18n("Darken")));
m_map.insert(m_categories[2], KoID(COMPOSITE_GAMMA_DARK , i18n("Gamma Dark")));
m_map.insert(m_categories[2], KoID(COMPOSITE_DARKER_COLOR , i18n("Darker Color")));
m_map.insert(m_categories[2], KoID(COMPOSITE_SHADE_IFS_ILLUSIONS, i18n("Shade (IFS Illusions)")));
m_map.insert(m_categories[2], KoID(COMPOSITE_FOG_DARKEN_IFS_ILLUSIONS, i18n("Fog Darken (IFS Illusions)")));
m_map.insert(m_categories[2], KoID(COMPOSITE_EASY_BURN , i18n("Easy Burn")));
m_map.insert(m_categories[3], KoID(COMPOSITE_DODGE , i18n("Color Dodge")));
m_map.insert(m_categories[3], KoID(COMPOSITE_DODGE_LOGARITHMIC , i18n("Color Dodge - Logarithmic")));
m_map.insert(m_categories[3], KoID(COMPOSITE_LINEAR_DODGE, i18n("Linear Dodge")));
m_map.insert(m_categories[3], KoID(COMPOSITE_LIGHTEN , i18n("Lighten")));
m_map.insert(m_categories[3], KoID(COMPOSITE_LINEAR_LIGHT, i18n("Linear Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_SCREEN , i18n("Screen")));
m_map.insert(m_categories[3], KoID(COMPOSITE_PIN_LIGHT , i18n("Pin Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_VIVID_LIGHT , i18n("Vivid Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_FLAT_LIGHT , i18n("Flat Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_HARD_LIGHT , i18n("Hard Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_SOFT_LIGHT_IFS_ILLUSIONS, i18n("Soft Light (IFS Illusions)")));
m_map.insert(m_categories[3], KoID(COMPOSITE_SOFT_LIGHT_PEGTOP_DELPHI, i18n("Soft Light (Pegtop-Delphi)")));
m_map.insert(m_categories[3], KoID(COMPOSITE_SOFT_LIGHT_PHOTOSHOP, i18n("Soft Light (Photoshop)")));
m_map.insert(m_categories[3], KoID(COMPOSITE_SOFT_LIGHT_SVG, i18n("Soft Light (SVG)")));
m_map.insert(m_categories[3], KoID(COMPOSITE_GAMMA_LIGHT , i18n("Gamma Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_GAMMA_ILLUMINATION , i18n("Gamma Illumination")));
m_map.insert(m_categories[3], KoID(COMPOSITE_LIGHTER_COLOR , i18n("Lighter Color")));
m_map.insert(m_categories[3], KoID(COMPOSITE_PNORM_A , i18n("P-Norm A")));
m_map.insert(m_categories[3], KoID(COMPOSITE_PNORM_B , i18n("P-Norm B")));
m_map.insert(m_categories[3], KoID(COMPOSITE_SUPER_LIGHT , i18n("Super Light")));
m_map.insert(m_categories[3], KoID(COMPOSITE_TINT_IFS_ILLUSIONS, i18n("Tint (IFS Illusions)")));
m_map.insert(m_categories[3], KoID(COMPOSITE_FOG_LIGHTEN_IFS_ILLUSIONS, i18n("Fog Lighten (IFS Illusions)")));
m_map.insert(m_categories[3], KoID(COMPOSITE_EASY_DODGE , i18n("Easy Dodge")));
m_map.insert(m_categories[4], KoID(COMPOSITE_MOD , i18n("Modulo")));
m_map.insert(m_categories[4], KoID(COMPOSITE_MOD_CON , i18n("Modulo - Continuous")));
m_map.insert(m_categories[4], KoID(COMPOSITE_DIVISIVE_MOD , i18n("Divisive Modulo")));
m_map.insert(m_categories[4], KoID(COMPOSITE_DIVISIVE_MOD_CON , i18n("Divisive Modulo - Continuous")));
m_map.insert(m_categories[4], KoID(COMPOSITE_MODULO_SHIFT , i18n("Modulo Shift")));
m_map.insert(m_categories[4], KoID(COMPOSITE_MODULO_SHIFT_CON , i18n("Modulo Shift - Continuous")));
m_map.insert(m_categories[5], KoID(COMPOSITE_DIFF , i18n("Difference")));
m_map.insert(m_categories[5], KoID(COMPOSITE_EQUIVALENCE , i18n("Equivalence")));
m_map.insert(m_categories[5], KoID(COMPOSITE_ADDITIVE_SUBTRACTIVE , i18n("Additive Subtractive")));
m_map.insert(m_categories[5], KoID(COMPOSITE_EXCLUSION , i18n("Exclusion")));
m_map.insert(m_categories[5], KoID(COMPOSITE_ARC_TANGENT , i18n("Arcus Tangent")));
m_map.insert(m_categories[5], KoID(COMPOSITE_NEGATION , i18n("Negation")));
m_map.insert(m_categories[6], KoID(COMPOSITE_OVER , i18n("Normal")));
m_map.insert(m_categories[6], KoID(COMPOSITE_BEHIND , i18n("Behind")));
m_map.insert(m_categories[6], KoID(COMPOSITE_GREATER , i18n("Greater")));
m_map.insert(m_categories[6], KoID(COMPOSITE_OVERLAY , i18n("Overlay")));
m_map.insert(m_categories[6], KoID(COMPOSITE_ERASE , i18n("Erase")));
m_map.insert(m_categories[6], KoID(COMPOSITE_ALPHA_DARKEN , i18n("Alpha Darken")));
m_map.insert(m_categories[6], KoID(COMPOSITE_HARD_MIX , i18n("Hard Mix")));
m_map.insert(m_categories[6], KoID(COMPOSITE_HARD_MIX_PHOTOSHOP, i18n("Hard Mix (Photoshop)")));
m_map.insert(m_categories[6], KoID(COMPOSITE_GRAIN_MERGE , i18n("Grain Merge")));
m_map.insert(m_categories[6], KoID(COMPOSITE_GRAIN_EXTRACT , i18n("Grain Extract")));
m_map.insert(m_categories[6], KoID(COMPOSITE_PARALLEL , i18n("Parallel")));
m_map.insert(m_categories[6], KoID(COMPOSITE_ALLANON , i18n("Allanon")));
m_map.insert(m_categories[6], KoID(COMPOSITE_GEOMETRIC_MEAN , i18n("Geometric Mean")));
m_map.insert(m_categories[6], KoID(COMPOSITE_DESTINATION_ATOP, i18n("Destination Atop")));
m_map.insert(m_categories[6], KoID(COMPOSITE_DESTINATION_IN , i18n("Destination In")));
m_map.insert(m_categories[6], KoID(COMPOSITE_HARD_OVERLAY , i18n("Hard Overlay")));
m_map.insert(m_categories[6], KoID(COMPOSITE_INTERPOLATION , i18n("Interpolation")));
m_map.insert(m_categories[6], KoID(COMPOSITE_INTERPOLATIONB , i18n("Interpolation - 2X")));
m_map.insert(m_categories[6], KoID(COMPOSITE_PENUMBRAA , i18n("Penumbra A")));
m_map.insert(m_categories[6], KoID(COMPOSITE_PENUMBRAB , i18n("Penumbra B")));
m_map.insert(m_categories[6], KoID(COMPOSITE_PENUMBRAC , i18n("Penumbra C")));
m_map.insert(m_categories[6], KoID(COMPOSITE_PENUMBRAD , i18n("Penumbra D")));
m_map.insert(m_categories[7], KoID(COMPOSITE_BUMPMAP , i18n("Bumpmap")));
m_map.insert(m_categories[7], KoID(COMPOSITE_COMBINE_NORMAL, i18n("Combine Normal Map")));
m_map.insert(m_categories[7], KoID(COMPOSITE_DISSOLVE , i18n("Dissolve")));
m_map.insert(m_categories[7], KoID(COMPOSITE_COPY_RED , i18n("Copy Red")));
m_map.insert(m_categories[7], KoID(COMPOSITE_COPY_GREEN, i18n("Copy Green")));
m_map.insert(m_categories[7], KoID(COMPOSITE_COPY_BLUE , i18n("Copy Blue")));
m_map.insert(m_categories[7], KoID(COMPOSITE_COPY , i18n("Copy")));
m_map.insert(m_categories[7], KoID(COMPOSITE_TANGENT_NORMALMAP, i18n("Tangent Normalmap")));
m_map.insert(m_categories[8], KoID(COMPOSITE_COLOR , i18n("Color")));
m_map.insert(m_categories[8], KoID(COMPOSITE_HUE , i18n("Hue")));
m_map.insert(m_categories[8], KoID(COMPOSITE_SATURATION , i18n("Saturation")));
m_map.insert(m_categories[8], KoID(COMPOSITE_LUMINIZE , i18n("Luminosity")));
m_map.insert(m_categories[8], KoID(COMPOSITE_DEC_SATURATION, i18n("Decrease Saturation")));
m_map.insert(m_categories[8], KoID(COMPOSITE_INC_SATURATION, i18n("Increase Saturation")));
m_map.insert(m_categories[8], KoID(COMPOSITE_DEC_LUMINOSITY, i18n("Decrease Luminosity")));
m_map.insert(m_categories[8], KoID(COMPOSITE_INC_LUMINOSITY, i18n("Increase Luminosity")));
m_map.insert(m_categories[9], KoID(COMPOSITE_COLOR_HSI , i18n("Color HSI")));
m_map.insert(m_categories[9], KoID(COMPOSITE_HUE_HSI , i18n("Hue HSI")));
m_map.insert(m_categories[9], KoID(COMPOSITE_SATURATION_HSI , i18n("Saturation HSI")));
m_map.insert(m_categories[9], KoID(COMPOSITE_INTENSITY , i18n("Intensity")));
m_map.insert(m_categories[9], KoID(COMPOSITE_DEC_SATURATION_HSI, i18n("Decrease Saturation HSI")));
m_map.insert(m_categories[9], KoID(COMPOSITE_INC_SATURATION_HSI, i18n("Increase Saturation HSI")));
m_map.insert(m_categories[9], KoID(COMPOSITE_DEC_INTENSITY , i18n("Decrease Intensity")));
m_map.insert(m_categories[9], KoID(COMPOSITE_INC_INTENSITY , i18n("Increase Intensity")));
m_map.insert(m_categories[10], KoID(COMPOSITE_COLOR_HSL , i18n("Color HSL")));
m_map.insert(m_categories[10], KoID(COMPOSITE_HUE_HSL , i18n("Hue HSL")));
m_map.insert(m_categories[10], KoID(COMPOSITE_SATURATION_HSL , i18n("Saturation HSL")));
m_map.insert(m_categories[10], KoID(COMPOSITE_LIGHTNESS , i18n("Lightness")));
m_map.insert(m_categories[10], KoID(COMPOSITE_DEC_SATURATION_HSL, i18n("Decrease Saturation HSL")));
m_map.insert(m_categories[10], KoID(COMPOSITE_INC_SATURATION_HSL, i18n("Increase Saturation HSL")));
m_map.insert(m_categories[10], KoID(COMPOSITE_DEC_LIGHTNESS , i18n("Decrease Lightness")));
m_map.insert(m_categories[10], KoID(COMPOSITE_INC_LIGHTNESS , i18n("Increase Lightness")));
m_map.insert(m_categories[11], KoID(COMPOSITE_COLOR_HSV , i18n("Color HSV")));
m_map.insert(m_categories[11], KoID(COMPOSITE_HUE_HSV , i18n("Hue HSV")));
m_map.insert(m_categories[11], KoID(COMPOSITE_SATURATION_HSV , i18n("Saturation HSV")));
m_map.insert(m_categories[11], KoID(COMPOSITE_VALUE , i18nc("HSV Value", "Value")));
m_map.insert(m_categories[11], KoID(COMPOSITE_DEC_SATURATION_HSV, i18n("Decrease Saturation HSV")));
m_map.insert(m_categories[11], KoID(COMPOSITE_INC_SATURATION_HSV, i18n("Increase Saturation HSV")));
m_map.insert(m_categories[11], KoID(COMPOSITE_DEC_VALUE , i18n("Decrease Value")));
m_map.insert(m_categories[11], KoID(COMPOSITE_INC_VALUE , i18n("Increase Value")));
m_map.insert(m_categories[12], KoID(COMPOSITE_REFLECT , i18n("Reflect")));
m_map.insert(m_categories[12], KoID(COMPOSITE_GLOW , i18n("Glow")));
m_map.insert(m_categories[12], KoID(COMPOSITE_FREEZE , i18n("Freeze")));
m_map.insert(m_categories[12], KoID(COMPOSITE_HEAT , i18n("Heat")));
m_map.insert(m_categories[12], KoID(COMPOSITE_GLEAT , i18n("Glow-Heat")));
m_map.insert(m_categories[12], KoID(COMPOSITE_HELOW , i18n("Heat-Glow")));
m_map.insert(m_categories[12], KoID(COMPOSITE_REEZE , i18n("Reflect-Freeze")));
m_map.insert(m_categories[12], KoID(COMPOSITE_FRECT , i18n("Freeze-Reflect")));
m_map.insert(m_categories[12], KoID(COMPOSITE_FHYRD , i18n("Heat-Glow & Freeze-Reflect Hybrid")));
}
const KoCompositeOpRegistry& KoCompositeOpRegistry::instance()
......
......@@ -42,6 +42,16 @@ const QString COMPOSITE_DESTINATION_IN = "destination-in";
const QString COMPOSITE_DESTINATION_ATOP = "destination-atop";
const QString COMPOSITE_XOR = "xor";
const QString COMPOSITE_OR = "or";
const QString COMPOSITE_AND = "and";
const QString COMPOSITE_NAND = "nand";
const QString COMPOSITE_NOR = "nor";
const QString COMPOSITE_XNOR = "xnor";
const QString COMPOSITE_IMPLICATION = "implication";
const QString COMPOSITE_NOT_IMPLICATION = "not_implication";
const QString COMPOSITE_CONVERSE = "converse";
const QString COMPOSITE_NOT_CONVERSE = "not_converse";
const QString COMPOSITE_PLUS = "plus";
const QString COMPOSITE_MINUS = "minus";
const QString COMPOSITE_ADD = "add";
......@@ -53,6 +63,14 @@ const QString COMPOSITE_DIVIDE = "divide";
const QString COMPOSITE_ARC_TANGENT = "arc_tangent";
const QString COMPOSITE_GEOMETRIC_MEAN = "geometric_mean";
const QString COMPOSITE_ADDITIVE_SUBTRACTIVE = "additive_subtractive";
const QString COMPOSITE_NEGATION = "negation";
const QString COMPOSITE_MOD = "modulo";
const QString COMPOSITE_MOD_CON = "modulo_continuous";
const QString COMPOSITE_DIVISIVE_MOD = "divisive_modulo";
const QString COMPOSITE_DIVISIVE_MOD_CON = "divisive_modulo_continuous";
const QString COMPOSITE_MODULO_SHIFT = "modulo_shift";
const QString COMPOSITE_MODULO_SHIFT_CON = "modulo_shift_continuous";
const QString COMPOSITE_EQUIVALENCE = "equivalence";
const QString COMPOSITE_ALLANON = "allanon";
......@@ -66,23 +84,44 @@ const QString COMPOSITE_OVERLAY = "overlay";
const QString COMPOSITE_BEHIND = "behind";
const QString COMPOSITE_GREATER = "greater";
const QString COMPOSITE_HARD_OVERLAY = "hard overlay";
const QString COMPOSITE_INTERPOLATION = "interpolation";
const QString COMPOSITE_INTERPOLATIONB = "interpolation 2x";
const QString COMPOSITE_PENUMBRAA = "penumbra a";
const QString COMPOSITE_PENUMBRAB = "penumbra b";
const QString COMPOSITE_PENUMBRAC = "penumbra c";
const QString COMPOSITE_PENUMBRAD = "penumbra d";
const QString COMPOSITE_DARKEN = "darken";
const QString COMPOSITE_BURN = "burn";//this is also known as 'color burn'.
const QString COMPOSITE_BURN_LOGARITHMIC = "burn_logarithmic";
const QString COMPOSITE_LINEAR_BURN = "linear_burn";
const QString COMPOSITE_GAMMA_DARK = "gamma_dark";
const QString COMPOSITE_SHADE_IFS_ILLUSIONS = "shade_ifs_illusions";
const QString COMPOSITE_FOG_DARKEN_IFS_ILLUSIONS = "fog_darken_ifs_illusions";
const QString COMPOSITE_EASY_BURN = "easy burn";
const QString COMPOSITE_LIGHTEN = "lighten";
const QString COMPOSITE_DODGE = "dodge";
const QString COMPOSITE_DODGE_LOGARITHMIC = "dodge_logarithmic";
const QString COMPOSITE_LINEAR_DODGE = "linear_dodge";
const QString COMPOSITE_SCREEN = "screen";
const QString COMPOSITE_HARD_LIGHT = "hard_light";
const QString COMPOSITE_SOFT_LIGHT_IFS_ILLUSIONS = "soft_light_ifs_illusions";
const QString COMPOSITE_SOFT_LIGHT_PEGTOP_DELPHI = "soft_light_pegtop_delphi";
const QString COMPOSITE_SOFT_LIGHT_PHOTOSHOP = "soft_light";
const QString COMPOSITE_SOFT_LIGHT_SVG = "soft_light_svg";
const QString COMPOSITE_GAMMA_LIGHT = "gamma_light";
const QString COMPOSITE_GAMMA_ILLUMINATION = "gamma_illumination";
const QString COMPOSITE_VIVID_LIGHT = "vivid_light";
const QString COMPOSITE_FLAT_LIGHT = "flat_light";
const QString COMPOSITE_LINEAR_LIGHT = "linear light";
const QString COMPOSITE_PIN_LIGHT = "pin_light";
const QString COMPOSITE_PNORM_A = "pnorm_a";
const QString COMPOSITE_PNORM_B = "pnorm_b";
const QString COMPOSITE_SUPER_LIGHT = "super_light";
const QString COMPOSITE_TINT_IFS_ILLUSIONS = "tint_ifs_illusions";
const QString COMPOSITE_FOG_LIGHTEN_IFS_ILLUSIONS = "fog_lighten_ifs_illusions";
const QString COMPOSITE_EASY_DODGE = "easy dodge";
const QString COMPOSITE_HUE = "hue";
const QString COMPOSITE_COLOR = "color";
......@@ -142,6 +181,11 @@ const QString COMPOSITE_REFLECT = "reflect";
const QString COMPOSITE_GLOW = "glow";
const QString COMPOSITE_FREEZE = "freeze";
const QString COMPOSITE_HEAT = "heat";
const QString COMPOSITE_GLEAT = "glow_heat";
const QString COMPOSITE_HELOW = "heat_glow";
const QString COMPOSITE_REEZE = "reflect_freeze";
const QString COMPOSITE_FRECT = "freeze_reflect";
const QString COMPOSITE_FHYRD = "heat_glow_freeze_reflect_hybrid";
......
......@@ -176,13 +176,14 @@ inline T cfLinearBurn(T src, T dst) {
template<class T>
inline T cfColorDodge(T src, T dst) {
using namespace Arithmetic;
//Fixing Color Dodge to avoid ZX Colors on bright area.
if(dst == zeroValue<T>())
return zeroValue<T>();
if(src == unitValue<T>())
return unitValue<T>();
T invSrc = inv(src);
if(invSrc < dst)
if(invSrc == zeroValue<T>())
return unitValue<T>();
return Arithmetic::clamp<T>(div(dst, invSrc));
......@@ -348,6 +349,14 @@ inline T cfParallel(T src, T dst) {
composite_type unit = unitValue<T>();
composite_type s = (src != zeroValue<T>()) ? div<T>(unit, src) : unit;
composite_type d = (dst != zeroValue<T>()) ? div<T>(unit, dst) : unit;
if (src == zeroValue<T>()) {
return zeroValue<T>();
}
if (dst == zeroValue<T>()) {
return zeroValue<T>();
}
return clamp<T>((unit+unit) * unit / (d+s));
}
......@@ -413,6 +422,12 @@ inline T cfGammaLight(T src, T dst) {
return scale<T>(pow(scale<qreal>(dst), scale<qreal>(src)));
}
template<class T>
inline T cfGammaIllumination(T src, T dst) {
using namespace Arithmetic;
return inv(cfGammaDark(inv(src),inv(dst)));
}
template<class T>
inline T cfGeometricMean(T src, T dst) {
using namespace Arithmetic;
......@@ -435,6 +450,9 @@ inline T cfHardOverlay(T src, T dst) {
qreal fsrc = scale<qreal>(src);
qreal fdst = scale<qreal>(dst);
if (fsrc == 1.0) {
return scale<T>(1.0);}
if(fsrc > 0.5f) {
return scale<T>(cfDivide(inv(2.0 * fsrc - 1.0f), fdst));
}
......@@ -458,14 +476,10 @@ 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<T>()) {
if (dst == unitValue<T>()) {
return unitValue<T>();
}
if(src == zeroValue<T>()) {
return zeroValue<T>();
}
return clamp<T>(div(mul(src, src), inv(dst)));
}
......@@ -473,31 +487,473 @@ template<class T>
inline T cfReflect(T src, T dst) {
using namespace Arithmetic;
return (cfGlow(dst,src));
return clamp<T>(cfGlow(dst,src));
}
template<class T>
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(src == unitValue<T>()) {
return unitValue<T>();
}
if(dst == zeroValue<T>()) {
return zeroValue<T>();
}
if(src == unitValue<T>()) {
return inv(clamp<T>(div(mul(inv(src), inv(src)),dst)));
}
template<class T>
inline T cfFreeze(T src, T dst) {
using namespace Arithmetic;
return (cfHeat(dst,src));
}
template<class T>
inline T cfHelow(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 (cfHardMixPhotoshop(src,dst) == unitValue<T>()) {
return cfHeat(src,dst);
}
if (src == zeroValue<T>()) {
return zeroValue<T>();
}
return (cfGlow(src,dst));
}
template<class T>
inline T cfFrect(T src, T dst) {
using namespace Arithmetic;
if (cfHardMixPhotoshop(src,dst) == unitValue<T>()) {
return cfFreeze(src,dst);
}
if (dst == zeroValue<T>()) {
return zeroValue<T>();
}
return (cfReflect(src,dst));
}
template<class T>
inline T cfGleat(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<T>()) {
return unitValue<T>();
}
return inv(clamp<T>(div(mul(inv(src), inv(src)),dst)));
if(cfHardMixPhotoshop(src,dst) == unitValue<T>()) {
return cfGlow(src,dst);
}
return (cfHeat(src,dst));
}
template<class T>
inline T cfFreeze(T src, T dst) {
inline T cfReeze(T src, T dst) {
using namespace Arithmetic;
return (cfGleat(dst,src));
}
template<class T>
inline T cfFhyrd(T src, T dst) {
using namespace Arithmetic;
return (cfAllanon(cfFrect(src,dst),cfHelow(src,dst)));
}
template<class T>
inline T cfInterpolation(T src, T dst) {
using namespace Arithmetic;
qreal fsrc = scale<qreal>(src);
qreal fdst = scale<qreal>(dst);
if(dst == zeroValue<T>() && src == zeroValue<T>()) {
return zeroValue<T>();
}
return scale<T>(.5f-.25f*cos(pi*(fsrc))-.25f*cos(pi*(fdst)));
}
template<class T>
inline T cfInterpolationB(T src, T dst) {
using namespace Arithmetic;
return cfInterpolation(cfInterpolation(src,dst),cfInterpolation(src,dst));
}
template<class T>
inline T cfPenumbraB(T src, T dst) {
using namespace Arithmetic;
if (dst == unitValue<T>()) {
return unitValue<T>();
}
if (dst + src < unitValue<T>()) {
return (cfColorDodge(dst,src)/2);
}
if (src == zeroValue<T>()) {
return zeroValue<T>();
}
return inv(clamp<T>(div(inv(dst),src)/2));
}
template<class T>
inline T cfPenumbraD(T src, T dst) {
using namespace Arithmetic;
if (dst ==