File indexing completed on 2025-03-09 04:08:37

0001 /*
0002  *  SPDX-FileCopyrightText: 2006 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #ifndef RGBCOMPOSITEOPOUT_H
0008 #define RGBCOMPOSITEOPOUT_H
0009 
0010 #include <KoCompositeOp.h>
0011 
0012 #define SCALE_TO_FLOAT( v ) KoColorSpaceMaths< channels_type, float>::scaleToA( v )
0013 #define SCALE_FROM_FLOAT( v ) KoColorSpaceMaths< float, channels_type>::scaleToA( v )
0014 
0015 template<class _CSTraits>
0016 class RgbCompositeOpOut : public KoCompositeOp
0017 {
0018     typedef typename _CSTraits::channels_type channels_type;
0019     typedef typename KoColorSpaceMathsTraits<typename _CSTraits::channels_type>::compositetype compositetype;
0020 
0021 public:
0022 
0023     RgbCompositeOpOut(KoColorSpace *cs)
0024         : KoCompositeOp(cs, COMPOSITE_OUT)
0025     {
0026     }
0027 
0028     using KoCompositeOp::composite;
0029 
0030     void composite(quint8 *dstRowStart, qint32 dstRowStride,
0031                    const quint8 *srcRowStart, qint32 srcRowStride,
0032                    const quint8 *maskRowStart, qint32 maskRowStride,
0033                    qint32 rows, qint32 numColumns,
0034                    quint8 opacity,
0035                    const QBitArray &channelFlags) const override
0036     {
0037         Q_UNUSED(maskRowStart);
0038         Q_UNUSED(maskRowStride);
0039 
0040         if (opacity == OPACITY_TRANSPARENT_U8) {
0041             return;
0042         }
0043 
0044         channels_type *d;
0045         const channels_type *s;
0046 
0047         qint32 i;
0048 
0049         //qreal sAlpha, dAlpha;
0050         qreal alpha;
0051 
0052         while (rows-- > 0) {
0053             d = reinterpret_cast<channels_type *>(dstRowStart);
0054             s = reinterpret_cast<const channels_type *>(srcRowStart);
0055             for (i = numColumns; i > 0; --i, d += _CSTraits::channels_nb, s += _CSTraits::channels_nb) {
0056                 if (s[_CSTraits::alpha_pos] == NATIVE_OPACITY_TRANSPARENT) {
0057                     continue;
0058                 } else if (s[_CSTraits::alpha_pos] == NATIVE_OPACITY_OPAQUE) {
0059                     d[_CSTraits::alpha_pos] = NATIVE_OPACITY_TRANSPARENT;
0060                     continue;
0061                 }
0062                 if (d[_CSTraits::alpha_pos] == NATIVE_OPACITY_TRANSPARENT) {
0063                     continue;
0064                 }
0065 
0066                 alpha = (channels_type)(s[_CSTraits::alpha_pos]) * d[_CSTraits::alpha_pos] / NATIVE_OPACITY_OPAQUE;
0067                 if (channelFlags.isEmpty() || channelFlags.testBit(_CSTraits::alpha_pos)) {
0068                     d[_CSTraits::alpha_pos] = (channels_type)((d[_CSTraits::alpha_pos] * (NATIVE_OPACITY_OPAQUE - alpha) / NATIVE_OPACITY_OPAQUE) + 0.5);
0069                 }
0070             }
0071             dstRowStart += dstRowStride;
0072             srcRowStart += srcRowStride;
0073         }
0074 
0075     }
0076 };
0077 
0078 #endif