aseprite/src/app/doc_range_tests.cpp

1526 lines
49 KiB
C++

// Aseprite
// Copyright (C) 2023 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#include "tests/app_test.h"
#include "app/context.h"
#include "app/doc.h"
#include "app/doc_api.h"
#include "app/doc_range.h"
#include "app/doc_range_ops.h"
#include "app/doc_undo.h"
#include "app/test_context.h"
#include "app/transaction.h"
#include "doc/doc.h"
using namespace app;
using namespace doc;
namespace std {
std::ostream& operator<<(std::ostream& os, const doc::Layer* layer) {
if (layer)
os << '"' << layer->name() << '"';
else
os << "(null layer)";
return os;
}
std::ostream& operator<<(std::ostream& os, const app::DocRange& range) {
os << "{ layers: [";
bool first = true;
for (auto layer : range.selectedLayers()) {
if (first)
first = false;
else
os << ", ";
os << layer;
}
os << "]";
os << ", frames: [";
first = true;
for (auto frame : range.selectedFrames()) {
if (first)
first = false;
else
os << ", ";
os << frame;
}
os << "] }";
return os;
}
std::ostream& operator<<(std::ostream& os, const doc::LayerList& layers) {
os << "[";
bool first = true;
for (auto layer : layers) {
if (first)
first = false;
else
os << ", ";
os << layer;
}
return os << "]";
}
} // namespace std
typedef std::unique_ptr<Doc> DocPtr;
#define EXPECT_LAYER_ORDER(a, b, c, d) \
EXPECT_TRUE(expect_layer(a, 0)); \
EXPECT_TRUE(expect_layer(b, 1)); \
EXPECT_TRUE(expect_layer(c, 2)); \
EXPECT_TRUE(expect_layer(d, 3));
#define EXPECT_FRAME_ORDER(a, b, c, d) \
EXPECT_TRUE(expect_frame(a, 0) && \
expect_frame(b, 1) && \
expect_frame(c, 2) && \
expect_frame(d, 3));
#define EXPECT_FRAME_ORDER6(a, b, c, d, e, f) \
EXPECT_TRUE(expect_frame(a, 0) && \
expect_frame(b, 1) && \
expect_frame(c, 2) && \
expect_frame(d, 3) && \
expect_frame(e, 4) && \
expect_frame(f, 5));
#define EXPECT_FRAME_COPY1(a, b, c, d, e) \
EXPECT_TRUE(expect_frame(a, 0)); \
EXPECT_TRUE(expect_frame(b, 1)); \
EXPECT_TRUE(expect_frame(c, 2)); \
EXPECT_TRUE(expect_frame(d, 3)); \
EXPECT_TRUE(expect_frame(e, 4));
#define EXPECT_FRAME_COPY2(a, b, c, d, e, f) \
EXPECT_TRUE(expect_frame(a, 0)); \
EXPECT_TRUE(expect_frame(b, 1)); \
EXPECT_TRUE(expect_frame(c, 2)); \
EXPECT_TRUE(expect_frame(d, 3)); \
EXPECT_TRUE(expect_frame(e, 4)); \
EXPECT_TRUE(expect_frame(f, 5));
#define EXPECT_FRAME_COPY3(a, b, c, d, e, f, g) \
EXPECT_TRUE(expect_frame(a, 0)); \
EXPECT_TRUE(expect_frame(b, 1)); \
EXPECT_TRUE(expect_frame(c, 2)); \
EXPECT_TRUE(expect_frame(d, 3)); \
EXPECT_TRUE(expect_frame(e, 4)); \
EXPECT_TRUE(expect_frame(f, 5)); \
EXPECT_TRUE(expect_frame(g, 6));
#define EXPECT_CEL(y, x, v, u) \
EXPECT_TRUE(expect_cel(y, x, v, u));
#define EXPECT_EMPTY_CEL(y, x) \
EXPECT_TRUE(expect_empty_cel(y, x));
class DocRangeOps : public ::testing::Test {
public:
DocRangeOps() {
expected_color = rgba(255, 255, 255, 255);
doc.reset(ctx.documents().add(6, 4));
sprite = doc->sprite();
layer1 = dynamic_cast<LayerImage*>(sprite->root()->firstLayer());
layer2 = new LayerImage(sprite);
layer3 = new LayerImage(sprite);
layer4 = new LayerImage(sprite);
sprite->root()->addLayer(layer2);
sprite->root()->addLayer(layer3);
sprite->root()->addLayer(layer4);
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
layer1->setName("layer1");
layer2->setName("layer2");
layer3->setName("layer3");
layer4->setName("layer4");
sprite->setTotalFrames(frame_t(6));
sprite->setFrameDuration(frame_t(0), 1); // These durations can be used to identify
sprite->setFrameDuration(frame_t(1), 2); // frames after a move operation
sprite->setFrameDuration(frame_t(2), 3);
sprite->setFrameDuration(frame_t(3), 4);
sprite->setFrameDuration(frame_t(4), 5);
sprite->setFrameDuration(frame_t(5), 6);
LayerList layers = sprite->allLayers();
for (layer_t l=0; l<layers.size(); l++) {
LayerImage* layer = static_cast<LayerImage*>(layers[l]);
for (frame_t f=0; f<sprite->totalFrames(); f++) {
Cel* cel = layer->cel(frame_t(f));
ImageRef image;
if (cel)
image = cel->imageRef();
else {
image.reset(Image::create(IMAGE_RGB, 6, 4));
cel = new Cel(frame_t(f), image);
layer->addCel(cel);
}
clear_image(image.get(), rgba(f + l*10, 0, 0, 64));
put_pixel(image.get(), f, l, expected_color);
}
}
}
~DocRangeOps() {
doc->close();
}
protected:
bool expect_layer(Layer* expected_layer, layer_t layer) {
LayerList layers = sprite->allLayers();
return expect_layer_frame(
find_layer_index(layers, expected_layer), -1, layer, -1);
}
bool expect_frame(layer_t expected_frame, frame_t frame) {
LayerList layers = sprite->allLayers();
for (int i=0; i<(int)layers.size(); ++i) {
if (!expect_layer_frame(i, expected_frame, i, frame))
return false;
}
return true;
}
bool expect_layer_frame(layer_t expected_layer, frame_t expected_frame,
layer_t layer, frame_t frame) {
if (frame >= 0) {
if (!expect_cel(expected_layer, expected_frame, layer, frame))
return false;
EXPECT_EQ((expected_frame+1), sprite->frameDuration(frame));
return ((expected_frame+1) == sprite->frameDuration(frame));
}
if (layer >= 0) {
LayerList layers = sprite->allLayers();
Layer* a = layers[expected_layer];
Layer* b = layers[layer];
EXPECT_EQ(a->name(), b->name()) << layers;
if (a != b)
return false;
}
return true;
}
bool expect_cel(layer_t expected_layer, frame_t expected_frame,
layer_t layer, frame_t frame) {
LayerList layers = sprite->allLayers();
Cel* cel = layers[layer]->cel(frame);
if (!cel)
return false;
color_t color = get_pixel(
cel->image(),
expected_frame, expected_layer);
EXPECT_EQ(expected_color, color)
<< " - expecting layer " << expected_layer << " in " << layer << " and it is " << int(rgba_getr(color)/10) << "\n"
<< " - expecting frame " << expected_frame << " in " << frame << " and it is " << int(rgba_getr(color)%10);
return (expected_color == color);
}
bool expect_empty_cel(layer_t layer, frame_t frame) {
LayerList layers = sprite->allLayers();
Cel* cel = layers[layer]->cel(frame);
EXPECT_EQ(NULL, cel);
return (cel == NULL);
}
DocRange range(Layer* fromLayer, frame_t fromFrNum, Layer* toLayer, frame_t toFrNum, DocRange::Type type) {
DocRange r;
r.startRange(fromLayer, fromFrNum, type);
r.endRange(toLayer, toFrNum);
return r;
}
DocRange range(layer_t fromLayer, frame_t fromFrNum,
layer_t toLayer, frame_t toFrNum, DocRange::Type type) {
LayerList layers = sprite->allLayers();
return range(layers[fromLayer], fromFrNum, layers[toLayer], toFrNum, type);
}
DocRange layers_range(Layer* fromLayer, Layer* toLayer) {
return range(fromLayer, -1, toLayer, -1, DocRange::kLayers);
}
DocRange layers_range(layer_t fromLayer, layer_t toLayer) {
LayerList layers = sprite->allLayers();
return layers_range(layers[fromLayer], layers[toLayer]);
}
DocRange layers_range(Layer* layer) {
return range(layer, -1, layer, -1, DocRange::kLayers);
}
DocRange layers_range(layer_t layer) {
LayerList layers = sprite->allLayers();
return layers_range(layers[layer]);
}
DocRange frames_range(frame_t fromFrame, frame_t toFrame) {
return range(nullptr, fromFrame, nullptr, toFrame, DocRange::kFrames);
}
DocRange frames_range(frame_t frame) {
return range(nullptr, frame, nullptr, frame, DocRange::kFrames);
}
DocRange cels_range(layer_t fromLayer, frame_t fromFrNum,
layer_t toLayer, frame_t toFrNum) {
return range(fromLayer, fromFrNum, toLayer, toFrNum, DocRange::kCels);
}
TestContextT<app::Context> ctx;
DocPtr doc;
Sprite* sprite;
LayerImage* layer1;
LayerImage* layer2;
LayerImage* layer3;
LayerImage* layer4;
color_t expected_color;
};
TEST_F(DocRangeOps, MoveLayersNoOp) {
// Move one layer to the same place
EXPECT_EQ(layers_range(layer1),
move_range(doc.get(),
layers_range(layer1),
layers_range(layer1), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer1),
move_range(doc.get(),
layers_range(layer1),
layers_range(layer2), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer4),
move_range(doc.get(),
layers_range(layer4),
layers_range(layer4), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer4),
move_range(doc.get(),
layers_range(layer4),
layers_range(layer4), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer4),
move_range(doc.get(),
layers_range(layer4),
layers_range(layer3), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
// Move two layer to the same place
EXPECT_EQ(layers_range(layer1, layer2),
move_range(doc.get(),
layers_range(layer1, layer2),
layers_range(layer1), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer1, layer2),
move_range(doc.get(),
layers_range(layer1, layer2),
layers_range(layer1), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer1, layer2),
move_range(doc.get(),
layers_range(layer1, layer2),
layers_range(layer2), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer1, layer2),
move_range(doc.get(),
layers_range(layer1, layer2),
layers_range(layer2), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer1, layer2),
move_range(doc.get(),
layers_range(layer1, layer2),
layers_range(layer3), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer3, layer4),
move_range(doc.get(),
layers_range(layer3, layer4),
layers_range(layer2), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer3, layer4),
move_range(doc.get(),
layers_range(layer3, layer4),
layers_range(layer3), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer3, layer4),
move_range(doc.get(),
layers_range(layer3, layer4),
layers_range(layer3), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer3, layer4),
move_range(doc.get(),
layers_range(layer3, layer4),
layers_range(layer4), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(layers_range(layer3, layer4),
move_range(doc.get(),
layers_range(layer3, layer4),
layers_range(layer4), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
// Move four layers
DocRangePlace places[] = { kDocRangeBefore, kDocRangeAfter };
for (int i=0; i<2; ++i) {
for (int layer=0; layer<4; ++layer) {
EXPECT_EQ(layers_range(layer1, layer4),
move_range(doc.get(),
layers_range(layer1, layer4),
layers_range(layer), places[i]));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
for (int layer=0; layer<3; ++layer) {
EXPECT_EQ(layers_range(layer1, layer4),
move_range(doc.get(),
layers_range(layer1, layer4),
layers_range(layer, layer+1), places[i]));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
for (int layer=0; layer<2; ++layer) {
EXPECT_EQ(layers_range(layer1, layer4),
move_range(doc.get(),
layers_range(layer1, layer4),
layers_range(layer, layer+2), places[i]));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
EXPECT_EQ(layers_range(layer1, layer4),
move_range(doc.get(),
layers_range(layer1, layer4),
layers_range(layer1, layer4), places[i]));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
}
TEST_F(DocRangeOps, MoveFramesNoOp) {
// Move one frame to the same place
EXPECT_EQ(frames_range(0),
move_range(doc.get(),
frames_range(0),
frames_range(0), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(0),
move_range(doc.get(),
frames_range(0),
frames_range(1), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(3),
move_range(doc.get(),
frames_range(3),
frames_range(3), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(3),
move_range(doc.get(),
frames_range(3),
frames_range(3), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(3),
move_range(doc.get(),
frames_range(3),
frames_range(2), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
// Move two frame to the same place
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(0, 1),
frames_range(0), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(0, 1),
frames_range(0), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(0, 1),
frames_range(1), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(0, 1),
frames_range(1), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(0, 1),
frames_range(2), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(1), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(2), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(2), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(3), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(3), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
// Move four frames
DocRangePlace places[] = { kDocRangeBefore, kDocRangeAfter };
for (int i=0; i<2; ++i) {
for (int frame=0; frame<4; ++frame) {
EXPECT_EQ(frames_range(0, 3),
move_range(doc.get(),
frames_range(0, 3),
frames_range(frame), places[i]));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
for (int frame=0; frame<3; ++frame) {
EXPECT_EQ(frames_range(0, 3),
move_range(doc.get(),
frames_range(0, 3),
frames_range(frame, frame+1), places[i]));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
for (int frame=0; frame<2; ++frame) {
EXPECT_EQ(frames_range(0, 3),
move_range(doc.get(),
frames_range(0, 3),
frames_range(frame, frame+2), places[i]));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
EXPECT_EQ(frames_range(0, 3),
move_range(doc.get(),
frames_range(0, 3),
frames_range(0, 3), places[i]));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
}
TEST_F(DocRangeOps, MoveCelsNoOp) {
EXPECT_EQ(cels_range(0, 0, 1, 1),
move_range(doc.get(),
cels_range(0, 0, 1, 1),
cels_range(0, 0, 1, 1), kDocRangeAfter));
EXPECT_CEL(0, 0, 0, 0);
EXPECT_CEL(0, 1, 0, 1);
EXPECT_CEL(1, 0, 1, 0);
EXPECT_CEL(1, 1, 1, 1);
EXPECT_FALSE(doc->undoHistory()->canUndo());
}
TEST_F(DocRangeOps, CopyCelsNoOp) {
// TODO
}
TEST_F(DocRangeOps, MoveLayers) {
// One layer at the bottom of another
EXPECT_EQ(layers_range(layer1),
move_range(doc.get(),
layers_range(layer1),
layers_range(layer2), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer2, layer1, layer3, layer4);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
// One layer at the bottom
EXPECT_EQ(layers_range(layer2),
move_range(doc.get(),
layers_range(layer2),
layers_range(layer1), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer2, layer1, layer3, layer4);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
// Try with a background
layer1->setBackground(true);
EXPECT_THROW({
move_range(doc.get(),
layers_range(layer1),
layers_range(layer2), kDocRangeAfter);
}, std::exception);
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
layer1->setBackground(false);
// Move one layer to the top
EXPECT_EQ(layers_range(layer2),
move_range(doc.get(),
layers_range(layer2),
layers_range(layer4), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer3, layer4, layer2);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
// Move one layers before other
EXPECT_EQ(layers_range(layer2),
move_range(doc.get(),
layers_range(layer2),
layers_range(layer4), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer1, layer3, layer2, layer4);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
EXPECT_EQ(layers_range(layer1),
move_range(doc.get(),
layers_range(layer1),
layers_range(layer3, layer4), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer2, layer1, layer3, layer4);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
// Move two layers on top of other
EXPECT_EQ(layers_range(layer2, layer3),
move_range(doc.get(),
layers_range(layer2, layer3),
layers_range(layer4), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer4, layer2, layer3);
EXPECT_EQ(layers_range(layer2, layer3),
move_range(doc.get(),
layers_range(layer2, layer3),
layers_range(layer1), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
// Move three layers at the bottom (but we cannot because the bottom is a background layer)
layer1->setBackground(true);
EXPECT_THROW({
move_range(doc.get(),
layers_range(layer2, layer4),
layers_range(layer1), kDocRangeBefore);
}, std::exception);
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
layer1->setBackground(false);
// Move three layers at the top
EXPECT_EQ(layers_range(layer1, layer3),
move_range(doc.get(),
layers_range(layer1, layer3),
layers_range(layer4), kDocRangeAfter));
EXPECT_LAYER_ORDER(layer4, layer1, layer2, layer3);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
// Move three layers at the bottom
EXPECT_EQ(layers_range(layer2, layer4),
move_range(doc.get(),
layers_range(layer2, layer4),
layers_range(layer1), kDocRangeBefore));
EXPECT_LAYER_ORDER(layer2, layer3, layer4, layer1);
doc->undoHistory()->undo();
EXPECT_LAYER_ORDER(layer1, layer2, layer3, layer4);
}
TEST_F(DocRangeOps, MoveFrames) {
// Move frame 0 after 1
EXPECT_EQ(frames_range(1),
move_range(doc.get(),
frames_range(0),
frames_range(1), kDocRangeAfter));
EXPECT_FRAME_ORDER(1, 0, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move frame 1 after frame 5 (at the end)
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
EXPECT_EQ(frames_range(5),
move_range(doc.get(),
frames_range(1),
frames_range(5), kDocRangeAfter));
EXPECT_FRAME_ORDER6(0, 2, 3, 4, 5, 1);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move frames 1,2 after 5
EXPECT_EQ(frames_range(4, 5),
move_range(
doc.get(),
frames_range(1, 2),
frames_range(5), kDocRangeAfter));
EXPECT_FRAME_ORDER6(0, 3, 4, 5, 1, 2);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move frames 1,2 after 3
EXPECT_EQ(frames_range(1, 2),
move_range(doc.get(),
frames_range(2, 3),
frames_range(0), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 2, 3, 1);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move three frames at the beginning
EXPECT_EQ(frames_range(0, 2),
move_range(doc.get(),
frames_range(1, 3),
frames_range(0), kDocRangeBefore));
EXPECT_FRAME_ORDER(1, 2, 3, 0);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move three frames at the end
EXPECT_EQ(frames_range(1, 3),
move_range(doc.get(),
frames_range(0, 2),
frames_range(3), kDocRangeAfter));
EXPECT_FRAME_ORDER(3, 0, 1, 2);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
}
TEST_F(DocRangeOps, MoveFramesNonAdjacent) {
// Move frames 0,2...
DocRange from;
from.startRange(nullptr, 0, DocRange::kFrames); from.endRange(nullptr, 0);
from.startRange(nullptr, 2, DocRange::kFrames); from.endRange(nullptr, 2);
// Move frames 0,2 after 3...
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(), from, frames_range(3), kDocRangeAfter));
EXPECT_FRAME_ORDER(1, 3, 0, 2);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move frames 0,2 before 3...
EXPECT_EQ(frames_range(1, 2),
move_range(doc.get(), from, frames_range(3), kDocRangeBefore));
EXPECT_FRAME_ORDER(1, 0, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move frames 0,2 before 0...
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(), from, frames_range(0), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 2, 1, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move frames 0,2 after 0...
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(), from, frames_range(0), kDocRangeAfter));
EXPECT_FRAME_ORDER(0, 2, 1, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move frames 0,2 before 1...
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(), from, frames_range(1), kDocRangeBefore));
EXPECT_FRAME_ORDER(0, 2, 1, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move frames 0,2 after 1...
EXPECT_EQ(frames_range(1, 2),
move_range(doc.get(), from, frames_range(1), kDocRangeAfter));
EXPECT_FRAME_ORDER(1, 0, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Move 1,2,5...
from.clearRange();
from.startRange(nullptr, 1, DocRange::kFrames);
from.endRange(nullptr, 2);
from.startRange(nullptr, 5, DocRange::kFrames);
from.endRange(nullptr, 5);
// Move 1,2,5 before 4...
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
EXPECT_EQ(frames_range(2, 4),
move_range(doc.get(), from, frames_range(4), kDocRangeBefore));
EXPECT_FRAME_ORDER6(0, 3, 1, 2, 5, 4);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,2,5 after 4...
EXPECT_EQ(frames_range(3, 5),
move_range(doc.get(), from, frames_range(4), kDocRangeAfter));
EXPECT_FRAME_ORDER6(0, 3, 4, 1, 2, 5);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,2,5 before 2...
EXPECT_EQ(frames_range(1, 3),
move_range(doc.get(), from, frames_range(2), kDocRangeBefore));
EXPECT_FRAME_ORDER6(0, 1, 2, 5, 3, 4);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,2,5 after 2...
EXPECT_EQ(frames_range(1, 3),
move_range(doc.get(), from, frames_range(2), kDocRangeAfter));
EXPECT_FRAME_ORDER6(0, 1, 2, 5, 3, 4);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,2,5 before 1...
EXPECT_EQ(frames_range(1, 3),
move_range(doc.get(), from, frames_range(1), kDocRangeBefore));
EXPECT_FRAME_ORDER6(0, 1, 2, 5, 3, 4);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,3,5...
from.clearRange();
from.startRange(nullptr, 1, DocRange::kFrames);
from.endRange(nullptr, 1);
from.startRange(nullptr, 3, DocRange::kFrames);
from.endRange(nullptr, 3);
from.startRange(nullptr, 5, DocRange::kFrames);
from.endRange(nullptr, 5);
// Move 1,3,5 before 4...
EXPECT_EQ(frames_range(2, 4),
move_range(doc.get(), from, frames_range(4), kDocRangeBefore));
EXPECT_FRAME_ORDER6(0, 2, 1, 3, 5, 4);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,3,5 after 4...
EXPECT_EQ(frames_range(3, 5),
move_range(doc.get(), from, frames_range(4), kDocRangeAfter));
EXPECT_FRAME_ORDER6(0, 2, 4, 1, 3, 5);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,3,5 before 5...
EXPECT_EQ(frames_range(3, 5),
move_range(doc.get(), from, frames_range(5), kDocRangeBefore));
EXPECT_FRAME_ORDER6(0, 2, 4, 1, 3, 5);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
// Move 1,3,5 after 5...
EXPECT_EQ(frames_range(3, 5),
move_range(doc.get(), from, frames_range(5), kDocRangeAfter));
EXPECT_FRAME_ORDER6(0, 2, 4, 1, 3, 5);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
}
TEST_F(DocRangeOps, MoveCels) {
DocRangePlace ignore = kDocRangeBefore;
move_range(doc.get(),
cels_range(0, 0, 0, 0),
cels_range(0, 1, 0, 1), ignore);
EXPECT_CEL(0, 0, 0, 1);
EXPECT_EMPTY_CEL(0, 0);
doc->undoHistory()->undo();
EXPECT_CEL(0, 0, 0, 0);
move_range(doc.get(),
cels_range(0, 0, 0, 1),
cels_range(0, 2, 0, 3), ignore);
EXPECT_CEL(0, 0, 0, 2);
EXPECT_CEL(0, 1, 0, 3);
EXPECT_EMPTY_CEL(0, 0);
EXPECT_EMPTY_CEL(0, 1);
doc->undoHistory()->undo();
move_range(doc.get(),
cels_range(0, 0, 1, 1),
cels_range(2, 2, 3, 3), ignore);
EXPECT_CEL(0, 0, 2, 2);
EXPECT_CEL(0, 1, 2, 3);
EXPECT_CEL(1, 0, 3, 2);
EXPECT_CEL(1, 1, 3, 3);
EXPECT_EMPTY_CEL(0, 0);
EXPECT_EMPTY_CEL(0, 1);
EXPECT_EMPTY_CEL(1, 0);
EXPECT_EMPTY_CEL(1, 1);
doc->undoHistory()->undo();
move_range(doc.get(),
cels_range(0, 0, 0, 3),
cels_range(1, 0, 1, 3), ignore);
EXPECT_CEL(0, 0, 1, 0);
EXPECT_CEL(0, 1, 1, 1);
EXPECT_CEL(0, 2, 1, 2);
EXPECT_CEL(0, 3, 1, 3);
EXPECT_EMPTY_CEL(0, 0);
EXPECT_EMPTY_CEL(0, 1);
EXPECT_EMPTY_CEL(0, 2);
EXPECT_EMPTY_CEL(0, 3);
doc->undoHistory()->undo();
// Moving with overlapping areas
move_range(doc.get(),
cels_range(0, 0, 0, 2),
cels_range(0, 1, 0, 3), ignore);
EXPECT_CEL(0, 0, 0, 1);
EXPECT_CEL(0, 1, 0, 2);
EXPECT_CEL(0, 2, 0, 3);
EXPECT_EMPTY_CEL(0, 0);
doc->undoHistory()->undo();
}
TEST_F(DocRangeOps, CopyLayers) {
// TODO
}
TEST_F(DocRangeOps, CopyFrames) {
// Copy one frame
EXPECT_EQ(frames_range(2),
copy_range(doc.get(),
frames_range(0),
frames_range(2, 3), kDocRangeBefore));
EXPECT_FRAME_COPY1(0, 1, 0, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(4),
copy_range(doc.get(),
frames_range(0),
frames_range(2, 3), kDocRangeAfter));
EXPECT_FRAME_COPY1(0, 1, 2, 3, 0);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(0),
copy_range(doc.get(),
frames_range(3),
frames_range(0, 1), kDocRangeBefore));
EXPECT_FRAME_COPY1(3, 0, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(2),
copy_range(doc.get(),
frames_range(3),
frames_range(0, 1), kDocRangeAfter));
EXPECT_FRAME_COPY1(0, 1, 3, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Copy three frames
EXPECT_EQ(frames_range(3, 5),
copy_range(doc.get(),
frames_range(0, 2),
frames_range(3), kDocRangeBefore));
EXPECT_FRAME_COPY3(0, 1, 2, 0, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(4, 6),
copy_range(doc.get(),
frames_range(0, 2),
frames_range(3), kDocRangeAfter));
EXPECT_FRAME_COPY3(0, 1, 2, 3, 0, 1, 2);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(0, 2),
copy_range(doc.get(),
frames_range(1, 3),
frames_range(0), kDocRangeBefore));
EXPECT_FRAME_COPY3(1, 2, 3, 0, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(1, 3),
copy_range(doc.get(),
frames_range(1, 3),
frames_range(0), kDocRangeAfter));
EXPECT_FRAME_COPY3(0, 1, 2, 3, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(0, 2),
copy_range(doc.get(),
frames_range(0, 2),
frames_range(0, 2), kDocRangeBefore));
EXPECT_FRAME_COPY3(0, 1, 2, 0, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(3, 5),
copy_range(doc.get(),
frames_range(0, 2),
frames_range(0, 2), kDocRangeAfter));
EXPECT_FRAME_COPY3(0, 1, 2, 0, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
}
TEST_F(DocRangeOps, CopyFramesNonAdjacent) {
// Copy frames 0 and 2...
DocRange from;
from.startRange(nullptr, 0, DocRange::kFrames); from.endRange(nullptr, 0);
from.startRange(nullptr, 2, DocRange::kFrames); from.endRange(nullptr, 2);
EXPECT_EQ(frames_range(3, 4),
copy_range(doc.get(), from, frames_range(3), kDocRangeBefore));
EXPECT_FRAME_COPY2(0, 1, 2, 0, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(4, 5),
copy_range(doc.get(), from, frames_range(3), kDocRangeAfter));
EXPECT_FRAME_COPY2(0, 1, 2, 3, 0, 2);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(2, 3),
copy_range(doc.get(), from, frames_range(1), kDocRangeAfter));
EXPECT_FRAME_COPY2(0, 1, 0, 2, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(1, 2),
copy_range(doc.get(), from, frames_range(1), kDocRangeBefore));
EXPECT_FRAME_COPY2(0, 0, 2, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
// Copy frames 1 and 3...
from.clearRange();
from.startRange(nullptr, 1, DocRange::kFrames); from.endRange(nullptr, 1);
from.startRange(nullptr, 3, DocRange::kFrames); from.endRange(nullptr, 3);
EXPECT_EQ(frames_range(0, 1),
copy_range(doc.get(), from, frames_range(0), kDocRangeBefore));
EXPECT_FRAME_COPY2(1, 3, 0, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
EXPECT_EQ(frames_range(1, 2),
copy_range(doc.get(), from, frames_range(0), kDocRangeAfter));
EXPECT_FRAME_COPY2(0, 1, 3, 1, 2, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
}
TEST_F(DocRangeOps, CopyCels) {
// TODO
}
TEST_F(DocRangeOps, ReverseFrames) {
reverse_frames(doc.get(), frames_range(0, 0));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
reverse_frames(doc.get(), frames_range(1, 1));
EXPECT_FRAME_ORDER(0, 1, 2, 3);
reverse_frames(doc.get(), frames_range(1, 2));
EXPECT_FRAME_ORDER(0, 2, 1, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
reverse_frames(doc.get(), frames_range(0, 2));
EXPECT_FRAME_ORDER(2, 1, 0, 3);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
reverse_frames(doc.get(), frames_range(1, 3));
EXPECT_FRAME_ORDER(0, 3, 2, 1);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
reverse_frames(doc.get(), frames_range(0, 3));
EXPECT_FRAME_ORDER(3, 2, 1, 0);
doc->undoHistory()->undo();
EXPECT_FRAME_ORDER(0, 1, 2, 3);
}
TEST_F(DocRangeOps, ReverseCels) {
// TODO
}
TEST(DocRangeOps2, DropInsideBugs) {
TestContextT<app::Context> ctx;
DocPtr doc(ctx.documents().add(4, 4));
auto sprite = doc->sprite();
auto layer1 = dynamic_cast<LayerImage*>(sprite->root()->firstLayer());
auto layer2 = new LayerGroup(sprite);
auto layer3 = new LayerGroup(sprite);
auto layer4 = new LayerGroup(sprite);
sprite->root()->addLayer(layer2);
sprite->root()->addLayer(layer3);
sprite->root()->addLayer(layer4);
EXPECT_EQ(layer1, sprite->root()->layers()[0]);
EXPECT_EQ(layer2, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, sprite->root()->layers()[2]);
EXPECT_EQ(layer4, sprite->root()->layers()[3]);
// layer4 layer4
// layer3 --> layer1
// layer2 layer3
// layer1 layer2
DocRange from, to;
from.selectLayer(layer1);
to.selectLayer(layer4);
move_range(doc.get(), from, to, kDocRangeFirstChild);
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer3, sprite->root()->layers()[1]);
EXPECT_EQ(layer4, sprite->root()->layers()[2]);
EXPECT_EQ(layer1, layer4->layers()[0]);
// layer4 layer4
// layer1 --> layer1
// layer3 layer3
// layer2 layer2
from.clearRange(); from.selectLayer(layer3);
to.clearRange(); to.selectLayer(layer1);
move_range(doc.get(), from, to, kDocRangeBefore);
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer4->layers()[1]);
// layer4 layer4
// layer1 --> layer3
// layer3 layer1
// layer2 layer2
from.clearRange(); from.selectLayer(layer1);
to.clearRange(); to.selectLayer(layer3);
move_range(doc.get(), from, to, kDocRangeFirstChild);
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer3->layers()[0]);
// move layer4 as first child of layer4 (invalid operation)
from.clearRange(); from.selectLayer(layer4);
to.clearRange(); to.selectLayer(layer4);
move_range(doc.get(), from, to, kDocRangeFirstChild);
// Everything is exactly the same (no new undo operation)
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer3->layers()[0]);
// move layer4 as first child of layer3 (invalid operation)
from.clearRange(); from.selectLayer(layer4);
to.clearRange(); to.selectLayer(layer3);
move_range(doc.get(), from, to, kDocRangeFirstChild);
// Everything is exactly the same (no new undo operation)
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer3->layers()[0]);
// move layer4 after layer1 (invalid operation)
from.clearRange(); from.selectLayer(layer4);
to.clearRange(); to.selectLayer(layer1);
move_range(doc.get(), from, to, kDocRangeAfter);
// Everything is exactly the same (no new undo operation)
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer3->layers()[0]);
// move layer4 after layer1 (invalid operation)
from.clearRange(); from.selectLayer(layer4);
to.clearRange(); to.selectLayer(layer1);
move_range(doc.get(), from, to, kDocRangeBefore);
// Everything is exactly the same (no new undo operation)
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer3->layers()[0]);
// move layer2 inside layer2 (invalid operation)
from.clearRange(); from.selectLayer(layer2);
to.clearRange(); to.selectLayer(layer2);
move_range(doc.get(), from, to, kDocRangeFirstChild);
// Everything is exactly the same (no new undo operation)
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer3->layers()[0]);
// layer4 layer4
// layer1 <-- layer3
// layer3 layer1
// layer2 layer2
doc->undoHistory()->undo();
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer4, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, layer4->layers()[0]);
EXPECT_EQ(layer1, layer4->layers()[1]);
// layer4 layer4
// layer1 <-- layer1
// layer3 layer3
// layer2 layer2
doc->undoHistory()->undo();
EXPECT_EQ(layer2, sprite->root()->layers()[0]);
EXPECT_EQ(layer3, sprite->root()->layers()[1]);
EXPECT_EQ(layer4, sprite->root()->layers()[2]);
EXPECT_EQ(layer1, layer4->layers()[0]);
// layer4 layer4
// layer3 <-- layer1
// layer2 layer3
// layer1 layer2
doc->undoHistory()->undo();
EXPECT_EQ(layer1, sprite->root()->layers()[0]);
EXPECT_EQ(layer2, sprite->root()->layers()[1]);
EXPECT_EQ(layer3, sprite->root()->layers()[2]);
EXPECT_EQ(layer4, sprite->root()->layers()[3]);
doc->close();
}
TEST_F(DocRangeOps, MoveRangeWithTags) {
auto a = new Tag(0, 2);
auto b = new Tag(3, 5);
sprite->tags().add(a);
sprite->tags().add(b);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
// Move before tag "a" (outside the tag)
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(1, 2),
frames_range(0),
kDocRangeBefore,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(1, 2, 0, 3, 4, 5);
EXPECT_EQ(2, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
// Check that undo for frame tags does work.
doc->undoHistory()->undo();
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
// Move before tag "a" (inside the tag)
EXPECT_EQ(frames_range(0, 1),
move_range(doc.get(),
frames_range(1, 2),
frames_range(0),
kDocRangeBefore,
kFitInsideTags));
EXPECT_FRAME_ORDER6(1, 2, 0, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Move after (and inside) tag "a"
EXPECT_EQ(frames_range(1, 2),
move_range(doc.get(),
frames_range(0, 1),
frames_range(2),
kDocRangeAfter,
kFitInsideTags));
EXPECT_FRAME_ORDER6(2, 0, 1, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Move between tag "a" and "b" (outside both tags)
EXPECT_EQ(frames_range(1, 2),
move_range(doc.get(),
frames_range(0, 1),
frames_range(2),
kDocRangeAfter,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(2, 0, 1, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(0, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
EXPECT_EQ(frames_range(1, 2),
move_range(doc.get(),
frames_range(0, 1),
frames_range(3),
kDocRangeBefore,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(2, 0, 1, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(0, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(2),
kDocRangeAfter,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(1, a->toFrame());
EXPECT_EQ(4, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
frames_range(2, 3),
frames_range(3),
kDocRangeBefore,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(0, 1, 2, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(1, a->toFrame());
EXPECT_EQ(4, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Move after tag "b" (inside tag)
EXPECT_EQ(frames_range(4, 5),
move_range(doc.get(),
frames_range(0, 1),
frames_range(5),
kDocRangeAfter,
kFitInsideTags));
EXPECT_FRAME_ORDER6(2, 3, 4, 5, 0, 1);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(0, a->toFrame());
EXPECT_EQ(1, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Move after tag "b" (outside tag)
EXPECT_EQ(frames_range(4, 5),
move_range(doc.get(),
frames_range(0, 1),
frames_range(5),
kDocRangeAfter,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(2, 3, 4, 5, 0, 1);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(0, a->toFrame());
EXPECT_EQ(1, b->fromFrame());
EXPECT_EQ(3, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Put frame 1 and 4 in the middle of both tags (outside)
DocRange from;
from.startRange(nullptr, 1, DocRange::kFrames); from.endRange(nullptr, 1);
from.startRange(nullptr, 4, DocRange::kFrames); from.endRange(nullptr, 4);
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
from,
frames_range(2),
kDocRangeAfter,
kFitOutsideTags));
EXPECT_FRAME_ORDER6(0, 2, 1, 4, 3, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(1, a->toFrame());
EXPECT_EQ(4, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Put frame 1 and 4 before tag "b" (inside)
EXPECT_EQ(frames_range(2, 3),
move_range(doc.get(),
from,
frames_range(3),
kDocRangeBefore,
kFitInsideTags));
EXPECT_FRAME_ORDER6(0, 2, 1, 4, 3, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(1, a->toFrame());
EXPECT_EQ(2, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
}
TEST_F(DocRangeOps, CopyRangeWithTags) {
auto a = new Tag(0, 2);
auto b = new Tag(3, 5);
sprite->tags().add(a);
sprite->tags().add(b);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(3, b->fromFrame());
EXPECT_EQ(5, b->toFrame());
// Copy before tag "a" (outside the tag)
EXPECT_EQ(frames_range(0),
copy_range(doc.get(),
frames_range(1),
frames_range(0),
kDocRangeBefore,
kFitOutsideTags));
EXPECT_FRAME_COPY3(1, 0, 1, 2, 3, 4, 5);
EXPECT_EQ(1, a->fromFrame());
EXPECT_EQ(3, a->toFrame());
EXPECT_EQ(4, b->fromFrame());
EXPECT_EQ(6, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Copy before tag "a" (inside the tag)
EXPECT_EQ(frames_range(0),
copy_range(doc.get(),
frames_range(1),
frames_range(0),
kDocRangeBefore,
kFitInsideTags));
EXPECT_FRAME_COPY3(1, 0, 1, 2, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(3, a->toFrame());
EXPECT_EQ(4, b->fromFrame());
EXPECT_EQ(6, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
// Copy after tag "a" (outside the tag)
EXPECT_EQ(frames_range(3),
copy_range(doc.get(),
frames_range(1),
frames_range(2),
kDocRangeAfter,
kFitOutsideTags));
EXPECT_FRAME_COPY3(0, 1, 2, 1, 3, 4, 5);
EXPECT_EQ(0, a->fromFrame());
EXPECT_EQ(2, a->toFrame());
EXPECT_EQ(4, b->fromFrame());
EXPECT_EQ(6, b->toFrame());
EXPECT_TRUE(doc->undoHistory()->canUndo());
doc->undoHistory()->undo();
}