void KisSelectionBasedLayer::copyOriginalToProjection(const KisPaintDeviceSP original,
        KisPaintDeviceSP projection,
        const QRect& rect) const
{
    lockTemporaryTarget();

    m_d->selection->updateProjection();
    KisSelectionSP tempSelection = m_d->selection;
    KisPainter gc(projection);

    if (m_d->selection) {
        if (hasTemporaryTarget()) {
            /**
             * Cloning a selection with COW
             * FIXME: check whether it's faster than usual bitBlt'ing
             */
            tempSelection = new KisSelection(*tempSelection);

            KisPainter gc2(tempSelection->pixelSelection());
            gc2.setOpacity(temporaryOpacity());
            gc2.setCompositeOp(temporaryCompositeOp());
            gc2.bitBlt(rect.topLeft(), temporaryTarget(), rect);
        }

        projection->clear(rect);
        gc.setCompositeOp(colorSpace()->compositeOp(COMPOSITE_OVER));
        gc.setSelection(tempSelection);
    } else
        gc.setCompositeOp(colorSpace()->compositeOp(COMPOSITE_COPY));


    gc.bitBlt(rect.topLeft(), original, rect);

    unlockTemporaryTarget();
}
void KisSelectionToVectorActionFactory::run(KisView2 *view)
{
    KisSelectionSP selection = view->selection();

    if (selection->hasShapeSelection() ||
        !selection->outlineCacheValid()) {

        return;
    }

    QPainterPath selectionOutline = selection->outlineCache();
    QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform();

    KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline));
    shape->setShapeId(KoPathShapeId);

    /**
     * Mark a shape that it belongs to a shape selection
     */
    if(!shape->userData()) {
        shape->setUserData(new KisShapeSelectionMarker);
    }

    KisProcessingApplicator *ap = beginAction(view, i18n("Convert to Vector Selection"));

    ap->applyCommand(view->canvasBase()->shapeController()->addShape(shape),
                     KisStrokeJobData::SEQUENTIAL,
                     KisStrokeJobData::EXCLUSIVE);

    endAction(ap, KisOperationConfiguration(id()).toXML());
}
void KisFilterTest::testDifferentSrcAndDst()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();

    QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");
    QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png");
    KisPaintDeviceSP src = new KisPaintDevice(cs);
    KisPaintDeviceSP dst = new KisPaintDevice(cs);
    KisSelectionSP sel = new KisSelection(new KisSelectionDefaultBounds(src));
    sel->getOrCreatePixelSelection()->invert(); // select everything
    sel->updateProjection();

    src->convertFromQImage(qimage, 0, 0, 0);

    KisFilterSP f = KisFilterRegistry::instance()->value("invert");
    Q_ASSERT(f);

    KisFilterConfiguration * kfc = f->defaultConfiguration(0);
    Q_ASSERT(kfc);

    f->process(src, dst, sel, QRect(QPoint(0,0), qimage.size()), kfc);

    QPoint errpoint;
    if (!TestUtil::compareQImages(errpoint, inverted, dst->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) {
        dst->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtertest.png");
        QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1());
    }
}
Example #4
0
void paintBevelSelection(KisPixelSelectionSP srcSelection,
                         KisPixelSelectionSP dstSelection,
                         const QRect &applyRect,
                         int size,
                         int initialSize,
                         bool invert)
{
    KisSelectionSP tmpBaseSelection = new KisSelection(new KisSelectionEmptyBounds(0));
    KisPixelSelectionSP tmpSelection = tmpBaseSelection->pixelSelection();

    // NOTE: we are not using createCompositionSourceDevice() intentionally,
    //       because the source device doesn't have alpha channel
    KisPixelSelectionSP fillDevice = new KisPixelSelection();

    KisPainter gc(dstSelection);
    gc.setCompositeOp(COMPOSITE_COPY);

    for (int i = 0; i < size; i++) {
        const int growSize = initialSize - i - 1;

        quint8 selectedness = invert ?
            qRound(qreal(size - i - 1) / size * 255.0) :
            qRound(qreal(i + 1) / size * 255.0);
        fillDevice->setDefaultPixel(KoColor(&selectedness, fillDevice->colorSpace()));

        tmpSelection->makeCloneFromRough(srcSelection, srcSelection->selectedRect());

        QRect changeRect = KisLsUtils::growSelectionUniform(tmpSelection, growSize, applyRect);

        gc.setSelection(tmpBaseSelection);
        gc.bitBlt(changeRect.topLeft(), fillDevice, changeRect);
    }
}
Example #5
0
void KisMaskTest::testCropUpdateBySelection()
{
    TestUtil::MaskParent p;

    /**
     * We do not use exact selection bounds for cropping,
     * so the rects should be covered by different tiles
     */
    QRect selectionRect(10, 10, 20, 20);
    QRect updateRect(64, 64, 20, 20);

    TestMaskSP mask = new TestMask;

    KisSelectionSP sel = new KisSelection();
    sel->pixelSelection()->select(selectionRect, MAX_SELECTED);

    mask->initSelection(sel, p.layer);

    mask->apply(p.layer->projection(), updateRect);
    // Here we crash! :)

    /**
     * If you see a crash, it means KisMask tried to update
     * the area that is outside its selection.
     * Please consider fixing KisMask::apply() first
     */
}
Example #6
0
bool KisKraLoadVisitor::visit(KisAdjustmentLayer* layer)
{
    loadNodeKeyframes(layer);

    // Adjustmentlayers are tricky: there's the 1.x style and the 2.x
    // style, which has selections with selection components
    bool result = true;
    if (m_syntaxVersion == 1) {
        KisSelectionSP selection = new KisSelection();
        KisPixelSelectionSP pixelSelection = selection->pixelSelection();
        result = loadPaintDevice(pixelSelection, getLocation(layer, ".selection"));
        layer->setInternalSelection(selection);
    } else if (m_syntaxVersion == 2) {
        result = loadSelection(getLocation(layer), layer->internalSelection());

    } else {
        // We use the default, empty selection
    }

    if (!loadMetaData(layer)) {
        return false;
    }

    loadFilterConfiguration(layer->filter().data(), getLocation(layer, DOT_FILTERCONFIG));

    result = visitAll(layer);
    return result;
}
Example #7
0
void KisMaskTest::testDeferredOffsetInitialization()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(0, 100, 100, cs, "stest");

    KisMaskSP mask = new TestMask;

    QCOMPARE(mask->x(), 0);
    QCOMPARE(mask->y(), 0);

    mask->setX(10);
    QCOMPARE(mask->x(), 10);
    QCOMPARE(mask->y(), 0);

    mask->setY(11);
    QCOMPARE(mask->x(), 10);
    QCOMPARE(mask->y(), 11);

    mask->initSelection(image->rootLayer());

    // IMPORTANT: a bit weird behavior, but it is needed for
    // KisKraLoadVisitor to work properly
    QCOMPARE(mask->x(), 10);
    QCOMPARE(mask->y(), 11);

    // Now there is no deferred initialization, so the offest
    // should simply be reset
    mask->initSelection(image->rootLayer());
    QCOMPARE(mask->x(), 0);
    QCOMPARE(mask->y(), 0);

    KisSelectionSP selection = mask->selection();
    QCOMPARE(selection->parentNode(), KisNodeSP(mask));
}
Example #8
0
void KisSelectionToolHelper::addSelectionShape(KoShape* shape)
{
    bool hasSelection = m_layer->selection();

    m_canvas->startMacro(m_name);

    if (!hasSelection)
        m_canvas->addCommand(new KisSetGlobalSelectionCommand(m_image, 0));

    KisSelectionSP selection = m_layer->selection();

    if (selection->isDeselected())
        new KisSelectionTransaction(m_name, m_image, m_layer->selection());

    KisShapeSelection* shapeSelection;
    if (!selection->hasShapeSelection()) {
        shapeSelection = new KisShapeSelection(m_image, selection);
        selection->setShapeSelection(shapeSelection);
    } else {
        shapeSelection = static_cast<KisShapeSelection*>(selection->shapeSelection());
    }
    QUndoCommand * cmd = m_canvas->shapeController()->addShape(shape);
    m_canvas->addCommand(cmd);

    m_canvas->stopMacro();
}
Example #9
0
bool KisKraLoadVisitor::loadSelection(const QString& location, KisSelectionSP dstSelection)
{
    // Pixel selection
    bool result = true;
    QString pixelSelectionLocation = location + DOT_PIXEL_SELECTION;
    if (m_store->hasFile(pixelSelectionLocation)) {
        KisPixelSelectionSP pixelSelection = dstSelection->pixelSelection();
        result = loadPaintDevice(pixelSelection, pixelSelectionLocation);
        if (!result) {
            m_errorMessages << i18n("Could not load raster selection %1.", location);
        }
        pixelSelection->invalidateOutlineCache();
    }

    // Shape selection
    QString shapeSelectionLocation = location + DOT_SHAPE_SELECTION;
    if (m_store->hasFile(shapeSelectionLocation + "/content.xml")) {
        m_store->pushDirectory();
        m_store->enterDirectory(shapeSelectionLocation) ;

        KisShapeSelection* shapeSelection = new KisShapeSelection(m_image, dstSelection);
        dstSelection->setShapeSelection(shapeSelection);
        result = shapeSelection->loadSelection(m_store);
        m_store->popDirectory();
        if (!result) {
            m_errorMessages << i18n("Could not load vector selection %1.", location);
        }
    }
    return result;
}
void KisSelectionTest::testInvertSelection()
{
    KisSelectionSP selection = new KisSelection();
    KisPixelSelectionSP pixelSelection = selection->getOrCreatePixelSelection();
    pixelSelection->select(QRect(20, 20, 20, 20));
    QCOMPARE(pixelSelection->selected(30, 30), MAX_SELECTED);
    QCOMPARE(pixelSelection->selected(0, 0), MIN_SELECTED);
    QCOMPARE(pixelSelection->selected(512, 512), MIN_SELECTED);

    pixelSelection->invert();


    QCOMPARE(pixelSelection->selected(100, 100), MAX_SELECTED);
    QCOMPARE(pixelSelection->selected(22, 22), MIN_SELECTED);
    QCOMPARE(pixelSelection->selected(0, 0), MAX_SELECTED);
    QCOMPARE(pixelSelection->selected(512, 512), MAX_SELECTED);
    pixelSelection->convertToQImage(0, 0, 0, 100, 100).save("yyy.png");
    // XXX: This should happen automatically
    selection->updateProjection();
    selection->convertToQImage(0, 0, 0, 100, 100).save("zzz.png");

    QCOMPARE(selection->selectedExactRect(), QRect(qint32_MIN/2, qint32_MIN/2, qint32_MAX, qint32_MAX));
    QCOMPARE(selection->selectedRect(), QRect(qint32_MIN/2, qint32_MIN/2, qint32_MAX, qint32_MAX));

    QCOMPARE(selection->selected(100, 100), MAX_SELECTED);
    QCOMPARE(selection->selected(22, 22), MIN_SELECTED);
    QCOMPARE(selection->selected(10, 10), MAX_SELECTED);
    QCOMPARE(selection->selected(0, 0), MAX_SELECTED);
    QCOMPARE(selection->selected(512, 512), MAX_SELECTED);

}
    void copyFromDevice(KisViewManager *view, KisPaintDeviceSP device, bool makeSharpClip = false)
    {
        KisImageWSP image = view->image();
        if (!image) return;

        KisSelectionSP selection = view->selection();

        QRect rc = (selection) ? selection->selectedExactRect() : image->bounds();

        KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace());
        Q_CHECK_PTR(clip);

        const KoColorSpace *cs = clip->colorSpace();

        // TODO if the source is linked... copy from all linked layers?!?

        // Copy image data
        KisPainter::copyAreaOptimized(QPoint(), device, clip, rc);

        if (selection) {
            // Apply selection mask.
            KisPaintDeviceSP selectionProjection = selection->projection();
            KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width());
            KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width());

            const KoColorSpace *selCs = selection->projection()->colorSpace();

            for (qint32 y = 0; y < rc.height(); y++) {

                for (qint32 x = 0; x < rc.width(); x++) {

                    /**
                     * Sharp method is an exact reverse of COMPOSITE_OVER
                     * so if you cover the cut/copied piece over its source
                     * you get an exactly the same image without any seams
                     */
                    if (makeSharpClip) {
                        qreal dstAlpha = cs->opacityF(layerIt->rawData());
                        qreal sel = selCs->opacityF(selectionIt->oldRawData());
                        qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha);
                        float mask = newAlpha / dstAlpha;

                        cs->applyAlphaNormedFloatMask(layerIt->rawData(), &mask, 1);
                    } else {
                        cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1);
                    }

                    layerIt->nextPixel();
                    selectionIt->nextPixel();
                }
                layerIt->nextRow();
                selectionIt->nextRow();
            }
        }

        KisClipboard::instance()->setClip(clip, rc.topLeft());
    }
