예제 #1
0
void KisTransformMaskTest::testMaskOnCloneLayer()
{
    QImage refImage(TestUtil::fetchDataFileLazy("test_transform_quality.png"));
    QRect refRect = refImage.rect();
    TestUtil::MaskParent p(refRect);

    p.layer->paintDevice()->convertFromQImage(refImage, 0);

    KisPaintLayerSP player = new KisPaintLayer(p.image, "bg", OPACITY_OPAQUE_U8, p.image->colorSpace());
    p.image->addNode(player, p.image->root(), KisNodeSP());

    KisCloneLayerSP clone = new KisCloneLayer(p.layer, p.image, "clone", OPACITY_OPAQUE_U8);
    p.image->addNode(clone, p.image->root());

    KisTransformMaskSP mask = new KisTransformMask();
    p.image->addNode(mask, clone);

    QTransform transform(-0.177454, -0.805953, -0.00213713,
                         -1.9295, -0.371835, -0.00290463,
                         3075.05, 2252.32, 7.62371);

    mask->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                 new KisDumbTransformMaskParams(transform)));

    QVERIFY(doPartialTests("cl", p.image, p.layer, clone, mask));
}
예제 #2
0
void KisTransformMaskTest::testMaskWithOffset()
{
    TestUtil::ExternalImageChecker chk("mask_with_offset", "transform_mask_updates");

    QRect refRect(0,0,512,512);
    QRect fillRect(400,400,100,100);
    TestUtil::MaskParent p(refRect);

    p.layer->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));

    KisPaintLayerSP player = new KisPaintLayer(p.image, "bg", OPACITY_OPAQUE_U8, p.image->colorSpace());
    p.image->addNode(player, p.image->root(), KisNodeSP());

    KisTransformMaskSP mask1 = new KisTransformMask();
    p.image->addNode(mask1, p.layer);

    mask1->setName("mask1");

    p.layer->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "00_initial_layer_update");

    QTest::qWait(4000);
    p.image->waitForDone();
    chk.checkImage(p.image, "00X_initial_layer_update");


    QTransform transform;

    transform = QTransform::fromTranslate(-150, 0);
    mask1->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform)));

    p.layer->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "01_mask1_moved_layer_update");

    QTest::qWait(4000);
    p.image->waitForDone();
    chk.checkImage(p.image, "01X_mask1_moved_layer_update");

    mask1->setY(-150);

    mask1->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "02_mask1_y_offset");

    QTest::qWait(4000);
    p.image->waitForDone();
    chk.checkImage(p.image, "02X_mask1_y_offset");

    QVERIFY(chk.testPassed());
}
예제 #3
0
void KisTransformMaskTest::testTransformHiddenPartsOfTheGroup()
{
    //TestUtil::ExternalImageChecker chk("mask_with_offset", "transform_mask_updates");

    QRect imageRect(0,0,512,512);
    QRect fillRect(10, 10, 236, 236);
    QRect outsideFillRect = fillRect.translated(0, -1.5 * 256);

    TestUtil::MaskParent p(imageRect);

    //p.layer->paintDevice()->fill(fillRect, KoColor(Qt::green, p.layer->colorSpace()));

    p.image->initialRefreshGraph();

    KisGroupLayerSP glayer = new KisGroupLayer(p.image, "gl", OPACITY_OPAQUE_U8);
    p.image->addNode(glayer, p.image->root());

    KisPaintLayerSP player1 = new KisPaintLayer(p.image, "pl1", OPACITY_OPAQUE_U8, p.image->colorSpace());
    player1->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));
    player1->paintDevice()->fill(outsideFillRect, KoColor(Qt::blue, p.layer->colorSpace()));
    p.image->addNode(player1, glayer);

    player1->setDirty();
    p.image->waitForDone();

    QCOMPARE(p.image->projection()->exactBounds(), fillRect);

    //KIS_DUMP_DEVICE_2(p.image->projection(), imageRect, "image_proj_initial", "dd");

    KisTransformMaskSP mask1 = new KisTransformMask();
    mask1->setName("mask1");
    QTransform transform1 =
        QTransform::fromTranslate(0, 1.5 * 256);
    mask1->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform1)));

    p.image->addNode(mask1, player1);

    mask1->setDirty();
    p.image->waitForDone();

    /**
     * Transform mask i sexpected to crop the externals of the layer by 50%
     * far behind the layer border! Take care!
     */
    QCOMPARE(p.image->projection()->exactBounds(), QRect(10, 128, 236, 384));

    //KIS_DUMP_DEVICE_2(p.image->projection(), imageRect, "image_proj_mask", "dd");
}
예제 #4
0
void KisTransformMaskTest::testMaskOnCloneLayerWithOffset()
{
    TestUtil::ExternalImageChecker chk("clone_offset_simple", "transform_mask_updates");

    QRect refRect(0,0,512,512);
    QRect fillRect(400,400,100,100);
    TestUtil::MaskParent p(refRect);

    p.layer->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));

    KisPaintLayerSP player = new KisPaintLayer(p.image, "bg", OPACITY_OPAQUE_U8, p.image->colorSpace());
    p.image->addNode(player, p.image->root(), KisNodeSP());

    KisCloneLayerSP clone = new KisCloneLayer(p.layer, p.image, "clone", OPACITY_OPAQUE_U8);
    p.image->addNode(clone, p.image->root());

    KisTransformMaskSP mask = new KisTransformMask();
    p.image->addNode(mask, clone);

    QTransform transform(1, 0, 0,
                         0, 1, 0,
                         0, -150, 1);

    mask->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                 new KisDumbTransformMaskParams(transform)));

    p.layer->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "0_initial");

    clone->setX(-300);
    clone->setDirty();
    p.image->waitForDone();
    chk.checkImage(p.image, "1_after_offset");

    mask->setDirty();
    p.image->waitForDone();
    chk.checkImage(p.image, "2_after_offset_dirty_mask");

    QTest::qWait(4000);
    chk.checkImage(p.image, "3_delayed_regeneration");

    KisPaintDeviceSP previewDevice = mask->buildPreviewDevice();
    chk.checkDevice(previewDevice, p.image, "4_preview_device");

    QVERIFY(chk.testPassed());

    QVERIFY(doPartialTests("clone_offset_complex", p.image, p.layer, clone, mask));
}
예제 #5
0
void KisTransformMaskTest::testWeirdFullUpdates()
{
    //TestUtil::ExternalImageChecker chk("mask_with_offset", "transform_mask_updates");

    QRect imageRect(0,0,512,512);
    QRect fillRect(10, 10, 236, 236);
    TestUtil::MaskParent p(imageRect);

    p.layer->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));

    KisPaintLayerSP player1 = new KisPaintLayer(p.image, "pl1", OPACITY_OPAQUE_U8, p.image->colorSpace());
    player1->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));
    p.image->addNode(player1, p.image->root());

    KisTransformMaskSP mask1 = new KisTransformMask();
    mask1->setName("mask1");
    QTransform transform1 =
        QTransform::fromTranslate(256, 0);
    mask1->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform1)));

    p.image->addNode(mask1, player1);


    KisPaintLayerSP player2 = new KisPaintLayer(p.image, "pl2", OPACITY_OPAQUE_U8, p.image->colorSpace());
    player2->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));
    p.image->addNode(player2, p.image->root());

    KisTransformMaskSP mask2 = new KisTransformMask();
    mask2->setName("mask2");
    QTransform transform2 =
        QTransform::fromTranslate(0, 256);
    mask2->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform2)));

    p.image->addNode(mask2, player2);


    KisPaintLayerSP player3 = new KisPaintLayer(p.image, "pl3", OPACITY_OPAQUE_U8, p.image->colorSpace());
    player3->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));
    p.image->addNode(player3, p.image->root());

    KisTransformMaskSP mask3 = new KisTransformMask();
    mask3->setName("mask3");
    QTransform transform3 =
        QTransform::fromTranslate(256, 256);
    mask3->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform3)));

    p.image->addNode(mask3, player3);



    //p.image->initialRefreshGraph();

    p.image->refreshGraphAsync(0, QRect(0,0,256,256), QRect());
    p.image->waitForDone();

    QVERIFY(player1->projection()->extent().isEmpty());
    QVERIFY(player1->projection()->exactBounds().isEmpty());

    QVERIFY(player2->projection()->extent().isEmpty());
    QVERIFY(player2->projection()->exactBounds().isEmpty());

    QVERIFY(player3->projection()->extent().isEmpty());
    QVERIFY(player3->projection()->exactBounds().isEmpty());

    QCOMPARE(p.image->projection()->exactBounds(), QRect(QRect(10,10,236,236)));



    p.image->refreshGraphAsync(0, QRect(0,256,256,256), QRect());
    p.image->waitForDone();

    QVERIFY(player1->projection()->extent().isEmpty());
    QVERIFY(player1->projection()->exactBounds().isEmpty());

    QVERIFY(!player2->projection()->extent().isEmpty());
    QVERIFY(!player2->projection()->exactBounds().isEmpty());

    QVERIFY(player3->projection()->extent().isEmpty());
    QVERIFY(player3->projection()->exactBounds().isEmpty());

    QCOMPARE(p.image->projection()->exactBounds(), QRect(QRect(10,10,236,492)));


    p.image->refreshGraphAsync(0, QRect(256,0,256,256), QRect());
    p.image->waitForDone();

    QVERIFY(!player1->projection()->extent().isEmpty());
    QVERIFY(!player1->projection()->exactBounds().isEmpty());

    QVERIFY(!player2->projection()->extent().isEmpty());
    QVERIFY(!player2->projection()->exactBounds().isEmpty());

    QVERIFY(player3->projection()->extent().isEmpty());
    QVERIFY(player3->projection()->exactBounds().isEmpty());

    QCOMPARE(p.image->projection()->exactBounds(), QRect(QRect(10,10,492,492)));
    QVERIFY((p.image->projection()->region() & QRect(256,256,256,256)).isEmpty());



    p.image->refreshGraphAsync(0, QRect(256,256,256,256), QRect());
    p.image->waitForDone();

    QVERIFY(!player1->projection()->extent().isEmpty());
    QVERIFY(!player1->projection()->exactBounds().isEmpty());

    QVERIFY(!player2->projection()->extent().isEmpty());
    QVERIFY(!player2->projection()->exactBounds().isEmpty());

    QVERIFY(!player3->projection()->extent().isEmpty());
    QVERIFY(!player3->projection()->exactBounds().isEmpty());

    QCOMPARE(p.image->projection()->exactBounds(), QRect(QRect(10,10,492,492)));
    QVERIFY(!(p.image->projection()->region() & QRect(256,256,256,256)).isEmpty());

    p.image->waitForDone();

    KIS_DUMP_DEVICE_2(p.image->projection(), imageRect, "image_proj", "dd");

}
예제 #6
0
void KisTransformMaskTest::testMultipleMasks()
{
    TestUtil::ExternalImageChecker chk("multiple_masks", "transform_mask_updates");

    QRect refRect(0,0,512,512);
    QRect fillRect(400,400,100,100);
    TestUtil::MaskParent p(refRect);

    p.layer->paintDevice()->fill(fillRect, KoColor(Qt::red, p.layer->colorSpace()));

    KisPaintLayerSP player = new KisPaintLayer(p.image, "bg", OPACITY_OPAQUE_U8, p.image->colorSpace());
    p.image->addNode(player, p.image->root(), KisNodeSP());

    //KisCloneLayerSP clone = new KisCloneLayer(p.layer, p.image, "clone", OPACITY_OPAQUE_U8);
    //p.image->addNode(clone, p.image->root());

    KisTransformMaskSP mask1 = new KisTransformMask();
    p.image->addNode(mask1, p.layer);

    KisTransformMaskSP mask2 = new KisTransformMask();
    p.image->addNode(mask2, p.layer);

    mask1->setName("mask1");
    mask2->setName("mask2");

    p.layer->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "00_initial_layer_update");

    QTransform transform;

    transform = QTransform::fromTranslate(-150, 0);
    mask1->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform)));

    p.layer->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "01_mask1_moved_layer_update");

    QTest::qWait(4000);
    p.image->waitForDone();
    chk.checkImage(p.image, "01X_mask1_moved_layer_update");


    transform = QTransform::fromTranslate(0, -150);
    mask2->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                  new KisDumbTransformMaskParams(transform)));

    p.layer->setDirty(refRect);
    p.image->waitForDone();
    chk.checkImage(p.image, "02_mask2_moved_layer_update");

    QTest::qWait(4000);
    p.image->waitForDone();
    chk.checkImage(p.image, "02X_mask2_moved_layer_update");

