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

0001 /*
0002  *  SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KOCOMPOSITEOPERASE_H_
0008 #define KOCOMPOSITEOPERASE_H_
0009 
0010 #include "KoColorSpaceMaths.h"
0011 #include "KoCompositeOp.h"
0012 
0013 #define NATIVE_OPACITY_OPAQUE KoColorSpaceMathsTraits<channels_type>::unitValue
0014 #define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::zeroValue
0015 
0016 /**
0017  * A template version of the erase composite operation to use in colorspaces<
0018  */
0019 template<class _CSTraits>
0020 class KoCompositeOpErase : public KoCompositeOp
0021 {
0022     typedef typename _CSTraits::channels_type channels_type;
0023 
0024 public:
0025 
0026     KoCompositeOpErase(const KoColorSpace * cs)
0027             : KoCompositeOp(cs, COMPOSITE_ERASE, KoCompositeOp::categoryMix()) {
0028     }
0029 
0030 public:
0031     using KoCompositeOp::composite;
0032 
0033     void composite(quint8 *dstRowStart,
0034                    qint32 dststride,
0035                    const quint8 *srcRowStart,
0036                    qint32 srcstride,
0037                    const quint8 *maskRowStart,
0038                    qint32 maskstride,
0039                    qint32 rows,
0040                    qint32 cols,
0041                    quint8 U8_opacity,
0042                    const QBitArray & channelFlags) const override {
0043         // XXX: How to use channelflags here? It would be cool to
0044         // erase all green from an image, for example.
0045         qint32 srcInc = (srcstride == 0) ? 0 : _CSTraits::channels_nb;
0046         channels_type opacity = KoColorSpaceMaths<quint8, channels_type>::scaleToA(U8_opacity);
0047         Q_UNUSED(channelFlags);
0048         while (rows-- > 0) {
0049             const channels_type *s = reinterpret_cast<const channels_type *>(srcRowStart);
0050             channels_type *d = reinterpret_cast<channels_type *>(dstRowStart);
0051             const quint8 *mask = maskRowStart;
0052 
0053             for (qint32 i = cols; i > 0; i--, s += srcInc, d += _CSTraits::channels_nb) {
0054                 channels_type srcAlpha = s[_CSTraits::alpha_pos];
0055 
0056                 // apply the alphamask
0057                 if (mask != 0) {
0058                     quint8 U8_mask = *mask;
0059 
0060                     if (U8_mask != OPACITY_TRANSPARENT_U8) {
0061                         srcAlpha = KoColorSpaceMaths<channels_type>::
0062                             multiply(srcAlpha, KoColorSpaceMaths<quint8, channels_type>::scaleToA(U8_mask));
0063                     } else {
0064                         srcAlpha = 0;
0065                     }
0066                     ++mask;
0067                 }
0068                 srcAlpha = KoColorSpaceMaths<channels_type>::multiply(srcAlpha, opacity);
0069                 srcAlpha = NATIVE_OPACITY_OPAQUE - srcAlpha;
0070                 d[_CSTraits::alpha_pos] = KoColorSpaceMaths<channels_type>::multiply(srcAlpha, d[_CSTraits::alpha_pos]);
0071             }
0072 
0073             dstRowStart += dststride;
0074             srcRowStart += srcstride;
0075             if (maskRowStart) {
0076                 maskRowStart += maskstride;
0077             }
0078         }
0079     }
0080 };
0081 
0082 #endif