14.20 round 1: the whole picture guarded, origins, streaks and the restarted wait tested

This commit is contained in:
ZacharyZhang-NY committed 2026-10-11 11:33:46 -04:00
1 parent 085b4dac6e
commit fc56a3801f
5 files changed
+91 -8

No files matched your search

+55
View File
@@ -0,0 +1,55 @@
#include "AddressSpaceLimit.h"
#include "Document/EditorSession.h"
#include "Rendering/RasterSnapshot.h"
#include "UI/NavigatorMinimap.h"
#include <QSettings>
#include <QStandardPaths>
#include <QtTest>
#include <malloc.h>
// The Navigator when a painted layer cannot flatten.
class NavigatorFailureTests : public QObject {
Q_OBJECT
private slots:
void aFlattenThatFindsNoMemoryDrawsNoPicture();
};
void NavigatorFailureTests::aFlattenThatFindsNoMemoryDrawsNoPicture()
{
QStandardPaths::setTestModeEnabled(true);
NavigatorMinimap::setVisibleSetting(true);
// 4000 by 3000 painted from two pixels: 48 MB flat.
QImage base(2, 2, QImage::Format_RGBA8888_Premultiplied);
base.fill(Qt::red);
EditorSession session;
session.createDocument(4000, 3000);
session.insert(ImportedImage(std::make_shared<const RasterSnapshot>(4000, 3000, base, QRectF(0, 0, 2, 2), std::vector<BrushPatch>{}), QImage(),
QStringLiteral("Painted")));
session.viewport.resize(QSizeF(800, 600), 1, QSizeF(4000, 3000));
std::optional<QImage> starved;
{
const AddressSpaceLimit limit(8ll << 20);
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("the navigator's picture could not be made"));
starved = session.navigatorImage(300);
// The minimap shows without a picture, never throwing.
NavigatorMinimap minimap(session);
session.zoom(4, session.viewport.center());
QVERIFY(!minimap.isHidden() && minimap.picture().isNull());
}
QVERIFY(!starved);
// With room again it draws: the base's corner, then clear.
const QImage drawn = session.navigatorImage(300).value();
QVERIFY(drawn.size() == QSize(300, 225) && drawn.pixelColor(150, 100).alpha() == 0);
QSettings().remove(QLatin1String(NavigatorMinimap::visibleKey));
}
int main(int argc, char **argv)
{
// Large asks map memory the limit counts.
mallopt(M_MMAP_THRESHOLD, 64 * 1024);
QApplication app(argc, argv);
NavigatorFailureTests tests;
return QTest::qExec(&tests, argc, argv);
}
#include "NavigatorFailureTests.moc"
+27
View File
@@ -227,6 +227,22 @@ void NavigatorTests::placedMasksMotionAndEachAxisScale()
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));
@@ -245,6 +261,8 @@ void NavigatorTests::placedMasksMotionAndEachAxisScale()
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 draws a bare session: a pending transform stays out.
@@ -304,6 +322,15 @@ void NavigatorTests::thePictureRedrawsOnceEditsSettle()
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());
+1
View File
@@ -187,6 +187,7 @@ compositor_test(ScanlinesTests)
target_include_directories(ScanlinesTests PRIVATE ${OMAPHOTO_KERNELS})
compositor_test(ScanlinesSheetTests)
compositor_test(NavigatorTests)
compositor_test(NavigatorFailureTests)
compositor_test(CameraRawCurveTests)
compositor_test(CameraRawCurveGraphTests)
compositor_test(OpenRecentTests)