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 addPaintingJobs(KisImageWSP image, KisResourcesSnapshotSP resources, KisPainter *painter) {

        Q_ASSERT(painter == m_painterInfo->painter);
        Q_UNUSED(painter);

        KisPaintInformation pi1;
        KisPaintInformation pi2;

        pi1 = KisPaintInformation(QPointF(200, 200));
        pi2 = KisPaintInformation(QPointF(300, 300));

        image->addJob(strokeId(),
            new FreehandStrokeStrategy::Data(resources->currentNode(),
                                             m_painterInfo, pi1, pi2));
    }
KisFilterStrokeStrategy::KisFilterStrokeStrategy(KisFilterSP filter,
                                                 KisSafeFilterConfigurationSP filterConfig,
                                                 KisResourcesSnapshotSP resources)
    : KisPainterBasedStrokeStrategy("FILTER_STROKE", filter->name(), resources,
                                    QVector<PainterInfo*>()),
      m_d(new Private())
{
    m_d->filter = filter;
    m_d->filterConfig = filterConfig;
    m_d->node = resources->currentNode();
    m_d->updatesFacade = resources->image().data();
    m_d->cancelSilently = false;
    m_d->secondaryTransaction = 0;

    enableJob(KisSimpleStrokeStrategy::JOB_DOSTROKE);
}