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")); }
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)); }
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(); }
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; } }