Skip to content

Commit

Permalink
Preserve aspect ratio when setting Image.sourceSize
Browse files Browse the repository at this point in the history
Setting both sourceSize.width and sourceSize.height results in changing
the image aspect ratio.  This is never what you'd want.

Fit the image to the provided sourceSize, maintaining the aspect ratio.

Task-number: QTBUG-21161
Change-Id: I77e9aacb8d31475d5df0aef1de52c0edbd1e2fc9
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
  • Loading branch information
Martin Jones authored and Qt by Nokia committed Feb 14, 2012
1 parent 58d8574 commit d951781
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 9 deletions.
1 change: 1 addition & 0 deletions doc/src/declarative/whatsnew.qdoc
Expand Up @@ -107,6 +107,7 @@ Added topMargin, bottomMargin, leftMargin, rightMargin, xOrigin, yOrigin propert

Image has two new properties: horizontalAlignment and verticalAlignment. It also has a new value for
fillMode (Image.Pad) that does not transform the image.
Setting Image sourceSize.width and sourceSize.height will now fit the image to the size, maintaining aspect.

Grid now has rowSpacing and columnSpacing properties.

Expand Down
6 changes: 5 additions & 1 deletion src/quick/items/qquickimage.cpp
Expand Up @@ -404,6 +404,10 @@ qreal QQuickImage::paintedHeight() const
other dimension is set in proportion to preserve the source image's aspect ratio.
(The \l fillMode is independent of this.)
If both the sourceSize.width and sourceSize.height are set the image will be scaled
down to fit within the specified size, maintaining the image's aspect ratio. The actual
size of the image after scaling is available via \l implicitWidth and \l implicitHeight.
If the source is an intrinsically scalable image (eg. SVG), this property
determines the size of the loaded image regardless of intrinsic size.
Avoid changing this property dynamically; rendering an SVG is \e slow compared
Expand All @@ -413,7 +417,7 @@ qreal QQuickImage::paintedHeight() const
be no greater than this property specifies. For some formats (currently only JPEG),
the whole image will never actually be loaded into memory.
Since QtQuick 1.1 the sourceSize can be cleared to the natural size of the image
sourceSize can be cleared to the natural size of the image
by setting sourceSize to \c undefined.
\note \e {Changing this property dynamically causes the image source to be reloaded,
Expand Down
18 changes: 10 additions & 8 deletions src/quick/util/qdeclarativepixmapcache.cpp
Expand Up @@ -323,20 +323,22 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
force_scale = true;
}

bool scaled = false;
if (requestSize.width() > 0 || requestSize.height() > 0) {
QSize s = imgio.size();
qreal ratio = 0.0;
if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
if (requestSize.height() <= 0)
s.setHeight(s.height()*requestSize.width()/s.width());
s.setWidth(requestSize.width()); scaled = true;
ratio = qreal(requestSize.width())/s.width();
}
if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
if (requestSize.width() <= 0)
s.setWidth(s.width()*requestSize.height()/s.height());
s.setHeight(requestSize.height()); scaled = true;
qreal hr = qreal(requestSize.height())/s.height();
if (ratio == 0.0 || hr < ratio)
ratio = hr;
}
if (ratio > 0.0) {
s.setHeight(qRound(s.height() * ratio));
s.setWidth(qRound(s.width() * ratio));
imgio.setScaledSize(s);
}
if (scaled) { imgio.setScaledSize(s); }
}

if (impsize)
Expand Down
7 changes: 7 additions & 0 deletions tests/auto/qtquick2/qquickimage/data/sourceSize.qml
@@ -0,0 +1,7 @@
import QtQuick 2.0

Image {
source: "heart.png"
sourceSize.width: srcWidth
sourceSize.height: srcHeight
}
46 changes: 46 additions & 0 deletions tests/auto/qtquick2/qquickimage/tst_qquickimage.cpp
Expand Up @@ -95,6 +95,8 @@ private slots:
void sourceSize_QTBUG_16389();
void nullPixmapPaint();
void imageCrash_QTBUG_22125();
void sourceSize_data();
void sourceSize();

private:
QDeclarativeEngine engine;
Expand Down Expand Up @@ -498,6 +500,8 @@ void tst_qquickimage::tiling_QTBUG_6716()
QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
}
}

delete canvas;
}

void tst_qquickimage::tiling_QTBUG_6716_data()
Expand Down Expand Up @@ -674,6 +678,8 @@ void tst_qquickimage::nullPixmapPaint()
qInstallMsgHandler(previousMsgHandler);
QVERIFY(numberOfWarnings == 0);
delete image;

delete canvas;
}

void tst_qquickimage::imageCrash_QTBUG_22125()
Expand All @@ -698,6 +704,46 @@ void tst_qquickimage::imageCrash_QTBUG_22125()
QCoreApplication::processEvents();
}

void tst_qquickimage::sourceSize_data()
{
QTest::addColumn<int>("sourceWidth");
QTest::addColumn<int>("sourceHeight");
QTest::addColumn<qreal>("implicitWidth");
QTest::addColumn<qreal>("implicitHeight");

QTest::newRow("unscaled") << 0 << 0 << 300.0 << 300.0;
QTest::newRow("scale width") << 100 << 0 << 100.0 << 100.0;
QTest::newRow("scale height") << 0 << 150 << 150.0 << 150.0;
QTest::newRow("larger sourceSize") << 400 << 400 << 300.0 << 300.0;
}

void tst_qquickimage::sourceSize()
{
QFETCH(int, sourceWidth);
QFETCH(int, sourceHeight);
QFETCH(qreal, implicitWidth);
QFETCH(qreal, implicitHeight);

QQuickView *canvas = new QQuickView(0);
QDeclarativeContext *ctxt = canvas->rootContext();
ctxt->setContextProperty("srcWidth", sourceWidth);
ctxt->setContextProperty("srcHeight", sourceHeight);

canvas->setSource(testFileUrl("sourceSize.qml"));
canvas->show();
qApp->processEvents();

QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
QVERIFY(image);

QCOMPARE(image->sourceSize().width(), sourceWidth);
QCOMPARE(image->sourceSize().height(), sourceHeight);
QCOMPARE(image->implicitWidth(), implicitWidth);
QCOMPARE(image->implicitHeight(), implicitHeight);

delete canvas;
}

QTEST_MAIN(tst_qquickimage)

#include "tst_qquickimage.moc"

0 comments on commit d951781

Please sign in to comment.