Files
OmaPhoto/tests/BrushRasterTests.cpp
T
雷电芽衣andClaude c864304695
Release / deb (push) Canceled after 0s
Release / rpm (push) Canceled after 0s
Release / arch (push) Canceled after 0s
Release / publish (push) Canceled after 0s
OmaPhoto 1.0.0: the Linux port of Compositor
A layered image editor for Linux and Omarchy, ported from Compositor
(github.com/robbietilton/Compositor), whose Swift source is its
specification. It reads and writes Compositor's .comp projects.

Packages for Ubuntu, Fedora and Arch come from the release workflow;
scripts/install/ holds one install script per distribution family,
and flake.nix serves NixOS.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-26 00:44:52 -04:00

85 lines
3.8 KiB
C++

#include "AddressSpaceLimit.h"
#include "BrushFixtures.h"
#include "IO/ImageExporter.h"
#include <malloc.h>
// The raster's edges: failed copies, canvas fills and clears.
class BrushRasterTests : public QObject {
Q_OBJECT
private slots:
void aTileThatCannotBeCopiedIsARenderError();
void clearPixelsStaysWithinTheSourceAndFillCoversTheCanvas();
};
namespace {
// Under a limit, every free chunk the copy could take.
struct Starved {
std::vector<void *> blocks;
explicit Starved(size_t bytes)
{
blocks.reserve(4096);
while (void *block = malloc(bytes))
blocks.push_back(block);
}
~Starved()
{
for (void *block : blocks)
free(block);
}
};
}
void BrushRasterTests::aTileThatCannotBeCopiedIsARenderError()
{
const auto paint = stroke(600, 300, red());
paint->append(QPointF(20, 40));
{
const AddressSpaceLimit limit(64 * 1024);
const Starved starved(256 * 256 * 4);
QVERIFY_THROWS_EXCEPTION(ExportError, paint->append(QPointF(30, 40)));
}
}
void BrushRasterTests::clearPixelsStaysWithinTheSourceAndFillCoversTheCanvas()
{
QImage blue = BrushRaster::context(20, 20, false);
blue.fill(Qt::blue);
const ImageLayer layer(ImportedImage(blue, blue, "Blue"), QPointF(10, 10));
BrushStroke clearing(layer, false, red(), QSizeF(600, 300));
DocumentSelection selection;
selection.path.addRect(QRectF(0, 0, 20, 300));
clearing.selectionClip = selection.clip(QSizeF(600, 300));
clearing.clearPixels();
// Only the layer's tile; the canvas' rest is untouched.
QCOMPARE(clearing.patches().size(), size_t(1));
QCOMPARE(clearing.dirtyDocumentRect(), std::optional(QRectF(0, 0, 600, 300)));
const BrushCommit::Output cleared = BrushCommit::render(clearing.commitInput());
const QImage result = render(cleared.asset, clearing.transform(cleared.pixelBounds.translated(clearing.committedBounds().topLeft())), QSizeF(600, 300));
QCOMPARE(alpha(result, 15, 15), 0);
QCOMPARE(pixel(result, 25, 15), (std::vector<int>{0, 0, 255, 255}));
// A fill covers the canvas, past the layer, selected.
BrushStroke filling(layer, false, red(), QSizeF(600, 300));
filling.selectionClip = selection.clip(QSizeF(600, 300));
filling.fill(Qt::red);
QCOMPARE(filling.patches().size(), size_t(2));
const BrushCommit::Output filled = BrushCommit::render(filling.commitInput());
const QImage whole = render(filled.asset, filling.transform(filled.pixelBounds.translated(filling.committedBounds().topLeft())), QSizeF(600, 300));
QCOMPARE(pixel(whole, 5, 295), (std::vector<int>{255, 0, 0, 255}));
QCOMPARE(pixel(whole, 15, 15), (std::vector<int>{255, 0, 0, 255}));
QCOMPARE(pixel(whole, 25, 15), (std::vector<int>{0, 0, 255, 255}));
QCOMPARE(alpha(whole, 45, 35), 0);
// A mask never erases: the fill refuses the mode outright.
QImage gray = BrushRaster::context(4, 4, true);
QVERIFY_THROWS_EXCEPTION(std::logic_error, BrushRaster::fill(Qt::white, gray, QRectF(0, 0, 4, 4), 1, gray, QPainter::CompositionMode_DestinationOut));
QVERIFY_THROWS_EXCEPTION(std::logic_error, BrushRaster::fill(Qt::white, gray, QRectF(0, 0, 4, 4), 1, gray, QPainter::CompositionMode_Multiply));
// A clip is gray coverage the coverage's size, or refused.
QImage colour = BrushRaster::context(4, 4, false);
const QImage small = BrushRaster::context(3, 4, true);
QVERIFY_THROWS_EXCEPTION(std::logic_error, BrushRaster::fill(Qt::white, gray, QRectF(0, 0, 4, 4), 1, colour, QPainter::CompositionMode_SourceOver, small));
QVERIFY_THROWS_EXCEPTION(std::logic_error, BrushRaster::fill(Qt::white, gray, QRectF(0, 0, 4, 4), 1, colour, QPainter::CompositionMode_SourceOver, colour));
}
QTEST_GUILESS_MAIN(BrushRasterTests)
#include "BrushRasterTests.moc"