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