Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Core-system includes
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Fx basics
Toshihiro Shimizu 890ddd
#include "tparamcontainer.h"
Toshihiro Shimizu 890ddd
#include "tbasefx.h"
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Images components
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Optimization components
Toshihiro Shimizu 890ddd
#include "trenderresourcemanager.h"
Toshihiro Shimizu 890ddd
#include "tfxcachemanager.h"
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Diagnostics
Toshihiro Shimizu 890ddd
//#define DIAGNOSTICS
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Toshihiro Shimizu 890ddd
#include "diagnostics.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // DIAGNOSTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
inline bool areEqual(const TRasterFxRenderDataP &d1,
Shinya Kitaoka 120a6e
                     const TRasterFxRenderDataP &d2) {
Shinya Kitaoka 120a6e
  return (*d1 == *d2);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline int myCeil(double x) {
Shinya Kitaoka 120a6e
  return ((x - (int)(x)) > TConsts::epsilon ? (int)(x) + 1 : (int)(x));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRect myConvert(const TRectD &r, TPointD &dp) {
Shinya Kitaoka 120a6e
  TRect ri(tfloor(r.x0), tfloor(r.y0), myCeil(r.x1), myCeil(r.y1));
Shinya Kitaoka 120a6e
  dp.x = r.x0 - ri.x0;
Shinya Kitaoka 120a6e
  dp.y = r.y0 - ri.y0;
Shinya Kitaoka 120a6e
  assert(dp.x >= 0 && dp.y >= 0);
Shinya Kitaoka 120a6e
  return ri;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline bool myIsEmpty(const TRectD &r) {
Shinya Kitaoka 120a6e
  return r.getLx() < 1 || r.getLy() < 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRect myConvert(const TRectD &rect) {
Shinya Kitaoka 120a6e
  return TRect(tround(rect.x0), tround(rect.y0), tround(rect.x1) - 1,
Shinya Kitaoka 120a6e
               tround(rect.y1) - 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRectD myConvert(const TRect &rect) {
Shinya Kitaoka 120a6e
  return TRectD(rect.x0, rect.y0, rect.x1 + 1, rect.y1 + 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void enlargeToI(TRectD &r) {
Shinya Kitaoka 120a6e
  TRectD temp(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1));
Shinya Kitaoka 120a6e
  // NOTE: If we enlarge a TConsts::infiniteRectD or one which trespass
Shinya Kitaoka 120a6e
  // ints' numerical bounds, the rect may become empty.
Shinya Kitaoka 120a6e
  if (!myIsEmpty(temp)) r = temp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Calculates the 2-norm of the passed affine A - that is, the max modulus
Shinya Kitaoka 120a6e
// of A*A's eigenvalues (*A being the adjoint).
Shinya Kitaoka 120a6e
double norm2(const TAffine &aff) {
Shinya Kitaoka 120a6e
  double a11 = aff.a11 * aff.a11 + aff.a12 * aff.a12;
Shinya Kitaoka 120a6e
  double a12 = aff.a11 * aff.a21 + aff.a12 * aff.a22;
Shinya Kitaoka 120a6e
  double a21 = aff.a21 * aff.a11 + aff.a22 * aff.a12;
Shinya Kitaoka 120a6e
  double a22 = aff.a21 * aff.a21 + aff.a22 * aff.a22;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double a11plusa22 = a11 + a22;
Shinya Kitaoka 120a6e
  double delta      = sq(a11 - a22) + 4 * a12 * a21;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  delta = sqrt(delta);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double eig1 = a11plusa22 + delta;
Shinya Kitaoka 120a6e
  double eig2 = a11plusa22 - delta;
Shinya Kitaoka 120a6e
  return std::max(sqrt(eig1 / 2.0), sqrt(eig2 / 2.0));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline int getResampleFilterRadius(const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  switch (info.m_quality) {
Shinya Kitaoka 120a6e
  case TRenderSettings::StandardResampleQuality:
Shinya Kitaoka 120a6e
    return 1;
Shinya Kitaoka 120a6e
  case TRenderSettings::ImprovedResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::HighResampleQuality:
Shinya Kitaoka 120a6e
    return 3;
Shinya Kitaoka 120a6e
  case TRenderSettings::Triangle_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 1;
Shinya Kitaoka 120a6e
  case TRenderSettings::Mitchell_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Cubic5_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Cubic75_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Cubic1_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Hann2_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Hann3_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 3;
Shinya Kitaoka 120a6e
  case TRenderSettings::Hamming2_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Hamming3_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 3;
Shinya Kitaoka 120a6e
  case TRenderSettings::Lanczos2_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::Lanczos3_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 3;
Shinya Kitaoka 120a6e
  case TRenderSettings::Gauss_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 2;
Shinya Kitaoka 120a6e
  case TRenderSettings::ClosestPixel_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 1;
Shinya Kitaoka 120a6e
  case TRenderSettings::Bilinear_FilterResampleQuality:
Shinya Kitaoka 120a6e
    return 1;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    assert(false);
Shinya Kitaoka 120a6e
    return -1;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline QString traduce(const TRectD &rect) {
Shinya Kitaoka 120a6e
  return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " +
Shinya Kitaoka 120a6e
         QString::number(rect.x1) + " " + QString::number(rect.y1) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline QString traduce(const TRect &rect) {
Shinya Kitaoka 120a6e
  return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " +
Shinya Kitaoka 120a6e
         QString::number(rect.x1) + " " + QString::number(rect.y1) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline QString qTraduce(const TAffine &aff) {
Shinya Kitaoka 120a6e
  return "[" + QString::number(aff.a11, 'g', 15) + "," +
Shinya Kitaoka 120a6e
         QString::number(aff.a12, 'g', 15) + "," +
Shinya Kitaoka 120a6e
         QString::number(aff.a13, 'g', 15) + "," +
Shinya Kitaoka 120a6e
         QString::number(aff.a21, 'g', 15) + "," +
Shinya Kitaoka 120a6e
         QString::number(aff.a22, 'g', 15) + "," +
Shinya Kitaoka 120a6e
         QString::number(aff.a23, 'g', 15) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline std::string traduce(const TAffine &aff) {
Shinya Kitaoka 120a6e
  return
Shinya Kitaoka 120a6e
      // Observe that toString distinguishes + and - 0. That is a problem
Shinya Kitaoka 120a6e
      // when comparing aliases - so near 0 values are explicitly rounded to 0.
Shinya Kitaoka 120a6e
      (areAlmostEqual(aff.a11, 0.0) ? "0" : ::to_string(aff.a11, 5)) + "," +
Shinya Kitaoka 120a6e
      (areAlmostEqual(aff.a12, 0.0) ? "0" : ::to_string(aff.a12, 5)) + "," +
Shinya Kitaoka 120a6e
      (areAlmostEqual(aff.a13, 0.0) ? "0" : ::to_string(aff.a13, 5)) + "," +
Shinya Kitaoka 120a6e
      (areAlmostEqual(aff.a21, 0.0) ? "0" : ::to_string(aff.a21, 5)) + "," +
Shinya Kitaoka 120a6e
      (areAlmostEqual(aff.a22, 0.0) ? "0" : ::to_string(aff.a22, 5)) + "," +
Shinya Kitaoka 120a6e
      (areAlmostEqual(aff.a23, 0.0) ? "0" : ::to_string(aff.a23, 5));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // Local namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// The following should be cleared - and its functionalities surrendered
Shinya Kitaoka 120a6e
// directly
Shinya Kitaoka 120a6e
// to an appropriate resource manager...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Declares an image to be kept in cache until the render ends or is canceled.
Shinya Kitaoka 120a6e
void addRenderCache(const std::string &alias, TImageP image) {
Shinya Kitaoka 120a6e
  TFxCacheManager::instance()->add(alias, image);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! The inverse function to addRenderCache.
Shinya Kitaoka 120a6e
void removeRenderCache(const std::string &alias) {
Shinya Kitaoka 120a6e
  TFxCacheManager::instance()->remove(alias);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// TrFx   (Affine Transformer Fx)
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Internal fx node which applies the implicit affine stored in the
Shinya Kitaoka 120a6e
//! TRenderSettings structure,
Toshihiro Shimizu 890ddd
//! replacing the old TRasterFx::doCompute.
Shinya Kitaoka d1f6c4
class TrFx final : public TBaseRasterFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(TrFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterFx *m_fx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TrFx() {}
Shinya Kitaoka 120a6e
  ~TrFx() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setFx(TRasterFx *fx) { m_fx = fx; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  bool isCachable() const override {
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }  // Currently cachable as a test. Observe that it was NOT in Toonz 6.1
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 38fd86
    return true;
Shinya Kitaoka 38fd86
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  std::string getAlias(double frame,
Shinya Kitaoka 38fd86
                       const TRenderSettings &info) const override {
Shinya Kitaoka 120a6e
    // NOTE: TrFx are not present at this recursive level. Affines dealing is
Shinya Kitaoka 120a6e
    // currently handled by inserting the
Shinya Kitaoka 120a6e
    // rendering affine AFTER a getAlias call. Ever.
Shinya Kitaoka 120a6e
    std::string alias = getFxType();
Shinya Kitaoka 120a6e
    return alias + "[" + m_fx->getAlias(frame, info) + "]";
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  bool doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    // NOTE: TrFx are not present at this recursive level. Affines dealing is
Shinya Kitaoka 120a6e
    // still handled by TGeometryFxs here....
Shinya Kitaoka 120a6e
    return m_fx->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void doCompute(TTile &tile, double frame,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    const TRectD &rectOut =
Shinya Kitaoka 120a6e
        myConvert(tile.getRaster()->getBounds()) + tile.m_pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRectD rectIn;
Shinya Kitaoka 120a6e
    TRenderSettings infoIn(info);
Shinya Kitaoka 120a6e
    TAffine appliedAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!buildInput(rectOut, frame, info, rectIn, infoIn, appliedAff)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    const TRect &rectInI = myConvert(rectIn);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // rasIn e' un raster dello stesso tipo di tile.getRaster()
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TTile inTile;
Shinya Kitaoka 120a6e
    m_fx->allocateAndCompute(inTile, rectIn.getP00(),
Shinya Kitaoka 120a6e
                             TDimension(rectInI.getLx(), rectInI.getLy()),
Shinya Kitaoka 120a6e
                             tile.getRaster(), frame, infoIn);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    infoIn.m_affine = appliedAff;
Shinya Kitaoka 120a6e
    TRasterFx::applyAffine(tile, inTile, infoIn);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 38fd86
                    const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    TRectD rectIn;
Shinya Kitaoka 120a6e
    TRenderSettings infoIn(info);
Shinya Kitaoka 120a6e
    TAffine appliedAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!buildInput(rect, frame, info, rectIn, infoIn, appliedAff)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_fx->dryCompute(rectIn, frame, infoIn);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 473e70
                           const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    TRectD rectIn;
Shinya Kitaoka 120a6e
    TRenderSettings infoIn(info);
Shinya Kitaoka 120a6e
    TAffine appliedAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!buildInput(rect, frame, info, rectIn, infoIn, appliedAff)) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return TRasterFx::memorySize(rectIn, info.m_bpp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  bool buildInput(const TRectD &rectOut, double frame,
Shinya Kitaoka 120a6e
                  const TRenderSettings &infoOut, TRectD &rectIn,
Shinya Kitaoka 120a6e
                  TRenderSettings &infoIn, TAffine &appliedAff) {
Shinya Kitaoka 120a6e
    if (myIsEmpty(rectOut)) return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Build the affines
Shinya Kitaoka 120a6e
    infoIn.m_affine = m_fx->handledAffine(infoOut, frame);
Shinya Kitaoka 120a6e
    appliedAff      = infoOut.m_affine * infoIn.m_affine.inv();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Quick fix - prevent near-singular transforms.
Shinya Kitaoka 120a6e
    // NOTE: This check **SHOULD BE REMOVED** and dealt with at the RESAMPLING
Shinya Kitaoka 120a6e
    // level.
Shinya Kitaoka 120a6e
    //       Observe how the tolerance value is quite arbitrary! Yeah I know
Shinya Kitaoka 120a6e
    //       it's shameful... :(
Shinya Kitaoka 120a6e
    if (fabs(appliedAff.det()) < 1e-6)  // TO BE REMOVED
Shinya Kitaoka 120a6e
      return false;                     // TO BE REMOVED
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Build the input rect
Shinya Kitaoka 120a6e
    const TAffine &appliedAffInv = appliedAff.inv();
Shinya Kitaoka 120a6e
    int filterRadius             = getResampleFilterRadius(infoOut);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD bbox;
Shinya Kitaoka 120a6e
    m_fx->getBBox(frame, bbox, infoIn);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    rectIn =
Shinya Kitaoka 120a6e
        ((appliedAffInv * rectOut)
Shinya Kitaoka 120a6e
             .enlarge(
Shinya Kitaoka 120a6e
                 filterRadius) +  // The filter size applies in input during
Shinya Kitaoka 120a6e
         (appliedAffInv * rectOut.enlarge(filterRadius))) *
Shinya Kitaoka 120a6e
        bbox;  // magnifications, and in output during
Shinya Kitaoka 120a6e
               // minifications. Thus, they basically cumulate.
Shinya Kitaoka 120a6e
    if (myIsEmpty(rectIn)) return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    enlargeToI(rectIn);
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_IDENTIFIER_IS_HIDDEN(TrFx, "trFx")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// FxResourceBuilder
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// This class is the internal interface with the cache regarding intermediate
Shinya Kitaoka 120a6e
// render
Shinya Kitaoka 120a6e
// results. Please refer to the ResourceBuilder documentation in
Shinya Kitaoka 120a6e
// tfxcachemanager.cpp
Shinya Kitaoka d1f6c4
class FxResourceBuilder final : public ResourceBuilder {
Shinya Kitaoka 120a6e
  TRasterFxP m_rfx;
Shinya Kitaoka 120a6e
  double m_frame;
Shinya Kitaoka 120a6e
  const TRenderSettings *m_rs;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TTile *m_outTile;
Shinya Kitaoka 120a6e
  TTile *m_currTile;
Shinya Kitaoka 120a6e
  TTile m_newTile;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD m_outRect;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  FxResourceBuilder(const std::string &resourceName, const TRasterFxP &fx,
Shinya Kitaoka 120a6e
                    const TRenderSettings &rs, double frame)
Shinya Kitaoka 120a6e
      : ResourceBuilder(resourceName, fx.getPointer(), frame, rs)
Shinya Kitaoka 120a6e
      , m_rfx(fx)
Shinya Kitaoka 120a6e
      , m_frame(frame)
Shinya Kitaoka 120a6e
      , m_rs(&rs)
Shinya Kitaoka 120a6e
      , m_currTile(0) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  inline void build(TTile &tile);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 473e70
  void simCompute(const TRectD &rect) override {
Shinya Kitaoka 120a6e
    TRectD rectCpy(
Shinya Kitaoka 120a6e
        rect);  // Why the hell dryCompute(..) has non-const TRectD& input ????
Shinya Kitaoka 120a6e
    m_rfx->doDryCompute(rectCpy, m_frame, *m_rs);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void buildTileToCalculate(const TRectD &tileRect);
Shinya Kitaoka 473e70
  void compute(const TRectD &tileRect) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void upload(TCacheResourceP &resource) override;
Shinya Kitaoka 473e70
  bool download(TCacheResourceP &resource) override;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void FxResourceBuilder::build(TTile &tile) {
Shinya Kitaoka 120a6e
  m_outTile = &tile;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDimension dim(tile.getRaster()->getSize());
Shinya Kitaoka 120a6e
  m_outRect = TRectD(tile.m_pos, TDimensionD(dim.lx, dim.ly));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ResourceBuilder::build(m_outRect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FxResourceBuilder::buildTileToCalculate(const TRectD &tileGeom) {
Shinya Kitaoka 120a6e
  if (tileGeom == m_outRect) {
Shinya Kitaoka 120a6e
    m_currTile = m_outTile;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_newTile.m_pos = tileGeom.getP00();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterP outRas(m_outTile->getRaster());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // If possible, try to reuse outRas's buffer.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDimension outputSize(outRas->getSize());
Shinya Kitaoka 120a6e
  TDimension requiredSize(tceil(tileGeom.getLx()), tceil(tileGeom.getLy()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterP ras;
Shinya Kitaoka 120a6e
  if (outputSize.lx >= requiredSize.lx && outputSize.ly >= requiredSize.ly) {
Shinya Kitaoka 120a6e
    // Reuse fxOutput's buffer
Shinya Kitaoka 120a6e
    TRect rect(0, 0, requiredSize.lx - 1, requiredSize.ly - 1);
Shinya Kitaoka 120a6e
    ras = outRas->extract(rect);
Shinya Kitaoka 120a6e
    ras->clear();
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    ras = outRas->create(requiredSize.lx, requiredSize.ly);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_newTile.setRaster(ras);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_currTile = &m_newTile;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FxResourceBuilder::compute(const TRectD &tileRect) {
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
  TStopWatch sw;
Shinya Kitaoka 120a6e
  sw.start();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  buildTileToCalculate(tileRect);
Shinya Kitaoka 120a6e
  m_rfx->doCompute(*m_currTile, m_frame, *m_rs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
  sw.stop();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DIAGNOSTICS_THRSET("FComputeTime", sw.getTotalTime());
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void FxResourceBuilder::upload(TCacheResourceP &resource) {
Shinya Kitaoka 120a6e
  resource->upload(*m_currTile);
Shinya Kitaoka 120a6e
  if (m_currTile == &m_newTile) m_newTile.setRaster(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool FxResourceBuilder::download(TCacheResourceP &resource) {
Shinya Kitaoka 120a6e
  // In case the output tile was used to calculate the fx, avoid downloading
Shinya Kitaoka 120a6e
  if (m_currTile == m_outTile) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return resource->downloadAll(*m_outTile);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// TRasterFx
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TRasterFx::TRasterFxImp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  bool m_cacheEnabled;
Shinya Kitaoka 120a6e
  TTile m_cachedTile;
Shinya Kitaoka 120a6e
  double m_frame;
Shinya Kitaoka 120a6e
  bool m_isEnabled;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRenderSettings m_info;
Shinya Kitaoka 120a6e
  std::string m_interactiveCacheId;
Shinya Kitaoka 120a6e
  mutable TThread::Mutex m_mutex;  // brutto
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterFxImp() : m_cacheEnabled(false), m_isEnabled(true), m_cachedTile(0) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~TRasterFxImp() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void enableCache(bool on) {
Shinya Kitaoka 120a6e
    QMutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
    m_cacheEnabled = on;
Shinya Kitaoka 120a6e
    if (!m_cacheEnabled) {
Shinya Kitaoka 120a6e
      m_interactiveCacheId = "";
Shinya Kitaoka 120a6e
      m_frame              = 0;
Shinya Kitaoka 120a6e
      m_info               = TRenderSettings();
Shinya Kitaoka 120a6e
      m_cachedTile.setRaster(0);
Shinya Kitaoka 120a6e
      m_cachedTile.m_pos = TPointD();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool isCacheEnabled() const { return m_cacheEnabled; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool isEnabled() const {
Shinya Kitaoka 120a6e
    QMutexLocker sl(&m_mutex);  // a che serve??
Shinya Kitaoka 120a6e
    return m_isEnabled;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void enable(bool on) {
Shinya Kitaoka 120a6e
    QMutexLocker sl(&m_mutex);  // a che serve
Shinya Kitaoka 120a6e
    m_isEnabled = on;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterFx::TRasterFx() : m_rasFxImp(new TRasterFxImp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterFx::~TRasterFx() { delete m_rasFxImp; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine TRasterFx::handledAffine(const TRenderSettings &info, double frame) {
Shinya Kitaoka 120a6e
  return (info.m_affine.a11 == info.m_affine.a22 && info.m_affine.a12 == 0 &&
Shinya Kitaoka 120a6e
          info.m_affine.a21 == 0 && info.m_affine.a13 == 0 &&
Shinya Kitaoka 120a6e
          info.m_affine.a23 == 0)
Shinya Kitaoka 120a6e
             ? info.m_affine
Shinya Kitaoka 120a6e
             : TScale(norm2(info.m_affine));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TRasterFx::getBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                        const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  bool ret = doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
  bBox     = info.m_affine * bBox;
Shinya Kitaoka 120a6e
  enlargeToI(bBox);
Shinya Kitaoka 120a6e
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRasterFx::transform(double frame, int port, const TRectD &rectOnOutput,
Shinya Kitaoka 120a6e
                          const TRenderSettings &infoOnOutput,
Shinya Kitaoka 120a6e
                          TRectD &rectOnInput, TRenderSettings &infoOnInput) {
Shinya Kitaoka 120a6e
  rectOnInput = rectOnOutput;
Shinya Kitaoka 120a6e
  infoOnInput = infoOnOutput;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TRasterFx::memorySize(const TRectD &rect, int bpp) {
Shinya Kitaoka 120a6e
  if (rect.x1 <= rect.x0 || rect.y1 <= rect.y0) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (unsigned long)(rect.getLx() + 1) * (unsigned long)(rect.getLy() + 1) *
Shinya Kitaoka 120a6e
             (bpp >> 3) >>
Shinya Kitaoka 120a6e
         20;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Specifies the approximate size (in MegaBytes) of the maximum allocation
Shinya Kitaoka 120a6e
//! instance that this fx
Toshihiro Shimizu 890ddd
//! will need to perform in order to render the passed input.
Shinya Kitaoka 120a6e
//! This method should be reimplemented in order to make the Toonz rendering
Shinya Kitaoka 120a6e
//! process aware of
Toshihiro Shimizu 890ddd
//! the use of big raster memory chunks, at least.
Shinya Kitaoka 120a6e
//! Observe that the passed tile geometry is implicitly  already allocated
Shinya Kitaoka 120a6e
//! <\i> for the fx output.
Toshihiro Shimizu 890ddd
//! \n
Shinya Kitaoka 120a6e
//! The default implementation returns 0, assuming that the passed implicit
Shinya Kitaoka 120a6e
//! memory size is passed
Shinya Kitaoka 120a6e
//! below in node computation without further allocation of resources. Fxs can
Shinya Kitaoka 120a6e
//! reimplement this
Toshihiro Shimizu 890ddd
//! to -1 to explicitly disable the Toonz's smart memory handling.
Toshihiro Shimizu 890ddd
//! \n \n
Shinya Kitaoka 120a6e
//! \note The rendering process ensures that the passed render settings are \a
Shinya Kitaoka 120a6e
//! handled
Toshihiro Shimizu 890ddd
//! by the fx before this function is invoked - do not waste code for it.
Toshihiro Shimizu 890ddd
//! \sa TRasterFx::memorySize and TRasterFx::canHandle methods.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TRasterFx::getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                    const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TRasterFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                                const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  std::string alias = getFxType();
Shinya Kitaoka 120a6e
  alias += "[";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // alias degli effetti connessi alle porte di input separati da virgole
Shinya Kitaoka 120a6e
  // una porta non connessa da luogo a un alias vuoto (stringa vuota)
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < getInputPortCount(); i++) {
Shinya Kitaoka 120a6e
    TFxPort *port = getInputPort(i);
Shinya Kitaoka 120a6e
    if (port->isConnected()) {
Shinya Kitaoka 120a6e
      TRasterFxP ifx = port->getFx();
Shinya Kitaoka 120a6e
      assert(ifx);
Shinya Kitaoka 120a6e
      alias += ifx->getAlias(frame, info);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    alias += ",";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // alias dei valori dei parametri dell'effetto al frame dato
Shinya Kitaoka 120a6e
  for (i = 0; i < getParams()->getParamCount(); i++) {
Shinya Kitaoka 120a6e
    TParam *param = getParams()->getParam(i);
Shinya Kitaoka 120a6e
    alias += param->getName() + "=" + param->getValueAlias(frame, 3);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  alias += "]";
Shinya Kitaoka 120a6e
  return alias;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRasterFx::dryCompute(TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                           const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (checkActiveTimeRegion() && !getActiveTimeRegion().contains(frame)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!getAttributes()->isEnabled() || !m_rasFxImp->isEnabled()) {
Shinya Kitaoka 120a6e
    if (getInputPortCount() == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TFxPort *port = getInputPort(getPreferredInputPort());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (port->isConnected())
Shinya Kitaoka 120a6e
      TRasterFxP(port->getFx())->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If the input tile has a fractionary position, it is passed to the
Shinya Kitaoka 120a6e
  // rendersettings' accumulated affine.
Shinya Kitaoka 120a6e
  TPoint intTilePos(tfloor(rect.x0), tfloor(rect.y0));
Shinya Kitaoka 120a6e
  TPointD fracTilePos(rect.x0 - intTilePos.x, rect.y0 - intTilePos.y);
Shinya Kitaoka 120a6e
  TPointD fracInfoTranslation(info.m_affine.a13 - fracTilePos.x,
Shinya Kitaoka 120a6e
                              info.m_affine.a23 - fracTilePos.y);
Shinya Kitaoka 120a6e
  TPoint intInfoTranslation(tfloor(fracInfoTranslation.x),
Shinya Kitaoka 120a6e
                            tfloor(fracInfoTranslation.y));
Shinya Kitaoka 120a6e
  TPointD newTilePos(intTilePos.x - intInfoTranslation.x,
Shinya Kitaoka 120a6e
                     intTilePos.y - intInfoTranslation.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (rect.getP00() != newTilePos) {
Shinya Kitaoka 120a6e
    TRenderSettings newInfo(info);
Shinya Kitaoka 120a6e
    newInfo.m_affine.a13 = fracInfoTranslation.x - intInfoTranslation.x;
Shinya Kitaoka 120a6e
    newInfo.m_affine.a23 = fracInfoTranslation.y - intInfoTranslation.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD newRect(newTilePos, rect.getSize());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    dryCompute(newRect, frame, newInfo);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If the fx can't handle the whole affine passed with the TRenderSettings,
Shinya Kitaoka 120a6e
  // the part
Shinya Kitaoka 120a6e
  // of it that the fx can't handle is retained and applied by an affine
Shinya Kitaoka 120a6e
  // transformer fx (TrFx)
Shinya Kitaoka 120a6e
  // after the node has been computed.
Shinya Kitaoka 120a6e
  bool canHandleAffine =
Shinya Kitaoka 120a6e
      canHandle(info, frame) || (handledAffine(info, frame) == info.m_affine);
Shinya Kitaoka 120a6e
  if (!info.m_affine.isIdentity() && !canHandleAffine) {
Shinya Kitaoka 120a6e
    TrFx *transformerFx = new TrFx;
Shinya Kitaoka 120a6e
    TFxP locker(transformerFx);
Shinya Kitaoka 120a6e
    transformerFx->setFx(this);
Shinya Kitaoka 120a6e
    transformerFx->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string alias = getAlias(frame, info) + "[" + ::traduce(info.m_affine) +
Shinya Kitaoka 120a6e
                      "][" + std::to_string(info.m_bpp) + "]";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int renderStatus =
Shinya Kitaoka 120a6e
      TRenderer::instance().getRenderStatus(TRenderer::renderId());
Shinya Kitaoka 120a6e
  TFxCacheManager *cacheManager = TFxCacheManager::instance();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (renderStatus == TRenderer::FIRSTRUN) {
Shinya Kitaoka 120a6e
    TRectD bbox;
Shinya Kitaoka 120a6e
    // ret = getBBox... puo' darsi che l'enlarge del trFx (o naturale del bbox)
Shinya Kitaoka 120a6e
    // faccia
Shinya Kitaoka 120a6e
    // diventare TRectD() non vuoto!!
Shinya Kitaoka 120a6e
    getBBox(frame, bbox, info);
Shinya Kitaoka 120a6e
    enlargeToI(bbox);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD interestingRect(rect * bbox);
Shinya Kitaoka 120a6e
    if (myIsEmpty(interestingRect)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Declare the tile to the tiles manager
Shinya Kitaoka 120a6e
    ResourceBuilder::declareResource(alias, this, interestingRect, frame, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    doDryCompute(interestingRect, frame, info);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TRectD bbox;
Shinya Kitaoka 120a6e
    getBBox(frame, bbox, info);
Shinya Kitaoka 120a6e
    enlargeToI(bbox);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD interestingRect(rect * bbox);
Shinya Kitaoka 120a6e
    if (myIsEmpty(interestingRect)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Invoke the fx-specific simulation process
Shinya Kitaoka 120a6e
    FxResourceBuilder rBuilder(alias, this, info, frame);
Shinya Kitaoka 120a6e
    rBuilder.simBuild(interestingRect);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Declares the computation scheme of this fx for rendering optimization
Shinya Kitaoka 120a6e
//! purposes.
Shinya Kitaoka 120a6e
//! This is an important function of the Toonz rendering API, and should be
Shinya Kitaoka 120a6e
//! reimplemented
Toshihiro Shimizu 890ddd
//! with the necessary care.
Toshihiro Shimizu 890ddd
//! The Toonz rendering process makes use of this function to enact most of the
Toshihiro Shimizu 890ddd
//! optimization steps about the fx computation, in particular fx caching.
Toshihiro Shimizu 890ddd
//! A correct implementation of this method should follow these rules:
Shinya Kitaoka 120a6e
//! 
  • The invocation of child node computations should be faithfully
  • Shinya Kitaoka 120a6e
    //! reproduced.
    Toshihiro Shimizu 890ddd
    //! 
  • TRasterFx::compute and TRasterFx::allocateAndCompute calls have to be
  • Toshihiro Shimizu 890ddd
    //!      translated to TRasterFx::dryCompute calls.
    Shinya Kitaoka 120a6e
    //! 
  • This fx is intended for precomputation stage, so the hard rendering
  • Shinya Kitaoka 120a6e
    //! code
    Toshihiro Shimizu 890ddd
    //!      should be skipped here.
    Shinya Kitaoka 120a6e
    //! By default, this method raises a dryCompute call to each input port in
    Shinya Kitaoka 120a6e
    //! increasing
    Shinya Kitaoka 120a6e
    //! order, using the TRasterFx::transform method to identify the tiles to be
    Shinya Kitaoka 120a6e
    //! passed
    Toshihiro Shimizu 890ddd
    //! on input precomputation.
    Shinya Kitaoka 120a6e
    void TRasterFx::doDryCompute(TRectD &rect, double frame,
    Shinya Kitaoka 120a6e
                                 const TRenderSettings &info) {
    Shinya Kitaoka 120a6e
      int inputPortCount = getInputPortCount();
    Shinya Kitaoka 120a6e
      for (int i = 0; i < inputPortCount; ++i) {
    Shinya Kitaoka 120a6e
        TFxPort *port = getInputPort(i);
    Shinya Kitaoka 120a6e
        if (port->isConnected()) {
    Shinya Kitaoka 120a6e
          TRectD rectOnInput;
    Shinya Kitaoka 120a6e
          TRenderSettings infoOnInput;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
          TRasterFxP fx = port->getFx();
    Shinya Kitaoka 120a6e
          transform(frame, i, rect, info, rectOnInput, infoOnInput);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
          if (!myIsEmpty(rectOnInput))
    Shinya Kitaoka 120a6e
            fx->dryCompute(rectOnInput, frame, infoOnInput);
    Shinya Kitaoka 120a6e
        }
    Shinya Kitaoka 120a6e
      }
    Toshihiro Shimizu 890ddd
    }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //--------------------------------------------------
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //! This is an overloaded member function that deals with
    Toshihiro Shimizu 890ddd
    //! the allocation of an input tile before invoking the TRasterFx::compute
    Toshihiro Shimizu 890ddd
    //! method on it.
    Shinya Kitaoka 120a6e
    void TRasterFx::allocateAndCompute(TTile &tile, const TPointD &pos,
    Shinya Kitaoka 120a6e
                                       const TDimension &size, TRasterP templateRas,
    Shinya Kitaoka 120a6e
                                       double frame, const TRenderSettings &info) {
    Shinya Kitaoka 120a6e
      if (templateRas) {
    Shinya Kitaoka 120a6e
        TRaster32P ras32(templateRas);
    Shinya Kitaoka 120a6e
        TRaster64P ras64(templateRas);
    Shinya Kitaoka 120a6e
        templateRas = 0;  // Release the reference to templateRas before allocation
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        TRasterP tileRas;
    Shinya Kitaoka 120a6e
        if (ras32)
    Shinya Kitaoka 120a6e
          tileRas = TRaster32P(size.lx, size.ly);
    Shinya Kitaoka 120a6e
        else if (ras64)
    Shinya Kitaoka 120a6e
          tileRas = TRaster64P(size.lx, size.ly);
    Shinya Kitaoka 120a6e
        else {
    Shinya Kitaoka 120a6e
          assert(false);
    Shinya Kitaoka 120a6e
          return;
    Shinya Kitaoka 120a6e
        }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        tile.setRaster(tileRas);
    Shinya Kitaoka 120a6e
      } else {
    Shinya Kitaoka 120a6e
        if (info.m_bpp == 32) {
    Shinya Kitaoka 120a6e
          TRaster32P tileRas(size.lx, size.ly);
    Shinya Kitaoka 120a6e
          tile.setRaster(tileRas);
    Shinya Kitaoka 120a6e
        } else if (info.m_bpp == 64) {
    Shinya Kitaoka 120a6e
          TRaster64P tileRas(size.lx, size.ly);
    Shinya Kitaoka 120a6e
          tile.setRaster(tileRas);
    Shinya Kitaoka 120a6e
        } else
    Shinya Kitaoka 120a6e
          assert(false);
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      tile.m_pos = pos;
    Shinya Kitaoka 120a6e
      compute(tile, frame, info);
    Toshihiro Shimizu 890ddd
    }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //-----------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //! This method supplies the actual fx rendering code.
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    void TRasterFx::compute(TTile &tile, double frame,
    Shinya Kitaoka 120a6e
                            const TRenderSettings &info) {
    Shinya Kitaoka 120a6e
      // If the render was aborted, avoid everything
    Shinya Kitaoka 120a6e
      // if(TRenderer::instance().isAborted(TRenderer::renderId()))
    Shinya Kitaoka 120a6e
      //  throw TException("Render canceled");
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      if (checkActiveTimeRegion() && !getActiveTimeRegion().contains(frame)) return;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      if (!getAttributes()->isEnabled() || !m_rasFxImp->isEnabled()) {
    Shinya Kitaoka 120a6e
        if (getInputPortCount() == 0) return;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        TFxPort *port = getInputPort(0);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        // la porta 0 non deve essere una porta di controllo
    Shinya Kitaoka 120a6e
        assert(port->isaControlPort() == false);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        if (port->isConnected()) {
    Shinya Kitaoka 120a6e
          TRasterFxP(port->getFx())->compute(tile, frame, info);
    Shinya Kitaoka 120a6e
          return;
    Shinya Kitaoka 120a6e
        }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        return;
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // If the input tile has a fractionary position, it is passed to the
    Shinya Kitaoka 120a6e
      // rendersettings' accumulated affine. At the same time, the integer part of
    Shinya Kitaoka 120a6e
      // such affine is transferred to the tile.
    Shinya Kitaoka 120a6e
      TPoint intTilePos(tfloor(tile.m_pos.x), tfloor(tile.m_pos.y));
    Shinya Kitaoka 120a6e
      TPointD fracTilePos(tile.m_pos.x - intTilePos.x, tile.m_pos.y - intTilePos.y);
    Shinya Kitaoka 120a6e
      TPointD fracInfoTranslation(info.m_affine.a13 - fracTilePos.x,
    Shinya Kitaoka 120a6e
                                  info.m_affine.a23 - fracTilePos.y);
    Shinya Kitaoka 120a6e
      TPoint intInfoTranslation(tfloor(fracInfoTranslation.x),
    Shinya Kitaoka 120a6e
                                tfloor(fracInfoTranslation.y));
    Shinya Kitaoka 120a6e
      TPointD newTilePos(intTilePos.x - intInfoTranslation.x,
    Shinya Kitaoka 120a6e
                         intTilePos.y - intInfoTranslation.y);
    Shinya Kitaoka 120a6e
      /*-- 入力タイルの位置が、小数値を持っていた場合 --*/
    Shinya Kitaoka 120a6e
      if (tile.m_pos != newTilePos) {
    Shinya Kitaoka 120a6e
        /*-- RenderSettingsのaffine行列に位置ずれを足しこむ --*/
    Shinya Kitaoka 120a6e
        TRenderSettings newInfo(info);
    Shinya Kitaoka 120a6e
        newInfo.m_affine.a13 = fracInfoTranslation.x - intInfoTranslation.x;
    Shinya Kitaoka 120a6e
        newInfo.m_affine.a23 = fracInfoTranslation.y - intInfoTranslation.y;
    Shinya Kitaoka 120a6e
        /*-- タイルの位置は整数値にする --*/
    Shinya Kitaoka 120a6e
        TPointD oldPos(tile.m_pos);
    Shinya Kitaoka 120a6e
        tile.m_pos = newTilePos;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        compute(tile, frame, newInfo);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        tile.m_pos = oldPos;
    Shinya Kitaoka 120a6e
        return;
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      bool canHandleAffine =
    Shinya Kitaoka 120a6e
          canHandle(info, frame) || (handledAffine(info, frame) == info.m_affine);
    Shinya Kitaoka 120a6e
      if (!info.m_affine.isIdentity() && !canHandleAffine) {
    Shinya Kitaoka 120a6e
        TrFx *transformerFx = new TrFx;
    Shinya Kitaoka 120a6e
        TFxP locker(transformerFx);
    Shinya Kitaoka 120a6e
        transformerFx->setFx(this);
    Shinya Kitaoka 120a6e
        transformerFx->compute(tile, frame, info);
    Shinya Kitaoka 120a6e
        return;
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // Retrieve tile's geometry
    Shinya Kitaoka 120a6e
      TRectD tilePlacement = myConvert(tile.getRaster()->getBounds()) + tile.m_pos;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // Build the fx result alias (in other words, its name)
    Shinya Kitaoka 120a6e
      std::string alias = getAlias(frame, info) + "[" + ::traduce(info.m_affine) +
    Shinya Kitaoka 120a6e
                          "][" + std::to_string(info.m_bpp) +
    Shinya Kitaoka 120a6e
                          "]";  // To be moved below
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRectD bbox;
    Shinya Kitaoka 120a6e
      getBBox(frame, bbox, info);
    Shinya Kitaoka 120a6e
      enlargeToI(bbox);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRectD interestingRect(tilePlacement * bbox);
    Shinya Kitaoka 120a6e
      if (myIsEmpty(interestingRect)) return;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // Extract the interesting tile from requested one
    Shinya Kitaoka 120a6e
      TTile interestingTile;
    Shinya Kitaoka 120a6e
      interestingTile.m_pos = interestingRect.getP00();
    Shinya Kitaoka 120a6e
      TRect interestingRectI(myConvert(interestingRect - tilePlacement.getP00()));
    Shinya Kitaoka 120a6e
      interestingTile.setRaster(tile.getRaster()->extract(interestingRectI));
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    #ifdef DIAGNOSTICS
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      // 1. Push fx name on call stack
    Shinya Kitaoka 120a6e
      QString fxName = QString::fromStdString(getDeclaration()->getId());
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_PUSH("FName", fxName);
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_THRSET("FComputeTime", 0);
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      TStopWatch sw;
    Shinya Kitaoka 120a6e
      sw.start();
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    #endif
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      // Invoke the fx-specific computation process
    Shinya Kitaoka 120a6e
      FxResourceBuilder rBuilder(alias, this, info, frame);
    Shinya Kitaoka 120a6e
      rBuilder.build(interestingTile);
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    #ifdef DIAGNOSTICS
    Shinya Kitaoka 120a6e
      sw.stop();
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      QString countsStr("#ftimes.txt | 4. " + fxName + " | 4. Calls count");
    Shinya Kitaoka 120a6e
      QString fxStr("fcum_4. " + fxName);
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      long computeTime      = DIAGNOSTICS_THRGET("FComputeTime");
    Shinya Kitaoka 120a6e
      long fxTime           = sw.getTotalTime();
    Shinya Kitaoka 120a6e
      long fxCumulativeTime = DIAGNOSTICS_GLOGET(fxStr);
    Shinya Kitaoka 120a6e
      long count            = DIAGNOSTICS_GET(countsStr);
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      // 2. Add this time to fx time, and subtract it from parent time
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_GLOADD(fxStr, computeTime);
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_ADD(countsStr, 1);
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_SET("#ftimes.txt | 4. " + fxName + " | 3. Mean time",
    Shinya Kitaoka 120a6e
                      (fxCumulativeTime + computeTime) / (count + 1));
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_POP("FName", 1);
    Shinya Kitaoka 120a6e
      QString parentFxName = DIAGNOSTICS_STACKGET("FName");
    Shinya Kitaoka 120a6e
      if (!parentFxName.isEmpty())
    Shinya Kitaoka 120a6e
        DIAGNOSTICS_GLOADD("fcum_4. " + parentFxName, -fxTime);
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      DIAGNOSTICS_GLOADD("fcum_03. Cached Fxs Retrieval", fxTime - computeTime);
    Toshihiro Shimizu 890ddd
    #endif
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    #ifdef WRITEIMAGES
    Shinya Kitaoka 120a6e
      static int iCount = 0;
    Shinya Kitaoka 120a6e
      QString qPath("C:\\butta\\image_" +
    Shinya Kitaoka 120a6e
                    QString::number(++iCount).rightJustified(3, '0') + ".tif");
    Shinya Kitaoka 120a6e
      TImageWriter::save(TFilePath(qPath.toStdWString()), tile.getRaster());
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      if (iCount >= 35) int aa = 1;
    Toshihiro Shimizu 890ddd
    #endif
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
      /*
    Shinya Kitaoka 120a6e
    return;
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    tryCanceled:
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    //if(TRenderer::instance().isAborted(TRenderer::renderId()))
    Shinya Kitaoka 120a6e
    //  throw TException("Render canceled");
    Shinya Kitaoka 120a6e
    ;
    Toshihiro Shimizu 890ddd
    */
    Toshihiro Shimizu 890ddd
    }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //------------------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    TRasterP TRasterFx::applyAffine(TTile &tileOut, const TTile &tileIn,
    Shinya Kitaoka 120a6e
                                    const TRenderSettings &info) {
    Shinya Kitaoka 120a6e
      TAffine aff = info.m_affine;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRasterP src_ras = tileIn.getRaster();
    Shinya Kitaoka 120a6e
      TRasterP dst_ras = tileOut.getRaster();
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      if (aff.isTranslation()) {
    Shinya Kitaoka 120a6e
        // Check the tile origins' fractionary displacement
    Shinya Kitaoka 120a6e
        TPointD diff(tileOut.m_pos - tileIn.m_pos - TPointD(aff.a13, aff.a23));
    Shinya Kitaoka 120a6e
        double fracX = diff.x - tfloor(diff.x);
    Shinya Kitaoka 120a6e
        double fracY = diff.y - tfloor(diff.y);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        if ((fracX < 0.01 || fracX > 0.99) && (fracY < 0.01 || fracY > 0.99)) {
    Shinya Kitaoka 120a6e
          // Just copy part of tileIn into tileOut
    Shinya Kitaoka 120a6e
          TRect geomIn(src_ras->getBounds());
    Shinya Kitaoka 120a6e
          TRect geomOut(dst_ras->getBounds());
    Shinya Kitaoka 120a6e
          TPoint diffI(convert(diff));
    Shinya Kitaoka 120a6e
          geomIn -= diffI;
    Shinya Kitaoka 120a6e
          geomOut += diffI;
    Shinya Kitaoka 120a6e
          geomIn *= dst_ras->getBounds();
    Shinya Kitaoka 120a6e
          geomOut *= src_ras->getBounds();
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
          if (geomIn.isEmpty()) return dst_ras;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
          TRasterP rasIn(src_ras->extract(geomOut));
    Shinya Kitaoka 120a6e
          TRasterP rasOut(dst_ras->extract(geomIn));
    Shinya Kitaoka 120a6e
          TRop::copy(rasOut, rasIn);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
          return dst_ras;
    Shinya Kitaoka 120a6e
        }
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRectD rectIn  = myConvert(src_ras->getBounds()) + tileIn.m_pos;
    Shinya Kitaoka 120a6e
      TRectD rectOut = myConvert(dst_ras->getBounds()) + tileOut.m_pos;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRectD rectInAfter = aff * myConvert(src_ras->getBounds());
    Shinya Kitaoka 120a6e
      TAffine rasterAff  = TTranslation((aff * rectIn).getP00() - rectOut.getP00() -
    Shinya Kitaoka 120a6e
                                       rectInAfter.getP00()) *
    Shinya Kitaoka 120a6e
                          aff;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRop::ResampleFilterType qual;
    Shinya Kitaoka 120a6e
      switch (info.m_quality) {
    Shinya Kitaoka 120a6e
      case TRenderSettings::StandardResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Triangle;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::ImprovedResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Hann2;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::HighResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Hamming3;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Triangle_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Triangle;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Mitchell_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Mitchell;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Cubic5_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Cubic5;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Cubic75_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Cubic75;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Cubic1_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Cubic1;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Hann2_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Hann2;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Hann3_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Hann3;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Hamming2_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Hamming2;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Hamming3_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Hamming3;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Lanczos2_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Lanczos2;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Lanczos3_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Lanczos3;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Gauss_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Gauss;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::ClosestPixel_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::ClosestPixel;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      case TRenderSettings::Bilinear_FilterResampleQuality:
    Shinya Kitaoka 120a6e
        qual = TRop::Bilinear;
    Shinya Kitaoka 120a6e
        break;
    Shinya Kitaoka 120a6e
      default:
    Shinya Kitaoka 120a6e
        assert(false);
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      TRop::resample(dst_ras, src_ras, rasterAff, qual);
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      return dst_ras;
    Toshihiro Shimizu 890ddd
    }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //--------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    bool TRasterFx::isCacheEnabled() const { return m_rasFxImp->m_cacheEnabled; }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //--------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    void TRasterFx::enableCache(bool on) { m_rasFxImp->enableCache(on); }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //==============================================================================
    Toshihiro Shimizu 890ddd
    //
    Toshihiro Shimizu 890ddd
    // TRenderSettings
    Toshihiro Shimizu 890ddd
    //
    Toshihiro Shimizu 890ddd
    //------------------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    TRenderSettings::TRenderSettings()
    Shinya Kitaoka 120a6e
        : m_gamma(1)
    Shinya Kitaoka 120a6e
        , m_timeStretchFrom(25)
    Shinya Kitaoka 120a6e
        , m_timeStretchTo(25)
    Shinya Kitaoka 120a6e
        , m_stereoscopicShift(0.05)
    Shinya Kitaoka 120a6e
        , m_bpp(32)
    Shinya Kitaoka 120a6e
        , m_maxTileSize((std::numeric_limits<int>::max)())</int>
    Shinya Kitaoka 120a6e
        , m_shrinkX(1)
    Shinya Kitaoka 120a6e
        , m_shrinkY(1)
    Shinya Kitaoka 120a6e
        , m_quality(StandardResampleQuality)
    Shinya Kitaoka 120a6e
        , m_fieldPrevalence(NoField)
    Shinya Kitaoka 120a6e
        , m_stereoscopic(false)
    Shinya Kitaoka 120a6e
        , m_isSwatch(false)
    Shinya Kitaoka 120a6e
        , m_applyShrinkToViewer(false)
    Shinya Kitaoka 120a6e
        , m_userCachable(true)
    Shinya Kitaoka 120a6e
        , m_isCanceled(NULL) {}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //------------------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    TRenderSettings::~TRenderSettings() {}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //------------------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    std::string TRenderSettings::toString() const {
    Shinya Kitaoka 120a6e
      std::string ss =
    Shinya Kitaoka 120a6e
          std::to_string(m_bpp) + ";" + std::to_string(m_quality) + ";" +
    Shinya Kitaoka 120a6e
          std::to_string(m_gamma) + ";" + std::to_string(m_timeStretchFrom) + ";" +
    Shinya Kitaoka 120a6e
          std::to_string(m_timeStretchTo) + ";" +
    Shinya Kitaoka 120a6e
          std::to_string(m_fieldPrevalence) + ";" + std::to_string(m_shrinkX) +
    Shinya Kitaoka 120a6e
          "," + std::to_string(m_shrinkY) + ";" + std::to_string(m_affine.a11) +
    Shinya Kitaoka 120a6e
          "," + std::to_string(m_affine.a12) + "," + std::to_string(m_affine.a13) +
    Shinya Kitaoka 120a6e
          "," + std::to_string(m_affine.a21) + "," + std::to_string(m_affine.a22) +
    Shinya Kitaoka 120a6e
          "," + std::to_string(m_affine.a23) + ";" + std::to_string(m_maxTileSize) +
    Shinya Kitaoka 120a6e
          ";" + std::to_string(m_isSwatch) + ";" + std::to_string(m_userCachable) +
    Shinya Kitaoka 120a6e
          ";{";
    Shinya Kitaoka 120a6e
      if (!m_data.empty()) {
    Shinya Kitaoka 120a6e
        ss += m_data[0]->toString();
    Shinya Kitaoka 120a6e
        for (int i = 1; i < (int)m_data.size(); i++)
    Shinya Kitaoka 120a6e
          ss += "," + m_data[i]->toString();
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
      ss += "}";
    Shinya Kitaoka 120a6e
      return ss;
    Toshihiro Shimizu 890ddd
    }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //------------------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    bool TRenderSettings::operator==(const TRenderSettings &rhs) const {
    Shinya Kitaoka 120a6e
      if (m_bpp != rhs.m_bpp || m_quality != rhs.m_quality ||
    Shinya Kitaoka 120a6e
          m_fieldPrevalence != rhs.m_fieldPrevalence ||
    Shinya Kitaoka 120a6e
          m_stereoscopic != rhs.m_stereoscopic ||
    Shinya Kitaoka 120a6e
          m_stereoscopicShift != rhs.m_stereoscopicShift ||
    Shinya Kitaoka 120a6e
          m_gamma != rhs.m_gamma || m_timeStretchFrom != rhs.m_timeStretchFrom ||
    Shinya Kitaoka 120a6e
          m_timeStretchTo != rhs.m_timeStretchTo || m_shrinkX != rhs.m_shrinkX ||
    Shinya Kitaoka 120a6e
          m_shrinkY != rhs.m_shrinkY ||
    Shinya Kitaoka 120a6e
          m_applyShrinkToViewer != rhs.m_applyShrinkToViewer ||
    Shinya Kitaoka 120a6e
          m_maxTileSize != rhs.m_maxTileSize || m_affine != rhs.m_affine ||
    Shinya Kitaoka 120a6e
          m_mark != rhs.m_mark || m_isSwatch != rhs.m_isSwatch ||
    Shinya Kitaoka 120a6e
          m_userCachable != rhs.m_userCachable)
    Shinya Kitaoka 120a6e
        return false;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      return std::equal(m_data.begin(), m_data.end(), rhs.m_data.begin(), areEqual);
    Toshihiro Shimizu 890ddd
    }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    //------------------------------------------------------------------------------
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    bool TRenderSettings::operator!=(const TRenderSettings &rhs) const {
    Shinya Kitaoka 120a6e
      return !operator==(rhs);
    Toshihiro Shimizu 890ddd
    }