Krita Source Code Documentation
Loading...
Searching...
No Matches
KoCompositeOpBehind.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2012 José Luis Vergara <pentalis@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#ifndef _KOCOMPOSITEOPBEHIND_H_
8#define _KOCOMPOSITEOPBEHIND_H_
9
10#include "KoCompositeOpBase.h"
11
15template<class CS_Traits, typename BlendingPolicy>
16class KoCompositeOpBehind : public KoCompositeOpBase<CS_Traits, KoCompositeOpBehind<CS_Traits, BlendingPolicy> >
17{
19 typedef typename CS_Traits::channels_type channels_type;
20
21 static const qint8 channels_nb = CS_Traits::channels_nb;
22 static const qint8 alpha_pos = CS_Traits::alpha_pos;
23
24public:
27
28public:
29 template<bool alphaLocked, bool allChannelFlags>
31 channels_type* dst, channels_type dstAlpha,
32 channels_type maskAlpha, channels_type opacity,
33 const QBitArray& channelFlags ) {
34 using namespace Arithmetic;
35
36 if (dstAlpha == unitValue<channels_type>()) return dstAlpha;
37 channels_type appliedAlpha = mul(maskAlpha, srcAlpha, opacity);
38
39 if (appliedAlpha == zeroValue<channels_type>()) return dstAlpha;
40 channels_type newDstAlpha = unionShapeOpacity(dstAlpha, appliedAlpha);
41
42 if (dstAlpha != zeroValue<channels_type>()) {
43 // blend the color channels as if we were painting on the layer below
44 for (qint8 channel = 0; channel < channels_nb; ++channel)
45 if(channel != alpha_pos && (allChannelFlags || channelFlags.testBit(channel))) {
46 /*each color blended in proportion to their calculated opacity*/
47 channels_type srcMult= mul(BlendingPolicy::toAdditiveSpace(src[channel]), appliedAlpha);
48 channels_type blendedValue = lerp(srcMult,BlendingPolicy::toAdditiveSpace(dst[channel]),dstAlpha);
49 dst[channel] = BlendingPolicy::fromAdditiveSpace(KoColorSpaceMaths<channels_type>::divide(blendedValue,newDstAlpha));
50 }
51 }
52 else {
53 // don't blend if the color of the destination is undefined (has zero opacity)
54 // copy the source channel instead
55 for (qint8 channel = 0; channel < channels_nb; ++channel)
56 if(channel != alpha_pos && (allChannelFlags || channelFlags.testBit(channel)))
57 dst[channel] = src[channel];
58 }
59
60 return newDstAlpha;
61 }
62};
63
64#endif // _KOCOMPOSITEOPBEHIND_H_
const QString COMPOSITE_BEHIND
QPointF lerp(const QPointF &p1, const QPointF &p2, qreal t)
static const qint8 alpha_pos
CS_Traits::channels_type channels_type
KoCompositeOpBehind(const KoColorSpace *cs)
static channels_type composeColorChannels(const channels_type *src, channels_type srcAlpha, channels_type *dst, channels_type dstAlpha, channels_type maskAlpha, channels_type opacity, const QBitArray &channelFlags)
static const qint8 channels_nb
KoCompositeOpBase< CS_Traits, KoCompositeOpBehind< CS_Traits, BlendingPolicy > > base_class
static QString categoryMix()