tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 
       
    43 #include <QtTest/QtTest>
       
    44 #include <QtGui/qdesktopwidget.h>
       
    45 #include <QtGui/qgraphicseffect.h>
       
    46 #include <QtGui/qgraphicsview.h>
       
    47 #include <QtGui/qgraphicsscene.h>
       
    48 #include <QtGui/qgraphicsitem.h>
       
    49 #include <QtGui/qstyleoption.h>
       
    50 
       
    51 #include "../../shared/util.h"
       
    52 
       
    53 //TESTED_CLASS=
       
    54 //TESTED_FILES=
       
    55 
       
    56 class tst_QGraphicsEffect : public QObject
       
    57 {
       
    58     Q_OBJECT
       
    59 public slots:
       
    60     void initTestCase();
       
    61 
       
    62 private slots:
       
    63     void setEnabled();
       
    64     void source();
       
    65     void boundingRectFor();
       
    66     void boundingRect();
       
    67     void draw();
       
    68     void opacity();
       
    69     void grayscale();
       
    70     void colorize();
       
    71 };
       
    72 
       
    73 void tst_QGraphicsEffect::initTestCase()
       
    74 {}
       
    75 
       
    76 class CustomItem : public QGraphicsRectItem
       
    77 {
       
    78 public:
       
    79     CustomItem(qreal x, qreal y, qreal width, qreal height)
       
    80         : QGraphicsRectItem(x, y, width, height), numRepaints(0),
       
    81           m_painter(0), m_styleOption(0)
       
    82     {}
       
    83 
       
    84     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
       
    85     {
       
    86         m_painter = painter;
       
    87         m_styleOption = option;
       
    88         ++numRepaints;
       
    89         QGraphicsRectItem::paint(painter, option, widget);
       
    90     }
       
    91 
       
    92     void reset()
       
    93     {
       
    94         numRepaints = 0;
       
    95         m_painter = 0;
       
    96         m_styleOption = 0;
       
    97     }
       
    98 
       
    99     int numRepaints;
       
   100     QPainter *m_painter;
       
   101     const QStyleOption *m_styleOption;
       
   102 };
       
   103 
       
   104 class CustomEffect : public QGraphicsEffect
       
   105 {
       
   106 public:
       
   107     CustomEffect()
       
   108         : QGraphicsEffect(), numRepaints(0), m_margin(10),
       
   109           doNothingInDraw(false), m_painter(0), m_styleOption(0), m_source(0), m_opacity(1.0)
       
   110     {}
       
   111 
       
   112     QRectF boundingRectFor(const QRectF &rect) const
       
   113     { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); }
       
   114 
       
   115     void reset()
       
   116     {
       
   117         numRepaints = 0;
       
   118         m_sourceChangedFlags = QGraphicsEffect::ChangeFlags();
       
   119         m_painter = 0;
       
   120         m_styleOption = 0;
       
   121         m_source = 0;
       
   122         m_opacity = 1.0;
       
   123     }
       
   124 
       
   125     void setMargin(int margin)
       
   126     {
       
   127         m_margin = margin;
       
   128         updateBoundingRect();
       
   129     }
       
   130 
       
   131     int margin() const
       
   132     { return m_margin; }
       
   133 
       
   134     void draw(QPainter *painter, QGraphicsEffectSource *source)
       
   135     {
       
   136         ++numRepaints;
       
   137         if (doNothingInDraw)
       
   138             return;
       
   139         m_source = source;
       
   140         m_painter = painter;
       
   141         m_styleOption = source->styleOption();
       
   142         m_opacity = painter->opacity();
       
   143         source->draw(painter);
       
   144     }
       
   145 
       
   146     void sourceChanged(QGraphicsEffect::ChangeFlags flags)
       
   147     { m_sourceChangedFlags |= flags; }
       
   148 
       
   149     int numRepaints;
       
   150     int m_margin;
       
   151     QGraphicsEffect::ChangeFlags m_sourceChangedFlags;
       
   152     bool doNothingInDraw;
       
   153     QPainter *m_painter;
       
   154     const QStyleOption *m_styleOption;
       
   155     QGraphicsEffectSource *m_source;
       
   156     qreal m_opacity;
       
   157 };
       
   158 
       
   159 void tst_QGraphicsEffect::setEnabled()
       
   160 {
       
   161     CustomEffect effect;
       
   162     QVERIFY(effect.isEnabled());
       
   163 
       
   164     effect.setEnabled(false);
       
   165     QVERIFY(!effect.isEnabled());
       
   166 }
       
   167 
       
   168 void tst_QGraphicsEffect::source()
       
   169 {
       
   170     QPointer<CustomEffect> effect = new CustomEffect;
       
   171     QVERIFY(!effect->source());
       
   172     QVERIFY(!effect->m_sourceChangedFlags);
       
   173 
       
   174     // Install effect on QGraphicsItem.
       
   175     QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
       
   176     item->setGraphicsEffect(effect);
       
   177     QVERIFY(effect->source());
       
   178     QCOMPARE(effect->source()->graphicsItem(), item);
       
   179     QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceAttached);
       
   180     effect->reset();
       
   181 
       
   182     // Make sure disabling/enabling the effect doesn't change the source.
       
   183     effect->setEnabled(false);
       
   184     QVERIFY(effect->source());
       
   185     QCOMPARE(effect->source()->graphicsItem(), item);
       
   186     QVERIFY(!effect->m_sourceChangedFlags);
       
   187     effect->reset();
       
   188 
       
   189     effect->setEnabled(true);
       
   190     QVERIFY(effect->source());
       
   191     QCOMPARE(effect->source()->graphicsItem(), item);
       
   192     QVERIFY(!effect->m_sourceChangedFlags);
       
   193     effect->reset();
       
   194 
       
   195     // Uninstall effect on QGraphicsItem.
       
   196     effect->reset();
       
   197     item->setGraphicsEffect(0);
       
   198     QVERIFY(!effect->source());
       
   199     QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceDetached);
       
   200 
       
   201     // The item takes ownership and should delete the effect when destroyed.
       
   202     item->setGraphicsEffect(effect);
       
   203     QPointer<QGraphicsEffectSource> source = effect->source();
       
   204     QVERIFY(source);
       
   205     QCOMPARE(source->graphicsItem(), item);
       
   206     delete item;
       
   207     QVERIFY(!effect);
       
   208     QVERIFY(!source);
       
   209 }
       
   210 
       
   211 void tst_QGraphicsEffect::boundingRectFor()
       
   212 {
       
   213     CustomEffect effect;
       
   214     int margin = effect.margin();
       
   215     const QRectF source(0, 0, 100, 100);
       
   216     QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin));
       
   217 
       
   218     effect.setMargin(margin = 20);
       
   219     QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin));
       
   220 }
       
   221 
       
   222 void tst_QGraphicsEffect::boundingRect()
       
   223 {
       
   224     // No source; empty bounding rect.
       
   225     CustomEffect *effect = new CustomEffect;
       
   226     QCOMPARE(effect->boundingRect(), QRectF());
       
   227 
       
   228     // Install effect on QGraphicsItem.
       
   229     QRectF itemRect(0, 0, 100, 100);
       
   230     QGraphicsRectItem *item = new QGraphicsRectItem;
       
   231     item->setRect(itemRect);
       
   232     item->setGraphicsEffect(effect);
       
   233     int margin = effect->margin();
       
   234     QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
       
   235     QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
       
   236 
       
   237     // Make sure disabling/enabling the effect doesn't change the bounding rect.
       
   238     effect->setEnabled(false);
       
   239     QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
       
   240     QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
       
   241     effect->setEnabled(true);
       
   242     QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
       
   243     QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
       
   244 
       
   245     // Change effect margins.
       
   246     effect->setMargin(margin = 20);
       
   247     QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
       
   248     QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
       
   249 
       
   250     // Uninstall effect on QGraphicsItem.
       
   251     item->setGraphicsEffect(0);
       
   252     QCOMPARE(effect->boundingRect(), QRectF());
       
   253 
       
   254     delete effect;
       
   255     delete item;
       
   256 }
       
   257 
       
   258 void tst_QGraphicsEffect::draw()
       
   259 {
       
   260     QGraphicsScene scene;
       
   261     CustomItem *item = new CustomItem(0, 0, 100, 100);
       
   262     scene.addItem(item);
       
   263 
       
   264     QGraphicsView view(&scene);
       
   265     view.show();
       
   266     QTest::qWaitForWindowShown(&view);
       
   267     QTRY_VERIFY(item->numRepaints > 0);
       
   268     item->reset();
       
   269 
       
   270     // Make sure installing the effect triggers a repaint.
       
   271     CustomEffect *effect = new CustomEffect;
       
   272     item->setGraphicsEffect(effect);
       
   273     QTest::qWait(50);
       
   274     QCOMPARE(effect->numRepaints, 1);
       
   275     QCOMPARE(item->numRepaints, 1);
       
   276 
       
   277     // Make sure QPainter* and QStyleOptionGraphicsItem* stays persistent
       
   278     // during QGraphicsEffect::draw/QGraphicsItem::paint.
       
   279     QVERIFY(effect->m_painter);
       
   280     QCOMPARE(effect->m_painter, item->m_painter);
       
   281     QCOMPARE(effect->m_styleOption, item->m_styleOption);
       
   282     // Make sure QGraphicsEffect::source is persistent.
       
   283     QCOMPARE(effect->m_source, effect->source());
       
   284     effect->reset();
       
   285     item->reset();
       
   286 
       
   287     // Make sure updating the source triggers a repaint.
       
   288     item->update();
       
   289     QTest::qWait(50);
       
   290     QCOMPARE(effect->numRepaints, 1);
       
   291     QCOMPARE(item->numRepaints, 1);
       
   292     QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceInvalidated);
       
   293     effect->reset();
       
   294     item->reset();
       
   295 
       
   296     // Make sure changing the effect's bounding rect triggers a repaint.
       
   297     effect->setMargin(20);
       
   298     QTest::qWait(50);
       
   299     QCOMPARE(effect->numRepaints, 1);
       
   300     QCOMPARE(item->numRepaints, 1);
       
   301     effect->reset();
       
   302     item->reset();
       
   303 
       
   304     // Make sure change the item's bounding rect triggers a repaint.
       
   305     item->setRect(0, 0, 50, 50);
       
   306     QTest::qWait(50);
       
   307     QCOMPARE(effect->numRepaints, 1);
       
   308     QCOMPARE(item->numRepaints, 1);
       
   309     QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceBoundingRectChanged);
       
   310     effect->reset();
       
   311     item->reset();
       
   312 
       
   313     // Make sure the effect is the one to issue a repaint of the item.
       
   314     effect->doNothingInDraw = true;
       
   315     item->update();
       
   316     QTest::qWait(50);
       
   317     QCOMPARE(effect->numRepaints, 1);
       
   318     QCOMPARE(item->numRepaints, 0);
       
   319     effect->doNothingInDraw = false;
       
   320     effect->reset();
       
   321     item->reset();
       
   322 
       
   323     // Make sure we update the source when disabling/enabling the effect.
       
   324     effect->setEnabled(false);
       
   325     QTest::qWait(50);
       
   326     QCOMPARE(effect->numRepaints, 0);
       
   327     QCOMPARE(item->numRepaints, 1);
       
   328     effect->reset();
       
   329     item->reset();
       
   330 
       
   331     effect->setEnabled(true);
       
   332     QTest::qWait(50);
       
   333     QCOMPARE(effect->numRepaints, 1);
       
   334     QCOMPARE(item->numRepaints, 1);
       
   335     effect->reset();
       
   336     item->reset();
       
   337 
       
   338     // Effect is already enabled; nothing should happen.
       
   339     effect->setEnabled(true);
       
   340     QTest::qWait(50);
       
   341     QCOMPARE(effect->numRepaints, 0);
       
   342     QCOMPARE(item->numRepaints, 0);
       
   343 
       
   344     // Make sure uninstalling an effect triggers a repaint.
       
   345     item->setGraphicsEffect(0);
       
   346     QTest::qWait(50);
       
   347     QCOMPARE(effect->numRepaints, 0);
       
   348     QCOMPARE(item->numRepaints, 1);
       
   349     delete effect;
       
   350 }
       
   351 
       
   352 void tst_QGraphicsEffect::opacity()
       
   353 {
       
   354     // Make sure the painter's opacity is correct in QGraphicsEffect::draw.
       
   355     QGraphicsScene scene;
       
   356     CustomItem *item = new CustomItem(0, 0, 100, 100);
       
   357     item->setOpacity(0.5);
       
   358     CustomEffect *effect = new CustomEffect;
       
   359     item->setGraphicsEffect(effect);
       
   360     scene.addItem(item);
       
   361 
       
   362     QGraphicsView view(&scene);
       
   363     view.show();
       
   364     QTest::qWaitForWindowShown(&view);
       
   365     QTRY_VERIFY(effect->numRepaints > 0);
       
   366     QCOMPARE(effect->m_opacity, qreal(0.5));
       
   367 }
       
   368 
       
   369 void tst_QGraphicsEffect::grayscale()
       
   370 {
       
   371     if (qApp->desktop()->depth() < 24) {
       
   372         QSKIP("Test only works on 32 bit displays", SkipAll);
       
   373         return;
       
   374     }
       
   375 
       
   376     QGraphicsScene scene(0, 0, 100, 100);
       
   377 
       
   378     QGraphicsRectItem *item = scene.addRect(0, 0, 50, 50);
       
   379     item->setPen(Qt::NoPen);
       
   380     item->setBrush(QColor(122, 193, 66)); // Qt light green
       
   381 
       
   382     QGraphicsGrayscaleEffect *effect = new QGraphicsGrayscaleEffect;
       
   383     item->setGraphicsEffect(effect);
       
   384 
       
   385     QPainter painter;
       
   386     QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
       
   387 
       
   388     image.fill(0);
       
   389     painter.begin(&image);
       
   390     painter.setRenderHint(QPainter::Antialiasing);
       
   391     scene.render(&painter);
       
   392     painter.end();
       
   393 
       
   394     QCOMPARE(image.pixel(10, 10), qRgb(148, 148, 148));
       
   395 
       
   396     effect->setStrength(0.5);
       
   397 
       
   398     image.fill(0);
       
   399     painter.begin(&image);
       
   400     painter.setRenderHint(QPainter::Antialiasing);
       
   401     scene.render(&painter);
       
   402     painter.end();
       
   403 
       
   404     QCOMPARE(image.pixel(10, 10), qRgb(135, 171, 107));
       
   405 
       
   406     effect->setStrength(0.0);
       
   407 
       
   408     image.fill(0);
       
   409     painter.begin(&image);
       
   410     painter.setRenderHint(QPainter::Antialiasing);
       
   411     scene.render(&painter);
       
   412     painter.end();
       
   413 
       
   414     QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66));
       
   415 }
       
   416 
       
   417 void tst_QGraphicsEffect::colorize()
       
   418 {
       
   419     if (qApp->desktop()->depth() < 24) {
       
   420         QSKIP("Test only works on 32 bit displays", SkipAll);
       
   421         return;
       
   422     }
       
   423 
       
   424     QGraphicsScene scene(0, 0, 100, 100);
       
   425 
       
   426     QGraphicsRectItem *item = scene.addRect(0, 0, 50, 50);
       
   427     item->setPen(Qt::NoPen);
       
   428     item->setBrush(QColor(122, 193, 66)); // Qt light green
       
   429 
       
   430     QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect;
       
   431     effect->setColor(QColor(102, 153, 51)); // Qt dark green
       
   432     item->setGraphicsEffect(effect);
       
   433 
       
   434     QPainter painter;
       
   435     QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
       
   436 
       
   437     image.fill(0);
       
   438     painter.begin(&image);
       
   439     painter.setRenderHint(QPainter::Antialiasing);
       
   440     scene.render(&painter);
       
   441     painter.end();
       
   442 
       
   443     QCOMPARE(image.pixel(10, 10), qRgb(191, 212, 169));
       
   444 
       
   445     effect->setStrength(0.5);
       
   446 
       
   447     image.fill(0);
       
   448     painter.begin(&image);
       
   449     painter.setRenderHint(QPainter::Antialiasing);
       
   450     scene.render(&painter);
       
   451     painter.end();
       
   452 
       
   453     QCOMPARE(image.pixel(10, 10), qRgb(156, 203, 117));
       
   454 
       
   455     effect->setStrength(0.0);
       
   456 
       
   457     image.fill(0);
       
   458     painter.begin(&image);
       
   459     painter.setRenderHint(QPainter::Antialiasing);
       
   460     scene.render(&painter);
       
   461     painter.end();
       
   462 
       
   463     QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66));
       
   464 }
       
   465 
       
   466 QTEST_MAIN(tst_QGraphicsEffect)
       
   467 #include "tst_qgraphicseffect.moc"
       
   468