File indexing completed on 2024-12-22 04:10:17

0001 /*
0002  *  SPDX-FileCopyrightText: 2005 Adrian Page <adrian@pagenet.plus.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_image_test.h"
0008 #include <QApplication>
0009 
0010 #include <simpletest.h>
0011 
0012 #include <KoColorSpaceRegistry.h>
0013 #include <KoColorSpace.h>
0014 
0015 #include "filter/kis_filter.h"
0016 #include "filter/kis_filter_configuration.h"
0017 #include "filter/kis_filter_registry.h"
0018 
0019 #include "kis_image.h"
0020 #include "kis_paint_layer.h"
0021 #include "kis_group_layer.h"
0022 #include "kis_adjustment_layer.h"
0023 #include "kis_selection.h"
0024 #include <kis_debug.h>
0025 #include <kis_layer_composition.h>
0026 #include "kis_keyframe_channel.h"
0027 #include "kis_selection_mask.h"
0028 #include "kis_layer_utils.h"
0029 #include "kis_annotation.h"
0030 #include "KisProofingConfiguration.h"
0031 #include <KisGlobalResourcesInterface.h>
0032 #include "KisImageResolutionProxy.h"
0033 #include <commands/kis_deselect_global_selection_command.h>
0034 #include <commands/kis_reselect_global_selection_command.h>
0035 #include <commands/kis_set_global_selection_command.h>
0036 
0037 #include "kis_undo_stores.h"
0038 
0039 #include <testimage.h>
0040 
0041 #define IMAGE_WIDTH 128
0042 #define IMAGE_HEIGHT 128
0043 
0044 void KisImageTest::layerTests()
0045 {
0046     KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests");
0047     QVERIFY(image->rootLayer() != 0);
0048     QVERIFY(image->rootLayer()->firstChild() == 0);
0049 
0050     KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8);
0051     image->addNode(layer);
0052 
0053     QVERIFY(image->rootLayer()->firstChild()->objectName() == layer->objectName());
0054 }
0055 
0056 void KisImageTest::benchmarkCreation()
0057 {
0058     const QRect imageRect(0,0,3000,2000);
0059     const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
0060 
0061     QList<KisImageSP> images;
0062     QList<KisSurrogateUndoStore*> stores;
0063 
0064 
0065     QBENCHMARK {
0066         for (int i = 0; i < 10; i++) {
0067             stores << new KisSurrogateUndoStore();
0068         }
0069 
0070         for (int i = 0; i < 10; i++) {
0071             KisImageSP image = new KisImage(stores.takeLast(), imageRect.width(), imageRect.height(), cs, "test image");
0072             images << image;
0073         }
0074     }
0075 }
0076 
0077 #include <testutil.h>
0078 #include "kis_stroke_strategy.h"
0079 #include <functional>
0080 
0081 
0082 class ForbiddenLodStrokeStrategy : public KisStrokeStrategy
0083 {
0084 public:
0085     ForbiddenLodStrokeStrategy(std::function<void()> lodCallback)
0086         : KisStrokeStrategy(QLatin1String("ForbiddenLodStrokeStrategy")),
0087           m_lodCallback(lodCallback)
0088     {
0089     }
0090 
0091     KisStrokeStrategy* createLodClone(int levelOfDetail) override {
0092         Q_UNUSED(levelOfDetail);
0093         m_lodCallback();
0094         return 0;
0095     }
0096 
0097 private:
0098     std::function<void()> m_lodCallback;
0099 };
0100 
0101 void notifyVar(bool *value) {
0102     *value = true;
0103 }
0104 
0105 void testingSetOldDesiredLevelOfDetail(KisImageSP image, int lod)
0106 {
0107     KisLodPreferences pref(lod);
0108     image->setLodPreferences(pref);
0109 }
0110 
0111 void testingSetOldLevelOfDetailBlocked(KisImageSP image, bool value)
0112 {
0113     if (value) {
0114         testingSetOldDesiredLevelOfDetail(image, 0);
0115     } else {
0116         KisLodPreferences pref(KisLodPreferences::None, 0);
0117         image->setLodPreferences(pref);
0118     }
0119 }
0120 
0121 void KisImageTest::testBlockLevelOfDetail()
0122 {
0123     TestUtil::MaskParent p;
0124 
0125     QCOMPARE(p.image->currentLevelOfDetail(), 0);
0126 
0127     testingSetOldDesiredLevelOfDetail(p.image, 1);
0128     p.image->waitForDone();
0129 
0130     QCOMPARE(p.image->currentLevelOfDetail(), 0);
0131 
0132     {
0133         bool lodCreated = false;
0134         KisStrokeId id = p.image->startStroke(
0135             new ForbiddenLodStrokeStrategy(
0136                 std::bind(&notifyVar, &lodCreated)));
0137         p.image->endStroke(id);
0138         p.image->waitForDone();
0139 
0140         QVERIFY(lodCreated);
0141     }
0142 
0143     testingSetOldLevelOfDetailBlocked(p.image, true);
0144 
0145     {
0146         bool lodCreated = false;
0147         KisStrokeId id = p.image->startStroke(
0148             new ForbiddenLodStrokeStrategy(
0149                 std::bind(&notifyVar, &lodCreated)));
0150         p.image->endStroke(id);
0151         p.image->waitForDone();
0152 
0153         QVERIFY(!lodCreated);
0154     }
0155 
0156     testingSetOldLevelOfDetailBlocked(p.image, false);
0157     testingSetOldDesiredLevelOfDetail(p.image, 1);
0158 
0159     {
0160         bool lodCreated = false;
0161         KisStrokeId id = p.image->startStroke(
0162             new ForbiddenLodStrokeStrategy(
0163                 std::bind(&notifyVar, &lodCreated)));
0164         p.image->endStroke(id);
0165         p.image->waitForDone();
0166 
0167         QVERIFY(lodCreated);
0168     }
0169 }
0170 
0171 void KisImageTest::testConvertImageColorSpace()
0172 {
0173     const KoColorSpace *cs8 = KoColorSpaceRegistry::instance()->rgb8();
0174     KisImageSP image = new KisImage(0, 1000, 1000, cs8, "stest");
0175 
0176     KisPaintDeviceSP device1 = new KisPaintDevice(cs8);
0177     KisLayerSP paint1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1);
0178 
0179     KisFilterSP filter = KisFilterRegistry::instance()->value("blur");
0180     Q_ASSERT(filter);
0181     KisFilterConfigurationSP configuration = filter->defaultConfiguration(KisGlobalResourcesInterface::instance());
0182     Q_ASSERT(configuration);
0183 
0184     KisLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration->cloneWithResourcesSnapshot(), 0);
0185 
0186     image->addNode(paint1, image->root());
0187     image->addNode(blur1, image->root());
0188 
0189     image->refreshGraph();
0190 
0191     const KoColorSpace *cs16 = KoColorSpaceRegistry::instance()->rgb16();
0192     image->convertImageColorSpace(cs16,
0193                                   KoColorConversionTransformation::internalRenderingIntent(),
0194                                   KoColorConversionTransformation::internalConversionFlags());
0195     image->waitForDone();
0196 
0197     QVERIFY(*cs16 == *image->colorSpace());
0198     QVERIFY(*cs16 == *image->root()->colorSpace());
0199     QVERIFY(*cs16 == *paint1->colorSpace());
0200     QVERIFY(*cs16 == *blur1->colorSpace());
0201 
0202     QVERIFY(!image->root()->compositeOp());
0203     QVERIFY(*cs16 == *paint1->compositeOp()->colorSpace());
0204     QVERIFY(*cs16 == *blur1->compositeOp()->colorSpace());
0205 
0206     image->refreshGraph();
0207 }
0208 
0209 void KisImageTest::testAssignImageProfile()
0210 {
0211     const KoColorSpace *rgb8 = KoColorSpaceRegistry::instance()->rgb8();
0212     const KoColorSpace *gray8 = KoColorSpaceRegistry::instance()->graya8();
0213     KisImageSP image = new KisImage(0, 1000, 1000, rgb8, "stest");
0214 
0215     KisPaintDeviceSP device1 = new KisPaintDevice(rgb8);
0216     KisLayerSP paint1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1);
0217 
0218     KisPaintDeviceSP device2 = new KisPaintDevice(gray8);
0219     KisLayerSP paint2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8, device2);
0220 
0221 
0222     KisFilterSP filter = KisFilterRegistry::instance()->value("blur");
0223     Q_ASSERT(filter);
0224     KisFilterConfigurationSP configuration = filter->defaultConfiguration(KisGlobalResourcesInterface::instance());
0225     Q_ASSERT(configuration);
0226 
0227     KisLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration->cloneWithResourcesSnapshot(), 0);
0228 
0229     image->addNode(paint1, image->root());
0230     image->addNode(paint2, image->root());
0231     image->addNode(blur1, image->root());
0232 
0233     QCOMPARE(*image->colorSpace(), *rgb8);
0234     QCOMPARE(*image->colorSpace()->profile(), *KoColorSpaceRegistry::instance()->p709SRGBProfile());
0235 
0236     QCOMPARE(*paint1->colorSpace(), *rgb8);
0237     QCOMPARE(*paint1->colorSpace()->profile(), *KoColorSpaceRegistry::instance()->p709SRGBProfile());
0238 
0239     QCOMPARE(*paint2->colorSpace(), *gray8);
0240 
0241     QCOMPARE(*blur1->colorSpace(), *rgb8);
0242     QCOMPARE(*blur1->colorSpace()->profile(), *KoColorSpaceRegistry::instance()->p709SRGBProfile());
0243 
0244 
0245     image->assignImageProfile(KoColorSpaceRegistry::instance()->p2020G10Profile());
0246     image->waitForDone();
0247 
0248     QVERIFY(*image->colorSpace() != *rgb8);
0249     QCOMPARE(*image->colorSpace()->profile(), *KoColorSpaceRegistry::instance()->p2020G10Profile());
0250 
0251     QVERIFY(*paint1->colorSpace() != *rgb8);
0252     QCOMPARE(*paint1->colorSpace()->profile(), *KoColorSpaceRegistry::instance()->p2020G10Profile());
0253 
0254     QCOMPARE(*paint2->colorSpace(), *gray8);
0255 
0256     QVERIFY(*blur1->colorSpace() != *rgb8);
0257     QCOMPARE(*blur1->colorSpace()->profile(), *KoColorSpaceRegistry::instance()->p2020G10Profile());
0258 }
0259 
0260 void KisImageTest::testGlobalSelection()
0261 {
0262     const KoColorSpace *cs8 = KoColorSpaceRegistry::instance()->rgb8();
0263     KisImageSP image = new KisImage(0, 1000, 1000, cs8, "stest");
0264 
0265     QCOMPARE(image->globalSelection(), KisSelectionSP(0));
0266     QCOMPARE(image->canReselectGlobalSelection(), false);
0267     QCOMPARE(image->root()->childCount(), 0U);
0268 
0269     KisSelectionSP selection1 = new KisSelection(new KisDefaultBounds(image), toQShared(new KisImageResolutionProxy(image)));
0270     KisSelectionSP selection2 = new KisSelection(new KisDefaultBounds(image), toQShared(new KisImageResolutionProxy(image)));
0271     KisSelectionSP selection3 = new KisSelection(new KisDefaultBounds(image), toQShared(new KisImageResolutionProxy(image)));
0272 
0273     image->undoAdapter()->addCommand(new KisSetGlobalSelectionCommand(image, selection1));
0274     QCOMPARE(image->globalSelection(), selection1);
0275     QCOMPARE(image->canReselectGlobalSelection(), false);
0276     QCOMPARE(image->root()->childCount(), 1U);
0277 
0278     image->undoAdapter()->addCommand(new KisSetGlobalSelectionCommand(image, selection2));
0279     QCOMPARE(image->globalSelection(), selection2);
0280     QCOMPARE(image->canReselectGlobalSelection(), false);
0281     QCOMPARE(image->root()->childCount(), 1U);
0282 
0283     image->undoAdapter()->addCommand(new KisDeselectGlobalSelectionCommand(image));
0284     QCOMPARE(image->globalSelection(), KisSelectionSP(0));
0285     QCOMPARE(image->canReselectGlobalSelection(), true);
0286     QCOMPARE(image->root()->childCount(), 0U);
0287 
0288     image->undoAdapter()->addCommand(new KisReselectGlobalSelectionCommand(image));
0289     QCOMPARE(image->globalSelection(), selection2);
0290     QCOMPARE(image->canReselectGlobalSelection(), false);
0291     QCOMPARE(image->root()->childCount(), 1U);
0292 
0293     // mixed deselecting/setting/reselecting
0294 
0295     image->undoAdapter()->addCommand(new KisDeselectGlobalSelectionCommand(image));
0296     QCOMPARE(image->globalSelection(), KisSelectionSP(0));
0297     QCOMPARE(image->canReselectGlobalSelection(), true);
0298     QCOMPARE(image->root()->childCount(), 0U);
0299 
0300     image->undoAdapter()->addCommand(new KisSetGlobalSelectionCommand(image, selection3));
0301     QCOMPARE(image->globalSelection(), selection3);
0302     QCOMPARE(image->canReselectGlobalSelection(), false);
0303     QCOMPARE(image->root()->childCount(), 1U);
0304 }
0305 
0306 void KisImageTest::testCloneImage()
0307 {
0308     KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests");
0309     QVERIFY(image->rootLayer() != 0);
0310     QVERIFY(image->rootLayer()->firstChild() == 0);
0311 
0312     KisAnnotationSP annotation = new KisAnnotation("mytype", "mydescription", QByteArray());
0313     image->addAnnotation(annotation);
0314     QVERIFY(image->annotation("mytype"));
0315 
0316     KisProofingConfigurationSP proofing = toQShared(new KisProofingConfiguration());
0317     image->setProofingConfiguration(proofing);
0318     QVERIFY(image->proofingConfiguration());
0319 
0320     const KoColor defaultColor(Qt::green, image->colorSpace());
0321     image->setDefaultProjectionColor(defaultColor);
0322     QCOMPARE(image->defaultProjectionColor(), defaultColor);
0323 
0324     KisLayerSP layer = new KisPaintLayer(image, "layer1", OPACITY_OPAQUE_U8);
0325     image->addNode(layer);
0326     KisLayerSP layer2 = new KisPaintLayer(image, "layer2", OPACITY_OPAQUE_U8);
0327     image->addNode(layer2);
0328 
0329     QVERIFY(layer->visible());
0330     QVERIFY(layer2->visible());
0331 
0332     QVERIFY(TestUtil::findNode(image->root(), "layer1"));
0333     QVERIFY(TestUtil::findNode(image->root(), "layer2"));
0334 
0335     QUuid uuid1 = layer->uuid();
0336     QUuid uuid2 = layer2->uuid();
0337 
0338     {
0339         KisImageSP newImage = image->clone();
0340 
0341         KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1");
0342         KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2");
0343 
0344         QVERIFY(newLayer1);
0345         QVERIFY(newLayer2);
0346 
0347         QVERIFY(newLayer1->uuid() != uuid1);
0348         QVERIFY(newLayer2->uuid() != uuid2);
0349 
0350         KisAnnotationSP newAnnotation = newImage->annotation("mytype");
0351         QVERIFY(newAnnotation);
0352         QVERIFY(newAnnotation != annotation);
0353 
0354 
0355         KisProofingConfigurationSP newProofing = newImage->proofingConfiguration();
0356         QVERIFY(newProofing);
0357         QVERIFY(newProofing != proofing);
0358 
0359         QCOMPARE(newImage->defaultProjectionColor(), defaultColor);
0360     }
0361 
0362     {
0363         KisImageSP newImage = image->clone(true);
0364 
0365         KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1");
0366         KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2");
0367 
0368         QVERIFY(newLayer1);
0369         QVERIFY(newLayer2);
0370 
0371         QVERIFY(newLayer1->uuid() == uuid1);
0372         QVERIFY(newLayer2->uuid() == uuid2);
0373     }
0374 }
0375 
0376 void KisImageTest::testLayerComposition()
0377 {
0378     KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests");
0379     QVERIFY(image->rootLayer() != 0);
0380     QVERIFY(image->rootLayer()->firstChild() == 0);
0381 
0382     KisLayerSP layer = new KisPaintLayer(image, "layer1", OPACITY_OPAQUE_U8);
0383     image->addNode(layer);
0384     KisLayerSP layer2 = new KisPaintLayer(image, "layer2", OPACITY_OPAQUE_U8);
0385     image->addNode(layer2);
0386 
0387     QVERIFY(layer->visible());
0388     QVERIFY(layer2->visible());
0389 
0390     KisLayerComposition comp(image, "comp 1");
0391     comp.store();
0392 
0393     layer2->setVisible(false);
0394 
0395     QVERIFY(layer->visible());
0396     QVERIFY(!layer2->visible());
0397 
0398     KisLayerComposition comp2(image, "comp 2");
0399     comp2.store();
0400 
0401     KisLayerCompositionSP comp3 = toQShared(new KisLayerComposition(image, "comp 3"));
0402     comp3->store();
0403     image->addComposition(comp3);
0404 
0405     comp.apply();
0406 
0407     QVERIFY(layer->visible());
0408     QVERIFY(layer2->visible());
0409 
0410     comp2.apply();
0411 
0412     QVERIFY(layer->visible());
0413     QVERIFY(!layer2->visible());
0414 
0415     comp.apply();
0416 
0417     QVERIFY(layer->visible());
0418     QVERIFY(layer2->visible());
0419 
0420     KisImageSP newImage = image->clone();
0421 
0422     KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1");
0423     KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2");
0424 
0425     QVERIFY(newLayer1);
0426     QVERIFY(newLayer2);
0427 
0428     QVERIFY(newLayer1->visible());
0429     QVERIFY(newLayer2->visible());
0430 
0431     KisLayerComposition newComp1(comp, newImage);
0432     newComp1.apply();
0433     QVERIFY(newLayer1->visible());
0434     QVERIFY(newLayer2->visible());
0435 
0436     KisLayerComposition newComp2(comp2, newImage);
0437     newComp2.apply();
0438     QVERIFY(newLayer1->visible());
0439     QVERIFY(!newLayer2->visible());
0440 
0441     newComp1.apply();
0442     QVERIFY(newLayer1->visible());
0443     QVERIFY(newLayer2->visible());
0444 
0445     QVERIFY(!newImage->compositions().isEmpty());
0446     KisLayerCompositionSP newComp3 = newImage->compositions().first();
0447     newComp3->apply();
0448     QVERIFY(newLayer1->visible());
0449     QVERIFY(!newLayer2->visible());
0450 }
0451 
0452 #include "kis_transparency_mask.h"
0453 #include "kis_psd_layer_style.h"
0454 
0455 struct FlattenTestImage
0456 {
0457     FlattenTestImage()
0458         : refRect(0,0,512,512)
0459         , p(refRect)
0460     {
0461 
0462         image = p.image;
0463         undoStore = p.undoStore;
0464         layer1 = p.layer;
0465 
0466         layer5 = new KisPaintLayer(p.image, "paint5", 0.4 * OPACITY_OPAQUE_U8);
0467         layer5->disableAlphaChannel(true);
0468 
0469         layer2 = new KisPaintLayer(p.image, "paint2", OPACITY_OPAQUE_U8);
0470         tmask = new KisTransparencyMask(p.image, "tmask");
0471 
0472         // check channel flags
0473         // make addition composite op
0474         group1 = new KisGroupLayer(p.image, "group1", OPACITY_OPAQUE_U8);
0475         layer3 = new KisPaintLayer(p.image, "paint3", OPACITY_OPAQUE_U8);
0476         layer4 = new KisPaintLayer(p.image, "paint4", OPACITY_OPAQUE_U8);
0477 
0478         layer6 = new KisPaintLayer(p.image, "paint6", OPACITY_OPAQUE_U8);
0479 
0480         layer7 = new KisPaintLayer(p.image, "paint7", OPACITY_OPAQUE_U8);
0481         layer8 = new KisPaintLayer(p.image, "paint8", OPACITY_OPAQUE_U8);
0482         layer7->setCompositeOpId(COMPOSITE_ADD);
0483         layer8->setCompositeOpId(COMPOSITE_ADD);
0484 
0485         QRect rect1(100, 100, 100, 100);
0486         QRect rect2(150, 150, 150, 150);
0487         QRect tmaskRect(200,200,100,100);
0488 
0489         QRect rect3(400, 100, 100, 100);
0490         QRect rect4(500, 100, 100, 100);
0491 
0492         QRect rect5(50, 50, 100, 100);
0493 
0494         QRect rect6(50, 250, 100, 100);
0495 
0496         QRect rect7(50, 350, 50, 50);
0497         QRect rect8(50, 400, 50, 50);
0498 
0499         layer1->paintDevice()->fill(rect1, KoColor(Qt::red, p.image->colorSpace()));
0500 
0501         layer2->paintDevice()->fill(rect2, KoColor(Qt::green, p.image->colorSpace()));
0502         tmask->testingInitSelection(tmaskRect, layer2);
0503 
0504         layer3->paintDevice()->fill(rect3, KoColor(Qt::blue, p.image->colorSpace()));
0505         layer4->paintDevice()->fill(rect4, KoColor(Qt::yellow, p.image->colorSpace()));
0506         layer5->paintDevice()->fill(rect5, KoColor(Qt::green, p.image->colorSpace()));
0507 
0508         layer6->paintDevice()->fill(rect6, KoColor(Qt::cyan, p.image->colorSpace()));
0509 
0510         layer7->paintDevice()->fill(rect7, KoColor(Qt::red, p.image->colorSpace()));
0511         layer8->paintDevice()->fill(rect8, KoColor(Qt::green, p.image->colorSpace()));
0512 
0513         KisPSDLayerStyleSP style(new KisPSDLayerStyle());
0514         style->dropShadow()->setEffectEnabled(true);
0515         style->dropShadow()->setDistance(10.0);
0516         style->dropShadow()->setSpread(80.0);
0517         style->dropShadow()->setSize(10);
0518         style->dropShadow()->setNoise(0);
0519         style->dropShadow()->setKnocksOut(false);
0520         style->dropShadow()->setOpacity(80.0);
0521         layer2->setLayerStyle(style);
0522 
0523         layer2->setCompositeOpId(COMPOSITE_ADD);
0524         group1->setCompositeOpId(COMPOSITE_ADD);
0525 
0526         p.image->addNode(layer5);
0527 
0528         p.image->addNode(layer2);
0529         p.image->addNode(tmask, layer2);
0530 
0531         p.image->addNode(group1);
0532         p.image->addNode(layer3, group1);
0533         p.image->addNode(layer4, group1);
0534 
0535         p.image->addNode(layer6);
0536 
0537         p.image->addNode(layer7);
0538         p.image->addNode(layer8);
0539 
0540         p.image->initialRefreshGraph();
0541 
0542         // dbgKrita << ppVar(layer1->exactBounds());
0543         // dbgKrita << ppVar(layer5->exactBounds());
0544         // dbgKrita << ppVar(layer2->exactBounds());
0545         // dbgKrita << ppVar(group1->exactBounds());
0546         // dbgKrita << ppVar(layer3->exactBounds());
0547         // dbgKrita << ppVar(layer4->exactBounds());
0548 
0549         TestUtil::ReferenceImageChecker chk("flatten", "imagetest");
0550         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
0551     }
0552 
0553     QRect refRect;
0554     TestUtil::MaskParent p;
0555 
0556     KisImageSP image;
0557     KisSurrogateUndoStore *undoStore;
0558     KisPaintLayerSP layer1;
0559 
0560     KisPaintLayerSP layer2;
0561     KisTransparencyMaskSP tmask;
0562 
0563     KisGroupLayerSP group1;
0564     KisPaintLayerSP layer3;
0565     KisPaintLayerSP layer4;
0566 
0567     KisPaintLayerSP layer5;
0568 
0569     KisPaintLayerSP layer6;
0570 
0571     KisPaintLayerSP layer7;
0572     KisPaintLayerSP layer8;
0573 };
0574 
0575 template<class ContainerTest>
0576 KisLayerSP flattenLayerHelper(ContainerTest &p, KisLayerSP layer, bool nothingHappens = false)
0577 {
0578     QSignalSpy spy(p.image.data(), SIGNAL(sigNodeAddedAsync(KisNodeSP)));
0579 
0580     //p.image->flattenLayer(layer);
0581     KisLayerUtils::flattenLayer(p.image, layer);
0582     p.image->waitForDone();
0583 
0584     if (nothingHappens) {
0585         Q_ASSERT(!spy.count());
0586         return layer;
0587     }
0588 
0589     Q_ASSERT(spy.count() == 1);
0590     QList<QVariant> arguments = spy.takeFirst();
0591     KisNodeSP newNode = arguments.first().value<KisNodeSP>();
0592 
0593     KisLayerSP newLayer = qobject_cast<KisLayer*>(newNode.data());
0594     return newLayer;
0595 }
0596 
0597 void KisImageTest::testFlattenLayer()
0598 {
0599     FlattenTestImage p;
0600 
0601     TestUtil::ReferenceImageChecker chk("flatten", "imagetest");
0602 
0603     {
0604         QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD);
0605 
0606         KisLayerSP newLayer = flattenLayerHelper(p, p.layer2);
0607 
0608         //KisLayerSP newLayer = p.image->flattenLayer(p.layer2);
0609         //p.image->waitForDone();
0610 
0611         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
0612         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer2_layerproj"));
0613 
0614         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0615     }
0616 
0617     {
0618         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD);
0619 
0620         KisLayerSP newLayer = flattenLayerHelper(p, p.group1);
0621 
0622         //KisLayerSP newLayer = p.image->flattenLayer(p.group1);
0623         //p.image->waitForDone();
0624 
0625         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
0626         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "02_group1_layerproj"));
0627 
0628         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_ADD);
0629         QCOMPARE(newLayer->exactBounds(), QRect(400, 100, 200, 100));
0630     }
0631 
0632     {
0633         QCOMPARE(p.layer5->compositeOpId(), COMPOSITE_OVER);
0634         QCOMPARE(p.layer5->alphaChannelDisabled(), true);
0635 
0636         KisLayerSP newLayer = flattenLayerHelper(p, p.layer5, true);
0637 
0638         //KisLayerSP newLayer = p.image->flattenLayer(p.layer5);
0639         //p.image->waitForDone();
0640 
0641         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
0642         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "03_layer5_layerproj"));
0643 
0644         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0645         QCOMPARE(newLayer->exactBounds(), QRect(50, 50, 100, 100));
0646 
0647         QCOMPARE(newLayer->alphaChannelDisabled(), true);
0648     }
0649 }
0650 
0651 #include <kis_meta_data_merge_strategy_registry.h>
0652 
0653 template<class ContainerTest>
0654 KisLayerSP mergeHelper(ContainerTest &p, KisLayerSP layer)
0655 {
0656     KisNodeSP parent = layer->parent();
0657     const int newIndex = parent->index(layer) - 1;
0658 
0659     p.image->mergeDown(layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
0660 
0661     //KisLayerUtils::mergeDown(p.image, layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
0662     p.image->waitForDone();
0663 
0664     KisLayerSP newLayer = qobject_cast<KisLayer*>(parent->at(newIndex).data());
0665     return newLayer;
0666 }
0667 
0668 void KisImageTest::testMergeDown()
0669 {
0670     FlattenTestImage p;
0671 
0672     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0673     TestUtil::ReferenceImageChecker chk("mergedown_simple", "imagetest");
0674 
0675 
0676     {
0677         QCOMPARE(p.layer5->compositeOpId(), COMPOSITE_OVER);
0678         QCOMPARE(p.layer5->alphaChannelDisabled(), true);
0679 
0680         KisLayerSP newLayer = mergeHelper(p, p.layer5);
0681 
0682         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0683         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer5_layerproj"));
0684 
0685         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0686         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0687     }
0688 
0689     {
0690         QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD);
0691         QCOMPARE(p.layer2->alphaChannelDisabled(), false);
0692 
0693         KisLayerSP newLayer = mergeHelper(p, p.layer2);
0694 
0695         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0696         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "02_layer2_layerproj"));
0697 
0698         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0699         QCOMPARE(newLayer->exactBounds(), QRect(100, 100, 213, 217));
0700         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0701     }
0702 
0703     {
0704         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD);
0705         QCOMPARE(p.group1->alphaChannelDisabled(), false);
0706 
0707         KisLayerSP newLayer = mergeHelper(p, p.group1);
0708 
0709         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0710         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "03_group1_mergedown_layerproj"));
0711 
0712         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0713         QCOMPARE(newLayer->exactBounds(), QRect(100, 100, 500, 217));
0714         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0715     }
0716 }
0717 
0718 void KisImageTest::testMergeDownDestinationInheritsAlpha()
0719 {
0720     FlattenTestImage p;
0721 
0722     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0723     TestUtil::ReferenceImageChecker chk("mergedown_dst_inheritsalpha", "imagetest");
0724 
0725     {
0726         QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD);
0727         QCOMPARE(p.layer2->alphaChannelDisabled(), false);
0728 
0729         KisLayerSP newLayer = mergeHelper(p, p.layer2);
0730 
0731         // WARN: this check is suspicious!
0732         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_proj_merged_layer2_over_layer5_IA"));
0733         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer2_layerproj"));
0734 
0735         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0736         QCOMPARE(newLayer->exactBounds(), QRect(50,50, 263, 267));
0737         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0738     }
0739 }
0740 
0741 void KisImageTest::testMergeDownDestinationCustomCompositeOp()
0742 {
0743     FlattenTestImage p;
0744 
0745     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0746     TestUtil::ReferenceImageChecker chk("mergedown_dst_customop", "imagetest");
0747 
0748     {
0749         QCOMPARE(p.layer6->compositeOpId(), COMPOSITE_OVER);
0750         QCOMPARE(p.layer6->alphaChannelDisabled(), false);
0751 
0752         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD);
0753         QCOMPARE(p.group1->alphaChannelDisabled(), false);
0754 
0755         KisLayerSP newLayer = mergeHelper(p, p.layer6);
0756 
0757         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0758         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer6_layerproj"));
0759 
0760         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0761         QCOMPARE(newLayer->exactBounds(), QRect(50, 100, 550, 250));
0762         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0763     }
0764 }
0765 
0766 void KisImageTest::testMergeDownDestinationSameCompositeOpLayerStyle()
0767 {
0768     FlattenTestImage p;
0769 
0770     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0771     TestUtil::ReferenceImageChecker chk("mergedown_sameop_ls", "imagetest");
0772 
0773     {
0774         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD);
0775         QCOMPARE(p.group1->alphaChannelDisabled(), false);
0776 
0777         QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD);
0778         QCOMPARE(p.layer2->alphaChannelDisabled(), false);
0779 
0780         KisLayerSP newLayer = mergeHelper(p, p.group1);
0781 
0782         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0783         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_group1_layerproj"));
0784 
0785         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0786         QCOMPARE(newLayer->exactBounds(), QRect(197, 100, 403, 217));
0787         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0788     }
0789 }
0790 
0791 void KisImageTest::testMergeDownDestinationSameCompositeOp()
0792 {
0793     FlattenTestImage p;
0794 
0795     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0796     TestUtil::ReferenceImageChecker chk("mergedown_sameop_fastpath", "imagetest");
0797 
0798     {
0799         QCOMPARE(p.layer8->compositeOpId(), COMPOSITE_ADD);
0800         QCOMPARE(p.layer8->alphaChannelDisabled(), false);
0801 
0802         QCOMPARE(p.layer7->compositeOpId(), COMPOSITE_ADD);
0803         QCOMPARE(p.layer7->alphaChannelDisabled(), false);
0804 
0805         KisLayerSP newLayer = mergeHelper(p, p.layer8);
0806 
0807         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0808         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer8_layerproj"));
0809 
0810         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_ADD);
0811         QCOMPARE(newLayer->exactBounds(), QRect(50, 350, 50, 100));
0812         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0813     }
0814 }
0815 #include "kis_image_animation_interface.h"
0816 void KisImageTest::testMergeDownMultipleFrames()
0817 {
0818     FlattenTestImage p;
0819 
0820     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0821     TestUtil::ReferenceImageChecker chk("mergedown_simple", "imagetest");
0822 
0823     QSet<int> initialFrames;
0824     {
0825         KisLayerSP l = p.layer5;
0826         l->enableAnimation();
0827         KisKeyframeChannel *channel = l->getKeyframeChannel(KisKeyframeChannel::Raster.id(), true);
0828         channel->addKeyframe(10);
0829         channel->addKeyframe(20);
0830         channel->addKeyframe(30);
0831 
0832         QCOMPARE(channel->keyframeCount(), 4);
0833         initialFrames = KisLayerUtils::fetchLayerFramesRecursive(l);
0834         QCOMPARE(initialFrames.size(), 4);
0835     }
0836 
0837     {
0838         QCOMPARE(p.layer5->compositeOpId(), COMPOSITE_OVER);
0839         QCOMPARE(p.layer5->alphaChannelDisabled(), true);
0840 
0841         KisLayerSP newLayer = mergeHelper(p, p.layer5);
0842 
0843         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0844         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer5_layerproj"));
0845 
0846         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0847         QCOMPARE(newLayer->alphaChannelDisabled(), false);
0848 
0849         QVERIFY(newLayer->isAnimated());
0850 
0851         QSet<int> newFrames = KisLayerUtils::fetchLayerFramesRecursive(newLayer);
0852         QCOMPARE(newFrames, initialFrames);
0853 
0854         foreach (int frame, newFrames) {
0855             KisImageAnimationInterface *interface = p.image->animationInterface();
0856             int savedSwitchedTime = 0;
0857             interface->saveAndResetCurrentTime(frame, &savedSwitchedTime);
0858             QCOMPARE(newLayer->exactBounds(), QRect(100,100,100,100));
0859             interface->restoreCurrentTime(&savedSwitchedTime);
0860         }
0861 
0862         p.undoStore->undo();
0863         p.image->waitForDone();
0864 
0865          QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0866     }
0867 }
0868 
0869 template<class ContainerTest>
0870 KisNodeSP mergeMultipleHelper(ContainerTest &p, QList<KisNodeSP> selectedNodes, KisNodeSP putAfter)
0871 {
0872     QSignalSpy spy(p.image.data(), SIGNAL(sigNodeAddedAsync(KisNodeSP)));
0873 
0874     p.image->mergeMultipleLayers(selectedNodes, putAfter);
0875     //KisLayerUtils::mergeMultipleLayers(p.image, selectedNodes, putAfter);
0876     p.image->waitForDone();
0877 
0878     Q_ASSERT(spy.count() == 1);
0879     QList<QVariant> arguments = spy.takeFirst();
0880     KisNodeSP newNode = arguments.first().value<KisNodeSP>();
0881     return newNode;
0882 }
0883 void KisImageTest::testMergeMultiple()
0884 {
0885     FlattenTestImage p;
0886 
0887     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
0888     TestUtil::ReferenceImageChecker chk("mergemultiple", "imagetest");
0889 
0890     {
0891         QList<KisNodeSP> selectedNodes;
0892 
0893         selectedNodes << p.layer2
0894                       << p.group1
0895                       << p.layer6;
0896 
0897         {
0898             KisNodeSP newLayer = mergeMultipleHelper(p, selectedNodes, 0);
0899 
0900             //KisNodeSP newLayer = p.image->mergeMultipleLayers(selectedNodes, 0);
0901             //p.image->waitForDone();
0902 
0903             QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0904             QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer8_layerproj"));
0905 
0906             QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0907             QCOMPARE(newLayer->exactBounds(), QRect(50, 100, 550, 250));
0908         }
0909     }
0910 
0911     p.p.undoStore->undo();
0912     p.image->waitForDone();
0913 
0914 
0915     // Test reversed order, the result must be the same
0916 
0917     {
0918         QList<KisNodeSP> selectedNodes;
0919 
0920         selectedNodes << p.layer6
0921                       << p.group1
0922                       << p.layer2;
0923 
0924         {
0925             KisNodeSP newLayer = mergeMultipleHelper(p, selectedNodes, 0);
0926 
0927             //KisNodeSP newLayer = p.image->mergeMultipleLayers(selectedNodes, 0);
0928             //p.image->waitForDone();
0929 
0930             QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
0931             QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer8_layerproj"));
0932 
0933             QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
0934             QCOMPARE(newLayer->exactBounds(), QRect(50, 100, 550, 250));
0935         }
0936     }
0937 
0938 }
0939 
0940 void testMergeCrossColorSpaceImpl(bool useProjectionColorSpace, bool swapSpaces)
0941 {
0942     TestUtil::MaskParent p;
0943 
0944     KisPaintLayerSP layer1;
0945     KisPaintLayerSP layer2;
0946     KisPaintLayerSP layer3;
0947 
0948     const KoColorSpace *cs2 = useProjectionColorSpace ?
0949         p.image->colorSpace() : KoColorSpaceRegistry::instance()->lab16();
0950 
0951     const KoColorSpace *cs3 = KoColorSpaceRegistry::instance()->rgb16();
0952 
0953     if (swapSpaces) {
0954         std::swap(cs2, cs3);
0955     }
0956 
0957     dbgKrita << "Testing testMergeCrossColorSpaceImpl:";
0958     dbgKrita << "    " << ppVar(cs2);
0959     dbgKrita << "    " << ppVar(cs3);
0960 
0961     layer1 = p.layer;
0962     layer2 = new KisPaintLayer(p.image, "paint2", OPACITY_OPAQUE_U8, cs2);
0963     layer3 = new KisPaintLayer(p.image, "paint3", OPACITY_OPAQUE_U8, cs3);
0964 
0965     QRect rect1(100, 100, 100, 100);
0966     QRect rect2(150, 150, 150, 150);
0967     QRect rect3(250, 250, 200, 200);
0968 
0969     layer1->paintDevice()->fill(rect1, KoColor(Qt::red, layer1->colorSpace()));
0970     layer2->paintDevice()->fill(rect2, KoColor(Qt::green, layer2->colorSpace()));
0971     layer3->paintDevice()->fill(rect3, KoColor(Qt::blue, layer3->colorSpace()));
0972 
0973     p.image->addNode(layer2);
0974     p.image->addNode(layer3);
0975 
0976     p.image->initialRefreshGraph();
0977 
0978     {
0979         KisLayerSP newLayer = mergeHelper(p, layer3);
0980 
0981         QCOMPARE(newLayer->colorSpace(), p.image->colorSpace());
0982 
0983         p.undoStore->undo();
0984         p.image->waitForDone();
0985     }
0986 
0987     {
0988         layer2->disableAlphaChannel(true);
0989 
0990         KisLayerSP newLayer = mergeHelper(p, layer3);
0991 
0992         QCOMPARE(newLayer->colorSpace(), p.image->colorSpace());
0993 
0994         p.undoStore->undo();
0995         p.image->waitForDone();
0996     }
0997 }
0998 
0999 void KisImageTest::testMergeCrossColorSpace()
1000 {
1001     testMergeCrossColorSpaceImpl(true, false);
1002     testMergeCrossColorSpaceImpl(true, true);
1003     testMergeCrossColorSpaceImpl(false, false);
1004     testMergeCrossColorSpaceImpl(false, true);
1005 }
1006 
1007 void KisImageTest::testMergeSelectionMasks()
1008 {
1009     TestUtil::MaskParent p;
1010 
1011     QRect rect1(100, 100, 100, 100);
1012     QRect rect2(150, 150, 150, 150);
1013     QRect rect3(50, 50, 100, 100);
1014 
1015     KisPaintLayerSP layer1 = p.layer;
1016     layer1->paintDevice()->fill(rect1, KoColor(Qt::red, layer1->colorSpace()));
1017 
1018     p.image->initialRefreshGraph();
1019 
1020     KisSelectionSP sel = new KisSelection(layer1->paintDevice()->defaultBounds(), toQShared(new KisImageResolutionProxy(p.image)));
1021 
1022     sel->pixelSelection()->select(rect2, MAX_SELECTED);
1023     KisSelectionMaskSP mask1 = new KisSelectionMask(p.image);
1024     mask1->initSelection(sel, layer1);
1025     p.image->addNode(mask1, layer1);
1026 
1027     QVERIFY(!layer1->selection());
1028 
1029     mask1->setActive(true);
1030 
1031     QCOMPARE(layer1->selection()->selectedExactRect(), QRect(150,150,150,150));
1032 
1033     sel->pixelSelection()->select(rect3, MAX_SELECTED);
1034     KisSelectionMaskSP mask2 = new KisSelectionMask(p.image);
1035     mask2->initSelection(sel, layer1);
1036     p.image->addNode(mask2, layer1);
1037 
1038     QCOMPARE(layer1->selection()->selectedExactRect(), QRect(150,150,150,150));
1039 
1040     mask2->setActive(true);
1041 
1042     QCOMPARE(layer1->selection()->selectedExactRect(), QRect(50,50,250,250));
1043 
1044     QList<KisNodeSP> selectedNodes;
1045 
1046     selectedNodes << mask2
1047                   << mask1;
1048 
1049     {
1050         KisNodeSP newLayer = mergeMultipleHelper(p, selectedNodes, 0);
1051         QCOMPARE(newLayer->parent(), KisNodeSP(layer1));
1052         QCOMPARE((int)layer1->childCount(), 1);
1053         QCOMPARE(layer1->selection()->selectedExactRect(), QRect(50,50,250,250));
1054     }
1055 }
1056 
1057 void KisImageTest::testFlattenImage()
1058 {
1059     FlattenTestImage p;
1060     KisImageSP image = p.image;
1061 
1062     TestUtil::ReferenceImageChecker img("flatten", "imagetest");
1063 
1064     {
1065         KisLayerUtils::flattenImage(p.image, 0);
1066         p.image->waitForDone();
1067         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1068 
1069         p.undoStore->undo();
1070         p.image->waitForDone();
1071 
1072         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1073     }
1074 
1075     {
1076         KisLayerUtils::flattenImage(p.image, p.layer5); // flatten with active layer just under the root (not inside any group)
1077         p.image->waitForDone();
1078         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1079 
1080         p.undoStore->undo();
1081         p.image->waitForDone();
1082 
1083         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1084     }
1085 
1086     {
1087         KisLayerUtils::flattenImage(p.image, p.layer2); // flatten with active layer just under the root (not inside any group), but with a mask
1088         p.image->waitForDone();
1089         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1090 
1091         p.undoStore->undo();
1092         p.image->waitForDone();
1093 
1094         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1095     }
1096 
1097     {
1098         KisLayerUtils::flattenImage(p.image, p.layer3); // flatten with active layer inside of a group
1099         p.image->waitForDone();
1100         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1101 
1102         p.undoStore->undo();
1103         p.image->waitForDone();
1104 
1105         QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial"));
1106     }
1107 }
1108 
1109 struct FlattenPassThroughTestImage
1110 {
1111     FlattenPassThroughTestImage()
1112         : refRect(0,0,512,512)
1113         , p(refRect)
1114     {
1115 
1116         image = p.image;
1117         undoStore = p.undoStore;
1118 
1119         group1 = new KisGroupLayer(p.image, "group1", OPACITY_OPAQUE_U8);
1120         layer2 = new KisPaintLayer(p.image, "paint2", OPACITY_OPAQUE_U8);
1121         layer3 = new KisPaintLayer(p.image, "paint3", OPACITY_OPAQUE_U8);
1122 
1123         group4 = new KisGroupLayer(p.image, "group4", OPACITY_OPAQUE_U8);
1124         layer5 = new KisPaintLayer(p.image, "paint5", OPACITY_OPAQUE_U8);
1125         layer6 = new KisPaintLayer(p.image, "paint6", OPACITY_OPAQUE_U8);
1126 
1127         QRect rect2(100, 100, 100, 100);
1128         QRect rect3(150, 150, 100, 100);
1129 
1130         QRect rect5(200, 200, 100, 100);
1131         QRect rect6(250, 250, 100, 100);
1132 
1133         group1->setPassThroughMode(true);
1134         layer2->paintDevice()->fill(rect2, KoColor(Qt::red, p.image->colorSpace()));
1135         layer3->paintDevice()->fill(rect3, KoColor(Qt::green, p.image->colorSpace()));
1136 
1137         group4->setPassThroughMode(true);
1138         layer5->paintDevice()->fill(rect5, KoColor(Qt::blue, p.image->colorSpace()));
1139         layer6->paintDevice()->fill(rect6, KoColor(Qt::yellow, p.image->colorSpace()));
1140 
1141 
1142         p.image->addNode(group1);
1143         p.image->addNode(layer2, group1);
1144         p.image->addNode(layer3, group1);
1145 
1146         p.image->addNode(group4);
1147         p.image->addNode(layer5, group4);
1148         p.image->addNode(layer6, group4);
1149 
1150         p.image->initialRefreshGraph();
1151 
1152         TestUtil::ReferenceImageChecker chk("passthrough", "imagetest");
1153         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1154     }
1155 
1156     QRect refRect;
1157     TestUtil::MaskParent p;
1158 
1159     KisImageSP image;
1160     KisSurrogateUndoStore *undoStore;
1161 
1162     KisGroupLayerSP group1;
1163     KisPaintLayerSP layer2;
1164     KisPaintLayerSP layer3;
1165 
1166     KisGroupLayerSP group4;
1167     KisPaintLayerSP layer5;
1168     KisPaintLayerSP layer6;
1169 };
1170 
1171 void KisImageTest::testFlattenPassThroughLayer()
1172 {
1173     FlattenPassThroughTestImage p;
1174 
1175     TestUtil::ReferenceImageChecker chk("passthrough", "imagetest");
1176 
1177     {
1178         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_OVER);
1179         QCOMPARE(p.group1->passThroughMode(), true);
1180 
1181         KisLayerSP newLayer = flattenLayerHelper(p, p.group1);
1182 
1183         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1184         QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_group1_layerproj"));
1185 
1186         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
1187         QVERIFY(newLayer->inherits("KisPaintLayer"));
1188     }
1189 }
1190 
1191 void KisImageTest::testMergeTwoPassThroughLayers()
1192 {
1193     FlattenPassThroughTestImage p;
1194 
1195     TestUtil::ReferenceImageChecker chk("passthrough", "imagetest");
1196 
1197     {
1198         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_OVER);
1199         QCOMPARE(p.group1->passThroughMode(), true);
1200 
1201         KisLayerSP newLayer = mergeHelper(p, p.group4);
1202 
1203         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1204 
1205         QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER);
1206         QVERIFY(newLayer->inherits("KisGroupLayer"));
1207     }
1208 }
1209 
1210 void KisImageTest::testMergePaintOverPassThroughLayer()
1211 {
1212     FlattenPassThroughTestImage p;
1213 
1214     TestUtil::ReferenceImageChecker chk("passthrough", "imagetest");
1215 
1216     {
1217         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_OVER);
1218         QCOMPARE(p.group1->passThroughMode(), true);
1219 
1220         KisLayerSP newLayer = flattenLayerHelper(p, p.group4);
1221         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1222         QVERIFY(newLayer->inherits("KisPaintLayer"));
1223 
1224         newLayer = mergeHelper(p, newLayer);
1225         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1226         QVERIFY(newLayer->inherits("KisPaintLayer"));
1227     }
1228 }
1229 
1230 void KisImageTest::testMergePassThroughOverPaintLayer()
1231 {
1232     FlattenPassThroughTestImage p;
1233 
1234     TestUtil::ReferenceImageChecker chk("passthrough", "imagetest");
1235 
1236     {
1237         QCOMPARE(p.group1->compositeOpId(), COMPOSITE_OVER);
1238         QCOMPARE(p.group1->passThroughMode(), true);
1239 
1240         KisLayerSP newLayer = flattenLayerHelper(p, p.group1);
1241         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1242         QVERIFY(newLayer->inherits("KisPaintLayer"));
1243 
1244         newLayer = mergeHelper(p, p.group4);
1245         QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial"));
1246         QVERIFY(newLayer->inherits("KisPaintLayer"));
1247     }
1248 }
1249 
1250 #include "kis_paint_device_debug_utils.h"
1251 #include "kis_algebra_2d.h"
1252 
1253 void KisImageTest::testPaintOverlayMask()
1254 {
1255     QRect refRect(0, 0, 512, 512);
1256     TestUtil::MaskParent p(refRect);
1257 
1258     QRect fillRect(50, 50, 412, 412);
1259     QRect selectionRect(200, 200, 100, 50);
1260 
1261     KisPaintLayerSP layer1 = p.layer;
1262     layer1->paintDevice()->fill(fillRect, KoColor(Qt::yellow, layer1->colorSpace()));
1263 
1264     KisSelectionMaskSP mask = new KisSelectionMask(p.image);
1265     KisSelectionSP selection = new KisSelection(new KisSelectionDefaultBounds(layer1->paintDevice()), toQShared(new KisImageResolutionProxy(p.image)));
1266 
1267     selection->pixelSelection()->select(selectionRect, 128);
1268     selection->pixelSelection()->select(KisAlgebra2D::blowRect(selectionRect,-0.3), 255);
1269 
1270     mask->setSelection(selection);
1271 
1272     //mask->setVisible(false);
1273     //mask->setActive(false);
1274 
1275     p.image->addNode(mask, layer1);
1276 
1277     // a simple layer to disable oblige-child mechanism
1278     KisPaintLayerSP layer2 = new KisPaintLayer(p.image, "layer2", OPACITY_OPAQUE_U8);
1279     p.image->addNode(layer2);
1280 
1281     p.image->initialRefreshGraph();
1282 
1283     KIS_DUMP_DEVICE_2(p.image->projection(), refRect, "00_initial", "dd");
1284 
1285     p.image->setOverlaySelectionMask(mask);
1286     p.image->waitForDone();
1287 
1288     KIS_DUMP_DEVICE_2(p.image->projection(), refRect, "01_activated_00_image", "dd");
1289     KIS_DUMP_DEVICE_2(p.image->root()->original(), refRect, "01_activated_01_root_original", "dd");
1290     KIS_DUMP_DEVICE_2(p.image->root()->projection(), refRect, "01_activated_02_root_projection", "dd");
1291 
1292     KisImageSP clonedImage = p.image->clone();
1293     clonedImage->waitForDone();
1294     KIS_DUMP_DEVICE_2(clonedImage->projection(), refRect, "02_cloned_when_activated_00_image", "dd");
1295     KIS_DUMP_DEVICE_2(clonedImage->root()->original(), refRect, "02_cloned_when_activated_01_root_original", "dd");
1296     KIS_DUMP_DEVICE_2(clonedImage->root()->projection(), refRect, "02_cloned_when_activated_02_root_projection", "dd");
1297 
1298     p.image->setOverlaySelectionMask(0);
1299     p.image->waitForDone();
1300 
1301     KIS_DUMP_DEVICE_2(p.image->projection(), refRect, "03_deactivated", "dd");
1302 }
1303 
1304 KISTEST_MAIN(KisImageTest)