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