#ifdef CHECK_MASK1_TOGGLE

    {
        mask1->setVisible(false);
        mask1->setDirty(refRect);
        p.image->waitForDone();
        chk.checkImage(p.image, "03_mask1_tg_off_refRect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "03X_mask1_tg_off_refRect");


        mask1->setVisible(true);
        mask1->setDirty(refRect);
        p.image->waitForDone();
        chk.checkImage(p.image, "04_mask1_tg_on_refRect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "04X_mask1_tg_on_refRect");


        mask1->setVisible(false);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "05_mask1_tg_off_default_rect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "05X_mask1_tg_off_default_rect");


        mask1->setVisible(true);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "06_mask1_tg_on_default_rect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "06X_mask1_tg_on_default_rect");
    }
#endif /* CHECK_MASK1_TOGGLE */


#ifdef CHECK_MASK2_TOGGLE

    {
        mask2->setVisible(false);
        mask2->setDirty(refRect);
        p.image->waitForDone();
        chk.checkImage(p.image, "07_mask2_tg_off_refRect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "07X_mask2_tg_off_refRect");


        mask2->setVisible(true);
        mask2->setDirty(refRect);
        p.image->waitForDone();
        chk.checkImage(p.image, "08_mask2_tg_on_refRect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "08X_mask2_tg_on_refRect");

        mask2->setVisible(false);
        mask2->setDirty(refRect);
        p.image->waitForDone();
        chk.checkImage(p.image, "09_mask2_tg_off_default_rect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "09X_mask2_tg_off_default_rect");


        mask2->setVisible(true);
        mask2->setDirty(refRect);
        p.image->waitForDone();
        chk.checkImage(p.image, "10_mask2_tg_on_default_rect");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "10X_mask2_tg_on_default_rect");

    }

#endif /* CHECK_MASK2_TOGGLE */


#ifdef CHECK_HIDE_ALL

    {
        mask1->setVisible(false);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "11.1_hide_both_update_default_mask1");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "11.1X_hide_both_update_default_mask1");

        mask2->setVisible(false);
        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "11.2_hide_both_update_default_mask2");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "11.2X_hide_both_update_default_mask2");

        mask1->setVisible(true);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "12_sh_mask1_on");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "12X_sh_mask1_on");

        mask1->setVisible(false);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "13_sh_mask1_off");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "13X_sh_mask1_off");

        mask2->setVisible(true);
        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "14_sh_mask2_on");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "14X_sh_mask2_on");


        mask2->setVisible(false);
        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "15_sh_mask2_off");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "15X_sh_mask2_off");
    }

