diff options
-rw-r--r-- | src/declarative/graphicsitems/qdeclarativeimage.cpp | 27 | ||||
-rw-r--r-- | src/declarative/graphicsitems/qdeclarativeimage_p.h | 1 | ||||
-rw-r--r-- | tests/auto/declarative/qdeclarativeimage/data/rect.png | bin | 0 -> 171 bytes | |||
-rw-r--r-- | tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp | 74 |
4 files changed, 99 insertions, 3 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index 1f1e93d..3b08a9b 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -259,8 +259,10 @@ void QDeclarativeImage::setFillMode(FillMode mode) \qmlproperty real Image::paintedHeight These properties hold the size of the image that is actually painted. - In most cases it is the same as \c width and \c height, but when using a \c fillMode like - \c PreserveAspectFit \c paintedWidth or \c paintedHeight can be smaller than \c width and \c height. + In most cases it is the same as \c width and \c height, but when using a + \c fillMode \c PreserveAspectFit or \c fillMode \c PreserveAspectCrop + \c paintedWidth or \c paintedHeight can be smaller or larger than + \c width and \c height of the Image element. */ qreal QDeclarativeImage::paintedWidth() const { @@ -399,6 +401,19 @@ void QDeclarativeImage::updatePaintedGeometry() if (heightValid() && !widthValid()) { setImplicitWidth(d->paintedWidth); } + } else if (d->fillMode == PreserveAspectCrop) { + if (!d->pix.width() || !d->pix.height()) + return; + qreal widthScale = width() / qreal(d->pix.width()); + qreal heightScale = height() / qreal(d->pix.height()); + if (widthScale < heightScale) { + widthScale = heightScale; + } else if(heightScale < widthScale) { + heightScale = widthScale; + } + + d->paintedHeight = heightScale * qreal(d->pix.height()); + d->paintedWidth = widthScale * qreal(d->pix.width()); } else { d->paintedWidth = width(); d->paintedHeight = height(); @@ -412,6 +427,12 @@ void QDeclarativeImage::geometryChanged(const QRectF &newGeometry, const QRectF updatePaintedGeometry(); } +QRectF QDeclarativeImage::boundingRect() const +{ + Q_D(const QDeclarativeImage); + return QRectF(0, 0, qMax(d->mWidth, d->paintedWidth), qMax(d->mHeight, d->paintedHeight)); +} + /*! \qmlproperty url Image::source @@ -496,7 +517,7 @@ void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWi } if (clip()) { p->save(); - p->setClipRect(boundingRect(), Qt::IntersectClip); + p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip); } scale.scale(widthScale, heightScale); QTransform old = p->transform(); diff --git a/src/declarative/graphicsitems/qdeclarativeimage_p.h b/src/declarative/graphicsitems/qdeclarativeimage_p.h index c8bb30b..0e8034e 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimage_p.h @@ -76,6 +76,7 @@ public: qreal paintedHeight() const; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + QRectF boundingRect() const; Q_SIGNALS: void fillModeChanged(); diff --git a/tests/auto/declarative/qdeclarativeimage/data/rect.png b/tests/auto/declarative/qdeclarativeimage/data/rect.png Binary files differnew file mode 100644 index 0000000..d564a2d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeimage/data/rect.png diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index f1e026f..bf779ad 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -80,6 +80,8 @@ private slots: void preserveAspectRatio(); void smooth(); void svg(); + void geometry(); + void geometry_data(); void big(); void tiling_QTBUG_6716(); void noLoading(); @@ -288,6 +290,78 @@ void tst_qdeclarativeimage::svg() delete obj; } +void tst_qdeclarativeimage::geometry_data() +{ + QTest::addColumn<QString>("fillMode"); + QTest::addColumn<bool>("explicitWidth"); + QTest::addColumn<bool>("explicitHeight"); + QTest::addColumn<double>("itemWidth"); + QTest::addColumn<double>("paintedWidth"); + QTest::addColumn<double>("boundingWidth"); + QTest::addColumn<double>("itemHeight"); + QTest::addColumn<double>("paintedHeight"); + QTest::addColumn<double>("boundingHeight"); + + // tested image has width 200, height 100 + + // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match + QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0; + QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0; + QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0; + QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0; + + // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match + QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0; + QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0; + QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0; + QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0; + + // bounding rect, painted rect and item rect are equal in stretching and tiling images + QStringList fillModes; + fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally"; + foreach (QString fillMode, fillModes) { + QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0; + QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0; + QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0; + QTest::newRow(QString(fillMode + " explicit width 300, height 400").toLatin1()) << fillMode << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 400.0 << 400.0; + } +} + +void tst_qdeclarativeimage::geometry() +{ + QFETCH(QString, fillMode); + QFETCH(bool, explicitWidth); + QFETCH(bool, explicitHeight); + QFETCH(double, itemWidth); + QFETCH(double, itemHeight); + QFETCH(double, paintedWidth); + QFETCH(double, paintedHeight); + QFETCH(double, boundingWidth); + QFETCH(double, boundingHeight); + + QString src = QUrl::fromLocalFile(SRCDIR "/data/rect.png").toString(); + QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; "; + + if (explicitWidth) + componentStr.append("width: 300; "); + if (explicitHeight) + componentStr.append("height: 400; "); + componentStr.append("}"); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeImage *obj = qobject_cast<QDeclarativeImage*>(component.create()); + QVERIFY(obj != 0); + + QCOMPARE(obj->width(), itemWidth); + QCOMPARE(obj->paintedWidth(), paintedWidth); + QCOMPARE(obj->boundingRect().width(), boundingWidth); + + QCOMPARE(obj->height(), itemHeight); + QCOMPARE(obj->paintedHeight(), paintedHeight); + QCOMPARE(obj->boundingRect().height(), boundingHeight); + delete obj; +} + void tst_qdeclarativeimage::big() { // If the JPEG loader does not implement scaling efficiently, it would |