void KisZoomAndPanTest::initializeViewport(ZoomAndPanTester &t, bool fullscreenMode, bool rotate, bool mirror)
{
    QCOMPARE(t.image()->size(), QSize(640,441));
    QCOMPARE(t.image()->xRes(), 1.0);
    QCOMPARE(t.image()->yRes(), 1.0);

    t.canvasController()->resize(QSize(500,500));
    t.zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, 1.0);
    t.canvasController()->setPreferredCenter(QPoint(320,220));

    QCOMPARE(t.canvasWidget()->size(), QSize(483,483));
    QCOMPARE(t.canvasWidget()->size(), t.canvasController()->viewportSize());
    QVERIFY(verifyOffset(t, QPoint(79,-21)));

    if (fullscreenMode) {
        QCOMPARE(t.canvasController()->preferredCenter(), QPointF(320,220));

        QAction *action = t.view()->actionCollection()->action("view_show_just_the_canvas");
        action->setChecked(true);

        QVERIFY(verifyOffset(t, QPoint(79,-21)));
        QCOMPARE(t.canvasController()->preferredCenter(), QPointF(329,220));


        t.canvasController()->resize(QSize(483,483));
        QCOMPARE(t.canvasWidget()->size(), QSize(483,483));
        QCOMPARE(t.canvasWidget()->size(), t.canvasController()->viewportSize());
        QVERIFY(verifyOffset(t, QPoint(79,-21)));


        /**
         * FIXME: here is a small flaw in KoCanvasControllerWidget
         * We cannot set the center point explicitly, because it'll be rounded
         * up by recenterPreferred function, so real center point will be
         * different. Make the preferredCenter() return real center of the
         * image instead of the set value
         */
        QCOMPARE(t.canvasController()->preferredCenter(), QPointF(320.5,220));
    }

    if (rotate) {
        t.canvasController()->rotateCanvas(90);
        QVERIFY(verifyOffset(t, QPoint(-21,79)));
        QVERIFY(compareWithRounding(QPointF(220,320), t.canvasController()->preferredCenter(), 2));
        QCOMPARE(t.coordinatesConverter()->imageRectInWidgetPixels().topLeft().toPoint(), -t.coordinatesConverter()->documentOffset());
    }

    if (mirror) {
        t.canvasController()->mirrorCanvas(true);
        QVERIFY(verifyOffset(t, QPoint(78, -21)));
        QVERIFY(compareWithRounding(QPointF(320,220), t.canvasController()->preferredCenter(), 2));
        QCOMPARE(t.coordinatesConverter()->imageRectInWidgetPixels().topLeft().toPoint(), -t.coordinatesConverter()->documentOffset());
    }
}
void KisZoomAndPanTest::testImageCropped()
{
    ZoomAndPanTester t;
    QApplication::processEvents();
    initializeViewport(t, false, false, false);
    QApplication::processEvents();
    QVERIFY(checkPan(t, QPoint(-150,-150)));
    QApplication::processEvents();

    QPointF oldStillPoint =
        t.coordinatesConverter()->imageToWidget(QPointF(150,150));

    t.image()->cropImage(QRect(100,100,100,100));
    t.image()->waitForDone();
    QApplication::processEvents();

    QPointF newStillPoint =
        t.coordinatesConverter()->imageToWidget(QPointF(50,50));

    QVERIFY(compareWithRounding(oldStillPoint, newStillPoint, 1.0));
}
void KisZoomAndPanTest::testZoom100ChangingWidgetSize()
{
    ZoomAndPanTester t;

    QCOMPARE(t.image()->size(), QSize(640,441));
    QCOMPARE(t.image()->xRes(), 1.0);
    QCOMPARE(t.image()->yRes(), 1.0);

    t.canvasController()->resize(QSize(1000,1000));
    t.zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, 1.0);
    t.canvasController()->setPreferredCenter(QPoint(320,220));

    QCOMPARE(t.canvasWidget()->size(), QSize(983,983));
    QCOMPARE(t.canvasWidget()->size(), t.canvasController()->viewportSize());
    QVERIFY(verifyOffset(t, QPoint(-171,-271)));

    t.canvasController()->resize(QSize(700,700));

    QCOMPARE(t.canvasWidget()->size(), QSize(683,683));
    QCOMPARE(t.canvasWidget()->size(), t.canvasController()->viewportSize());
    QVERIFY(verifyOffset(t, QPoint(-171,-271)));

    t.canvasController()->setPreferredCenter(QPoint(320,220));

    QVERIFY(verifyOffset(t, QPoint(-21,-121)));

    t.canvasController()->resize(QSize(400,400));

    QCOMPARE(t.canvasWidget()->size(), QSize(383,383));
    QCOMPARE(t.canvasWidget()->size(), t.canvasController()->viewportSize());
    QVERIFY(verifyOffset(t, QPoint(-21,-121)));

    t.canvasController()->setPreferredCenter(QPoint(320,220));

    QVERIFY(verifyOffset(t, QPoint(129,29)));

    t.canvasController()->pan(QPoint(100,100));

    QVERIFY(verifyOffset(t, QPoint(229,129)));
}
void KisZoomAndPanTest::testImageRescaled_0_5()
{
    ZoomAndPanTester t;
    QApplication::processEvents();
    initializeViewport(t, false, false, false);
    QApplication::processEvents();
    QVERIFY(checkPan(t, QPoint(200,200)));
    QApplication::processEvents();

    QPointF oldStillPoint =
        t.coordinatesConverter()->imageRectInWidgetPixels().center();

    KisFilterStrategy *strategy = new KisBilinearFilterStrategy();
    t.image()->scaleImage(QSize(320, 220), t.image()->xRes(), t.image()->yRes(), strategy);
    t.image()->waitForDone();
    QApplication::processEvents();
    delete strategy;

    QPointF newStillPoint =
        t.coordinatesConverter()->imageRectInWidgetPixels().center();

    QVERIFY(compareWithRounding(oldStillPoint, newStillPoint, 1.0));
}
void KisZoomAndPanTest::testRotation(qreal vastScrolling, qreal zoom)
{
    KisConfig cfg;
    cfg.setVastScrolling(vastScrolling);

    ZoomAndPanTester t;

    QCOMPARE(t.image()->size(), QSize(640,441));
    QCOMPARE(t.image()->xRes(), 1.0);
    QCOMPARE(t.image()->yRes(), 1.0);

    QPointF preferredCenter = zoom * t.image()->bounds().center();

    t.canvasController()->resize(QSize(500,500));
    t.zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, zoom);
    t.canvasController()->setPreferredCenter(preferredCenter.toPoint());

    QCOMPARE(t.canvasWidget()->size(), QSize(483,483));
    QCOMPARE(t.canvasWidget()->size(), t.canvasController()->viewportSize());

    QPointF realCenterPoint = t.coordinatesConverter()->widgetToImage(t.coordinatesConverter()->widgetCenterPoint());
    QPointF expectedCenterPoint = QPointF(t.image()->bounds().center());

    if(!compareWithRounding(realCenterPoint, expectedCenterPoint, 2/zoom)) {
        qDebug() << "Failed to set initial center point";
        qDebug() << ppVar(expectedCenterPoint) << ppVar(realCenterPoint);
        QFAIL("FAIL: Failed to set initial center point");
    }

    QVERIFY(checkRotation(t, 30));
    QVERIFY(checkRotation(t, 20));
    QVERIFY(checkRotation(t, 10));
    QVERIFY(checkRotation(t, 5));
    QVERIFY(checkRotation(t, 5));
    QVERIFY(checkRotation(t, 5));

    if(vastScrolling < 0.5 && zoom < 1) {
        qWarning() << "Disabling a few tests for vast scrolling ="
                   << vastScrolling << ". See comment for more";
        /**
         * We have to disable a couple of tests here for the case when
         * vastScrolling value is 0.2. The problem is that the centering
         * correction applied  to the offset in
         * KisCanvasController::rotateCanvas pollutes the preferredCenter
         * value, because KoCnvasControllerWidget has no access to this
         * correction and cannot calculate the real value of the center of
         * the image. To fix this bug the calculation of correction
         * (aka "origin") should be moved to the KoCanvasControllerWidget
         * itself which would cause quite huge changes (including the change
         * of the external interface of it). Namely, we would have to
         * *calculate* offset from the value of the scroll bars, but not
         * use their values directly:
         *
         * offset = scrollBarValue - origin
         *
         * So now we just disable these unittests and allow a couple
         * of "jumping" bugs appear in vastScrolling < 0.5 modes, which
         * is, actually, not the default case.
         */

    } else {
        QVERIFY(checkRotation(t, 5));
        QVERIFY(checkRotation(t, 5));
        QVERIFY(checkRotation(t, 5));
    }
}