shun-iwasawa 00ed45
#include "iwa_spingradientfx.h"
shun-iwasawa 00ed45
shun-iwasawa 00ed45
#include "trop.h"
shun-iwasawa 00ed45
#include "tparamuiconcept.h"
shun-iwasawa 00ed45
#include "tspectrumparam.h"
shun-iwasawa 00ed45
#include "gradients.h"
shun-iwasawa 00ed45
shun-iwasawa 00ed45
#include <qpolygonf></qpolygonf>
shun-iwasawa 00ed45
shun-iwasawa 00ed45
#include <array></array>
shun-iwasawa 00ed45
#include <algorithm></algorithm>
shun-iwasawa 00ed45
shun-iwasawa 00ed45
//------------------------------------------------------------
shun-iwasawa 00ed45
shun-iwasawa 00ed45
Iwa_SpinGradientFx::Iwa_SpinGradientFx()
shun-iwasawa 00ed45
    : m_center(TPointD(0.0, 0.0))
shun-iwasawa 00ed45
    , m_startAngle(0.0)
shun-iwasawa 00ed45
    , m_endAngle(0.0)
shun-iwasawa 00ed45
    , m_startColor(TPixel32::Black)
shun-iwasawa 00ed45
    , m_endColor(TPixel32::White)
shun-iwasawa 00ed45
    , m_curveType(new TIntEnumParam()) {
shun-iwasawa 00ed45
  m_center->getX()->setMeasureName("fxLength");
shun-iwasawa 00ed45
  m_center->getY()->setMeasureName("fxLength");
shun-iwasawa 00ed45
  bindParam(this, "center", m_center);
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  m_startAngle->setValueRange(-360, 720);
shun-iwasawa 00ed45
  m_endAngle->setValueRange(-360, 720);
shun-iwasawa 00ed45
  bindParam(this, "startAngle", m_startAngle);
shun-iwasawa 00ed45
  bindParam(this, "endAngle", m_endAngle);
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  m_curveType->addItem(EaseInOut, "Ease In-Out");
shun-iwasawa 00ed45
  m_curveType->addItem(Linear, "Linear");
shun-iwasawa 00ed45
  m_curveType->addItem(EaseIn, "Ease In");
shun-iwasawa 00ed45
  m_curveType->addItem(EaseOut, "Ease Out");
shun-iwasawa 00ed45
  m_curveType->setDefaultValue(Linear);
shun-iwasawa 00ed45
  m_curveType->setValue(Linear);
shun-iwasawa 00ed45
  bindParam(this, "curveType", m_curveType);
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  bindParam(this, "startColor", m_startColor);
shun-iwasawa 00ed45
  bindParam(this, "endColor", m_endColor);
shun-iwasawa 481b59
shun-iwasawa 481b59
  enableComputeInFloat(true);
shun-iwasawa 00ed45
}
shun-iwasawa 00ed45
shun-iwasawa 00ed45
//------------------------------------------------------------
shun-iwasawa 00ed45
shun-iwasawa 00ed45
bool Iwa_SpinGradientFx::doGetBBox(double frame, TRectD &bBox,
shun-iwasawa 00ed45
                                   const TRenderSettings &ri) {
shun-iwasawa 00ed45
  bBox = TConsts::infiniteRectD;
shun-iwasawa 00ed45
  return true;
shun-iwasawa 00ed45
}
shun-iwasawa 00ed45
shun-iwasawa 00ed45
//------------------------------------------------------------
shun-iwasawa 00ed45
namespace {
shun-iwasawa 00ed45
template <typename pixel="" raster,="" typename=""></typename>
shun-iwasawa 00ed45
void doSpinGradientT(RASTER ras, TDimensionI dim, TPointD centerPos,
shun-iwasawa 00ed45
                     double startAngle, double endAngle,
shun-iwasawa 00ed45
                     const TSpectrumT<pixel> &spectrum,</pixel>
shun-iwasawa 00ed45
                     GradientCurveType type) {
shun-iwasawa 00ed45
  auto getFactor = [&](double angle) {
shun-iwasawa 00ed45
    double p = angle - startAngle;
shun-iwasawa 00ed45
    if (p < 0) p += 2.0 * M_PI;
shun-iwasawa 00ed45
    double range = endAngle - startAngle;
shun-iwasawa 00ed45
    if (range <= 0) range += 2.0 * M_PI;
shun-iwasawa 00ed45
shun-iwasawa 00ed45
    double t;
shun-iwasawa 00ed45
    if (range >= p)
shun-iwasawa 00ed45
      t = p / range;
shun-iwasawa 00ed45
    else if (M_PI + range / 2.0 > p)
shun-iwasawa 00ed45
      t = 1.0;
shun-iwasawa 00ed45
    else
shun-iwasawa 00ed45
      t = 0.0;
shun-iwasawa 00ed45
shun-iwasawa 00ed45
    double factor;
shun-iwasawa 00ed45
    switch (type) {
shun-iwasawa 00ed45
    case Linear:
shun-iwasawa 00ed45
      factor = t;
shun-iwasawa 00ed45
      break;
shun-iwasawa 00ed45
    case EaseIn:
shun-iwasawa 00ed45
      factor = t * t;
shun-iwasawa 00ed45
      break;
shun-iwasawa 00ed45
    case EaseOut:
shun-iwasawa 00ed45
      factor = 1.0 - (1.0 - t) * (1.0 - t);
shun-iwasawa 00ed45
      break;
shun-iwasawa 00ed45
    case EaseInOut:
shun-iwasawa 00ed45
    default:
shun-iwasawa 00ed45
      factor = (-2 * t + 3) * (t * t);
shun-iwasawa 00ed45
      break;
shun-iwasawa 00ed45
    }
shun-iwasawa 00ed45
    return factor;
shun-iwasawa 00ed45
  };
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  ras->lock();
shun-iwasawa 00ed45
  for (int j = 0; j < ras->getLy(); j++) {
shun-iwasawa 00ed45
    PIXEL *pix    = ras->pixels(j);
shun-iwasawa 00ed45
    PIXEL *endPix = pix + ras->getLx();
shun-iwasawa 00ed45
    double dy     = (double)j - centerPos.y;
shun-iwasawa 00ed45
    double dx     = -centerPos.x;
shun-iwasawa 00ed45
    while (pix < endPix) {
shun-iwasawa 00ed45
      double angle  = std::atan2(dy, dx);
shun-iwasawa 00ed45
      double factor = getFactor(angle);
shun-iwasawa 00ed45
      *pix++        = spectrum.getPremultipliedValue(factor);
shun-iwasawa 00ed45
      dx += 1.0;
shun-iwasawa 00ed45
    }
shun-iwasawa 00ed45
  }
shun-iwasawa 00ed45
  ras->unlock();
shun-iwasawa 00ed45
}
shun-iwasawa 00ed45
}  // namespace
shun-iwasawa 00ed45
shun-iwasawa 00ed45
//------------------------------------------------------------
shun-iwasawa 00ed45
shun-iwasawa 00ed45
void Iwa_SpinGradientFx::doCompute(TTile &tile, double frame,
shun-iwasawa 00ed45
                                   const TRenderSettings &ri) {
shun-iwasawa 481b59
  if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster()) &&