void KisImageResizeToSelectionActionFactory::run(KisViewManager *view)
{
    // XXX: "Add saving of XML data for Image Resize To Selection action"

    KisSelectionSP selection = view->selection();
    if (!selection) return;

    view->image()->cropImage(selection->selectedExactRect());
}
void testShapedGradientPainterImpl(const QPolygonF &selectionPolygon,
                                   const QString &testName,
                                   const QPolygonF &selectionErasePolygon = QPolygonF())
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP dev = new KisPaintDevice(cs);

    QRect imageRect(0,0,300,300);

    KisSelectionSP selection = new KisSelection();
    KisPixelSelectionSP pixelSelection = selection->pixelSelection();

    KisPainter selPainter(pixelSelection);
    selPainter.setFillStyle(KisPainter::FillStyleForegroundColor);
    selPainter.setPaintColor(KoColor(Qt::white, pixelSelection->colorSpace()));
    selPainter.paintPolygon(selectionPolygon);

    if (!selectionErasePolygon.isEmpty()) {
        selPainter.setCompositeOp(COMPOSITE_ERASE);
        selPainter.setPaintColor(KoColor(Qt::white, pixelSelection->colorSpace()));
        selPainter.paintPolygon(selectionErasePolygon);
    }

    selPainter.end();

    pixelSelection->invalidateOutlineCache();

    pixelSelection->convertToQImage(0, imageRect).save("sgt_selection.png");

    QLinearGradient testGradient;
    testGradient.setColorAt(0.0, Qt::white);
    testGradient.setColorAt(0.5, Qt::green);
    testGradient.setColorAt(1.0, Qt::black);
    testGradient.setSpread(QGradient::ReflectSpread);
    QScopedPointer<KoStopGradient> gradient(
        KoStopGradient::fromQGradient(&testGradient));

    KisGradientPainter gc(dev, selection);
    gc.setGradient(gradient.data());
    gc.setGradientShape(KisGradientPainter::GradientShapePolygonal);

    gc.paintGradient(selectionPolygon.boundingRect().topLeft(),
                     selectionPolygon.boundingRect().bottomRight(),
                     KisGradientPainter::GradientRepeatNone,
                     0,
                     false,
                     imageRect.x(),
                     imageRect.y(),
                     imageRect.width(),
                     imageRect.height());

    QVERIFY(TestUtil::checkQImageExternal(dev->convertToQImage(0, imageRect),
                                          "shaped_gradient",
                                          "fill",
                                          testName, 1, 1, 0));
}
void KisImageResizeToSelectionActionFactory::run(KisView2 *view)
{
#ifdef __GNUC__
#warning "Add saving of XML data for Image Resize To Selection action"
#endif

    KisSelectionSP selection = view->selection();
    if (!selection) return;

    view->image()->cropImage(selection->selectedExactRect());
}
void KisSelectionTest::testUpdatePixelSelection()
{
    KisSelectionSP selection = new KisSelection();
    KisPixelSelectionSP pSel = selection->getOrCreatePixelSelection();
    pSel->select(QRect(0, 0, 348, 212));
    QVERIFY(selection->pixelSelection()->selectedExactRect() == QRect(0, 0, 348, 212));
    selection->updateProjection(QRect(0, 0, 348, 212));
    for (int i = 0; i < 212; ++i) {
        for (int j = 0; j < 348; ++j) {
            QVERIFY(selection->selected(j, i) == MAX_SELECTED);
        }
    }

}
void KisFillActionFactory::run(const QString &fillSource, KisViewManager *view)
{
    KisNodeSP node = view->activeNode();
    if (!node || !node->hasEditablePaintDevice()) return;

    KisSelectionSP selection = view->selection();
    QRect selectedRect = selection ?
                         selection->selectedRect() : view->image()->bounds();
    Q_UNUSED(selectedRect);
    KisPaintDeviceSP filled = node->paintDevice()->createCompositionSourceDevice();
    Q_UNUSED(filled);
    bool usePattern = false;
    bool useBgColor = false;

    if (fillSource.contains("pattern")) {
        usePattern = true;
    } else if (fillSource.contains("bg")) {
        useBgColor = true;
    }

    KisProcessingApplicator applicator(view->image(), node,
                                       KisProcessingApplicator::NONE,
                                       KisImageSignalVector() << ModifiedSignal,
                                       kundo2_i18n("Flood Fill Layer"));

    KisResourcesSnapshotSP resources =
        new KisResourcesSnapshot(view->image(), node, 0, view->resourceProvider()->resourceManager());
    if (!fillSource.contains("opacity")) {
        resources->setOpacity(1.0);
    }

    KisProcessingVisitorSP visitor =
        new FillProcessingVisitor(QPoint(0, 0), // start position
                                  selection,
                                  resources,
                                  false, // fast mode
                                  usePattern,
                                  true, // fill only selection,
                                  0, // feathering radius
                                  0, // sizemod
                                  80, // threshold,
                                  false, // unmerged
                                  useBgColor);

    applicator.applyVisitor(visitor,
                            KisStrokeJobData::SEQUENTIAL,
                            KisStrokeJobData::EXCLUSIVE);

    applicator.end();
}
void KisSelectionTest::testCopy()
{
    KisSelectionSP sel = new KisSelection();
    sel->getOrCreatePixelSelection()->select(QRect(10, 10, 200, 200), 128);
    KisSelectionSP sel2 = new KisSelection(*sel.data());
    QCOMPARE(sel2->selectedExactRect(), sel->selectedExactRect());
    QPoint errpoint;
    if (!TestUtil::comparePaintDevices(errpoint, sel, sel2)) {
        sel2->convertToQImage(0, 0, 0, 200, 200).save("merge_visitor6.png");
        QFAIL(QString("Failed to copy selection, first different pixel: %1,%2 ")
              .arg(errpoint.x())
              .arg(errpoint.y())
              .toAscii());
    }
}
Example #18
0
void KisMaskTest::testSelection()
{
    TestUtil::MaskParent p;
    TestMaskSP mask = new TestMask;

    KisSelectionSP sel = new KisSelection();
    sel->pixelSelection()->select(QRect(0,0,100,100), MAX_SELECTED);

    mask->initSelection(sel, p.layer);

    QCOMPARE(mask->extent(), QRect(0,0,128,128));
    QCOMPARE(mask->exactBounds(), QRect(0,0,100,100));

    mask->select(QRect(0,0,500,500), MAX_SELECTED);;

    QCOMPARE(mask->extent(), QRect(0,0,512,512));
    QCOMPARE(mask->exactBounds(), QRect(0,0,500,500));
}
void KisSelectionBasedLayer::setInternalSelection(KisSelectionSP selection)
{
    if (selection) {
        m_d->selection = new KisSelection(*selection.data());
        m_d->selection->setParentNode(this);
        m_d->selection->updateProjection();
    } else
        m_d->selection = 0;
}
Example #20
0
    KisSelectionSP selectionFromAlphaChannel(KisPaintDeviceSP device,
                                             const QRect &srcRect)
    {
        const KoColorSpace *cs = device->colorSpace();

        KisSelectionSP baseSelection = new KisSelection(new KisSelectionEmptyBounds(0));
        KisPixelSelectionSP selection = baseSelection->pixelSelection();

        KisSequentialConstIterator srcIt(device, srcRect);
        KisSequentialIterator dstIt(selection, srcRect);

        do {
            quint8 *dstPtr = dstIt.rawData();
            const quint8* srcPtr = srcIt.rawDataConst();
            *dstPtr = cs->opacityU8(srcPtr);
        } while(srcIt.nextPixel() && dstIt.nextPixel());

        return baseSelection;
    }
