Files
OmaPhoto/tests/CanvasThumbnailTests.cpp
T

89 lines
3.7 KiB
C++

#include "UI/CanvasThumbnail.h"
#include "Document/LayerMask.h"
#include "RenderFixtures.h"
#include <QtTest>
// Thumbnails take the canvas's shape; pixels sit where they are.
namespace {
// One pixel's RGBA bytes of a thumbnail, top row first.
QList<int> read(const QPixmap &thumbnail, int x, int y)
{
const QImage image = thumbnail.toImage().convertToFormat(QImage::Format_RGBA8888);
const uchar *pixel = image.constScanLine(y) + x * 4;
return {pixel[0], pixel[1], pixel[2], pixel[3]};
}
}
class CanvasThumbnailTests : public QObject {
Q_OBJECT
private slots:
void thumbnailsTakeTheCanvasShape();
void layerPixelsSitWhereTheyAreOnTheCanvas();
void masksFillTheCanvasWithTheirEdgeTone();
};
void CanvasThumbnailTests::thumbnailsTakeTheCanvasShape()
{
QCOMPARE(CanvasThumbnail::fittedSize(QSizeF(400, 200), 36), QSize(36, 18));
QCOMPARE(CanvasThumbnail::fittedSize(QSizeF(300, 600), 36), QSize(18, 36));
QCOMPARE(CanvasThumbnail::fittedSize(QSizeF(0, 0), 30), QSize(30, 30));
QCOMPARE(CanvasThumbnail::fittedSize(QSizeF(3000, 7), 36), QSize(36, 1));
// Rounded, as Swift rounds: 22.5 is 23, not 22.
QCOMPARE(CanvasThumbnail::fittedSize(QSizeF(400, 250), 36), QSize(36, 23));
QCOMPARE(CanvasThumbnail::fittedSize(QSizeF(std::nan(""), 7), 36), QSize(36, 36));
}
void CanvasThumbnailTests::layerPixelsSitWhereTheyAreOnTheCanvas()
{
const QImage red = solid(100, 100, qRgba(255, 0, 0, 255));
const QPixmap thumbnail = CanvasThumbnail::layer(red, LayerTransform{.origin = {0, 0}, .size = {100, 100}}, QSizeF(400, 200), 36);
QCOMPARE(thumbnail.deviceIndependentSize(), QSizeF(36, 18));
QCOMPARE(thumbnail.width(), 72);
QCOMPARE(read(thumbnail, 4, 4), (QList<int>{255, 0, 0, 255}));
QCOMPARE(read(thumbnail, 12, 12)[0], 255);
// The rest shows the checkerboard; nothing is flipped.
QVERIFY(read(thumbnail, 60, 30)[0] < 200);
QVERIFY(read(thumbnail, 4, 30)[0] < 200);
const QPixmap blank = CanvasThumbnail::layer(QImage(), LayerTransform{.origin = {0, 0}, .size = {400, 200}}, QSizeF(400, 200), 36);
QCOMPARE(read(blank, 4, 4)[3], 255);
// Two tones of gray, six points a tile.
QCOMPARE(read(blank, 4, 4)[0], 82);
QCOMPARE(read(blank, 16, 4)[0], 56);
QCOMPARE(read(blank, 16, 16)[0], 82);
}
void CanvasThumbnailTests::masksFillTheCanvasWithTheirEdgeTone()
{
const LayerTransform transform{.origin = {100, 50}, .size = {100, 100}};
const QSizeF canvas(400, 200);
const QImage hideAll = LayerMask::solid(false).asset.thumbnail;
const QPixmap hidden = CanvasThumbnail::mask(hideAll, transform, canvas, 30);
QVERIFY(read(hidden, 1, 1)[0] < 10);
QVERIFY(read(hidden, 55, 25)[0] < 10);
// White edges round a black middle: white around, black within.
QImage framed(20, 20, QImage::Format_Grayscale8);
framed.fill(255);
for (int y = 5; y < 15; ++y) {
for (int x = 5; x < 15; ++x)
framed.setPixel(x, y, qRgb(0, 0, 0));
}
QCOMPARE(LayerMask::background(framed), 1.0);
const QPixmap shown = CanvasThumbnail::mask(framed, transform, canvas, 30);
QCOMPARE(shown.deviceIndependentSize(), QSizeF(30, 15));
QVERIFY(read(shown, 2, 2)[0] > 245);
QVERIFY(read(shown, 22, 15)[0] < 10);
// A stroke reaching the edge: the rest still reads white.
for (int y = 8; y < 12; ++y) {
for (int x = 0; x < 20; ++x)
framed.setPixel(x, y, qRgb(0, 0, 0));
}
QVERIFY(read(CanvasThumbnail::mask(framed, transform, canvas, 30), 2, 2)[0] > 245);
// Mostly black at the edge: black beyond.
QImage dark(4, 3, QImage::Format_Grayscale8);
dark.fill(100);
QVERIFY(read(CanvasThumbnail::mask(dark, transform, canvas, 30), 2, 2)[0] < 10);
}
QTEST_MAIN(CanvasThumbnailTests)
#include "CanvasThumbnailTests.moc"