Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonzqt/swatchviewer.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/gutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qpainter></qpainter>
Toshihiro Shimizu 890ddd
#include <qmouseevent></qmouseevent>
Toshihiro Shimizu 890ddd
#include <qresizeevent></qresizeevent>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "tparamcontainer.h"
Toshihiro Shimizu 890ddd
#include "tfxutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Rendering cache management includes
Toshihiro Shimizu 890ddd
#include "tfxcachemanager.h"
Toshihiro Shimizu 890ddd
#include "tcacheresourcepool.h"
Toshihiro Shimizu 890ddd
#include "tpassivecachemanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qeventloop></qeventloop>
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace TFxUtil;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define USE_SQLITE_HDPOOL
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*************************************************************************************
Toshihiro Shimizu 890ddd
//    Swatch cache delegate
Toshihiro Shimizu 890ddd
//*************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
The swatch cache delegate is used to temporary store intermediate rendering results
Toshihiro Shimizu 890ddd
in cache when an fx is being edited.
Toshihiro Shimizu 890ddd
Input fxs of an edited fx are typically requested to produce the same results multiple times
Toshihiro Shimizu 890ddd
as parameters of their schematic parent change - so, caching these results is a remunerative
Toshihiro Shimizu 890ddd
practice as long as the fx is open for edit.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
This delegate stores resources on two different levels: one is directly related to swatch rendering,
Toshihiro Shimizu 890ddd
while the other is used to cache results on the other rendering contexts.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
In the swatch case, we store the above mentioned input results associated with the current scene
Toshihiro Shimizu 890ddd
scale, releasing them when the scene scale changes; plus, the resource associated with the current
Toshihiro Shimizu 890ddd
output is also stored.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
In other rendering contexts, the scene scale can be assumed constant - so the above distinction
Toshihiro Shimizu 890ddd
is unnecessary. All results from the input fxs are stored until the edited fx is unset from the swatch.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Please observe that variations in the scene context - such as frame change, schematic changes, scene changes
Toshihiro Shimizu 890ddd
and so on - actually cause the fx to be re-set for edit in the swatch. Once this happens, the previously
Toshihiro Shimizu 890ddd
stored results are conveniently flushed from the cache.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*NOTE: This can be extended in case we realize multiple swatch viewers... It should be sufficient to map
Toshihiro Shimizu 890ddd
a swatch pointer to its associated cache data - the advantage being that cache resources are shared at the
Toshihiro Shimizu 890ddd
same scene zoom.*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SwatchCacheManager : public TFxCacheManagerDelegate
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	T_RENDER_RESOURCE_MANAGER
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned long m_setFxId;
Toshihiro Shimizu 890ddd
	std::set<unsigned long=""> m_childrenFxIds;</unsigned>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<tcacheresourcep> m_genericCacheContainer;</tcacheresourcep>
Toshihiro Shimizu 890ddd
	std::set<tcacheresourcep> m_swatchCacheContainer;</tcacheresourcep>
Toshihiro Shimizu 890ddd
	TCacheResourceP m_currEditedFxResult;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutex m_mutex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	SwatchCacheManager() {}
