File indexing completed on 2024-12-22 04:11:38

0001 /*
0002  *  SPDX-FileCopyrightText: 2006, 2010 Cyrille Berger <cberger@cberger.net>
0003  *  SPDX-FileCopyrightText: 2007 Emanuele Tamponi <emanuele@valinor.it>
0004  *  SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
0005  *  SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
0006  *
0007  * SPDX-License-Identifier: LGPL-2.1-or-later
0008 */
0009 
0010 #ifndef KO_COMPOSITEOP_COPY2_H
0011 #define KO_COMPOSITEOP_COPY2_H
0012 
0013 #include "KoCompositeOpBase.h"
0014 
0015 /**
0016  * Generic implementation of the COPY composite op which respects selection.
0017  *
0018  * Note: this composite op is necessary with the deform brush and should not
0019  * be hidden.
0020  */
0021 template<class Traits>
0022 class KoCompositeOpCopy2: public KoCompositeOpBase< Traits, KoCompositeOpCopy2<Traits> >
0023 {
0024     typedef KoCompositeOpBase< Traits, KoCompositeOpCopy2<Traits> > base_class;
0025     typedef typename Traits::channels_type                          channels_type;
0026 
0027     static const qint32 channels_nb = Traits::channels_nb;
0028     static const qint32 alpha_pos   = Traits::alpha_pos;
0029 
0030 public:
0031     KoCompositeOpCopy2(const KoColorSpace* cs)
0032         : base_class(cs, COMPOSITE_COPY, KoCompositeOp::categoryMisc()) { }
0033 
0034 public:
0035     template<bool alphaLocked, bool allChannelFlags>
0036     inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
0037                                                      channels_type*       dst, channels_type dstAlpha, channels_type maskAlpha,
0038                                                      channels_type opacity, const QBitArray& channelFlags) {
0039         using namespace Arithmetic;
0040         opacity = mul(maskAlpha, opacity);
0041 
0042         channels_type newAlpha = zeroValue<channels_type>();
0043 
0044         if (opacity == unitValue<channels_type>()) {
0045             if (!alphaLocked || srcAlpha != zeroValue<channels_type>()) {
0046                 // don't blend if the color of the destination is undefined (has zero opacity)
0047                 // copy the source channel instead
0048                 for(qint32 i=0; i<channels_nb; ++i)
0049                     if(i != alpha_pos && (allChannelFlags || channelFlags.testBit(i)))
0050                         dst[i] = src[i];
0051             }
0052 
0053             newAlpha = srcAlpha;
0054 
0055         } else if (opacity == zeroValue<channels_type>()) {
0056 
0057             newAlpha = dstAlpha;
0058 
0059         } else { // opacity 0...1
0060 
0061             if (!alphaLocked || srcAlpha != zeroValue<channels_type>()) {
0062 
0063                 newAlpha = lerp(dstAlpha, srcAlpha, opacity);
0064 
0065                 if (newAlpha == zeroValue<channels_type>()) {
0066                     return newAlpha;
0067                 }
0068 
0069                 // blend the color channels
0070                 for(qint32 i=0; i<channels_nb; ++i) {
0071                     if(i != alpha_pos && (allChannelFlags || channelFlags.testBit(i))) {
0072 
0073                         // We use the most fundamental OVER algorithm here,
0074                         // which multiplies, blends and then unmultiplies the
0075                         // channels
0076 
0077                         typedef typename KoColorSpaceMathsTraits<channels_type>::compositetype composite_type;
0078 
0079                         channels_type dstMult = mul(dst[i], dstAlpha);
0080                         channels_type srcMult = mul(src[i], srcAlpha);
0081                         channels_type blendedValue = lerp(dstMult, srcMult, opacity);
0082 
0083                         composite_type normedValue = KoColorSpaceMaths<channels_type>::divide(blendedValue, newAlpha);
0084 
0085                         dst[i] = KoColorSpaceMaths<channels_type>::clampAfterScale(normedValue);
0086                     }
0087                 }
0088             }
0089 
0090         }
0091 
0092         return newAlpha;
0093     }
0094 };
0095 
0096 #endif // KO_COMPOSITEOP_COPY2_H