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

0001 /*
0002  *  SPDX-FileCopyrightText: 2007 Sven Langkamp <sven.langkamp@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_painter_test.h"
0008 #include <simpletest.h>
0009 
0010 #include <kis_debug.h>
0011 #include <QRect>
0012 #include <QElapsedTimer>
0013 #include <QtXml>
0014 
0015 #include <KoChannelInfo.h>
0016 #include <KoColorSpace.h>
0017 #include <KoColorSpaceRegistry.h>
0018 #include <KoCompositeOpRegistry.h>
0019 
0020 #include "kis_datamanager.h"
0021 #include "kis_types.h"
0022 #include "kis_paint_device.h"
0023 #include "kis_painter.h"
0024 #include "kis_pixel_selection.h"
0025 #include "kis_fill_painter.h"
0026 #include <kis_fixed_paint_device.h>
0027 #include <testutil.h>
0028 #include <kis_iterator_ng.h>
0029 #include <testimage.h>
0030 
0031 void KisPainterTest::allCsApplicator(void (KisPainterTest::* funcPtr)(const KoColorSpace*cs))
0032 {
0033     qDebug() << qAppName();
0034 
0035     QList<const KoColorSpace*> colorspaces = KoColorSpaceRegistry::instance()->allColorSpaces(KoColorSpaceRegistry::AllColorSpaces, KoColorSpaceRegistry::OnlyDefaultProfile);
0036 
0037     Q_FOREACH (const KoColorSpace* cs, colorspaces) {
0038 
0039         QString csId = cs->id();
0040         // ALL THESE COLORSPACES ARE BROKEN: WE NEED UNITTESTS FOR COLORSPACES!
0041         if (csId.startsWith("KS")) continue;
0042         if (csId.startsWith("Xyz")) continue;
0043         if (csId.startsWith('Y')) continue;
0044         if (csId.contains("AF")) continue;
0045         if (csId == "GRAYU16") continue; // No point in testing bounds with a cs without alpha
0046         if (csId == "GRAYU8") continue; // No point in testing bounds with a cs without alpha
0047 
0048         dbgKrita << "Testing with cs" << csId;
0049 
0050         if (cs && cs->compositeOp(COMPOSITE_OVER) != 0) {
0051             (this->*funcPtr)(cs);
0052         } else {
0053             dbgKrita << "Cannot bitBlt for cs" << csId;
0054         }
0055     }
0056 }
0057 
0058 void KisPainterTest::testSimpleBlt(const KoColorSpace * cs)
0059 {
0060 
0061     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0062     KisPaintDeviceSP src = new KisPaintDevice(cs);
0063     KoColor c(Qt::red, cs);
0064     c.setOpacity(quint8(128));
0065     src->fill(20, 20, 20, 20, c.data());
0066 
0067     QCOMPARE(src->exactBounds(), QRect(20, 20, 20, 20));
0068 
0069     const KoCompositeOp* op;
0070 
0071     {
0072         op = cs->compositeOp(COMPOSITE_OVER);
0073         KisPainter painter(dst);
0074         painter.setCompositeOpId(op);
0075         painter.bitBlt(50, 50, src, 20, 20, 20, 20);
0076         painter.end();
0077         QCOMPARE(dst->exactBounds(), QRect(50,50,20,20));
0078     }
0079 
0080     dst->clear();
0081 
0082     {
0083         op = cs->compositeOp(COMPOSITE_COPY);
0084         KisPainter painter(dst);
0085         painter.setCompositeOpId(op);
0086         painter.bitBlt(50, 50, src, 20, 20, 20, 20);
0087         painter.end();
0088         QCOMPARE(dst->exactBounds(), QRect(50,50,20,20));
0089     }
0090 }
0091 
0092 void KisPainterTest::testSimpleBlt()
0093 {
0094     allCsApplicator(&KisPainterTest::testSimpleBlt);
0095 }
0096 
0097 /*
0098 
0099 Note: the bltSelection tests assume the following geometry:
0100 
0101 0,0               0,30
0102   +---------+------+
0103   |  10,10  |      |
0104   |    +----+      |
0105   |    |####|      |
0106   |    |####|      |
0107   +----+----+      |
0108   |       20,20    |
0109   |                |
0110   |                |
0111   +----------------+
0112                   30,30
0113  */
0114 void KisPainterTest::testPaintDeviceBltSelection(const KoColorSpace * cs)
0115 {
0116 
0117     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0118 
0119     KisPaintDeviceSP src = new KisPaintDevice(cs);
0120     KoColor c(Qt::red, cs);
0121     c.setOpacity(quint8(128));
0122     src->fill(0, 0, 20, 20, c.data());
0123 
0124     QCOMPARE(src->exactBounds(), QRect(0, 0, 20, 20));
0125 
0126     KisSelectionSP selection = new KisSelection();
0127     selection->pixelSelection()->select(QRect(10, 10, 20, 20));
0128     selection->updateProjection();
0129     QCOMPARE(selection->selectedExactRect(), QRect(10, 10, 20, 20));
0130 
0131     KisPainter painter(dst);
0132     painter.setSelection(selection);
0133 
0134     painter.bitBlt(0, 0, src, 0, 0, 30, 30);
0135     painter.end();
0136 
0137     QImage image = dst->convertToQImage(0);
0138     image.save("blt_Selection_" + cs->name() + ".png");
0139 
0140     QCOMPARE(dst->exactBounds(), QRect(10, 10, 10, 10));
0141 
0142     const KoCompositeOp* op = cs->compositeOp(COMPOSITE_SUBTRACT);
0143     if (op->id() == COMPOSITE_SUBTRACT) {
0144 
0145         KisPaintDeviceSP dst2 = new KisPaintDevice(cs);
0146         KisPainter painter2(dst2);
0147         painter2.setSelection(selection);
0148         painter2.setCompositeOpId(op);
0149         painter2.bitBlt(0, 0, src, 0, 0, 30, 30);
0150         painter2.end();
0151 
0152         QCOMPARE(dst2->exactBounds(), QRect(10, 10, 10, 10));
0153     }
0154 }
0155 
0156 void KisPainterTest::testPaintDeviceBltSelection()
0157 {
0158     allCsApplicator(&KisPainterTest::testPaintDeviceBltSelection);
0159 }
0160 
0161 void KisPainterTest::testPaintDeviceBltSelectionIrregular(const KoColorSpace * cs)
0162 {
0163 
0164     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0165     KisPaintDeviceSP src = new KisPaintDevice(cs);
0166     KisFillPainter gc(src);
0167     gc.fillRect(0, 0, 20, 20, KoColor(Qt::red, cs));
0168     gc.end();
0169 
0170     QCOMPARE(src->exactBounds(), QRect(0, 0, 20, 20));
0171 
0172     KisSelectionSP sel = new KisSelection();
0173 
0174     KisPixelSelectionSP psel = sel->pixelSelection();
0175     psel->select(QRect(10, 15, 20, 15));
0176     psel->select(QRect(15, 10, 15, 5));
0177 
0178     QCOMPARE(psel->selectedExactRect(), QRect(10, 10, 20, 20));
0179     QCOMPARE(TestUtil::alphaDevicePixel(psel, 13, 13), MIN_SELECTED);
0180 
0181     KisPainter painter(dst);
0182     painter.setSelection(sel);
0183     painter.bitBlt(0, 0, src, 0, 0, 30, 30);
0184     painter.end();
0185 
0186     QImage image = dst->convertToQImage(0);
0187     image.save("blt_Selection_irregular" + cs->name() + ".png");
0188 
0189     QCOMPARE(dst->exactBounds(), QRect(10, 10, 10, 10));
0190     Q_FOREACH (KoChannelInfo * channel, cs->channels()) {
0191         // Only compare alpha if there actually is an alpha channel in
0192         // this colorspace
0193         if (channel->channelType() == KoChannelInfo::ALPHA) {
0194             QColor c;
0195 
0196             dst->pixel(13, 13, &c);
0197 
0198             QCOMPARE((int) c.alpha(), (int) OPACITY_TRANSPARENT_U8);
0199         }
0200     }
0201 }
0202 
0203 
0204 void KisPainterTest::testPaintDeviceBltSelectionIrregular()
0205 {
0206     allCsApplicator(&KisPainterTest::testPaintDeviceBltSelectionIrregular);
0207 }
0208 
0209 void KisPainterTest::testPaintDeviceBltSelectionInverted(const KoColorSpace * cs)
0210 {
0211 
0212     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0213     KisPaintDeviceSP src = new KisPaintDevice(cs);
0214     KisFillPainter gc(src);
0215     gc.fillRect(0, 0, 30, 30, KoColor(Qt::red, cs));
0216     gc.end();
0217     QCOMPARE(src->exactBounds(), QRect(0, 0, 30, 30));
0218 
0219     KisSelectionSP sel = new KisSelection();
0220     KisPixelSelectionSP psel = sel->pixelSelection();
0221     psel->select(QRect(10, 10, 20, 20));
0222     psel->invert();
0223     sel->updateProjection();
0224 
0225     KisPainter painter(dst);
0226     painter.setSelection(sel);
0227     painter.bitBlt(0, 0, src, 0, 0, 30, 30);
0228     painter.end();
0229     QCOMPARE(dst->exactBounds(), QRect(0, 0, 30, 30));
0230 }
0231 
0232 void KisPainterTest::testPaintDeviceBltSelectionInverted()
0233 {
0234     allCsApplicator(&KisPainterTest::testPaintDeviceBltSelectionInverted);
0235 }
0236 
0237 
0238 void KisPainterTest::testSelectionBltSelection()
0239 {
0240     KisPixelSelectionSP src = new KisPixelSelection();
0241     src->select(QRect(0, 0, 20, 20));
0242     QCOMPARE(src->selectedExactRect(), QRect(0, 0, 20, 20));
0243 
0244     KisSelectionSP sel = new KisSelection();
0245 
0246     KisPixelSelectionSP Selection = sel->pixelSelection();
0247     Selection->select(QRect(10, 10, 20, 20));
0248     QCOMPARE(Selection->selectedExactRect(), QRect(10, 10, 20, 20));
0249 
0250     sel->updateProjection();
0251     KisPixelSelectionSP dst = new KisPixelSelection();
0252     KisPainter painter(dst);
0253     painter.setSelection(sel);
0254     painter.bitBlt(0, 0, src, 0, 0, 30, 30);
0255     painter.end();
0256 
0257     QCOMPARE(dst->selectedExactRect(), QRect(10, 10, 10, 10));
0258 
0259     KisSequentialConstIterator it(dst, QRect(10, 10, 10, 10));
0260     while (it.nextPixel()) {
0261         // These are selections, so only one channel and it should
0262         // be totally selected
0263         QCOMPARE(it.oldRawData()[0], MAX_SELECTED);
0264     }
0265 }
0266 
0267 /*
0268 
0269 Test with non-square selection
0270 
0271 0,0               0,30
0272   +-----------+------+
0273   |    13,13  |      |
0274   |      x +--+      |
0275   |     +--+##|      |
0276   |     |#####|      |
0277   +-----+-----+      |
0278   |         20,20    |
0279   |                  |
0280   |                  |
0281   +------------------+
0282                   30,30
0283  */
0284 void KisPainterTest::testSelectionBltSelectionIrregular()
0285 {
0286 
0287     KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
0288 
0289     KisPixelSelectionSP src = new KisPixelSelection();
0290     src->select(QRect(0, 0, 20, 20));
0291     QCOMPARE(src->selectedExactRect(), QRect(0, 0, 20, 20));
0292 
0293     KisSelectionSP sel = new KisSelection();
0294 
0295     KisPixelSelectionSP Selection = sel->pixelSelection();
0296     Selection->select(QRect(10, 15, 20, 15));
0297     Selection->select(QRect(15, 10, 15, 5));
0298     QCOMPARE(Selection->selectedExactRect(), QRect(10, 10, 20, 20));
0299     QCOMPARE(TestUtil::alphaDevicePixel(Selection, 13, 13), MIN_SELECTED);
0300 
0301     sel->updateProjection();
0302 
0303     KisPixelSelectionSP dst = new KisPixelSelection();
0304     KisPainter painter(dst);
0305     painter.setSelection(sel);
0306     painter.bitBlt(0, 0, src, 0, 0, 30, 30);
0307     painter.end();
0308 
0309     QCOMPARE(dst->selectedExactRect(), QRect(10, 10, 10, 10));
0310     QCOMPARE(TestUtil::alphaDevicePixel(dst, 13, 13), MIN_SELECTED);
0311 }
0312 
0313 void KisPainterTest::testSelectionBitBltFixedSelection()
0314 {
0315     const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8();
0316     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0317 
0318     KisPaintDeviceSP src = new KisPaintDevice(cs);
0319     KoColor c(Qt::red, cs);
0320     c.setOpacity(quint8(128));
0321     src->fill(0, 0, 20, 20, c.data());
0322 
0323     QCOMPARE(src->exactBounds(), QRect(0, 0, 20, 20));
0324 
0325     KisFixedPaintDeviceSP fixedSelection = new KisFixedPaintDevice(cs);
0326     fixedSelection->setRect(QRect(0, 0, 20, 20));
0327     fixedSelection->initialize();
0328     KoColor fill(Qt::white, cs);
0329     fixedSelection->fill(5, 5, 10, 10, fill.data());
0330     fixedSelection->convertTo(KoColorSpaceRegistry::instance()->alpha8());
0331 
0332     KisPainter painter(dst);
0333 
0334     painter.bitBltWithFixedSelection(0, 0, src, fixedSelection, 20, 20);
0335     painter.end();
0336 
0337     QCOMPARE(dst->exactBounds(), QRect(5, 5, 10, 10));
0338     /*
0339 dbgKrita << "canary1.5";
0340     dst->clear();
0341     painter.begin(dst);
0342 
0343     painter.bitBltWithFixedSelection(0, 0, src, fixedSelection, 10, 20);
0344     painter.end();
0345 dbgKrita << "canary2";
0346     QCOMPARE(dst->exactBounds(), QRect(5, 5, 5, 10));
0347 
0348     dst->clear();
0349     painter.begin(dst);
0350 
0351     painter.bitBltWithFixedSelection(0, 0, src, fixedSelection, 5, 5, 5, 5, 10, 20);
0352     painter.end();
0353 dbgKrita << "canary3";
0354     QCOMPARE(dst->exactBounds(), QRect(5, 5, 5, 10));
0355 
0356     dst->clear();
0357     painter.begin(dst);
0358 
0359     painter.bitBltWithFixedSelection(5, 5, src, fixedSelection, 10, 20);
0360     painter.end();
0361 dbgKrita << "canary4";
0362     QCOMPARE(dst->exactBounds(), QRect(10, 10, 5, 10));
0363     */
0364 }
0365 
0366 void KisPainterTest::testSelectionBitBltEraseCompositeOp()
0367 {
0368     const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8();
0369     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0370     KoColor c(Qt::red, cs);
0371     dst->fill(0, 0, 150, 150, c.data());
0372 
0373     KisPaintDeviceSP src = new KisPaintDevice(cs);
0374     KoColor c2(Qt::black, cs);
0375     src->fill(50, 50, 50, 50, c2.data());
0376 
0377     KisSelectionSP sel = new KisSelection();
0378     KisPixelSelectionSP selection = sel->pixelSelection();
0379     selection->select(QRect(25, 25, 100, 100));
0380     sel->updateProjection();
0381 
0382     const KoCompositeOp* op = cs->compositeOp(COMPOSITE_ERASE);
0383     KisPainter painter(dst);
0384     painter.setSelection(sel);
0385     painter.setCompositeOpId(op);
0386     painter.bitBlt(0, 0, src, 0, 0, 150, 150);
0387     painter.end();
0388 
0389     //dst->convertToQImage(0).save("result.png");
0390 
0391     QRect erasedRect(50, 50, 50, 50);
0392     KisSequentialConstIterator it(dst, QRect(0, 0, 150, 150));
0393     while (it.nextPixel()) {
0394         if(!erasedRect.contains(it.x(), it.y())) {
0395              QVERIFY(memcmp(it.oldRawData(), c.data(), cs->pixelSize()) == 0);
0396         }
0397     }
0398 
0399 }
0400 
0401 void KisPainterTest::testSimpleAlphaCopy()
0402 {
0403     KisPaintDeviceSP src = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
0404     KisPaintDeviceSP dst = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
0405     quint8 p = 128;
0406     src->fill(0, 0, 100, 100, &p);
0407     QVERIFY(src->exactBounds() == QRect(0, 0, 100, 100));
0408     KisPainter gc(dst);
0409     gc.setCompositeOpId(KoColorSpaceRegistry::instance()->alpha8()->compositeOp(COMPOSITE_COPY));
0410     gc.bitBlt(QPoint(0, 0), src, src->exactBounds());
0411     gc.end();
0412     QCOMPARE(dst->exactBounds(), QRect(0, 0, 100, 100));
0413 
0414 }
0415 
0416 void KisPainterTest::checkPerformance()
0417 {
0418     KisPaintDeviceSP src = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
0419     KisPaintDeviceSP dst = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
0420     quint8 p = 128;
0421     src->fill(0, 0, 10000, 5000, &p);
0422     KisSelectionSP sel = new KisSelection();
0423     sel->pixelSelection()->select(QRect(0, 0, 10000, 5000), 128);
0424     sel->updateProjection();
0425 
0426     QElapsedTimer t;
0427     t.start();
0428     for (int i = 0; i < 10; ++i) {
0429         KisPainter gc(dst);
0430         gc.bitBlt(0, 0, src, 0, 0, 10000, 5000);
0431     }
0432 
0433     t.restart();
0434     for (int i = 0; i < 10; ++i) {
0435         KisPainter gc(dst, sel);
0436         gc.bitBlt(0, 0, src, 0, 0, 10000, 5000);
0437     }
0438 }
0439 
0440 void KisPainterTest::testBitBltOldData()
0441 {
0442     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->alpha8();
0443 
0444     KisPaintDeviceSP src = new KisPaintDevice(cs);
0445     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0446 
0447     quint8 defaultPixel = 0;
0448     quint8 p1 = 128;
0449     quint8 p2 = 129;
0450     quint8 p3 = 130;
0451     KoColor defaultColor(&defaultPixel, cs);
0452     KoColor color1(&p1, cs);
0453     KoColor color2(&p2, cs);
0454     KoColor color3(&p3, cs);
0455     QRect fillRect(0,0,5000,5000);
0456 
0457     src->fill(fillRect, color1);
0458 
0459     KisPainter srcGc(src);
0460     srcGc.beginTransaction();
0461     src->fill(fillRect, color2);
0462 
0463     KisPainter dstGc(dst);
0464     dstGc.bitBltOldData(QPoint(), src, fillRect);
0465 
0466     QVERIFY(TestUtil::checkAlphaDeviceFilledWithPixel(dst, fillRect, p1));
0467 
0468     dstGc.end();
0469     srcGc.deleteTransaction();
0470 }
0471 
0472 #include "kis_paint_device_debug_utils.h"
0473 #include "KisRenderedDab.h"
0474 
0475 void testMassiveBltFixedImpl(int numRects, bool varyOpacity = false, bool useSelection = false)
0476 {
0477     const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8();
0478     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0479 
0480     QList<QColor> colors;
0481     colors << Qt::red;
0482     colors << Qt::green;
0483     colors << Qt::blue;
0484 
0485     QRect devicesRect;
0486     QList<KisRenderedDab> devices;
0487 
0488     for (int i = 0; i < numRects; i++) {
0489         const QRect rc(10 + i * 10, 10 + i * 10, 30, 30);
0490         KisFixedPaintDeviceSP dev = new KisFixedPaintDevice(cs);
0491         dev->setRect(rc);
0492         dev->initialize();
0493         dev->fill(rc, KoColor(colors[i % 3], cs));
0494         dev->fill(kisGrowRect(rc, -5), KoColor(Qt::white, cs));
0495 
0496         KisRenderedDab dab;
0497         dab.device = dev;
0498         dab.offset = dev->bounds().topLeft();
0499         dab.opacity = varyOpacity ? qreal(1 + i) / numRects : 1.0;
0500         dab.flow = 1.0;
0501 
0502         devices << dab;
0503         devicesRect |= rc;
0504     }
0505 
0506     KisSelectionSP selection;
0507 
0508     if (useSelection) {
0509         selection = new KisSelection();
0510         selection->pixelSelection()->select(kisGrowRect(devicesRect, -7));
0511     }
0512 
0513     const QString opacityPostfix = varyOpacity ? "_varyop" : "";
0514     const QString selectionPostfix = useSelection ? "_sel" : "";
0515 
0516     const QRect fullRect = kisGrowRect(devicesRect, 10);
0517 
0518     {
0519         KisPainter painter(dst);
0520         painter.setSelection(selection);
0521         painter.bltFixed(fullRect, devices);
0522         painter.end();
0523         QVERIFY(TestUtil::checkQImage(dst->convertToQImage(0, fullRect),
0524                                       "kispainter_test",
0525                                       "massive_bitblt",
0526                                       QString("full_update_%1%2%3")
0527                                           .arg(numRects)
0528                                           .arg(opacityPostfix)
0529                                           .arg(selectionPostfix), 2, 2));
0530     }
0531 
0532     dst->clear();
0533 
0534     {
0535         KisPainter painter(dst);
0536         painter.setSelection(selection);
0537 
0538         for (int i = fullRect.x(); i <= fullRect.center().x(); i += 10) {
0539             const QRect rc(i, fullRect.y(), 10, fullRect.height());
0540             painter.bltFixed(rc, devices);
0541         }
0542 
0543         painter.end();
0544 
0545         QVERIFY(TestUtil::checkQImage(dst->convertToQImage(0, fullRect),
0546                                       "kispainter_test",
0547                                       "massive_bitblt",
0548                                       QString("partial_update_%1%2%3")
0549                                           .arg(numRects)
0550                                           .arg(opacityPostfix)
0551                                           .arg(selectionPostfix), 2, 2));
0552 
0553     }
0554 }
0555 
0556 void KisPainterTest::testMassiveBltFixedSingleTile()
0557 {
0558     testMassiveBltFixedImpl(3);
0559 }
0560 
0561 void KisPainterTest::testMassiveBltFixedMultiTile()
0562 {
0563     testMassiveBltFixedImpl(6);
0564 }
0565 
0566 void KisPainterTest::testMassiveBltFixedMultiTileWithOpacity()
0567 {
0568     testMassiveBltFixedImpl(6, true);
0569 }
0570 
0571 void KisPainterTest::testMassiveBltFixedMultiTileWithSelection()
0572 {
0573     testMassiveBltFixedImpl(6, false, true);
0574 }
0575 
0576 void KisPainterTest::testMassiveBltFixedCornerCases()
0577 {
0578     const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8();
0579     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0580 
0581     QList<KisRenderedDab> devices;
0582 
0583     QVERIFY(dst->extent().isEmpty());
0584 
0585     {
0586         // empty devices, shouldn't crash
0587         KisPainter painter(dst);
0588         painter.bltFixed(QRect(60,60,20,20), devices);
0589         painter.end();
0590     }
0591 
0592     QVERIFY(dst->extent().isEmpty());
0593 
0594     const QRect rc(10,10,20,20);
0595     KisFixedPaintDeviceSP dev = new KisFixedPaintDevice(cs);
0596     dev->setRect(rc);
0597     dev->initialize();
0598     dev->fill(rc, KoColor(Qt::white, cs));
0599 
0600     devices.append(KisRenderedDab(dev));
0601 
0602     {
0603         // rect outside the devices bounds, shouldn't crash
0604         KisPainter painter(dst);
0605         painter.bltFixed(QRect(60,60,20,20), devices);
0606         painter.end();
0607     }
0608 
0609     QVERIFY(dst->extent().isEmpty());
0610 }
0611 
0612 
0613 #include "kis_lod_transform.h"
0614 
0615 inline QRect extentifyRect(const QRect &rc)
0616 {
0617     return KisLodTransform::alignedRect(rc, 6);
0618 }
0619 
0620 void testOptimizedCopyingImpl(const QRect &srcRect,
0621                               const QRect &dstRect,
0622                               const QRect &srcCopyRect,
0623                               const QPoint &dstPt,
0624                               const QRect &expectedDstBounds)
0625 {
0626     const QRect expectedDstExtent = extentifyRect(expectedDstBounds);
0627 
0628     const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8();
0629     KisPaintDeviceSP src = new KisPaintDevice(cs);
0630     KisPaintDeviceSP dst = new KisPaintDevice(cs);
0631 
0632     const KoColor color1(Qt::red, cs);
0633     const KoColor color2(Qt::blue, cs);
0634 
0635     src->fill(srcRect, color1);
0636     dst->fill(dstRect, color2);
0637 
0638     KisPainter::copyAreaOptimized(dstPt, src, dst, srcCopyRect);
0639 
0640     //KIS_DUMP_DEVICE_2(dst, QRect(0,0,5000,5000), "dst", "dd");
0641 
0642     QCOMPARE(dst->exactBounds(), expectedDstBounds);
0643     QCOMPARE(dst->extent(), expectedDstExtent);
0644 }
0645 
0646 void KisPainterTest::testOptimizedCopying()
0647 {
0648     const QRect srcRect(1000, 1000, 1000, 1000);
0649     const QRect srcCopyRect(0, 0, 5000, 5000);
0650 
0651 
0652     testOptimizedCopyingImpl(srcRect, QRect(6000, 500, 1000,1000),
0653                              srcCopyRect, srcCopyRect.topLeft(),
0654                              QRect(1000, 500, 6000, 1500));
0655 
0656     testOptimizedCopyingImpl(srcRect, QRect(4500, 1500, 1000, 1000),
0657                              srcCopyRect, srcCopyRect.topLeft(),
0658                              QRect(1000, 1000, 4500, 1500));
0659 
0660     testOptimizedCopyingImpl(srcRect, QRect(2500, 2500, 1000, 1000),
0661                              srcCopyRect, srcCopyRect.topLeft(),
0662                              srcRect);
0663 
0664     testOptimizedCopyingImpl(srcRect, QRect(1200, 1200, 600, 1600),
0665                              srcCopyRect, srcCopyRect.topLeft(),
0666                              srcRect);
0667 
0668     testOptimizedCopyingImpl(srcRect, QRect(1200, 1200, 600, 600),
0669                              srcCopyRect, srcCopyRect.topLeft(),
0670                              srcRect);
0671 
0672 }
0673 
0674 KISTEST_MAIN(KisPainterTest)
0675 
0676