Example #21
0
void KisMaskTest::testSelectionParent()
{
    {
        const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
        KisImageSP image = new KisImage(0, 100, 100, cs, "stest");

        KisMaskSP mask = new TestMask;
        mask->initSelection(image->rootLayer());
        KisSelectionSP selection = mask->selection();
        QCOMPARE(selection->parentNode(), KisNodeSP(mask));
    }

    {
        KisMaskSP mask = new TestMask;
        mask->setSelection(new KisSelection());
        KisSelectionSP selection = mask->selection();
        QCOMPARE(selection->parentNode(), KisNodeSP(mask));
    }
}
    void copyFromDevice(KisView2 *view, KisPaintDeviceSP device) {
        KisImageWSP image = view->image();
        KisSelectionSP selection = view->selection();

        QRect rc = (selection) ? selection->selectedExactRect() : image->bounds();

        KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace());
        Q_CHECK_PTR(clip);

        const KoColorSpace *cs = clip->colorSpace();

        // TODO if the source is linked... copy from all linked layers?!?

        // Copy image data
        KisPainter gc;
        gc.begin(clip);
        gc.setCompositeOp(COMPOSITE_COPY);
        gc.bitBlt(0, 0, device, rc.x(), rc.y(), rc.width(), rc.height());
        gc.end();

        if (selection) {
            // Apply selection mask.
            KisPaintDeviceSP selectionProjection = selection->projection();
            KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width());
            KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width());

            for (qint32 y = 0; y < rc.height(); y++) {

                for (qint32 x = 0; x < rc.width(); x++) {

                    cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1);

                    layerIt->nextPixel();
                    selectionIt->nextPixel();
                }
                layerIt->nextRow();
                selectionIt->nextRow();
            }
        }

        KisClipboard::instance()->setClip(clip, rc.topLeft());
    }
