Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// String includes
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Image includes
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Toonz Image cache
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// TTile class
Toshihiro Shimizu 890ddd
#include "ttile.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Trop include
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// File I/O includes
Toshihiro Shimizu 890ddd
//#include "tstream.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Qt classes
Toshihiro Shimizu 890ddd
#include <qregion></qregion>
Toshihiro Shimizu 890ddd
#include <qbytearray></qbytearray>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Resources pool manager
Toshihiro Shimizu 890ddd
#include "tcacheresourcepool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcacheresource.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
//Debug
Toshihiro Shimizu 890ddd
#define DIAGNOSTICS
Toshihiro Shimizu 890ddd
#include "diagnostics.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Debug stuff
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  QString prefix("#resources.txt | RISORSE | ");
Toshihiro Shimizu 890ddd
  QString prefixMem("#memory.txt | ");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  QString traduce(const TRectD& rect)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " "
Shinya Kitaoka 120a6e
               + QString::number(rect.x1) + " " + QString::number(rect.y1) +
Shinya Kitaoka 120a6e
"]";
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  QString traduce(const TRect& rect)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " "
Shinya Kitaoka 120a6e
               + QString::number(rect.x1+1) + " " + QString::number(rect.y1+1) +
Shinya Kitaoka 120a6e
"]";
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  QString traduce(const TTile& tile)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TDimension size(tile.getRaster()->getSize());
Toshihiro Shimizu 890ddd
    TRectD tileRect(tile.m_pos, TDimensionD(size.lx,size.ly));
