util/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtTest/QtTest>
       
    43 #include <QtGui/qgraphicseffect.h>
       
    44 #include <QtGui/qgraphicsview.h>
       
    45 #include <QtGui/qgraphicsscene.h>
       
    46 #include <QtGui/qgraphicsitem.h>
       
    47 #include <QtGui/qstyleoption.h>
       
    48 
       
    49 #include <private/qgraphicseffect_p.h>
       
    50 
       
    51 //TESTED_CLASS=
       
    52 //TESTED_FILES=
       
    53 
       
    54 class CustomItem : public QGraphicsRectItem
       
    55 {
       
    56 public:
       
    57     CustomItem(qreal x, qreal y, qreal width, qreal height)
       
    58         : QGraphicsRectItem(x, y, width, height), numRepaints(0),
       
    59           m_painter(0)
       
    60     {}
       
    61 
       
    62     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
       
    63     {
       
    64         m_painter = painter;
       
    65         ++numRepaints;
       
    66         QGraphicsRectItem::paint(painter, option, widget);
       
    67     }
       
    68 
       
    69     void reset()
       
    70     {
       
    71         numRepaints = 0;
       
    72         m_painter = 0;
       
    73     }
       
    74 
       
    75     int numRepaints;
       
    76     QPainter *m_painter;
       
    77 };
       
    78 
       
    79 class CustomEffect : public QGraphicsEffect
       
    80 {
       
    81 public:
       
    82     CustomEffect()
       
    83         : QGraphicsEffect(), numRepaints(0), m_margin(10), m_sourceChanged(false),
       
    84           m_sourceBoundingRectChanged(false), doNothingInDraw(false),
       
    85           storeDeviceDependentStuff(false),
       
    86           m_painter(0), m_source(0)
       
    87     {}
       
    88 
       
    89     QRectF boundingRectFor(const QRectF &rect) const
       
    90     { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); }
       
    91 
       
    92     void reset()
       
    93     {
       
    94         numRepaints = 0;
       
    95         m_sourceChanged = false;
       
    96         m_sourceBoundingRectChanged = false;
       
    97         m_painter = 0;
       
    98         m_source = 0;
       
    99         deviceCoordinatesPixmap = QPixmap();
       
   100         deviceRect = QRect();
       
   101         sourceDeviceBoundingRect = QRectF();
       
   102     }
       
   103 
       
   104     void setMargin(int margin)
       
   105     {
       
   106         m_margin = margin;
       
   107         updateBoundingRect();
       
   108     }
       
   109 
       
   110     int margin() const
       
   111     { return m_margin; }
       
   112 
       
   113     void draw(QPainter *painter)
       
   114     {
       
   115         ++numRepaints;
       
   116         if (storeDeviceDependentStuff) {
       
   117             deviceCoordinatesPixmap = source()->pixmap(Qt::DeviceCoordinates);
       
   118             deviceRect = QRect(0, 0, painter->device()->width(), painter->device()->height());
       
   119             sourceDeviceBoundingRect = source()->boundingRect(Qt::DeviceCoordinates);
       
   120         }
       
   121         if (doNothingInDraw)
       
   122             return;
       
   123         m_source = source();
       
   124         m_painter = painter;
       
   125         source()->draw(painter);
       
   126     }
       
   127 
       
   128     void sourceChanged()
       
   129     { m_sourceChanged = true; }
       
   130 
       
   131     void sourceBoundingRectChanged()
       
   132     { m_sourceBoundingRectChanged = true; }
       
   133 
       
   134     int numRepaints;
       
   135     int m_margin;
       
   136     bool m_sourceChanged;
       
   137     bool m_sourceBoundingRectChanged;
       
   138     bool doNothingInDraw;
       
   139     bool storeDeviceDependentStuff;
       
   140     QPainter *m_painter;
       
   141     QGraphicsEffectSource *m_source;
       
   142     QPixmap deviceCoordinatesPixmap;
       
   143     QRect deviceRect;
       
   144     QRectF sourceDeviceBoundingRect;
       
   145 };
       
   146 
       
   147 class tst_QGraphicsEffectSource : public QObject
       
   148 {
       
   149     Q_OBJECT
       
   150 public slots:
       
   151     void initTestCase();
       
   152     void cleanupTestCase();
       
   153     void init();
       
   154 
       
   155 private slots:
       
   156     void graphicsItem();
       
   157     void styleOption();
       
   158     void isPixmap();
       
   159     void draw();
       
   160     void update();
       
   161     void boundingRect();
       
   162     void deviceRect();
       
   163     void pixmap();
       
   164 
       
   165     void pixmapPadding_data();
       
   166     void pixmapPadding();
       
   167 
       
   168 private:
       
   169     QGraphicsView *view;
       
   170     QGraphicsScene *scene;
       
   171     CustomItem *item;
       
   172     CustomEffect *effect;
       
   173 };
       
   174 
       
   175 void tst_QGraphicsEffectSource::initTestCase()
       
   176 {
       
   177     scene = new QGraphicsScene;
       
   178     item = new CustomItem(0, 0, 100, 100);
       
   179     effect = new CustomEffect;
       
   180     item->setGraphicsEffect(effect);
       
   181     scene->addItem(item);
       
   182     view = new QGraphicsView(scene);
       
   183     view->show();
       
   184 #ifdef Q_WS_X11
       
   185     qt_x11_wait_for_window_manager(view);
       
   186 #endif
       
   187     QTest::qWait(200);
       
   188 }
       
   189 
       
   190 void tst_QGraphicsEffectSource::cleanupTestCase()
       
   191 {
       
   192     delete view;
       
   193 }
       
   194 
       
   195 void tst_QGraphicsEffectSource::init()
       
   196 {
       
   197     QVERIFY(effect);
       
   198     QVERIFY(item);
       
   199     QVERIFY(effect->source());
       
   200     effect->reset();
       
   201     effect->storeDeviceDependentStuff = false;
       
   202     effect->doNothingInDraw = false;
       
   203     item->reset();
       
   204 }
       
   205 
       
   206 void tst_QGraphicsEffectSource::graphicsItem()
       
   207 {
       
   208     QVERIFY(effect->source());
       
   209     QCOMPARE(effect->source()->graphicsItem(), item);
       
   210 }
       
   211 
       
   212 void tst_QGraphicsEffectSource::styleOption()
       
   213 {
       
   214     // We don't have style options unless the source is drawing.
       
   215     QVERIFY(effect->source());
       
   216     QVERIFY(!effect->source()->styleOption());
       
   217 
       
   218     // Trigger an update and check that the style option in QGraphicsEffect::draw
       
   219     // was the same as the one in QGraphicsItem::paint.
       
   220     QCOMPARE(item->numRepaints, 0);
       
   221     QCOMPARE(effect->numRepaints, 0);
       
   222     item->update();
       
   223     QTest::qWait(50);
       
   224     QCOMPARE(item->numRepaints, 1);
       
   225     QCOMPARE(effect->numRepaints, 1);
       
   226 }
       
   227 
       
   228 void tst_QGraphicsEffectSource::isPixmap()
       
   229 {
       
   230     // Current source is a CustomItem (which is not a pixmap item).
       
   231     QVERIFY(!effect->source()->isPixmap());
       
   232 
       
   233     // Make sure isPixmap() returns true for QGraphicsPixmapItem.
       
   234     QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem;
       
   235     CustomEffect *anotherEffect = new CustomEffect;
       
   236     pixmapItem->setGraphicsEffect(anotherEffect);
       
   237     QVERIFY(anotherEffect->source());
       
   238     QCOMPARE(anotherEffect->source()->graphicsItem(), static_cast<QGraphicsItem *>(pixmapItem));
       
   239     QVERIFY(anotherEffect->source()->isPixmap());
       
   240     delete pixmapItem;
       
   241 }
       
   242 
       
   243 void tst_QGraphicsEffectSource::draw()
       
   244 {
       
   245     // The source can only draw as a result of QGraphicsEffect::draw.
       
   246     QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
       
   247     QPixmap dummyPixmap(10, 10);
       
   248     QPainter dummyPainter(&dummyPixmap);
       
   249     effect->source()->draw(&dummyPainter);
       
   250 }
       
   251 
       
   252 void tst_QGraphicsEffectSource::update()
       
   253 {
       
   254     QCOMPARE(item->numRepaints, 0);
       
   255     QCOMPARE(effect->numRepaints, 0);
       
   256 
       
   257     effect->source()->update();
       
   258     QTest::qWait(50);
       
   259 
       
   260     QCOMPARE(item->numRepaints, 1);
       
   261     QCOMPARE(effect->numRepaints, 1);
       
   262 }
       
   263 
       
   264 void tst_QGraphicsEffectSource::boundingRect()
       
   265 {
       
   266     QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
       
   267     QCOMPARE(effect->source()->boundingRect(Qt::DeviceCoordinates), QRectF());
       
   268 
       
   269     QRectF itemBoundingRect = item->boundingRect();
       
   270     if (!item->children().isEmpty())
       
   271         itemBoundingRect |= item->childrenBoundingRect();
       
   272 
       
   273     // We can at least check that the device bounding rect was correct in QGraphicsEffect::draw.
       
   274     effect->storeDeviceDependentStuff = true;
       
   275     effect->source()->update();
       
   276     QTest::qWait(50);
       
   277     const QTransform deviceTransform = item->deviceTransform(view->viewportTransform());
       
   278     QCOMPARE(effect->sourceDeviceBoundingRect, deviceTransform.mapRect(itemBoundingRect));
       
   279 
       
   280     // Bounding rect in logical coordinates is of course fine.
       
   281     QCOMPARE(effect->source()->boundingRect(Qt::LogicalCoordinates), itemBoundingRect);
       
   282     // Make sure default value is Qt::LogicalCoordinates.
       
   283     QCOMPARE(effect->source()->boundingRect(), itemBoundingRect);
       
   284 }
       
   285 
       
   286 void tst_QGraphicsEffectSource::deviceRect()
       
   287 {
       
   288     effect->storeDeviceDependentStuff = true;
       
   289     effect->source()->update();
       
   290     QTest::qWait(50);
       
   291     QCOMPARE(effect->deviceRect, view->viewport()->rect());
       
   292 }
       
   293 
       
   294 void tst_QGraphicsEffectSource::pixmap()
       
   295 {
       
   296     QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
       
   297     QCOMPARE(effect->source()->pixmap(Qt::DeviceCoordinates), QPixmap());
       
   298 
       
   299     // We can at least verify a valid pixmap from QGraphicsEffect::draw.
       
   300     effect->storeDeviceDependentStuff = true;
       
   301     effect->source()->update();
       
   302     QTest::qWait(50);
       
   303     QVERIFY(!effect->deviceCoordinatesPixmap.isNull());
       
   304 
       
   305     // Pixmaps in logical coordinates we can do fine.
       
   306     QPixmap pixmap1 = effect->source()->pixmap(Qt::LogicalCoordinates);
       
   307     QVERIFY(!pixmap1.isNull());
       
   308 
       
   309     // Make sure default value is Qt::LogicalCoordinates.
       
   310     QPixmap pixmap2 = effect->source()->pixmap();
       
   311     QCOMPARE(pixmap1, pixmap2);
       
   312 }
       
   313 
       
   314 class PaddingEffect : public QGraphicsEffect
       
   315 {
       
   316 public:
       
   317     PaddingEffect(QObject *parent) : QGraphicsEffect(parent)
       
   318     {
       
   319     }
       
   320 
       
   321     QRectF boundingRectFor(const QRectF &src) const {
       
   322         return src.adjusted(-10, -10, 10, 10);
       
   323     }
       
   324 
       
   325     void draw(QPainter *) {
       
   326         pix = source()->pixmap(coordinateMode, &offset, padMode);
       
   327     }
       
   328 
       
   329     QPixmap pix;
       
   330     QPoint offset;
       
   331     QGraphicsEffect::PixmapPadMode padMode;
       
   332     Qt::CoordinateSystem coordinateMode;
       
   333 };
       
   334 
       
   335 void tst_QGraphicsEffectSource::pixmapPadding_data()
       
   336 {
       
   337     QTest::addColumn<int>("coordinateMode");
       
   338     QTest::addColumn<int>("padMode");
       
   339     QTest::addColumn<QSize>("size");
       
   340     QTest::addColumn<QPoint>("offset");
       
   341     QTest::addColumn<uint>("ulPixel");
       
   342 
       
   343     QTest::newRow("log,nopad") << int(Qt::LogicalCoordinates)
       
   344                                << int(QGraphicsEffect::NoPad)
       
   345                                << QSize(10, 10) << QPoint(0, 0)
       
   346                                << 0xffff0000u;
       
   347 
       
   348     QTest::newRow("log,transparent") << int(Qt::LogicalCoordinates)
       
   349                                      << int(QGraphicsEffect::PadToTransparentBorder)
       
   350                                      << QSize(14, 14) << QPoint(-2, -2)
       
   351                                      << 0x00000000u;
       
   352 
       
   353     QTest::newRow("log,effectrect") << int(Qt::LogicalCoordinates)
       
   354                                     << int(QGraphicsEffect::PadToEffectiveBoundingRect)
       
   355                                     << QSize(20, 20) << QPoint(-5, -5)
       
   356                                     << 0x00000000u;
       
   357 
       
   358     QTest::newRow("dev,nopad") << int(Qt::DeviceCoordinates)
       
   359                                << int(QGraphicsEffect::NoPad)
       
   360                                << QSize(20, 20) << QPoint(40, 40)
       
   361                                << 0xffff0000u;
       
   362 
       
   363     QTest::newRow("dev,transparent") << int(Qt::DeviceCoordinates)
       
   364                                      << int(QGraphicsEffect::PadToTransparentBorder)
       
   365                                      << QSize(24, 24) << QPoint(38, 38)
       
   366                                      << 0x00000000u;
       
   367 
       
   368     QTest::newRow("dev,effectrect") << int(Qt::DeviceCoordinates)
       
   369                                     << int(QGraphicsEffect::PadToEffectiveBoundingRect)
       
   370                                     << QSize(40, 40) << QPoint(30, 30)
       
   371                                     << 0x00000000u;
       
   372 
       
   373 }
       
   374 
       
   375 void tst_QGraphicsEffectSource::pixmapPadding()
       
   376 {
       
   377     QPixmap dummyTarget(100, 100);
       
   378     QPainter dummyPainter(&dummyTarget);
       
   379     dummyPainter.translate(40, 40);
       
   380     dummyPainter.scale(2, 2);
       
   381 
       
   382     QPixmap pm(10, 10);
       
   383     pm.fill(Qt::red);
       
   384 
       
   385     QGraphicsScene *scene = new QGraphicsScene();
       
   386     PaddingEffect *effect = new PaddingEffect(scene);
       
   387     QGraphicsPixmapItem *pmItem = new QGraphicsPixmapItem(pm);
       
   388     scene->addItem(pmItem);
       
   389     pmItem->setGraphicsEffect(effect);
       
   390 
       
   391     QFETCH(int, coordinateMode);
       
   392     QFETCH(int, padMode);
       
   393     QFETCH(QPoint, offset);
       
   394     QFETCH(QSize, size);
       
   395     QFETCH(uint, ulPixel);
       
   396 
       
   397     effect->padMode = (QGraphicsEffect::PixmapPadMode) padMode;
       
   398     effect->coordinateMode = (Qt::CoordinateSystem) coordinateMode;
       
   399 
       
   400     scene->render(&dummyPainter, scene->itemsBoundingRect(), scene->itemsBoundingRect());
       
   401 
       
   402     QCOMPARE(effect->pix.size(), size);
       
   403     QCOMPARE(effect->offset, offset);
       
   404     QCOMPARE(effect->pix.toImage().pixel(0, 0), ulPixel);
       
   405 
       
   406     // ### Fix corruption in scene destruction, then enable...
       
   407     // delete scene;
       
   408 }
       
   409 
       
   410 QTEST_MAIN(tst_QGraphicsEffectSource)
       
   411 #include "tst_qgraphicseffectsource.moc"
       
   412