Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_gauss_rect_mask_generator.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
3 * SPDX-FileCopyrightText: 2011 Geoffry Song <goffrie@gmail.com>
4 * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include <cmath>
10#include <algorithm>
11
12
13#include <QDomDocument>
14
16
17#include "kis_fast_math.h"
18
25
26#define M_SQRT_2 1.41421356237309504880
27
28#ifdef Q_OS_WIN
29// on windows we get our erf() from boost
30#include <boost/math/special_functions/erf.hpp>
31#define erf(x) boost::math::erf(x)
32#endif
33
34
35
36KisGaussRectangleMaskGenerator::KisGaussRectangleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges)
37 : KisMaskGenerator(diameter, ratio, fh, fv, spikes, antialiasEdges, RECTANGLE, GaussId), d(new Private(antialiasEdges))
38{
39 setScale(1.0, 1.0);
40
42}
43
50
55
56void KisGaussRectangleMaskGenerator::setScale(qreal scaleX, qreal scaleY)
57{
59
60 qreal width = effectiveSrcWidth();
61 qreal height = effectiveSrcHeight();
62
63 qreal xfade = (1.0 - horizontalFade()/2.0) * width * 0.1;
64 qreal yfade = (1.0 - verticalFade()/2.0) * height * 0.1;
65 d->xfade = 1.0 / (M_SQRT_2 * xfade);
66 d->yfade = 1.0 / (M_SQRT_2 * yfade);
67 d->halfWidth = width * 0.5 - 2.5 * xfade;
68 d->halfHeight = height * 0.5 - 2.5 * yfade;
69 d->alphafactor = 255.0 / (4.0 * erf(d->halfWidth * d->xfade) * erf(d->halfHeight * d->yfade));
70
71 if (std::isnan(d->alphafactor)) d->alphafactor = 0.0f; // erf can return nan if ratio is 0
72
73 d->fadeMaker.setLimits(0.5 * width, 0.5 * height);
74}
75
79
80inline quint8 KisGaussRectangleMaskGenerator::Private::value(qreal xr, qreal yr) const
81{
82 return (quint8) 255 - (quint8) (alphafactor * (erf((halfWidth + xr) * xfade) + erf((halfWidth - xr) * xfade))
83 * (erf((halfHeight + yr) * yfade) + erf((halfHeight - yr) * yfade)));
84}
85
86quint8 KisGaussRectangleMaskGenerator::valueAt(qreal x, qreal y) const
87{
88 if (isEmpty()) return 255;
89 qreal xr = x;
90 qreal yr = qAbs(y);
91 fixRotation(xr, yr);
92
93 quint8 value;
94 if (d->fadeMaker.needFade(xr, yr, &value)) {
95 return value;
96 }
97
98 return d->value(xr, yr);
99}
100
102{
103 return !shouldSupersample() && spikes() == 2;
104}
105
107{
108 return d->applicator.data();
109}
110
float value(const T *src, size_t ch)
auto createOptimizedClass(Args &&...param)
auto createScalarClass(Args &&...params)
KisMaskGenerator * clone() const override
void setScale(qreal scaleX, qreal scaleY) override
quint8 valueAt(qreal x, qreal y) const override
QScopedPointer< KisBrushMaskApplicatorBase > applicator
KisGaussRectangleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges)
virtual bool shouldSupersample() const
const QScopedPointer< Private > d
void fixRotation(qreal &xr, qreal &yr) const
virtual void setScale(qreal scaleX, qreal scaleY)
const KoID GaussId("gauss", ki18n("Gaussian"))
generate brush mask with a Gaussian-blurred edge