shun-iwasawa 5903e5
#include "iwa_lineargradientfx.h"
shun-iwasawa 5903e5
shun-iwasawa 5903e5
#include "tspectrumparam.h"
shun-iwasawa 5903e5
#include "gradients.h"
shun-iwasawa 5903e5
#include "tparamuiconcept.h"
shun-iwasawa 5903e5
#include "traster.h"
shun-iwasawa 5903e5
shun-iwasawa 5903e5
//------------------------------------------------------------
shun-iwasawa 5903e5
shun-iwasawa 5903e5
Iwa_LinearGradientFx::Iwa_LinearGradientFx()
shun-iwasawa 5903e5
    : m_startPoint(TPointD(-50.0, 0.0))
shun-iwasawa 5903e5
    , m_endPoint(TPointD(50.0, 0.0))
shun-iwasawa 5903e5
    , m_startColor(TPixel32::Black)
shun-iwasawa 5903e5
    , m_endColor(TPixel32::White)
shun-iwasawa 5903e5
    , m_curveType(new TIntEnumParam(EaseInOut, "Ease In-Out"))
shun-iwasawa 5903e5
    , m_wave_amplitude(0.0)
shun-iwasawa 5903e5
    , m_wave_freq(0.0)
shun-iwasawa 5903e5
    , m_wave_phase(0.0) {
shun-iwasawa 5903e5
  m_startPoint->getX()->setMeasureName("fxLength");
shun-iwasawa 5903e5
  m_startPoint->getY()->setMeasureName("fxLength");
shun-iwasawa 5903e5
  m_endPoint->getX()->setMeasureName("fxLength");
shun-iwasawa 5903e5
  m_endPoint->getY()->setMeasureName("fxLength");
shun-iwasawa 5903e5
  bindParam(this, "startPoint", m_startPoint);
shun-iwasawa 5903e5
  bindParam(this, "endPoint", m_endPoint);
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  m_curveType->addItem(Linear, "Linear");
shun-iwasawa 5903e5
  m_curveType->addItem(EaseIn, "Ease In");
shun-iwasawa 5903e5
  m_curveType->addItem(EaseOut, "Ease Out");
shun-iwasawa 5903e5
  bindParam(this, "curveType", m_curveType);
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  m_wave_amplitude->setValueRange(0, std::numeric_limits<double>::max());</double>
shun-iwasawa 5903e5
  m_wave_amplitude->setMeasureName("fxLength");
shun-iwasawa 5903e5
  bindParam(this, "wave_amplitude", m_wave_amplitude);
shun-iwasawa 5903e5
  bindParam(this, "wave_frequency", m_wave_freq);
shun-iwasawa 5903e5
  bindParam(this, "wave_phase", m_wave_phase);
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  bindParam(this, "startColor", m_startColor);
shun-iwasawa 5903e5
  bindParam(this, "endColor", m_endColor);
shun-iwasawa 5903e5
}
shun-iwasawa 5903e5
shun-iwasawa 5903e5
//------------------------------------------------------------
shun-iwasawa 5903e5
shun-iwasawa 5903e5
bool Iwa_LinearGradientFx::doGetBBox(double frame, TRectD &bBox,
shun-iwasawa 5903e5
                                     const TRenderSettings &ri) {
shun-iwasawa 5903e5
  bBox = TConsts::infiniteRectD;
shun-iwasawa 5903e5
  return true;
shun-iwasawa 5903e5
}
shun-iwasawa 5903e5
shun-iwasawa 5903e5
//------------------------------------------------------------
shun-iwasawa 5903e5
shun-iwasawa 5903e5
namespace {
shun-iwasawa 5903e5
template <typename pixel="" raster,="" typename=""></typename>
shun-iwasawa 5903e5
void doLinearGradientT(RASTER ras, TDimensionI dim, TPointD startPos,
shun-iwasawa 5903e5
                       TPointD endPos, const TSpectrumT<pixel> &spectrum,</pixel>
shun-iwasawa 5903e5
                       GradientCurveType type, double w_amplitude,
shun-iwasawa 5903e5
                       double w_freq, double w_phase, const TAffine &affInv) {
shun-iwasawa 5903e5
  auto getFactor = [&](double t) {
shun-iwasawa 5903e5
    if (t > 1.0)
shun-iwasawa 5903e5
      t = 1.0;
shun-iwasawa 5903e5
    else if (t < 0.0)
shun-iwasawa 5903e5
      t = 0.0;
shun-iwasawa 5903e5
shun-iwasawa 5903e5
    double factor;
shun-iwasawa 5903e5
    switch (type) {
shun-iwasawa 5903e5
    case Linear:
shun-iwasawa 5903e5
      factor = t;
shun-iwasawa 5903e5
      break;
shun-iwasawa 5903e5
    case EaseIn:
shun-iwasawa 5903e5
      factor = t * t;
shun-iwasawa 5903e5
      break;
shun-iwasawa 5903e5
    case EaseOut:
shun-iwasawa 5903e5
      factor = 1.0 - (1.0 - t) * (1.0 - t);
shun-iwasawa 5903e5
      break;
shun-iwasawa 5903e5
    case EaseInOut:
shun-iwasawa 5903e5
    default:
shun-iwasawa 5903e5
      factor = (-2 * t + 3) * (t * t);
shun-iwasawa 5903e5
      break;
shun-iwasawa 5903e5
    }
shun-iwasawa 5903e5
    return factor;
shun-iwasawa 5903e5
  };
shun-iwasawa 5903e5
  startPos      = affInv * startPos;
shun-iwasawa 5903e5
  endPos        = affInv * endPos;
shun-iwasawa 5903e5
  TPointD seVec = endPos - startPos;
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  if (seVec == TPointD()) {
shun-iwasawa 5903e5
    ras->fill(spectrum.getPremultipliedValue(0.0));
shun-iwasawa 5903e5
    return;
shun-iwasawa 5903e5
  }
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  TPointD posTrasf = -startPos;
shun-iwasawa 5903e5
  double seVecLen2 = seVec.x * seVec.x + seVec.y * seVec.y;
shun-iwasawa 5903e5
  double seVecLen  = sqrt(seVecLen2);
shun-iwasawa 5903e5
  double amplitude = w_amplitude / seVecLen;
shun-iwasawa 5903e5
  TPointD auxVec(-seVec.y / seVecLen, seVec.x / seVecLen);
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  ras->lock();
shun-iwasawa 5903e5
  for (int j = 0; j < ras->getLy(); j++) {
shun-iwasawa 5903e5
    TPointD posAux = posTrasf;
shun-iwasawa 5903e5
shun-iwasawa 5903e5
    PIXEL *pix    = ras->pixels(j);
shun-iwasawa 5903e5
    PIXEL *endPix = pix + ras->getLx();
shun-iwasawa 5903e5
shun-iwasawa 5903e5
    while (pix < endPix) {
shun-iwasawa 5903e5
      double t = (seVec.x * posAux.x + seVec.y * posAux.y) / seVecLen2;
shun-iwasawa 5903e5
      if (amplitude) {
shun-iwasawa 5903e5
        double distance = posAux.x * auxVec.x + posAux.y * auxVec.y;
shun-iwasawa 5903e5
        t += amplitude * sin(w_freq * distance + w_phase);
shun-iwasawa 5903e5
      }
shun-iwasawa 5903e5
      double factor = getFactor(t);
shun-iwasawa 5903e5
      *pix++        = spectrum.getPremultipliedValue(factor);
shun-iwasawa 5903e5
shun-iwasawa 5903e5
      posAux.x += affInv.a11;
shun-iwasawa 5903e5
      posAux.y += affInv.a21;
shun-iwasawa 5903e5
    }
shun-iwasawa 5903e5
    posTrasf.x += affInv.a12;
shun-iwasawa 5903e5
    posTrasf.y += affInv.a22;
shun-iwasawa 5903e5
  }
shun-iwasawa 5903e5
  ras->unlock();
shun-iwasawa 5903e5
}
shun-iwasawa 5903e5
}  // namespace
shun-iwasawa 5903e5
shun-iwasawa 5903e5
//------------------------------------------------------------
shun-iwasawa 5903e5
shun-iwasawa 5903e5
void Iwa_LinearGradientFx::doCompute(TTile &tile, double frame,
shun-iwasawa 5903e5
                                     const TRenderSettings &ri) {
shun-iwasawa 5903e5
  if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) {
shun-iwasawa 5903e5
    throw TRopException("unsupported input pixel type");
shun-iwasawa 5903e5
  }
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  // convert shape position to render region coordinate
shun-iwasawa 5903e5
  TAffine aff = ri.m_affine;
