1 #include "iwa_lineargradientfx.h"
2 
3 #include "tspectrumparam.h"
4 #include "gradients.h"
5 #include "tparamuiconcept.h"
6 #include "traster.h"
7 
8 //------------------------------------------------------------
9 
Iwa_LinearGradientFx()10 Iwa_LinearGradientFx::Iwa_LinearGradientFx()
11     : m_startPoint(TPointD(-50.0, 0.0))
12     , m_endPoint(TPointD(50.0, 0.0))
13     , m_startColor(TPixel32::Black)
14     , m_endColor(TPixel32::White)
15     , m_curveType(new TIntEnumParam(EaseInOut, "Ease In-Out"))
16     , m_wave_amplitude(0.0)
17     , m_wave_freq(0.0)
18     , m_wave_phase(0.0) {
19   m_startPoint->getX()->setMeasureName("fxLength");
20   m_startPoint->getY()->setMeasureName("fxLength");
21   m_endPoint->getX()->setMeasureName("fxLength");
22   m_endPoint->getY()->setMeasureName("fxLength");
23   bindParam(this, "startPoint", m_startPoint);
24   bindParam(this, "endPoint", m_endPoint);
25 
26   m_curveType->addItem(Linear, "Linear");
27   m_curveType->addItem(EaseIn, "Ease In");
28   m_curveType->addItem(EaseOut, "Ease Out");
29   bindParam(this, "curveType", m_curveType);
30 
31   m_wave_amplitude->setValueRange(0, std::numeric_limits<double>::max());
32   m_wave_amplitude->setMeasureName("fxLength");
33   bindParam(this, "wave_amplitude", m_wave_amplitude);
34   bindParam(this, "wave_frequency", m_wave_freq);
35   bindParam(this, "wave_phase", m_wave_phase);
36 
37   bindParam(this, "startColor", m_startColor);
38   bindParam(this, "endColor", m_endColor);
39 }
40 
41 //------------------------------------------------------------
42 
doGetBBox(double frame,TRectD & bBox,const TRenderSettings & ri)43 bool Iwa_LinearGradientFx::doGetBBox(double frame, TRectD &bBox,
44                                      const TRenderSettings &ri) {
45   bBox = TConsts::infiniteRectD;
46   return true;
47 }
48 
49 //------------------------------------------------------------
50 
51 namespace {
52 template <typename RASTER, typename PIXEL>
doLinearGradientT(RASTER ras,TDimensionI dim,TPointD startPos,TPointD endPos,const TSpectrumT<PIXEL> & spectrum,GradientCurveType type,double w_amplitude,double w_freq,double w_phase,const TAffine & affInv)53 void doLinearGradientT(RASTER ras, TDimensionI dim, TPointD startPos,
54                        TPointD endPos, const TSpectrumT<PIXEL> &spectrum,
55                        GradientCurveType type, double w_amplitude,
56                        double w_freq, double w_phase, const TAffine &affInv) {
57   auto getFactor = [&](double t) {
58     if (t > 1.0)
59       t = 1.0;
60     else if (t < 0.0)
61       t = 0.0;
62 
63     double factor;
64     switch (type) {
65     case Linear:
66       factor = t;
67       break;
68     case EaseIn:
69       factor = t * t;
70       break;
71     case EaseOut:
72       factor = 1.0 - (1.0 - t) * (1.0 - t);
73       break;
74     case EaseInOut:
75     default:
76       factor = (-2 * t + 3) * (t * t);
77       break;
78     }
79     return factor;
80   };
81   startPos      = affInv * startPos;
82   endPos        = affInv * endPos;
83   TPointD seVec = endPos - startPos;
84 
85   if (seVec == TPointD()) {
86     ras->fill(spectrum.getPremultipliedValue(0.0));
87     return;
88   }
89 
90   TPointD posTrasf = -startPos;
91   double seVecLen2 = seVec.x * seVec.x + seVec.y * seVec.y;
92   double seVecLen  = sqrt(seVecLen2);
93   double amplitude = w_amplitude / seVecLen;
94   TPointD auxVec(-seVec.y / seVecLen, seVec.x / seVecLen);
95 
96   ras->lock();
97   for (int j = 0; j < ras->getLy(); j++) {
98     TPointD posAux = posTrasf;
99 
100     PIXEL *pix    = ras->pixels(j);
101     PIXEL *endPix = pix + ras->getLx();
102 
103     while (pix < endPix) {
104       double t = (seVec.x * posAux.x + seVec.y * posAux.y) / seVecLen2;
105       if (amplitude) {
106         double distance = posAux.x * auxVec.x + posAux.y * auxVec.y;
107         t += amplitude * sin(w_freq * distance + w_phase);
108       }
109       double factor = getFactor(t);
110       *pix++        = spectrum.getPremultipliedValue(factor);
111 
112       posAux.x += affInv.a11;
113       posAux.y += affInv.a21;
114     }
115     posTrasf.x += affInv.a12;
116     posTrasf.y += affInv.a22;
117   }
118   ras->unlock();
119 }
120 }  // namespace
121 
122 //------------------------------------------------------------
123 
doCompute(TTile & tile,double frame,const TRenderSettings & ri)124 void Iwa_LinearGradientFx::doCompute(TTile &tile, double frame,
125                                      const TRenderSettings &ri) {
126   if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) {
127     throw TRopException("unsupported input pixel type");
128   }
129 
130   // convert shape position to render region coordinate
131   TAffine aff = ri.m_affine;
132   TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy());
133   TPointD dimOffset((float)dimOut.lx / 2.0f, (float)dimOut.ly / 2.0f);
134   TPointD startPos = aff * m_startPoint->getValue(frame) -
135                      (tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
136   TPointD endPos = aff * m_endPoint->getValue(frame) -
137                    (tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
138 
139   double w_amplitude = m_wave_amplitude->getValue(frame) / ri.m_shrinkX;
140   double w_freq      = m_wave_freq->getValue(frame) * ri.m_shrinkX;
141   double w_phase     = m_wave_phase->getValue(frame);
142   w_freq *= 0.01 * M_PI_180;
143 
144   std::vector<TSpectrum::ColorKey> colors = {
145       TSpectrum::ColorKey(0, m_startColor->getValue(frame)),
146       TSpectrum::ColorKey(1, m_endColor->getValue(frame))};
147   TSpectrumParamP m_colors = TSpectrumParamP(colors);
148 
149   tile.getRaster()->clear();
150   TRaster32P outRas32 = (TRaster32P)tile.getRaster();
151   TRaster64P outRas64 = (TRaster64P)tile.getRaster();
152   if (outRas32)
153     doLinearGradientT<TRaster32P, TPixel32>(
154         outRas32, dimOut, startPos, endPos, m_colors->getValue(frame),
155         (GradientCurveType)m_curveType->getValue(), w_amplitude, w_freq,
156         w_phase, aff.inv());
157   else if (outRas64)
158     doLinearGradientT<TRaster64P, TPixel64>(
159         outRas64, dimOut, startPos, endPos, m_colors->getValue64(frame),
160         (GradientCurveType)m_curveType->getValue(), w_amplitude, w_freq,
161         w_phase, aff.inv());
162 }
163 
164 //------------------------------------------------------------
165 
getParamUIs(TParamUIConcept * & concepts,int & length)166 void Iwa_LinearGradientFx::getParamUIs(TParamUIConcept *&concepts,
167                                        int &length) {
168   concepts = new TParamUIConcept[length = 1];
169 
170   concepts[0].m_type  = TParamUIConcept::LINEAR_RANGE;
171   concepts[0].m_label = "";
172   concepts[0].m_params.push_back(m_startPoint);
173   concepts[0].m_params.push_back(m_endPoint);
174 }
175 
176 //------------------------------------------------------------
177 
178 FX_PLUGIN_IDENTIFIER(Iwa_LinearGradientFx, "iwa_LinearGradientFx");
179