File indexing completed on 2024-05-26 04:26:29

0001 /*
0002  *  SPDX-FileCopyrightText: 2006-2010 Thomas Zander <zander@kde.org>
0003  *  SPDX-License-Identifier: GPL-2.0-or-later
0004  */
0005 
0006 #include "TestShapePainting.h"
0007 
0008 #include <QtGui>
0009 #include "KoShapeContainer.h"
0010 #include "KoShapeManager.h"
0011 
0012 #include <MockShapes.h>
0013 #include <testflake.h>
0014 
0015 
0016 #include <simpletest.h>
0017 
0018 void TestShapePainting::testPaintShape()
0019 {
0020     MockShape *shape1 = new MockShape();
0021     MockShape *shape2 = new MockShape();
0022     QScopedPointer<MockContainer> container(new MockContainer());
0023 
0024     container->addShape(shape1);
0025     container->addShape(shape2);
0026     QCOMPARE(shape1->parent(), container.data());
0027     QCOMPARE(shape2->parent(), container.data());
0028     container->setClipped(shape1, false);
0029     container->setClipped(shape2, false);
0030     QCOMPARE(container->isClipped(shape1), false);
0031     QCOMPARE(container->isClipped(shape2), false);
0032 
0033     MockCanvas canvas;
0034     KoShapeManager manager(&canvas);
0035     manager.addShape(container.data());
0036     QCOMPARE(manager.shapes().count(), 3);
0037 
0038     QImage image(100, 100,  QImage::Format_Mono);
0039     QPainter painter(&image);
0040     manager.paint(painter);
0041 
0042     // with the shape not being clipped, the shapeManager will paint it for us.
0043     QCOMPARE(shape1->paintedCount, 1);
0044     QCOMPARE(shape2->paintedCount, 1);
0045     QCOMPARE(container->paintedCount, 1);
0046 
0047     // the container should thus not paint the shape
0048     shape1->paintedCount = 0;
0049     shape2->paintedCount = 0;
0050     container->paintedCount = 0;
0051 
0052     container->paint(painter);
0053     QCOMPARE(shape1->paintedCount, 0);
0054     QCOMPARE(shape2->paintedCount, 0);
0055     QCOMPARE(container->paintedCount, 1);
0056 
0057 
0058     container->setClipped(shape1, false);
0059     container->setClipped(shape2, true);
0060     QCOMPARE(container->isClipped(shape1), false);
0061     QCOMPARE(container->isClipped(shape2), true);
0062 
0063     shape1->paintedCount = 0;
0064     shape2->paintedCount = 0;
0065     container->paintedCount = 0;
0066     manager.paint(painter);
0067 
0068 
0069     // with this shape not being clipped, the shapeManager will paint the container and this shape
0070     QCOMPARE(shape1->paintedCount, 1);
0071     // with this shape being clipped, the container will paint it for us.
0072     QCOMPARE(shape2->paintedCount, 1);
0073     QCOMPARE(container->paintedCount, 1);
0074 }
0075 
0076 void TestShapePainting::testPaintHiddenShape()
0077 {
0078     QScopedPointer<MockContainer> top(new MockContainer());
0079 
0080     MockShape *shape = new MockShape();
0081     MockContainer *fourth = new MockContainer();
0082     MockContainer *third = new MockContainer();
0083     MockContainer *second = new MockContainer();
0084 
0085 
0086     top->addShape(second);
0087     second->addShape(third);
0088     third->addShape(fourth);
0089     fourth->addShape(shape);
0090 
0091     second->setVisible(false);
0092 
0093     MockCanvas canvas;
0094     KoShapeManager manager(&canvas);
0095     manager.addShape(top.data());
0096     QCOMPARE(manager.shapes().count(), 5);
0097 
0098     QImage image(100, 100,  QImage::Format_Mono);
0099     QPainter painter(&image);
0100     manager.paint(painter);
0101 
0102     QCOMPARE(top->paintedCount, 1);
0103     QCOMPARE(second->paintedCount, 0);
0104     QCOMPARE(third->paintedCount, 0);
0105     QCOMPARE(fourth->paintedCount, 0);
0106     QCOMPARE(shape->paintedCount, 0);
0107 }
0108 
0109 void TestShapePainting::testPaintOrder()
0110 {
0111     // the stacking order determines the painting order so things on top
0112     // get their paint called last.
0113     // Each shape has a zIndex and within the children a container has
0114     // it determines the stacking order. Its important to realize that
0115     // the zIndex is thus local to a container, if you have layer1 and layer2
0116     // with both various child shapes the stacking order of the layer shapes
0117     // is most important, then within this the child shape index is used.
0118 
0119     class OrderedMockShape : public MockShape {
0120     public:
0121         OrderedMockShape(QList<const MockShape*> *list) : order(list) {}
0122         void paint(QPainter &painter) const override {
0123             order->append(this);
0124             MockShape::paint(painter);
0125         }
0126         mutable QList<const MockShape*> *order;
0127     };
0128 
0129     QList<const MockShape*> order;
0130 
0131     {
0132         QScopedPointer<MockContainer> top(new MockContainer());
0133         top->setZIndex(2);
0134         OrderedMockShape *shape1 = new OrderedMockShape(&order);
0135         shape1->setZIndex(5);
0136         OrderedMockShape *shape2 = new OrderedMockShape(&order);
0137         shape2->setZIndex(0);
0138         top->addShape(shape1);
0139         top->addShape(shape2);
0140 
0141         QScopedPointer<MockContainer> bottom(new MockContainer());
0142         bottom->setZIndex(1);
0143         OrderedMockShape *shape3 = new OrderedMockShape(&order);
0144         shape3->setZIndex(-1);
0145         OrderedMockShape *shape4 = new OrderedMockShape(&order);
0146         shape4->setZIndex(9);
0147         bottom->addShape(shape3);
0148         bottom->addShape(shape4);
0149 
0150         MockCanvas canvas;
0151         KoShapeManager manager(&canvas);
0152         manager.addShape(top.data());
0153         manager.addShape(bottom.data());
0154         QCOMPARE(manager.shapes().count(), 6);
0155 
0156         QImage image(100, 100,  QImage::Format_Mono);
0157         QPainter painter(&image);
0158         manager.paint(painter);
0159         QCOMPARE(top->paintedCount, 1);
0160         QCOMPARE(bottom->paintedCount, 1);
0161         QCOMPARE(shape1->paintedCount, 1);
0162         QCOMPARE(shape2->paintedCount, 1);
0163         QCOMPARE(shape3->paintedCount, 1);
0164         QCOMPARE(shape4->paintedCount, 1);
0165 
0166         QCOMPARE(order.count(), 4);
0167         QVERIFY(order[0] == shape3); // lowest first
0168         QVERIFY(order[1] == shape4);
0169         QVERIFY(order[2] == shape2);
0170         QVERIFY(order[3] == shape1);
0171 
0172         // again, with clipping.
0173         order.clear();
0174         painter.setClipRect(0, 0, 100, 100);
0175         manager.paint(painter);
0176         QCOMPARE(top->paintedCount, 2);
0177         QCOMPARE(bottom->paintedCount, 2);
0178         QCOMPARE(shape1->paintedCount, 2);
0179         QCOMPARE(shape2->paintedCount, 2);
0180         QCOMPARE(shape3->paintedCount, 2);
0181         QCOMPARE(shape4->paintedCount, 2);
0182 
0183         QCOMPARE(order.count(), 4);
0184         QVERIFY(order[0] == shape3); // lowest first
0185         QVERIFY(order[1] == shape4);
0186         QVERIFY(order[2] == shape2);
0187         QVERIFY(order[3] == shape1);
0188 
0189     }
0190 
0191     order.clear();
0192 
0193     {
0194         QScopedPointer<MockContainer> root(new MockContainer());
0195         root->setZIndex(0);
0196 
0197         MockContainer *branch1 = new MockContainer();
0198         branch1->setZIndex(1);
0199         OrderedMockShape *child1_1 = new OrderedMockShape(&order);
0200         child1_1->setZIndex(1);
0201         OrderedMockShape *child1_2 = new OrderedMockShape(&order);
0202         child1_2->setZIndex(2);
0203         branch1->addShape(child1_1);
0204         branch1->addShape(child1_2);
0205 
0206         MockContainer *branch2 = new MockContainer();
0207         branch2->setZIndex(2);
0208         OrderedMockShape *child2_1 = new OrderedMockShape(&order);
0209         child2_1->setZIndex(1);
0210         OrderedMockShape *child2_2 = new OrderedMockShape(&order);
0211         child2_2->setZIndex(2);
0212         branch2->addShape(child2_1);
0213         branch2->addShape(child2_2);
0214 
0215         root->addShape(branch1);
0216         root->addShape(branch2);
0217 
0218         QList<KoShape*> sortedShapes;
0219         sortedShapes.append(root.data());
0220         sortedShapes.append(branch1);
0221         sortedShapes.append(branch2);
0222         sortedShapes.append(branch1->shapes());
0223         sortedShapes.append(branch2->shapes());
0224 
0225         std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
0226         QCOMPARE(sortedShapes.count(), 7);
0227         QVERIFY(sortedShapes[0] == root.data());
0228         QVERIFY(sortedShapes[1] == branch1);
0229         QVERIFY(sortedShapes[2] == child1_1);
0230         QVERIFY(sortedShapes[3] == child1_2);
0231         QVERIFY(sortedShapes[4] == branch2);
0232         QVERIFY(sortedShapes[5] == child2_1);
0233         QVERIFY(sortedShapes[6] == child2_2);
0234     }
0235 }
0236 #include <kundo2command.h>
0237 #include <KoShapeController.h>
0238 #include <KoShapeGroupCommand.h>
0239 #include <KoShapeUngroupCommand.h>
0240 #include "kis_debug.h"
0241 void TestShapePainting::testGroupUngroup()
0242 {
0243     MockShapeController controller;
0244     MockCanvas canvas(&controller);
0245 
0246     KoShapeManager *manager = canvas.shapeManager();
0247 
0248     QScopedPointer<MockContainer> shapesFakeLayer(new MockContainer());
0249     shapesFakeLayer->setAssociatedRootShapeManager(manager);
0250 
0251     MockShape *shape1(new MockShape());
0252     MockShape *shape2(new MockShape());
0253     shape1->setName("shape1");
0254     shape2->setName("shape2");
0255     shape1->setParent(shapesFakeLayer.data());
0256     shape2->setParent(shapesFakeLayer.data());
0257 
0258     QList<KoShape*> groupedShapes = {shape1, shape2};
0259 
0260     QImage image(100, 100,  QImage::Format_Mono);
0261     QPainter painter(&image);
0262     painter.setClipRect(image.rect());
0263 
0264     for (int i = 0; i < 3; i++) {
0265         KoShapeGroup *group = new KoShapeGroup();
0266 
0267         {
0268             group->setName("group");
0269 
0270             KUndo2Command groupingCommand;
0271             canvas.shapeController()->addShapeDirect(group, shapesFakeLayer.data(), &groupingCommand);
0272             new KoShapeGroupCommand(group, groupedShapes, true, &groupingCommand);
0273 
0274             groupingCommand.redo();
0275 
0276             manager->paint(painter);
0277 
0278             QCOMPARE(shape1->paintedCount, 2 * i + 1);
0279             QCOMPARE(shape2->paintedCount, 2 * i + 1);
0280             QCOMPARE(manager->shapes().size(), 3);
0281         }
0282 
0283         {
0284             KUndo2Command ungroupingCommand;
0285 
0286             new KoShapeUngroupCommand(group, group->shapes(), QList<KoShape*>(), &ungroupingCommand);
0287             canvas.shapeController()->removeShape(group, &ungroupingCommand);
0288             // NOTE: group will be deleted in ungroupingCommand's d-tor
0289 
0290             ungroupingCommand.redo();
0291 
0292             manager->paint(painter);
0293 
0294             QCOMPARE(shape1->paintedCount, 2 * i + 2);
0295             QCOMPARE(shape2->paintedCount, 2 * i + 2);
0296             QCOMPARE(manager->shapes().size(), 2);
0297         }
0298     }
0299 }
0300 
0301 KISTEST_MAIN(TestShapePainting)