#endif /* CHECK_HIDE_ALL */

#ifdef CHECK_HIDE_ALL_AFTER_MOVE

    {
        transform = QTransform::fromTranslate(50, -150);
        mask2->setTransformParams(KisTransformMaskParamsInterfaceSP(
                                      new KisDumbTransformMaskParams(transform)));

        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "20_moved_mask2");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "20X_moved_mask2");
    }

    {
        mask1->setVisible(false);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "21.1_hide_both_update_default_mask1");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "21.1X_hide_both_update_default_mask1");

        mask2->setVisible(false);
        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "21.2_hide_both_update_default_mask2");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "21.2X_hide_both_update_default_mask2");

        mask1->setVisible(true);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "22_sh_mask1_on");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "22X_sh_mask1_on");

        mask1->setVisible(false);
        mask1->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "23_sh_mask1_off");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "23X_sh_mask1_off");

        mask2->setVisible(true);
        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "24_sh_mask2_on");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "24X_sh_mask2_on");


        mask2->setVisible(false);
        mask2->setDirty();
        p.image->waitForDone();
        chk.checkImage(p.image, "25_sh_mask2_off");

        QTest::qWait(4000);
        p.image->waitForDone();
        chk.checkImage(p.image, "25X_sh_mask2_off");
    }

#endif /* CHECK_HIDE_ALL_AFTER_MOVE */

    QVERIFY(chk.testPassed());
}
KisTransformMaskParamsInterfaceSP KisTransformMaskParamsFactoryRegistry::animateParams(KisTransformMaskParamsInterfaceSP params)
{
    if (!m_animatedParamsFactory) return KisTransformMaskParamsInterfaceSP();

    return m_animatedParamsFactory(params);
}
KisTransformMaskParamsInterfaceSP
KisTransformMaskParamsFactoryRegistry::createParams(const QString &id, const QDomElement &e)
{
    KisTransformMaskParamsFactoryMap::iterator it = m_map.find(id);
    return it != m_map.end() ? (*it)(e) : KisTransformMaskParamsInterfaceSP(0);
}
예제 #9
0
void TransformStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
{
    TransformData *td = dynamic_cast<TransformData*>(data);
    ClearSelectionData *csd = dynamic_cast<ClearSelectionData*>(data);

    if(td) {
        m_savedTransformArgs = td->config;

        if (td->destination == TransformData::PAINT_DEVICE) {
            QRect oldExtent = td->node->extent();
            KisPaintDeviceSP device = td->node->paintDevice();

            if (device && !checkBelongsToSelection(device)) {
                KisPaintDeviceSP cachedPortion = getDeviceCache(device);
                Q_ASSERT(cachedPortion);

                KisTransaction transaction(device);

                KisProcessingVisitor::ProgressHelper helper(td->node);
                transformAndMergeDevice(td->config, cachedPortion,
                                        device, &helper);

                runAndSaveCommand(KUndo2CommandSP(transaction.endAndTake()),
                                  KisStrokeJobData::CONCURRENT,
                                  KisStrokeJobData::NORMAL);

                td->node->setDirty(oldExtent | td->node->extent());
            } if (KisExternalLayer *extLayer =
                  dynamic_cast<KisExternalLayer*>(td->node.data())) {

                if (td->config.mode() == ToolTransformArgs::FREE_TRANSFORM ||
                    td->config.mode() == ToolTransformArgs::PERSPECTIVE_4POINT) {

                    if (td->config.aX() || td->config.aY()) {
                        warnKrita << "Perspective transform of an external layer is not supported:" << extLayer->name();
                    }

                    QVector3D transformedCenter;
                    KisTransformWorker w = KisTransformUtils::createTransformWorker(td->config, 0, 0, &transformedCenter);
                    QTransform t = w.transform();

                    runAndSaveCommand(KUndo2CommandSP(extLayer->transform(t)),
                                      KisStrokeJobData::CONCURRENT,
                                      KisStrokeJobData::NORMAL);
                }

            } else if (KisTransformMask *transformMask =
                       dynamic_cast<KisTransformMask*>(td->node.data())) {

                runAndSaveCommand(KUndo2CommandSP(
                                      new ModifyTransformMaskCommand(transformMask,
                                                                     KisTransformMaskParamsInterfaceSP(
                                                                         new KisTransformMaskAdapter(td->config)))),
                                  KisStrokeJobData::CONCURRENT,
                                  KisStrokeJobData::NORMAL);
            }
        } else if (m_selection) {

            /**
             * We use usual transaction here, because we cannot calsulate
             * transformation for perspective and warp workers.
             */
            KisTransaction transaction(m_selection->pixelSelection());

            KisProcessingVisitor::ProgressHelper helper(td->node);
            KisTransformUtils::transformDevice(td->config,
                                               m_selection->pixelSelection(),
                                               &helper);

            runAndSaveCommand(KUndo2CommandSP(transaction.endAndTake()),
                              KisStrokeJobData::CONCURRENT,
                              KisStrokeJobData::NORMAL);
        }
    } else if (csd) {
        KisPaintDeviceSP device = csd->node->paintDevice();
        if (device && !checkBelongsToSelection(device)) {
            if (!haveDeviceInCache(device)) {
                putDeviceCache(device, createDeviceCache(device));
            }
            clearSelection(device);
        } else if (KisTransformMask *transformMask =
                   dynamic_cast<KisTransformMask*>(csd->node.data())) {

            runAndSaveCommand(KUndo2CommandSP(
                                  new ModifyTransformMaskCommand(transformMask,
                                                                 KisTransformMaskParamsInterfaceSP(
                                                                     new KisDumbTransformMaskParams(true)))),
                                  KisStrokeJobData::SEQUENTIAL,
                                  KisStrokeJobData::NORMAL);
        }
    } else {
        KisStrokeStrategyUndoCommandBased::doStrokeCallback(data);
    }
}