void KisProcessingApplicatorTest::testNoUIUpdates()
{
    KisSurrogateUndoStore *undoStore = new KisSurrogateUndoStore();
    KisPaintLayerSP paintLayer1;
    KisPaintLayerSP paintLayer2;
    KisImageSP image = createImage(undoStore, paintLayer1, paintLayer2);
    QSignalSpy uiSignalsCounter(image.data(), SIGNAL(sigImageUpdated(const QRect&)));

    QRect cropRect1(40,40,86,86);

    {
        KisProcessingApplicator applicator(image, image->rootLayer(),
                                           KisProcessingApplicator::RECURSIVE |
                                           KisProcessingApplicator::NO_UI_UPDATES);

        KisProcessingVisitorSP visitor =
            new KisCropProcessingVisitor(cropRect1, true, true);
        applicator.applyVisitor(visitor);
        applicator.end();
        image->waitForDone();
    }

    QCOMPARE(uiSignalsCounter.size(), 0);

    uiSignalsCounter.clear();

    undoStore->undo();
    image->waitForDone();

    QCOMPARE(uiSignalsCounter.size(), 0);
}
void KisProcessingApplicatorTest::testRecursiveProcessing()
{
    KisSurrogateUndoStore *undoStore = new KisSurrogateUndoStore();
    KisPaintLayerSP paintLayer1;
    KisPaintLayerSP paintLayer2;
    KisImageSP image = createImage(undoStore, paintLayer1, paintLayer2);

    QRect cropRect1(40,40,86,86);

    QVERIFY(checkLayers(image, "recursive_initial"));

    {
        KisProcessingApplicator applicator(image, image->rootLayer(),
                                           KisProcessingApplicator::RECURSIVE);

        KisProcessingVisitorSP visitor =
            new KisCropProcessingVisitor(cropRect1, true, true);
        applicator.applyVisitor(visitor);
        applicator.end();
        image->waitForDone();
    }

    QVERIFY(checkLayers(image, "recursive_crop"));

    undoStore->undo();
    image->waitForDone();
    QVERIFY(checkLayers(image, "recursive_initial"));
}
Example #3
0
void KisKraLoaderTest::testLoadAnimated()
{
    KisDocument *doc = KisPart::instance()->createDocument();
    doc->loadNativeFormat(QString(FILES_DATA_DIR) + QDir::separator() + "load_test_animation.kra");
    KisImageSP image = doc->image();

    KisNodeSP node1 = image->root()->firstChild();
    KisNodeSP node2 = node1->nextSibling();

    QVERIFY(node1->inherits("KisPaintLayer"));
    QVERIFY(node2->inherits("KisPaintLayer"));

    KisPaintLayerSP layer1 = qobject_cast<KisPaintLayer*>(node1.data());
    KisPaintLayerSP layer2 = qobject_cast<KisPaintLayer*>(node2.data());
    KisKeyframeChannel *channel1 = layer1->getKeyframeChannel(KisKeyframeChannel::Content.id());
    KisKeyframeChannel *channel2 = layer2->getKeyframeChannel(KisKeyframeChannel::Content.id());

    QCOMPARE(channel1->keyframeCount(), 3);
    QCOMPARE(channel2->keyframeCount(), 1);

    QCOMPARE(image->animationInterface()->framerate(), 17);
    QCOMPARE(image->animationInterface()->fullClipRange(), KisTimeRange::fromTime(15, 45));
    QCOMPARE(image->animationInterface()->currentTime(), 19);

    KisPaintDeviceSP dev = layer1->paintDevice();

    const KoColorSpace *cs = dev->colorSpace();
    KoColor transparent(Qt::transparent, cs);
    KoColor white(Qt::white, cs);
    KoColor red(Qt::red, cs);

    image->animationInterface()->switchCurrentTimeAsync(0);
    image->waitForDone();

    QCOMPARE(dev->exactBounds(), QRect(506, 378, 198, 198));
    QCOMPARE(dev->x(), -26);
    QCOMPARE(dev->y(), -128);
    QCOMPARE(dev->defaultPixel(), transparent);

    image->animationInterface()->switchCurrentTimeAsync(20);
    image->waitForDone();

    QCOMPARE(dev->nonDefaultPixelArea(), QRect(615, 416, 129, 129));
    QCOMPARE(dev->x(), 502);
    QCOMPARE(dev->y(), 224);
    QCOMPARE(dev->defaultPixel(), white);

    image->animationInterface()->switchCurrentTimeAsync(30);
    image->waitForDone();

    QCOMPARE(dev->nonDefaultPixelArea(), QRect(729, 452, 45, 44));
    QCOMPARE(dev->x(), 645);
    QCOMPARE(dev->y(), -10);
    QCOMPARE(dev->defaultPixel(), red);
}
void KisProcessingApplicatorTest::testNonRecursiveProcessing()
{
    KisSurrogateUndoStore *undoStore = new KisSurrogateUndoStore();
    KisPaintLayerSP paintLayer1;
    KisPaintLayerSP paintLayer2;
    KisImageSP image = createImage(undoStore, paintLayer1, paintLayer2);

    QRect cropRect1(25,25,75,75);
    QRect cropRect2(100,100,50,50);

    QVERIFY(checkLayers(image, "initial"));

    {
        KisProcessingApplicator applicator(image, paintLayer1,
                                           KisProcessingApplicator::NONE);

        KisProcessingVisitorSP visitor =
            new KisCropProcessingVisitor(cropRect1, true, false);
        applicator.applyVisitor(visitor);
        applicator.end();
        image->waitForDone();
    }

    QVERIFY(checkLayers(image, "crop_l1"));

    {
        KisProcessingApplicator applicator(image, paintLayer2,
                                           KisProcessingApplicator::NONE);

        KisProcessingVisitorSP visitor =
            new KisCropProcessingVisitor(cropRect2, true, false);
        applicator.applyVisitor(visitor);
        applicator.end();
        image->waitForDone();
    }

    QVERIFY(checkLayers(image, "crop_l2"));

    undoStore->undo();
    image->waitForDone();
    QVERIFY(checkLayers(image, "crop_l1"));

    undoStore->undo();
    image->waitForDone();
    QVERIFY(checkLayers(image, "initial"));
}
QImage utils::StrokeTester::doStroke(bool cancelled,
                                     bool indirectPainting,
                                     bool externalLayer,
                                     bool testUpdates,
                                     bool needQImage)
{
    KisImageSP image = utils::createImage(0, m_imageSize);
    KoCanvasResourceManager *manager = utils::createResourceManager(image, 0, m_presetFilename);
    KisNodeSP currentNode;

    for (int i = 0; i < m_numIterations; i++) {
        modifyResourceManager(manager, image, i);

        KisPainter *painter = new KisPainter();
        KisResourcesSnapshotSP resources =
            new KisResourcesSnapshot(image,
                                     image->rootLayer()->firstChild(),
                                     image->postExecutionUndoAdapter(),
                                     manager);

        if(externalLayer) {
            KisNodeSP externalNode = new KisPaintLayer(0, "extlyr", OPACITY_OPAQUE_U8, image->colorSpace());
            resources->setCurrentNode(externalNode);
            Q_ASSERT(resources->currentNode() == externalNode);
        }

        initImage(image, resources->currentNode(), i);

        KisStrokeStrategy *stroke = createStroke(indirectPainting, resources, painter, image);
        m_strokeId = image->startStroke(stroke);
        addPaintingJobs(image, resources, painter, i);

        if(!cancelled) {
            image->endStroke(m_strokeId);
        }
        else {
            image->cancelStroke(m_strokeId);
        }

        image->waitForDone();
        currentNode = resources->currentNode();
    }

    QImage resultImage;
    if(needQImage) {
        KisPaintDeviceSP device = testUpdates ?
            image->projection() :
            currentNode->paintDevice();

        resultImage = device->convertToQImage(0, 0, 0, image->width(), image->height());
    }

    image = 0;
    delete manager;
    return resultImage;
}
    void test(const QString &testname, KisProcessingVisitorSP visitor) {
        KisSurrogateUndoStore *undoStore = new KisSurrogateUndoStore();
        KisImageSP image = createImage(undoStore);
        image->initialRefreshGraph();

        QVERIFY(checkLayersInitial(image));

        KisProcessingApplicator applicator(image, image->root(),
                                           KisProcessingApplicator::RECURSIVE);

        applicator.applyVisitor(visitor);
        applicator.end();
        image->waitForDone();

        QVERIFY(checkLayers(image, testname));

        undoStore->undo();
        image->waitForDone();

        QVERIFY(checkLayersInitial(image));
    }
