Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_antialiasing_fade_maker.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
3 * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#ifndef __KIS_ANTIALIASING_FADE_MAKER_H
9#define __KIS_ANTIALIASING_FADE_MAKER_H
10
11#include <kis_global.h>
12
14
15template<class BaseFade>
17{
18public:
19 KisAntialiasingFadeMaker1D(const BaseFade &baseFade, bool enableAntialiasing)
20 : m_radius(0.0)
24 , m_enableAntialiasing(enableAntialiasing)
25 , m_baseFade(baseFade)
26 {
27 }
28
38
39 void setSquareNormCoeffs(qreal xcoeff, qreal ycoeff)
40 {
41 m_radius = 1.0;
42
43 const qreal xf = qMax(0.0, ((1.0 / xcoeff) - 1.0) * xcoeff);
44 const qreal yf = qMax(0.0, ((1.0 / ycoeff) - 1.0) * ycoeff);
45
46 m_antialiasingFadeStart = pow2(0.5 * (xf + yf));
47
50 }
51
52 void setRadius(qreal radius)
53 {
54 m_radius = radius;
55 m_antialiasingFadeStart = qMax(0.0, m_radius - 1.0);
56
59 }
60
61 inline bool needFade(qreal dist, quint8 *value)
62 {
63 if (dist > m_radius) {
64 *value = 255;
65 return true;
66 }
67
69 return false;
70 }
71
72 if (dist > m_antialiasingFadeStart) {
74 return true;
75 }
76
77 return false;
78 }
79
80#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
81 template<typename A>
82 xsimd::batch_bool<float, A> needFade(xsimd::batch<float, A> &dist)
83 {
84 using float_v = xsimd::batch<float, A>;
85 using float_m = typename float_v::batch_bool_type;
86
87 const float_v vOne(1);
88 const float_v vValMax(255.f);
89
90 const float_v vRadius(m_radius);
91 const float_v vFadeStartValue(m_fadeStartValue);
92 const float_v vAntialiasingFadeStart(m_antialiasingFadeStart);
93 const float_v vAntialiasingFadeCoeff(m_antialiasingFadeCoeff);
94
95 const float_m outsideMask = dist > vRadius;
96 dist = xsimd::set_one(dist, outsideMask);
97
98 float_m fadeStartMask(false);
99
101 fadeStartMask = dist > vAntialiasingFadeStart;
102 dist = xsimd::select((outsideMask ^ fadeStartMask) & fadeStartMask,
103 (vFadeStartValue + (dist - vAntialiasingFadeStart) * vAntialiasingFadeCoeff) / vValMax,
104 dist);
105 }
106 return (outsideMask | fadeStartMask);
107 }
108
109#endif /* !defined XSIMD_NO_SUPPORTED_ARCHITECTURE */
110
111private:
112 qreal m_radius;
117 const BaseFade &m_baseFade;
118};
119
120template<class BaseFade>
122{
123public:
124 KisAntialiasingFadeMaker2D(const BaseFade &baseFade, bool enableAntialiasing)
125 : m_xLimit(0)
126 , m_yLimit(0)
129 , m_xFadeCoeff(0)
130 , m_yFadeCoeff(0)
131 , m_enableAntialiasing(enableAntialiasing)
132 , m_baseFade(baseFade)
133 {
134 }
135
147
148 void setLimits(qreal halfWidth, qreal halfHeight)
149 {
150 m_xLimit = halfWidth;
151 m_yLimit = halfHeight;
152
155
158 }
159
160 inline bool needFade(qreal x, qreal y, quint8 *value)
161 {
162 x = qAbs(x);
163 y = qAbs(y);
164
165 if (x > m_xLimit) {
166 *value = 255;
167 return true;
168 }
169
170 if (y > m_yLimit) {
171 *value = 255;
172 return true;
173 }
174
176 return false;
177 }
178
179 if (x > m_xFadeLimitStart) {
180 quint8 baseValue = m_baseFade.value(x, y);
181 *value = baseValue + (255.0 - baseValue) * (x - m_xFadeLimitStart) * m_xFadeCoeff;
182
183 if (y > m_yFadeLimitStart && *value < 255) {
184 *value += (255.0 - *value) * (y - m_yFadeLimitStart) * m_yFadeCoeff;
185 }
186
187 return true;
188 }
189
190 if (y > m_yFadeLimitStart) {
191 quint8 baseValue = m_baseFade.value(x, y);
192 *value = baseValue + (255.0 - baseValue) * (y - m_yFadeLimitStart) * m_yFadeCoeff;
193
194 if (x > m_xFadeLimitStart && *value < 255) {
195 *value += (255.0 - *value) * (x - m_xFadeLimitStart) * m_xFadeCoeff;
196 }
197
198 return true;
199 }
200
201 return false;
202 }
203
204#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
205 template<typename A>
206 xsimd::batch_bool<float, A> needFade(xsimd::batch<float, A> &xr, xsimd::batch<float, A> &yr) const
207 {
208 using float_v = xsimd::batch<float, A>;
209 using float_m = typename float_v::batch_bool_type;
210
211 const float_v vXLimit(m_xLimit);
212 const float_v vYLimit(m_yLimit);
213
214 const float_m outXMask = xsimd::abs(xr) > vXLimit;
215 const float_m outYMask = xsimd::abs(yr) > vYLimit;
216
217 return (outXMask | outYMask);
218 }
219
220 // Apply fader separately to avoid calculating vValue twice.
221 template<typename A>
222 void apply2DFader(xsimd::batch<float, A> &vValue, xsimd::batch_bool<float, A> &excludeMask, xsimd::batch<float, A> &xr, xsimd::batch<float, A> &yr) const
223 {
224 using float_v = xsimd::batch<float, A>;
225 using float_m = typename float_v::batch_bool_type;
226
227 const float_v vValMax(255.f);
228
230 const float_v vXFadeLimitStart(m_xFadeLimitStart);
231 const float_v vYFadeLimitStart(m_yFadeLimitStart);
232 const float_v vXFadeCoeff(m_xFadeCoeff);
233 const float_v vYFadeCoeff(m_yFadeCoeff);
234
235 const float_v xra = xsimd::abs(xr);
236 float_m fadeXStartMask(false);
237 float_m fadeYStartMask(false);
238
239 float_v fadeValue(0);
240 const float_v vBaseValue =
241 xsimd::truncate_to_type<uint16_t>(vValue);
242
243 fadeXStartMask = xra > vXFadeLimitStart;
244 fadeXStartMask = (fadeXStartMask ^ excludeMask) & fadeXStartMask;
245 if (!xsimd::all(fadeXStartMask)) {
246 fadeValue = vBaseValue + (vValMax - vBaseValue) * (xra - vXFadeLimitStart) * vXFadeCoeff;
247 fadeValue = xsimd::select(fadeXStartMask & ((yr > vYFadeLimitStart) & (fadeValue < vValMax)),
248 fadeValue + (vValMax - fadeValue) * (yr - vYFadeLimitStart) * vYFadeCoeff,
249 fadeValue);
250 vValue = xsimd::select(fadeXStartMask, fadeValue, vValue);
251 }
252
253 fadeYStartMask = yr > vYFadeLimitStart;
254 fadeYStartMask = (fadeYStartMask ^ fadeXStartMask) & fadeYStartMask;
255 if (!xsimd::all(fadeYStartMask)) {
256 fadeValue = vBaseValue + (vValMax - vBaseValue) * (yr - vYFadeLimitStart) * vYFadeCoeff;
257 fadeValue = xsimd::select(fadeYStartMask & ((xra > vXFadeLimitStart) & (fadeValue < vValMax)),
258 fadeValue + (vValMax - fadeValue) * (xra - vXFadeLimitStart) * vXFadeCoeff,
259 fadeValue);
260 vValue = xsimd::select(fadeYStartMask, fadeValue, vValue);
261 }
262 }
263 }
264
265#endif /* !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE) */
266
267private:
268 qreal m_xLimit;
269 qreal m_yLimit;
270
273
276
278
279 const BaseFade &m_baseFade;
280};
281
282#endif /* __KIS_ANTIALIASING_FADE_MAKER_H */
float value(const T *src, size_t ch)
KisAntialiasingFadeMaker1D(const KisAntialiasingFadeMaker1D &rhs, const BaseFade &baseFade)
void setSquareNormCoeffs(qreal xcoeff, qreal ycoeff)
bool needFade(qreal dist, quint8 *value)
xsimd::batch_bool< float, A > needFade(xsimd::batch< float, A > &dist)
KisAntialiasingFadeMaker1D(const BaseFade &baseFade, bool enableAntialiasing)
void setLimits(qreal halfWidth, qreal halfHeight)
KisAntialiasingFadeMaker2D(const BaseFade &baseFade, bool enableAntialiasing)
void apply2DFader(xsimd::batch< float, A > &vValue, xsimd::batch_bool< float, A > &excludeMask, xsimd::batch< float, A > &xr, xsimd::batch< float, A > &yr) const
xsimd::batch_bool< float, A > needFade(xsimd::batch< float, A > &xr, xsimd::batch< float, A > &yr) const
bool needFade(qreal x, qreal y, quint8 *value)
KisAntialiasingFadeMaker2D(const KisAntialiasingFadeMaker2D &rhs, const BaseFade &baseFade)
T pow2(const T &x)
Definition kis_global.h:166
auto set_one(const batch< T, A > &src, const batch_bool< T, A > &mask) noexcept