Toshihiro Shimizu 890ddd
	~SwatchCacheManager() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static SwatchCacheManager *instance();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setFx(const TFxP &actualFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void clearSwatchResults();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getResource(
Shinya Kitaoka 3bfa54
		TCacheResourceP &resource, const std::string &alias,
Toshihiro Shimizu 890ddd
		const TFxP &fx, double frame, const TRenderSettings &rs,
Toshihiro Shimizu 890ddd
		ResourceDeclaration *resData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//void onRenderInstanceStart(unsigned long renderId);
Toshihiro Shimizu 890ddd
	//void onRenderInstanceEnd(unsigned long renderId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool renderHasOwnership() { return false; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
//    Manager generator
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SwatchCacheManagerGenerator : public TRenderResourceManagerGenerator
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRenderResourceManager *operator()(void)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//return new TPassiveCacheManager;
Toshihiro Shimizu 890ddd
		return SwatchCacheManager::instance();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MANAGER_FILESCOPE_DECLARATION_DEP(
Toshihiro Shimizu 890ddd
	SwatchCacheManager,
Toshihiro Shimizu 890ddd
	SwatchCacheManagerGenerator,
Toshihiro Shimizu 890ddd
	TFxCacheManager::deps())
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Abilita o disabilita la cache nell'effetto \b fx di \b frame in funzione di \b on
Toshihiro Shimizu 890ddd
void setFxForCaching(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SwatchCacheManager::instance()->setFx(fx);
Toshihiro Shimizu 890ddd
	TPassiveCacheManager::instance()->releaseContextNamesWithPrefix("S");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Se name finisce con suffix ritorna la parte iniziale, altrimenti ""
Shinya Kitaoka 3bfa54
std::string matchSuffix(std::string name, std::string suffix)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (name.length() <= suffix.length())
Toshihiro Shimizu 890ddd
		return "";
Toshihiro Shimizu 890ddd
	int i = name.length() - suffix.length();
Toshihiro Shimizu 890ddd
	if (name.substr(i) == suffix)
Toshihiro Shimizu 890ddd
		return name.substr(0, i);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return "";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRaster32P createCrossIcon()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRaster32P crossIcon = TRaster32P(7, 7);
Toshihiro Shimizu 890ddd
	//m_crossIcon e' utilizzata per evidenziare gli eventuali \b Point memorizzati in \b m_points.
Toshihiro Shimizu 890ddd
	crossIcon->fill(TPixel32(0, 0, 0, 0));
Toshihiro Shimizu 890ddd
	TPixel32 *c = crossIcon->pixels(3) + 3;
Toshihiro Shimizu 890ddd
	for (int i = 1; i <= 3; i++)
Toshihiro Shimizu 890ddd
		c[i] = c[-i] = c[7 * i] = c[-7 * i] =
Toshihiro Shimizu 890ddd
			(i & 1) == 0 ? TPixel32::White : TPixel32::Red;
Toshihiro Shimizu 890ddd
	return crossIcon;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//!Disegna una freccia lunga \b len pixel.
Toshihiro Shimizu 890ddd
/*!La punta della freccia si trova a coordinate (0,ly/2), la coda a (len-1,ly/2).
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TRaster32P createArrowShape(int len)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int d = 5;
Toshihiro Shimizu 890ddd
	if (len < d)
Toshihiro Shimizu 890ddd
		len = d;
Toshihiro Shimizu 890ddd
	TPixel32 c0(210, 210, 210);
Toshihiro Shimizu 890ddd
	TPixel32 c1(10, 10, 10);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P ras(len, d * 2 + 1);
Toshihiro Shimizu 890ddd
	ras->clear();
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	TPixel32 *pix = ras->pixels(d);
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	for (x = 0; x < len; x++)
Toshihiro Shimizu 890ddd
		pix[x] = (x & 8) == 0 ? c0 : c1;
Toshihiro Shimizu 890ddd
	for (x = 1; x < d; x++)
Toshihiro Shimizu 890ddd
		for (int y = -x; y < x; y++) {
Toshihiro Shimizu 890ddd
			assert(ras->getBounds().contains(TPoint(x, y + d)));
Toshihiro Shimizu 890ddd
			pix[len * y + x] = c0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
	return ras;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// Preso da sceneViewer.cpp quando si spostera' lo SceneViewer in toonzqt mettere
Toshihiro Shimizu 890ddd
// il codice in comune!
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define ZOOMLEVELS 30
Toshihiro Shimizu 890ddd
#define NOZOOMINDEX 20
Toshihiro Shimizu 890ddd
double ZoomFactors[ZOOMLEVELS] = {0.001, 0.002, 0.003, 0.004, 0.005, 0.007,
Toshihiro Shimizu 890ddd
								  0.01, 0.015, 0.02, 0.03, 0.04, 0.05,
Toshihiro Shimizu 890ddd
								  0.0625, 0.0833, 0.125, 0.167, 0.25, 0.333,
Toshihiro Shimizu 890ddd
								  0.5, 0.667, 1, 2, 3, 4,
Toshihiro Shimizu 890ddd
								  5, 6, 7, 8, 12, 16};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double getQuantizedZoomFactor(double zf, bool forward)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (forward && zf > ZoomFactors[ZOOMLEVELS - 1] ||
Toshihiro Shimizu 890ddd
		areAlmostEqual(zf, ZoomFactors[ZOOMLEVELS - 1], 1e-5))
Toshihiro Shimizu 890ddd
		return zf;
Toshihiro Shimizu 890ddd
	else if (!forward && zf < ZoomFactors[0] ||
Toshihiro Shimizu 890ddd
			 areAlmostEqual(zf, ZoomFactors[0], 1e-5))
Toshihiro Shimizu 890ddd
		return zf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert((!forward && zf > ZoomFactors[0]) || (forward && zf < ZoomFactors[ZOOMLEVELS - 1]));
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	for (i = 0; i <= ZOOMLEVELS - 1; i++)
Toshihiro Shimizu 890ddd
		if (areAlmostEqual(zf, ZoomFactors[i], 1e-5))
Toshihiro Shimizu 890ddd
			zf = ZoomFactors[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (forward && zf < ZoomFactors[0])
Toshihiro Shimizu 890ddd
		return ZoomFactors[0];
Toshihiro Shimizu 890ddd
	else if (!forward && zf > ZoomFactors[ZOOMLEVELS - 1])
Toshihiro Shimizu 890ddd
		return ZoomFactors[ZOOMLEVELS - 1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < ZOOMLEVELS - 1; i++)
Toshihiro Shimizu 890ddd
		if (ZoomFactors[i + 1] - zf >= 0 && zf - ZoomFactors[i] >= 0) {
Toshihiro Shimizu 890ddd
			if (forward && ZoomFactors[i + 1] == zf)
Toshihiro Shimizu 890ddd
				return ZoomFactors[i + 2];
Toshihiro Shimizu 890ddd
			else if (!forward && ZoomFactors[i] == zf)
Toshihiro Shimizu 890ddd
				return ZoomFactors[i - 1];
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				return forward ? ZoomFactors[i + 1] : ZoomFactors[i];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	return ZoomFactors[NOZOOMINDEX];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool suspendedRendering = false; //Global vars for swatch rendering suspension
Toshihiro Shimizu 890ddd
QEventLoop *waitingLoop = 0;
Toshihiro Shimizu 890ddd
int submittedTasks = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// SwatchViewer
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if QT_VERSION >= 0x050500
Toshihiro Shimizu 890ddd
SwatchViewer::SwatchViewer(QWidget *parent, Qt::WindowFlags flags)
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
SwatchViewer::SwatchViewer(QWidget *parent, Qt::WFlags flags)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	: QWidget(parent, flags), m_fx(0), m_actualFxClone(0), m_mouseButton(Qt::NoButton), m_selectedPoint(0), m_pointPosDelta(TPointD()), m_enabled(false), m_content(), m_aff(TAffine()), m_fxAff(TAffine()), m_cameraRect(), m_bgPainter(0), m_pos(TPoint()), m_firstPos(TPoint()), m_oldContent(), m_curContent(), m_executor()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//setMinimumSize(150,150);
Toshihiro Shimizu 890ddd
	setMinimumHeight(150);
Toshihiro Shimizu 890ddd
	setFixedWidth(150);
Toshihiro Shimizu 890ddd
	setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_raster = TRaster32P(width(), height());
Toshihiro Shimizu 890ddd
	m_crossIcon = createCrossIcon();
Toshihiro Shimizu 890ddd
	setFocusPolicy(Qt::StrongFocus);
Toshihiro Shimizu 890ddd
	m_executor.setDedicatedThreads(true);
Toshihiro Shimizu 890ddd
	m_executor.setMaxActiveTasks(1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_renderer.enablePrecomputing(false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SwatchViewer::~SwatchViewer()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!This static method is used to temporarily suspend all swatch-related render
Toshihiro Shimizu 890ddd
//!processing, typically because the rendering scene is being deleted.
Toshihiro Shimizu 890ddd
//!When a suspension is invoked, all further rendering requests made to
Toshihiro Shimizu 890ddd
//!swatch viewers are silently rejected, while currently active or scheduled ones
Toshihiro Shimizu 890ddd
//!are canceled and waited for completion.
Toshihiro Shimizu 890ddd
void SwatchViewer::suspendRendering(bool suspend, bool blocking)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	suspendedRendering = suspend;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (suspend && submittedTasks > 0 && blocking) {
Toshihiro Shimizu 890ddd
		QEventLoop loop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		waitingLoop = &loop;
Toshihiro Shimizu 890ddd
		loop.exec();
Toshihiro Shimizu 890ddd
		waitingLoop = 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::setCameraSize(const TDimension &cameraSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRect cameraRect(cameraSize);
Toshihiro Shimizu 890ddd
	if (cameraRect != m_cameraRect) {
Toshihiro Shimizu 890ddd
		m_cameraRect = cameraRect;
Toshihiro Shimizu 890ddd
		updateSize(size()); //Invoke a size update to adapt the widget to the new camera ratio
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::setFx(const TFxP &fx, const TFxP &actualFx, int frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_fx = m_actualFxClone = fx;
Toshihiro Shimizu 890ddd
	m_frame = frame;
Toshihiro Shimizu 890ddd
	m_points.clear();
Toshihiro Shimizu 890ddd
	m_pointPairs.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!fx) {
Toshihiro Shimizu 890ddd
		::setFxForCaching(0);
Toshihiro Shimizu 890ddd
		computeContent();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// abilita la cache nel nuovo effetto corrente
Toshihiro Shimizu 890ddd
	::setFxForCaching(actualFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (NaAffineFx *affFx = dynamic_cast<naaffinefx *="">(m_fx.getPointer()))</naaffinefx>
Toshihiro Shimizu 890ddd
		m_fxAff = affFx->getPlacement(m_frame);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_fxAff = TAffine();
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < actualFx->getParams()->getParamCount(); i++) {
Toshihiro Shimizu 890ddd
		TPointParam *pointParam =
Toshihiro Shimizu 890ddd
			dynamic_cast<tpointparam *="">(actualFx->getParams()->getParam(i));</tpointparam>
Toshihiro Shimizu 890ddd
		if (pointParam)
Toshihiro Shimizu 890ddd
			m_points.push_back(Point(i, pointParam));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	// cerco i segmenti
Toshihiro Shimizu 890ddd
	int n = m_points.size();
Toshihiro Shimizu 890ddd
	for (i = 0; i < n; i++) {
Shinya Kitaoka 3bfa54
		std::string name = m_points[i].m_param->getName();
Shinya Kitaoka 3bfa54
		std::string prefix = matchSuffix(name, "_a");
Toshihiro Shimizu 890ddd
		if (prefix == "")
Toshihiro Shimizu 890ddd
			continue;
Shinya Kitaoka 3bfa54
		std::string otherName = prefix + "_b";
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = 0; j < n; j++)
Toshihiro Shimizu 890ddd
			if (i != j && m_points[j].m_param->getName() == otherName)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		if (j < n) {
Toshihiro Shimizu 890ddd
			m_pointPairs.push_back(std::make_pair(i, j));
Toshihiro Shimizu 890ddd
			m_points[i].m_pairFlag = m_points[j].m_pairFlag = true;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	computeContent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::updateFrame(int frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_frame = frame;
Toshihiro Shimizu 890ddd
	computeContent();
Toshihiro Shimizu 890ddd
	update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::setEnable(bool enabled)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_enabled == enabled)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	m_enabled = enabled;
Toshihiro Shimizu 890ddd
	if (m_enabled)
Toshihiro Shimizu 890ddd
		computeContent();
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::updateSize(const QSize &size)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int h = size.height();
Toshihiro Shimizu 890ddd
	double ratio = m_cameraRect.getLy() > 0 ? m_cameraRect.getLx() / (double)m_cameraRect.getLy() : 1.0;
Shinya Kitaoka 12c444
	int w = std::min((int)(h * ratio), parentWidget()->width());
Toshihiro Shimizu 890ddd
	setFixedWidth(w);
Toshihiro Shimizu 890ddd
	if (w > 2 && h > 2)
Toshihiro Shimizu 890ddd
		m_raster = TRaster32P(TDimension(w, h));
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_raster = TRaster32P();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::setBgPainter(TPixel32 color1, TPixel32 color2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (color2 == TPixel32())
Toshihiro Shimizu 890ddd
		m_bgPainter = new SolidColorBgPainter("", color1);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_bgPainter = new CheckboardBgPainter("", color1, color2);
Toshihiro Shimizu 890ddd
	updateRaster();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPoint SwatchViewer::world2win(const TPointD &p) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD center(width() * 0.5, height() * 0.5);
Toshihiro Shimizu 890ddd
	return convert(m_aff * m_fxAff * p + center);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPointD SwatchViewer::win2world(const TPoint &p) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD center(width() * 0.5, height() * 0.5);
Toshihiro Shimizu 890ddd
	TPointD point = TPointD(convert(p) - center);
Toshihiro Shimizu 890ddd
	return m_fxAff.inv() * m_aff.inv() * TPointD(point.x, -point.y);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::zoom(const TPoint &pos, double factor)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_content || factor == 1.0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD delta = convert(pos);
Toshihiro Shimizu 890ddd
	double scale = m_aff.det();
Toshihiro Shimizu 890ddd
	TAffine aff;
Toshihiro Shimizu 890ddd
	if ((scale < 2000 || factor < 1) && (scale > 0.004 || factor > 1)) {
Toshihiro Shimizu 890ddd
		aff = TTranslation(delta) * TScale(factor) * TTranslation(-delta);
Toshihiro Shimizu 890ddd
		setAff(aff * m_aff);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::zoom(bool forward, bool reset)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double scale2 = m_aff.det();
Toshihiro Shimizu 890ddd
	if (reset || ((scale2 < 2000 || !forward) && (scale2 > 0.004 || forward))) {
Toshihiro Shimizu 890ddd
		double oldZoomScale = sqrt(scale2);
Toshihiro Shimizu 890ddd
		double zoomScale = reset ? 1 : getQuantizedZoomFactor(oldZoomScale, forward);
Toshihiro Shimizu 890ddd
		TAffine aff = TScale(zoomScale / oldZoomScale);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		setAff(aff * m_aff);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::computeContent()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (suspendedRendering)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (!m_enabled)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (!m_raster)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Clear the swatch cache when the zoom scale has changed (cache results are not compatible
Toshihiro Shimizu 890ddd
	//between different scale levels)
Toshihiro Shimizu 890ddd
	if (m_aff.a11 != m_contentAff.a11)
Toshihiro Shimizu 890ddd
		SwatchCacheManager::instance()->clearSwatchResults();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect rect(0, 0, width() - 1, height() - 1);
Toshihiro Shimizu 890ddd
	TDimension size = rect.getSize();
Toshihiro Shimizu 890ddd
	assert(m_raster->getSize() == size);
Toshihiro Shimizu 890ddd
	if (m_fx) {
Toshihiro Shimizu 890ddd
		//TFxP fx = makeAffine(m_fx, m_aff);
Toshihiro Shimizu 890ddd
		//TRasterFxP rasterFx = fx;
Toshihiro Shimizu 890ddd
		TRasterFxP rasterFx = m_fx;
Toshihiro Shimizu 890ddd
		if (rasterFx) {
Toshihiro Shimizu 890ddd
			m_executor.cancelAll();
Toshihiro Shimizu 890ddd
			m_executor.addTask(new ContentRender(rasterFx.getPointer(), m_frame, size, this));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			submittedTasks++;
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_content = TRaster32P(size);
Toshihiro Shimizu 890ddd
			m_content->fill(TPixel32::Red);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_content = TRaster32P(size);
Toshihiro Shimizu 890ddd
		m_content->fill(TPixel32::Transparent);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	updateRaster();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::updateRaster()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_enabled)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (!m_raster)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (m_bgPainter)
Toshihiro Shimizu 890ddd
		m_bgPainter->paint(m_raster);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_raster->fill(TPixel32(127, 127, 127));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_cameraMode && !m_cameraRect.isEmpty()) {
Toshihiro Shimizu 890ddd
		TPointD p0(m_cameraRect.x0, m_cameraRect.y0);
Toshihiro Shimizu 890ddd
		TPointD p1(m_cameraRect.x1, m_cameraRect.y1);
Toshihiro Shimizu 890ddd
		TPointD center(width() * 0.5, height() * 0.5);
Toshihiro Shimizu 890ddd
		TPoint transP0 = convert(m_aff * p0 + center);
Toshihiro Shimizu 890ddd
		TPoint transP1 = convert(m_aff * p1 + center);
Toshihiro Shimizu 890ddd
		TPoint p = convert((TPointD(transP1.x, transP1.y) - TPointD(transP0.x, transP0.y)) * 0.5);
Toshihiro Shimizu 890ddd
		TRect rect(transP0 - p, transP1 - p);
Toshihiro Shimizu 890ddd
		m_content->fillOutside(rect, TPixel32(255, 0, 0, 255));
Toshihiro Shimizu 890ddd
		m_content->fillOutside(rect.enlarge(TDimension(1, 1)), TPixel32(0, 0, 0, 0));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_content)
Toshihiro Shimizu 890ddd
		TRop::over(m_raster, m_content);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_points.size(); i++) {
Toshihiro Shimizu 890ddd
		if (m_points[i].m_pairFlag)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		TPoint p = world2win(m_points[i].m_param->getValue(m_frame));
Toshihiro Shimizu 890ddd
		TRop::over(m_raster, m_crossIcon, p - TPoint(4, 4));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_pointPairs.size(); i++) {
Toshihiro Shimizu 890ddd
		int i0 = m_pointPairs[i].first;
Toshihiro Shimizu 890ddd
		int i1 = m_pointPairs[i].second;
Toshihiro Shimizu 890ddd
		assert(i0 != i1);
Toshihiro Shimizu 890ddd
		assert(0 <= i0 && i0 < (int)m_points.size());
Toshihiro Shimizu 890ddd
		assert(0 <= i1 && i1 < (int)m_points.size());
Toshihiro Shimizu 890ddd
		TPoint p0 = world2win(m_points[i0].m_param->getValue(m_frame));
Toshihiro Shimizu 890ddd
		TPoint p1 = world2win(m_points[i1].m_param->getValue(m_frame));
Toshihiro Shimizu 890ddd
		TPoint delta = p1 - p0;
Toshihiro Shimizu 890ddd
		int len = tround(sqrt((double)(delta * delta)));
Toshihiro Shimizu 890ddd
		double phi = 0;
Toshihiro Shimizu 890ddd
		if (len > 0)
Toshihiro Shimizu 890ddd
			phi = 180 * atan2((double)delta.y, (double)delta.x) / TConsts::pi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (len > 500) {
Toshihiro Shimizu 890ddd
			// puo' succedere per zoom molto grandi.
Toshihiro Shimizu 890ddd
			// dovrei fare qualcosa, ma non so bene che cosa e non credo sia
Toshihiro Shimizu 890ddd
			// importantissimo
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TRaster32P arrowShape = createArrowShape(len);
Toshihiro Shimizu 890ddd
			TAffine aff = TRotation(phi).place(0, arrowShape->getLy() / 2, p0.x, p0.y);
Toshihiro Shimizu 890ddd
			TRop::over(m_raster, arrowShape, aff);
Toshihiro Shimizu 890ddd
			// verrebbe la tentazione di usare il filtro TRop::Bilinear (piu'veloce),
Toshihiro Shimizu 890ddd
			// ma la qualita' ne risente molto
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::setContent(const TRaster32P &content, const TAffine &contentAff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_content = content;
Toshihiro Shimizu 890ddd
	m_contentAff = contentAff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	updateRaster();
Toshihiro Shimizu 890ddd
	update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::setAff(const TAffine &aff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_aff = aff;
Toshihiro Shimizu 890ddd
	computeContent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::paintEvent(QPaintEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QPainter p(this);
Toshihiro Shimizu 890ddd
	QRect rectBox = rect();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_enabled)
Toshihiro Shimizu 890ddd
		p.fillRect(rectBox, QBrush(QColor(120, 120, 120)));
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		if (!m_raster)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		QImage image = rasterToQImage(m_raster);
Toshihiro Shimizu 890ddd
		p.drawImage(rectBox, image);
Toshihiro Shimizu 890ddd
		if (m_computing) {
Toshihiro Shimizu 890ddd
			QPen pen;
Toshihiro Shimizu 890ddd
			pen.setColor(Qt::red);
Toshihiro Shimizu 890ddd
			pen.setWidth(3);
Toshihiro Shimizu 890ddd
			p.setPen(pen);
Toshihiro Shimizu 890ddd
			p.drawRect(rectBox.adjusted(0, 0, -1, -1));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::resizeEvent(QResizeEvent *re)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int oldHeight = re->oldSize().height();
Toshihiro Shimizu 890ddd
	int newHeight = re->size().height();
Toshihiro Shimizu 890ddd
	if (oldHeight != newHeight) {
Toshihiro Shimizu 890ddd
		updateSize(QSize(newHeight, newHeight));
Toshihiro Shimizu 890ddd
		computeContent();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::mousePressEvent(QMouseEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPoint pos = TPoint(event->pos().x(), event->pos().y());
Toshihiro Shimizu 890ddd
	m_mouseButton = event->button();
Toshihiro Shimizu 890ddd
	if (m_mouseButton == Qt::LeftButton) {
Toshihiro Shimizu 890ddd
		m_selectedPoint = -1;
Toshihiro Shimizu 890ddd
		if (m_points.empty())
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		TPointD p = win2world(pos);
Toshihiro Shimizu 890ddd
		TPointD q;
Toshihiro Shimizu 890ddd
		double minDist2 = 1e6;
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < (int)m_points.size(); i++) {
Toshihiro Shimizu 890ddd
			TPointD paramPoint = m_points[i].m_param->getValue(m_frame);
Toshihiro Shimizu 890ddd
			double d2 = tdistance2(p, paramPoint);
Toshihiro Shimizu 890ddd
			if (m_selectedPoint < 0 || d2 < minDist2) {
Toshihiro Shimizu 890ddd
				m_selectedPoint = i;
Toshihiro Shimizu 890ddd
				minDist2 = d2;
Toshihiro Shimizu 890ddd
				q = paramPoint;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (m_selectedPoint >= 0) {
Toshihiro Shimizu 890ddd
			m_pointPosDelta = q - p;
Toshihiro Shimizu 890ddd
			TPoint d = world2win(p) - world2win(q);
Toshihiro Shimizu 890ddd
			int dd2 = d.x * d.x + d.y * d.y;
Toshihiro Shimizu 890ddd
			if (dd2 > 400)
Toshihiro Shimizu 890ddd
				m_selectedPoint = -1;
Toshihiro Shimizu 890ddd
			else {
Shinya Kitaoka 3bfa54
				std::string name = m_points[m_selectedPoint].m_param->getName();
Shinya Kitaoka 3bfa54
				std::string prefix = matchSuffix(name, "_b");
Toshihiro Shimizu 890ddd
				if (prefix != "") {
Shinya Kitaoka 3bfa54
					std::string otherName = prefix + "_a";
Toshihiro Shimizu 890ddd
					int n = (int)m_points.size();
Toshihiro Shimizu 890ddd
					int j;
Toshihiro Shimizu 890ddd
					for (j = 0; j < n; j++)
Toshihiro Shimizu 890ddd
						if (i != j && m_points[j].m_param->getName() == otherName)
Toshihiro Shimizu 890ddd
							break;
Toshihiro Shimizu 890ddd
					if (j < n) {
Toshihiro Shimizu 890ddd
						TPoint dist = world2win(m_points[m_selectedPoint].m_param->getValue(m_frame)) -
Toshihiro Shimizu 890ddd
									  world2win(m_points[j].m_param->getValue(m_frame));
Toshihiro Shimizu 890ddd
						int ddist2 = dist.x * dist.x + dist.y * dist.y;
Toshihiro Shimizu 890ddd
						if (ddist2 < 100)
Toshihiro Shimizu 890ddd
							m_selectedPoint = j;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		update();
Toshihiro Shimizu 890ddd
	} else if (m_mouseButton == Qt::MidButton) {
Toshihiro Shimizu 890ddd
		m_pos = pos;
Toshihiro Shimizu 890ddd
		m_firstPos = pos;
Toshihiro Shimizu 890ddd
		m_oldContent = getContent();
Toshihiro Shimizu 890ddd
		if (m_oldContent)
Toshihiro Shimizu 890ddd
			m_curContent = TRaster32P(m_oldContent->getSize());
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			m_curContent = TRaster32P();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::mouseMoveEvent(QMouseEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPoint pos = TPoint(event->pos().x(), event->pos().y());
Toshihiro Shimizu 890ddd
	if (m_mouseButton == Qt::LeftButton) {
Toshihiro Shimizu 890ddd
		if (m_selectedPoint < 0 || m_selectedPoint >= (int)m_points.size())
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		TPointD p = win2world(pos) + m_pointPosDelta;
Toshihiro Shimizu 890ddd
		int index = m_points[m_selectedPoint].m_index;
Toshihiro Shimizu 890ddd
		emit pointPositionChanged(index, p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//It seems that mouse move events may jeopardize our rendering notification deliveries
Toshihiro Shimizu 890ddd
		// - probably because Qt considers them 'higher priority stuff' with respect
Toshihiro Shimizu 890ddd
		//to common queued signal-slot connections.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//In order to allow processing of the ContentRender::started() and ContentRender::finished()
Toshihiro Shimizu 890ddd
		//signals, we need to process events. We will exclude user input events (ie other mouse events)
Toshihiro Shimizu 890ddd
		//to avoid unnecessary recursions.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
Toshihiro Shimizu 890ddd
	} else if (m_mouseButton == Qt::MidButton) {
Toshihiro Shimizu 890ddd
		if (!m_oldContent || !m_curContent)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		m_curContent->fill(TPixel32::Transparent);
Toshihiro Shimizu 890ddd
		TPointD step = convert(pos - m_pos);
Toshihiro Shimizu 890ddd
		//Devo aggiornare l'affine per riposizionare la camera.
Toshihiro Shimizu 890ddd
		m_aff = TTranslation(step.x, -step.y) * m_aff;
Toshihiro Shimizu 890ddd
		m_pos = pos;
Toshihiro Shimizu 890ddd
		TPoint p = pos - m_firstPos;
Toshihiro Shimizu 890ddd
		m_curContent->copy(m_oldContent, TPoint(p.x, -p.y));
Toshihiro Shimizu 890ddd
		setContent(m_curContent, TTranslation(step.x, -step.y) * m_contentAff);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::mouseReleaseEvent(QMouseEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_mouseButton = Qt::NoButton;
Toshihiro Shimizu 890ddd
	m_selectedPoint = -1;
Toshihiro Shimizu 890ddd
	TPoint pos = TPoint(event->pos().x(), event->pos().y());
Toshihiro Shimizu 890ddd
	if (event->button() == Qt::MidButton) {
Toshihiro Shimizu 890ddd
		if (!m_oldContent || !m_curContent)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		TPointD p = convert(pos - m_pos);
Toshihiro Shimizu 890ddd
		setAff(TTranslation(p.x, -p.y) * m_aff);
Toshihiro Shimizu 890ddd
		update();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::wheelEvent(QWheelEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPoint center(event->pos().x() - width() / 2, -event->pos().y() + height() / 2);
Toshihiro Shimizu 890ddd
	zoom(center, exp(0.001 * event->delta()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::keyPressEvent(QKeyEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int key = event->key();
Toshihiro Shimizu 890ddd
	if (key == '+' || key == '-' || key == '0') {
Toshihiro Shimizu 890ddd
		zoom(key == '+', key == '0');
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::hideEvent(QHideEvent *event)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Clear the swatch cache
Toshihiro Shimizu 890ddd
	::setFxForCaching(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// SwatchViewer::ContentRender
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SwatchViewer::ContentRender::ContentRender(
Toshihiro Shimizu 890ddd
	TRasterFx *fx, int frame, const TDimension &size, SwatchViewer *viewer)
Toshihiro Shimizu 890ddd
	: m_fx(fx), m_raster(0), m_frame(frame), m_size(size), m_aff(viewer->m_aff), m_viewer(viewer), m_started(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Is there a less complicated way...?
Toshihiro Shimizu 890ddd
	connect(this, SIGNAL(started(TThread::RunnableP)), this, SLOT(onStarted(TThread::RunnableP)));
Toshihiro Shimizu 890ddd
	connect(this, SIGNAL(finished(TThread::RunnableP)), this, SLOT(onFinished(TThread::RunnableP)));
Toshihiro Shimizu 890ddd
	connect(this, SIGNAL(exception(TThread::RunnableP)), this, SLOT(onFinished(TThread::RunnableP)));
Toshihiro Shimizu 890ddd
	connect(this, SIGNAL(canceled(TThread::RunnableP)), this, SLOT(onCanceled(TThread::RunnableP)), Qt::QueuedConnection); //Starts will need to come *strictly before* cancels
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SwatchViewer::ContentRender::~ContentRender()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::ContentRender::run()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (suspendedRendering)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned long renderId = TRenderer::buildRenderId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPassiveCacheManager::instance()->setContextName(renderId, "S");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_viewer->m_renderer.install(renderId);
Toshihiro Shimizu 890ddd
	m_viewer->m_renderer.declareRenderStart(renderId);
Toshihiro Shimizu 890ddd
	m_viewer->m_renderer.declareFrameStart(m_frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderSettings info;
Toshihiro Shimizu 890ddd
	info.m_isSwatch = true;
Toshihiro Shimizu 890ddd
	info.m_affine = m_aff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTile tile;
Toshihiro Shimizu 890ddd
	m_fx->allocateAndCompute(tile, -0.5 * TPointD(m_size.lx, m_size.ly), m_size, 0, (double)m_frame, info);
Toshihiro Shimizu 890ddd
	m_raster = tile.getRaster();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_viewer->m_renderer.declareFrameEnd(m_frame);
Toshihiro Shimizu 890ddd
	m_viewer->m_renderer.declareRenderEnd(renderId);
Toshihiro Shimizu 890ddd
	m_viewer->m_renderer.uninstall();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int SwatchViewer::ContentRender::taskLoad()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return 100;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::ContentRender::onStarted(TThread::RunnableP task)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_started = true;
Toshihiro Shimizu 890ddd
	m_viewer->m_computing = true;
Toshihiro Shimizu 890ddd
	m_viewer->update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::ContentRender::onFinished(TThread::RunnableP task)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_viewer->m_computing = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_viewer->setContent(m_raster, m_aff);
Toshihiro Shimizu 890ddd
	if ((--submittedTasks == 0) && waitingLoop)
Toshihiro Shimizu 890ddd
		waitingLoop->quit();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchViewer::ContentRender::onCanceled(TThread::RunnableP task)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_started)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((--submittedTasks == 0) && waitingLoop)
Toshihiro Shimizu 890ddd
		waitingLoop->quit();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*************************************************************************************
Toshihiro Shimizu 890ddd
//    Swatch cache manager implementation
Toshihiro Shimizu 890ddd
//*************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SwatchCacheManager *SwatchCacheManager::instance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static SwatchCacheManager theInstance;
Toshihiro Shimizu 890ddd
	return &theInstance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchCacheManager::setFx(const TFxP &fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Update the fxs id data
Toshihiro Shimizu 890ddd
	if (fx == TFxP()) {
Toshihiro Shimizu 890ddd
		//Clear if no fx is set
Toshihiro Shimizu 890ddd
		m_setFxId = 0;
Toshihiro Shimizu 890ddd
		m_childrenFxIds.clear();
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_setFxId = fx->getIdentifier();
Toshihiro Shimizu 890ddd
		m_childrenFxIds.clear();
Toshihiro Shimizu 890ddd
		assert(m_setFxId != 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRasterFx *rfx = dynamic_cast<trasterfx *="">(fx.getPointer());</trasterfx>
Toshihiro Shimizu 890ddd
		assert(rfx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int i = 0; i < fx->getInputPortCount(); ++i) {
Toshihiro Shimizu 890ddd
			//Fxs not allowing cache on the input port are skipped
Toshihiro Shimizu 890ddd
			if (!rfx->allowUserCacheOnPort(i))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFxPort *iport = fx->getInputPort(i);
Toshihiro Shimizu 890ddd
			if (iport && iport->isConnected()) {
Toshihiro Shimizu 890ddd
				TFx *child = iport->getFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//In the zerary case, extract the actual fx
Toshihiro Shimizu 890ddd
				TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(child);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
				if (zcfx)
Toshihiro Shimizu 890ddd
					child = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				assert(child && child->getIdentifier() != 0);
Toshihiro Shimizu 890ddd
				m_childrenFxIds.insert(child->getIdentifier());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//NOTE: Check if this should be avoided in some case...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Release the locks and clear the resources
Toshihiro Shimizu 890ddd
	if (m_currEditedFxResult)
Toshihiro Shimizu 890ddd
		m_currEditedFxResult->releaseLock();
Toshihiro Shimizu 890ddd
	m_currEditedFxResult = TCacheResourceP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<tcacheresourcep>::iterator it;</tcacheresourcep>
Toshihiro Shimizu 890ddd
	for (it = m_swatchCacheContainer.begin(); it != m_swatchCacheContainer.end(); ++it)
Toshihiro Shimizu 890ddd
		(*it)->releaseLock();
Toshihiro Shimizu 890ddd
	m_swatchCacheContainer.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Toshihiro Shimizu 890ddd
	TCacheResourcePool::instance()->releaseReferences("S");
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	for (it = m_genericCacheContainer.begin(); it != m_genericCacheContainer.end(); ++it)
Toshihiro Shimizu 890ddd
		(*it)->releaseLock();
Toshihiro Shimizu 890ddd
	m_genericCacheContainer.clear();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//This method is invoked by the swatch when its scene scale changes. Find it above.
Toshihiro Shimizu 890ddd
void SwatchCacheManager::clearSwatchResults()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_currEditedFxResult)
Toshihiro Shimizu 890ddd
		m_currEditedFxResult->releaseLock();
Toshihiro Shimizu 890ddd
	m_currEditedFxResult = TCacheResourceP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<tcacheresourcep>::iterator it;</tcacheresourcep>
Toshihiro Shimizu 890ddd
	for (it = m_swatchCacheContainer.begin(); it != m_swatchCacheContainer.end(); ++it)
Toshihiro Shimizu 890ddd
		(*it)->releaseLock();
Toshihiro Shimizu 890ddd
	m_swatchCacheContainer.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SwatchCacheManager::getResource(
Shinya Kitaoka 3bfa54
	TCacheResourceP &resource, const std::string &alias,
Toshihiro Shimizu 890ddd
	const TFxP &fx, double frame, const TRenderSettings &rs,
Toshihiro Shimizu 890ddd
	ResourceDeclaration *resData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Only FX RESULTS are interesting - plus, avoid if we're not currently
Toshihiro Shimizu 890ddd
	//editing an fx.
Toshihiro Shimizu 890ddd
	if (!(fx && m_setFxId > 0))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Cache the result in case the fx's id is among the stored ones.
Toshihiro Shimizu 890ddd
	unsigned long fxId = fx->getIdentifier();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fxId == m_setFxId && rs.m_isSwatch) {
Toshihiro Shimizu 890ddd
		if (!resource)
Toshihiro Shimizu 890ddd
			resource = TCacheResourceP(alias, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		resource->addLock();
Toshihiro Shimizu 890ddd
		if (m_currEditedFxResult)
Toshihiro Shimizu 890ddd
			m_currEditedFxResult->releaseLock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_currEditedFxResult = resource;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_childrenFxIds.find(fxId) != m_childrenFxIds.end()) {
Toshihiro Shimizu 890ddd
		if (!resource)
Toshihiro Shimizu 890ddd
			resource = TCacheResourceP(alias, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (rs.m_isSwatch) {
Toshihiro Shimizu 890ddd
			std::set<tcacheresourcep>::iterator it =</tcacheresourcep>
Toshihiro Shimizu 890ddd
				m_swatchCacheContainer.find(resource);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (it == m_swatchCacheContainer.end()) {
Toshihiro Shimizu 890ddd
				resource->addLock();
Toshihiro Shimizu 890ddd
				m_swatchCacheContainer.insert(resource);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Toshihiro Shimizu 890ddd
			resource->enableBackup();
Toshihiro Shimizu 890ddd
			TCacheResourcePool::instance()->addReference(resource, "S");
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
			std::set<tcacheresourcep>::iterator it =</tcacheresourcep>
Toshihiro Shimizu 890ddd
				m_genericCacheContainer.find(resource);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (it == m_genericCacheContainer.end()) {
Toshihiro Shimizu 890ddd
				resource->addLock();
Toshihiro Shimizu 890ddd
				m_genericCacheContainer.insert(resource);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}