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

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_scanline_fill_test.h"
0008 
0009 #include <testutil.h>
0010 
0011 #include <simpletest.h>
0012 #include <floodfill/kis_scanline_fill.h>
0013 #include <floodfill/kis_fill_interval.h>
0014 #include <floodfill/kis_fill_interval_map.h>
0015 
0016 #include <KoColor.h>
0017 #include <KoColorSpace.h>
0018 #include <KoColorSpaceRegistry.h>
0019 #include "kis_types.h"
0020 #include "kis_paint_device.h"
0021 
0022 
0023 void KisScanlineFillTest::testFillGeneral(const QVector<KisFillInterval> &initialBackwardIntervals,
0024                                           const QVector<QColor> &expectedResult,
0025                                           const QVector<KisFillInterval> &expectedForwardIntervals,
0026                                           const QVector<KisFillInterval> &expectedBackwardIntervals)
0027 {
0028     const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
0029     KisPaintDeviceSP dev = new KisPaintDevice(cs);
0030 
0031     dev->setPixel(1, 0, Qt::white);
0032     dev->setPixel(2, 0, Qt::white);
0033     dev->setPixel(5, 0, Qt::white);
0034     dev->setPixel(8, 0, Qt::white);
0035     dev->setPixel(17, 0, Qt::white);
0036 
0037     QRect boundingRect(-10, -10, 30, 30);
0038 
0039     KisScanlineFill gc(dev, QPoint(), boundingRect);
0040 
0041     KisFillIntervalMap *backwardMap = gc.testingGetBackwardIntervals();
0042     Q_FOREACH (const KisFillInterval &i, initialBackwardIntervals) {
0043         backwardMap->insertInterval(i);
0044     }
0045 
0046     KisFillInterval processInterval(0,10,0);
0047     gc.testingProcessLine(processInterval);
0048 
0049     Q_ASSERT(expectedResult.size() == processInterval.width());
0050 
0051     for (int i = 0; i < 11; i++) {
0052         QColor c;
0053         dev->pixel(i, 0, &c);
0054         dbgKrita << i << ":" << c.red();
0055 
0056         QCOMPARE(c, expectedResult[i]);
0057     }
0058 
0059     QVector<KisFillInterval> forwardIntervals =
0060         gc.testingGetForwardIntervals();
0061 
0062     for (int i = 0; i < forwardIntervals.size(); i++) {
0063         dbgKrita << "FW:" << forwardIntervals[i];
0064         QCOMPARE(forwardIntervals[i], expectedForwardIntervals[i]);
0065     }
0066     QCOMPARE(forwardIntervals.size(), expectedForwardIntervals.size());
0067 
0068 
0069     QStack<KisFillInterval> backwardIntervals =
0070         gc.testingGetBackwardIntervals()->fetchAllIntervals();
0071 
0072     for (int i = 0; i < backwardIntervals.size(); i++) {
0073         dbgKrita << "BW:" << backwardIntervals[i];
0074         QCOMPARE(backwardIntervals[i], expectedBackwardIntervals[i]);
0075     }
0076     QCOMPARE(backwardIntervals.size(), expectedBackwardIntervals.size());
0077 }
0078 
0079 inline QColor testingColor(quint8 c) {
0080     return QColor(c, c, c, c);
0081 }
0082 
0083 void KisScanlineFillTest::testSimpleFill()
0084 {
0085     QVector<KisFillInterval> initialBackwardIntervals;
0086     QVector<QColor> expectedResult;
0087     expectedResult << testingColor(200); //  0
0088     expectedResult << testingColor(255); //  1
0089     expectedResult << testingColor(255); //  2
0090     expectedResult << testingColor(200); //  3
0091     expectedResult << testingColor(200); //  4
0092     expectedResult << testingColor(255); //  5
0093     expectedResult << testingColor(200); //  6
0094     expectedResult << testingColor(200); //  7
0095     expectedResult << testingColor(255); //  8
0096     expectedResult << testingColor(200); //  9
0097     expectedResult << testingColor(200); // 10
0098 
0099     QVector<KisFillInterval> expectedForwardIntervals;
0100     expectedForwardIntervals << KisFillInterval(-10,  0, 1);
0101     expectedForwardIntervals << KisFillInterval(3,  4, 1);
0102     expectedForwardIntervals << KisFillInterval(6,  7, 1);
0103     expectedForwardIntervals << KisFillInterval(9, 16, 1);
0104 
0105     QVector<KisFillInterval> expectedBackwardIntervals;
0106     expectedBackwardIntervals << KisFillInterval(-10,  -1, 0);
0107     expectedBackwardIntervals << KisFillInterval(11, 16, 0);
0108 
0109     testFillGeneral(initialBackwardIntervals,
0110                     expectedResult,
0111                     expectedForwardIntervals,
0112                     expectedBackwardIntervals);
0113 }
0114 
0115 void KisScanlineFillTest::testFillBackwardCollisionOnTheLeft()
0116 {
0117     QVector<KisFillInterval> initialBackwardIntervals;
0118     initialBackwardIntervals << KisFillInterval(-10,  0, 0);
0119 
0120     QVector<QColor> expectedResult;
0121     expectedResult << testingColor(  0); //  0
0122     expectedResult << testingColor(255); //  1
0123     expectedResult << testingColor(255); //  2
0124     expectedResult << testingColor(200); //  3
0125     expectedResult << testingColor(200); //  4
0126     expectedResult << testingColor(255); //  5
0127     expectedResult << testingColor(200); //  6
0128     expectedResult << testingColor(200); //  7
0129     expectedResult << testingColor(255); //  8
0130     expectedResult << testingColor(200); //  9
0131     expectedResult << testingColor(200); // 10
0132 
0133     QVector<KisFillInterval> expectedForwardIntervals;
0134     expectedForwardIntervals << KisFillInterval(3,  4, 1);
0135     expectedForwardIntervals << KisFillInterval(6,  7, 1);
0136     expectedForwardIntervals << KisFillInterval(9, 16, 1);
0137 
0138     QVector<KisFillInterval> expectedBackwardIntervals;
0139     expectedBackwardIntervals << KisFillInterval(-10,  -1, 0);
0140     expectedBackwardIntervals << KisFillInterval(11, 16, 0);
0141 
0142 
0143     testFillGeneral(initialBackwardIntervals,
0144                     expectedResult,
0145                     expectedForwardIntervals,
0146                     expectedBackwardIntervals);
0147 }
0148 
0149 void KisScanlineFillTest::testFillBackwardCollisionOnTheRight()
0150 {
0151     QVector<KisFillInterval> initialBackwardIntervals;
0152     initialBackwardIntervals << KisFillInterval(9, 20, 0);
0153 
0154     QVector<QColor> expectedResult;
0155     expectedResult << testingColor(200); //  0
0156     expectedResult << testingColor(255); //  1
0157     expectedResult << testingColor(255); //  2
0158     expectedResult << testingColor(200); //  3
0159     expectedResult << testingColor(200); //  4
0160     expectedResult << testingColor(255); //  5
0161     expectedResult << testingColor(200); //  6
0162     expectedResult << testingColor(200); //  7
0163     expectedResult << testingColor(255); //  8
0164     expectedResult << testingColor(  0); //  9
0165     expectedResult << testingColor(  0); // 10
0166 
0167     QVector<KisFillInterval> expectedForwardIntervals;
0168     expectedForwardIntervals << KisFillInterval(-10,  0, 1);
0169     expectedForwardIntervals << KisFillInterval(3,  4, 1);
0170     expectedForwardIntervals << KisFillInterval(6,  7, 1);
0171 
0172     QVector<KisFillInterval> expectedBackwardIntervals;
0173     expectedBackwardIntervals << KisFillInterval(-10,  -1, 0);
0174     expectedBackwardIntervals << KisFillInterval(11, 20, 0);
0175 
0176     testFillGeneral(initialBackwardIntervals,
0177                     expectedResult,
0178                     expectedForwardIntervals,
0179                     expectedBackwardIntervals);
0180 }
0181 
0182 void KisScanlineFillTest::testFillBackwardCollisionFull()
0183 {
0184     QVector<KisFillInterval> initialBackwardIntervals;
0185     initialBackwardIntervals << KisFillInterval(-10, 20, 0);
0186 
0187     QVector<QColor> expectedResult;
0188     expectedResult << testingColor(  0); //  0
0189     expectedResult << testingColor(255); //  1
0190     expectedResult << testingColor(255); //  2
0191     expectedResult << testingColor(  0); //  3
0192     expectedResult << testingColor(  0); //  4
0193     expectedResult << testingColor(255); //  5
0194     expectedResult << testingColor(  0); //  6
0195     expectedResult << testingColor(  0); //  7
0196     expectedResult << testingColor(255); //  8
0197     expectedResult << testingColor(  0); //  9
0198     expectedResult << testingColor(  0); // 10
0199 
0200     QVector<KisFillInterval> expectedForwardIntervals;
0201 
0202     QVector<KisFillInterval> expectedBackwardIntervals;
0203     expectedBackwardIntervals << KisFillInterval(-10, -1, 0);
0204     expectedBackwardIntervals << KisFillInterval(11, 20, 0);
0205 
0206     testFillGeneral(initialBackwardIntervals,
0207                     expectedResult,
0208                     expectedForwardIntervals,
0209                     expectedBackwardIntervals);
0210 }
0211 
0212 void KisScanlineFillTest::testFillBackwardCollisionSanityCheck()
0213 {
0214 #if defined ENABLE_FILL_SANITY_CHECKS && defined ENABLE_CHECKS_FOR_TESTING
0215     QVector<KisFillInterval> initialBackwardIntervals;
0216     initialBackwardIntervals << KisFillInterval(0, 10, 0);
0217 
0218     QVector<QColor> expectedResult;
0219     QVector<KisFillInterval> expectedForwardIntervals;
0220     QVector<KisFillInterval> expectedBackwardIntervals;
0221     expectedBackwardIntervals << KisFillInterval(0, 10, 0);
0222 
0223     bool gotException = false;
0224 
0225     try {
0226         testFillGeneral(initialBackwardIntervals,
0227                         expectedResult,
0228                         expectedForwardIntervals,
0229                         expectedBackwardIntervals);
0230     } catch (...) {
0231         gotException = true;
0232     }
0233 
0234     QVERIFY(gotException);
0235 #endif /* ENABLE_FILL_SANITY_CHECKS */
0236 }
0237 
0238 void KisScanlineFillTest::testClearNonZeroComponent()
0239 {
0240     const QRect rc1(10, 10, 10, 10);
0241     const QRect rc2(30, 10, 10, 10);
0242     const QRect boundingRect(0,0,100,100);
0243 
0244     KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
0245 
0246     dev->fill(rc1, KoColor(Qt::red, dev->colorSpace()));
0247     dev->fill(rc2, KoColor(Qt::green, dev->colorSpace()));
0248 
0249     QCOMPARE(dev->exactBounds(), rc1 | rc2);
0250 
0251     KisScanlineFill fill(dev, QPoint(10,10), boundingRect);
0252     fill.clearNonZeroComponent();
0253 
0254     QCOMPARE(dev->exactBounds(), rc2);
0255 }
0256 
0257 void KisScanlineFillTest::testExternalFill()
0258 {
0259     const QRect rc1(10, 10, 10, 10);
0260     const QRect rc2(30, 10, 10, 10);
0261     const QRect boundingRect(0,0,100,100);
0262 
0263     KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
0264     KisPaintDeviceSP other = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
0265 
0266     dev->fill(rc1, KoColor(Qt::red, dev->colorSpace()));
0267     dev->fill(rc2, KoColor(Qt::green, dev->colorSpace()));
0268 
0269     QCOMPARE(dev->exactBounds(), rc1 | rc2);
0270 
0271     KisScanlineFill fill(dev, QPoint(10,10), boundingRect);
0272     fill.fill(KoColor(Qt::blue, dev->colorSpace()), other);
0273 
0274     QCOMPARE(dev->exactBounds(), rc1 | rc2);
0275     QCOMPARE(other->exactBounds(), rc1);
0276 
0277     QColor c;
0278 
0279     dev->pixel(10, 10, &c);
0280     QCOMPARE(c, QColor(Qt::red));
0281 
0282     other->pixel(10, 10, &c);
0283     QCOMPARE(c, QColor(Qt::blue));
0284 }
0285 
0286 SIMPLE_TEST_MAIN(KisScanlineFillTest)