bool KisMirrorVisitor::mirrorMask(KisMask* mask)
{
    KoProperties properties;
    KisSelectionSP selection = mask->selection();
    if (selection->hasPixelSelection()) {
        KisPaintDeviceSP dev = selection->pixelSelection();

        QString name;
        if (m_orientation == Qt::Horizontal) {
            name = i18n("Mirror Mask X");
        } else {
            name = i18n("Mirror Mask Y");
        }

        // TODO: use a selection transaction to cache the outline
        KisTransaction transaction(name, dev);

        QRect dirty;
        if (m_orientation == Qt::Horizontal) {
            dirty = KisTransformWorker::mirrorX(dev, m_image->width()/2.0f);
        } else {
            dirty = KisTransformWorker::mirrorY(dev, m_image->height()/2.0f);
        }
        mask->setDirty(dirty);
        transaction.commit(m_image->undoAdapter());
        dev->setDirty(dirty);
    }
/* TODO: Doesn't work correctly even thoush it's the same code as the shape layer
    if (selection->hasShapeSelection()) {
        if (m_orientation == Qt::Horizontal) {
            KisTransformVisitor visitor(m_image, -1.0, 1.0, 0.0, 0.0, 0.0, m_image->width(), 0, 0, 0, true);
            mask->accept(visitor);
        } else {
            KisTransformVisitor visitor(m_image, 1.0, -1.0, 0.0, 0.0, 0.0, 0, m_image->height(), 0, 0, true);
            mask->accept(visitor);
        }
    } */
    selection->updateProjection();
    return true;
}
bool KisKraSaveVisitor::saveSelection(KisNode* node)
{
    KisSelectionSP selection;
    if (node->inherits("KisMask")) {
        selection = static_cast<KisMask*>(node)->selection();
    } else if (node->inherits("KisAdjustmentLayer")) {
        selection = static_cast<KisAdjustmentLayer*>(node)->internalSelection();
    } else if (node->inherits("KisGeneratorLayer")) {
        selection = static_cast<KisGeneratorLayer*>(node)->internalSelection();
    } else {
        return false;
    }

    bool retval = true;

    if (selection->hasPixelSelection()) {
        KisPaintDeviceSP dev = selection->pixelSelection();
        if (!savePaintDevice(dev, getLocation(node, DOT_PIXEL_SELECTION))) {
            m_errorMessages << i18n("Failed to save the pixel selection data for layer %1.", node->name());
            retval = false;
        }
    }
    if (selection->hasShapeSelection()) {
        m_store->pushDirectory();
        retval = m_store->enterDirectory(getLocation(node, DOT_SHAPE_SELECTION));
        if (retval) {
            KisShapeSelection* shapeSelection = dynamic_cast<KisShapeSelection*>(selection->shapeSelection());
            if (!shapeSelection) {
                retval = false;
            }

            if (retval && !shapeSelection->saveSelection(m_store)) {
                m_errorMessages << i18n("Failed to save the vector selection data for layer %1.", node->name());
                retval = false;
            }
        }
        m_store->popDirectory();
    }
    return retval;
}
Example #25
0
bool KisKraLoadVisitor::visit(KisPaintLayer *layer)
{
    loadNodeKeyframes(layer);

    dbgFile << "Visit: " << layer->name() << " colorSpace: " << layer->colorSpace()->id();
    if (!loadPaintDevice(layer->paintDevice(), getLocation(layer))) {
        return false;
    }
    if (!loadProfile(layer->paintDevice(), getLocation(layer, DOT_ICC))) {
        return false;
    }
    if (!loadMetaData(layer)) {
        return false;
    }

    if (m_syntaxVersion == 1) {
        // Check whether there is a file with a .mask extension in the
        // layer directory, if so, it's an old-style transparency mask
        // that should be converted.
        QString location = getLocation(layer, ".mask");

        if (m_store->open(location)) {

            KisSelectionSP selection = KisSelectionSP(new KisSelection());
            KisPixelSelectionSP pixelSelection = selection->pixelSelection();
            if (!pixelSelection->read(m_store->device())) {
                pixelSelection->disconnect();
            } else {
                KisTransparencyMask* mask = new KisTransparencyMask();
                mask->setSelection(selection);
                m_image->addNode(mask, layer, layer->firstChild());
            }
            m_store->close();
        }
    }
    bool result = visitAll(layer);
    return result;
}
void KisSelectionTest::testSelectionExactBounds()
{
    QRect referenceImageRect(0,0,1000,1000);
    QRect referenceDeviceRect(10,10,1000,1000);

    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();

    KisImageSP image = new KisImage(0, referenceImageRect.width(),
                                    referenceImageRect.height(),
                                    cs, "stest");

    KisPaintDeviceSP device = new KisPaintDevice(cs);
    device->fill(referenceDeviceRect, KoColor(Qt::white, cs));

    QCOMPARE(device->exactBounds(), referenceDeviceRect);

    KisSelectionSP selection = new KisSelection(device, new KisSelectionDefaultBounds(device, image));

    quint8 defaultPixel = MAX_SELECTED;
    selection->setDefaultPixel(&defaultPixel);

    QCOMPARE(selection->selectedExactRect(), referenceImageRect | referenceDeviceRect);
}
                    KUndo2Command* paint() {
                        KisSelectionSP cutSelection = m_sel;
                        // Shrinking the cutting area was previously used
                        // for getting seamless cut-paste. Now we use makeSharpClip
                        // instead.
                        // QRect originalRect = cutSelection->selectedExactRect();
                        // static const int preciseSelectionThreshold = 16;
                        //
                        // if (originalRect.width() > preciseSelectionThreshold ||
                        //     originalRect.height() > preciseSelectionThreshold) {
                        //     cutSelection = new KisSelection(*m_sel);
                        //     delete cutSelection->flatten();
                        //
                        //     KisSelectionFilter* filter = new KisShrinkSelectionFilter(1, 1, false);
                        //
                        //     QRect processingRect = filter->changeRect(originalRect);
                        //     filter->process(cutSelection->pixelSelection(), processingRect);
                        // }

                        KisTransaction transaction(m_node->paintDevice());
                        m_node->paintDevice()->clearSelection(cutSelection);
                        m_node->setDirty(cutSelection->selectedRect());
                        return transaction.endAndTake();
                    }
