You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/chalk/core/tiles/kis_tiled_random_accessor.cc

116 lines
3.9 KiB

/*
* copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
*
* this program is free software; you can redistribute it and/or modify
* it under the terms of the gnu general public license as published by
* the free software foundation; either version 2 of the license, or
* (at your option) any later version.
*
* this program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. see the
* gnu general public license for more details.
*
* you should have received a copy of the gnu general public license
* along with this program; if not, write to the free software
* foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
*/
#include "kis_tiled_random_accessor.h"
const TQ_UINT32 KisTiledRandomAccessor::CACHESIZE = 4; // Define the number of tiles we keep in cache
KisTiledRandomAccessor::KisTiledRandomAccessor(KisTiledDataManager *ktm, TQ_INT32 x, TQ_INT32 y, bool writable) : m_ktm(ktm), m_tilesCache(new KisTileInfo*[4]), m_tilesCacheSize(0), m_pixelSize (m_ktm->pixelSize()), m_writable(writable)
{
Q_ASSERT(ktm != 0);
moveTo(x, y);
}
KisTiledRandomAccessor::~KisTiledRandomAccessor()
{
for( uint i = 0; i < m_tilesCacheSize; i++)
{
m_tilesCache[i]->tile->removeReader();
m_tilesCache[i]->oldtile->removeReader();
delete m_tilesCache[i];
}
delete m_tilesCache;
}
void KisTiledRandomAccessor::moveTo(TQ_INT32 x, TQ_INT32 y)
{
// Look in the cache if the tile if the data is available
for( uint i = 0; i < m_tilesCacheSize; i++)
{
if( x >= m_tilesCache[i]->area_x1 && x <= m_tilesCache[i]->area_x2 &&
y >= m_tilesCache[i]->area_y1 && y <= m_tilesCache[i]->area_y2 )
{
KisTileInfo* kti = m_tilesCache[i];
TQ_UINT32 offset = x - kti->area_x1 + (y -kti->area_y1) * KisTile::WIDTH;
offset *= m_pixelSize;
m_data = kti->data + offset;
m_oldData = kti->oldData + offset;
if(i > 0)
{
memmove(m_tilesCache+1,m_tilesCache, i * sizeof(KisTileInfo*));
m_tilesCache[0] = kti;
}
return;
}
}
// The tile wasn't in cache
if(m_tilesCacheSize == KisTiledRandomAccessor::CACHESIZE )
{ // Remove last element of cache
m_tilesCache[CACHESIZE-1]->tile->removeReader();
m_tilesCache[CACHESIZE-1]->oldtile->removeReader();
delete m_tilesCache[CACHESIZE-1];
} else {
m_tilesCacheSize++;
}
TQ_UINT32 col = xToCol( x );
TQ_UINT32 row = yToRow( y );
KisTileInfo* kti = fetchTileData(col, row);
TQ_UINT32 offset = x - kti->area_x1 + (y - kti->area_y1) * KisTile::WIDTH;
offset *= m_pixelSize;
m_data = kti->data + offset;
m_oldData = kti->oldData + offset;
memmove(m_tilesCache+1,m_tilesCache, (KisTiledRandomAccessor::CACHESIZE-1) * sizeof(KisTileInfo*));
m_tilesCache[0] = kti;
}
TQ_UINT8 * KisTiledRandomAccessor::rawData() const
{
return m_data;
}
const TQ_UINT8 * KisTiledRandomAccessor::oldRawData() const
{
#ifdef DEBUG
kdWarning(!m_ktm->hasCurrentMemento(), DBG_AREA_TILES) << "Accessing oldRawData() when no transaction is in progress.\n";
#endif
return m_oldData;
}
KisTiledRandomAccessor::KisTileInfo* KisTiledRandomAccessor::fetchTileData(TQ_INT32 col, TQ_INT32 row)
{
KisTileInfo* kti = new KisTileInfo;
kti->tile = m_ktm->getTile(col, row, m_writable);
kti->tile->addReader();
kti->data = kti->tile->data();
kti->area_x1 = col * KisTile::HEIGHT;
kti->area_y1 = row * KisTile::WIDTH;
kti->area_x2 = kti->area_x1 + KisTile::HEIGHT - 2;
kti->area_y2 = kti->area_y1 + KisTile::WIDTH - 2;
// set old data
kti->oldtile = m_ktm->getOldTile(col, row, kti->tile);
kti->oldtile->addReader();
kti->oldData = kti->oldtile->data();
return kti;
}