Krita Source Code Documentation
Loading...
Searching...
No Matches
KoCompositeOpCopy2.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006, 2010 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2007 Emanuele Tamponi <emanuele@valinor.it>
4 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
5 * SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8*/
9
10#ifndef KO_COMPOSITEOP_COPY2_H
11#define KO_COMPOSITEOP_COPY2_H
12
13#include "KoCompositeOpBase.h"
14
21template<class Traits>
22class KoCompositeOpCopy2: public KoCompositeOpBase< Traits, KoCompositeOpCopy2<Traits> >
23{
25 typedef typename Traits::channels_type channels_type;
26
27 static const qint32 channels_nb = Traits::channels_nb;
28 static const qint32 alpha_pos = Traits::alpha_pos;
29
30public:
33
34public:
35 template<bool alphaLocked, bool allChannelFlags>
37 channels_type* dst, channels_type dstAlpha, channels_type maskAlpha,
38 channels_type opacity, const QBitArray& channelFlags) {
39 using namespace Arithmetic;
40 opacity = mul(maskAlpha, opacity);
41
42 channels_type newAlpha = zeroValue<channels_type>();
43
44 if (opacity == unitValue<channels_type>()) {
45 if (!alphaLocked || srcAlpha != zeroValue<channels_type>()) {
46 // don't blend if the color of the destination is undefined (has zero opacity)
47 // copy the source channel instead
48 for(qint32 i=0; i<channels_nb; ++i)
49 if(i != alpha_pos && (allChannelFlags || channelFlags.testBit(i)))
50 dst[i] = src[i];
51 }
52
53 newAlpha = srcAlpha;
54
55 } else if (opacity == zeroValue<channels_type>()) {
56
57 newAlpha = dstAlpha;
58
59 } else { // opacity 0...1
60
61 if (!alphaLocked || srcAlpha != zeroValue<channels_type>()) {
62
63 newAlpha = lerp(dstAlpha, srcAlpha, opacity);
64
65 if (newAlpha == zeroValue<channels_type>()) {
66 return newAlpha;
67 }
68
69 // blend the color channels
70 for(qint32 i=0; i<channels_nb; ++i) {
71 if(i != alpha_pos && (allChannelFlags || channelFlags.testBit(i))) {
72
73 // We use the most fundamental OVER algorithm here,
74 // which multiplies, blends and then unmultiplies the
75 // channels
76
77 typedef typename KoColorSpaceMathsTraits<channels_type>::compositetype composite_type;
78
79 channels_type dstMult = mul(dst[i], dstAlpha);
80 channels_type srcMult = mul(src[i], srcAlpha);
81 channels_type blendedValue = lerp(dstMult, srcMult, opacity);
82
83 composite_type normedValue = KoColorSpaceMaths<channels_type>::divide(blendedValue, newAlpha);
84
86 }
87 }
88 }
89
90 }
91
92 return newAlpha;
93 }
94};
95
96#endif // KO_COMPOSITEOP_COPY2_H
const QString COMPOSITE_COPY
QPointF lerp(const QPointF &p1, const QPointF &p2, qreal t)
static _Tdst clampAfterScale(dst_compositetype val)
static dst_compositetype divide(_T a, _Tdst b)
static const qint32 alpha_pos
KoCompositeOpBase< Traits, KoCompositeOpCopy2< Traits > > base_class
static const qint32 channels_nb
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)
Traits::channels_type channels_type
KoCompositeOpCopy2(const KoColorSpace *cs)
static QString categoryMisc()