Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ttest.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tfilepath_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tlevel_io.h"
Toshihiro Shimizu 890ddd
#include "tfx.h"
Toshihiro Shimizu 890ddd
#include "tparam.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
Campbell Barton 0648b4
#if defined(LINUX)
Campbell Barton 107701
#include <typeinfo></typeinfo>
Campbell Barton 107701
#endif
Campbell Barton 107701
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TTestTable
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef map<string, *="" ttest=""> Table;</string,>
Toshihiro Shimizu 890ddd
	typedef set<string> SkipTable;</string>
Toshihiro Shimizu 890ddd
	Table m_table;
Toshihiro Shimizu 890ddd
	SkipTable m_skipTable;
Toshihiro Shimizu 890ddd
	TTestTable(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	static TTestTable *table()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		static TTestTable *theTable = 0;
Toshihiro Shimizu 890ddd
		if (!theTable)
Toshihiro Shimizu 890ddd
			theTable = new TTestTable;
Toshihiro Shimizu 890ddd
		return theTable;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void add(const string &str, TTest *test)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(test);
Toshihiro Shimizu 890ddd
		if (m_table.find(str) != m_table.end()) {
Toshihiro Shimizu 890ddd
			cout << "*error* Duplicate test name '" << str << "'" << endl;
Toshihiro Shimizu 890ddd
			assert(0);
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_table[str] = test;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void skip(const string &str)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_skipTable.insert(str);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void run(const string &str)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_skipTable.find(str) != m_skipTable.end())
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		Table::iterator it = m_table.find(str);
Toshihiro Shimizu 890ddd
		if (it == m_table.end())
Toshihiro Shimizu 890ddd
			cout << "*error* test '" << str << "' not found" << endl;
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			cout << "\nVerifying " << str << " ... " << endl;
Toshihiro Shimizu 890ddd
			it->second->before();
Toshihiro Shimizu 890ddd
			it->second->test();
Toshihiro Shimizu 890ddd
			it->second->after();
Toshihiro Shimizu 890ddd
			cout << "OK" << endl;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void runAll()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int count = 0;
Toshihiro Shimizu 890ddd
		cout << "Running all tests:" << endl;
Toshihiro Shimizu 890ddd
		Table::iterator it;
Toshihiro Shimizu 890ddd
		for (it = m_table.begin(); it != m_table.end(); ++it) {
Toshihiro Shimizu 890ddd
			run(it->first);
Toshihiro Shimizu 890ddd
			++count;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		cout << count << " test(s) launched" << endl;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void runType(string type)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int count = 0;
Toshihiro Shimizu 890ddd
		cout << "Running " << type << " tests:" << endl;
Toshihiro Shimizu 890ddd
		Table::iterator it;
Toshihiro Shimizu 890ddd
		for (it = m_table.begin(); it != m_table.end(); ++it) {
Toshihiro Shimizu 890ddd
			string str(it->first);
Toshihiro Shimizu 890ddd
			int i = str.find("_");
Toshihiro Shimizu 890ddd
			if (i <= 0)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			string subStr(str, 0, i);
Toshihiro Shimizu 890ddd
			if (subStr == type)
Toshihiro Shimizu 890ddd
				run(it->first);
Toshihiro Shimizu 890ddd
			++count;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		cout << count << " test(s) launched" << endl;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TTest::TTest(const string &testName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTestTable::table()->add(testName, this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TTest::~TTest()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TTest::setInstanceCount()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_levelInstanceCount = TLevel::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_imageInstanceCount = TImage::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_rasterInstanceCount = TRaster::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_imageReaderInstanceCount = TImageReader::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_imageWriterInstanceCount = TImageWriter::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_levelReaderInstanceCount = TLevelReader::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_levelWriterInstanceCount = TLevelWriter::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_paramInstanceCount = TParam::getInstanceCount();
Toshihiro Shimizu 890ddd
	m_fxInstanceCount = TFx::getInstanceCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TTest::verifyInstanceCount()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_levelInstanceCount == TLevel::getInstanceCount());
Toshihiro Shimizu 890ddd
	assert(m_imageInstanceCount == TImage::getInstanceCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//assert(m_rasterInstanceCount==TRaster::getInstanceCount());
Toshihiro Shimizu 890ddd
	// commentata da gmt: in qualche test viene creata un
Toshihiro Shimizu 890ddd
	// offline gl context con annesso raster che ovviamente non
Toshihiro Shimizu 890ddd
	// viene liberato.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_imageReaderInstanceCount == TImageReader::getInstanceCount());
Toshihiro Shimizu 890ddd
	assert(m_imageWriterInstanceCount == TImageWriter::getInstanceCount());
Toshihiro Shimizu 890ddd
	assert(m_levelReaderInstanceCount == TLevelReader::getInstanceCount());
Toshihiro Shimizu 890ddd
	assert(m_levelWriterInstanceCount == TLevelWriter::getInstanceCount());
Toshihiro Shimizu 890ddd
	assert(m_paramInstanceCount == TParam::getInstanceCount());
Toshihiro Shimizu 890ddd
	assert(m_fxInstanceCount == TFx::getInstanceCount());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TTest::runTests(string name)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath testFile = getTestFile(name);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<string> testType;</string>
Toshihiro Shimizu 890ddd
	if (name == "verif_image") {
Toshihiro Shimizu 890ddd
		testType.push_back("write");
Toshihiro Shimizu 890ddd
		testType.push_back("read");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	Tifstream is(testFile);
Toshihiro Shimizu 890ddd
	if (!is) {
Toshihiro Shimizu 890ddd
		cout << "*error* test file '" << testFile << "' not found" << endl;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	cout << "Test file : '" << testFile << "'" << endl;
Toshihiro Shimizu 890ddd
	char buffer[1024];
Toshihiro Shimizu 890ddd
	while (is.getline(buffer, sizeof(buffer))) {
Toshihiro Shimizu 890ddd
		istrstream ss(buffer);
Toshihiro Shimizu 890ddd
		while (ss) {
Toshihiro Shimizu 890ddd
			string s;
Toshihiro Shimizu 890ddd
			ss >> s;
Toshihiro Shimizu 890ddd
			if (s == "")
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			if (s[0] == '#' || s[0] == '!')
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			//Verifica tutti i test
Toshihiro Shimizu 890ddd
			if (s == "all") {
Toshihiro Shimizu 890ddd
				TTestTable::table()->runAll();
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			//Verifica una parte dei test che ha come nome iniziale testType[i]
Toshihiro Shimizu 890ddd
			int i;
Toshihiro Shimizu 890ddd
			bool isTypeFound = false;
Toshihiro Shimizu 890ddd
			for (i = 0; i < (int)testType.size(); i++)
Toshihiro Shimizu 890ddd
				if (s == testType[i]) {
Toshihiro Shimizu 890ddd
					isTypeFound = true;
Toshihiro Shimizu 890ddd
					TTestTable::table()->runType(testType[i]);
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			if (isTypeFound)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			if (s[0] == '~')
Toshihiro Shimizu 890ddd
				TTestTable::table()->skip(s.substr(1));
Toshihiro Shimizu 890ddd
			else //Verifica il test di nome s
Toshihiro Shimizu 890ddd
				TTestTable::table()->run(s);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//================================================================================
Toshihiro Shimizu 890ddd
// Utility
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath getTestFile(string name)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath testFile;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath parentDir = TSystem::getBinDir().getParentDir();
Toshihiro Shimizu 890ddd
#ifndef WIN32
Toshihiro Shimizu 890ddd
	parentDir = parentDir.getParentDir();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath relativePath;
Toshihiro Shimizu 890ddd
#ifndef NDEBUG
Toshihiro Shimizu 890ddd
	relativePath = parentDir + TFilePath("projects\\test\\") + TFilePath(name);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	if (name == "verify_tnzcore")
Toshihiro Shimizu 890ddd
		testFile = relativePath + TFilePath(name).withType("txt");
Toshihiro Shimizu 890ddd
	else if (name == "verify_toonzlib")
Toshihiro Shimizu 890ddd
		testFile = relativePath + TFilePath(name).withType("txt");
Toshihiro Shimizu 890ddd
	else if (name == "verify_image")
Toshihiro Shimizu 890ddd
		testFile = relativePath + TFilePath(name).withType("txt");
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		testFile = parentDir + TFilePath(name).withType("txt");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return testFile;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
*  Return true if \b ra raster and \b rb raster are equal, with an error
Toshihiro Shimizu 890ddd
*  less than \b err; return false otherwise.
Toshihiro Shimizu 890ddd
*  To verify rasters parity check pixel raster; if rasters are different is
Toshihiro Shimizu 890ddd
*	 showed an error message.
Toshihiro Shimizu 890ddd
*
Toshihiro Shimizu 890ddd
*  \b err max variance allowed to value pixels.
Toshihiro Shimizu 890ddd
*
Toshihiro Shimizu 890ddd
*  OSS.: Usually \b ra is check image and \b rb reference image.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int areEqual(TRasterP ra, TRasterP rb, double err)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!ra && !rb)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	int y, x;
Toshihiro Shimizu 890ddd
	if (typeid(ra) != typeid(rb))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!ra || !rb)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (ra->getSize() != rb->getSize())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	const int rowSize = ra->getRowSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P ra32 = ra;
Toshihiro Shimizu 890ddd
	TRaster64P ra64 = ra;
Toshihiro Shimizu 890ddd
	TRasterGR8P raGR8 = ra;
Toshihiro Shimizu 890ddd
	TRasterCM32P raCM32 = ra;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ra32) {
Toshihiro Shimizu 890ddd
		TRaster32P rb32 = rb;
Toshihiro Shimizu 890ddd
		if (!rb32)
Toshihiro Shimizu 890ddd
			return 2;
Toshihiro Shimizu 890ddd
		for (y = 0; y < ra->getLy(); y++)
Toshihiro Shimizu 890ddd
			for (x = 0; x < ra->getLx(); x++) {
Toshihiro Shimizu 890ddd
				TPixel32 *apix = (TPixel32 *)ra->getRawData(x, y);
Toshihiro Shimizu 890ddd
				TPixel32 *bpix = (TPixel32 *)rb->getRawData(x, y);
Toshihiro Shimizu 890ddd
				int rA = apix->r;
Toshihiro Shimizu 890ddd
				int gA = apix->g;
Toshihiro Shimizu 890ddd
				int bA = apix->b;
Toshihiro Shimizu 890ddd
				int mA = apix->m;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int rB = bpix->r;
Toshihiro Shimizu 890ddd
				int gB = bpix->g;
Toshihiro Shimizu 890ddd
				int bB = bpix->b;
Toshihiro Shimizu 890ddd
				int mB = bpix->m;
Toshihiro Shimizu 890ddd
				if (!areAlmostEqual(double(rA), double(rB), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(gA), double(gB), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(bA), double(bB), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(mA), double(mB), err)) {
Toshihiro Shimizu 890ddd
					cout << "MISMATCH: x=" << x << " y=" << y
Toshihiro Shimizu 890ddd
						 << ". Pixel a = (" << (int)rA << "," << (int)gA << ","
Toshihiro Shimizu 890ddd
						 << (int)bA << "," << (int)mA << ")"
Toshihiro Shimizu 890ddd
						 << ". Pixel b = (" << (int)rB << "," << (int)gB << ","
Toshihiro Shimizu 890ddd
						 << (int)bB << "," << (int)mB << ")" << endl;
Toshihiro Shimizu 890ddd
					return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	} else if (ra64) {
Toshihiro Shimizu 890ddd
		TRaster64P rb64 = rb;
Toshihiro Shimizu 890ddd
		if (!rb64)
Toshihiro Shimizu 890ddd
			return 2;
Toshihiro Shimizu 890ddd
		for (y = 0; y < ra->getLy(); y++)
Toshihiro Shimizu 890ddd
			for (x = 0; x < ra->getLx(); x++) {
Toshihiro Shimizu 890ddd
				TPixel64 *apix = (TPixel64 *)ra->getRawData(x, y);
Toshihiro Shimizu 890ddd
				TPixel64 *bpix = (TPixel64 *)rb->getRawData(x, y);
Toshihiro Shimizu 890ddd
				int rA = apix->r;
Toshihiro Shimizu 890ddd
				int gA = apix->g;
Toshihiro Shimizu 890ddd
				int bA = apix->b;
Toshihiro Shimizu 890ddd
				int mA = apix->m;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int rB = bpix->r;
Toshihiro Shimizu 890ddd
				int gB = bpix->g;
Toshihiro Shimizu 890ddd
				int bB = bpix->b;
Toshihiro Shimizu 890ddd
				int mB = bpix->m;
Toshihiro Shimizu 890ddd
				if (!areAlmostEqual(double(rA), double(rB), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(gA), double(gB), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(bA), double(bB), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(mA), double(mB), err)) {
Toshihiro Shimizu 890ddd
					cout << "MISMATCH: x=" << x << " y=" << y
Toshihiro Shimizu 890ddd
						 << ". Pixel a = (" << (int)rA << "," << (int)gA << ","
Toshihiro Shimizu 890ddd
						 << (int)bA << "," << (int)mA << ")"
Toshihiro Shimizu 890ddd
						 << ". Pixel b = (" << (int)rB << "," << (int)gB << ","
Toshihiro Shimizu 890ddd
						 << (int)bB << "," << (int)mB << ")" << endl;
Toshihiro Shimizu 890ddd
					return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	} else if (raGR8) {
Toshihiro Shimizu 890ddd
		TRasterGR8P rbGR8 = rb;
Toshihiro Shimizu 890ddd
		if (!rbGR8)
Toshihiro Shimizu 890ddd
			return 2;
Toshihiro Shimizu 890ddd
		for (y = 0; y < ra->getLy(); y++)
Toshihiro Shimizu 890ddd
			for (x = 0; x < ra->getLx(); x++) {
Toshihiro Shimizu 890ddd
				TPixelGR8 *apix = (TPixelGR8 *)ra->getRawData(x, y);
Toshihiro Shimizu 890ddd
				TPixelGR8 *bpix = (TPixelGR8 *)rb->getRawData(x, y);
Toshihiro Shimizu 890ddd
				int rA = apix->value;
Toshihiro Shimizu 890ddd
				int rB = bpix->value;
Toshihiro Shimizu 890ddd
				if (!areAlmostEqual(double(rA), double(rB), err)) {
Toshihiro Shimizu 890ddd
					cout << "MISMATCH: x=" << x << " y=" << y
Toshihiro Shimizu 890ddd
						 << ". Pixel a = (" << (int)rA << ")"
Toshihiro Shimizu 890ddd
						 << ". Pixel b = (" << (int)rB << ")" << endl;
Toshihiro Shimizu 890ddd
					return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	} else if (raCM32) {
Toshihiro Shimizu 890ddd
		TRasterCM32P rbCM32 = rb;
Toshihiro Shimizu 890ddd
		if (!rbCM32)
Toshihiro Shimizu 890ddd
			return 2;
Toshihiro Shimizu 890ddd
		for (y = 0; y < ra->getLy(); y++)
Toshihiro Shimizu 890ddd
			for (x = 0; x < ra->getLx(); x++) {
Toshihiro Shimizu 890ddd
				TPixelCM32 *apix = (TPixelCM32 *)ra->getRawData(x, y);
Toshihiro Shimizu 890ddd
				TPixelCM32 *bpix = (TPixelCM32 *)rb->getRawData(x, y);
Toshihiro Shimizu 890ddd
				int rAink = apix->getInk();
Toshihiro Shimizu 890ddd
				int rAtone = apix->getTone();
Toshihiro Shimizu 890ddd
				int rAPaint = apix->getPaint();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int rBink = bpix->getInk();
Toshihiro Shimizu 890ddd
				int rBtone = bpix->getTone();
Toshihiro Shimizu 890ddd
				int rBPaint = bpix->getPaint();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (!areAlmostEqual(double(rAink), double(rBink), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(rAtone), double(rBtone), err) ||
Toshihiro Shimizu 890ddd
					!areAlmostEqual(double(rAPaint), double(rBPaint), err)) {
Toshihiro Shimizu 890ddd
					cout << "MISMATCH: x=" << x << " y=" << y
Toshihiro Shimizu 890ddd
						 << ". Pixel a = (Ink: " << (int)rAink << ",Tone: " << (int)rAtone << ",Paint: " << (int)rBPaint << ")"
Toshihiro Shimizu 890ddd
						 << ". Pixel b = (Ink: " << (int)rBink << ",Tone: " << (int)rBtone << ",Paint: " << (int)rBPaint << ")" << endl;
Toshihiro Shimizu 890ddd
					return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return 2;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
*  Return true if \b va vector image and \b vb vector image are equal, with an
Toshihiro Shimizu 890ddd
*	 error less than \b err; return false otherwise.
Toshihiro Shimizu 890ddd
*  To verify vector image parity check stroke count, control point count and
Toshihiro Shimizu 890ddd
*	 control point position; if vector image are different is showed an error message.
Toshihiro Shimizu 890ddd
*
Toshihiro Shimizu 890ddd
*  \b err max percentage variance, related to save box, allowed to control point
Toshihiro Shimizu 890ddd
*					position.
Toshihiro Shimizu 890ddd
*
Toshihiro Shimizu 890ddd
*  OSS.: Usually \b va is check image and \b vb reference image.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int areEqual(TVectorImageP va, TVectorImageP vb, double err)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!va && !vb)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	int aStrokeCount = va->getStrokeCount();
Toshihiro Shimizu 890ddd
	int bStrokeCount = vb->getStrokeCount();
Toshihiro Shimizu 890ddd
	if (aStrokeCount != bStrokeCount) {
Toshihiro Shimizu 890ddd
		cout << "MISMATCH: image stroke count = " << aStrokeCount
Toshihiro Shimizu 890ddd
			 << ". Reference image stroke count = " << bStrokeCount << "." << endl;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD aRect = va->getBBox();
Toshihiro Shimizu 890ddd
	double lxErr = 0.00001;
Toshihiro Shimizu 890ddd
	double lyErr = 0.00001;
Toshihiro Shimizu 890ddd
	if (err != 0) {
Toshihiro Shimizu 890ddd
		lxErr = (aRect.getLx() * err) * 0.01;
Toshihiro Shimizu 890ddd
		lyErr = (aRect.getLy() * err) * 0.01;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TRectD bRect = vb->getBBox();
Toshihiro Shimizu 890ddd
	if (!areAlmostEqual(bRect.getLx(), aRect.getLx(), lxErr) ||
Toshihiro Shimizu 890ddd
		!areAlmostEqual(bRect.getLy(), aRect.getLy(), lyErr)) {
Toshihiro Shimizu 890ddd
		cout << "MISMATCH: different save box rect." << endl;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < aStrokeCount; i++) {
Toshihiro Shimizu 890ddd
		TStroke *aStroke = va->getStroke(i);
Toshihiro Shimizu 890ddd
		TStroke *bStroke = vb->getStroke(i);
Toshihiro Shimizu 890ddd
		int aStrCPCount = aStroke->getControlPointCount();
Toshihiro Shimizu 890ddd
		int bStrCPCount = bStroke->getControlPointCount();
Toshihiro Shimizu 890ddd
		if (aStrCPCount != bStrCPCount) {
Toshihiro Shimizu 890ddd
			cout << "MISMATCH: image stroke " << i << "_mo control point count = " << aStrCPCount
Toshihiro Shimizu 890ddd
				 << ". Reference image stroke " << i << "_mo control point count = " << bStrCPCount
Toshihiro Shimizu 890ddd
				 << "." << endl;
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = 0; j <= aStrCPCount; j++) {
Toshihiro Shimizu 890ddd
			TThickPoint aControlPoint = aStroke->getControlPoint(j);
Toshihiro Shimizu 890ddd
			TThickPoint bControlPoint = bStroke->getControlPoint(j);
Toshihiro Shimizu 890ddd
			if (!areAlmostEqual(aControlPoint.x, bControlPoint.x, lxErr)) {
Toshihiro Shimizu 890ddd
				cout << "MISMATCH: different control point x position." << endl;
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (!areAlmostEqual(aControlPoint.y, bControlPoint.y, lyErr)) {
Toshihiro Shimizu 890ddd
				cout << "MISMATCH: different control point y position." << endl;
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (!areAlmostEqual(aControlPoint.thick, bControlPoint.thick)) {
Toshihiro Shimizu 890ddd
				cout << "MISMATCH: different control point thickness." << endl;
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/* Non controllo i punti di controllo!!!
Toshihiro Shimizu 890ddd
	int aStrCPCount = aStroke->getControlPointCount();
Toshihiro Shimizu 890ddd
	int bStrCPCount = bStroke->getControlPointCount();
Toshihiro Shimizu 890ddd
	if(aStrCPCount != bStrCPCount)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cout << "MISMATCH: image stroke " << i << "_mo control point count = " << aStrCPCount
Toshihiro Shimizu 890ddd
				 << ". Reference image stroke " << i << "_mo control point count = " << bStrCPCount
Toshihiro Shimizu 890ddd
				 << "." << endl;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int j;
Toshihiro Shimizu 890ddd
	for(j=0; j<=aStrCPCount; j++)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TThickPoint aControlPoint = aStroke->getControlPoint(j);
Toshihiro Shimizu 890ddd
		TThickPoint bControlPoint = bStroke->getControlPoint(j);
Toshihiro Shimizu 890ddd
		if(!areAlmostEqual(aControlPoint.x, bControlPoint.x, lxErr))
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			cout << "MISMATCH: different control point x position." << endl;
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if(!areAlmostEqual(aControlPoint.y, bControlPoint.y, lyErr))
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			cout << "MISMATCH: different control point y position." << endl;
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if(!areAlmostEqual(aControlPoint.thick, bControlPoint.thick))
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			cout << "MISMATCH: different control point thickness." << endl;
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}*/
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
*  Return true if images \b a and \b b are equal, with an error
Toshihiro Shimizu 890ddd
*  less than \b err; return false otherwise.
Toshihiro Shimizu 890ddd
*
Toshihiro Shimizu 890ddd
*  If images are rasters recall
Toshihiro Shimizu 890ddd
*  \b bool areEqual(TRasterP ra, TRasterP rb)
Toshihiro Shimizu 890ddd
*  else if image are vectorImage recall
Toshihiro Shimizu 890ddd
*  \b bool areEqual(TVectorImageP ra, TVectorImageP rb)
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int areEqual(TImageP a, TImageP b, double err)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!a && !b)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	if (!a || !b)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (a->getType() != b->getType())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterImageP ra(a);
Toshihiro Shimizu 890ddd
	TRasterImageP rb(b);
Toshihiro Shimizu 890ddd
	if ((!ra && rb) || (ra && !rb))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (ra && rb)
Toshihiro Shimizu 890ddd
		return areEqual(ra->getRaster(), rb->getRaster(), err);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TToonzImageP ta(a);
Toshihiro Shimizu 890ddd
	TToonzImageP tb(b);
Toshihiro Shimizu 890ddd
	if ((!ta && tb) || (ta && !tb))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (ta && tb)
Toshihiro Shimizu 890ddd
		return areEqual(ta->getRaster(), tb->getRaster(), err);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP va(a);
Toshihiro Shimizu 890ddd
	TVectorImageP vb(b);
Toshihiro Shimizu 890ddd
	if (va && vb)
Toshihiro Shimizu 890ddd
		return areEqual(va, vb, err);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool areEqual(const TPalette *paletteA, const TPalette *paletteB)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (paletteA->getStyleCount() != paletteB->getStyleCount() ||
Toshihiro Shimizu 890ddd
		paletteA->getPageCount() != paletteB->getPageCount()) {
Toshihiro Shimizu 890ddd
		cout << "PALETTE style count MISMATCH" << endl;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < paletteA->getStyleCount(); i++) {
Toshihiro Shimizu 890ddd
		TColorStyle *styleA = paletteA->getStyle(i);
Toshihiro Shimizu 890ddd
		TColorStyle *styleB = paletteB->getStyle(i);
Toshihiro Shimizu 890ddd
		if (styleA->getMainColor() == styleB->getMainColor())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		cout << "PALETTE style MISMATCH" << endl;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool areEqual(TLevelP la, TLevelP lb)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (la->getFrameCount() != lb->getFrameCount()) {
Toshihiro Shimizu 890ddd
		cout << "FRAME COUNT MISMATCH" << endl;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!areEqual(la->getPalette(), lb->getPalette()))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TLevel::Iterator ait = la->begin(), bit = lb->begin();
Toshihiro Shimizu 890ddd
	for (; ait != la->end(); ait++, bit++) {
Toshihiro Shimizu 890ddd
		assert(bit != lb->end());
Toshihiro Shimizu 890ddd
		if (!areEqual(ait->second, bit->second))
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}