1 /*
2 * Copyright (c) 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
20
21 #include <cmath>
22
23 #include <config-vc.h>
24 #ifdef HAVE_VC
25 #if defined(__clang__)
26 #pragma GCC diagnostic ignored "-Wundef"
27 #pragma GCC diagnostic ignored "-Wlocal-type-template-args"
28 #endif
29 #if defined _MSC_VER
30 // Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
31 #pragma warning ( push )
32 #pragma warning ( disable : 4244 )
33 #pragma warning ( disable : 4800 )
34 #endif
35 #include <Vc/Vc>
36 #include <Vc/IO>
37 #if defined _MSC_VER
38 #pragma warning ( pop )
39 #endif
40 #endif
41
42 #include <QDomDocument>
43 #include <QVector>
44 #include <QPointF>
45
46 #include <kis_fast_math.h>
47 #include "kis_antialiasing_fade_maker.h"
48 #include "kis_brush_mask_applicator_factories.h"
49 #include "kis_brush_mask_applicator_base.h"
50
51 #include "kis_curve_rect_mask_generator.h"
52 #include "kis_curve_rect_mask_generator_p.h"
53 #include "kis_cubic_curve.h"
54
55
KisCurveRectangleMaskGenerator(qreal diameter,qreal ratio,qreal fh,qreal fv,int spikes,const KisCubicCurve & curve,bool antialiasEdges)56 KisCurveRectangleMaskGenerator::KisCurveRectangleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, const KisCubicCurve &curve, bool antialiasEdges)
57 : KisMaskGenerator(diameter, ratio, fh, fv, spikes, antialiasEdges, RECTANGLE, SoftId), d(new Private(antialiasEdges))
58 {
59 d->curveResolution = qRound( qMax(width(),height()) * OVERSAMPLING);
60 d->curveData = curve.floatTransfer( d->curveResolution + 1);
61 d->curvePoints = curve.points();
62 setCurveString(curve.toString());
63 d->dirty = false;
64
65 setScale(1.0, 1.0);
66
67 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
68 }
69
KisCurveRectangleMaskGenerator(const KisCurveRectangleMaskGenerator & rhs)70 KisCurveRectangleMaskGenerator::KisCurveRectangleMaskGenerator(const KisCurveRectangleMaskGenerator &rhs)
71 : KisMaskGenerator(rhs),
72 d(new Private(*rhs.d))
73 {
74 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
75 }
76
clone() const77 KisMaskGenerator* KisCurveRectangleMaskGenerator::clone() const
78 {
79 return new KisCurveRectangleMaskGenerator(*this);
80 }
81
setScale(qreal scaleX,qreal scaleY)82 void KisCurveRectangleMaskGenerator::setScale(qreal scaleX, qreal scaleY)
83 {
84 KisMaskGenerator::setScale(scaleX, scaleY);
85
86 qreal halfWidth = 0.5 * effectiveSrcWidth();
87 qreal halfHeight = 0.5 * effectiveSrcHeight();
88
89 d->xcoeff = 1.0 / halfWidth;
90 d->ycoeff = 1.0 / halfHeight;
91
92 d->fadeMaker.setLimits(halfWidth, halfHeight);
93 }
94
~KisCurveRectangleMaskGenerator()95 KisCurveRectangleMaskGenerator::~KisCurveRectangleMaskGenerator()
96 {
97 }
98
value(qreal xr,qreal yr) const99 quint8 KisCurveRectangleMaskGenerator::Private::value(qreal xr, qreal yr) const
100 {
101 xr = qAbs(xr) * xcoeff;
102 yr = qAbs(yr) * ycoeff;
103
104 int sIndex = qRound(xr * (curveResolution));
105 int tIndex = qRound(yr * (curveResolution));
106
107 int sIndexInverted = curveResolution - sIndex;
108 int tIndexInverted = curveResolution - tIndex;
109
110 qreal blend = (curveData.at(sIndex) * (1.0 - curveData.at(sIndexInverted)) *
111 curveData.at(tIndex) * (1.0 - curveData.at(tIndexInverted)));
112
113 return (1.0 - blend) * 255;
114 }
115
valueAt(qreal x,qreal y) const116 quint8 KisCurveRectangleMaskGenerator::valueAt(qreal x, qreal y) const
117 {
118 if (isEmpty()) return 255;
119 qreal xr = x;
120 qreal yr = qAbs(y);
121 fixRotation(xr, yr);
122
123 quint8 value;
124 if (d->fadeMaker.needFade(xr, yr, &value)) {
125 return value;
126 }
127
128 return d->value(xr, yr);
129 }
130
toXML(QDomDocument & doc,QDomElement & e) const131 void KisCurveRectangleMaskGenerator::toXML(QDomDocument& doc, QDomElement& e) const
132 {
133 KisMaskGenerator::toXML(doc, e);
134 e.setAttribute("softness_curve", curveString());
135 }
136
setSoftness(qreal softness)137 void KisCurveRectangleMaskGenerator::setSoftness(qreal softness)
138 {
139 // performance
140 if (!d->dirty && softness == 1.0) return;
141 d->dirty = true;
142 KisMaskGenerator::setSoftness(softness);
143 KisCurveCircleMaskGenerator::transformCurveForSoftness(softness,d->curvePoints, d->curveResolution + 1, d->curveData);
144 d->dirty = false;
145 }
146
shouldVectorize() const147 bool KisCurveRectangleMaskGenerator::shouldVectorize() const
148 {
149 return !shouldSupersample() && spikes() == 2;
150 }
151
applicator()152 KisBrushMaskApplicatorBase* KisCurveRectangleMaskGenerator::applicator()
153 {
154 return d->applicator.data();
155 }
156
resetMaskApplicator(bool forceScalar)157 void KisCurveRectangleMaskGenerator::resetMaskApplicator(bool forceScalar)
158 {
159 d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
160 }
161
162