Toshihiro Shimizu 890ddd
    return traduce(tileRect);
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//====================================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
The TCacheResource class models the idea of sparsely defined tile objects.
Shinya Kitaoka 120a6e
Whereas common TTile instances can be used to represent images bounded on a
Shinya Kitaoka 120a6e
specific
Toshihiro Shimizu 890ddd
rect of the plane, this model does not suit well in case the image object is
Toshihiro Shimizu 890ddd
sparse across the image plane.
Toshihiro Shimizu 890ddd
\n \n
Shinya Kitaoka 120a6e
The TCacheResource internal  representation assumes that the image plane is
Shinya Kitaoka 120a6e
split
Shinya Kitaoka 120a6e
in a fixed-length integer lattice, each cell of which may host an image object
Shinya Kitaoka 120a6e
in
Toshihiro Shimizu 890ddd
case some part of the complex inside the cell has been defined.
Toshihiro Shimizu 890ddd
The plane outside the complex is assumed to be transparent.
Toshihiro Shimizu 890ddd
\n
Toshihiro Shimizu 890ddd
The lattice origin must be specified in the complex's contructor, and all tiles
Shinya Kitaoka 120a6e
uploaded into and downloaded from it must have an integer displacement with
Shinya Kitaoka 120a6e
respect
Shinya Kitaoka 120a6e
to it - in other words, it is required that the complex has a well-defined pixel
Shinya Kitaoka 120a6e
geometry.
Toshihiro Shimizu 890ddd
\n \n
Shinya Kitaoka 120a6e
Specific regions of the complex can be cleared through the apposite clear()
Shinya Kitaoka 120a6e
method.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
\warning
Shinya Kitaoka 120a6e
This class does not ensure thread-safety. Concurrent accesses must be dealt by
Shinya Kitaoka 120a6e
users.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//====================================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  Docs stuff
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn QRegion TCacheResource::getAvailableRegion() const
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Returns the current region currently available in the complex, with respect to
Toshihiro Shimizu 890ddd
the complex's origin.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn int TCacheResource::getRasterType() const
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Returns the type of raster currently present in the tile complex. Only images
Shinya Kitaoka 120a6e
providing a raster representation coherent with the complex's one may be
Shinya Kitaoka 120a6e
exchanged
Toshihiro Shimizu 890ddd
with it.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn void TCacheResource::clear()
Toshihiro Shimizu 890ddd
Clears the whole complex. This is an overloaded method equivalent to
Toshihiro Shimizu 890ddd
clear(getAvailableRegion()), supplied for convience.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//====================================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Preliminaries
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
// Store tile textures of 512 x 512 pixels. Their memory usage ranges around 1-2
Shinya Kitaoka 120a6e
// MB each.
Toshihiro Shimizu 890ddd
const int latticeStep = 512;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static unsigned long cacheId = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline int getRasterType(const TRasterP &ras) {
Shinya Kitaoka 120a6e
  if ((TRaster32P)ras)
Shinya Kitaoka 120a6e
    return TCacheResource::RGBM32;
Shinya Kitaoka 120a6e
  else if ((TRaster64P)ras)
Shinya Kitaoka 120a6e
    return TCacheResource::RGBM64;
Shinya Kitaoka 120a6e
  else if ((TRasterCM32P)ras)
Shinya Kitaoka 120a6e
    return TCacheResource::CM32;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TCacheResource::NONE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRasterP getRaster(const TImageP &img) {
Shinya Kitaoka 120a6e
  TRasterImageP rimg(img);
Shinya Kitaoka 120a6e
  if (rimg) return rimg->getRaster();
Shinya Kitaoka 120a6e
  TToonzImageP timg(img);
Shinya Kitaoka 120a6e
  if (timg) return timg->getRaster();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(!"Wrong image type!");
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline bool isEmpty(const TRect &rect) {
Shinya Kitaoka 120a6e
  return rect.x0 > rect.x1 || rect.y0 > rect.y1;
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline QRect toQRect(const TRect &r) {
Shinya Kitaoka 120a6e
  return QRect(r.x0, r.y0, r.getLx(), r.getLy());
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
inline TRect toTRect(const QRect &r) {
Shinya Kitaoka 120a6e
  return TRect(r.left(), r.top(), r.right(), r.bottom());
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
inline QPoint toQPoint(const TPoint &p) { return QPoint(p.x, p.y); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRect getTileRect(const TTile &tile) {
Shinya Kitaoka 120a6e
  return TRect(TPoint(tfloor(tile.m_pos.x), tfloor(tile.m_pos.y)),
Shinya Kitaoka 120a6e
               tile.getRaster()->getSize());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Qt's contains actually returns QRegion::intersected... I wonder why...
Shinya Kitaoka 120a6e
inline bool contains(const QRegion ®ion, const TRect &rect) {
Shinya Kitaoka 120a6e
  return QRegion(toQRect(rect)).subtracted(region).isEmpty();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void saveCompressed(const TFilePath &fp, const TRasterP &ras) {
Shinya Kitaoka 120a6e
  assert(ras->getLx() == latticeStep && ras->getLy() == latticeStep);
Shinya Kitaoka 120a6e
  unsigned int size = sq(latticeStep) * ras->getPixelSize();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  QByteArray data = qCompress((const char *)ras->getRawData(), size);
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Tofstream oss(fp);
Shinya Kitaoka 120a6e
  oss.write((const char *)&size, sizeof(unsigned int));
Shinya Kitaoka 120a6e
  oss.write(data.constData(), data.size());
Shinya Kitaoka 120a6e
  assert(!oss.fail());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void loadCompressed(const TFilePath &fp, TRasterP &ras,
Shinya Kitaoka 120a6e
                           TCacheResource::Type rasType) {
Shinya Kitaoka 120a6e
  Tifstream is(fp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (rasType == TCacheResource::CM32)
Shinya Kitaoka 120a6e
    ras = TRasterCM32P(latticeStep, latticeStep);
Shinya Kitaoka 120a6e
  else if (rasType == TCacheResource::RGBM32)
Shinya Kitaoka 120a6e
    ras = TRaster32P(latticeStep, latticeStep);
Shinya Kitaoka 120a6e
  else if (rasType == TCacheResource::RGBM64)
Shinya Kitaoka 120a6e
    ras = TRaster64P(latticeStep, latticeStep);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    assert(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ras->lock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  char *rawData = (char *)ras->getRawData();
Shinya Kitaoka 120a6e
  unsigned int dataSize;
Shinya Kitaoka 120a6e
  is.read((char *)&dataSize, sizeof(unsigned int));
Shinya Kitaoka 120a6e
  is.read(rawData, dataSize);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Observe that QByteArray::fromRawData does NOT cause a deep copy to occur.
Shinya Kitaoka 120a6e
  QByteArray data(QByteArray::fromRawData(rawData, dataSize));
Shinya Kitaoka 120a6e
  data = qUncompress(data);
Shinya Kitaoka 120a6e
  memcpy(rawData, data.constData(), data.size());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    TCacheResourceP implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCacheResourceP::TCacheResourceP(const std::string &imageName,
Shinya Kitaoka 120a6e
                                 bool createIfNone)
Shinya Kitaoka 120a6e
    : m_pointer(TCacheResourcePool::instance()->getResource(imageName,
Shinya Kitaoka 120a6e
                                                            createIfNone)) {
Shinya Kitaoka 120a6e
  if (m_pointer) m_pointer->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCacheResourceP::~TCacheResourceP() {
Shinya Kitaoka 120a6e
  if (m_pointer) {
Shinya Kitaoka 120a6e
    m_pointer->release();
Shinya Kitaoka 120a6e
    m_pointer = 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Member functions implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=====================
Toshihiro Shimizu 890ddd
//    TCacheResource
Toshihiro Shimizu 890ddd
//---------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCacheResource::TCacheResource()
Shinya Kitaoka 120a6e
    : m_id(cacheId++)
Shinya Kitaoka 120a6e
    , m_tileType(NONE)
Shinya Kitaoka 120a6e
    , m_cellsCount(0)
Shinya Kitaoka 120a6e
    , m_locksCount(0)
Shinya Kitaoka 120a6e
    , m_backEnabled(false)
Shinya Kitaoka 120a6e
    , m_invalidated(false) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCacheResource::~TCacheResource() { clear(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::release() {
Shinya Kitaoka 120a6e
  if ((--m_refCount) <= 0) {
Shinya Kitaoka 120a6e
    // Attempt release from the resource pool
Shinya Kitaoka 120a6e
    TCacheResourcePool::instance()->releaseResource(this);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TCacheResource::PointLess TCacheResource::getCellIndex(
Shinya Kitaoka 120a6e
    const TPoint &pos) const {
Shinya Kitaoka 120a6e
  return PointLess(tfloor(pos.x / (double)latticeStep),
Shinya Kitaoka 120a6e
                   tfloor(pos.y / (double)latticeStep));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TPoint TCacheResource::getCellPos(const PointLess &cellIndex) const {
Shinya Kitaoka 120a6e
  return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Returns the lattice cell containing the position pos.
Shinya Kitaoka 120a6e
inline TPoint TCacheResource::getCellPos(const TPoint &pos) const {
Shinya Kitaoka 120a6e
  TPoint cellIndex(tfloor(pos.x / (double)latticeStep),
Shinya Kitaoka 120a6e
                   tfloor(pos.y / (double)latticeStep));
Shinya Kitaoka 120a6e
  return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Returns the lattice cell containing the relative position pos.
Shinya Kitaoka 120a6e
inline TPoint TCacheResource::getCellPos(const TPointD &pos) const {
Shinya Kitaoka 120a6e
  TPoint cellIndex(tfloor(pos.x / (double)latticeStep),
Shinya Kitaoka 120a6e
                   tfloor(pos.y / (double)latticeStep));
Shinya Kitaoka 120a6e
  return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Tough stuff
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::checkRasterType(const TRasterP &ras, int &rasType) const {
Shinya Kitaoka 120a6e
  rasType = ::getRasterType(ras);
Shinya Kitaoka 120a6e
  if (rasType == NONE) {
Shinya Kitaoka 120a6e
    assert(!"The passed raster has unkown type!");
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_tileType != NONE && m_tileType != rasType) {
Shinya Kitaoka 120a6e
    assert(!"The passed raster has not the same type of the cache resource!");
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterP TCacheResource::buildCompatibleRaster(const TDimension &size) {
Shinya Kitaoka 120a6e
  TRasterP result;
Shinya Kitaoka 120a6e
  if (m_tileType == RGBM32)
Shinya Kitaoka 120a6e
    result = TRaster32P(size);
Shinya Kitaoka 120a6e
  else if (m_tileType == RGBM64)
Shinya Kitaoka 120a6e
    result = TRaster64P(size);
Shinya Kitaoka 120a6e
  else if (m_tileType == CM32)
Shinya Kitaoka 120a6e
    result = TRasterCM32P(size);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::checkTile(const TTile &tile) const {
Shinya Kitaoka 120a6e
  // Ensure that tile has integer geoometry.
Shinya Kitaoka 120a6e
  TPointD tileFracPos(tile.m_pos.x - tfloor(tile.m_pos.x),
Shinya Kitaoka 120a6e
                      tile.m_pos.y - tfloor(tile.m_pos.y));
Shinya Kitaoka 120a6e
  if (tileFracPos.x != 0.0 || tileFracPos.y != 0.0) {
Shinya Kitaoka 120a6e
    assert(!"The passed tile must have integer geometry!");
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline std::string TCacheResource::getCellName(int idxX, int idxY) const {
Shinya Kitaoka 120a6e
  return "cell" + std::to_string(idxX) + "," + std::to_string(idxY);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline std::string TCacheResource::getCellCacheId(int idxX, int idxY) const {
Shinya Kitaoka 120a6e
  return "TCacheResource" + std::to_string(m_id) + getCellName(idxX, idxY);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline std::string TCacheResource::getCellCacheId(const TPoint &cellPos) const {
Shinya Kitaoka 120a6e
  return getCellCacheId(tfloor(cellPos.x / (double)latticeStep),
Shinya Kitaoka 120a6e
                        tfloor(cellPos.y / (double)latticeStep));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRasterP TCacheResource::createCellRaster(int rasterType,
Shinya Kitaoka 120a6e
                                                 const std::string &cacheId) {
Shinya Kitaoka 120a6e
  TRasterP result;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (rasterType == TCacheResource::NONE) {
Shinya Kitaoka 120a6e
    assert(!"Unknown raster type!");
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageP img;
Shinya Kitaoka 120a6e
  if (rasterType == TCacheResource::RGBM32) {
Shinya Kitaoka 120a6e
    result = TRaster32P(latticeStep, latticeStep);
Shinya Kitaoka 120a6e
    img    = TRasterImageP(result);
Shinya Kitaoka 120a6e
  } else if (rasterType == TCacheResource::RGBM64) {
Shinya Kitaoka 120a6e
    result = TRaster64P(latticeStep, latticeStep);
Shinya Kitaoka 120a6e
    img    = TRasterImageP(result);
Shinya Kitaoka 120a6e
  } else if (rasterType == TCacheResource::CM32) {
Shinya Kitaoka 120a6e
    result = TRasterCM32P(latticeStep, latticeStep);
Shinya Kitaoka 120a6e
    img    = TToonzImageP(result, result->getBounds());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageCache::instance()->add(cacheId, img);
Shinya Kitaoka 120a6e
  ++m_cellsCount;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_GLOADD("crCellsCnt", 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::canDownloadSome(const TRect &rect) const {
Shinya Kitaoka 120a6e
  return m_region.intersects(toQRect(rect));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::canDownloadAll(const TRect &rect) const {
Shinya Kitaoka 120a6e
  return contains(m_region, rect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::canUpload(const TTile &tile) const {
Shinya Kitaoka 120a6e
  int tileType;
Shinya Kitaoka 120a6e
  return checkTile(tile) && checkRasterType(tile.getRaster(), tileType);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns true if the passed tile is compatible with the complex, and some
Toshihiro Shimizu 890ddd
//! part of it is downloadable.
Shinya Kitaoka 120a6e
bool TCacheResource::canDownloadSome(const TTile &tile) const {
Shinya Kitaoka 120a6e
  return checkTile(tile) && m_region.intersects(toQRect(getTileRect(tile)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns true if the passed tile is compatible, and it can be downloaded
Toshihiro Shimizu 890ddd
//! entirely.
Shinya Kitaoka 120a6e
bool TCacheResource::canDownloadAll(const TTile &tile) const {
Shinya Kitaoka 120a6e
  return checkTile(tile) && contains(m_region, getTileRect(tile));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Copies the passed tile in the tile complex. The passed tile \b must
Toshihiro Shimizu 890ddd
//! possess integer geometry (ie tile.m_pos must have integer coordinates),
Toshihiro Shimizu 890ddd
//! otherwise this function is a no-op.
Shinya Kitaoka 120a6e
bool TCacheResource::upload(const TPoint &pos, TRasterP ras) {
Shinya Kitaoka 120a6e
  int tileType;
Shinya Kitaoka 120a6e
  if (!checkRasterType(ras, tileType)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_tileType == NONE) m_tileType = tileType;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // For all cells of the lattice which intersect the tile, upload the content
Shinya Kitaoka 120a6e
  // in the
Shinya Kitaoka 120a6e
  // complex
Shinya Kitaoka 120a6e
  TRect tileRect(ras->getBounds() + pos);
Shinya Kitaoka 120a6e
  TPoint initialPos(getCellPos(tileRect.getP00()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " |
Shinya Kitaoka 120a6e
  // Stack | ",
Shinya Kitaoka 120a6e
  //"crStack", "upload", ::traduce(TRect(pos, ras->getSize())));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPoint currPos;
Shinya Kitaoka 120a6e
  for (currPos.x = initialPos.x; currPos.x <= tileRect.x1;
Shinya Kitaoka 120a6e
       currPos.x += latticeStep)
Shinya Kitaoka 120a6e
    for (currPos.y = initialPos.y; currPos.y <= tileRect.y1;
Shinya Kitaoka 120a6e
         currPos.y += latticeStep) {
Shinya Kitaoka 120a6e
      // Copy tile's content into the cell's raster.
Shinya Kitaoka 120a6e
      TRect cellRect(currPos, TDimension(latticeStep, latticeStep));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TRect overlapRect(tileRect * cellRect);
Shinya Kitaoka 120a6e
      assert(!overlapRect.isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      PointLess cellIndex(getCellIndex(currPos));
Shinya Kitaoka 120a6e
      std::pair<trasterp, *="" celldata=""> cellInfos(touch(cellIndex));</trasterp,>
Shinya Kitaoka 120a6e
      TRasterP cellRas(cellInfos.first);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TRect temp(overlapRect - currPos);
Shinya Kitaoka 120a6e
      TRasterP overlappingCellRas(cellRas->extract(temp));
Shinya Kitaoka 120a6e
      temp = TRect(overlapRect - tileRect.getP00());
Shinya Kitaoka 120a6e
      TRasterP overlappingTileRas(ras->extract(temp));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      assert(overlappingCellRas->getBounds() ==
Shinya Kitaoka 120a6e
             overlappingTileRas->getBounds());
Shinya Kitaoka 120a6e
      TRop::copy(overlappingCellRas, overlappingTileRas);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      cellInfos.second->m_modified = true;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Update the complex's content region
Shinya Kitaoka 120a6e
  m_region += toQRect(tileRect);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::upload(const TTile &tile) {
Shinya Kitaoka 120a6e
  if (!checkTile(tile)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return upload(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Fills the passed tile with the data contained in the complex, returning
Toshihiro Shimizu 890ddd
//! the copied region.
Toshihiro Shimizu 890ddd
//! The same restriction of the upload() method applies here.
Shinya Kitaoka 120a6e
QRegion TCacheResource::download(const TPoint &pos, TRasterP ras) {
Shinya Kitaoka 120a6e
  int tileType;
Shinya Kitaoka 120a6e
  if (!checkRasterType(ras, tileType)) return QRegion();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build the tile's rect
Shinya Kitaoka 120a6e
  TRect tileRect(ras->getBounds() + pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_region.intersects(toQRect(tileRect))) return QRegion();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // For all cells intersecting the tile's rect, copy all those intersecting the
Shinya Kitaoka 120a6e
  // complex's content region.
Shinya Kitaoka 120a6e
  TPoint initialPos(getCellPos(tileRect.getP00()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPoint currPos;
Shinya Kitaoka 120a6e
  for (currPos.x = initialPos.x; currPos.x <= tileRect.x1;
Shinya Kitaoka 120a6e
       currPos.x += latticeStep)
Shinya Kitaoka 120a6e
    for (currPos.y = initialPos.y; currPos.y <= tileRect.y1;
Shinya Kitaoka 120a6e
         currPos.y += latticeStep) {
Shinya Kitaoka 120a6e
      TRect cellRect(currPos, TDimension(latticeStep, latticeStep));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TRect overlapRect(tileRect * cellRect);
Shinya Kitaoka 120a6e
      assert(!overlapRect.isEmpty());
Shinya Kitaoka 120a6e
      QRect overlapQRect(toQRect(overlapRect));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (m_region.intersects(overlapQRect)) {
Shinya Kitaoka 120a6e
        // Extract the associated rasters and perform the copy to the input
Shinya Kitaoka 120a6e
        // tile.
Shinya Kitaoka 120a6e
        std::pair<trasterp, *="" celldata=""> cellInfos(touch(getCellIndex(currPos)));</trasterp,>
Shinya Kitaoka 120a6e
        TRasterP cellRas(cellInfos.first);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TRect temp(overlapRect - currPos);
Shinya Kitaoka 120a6e
        TRasterP overlappingCellRas(cellRas->extract(temp));
Shinya Kitaoka 120a6e
        temp = TRect(overlapRect - tileRect.getP00());
Shinya Kitaoka 120a6e
        TRasterP overlappingTileRas(ras->extract(temp));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TRop::copy(overlappingTileRas, overlappingCellRas);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_region.intersected(QRegion(toQRect(tileRect)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QRegion TCacheResource::download(TTile &tile) {
Shinya Kitaoka 120a6e
  if (!checkTile(tile)) return QRegion();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return download(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::downloadAll(const TPoint &pos, TRasterP ras) {
Shinya Kitaoka 120a6e
  int tileType;
Shinya Kitaoka 120a6e
  if (!checkRasterType(ras, tileType)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build the tile's rect
Shinya Kitaoka 120a6e
  TRect tileRect(ras->getBounds() + pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!contains(m_region, tileRect)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " |
Shinya Kitaoka 120a6e
  // Stack | ",
Shinya Kitaoka 120a6e
  //"crStack", "downloadAll", ::traduce(TRect(pos, ras->getSize())));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // For all cells intersecting the tile's rect, copy all those intersecting the
Shinya Kitaoka 120a6e
  // complex's content region.
Shinya Kitaoka 120a6e
  TPoint initialPos(getCellPos(tileRect.getP00()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPoint currPos;
Shinya Kitaoka 120a6e
  for (currPos.x = initialPos.x; currPos.x <= tileRect.x1;
Shinya Kitaoka 120a6e
       currPos.x += latticeStep)
Shinya Kitaoka 120a6e
    for (currPos.y = initialPos.y; currPos.y <= tileRect.y1;
Shinya Kitaoka 120a6e
         currPos.y += latticeStep) {
Shinya Kitaoka 120a6e
      TRect cellRect(currPos, TDimension(latticeStep, latticeStep));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TRect overlapRect(tileRect * cellRect);
Shinya Kitaoka 120a6e
      assert(!overlapRect.isEmpty());
Shinya Kitaoka 120a6e
      QRect overlapQRect(toQRect(overlapRect));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (m_region.intersects(overlapQRect)) {
Shinya Kitaoka 120a6e
        // Extract the associated rasters and perform the copy to the input
Shinya Kitaoka 120a6e
        // tile.
Shinya Kitaoka 120a6e
        std::pair<trasterp, *="" celldata=""> cellInfos(touch(getCellIndex(currPos)));</trasterp,>
Shinya Kitaoka 120a6e
        TRasterP cellRas(cellInfos.first);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TRect temp(overlapRect - currPos);
Shinya Kitaoka 120a6e
        TRasterP overlappingCellRas(cellRas->extract(temp));
Shinya Kitaoka 120a6e
        temp = TRect(overlapRect - tileRect.getP00());
Shinya Kitaoka 120a6e
        TRasterP overlappingTileRas(ras->extract(temp));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        TRop::copy(overlappingTileRas, overlappingCellRas);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::downloadAll(TTile &tile) {
Shinya Kitaoka 120a6e
  if (!checkTile(tile)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return downloadAll(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Clears the complex on the specified region. Please observe that the actually
Shinya Kitaoka 120a6e
//! cleared region
Shinya Kitaoka 120a6e
//! consists of all lattice cells intersecting the passed region, therefore
Shinya Kitaoka 120a6e
//! resulting in a cleared region
Toshihiro Shimizu 890ddd
//! typically larger than passed one, up to the lattice granularity.
Shinya Kitaoka 120a6e
void TCacheResource::clear(QRegion region) {
Shinya Kitaoka 120a6e
  if (!m_region.intersects(region)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Get the region bbox
Shinya Kitaoka 120a6e
  TRect bbox(toTRect(region.boundingRect()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // For all cells intersecting the bbox
Shinya Kitaoka 120a6e
  TPoint initialPos(getCellPos(bbox.getP00()));
Shinya Kitaoka 120a6e
  TPoint pos;
Shinya Kitaoka 120a6e
  for (pos.x = initialPos.x; pos.x <= bbox.x1; pos.x += latticeStep)
Shinya Kitaoka 120a6e
    for (pos.y = initialPos.y; pos.y <= bbox.y1; pos.y += latticeStep) {
Shinya Kitaoka 120a6e
      QRect cellQRect(
Shinya Kitaoka 120a6e
          toQRect(TRect(pos, TDimension(latticeStep, latticeStep))));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (region.intersects(cellQRect) && m_region.intersects(cellQRect)) {
Shinya Kitaoka 120a6e
        // Release the associated cell from cache and clear the cell from the
Shinya Kitaoka 120a6e
        // content region.
Shinya Kitaoka 120a6e
        TImageCache::instance()->remove(getCellCacheId(pos));
Shinya Kitaoka 120a6e
        m_region -= cellQRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        --m_cellsCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // DIAGNOSTICS_GLOADD("crCellsCnt", -1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Release the cell from m_cellDatas
Shinya Kitaoka 120a6e
        m_cellDatas[getCellIndex(pos)].m_modified = true;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_region.isEmpty()) {
Shinya Kitaoka 120a6e
    m_tileType   = NONE;
Shinya Kitaoka 120a6e
    m_locksCount = 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Palette management
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::uploadPalette(TPaletteP palette) {
Shinya Kitaoka 120a6e
  if (m_tileType == NONE) m_tileType = CM32;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_tileType != CM32) {
Shinya Kitaoka 120a6e
    assert(!"The resource already holds a non-colormap content!");
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_palette = palette;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::downloadPalette(TPaletteP &palette) {
Shinya Kitaoka 120a6e
  palette = m_palette;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    References management
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::addRef2(const TRect &rect) {
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " |
Shinya Kitaoka 120a6e
  // Stack | ",
Shinya Kitaoka 120a6e
  //"crStack", "addRef", ::traduce(rect));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Add a reference to all cells intersecting the passed one
Shinya Kitaoka 120a6e
  TPoint initialPos(getCellPos(rect.getP00()));
Shinya Kitaoka 120a6e
  TPoint pos;
Shinya Kitaoka 120a6e
  for (pos.x = initialPos.x; pos.x <= rect.x1; pos.x += latticeStep)
Shinya Kitaoka 120a6e
    for (pos.y = initialPos.y; pos.y <= rect.y1; pos.y += latticeStep) {
Shinya Kitaoka 120a6e
      PointLess cellIndex(getCellIndex(pos));
Shinya Kitaoka 120a6e
      CellData &cellData    = m_cellDatas[cellIndex];
Shinya Kitaoka 120a6e
      cellData.m_referenced = true;
Shinya Kitaoka 120a6e
      cellData.m_refsCount++;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::release2(const TRect &rect) {
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " |
Shinya Kitaoka 120a6e
  // Stack | ",
Shinya Kitaoka 120a6e
  //"crStack", "release", ::traduce(rect));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_locksCount > 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<pointless, celldata="">::iterator it;</pointless,>
Shinya Kitaoka 120a6e
  for (it = m_cellDatas.begin(); it != m_cellDatas.end();) {
Shinya Kitaoka 120a6e
    if (!it->second.m_referenced) {
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPoint cellPos(getCellPos(it->first));
Shinya Kitaoka 120a6e
    TRect cellRect(cellPos, TDimension(latticeStep, latticeStep));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (isEmpty(cellRect * rect)) {
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    QRect cellQRect(toQRect(cellRect));
Shinya Kitaoka 120a6e
    if (--it->second.m_refsCount <= 0) {
Shinya Kitaoka 120a6e
      releaseCell(cellQRect, it->first, it->second.m_modified);
Shinya Kitaoka 120a6e
      std::map<pointless, celldata="">::iterator jt = it++;</pointless,>
Shinya Kitaoka 120a6e
      m_cellDatas.erase(jt);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::addLock() {
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_NUMBEREDSTR(prefix + QString::number((UINT) this) + " | Stack |
Shinya Kitaoka 120a6e
  // ",
Shinya Kitaoka 120a6e
  //"crStack", "addLock");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ++m_locksCount;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::releaseLock() {
Shinya Kitaoka 120a6e
  // DIAGNOSTICS_NUMBEREDSTR(prefix + QString::number((UINT) this) + " | Stack |
Shinya Kitaoka 120a6e
  // ",
Shinya Kitaoka 120a6e
  //"crStack", "releaseLock");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_locksCount = std::max(m_locksCount - 1, 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_locksCount > 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Check for released cells
Shinya Kitaoka 120a6e
  std::map<pointless, celldata="">::iterator it;</pointless,>
Shinya Kitaoka 120a6e
  for (it = m_cellDatas.begin(); it != m_cellDatas.end();)
Shinya Kitaoka 120a6e
    if (it->second.m_referenced) {
Shinya Kitaoka 120a6e
      TPoint cellPos(getCellPos(it->first));
Shinya Kitaoka 120a6e
      QRect cellQRect(cellPos.x, cellPos.y, latticeStep, latticeStep);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      releaseCell(cellQRect, it->first, it->second.m_modified);
Shinya Kitaoka 120a6e
      std::map<pointless, celldata="">::iterator jt = it++;</pointless,>
Shinya Kitaoka 120a6e
      m_cellDatas.erase(jt);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      ++it;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::releaseCell(const QRect &cellQRect,
Shinya Kitaoka 120a6e
                                 const PointLess &cellIndex, bool doSave) {
Shinya Kitaoka 120a6e
  if (m_region.intersects(cellQRect)) {
Shinya Kitaoka 120a6e
    std::string cellCacheId(getCellCacheId(cellIndex.x, cellIndex.y));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!(doSave && save(cellIndex))) m_region -= cellQRect;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TImageCache::instance()->remove(cellCacheId);
Shinya Kitaoka 120a6e
    --m_cellsCount;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // DIAGNOSTICS_GLOADD("crCellsCnt", -1);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns the current size, in MB, of the cache resource.
Shinya Kitaoka 120a6e
int TCacheResource::size() const {
Shinya Kitaoka 120a6e
  // NOTE: It's better to store the size incrementally. This complies
Shinya Kitaoka 120a6e
  // with the possibility of specifying a bbox to fit the stored cells to...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_tileType == NONE ? 0
Shinya Kitaoka 120a6e
                            : m_tileType == RGBM64 ? (m_cellsCount << 11)
Shinya Kitaoka 120a6e
                                                   : (m_cellsCount << 10);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Hard disk backing procedures
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::enableBackup() {
Shinya Kitaoka 120a6e
  if (m_backEnabled) return;
Shinya Kitaoka 120a6e
  TCacheResourcePool::instance()->startBacking(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::invalidate() { m_invalidated = true; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::setPath(const TFilePath &path) { m_path = path; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TFilePath &TCacheResource::getPath() const { return m_path; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TCacheResource::save(const PointLess &cellIndex, TRasterP cellRas) const {
Shinya Kitaoka 120a6e
  if (!m_backEnabled || m_invalidated) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(!m_path.isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!cellRas)
Shinya Kitaoka 120a6e
    cellRas = getRaster(TImageCache::instance()->get(
Shinya Kitaoka 120a6e
        getCellCacheId(cellIndex.x, cellIndex.y), false));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(m_tileType != NONE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath fp(TCacheResourcePool::instance()->getPath() + m_path +
Shinya Kitaoka 120a6e
               getCellName(cellIndex.x, cellIndex.y));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_tileType == CM32) {
Shinya Kitaoka 120a6e
    ::saveCompressed(fp, cellRas);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TImageWriter::save(fp.withType(".tif"), cellRas);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterP TCacheResource::load(const PointLess &cellPos) {
Shinya Kitaoka 120a6e
  if (m_path.isEmpty()) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath cellPath(TCacheResourcePool::instance()->getPath() + m_path +
Shinya Kitaoka 120a6e
                     TFilePath(getCellName(cellPos.x, cellPos.y)));
Shinya Kitaoka 120a6e
  TRasterP ras;
Shinya Kitaoka 120a6e
  if (m_tileType == CM32) {
Shinya Kitaoka 120a6e
    ::loadCompressed(cellPath, ras, CM32);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TImageReader::load(cellPath.withType(".tif"), ras);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return ras;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::pair<trasterp, *="" tcacheresource::celldata=""> TCacheResource::touch(</trasterp,>
Shinya Kitaoka 120a6e
    const PointLess &cellIndex) {
Shinya Kitaoka 120a6e
  std::string cellId(getCellCacheId(cellIndex.x, cellIndex.y));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<pointless, celldata="">::iterator it = m_cellDatas.find(cellIndex);</pointless,>
Shinya Kitaoka 120a6e
  if (it != m_cellDatas.end()) {
Shinya Kitaoka 120a6e
    // Retrieve the raster from image cache
Shinya Kitaoka 120a6e
    TImageP img(TImageCache::instance()->get(cellId, true));
Shinya Kitaoka 120a6e
    if (img) return std::make_pair(getRaster(img), &it->second);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  it = m_cellDatas.insert(std::make_pair(cellIndex, CellData())).first;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Then, attempt retrieval from back resource
Shinya Kitaoka 120a6e
  TRasterP ras(load(cellIndex));
Shinya Kitaoka 120a6e
  if (ras) {
Shinya Kitaoka 120a6e
    TImageCache::instance()->add(cellId, TRasterImageP(ras));
Shinya Kitaoka 120a6e
    return std::make_pair(ras, &it->second);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Else, create it
Shinya Kitaoka 120a6e
  return std::make_pair(
Shinya Kitaoka 120a6e
      createCellRaster(m_tileType, cellId),  // increases m_cellsCount too
Shinya Kitaoka 120a6e
      &it->second);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::save() {
Shinya Kitaoka 120a6e
  if (m_backEnabled && !m_invalidated) {
Shinya Kitaoka 120a6e
    assert(!m_path.isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Save each modified cell raster
Shinya Kitaoka 120a6e
    std::map<pointless, celldata="">::iterator it;</pointless,>
Shinya Kitaoka 120a6e
    for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) {
Shinya Kitaoka 120a6e
      if (it->second.m_modified) save(it->first);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Save the palette, if any
Shinya Kitaoka 120a6e
    // SHOULD BE MOVED TO THE CACHERESOURCEPOOL!!
Shinya Kitaoka 120a6e
    /*if(m_palette)
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
TFilePath fp(TCacheResourcePool::instance()->getPath() + m_path);
Shinya Kitaoka 120a6e
TOStream oss(fp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
m_palette->saveData(oss);
Shinya Kitaoka 120a6e
}*/
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::save(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  assert(!fp.isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<pointless, celldata="">::iterator it;</pointless,>
Shinya Kitaoka 120a6e
  for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) {
Shinya Kitaoka 120a6e
    TRasterP cellRas = getRaster(TImageCache::instance()->get(
Shinya Kitaoka 120a6e
        getCellCacheId(it->first.x, it->first.y), false));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    assert(m_tileType != NONE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TFilePath cellFp(fp + TFilePath(getCellName(it->first.x, it->first.y)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_tileType == CM32)
Shinya Kitaoka 120a6e
      ::saveCompressed(cellFp, cellRas);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      TImageWriter::save(cellFp.withType(".tif"), cellRas);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCacheResource::clear() {
Shinya Kitaoka 120a6e
  std::map<pointless, celldata="">::iterator it;</pointless,>
Shinya Kitaoka 120a6e
  for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) {
Shinya Kitaoka 120a6e
    std::string cellCacheId(getCellCacheId(it->first.x, it->first.y));
Shinya Kitaoka 120a6e
    TImageCache::instance()->remove(cellCacheId);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_cellDatas.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Shinya Kitaoka 120a6e
//
Shinya Kitaoka 120a6e
***************************************************************************************************
Toshihiro Shimizu 890ddd
//    Disk reference
Shinya Kitaoka 120a6e
//
Shinya Kitaoka 120a6e
***************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qsettings></qsettings>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCacheResource::DiskReference::DiskReference(const TFilePath& fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  QSettings settings(
Shinya Kitaoka 120a6e
    QString::fromStdWString((TCacheResourcePool::instance()->getPath() + m_path
Shinya Kitaoka 120a6e
+ "resource.ini").getWideString()),
Toshihiro Shimizu 890ddd
    QSettings::IniFormat);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  settings.setValue("MemReference", 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCacheResource::DiskReference::~DiskReference()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  QSettings settings(
Shinya Kitaoka 120a6e
    QString::fromStdWString((TCacheResourcePool::instance()->getPath() + m_path
Shinya Kitaoka 120a6e
+ "resource.ini").getWideString()),
Toshihiro Shimizu 890ddd
    QSettings::IniFormat);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  int diskReference = settings.value("DiskReference").toInt();
Toshihiro Shimizu 890ddd
  if(diskReference == 0)
Toshihiro Shimizu 890ddd
    TCacheResourcePool::instance()->clearResource(QString::fromStdWString(m_path.getWideString()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/