File indexing completed on 2024-12-22 04:10:18
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org> 0003 * SPDX-FileCopyrightText: 2010 Cyrille Berger <cberger@cberger.net> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kis_iterators_ng_test.h" 0009 #include <QApplication> 0010 0011 #include <simpletest.h> 0012 #include <KoColor.h> 0013 #include <KoColorSpace.h> 0014 #include <KoColorSpaceRegistry.h> 0015 #include <KoColorProfile.h> 0016 0017 #include "kis_random_accessor_ng.h" 0018 #include "kis_random_sub_accessor.h" 0019 0020 #include "kis_paint_device.h" 0021 #include <kis_iterator_ng.h> 0022 #include "kis_global.h" 0023 #include <testutil.h> 0024 #include <testimage.h> 0025 0026 void KisIteratorNGTest::allCsApplicator(void (KisIteratorNGTest::* funcPtr)(const KoColorSpace*cs)) 0027 { 0028 QList<const KoColorSpace*> colorspaces = KoColorSpaceRegistry::instance()->allColorSpaces(KoColorSpaceRegistry::AllColorSpaces, KoColorSpaceRegistry::OnlyDefaultProfile); 0029 0030 Q_FOREACH (const KoColorSpace* cs, colorspaces) { 0031 0032 dbgKrita << "Testing with" << cs->id(); 0033 if (cs->id() != "GRAYU16") // No point in testing extend for GRAYU16 0034 (this->*funcPtr)(cs); 0035 } 0036 } 0037 0038 inline quint8* allocatePixels(const KoColorSpace *colorSpace, int numPixels) 0039 { 0040 quint8 * bytes = new quint8[colorSpace->pixelSize() * 64 * 64 * 10]; 0041 KoColor color(Qt::red, colorSpace); 0042 const int pixelSize = colorSpace->pixelSize(); 0043 for(int i = 0; i < numPixels; i++) { 0044 memcpy(bytes + i * pixelSize, color.data(), pixelSize); 0045 } 0046 0047 return bytes; 0048 } 0049 0050 void KisIteratorNGTest::writeBytes(const KoColorSpace * colorSpace) 0051 { 0052 0053 0054 KisPaintDevice dev(colorSpace); 0055 0056 QCOMPARE(dev.extent(), QRect()); 0057 0058 // Check allocation on tile boundaries 0059 0060 // Allocate memory for a 2 * 5 tiles grid 0061 QScopedArrayPointer<quint8> bytes(allocatePixels(colorSpace, 64 * 64 * 10)); 0062 0063 // Covers 5 x 2 tiles 0064 dev.writeBytes(bytes.data(), 0, 0, 5 * 64, 2 * 64); 0065 0066 // Covers 0067 QCOMPARE(dev.extent(), QRect(0, 0, 64 * 5, 64 * 2)); 0068 QCOMPARE(dev.exactBounds(), QRect(0, 0, 64 * 5, 64 * 2)); 0069 0070 dev.clear(); 0071 QCOMPARE(dev.extent(), QRect()); 0072 0073 dev.clear(); 0074 // Covers three by three tiles 0075 dev.writeBytes(bytes.data(), 10, 10, 130, 130); 0076 0077 QCOMPARE(dev.extent(), QRect(0, 0, 64 * 3, 64 * 3)); 0078 QCOMPARE(dev.exactBounds(), QRect(10, 10, 130, 130)); 0079 0080 dev.clear(); 0081 // Covers 11 x 2 tiles 0082 dev.writeBytes(bytes.data(), -10, -10, 10 * 64, 64); 0083 0084 QCOMPARE(dev.extent(), QRect(-64, -64, 64 * 11, 64 * 2)); 0085 QCOMPARE(dev.exactBounds(), QRect(-10, -10, 640, 64)); 0086 } 0087 0088 void KisIteratorNGTest::fill(const KoColorSpace * colorSpace) 0089 { 0090 0091 KisPaintDevice dev(colorSpace); 0092 0093 QCOMPARE(dev.extent(), QRect()); 0094 0095 QScopedArrayPointer<quint8> bytes(allocatePixels(colorSpace, 1)); 0096 0097 dev.fill(0, 0, 5, 5, bytes.data()); 0098 QCOMPARE(dev.extent(), QRect(0, 0, 64, 64)); 0099 QCOMPARE(dev.exactBounds(), QRect(0, 0, 5, 5)); 0100 0101 dev.clear(); 0102 dev.fill(5, 5, 5, 5, bytes.data()); 0103 QCOMPARE(dev.extent(), QRect(0, 0, 64, 64)); 0104 QCOMPARE(dev.exactBounds(), QRect(5, 5, 5, 5)); 0105 0106 dev.clear(); 0107 dev.fill(5, 5, 500, 500, bytes.data()); 0108 QCOMPARE(dev.extent(), QRect(0, 0, 8 * 64, 8 * 64)); 0109 QCOMPARE(dev.exactBounds(), QRect(5, 5, 500, 500)); 0110 0111 dev.clear(); 0112 dev.fill(33, -10, 348, 1028, bytes.data()); 0113 QCOMPARE(dev.extent(), QRect(0, -64, 6 * 64, 17 * 64)); 0114 QCOMPARE(dev.exactBounds(), QRect(33, -10, 348, 1028)); 0115 } 0116 0117 void KisIteratorNGTest::sequentialIter(const KoColorSpace * colorSpace) 0118 { 0119 0120 KisPaintDeviceSP dev = new KisPaintDevice(colorSpace); 0121 0122 QCOMPARE(dev->extent(), QRect()); 0123 0124 // Const does not extend the extent 0125 { 0126 KisSequentialConstIterator it(dev, QRect(0, 0, 128, 128)); 0127 while (it.nextPixel()); 0128 QCOMPARE(dev->extent(), QRect()); 0129 QCOMPARE(dev->exactBounds(), QRect(QPoint(0, 0), QPoint(-1, -1))); 0130 } 0131 0132 // Non-const does 0133 { 0134 KisSequentialIterator it(dev, QRect(0, 0, 128, 128)); 0135 int i = -1; 0136 0137 while (it.nextPixel()) { 0138 i++; 0139 KoColor c(QColor(i % 255, i / 255, 0), colorSpace); 0140 memcpy(it.rawData(), c.data(), colorSpace->pixelSize()); 0141 0142 QCOMPARE(it.x(), i % 128); 0143 QCOMPARE(it.y(), i / 128); 0144 } 0145 0146 QCOMPARE(dev->extent(), QRect(0, 0, 128, 128)); 0147 QCOMPARE(dev->exactBounds(), QRect(0, 0, 128, 128)); 0148 } 0149 0150 { // check const iterator 0151 KisSequentialConstIterator it(dev, QRect(0, 0, 128, 128)); 0152 int i = -1; 0153 0154 while (it.nextPixel()) { 0155 i++; 0156 KoColor c(QColor(i % 255, i / 255, 0), colorSpace); 0157 QVERIFY(memcmp(it.rawDataConst(), c.data(), colorSpace->pixelSize()) == 0); 0158 } 0159 0160 QCOMPARE(dev->extent(), QRect(0, 0, 128, 128)); 0161 QCOMPARE(dev->exactBounds(), QRect(0, 0, 128, 128)); 0162 } 0163 0164 { // check const iterator with **empty** area! It should neither crash nor enter the loop 0165 KisSequentialConstIterator it(dev, QRect()); 0166 0167 QVERIFY(!it.rawDataConst()); 0168 QVERIFY(!it.oldRawData()); 0169 0170 while (it.nextPixel()) { 0171 QVERIFY(0 && "we should never enter the loop"); 0172 } 0173 } 0174 0175 { // check const iterator with strides 0176 KisSequentialConstIterator it(dev, QRect(0, 0, 128, 128)); 0177 int i = -1; 0178 0179 int numConseqPixels = it.nConseqPixels(); 0180 while (it.nextPixels(numConseqPixels)) { 0181 0182 numConseqPixels = it.nConseqPixels(); 0183 0184 for (int j = 0; j < numConseqPixels; j++) { 0185 i++; 0186 KoColor c(QColor(i % 255, i / 255, 0), colorSpace); 0187 QVERIFY(memcmp(it.rawDataConst() + j * colorSpace->pixelSize(), 0188 c.data(), 0189 colorSpace->pixelSize()) == 0); 0190 } 0191 } 0192 0193 QCOMPARE(dev->extent(), QRect(0, 0, 128, 128)); 0194 QCOMPARE(dev->exactBounds(), QRect(0, 0, 128, 128)); 0195 } 0196 0197 { // check const iterator with strides and **empty** area 0198 KisSequentialConstIterator it(dev, QRect()); 0199 0200 QVERIFY(!it.rawDataConst()); 0201 QVERIFY(!it.oldRawData()); 0202 0203 int numConseqPixels = it.nConseqPixels(); 0204 while (it.nextPixels(numConseqPixels)) { 0205 QVERIFY(0 && "we should never enter the loop"); 0206 } 0207 } 0208 0209 dev->clear(); 0210 0211 { 0212 KisSequentialIterator it(dev, QRect(10, 10, 128, 128)); 0213 int i = -1; 0214 0215 while (it.nextPixel()) { 0216 i++; 0217 KoColor c(QColor(i % 255, i / 255, 0), colorSpace); 0218 0219 memcpy(it.rawData(), c.data(), colorSpace->pixelSize()); 0220 } 0221 0222 QCOMPARE(dev->extent(), QRect(0, 0, 3 * 64, 3 * 64)); 0223 QCOMPARE(dev->exactBounds(), QRect(10, 10, 128, 128)); 0224 } 0225 0226 dev->clear(); 0227 dev->setX(10); 0228 dev->setY(-15); 0229 0230 { 0231 KisSequentialIterator it(dev, QRect(10, 10, 128, 128)); 0232 int i = -1; 0233 0234 while (it.nextPixel()) { 0235 i++; 0236 KoColor c(QColor(i % 255, i / 255, 0), colorSpace); 0237 0238 memcpy(it.rawData(), c.data(), colorSpace->pixelSize()); 0239 } 0240 QCOMPARE(dev->extent(), QRect(10, -15, 128, 192)); 0241 QCOMPARE(dev->exactBounds(), QRect(10, 10, 128, 128)); 0242 } 0243 { 0244 KisSequentialIterator it(dev, QRect(10, 10, 128, 128)); 0245 QCOMPARE(it.rawData(), it.oldRawData()); 0246 } 0247 } 0248 0249 void KisIteratorNGTest::hLineIter(const KoColorSpace * colorSpace) 0250 { 0251 KisPaintDevice dev(colorSpace); 0252 0253 QScopedArrayPointer<quint8> bytes(allocatePixels(colorSpace, 1)); 0254 0255 QCOMPARE(dev.extent(), QRect()); 0256 0257 KisHLineConstIteratorSP cit = dev.createHLineConstIteratorNG(0, 0, 128); 0258 while (!cit->nextPixel()); 0259 QCOMPARE(dev.extent(), QRect()); 0260 QCOMPARE(dev.exactBounds(), QRect(QPoint(0, 0), QPoint(-1, -1))); 0261 0262 dev.clear(); 0263 KisHLineIteratorSP it = dev.createHLineIteratorNG(0, 0, 128); 0264 do { 0265 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0266 } while (it->nextPixel()); 0267 0268 0269 QCOMPARE(dev.extent(), QRect(0, 0, 128, 64)); 0270 QCOMPARE(dev.exactBounds(), QRect(0, 0, 128, 1)); 0271 0272 dev.clear(); 0273 0274 it = dev.createHLineIteratorNG(0, 1, 128); 0275 do { 0276 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0277 } while (it->nextPixel()); 0278 0279 QCOMPARE(dev.extent(), QRect(0, 0, 128, 64)); 0280 QCOMPARE(dev.exactBounds(), QRect(0, 1, 128, 1)); 0281 0282 dev.clear(); 0283 0284 it = dev.createHLineIteratorNG(10, 10, 128); 0285 do { 0286 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0287 } while (it->nextPixel()); 0288 0289 QCOMPARE(dev.extent(), QRect(0, 0, 192, 64)); 0290 QCOMPARE(dev.exactBounds(), QRect(10, 10, 128, 1)); 0291 0292 dev.clear(); 0293 dev.setX(10); 0294 dev.setY(-15); 0295 0296 it = dev.createHLineIteratorNG(10, 10, 128); 0297 do { 0298 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0299 } while (it->nextPixel()); 0300 0301 QCOMPARE(dev.extent(), QRect(10, -15, 128, 64)); 0302 QCOMPARE(dev.exactBounds(), QRect(10, 10, 128, 1)); 0303 0304 it = dev.createHLineIteratorNG(10, 10, 128); 0305 it->nextRow(); 0306 QCOMPARE(it->rawData(), it->oldRawData()); 0307 } 0308 0309 void KisIteratorNGTest::justCreation(const KoColorSpace * colorSpace) 0310 { 0311 KisPaintDevice dev(colorSpace); 0312 dev.createVLineConstIteratorNG(0, 0, 128); 0313 dev.createVLineIteratorNG(0, 0, 128); 0314 dev.createHLineConstIteratorNG(0, 0, 128); 0315 dev.createHLineIteratorNG(0, 0, 128); 0316 } 0317 0318 void KisIteratorNGTest::vLineIter(const KoColorSpace * colorSpace) 0319 { 0320 0321 KisPaintDevice dev(colorSpace); 0322 QScopedArrayPointer<quint8> bytes(allocatePixels(colorSpace, 1)); 0323 0324 QCOMPARE(dev.extent(), QRect()); 0325 0326 KisVLineConstIteratorSP cit = dev.createVLineConstIteratorNG(0, 0, 128); 0327 while (cit->nextPixel()); 0328 QCOMPARE(dev.extent(), QRect()); 0329 QCOMPARE(dev.exactBounds(), QRect(QPoint(0, 0), QPoint(-1, -1))); 0330 cit.clear(); 0331 0332 KisVLineIteratorSP it = dev.createVLineIteratorNG(0, 0, 128); 0333 do { 0334 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0335 } while(it->nextPixel()); 0336 0337 QCOMPARE((QRect) dev.extent(), QRect(0, 0, 64, 128)); 0338 QCOMPARE((QRect) dev.exactBounds(), QRect(0, 0, 1, 128)); 0339 it.clear(); 0340 0341 dev.clear(); 0342 0343 it = dev.createVLineIteratorNG(10, 10, 128); 0344 do { 0345 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0346 } while(it->nextPixel()); 0347 0348 QCOMPARE(dev.extent(), QRect(0, 0, 64, 192)); 0349 QCOMPARE(dev.exactBounds(), QRect(10, 10, 1, 128)); 0350 0351 dev.clear(); 0352 dev.setX(10); 0353 dev.setY(-15); 0354 0355 it = dev.createVLineIteratorNG(10, 10, 128); 0356 do { 0357 memcpy(it->rawData(), bytes.data(), colorSpace->pixelSize()); 0358 } while(it->nextPixel()); 0359 0360 QCOMPARE(dev.extent(), QRect(10, -15, 64, 192)); 0361 QCOMPARE(dev.exactBounds(), QRect(10, 10, 1, 128)); 0362 0363 it = dev.createVLineIteratorNG(10, 10, 128); 0364 it->nextColumn(); 0365 QCOMPARE(it->rawData(), it->oldRawData()); 0366 } 0367 0368 void KisIteratorNGTest::randomAccessor(const KoColorSpace * colorSpace) 0369 { 0370 0371 KisPaintDevice dev(colorSpace); 0372 QScopedArrayPointer<quint8> bytes(allocatePixels(colorSpace, 1)); 0373 0374 QCOMPARE(dev.extent(), QRect()); 0375 0376 KisRandomConstAccessorSP acc = dev.createRandomConstAccessorNG(); 0377 for (int y = 0; y < 128; ++y) { 0378 for (int x = 0; x < 128; ++x) { 0379 acc->moveTo(x, y); 0380 } 0381 } 0382 QCOMPARE(dev.extent(), QRect()); 0383 0384 KisRandomAccessorSP ac = dev.createRandomAccessorNG(); 0385 for (int y = 0; y < 128; ++y) { 0386 for (int x = 0; x < 128; ++x) { 0387 ac->moveTo(x, y); 0388 memcpy(ac->rawData(), bytes.data(), colorSpace->pixelSize()); 0389 } 0390 } 0391 QCOMPARE(dev.extent(), QRect(0, 0, 128, 128)); 0392 QCOMPARE(dev.exactBounds(), QRect(0, 0, 128, 128)); 0393 0394 dev.clear(); 0395 dev.setX(10); 0396 dev.setY(-15); 0397 0398 ac = dev.createRandomAccessorNG(); 0399 for (int y = 0; y < 128; ++y) { 0400 for (int x = 0; x < 128; ++x) { 0401 ac->moveTo(x, y); 0402 memcpy(ac->rawData(), bytes.data(), colorSpace->pixelSize()); 0403 } 0404 } 0405 QCOMPARE(dev.extent(), QRect(-54, -15, 192, 192)); 0406 QCOMPARE(dev.exactBounds(), QRect(0, 0, 128, 128)); 0407 } 0408 0409 0410 void KisIteratorNGTest::writeBytes() 0411 { 0412 allCsApplicator(&KisIteratorNGTest::writeBytes); 0413 } 0414 0415 void KisIteratorNGTest::fill() 0416 { 0417 allCsApplicator(&KisIteratorNGTest::fill); 0418 } 0419 0420 void KisIteratorNGTest::sequentialIter() 0421 { 0422 allCsApplicator(&KisIteratorNGTest::sequentialIter); 0423 } 0424 0425 #include <KisSequentialIteratorProgress.h> 0426 0427 void KisIteratorNGTest::sequentialIteratorWithProgress() 0428 { 0429 KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8()); 0430 0431 const QRect rc(10,10,200,200); 0432 TestUtil::TestProgressBar proxy; 0433 0434 KisSequentialConstIteratorProgress it (dev, rc, &proxy); 0435 0436 while (it.nextPixel()) { 0437 QCOMPARE(proxy.min(), rc.top()); 0438 QCOMPARE(proxy.max(), rc.top() + rc.height()); 0439 QCOMPARE(proxy.value(), it.y()); 0440 } 0441 0442 QCOMPARE(proxy.max(), rc.top() + rc.height()); 0443 QCOMPARE(proxy.value(), proxy.max()); 0444 } 0445 0446 void KisIteratorNGTest::sequentialIteratorWithProgressIncomplete() 0447 { 0448 KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8()); 0449 0450 const QRect rc(10,10,100,100); 0451 TestUtil::TestProgressBar proxy; 0452 0453 { 0454 KisSequentialConstIteratorProgress it (dev, rc, &proxy); 0455 0456 QCOMPARE(proxy.max(), rc.top() + rc.height()); 0457 QCOMPARE(proxy.value(), rc.top()); 0458 } 0459 0460 // on destruction, iterator automatically completes progress reporting 0461 QCOMPARE(proxy.max(), rc.top() + rc.height()); 0462 QCOMPARE(proxy.value(), proxy.max()); 0463 } 0464 0465 void KisIteratorNGTest::hLineIter() 0466 { 0467 allCsApplicator(&KisIteratorNGTest::hLineIter); 0468 } 0469 0470 void KisIteratorNGTest::justCreation() 0471 { 0472 allCsApplicator(&KisIteratorNGTest::justCreation); 0473 } 0474 0475 void KisIteratorNGTest::vLineIter() 0476 { 0477 allCsApplicator(&KisIteratorNGTest::vLineIter); 0478 } 0479 0480 void KisIteratorNGTest::randomAccessor() 0481 { 0482 allCsApplicator(&KisIteratorNGTest::randomAccessor); 0483 } 0484 0485 KISTEST_MAIN(KisIteratorNGTest)