File indexing completed on 2024-05-12 15:58:14
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include <cmath> 0008 0009 #include <QDomDocument> 0010 #include <QVector> 0011 #include <QPointF> 0012 0013 #include <kis_fast_math.h> 0014 #include "kis_antialiasing_fade_maker.h" 0015 #include "kis_brush_mask_applicator_factories.h" 0016 #include "kis_brush_mask_applicator_base.h" 0017 0018 #include "kis_curve_rect_mask_generator.h" 0019 #include "kis_curve_rect_mask_generator_p.h" 0020 #include "kis_curve_circle_mask_generator.h" 0021 #include "kis_cubic_curve.h" 0022 0023 0024 KisCurveRectangleMaskGenerator::KisCurveRectangleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, const KisCubicCurve &curve, bool antialiasEdges) 0025 : KisMaskGenerator(diameter, ratio, fh, fv, spikes, antialiasEdges, RECTANGLE, SoftId), d(new Private(antialiasEdges)) 0026 { 0027 d->curveResolution = qRound( qMax(width(),height()) * OVERSAMPLING); 0028 d->curveData = curve.floatTransfer( d->curveResolution + 1); 0029 d->curvePoints = curve.points(); 0030 setCurveString(curve.toString()); 0031 d->dirty = false; 0032 0033 setScale(1.0, 1.0); 0034 0035 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator>>(this)); 0036 } 0037 0038 KisCurveRectangleMaskGenerator::KisCurveRectangleMaskGenerator(const KisCurveRectangleMaskGenerator &rhs) 0039 : KisMaskGenerator(rhs), 0040 d(new Private(*rhs.d)) 0041 { 0042 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator>>(this)); 0043 } 0044 0045 KisMaskGenerator* KisCurveRectangleMaskGenerator::clone() const 0046 { 0047 return new KisCurveRectangleMaskGenerator(*this); 0048 } 0049 0050 void KisCurveRectangleMaskGenerator::setScale(qreal scaleX, qreal scaleY) 0051 { 0052 KisMaskGenerator::setScale(scaleX, scaleY); 0053 0054 qreal halfWidth = 0.5 * effectiveSrcWidth(); 0055 qreal halfHeight = 0.5 * effectiveSrcHeight(); 0056 0057 d->xcoeff = 1.0 / halfWidth; 0058 d->ycoeff = 1.0 / halfHeight; 0059 0060 d->fadeMaker.setLimits(halfWidth, halfHeight); 0061 } 0062 0063 KisCurveRectangleMaskGenerator::~KisCurveRectangleMaskGenerator() 0064 { 0065 } 0066 0067 quint8 KisCurveRectangleMaskGenerator::Private::value(qreal xr, qreal yr) const 0068 { 0069 xr = qAbs(xr) * xcoeff; 0070 yr = qAbs(yr) * ycoeff; 0071 0072 int sIndex = qRound(xr * (curveResolution)); 0073 int tIndex = qRound(yr * (curveResolution)); 0074 0075 int sIndexInverted = curveResolution - sIndex; 0076 int tIndexInverted = curveResolution - tIndex; 0077 0078 qreal blend = (curveData.at(sIndex) * (1.0 - curveData.at(sIndexInverted)) * 0079 curveData.at(tIndex) * (1.0 - curveData.at(tIndexInverted))); 0080 0081 return (1.0 - blend) * 255; 0082 } 0083 0084 quint8 KisCurveRectangleMaskGenerator::valueAt(qreal x, qreal y) const 0085 { 0086 if (isEmpty()) return 255; 0087 qreal xr = x; 0088 qreal yr = qAbs(y); 0089 fixRotation(xr, yr); 0090 0091 quint8 value; 0092 if (d->fadeMaker.needFade(xr, yr, &value)) { 0093 return value; 0094 } 0095 0096 return d->value(xr, yr); 0097 } 0098 0099 void KisCurveRectangleMaskGenerator::toXML(QDomDocument& doc, QDomElement& e) const 0100 { 0101 KisMaskGenerator::toXML(doc, e); 0102 e.setAttribute("softness_curve", curveString()); 0103 } 0104 0105 void KisCurveRectangleMaskGenerator::setSoftness(qreal softness) 0106 { 0107 // performance 0108 if (!d->dirty && softness == 1.0) return; 0109 d->dirty = true; 0110 KisMaskGenerator::setSoftness(softness); 0111 KisCurveCircleMaskGenerator::transformCurveForSoftness(softness,d->curvePoints, d->curveResolution + 1, d->curveData); 0112 d->dirty = false; 0113 } 0114 0115 bool KisCurveRectangleMaskGenerator::shouldVectorize() const 0116 { 0117 return !shouldSupersample() && spikes() == 2; 0118 } 0119 0120 KisBrushMaskApplicatorBase* KisCurveRectangleMaskGenerator::applicator() 0121 { 0122 return d->applicator.data(); 0123 } 0124 0125 void KisCurveRectangleMaskGenerator::resetMaskApplicator(bool forceScalar) 0126 { 0127 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator>>(this,forceScalar)); 0128 } 0129