void KisSelectionTest::testUpdateSelectionProjection()
{
    KisSelectionSP selection = new KisSelection();
    QVERIFY(selection->selectedExactRect().isNull());

    // Now fill the layer with some opaque pixels
    KisFillPainter gc(selection->getOrCreatePixelSelection());
    gc.fillRect(QRect(0, 0, 100, 100),
                KoColor(QColor(0, 0, 0, 0), KoColorSpaceRegistry::instance()->rgb8()),
                MAX_SELECTED);
    gc.end();

    QVERIFY(selection->pixelSelection()->selectedExactRect() == QRect(0, 0, 100, 100));
    selection->updateProjection();
    QCOMPARE(selection->pixelSelection()->selectedExactRect(), QRect(0, 0, 100, 100));
    QCOMPARE(selection->selectedExactRect(), QRect(0, 0, 100, 100));
}
void KisShapeSelectionTest::testAddChild()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(new KisUndoAdapter(0), 300, 300, cs, "test");

    KisSelectionSP selection = new KisSelection();
    QVERIFY(selection->hasPixelSelection() == false);
    QVERIFY(selection->hasShapeSelection() == false);
    KisPixelSelectionSP pixelSelection = selection->getOrCreatePixelSelection();

    pixelSelection->select(QRect(0, 0, 100, 100));
    // Selection is using the pixel selection as datamanager so no projection update
    // needed
    QCOMPARE(pixelSelection->selected(25, 25), MAX_SELECTED);
    QCOMPARE(selection->selectedExactRect(), QRect(0, 0, 100, 100));

    QRect rect(50, 50, 100, 100);
    QTransform matrix;
    matrix.scale(1 / image->xRes(), 1 / image->yRes());
    rect = matrix.mapRect(rect);

    KoPathShape* shape = new KoPathShape();
    shape->setShapeId(KoPathShapeId);
    shape->moveTo(rect.topLeft());
    shape->lineTo(rect.topLeft() + QPointF(rect.width(), 0));
    shape->lineTo(rect.bottomRight());
    shape->lineTo(rect.topLeft() + QPointF(0, rect.height()));
    shape->close();
    shape->normalize();

    KisShapeSelection * shapeSelection = new KisShapeSelection(image, selection);
    selection->setShapeSelection(shapeSelection);
    shapeSelection->addShape(shape);

    QCOMPARE(pixelSelection->selected(25, 25), MAX_SELECTED);
    QCOMPARE(selection->selectedExactRect(), QRect(0, 0, 150, 150));

    selection->updateProjection();
}
void KisTransformProcessingVisitor::transformSelection(KisSelectionSP selection, KisUndoAdapter *adapter, const ProgressHelper &helper)
{
    if(selection->hasPixelSelection()) {
        transformPaintDevice(selection->pixelSelection(), adapter, helper);
    }

    if (selection->hasShapeSelection()) {
        KisTransformWorker tw(selection->projection(), m_sx, m_sy, m_shearx, m_sheary,
                              m_shearOrigin.x(), m_shearOrigin.y(),
                              m_angle, m_tx, m_ty, 0,
                              m_filter);

        KUndo2Command* command =
            selection->shapeSelection()->transform(tw.transform() * m_shapesCorrection);
        if (command) {
            adapter->addCommand(command);
        }
    }

    selection->updateProjection();
}