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