summaryrefslogtreecommitdiffstats
path: root/chalk/core/tiles/kis_tiled_random_accessor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chalk/core/tiles/kis_tiled_random_accessor.cpp')
-rw-r--r--chalk/core/tiles/kis_tiled_random_accessor.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/chalk/core/tiles/kis_tiled_random_accessor.cpp b/chalk/core/tiles/kis_tiled_random_accessor.cpp
new file mode 100644
index 000000000..159faf18c
--- /dev/null
+++ b/chalk/core/tiles/kis_tiled_random_accessor.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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;
+}