Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "imagebuilders.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
#include "toonz/imagemanager.h"
Toshihiro Shimizu 890ddd
#include "toonz/studiopalette.h"
Toshihiro Shimizu 890ddd
#include "toonz/hook.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelupdater.h"
Toshihiro Shimizu 890ddd
#include "toonz/fullcolorpalette.h"
Toshihiro Shimizu 890ddd
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "toonz/textureutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelset.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "tmeshimage.h"
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tvectorgl.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tropcm.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "timageinfo.h"
Toshihiro Shimizu 890ddd
#include "tlogger.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tcontenthistory.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qdir></qdir>
Toshihiro Shimizu 890ddd
#include <qregexp></qregexp>
Toshihiro Shimizu 890ddd
#include <qmessagebox></qmessagebox>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "../common/psdlib/psd.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace bc = boost::container;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    Global stuff
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(TXshSimpleLevel, 20)
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(TXshSimpleLevel, "level")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace stuff
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int idBaseCode = 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct CompatibilityStruct {
Toshihiro Shimizu 890ddd
	int writeMask, neededMask, forbiddenMask;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
CompatibilityStruct compatibility =
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		0x00F1, // mask written.   Note: Student main must be 0x00F2
Toshihiro Shimizu 890ddd
				//                 Note: the 0x00F0 part is currently not used.
Toshihiro Shimizu 890ddd
		0x0000, // mandatory mask: loaded levels MUST have a mask with these bits set
Toshihiro Shimizu 890ddd
				//                 Note: if mandatory mask != 0 then no old level (without mask)
Toshihiro Shimizu 890ddd
				//                       can be loaded
Toshihiro Shimizu 890ddd
				//                 Note: this mask is currently not used.
Toshihiro Shimizu 890ddd
		0x000E  // forbidden mask: loaded levels MUST NOT have a mask with these bits set
Toshihiro Shimizu 890ddd
		//
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline std::string rasterized(std::string id) { return id + "_rasterized"; }
Toshihiro Shimizu 890ddd
inline std::string filled(std::string id) { return id + "_filled"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString getCreatorString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QString creator =
Toshihiro Shimizu 890ddd
		QString::fromStdString(TEnv::getApplicationName()) + " " +
Toshihiro Shimizu 890ddd
		QString::fromStdString(TEnv::getApplicationVersion()) +
Toshihiro Shimizu 890ddd
		" CM(" + QString::number(compatibility.writeMask, 16) + ")";
Toshihiro Shimizu 890ddd
	return creator;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool checkCreatorString(const QString &creator)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int mask = 0;
Toshihiro Shimizu 890ddd
	if (creator != "") {
Toshihiro Shimizu 890ddd
		QRegExp rx("CM\\([0-9A-Fa-f]*\\)");
Toshihiro Shimizu 890ddd
		int pos = rx.indexIn(creator);
Toshihiro Shimizu 890ddd
		int len = rx.matchedLength();
Toshihiro Shimizu 890ddd
		if (pos >= 0 && len >= 4) {
Toshihiro Shimizu 890ddd
			QString v;
Toshihiro Shimizu 890ddd
			if (len > 4)
Toshihiro Shimizu 890ddd
				v = creator.mid(pos + 3, len - 4);
Toshihiro Shimizu 890ddd
			bool ok = true;
Toshihiro Shimizu 890ddd
			mask = v.toInt(&ok, 16);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return (mask & compatibility.neededMask) == compatibility.neededMask &&
Toshihiro Shimizu 890ddd
		   (mask & compatibility.forbiddenMask) == 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool isAreadOnlyLevel(const TFilePath &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (path.isEmpty() || !path.isAbsolute())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (path.getDots() == "." || (path.getDots() == ".." && (path.getType() == "tlv" || path.getType() == "tpl"))) {
Toshihiro Shimizu 890ddd
		if (!TSystem::doesExistFileOrLevel(path))
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		TFileStatus fs(path);
Toshihiro Shimizu 890ddd
		return !fs.isWritable();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/*- 処理が重くなるので、連番ファイルは全てfalseを返す -*/
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  else if(path.getDots() == "..")
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TFilePath dir = path.getParentDir();
Toshihiro Shimizu 890ddd
    QDir qDir(QString::fromStdWString(dir.getWideString()));
Toshihiro Shimizu 890ddd
    QString levelName = QRegExp::escape(QString::fromStdWString(path.getWideName()));
Toshihiro Shimizu 890ddd
    QString levelType = QString::fromStdString(path.getType());
Toshihiro Shimizu 890ddd
    QString exp(levelName+".[0-9]{1,4}."+levelType);
Toshihiro Shimizu 890ddd
    QRegExp regExp(exp);
Toshihiro Shimizu 890ddd
    QStringList list = qDir.entryList(QDir::Files);
Toshihiro Shimizu 890ddd
    QStringList livelFrames = list.filter(regExp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    bool isReadOnly=false;
Toshihiro Shimizu 890ddd
    int i;
Toshihiro Shimizu 890ddd
    for(i=0; i
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      TFilePath frame = dir+TFilePath(livelFrames[i].toStdWString());
Toshihiro Shimizu 890ddd
      if(frame.isEmpty() || !frame.isAbsolute()) continue;
Toshihiro Shimizu 890ddd
      TFileStatus fs(frame);
Toshihiro Shimizu 890ddd
      isReadOnly = !fs.isWritable();
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    return isReadOnly;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void getIndexesRangefromFids(
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level, const std::set<tframeid> &fids, int &fromIndex, int &toIndex)</tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fids.empty()) {
Toshihiro Shimizu 890ddd
		fromIndex = toIndex = -1;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	toIndex = 0;
Toshihiro Shimizu 890ddd
	fromIndex = level->getFrameCount() - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<tframeid>::const_iterator it;</tframeid>
Toshihiro Shimizu 890ddd
	for (it = fids.begin(); it != fids.end(); ++it) {
Toshihiro Shimizu 890ddd
		int index = level->guessIndex(*it);
Toshihiro Shimizu 890ddd
		if (index > toIndex)
Toshihiro Shimizu 890ddd
			toIndex = index;
Toshihiro Shimizu 890ddd
		if (index < fromIndex)
Toshihiro Shimizu 890ddd
			fromIndex = index;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    TXshSimpleLevel  impementation
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TXshSimpleLevel::m_rasterizePli = false;
Toshihiro Shimizu 890ddd
bool TXshSimpleLevel::m_fillFullColorRaster = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
TXshSimpleLevel::TXshSimpleLevel(const std::wstring &name)
Toshihiro Shimizu 890ddd
	: TXshLevel(m_classCode, name), m_properties(new LevelProperties), m_palette(0), m_idBase(toString(idBaseCode++)), m_editableRangeUserInfo(L""), m_isSubsequence(false), m_16BitChannelLevel(false), m_isReadOnly(false), m_temporaryHookMerged(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TXshSimpleLevel::~TXshSimpleLevel()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	clearFrames();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_palette)
Toshihiro Shimizu 890ddd
		m_palette->release();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
void TXshSimpleLevel::setEditableRange(unsigned int from, unsigned int to, const std::wstring &userName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(from <= to && to < (unsigned int)getFrameCount());
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = from; i <= to; i++)
Toshihiro Shimizu 890ddd
		m_editableRange.insert(index2fid(i));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString hostName = TSystem::getHostName();
Toshihiro Shimizu 890ddd
	m_editableRangeUserInfo = userName + L"_" + hostName.toStdWString();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::wstring fileName = getEditableFileName();
Toshihiro Shimizu 890ddd
	TFilePath dstPath = getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
	dstPath = dstPath.withName(fileName).withType(dstPath.getType());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Load temporary level file (for pli and tlv types only)
Toshihiro Shimizu 890ddd
	if (getType() != OVL_XSHLEVEL && TSystem::doesExistFileOrLevel(dstPath)) {
Toshihiro Shimizu 890ddd
		TLevelReaderP lr(dstPath);
Toshihiro Shimizu 890ddd
		TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
		setPalette(level->getPalette());
Toshihiro Shimizu 890ddd
		for (TLevel::Iterator it = level->begin(); it != level->end(); it++) {
Toshihiro Shimizu 890ddd
			TImageP img = lr->getFrameReader(it->first)->load();
Toshihiro Shimizu 890ddd
			setFrame(it->first, img);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Merge temporary hook file with current hookset
Toshihiro Shimizu 890ddd
	const TFilePath &hookFile = getHookPath(dstPath);
Toshihiro Shimizu 890ddd
	mergeTemporaryHookFile(from, to, hookFile);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::mergeTemporaryHookFile(unsigned int from, unsigned int to, const TFilePath &hookFile)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!TFileStatus(hookFile).doesExist())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HookSet *tempHookSet = new HookSet;
Toshihiro Shimizu 890ddd
	TIStream is(hookFile);
Shinya Kitaoka 3bfa54
	std::string tagName;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		if (is.matchTag(tagName) && tagName == "hooks")
Toshihiro Shimizu 890ddd
			tempHookSet->loadData(is);
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HookSet *hookSet = getHookSet();
Toshihiro Shimizu 890ddd
	int tempHookCount = tempHookSet->getHookCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (tempHookCount == 0) {
Toshihiro Shimizu 890ddd
		for (unsigned int f = from; f <= to; f++) {
Toshihiro Shimizu 890ddd
			TFrameId fid = index2fid(f);
Toshihiro Shimizu 890ddd
			hookSet->eraseFrame(fid);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		for (int i = 0; i < tempHookCount; i++) {
Toshihiro Shimizu 890ddd
			Hook *hook = tempHookSet->getHook(i);
Toshihiro Shimizu 890ddd
			Hook *newHook = hookSet->touchHook(hook->getId());
Toshihiro Shimizu 890ddd
			newHook->setTrackerObjectId(hook->getTrackerObjectId());
Toshihiro Shimizu 890ddd
			newHook->setTrackerRegionHeight(hook->getTrackerRegionHeight());
Toshihiro Shimizu 890ddd
			newHook->setTrackerRegionWidth(hook->getTrackerRegionWidth());
Toshihiro Shimizu 890ddd
			for (unsigned int f = from; f <= to; f++) {
Toshihiro Shimizu 890ddd
				TFrameId fid = index2fid(f);
Toshihiro Shimizu 890ddd
				newHook->setAPos(fid, hook->getAPos(fid));
Toshihiro Shimizu 890ddd
				newHook->setBPos(fid, hook->getBPos(fid));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_temporaryHookMerged = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::clearEditableRange()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_editableRange.clear();
Toshihiro Shimizu 890ddd
	m_editableRangeUserInfo = L"";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
std::wstring TXshSimpleLevel::getEditableFileName()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Shinya Kitaoka 3bfa54
	std::wstring fileName = L"." + m_path.getWideName();
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 3bfa54
	std::wstring fileName = m_path.getWideName();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	fileName += L"_" + m_editableRangeUserInfo;
Toshihiro Shimizu 890ddd
	int from, to;
Toshihiro Shimizu 890ddd
	getIndexesRangefromFids(this, m_editableRange, from, to);
Toshihiro Shimizu 890ddd
	if (from == -1 && to == -1)
Toshihiro Shimizu 890ddd
		return L"";
Toshihiro Shimizu 890ddd
	fileName += L"_" + toWideString(from + 1) + L"-" + toWideString(to + 1);
Toshihiro Shimizu 890ddd
	return fileName;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::set<tframeid> TXshSimpleLevel::getEditableRange()</tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_editableRange;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setRenumberTable()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_renumberTable.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FramesSet::iterator ft, fEnd = m_frames.end();
Toshihiro Shimizu 890ddd
	for (ft = m_frames.begin(); ft != fEnd; ++ft)
Toshihiro Shimizu 890ddd
		m_renumberTable[*ft] = *ft;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setDirtyFlag(bool on)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_properties->setDirtyFlag(on);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TXshSimpleLevel::getDirtyFlag() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_properties->getDirtyFlag();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::touchFrame(const TFrameId &fid)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_properties->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
	TContentHistory *ch = getContentHistory();
Toshihiro Shimizu 890ddd
	if (!ch) {
Toshihiro Shimizu 890ddd
		ch = new TContentHistory(true);
Toshihiro Shimizu 890ddd
		setContentHistory(ch);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ch->frameModifiedNow(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getType() == PLI_XSHLEVEL) {
Shinya Kitaoka 3bfa54
		std::string id = rasterized(getImageId(fid));
Toshihiro Shimizu 890ddd
		ImageManager::instance()->invalidate(id);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (getType() & FULLCOLOR_TYPE) {
Shinya Kitaoka 3bfa54
		std::string id = filled(getImageId(fid));
Toshihiro Shimizu 890ddd
		ImageManager::instance()->invalidate(id);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::onPaletteChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FramesSet::iterator ft, fEnd = m_frames.end();
Toshihiro Shimizu 890ddd
	for (ft = m_frames.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		const TFrameId &fid = *ft;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (getType() == PLI_XSHLEVEL) {
Shinya Kitaoka 3bfa54
			std::string id = rasterized(getImageId(fid));
Toshihiro Shimizu 890ddd
			ImageManager::instance()->invalidate(id);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (getType() & FULLCOLOR_TYPE) {
Shinya Kitaoka 3bfa54
			std::string id = filled(getImageId(fid));
Toshihiro Shimizu 890ddd
			ImageManager::instance()->invalidate(id);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		texture_utils::invalidateTexture(this, fid);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setScannedPath(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_scannedPath = fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setPath(const TFilePath &fp, bool keepFrames)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_path = fp;
Toshihiro Shimizu 890ddd
	if (!keepFrames) {
Toshihiro Shimizu 890ddd
		clearFrames();
Toshihiro Shimizu 890ddd
		assert(getScene());
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			load();
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getType() != PLI_XSHLEVEL) {
Toshihiro Shimizu 890ddd
		if (!m_frames.empty()) {
Shinya Kitaoka 3bfa54
			std::string imageId = getImageId(getFirstFid());
Toshihiro Shimizu 890ddd
			const TImageInfo *imageInfo = ImageManager::instance()->getInfo(imageId, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
			if (imageInfo) {
Toshihiro Shimizu 890ddd
				TDimension imageRes(0, 0);
Toshihiro Shimizu 890ddd
				TPointD imageDpi;
Toshihiro Shimizu 890ddd
				imageRes.lx = imageInfo->m_lx;
Toshihiro Shimizu 890ddd
				imageRes.ly = imageInfo->m_ly;
Toshihiro Shimizu 890ddd
				imageDpi.x = imageInfo->m_dpix;
Toshihiro Shimizu 890ddd
				imageDpi.y = imageInfo->m_dpiy;
Toshihiro Shimizu 890ddd
				m_properties->setImageDpi(imageDpi);
Toshihiro Shimizu 890ddd
				m_properties->setImageRes(imageRes);
Toshihiro Shimizu 890ddd
				m_properties->setBpp(imageInfo->m_bitsPerSample * imageInfo->m_samplePerPixel);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::clonePropertiesFrom(const TXshSimpleLevel *oldSl)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_properties->setImageDpi(oldSl->m_properties->getImageDpi()); // Watch out - may change dpi policy!
Toshihiro Shimizu 890ddd
	m_properties->setDpi(oldSl->m_properties->getDpi());
Toshihiro Shimizu 890ddd
	m_properties->setDpiPolicy(oldSl->m_properties->getDpiPolicy());
Toshihiro Shimizu 890ddd
	m_properties->setImageRes(oldSl->m_properties->getImageRes());
Toshihiro Shimizu 890ddd
	m_properties->setBpp(oldSl->m_properties->getBpp());
Toshihiro Shimizu 890ddd
	m_properties->setSubsampling(oldSl->m_properties->getSubsampling());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPalette *TXshSimpleLevel::getPalette() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_palette;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setPalette(TPalette *palette)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_palette != palette) {
Toshihiro Shimizu 890ddd
		if (m_palette)
Toshihiro Shimizu 890ddd
			m_palette->release();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_palette = palette;
Toshihiro Shimizu 890ddd
		if (m_palette) {
Toshihiro Shimizu 890ddd
			m_palette->addRef();
Toshihiro Shimizu 890ddd
			if (!(getType() & FULLCOLOR_TYPE))
Toshihiro Shimizu 890ddd
				m_palette->setPaletteName(getName());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::getFids(std::vector<tframeid> &fids) const</tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	fids.assign(m_frames.begin(), m_frames.end());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::vector<tframeid> TXshSimpleLevel::getFids() const</tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return std::vector<tframeid>(m_frames.begin(), m_frames.end());</tframeid>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TXshSimpleLevel::isFid(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_frames.count(fid);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TFrameId &TXshSimpleLevel::getFrameId(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return *(m_frames.begin() += index);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFrameId TXshSimpleLevel::getFirstFid() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return !isEmpty() ? *m_frames.begin() : TFrameId(TFrameId::NO_FRAME);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFrameId TXshSimpleLevel::getLastFid() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return !isEmpty() ? *m_frames.rbegin() : TFrameId(TFrameId::NO_FRAME);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TXshSimpleLevel::guessStep() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int frameCount = m_frames.size();
Toshihiro Shimizu 890ddd
	if (frameCount < 2)
Toshihiro Shimizu 890ddd
		return 1; // un livello con zero o un frame ha per def. step=1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FramesSet::const_iterator ft = m_frames.begin();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFrameId firstFid = *ft++,
Toshihiro Shimizu 890ddd
			 secondFid = *ft++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (firstFid.getLetter() != 0 || secondFid.getLetter() != 0)
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int step = secondFid.getNumber() - firstFid.getNumber();
Toshihiro Shimizu 890ddd
	if (step == 1)
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// controllo subito se lo step vale per l'ultimo frame
Toshihiro Shimizu 890ddd
	// (cerco di limitare il numero di volte in cui devo controllare tutta la lista)
Toshihiro Shimizu 890ddd
	TFrameId lastFid = *m_frames.rbegin();
Toshihiro Shimizu 890ddd
	if (lastFid.getLetter() != 0)
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (lastFid.getNumber() != firstFid.getNumber() + step * (frameCount - 1))
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 2; ft != m_frames.end(); ++ft, ++i) {
Toshihiro Shimizu 890ddd
		const TFrameId &fid = *ft;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fid.getLetter() != 0)
Toshihiro Shimizu 890ddd
			return 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fid.getNumber() != firstFid.getNumber() + step * i)
Toshihiro Shimizu 890ddd
			return 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return step;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TXshSimpleLevel::fid2index(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FramesSet::const_iterator ft = m_frames.find(fid);
Toshihiro Shimizu 890ddd
	return (ft != m_frames.end()) ? std::distance(m_frames.begin(), ft) : // Note: flat_set has random access
Toshihiro Shimizu 890ddd
			   -1;														  // iterators, so this is FAST
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TXshSimpleLevel::guessIndex(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_frames.empty())
Toshihiro Shimizu 890ddd
		return 0; // no frames, return 0 (by definition)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FramesSet::const_iterator ft = m_frames.lower_bound(fid);
Toshihiro Shimizu 890ddd
	if (ft == m_frames.end()) {
Toshihiro Shimizu 890ddd
		const TFrameId &maxFid = *m_frames.rbegin();
Toshihiro Shimizu 890ddd
		assert(fid > maxFid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fid not in the table, but greater than the last one.
Toshihiro Shimizu 890ddd
		// return a suitable index. (e.g. frames are 1,3,5,7; fid2index(11) should return index=5)
Toshihiro Shimizu 890ddd
		int step = guessStep();
Toshihiro Shimizu 890ddd
		int i = (fid.getNumber() - maxFid.getNumber()) / step;
Toshihiro Shimizu 890ddd
		return m_frames.size() - 1 + i;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return std::distance(m_frames.begin(), ft);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFrameId TXshSimpleLevel::index2fid(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (index < 0)
Toshihiro Shimizu 890ddd
		return TFrameId(-2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int frameCount = m_frames.size();
Toshihiro Shimizu 890ddd
	if (frameCount == 0)
Toshihiro Shimizu 890ddd
		return TFrameId(1); // o_o?
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (index < frameCount) {
Toshihiro Shimizu 890ddd
		FramesSet::const_iterator ft = m_frames.begin();
Toshihiro Shimizu 890ddd
		std::advance(ft, index);
Toshihiro Shimizu 890ddd
		return *ft;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		int step = guessStep();
Toshihiro Shimizu 890ddd
		TFrameId maxFid = *m_frames.rbegin();
Toshihiro Shimizu 890ddd
		int d = step * (index - frameCount + 1);
Toshihiro Shimizu 890ddd
		return TFrameId(maxFid.getNumber() + d);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageP TXshSimpleLevel::getFrame(const TFrameId &fid, UCHAR imFlags, int subsampling) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_type != UNKNOWN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// If the required frame is not in range, quit
Toshihiro Shimizu 890ddd
	if (m_frames.count(fid) == 0)
Toshihiro Shimizu 890ddd
		return TImageP();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	const std::string &imgId = getImageId(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageLoader::BuildExtData extData(this, fid, subsampling);
Toshihiro Shimizu 890ddd
	TImageP img = ImageManager::instance()->getImage(
Toshihiro Shimizu 890ddd
		imgId, imFlags, &extData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (imFlags & ImageManager::toBeModified) {
Toshihiro Shimizu 890ddd
		// The image will be modified. Perform any related invalidation.
Toshihiro Shimizu 890ddd
		texture_utils::invalidateTexture(this, fid); // We must rebuild associated textures
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return img;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageInfo *TXshSimpleLevel::getFrameInfo(const TFrameId &fid, bool toBeModified)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_type != UNKNOWN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// If the required frame is not in range, quit
Toshihiro Shimizu 890ddd
	if (m_frames.count(fid) == 0)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	const std::string &imgId = getImageId(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TImageInfo *info = ImageManager::instance()->getInfo(
Toshihiro Shimizu 890ddd
		imgId, toBeModified ? ImageManager::toBeModified : ImageManager::none, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return info;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageP TXshSimpleLevel::getFrameIcon(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_type != UNKNOWN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_frames.count(fid) == 0)
Toshihiro Shimizu 890ddd
		return TImageP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: Icons caching is DISABLED at this stage. It is now responsibility of
Toshihiro Shimizu 890ddd
	// ToonzQt's IconGenerator class.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageLoader::BuildExtData extData(this, fid);
Toshihiro Shimizu 890ddd
	extData.m_subs = 1, extData.m_icon = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const std::string &imgId = getImageId(fid);
Toshihiro Shimizu 890ddd
	TImageP img = ImageManager::instance()->getImage(imgId, ImageManager::dontPutInCache, &extData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TToonzImageP timg = (TToonzImageP)img;
Toshihiro Shimizu 890ddd
	if (timg && m_palette)
Toshihiro Shimizu 890ddd
		timg->setPalette(m_palette);
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 TXshSimpleLevel::loadAllIconsAndPutInCache(bool cacheImagesAsWell)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_type != TZP_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
	getFids(fids);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<std::string> iconIds;</std::string>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < (int)fids.size(); i++) {
Toshihiro Shimizu 890ddd
		iconIds.push_back(getIconId(fids[i]));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageManager::instance()->loadAllTlvIconsAndPutInCache(this, fids, iconIds, cacheImagesAsWell);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRasterImageP TXshSimpleLevel::getFrameToCleanup(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_type != UNKNOWN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FramesSet::const_iterator ft = m_frames.find(fid);
Toshihiro Shimizu 890ddd
	if (ft == m_frames.end())
Toshihiro Shimizu 890ddd
		return TImageP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool flag = (m_scannedPath != TFilePath());
Shinya Kitaoka 3bfa54
	std::string imageId = getImageId(fid, flag ? Scanned : 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageLoader::BuildExtData extData(this, fid, 1);
Toshihiro Shimizu 890ddd
	TRasterImageP img = ImageManager::instance()->getImage(imageId, ImageManager::dontPutInCache, &extData);
Toshihiro Shimizu 890ddd
	if (!img)
Toshihiro Shimizu 890ddd
		return img;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double x_dpi, y_dpi;
Toshihiro Shimizu 890ddd
	img->getDpi(x_dpi, y_dpi);
Toshihiro Shimizu 890ddd
	if (!x_dpi && !y_dpi) {
Toshihiro Shimizu 890ddd
		TPointD dpi = m_properties->getDpi();
Toshihiro Shimizu 890ddd
		img->setDpi(dpi.x, dpi.y);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return img;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageP TXshSimpleLevel::getFullsampledFrame(const TFrameId &fid, UCHAR imFlags) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_type != UNKNOWN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FramesSet::const_iterator it = m_frames.find(fid);
Toshihiro Shimizu 890ddd
	if (it == m_frames.end())
Toshihiro Shimizu 890ddd
		return TRasterImageP();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::string imageId = getImageId(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageLoader::BuildExtData extData(this, fid, 1);
Toshihiro Shimizu 890ddd
	TImageP img = ImageManager::instance()->getImage(imageId, imFlags, &extData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (imFlags & ImageManager::toBeModified) {
Toshihiro Shimizu 890ddd
		// The image will be modified. Perform any related invalidation.
Toshihiro Shimizu 890ddd
		texture_utils::invalidateTexture(this, fid); // We must rebuild associated textures
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return img;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
std::string TXshSimpleLevel::getIconId(const TFrameId &fid, int frameStatus) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return "icon:" + getImageId(fid, frameStatus);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
std::string TXshSimpleLevel::getIconId(const TFrameId &fid, const TDimension &size) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return getImageId(fid) + ":" + toString(size.lx) + "x" + toString(size.ly);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TAffine getAffine(const TDimension &srcSize, const TDimension &dstSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double scx = 1 * dstSize.lx / (double)srcSize.lx;
Toshihiro Shimizu 890ddd
	double scy = 1 * dstSize.ly / (double)srcSize.ly;
Toshihiro Shimizu 890ddd
	double sc = tmin(scx, scy);
Toshihiro Shimizu 890ddd
	double dx = (dstSize.lx - srcSize.lx * sc) * 0.5;
Toshihiro Shimizu 890ddd
	double dy = (dstSize.ly - srcSize.ly * sc) * 0.5;
Toshihiro Shimizu 890ddd
	return TScale(sc) * TTranslation(0.5 * TPointD(srcSize.lx, srcSize.ly) + TPointD(dx, dy));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!Costruisce l'icona di dimesione \b size dell'immagine \b img.*/
Toshihiro Shimizu 890ddd
TImageP buildIcon(const TImageP &img, const TDimension &size)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRaster32P raster(size);
Toshihiro Shimizu 890ddd
	if (TVectorImageP vi = img) {
Toshihiro Shimizu 890ddd
		TOfflineGL *glContext = new TOfflineGL(size);
Toshihiro Shimizu 890ddd
		TDimension cameraSize(768, 576);
Toshihiro Shimizu 890ddd
		TPalette *vPalette = img->getPalette();
Toshihiro Shimizu 890ddd
		assert(vPalette);
Toshihiro Shimizu 890ddd
		const TVectorRenderData rd(
Toshihiro Shimizu 890ddd
			getAffine(cameraSize, size),
Toshihiro Shimizu 890ddd
			TRect(),
Toshihiro Shimizu 890ddd
			vPalette,
Toshihiro Shimizu 890ddd
			0, false);
Toshihiro Shimizu 890ddd
		glContext->clear(TPixel32::White);
Toshihiro Shimizu 890ddd
		glContext->draw(vi, rd);
Toshihiro Shimizu 890ddd
		raster->copy(glContext->getRaster());
Toshihiro Shimizu 890ddd
		delete glContext;
Toshihiro Shimizu 890ddd
	} else if (TToonzImageP ti = img) {
Toshihiro Shimizu 890ddd
		raster->fill(TPixel32(255, 255, 255, 255));
Toshihiro Shimizu 890ddd
		TRasterCM32P rasCM32 = ti->getRaster();
Toshihiro Shimizu 890ddd
		TRect bbox;
Toshihiro Shimizu 890ddd
		bbox = ti->getSavebox();
Toshihiro Shimizu 890ddd
		if (!bbox.isEmpty()) {
Toshihiro Shimizu 890ddd
			rasCM32 = rasCM32->extractT(bbox);
Toshihiro Shimizu 890ddd
			double sx = raster->getLx() / (double)rasCM32->getLx();
Toshihiro Shimizu 890ddd
			double sy = raster->getLy() / (double)rasCM32->getLy();
Toshihiro Shimizu 890ddd
			double sc = tmin(sx, sy);
Toshihiro Shimizu 890ddd
			TAffine aff = TScale(sc).place(
Toshihiro Shimizu 890ddd
				rasCM32->getCenterD(),
Toshihiro Shimizu 890ddd
				raster->getCenterD());
Toshihiro Shimizu 890ddd
			TRop::resample(
Toshihiro Shimizu 890ddd
				raster,
Toshihiro Shimizu 890ddd
				rasCM32,
Toshihiro Shimizu 890ddd
				ti->getPalette(),
Toshihiro Shimizu 890ddd
				aff);
Toshihiro Shimizu 890ddd
			raster->lock();
Toshihiro Shimizu 890ddd
			for (int y = 0; y < raster->getLy(); y++) {
Toshihiro Shimizu 890ddd
				TPixel32 *pix = raster->pixels(y);
Toshihiro Shimizu 890ddd
				TPixel32 *endPix = pix + raster->getLx();
Toshihiro Shimizu 890ddd
				while (pix < endPix) {
Toshihiro Shimizu 890ddd
					*pix = overPix(TPixel32::White, *pix);
Toshihiro Shimizu 890ddd
					pix++;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			raster->unlock();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TRasterImageP ri = img;
Toshihiro Shimizu 890ddd
		if (ri) {
Toshihiro Shimizu 890ddd
			ri->makeIcon(raster);
Toshihiro Shimizu 890ddd
			TRop::addBackground(raster, TPixel32::White);
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			raster->fill(TPixel32(127, 50, 20));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TRasterImageP(raster);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // anonymous namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setFrame(const TFrameId &fid, const TImageP &img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_type != UNKNOWN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (img)
Toshihiro Shimizu 890ddd
		img->setPalette(getPalette());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_frames.insert(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath path = m_path;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int frameStatus = getFrameStatus(fid);
Toshihiro Shimizu 890ddd
	static const int SCANNED_OR_CLEANUPPED = (Scanned | Cleanupped);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((frameStatus & SCANNED_OR_CLEANUPPED) == Scanned)
Toshihiro Shimizu 890ddd
		path = m_scannedPath;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Deal with the ImageManger: ensure the identifiers are bound, and the
Toshihiro Shimizu 890ddd
	// associated image is either modified to img or (if !img) invalidated.
Shinya Kitaoka 3bfa54
	const std::string &imageId = getImageId(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!ImageManager::instance()->isBound(imageId)) {
Toshihiro Shimizu 890ddd
		const TFilePath &decodedPath = getScene()->decodeFilePath(path);
Toshihiro Shimizu 890ddd
		ImageManager::instance()->bind(imageId, new ImageLoader(decodedPath, fid));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageManager::instance()->setImage(imageId, img); // Invalidates if !img
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (frameStatus == Normal) {
Toshihiro Shimizu 890ddd
		// Only a normal frame can have these. Justified since:
Toshihiro Shimizu 890ddd
		//  a) PLIs have nothing to share with cleanup stuff
Toshihiro Shimizu 890ddd
		//  b) The latter is used only in LineTest - which does not have Cleanup
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == PLI_XSHLEVEL) {
Shinya Kitaoka 3bfa54
			const std::string &imageId2 = rasterized(imageId);
Toshihiro Shimizu 890ddd
			if (!ImageManager::instance()->isBound(imageId2))
Toshihiro Shimizu 890ddd
				ImageManager::instance()->bind(imageId2, new ImageRasterizer);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				ImageManager::instance()->invalidate(imageId2);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == OVL_XSHLEVEL || m_type == TZI_XSHLEVEL) {
Shinya Kitaoka 3bfa54
			const std::string &imageId2 = filled(imageId);
Toshihiro Shimizu 890ddd
			if (!ImageManager::instance()->isBound(imageId2))
Toshihiro Shimizu 890ddd
				ImageManager::instance()->bind(imageId2, new ImageFiller);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				ImageManager::instance()->invalidate(imageId2);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::eraseFrame(const TFrameId &fid)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FramesSet::iterator ft = m_frames.find(fid);
Toshihiro Shimizu 890ddd
	if (ft == m_frames.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Erase the corresponding entry in the renumber table
Toshihiro Shimizu 890ddd
	std::map<tframeid, tframeid="">::iterator rt, rEnd(m_renumberTable.end());</tframeid,>
Toshihiro Shimizu 890ddd
	for (rt = m_renumberTable.begin(); rt != rEnd; ++rt) {
Toshihiro Shimizu 890ddd
		if (rt->second == fid) {
Toshihiro Shimizu 890ddd
			m_renumberTable.erase(rt->first);
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_frames.erase(ft);
Toshihiro Shimizu 890ddd
	getHookSet()->eraseFrame(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageManager *im = ImageManager::instance();
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		im->unbind(getImageId(fid, Normal));
Toshihiro Shimizu 890ddd
		im->unbind(getImageId(fid, Scanned));
Toshihiro Shimizu 890ddd
		im->unbind(getImageId(fid, CleanupPreview));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == PLI_XSHLEVEL)
Toshihiro Shimizu 890ddd
			im->unbind(rasterized(getImageId(fid)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == OVL_XSHLEVEL || m_type == TZI_XSHLEVEL)
Toshihiro Shimizu 890ddd
			im->unbind(filled(getImageId(fid)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		texture_utils::invalidateTexture(this, fid);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::clearFrames()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ImageManager *im = ImageManager::instance();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Unbind frames
Toshihiro Shimizu 890ddd
	FramesSet::iterator ft, fEnd = m_frames.end();
Toshihiro Shimizu 890ddd
	for (ft = m_frames.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		im->unbind(getImageId(*ft, Scanned));
Toshihiro Shimizu 890ddd
		im->unbind(getImageId(*ft, Cleanupped));
Toshihiro Shimizu 890ddd
		im->unbind(getImageId(*ft, CleanupPreview));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == PLI_XSHLEVEL)
Toshihiro Shimizu 890ddd
			im->unbind(rasterized(getImageId(*ft)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == OVL_XSHLEVEL || m_type == TZI_XSHLEVEL)
Toshihiro Shimizu 890ddd
			im->unbind(filled(getImageId(*ft)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		texture_utils::invalidateTexture(this, *ft);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Clear level
Toshihiro Shimizu 890ddd
	m_frames.clear();
Toshihiro Shimizu 890ddd
	m_editableRange.clear();
Toshihiro Shimizu 890ddd
	m_editableRangeUserInfo.clear();
Toshihiro Shimizu 890ddd
	m_renumberTable.clear();
Toshihiro Shimizu 890ddd
	m_framesStatus.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::loadData(TIStream &is)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 3bfa54
	std::string tagName;
Toshihiro Shimizu 890ddd
	bool flag = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int type = UNKNOWN_XSHLEVEL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (;;) {
Toshihiro Shimizu 890ddd
		if (is.matchTag(tagName)) {
Toshihiro Shimizu 890ddd
			if (tagName == "path") {
Toshihiro Shimizu 890ddd
				is >> m_path;
Toshihiro Shimizu 890ddd
				is.matchEndTag();
Toshihiro Shimizu 890ddd
			} else if (tagName == "scannedPath") {
Toshihiro Shimizu 890ddd
				is >> m_scannedPath;
Toshihiro Shimizu 890ddd
				is.matchEndTag();
Toshihiro Shimizu 890ddd
			} else if (tagName == "info") {
Shinya Kitaoka 3bfa54
				std::string v;
Toshihiro Shimizu 890ddd
				double xdpi = 0, ydpi = 0;
Toshihiro Shimizu 890ddd
				int subsampling = 1;
Toshihiro Shimizu 890ddd
				int doPremultiply = 0;
Toshihiro Shimizu 890ddd
				int whiteTransp = 0;
Toshihiro Shimizu 890ddd
				int antialiasSoftness = 0;
Toshihiro Shimizu 890ddd
				LevelProperties::DpiPolicy dpiPolicy = LevelProperties::DP_ImageDpi;
Toshihiro Shimizu 890ddd
				if (is.getTagParam("dpix", v))
Toshihiro Shimizu 890ddd
					xdpi = toDouble(v);
Toshihiro Shimizu 890ddd
				if (is.getTagParam("dpiy", v))
Toshihiro Shimizu 890ddd
					ydpi = toDouble(v);
Toshihiro Shimizu 890ddd
				if (xdpi != 0 && ydpi != 0)
Toshihiro Shimizu 890ddd
					dpiPolicy = LevelProperties::DP_CustomDpi;
Shinya Kitaoka 3bfa54
				std::string dpiType = is.getTagAttribute("dpiType");
Toshihiro Shimizu 890ddd
				if (dpiType == "image")
Toshihiro Shimizu 890ddd
					dpiPolicy = LevelProperties::DP_ImageDpi;
Toshihiro Shimizu 890ddd
				if (is.getTagParam("type", v) && v == "s")
Toshihiro Shimizu 890ddd
					type = TZI_XSHLEVEL;
Toshihiro Shimizu 890ddd
				if (is.getTagParam("subsampling", v))
Toshihiro Shimizu 890ddd
					subsampling = toInt(v);
Toshihiro Shimizu 890ddd
				if (is.getTagParam("premultiply", v))
Toshihiro Shimizu 890ddd
					doPremultiply = toInt(v);
Toshihiro Shimizu 890ddd
				if (is.getTagParam("antialias", v))
Toshihiro Shimizu 890ddd
					antialiasSoftness = toInt(v);
Toshihiro Shimizu 890ddd
				if (is.getTagParam("whiteTransp", v))
Toshihiro Shimizu 890ddd
					whiteTransp = toInt(v);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_properties->setDpiPolicy(dpiPolicy);
Toshihiro Shimizu 890ddd
				m_properties->setDpi(TPointD(xdpi, ydpi));
Toshihiro Shimizu 890ddd
				m_properties->setSubsampling(subsampling);
Toshihiro Shimizu 890ddd
				m_properties->setDoPremultiply(doPremultiply);
Toshihiro Shimizu 890ddd
				m_properties->setDoAntialias(antialiasSoftness);
Toshihiro Shimizu 890ddd
				m_properties->setWhiteTransp(whiteTransp);
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				throw TException("unexpected tag " + tagName);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (flag)
Toshihiro Shimizu 890ddd
				break; // ci puo' essere un solo nome
Toshihiro Shimizu 890ddd
			flag = true;
Shinya Kitaoka 3bfa54
			std::wstring token;
Toshihiro Shimizu 890ddd
			is >> token;
Toshihiro Shimizu 890ddd
			if (token == L"__empty") {
Toshihiro Shimizu 890ddd
				// empty = true;
Toshihiro Shimizu 890ddd
				is >> token;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (token == L"_raster") // obsoleto (Tab2.2)
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				double xdpi = 1, ydpi = 1;
Toshihiro Shimizu 890ddd
				is >> xdpi >> ydpi >> m_name;
Toshihiro Shimizu 890ddd
				setName(m_name);
Toshihiro Shimizu 890ddd
				type = OVL_XSHLEVEL;
Toshihiro Shimizu 890ddd
				m_properties->setDpi(TPointD(xdpi, ydpi));
Toshihiro Shimizu 890ddd
				setType(type);
Toshihiro Shimizu 890ddd
				setPath(TFilePath("+drawings/") + (getName() + L"." + toWideString("bmp")), true);
Toshihiro Shimizu 890ddd
			} else if (token == L"__raster") // obsoleto (Tab2.2)
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				double xdpi = 1, ydpi = 1;
Shinya Kitaoka 3bfa54
				std::string extension;
Toshihiro Shimizu 890ddd
				is >> xdpi >> ydpi >> m_name >> extension;
Toshihiro Shimizu 890ddd
				setName(m_name);
Toshihiro Shimizu 890ddd
				type = OVL_XSHLEVEL;
Toshihiro Shimizu 890ddd
				m_properties->setDpi(TPointD(xdpi, ydpi));
Toshihiro Shimizu 890ddd
				setType(type);
Toshihiro Shimizu 890ddd
				setPath(TFilePath("+drawings/") + (getName() + L"." + toWideString(extension)), true);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				m_name = token;
Toshihiro Shimizu 890ddd
				setName(m_name);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (type == UNKNOWN_XSHLEVEL) {
Shinya Kitaoka 3bfa54
		std::string ext = m_path.getType();
Toshihiro Shimizu 890ddd
		if (ext == "pli" || ext == "svg")
Toshihiro Shimizu 890ddd
			type = PLI_XSHLEVEL;
Toshihiro Shimizu 890ddd
		else if (ext == "tlv" || ext == "tzu" || ext == "tzp" || ext == "tzl")
Toshihiro Shimizu 890ddd
			type = TZP_XSHLEVEL;
Toshihiro Shimizu 890ddd
		else if (ext == "tzi")
Toshihiro Shimizu 890ddd
			type = TZI_XSHLEVEL;
Toshihiro Shimizu 890ddd
		else if (ext == "mesh")
Toshihiro Shimizu 890ddd
			type = MESH_XSHLEVEL;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			type = OVL_XSHLEVEL;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	setType(type);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
class LoadingLevelRange
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TFrameId m_fromFid, m_toFid;
Toshihiro Shimizu 890ddd
	LoadingLevelRange() : m_fromFid(1), m_toFid(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool match(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		/*-- ↓SubSequent範囲内にある条件		↓全部ロードする場合 --*/
Toshihiro Shimizu 890ddd
		return m_fromFid <= fid && fid <= m_toFid || m_fromFid > m_toFid;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isEnabled() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return m_fromFid <= m_toFid;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void reset()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_fromFid = TFrameId(1);
Toshihiro Shimizu 890ddd
		m_toFid = TFrameId(0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} loadingLevelRange;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void setLoadingLevelRange(const TFrameId &fromFid, const TFrameId &toFid)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	loadingLevelRange.m_fromFid = fromFid;
Toshihiro Shimizu 890ddd
	loadingLevelRange.m_toFid = toFid;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void getLoadingLevelRange(TFrameId &fromFid, TFrameId &toFid)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	fromFid = loadingLevelRange.m_fromFid;
Toshihiro Shimizu 890ddd
	toFid = loadingLevelRange.m_toFid;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath getLevelPathAndSetNameWithPsdLevelName(TXshSimpleLevel *xshLevel)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath retfp = xshLevel->getPath();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString name = QString::fromStdWString(retfp.getWideName());
Toshihiro Shimizu 890ddd
	QStringList list = name.split("#");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (list.size() >= 2 && list.at(1) != "frames") {
Toshihiro Shimizu 890ddd
		bool hasLayerId;
Toshihiro Shimizu 890ddd
		int layid = list.at(1).toInt(&hasLayerId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (hasLayerId) {
Toshihiro Shimizu 890ddd
			// An explicit photoshop layer id must be converted to the associated level name
Toshihiro Shimizu 890ddd
			TPSDParser psdparser(xshLevel->getScene()->decodeFilePath(retfp));
Toshihiro Shimizu 890ddd
			std::string levelName = psdparser.getLevelNameWithCounter(layid); // o_o  what about UNICODE names??
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			list[1] = QString::fromStdString(levelName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::wstring wLevelName = list.join("#").toStdWString();
Toshihiro Shimizu 890ddd
			retfp = retfp.withName(wLevelName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TLevelSet *levelSet = xshLevel->getScene()->getLevelSet();
Toshihiro Shimizu 890ddd
			if (levelSet && levelSet->hasLevel(wLevelName)) // levelSet should be asserted instead
Toshihiro Shimizu 890ddd
				levelSet->renameLevel(xshLevel, wLevelName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			xshLevel->setName(wLevelName);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return retfp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Nota: load() NON fa clearFrames(). si limita ad aggiungere le informazioni
Toshihiro Shimizu 890ddd
// relative ai frames su disco
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::load()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	getProperties()->setCreator("");
Toshihiro Shimizu 890ddd
	QString creator;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(getScene());
Toshihiro Shimizu 890ddd
	if (!getScene())
Toshihiro Shimizu 890ddd
		return;
shun_iwasawa 2ca36a
	
Toshihiro Shimizu 890ddd
	m_isSubsequence = loadingLevelRange.isEnabled();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath checkpath = getScene()->decodeFilePath(m_path);
Shinya Kitaoka 3bfa54
	std::string type = checkpath.getType();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_scannedPath != TFilePath()) {
Toshihiro Shimizu 890ddd
		getProperties()->setDirtyFlag(false); // Level is now supposedly loaded from disk
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static const int ScannedCleanuppedMask = Scanned | Cleanupped;
Toshihiro Shimizu 890ddd
		TFilePath path = getScene()->decodeFilePath(m_scannedPath);
Toshihiro Shimizu 890ddd
		if (TSystem::doesExistFileOrLevel(path)) {
Toshihiro Shimizu 890ddd
			TLevelReaderP lr(path);
Toshihiro Shimizu 890ddd
			assert(lr);
Toshihiro Shimizu 890ddd
			TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
			if (!checkCreatorString(creator = lr->getCreator()))
Toshihiro Shimizu 890ddd
				getProperties()->setIsForbidden(true);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				for (TLevel::Iterator it = level->begin(); it != level->end(); it++) {
Toshihiro Shimizu 890ddd
					TFrameId fid = it->first;
Toshihiro Shimizu 890ddd
					if (!loadingLevelRange.match(fid))
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
					setFrameStatus(fid, (getFrameStatus(fid) & ~ScannedCleanuppedMask) | Scanned);
Toshihiro Shimizu 890ddd
					setFrame(fid, TImageP());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		path = getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
		if (TSystem::doesExistFileOrLevel(path)) {
Toshihiro Shimizu 890ddd
			TLevelReaderP lr(path);
Toshihiro Shimizu 890ddd
			assert(lr);
Toshihiro Shimizu 890ddd
			TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
			if (getType() & FULLCOLOR_TYPE)
Toshihiro Shimizu 890ddd
				setPalette(FullColorPalette::instance()->getPalette(getScene()));
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				setPalette(level->getPalette());
Toshihiro Shimizu 890ddd
			if (!checkCreatorString(creator = lr->getCreator()))
Toshihiro Shimizu 890ddd
				getProperties()->setIsForbidden(true);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				for (TLevel::Iterator it = level->begin(); it != level->end(); it++) {
Toshihiro Shimizu 890ddd
					TFrameId fid = it->first;
Toshihiro Shimizu 890ddd
					if (!loadingLevelRange.match(fid))
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
					setFrameStatus(fid, getFrameStatus(fid) | Cleanupped);
Toshihiro Shimizu 890ddd
					setFrame(fid, TImageP());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			setContentHistory(lr->getContentHistory() ? lr->getContentHistory()->clone() : 0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// Not a scan + cleanup level
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_path.getType() == "psd" && this->getScene()->getVersionNumber().first < 71)
Toshihiro Shimizu 890ddd
			m_path = getLevelPathAndSetNameWithPsdLevelName(this);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFilePath path = getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		getProperties()->setDirtyFlag(false); // Level is now supposedly loaded from disk
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TLevelReaderP lr(path); // May throw
Toshihiro Shimizu 890ddd
		assert(lr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
		if (level->getFrameCount() > 0) {
Toshihiro Shimizu 890ddd
			const TImageInfo *info = lr->getImageInfo(level->begin()->first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (info && info->m_samplePerPixel >= 5) {
Toshihiro Shimizu 890ddd
				QString msg = QString("Failed to open %1.\nSamples per pixel is more than 4. It may containt more than one alpha channel.").arg(QString::fromStdWString(m_path.getWideString()));
Toshihiro Shimizu 890ddd
				QMessageBox::warning(0, "Image format not supported", msg);
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (info)
Toshihiro Shimizu 890ddd
				set16BitChannelLevel(info->m_bitsPerSample == 16);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if ((getType() & FULLCOLOR_TYPE) && !is16BitChannelLevel())
Toshihiro Shimizu 890ddd
			setPalette(FullColorPalette::instance()->getPalette(getScene()));
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			setPalette(level->getPalette());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!checkCreatorString(creator = lr->getCreator()))
Toshihiro Shimizu 890ddd
			getProperties()->setIsForbidden(true);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			for (TLevel::Iterator it = level->begin(); it != level->end(); it++) {
Toshihiro Shimizu 890ddd
				m_renumberTable[it->first] = it->first; //Voglio che la tabella contenga anche i frame che non vengono caricati
Toshihiro Shimizu 890ddd
				if (!loadingLevelRange.match(it->first))
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				setFrame(it->first, TImageP());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		setContentHistory(lr->getContentHistory() ? lr->getContentHistory()->clone() : 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	getProperties()->setCreator(creator.toStdString());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	loadingLevelRange.reset();
Toshihiro Shimizu 890ddd
	if (getType() != PLI_XSHLEVEL) {
Toshihiro Shimizu 890ddd
		if (m_properties->getImageDpi() == TPointD() && !m_frames.empty()) {
Toshihiro Shimizu 890ddd
			TDimension imageRes(0, 0);
Toshihiro Shimizu 890ddd
			TPointD imageDpi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const TFrameId &firstFid = getFirstFid();
Shinya Kitaoka 3bfa54
			std::string imageId = getImageId(firstFid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const TImageInfo *imageInfo = ImageManager::instance()->getInfo(imageId, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
			if (imageInfo) {
Toshihiro Shimizu 890ddd
				imageRes.lx = imageInfo->m_lx;
Toshihiro Shimizu 890ddd
				imageRes.ly = imageInfo->m_ly;
Toshihiro Shimizu 890ddd
				imageDpi.x = imageInfo->m_dpix;
Toshihiro Shimizu 890ddd
				imageDpi.y = imageInfo->m_dpiy;
Toshihiro Shimizu 890ddd
				m_properties->setImageDpi(imageDpi);
Toshihiro Shimizu 890ddd
				m_properties->setImageRes(imageRes);
Toshihiro Shimizu 890ddd
				m_properties->setBpp(imageInfo->m_bitsPerSample * imageInfo->m_samplePerPixel);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		setRenumberTable();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getPalette() && StudioPalette::isEnabled())
Toshihiro Shimizu 890ddd
		StudioPalette::instance()->updateLinkedColors(getPalette());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath refImgName;
Toshihiro Shimizu 890ddd
	if (m_palette) {
Toshihiro Shimizu 890ddd
		refImgName = m_palette->getRefImgPath();
Toshihiro Shimizu 890ddd
		TFilePath refImgPath = refImgName;
Toshihiro Shimizu 890ddd
		if (refImgName != TFilePath() &&
Toshihiro Shimizu 890ddd
			TFileStatus(refImgPath).doesExist()) {
Toshihiro Shimizu 890ddd
			TLevelReaderP lr(refImgPath);
Toshihiro Shimizu 890ddd
			if (lr) {
Toshihiro Shimizu 890ddd
				TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
				if (level->getFrameCount() > 0) {
Toshihiro Shimizu 890ddd
					TImageP img = lr->getFrameReader(level->begin()->first)->load();
Toshihiro Shimizu 890ddd
					if (img && getPalette()) {
Toshihiro Shimizu 890ddd
						img->setPalette(0);
Toshihiro Shimizu 890ddd
						getPalette()->setRefImg(img);
Toshihiro Shimizu 890ddd
						std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
						for (TLevel::Iterator it = level->begin(); it != level->end(); ++it)
Toshihiro Shimizu 890ddd
							fids.push_back(it->first);
Toshihiro Shimizu 890ddd
						getPalette()->setRefLevelFids(fids);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Load hooks
Toshihiro Shimizu 890ddd
	HookSet *hookSet = getHookSet();
Toshihiro Shimizu 890ddd
	hookSet->clearHooks();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TFilePath &hookFile = TXshSimpleLevel::getExistingHookFile(
Toshihiro Shimizu 890ddd
		getScene()->decodeFilePath(m_path));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!hookFile.isEmpty()) {
Toshihiro Shimizu 890ddd
		TIStream is(hookFile);
Shinya Kitaoka 3bfa54
		std::string tagName;
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			if (is.matchTag(tagName) && tagName == "hooks")
Toshihiro Shimizu 890ddd
				hookSet->loadData(is);
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	updateReadOnly();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::load(const std::vector<tframeid> &fIds)</tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	getProperties()->setCreator("");
Toshihiro Shimizu 890ddd
	QString creator;
Toshihiro Shimizu 890ddd
	assert(getScene());
Toshihiro Shimizu 890ddd
	getProperties()->setDirtyFlag(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_isSubsequence = loadingLevelRange.isEnabled();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// non e' un livello scan+cleanup
Toshihiro Shimizu 890ddd
	TFilePath path = getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TLevelReaderP lr(path);
Toshihiro Shimizu 890ddd
	assert(lr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!checkCreatorString(creator = lr->getCreator()))
Toshihiro Shimizu 890ddd
		getProperties()->setIsForbidden(true);
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		if (fIds.size() != 0) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < (int)fIds.size(); i++) {
Toshihiro Shimizu 890ddd
				m_renumberTable[fIds[i]] = fIds[i];
Toshihiro Shimizu 890ddd
				if (!loadingLevelRange.match(fIds[i]))
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				setFrame(fIds[i], TImageP());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
			for (TLevel::Iterator it = level->begin(); it != level->end(); it++) {
Toshihiro Shimizu 890ddd
				m_renumberTable[it->first] = it->first;
Toshihiro Shimizu 890ddd
				if (!loadingLevelRange.match(it->first))
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				setFrame(it->first, TImageP());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	setContentHistory(lr->getContentHistory() ? lr->getContentHistory()->clone() : 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	getProperties()->setCreator(creator.toStdString());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	loadingLevelRange.reset();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getType() != PLI_XSHLEVEL) {
Toshihiro Shimizu 890ddd
		if (m_properties->getImageDpi() == TPointD() && !m_frames.empty()) {
Toshihiro Shimizu 890ddd
			TDimension imageRes(0, 0);
Toshihiro Shimizu 890ddd
			TPointD imageDpi;
Shinya Kitaoka 3bfa54
			std::string imageId = getImageId(getFirstFid());
Toshihiro Shimizu 890ddd
			const TImageInfo *imageInfo = ImageManager::instance()->getInfo(imageId, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
			if (imageInfo) {
Toshihiro Shimizu 890ddd
				imageRes.lx = imageInfo->m_lx;
Toshihiro Shimizu 890ddd
				imageRes.ly = imageInfo->m_ly;
Toshihiro Shimizu 890ddd
				imageDpi.x = imageInfo->m_dpix;
Toshihiro Shimizu 890ddd
				imageDpi.y = imageInfo->m_dpiy;
Toshihiro Shimizu 890ddd
				m_properties->setImageDpi(imageDpi);
Toshihiro Shimizu 890ddd
				m_properties->setImageRes(imageRes);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		setRenumberTable();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::updateReadOnly()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath path = getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
	m_isReadOnly = isAreadOnlyLevel(path);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::saveData(TOStream &os)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	os << m_name;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::map<std::string, std::string=""> attr;</std::string,>
Toshihiro Shimizu 890ddd
	if (getProperties()->getDpiPolicy() == LevelProperties::DP_CustomDpi) {
Toshihiro Shimizu 890ddd
		TPointD dpi = getProperties()->getDpi();
Toshihiro Shimizu 890ddd
		if (dpi.x != 0 && dpi.y != 0) {
Toshihiro Shimizu 890ddd
			attr["dpix"] = toString(dpi.x);
Toshihiro Shimizu 890ddd
			attr["dpiy"] = toString(dpi.y);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		attr["dpiType"] = "image";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getProperties()->getSubsampling() != 1) {
Toshihiro Shimizu 890ddd
		attr["subsampling"] = toString(getProperties()->getSubsampling());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (getProperties()->antialiasSoftness() > 0) {
Toshihiro Shimizu 890ddd
		attr["antialias"] = toString(getProperties()->antialiasSoftness());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (getProperties()->doPremultiply()) {
Toshihiro Shimizu 890ddd
		attr["premultiply"] = toString(getProperties()->doPremultiply());
Toshihiro Shimizu 890ddd
	} else if (getProperties()->whiteTransp()) {
Toshihiro Shimizu 890ddd
		attr["whiteTransp"] = toString(getProperties()->whiteTransp());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_type == TZI_XSHLEVEL)
Toshihiro Shimizu 890ddd
		attr["type"] = "s";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os.openCloseChild("info", attr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os.child("path") << m_path; // fp;
Toshihiro Shimizu 890ddd
	if (m_scannedPath != TFilePath())
Toshihiro Shimizu 890ddd
		os.child("scannedPath") << m_scannedPath; // fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::save()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(getScene());
Toshihiro Shimizu 890ddd
	TFilePath path = getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
	TSystem::outputDebug("save() : " + toString(m_path) + " = " + toString(path) + "\n");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getProperties()->getDirtyFlag() == false &&
Toshihiro Shimizu 890ddd
		getPalette()->getDirtyFlag() == false &&
Toshihiro Shimizu 890ddd
		TSystem::doesExistFileOrLevel(path))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!TFileStatus(path.getParentDir()).doesExist()) {
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			TSystem::mkDir(path.getParentDir());
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	save(path);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void saveBackup(TFilePath path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		TFilePath backup = path.withName(path.getName() + "_backup");
Toshihiro Shimizu 890ddd
		if (TSystem::doesExistFileOrLevel(backup))
Toshihiro Shimizu 890ddd
			TSystem::removeFileOrLevel_throw(backup);
Toshihiro Shimizu 890ddd
		TSystem::copyFileOrLevel_throw(backup, path);
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::save(const TFilePath &fp, const TFilePath &oldFp, bool overwritePalette)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath dOldPath = (!oldFp.isEmpty()) ? oldFp : getScene()->decodeFilePath(m_path);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath dDstPath = getScene()->decodeFilePath(fp);
Toshihiro Shimizu 890ddd
	TSystem::touchParentDir(dDstPath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// backup
Toshihiro Shimizu 890ddd
	if (Preferences::instance()->isLevelsBackupEnabled() &&
Toshihiro Shimizu 890ddd
		dOldPath == dDstPath &&
Toshihiro Shimizu 890ddd
		TSystem::doesExistFileOrLevel(dDstPath))
Toshihiro Shimizu 890ddd
		saveBackup(dDstPath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAreadOnlyLevel(dDstPath)) {
Toshihiro Shimizu 890ddd
		if (m_editableRange.empty() && !m_temporaryHookMerged) //file interaly locked
Toshihiro Shimizu 890ddd
			throw TSystemException(dDstPath, "The level cannot be saved: it is a read only level.");
Toshihiro Shimizu 890ddd
		else if (getType() != OVL_XSHLEVEL) {
Toshihiro Shimizu 890ddd
			//file partially unlocked
Shinya Kitaoka 3bfa54
			std::wstring fileName = getEditableFileName();
Toshihiro Shimizu 890ddd
			assert(!fileName.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFilePath app = dDstPath.withName(fileName).withType(dDstPath.getType());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//removes old files
Toshihiro Shimizu 890ddd
			if (TSystem::doesExistFileOrLevel(app))
Toshihiro Shimizu 890ddd
				TSystem::removeFileOrLevel(app);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFilePathSet oldFilePaths;
Toshihiro Shimizu 890ddd
			getFiles(app, oldFilePaths);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFilePathSet::iterator it;
Toshihiro Shimizu 890ddd
			for (it = oldFilePaths.begin(); it != oldFilePaths.end(); ++it) {
Toshihiro Shimizu 890ddd
				if (TSystem::doesExistFileOrLevel(*it))
Toshihiro Shimizu 890ddd
					TSystem::removeFileOrLevel(*it);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// save new files
Toshihiro Shimizu 890ddd
			TXshSimpleLevel *sl = new TXshSimpleLevel;
Toshihiro Shimizu 890ddd
			sl->setScene(getScene());
Toshihiro Shimizu 890ddd
			sl->setPalette(getPalette());
Toshihiro Shimizu 890ddd
			sl->setPath(getScene()->codeFilePath(app));
Toshihiro Shimizu 890ddd
			sl->setType(getType());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 2148c8
			std::set<tframeid>::iterator eft, efEnd;</tframeid>
Toshihiro Shimizu 890ddd
			for (eft = m_editableRange.begin(); eft != efEnd; ++eft) {
Toshihiro Shimizu 890ddd
				const TFrameId &fid = *eft;
Toshihiro Shimizu 890ddd
				sl->setFrame(fid, getFrame(fid, false));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Copy hooks
Toshihiro Shimizu 890ddd
			HookSet *hookSet = sl->getHookSet();
Toshihiro Shimizu 890ddd
			*hookSet = *getHookSet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			FramesSet::iterator ft, fEnd = m_frames.end();
Toshihiro Shimizu 890ddd
			for (ft = m_frames.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
				const TFrameId &fid = *ft;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (m_editableRange.find(fid) == m_editableRange.end())
Toshihiro Shimizu 890ddd
					hookSet->eraseFrame(fid);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Copy mesh level
Toshihiro Shimizu 890ddd
			sl->save(app);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//hides files
Toshihiro Shimizu 890ddd
			oldFilePaths.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (TSystem::doesExistFileOrLevel(app))
Toshihiro Shimizu 890ddd
				TSystem::hideFileOrLevel(app);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			getFiles(app, oldFilePaths);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (it = oldFilePaths.begin(); it != oldFilePaths.end(); ++it) {
Toshihiro Shimizu 890ddd
				if (TSystem::doesExistFileOrLevel(*it))
Toshihiro Shimizu 890ddd
					TSystem::hideFileOrLevel(*it);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dOldPath != dDstPath && m_path != TFilePath()) {
Toshihiro Shimizu 890ddd
		const TFilePath &dSrcPath = dOldPath;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			if (TSystem::doesExistFileOrLevel(dSrcPath)) {
Toshihiro Shimizu 890ddd
				if (TSystem::doesExistFileOrLevel(dDstPath))
Toshihiro Shimizu 890ddd
					TSystem::removeFileOrLevel(dDstPath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				copyFiles(dDstPath, dSrcPath);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//when saving the level palette with global name
Toshihiro Shimizu 890ddd
	if (overwritePalette && getType() == TZP_XSHLEVEL && getPalette() && getPalette()->getGlobalName() != L"") {
Toshihiro Shimizu 890ddd
		overwritePalette = false;
Toshihiro Shimizu 890ddd
		TFilePath palettePath = dDstPath.withNoFrame().withType("tpl");
Toshihiro Shimizu 890ddd
		StudioPalette::instance()->save(palettePath, getPalette());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	saveSimpleLevel(dDstPath, overwritePalette);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::saveSimpleLevel(const TFilePath &decodedFp, bool overwritePalette)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* Precondition: Destination level with path decodedFp is supposed to already
Toshihiro Shimizu 890ddd
                   store those image frames not tagged as 'modified' in this level
Toshihiro Shimizu 890ddd
                   instance.                                                          */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath oldPath = m_path;
Toshihiro Shimizu 890ddd
	TFilePath dOldPath = getScene()->decodeFilePath(oldPath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Substitute m_path with decodedFp until the function quits.
Toshihiro Shimizu 890ddd
	struct CopyOnExit {
Toshihiro Shimizu 890ddd
		TFilePath &m_dstPath, &m_srcPath;
Toshihiro Shimizu 890ddd
		~CopyOnExit() { m_dstPath = m_srcPath; }
Toshihiro Shimizu 890ddd
	} copyOnExit = {m_path = decodedFp, oldPath}; // m_path substituted here until function quits
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool savingOriginal = (decodedFp == dOldPath),
Toshihiro Shimizu 890ddd
		 paletteNotSaved = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int imFlags = savingOriginal ? ImageManager::dontPutInCache | ImageManager::toBeSaved : ImageManager::dontPutInCache;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
	getFids(fids);
Toshihiro Shimizu 890ddd
	std::vector<tframeid>::iterator it;</tframeid>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isLevelModified = getProperties()->getDirtyFlag();
Toshihiro Shimizu 890ddd
	bool isPaletteModified = false;
Toshihiro Shimizu 890ddd
	if (getPalette())
Toshihiro Shimizu 890ddd
		isPaletteModified = getPalette()->getDirtyFlag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isLevelModified || isPaletteModified) {
Toshihiro Shimizu 890ddd
		// gmt (8/8/08. provo a risolvere il pasticcio della scrittura dei tlv. Dobbiamo
Toshihiro Shimizu 890ddd
		// ripensarci con piu' calma. Per ora cerco di fare meno danno possibile).
Toshihiro Shimizu 890ddd
		TDimension oldRes(0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TSystem::doesExistFileOrLevel(decodedFp)) {
Toshihiro Shimizu 890ddd
			TLevelReaderP lr(decodedFp);
Toshihiro Shimizu 890ddd
			const TImageInfo *imageInfo = m_frames.empty() ? lr->getImageInfo() : lr->getImageInfo(*(m_frames.begin()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (imageInfo) {
Toshihiro Shimizu 890ddd
				oldRes.lx = imageInfo->m_lx;
Toshihiro Shimizu 890ddd
				oldRes.ly = imageInfo->m_ly;
Toshihiro Shimizu 890ddd
				lr = TLevelReaderP();
Toshihiro Shimizu 890ddd
				if (getProperties()->getImageRes() != oldRes) {
Toshihiro Shimizu 890ddd
					//Il comando canvas size cambia le dimensioni del livello!!!
Toshihiro Shimizu 890ddd
					//Se il file già esiste, nel level writer vengono risettate le dimesnioni del file esistente
Toshihiro Shimizu 890ddd
					//e salva male
Toshihiro Shimizu 890ddd
					TSystem::removeFileOrLevel(decodedFp);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// overwrite tlv
Toshihiro Shimizu 890ddd
		if (decodedFp.getType() == "tlv" && TSystem::doesExistFileOrLevel(decodedFp)) {
Toshihiro Shimizu 890ddd
			if (isLevelModified) {
Toshihiro Shimizu 890ddd
				// in questo caso dovrei scrivere solo i frame modificati.
Toshihiro Shimizu 890ddd
				// certamente NON DEVO scrivere quelli che non ho (e che dovrei
Toshihiro Shimizu 890ddd
				// rileggere dallo stesso file che sto scrivendo
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int oldSubs = getProperties()->getSubsampling();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TLevelWriterP lw;
Toshihiro Shimizu 890ddd
				try {
Toshihiro Shimizu 890ddd
					lw = TLevelWriterP(decodedFp);
Toshihiro Shimizu 890ddd
				} catch (...) {
Toshihiro Shimizu 890ddd
					//revert subsampling
Toshihiro Shimizu 890ddd
					m_properties->setSubsampling(oldSubs);
Toshihiro Shimizu 890ddd
					m_path = oldPath;
Toshihiro Shimizu 890ddd
					throw TSystemException(decodedFp, "can't fopen.\nSomeone may be saving the same file. Please wait a while and retry.");
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				lw->setOverwritePaletteFlag(overwritePalette);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				lw->setCreator(getCreatorString());
Toshihiro Shimizu 890ddd
				lw->setPalette(getPalette());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Filter out of the renumber table all non-tlv frames (could happen if the level
Toshihiro Shimizu 890ddd
				// is a scan-cleanup mix). This is fine even on the temporarily substituted m_path.
Toshihiro Shimizu 890ddd
				std::map<tframeid, tframeid=""> renumberTable;</tframeid,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				std::map<tframeid, tframeid="">::reverse_iterator mapIt = m_renumberTable.rbegin();</tframeid,>
Toshihiro Shimizu 890ddd
				for (mapIt; mapIt != m_renumberTable.rend(); ++mapIt) {
Toshihiro Shimizu 890ddd
					TFrameId id = mapIt->first;
Toshihiro Shimizu 890ddd
					if (getFrameStatus(id) != Scanned && getFrameStatus(id) != CleanupPreview)
Toshihiro Shimizu 890ddd
						renumberTable[id] = mapIt->second;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_renumberTable.clear();
Toshihiro Shimizu 890ddd
				m_renumberTable = renumberTable;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				lw->setIconSize(Preferences::instance()->getIconSize());
Toshihiro Shimizu 890ddd
				if (!isSubsequence())
Toshihiro Shimizu 890ddd
					lw->renumberFids(m_renumberTable);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (getContentHistory())
Toshihiro Shimizu 890ddd
					lw->setContentHistory(getContentHistory()->clone());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				ImageLoader::BuildExtData extData(this, TFrameId());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (it = fids.begin(); it != fids.end(); ++it) {
Shinya Kitaoka 3bfa54
					std::string imageId = getImageId(*it, Normal); // Retrieve the actual level frames ("L_whatever")
Toshihiro Shimizu 890ddd
					if (!ImageManager::instance()->isModified(imageId))
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					extData.m_fid = *it;
Toshihiro Shimizu 890ddd
					TImageP img = ImageManager::instance()->getImage(imageId, imFlags, &extData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					assert(img);
Toshihiro Shimizu 890ddd
					if (!img)
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					int subs = 1;
Toshihiro Shimizu 890ddd
					if (TToonzImageP ti = img)
Toshihiro Shimizu 890ddd
						subs = ti->getSubsampling();
Toshihiro Shimizu 890ddd
					else if (TRasterImageP ri = img)
Toshihiro Shimizu 890ddd
						subs = ri->getSubsampling();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					assert(subs == 1);
Toshihiro Shimizu 890ddd
					if (subs != 1)
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (TToonzImageP ti = img) {
Toshihiro Shimizu 890ddd
						/*- SaveBoxを塗り漏れ防止に使用している場合、実際の画像範囲とSaveBoxのサイズが異なるため、ここで更新しておく-*/
Toshihiro Shimizu 890ddd
						TRect saveBox;
Toshihiro Shimizu 890ddd
						TRop::computeBBox(ti->getRaster(), saveBox);
Toshihiro Shimizu 890ddd
						ti->setSavebox(saveBox);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					lw->getFrameWriter(*it)->save(img);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				lw = TLevelWriterP(); // TLevelWriterP's destructor saves the palette
Toshihiro Shimizu 890ddd
			} else if (isPaletteModified && overwritePalette) {
Toshihiro Shimizu 890ddd
				TFilePath palettePath = decodedFp.withNoFrame().withType("tpl");
Toshihiro Shimizu 890ddd
				if (Preferences::instance()->isLevelsBackupEnabled() && TSystem::doesExistFileOrLevel(palettePath))
Toshihiro Shimizu 890ddd
					saveBackup(palettePath);
Toshihiro Shimizu 890ddd
				TOStream os(palettePath);
Toshihiro Shimizu 890ddd
				if (os.checkStatus())
Toshihiro Shimizu 890ddd
					os << getPalette();
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					paletteNotSaved = true;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			// per ora faccio quello che facevo prima, ma dobbiamo rivedere tutta la strategia
Toshihiro Shimizu 890ddd
			LevelUpdater updater(this);
Toshihiro Shimizu 890ddd
			updater.getLevelWriter()->setCreator(getCreatorString());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (isLevelModified) {
Toshihiro Shimizu 890ddd
				// Apply the level's renumber table, before saving other files.
Toshihiro Shimizu 890ddd
				// NOTE: This is currently NOT under LevelUpdater's responsibility, as renumber tables
Toshihiro Shimizu 890ddd
				// are set/manipulated heavily here. The approach should be re-designed, though...
Toshihiro Shimizu 890ddd
				updater.getLevelWriter()->renumberFids(m_renumberTable);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (!m_editableRange.empty())
Shinya Kitaoka 3bfa54
					fids = std::vector<tframeid>(m_editableRange.begin(), m_editableRange.end());</tframeid>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				ImageLoader::BuildExtData extData(this, TFrameId());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (it = fids.begin(); it != fids.end(); ++it) {
Shinya Kitaoka 3bfa54
					std::string imageId = getImageId(*it, Normal); // Retrieve the actual level frames ("L_whatever")
Toshihiro Shimizu 890ddd
					if (!ImageManager::instance()->isModified(imageId))
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					extData.m_fid = *it;
Toshihiro Shimizu 890ddd
					TImageP img = ImageManager::instance()->getImage(imageId, imFlags, &extData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					assert(img);
Toshihiro Shimizu 890ddd
					if (!img)
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					int subs = 1;
Toshihiro Shimizu 890ddd
					if (TToonzImageP ti = img)
Toshihiro Shimizu 890ddd
						subs = ti->getSubsampling();
Toshihiro Shimizu 890ddd
					else if (TRasterImageP ri = img)
Toshihiro Shimizu 890ddd
						subs = ri->getSubsampling();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					assert(subs == 1);
Toshihiro Shimizu 890ddd
					if (subs != 1)
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					updater.update(*it, img);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			updater.close(); //Needs the original level subs
Toshihiro Shimizu 890ddd
			if ((getType() & FULLCOLOR_TYPE) && isPaletteModified)
Toshihiro Shimizu 890ddd
				FullColorPalette::instance()->savePalette(getScene());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Save hooks
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath hookFile;
Toshihiro Shimizu 890ddd
	HookSet *hookSet = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Save the hookSet in a temporary hook file
Toshihiro Shimizu 890ddd
	if (getType() == OVL_XSHLEVEL && !m_editableRange.empty()) {
Toshihiro Shimizu 890ddd
		hookSet = new HookSet(*getHookSet());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FramesSet::const_iterator it;
Toshihiro Shimizu 890ddd
		for (it = m_frames.begin(); it != m_frames.end(); ++it) {
Toshihiro Shimizu 890ddd
			TFrameId fid = *it;
Toshihiro Shimizu 890ddd
			if (m_editableRange.find(fid) == m_editableRange.end())
Toshihiro Shimizu 890ddd
				hookSet->eraseFrame(fid);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//file partially unlocked
Shinya Kitaoka 3bfa54
		std::wstring fileName = getEditableFileName();
Toshihiro Shimizu 890ddd
		assert(!fileName.empty());
Toshihiro Shimizu 890ddd
		TFilePath app = decodedFp.withName(fileName).withType(decodedFp.getType());
Toshihiro Shimizu 890ddd
		hookFile = getHookPath(app);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		hookFile = getHookPath(decodedFp);
Toshihiro Shimizu 890ddd
		hookSet = getHookSet();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	// Remove the hidden attribute (since TOStream's fopen fails on hidden files)
Toshihiro Shimizu 890ddd
	if (getType() == OVL_XSHLEVEL && !m_editableRange.empty())
Toshihiro Shimizu 890ddd
		SetFileAttributesW(hookFile.getWideString().c_str(), FILE_ATTRIBUTE_NORMAL);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (hookSet && hookSet->getHookCount() > 0) {
Toshihiro Shimizu 890ddd
		TOStream os(hookFile);
Toshihiro Shimizu 890ddd
		os.openChild("hooks");
Toshihiro Shimizu 890ddd
		hookSet->saveData(os);
Toshihiro Shimizu 890ddd
		os.closeChild();
Toshihiro Shimizu 890ddd
	} else if (TFileStatus(hookFile).doesExist()) {
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			TSystem::deleteFile(hookFile);
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	if (getType() == OVL_XSHLEVEL && !m_editableRange.empty())
Toshihiro Shimizu 890ddd
		TSystem::hideFileOrLevel(hookFile);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (savingOriginal) {
Toshihiro Shimizu 890ddd
		setRenumberTable(); // Since the renumber table refers to the
Toshihiro Shimizu 890ddd
							// 'original' frames saved on disk
Toshihiro Shimizu 890ddd
		if (m_properties)
Toshihiro Shimizu 890ddd
			m_properties->setDirtyFlag(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (getPalette() && overwritePalette)
Toshihiro Shimizu 890ddd
			getPalette()->setDirtyFlag(false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (paletteNotSaved)
Toshihiro Shimizu 890ddd
		throw TSystemException(m_path, "The palette of the level could not be saved.");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string TXshSimpleLevel::getImageId(const TFrameId &fid, int frameStatus) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (frameStatus < 0)
Toshihiro Shimizu 890ddd
		frameStatus = getFrameStatus(fid);
Shinya Kitaoka 3bfa54
	std::string prefix = "L";
Toshihiro Shimizu 890ddd
	if (frameStatus & CleanupPreview)
Toshihiro Shimizu 890ddd
		prefix = "P";
Toshihiro Shimizu 890ddd
	else if ((frameStatus & (Scanned | Cleanupped)) == Scanned)
Toshihiro Shimizu 890ddd
		prefix = "S";
Shinya Kitaoka 3bfa54
	std::string imageId = m_idBase + "_" + prefix + fid.expand();
Toshihiro Shimizu 890ddd
	return imageId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TXshSimpleLevel::getFrameStatus(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<tframeid, int="">::const_iterator it = m_framesStatus.find(fid);</tframeid,>
Toshihiro Shimizu 890ddd
	return (it != m_framesStatus.end()) ? it->second : Normal;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setFrameStatus(const TFrameId &fid, int status)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert((status & ~(Scanned | Cleanupped | CleanupPreview)) == 0);
Toshihiro Shimizu 890ddd
	m_framesStatus[fid] = status;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*- CleanupPopup::setCurrentLevel / TCleanupper で使用 -*/
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::makeTlv(const TFilePath &tlvPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int ltype = getType();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!(ltype & FULLCOLOR_TYPE)) {
Toshihiro Shimizu 890ddd
		assert(ltype & FULLCOLOR_TYPE);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	setType(TZP_XSHLEVEL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_scannedPath = m_path;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(tlvPath.getType() == "tlv");
Toshihiro Shimizu 890ddd
	m_path = tlvPath;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FramesSet::const_iterator it;
Toshihiro Shimizu 890ddd
	for (it = m_frames.begin(); it != m_frames.end(); ++it) {
Toshihiro Shimizu 890ddd
		TFrameId fid = *it;
Toshihiro Shimizu 890ddd
		setFrameStatus(fid, Scanned);
Toshihiro Shimizu 890ddd
		ImageManager::instance()->rebind(getImageId(fid, Scanned), getImageId(fid, 0));
Toshihiro Shimizu 890ddd
		ImageManager::instance()->rebind(getIconId(fid, Scanned), getIconId(fid, 0));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::invalidateFrames()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FramesSet::iterator ft, fEnd = m_frames.end();
Toshihiro Shimizu 890ddd
	for (ft = m_frames.begin(); ft != fEnd; ++ft)
Toshihiro Shimizu 890ddd
		ImageManager::instance()->invalidate(getImageId(*ft));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*- 指定したFIdのみInvalidateする -*/
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::invalidateFrame(const TFrameId &fid)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 3bfa54
	std::string id = getImageId(fid);
Toshihiro Shimizu 890ddd
	ImageManager::instance()->invalidate(id);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// crea un frame con tipo, dimensioni, dpi, ecc. compatibili con il livello
Toshihiro Shimizu 890ddd
TImageP TXshSimpleLevel::createEmptyFrame()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TImageP result;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (m_type) {
Toshihiro Shimizu 890ddd
	case PLI_XSHLEVEL:
Toshihiro Shimizu 890ddd
		result = new TVectorImage;
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
	case MESH_XSHLEVEL:
Shinya Kitaoka d4642c
		assert(false); // Not implemented yet
Shinya Kitaoka d4642c
		break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
	default: {
Toshihiro Shimizu 890ddd
		// normally the image must have the level->getProperties()->getImageDpi().
Toshihiro Shimizu 890ddd
		// if this value is missing (for some reason - can this happen, ever?) then
Toshihiro Shimizu 890ddd
		// we use the getDpi() (that is the current dpi, e.g. cameraDpi or customDpi).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD dpi = getProperties()->getImageDpi();
Shinya Kitaoka d4642c
		/*--
Toshihiro Shimizu 890ddd
		tgaからtlvにconvertしたものをInsert Pasteしたとき、
Toshihiro Shimizu 890ddd
		ペーストしたフレームにのみDPIが付いてしまうので、この処理は省く
Toshihiro Shimizu 890ddd
		--*/
Toshihiro Shimizu 890ddd
		//if(dpi.x==0.0 || dpi.y==0.0)
Toshihiro Shimizu 890ddd
		//  dpi = getProperties()->getDpi();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TDimension res = getProperties()->getImageRes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_type == TZP_XSHLEVEL) {
Toshihiro Shimizu 890ddd
			TRasterCM32P raster(res);
Toshihiro Shimizu 890ddd
			raster->fill(TPixelCM32());
Toshihiro Shimizu 890ddd
			TToonzImageP ti(raster, TRect());
Toshihiro Shimizu 890ddd
			ti->setDpi(dpi.x, dpi.y);
Toshihiro Shimizu 890ddd
			ti->setSavebox(TRect(0, 0, res.lx - 1, res.ly - 1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			result = ti;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TRaster32P raster(res);
Toshihiro Shimizu 890ddd
			raster->fill(TPixel32(0, 0, 0, 0));
Toshihiro Shimizu 890ddd
			TRasterImageP ri(raster);
Toshihiro Shimizu 890ddd
			ri->setDpi(dpi.x, dpi.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			result = ri;
Toshihiro Shimizu 890ddd
		}
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ritorna la risoluzione dei frames del livello (se il livello non e' vettoriale)
Toshihiro Shimizu 890ddd
TDimension TXshSimpleLevel::getResolution()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isEmpty() || getType() == PLI_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return TDimension();
Toshihiro Shimizu 890ddd
	return m_properties->getImageRes();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ritorna il dpi letto da file
Toshihiro Shimizu 890ddd
TPointD TXshSimpleLevel::getImageDpi(const TFrameId &fid, int frameStatus)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isEmpty() || getType() == PLI_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return TPointD();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TFrameId &theFid = (fid == TFrameId::NO_FRAME || !isFid(fid)) ? getFirstFid() : fid;
Shinya Kitaoka 3bfa54
	const std::string &imageId = getImageId(theFid, frameStatus);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TImageInfo *imageInfo = ImageManager::instance()->getInfo(imageId, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!imageInfo)
Toshihiro Shimizu 890ddd
		return TPointD();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TPointD(imageInfo->m_dpix, imageInfo->m_dpiy);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TXshSimpleLevel::getImageSubsampling(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isEmpty() || getType() == PLI_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	TImageP img = TImageCache::instance()->get(getImageId(fid), false);
Toshihiro Shimizu 890ddd
	if (!img)
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	if (TRasterImageP ri = img)
Toshihiro Shimizu 890ddd
		return ri->getSubsampling();
Toshihiro Shimizu 890ddd
	if (TToonzImageP ti = img)
Toshihiro Shimizu 890ddd
		return ti->getSubsampling();
Toshihiro Shimizu 890ddd
	return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ritorna il dpi corrente del livello
Toshihiro Shimizu 890ddd
TPointD TXshSimpleLevel::getDpi(const TFrameId &fid, int frameStatus)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD dpi;
Toshihiro Shimizu 890ddd
	if (m_properties->getDpiPolicy() == LevelProperties::DP_ImageDpi)
Toshihiro Shimizu 890ddd
		dpi = getImageDpi(fid, frameStatus);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		dpi = m_properties->getDpi();
Toshihiro Shimizu 890ddd
	return dpi;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::renumber(const std::vector<tframeid> &fids)</tframeid>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(fids.size() == m_frames.size());
Toshihiro Shimizu 890ddd
	int n = fids.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	std::vector<tframeid> oldFids;</tframeid>
Toshihiro Shimizu 890ddd
	getFids(oldFids);
Toshihiro Shimizu 890ddd
	std::map<tframeid, tframeid=""> table;</tframeid,>
Toshihiro Shimizu 890ddd
	std::map<tframeid, tframeid=""> newRenumberTable;</tframeid,>
Toshihiro Shimizu 890ddd
	for (std::vector<tframeid>::iterator it = oldFids.begin(); it != oldFids.end(); ++it) {</tframeid>
Toshihiro Shimizu 890ddd
		TFrameId oldFrameId = *it;
Toshihiro Shimizu 890ddd
		TFrameId newFrameId = fids[i++];
Toshihiro Shimizu 890ddd
		table[oldFrameId] = newFrameId;
Toshihiro Shimizu 890ddd
		std::map<tframeid, tframeid="">::iterator mapIt = m_renumberTable.begin();</tframeid,>
Toshihiro Shimizu 890ddd
		for (mapIt; mapIt != m_renumberTable.end(); ++mapIt)
Toshihiro Shimizu 890ddd
			if (mapIt->second == oldFrameId) {
Toshihiro Shimizu 890ddd
				newRenumberTable[mapIt->first] = newFrameId;
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	std::map<tframeid, tframeid="">::iterator newMapIt = newRenumberTable.begin();</tframeid,>
Toshihiro Shimizu 890ddd
	for (newMapIt; newMapIt != newRenumberTable.end(); ++newMapIt)
Toshihiro Shimizu 890ddd
		m_renumberTable[newMapIt->first] = newMapIt->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_frames.clear();
Toshihiro Shimizu 890ddd
	for (i = 0; i < n; ++i) {
Toshihiro Shimizu 890ddd
		TFrameId fid(fids[i]);
Toshihiro Shimizu 890ddd
		assert(m_frames.count(fid) == 0);
Toshihiro Shimizu 890ddd
		m_frames.insert(fid);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageManager *im = ImageManager::instance();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<tframeid, tframeid="">::iterator jt;</tframeid,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i)
Toshihiro Shimizu 890ddd
			im->rebind(getImageId(jt->first), "^" + toString(i));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i)
Toshihiro Shimizu 890ddd
			im->rebind("^" + toString(i), getImageId(jt->second));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getType() == PLI_XSHLEVEL) {
Toshihiro Shimizu 890ddd
		for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i) {
Toshihiro Shimizu 890ddd
			const std::string &id = rasterized(getImageId(jt->first));
Toshihiro Shimizu 890ddd
			if (im->isBound(id))
Toshihiro Shimizu 890ddd
				im->rebind(id, rasterized("^" + toString(i)));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i) {
Toshihiro Shimizu 890ddd
			const std::string &id = rasterized("^" + toString(i));
Toshihiro Shimizu 890ddd
			if (im->isBound(id))
Toshihiro Shimizu 890ddd
				im->rebind(id, rasterized(getImageId(jt->second)));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getType() & FULLCOLOR_TYPE) {
Toshihiro Shimizu 890ddd
		for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i) {
Toshihiro Shimizu 890ddd
			const std::string &id = filled(getImageId(jt->first));
Toshihiro Shimizu 890ddd
			if (im->isBound(id))
Toshihiro Shimizu 890ddd
				im->rebind(id, filled("^" + toString(i)));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i) {
Toshihiro Shimizu 890ddd
			const std::string &id = filled("^" + toString(i));
Toshihiro Shimizu 890ddd
			if (im->isBound(id))
Toshihiro Shimizu 890ddd
				im->rebind(id, filled(getImageId(jt->second)));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_properties->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getHookSet())
Toshihiro Shimizu 890ddd
		getHookSet()->renumber(table);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::copyFiles(const TFilePath &dst, const TFilePath &src)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (dst == src)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TSystem::touchParentDir(dst);
Toshihiro Shimizu 890ddd
	TSystem::copyFileOrLevel_throw(dst, src);
Toshihiro Shimizu 890ddd
	if (dst.getType() == "tlv") {
Toshihiro Shimizu 890ddd
		//Copio la palette del livello
Toshihiro Shimizu 890ddd
		TFilePath srcPltPath = src.getParentDir() + TFilePath(src.getWideName() + L".tpl");
Toshihiro Shimizu 890ddd
		if (TFileStatus(srcPltPath).doesExist())
Toshihiro Shimizu 890ddd
			TSystem::copyFile(dst.getParentDir() + TFilePath(dst.getWideName() + L".tpl"), srcPltPath, true);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (dst.getType() == "tzp" || dst.getType() == "tzu") {
Toshihiro Shimizu 890ddd
		//Copio la palette del livello
Toshihiro Shimizu 890ddd
		TFilePath srcPltPath = src.getParentDir() + TFilePath(src.getWideName() + L".plt");
Toshihiro Shimizu 890ddd
		if (TFileStatus(srcPltPath).doesExist())
Toshihiro Shimizu 890ddd
			TSystem::copyFile(dst.getParentDir() + TFilePath(dst.getWideName() + L".plt"), srcPltPath, true);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TFilePath &srcHookFile = TXshSimpleLevel::getExistingHookFile(src);
Toshihiro Shimizu 890ddd
	if (!srcHookFile.isEmpty()) {
Toshihiro Shimizu 890ddd
		const TFilePath &dstHookFile = getHookPath(dst);
Toshihiro Shimizu 890ddd
		TSystem::copyFile(dstHookFile, srcHookFile, true);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TFilePath files = src.getParentDir() + (src.getName() + "_files");
Toshihiro Shimizu 890ddd
	if (TFileStatus(files).doesExist() && TFileStatus(files).isDirectory())
Toshihiro Shimizu 890ddd
		TSystem::copyDir(dst.getParentDir() + (src.getName() + "_files"), files);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::renameFiles(const TFilePath &dst, const TFilePath &src)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (dst == src)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TSystem::touchParentDir(dst);
Toshihiro Shimizu 890ddd
	if (TSystem::doesExistFileOrLevel(dst))
Toshihiro Shimizu 890ddd
		TXshSimpleLevel::removeFiles(dst);
Toshihiro Shimizu 890ddd
	TSystem::renameFileOrLevel_throw(dst, src);
Toshihiro Shimizu 890ddd
	if (dst.getType() == "tlv")
Toshihiro Shimizu 890ddd
		TSystem::renameFile(dst.withType("tpl"), src.withType("tpl"));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TFilePath &srcHookFile = TXshSimpleLevel::getExistingHookFile(src);
Toshihiro Shimizu 890ddd
	if (!srcHookFile.isEmpty()) {
Toshihiro Shimizu 890ddd
		const TFilePath &dstHookFile = getHookPath(dst);
Toshihiro Shimizu 890ddd
		TSystem::renameFile(dstHookFile, srcHookFile);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath files = src.getParentDir() + (src.getName() + "_files");
Toshihiro Shimizu 890ddd
	if (TFileStatus(files).doesExist() && TFileStatus(files).isDirectory())
Toshihiro Shimizu 890ddd
		TSystem::renameFile(dst.getParentDir() + (dst.getName() + "_files"), files);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::removeFiles(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSystem::moveFileOrLevelToRecycleBin(fp);
Toshihiro Shimizu 890ddd
	if (fp.getType() == "tlv") {
Toshihiro Shimizu 890ddd
		TFilePath tpl = fp.withType("tpl");
Toshihiro Shimizu 890ddd
		if (TFileStatus(tpl).doesExist())
Toshihiro Shimizu 890ddd
			TSystem::moveFileToRecycleBin(tpl);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Delete ALL hook files (ie from every Toonz version)
Toshihiro Shimizu 890ddd
	const QStringList &hookFiles = TXshSimpleLevel::getHookFiles(fp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int f, fCount = hookFiles.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f)
Toshihiro Shimizu 890ddd
		TSystem::moveFileToRecycleBin(TFilePath(hookFiles[f].toStdWString()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath files = fp.getParentDir() + (fp.getName() + "_files");
Toshihiro Shimizu 890ddd
	if (TFileStatus(files).doesExist() && TFileStatus(files).isDirectory())
Toshihiro Shimizu 890ddd
		TSystem::rmDirTree(files);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::getFiles(const TFilePath &fp, TFilePathSet &fpset)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fp.getType() == "tlv") {
Toshihiro Shimizu 890ddd
		TFilePath tpl = fp.withType("tpl");
Toshihiro Shimizu 890ddd
		if (TFileStatus(tpl).doesExist())
Toshihiro Shimizu 890ddd
			fpset.push_back(tpl);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store the hooks file if any (NOTE: there could be more than one hooks
Toshihiro Shimizu 890ddd
	// file. I'm retaining the behavior I've seen, but was this really intended?
Toshihiro Shimizu 890ddd
	// Shouldn't we return ALL the hooks files?)
Toshihiro Shimizu 890ddd
	const TFilePath &hookFile = getExistingHookFile(fp);
Toshihiro Shimizu 890ddd
	if (!hookFile.isEmpty())
Toshihiro Shimizu 890ddd
		fpset.push_back(hookFile);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Needed for TAB Manga & Kids and not used in Toonz
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//TFilePath files = fp.getParentDir() + (fp.getName() + "_files");
Toshihiro Shimizu 890ddd
	//if(TFileStatus(files).doesExist() && TFileStatus(files).isDirectory())
Toshihiro Shimizu 890ddd
	//  TSystem::rmDirTree(files);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setContentHistory(TContentHistory *contentHistory)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (contentHistory != m_contentHistory.get())
Toshihiro Shimizu 890ddd
		m_contentHistory.reset(contentHistory);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TXshSimpleLevel::setCompatibilityMasks(int writeMask, int neededMask, int forbiddenMask)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	compatibility.writeMask = writeMask;
Toshihiro Shimizu 890ddd
	compatibility.neededMask = neededMask;
Toshihiro Shimizu 890ddd
	compatibility.forbiddenMask = forbiddenMask;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath TXshSimpleLevel::getHookPath(const TFilePath &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Translates:  levelName..ext  into  levelName_hooks..ext.xml
Toshihiro Shimizu 890ddd
	//              levelName.ext   into  levelName_hooks.ext.xml
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Observe that retaining the original level extension IS IMPORTANT, as it ensures
Toshihiro Shimizu 890ddd
	// the UNICITY of the association between a level path and its hook path (ie
Toshihiro Shimizu 890ddd
	// levels  test..png  and  test..tif  have separate hook files).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TFilePath(path.withName(path.getName() + "_hooks").getWideString() + L".xml");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QStringList TXshSimpleLevel::getHookFiles(const TFilePath &decodedLevelPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const TFilePath &dirPath = decodedLevelPath.getParentDir();
Toshihiro Shimizu 890ddd
	QDir levelDir(QString::fromStdWString(dirPath.getWideString()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QStringList hookFileFilter(QString::fromStdWString(		// We have to scan for files of the
Toshihiro Shimizu 890ddd
		decodedLevelPath.getWideName() + L"_hooks*.xml"));  // form  levelName_hooks*.xml  to
Toshihiro Shimizu 890ddd
															// retain backward compatibility
Toshihiro Shimizu 890ddd
	return levelDir.entryList(								//
Toshihiro Shimizu 890ddd
		hookFileFilter, QDir::Files | QDir::NoDotAndDotDot, // Observe that we cleverly sort by
Toshihiro Shimizu 890ddd
		QDir::Time);										// mod date :)
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath TXshSimpleLevel::getExistingHookFile(const TFilePath &decodedLevelPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static const int pCount = 3;
Toshihiro Shimizu 890ddd
	static const QRegExp pattern[pCount] = {
Toshihiro Shimizu 890ddd
		// Prioritized in this order
Toshihiro Shimizu 890ddd
		QRegExp(".*\\.\\.?.+\\.xml$"), // whatever.(.)ext.xml
Toshihiro Shimizu 890ddd
		QRegExp(".*\\.xml$"),		   // whatever.xml
Toshihiro Shimizu 890ddd
		QRegExp(".*\\.\\.?xml$")	   // whatever.(.)xml
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static inline int getPattern(const QString &fp)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			for (int p = 0; p != pCount; ++p)
Toshihiro Shimizu 890ddd
				if (pattern[p].exactMatch(fp))
Toshihiro Shimizu 890ddd
					return p;
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}; // locals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const QStringList &hookFiles = getHookFiles(decodedLevelPath);
Toshihiro Shimizu 890ddd
	if (hookFiles.empty())
Toshihiro Shimizu 890ddd
		return TFilePath();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Return the hook file with the most recent (smallest) identified
Toshihiro Shimizu 890ddd
	// regexp pattern
Toshihiro Shimizu 890ddd
	int fPattern, p = pCount, h = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int f, fCount = hookFiles.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		fPattern = locals::getPattern(hookFiles[f]);
Toshihiro Shimizu 890ddd
		if (fPattern < p)
Toshihiro Shimizu 890ddd
			p = fPattern, h = f;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(h >= 0);
Toshihiro Shimizu 890ddd
	return (h < 0) ? TFilePath() : decodedLevelPath.getParentDir() + TFilePath(hookFiles[h].toStdWString());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TXshSimpleLevel::getBBox(const TFrameId &fid) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD bbox;
Toshihiro Shimizu 890ddd
	double dpiX = Stage::inch, dpiY = dpiX;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get the frame bbox in image coordinates
Toshihiro Shimizu 890ddd
	switch (getType()) {
Toshihiro Shimizu 890ddd
	case PLI_XSHLEVEL:
Toshihiro Shimizu 890ddd
	case MESH_XSHLEVEL: {
Toshihiro Shimizu 890ddd
		// Load the image and extract its bbox forcibly
Toshihiro Shimizu 890ddd
		TImageP img = getFrame(fid, false);
Toshihiro Shimizu 890ddd
		if (!img)
Toshihiro Shimizu 890ddd
			return TRectD();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bbox = img->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TMeshImageP mi = img)
Toshihiro Shimizu 890ddd
			mi->getDpi(dpiX, dpiY);
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
	default: {
Toshihiro Shimizu 890ddd
		// Raster case: retrieve the image info from the ImageManager
Toshihiro Shimizu 890ddd
		const std::string &imageId = getImageId(fid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const TImageInfo *info = ImageManager::instance()->getInfo(imageId, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
		if (!info)
Toshihiro Shimizu 890ddd
			return TRectD();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bbox =
Toshihiro Shimizu 890ddd
			TRectD(TPointD(info->m_x0, info->m_y0), TDimensionD(info->m_lx, info->m_ly)) - // Using lx, ly is less ambiguous
Toshihiro Shimizu 890ddd
			0.5 * TPointD(info->m_lx, info->m_ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (info->m_dpix > 0.0 && info->m_dpiy > 0.0)
Toshihiro Shimizu 890ddd
			dpiX = info->m_dpix, dpiY = info->m_dpiy;
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get the frame's dpi and traduce the bbox to inch coordinates
Toshihiro Shimizu 890ddd
	return TScale(1.0 / dpiX, 1.0 / dpiY) * bbox;
Toshihiro Shimizu 890ddd
}