File indexing completed on 2024-06-09 04:22:03

0001 /*
0002  *  SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_base_node_test.h"
0008 #include "KoColor.h"
0009 #include "kis_base_node.h"
0010 #include "kis_global.h"
0011 #include "kis_image_animation_interface.h"
0012 #include "kis_paint_device.h"
0013 #include "kis_scalar_keyframe_channel.h"
0014 #include "kis_types.h"
0015 #include <limits.h>
0016 #include <simpletest.h>
0017 #include <testing_nodes.h>
0018 #include <testutil.h>
0019 
0020 
0021 #include <KoProperties.h>
0022 
0023 class TestNode : public TestUtil::DefaultNode
0024 {
0025     using KisBaseNode::accept;
0026 
0027     KisNodeSP clone() const override {
0028         return new TestNode(*this);
0029     }
0030 };
0031 
0032 void KisBaseNodeTest::testCreation()
0033 {
0034     KisBaseNodeSP node = new TestNode();
0035     QVERIFY(node->name().isEmpty());
0036     QVERIFY(node->name() == node->objectName());
0037     QVERIFY(node->icon().isNull());
0038     QVERIFY(node->visible() == true);
0039     QVERIFY(node->userLocked() == false);
0040     QVERIFY(node->x() == 0);
0041     QVERIFY(node->y() == 0);
0042 }
0043 
0044 void KisBaseNodeTest::testContract()
0045 {
0046     KisBaseNodeSP node = new TestNode();
0047 
0048     node->setName("bla");
0049     QVERIFY(node->name()  == "bla");
0050     QVERIFY(node->objectName() == "bla");
0051 
0052     node->setObjectName("zxc");
0053     QVERIFY(node->name()  == "zxc");
0054     QVERIFY(node->objectName() == "zxc");
0055 
0056     node->setVisible(!node->visible());
0057     QVERIFY(node->visible() == false);
0058 
0059     node->setUserLocked(!node->userLocked());
0060     QVERIFY(node->userLocked() == true);
0061 
0062     KisBaseNode::PropertyList list = node->sectionModelProperties();
0063     QVERIFY(list.count() == 2);
0064     QVERIFY(list.at(0).state == node->visible());
0065     QVERIFY(list.at(1).state == node->userLocked());
0066 
0067     QImage image = node->createThumbnail(10, 10);
0068     QCOMPARE(image.size(), QSize(10, 10));
0069     QVERIFY(image.pixel(5, 5) == QColor(0, 0, 0, 0).rgba());
0070 
0071 }
0072 
0073 void KisBaseNodeTest::testProperties()
0074 {
0075     KisBaseNodeSP node = new TestNode();
0076 
0077     {
0078         KoProperties props;
0079 
0080         props.setProperty("bladiebla", false);
0081         QVERIFY(node->check(props));
0082 
0083         props.setProperty("visible", true);
0084         props.setProperty("locked", false);
0085         QVERIFY(node->check(props));
0086 
0087         props.setProperty("locked", true);
0088         QVERIFY(!node->check(props));
0089 
0090         node->setNodeProperty("locked", false);
0091         QVERIFY(node->userLocked() == false);
0092     }
0093     {
0094         KoProperties props;
0095         props.setProperty("blablabla", 10);
0096         node->mergeNodeProperties(props);
0097 
0098         QVERIFY(node->nodeProperties().intProperty("blablabla") == 10);
0099         QVERIFY(node->check(props));
0100         props.setProperty("blablabla", 12);
0101         QVERIFY(!node->check(props));
0102     }
0103 }
0104 
0105 void KisBaseNodeTest::testOpacityKeyframing()
0106 {
0107     TestUtil::MaskParent context;
0108 
0109     // Get/create channel..
0110     KisScalarKeyframeChannel *opacityChannel = dynamic_cast<KisScalarKeyframeChannel*>(
0111                 context.layer->getKeyframeChannel(KisKeyframeChannel::Opacity.id(), true));
0112     QVERIFY(opacityChannel);
0113     QVERIFY(opacityChannel->limits());
0114 
0115     const int timeA = 7;
0116     const int timeB = 15;
0117     const int halfTimeOffset = (timeB - timeA) / 2;
0118 
0119     // Keyframe values are stored in percent,
0120     // but opacity values are stored as bytes
0121     // Therefore, we should convert all percentage
0122     // values to bytes for comparison testing.
0123     const qreal valueA = 50;
0124     const quint8 valueAU8 = (valueA / 100) * 255;
0125     const qreal valueB = 25;
0126     const quint8 valueBU8 = (valueB / 100) * 255;
0127 
0128     // Interpolated value lands on frame edge, so value isn't quite in the middle..
0129     const qreal valueDeltaPerFrame = (valueA - valueB) / qreal(timeB - timeA);
0130     const qreal interpolatedValueAB = valueB + valueDeltaPerFrame * halfTimeOffset;
0131     const quint8 interpValueABU8 = (interpolatedValueAB / 100) * 255;
0132 
0133     // Add frames..
0134     opacityChannel->addScalarKeyframe(timeA, valueA);
0135     opacityChannel->addScalarKeyframe(timeB, valueB);
0136 
0137     QVERIFY(opacityChannel->keyframeCount() == 2);
0138 
0139     // Paint starting color..
0140     const KoColorSpace *colorSpace = context.layer->paintDevice()->colorSpace();
0141     const KoColor originalColor = KoColor(Qt::red, colorSpace);
0142     context.layer->paintDevice()->fill(context.imageRect, originalColor);
0143 
0144     // Regenerate projection..
0145     context.image->refreshGraph();
0146 
0147     {   // Before A (Opacity should be the same as A!)
0148         context.image->animationInterface()->switchCurrentTimeAsync(0);
0149         context.image->waitForDone();
0150 
0151         KoColor sample(colorSpace);
0152         context.image->projection()->pixel(16, 16, &sample);
0153         QCOMPARE(opacityChannel->valueAt(0), valueA);
0154         QCOMPARE(sample.opacityU8(), valueAU8);
0155     }
0156 
0157     {   // A
0158         context.image->animationInterface()->switchCurrentTimeAsync(timeA);
0159         context.image->waitForDone();
0160 
0161         KoColor sample;
0162         context.image->projection()->pixel(16, 16, &sample);
0163         QCOMPARE(opacityChannel->valueAt(timeA), valueA);
0164         QCOMPARE(sample.opacityU8(), valueAU8);
0165     }
0166 
0167     {   // Between A-B (Opacity interpolated)
0168         context.image->animationInterface()->switchCurrentTimeAsync(timeA + halfTimeOffset);
0169         context.image->waitForDone();
0170 
0171         QCOMPARE(opacityChannel->valueAt(timeA + halfTimeOffset), interpolatedValueAB);
0172 
0173         KoColor sample;
0174         context.image->projection()->pixel(16, 16, &sample);
0175         QCOMPARE(sample.opacityU8(), interpValueABU8);
0176 
0177         // Restore opacity and double check color continuity..
0178         sample.setOpacity(originalColor.opacityU8());
0179         QCOMPARE(sample, originalColor);
0180     }
0181 
0182     {   // B
0183         context.image->animationInterface()->switchCurrentTimeAsync(timeB);
0184         context.image->waitForDone();
0185 
0186         QCOMPARE(opacityChannel->valueAt(timeB), valueB);
0187 
0188         KoColor sample;
0189         context.image->projection()->pixel(16, 16, &sample);
0190         QCOMPARE(sample.opacityU8(), valueBU8);
0191     }
0192 
0193     {   // After B (Opacity should be the same as B!)
0194         context.image->animationInterface()->switchCurrentTimeAsync(timeB + halfTimeOffset);
0195         context.image->waitForDone();
0196 
0197         QCOMPARE(opacityChannel->valueAt(timeB + halfTimeOffset), valueB);
0198 
0199         KoColor sample;
0200         context.image->projection()->pixel(16, 16, &sample);
0201         QCOMPARE(sample.opacityU8(), valueBU8);
0202     }
0203 }
0204 
0205 SIMPLE_TEST_MAIN(KisBaseNodeTest)
0206 
0207