File indexing completed on 2024-05-12 15:58:12
0001 /* 0002 * SPDX-FileCopyrightText: 2004, 2007-2009 Cyrille Berger <cberger@cberger.net> 0003 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com> 0004 * SPDX-FileCopyrightText: 2012 Sven Langkamp <sven.langkamp@gmail.com> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include <cmath> 0010 0011 #include <QDomDocument> 0012 0013 #include "kis_fast_math.h" 0014 #include "kis_circle_mask_generator.h" 0015 #include "kis_circle_mask_generator_p.h" 0016 #include "kis_base_mask_generator.h" 0017 #include "kis_brush_mask_applicator_factories.h" 0018 #include "kis_brush_mask_applicator_base.h" 0019 0020 0021 KisCircleMaskGenerator::KisCircleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges) 0022 : KisMaskGenerator(diameter, ratio, fh, fv, spikes, antialiasEdges, CIRCLE, DefaultId), 0023 d(new Private) 0024 { 0025 setScale(1.0, 1.0); 0026 0027 // store the variable locally to allow vector implementation read it easily 0028 d->copyOfAntialiasEdges = antialiasEdges; 0029 0030 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator> >(this)); 0031 } 0032 0033 KisCircleMaskGenerator::KisCircleMaskGenerator(const KisCircleMaskGenerator &rhs) 0034 : KisMaskGenerator(rhs), 0035 d(new Private(*rhs.d)) 0036 { 0037 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator> >(this)); 0038 } 0039 0040 KisMaskGenerator* KisCircleMaskGenerator::clone() const 0041 { 0042 return new KisCircleMaskGenerator(*this); 0043 } 0044 0045 void KisCircleMaskGenerator::setScale(qreal scaleX, qreal scaleY) 0046 { 0047 KisMaskGenerator::setScale(scaleX, scaleY); 0048 0049 d->xcoef = 2.0 / effectiveSrcWidth(); 0050 d->ycoef = 2.0 / effectiveSrcHeight(); 0051 d->xfadecoef = qFuzzyCompare(horizontalFade(), 0) ? 1 : (2.0 / (horizontalFade() * effectiveSrcWidth())); 0052 d->yfadecoef = qFuzzyCompare(verticalFade() , 0) ? 1 : (2.0 / (verticalFade() * effectiveSrcHeight())); 0053 d->transformedFadeX = d->xfadecoef * d->safeSoftnessCoeff; 0054 d->transformedFadeY = d->yfadecoef * d->safeSoftnessCoeff; 0055 } 0056 0057 KisCircleMaskGenerator::~KisCircleMaskGenerator() 0058 { 0059 } 0060 0061 bool KisCircleMaskGenerator::shouldVectorize() const 0062 { 0063 return !shouldSupersample() && spikes() == 2; 0064 } 0065 0066 KisBrushMaskApplicatorBase* KisCircleMaskGenerator::applicator() 0067 { 0068 return d->applicator.data(); 0069 } 0070 0071 quint8 KisCircleMaskGenerator::valueAt(qreal x, qreal y) const 0072 { 0073 if (isEmpty()) return 255; 0074 qreal xr = (x /*- m_xcenter*/); 0075 qreal yr = qAbs(y /*- m_ycenter*/); 0076 fixRotation(xr, yr); 0077 0078 qreal n = norme(xr * d->xcoef, yr * d->ycoef); 0079 if (n > 1.0) return 255; 0080 0081 // we add +1.0 to ensure correct antialiasing on the border 0082 if (antialiasEdges()) { 0083 xr = qAbs(xr) + 1.0; 0084 yr = qAbs(yr) + 1.0; 0085 } 0086 0087 qreal nf = norme(xr * d->transformedFadeX, 0088 yr * d->transformedFadeY); 0089 0090 if (nf < 1.0) return 0; 0091 return 255 * n * (nf - 1.0) / (nf - n); 0092 } 0093 0094 void KisCircleMaskGenerator::setSoftness(qreal softness) 0095 { 0096 KisMaskGenerator::setSoftness(softness); 0097 d->safeSoftnessCoeff = qreal(1.0) / qMax(qreal(0.01), softness); 0098 0099 d->transformedFadeX = d->xfadecoef * d->safeSoftnessCoeff; 0100 d->transformedFadeY = d->yfadecoef * d->safeSoftnessCoeff; 0101 } 0102 0103 void KisCircleMaskGenerator::resetMaskApplicator(bool forceScalar) 0104 { 0105 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator> >(this,forceScalar)); 0106 }