Commit a2e32e96 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fixed undoing operations involving changing default pixel of the device

WARNING: You have to do 'make clean' in ./krita/image/ folder. Sorry =(

BUG:290406
CC:kimageshop@kde.org
parent 06a34ed7
......@@ -41,17 +41,17 @@ class KisMemento : public KisShared
{
public:
inline KisMemento(KisMementoManager* mementoManager) {
m_mementoManager = mementoManager;
m_valid = true;
m_extentMinX = qint32_MAX;
m_extentMinY = qint32_MAX;
m_extentMaxX = qint32_MIN;
m_extentMaxY = qint32_MIN;
m_oldDefaultPixel = m_newDefaultPixel = 0;
}
inline ~KisMemento() {
delete m_oldDefaultPixel;
delete m_newDefaultPixel;
}
inline void extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) {
......@@ -67,24 +67,23 @@ public:
return QRect(x, y, w, h);
}
inline bool containsTile(qint32 col, qint32 row, quint32 tileHash) const {
Q_UNUSED(col);
Q_UNUSED(row);
Q_UNUSED(tileHash);
Q_ASSERT_X(0, "KisMemento::containsTile", "Not implemented");
return false; // Compiller would be happy! =)
void saveOldDefaultPixel(const quint8* pixel, quint32 pixelSize) {
m_oldDefaultPixel = new quint8[pixelSize];
memcpy(m_oldDefaultPixel, pixel, pixelSize);
}
void saveNewDefaultPixel(const quint8* pixel, quint32 pixelSize) {
m_newDefaultPixel = new quint8[pixelSize];
memcpy(m_newDefaultPixel, pixel, pixelSize);
}
const quint8* oldDefaultPixel() const {
return m_oldDefaultPixel;
}
/**
* Not used, happily
*/
// inline bool valid() const {
// return m_valid;
// }
// inline void setInvalid() {
// m_valid = false;
// }
const quint8* newDefaultPixel() const {
return m_newDefaultPixel;
}
private:
friend class KisMementoManager;
......@@ -102,14 +101,13 @@ private:
}
private:
KisMementoManager* m_mementoManager;
quint8 *m_oldDefaultPixel;
quint8 *m_newDefaultPixel;
qint32 m_extentMinX;
qint32 m_extentMaxX;
qint32 m_extentMinY;
qint32 m_extentMaxY;
bool m_valid;
};
#endif // KIS_MEMENTO_H_
......@@ -248,6 +248,10 @@ KisMementoSP KisMementoManager::getMemento()
return m_currentMemento;
}
KisMementoSP KisMementoManager::currentMemento() {
return m_currentMemento;
}
#define forEachReversed(iter, list) \
for(iter=list.end(); iter-- != list.begin();)
......
......@@ -96,6 +96,8 @@ public:
return m_currentMemento;
}
KisMementoSP currentMemento();
void setDefaultTileData(KisTileData *defaultTileData);
void debugPrintInfo();
......
......@@ -105,7 +105,11 @@ KisTiledDataManager::~KisTiledDataManager()
void KisTiledDataManager::setDefaultPixel(const quint8 *defaultPixel)
{
QWriteLocker locker(&m_lock);
setDefaultPixelImpl(defaultPixel);
}
void KisTiledDataManager::setDefaultPixelImpl(const quint8 *defaultPixel)
{
KisTileData *td = KisTileDataStore::instance()->createDefaultTileData(pixelSize(), defaultPixel);
m_hashTable->setDefaultTileData(td);
m_mementoManager->setDefaultTileData(td);
......@@ -113,7 +117,6 @@ void KisTiledDataManager::setDefaultPixel(const quint8 *defaultPixel)
memcpy(m_defaultPixel, defaultPixel, pixelSize());
}
bool KisTiledDataManager::write(KoStore *store)
{
QReadLocker locker(&m_lock);
......
......@@ -145,16 +145,13 @@ protected:
friend class KisTiledRandomAccessor;
friend class KisRandomAccessor2;
friend class KisStressJob;
protected:
public:
void setDefaultPixel(const quint8 *defPixel);
const quint8 *defaultPixel() const {
return m_defaultPixel;
}
/* FIXME:*/
public:
inline KisTileSP getTile(qint32 col, qint32 row, bool writable) {
if (writable) {
bool newTile;
......@@ -176,7 +173,9 @@ public:
KisMementoSP getMemento() {
QWriteLocker locker(&m_lock);
return m_mementoManager->getMemento();
KisMementoSP memento = m_mementoManager->getMemento();
memento->saveOldDefaultPixel(m_defaultPixel, m_pixelSize);
return memento;
}
/**
......@@ -184,19 +183,35 @@ public:
*/
void commit() {
QWriteLocker locker(&m_lock);
KisMementoSP memento = m_mementoManager->currentMemento();
if(memento) {
memento->saveNewDefaultPixel(m_defaultPixel, m_pixelSize);
}
m_mementoManager->commit();
}
void rollback(KisMementoSP memento) {
Q_UNUSED(memento);
commit();
QWriteLocker locker(&m_lock);
m_mementoManager->rollback(m_hashTable);
const quint8 *defaultPixel = memento->oldDefaultPixel();
if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) {
setDefaultPixelImpl(defaultPixel);
}
recalculateExtent();
}
void rollforward(KisMementoSP memento) {
Q_UNUSED(memento);
commit();
QWriteLocker locker(&m_lock);
m_mementoManager->rollforward(m_hashTable);
const quint8 *defaultPixel = memento->newDefaultPixel();
if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) {
setDefaultPixelImpl(defaultPixel);
}
recalculateExtent();
}
bool hasCurrentMemento() const {
......@@ -350,6 +365,8 @@ private:
qint32 yToRow(qint32 y) const;
private:
void setDefaultPixelImpl(const quint8 *defPixel);
bool writeTilesHeader(KoStore *store, quint32 numTiles);
bool processTilesHeader(QIODevice *stream, quint32 &numTiles);
......
......@@ -428,6 +428,71 @@ void KisTiledDataManagerTest::testPurgeHistory()
dm.purgeHistory(memento4);
}
void KisTiledDataManagerTest::testUndoSetDefaultPixel()
{
quint8 defaultPixel = 0;
KisTiledDataManager dm(1, &defaultPixel);
quint8 oddPixel1 = 128;
quint8 oddPixel2 = 129;
QRect fillRect(0,0,64,64);
KisTileSP tile00;
KisTileSP tile10;
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(defaultPixel, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(defaultPixel, tile10->data(), TILESIZE));
KisMementoSP memento1 = dm.getMemento();
dm.clear(fillRect, &oddPixel1);
dm.commit();
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(oddPixel1, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(defaultPixel, tile10->data(), TILESIZE));
KisMementoSP memento2 = dm.getMemento();
dm.setDefaultPixel(&oddPixel2);
dm.commit();
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(oddPixel1, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(oddPixel2, tile10->data(), TILESIZE));
dm.rollback(memento2);
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(oddPixel1, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(defaultPixel, tile10->data(), TILESIZE));
dm.rollback(memento1);
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(defaultPixel, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(defaultPixel, tile10->data(), TILESIZE));
dm.rollforward(memento1);
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(oddPixel1, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(defaultPixel, tile10->data(), TILESIZE));
dm.rollforward(memento2);
tile00 = dm.getTile(0, 0, false);
tile10 = dm.getTile(1, 0, false);
QVERIFY(memoryIsFilled(oddPixel1, tile00->data(), TILESIZE));
QVERIFY(memoryIsFilled(oddPixel2, tile10->data(), TILESIZE));
}
//#include <valgrind/callgrind.h>
void KisTiledDataManagerTest::benchmarkReadOnlyTileLazy()
......
......@@ -50,6 +50,8 @@ private slots:
void testBitBltRough();
void testTransactions();
void testPurgeHistory();
void testUndoSetDefaultPixel();
void benchmarkReadOnlyTileLazy();
void benchmarkSharedPointers();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment