1 /*
2 * This file is part of Calligra tests
3 *
4 * Copyright (C) 2006-2010 Thomas Zander <zander@kde.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include "TestShapePainting.h"
22
23 #include <QtGui>
24 #include "KoShapeContainer.h"
25 #include "KoShapeManager.h"
26 #include "KoShapePaintingContext.h"
27 #include <sdk/tests/kistest.h>
28 #include <MockShapes.h>
29
30 #include <QTest>
31
testPaintShape()32 void TestShapePainting::testPaintShape()
33 {
34 MockShape *shape1 = new MockShape();
35 MockShape *shape2 = new MockShape();
36 QScopedPointer<MockContainer> container(new MockContainer());
37
38 container->addShape(shape1);
39 container->addShape(shape2);
40 QCOMPARE(shape1->parent(), container.data());
41 QCOMPARE(shape2->parent(), container.data());
42 container->setClipped(shape1, false);
43 container->setClipped(shape2, false);
44 QCOMPARE(container->isClipped(shape1), false);
45 QCOMPARE(container->isClipped(shape2), false);
46
47 MockCanvas canvas;
48 KoShapeManager manager(&canvas);
49 manager.addShape(container.data());
50 QCOMPARE(manager.shapes().count(), 3);
51
52 QImage image(100, 100, QImage::Format_Mono);
53 QPainter painter(&image);
54 manager.paint(painter, false);
55
56 // with the shape not being clipped, the shapeManager will paint it for us.
57 QCOMPARE(shape1->paintedCount, 1);
58 QCOMPARE(shape2->paintedCount, 1);
59 QCOMPARE(container->paintedCount, 1);
60
61 // the container should thus not paint the shape
62 shape1->paintedCount = 0;
63 shape2->paintedCount = 0;
64 container->paintedCount = 0;
65 KoShapePaintingContext paintContext;
66 container->paint(painter, paintContext);
67 QCOMPARE(shape1->paintedCount, 0);
68 QCOMPARE(shape2->paintedCount, 0);
69 QCOMPARE(container->paintedCount, 1);
70
71
72 container->setClipped(shape1, false);
73 container->setClipped(shape2, true);
74 QCOMPARE(container->isClipped(shape1), false);
75 QCOMPARE(container->isClipped(shape2), true);
76
77 shape1->paintedCount = 0;
78 shape2->paintedCount = 0;
79 container->paintedCount = 0;
80 manager.paint(painter, false);
81
82
83 // with this shape not being clipped, the shapeManager will paint the container and this shape
84 QCOMPARE(shape1->paintedCount, 1);
85 // with this shape being clipped, the container will paint it for us.
86 QCOMPARE(shape2->paintedCount, 1);
87 QCOMPARE(container->paintedCount, 1);
88 }
89
testPaintHiddenShape()90 void TestShapePainting::testPaintHiddenShape()
91 {
92 QScopedPointer<MockContainer> top(new MockContainer());
93
94 MockShape *shape = new MockShape();
95 MockContainer *fourth = new MockContainer();
96 MockContainer *thirth = new MockContainer();
97 MockContainer *second = new MockContainer();
98
99
100 top->addShape(second);
101 second->addShape(thirth);
102 thirth->addShape(fourth);
103 fourth->addShape(shape);
104
105 second->setVisible(false);
106
107 MockCanvas canvas;
108 KoShapeManager manager(&canvas);
109 manager.addShape(top.data());
110 QCOMPARE(manager.shapes().count(), 5);
111
112 QImage image(100, 100, QImage::Format_Mono);
113 QPainter painter(&image);
114 manager.paint(painter, false);
115
116 QCOMPARE(top->paintedCount, 1);
117 QCOMPARE(second->paintedCount, 0);
118 QCOMPARE(thirth->paintedCount, 0);
119 QCOMPARE(fourth->paintedCount, 0);
120 QCOMPARE(shape->paintedCount, 0);
121 }
122
testPaintOrder()123 void TestShapePainting::testPaintOrder()
124 {
125 // the stacking order determines the painting order so things on top
126 // get their paint called last.
127 // Each shape has a zIndex and within the children a container has
128 // it determines the stacking order. Its important to realize that
129 // the zIndex is thus local to a container, if you have layer1 and layer2
130 // with both various child shapes the stacking order of the layer shapes
131 // is most important, then within this the child shape index is used.
132
133 class OrderedMockShape : public MockShape {
134 public:
135 OrderedMockShape(QList<const MockShape*> *list) : order(list) {}
136 void paint(QPainter &painter, KoShapePaintingContext &paintcontext) const override {
137 order->append(this);
138 MockShape::paint(painter, paintcontext);
139 }
140 mutable QList<const MockShape*> *order;
141 };
142
143 QList<const MockShape*> order;
144
145 {
146 QScopedPointer<MockContainer> top(new MockContainer());
147 top->setZIndex(2);
148 OrderedMockShape *shape1 = new OrderedMockShape(&order);
149 shape1->setZIndex(5);
150 OrderedMockShape *shape2 = new OrderedMockShape(&order);
151 shape2->setZIndex(0);
152 top->addShape(shape1);
153 top->addShape(shape2);
154
155 QScopedPointer<MockContainer> bottom(new MockContainer());
156 bottom->setZIndex(1);
157 OrderedMockShape *shape3 = new OrderedMockShape(&order);
158 shape3->setZIndex(-1);
159 OrderedMockShape *shape4 = new OrderedMockShape(&order);
160 shape4->setZIndex(9);
161 bottom->addShape(shape3);
162 bottom->addShape(shape4);
163
164 MockCanvas canvas;
165 KoShapeManager manager(&canvas);
166 manager.addShape(top.data());
167 manager.addShape(bottom.data());
168 QCOMPARE(manager.shapes().count(), 6);
169
170 QImage image(100, 100, QImage::Format_Mono);
171 QPainter painter(&image);
172 manager.paint(painter, false);
173 QCOMPARE(top->paintedCount, 1);
174 QCOMPARE(bottom->paintedCount, 1);
175 QCOMPARE(shape1->paintedCount, 1);
176 QCOMPARE(shape2->paintedCount, 1);
177 QCOMPARE(shape3->paintedCount, 1);
178 QCOMPARE(shape4->paintedCount, 1);
179
180 QCOMPARE(order.count(), 4);
181 QVERIFY(order[0] == shape3); // lowest first
182 QVERIFY(order[1] == shape4);
183 QVERIFY(order[2] == shape2);
184 QVERIFY(order[3] == shape1);
185
186 // again, with clipping.
187 order.clear();
188 painter.setClipRect(0, 0, 100, 100);
189 manager.paint(painter, false);
190 QCOMPARE(top->paintedCount, 2);
191 QCOMPARE(bottom->paintedCount, 2);
192 QCOMPARE(shape1->paintedCount, 2);
193 QCOMPARE(shape2->paintedCount, 2);
194 QCOMPARE(shape3->paintedCount, 2);
195 QCOMPARE(shape4->paintedCount, 2);
196
197 QCOMPARE(order.count(), 4);
198 QVERIFY(order[0] == shape3); // lowest first
199 QVERIFY(order[1] == shape4);
200 QVERIFY(order[2] == shape2);
201 QVERIFY(order[3] == shape1);
202
203 }
204
205 order.clear();
206
207 {
208 QScopedPointer<MockContainer> root(new MockContainer());
209 root->setZIndex(0);
210
211 MockContainer *branch1 = new MockContainer();
212 branch1->setZIndex(1);
213 OrderedMockShape *child1_1 = new OrderedMockShape(&order);
214 child1_1->setZIndex(1);
215 OrderedMockShape *child1_2 = new OrderedMockShape(&order);
216 child1_2->setZIndex(2);
217 branch1->addShape(child1_1);
218 branch1->addShape(child1_2);
219
220 MockContainer *branch2 = new MockContainer();
221 branch2->setZIndex(2);
222 OrderedMockShape *child2_1 = new OrderedMockShape(&order);
223 child2_1->setZIndex(1);
224 OrderedMockShape *child2_2 = new OrderedMockShape(&order);
225 child2_2->setZIndex(2);
226 branch2->addShape(child2_1);
227 branch2->addShape(child2_2);
228
229 root->addShape(branch1);
230 root->addShape(branch2);
231
232 QList<KoShape*> sortedShapes;
233 sortedShapes.append(root.data());
234 sortedShapes.append(branch1);
235 sortedShapes.append(branch2);
236 sortedShapes.append(branch1->shapes());
237 sortedShapes.append(branch2->shapes());
238
239 std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
240 QCOMPARE(sortedShapes.count(), 7);
241 QVERIFY(sortedShapes[0] == root.data());
242 QVERIFY(sortedShapes[1] == branch1);
243 QVERIFY(sortedShapes[2] == child1_1);
244 QVERIFY(sortedShapes[3] == child1_2);
245 QVERIFY(sortedShapes[4] == branch2);
246 QVERIFY(sortedShapes[5] == child2_1);
247 QVERIFY(sortedShapes[6] == child2_2);
248 }
249 }
250 #include <kundo2command.h>
251 #include <KoShapeController.h>
252 #include <KoShapeGroupCommand.h>
253 #include <KoShapeUngroupCommand.h>
254 #include "kis_debug.h"
testGroupUngroup()255 void TestShapePainting::testGroupUngroup()
256 {
257 MockShapeController controller;
258 MockCanvas canvas(&controller);
259
260 KoShapeManager *manager = canvas.shapeManager();
261
262 QScopedPointer<MockContainer> shapesFakeLayer(new MockContainer());
263 shapesFakeLayer->setAssociatedRootShapeManager(manager);
264
265 MockShape *shape1(new MockShape());
266 MockShape *shape2(new MockShape());
267 shape1->setName("shape1");
268 shape2->setName("shape2");
269 shape1->setParent(shapesFakeLayer.data());
270 shape2->setParent(shapesFakeLayer.data());
271
272 QList<KoShape*> groupedShapes = {shape1, shape2};
273
274 QImage image(100, 100, QImage::Format_Mono);
275 QPainter painter(&image);
276 painter.setClipRect(image.rect());
277
278 for (int i = 0; i < 3; i++) {
279 KoShapeGroup *group = new KoShapeGroup();
280
281 {
282 group->setName("group");
283
284 KUndo2Command groupingCommand;
285 canvas.shapeController()->addShapeDirect(group, shapesFakeLayer.data(), &groupingCommand);
286 new KoShapeGroupCommand(group, groupedShapes, true, &groupingCommand);
287
288 groupingCommand.redo();
289
290 manager->paint(painter, false);
291
292 QCOMPARE(shape1->paintedCount, 2 * i + 1);
293 QCOMPARE(shape2->paintedCount, 2 * i + 1);
294 QCOMPARE(manager->shapes().size(), 3);
295 }
296
297 {
298 KUndo2Command ungroupingCommand;
299
300 new KoShapeUngroupCommand(group, group->shapes(), QList<KoShape*>(), &ungroupingCommand);
301 canvas.shapeController()->removeShape(group, &ungroupingCommand);
302 // NOTE: group will be deleted in ungroupingCommand's d-tor
303
304 ungroupingCommand.redo();
305
306 manager->paint(painter, false);
307
308 QCOMPARE(shape1->paintedCount, 2 * i + 2);
309 QCOMPARE(shape2->paintedCount, 2 * i + 2);
310 QCOMPARE(manager->shapes().size(), 2);
311 }
312 }
313 }
314
315 KISTEST_MAIN(TestShapePainting)
316