File indexing completed on 2024-05-12 15:58:39

0001 /*
0002  *  SPDX-FileCopyrightText: 2004, 2007-2010 Cyrille Berger <cberger@cberger.net>
0003  *  SPDX-FileCopyrightText: 2018 Ivan Santa Maria <ghevan@gmail.com>
0004  *  SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include <cmath>
0010 
0011 
0012 #include <QDomDocument>
0013 
0014 #include "kis_fast_math.h"
0015 #include "kis_rect_mask_generator.h"
0016 #include "kis_rect_mask_generator_p.h"
0017 #include "kis_base_mask_generator.h"
0018 
0019 #include "kis_brush_mask_applicator_factories.h"
0020 #include "kis_brush_mask_applicator_base.h"
0021 
0022 #include <qnumeric.h>
0023 
0024 KisRectangleMaskGenerator::KisRectangleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges)
0025     : KisMaskGenerator(radius, ratio, fh, fv, spikes, antialiasEdges, RECTANGLE, DefaultId), d(new Private)
0026 {
0027     setScale(1.0, 1.0);
0028 
0029     // store the variable locally to allow vector implementation read it easily
0030     d->copyOfAntialiasEdges = antialiasEdges;
0031     d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator>>(this));
0032 }
0033 
0034 KisRectangleMaskGenerator::KisRectangleMaskGenerator(const KisRectangleMaskGenerator &rhs)
0035     : KisMaskGenerator(rhs),
0036       d(new Private(*rhs.d))
0037 {
0038     d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator>>(this));
0039 }
0040 
0041 KisMaskGenerator* KisRectangleMaskGenerator::clone() const
0042 {
0043     return new KisRectangleMaskGenerator(*this);
0044 }
0045 
0046 KisRectangleMaskGenerator::~KisRectangleMaskGenerator()
0047 {
0048 }
0049 
0050 void KisRectangleMaskGenerator::setScale(qreal scaleX, qreal scaleY)
0051 {
0052     KisMaskGenerator::setScale(scaleX, scaleY);
0053 
0054     d->xcoeff = 2.0 / effectiveSrcWidth();
0055     d->ycoeff = 2.0 / effectiveSrcHeight();
0056     d->xfadecoeff = (horizontalFade() == 0) ? 1 : (2.0 / (horizontalFade() * effectiveSrcWidth()));
0057     d->yfadecoeff = (verticalFade() == 0)   ? 1 : (2.0 / (verticalFade() * effectiveSrcHeight()));
0058 
0059     setSoftness(this->softness());
0060 }
0061 
0062 void KisRectangleMaskGenerator::setSoftness(qreal softness)
0063 {
0064     KisMaskGenerator::setSoftness(softness);
0065     qreal safeSoftnessCoeff = qreal(1.0) / qMax(qreal(0.01), softness);
0066 
0067     d->transformedFadeX = d->xfadecoeff * safeSoftnessCoeff;
0068     d->transformedFadeY = d->yfadecoeff * safeSoftnessCoeff;
0069 }
0070 
0071 bool KisRectangleMaskGenerator::shouldVectorize() const
0072 {
0073     return !shouldSupersample() && spikes() == 2;
0074 }
0075 
0076 KisBrushMaskApplicatorBase* KisRectangleMaskGenerator::applicator()
0077 {
0078     return d->applicator.data();
0079 }
0080 
0081 void KisRectangleMaskGenerator::resetMaskApplicator(bool forceScalar)
0082 {
0083     d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator>>(this,forceScalar));
0084 }
0085 
0086 quint8 KisRectangleMaskGenerator::valueAt(qreal x, qreal y) const
0087 {
0088     if (isEmpty()) return 255;
0089     qreal xr = qAbs(x /*- m_xcenter*/);
0090     qreal yr = qAbs(y /*- m_ycenter*/);
0091     fixRotation(xr, yr);
0092 
0093     xr = qAbs(xr);
0094     yr = qAbs(yr);
0095 
0096     qreal nxr = xr * d->xcoeff;
0097     qreal nyr = yr * d->ycoeff;
0098 
0099     if (nxr > 1.0 || nyr > 1.0) return 255;
0100 
0101     if (antialiasEdges()) {
0102         xr += 1.0;
0103         yr += 1.0;
0104     }
0105 
0106     qreal fxr = xr * d->transformedFadeX;
0107     qreal fyr = yr * d->transformedFadeY;
0108 
0109     qreal fxnorm = nxr * (fxr - 1.0) / (fxr - nxr);
0110     qreal fynorm = nyr * (fyr - 1.0) / (fyr - nyr);
0111 
0112     qreal retValue = 0;
0113 
0114     if(fxr > 1.0) {
0115         retValue = fxnorm;
0116      }
0117 
0118     if (fxnorm < fynorm && fyr > 1.0) {
0119         retValue = fynorm;
0120      }
0121 
0122     return retValue * 255;
0123 }
0124