File indexing completed on 2024-12-22 04:10:23
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_paint_layer_test.h" 0008 #include <simpletest.h> 0009 #include <QImage> 0010 #include <QCoreApplication> 0011 0012 #include <KoColorSpace.h> 0013 #include <KoColorSpaceRegistry.h> 0014 0015 #include "kundo2command.h" 0016 0017 #include "kis_group_layer.h" 0018 #include "kis_types.h" 0019 #include "kis_paint_layer.h" 0020 #include "kis_image.h" 0021 #include "kis_paint_device.h" 0022 #include "kis_transparency_mask.h" 0023 #include <testutil.h> 0024 #include "kis_selection.h" 0025 #include "kis_fill_painter.h" 0026 #include "kis_pixel_selection.h" 0027 #include <kis_iterator_ng.h> 0028 #include "kis_layer_projection_plane.h" 0029 #include "kis_psd_layer_style.h" 0030 #include "filter/kis_filter_registry.h" 0031 #include "kis_keyframe_channel.h" 0032 #include "kis_paint_device_debug_utils.h" 0033 0034 void KisPaintLayerTest::testProjection() 0035 { 0036 0037 QImage qimage(QString(FILES_DATA_DIR) + '/' + "hakonepa.png"); 0038 const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); 0039 KisImageSP image = new KisImage(0, qimage.width(), qimage.height(), cs, "merge test"); 0040 0041 KisPaintLayerSP layer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); 0042 layer->paintDevice()->convertFromQImage(qimage, 0, 0, 0); 0043 image->addNode(layer.data()); 0044 0045 // Make sure the projection and the paint device are the same -- we don't have masks yet 0046 QVERIFY(layer->paintDevice().data() == layer->projection().data()); 0047 0048 KisTransparencyMaskSP transparencyMask = new KisTransparencyMask(image, "tmask"); 0049 transparencyMask->initSelection(layer); 0050 transparencyMask->selection()->pixelSelection()->invert(); 0051 image->addNode(transparencyMask.data(), layer.data()); 0052 0053 // Now there are masks. Verify that 0054 Q_ASSERT(layer->hasEffectMasks()); 0055 0056 // And now we're going to update the projection, but nothing is dirty yet 0057 layer->projectionPlane()->recalculate(qimage.rect(), layer); 0058 0059 // Which also means that the projection is no longer the paint device 0060 QVERIFY(layer->paintDevice().data() != layer->projection().data()); 0061 0062 // Now the machinery will start to roll 0063 layer->setDirty(qimage.rect()); 0064 0065 // And now we're going to update the projection, but nothing is dirty yet 0066 layer->projectionPlane()->recalculate(qimage.rect(), layer); 0067 0068 // Which also means that the projection is no longer the paint device 0069 QVERIFY(layer->paintDevice().data() != layer->projection().data()); 0070 0071 // And the projection is no longer 0, because while we've updated it, nothing is dirty, 0072 // so nothing gets updated 0073 QVERIFY(layer->projection().data() != 0); 0074 0075 // The selection is initially empty, so after an update, all pixels are still visible 0076 layer->projectionPlane()->recalculate(qimage.rect(), layer); 0077 0078 // We've inverted the mask, so now nothing is seen 0079 KisSequentialConstIterator it(layer->projection(), qimage.rect()); 0080 while (it.nextPixel()) { 0081 QVERIFY(cs->opacityU8(it.oldRawData()) == OPACITY_TRANSPARENT_U8); 0082 }; 0083 0084 // Now fill the layer with some opaque pixels 0085 transparencyMask->select(qimage.rect()); 0086 transparencyMask->setDirty(qimage.rect()); 0087 image->waitForDone(); 0088 0089 layer->projection()->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("aaa.png"); 0090 // Nothing is transparent anymore, so the projection and the paint device should be identical again 0091 QPoint errpoint; 0092 if (!TestUtil::compareQImages(errpoint, qimage, layer->projection()->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { 0093 QFAIL(QString("Failed to create identical image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); 0094 } 0095 0096 } 0097 0098 void KisPaintLayerTest::testKeyframing() 0099 { 0100 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); 0101 KisImageSP image = new KisImage(0, 512, 512, cs, ""); 0102 KisPaintLayerSP layer = new KisPaintLayer(image, "", OPACITY_OPAQUE_U8); 0103 KisPaintDeviceSP dev = layer->paintDevice(); 0104 0105 KisKeyframeChannel *contentChannel = layer->getKeyframeChannel(KisKeyframeChannel::Raster.id()); 0106 QVERIFY(!contentChannel); 0107 0108 layer->enableAnimation(); 0109 0110 contentChannel = layer->getKeyframeChannel("content", true); 0111 QVERIFY(contentChannel); 0112 QCOMPARE(contentChannel->keyframeCount(), 1); 0113 0114 KUndo2Command parentCommand; 0115 0116 contentChannel->addKeyframe(7, &parentCommand); 0117 QCOMPARE(contentChannel->keyframeCount(), 2); 0118 QVERIFY(contentChannel->keyframeAt(0) != contentChannel->keyframeAt(7)); 0119 0120 KisPaintLayerSP layerCopy = new KisPaintLayer(*layer.data()); 0121 } 0122 0123 void KisPaintLayerTest::testLayerStyles() 0124 { 0125 /** 0126 * FIXME: Right now the layer style plugin is stored in 'filters' 0127 * directory, so we need to load filters to get it registered 0128 * in the factory. 0129 */ 0130 KisFilterRegistry::instance(); 0131 0132 const QRect imageRect(0, 0, 200, 200); 0133 const QRect rFillRect(10, 10, 100, 100); 0134 const QRect tMaskRect(50, 50, 20, 20); 0135 const QRect partialSelectionRect(90, 50, 20, 20); 0136 0137 0138 const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); 0139 KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "styles test"); 0140 0141 KisPaintLayerSP layer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); 0142 image->addNode(layer); 0143 0144 layer->paintDevice()->fill(rFillRect, KoColor(Qt::red, cs)); 0145 0146 layer->setDirty(); 0147 image->waitForDone(); 0148 KIS_DUMP_DEVICE_2(layer->projection(), imageRect, "00L_initial", "dd"); 0149 0150 KisPSDLayerStyleSP style(new KisPSDLayerStyle()); 0151 style->dropShadow()->setNoise(30); 0152 style->dropShadow()->setEffectEnabled(true); 0153 0154 layer->setLayerStyle(style); 0155 0156 layer->setDirty(); 0157 image->waitForDone(); 0158 KIS_DUMP_DEVICE_2(image->projection(), imageRect, "02P_styled", "dd"); 0159 0160 KisTransparencyMaskSP transparencyMask = new KisTransparencyMask(image, "tmask"); 0161 0162 KisSelectionSP selection = new KisSelection(); 0163 selection->pixelSelection()->select(tMaskRect, OPACITY_OPAQUE_U8); 0164 transparencyMask->setSelection(selection); 0165 image->addNode(transparencyMask, layer); 0166 0167 layer->setDirty(); 0168 image->waitForDone(); 0169 KIS_DUMP_DEVICE_2(image->projection(), imageRect, "03P_styled", "dd"); 0170 0171 selection->pixelSelection()->select(partialSelectionRect, OPACITY_OPAQUE_U8); 0172 layer->setDirty(partialSelectionRect); 0173 0174 layer->setDirty(); 0175 image->waitForDone(); 0176 KIS_DUMP_DEVICE_2(image->projection(), imageRect, "04P_partial", "dd"); 0177 } 0178 0179 0180 SIMPLE_TEST_MAIN(KisPaintLayerTest)