1 /*
2  *  Copyright (c) 2007 Boudewijn Rempt <boud@valdyas.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_transaction_test.h"
20 #include <QTest>
21 #include <KoColorSpace.h>
22 #include <KoColorSpaceRegistry.h>
23 
24 #include <kundo2qstack.h>
25 
26 #include "kis_types.h"
27 #include "kis_transform_worker.h"
28 #include "kis_paint_device.h"
29 #include "kis_transaction.h"
30 #include "kis_surrogate_undo_adapter.h"
31 #include "kis_image.h"
32 #include "kis_paint_device_debug_utils.h"
33 
testUndo()34 void KisTransactionTest::testUndo()
35 {
36     KisSurrogateUndoAdapter undoAdapter;
37     const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
38     KisPaintDeviceSP dev = new KisPaintDevice(cs);
39 
40     quint8* pixel = new quint8[cs->pixelSize()];
41     cs->fromQColor(Qt::white, pixel);
42     dev->fill(0, 0, 512, 512, pixel);
43 
44     cs->fromQColor(Qt::black, pixel);
45     dev->fill(512, 0, 512, 512, pixel);
46 
47     QColor c1, c2;
48     dev->pixel(5, 5, &c1);
49     dev->pixel(517, 5, &c2);
50 
51     QVERIFY(c1 == Qt::white);
52     QVERIFY(c2 == Qt::black);
53 
54     KisTransaction transaction(kundo2_noi18n("mirror"), dev, 0);
55     KisTransformWorker::mirrorX(dev);
56     transaction.commit(&undoAdapter);
57 
58     dev->pixel(5, 5, &c1);
59     dev->pixel(517, 5, &c2);
60 
61     QVERIFY(c1 == Qt::black);
62     QVERIFY(c2 == Qt::white);
63 
64     undoAdapter.undo();
65 
66     dev->pixel(5, 5, &c1);
67     dev->pixel(517, 5, &c2);
68 
69     QVERIFY(c1 == Qt::white);
70     QVERIFY(c2 == Qt::black);
71 
72 }
73 
testRedo()74 void KisTransactionTest::testRedo()
75 {
76     KisSurrogateUndoAdapter undoAdapter;
77 
78     const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
79     KisPaintDeviceSP dev = new KisPaintDevice(cs);
80 
81     quint8* pixel = new quint8[cs->pixelSize()];
82     cs->fromQColor(Qt::white, pixel);
83     dev->fill(0, 0, 512, 512, pixel);
84 
85     cs->fromQColor(Qt::black, pixel);
86     dev->fill(512, 0, 512, 512, pixel);
87 
88     QColor c1, c2;
89     dev->pixel(5, 5, &c1);
90     dev->pixel(517, 5, &c2);
91 
92     QVERIFY(c1 == Qt::white);
93     QVERIFY(c2 == Qt::black);
94 
95     KisTransaction transaction(kundo2_noi18n("mirror"), dev, 0);
96     KisTransformWorker::mirrorX(dev);
97     transaction.commit(&undoAdapter);
98 
99     dev->pixel(5, 5, &c1);
100     dev->pixel(517, 5, &c2);
101 
102     QVERIFY(c1 == Qt::black);
103     QVERIFY(c2 == Qt::white);
104 
105 
106     undoAdapter.undo();
107 
108     dev->pixel(5, 5, &c1);
109     dev->pixel(517, 5, &c2);
110 
111     QVERIFY(c1 == Qt::white);
112     QVERIFY(c2 == Qt::black);
113 
114     undoAdapter.redo();
115 
116     dev->pixel(5, 5, &c1);
117     dev->pixel(517, 5, &c2);
118 
119     QVERIFY(c1 == Qt::black);
120     QVERIFY(c2 == Qt::white);
121 }
122 
testDeviceMove()123 void KisTransactionTest::testDeviceMove()
124 {
125     KisSurrogateUndoAdapter undoAdapter;
126 
127     const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
128     KisPaintDeviceSP dev = new KisPaintDevice(cs);
129 
130     QCOMPARE(dev->x(), 0);
131     QCOMPARE(dev->y(), 0);
132 
133     KisTransaction t1(kundo2_noi18n("move1"), dev, 0);
134     dev->moveTo(10,20);
135     t1.commit(&undoAdapter);
136 
137     QCOMPARE(dev->x(), 10);
138     QCOMPARE(dev->y(), 20);
139 
140     KisTransaction t2(kundo2_noi18n("move2"), dev, 0);
141     dev->moveTo(7,11);
142     t2.commit(&undoAdapter);
143 
144     QCOMPARE(dev->x(),  7);
145     QCOMPARE(dev->y(), 11);
146 
147     undoAdapter.undo();
148 
149     QCOMPARE(dev->x(), 10);
150     QCOMPARE(dev->y(), 20);
151 
152     undoAdapter.undo();
153 
154     QCOMPARE(dev->x(), 0);
155     QCOMPARE(dev->y(), 0);
156 
157     undoAdapter.redo();
158 
159     QCOMPARE(dev->x(), 10);
160     QCOMPARE(dev->y(), 20);
161 
162     undoAdapter.redo();
163 
164     QCOMPARE(dev->x(),  7);
165     QCOMPARE(dev->y(), 11);
166 }
167 
168 #include "kis_keyframe_channel.h"
169 #include "kis_raster_keyframe_channel.h"
170 #include "kis_paint_device_frames_interface.h"
171 #include "testing_timed_default_bounds.h"
172 
173 #include <KoColor.h>
174 
175 
testUndoWithUnswitchedFrames()176 void KisTransactionTest::testUndoWithUnswitchedFrames()
177 {
178     KisSurrogateUndoAdapter undoAdapter;
179     const QRect imageRect(0,0,100,100);
180 
181 
182     const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
183     KisPaintDeviceSP dev = new KisPaintDevice(cs);
184 
185     TestUtil::TestingTimedDefaultBounds *bounds = new TestUtil::TestingTimedDefaultBounds();
186     dev->setDefaultBounds(bounds);
187 
188     KisRasterKeyframeChannel *channel = dev->createKeyframeChannel(KisKeyframeChannel::Content);
189     QVERIFY(channel);
190 
191     KisPaintDeviceFramesInterface *i = dev->framesInterface();
192     QVERIFY(i);
193 
194     QCOMPARE(i->frames().size(), 1);
195 
196 
197     dev->fill(QRect(10,10,20,20), KoColor(Qt::white, cs));
198 
199     KIS_DUMP_DEVICE_2(dev, imageRect, "00_f0_w20", "dd");
200     QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));
201 
202 
203     // add keyframe at position 10
204     channel->addKeyframe(10);
205 
206     // add keyframe at position 11
207     channel->addKeyframe(11);
208 
209     // add keyframe at position 12
210     channel->addKeyframe(12);
211 
212     KIS_DUMP_DEVICE_2(dev, imageRect, "01_f0_b20", "dd");
213     QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));
214 
215     {
216         KisTransaction transaction(kundo2_noi18n("first_stroke"), dev, 0);
217 
218         dev->clear();
219         dev->fill(QRect(40,40,21,21), KoColor(Qt::red, cs));
220 
221         transaction.commit(&undoAdapter);
222 
223         KIS_DUMP_DEVICE_2(dev, imageRect, "02_f0_b21_stroke", "dd");
224         QCOMPARE(dev->exactBounds(), QRect(40,40,21,21));
225     }
226 
227     // switch to frame 10
228     bounds->testingSetTime(10);
229 
230     KIS_DUMP_DEVICE_2(dev, imageRect, "03_f10_b0_switched", "dd");
231     QVERIFY(dev->exactBounds().isEmpty());
232 
233     {
234         KisTransaction transaction(kundo2_noi18n("second_stroke"), dev, 0);
235 
236         dev->fill(QRect(60,60,22,22), KoColor(Qt::green, cs));
237 
238         transaction.commit(&undoAdapter);
239 
240         KIS_DUMP_DEVICE_2(dev, imageRect, "04_f10_b22_stroke", "dd");
241         QCOMPARE(dev->exactBounds(), QRect(60,60,22,22));
242     }
243 
244     undoAdapter.undo();
245 
246     KIS_DUMP_DEVICE_2(dev, imageRect, "05_f10_b0_undone", "dd");
247     QVERIFY(dev->exactBounds().isEmpty());
248 
249     bounds->testingSetTime(0);
250     KIS_DUMP_DEVICE_2(dev, imageRect, "06_f0_b21_undone", "dd");
251     QCOMPARE(dev->exactBounds(), QRect(40,40,21,21));
252 
253     bounds->testingSetTime(10);
254     QVERIFY(dev->exactBounds().isEmpty());
255 
256     undoAdapter.undo();
257 
258     KIS_DUMP_DEVICE_2(dev, imageRect, "07_f10_b0_undone_x2", "dd");
259     QVERIFY(dev->exactBounds().isEmpty());
260 
261     bounds->testingSetTime(0);
262     KIS_DUMP_DEVICE_2(dev, imageRect, "08_f0_b20_undone_x2", "dd");
263     QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));
264 
265     {
266         KisTransaction transaction(kundo2_noi18n("third_move"), dev, 0);
267 
268         dev->moveTo(17,17);
269 
270         transaction.commit(&undoAdapter);
271 
272         KIS_DUMP_DEVICE_2(dev, imageRect, "09_f0_o27_move", "dd");
273         QCOMPARE(dev->exactBounds(), QRect(27,27,20,20));
274     }
275 
276     bounds->testingSetTime(10);
277     QVERIFY(dev->exactBounds().isEmpty());
278 
279     undoAdapter.undo();
280 
281     KIS_DUMP_DEVICE_2(dev, imageRect, "10_f10_b0_undone_x3", "dd");
282     QVERIFY(dev->exactBounds().isEmpty());
283 
284     bounds->testingSetTime(0);
285     KIS_DUMP_DEVICE_2(dev, imageRect, "11_f0_b20_undone_x3", "dd");
286     QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));
287 }
288 
289 QTEST_MAIN(KisTransactionTest)
290 
291 
292