Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Toonz core includes
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tmeshimage.h"
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Qt includes (mutexing classes)
Toshihiro Shimizu 890ddd
#include <qmutex></qmutex>
Toshihiro Shimizu 890ddd
#include <qmutexlocker></qmutexlocker>
Toshihiro Shimizu 890ddd
#include <qreadwritelock></qreadwritelock>
Toshihiro Shimizu 890ddd
#include <qreadlocker></qreadlocker>
Toshihiro Shimizu 890ddd
#include <qwritelocker></qwritelocker>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/imagemanager.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* EXPLANATION (by Daniele):
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  Images / Image Infos retrieval is quite a frequent task throughout Toonz - in particular,
Toshihiro Shimizu 890ddd
  as Render operations tend to be multithreaded, it is important to ensure that the
Toshihiro Shimizu 890ddd
  ImageManager treats these operations efficiently.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  Most of the image manager's job is that of caching hard-built image data so that successive
Toshihiro Shimizu 890ddd
  queries avoid rebuilding the same images again.
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  In a multithreaded environment, we must make sure that multiple threads block each other out
Toshihiro Shimizu 890ddd
  as little as possible.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  Here are the main performance and threading notes:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    - Image infos are completely cached, while image cachability is user-specified.
Toshihiro Shimizu 890ddd
      This is needed as some images must be loaded only temporarily.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    - One mutex will be used to protect the bindings table. It is the outermost mutex.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    - One mutex (read/write lock) will be used to protect access to EACH individual image.
Toshihiro Shimizu 890ddd
      Testing should be required. If file access is found to be too strictly sequential,
Toshihiro Shimizu 890ddd
      perhaps a single mutex could suffice.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    - Having different mutexes to protect images and image infos is currently not implemented,
Toshihiro Shimizu 890ddd
      but could be. Testing required.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  TODO: TXshSimpleLevel::setFrame(...) usa aggiunte/rimozioni manuali di immagini associate
Toshihiro Shimizu 890ddd
  a binding nell'ImageManager - aspettandosi che poiche' l'immagine e' presente in cache,
Toshihiro Shimizu 890ddd
  verra' beccata...
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    Image Builder implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(ImageBuilder, 100)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ImageBuilder::ImageBuilder()
Toshihiro Shimizu 890ddd
	: TSmartObject(m_classCode), m_imageBuildingLock(QReadWriteLock::Recursive), m_cached(false), m_modified(false), m_imFlags(ImageManager::none)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ImageBuilder::~ImageBuilder()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageBuilder::areInfosCompatible(int imFlags, void *extData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_info.m_valid;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageBuilder::isImageCompatible(int imFlags, void *extData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_info.m_valid;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageBuilder::setImageInfo(TImageInfo &info, const TDimension &size)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	info = TImageInfo();
Toshihiro Shimizu 890ddd
	info.m_lx = size.lx;
Toshihiro Shimizu 890ddd
	info.m_ly = size.ly;
Toshihiro Shimizu 890ddd
	info.m_x0 = 0;
Toshihiro Shimizu 890ddd
	info.m_y0 = 0;
Toshihiro Shimizu 890ddd
	info.m_x1 = size.lx - 1;
Toshihiro Shimizu 890ddd
	info.m_y1 = size.ly - 1;
Toshihiro Shimizu 890ddd
	info.m_valid = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageBuilder::setImageInfo(TImageInfo &info, TImage *img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	info = TImageInfo();
Toshihiro Shimizu 890ddd
	if (TRasterImageP ri = TRasterImageP(img)) {
Toshihiro Shimizu 890ddd
		TRasterP ras = ri->getRaster();
Toshihiro Shimizu 890ddd
		info.m_lx = ras->getLx();
Toshihiro Shimizu 890ddd
		info.m_ly = ras->getLy();
Toshihiro Shimizu 890ddd
		ri->getDpi(info.m_dpix, info.m_dpiy);
Toshihiro Shimizu 890ddd
		TRect savebox = ri->getSavebox();
Toshihiro Shimizu 890ddd
		info.m_x0 = savebox.x0;
Toshihiro Shimizu 890ddd
		info.m_y0 = savebox.y0;
Toshihiro Shimizu 890ddd
		info.m_x1 = savebox.x1;
Toshihiro Shimizu 890ddd
		info.m_y1 = savebox.y1;
Toshihiro Shimizu 890ddd
	} else if (TToonzImageP ti = TToonzImageP(img)) {
Toshihiro Shimizu 890ddd
		TRasterP ras = ti->getRaster();
Toshihiro Shimizu 890ddd
		info.m_lx = ras->getLx();
Toshihiro Shimizu 890ddd
		info.m_ly = ras->getLy();
Toshihiro Shimizu 890ddd
		ti->getDpi(info.m_dpix, info.m_dpiy);
Toshihiro Shimizu 890ddd
		TRect savebox = ti->getSavebox();
Toshihiro Shimizu 890ddd
		info.m_x0 = savebox.x0;
Toshihiro Shimizu 890ddd
		info.m_y0 = savebox.y0;
Toshihiro Shimizu 890ddd
		info.m_x1 = savebox.x1;
Toshihiro Shimizu 890ddd
		info.m_y1 = savebox.y1;
Toshihiro Shimizu 890ddd
	} else if (TMeshImageP mi = TMeshImageP(img)) {
Toshihiro Shimizu 890ddd
		mi->getDpi(info.m_dpix, info.m_dpiy);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	info.m_valid = true;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageBuilder::setImageInfo(TImageInfo &info, TImageReader *ir)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	info = TImageInfo();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TImageInfo *tmp = ir->getImageInfo();
Toshihiro Shimizu 890ddd
	if (tmp) {
Toshihiro Shimizu 890ddd
		info = *tmp;
Toshihiro Shimizu 890ddd
		if (info.m_x1 < info.m_x0 || info.m_y1 < info.m_y0) {
Toshihiro Shimizu 890ddd
			info.m_x0 = info.m_y0 = 0;
Toshihiro Shimizu 890ddd
			info.m_x1 = info.m_lx - 1;
Toshihiro Shimizu 890ddd
			info.m_y1 = info.m_ly - 1;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		info.m_valid = true;
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    Image Manager Privates implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct ImageManager::Imp {
Toshihiro Shimizu 890ddd
	QReadWriteLock m_tableLock;					//!< Lock for the builders table
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp=""> m_builders; //!< identifier -> ImageBuilder table</string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Imp() : m_tableLock(QReadWriteLock::Recursive) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void clear() { m_builders.clear(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    Image Manager implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ImageManager::ImageManager()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ImageManager::~ImageManager()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ImageManager *ImageManager::instance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Re-introdotto possibile baco: voglio controllare se esiste ancora
Toshihiro Shimizu 890ddd
	static ImageManager theInstance;
Toshihiro Shimizu 890ddd
	return &theInstance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ImageManager::bind(const string &id, ImageBuilder *builderPtr)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!builderPtr) {
Toshihiro Shimizu 890ddd
		unbind(id);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP &builderP = m_imp->m_builders[id];
Toshihiro Shimizu 890ddd
	if (builderP && builderP->m_cached)
Toshihiro Shimizu 890ddd
		TImageCache::instance()->remove(id);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	builderP = builderPtr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::unbind(const string &id)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<std::string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</std::string,>
Toshihiro Shimizu 890ddd
	if (it == m_imp->m_builders.end())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP &builderP = it->second;
Toshihiro Shimizu 890ddd
	if (builderP && builderP->m_cached)
Toshihiro Shimizu 890ddd
		TImageCache::instance()->remove(id);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_builders.erase(it);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::isBound(const string &id) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QReadLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
	return m_imp->m_builders.find(id) != m_imp->m_builders.end();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::rebind(const string &srcId, const string &dstId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator st = m_imp->m_builders.find(srcId);</string,>
Toshihiro Shimizu 890ddd
	if (st == m_imp->m_builders.end())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP builder = st->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_builders.erase(st);
Toshihiro Shimizu 890ddd
	m_imp->m_builders[dstId] = builder;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageCache::instance()->remap(dstId, srcId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ImageManager::clear()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageCache::instance()->clearSceneImages();
Toshihiro Shimizu 890ddd
	m_imp->clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageInfo *ImageManager::getInfo(const string &id, int imFlags, void *extData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Lock for table read and try to find data in the cache
Toshihiro Shimizu 890ddd
	QReadLocker tableLocker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	if (it == m_imp->m_builders.end())
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP &builder = it->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!((imFlags & ImageManager::toBeModified) && !builder->m_modified));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Check cached data
Toshihiro Shimizu 890ddd
	if (builder->areInfosCompatible(imFlags, extData))
Toshihiro Shimizu 890ddd
		return &builder->m_info;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QWriteLocker imageBuildingLocker(&builder->m_imageBuildingLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Re-check as waiting may have changed the situation
Toshihiro Shimizu 890ddd
	if (builder->areInfosCompatible(imFlags, extData))
Toshihiro Shimizu 890ddd
		return &builder->m_info;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageInfo info;
Toshihiro Shimizu 890ddd
	if (builder->getInfo(info, imFlags, extData)) {
Toshihiro Shimizu 890ddd
		builder->m_info = info;
Toshihiro Shimizu 890ddd
		return &builder->m_info;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageP ImageManager::getImage(const string &id, int imFlags, void *extData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!((imFlags & ImageManager::toBeModified) && (imFlags & ImageManager::dontPutInCache)));
Toshihiro Shimizu 890ddd
	assert(!((imFlags & ImageManager::toBeModified) && (imFlags & ImageManager::toBeSaved)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Lock for table read and try to find data in the cache
Toshihiro Shimizu 890ddd
	QReadLocker tableLocker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	if (it == m_imp->m_builders.end())
Toshihiro Shimizu 890ddd
		return TImageP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP &builder = it->second;
Toshihiro Shimizu 890ddd
	bool modified = builder->m_modified;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Analyze imFlags
Toshihiro Shimizu 890ddd
	bool _putInCache = TImageCache::instance()->isEnabled() && !(bool)(imFlags & dontPutInCache);
Toshihiro Shimizu 890ddd
	bool _toBeModified = (imFlags & toBeModified);
Toshihiro Shimizu 890ddd
	bool _toBeSaved = (imFlags & toBeSaved);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Update the modified flag according to the specified flags
Toshihiro Shimizu 890ddd
	if (_toBeModified)
Toshihiro Shimizu 890ddd
		builder->m_modified = true;
Toshihiro Shimizu 890ddd
	else if (_toBeSaved)
Toshihiro Shimizu 890ddd
		builder->m_modified = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, fetch the image.
Toshihiro Shimizu 890ddd
	TImageP img;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (builder->m_cached) {
Toshihiro Shimizu 890ddd
		if (modified || builder->isImageCompatible(imFlags, extData)) {
Toshihiro Shimizu 890ddd
			img = TImageCache::instance()->get(id, _toBeModified);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			assert(img);
Toshihiro Shimizu 890ddd
			if (img)
Toshihiro Shimizu 890ddd
				return img;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Lock for image building
Toshihiro Shimizu 890ddd
	QWriteLocker imageBuildingLocker(&builder->m_imageBuildingLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//As multiple threads may block on filesLocker, re-check if the image is now available
Toshihiro Shimizu 890ddd
	if (builder->m_cached) {
Toshihiro Shimizu 890ddd
		if (modified || builder->isImageCompatible(imFlags, extData)) {
Toshihiro Shimizu 890ddd
			img = TImageCache::instance()->get(id, _toBeModified);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			assert(img);
Toshihiro Shimizu 890ddd
			if (img)
Toshihiro Shimizu 890ddd
				return img;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// The image was either not available or not conforming to the required specifications.
Toshihiro Shimizu 890ddd
	// We have to build it now, then.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build the image
Toshihiro Shimizu 890ddd
	img = builder->build(imFlags, extData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (img && _putInCache) {
Toshihiro Shimizu 890ddd
		builder->m_cached = true;
Toshihiro Shimizu 890ddd
		builder->m_modified = _toBeModified;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TImageCache::instance()->add(id, img, true);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return img;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// load icon (and image) data of all frames into cache
Toshihiro Shimizu 890ddd
void ImageManager::loadAllTlvIconsAndPutInCache(TXshSimpleLevel *level, vector<tframeid> fids, vector<string> iconIds, bool cacheImagesAsWell)</string></tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fids.empty() || iconIds.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	//number of fid and iconId should be the same
Toshihiro Shimizu 890ddd
	if ((int)fids.size() != (int)iconIds.size())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//obtain ImageLoader with the first fId
Toshihiro Shimizu 890ddd
	TImageInfo info;
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(level->getImageId(fids[0]));</string,>
Toshihiro Shimizu 890ddd
	if (it != m_imp->m_builders.end()) {
Toshihiro Shimizu 890ddd
		const ImageBuilderP &builder = it->second;
Toshihiro Shimizu 890ddd
		assert(builder);
Toshihiro Shimizu 890ddd
		assert(builder->getRefCount() > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//this function in reimpremented only in ImageLoader
Toshihiro Shimizu 890ddd
		builder->buildAllIconsAndPutInCache(level, fids, iconIds, cacheImagesAsWell);
Toshihiro Shimizu 890ddd
		builder->getInfo(info, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (cacheImagesAsWell) {
Toshihiro Shimizu 890ddd
		// reset the savebox
Toshihiro Shimizu 890ddd
		info.m_x0 = info.m_y0 = 0;
Toshihiro Shimizu 890ddd
		info.m_x1 = info.m_lx - 1;
Toshihiro Shimizu 890ddd
		info.m_y1 = info.m_ly - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// put flags to all builders
Toshihiro Shimizu 890ddd
		for (int f = 0; f < fids.size(); f++) {
Toshihiro Shimizu 890ddd
			std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(level->getImageId(fids[f]));</string,>
Toshihiro Shimizu 890ddd
			if (it != m_imp->m_builders.end()) {
Toshihiro Shimizu 890ddd
				const ImageBuilderP &builder = it->second;
Toshihiro Shimizu 890ddd
				builder->setImageCachedAndModified();
Toshihiro Shimizu 890ddd
				builder->m_info = info;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::invalidate(const string &id)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	if (it == m_imp->m_builders.end())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP &builder = it->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	builder->invalidate();
Toshihiro Shimizu 890ddd
	builder->m_cached = builder->m_modified = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageCache::instance()->remove(id);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::setImage(const string &id, const TImageP &img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!img)
Toshihiro Shimizu 890ddd
		return invalidate(id);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	if (it == m_imp->m_builders.end())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageBuilderP &builder = it->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	builder->invalidate();										   // WARNING: Not all infos are correctly restored
Toshihiro Shimizu 890ddd
	ImageBuilder::setImageInfo(builder->m_info, img.getPointer()); // from supplied image - must investigate further...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageCache::instance()->add(id, img, true);
Toshihiro Shimizu 890ddd
	builder->m_cached = builder->m_modified = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ImageBuilder *ImageManager::getBuilder(const string &id)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	return (it == m_imp->m_builders.end()) ? (ImageBuilder *)0 : it->second.getPointer();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::isCached(const string &id)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	return (it == m_imp->m_builders.end()) ? false : it->second->m_cached;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ImageManager::isModified(const string &id)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_tableLock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<string, imagebuilderp="">::iterator it = m_imp->m_builders.find(id);</string,>
Toshihiro Shimizu 890ddd
	return (it == m_imp->m_builders.end()) ? false : it->second->m_modified;
Toshihiro Shimizu 890ddd
}