shun-iwasawa 5903e5
  TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy());
shun-iwasawa 5903e5
  TPointD dimOffset((float)dimOut.lx / 2.0f, (float)dimOut.ly / 2.0f);
shun-iwasawa 5903e5
  TPointD startPos = aff * m_startPoint->getValue(frame) -
shun-iwasawa 5903e5
                     (tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
shun-iwasawa 5903e5
  TPointD endPos = aff * m_endPoint->getValue(frame) -
shun-iwasawa 5903e5
                   (tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  double w_amplitude = m_wave_amplitude->getValue(frame) / ri.m_shrinkX;
shun-iwasawa 5903e5
  double w_freq      = m_wave_freq->getValue(frame) * ri.m_shrinkX;
shun-iwasawa 5903e5
  double w_phase     = m_wave_phase->getValue(frame);
shun-iwasawa 5903e5
  w_freq *= 0.01 * M_PI_180;
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  std::vector<tspectrum::colorkey> colors = {</tspectrum::colorkey>
shun-iwasawa 5903e5
      TSpectrum::ColorKey(0, m_startColor->getValue(frame)),
shun-iwasawa 5903e5
      TSpectrum::ColorKey(1, m_endColor->getValue(frame))};
shun-iwasawa 5903e5
  TSpectrumParamP m_colors = TSpectrumParamP(colors);
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  tile.getRaster()->clear();
shun-iwasawa 5903e5
  TRaster32P outRas32 = (TRaster32P)tile.getRaster();
shun-iwasawa 5903e5
  TRaster64P outRas64 = (TRaster64P)tile.getRaster();
shun-iwasawa 5903e5
  if (outRas32)
shun-iwasawa 5903e5
    doLinearGradientT<traster32p, tpixel32="">(</traster32p,>
shun-iwasawa 5903e5
        outRas32, dimOut, startPos, endPos, m_colors->getValue(frame),
shun-iwasawa 5903e5
        (GradientCurveType)m_curveType->getValue(), w_amplitude, w_freq,
shun-iwasawa 5903e5
        w_phase, aff.inv());
shun-iwasawa 5903e5
  else if (outRas64)
shun-iwasawa 5903e5
    doLinearGradientT<traster64p, tpixel64="">(</traster64p,>
shun-iwasawa 5903e5
        outRas64, dimOut, startPos, endPos, m_colors->getValue64(frame),
shun-iwasawa 5903e5
        (GradientCurveType)m_curveType->getValue(), w_amplitude, w_freq,
shun-iwasawa 5903e5
        w_phase, aff.inv());
shun-iwasawa 5903e5
}
shun-iwasawa 5903e5
shun-iwasawa 5903e5
//------------------------------------------------------------
shun-iwasawa 5903e5
shun-iwasawa 5903e5
void Iwa_LinearGradientFx::getParamUIs(TParamUIConcept *&concepts,
shun-iwasawa 5903e5
                                       int &length) {
shun-iwasawa 5903e5
  concepts = new TParamUIConcept[length = 1];
shun-iwasawa 5903e5
shun-iwasawa 5903e5
  concepts[0].m_type  = TParamUIConcept::LINEAR_RANGE;
shun-iwasawa 5903e5
  concepts[0].m_label = "";
shun-iwasawa 5903e5
  concepts[0].m_params.push_back(m_startPoint);
shun-iwasawa 5903e5
  concepts[0].m_params.push_back(m_endPoint);
shun-iwasawa 5903e5
}
shun-iwasawa 5903e5
shun-iwasawa 5903e5
//------------------------------------------------------------
shun-iwasawa 5903e5
shun-iwasawa 5903e5
FX_PLUGIN_IDENTIFIER(Iwa_LinearGradientFx, "iwa_LinearGradientFx");