File indexing completed on 2024-05-26 04:29:13
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Nicholas Guttenberg <ngutten@gmail.com> 0003 * 0004 * Based on KoCompositeOpBehind.h, 0005 * SPDX-FileCopyrightText: 2012 José Luis Vergara <pentalis@gmail.com> 0006 * 0007 * SPDX-License-Identifier: LGPL-2.0-or-later 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public License 0015 * along with this library; see the file COPYING.LIB. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #ifndef _KOCOMPOSITEOPGREATER_H_ 0021 #define _KOCOMPOSITEOPGREATER_H_ 0022 0023 #include "KoCompositeOpBase.h" 0024 0025 /** 0026 * Greater-than compositor - uses the greater of two alpha values to determine the color 0027 */ 0028 template<class CS_Traits, typename BlendingPolicy> 0029 class KoCompositeOpGreater : public KoCompositeOpBase<CS_Traits, KoCompositeOpGreater<CS_Traits, BlendingPolicy>> 0030 { 0031 typedef KoCompositeOpBase<CS_Traits, KoCompositeOpGreater<CS_Traits, BlendingPolicy>> base_class; 0032 typedef typename CS_Traits::channels_type channels_type; 0033 typedef typename KoColorSpaceMathsTraits<typename CS_Traits::channels_type>::compositetype composite_type; 0034 0035 static const qint8 channels_nb = CS_Traits::channels_nb; 0036 static const qint8 alpha_pos = CS_Traits::alpha_pos; 0037 0038 public: 0039 KoCompositeOpGreater(const KoColorSpace * cs) 0040 : base_class(cs, COMPOSITE_GREATER, KoCompositeOp::categoryMix()) { } 0041 0042 public: 0043 template<bool alphaLocked, bool allChannelFlags> 0044 inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha, 0045 channels_type* dst, channels_type dstAlpha, 0046 channels_type maskAlpha, channels_type opacity, 0047 const QBitArray& channelFlags ) { 0048 using namespace Arithmetic; 0049 0050 if (dstAlpha == unitValue<channels_type>()) return dstAlpha; 0051 channels_type appliedAlpha = mul(maskAlpha, srcAlpha, opacity); 0052 0053 if (appliedAlpha == zeroValue<channels_type>()) return dstAlpha; 0054 channels_type newDstAlpha; 0055 0056 float dA = scale<float>(dstAlpha); 0057 0058 float w = 1.0/(1.0+exp(-40.0*(dA - scale<float>(appliedAlpha)))); 0059 float a = dA*w + scale<float>(appliedAlpha)*(1.0-w); 0060 if (a < 0.0f) { 0061 a = 0.0f; 0062 } 0063 if (a > 1.0f) { 0064 a = 1.0f; 0065 } 0066 0067 // For a standard Over, the resulting alpha is: a = opacity*dstAlpha + (1-opacity)*srcAlpha 0068 // Let us assume we're blending with a color with srcAlpha = 1 here 0069 // Therefore, opacity = (1.0 - a)/(1.0 - dstAlpha) 0070 if (a<dA) a = dA; 0071 float fakeOpacity = 1.0f - (1.0f - a)/(1.0f - dA + 1e-16f); 0072 newDstAlpha=scale<channels_type>(a); 0073 0074 if (dstAlpha != zeroValue<channels_type>()) { 0075 for (qint8 channel = 0; channel < channels_nb; ++channel) 0076 if(channel != alpha_pos && (allChannelFlags || channelFlags.testBit(channel))) 0077 { 0078 typedef typename KoColorSpaceMathsTraits<channels_type>::compositetype composite_type; 0079 0080 channels_type dstMult = mul(BlendingPolicy::toAdditiveSpace(dst[channel]), dstAlpha); 0081 channels_type srcMult = mul(BlendingPolicy::toAdditiveSpace(src[channel]), unitValue<channels_type>()); 0082 channels_type blendedValue = lerp(dstMult, srcMult, scale<channels_type>(fakeOpacity)); 0083 // CID 249016 (#1 of 15): 0084 // Division or modulo by zero (DIVIDE_BY_ZERO)12. divide_by_zero: In function call divide, division by expression newDstAlpha which may be zero has undefined behavior. 0085 if (newDstAlpha == 0) newDstAlpha = 1; 0086 composite_type normedValue = KoColorSpaceMaths<channels_type>::divide(blendedValue, newDstAlpha); 0087 0088 dst[channel] = BlendingPolicy::fromAdditiveSpace(KoColorSpaceMaths<channels_type>::clampAfterScale(normedValue)); 0089 } 0090 } 0091 else { 0092 // don't blend if the color of the destination is undefined (has zero opacity) 0093 // copy the source channel instead 0094 for (qint8 channel = 0; channel < channels_nb; ++channel) 0095 if(channel != alpha_pos && (allChannelFlags || channelFlags.testBit(channel))) 0096 dst[channel] = src[channel]; 0097 } 0098 0099 return newDstAlpha; 0100 } 0101 }; 0102 0103 #endif // _KOCOMPOSITEOPGREATER_H_