File indexing completed on 2024-12-22 04:14:39

0001 /*
0002  *  SPDX-License-Identifier: GPL-3.0-or-later
0003  */
0004 
0005 #include "kis_animation_utils_test.h"
0006 
0007 #include <KoColor.h>
0008 #include <KoColorSpace.h>
0009 #include <KoColorSpaceRegistry.h>
0010 
0011 #include "kis_image_animation_interface.h"
0012 #include "kis_paint_layer.h"
0013 #include "kis_keyframe_channel.h"
0014 #include <testutil.h>
0015 #include "KisAnimUtils.h"
0016 
0017 #include <tuple>
0018 
0019 
0020 bool verifyFrames(TestUtil::MaskParent &p,
0021                   const QVector<KisNodeSP> &nodes,
0022                   const QVector<std::tuple<int, QRect, QRect>> &offsets)
0023 {
0024     KisImageAnimationInterface *i = p.image->animationInterface();
0025 
0026     Q_FOREACH (const auto &offset, offsets) {
0027         int time = 0;
0028         QRect rc1;
0029         QRect rc2;
0030         std::tie(time, rc1, rc2) = offset;
0031 
0032         i->switchCurrentTimeAsync(time);
0033         p.image->waitForDone();
0034 
0035         KIS_SAFE_ASSERT_RECOVER_NOOP(nodes[0]->paintDevice()->defaultBounds()->currentTime() == time);
0036         KIS_SAFE_ASSERT_RECOVER_NOOP(nodes[1]->paintDevice()->defaultBounds()->currentTime() == time);
0037 
0038         KisKeyframeChannel *channel1 = nodes[0]->getKeyframeChannel("content");
0039         KisKeyframeChannel *channel2 = nodes[1]->getKeyframeChannel("content");
0040 
0041 
0042         if (!rc1.isValid() && !channel1->keyframeAt(time)) {
0043             // noop
0044         } else if (nodes[0]->paintDevice()->exactBounds() != rc1) {
0045             qWarning() << "Compared values are not the same:";
0046             qWarning() << "    " << ppVar(nodes[0]->paintDevice()->exactBounds());
0047             qWarning() << "    " << ppVar(rc1);
0048             qWarning() << "    " << ppVar(time);
0049             return false;
0050         }
0051 
0052         if (!rc2.isValid() && !channel2->keyframeAt(time)) {
0053             // noop
0054         } else if (nodes[1]->paintDevice()->exactBounds() != rc2) {
0055             qWarning() << "Compared values are not the same:";
0056             qWarning() << "    "  << ppVar(nodes[1]->paintDevice()->exactBounds());
0057             qWarning() << "    "  << ppVar(rc2);
0058             qWarning() << "    " << ppVar(time);
0059             return false;
0060         }
0061     }
0062 
0063     return true;
0064 }
0065 
0066 
0067 void KisAnimationUtilsTest::test()
0068 {
0069     QRect refRect(QRect(0,0,512,512));
0070     TestUtil::MaskParent p(refRect);
0071 
0072     const KoColor fillColor(Qt::red, p.image->colorSpace());
0073 
0074     KisPaintLayerSP layer1 = p.layer;
0075     KisPaintLayerSP layer2 = new KisPaintLayer(p.image, "paint2", OPACITY_OPAQUE_U8);
0076     p.image->addNode(layer2);
0077 
0078     QVector<KisNodeSP> nodes({layer1, layer2});
0079 
0080     KisPaintDeviceSP dev1 = layer1->paintDevice();
0081     KisPaintDeviceSP dev2 = layer2->paintDevice();
0082 
0083     KisKeyframeChannel *channel1 = layer1->getKeyframeChannel(KisKeyframeChannel::Raster.id(), true);
0084     KisKeyframeChannel *channel2 = layer2->getKeyframeChannel(KisKeyframeChannel::Raster.id(), true);
0085 
0086     channel1->addKeyframe(0);
0087     channel2->addKeyframe(0);
0088     channel1->addKeyframe(10);
0089     channel2->addKeyframe(10);
0090     channel1->addKeyframe(20);
0091     channel2->addKeyframe(20);
0092 
0093     KisImageAnimationInterface *i = p.image->animationInterface();
0094 
0095     i->switchCurrentTimeAsync(0);
0096     p.image->waitForDone();
0097 
0098     dev1->fill(QRect(0, 0, 10, 10), fillColor);
0099     dev2->fill(QRect(0, 10, 10, 10), fillColor);
0100 
0101     i->switchCurrentTimeAsync(10);
0102     p.image->waitForDone();
0103 
0104     dev1->fill(QRect(10, 0, 10, 10), fillColor);
0105     dev2->fill(QRect(10, 10, 10, 10), fillColor);
0106 
0107     i->switchCurrentTimeAsync(20);
0108     p.image->waitForDone();
0109 
0110     dev1->fill(QRect(20, 0, 10, 10), fillColor);
0111     dev2->fill(QRect(20, 10, 10, 10), fillColor);
0112 
0113 
0114     QVector<std::tuple<int, QRect, QRect>> initialReferenceRects;
0115     initialReferenceRects << std::make_tuple( 0, QRect( 0, 0, 10, 10), QRect( 0, 10, 10, 10));
0116     initialReferenceRects << std::make_tuple(10, QRect(10, 0, 10, 10), QRect(10, 10, 10, 10));
0117     initialReferenceRects << std::make_tuple(20, QRect(20, 0, 10, 10), QRect(20, 10, 10, 10));
0118 
0119     QVERIFY(verifyFrames(p, nodes, initialReferenceRects));
0120 
0121     using namespace KisAnimUtils;
0122 
0123     FrameMovePairList frameMoves;
0124 
0125     //
0126     // Cycling single-layer move
0127     //
0128     frameMoves << std::make_pair(FrameItem(layer1, "content", 0), FrameItem(layer1, "content", 10));
0129     frameMoves << std::make_pair(FrameItem(layer1, "content", 10), FrameItem(layer1, "content", 20));
0130     frameMoves << std::make_pair(FrameItem(layer1, "content", 20), FrameItem(layer1, "content", 0));
0131 
0132     QScopedPointer<KUndo2Command> cmd(createMoveKeyframesCommand(frameMoves, false, false));
0133     cmd->redo();
0134 
0135     QVector<std::tuple<int, QRect, QRect>> referenceRects;
0136     referenceRects << std::make_tuple( 0, QRect(20, 0, 10, 10), QRect( 0, 10, 10, 10));
0137     referenceRects << std::make_tuple(10, QRect( 0, 0, 10, 10), QRect(10, 10, 10, 10));
0138     referenceRects << std::make_tuple(20, QRect(10, 0, 10, 10), QRect(20, 10, 10, 10));
0139     QVERIFY(verifyFrames(p, nodes, referenceRects));
0140 
0141     cmd->undo();
0142 
0143     QVERIFY(verifyFrames(p, nodes, initialReferenceRects));
0144 
0145     frameMoves.clear();
0146     referenceRects.clear();
0147     cmd.reset();
0148 
0149     //
0150     // Just a complex non-cycling move
0151     //
0152 
0153     frameMoves << std::make_pair(FrameItem(layer1, "content", 0), FrameItem(layer2, "content", 10));
0154     frameMoves << std::make_pair(FrameItem(layer2, "content", 10), FrameItem(layer1, "content", 10));
0155     frameMoves << std::make_pair(FrameItem(layer1, "content", 20), FrameItem(layer2, "content", 20));
0156 
0157     cmd.reset(createMoveKeyframesCommand(frameMoves, false, false));
0158     cmd->redo();
0159 
0160     referenceRects << std::make_tuple( 0, QRect()              , QRect( 0, 10, 10, 10));
0161     referenceRects << std::make_tuple(10, QRect(10, 10, 10, 10), QRect( 0,  0, 10, 10));
0162     referenceRects << std::make_tuple(20, QRect()              , QRect(20,  0, 10, 10));
0163     QVERIFY(verifyFrames(p, nodes, referenceRects));
0164 
0165     cmd->undo();
0166 
0167     QVERIFY(verifyFrames(p, nodes, initialReferenceRects));
0168 
0169     frameMoves.clear();
0170     referenceRects.clear();
0171     cmd.reset();
0172 
0173     //
0174     // Cross-node swap of the frames
0175     //
0176     frameMoves << std::make_pair(FrameItem(layer1, "content", 0), FrameItem(layer2, "content", 0));
0177     frameMoves << std::make_pair(FrameItem(layer1, "content", 10), FrameItem(layer2, "content", 10));
0178     frameMoves << std::make_pair(FrameItem(layer1, "content", 20), FrameItem(layer2, "content", 20));
0179     frameMoves << std::make_pair(FrameItem(layer2, "content", 0), FrameItem(layer1, "content", 0));
0180     frameMoves << std::make_pair(FrameItem(layer2, "content", 10), FrameItem(layer1, "content", 10));
0181     frameMoves << std::make_pair(FrameItem(layer2, "content", 20), FrameItem(layer1, "content", 20));
0182 
0183     cmd.reset(createMoveKeyframesCommand(frameMoves, false, false));
0184     cmd->redo();
0185 
0186     referenceRects << std::make_tuple( 0, QRect( 0, 10, 10, 10), QRect( 0, 0, 10, 10));
0187     referenceRects << std::make_tuple(10, QRect(10, 10, 10, 10), QRect(10, 0, 10, 10));
0188     referenceRects << std::make_tuple(20, QRect(20, 10, 10, 10), QRect(20, 0, 10, 10));
0189     QVERIFY(verifyFrames(p, nodes, referenceRects));
0190 
0191     cmd->undo();
0192 
0193     QVERIFY(verifyFrames(p, nodes, initialReferenceRects));
0194 
0195     frameMoves.clear();
0196     referenceRects.clear();
0197     cmd.reset();
0198 
0199     //
0200     // Cross-node move and swap
0201     //
0202     frameMoves << std::make_pair(FrameItem(layer1, "content", 0), FrameItem(layer2, "content", 0));
0203     frameMoves << std::make_pair(FrameItem(layer1, "content", 10), FrameItem(layer2, "content", 10));
0204     frameMoves << std::make_pair(FrameItem(layer1, "content", 20), FrameItem(layer2, "content", 20));
0205 
0206     frameMoves << std::make_pair(FrameItem(layer2, "content", 0), FrameItem(layer1, "content", 0));
0207     frameMoves << std::make_pair(FrameItem(layer2, "content", 10), FrameItem(layer1, "content",  9));
0208     frameMoves << std::make_pair(FrameItem(layer2, "content", 20), FrameItem(layer1, "content", 20));
0209 
0210     cmd.reset(createMoveKeyframesCommand(frameMoves, false, false));
0211     cmd->redo();
0212 
0213     referenceRects << std::make_tuple( 0, QRect( 0, 10, 10, 10), QRect( 0, 0, 10, 10));
0214     referenceRects << std::make_tuple( 9, QRect(10, 10, 10, 10), QRect()             );
0215     referenceRects << std::make_tuple(10, QRect()              , QRect(10, 0, 10, 10));
0216     referenceRects << std::make_tuple(20, QRect(20, 10, 10, 10), QRect(20, 0, 10, 10));
0217     QVERIFY(verifyFrames(p, nodes, referenceRects));
0218 
0219     cmd->undo();
0220 
0221     QVERIFY(verifyFrames(p, nodes, initialReferenceRects));
0222 
0223     frameMoves.clear();
0224     referenceRects.clear();
0225     cmd.reset();
0226 
0227 
0228 
0229 }
0230 
0231 SIMPLE_TEST_MAIN(KisAnimationUtilsTest)