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)