Example #7
0
void KisStrokeStrategyUndoCommandBasedTest::testCancelledStroke()
{
    QString result;
    KUndo2CommandSP initCommand(new TestingUndoCommand(kundo2_noi18n("init"), result));
    KUndo2CommandSP dabCommand(new TestingUndoCommand(kundo2_noi18n("dab"), result));
    KUndo2CommandSP finishCommand(new TestingUndoCommand(kundo2_noi18n("finish"), result));

    const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(0, 300, 300, cs, "test", true);

    KisStrokeStrategy *strategy =
        new KisStrokeStrategyUndoCommandBased(kundo2_noi18n("test"), false,
                                              image->postExecutionUndoAdapter(),
                                              initCommand, finishCommand);

    KisStrokeId id = image->startStroke(strategy);
    image->addJob(id, new KisStrokeStrategyUndoCommandBased::Data(dabCommand));
    QTest::qSleep(500);
    image->cancelStroke(id);
    image->waitForDone();

    SCOMPARE(result.trimmed(), "init_redo dab_redo dab_undo init_undo");
}
void KisSelectionDecorationTest::testConcurrentSelectionFetches()
{
    KisImageSP image = utils::createImage(0, QSize(3000, 3000));

    for (int i = 0; i < 10000; i++) {
        KisProcessingApplicator applicator(image,
                                           0 /* we need no automatic updates */,
                                           KisProcessingApplicator::SUPPORTS_WRAPAROUND_MODE,
                                           KisImageSignalVector() << ModifiedSignal,
                                           kundo2_noi18n("test stroke"));


        applicator.applyCommand(new KisSetEmptyGlobalSelectionCommand(image));
        applicator.applyCommand(new KisDeselectGlobalSelectionCommand(image));

        applicator.end();

        for (int j = 0; j < 100; j++) {
            KisSelectionSP selection = image->globalSelection();
        }
    }

    image->waitForDone();
}
Example #9
0
void KisStrokeStrategyUndoCommandBasedTest::stressTestSequentialCommands()
{

    const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(0, 300, 300, cs, "test", true);

    QAtomicInt counter;
    QAtomicInt hadConcurrency;

    KisStrokeStrategy *strategy =
        new KisStrokeStrategyUndoCommandBased(kundo2_noi18n("test"), false, 0);

    KisStrokeId id = image->startStroke(strategy);

    for(int i = 0; i < NUM_JOBS; i++) {
        bool isSequential = i % SEQUENTIAL_NTH == 0;

        KisStrokeJobData::Sequentiality seq = isSequential ?
            KisStrokeJobData::SEQUENTIAL : KisStrokeJobData::CONCURRENT;

        KUndo2CommandSP command(new ExclusivenessCheckerCommand(counter,
                                                                hadConcurrency,
                                                                isSequential));

        image->addJob(id,
            new KisStrokeStrategyUndoCommandBased::Data(command, seq));

    }

    image->endStroke(id);
    image->waitForDone();

    QVERIFY(!counter);
    qDebug() << "Concurrency observed:" << hadConcurrency
             << "/" << NUM_CHECKS * NUM_JOBS;
}
void KisOcioDisplayFilterTest::test()
{
    KisExposureGammaCorrectionInterface *egInterface =
        new KisDumbExposureGammaCorrectionInterface();

    OcioDisplayFilter filter(egInterface);

    QString configFile = TestUtil::fetchDataFileLazy("./psyfiTestingConfig-master/config.ocio");
    dbgKrita << ppVar(configFile);

    Q_ASSERT(QFile::exists(configFile));

    OCIO::ConstConfigRcPtr ocioConfig =
        OCIO::Config::CreateFromFile(configFile.toUtf8());

    filter.config = ocioConfig;
    filter.inputColorSpaceName = ocioConfig->getColorSpaceNameByIndex(0);
    filter.displayDevice = ocioConfig->getDisplay(1);
    filter.view = ocioConfig->getView(filter.displayDevice, 0);
    filter.gamma = 1.0;
    filter.exposure = 0.0;
    filter.swizzle = RGBA;

    filter.blackPoint = 0.0;
    filter.whitePoint = 1.0;

    filter.forceInternalColorManagement = false;
    filter.setLockCurrentColorVisualRepresentation(false);

    filter.updateProcessor();

    dbgKrita << ppVar(filter.inputColorSpaceName);
    dbgKrita << ppVar(filter.displayDevice);
    dbgKrita << ppVar(filter.view);
    dbgKrita << ppVar(filter.gamma);
    dbgKrita << ppVar(filter.exposure);

    const KoColorSpace *paintingCS =
                KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), 0);

    KisImageSP image = utils::createImage(0, QSize(100, 100));
    image->convertImageColorSpace(paintingCS, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags);
    image->waitForDone();

