File indexing completed on 2024-06-09 04:23:12

0001 /* SPDX-FileCopyrightText: 2017 Boudewijn Rempt <boud@valdyas.org>
0002 
0003    SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 #include "TestDocument.h"
0006 #include <simpletest.h>
0007 
0008 #include <KritaVersionWrapper.h>
0009 #include <QColor>
0010 #include <QDataStream>
0011 #include <QDir>
0012 #include <QBuffer>
0013 #include <QTextStream>
0014 
0015 #include <Node.h>
0016 #include <Krita.h>
0017 #include <Document.h>
0018 
0019 #include <KoColorSpaceRegistry.h>
0020 #include <KoColorProfile.h>
0021 #include <KoColor.h>
0022 
0023 #include <KisDocument.h>
0024 #include <kis_image.h>
0025 #include <kis_fill_painter.h>
0026 #include <kis_paint_layer.h>
0027 #include <KisPart.h>
0028 
0029 #include <kis_transform_mask_params_factory_registry.h>
0030 #include <kis_undo_stores.h>
0031 #include <testui.h>
0032 
0033 void TestDocument::testSetColorSpace()
0034 {
0035     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0036     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0037     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0038     image->addNode(layer);
0039     kisdoc->setCurrentImage(image);
0040 
0041     Document d(kisdoc.data(), false);
0042     QStringList profiles = Krita().profiles("GRAYA", "U16");
0043     d.setColorSpace("GRAYA", "U16", profiles.first());
0044 
0045     QVERIFY(layer->colorSpace()->colorModelId().id() == "GRAYA");
0046     QVERIFY(layer->colorSpace()->colorDepthId().id() == "U16");
0047     QVERIFY(layer->colorSpace()->profile()->name() == profiles.first());
0048 
0049     KisPart::instance()->removeDocument(kisdoc.data(), false);
0050 }
0051 
0052 void TestDocument::testSetColorProfile()
0053 {
0054     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0055     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0056     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0057     image->addNode(layer);
0058     kisdoc->setCurrentImage(image);
0059 
0060     Document d(kisdoc.data(), false);
0061 
0062     QStringList profiles = Krita().profiles("RGBA", "U8");
0063     Q_FOREACH(const QString &profileName, profiles) {
0064         const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(profileName);
0065 
0066         // skip input-only profiles (e.g. for scanners)
0067         if (!profile->isSuitableForOutput()) continue;
0068 
0069         d.setColorProfile(profileName);
0070         QVERIFY(image->colorSpace()->profile()->name() == profileName);
0071     }
0072     KisPart::instance()->removeDocument(kisdoc.data(), false);
0073 }
0074 
0075 void TestDocument::testPixelData()
0076 {
0077     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0078     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0079     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0080     KisFillPainter gc(layer->paintDevice());
0081     gc.fillRect(0, 0, 100, 100, KoColor(Qt::red, layer->colorSpace()));
0082     image->addNode(layer);
0083     kisdoc->setCurrentImage(image);
0084 
0085     Document d(kisdoc.data(), false);
0086     d.refreshProjection();
0087 
0088     QByteArray ba = d.pixelData(0, 0, 100, 100);
0089     QDataStream ds(ba);
0090     do {
0091         quint8 channelvalue;
0092         ds >> channelvalue;
0093         QVERIFY(channelvalue == 0);
0094         ds >> channelvalue;
0095         QVERIFY(channelvalue == 0);
0096         ds >> channelvalue;
0097         QVERIFY(channelvalue == 255);
0098         ds >> channelvalue;
0099         QVERIFY(channelvalue == 255);
0100     } while (!ds.atEnd());
0101 
0102     KisPart::instance()->removeDocument(kisdoc.data(), false);
0103 }
0104 
0105 void TestDocument::testThumbnail()
0106 {
0107     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0108     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0109     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0110     KisFillPainter gc(layer->paintDevice());
0111     gc.fillRect(0, 0, 100, 100, KoColor(Qt::red, layer->colorSpace()));
0112     image->addNode(layer);
0113     kisdoc->setCurrentImage(image);
0114 
0115     Document d(kisdoc.data(), false);
0116     d.refreshProjection();
0117 
0118     QImage thumb = d.thumbnail(10, 10);
0119     thumb.save("thumb.png");
0120     QVERIFY(thumb.width() == 10);
0121     QVERIFY(thumb.height() == 10);
0122     // Our thumbnail calculator in KisPaintDevice cannot make a filled 10x10 thumbnail from a 100x100 device,
0123     // it makes it 10x10 empty, then puts 8x8 pixels in there... Not a bug in the Node class
0124     for (int i = 0; i < 8; ++i) {
0125         for (int j = 0; j < 8; ++j) {
0126             QVERIFY(thumb.pixelColor(i, j) == QColor(Qt::red));
0127         }
0128     }
0129     KisPart::instance()->removeDocument(kisdoc.data(), false);
0130 }
0131 
0132 void TestDocument::testCreateFillLayer()
0133 {
0134     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0135     KisImageSP image = new KisImage(0, 50, 50, KoColorSpaceRegistry::instance()->rgb16(), "test");
0136     kisdoc->setCurrentImage(image);
0137     Document d(kisdoc.data(), false);
0138 
0139     const QString pattern("pattern");
0140     const QString color("color");
0141     const QString filllayer = "filllayer";
0142     InfoObject info;
0143     Selection sel(image->globalSelection());
0144 
0145     FillLayer *f = d.createFillLayer("test1", pattern, info, sel);
0146     QVERIFY(f->generatorName() == pattern);
0147     QVERIFY(f->type() == filllayer);
0148     delete f;
0149     f = d.createFillLayer("test1", color, info, sel);
0150     QVERIFY(f->generatorName() == color);
0151     QVERIFY(f->type() == filllayer);
0152 
0153     info.setProperty(pattern, "Cross01.pat");
0154     QVERIFY(f->setGenerator(pattern, &info));
0155     QVERIFY(f->filterConfig()->property(pattern).toString() == "Cross01.pat");
0156     QVERIFY(f->generatorName() == pattern);
0157     QVERIFY(f->type() == filllayer);
0158 
0159     info.setProperty(color, QColor(Qt::red));
0160     QVERIFY(f->setGenerator(color, &info));
0161     QVariant v = f->filterConfig()->property(color);
0162     QColor c = v.value<QColor>();
0163     QVERIFY(c == QColor(Qt::red));
0164     QVERIFY(f->generatorName() == color);
0165     QVERIFY(f->type() == filllayer);
0166 
0167     bool r = f->setGenerator(QString("xxx"), &info);
0168     QVERIFY(!r);
0169 
0170     delete f;
0171 
0172     QVERIFY(d.createFillLayer("test1", "xxx", info, sel) == 0);
0173 
0174     KisPart::instance()->removeDocument(kisdoc.data(), false);
0175 }
0176 
0177 void TestDocument::testCreateCloneLayer()
0178 {
0179     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0180     KisImageSP image = new KisImage(0, 50, 50, KoColorSpaceRegistry::instance()->rgb16(), "test");
0181     kisdoc->setCurrentImage(image);
0182     Document d(kisdoc.data(), false);
0183 
0184     const QString layerType = "clonelayer";
0185     const QString node1Name = "node1";
0186     const QString node2Name = "node2";
0187 
0188     Node *node1 = d.createNode(node1Name,"paintlayer");
0189     Node *node2 = d.createNode(node2Name,"paintlayer");
0190     CloneLayer *layer = d.createCloneLayer("test1", node1);
0191     Node* rootNode = d.rootNode();
0192 
0193     rootNode->addChildNode(node1,0);
0194     rootNode->addChildNode(node2,0);
0195     rootNode->addChildNode(layer,0);
0196 
0197     QVERIFY(layer->type() == layerType);
0198 
0199     Node *sourceNode1 = layer->sourceNode();
0200 
0201     QVERIFY(sourceNode1->name() == node1Name);
0202 
0203     layer->setSourceNode(node2);
0204 
0205     Node *sourceNode2 = layer->sourceNode();
0206 
0207     QVERIFY(sourceNode2->name() == node2Name);
0208 
0209     delete layer;
0210     delete node1;
0211     delete node2;
0212     delete sourceNode1;
0213     delete sourceNode2;
0214     delete rootNode;
0215 
0216     KisPart::instance()->removeDocument(kisdoc.data(), false);
0217 }
0218 
0219 void TestDocument::testCreateTransparencyMask()
0220 {
0221     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0222     KisImageSP image = new KisImage(0, 50, 50, KoColorSpaceRegistry::instance()->rgb16(), "test");
0223     kisdoc->setCurrentImage(image);
0224     Document d(kisdoc.data(), false);
0225 
0226     const QString layerType = "transparencymask";
0227 
0228     Selection sel(image->globalSelection());
0229 
0230     sel.select(10,10,10,10,255);
0231 
0232     Node *node = d.createNode("node1","paintlayer");
0233     TransparencyMask *mask = d.createTransparencyMask("test1");
0234     Node* rootNode = d.rootNode();
0235 
0236     rootNode->addChildNode(node,0);
0237     node->addChildNode(mask,0);
0238 
0239     Selection* selResult = mask->selection();
0240 
0241     QVERIFY(mask->type() == layerType);
0242     QVERIFY(selResult->width() == sel.width() && selResult->height() == sel.height());
0243 
0244     delete selResult;
0245     delete mask;
0246     delete node;
0247     delete rootNode;
0248 
0249     KisPart::instance()->removeDocument(kisdoc.data(), false);
0250 }
0251 
0252 void TestDocument::testCreateColorizeMask()
0253 {
0254     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0255     KisImageSP image = new KisImage(new KisSurrogateUndoStore(),  10, 3, KoColorSpaceRegistry::instance()->rgb8(), "test");
0256 
0257     kisdoc->setCurrentImage(image);
0258 
0259     Document d(kisdoc.data(), false);
0260     const QString layerType = "colorizemask";
0261 
0262     Node *node = d.createNode("node1","paintlayer");
0263 
0264     ColorizeMask *mask = d.createColorizeMask("test1");
0265     Node* rootNode = d.rootNode();
0266 
0267     QByteArray nodeData = QByteArray::fromBase64("AAAAAAAAAAAAAAAAEQYMBhEGDP8RBgz/EQYMAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBgz5EQYM/xEGDAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQYMAhEGDAkRBgwCAAAAAAAAAAAAAAAA");
0268 
0269     node->setPixelData(nodeData,0,0,10,3);
0270     rootNode->addChildNode(node,0);
0271 
0272     d.waitForDone();
0273     d.refreshProjection();
0274 
0275     node->addChildNode(mask,0);
0276 
0277     qApp->processEvents();
0278     d.waitForDone();
0279 
0280     ManagedColor col1("RGBA","U8","");
0281     ManagedColor col2("RGBA","U8","");
0282 
0283     col1.setComponents({1.0, 0.0, 0.0, 1.0});
0284     col2.setComponents({0.0, 0.0, 1.0, 1.0});
0285 
0286     QVERIFY(mask->type() == layerType);
0287 
0288     mask->setEditKeyStrokes(true);
0289     QVERIFY(mask->editKeyStrokes() == true);
0290 
0291     mask->setUseEdgeDetection(true);
0292     QVERIFY(mask->useEdgeDetection() == true);
0293 
0294     mask->setEdgeDetectionSize(4.0);
0295     QVERIFY(mask->edgeDetectionSize() == 4.0);
0296 
0297     mask->setCleanUpAmount(70.0);
0298     QVERIFY(mask->cleanUpAmount() == 70.0);
0299 
0300     mask->setLimitToDeviceBounds(true);
0301     QVERIFY(mask->limitToDeviceBounds() == true);
0302 
0303     mask->initializeKeyStrokeColors({&col1, &col2});
0304 
0305     QByteArray pdata1 = QByteArray::fromBase64("//8AAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA");
0306     QByteArray pdata2 = QByteArray::fromBase64("AAAAAAAAAAD//wAAAAAAAAAAAP8AAAAAAAAAAAAA");
0307 
0308     mask->setKeyStrokePixelData(pdata1,&col1,0,0,10,3);
0309     mask->setKeyStrokePixelData(pdata2,&col2,0,0,10,3);
0310 
0311     QList<ManagedColor *> checkColors(mask->keyStrokesColors());
0312 
0313     QVERIFY(checkColors.size() == 2);
0314     QVERIFY(col1.toQString() == checkColors[0]->toQString());
0315     QVERIFY(col2.toQString() == checkColors[1]->toQString());
0316 
0317     QVERIFY(mask->keyStrokePixelData(&col1,0,0,10,3) == pdata1);
0318     QVERIFY(mask->keyStrokePixelData(&col2,0,0,10,3) == pdata2);
0319 
0320     delete checkColors[0];
0321     delete checkColors[1];
0322 
0323     mask->updateMask(true);
0324     mask->setEditKeyStrokes(false);
0325     mask->setShowOutput(true);
0326 
0327     d.waitForDone();
0328     d.refreshProjection();
0329 
0330     QByteArray pdata = d.pixelData(0,0,10,3);
0331 
0332     QVERIFY(d.pixelData(3,2,1,1).toBase64() == "/wAA/w==");
0333     QVERIFY(d.pixelData(6,2,1,1).toBase64() == "AAD9/w==");
0334 
0335     mask->removeKeyStroke(&col2);
0336     qApp->processEvents();
0337     d.waitForDone();
0338 
0339     checkColors = mask->keyStrokesColors();
0340 
0341     QVERIFY(checkColors.size() == 1);
0342     QVERIFY(col1.toQString() == checkColors[0]->toQString());
0343 
0344     delete checkColors[0];
0345     delete mask;
0346     delete node;
0347     delete rootNode;
0348 
0349     KisPart::instance()->removeDocument(kisdoc.data(), false);
0350 }
0351 
0352 
0353 
0354 void TestDocument::testAnnotations()
0355 {
0356     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0357     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0358     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0359     image->addNode(layer);
0360     kisdoc->setCurrentImage(image);
0361 
0362     Document d(kisdoc.data(), false);
0363 
0364     QVERIFY(d.annotationTypes().isEmpty());
0365 
0366     QBuffer buf;
0367     buf.open(QBuffer::WriteOnly);
0368     QTextStream in(&buf);
0369     in.setCodec("UTF-8");
0370     in << "AnnotationTest";
0371     buf.close();
0372 
0373     d.setAnnotation("test", "description", buf.data());
0374 
0375     QVERIFY(d.annotationTypes().size() == 1);
0376     QVERIFY(d.annotationTypes().contains("test"));
0377     QVERIFY(d.annotation("test").toHex() == buf.data().toHex());
0378     QVERIFY(d.annotationDescription("test") == "description");
0379 
0380     d.saveAs("roundtriptest.kra");
0381 
0382     d.removeAnnotation("test");
0383     QVERIFY(d.annotationTypes().isEmpty());
0384 
0385     d.close();
0386 
0387     Krita *krita = Krita::instance();
0388     Document *d2 = krita->openDocument("roundtriptest.kra");
0389 
0390     QVERIFY(d2->annotationTypes().size() == 1);
0391     QVERIFY(d2->annotationTypes().contains("test"));
0392     QVERIFY(d2->annotation("test").toHex() == buf.data().toHex());
0393     QVERIFY(d2->annotationDescription("test") == "description");
0394 
0395     d2->close();
0396 }
0397 
0398 void TestDocument::testNodeByName()
0399 {
0400     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0401     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0402     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0403     image->addNode(layer);
0404     kisdoc->setCurrentImage(image);
0405 
0406     Document d(kisdoc.data(), false);
0407 
0408     QVERIFY(d.nodeByName("test1")->name() == layer->name());
0409     QVERIFY(d.nodeByName("test2") == 0);
0410 }
0411 
0412 void TestDocument::testNodeByUniqueId()
0413 {
0414     QScopedPointer<KisDocument> kisdoc(KisPart::instance()->createDocument());
0415     KisImageSP image = new KisImage(0, 100, 100, KoColorSpaceRegistry::instance()->rgb8(), "test");
0416     KisNodeSP layer = new KisPaintLayer(image, "test1", 255);
0417     image->addNode(layer);
0418     kisdoc->setCurrentImage(image);
0419 
0420     Document d(kisdoc.data(), false);
0421 
0422     QVERIFY(d.nodeByUniqueID(layer->uuid())->name() == layer->name());
0423 
0424     QUuid test(QUuid::createUuid());
0425 
0426     while (test == layer->uuid()) {
0427         test = QUuid::createUuid();
0428     }
0429     QVERIFY(d.nodeByUniqueID(test) == 0);
0430 }
0431 
0432 class KisTransformMaskAdapter;
0433 
0434 KISTEST_MAIN(TestDocument)
0435