00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef KOCOMPOSITEOPOVER_H_
00021 #define KOCOMPOSITEOPOVER_H_
00022
00023 #include "KoColorSpaceMaths.h"
00024 #include "KoCompositeOp.h"
00025
00026 #define NATIVE_OPACITY_OPAQUE KoColorSpaceMathsTraits<channels_type>::max()
00027 #define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::min()
00028
00032 template<class _CSTraits>
00033 class KoCompositeOpOver : public KoCompositeOp {
00034 typedef typename _CSTraits::channels_type channels_type;
00035 public:
00036
00037 KoCompositeOpOver(KoColorSpace * cs)
00038 : KoCompositeOp(cs, COMPOSITE_OVER, i18n("Normal" ) )
00039 {
00040 }
00041
00042 public:
00043 struct Pixel {
00044 quint16 lightness;
00045 quint16 a;
00046 quint16 b;
00047 quint16 alpha;
00048 };
00049
00050 void composite(quint8 *dstRowStart,
00051 qint32 dststride,
00052 const quint8 *srcRowStart,
00053 qint32 srcstride,
00054 const quint8 *maskRowStart,
00055 qint32 maskstride,
00056 qint32 rows,
00057 qint32 cols,
00058 quint8 U8_opacity,
00059 const QBitArray & channelFlags) const
00060 {
00061 Q_UNUSED( channelFlags );
00062
00063 channels_type opacity = KoColorSpaceMaths<quint8, channels_type>::scaleToA(U8_opacity);
00064 qint32 pixelSize = colorSpace()->pixelSize();
00065
00066 while (rows > 0) {
00067 const channels_type *srcN = reinterpret_cast<const channels_type *>(srcRowStart);
00068 channels_type *dstN = reinterpret_cast<channels_type *>(dstRowStart);
00069 const quint8 *mask = maskRowStart;
00070
00071 qint32 columns = cols;
00072
00073 while (columns > 0) {
00074
00075 channels_type srcAlpha = srcN[_CSTraits::alpha_pos];
00076
00077
00078 if (mask != 0) {
00079 if (*mask != OPACITY_OPAQUE) {
00080 srcAlpha = KoColorSpaceMaths<channels_type,quint8>::multiply(srcAlpha, *mask);
00081 }
00082 mask++;
00083 }
00084
00085 if (srcAlpha != NATIVE_OPACITY_TRANSPARENT) {
00086
00087 if (opacity != NATIVE_OPACITY_OPAQUE) {
00088 srcAlpha = KoColorSpaceMaths<channels_type>::multiply(srcAlpha, opacity);
00089 }
00090
00091 if (srcAlpha == NATIVE_OPACITY_OPAQUE) {
00092 memcpy(dstN, srcN, pixelSize);
00093 } else {
00094 channels_type dstAlpha = dstN[_CSTraits::alpha_pos];
00095
00096 channels_type srcBlend;
00097
00098 if (dstAlpha == NATIVE_OPACITY_OPAQUE) {
00099 srcBlend = srcAlpha;
00100 } else {
00101 channels_type newAlpha = dstAlpha + KoColorSpaceMaths<channels_type>::multiply(NATIVE_OPACITY_OPAQUE - dstAlpha, srcAlpha);
00102 dstN[_CSTraits::alpha_pos] = newAlpha;
00103
00104 if (newAlpha != 0) {
00105 srcBlend = KoColorSpaceMaths<channels_type>::divide(srcAlpha, newAlpha);
00106 } else {
00107 srcBlend = srcAlpha;
00108 }
00109 }
00110
00111 if (srcBlend == NATIVE_OPACITY_OPAQUE) {
00112 memcpy(dstN, srcN, pixelSize);
00113 } else {
00114 for(uint i = 0; i < _CSTraits::channels_nb; i++)
00115 {
00116 if( (int)i != _CSTraits::alpha_pos)
00117 dstN[i] = KoColorSpaceMaths<channels_type>::blend(srcN[i], dstN[i], srcBlend);
00118 }
00119 }
00120 }
00121 }
00122 columns--;
00123 srcN+=_CSTraits::channels_nb;
00124 dstN+=_CSTraits::channels_nb;
00125 }
00126
00127 rows--;
00128 srcRowStart += srcstride;
00129 dstRowStart += dststride;
00130 if(maskRowStart) {
00131 maskRowStart += maskstride;
00132 }
00133 }
00134 }
00135
00136 };
00137
00138 #endif