Krita Source Code Documentation
Loading...
Searching...
No Matches
KoCompositeOpAlphaBase.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6
7#ifndef _KOCOMPOSITEOPALPHABASE_H_
8#define _KOCOMPOSITEOPALPHABASE_H_
9
10
11#include <KoColorSpaceMaths.h>
12#include <KoCompositeOp.h>
14
15#define NATIVE_MIN_VALUE KoColorSpaceMathsTraits<channels_type>::min
16#define NATIVE_MAX_VALUE KoColorSpaceMathsTraits<channels_type>::max
17#define NATIVE_OPACITY_OPAQUE KoColorSpaceMathsTraits<channels_type>::unitValue
18#define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::zeroValue
19#define NATIVE_ZERO_VALUE KoColorSpaceMathsTraits<channels_type>::zeroValue
20
21
29template<class _CSTraits, class _compositeOp, bool _alphaLocked>
31{
32 typedef typename _CSTraits::channels_type channels_type;
33public:
34
35 KoCompositeOpAlphaBase(const KoColorSpace * cs, const QString& id, const QString& category)
36 : KoCompositeOp(cs, id, category) {
37 }
38
39public:
41
42 template<bool alphaLocked, bool allChannelFlags>
43 void composite(const KoCompositeOp::ParameterInfo& params) const {
44 qint32 srcInc = (params.srcRowStride == 0) ? 0 : _CSTraits::channels_nb;
45
47
48 const quint8 *srcRowStart = params.srcRowStart;
49 quint8 *dstRowStart = params.dstRowStart;
50 const quint8 *maskRowStart = params.maskRowStart;
51
52 qint32 rows = params.rows;
53
54 while (rows > 0) {
55 const channels_type *srcN = reinterpret_cast<const channels_type *>(srcRowStart);
56 channels_type *dstN = reinterpret_cast<channels_type *>(dstRowStart);
57 const quint8 *mask = maskRowStart;
58
59 qint32 columns = params.cols;
60
61 while (columns > 0) {
62
63 channels_type srcAlpha = _CSTraits::alpha_pos == -1 ? NATIVE_OPACITY_OPAQUE : _compositeOp::selectAlpha(srcN[_CSTraits::alpha_pos], dstN[_CSTraits::alpha_pos]);
64
65 // apply the alphamask
66 if (mask != 0) {
67 srcAlpha = KoColorSpaceMaths<quint8, channels_type>::multiply(*mask, srcAlpha, opacity);
68 mask++;
69 } else if (opacity != NATIVE_OPACITY_OPAQUE) {
70 srcAlpha = KoColorSpaceMaths<channels_type>::multiply(srcAlpha, opacity);
71 }
72
73 if (srcAlpha != NATIVE_OPACITY_TRANSPARENT) {
74
75
76 channels_type dstAlpha = _CSTraits::alpha_pos == -1 ? NATIVE_OPACITY_OPAQUE : dstN[_CSTraits::alpha_pos];
77
78 channels_type srcBlend;
79
80 if (alphaLocked || _alphaLocked ||
81 dstAlpha == NATIVE_OPACITY_OPAQUE) {
82
83 srcBlend = srcAlpha;
84
85 } else if (dstAlpha == NATIVE_OPACITY_TRANSPARENT) {
86 if (!allChannelFlags) {
87 for (int i = 0; i < (int)_CSTraits::channels_nb; i++) {
88 if (i != _CSTraits::alpha_pos) {
89 dstN[i] = NATIVE_ZERO_VALUE;
90 }
91 }
92 }
93
94 if (!alphaLocked && !_alphaLocked) {
95 dstN[_CSTraits::alpha_pos] = srcAlpha;
96 }
97 srcBlend = NATIVE_OPACITY_OPAQUE;
98
99 } else {
100 channels_type newAlpha = dstAlpha + KoColorSpaceMaths<channels_type>::multiply(NATIVE_OPACITY_OPAQUE - dstAlpha, srcAlpha);
101 if (!alphaLocked && !_alphaLocked) { // No need to check for _CSTraits::alpha_pos == -1 since it is contained in alphaLocked
102 dstN[_CSTraits::alpha_pos] = newAlpha;
103 }
104 // newAlpha cannot be zero, because srcAlpha!=zero and dstAlpha!=unit here
105 srcBlend = KoColorSpaceMaths<channels_type>::divide(srcAlpha, newAlpha);
106 }
107 _compositeOp::composeColorChannels(srcBlend, srcN, dstN, allChannelFlags, params.channelFlags);
108
109 }
110 columns--;
111 srcN += srcInc;
112 dstN += _CSTraits::channels_nb;
113 }
114
115 rows--;
116 srcRowStart += params.srcRowStride;
117 dstRowStart += params.dstRowStride;
118 if (maskRowStart) {
119 maskRowStart += params.maskRowStride;
120 }
121 }
122 }
123 template<bool alphaLocked>
124 void composite(const KoCompositeOp::ParameterInfo& params) const
125 {
126 bool allChannelFlags = params.channelFlags.isEmpty();
127 if(allChannelFlags)
128 {
129 composite<alphaLocked, true>(params);
130 } else {
131 composite<alphaLocked, false>(params);
132 }
133 }
134
135 void composite(const KoCompositeOp::ParameterInfo& params) const override
136 {
137 bool alphaLocked = false;
138 if (!params.channelFlags.isEmpty()) {
139 if (_CSTraits::alpha_pos == -1 || !params.channelFlags.testBit(_CSTraits::alpha_pos)) {
140 alphaLocked = true;
141 }
142 }
143 if(alphaLocked)
144 {
145 composite<true>(params);
146 } else {
147 composite<false>(params);
148 }
149 }
150};
151
152#endif
#define NATIVE_OPACITY_TRANSPARENT
#define NATIVE_ZERO_VALUE
#define NATIVE_OPACITY_OPAQUE
static _Tdst multiply(_T a, _Tdst b)
static _Tdst scaleToA(_T a)
static dst_compositetype divide(_T a, _Tdst b)
_CSTraits::channels_type channels_type
void composite(const KoCompositeOp::ParameterInfo &params) const override
KoCompositeOpAlphaBase(const KoColorSpace *cs, const QString &id, const QString &category)
void composite(const KoCompositeOp::ParameterInfo &params) const
void composite(const KoCompositeOp::ParameterInfo &params) const
void composite(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, float opacity, const QBitArray &channelFlags=QBitArray()) const