Warning, file /graphics/krita/sdk/tests/stroke_testing_utils.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "stroke_testing_utils.h" 0008 0009 #include <simpletest.h> 0010 0011 #include <QDir> 0012 #include <KoColor.h> 0013 #include <KoColorSpace.h> 0014 #include <KoColorSpaceRegistry.h> 0015 #include <KoCompositeOpRegistry.h> 0016 #include <brushengine/kis_paintop_preset.h> 0017 #include <resources/KoPattern.h> 0018 #include "kis_canvas_resource_provider.h" 0019 #include "kis_image.h" 0020 #include "kis_paint_device.h" 0021 #include "kis_paint_layer.h" 0022 #include "kis_group_layer.h" 0023 #include <KisViewManager.h> 0024 0025 #include <testutil.h> 0026 #include <KisGlobalResourcesInterface.h> 0027 0028 0029 KisImageSP utils::createImage(KisUndoStore *undoStore, const QSize &imageSize) { 0030 QRect imageRect(0,0,imageSize.width(),imageSize.height()); 0031 0032 const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); 0033 KisImageSP image = new KisImage(undoStore, imageRect.width(), imageRect.height(), cs, "stroke test"); 0034 0035 KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); 0036 KisPaintLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); 0037 KisPaintLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); 0038 KisPaintLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); 0039 KisPaintLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); 0040 0041 image->barrierLock(); 0042 image->addNode(paintLayer1); 0043 image->addNode(paintLayer2); 0044 image->addNode(paintLayer3); 0045 image->addNode(paintLayer4); 0046 image->addNode(paintLayer5); 0047 image->unlock(); 0048 return image; 0049 } 0050 0051 KoCanvasResourceProvider* utils::createResourceManager(KisImageWSP image, 0052 KisNodeSP node, 0053 const QString &presetFileName) 0054 { 0055 KoCanvasResourceProvider *manager = new KoCanvasResourceProvider(); 0056 KisViewManager::initializeResourceManager(manager); 0057 0058 QVariant i; 0059 0060 i.setValue(KoColor(Qt::black, image->colorSpace())); 0061 manager->setResource(KoCanvasResource::ForegroundColor, i); 0062 0063 i.setValue(KoColor(Qt::white, image->colorSpace())); 0064 manager->setResource(KoCanvasResource::BackgroundColor, i); 0065 0066 i.setValue(static_cast<void*>(0)); 0067 manager->setResource(KoCanvasResource::CurrentPattern, i); 0068 manager->setResource(KoCanvasResource::CurrentGradient, i); 0069 manager->setResource(KoCanvasResource::CurrentGeneratorConfiguration, i); 0070 0071 if(!node) { 0072 node = image->root(); 0073 0074 while(node && !dynamic_cast<KisPaintLayer*>(node.data())) { 0075 node = node->firstChild(); 0076 } 0077 0078 Q_ASSERT(node && dynamic_cast<KisPaintLayer*>(node.data())); 0079 } 0080 0081 i.setValue(node); 0082 manager->setResource(KoCanvasResource::CurrentKritaNode, i); 0083 0084 KisPaintOpPresetSP preset; 0085 0086 if (!presetFileName.isEmpty()) { 0087 QString fullFileName = TestUtil::fetchDataFileLazy(presetFileName); 0088 preset = KisPaintOpPresetSP(new KisPaintOpPreset(fullFileName)); 0089 bool presetValid = preset->load(KisGlobalResourcesInterface::instance()); 0090 Q_ASSERT(presetValid); Q_UNUSED(presetValid); 0091 0092 i.setValue(preset); 0093 manager->setResource(KoCanvasResource::CurrentPaintOpPreset, i); 0094 } 0095 0096 i.setValue(COMPOSITE_OVER); 0097 manager->setResource(KoCanvasResource::CurrentCompositeOp, i); 0098 0099 i.setValue(false); 0100 manager->setResource(KoCanvasResource::MirrorHorizontal, i); 0101 0102 i.setValue(false); 0103 manager->setResource(KoCanvasResource::MirrorVertical, i); 0104 0105 i.setValue(1.0); 0106 manager->setResource(KoCanvasResource::Opacity, i); 0107 0108 i.setValue(1.0); 0109 manager->setResource(KoCanvasResource::HdrExposure, i); 0110 0111 return manager; 0112 } 0113 0114 utils::StrokeTester::StrokeTester(const QString &name, const QSize &imageSize, const QString &presetFilename) 0115 : m_name(name), 0116 m_imageSize(imageSize), 0117 m_presetFilename(presetFilename), 0118 m_numIterations(1), 0119 m_baseFuzziness(1) 0120 { 0121 } 0122 0123 utils::StrokeTester::~StrokeTester() 0124 { 0125 } 0126 0127 void utils::StrokeTester::setNumIterations(int value) 0128 { 0129 m_numIterations = value; 0130 } 0131 0132 void utils::StrokeTester::setBaseFuzziness(int value) 0133 { 0134 m_baseFuzziness = value; 0135 } 0136 0137 void utils::StrokeTester::testSimpleStroke() 0138 { 0139 testOneStroke(false, true, false, true); 0140 } 0141 0142 int utils::StrokeTester::lastStrokeTime() const 0143 { 0144 return m_strokeTime; 0145 } 0146 0147 void utils::StrokeTester::test() 0148 { 0149 testOneStroke(false, false, false); 0150 testOneStroke(false, true, false); 0151 testOneStroke(true, false, false); 0152 testOneStroke(true, true, false); 0153 0154 // The same but with updates (compare against projection) 0155 0156 testOneStroke(false, false, false, true); 0157 testOneStroke(false, true, false, true); 0158 testOneStroke(true, false, false, true); 0159 testOneStroke(true, true, false, true); 0160 0161 // The same, but with an external layer 0162 0163 testOneStroke(false, false, true); 0164 testOneStroke(false, true, true); 0165 testOneStroke(true, false, true); 0166 testOneStroke(true, true, true); 0167 } 0168 0169 void utils::StrokeTester::benchmark() 0170 { 0171 // not cancelled, indirect painting, internal, no updates, no qimage 0172 doStroke(false, false, false, false); 0173 } 0174 0175 void utils::StrokeTester::testSimpleStrokeNoVerification() 0176 { 0177 doStroke(false, false, true, false); 0178 } 0179 0180 void utils::StrokeTester::testOneStroke(bool cancelled, 0181 bool indirectPainting, 0182 bool externalLayer, 0183 bool testUpdates) 0184 { 0185 // TODO: indirectPainting option is not used anymore! The real value is 0186 // taken from the preset! 0187 0188 QString testName = formatTestName(m_name, 0189 cancelled, 0190 indirectPainting, 0191 externalLayer); 0192 0193 dbgKrita << "Testcase:" << testName 0194 << "(compare against " << (testUpdates ? "projection" : "layer") << ")"; 0195 0196 QImage resultImage; 0197 resultImage = doStroke(cancelled, externalLayer, testUpdates); 0198 0199 QImage refImage; 0200 refImage.load(referenceFile(testName)); 0201 0202 QPoint temp; 0203 if(!TestUtil::compareQImages(temp, refImage, resultImage, m_baseFuzziness, m_baseFuzziness)) { 0204 refImage.save(dumpReferenceFile(testName)); 0205 resultImage.save(resultFile(testName)); 0206 0207 QFAIL("Images do not coincide"); 0208 } 0209 } 0210 0211 QString utils::StrokeTester::formatTestName(const QString &baseName, 0212 bool cancelled, 0213 bool indirectPainting, 0214 bool externalLayer) 0215 { 0216 QString result = baseName; 0217 result += "_" + m_presetFilename; 0218 result += indirectPainting ? "_indirect" : "_incremental"; 0219 result += cancelled ? "_cancelled" : "_finished"; 0220 result += externalLayer ? "_external" : "_internal"; 0221 return result; 0222 } 0223 0224 QString utils::StrokeTester::referenceFile(const QString &testName) 0225 { 0226 QString path = 0227 QString(FILES_DATA_DIR) + '/' + 0228 m_name + '/'; 0229 0230 path += testName; 0231 path += ".png"; 0232 return path; 0233 } 0234 0235 QString utils::StrokeTester::dumpReferenceFile(const QString &testName) 0236 { 0237 QString path = QString(FILES_OUTPUT_DIR) + '/'; 0238 path += testName; 0239 path += "_expected"; 0240 path += ".png"; 0241 return path; 0242 } 0243 0244 QString utils::StrokeTester::resultFile(const QString &testName) 0245 { 0246 QString path = QString(FILES_OUTPUT_DIR) + '/'; 0247 path += testName; 0248 path += ".png"; 0249 return path; 0250 } 0251 0252 QImage utils::StrokeTester::doStroke(bool cancelled, 0253 bool externalLayer, 0254 bool testUpdates, 0255 bool needQImage) 0256 { 0257 KisImageSP image = utils::createImage(0, m_imageSize); 0258 KoCanvasResourceProvider *manager = utils::createResourceManager(image, 0, m_presetFilename); 0259 KisNodeSP currentNode; 0260 0261 for (int i = 0; i < m_numIterations; i++) { 0262 modifyResourceManager(manager, image, i); 0263 0264 KisResourcesSnapshotSP resources = 0265 new KisResourcesSnapshot(image, 0266 image->rootLayer()->firstChild(), 0267 manager); 0268 0269 if(externalLayer) { 0270 KisNodeSP externalNode = new KisPaintLayer(0, "extlyr", OPACITY_OPAQUE_U8, image->colorSpace()); 0271 resources->setCurrentNode(externalNode); 0272 Q_ASSERT(resources->currentNode() == externalNode); 0273 } 0274 0275 initImage(image, resources->currentNode(), i); 0276 0277 QElapsedTimer strokeTime; 0278 strokeTime.start(); 0279 0280 KisStrokeStrategy *stroke = createStroke(resources, image); 0281 m_strokeId = image->startStroke(stroke); 0282 addPaintingJobs(image, resources, i); 0283 0284 if(!cancelled) { 0285 image->endStroke(m_strokeId); 0286 } 0287 else { 0288 image->cancelStroke(m_strokeId); 0289 } 0290 0291 image->waitForDone(); 0292 0293 m_strokeTime = strokeTime.elapsed(); 0294 currentNode = resources->currentNode(); 0295 } 0296 0297 beforeCheckingResult(image, currentNode); 0298 0299 QImage resultImage; 0300 if(needQImage) { 0301 KisPaintDeviceSP device = testUpdates ? 0302 image->projection() : 0303 currentNode->paintDevice(); 0304 0305 resultImage = device->convertToQImage(0, 0, 0, image->width(), image->height()); 0306 } 0307 0308 image = 0; 0309 delete manager; 0310 return resultImage; 0311 } 0312 0313 void utils::StrokeTester::modifyResourceManager(KoCanvasResourceProvider *manager, 0314 KisImageWSP image, int iteration) 0315 { 0316 Q_UNUSED(iteration); 0317 modifyResourceManager(manager, image); 0318 } 0319 0320 void utils::StrokeTester::modifyResourceManager(KoCanvasResourceProvider *manager, 0321 KisImageWSP image) 0322 { 0323 Q_UNUSED(manager); 0324 Q_UNUSED(image); 0325 } 0326 0327 void utils::StrokeTester::initImage(KisImageWSP image, KisNodeSP activeNode, int iteration) 0328 { 0329 Q_UNUSED(iteration); 0330 initImage(image, activeNode); 0331 } 0332 0333 void utils::StrokeTester::initImage(KisImageWSP image, KisNodeSP activeNode) 0334 { 0335 Q_UNUSED(image); 0336 Q_UNUSED(activeNode); 0337 } 0338 0339 void utils::StrokeTester::addPaintingJobs(KisImageWSP image, 0340 KisResourcesSnapshotSP resources, 0341 int iteration) 0342 { 0343 Q_UNUSED(iteration); 0344 addPaintingJobs(image, resources); 0345 } 0346 0347 void utils::StrokeTester::addPaintingJobs(KisImageWSP image, 0348 KisResourcesSnapshotSP resources) 0349 { 0350 Q_UNUSED(image); 0351 Q_UNUSED(resources); 0352 } 0353 0354 void utils::StrokeTester::beforeCheckingResult(KisImageWSP image, KisNodeSP activeNode) 0355 { 0356 Q_UNUSED(image); 0357 Q_UNUSED(activeNode); 0358 }