File indexing completed on 2024-05-26 04:28:04
0001 /* 0002 * copyright (c) 2006,2010 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_random_accessor.h" 0008 0009 0010 #include <kis_debug.h> 0011 0012 0013 const quint32 KisRandomAccessor2::CACHESIZE = 4; // Define the number of tiles we keep in cache 0014 0015 KisRandomAccessor2::KisRandomAccessor2(KisTiledDataManager *ktm, qint32 offsetX, qint32 offsetY, bool writable, KisIteratorCompleteListener *completeListener) : 0016 m_ktm(ktm), 0017 m_tilesCache(new KisTileInfo*[CACHESIZE]), 0018 m_tilesCacheSize(0), 0019 m_pixelSize(m_ktm->pixelSize()), 0020 m_data(0), 0021 m_oldData(0), 0022 m_writable(writable), 0023 m_lastX(0), 0024 m_lastY(0), 0025 m_offsetX(offsetX), 0026 m_offsetY(offsetY), 0027 m_completeListener(completeListener) 0028 { 0029 Q_ASSERT(ktm != 0); 0030 } 0031 0032 KisRandomAccessor2::~KisRandomAccessor2() 0033 { 0034 for (uint i = 0; i < m_tilesCacheSize; i++) { 0035 unlockTile(m_tilesCache[i]->tile); 0036 unlockOldTile(m_tilesCache[i]->oldtile); 0037 delete m_tilesCache[i]; 0038 } 0039 delete [] m_tilesCache; 0040 0041 if (m_writable && m_completeListener) { 0042 m_completeListener->notifyWritableIteratorCompleted(); 0043 } 0044 } 0045 0046 void KisRandomAccessor2::moveTo(qint32 x, qint32 y) 0047 { 0048 m_lastX = x; 0049 m_lastY = y; 0050 0051 x -= m_offsetX; 0052 y -= m_offsetY; 0053 0054 // Look in the cache if the tile if the data is available 0055 for (uint i = 0; i < m_tilesCacheSize; i++) { 0056 if (x >= m_tilesCache[i]->area_x1 && x <= m_tilesCache[i]->area_x2 && 0057 y >= m_tilesCache[i]->area_y1 && y <= m_tilesCache[i]->area_y2) { 0058 KisTileInfo* kti = m_tilesCache[i]; 0059 quint32 offset = x - kti->area_x1 + (y - kti->area_y1) * KisTileData::WIDTH; 0060 offset *= m_pixelSize; 0061 m_data = kti->data + offset; 0062 m_oldData = kti->oldData + offset; 0063 if (i > 0) { 0064 memmove(m_tilesCache + 1, m_tilesCache, i * sizeof(KisTileInfo*)); 0065 m_tilesCache[0] = kti; 0066 } 0067 return; 0068 } 0069 } 0070 // The tile wasn't in cache 0071 if (m_tilesCacheSize == KisRandomAccessor2::CACHESIZE) { // Remove last element of cache 0072 unlockTile(m_tilesCache[CACHESIZE-1]->tile); 0073 unlockOldTile(m_tilesCache[CACHESIZE-1]->oldtile); 0074 delete m_tilesCache[CACHESIZE-1]; 0075 } else { 0076 m_tilesCacheSize++; 0077 } 0078 quint32 col = xToCol(x); 0079 quint32 row = yToRow(y); 0080 KisTileInfo* kti = fetchTileData(col, row); 0081 quint32 offset = x - kti->area_x1 + (y - kti->area_y1) * KisTileData::WIDTH; 0082 offset *= m_pixelSize; 0083 m_data = kti->data + offset; 0084 m_oldData = kti->oldData + offset; 0085 memmove(m_tilesCache + 1, m_tilesCache, (KisRandomAccessor2::CACHESIZE - 1) * sizeof(KisTileInfo*)); 0086 m_tilesCache[0] = kti; 0087 } 0088 0089 0090 quint8* KisRandomAccessor2::rawData() 0091 { 0092 return m_data; 0093 } 0094 0095 0096 const quint8* KisRandomAccessor2::oldRawData() const 0097 { 0098 #ifdef DEBUG 0099 if (!m_ktm->hasCurrentMemento()) warnTiles << "Accessing oldRawData() when no transaction is in progress."; 0100 #endif 0101 return m_oldData; 0102 } 0103 0104 const quint8* KisRandomAccessor2::rawDataConst() const 0105 { 0106 return m_data; 0107 } 0108 0109 KisRandomAccessor2::KisTileInfo* KisRandomAccessor2::fetchTileData(qint32 col, qint32 row) 0110 { 0111 KisTileInfo* kti = new KisTileInfo; 0112 0113 m_ktm->getTilesPair(col, row, m_writable, &kti->tile, &kti->oldtile); 0114 0115 lockTile(kti->tile); 0116 kti->data = kti->tile->data(); 0117 0118 lockOldTile(kti->oldtile); 0119 kti->oldData = kti->oldtile->data(); 0120 0121 kti->area_x1 = col * KisTileData::HEIGHT; 0122 kti->area_y1 = row * KisTileData::WIDTH; 0123 kti->area_x2 = kti->area_x1 + KisTileData::HEIGHT - 1; 0124 kti->area_y2 = kti->area_y1 + KisTileData::WIDTH - 1; 0125 0126 return kti; 0127 } 0128 0129 qint32 KisRandomAccessor2::numContiguousColumns(qint32 x) const 0130 { 0131 return m_ktm->numContiguousColumns(x - m_offsetX, 0, 0); 0132 } 0133 0134 qint32 KisRandomAccessor2::numContiguousRows(qint32 y) const 0135 { 0136 return m_ktm->numContiguousRows(y - m_offsetY, 0, 0); 0137 } 0138 0139 qint32 KisRandomAccessor2::rowStride(qint32 x, qint32 y) const 0140 { 0141 return m_ktm->rowStride(x - m_offsetX, y - m_offsetY); 0142 } 0143 0144 qint32 KisRandomAccessor2::x() const 0145 { 0146 return m_lastX; 0147 } 0148 0149 qint32 KisRandomAccessor2::y() const 0150 { 0151 return m_lastY; 0152 }