dbgKrita << ppVar(paintingCS) << ppVar(image->root()->firstChild()->colorSpace());

    KoCanvasResourceManager *resourceManager =
        utils::createResourceManager(image,
                                     image->root(), "");

    KisDisplayColorConverter converter(resourceManager, 0);

    dbgKrita << ppVar(image->root()->firstChild());

    QVariant v;
    v.setValue(KisNodeWSP(image->root()->firstChild()));
    resourceManager->setResource(KisCanvasResourceProvider::CurrentKritaNode, v);

    converter.setDisplayFilter(&filter);
    dbgKrita << ppVar(converter.paintingColorSpace());

    {
        QColor refColor(255, 128, 0);
        KoColor realColor = converter.approximateFromRenderedQColor(refColor);
        QColor roundTripColor = converter.toQColor(realColor);

        dbgKrita << ppVar(refColor);
        dbgKrita << ppVar(realColor.colorSpace()) << ppVar(KoColor::toQString(realColor));
        dbgKrita << ppVar(roundTripColor);
    }

    {
        KoColor realColor(Qt::red, paintingCS);
        QColor roundTripColor = converter.toQColor(realColor);

        dbgKrita << ppVar(realColor.colorSpace()) << ppVar(KoColor::toQString(realColor));
        dbgKrita << ppVar(roundTripColor);
    }

}
bool doPartialTests(const QString &prefix, KisImageSP image, KisLayerSP paintLayer,
                    KisLayerSP visibilityToggleLayer, KisTransformMaskSP mask)
{
    TestUtil::ExternalImageChecker chk(prefix, "transform_mask_updates");

    bool result = true;

    QRect refRect = image->bounds();

    int testIndex = 1;
    QString testName;

    for (int y = 0; y < refRect.height(); y += 512) {
        for (int x = 0; x < refRect.width(); x += 512) {
            QRect rc(x, y, 512, 512);

            if (rc.right() > refRect.right()) {
                rc.setRight(refRect.right());
                if (rc.isEmpty()) continue;
            }

            if (rc.bottom() > refRect.bottom()) {
                rc.setBottom(refRect.bottom());
                if (rc.isEmpty()) continue;
            }

            paintLayer->setDirty(rc);
            image->waitForDone();
            testName = QString("tm_%1_partial_%2_%3").arg(testIndex++).arg(x).arg(y);
            result &= chk.checkImage(image, testName);
        }
    }

    // initial update of the mask to clear the unused portions of the projection
    // (it updates only when we call set dirty on the mask itself, which happens
    // in Krita right after the addition of the mask onto a layer)

    mask->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_initial_mask_visible_on").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    // start layer visibility testing

    paintLayer->setVisible(false);
    paintLayer->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_layer_visible_off").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    paintLayer->setVisible(true);
    paintLayer->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_layer_visible_on").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    if (paintLayer != visibilityToggleLayer) {
        visibilityToggleLayer->setVisible(false);
        visibilityToggleLayer->setDirty();
        image->waitForDone();
        testName = QString("tm_%1_extra_layer_visible_off").arg(testIndex++);
        result &= chk.checkImage(image, testName);


        visibilityToggleLayer->setVisible(true);
        visibilityToggleLayer->setDirty();
        image->waitForDone();
        testName = QString("tm_%1_extra_layer_visible_on").arg(testIndex++);
        result &= chk.checkImage(image, testName);
    }

    // toggle mask visibility

    mask->setVisible(false);
    mask->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_mask_visible_off").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    mask->setVisible(true);
    mask->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_mask_visible_on").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    // entire bounds update

    // no clearing, just don't hang up

    paintLayer->setDirty(refRect);
    image->waitForDone();
    testName = QString("tm_%1_layer_dirty_bounds").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    // no clearing, just don't hang up

    mask->setDirty(refRect);
    image->waitForDone();
    testName = QString("tm_%1_mask_dirty_bounds").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    if (paintLayer != visibilityToggleLayer) {
        // no clearing, just don't hang up

        visibilityToggleLayer->setDirty(refRect);
        image->waitForDone();
        testName = QString("tm_%1_extra_layer_dirty_bounds").arg(testIndex++);
        result &= chk.checkImage(image, testName);
    }

    QRect fillRect;

    // partial updates outside

    fillRect = QRect(-100, 0.5 * refRect.height(), 50, 100);
    paintLayer->paintDevice()->fill(fillRect, KoColor(Qt::red, image->colorSpace()));
    paintLayer->setDirty(fillRect);
    image->waitForDone();
    testName = QString("tm_%1_layer_dirty_outside_%2_%3").arg(testIndex++).arg(fillRect.x()).arg(fillRect.y());
    result &= chk.checkImage(image, testName);

    fillRect = QRect(0.5 * refRect.width(), -100, 100, 50);
    paintLayer->paintDevice()->fill(fillRect, KoColor(Qt::red, image->colorSpace()));
    paintLayer->setDirty(fillRect);
    image->waitForDone();
    testName = QString("tm_%1_layer_dirty_outside_%2_%3").arg(testIndex++).arg(fillRect.x()).arg(fillRect.y());
    result &= chk.checkImage(image, testName);

    fillRect = QRect(refRect.width() + 50, 0.2 * refRect.height(), 50, 100);
    paintLayer->paintDevice()->fill(fillRect, KoColor(Qt::red, image->colorSpace()));
    paintLayer->setDirty(fillRect);
    image->waitForDone();
    testName = QString("tm_%1_layer_dirty_outside_%2_%3").arg(testIndex++).arg(fillRect.x()).arg(fillRect.y());
    result &= chk.checkImage(image, testName);

    // partial update inside

    fillRect = QRect(0.5 * refRect.width() - 50, 0.5 * refRect.height() - 50, 100, 100);
    paintLayer->paintDevice()->fill(fillRect, KoColor(Qt::red, image->colorSpace()));
    paintLayer->setDirty(fillRect);
    image->waitForDone();
    testName = QString("tm_%1_layer_dirty_inside_%2_%3").arg(testIndex++).arg(fillRect.x()).arg(fillRect.y());
    result &= chk.checkImage(image, testName);

    // clear explicitly
    image->projection()->clear();

    mask->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_mask_dirty_bounds").arg(testIndex++);
    result &= chk.checkImage(image, testName);


    KisDumbTransformMaskParams *params =
        dynamic_cast<KisDumbTransformMaskParams*>(mask->transformParams().data());

    QTransform t = params->testingGetTransform();
    t *= QTransform::fromTranslate(400, 300);
    params->testingSetTransform(t);
    mask->setTransformParams(mask->transformParams());

    mask->setDirty();
    image->waitForDone();
    testName = QString("tm_%1_mask_dirty_after_offset").arg(testIndex++);
    result &= chk.checkImage(image, testName);

    return result;
}
void KisAsyncMergerTest::testFullRefreshWithClones()
{
    const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(0, 128, 128, colorSpace, "clones test");

    KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace);
    device1->fill(image->bounds(), KoColor( Qt::white, colorSpace));

    KisFilterSP filter = KisFilterRegistry::instance()->value("invert");
    Q_ASSERT(filter);
    KisFilterConfiguration *configuration = filter->defaultConfiguration(0);
    Q_ASSERT(configuration);

    KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1);
    KisFilterMaskSP invertMask1 = new KisFilterMask();
    invertMask1->initSelection(0, paintLayer1);
    invertMask1->setFilter(configuration);

    KisLayerSP cloneLayer1 = new KisCloneLayer(paintLayer1, image, "clone_of_1", OPACITY_OPAQUE_U8);
    /**
     * The clone layer must have a projection to allow us
     * to read what it got from its source. Just shift it.
     */
    cloneLayer1->setX(10);
    cloneLayer1->setY(10);

    image->addNode(cloneLayer1, image->rootLayer());
    image->addNode(paintLayer1, image->rootLayer());
    image->addNode(invertMask1, paintLayer1);

    QRect cropRect(image->bounds());

    KisFullRefreshWalker walker(cropRect);
    KisAsyncMerger merger;

    walker.collectRects(image->rootLayer(), image->bounds());
    merger.startMerge(walker);

    // Wait for additional jobs generated by the clone are finished
    image->waitForDone();

    QRect filledRect(10, 10,
                     image->width() - cloneLayer1->x(),
                     image->height() - cloneLayer1->y());

    const int pixelSize = device1->pixelSize();
    const int numPixels = filledRect.width() * filledRect.height();

    QByteArray bytes(numPixels * pixelSize, 13);
    cloneLayer1->projection()->readBytes((quint8*)bytes.data(), filledRect);

    KoColor desiredPixel(Qt::black, colorSpace);
    quint8 *srcPtr = (quint8*)bytes.data();
    quint8 *dstPtr = desiredPixel.data();
    for(int i = 0; i < numPixels; i++) {
        if(memcmp(srcPtr, dstPtr, pixelSize)) {
            qDebug() << "expected:" << dstPtr[0] << dstPtr[1] << dstPtr[2] << dstPtr[3];
            qDebug() << "result:  " << srcPtr[0] << srcPtr[1] << srcPtr[2] << srcPtr[3];
            QFAIL("Failed to compare pixels");
        }
        srcPtr += pixelSize;
    }
}