void KisProjectionTest::testDirty() { KisImageSP image = new KisImage(0, 1000, 1000, 0, "layer tests"); // Two layers so the single-layer-is-rootlayer optimization doesn't kick in KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8); KisLayerSP layer2 = new KisPaintLayer(image, "layer 2", OPACITY_OPAQUE_U8); image->addNode(layer); image->addNode(layer2); KisFillPainter gc(layer2->paintDevice()); KoColor c(Qt::red, layer2->colorSpace()); gc.fillRect(0, 0, 1000, 1000, c); gc.end(); layer2->setDirty(gc.takeDirtyRegion()); // wait a little for the projection to finish QTest::qSleep(250); // Check that the projection is totally redistribute KisSequentialConstIterator it(image->projection(), QRect(0, 0, 1000, 1000)); do { QColor c; image->colorSpace()->toQColor(it.oldRawData(), &c, image->profile()); QVERIFY(c == Qt::red); } while (it.nextPixel()); }
KoFilter::ConversionStatus MagickExport::convert(const QCString& from, const QCString& to) { kdDebug(41008) << "magick export! From: " << from << ", To: " << to << "\n"; if (from != "application/x-krita") return KoFilter::NotImplemented; // XXX: Add dialog about flattening layers here KisDoc *output = dynamic_cast<KisDoc*>(m_chain->inputDocument()); QString filename = m_chain->outputFile(); if (!output) return KoFilter::CreationError; if (filename.isEmpty()) return KoFilter::FileNotFound; KURL url; url.setPath(filename); KisImageSP img = output->currentImage(); KisImageMagickConverter ib(output, output->undoAdapter()); KisPaintDeviceSP pd = new KisPaintDevice(*img->projection()); KisPaintLayerSP l = new KisPaintLayer(img, "projection", OPACITY_OPAQUE, pd); vKisAnnotationSP_it beginIt = img->beginAnnotations(); vKisAnnotationSP_it endIt = img->endAnnotations(); if (ib.buildFile(url, l, beginIt, endIt) == KisImageBuilder_RESULT_OK) { return KoFilter::OK; } return KoFilter::InternalError; }
void KisTransparencyMaskTest::testMoveParentLayer() { KisImageSP image; KisPaintLayerSP layer; KisPaintDeviceSP dev; KisTransparencyMaskSP mask; initImage(image, layer, dev, mask); mask->initSelection(layer); mask->selection()->pixelSelection()->invert(); mask->select(QRect(50, 50, 100, 100)); KisFullRefreshWalker walker(image->bounds()); KisAsyncMerger merger; walker.collectRects(layer, image->bounds()); merger.startMerge(walker); // image->projection()->convertToQImage(0, 0,0,300,300).save("proj_before.png"); QRect initialRect(0,0,200,100); QCOMPARE(layer->exactBounds(), initialRect); QCOMPARE(image->projection()->exactBounds(), QRect(50,50,100,50)); layer->setX(100); layer->setY(100); dbgKrita << "Sel. rect before:" << mask->selection()->selectedExactRect(); mask->setX(100); mask->setY(100); dbgKrita << "Sel. rect after:" << mask->selection()->selectedExactRect(); QRect finalRect(100,100,200,100); QCOMPARE(layer->exactBounds(), finalRect); walker.collectRects(layer, initialRect | finalRect); merger.startMerge(walker); // image->projection()->convertToQImage(0, 0,0,300,300).save("proj_after.png"); QCOMPARE(image->projection()->exactBounds(), QRect(150,150,100,50)); }
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 KisAsyncMergerTest::testSubgraphingWithoutUpdatingParent() { 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)); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisPaintDeviceSP device2 = new KisPaintDevice(colorSpace); device2->fill(image->bounds(), KoColor(Qt::black, colorSpace)); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", 128, device2); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); image->initialRefreshGraph(); QImage refImage(QString(FILES_DATA_DIR) + QDir::separator() + "subgraphing_without_updating.png"); { QImage resultImage = image->projection()->convertToQImage(0); QCOMPARE(resultImage, refImage); } QRect cropRect(image->bounds()); KisRefreshSubtreeWalker walker(cropRect); KisAsyncMerger merger; walker.collectRects(paintLayer2, image->bounds()); merger.startMerge(walker); { QImage resultImage = image->projection()->convertToQImage(0); QCOMPARE(resultImage, refImage); } }
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; }