438 lines
20 KiB
C++
438 lines
20 KiB
C++
#include "Document/EditorSession.h"
|
||
#include "Rendering/NavigatorGeometry.h"
|
||
#include "SessionFixtures.h"
|
||
#include "UI/NavigatorMinimap.h"
|
||
#include <QSettings>
|
||
#include <QStandardPaths>
|
||
#include <QtTest>
|
||
|
||
// Swift 1.4.9's Navigator: the geometry, the picture, the minimap.
|
||
class NavigatorTests : public QObject {
|
||
Q_OBJECT
|
||
private slots:
|
||
void initTestCase();
|
||
void documentFitsTheBoxCentered();
|
||
void visibleRectFollowsZoomAndPan();
|
||
void centeringKeepsZoomAndStopsFollowingFit();
|
||
void pictureFitsTheLongerSideAndShowsTheComposite();
|
||
void smallDocumentsAreNotEnlarged();
|
||
void minimapFitsTheDocument();
|
||
void hugeDocumentsWithAdjustmentsStillShow();
|
||
void blursShrinkWithThePicture();
|
||
void selectionChangesDoNotRedrawThePicture();
|
||
void placedMasksMotionAndEachAxisScale();
|
||
void editsInProgressStayOut();
|
||
void blursTakeTheWidthsFactor();
|
||
void theMinimapShowsFrom300PercentWhenTurnedOn();
|
||
void thePictureRedrawsOnceEditsSettle();
|
||
void aClickOrDragMovesTheView();
|
||
void theViewsBoxIsDrawnInTheAccent();
|
||
};
|
||
|
||
namespace {
|
||
ImportedImage red(int width, int height)
|
||
{
|
||
QImage image(width, height, QImage::Format_RGBA8888_Premultiplied);
|
||
image.fill(Qt::red);
|
||
return ImportedImage(image, image, QStringLiteral("Red"));
|
||
}
|
||
|
||
// A 400 by 300 document, viewed 800 by 600.
|
||
CanvasViewport viewport()
|
||
{
|
||
CanvasViewport viewport;
|
||
viewport.resize(QSizeF(800, 600), 1, QSizeF(400, 300));
|
||
return viewport;
|
||
}
|
||
|
||
QColor at(const QImage &image, int x, int y)
|
||
{
|
||
return image.pixelColor(x, y);
|
||
}
|
||
|
||
// A red layer of `size` at the origin.
|
||
QUuid placeRed(EditorSession &session, QSize pixels, QSizeF size)
|
||
{
|
||
session.insert(red(pixels.width(), pixels.height()));
|
||
const QUuid id = session.activeLayerID().value();
|
||
rewrite(session, [&](ProjectSnapshot &snapshot) {
|
||
record(snapshot, id).transform.origin = QPointF(0, 0);
|
||
record(snapshot, id).transform.size = size;
|
||
});
|
||
session.selectLayer(id);
|
||
return id;
|
||
}
|
||
|
||
struct Shown {
|
||
EditorSession session;
|
||
NavigatorMinimap minimap{session};
|
||
Shown()
|
||
{
|
||
NavigatorMinimap::setVisibleSetting(true);
|
||
session.createDocument(400, 300);
|
||
placeRed(session, QSize(400, 300), QSizeF(400, 300));
|
||
session.viewport.resize(QSizeF(800, 600), 1, QSizeF(400, 300));
|
||
session.zoom(4, session.viewport.center());
|
||
}
|
||
};
|
||
}
|
||
|
||
void NavigatorTests::initTestCase()
|
||
{
|
||
QStandardPaths::setTestModeEnabled(true);
|
||
QSettings().clear();
|
||
}
|
||
|
||
void NavigatorTests::documentFitsTheBoxCentered()
|
||
{
|
||
const NavigatorGeometry geometry{QSizeF(400, 200), QSizeF(200, 200)};
|
||
QCOMPARE(geometry.imageRect(), QRectF(0, 50, 200, 100));
|
||
QCOMPARE(geometry.thumbnailRect(QRectF(100, 50, 200, 100)), QRectF(50, 75, 100, 50));
|
||
QCOMPARE(geometry.documentPoint(QPointF(100, 100)), QPointF(200, 100));
|
||
// Points outside the picture land on the document's edge.
|
||
QCOMPARE(geometry.documentPoint(QPointF(-20, 199)), QPointF(0, 200));
|
||
QCOMPARE((NavigatorGeometry{QSizeF(0, 0), QSizeF(10, 10)}.imageRect()), QRectF());
|
||
QCOMPARE((NavigatorGeometry{QSizeF(0, 0), QSizeF(10, 10)}.documentPoint(QPointF(5, 5))), QPointF());
|
||
QCOMPARE((NavigatorGeometry{QSizeF(10, 10), QSizeF(0, 10)}.imageRect()), QRectF());
|
||
QCOMPARE((NavigatorGeometry{QSizeF(10, 0), QSizeF(10, 10)}.imageRect()), QRectF());
|
||
QCOMPARE((NavigatorGeometry{QSizeF(0, 10), QSizeF(10, 10)}.thumbnailRect(QRectF(1, 1, 2, 2))), QRectF());
|
||
QCOMPARE((NavigatorGeometry{QSizeF(0, 10), QSizeF(10, 10)}.documentPoint(QPointF(5, 5))), QPointF());
|
||
}
|
||
|
||
void NavigatorTests::visibleRectFollowsZoomAndPan()
|
||
{
|
||
const QSizeF size(400, 300);
|
||
CanvasViewport view = viewport();
|
||
view.setZoom(4, view.center(), size);
|
||
const QRectF visible = view.visibleDocumentRect(size);
|
||
QVERIFY(std::abs(visible.width() - 200) < 0.001 && std::abs(visible.height() - 150) < 0.001);
|
||
QVERIFY(std::abs(visible.center().x() - 200) < 0.001 && std::abs(visible.center().y() - 150) < 0.001);
|
||
// Panned by 40 points: 10 pixels across at 4×.
|
||
view.translate(QSizeF(40, -80));
|
||
QVERIFY(std::abs(view.visibleDocumentRect(size).center().x() - 190) < 0.001 && std::abs(view.visibleDocumentRect(size).center().y() - 170) < 0.001);
|
||
}
|
||
|
||
void NavigatorTests::centeringKeepsZoomAndStopsFollowingFit()
|
||
{
|
||
const QSizeF size(400, 300);
|
||
CanvasViewport view = viewport();
|
||
const double zoom = view.zoom();
|
||
view.centerView(QPointF(50, 60), size);
|
||
const QRectF visible = view.visibleDocumentRect(size);
|
||
QVERIFY(std::abs(visible.center().x() - 50) < 0.001 && std::abs(visible.center().y() - 60) < 0.001);
|
||
QCOMPARE(view.zoom(), zoom);
|
||
QVERIFY(!view.followsFit());
|
||
// At a backing scale of two, points per pixel halve.
|
||
CanvasViewport sharp;
|
||
sharp.resize(QSizeF(800, 600), 2, size);
|
||
sharp.setZoom(4, sharp.center(), size);
|
||
sharp.centerView(QPointF(50, 60), size);
|
||
QVERIFY(std::abs(sharp.visibleDocumentRect(size).center().x() - 50) < 0.001 && std::abs(sharp.visibleDocumentRect(size).center().y() - 60) < 0.001);
|
||
QCOMPARE(sharp.zoom(), 4.0);
|
||
// A later window resize keeps the view where it was.
|
||
view.resize(QSizeF(1000, 700), 1, size);
|
||
QCOMPARE(view.zoom(), zoom);
|
||
}
|
||
|
||
void NavigatorTests::pictureFitsTheLongerSideAndShowsTheComposite()
|
||
{
|
||
EditorSession session;
|
||
QVERIFY(!session.navigatorImage(100));
|
||
session.createDocument(400, 200);
|
||
QVERIFY(!session.navigatorImage(0));
|
||
placeRed(session, QSize(200, 200), QSizeF(200, 200));
|
||
const QImage picture = session.navigatorImage(100).value();
|
||
QCOMPARE(picture.size(), QSize(100, 50));
|
||
QCOMPARE(at(picture, 25, 25), QColor(255, 0, 0));
|
||
QCOMPARE(at(picture, 75, 25).alpha(), 0);
|
||
// Adjustment layers apply, as on the canvas.
|
||
session.addAdjustment(AdjustmentKind::invert);
|
||
QCOMPARE(at(session.navigatorImage(100).value(), 25, 25), QColor(0, 255, 255));
|
||
}
|
||
|
||
void NavigatorTests::smallDocumentsAreNotEnlarged()
|
||
{
|
||
EditorSession session;
|
||
session.createDocument(40, 30);
|
||
QCOMPARE(session.navigatorImage(900).value().size(), QSize(40, 30));
|
||
// Each side rounded, a pixel at least.
|
||
session.createDocument(1000, 3);
|
||
QCOMPARE(session.navigatorImage(100).value().size(), QSize(100, 1));
|
||
session.createDocument(1000, 15);
|
||
QCOMPARE(session.navigatorImage(100).value().size(), QSize(100, 2));
|
||
}
|
||
|
||
void NavigatorTests::minimapFitsTheDocument()
|
||
{
|
||
QCOMPARE(NavigatorMinimap::sizeFor(QSizeF(4000, 3000)), QSizeF(120, 90));
|
||
QCOMPARE(NavigatorMinimap::sizeFor(QSizeF(6000, 2000)), QSizeF(126, 42));
|
||
QCOMPARE(NavigatorMinimap::sizeFor(QSizeF(1000, 999)), QSizeF(90, 90));
|
||
// 125.7 rounds up.
|
||
QCOMPARE(NavigatorMinimap::sizeFor(QSizeF(1000, 716)), QSizeF(126, 90));
|
||
QCOMPARE(NavigatorMinimap::sizeFor(QSizeF(0, 0)), QSizeF(0, 0));
|
||
}
|
||
|
||
// Past one surface, drawn at the picture's size, it shows.
|
||
void NavigatorTests::hugeDocumentsWithAdjustmentsStillShow()
|
||
{
|
||
EditorSession session;
|
||
session.createDocument(20'000, 12'000);
|
||
placeRed(session, QSize(200, 120), QSizeF(20'000, 12'000));
|
||
session.addAdjustment(AdjustmentKind::invert);
|
||
const QImage picture = session.navigatorImage(100).value();
|
||
QCOMPARE(picture.size(), QSize(100, 60));
|
||
QCOMPARE(at(picture, 50, 30), QColor(0, 255, 255));
|
||
}
|
||
|
||
void NavigatorTests::blursShrinkWithThePicture()
|
||
{
|
||
EditorSession session;
|
||
session.createDocument(2000, 2000);
|
||
placeRed(session, QSize(100, 200), QSizeF(1000, 2000));
|
||
session.addAdjustment(AdjustmentKind::gaussianBlur);
|
||
session.setAdjustmentEditingID(std::nullopt);
|
||
const QUuid blur = session.activeLayerID().value();
|
||
LayerAdjustment adjustment = layerWith(session, blur).adjustment.value();
|
||
adjustment.blurRadius = 100;
|
||
session.updateAdjustment(blur, adjustment);
|
||
const QImage picture = session.navigatorImage(100).value();
|
||
// Five radii from every edge at the picture's scale: solid.
|
||
QVERIFY2(at(picture, 25, 50).alpha() >= 250, qPrintable(QString::number(at(picture, 25, 50).alpha())));
|
||
// Unshrunk, a radius of 100 would reach the edge here.
|
||
QVERIFY(at(picture, 49, 50).alpha() > 0 && at(picture, 49, 50).alpha() < 250);
|
||
}
|
||
|
||
void NavigatorTests::selectionChangesDoNotRedrawThePicture()
|
||
{
|
||
EditorSession session;
|
||
session.createDocument(100, 100);
|
||
placeRed(session, QSize(10, 10), QSizeF(10, 10));
|
||
const NavigatorMinimap::RenderKey key(session.document(), 0);
|
||
session.selectAll();
|
||
QVERIFY(NavigatorMinimap::RenderKey(session.document(), 0) == key);
|
||
QVERIFY(!(NavigatorMinimap::RenderKey(session.document(), 1) == key));
|
||
std::optional<CanvasDocument> hidden = session.document();
|
||
hidden->layers.back().isVisible = false;
|
||
QVERIFY(!(NavigatorMinimap::RenderKey(hidden, 0) == key));
|
||
std::optional<CanvasDocument> other = session.document();
|
||
other->id = QUuid::createUuid();
|
||
QVERIFY(!(NavigatorMinimap::RenderKey(other, 0) == key));
|
||
}
|
||
|
||
void NavigatorTests::placedMasksMotionAndEachAxisScale()
|
||
{
|
||
// A placed mask shrinks with its layer: white, then black.
|
||
EditorSession session;
|
||
session.createDocument(400, 200);
|
||
const QUuid id = placeRed(session, QSize(300, 200), QSizeF(300, 200));
|
||
QImage halves(4, 1, QImage::Format_Grayscale8);
|
||
const uchar values[] = {255, 255, 0, 0};
|
||
std::copy_n(values, 4, halves.scanLine(0));
|
||
rewrite(session, [&](ProjectSnapshot &snapshot) {
|
||
setMask(snapshot, id, LayerMask::assetFrom(halves));
|
||
record(snapshot, id).maskPlacement = LayerTransform{.origin = QPointF(0, 0), .size = QSizeF(200, 200)};
|
||
});
|
||
const QImage masked = session.navigatorImage(100).value();
|
||
// At a quarter: white to 25, black to 50.
|
||
QVERIFY(at(masked, 15, 25).alpha() == 255 && at(masked, 40, 25).alpha() == 0);
|
||
// A layer at 100, 40; its mask at 80, 20.
|
||
const QUuid moved = placeRed(session, QSize(120, 120), QSizeF(120, 120));
|
||
// Four mask pixels: white to its middle, black after.
|
||
QImage half(4, 1, QImage::Format_Grayscale8);
|
||
std::copy_n(values, 4, half.scanLine(0));
|
||
rewrite(session, [&](ProjectSnapshot &snapshot) {
|
||
record(snapshot, id).isVisible = false;
|
||
record(snapshot, moved).transform.origin = QPointF(100, 40);
|
||
setMask(snapshot, moved, LayerMask::assetFrom(half));
|
||
record(snapshot, moved).maskPlacement = LayerTransform{.origin = QPointF(80, 20), .size = QSizeF(160, 160)};
|
||
});
|
||
const QImage away = session.navigatorImage(100).value();
|
||
// Spans 25–55 and 10–40; black from 45.
|
||
QVERIFY(at(away, 24, 30).alpha() == 0 && at(away, 26, 30).alpha() == 255 && at(away, 33, 30).alpha() == 255);
|
||
QVERIFY(at(away, 30, 9).alpha() == 0 && at(away, 30, 11).alpha() == 255 && at(away, 30, 38).alpha() == 255 && at(away, 30, 41).alpha() == 0);
|
||
QVERIFY(at(away, 46, 30).alpha() == 0 && at(away, 53, 30).alpha() == 0);
|
||
// Each side alone: 1000 by 15 is 100 by 2.
|
||
session.createDocument(1000, 15);
|
||
placeRed(session, QSize(1000, 15), QSizeF(1000, 15));
|
||
// The halving softens the last row; half would show half.
|
||
const int bottom = at(session.navigatorImage(100).value(), 50, 1).alpha();
|
||
QVERIFY2(bottom > 200, qPrintable(QString::number(bottom)));
|
||
// A streak measured in document pixels shrinks too.
|
||
session.createDocument(2000, 2000);
|
||
placeRed(session, QSize(100, 200), QSizeF(1000, 2000));
|
||
session.addAdjustment(AdjustmentKind::motionBlur);
|
||
session.setAdjustmentEditingID(std::nullopt);
|
||
const QUuid streak = session.activeLayerID().value();
|
||
LayerAdjustment adjustment = layerWith(session, streak).adjustment.value();
|
||
adjustment.motionAngle = 0;
|
||
adjustment.motionDistance = 100;
|
||
session.updateAdjustment(streak, adjustment);
|
||
const QImage picture = session.navigatorImage(100).value();
|
||
QVERIFY2(at(picture, 25, 50).alpha() >= 250, qPrintable(QString::number(at(picture, 25, 50).alpha())));
|
||
// Five pixels of streak soften the edge; none would not.
|
||
QVERIFY2(at(picture, 49, 50).alpha() < 250 && at(picture, 51, 50).alpha() > 0, qPrintable(QString::number(at(picture, 49, 50).alpha())));
|
||
}
|
||
|
||
// Swift scales both blurs by the width's factor alone.
|
||
void NavigatorTests::blursTakeTheWidthsFactor()
|
||
{
|
||
const auto edge = [](AdjustmentKind kind, QSize document, double amount, QPoint probe) {
|
||
EditorSession session;
|
||
session.createDocument(document.width(), document.height());
|
||
// Red on top, or on the left when wide.
|
||
const QSize half = document.width() > document.height() ? QSize(document.width() / 2, document.height()) : QSize(document.width(), document.height() / 2);
|
||
placeRed(session, half, QSizeF(half));
|
||
session.addAdjustment(kind);
|
||
session.setAdjustmentEditingID(std::nullopt);
|
||
const QUuid id = session.activeLayerID().value();
|
||
LayerAdjustment adjustment = layerWith(session, id).adjustment.value();
|
||
if (kind == AdjustmentKind::motionBlur)
|
||
adjustment.motionAngle = 90, adjustment.motionDistance = amount;
|
||
else
|
||
adjustment.blurRadius = amount;
|
||
session.updateAdjustment(id, adjustment);
|
||
return session.navigatorImage(100).value().pixelColor(probe).alpha();
|
||
};
|
||
// 3 by 1000 becomes 1 by 100: a 33-pixel streak.
|
||
const int streak = edge(AdjustmentKind::motionBlur, QSize(3, 1000), 100, QPoint(0, 55));
|
||
QVERIFY2(streak > 30, qPrintable(QString::number(streak)));
|
||
// 1000 by 25 becomes 100 by 3: 19, not 15.
|
||
const int blur = edge(AdjustmentKind::gaussianBlur, QSize(1000, 25), 100, QPoint(45, 1));
|
||
QVERIFY2(blur >= 18, qPrintable(QString::number(blur)));
|
||
}
|
||
|
||
// Swift draws a bare session: a pending transform stays out.
|
||
void NavigatorTests::editsInProgressStayOut()
|
||
{
|
||
EditorSession session;
|
||
session.createDocument(400, 200);
|
||
placeRed(session, QSize(200, 200), QSizeF(200, 200));
|
||
session.selectTool(NavigationTool::move);
|
||
session.beginTransform();
|
||
LayerTransform moved = session.transformEdit().value().draft;
|
||
moved.origin = QPointF(200, 0);
|
||
session.previewTransform(moved);
|
||
const QImage picture = session.navigatorImage(100).value();
|
||
QVERIFY(at(picture, 25, 25).alpha() == 255 && at(picture, 75, 25).alpha() == 0);
|
||
}
|
||
|
||
void NavigatorTests::theMinimapShowsFrom300PercentWhenTurnedOn()
|
||
{
|
||
NavigatorMinimap::setVisibleSetting(false);
|
||
QCOMPARE(QSettings().value(QLatin1String(NavigatorMinimap::visibleKey)).toBool(), false);
|
||
Shown shown;
|
||
QVERIFY(!shown.minimap.isHidden() && shown.minimap.size() == QSize(120, 90));
|
||
QCOMPARE(shown.minimap.picture().size(), QSize(300, 225));
|
||
QCOMPARE(shown.minimap.accessibleName(), QString("Navigator"));
|
||
QCOMPARE(shown.minimap.accessibleDescription(), QString("Click or drag to move the view"));
|
||
shown.session.zoom(2.9, shown.session.viewport.center());
|
||
QVERIFY(shown.minimap.isHidden() && shown.minimap.picture().isNull());
|
||
shown.session.zoom(3, shown.session.viewport.center());
|
||
QVERIFY(!shown.minimap.isHidden() && !shown.minimap.picture().isNull());
|
||
shown.session.setCanvasOnly(true);
|
||
QVERIFY(shown.minimap.isHidden());
|
||
shown.session.setCanvasOnly(false);
|
||
NavigatorMinimap::setVisibleSetting(false);
|
||
shown.session.notify();
|
||
QVERIFY(shown.minimap.isHidden());
|
||
NavigatorMinimap::setVisibleSetting(true);
|
||
shown.session.notify();
|
||
QVERIFY(!shown.minimap.isHidden());
|
||
shown.session.clearProject();
|
||
QVERIFY(shown.minimap.isHidden());
|
||
}
|
||
|
||
void NavigatorTests::thePictureRedrawsOnceEditsSettle()
|
||
{
|
||
Shown shown;
|
||
QTimer &wait = *shown.minimap.findChild<QTimer *>(QStringLiteral("navigatorWait"));
|
||
QVERIFY(wait.interval() == 250 && wait.isSingleShot() && wait.timerType() == Qt::PreciseTimer && !wait.isActive());
|
||
const QImage first = shown.minimap.picture();
|
||
QCOMPARE(at(first, 150, 100), QColor(255, 0, 0));
|
||
// A selection redraws nothing.
|
||
shown.session.selectAll();
|
||
QVERIFY(!wait.isActive());
|
||
// An edit waits a moment, then redraws once.
|
||
shown.session.addAdjustment(AdjustmentKind::invert);
|
||
QVERIFY(wait.isActive());
|
||
QCOMPARE(shown.minimap.picture().cacheKey(), first.cacheKey());
|
||
QTRY_COMPARE(at(shown.minimap.picture(), 150, 100), QColor(0, 255, 255));
|
||
QVERIFY(!wait.isActive());
|
||
// A new edit midway waits its whole 250 ms anew.
|
||
shown.session.setLayerOpacity(0.8);
|
||
QTest::qWait(130);
|
||
shown.session.setLayerOpacity(0.6);
|
||
QVERIFY(wait.remainingTime() > 200);
|
||
QTRY_VERIFY(!wait.isActive());
|
||
// The Invert at 60% over red: 102, 153, 153.
|
||
const QColor mixed = at(shown.minimap.picture(), 150, 100);
|
||
QVERIFY2(std::abs(mixed.red() - 102) <= 1 && std::abs(mixed.green() - 153) <= 1, qPrintable(mixed.name()));
|
||
// Hidden mid-wait, the wait goes with the picture.
|
||
shown.session.setLayerOpacity(0.5);
|
||
QVERIFY(wait.isActive());
|
||
shown.session.zoom(2, shown.session.viewport.center());
|
||
QVERIFY(!wait.isActive() && shown.minimap.picture().isNull());
|
||
}
|
||
|
||
void NavigatorTests::aClickOrDragMovesTheView()
|
||
{
|
||
Shown shown;
|
||
const QSizeF size(400, 300);
|
||
QSignalSpy changes(&shown.session, &EditorSession::changed);
|
||
QTest::mousePress(&shown.minimap, Qt::LeftButton, Qt::NoModifier, QPoint(30, 30));
|
||
QCOMPARE(changes.count(), 1);
|
||
QRectF visible = shown.session.viewport.visibleDocumentRect(size);
|
||
QVERIFY(std::abs(visible.center().x() - 100) < 0.001 && std::abs(visible.center().y() - 100) < 0.001);
|
||
QCOMPARE(shown.session.viewport.zoom(), 4.0);
|
||
// A drag past the picture holds to the document's edge.
|
||
QTest::mouseMove(&shown.minimap, QPoint(119, 89));
|
||
QMouseEvent move(QEvent::MouseMove, QPointF(200, 200), QPointF(200, 200), Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
|
||
QApplication::sendEvent(&shown.minimap, &move);
|
||
visible = shown.session.viewport.visibleDocumentRect(size);
|
||
QVERIFY(std::abs(visible.center().x() - 400) < 0.001 && std::abs(visible.center().y() - 300) < 0.001);
|
||
// Without the left button nothing moves.
|
||
QMouseEvent hover(QEvent::MouseMove, QPointF(60, 45), QPointF(60, 45), Qt::NoButton, Qt::RightButton, Qt::NoModifier);
|
||
QApplication::sendEvent(&shown.minimap, &hover);
|
||
QTest::mousePress(&shown.minimap, Qt::RightButton, Qt::NoModifier, QPoint(60, 45));
|
||
QVERIFY(std::abs(shown.session.viewport.visibleDocumentRect(size).center().x() - 400) < 0.001);
|
||
// Over the canvas's cross, the arrow.
|
||
QWidget canvas;
|
||
canvas.setCursor(Qt::CrossCursor);
|
||
NavigatorMinimap inside(shown.session, &canvas);
|
||
QCOMPARE(inside.cursor().shape(), Qt::ArrowCursor);
|
||
}
|
||
|
||
void NavigatorTests::theViewsBoxIsDrawnInTheAccent()
|
||
{
|
||
Shown shown;
|
||
QPalette palette = shown.minimap.palette();
|
||
palette.setColor(QPalette::Active, QPalette::Highlight, QColor(0, 200, 0));
|
||
shown.minimap.setPalette(palette);
|
||
const QImage drawn = shown.minimap.grab().toImage();
|
||
// The view's middle 200 × 150 pixels: 30 to 90.
|
||
QCOMPARE(at(drawn, 30, 45), QColor(0, 200, 0));
|
||
QCOMPARE(at(drawn, 31, 45), QColor(0, 200, 0));
|
||
QCOMPARE(at(drawn, 89, 45), QColor(0, 200, 0));
|
||
QCOMPARE(at(drawn, 60, 23), QColor(0, 200, 0));
|
||
QCOMPARE(at(drawn, 60, 45), QColor(255, 0, 0));
|
||
QCOMPARE(at(drawn, 28, 45), QColor(255, 0, 0));
|
||
// The rim: white at 25% over red at the edge.
|
||
QCOMPARE(at(drawn, 0, 45), QColor(255, 64, 64));
|
||
// Clear pixels show the minimap's own gray 0.11.
|
||
rewrite(shown.session, [](ProjectSnapshot &snapshot) { snapshot.manifest.layers.back().transform.size = QSizeF(200, 300); });
|
||
shown.session.zoom(4, shown.session.viewport.center());
|
||
QTRY_COMPARE(at(shown.minimap.grab().toImage(), 110, 80), QColor(28, 28, 28));
|
||
// A view smaller than three points still shows three.
|
||
shown.session.viewport.resize(QSizeF(40, 30), 1, QSizeF(400, 300));
|
||
shown.session.zoom(32, shown.session.viewport.center());
|
||
const QRectF view = shown.session.viewport.visibleDocumentRect(QSizeF(400, 300));
|
||
QVERIFY(view.width() * 0.3 < 1);
|
||
const int left = int(std::floor(view.left() * 0.3)), row = int(view.center().y() * 0.3);
|
||
const QImage tiny = shown.minimap.grab().toImage();
|
||
QVERIFY(at(tiny, left + 1, row).green() > 100 && at(tiny, left + 1, row).red() < 60);
|
||
QCOMPARE(at(tiny, left - 2, row), QColor(255, 0, 0));
|
||
}
|
||
|
||
QTEST_MAIN(NavigatorTests)
|
||
#include "NavigatorTests.moc"
|