shun-iwasawa 481b59
      !((TRasterFP)tile.getRaster())) {
shun-iwasawa 00ed45
    throw TRopException("unsupported input pixel type");
shun-iwasawa 00ed45
  }
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  // convert shape position to render region coordinate
shun-iwasawa 00ed45
  TAffine aff = ri.m_affine;
shun-iwasawa 00ed45
  TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy());
shun-iwasawa 00ed45
  TPointD dimOffset((float)dimOut.lx / 2.0f, (float)dimOut.ly / 2.0f);
shun-iwasawa 00ed45
  TPointD centerPos = aff * m_center->getValue(frame) -
shun-iwasawa 00ed45
                      (tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  std::vector<tspectrum::colorkey> colors = {</tspectrum::colorkey>
shun-iwasawa 00ed45
      TSpectrum::ColorKey(0, m_startColor->getValue(frame)),
shun-iwasawa 00ed45
      TSpectrum::ColorKey(1, m_endColor->getValue(frame))};
shun-iwasawa 00ed45
  TSpectrumParamP m_colors = TSpectrumParamP(colors);
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  auto conv2RadianAndClamp = [](double angle) {
shun-iwasawa 00ed45
    double ret = angle * M_PI / 180.0;
shun-iwasawa 00ed45
    while (ret < -M_PI) {
shun-iwasawa 00ed45
      ret += 2.0 * M_PI;
shun-iwasawa 00ed45
    }
shun-iwasawa 00ed45
    while (ret >= M_PI) {
shun-iwasawa 00ed45
      ret -= 2.0 * M_PI;
shun-iwasawa 00ed45
    }
shun-iwasawa 00ed45
    return ret;
shun-iwasawa 00ed45
  };
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  double startAngle = conv2RadianAndClamp(m_startAngle->getValue(frame));
shun-iwasawa 00ed45
  double endAngle   = conv2RadianAndClamp(m_endAngle->getValue(frame));
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  tile.getRaster()->clear();
shun-iwasawa 00ed45
  TRaster32P outRas32 = (TRaster32P)tile.getRaster();
shun-iwasawa 00ed45
  TRaster64P outRas64 = (TRaster64P)tile.getRaster();
shun-iwasawa 481b59
  TRasterFP outRasF   = (TRasterFP)tile.getRaster();
shun-iwasawa 00ed45
  if (outRas32)
shun-iwasawa 00ed45
    doSpinGradientT<traster32p, tpixel32="">(</traster32p,>
shun-iwasawa 00ed45
        outRas32, dimOut, centerPos, startAngle, endAngle,
shun-iwasawa 00ed45
        m_colors->getValue(frame), (GradientCurveType)m_curveType->getValue());
shun-iwasawa 00ed45
  else if (outRas64)
shun-iwasawa 00ed45
    doSpinGradientT<traster64p, tpixel64="">(</traster64p,>
shun-iwasawa 00ed45
        outRas64, dimOut, centerPos, startAngle, endAngle,
shun-iwasawa 00ed45
        m_colors->getValue64(frame),
shun-iwasawa 00ed45
        (GradientCurveType)m_curveType->getValue());
shun-iwasawa 481b59
  else if (outRasF)
shun-iwasawa 481b59
    doSpinGradientT<trasterfp, tpixelf="">(</trasterfp,>
shun-iwasawa 481b59
        outRasF, dimOut, centerPos, startAngle, endAngle,
shun-iwasawa 481b59
        m_colors->getValueF(frame), (GradientCurveType)m_curveType->getValue());
shun-iwasawa 00ed45
}
shun-iwasawa 00ed45
shun-iwasawa 00ed45
//------------------------------------------------------------
shun-iwasawa 00ed45
shun-iwasawa 00ed45
void Iwa_SpinGradientFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
shun-iwasawa 00ed45
  concepts = new TParamUIConcept[length = 2];
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  concepts[0].m_type  = TParamUIConcept::ANGLE_2;
shun-iwasawa 00ed45
  concepts[0].m_label = "Angle";
shun-iwasawa 00ed45
  concepts[0].m_params.push_back(m_startAngle);
shun-iwasawa 00ed45
  concepts[0].m_params.push_back(m_endAngle);
shun-iwasawa 00ed45
  concepts[0].m_params.push_back(m_center);
shun-iwasawa 00ed45
shun-iwasawa 00ed45
  concepts[1].m_type  = TParamUIConcept::POINT;
shun-iwasawa 00ed45
  concepts[1].m_label = "Center";
shun-iwasawa 00ed45
  concepts[1].m_params.push_back(m_center);
shun-iwasawa 00ed45
}
shun-iwasawa 00ed45
shun-iwasawa 00ed45
//------------------------------------------------------------
shun-iwasawa 00ed45
shun-iwasawa 00ed45
FX_PLUGIN_IDENTIFIER(Iwa_SpinGradientFx, "iwa_SpinGradientFx");