aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickimagebase.cpp
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2013-08-19 13:29:43 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-20 22:12:24 +0100
commit63fb30eb29c26cd7ba0d9133610acb85cad83775 (patch)
treefb0d4870c3f2c22d14a90ad26956b8b6f45d3886 /src/quick/items/qquickimagebase.cpp
parent5277a60f56c83376c1f2e9d9d502f1793d8c4857 (diff)
Implement high-dpi "@2x" image handling.
Make QQuickBaseImage::load() load "@2x" image files on high-dpi displays. Reload images on screen change in order to load the correct version depending on screen dpi. Modify QQuickImageBase::updatePaintNode() to work with @2x images. QQuickBaseImage::load() now looks at the target window's devicePixelRatio and checks for the presence of a "@2x" file on disk. If found the @2x version will be used. Unlike QPixmap, QQuickPixmap has no special knowledge of "@2x" files. They pixmap system will be asked to load "@2x" files and will cache them and report the (device) pixel size, like any other pixmap. Add auto-test and manual test. Task-number: QTBUG-32862, QTBUG-33069 Change-Id: I1f57a10075e499f6eee61df5421e1986521c6ab0 Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src/quick/items/qquickimagebase.cpp')
-rw-r--r--src/quick/items/qquickimagebase.cpp73
1 files changed, 71 insertions, 2 deletions
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index c842922dc6..edd6faa569 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -42,7 +42,10 @@
#include "qquickimagebase_p.h"
#include "qquickimagebase_p_p.h"
+#include <QtGui/qguiapplication.h>
+
#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlfile.h>
QT_BEGIN_NAMESPACE
@@ -50,12 +53,14 @@ QQuickImageBase::QQuickImageBase(QQuickItem *parent)
: QQuickImplicitSizeItem(*(new QQuickImageBasePrivate), parent)
{
setFlag(ItemHasContents);
+ connect(this, SIGNAL(windowChanged(QQuickWindow*)), SLOT(handleWindowChanged(QQuickWindow*)));
}
QQuickImageBase::QQuickImageBase(QQuickImageBasePrivate &dd, QQuickItem *parent)
: QQuickImplicitSizeItem(dd, parent)
{
setFlag(ItemHasContents);
+ connect(this, SIGNAL(windowChanged(QQuickWindow*)), SLOT(handleWindowChanged(QQuickWindow*)));
}
QQuickImageBase::~QQuickImageBase()
@@ -208,7 +213,13 @@ void QQuickImageBase::load()
if (d->cache)
options |= QQuickPixmap::Cache;
d->pix.clear(this);
- d->pix.load(qmlEngine(this), d->url, d->sourcesize, options);
+
+ const qreal targetDevicePixelRatio = (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio());
+ d->devicePixelRatio = 1.0;
+
+ QUrl loadUrl = d->url;
+ resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
+ d->pix.load(qmlEngine(this), loadUrl, d->sourcesize * d->devicePixelRatio, options);
if (d->pix.isLoading()) {
if (d->progress != 0.0) {
@@ -275,6 +286,19 @@ void QQuickImageBase::requestProgress(qint64 received, qint64 total)
}
}
+void QQuickImageBase::handleWindowChanged(QQuickWindow* window)
+{
+ if (window)
+ connect(window, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChanged(QScreen*)));
+}
+
+void QQuickImageBase::handleScreenChanged(QScreen*)
+{
+ // Screen DPI might have changed, reload images on screen change.
+ if (isComponentComplete())
+ load();
+}
+
void QQuickImageBase::componentComplete()
{
Q_D(QQuickImageBase);
@@ -286,7 +310,52 @@ void QQuickImageBase::componentComplete()
void QQuickImageBase::pixmapChange()
{
Q_D(QQuickImageBase);
- setImplicitSize(d->pix.width(), d->pix.height());
+ setImplicitSize(d->pix.width() / d->devicePixelRatio, d->pix.height() / d->devicePixelRatio);
+}
+
+// /path/to/foo.png -> path/too/foo@2x.png
+static QString image2xPath(const QString &path)
+{
+ const int dotIndex = path.lastIndexOf(QLatin1Char('.'));
+ if (dotIndex == -1)
+ return path;
+ if (path.contains("@2x."))
+ return path;
+
+ QString retinaPath = path;
+ retinaPath.insert(dotIndex, QStringLiteral("@2x"));
+ return retinaPath;
+}
+
+void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio)
+{
+ Q_ASSERT(sourceUrl);
+ Q_ASSERT(sourceDevicePixelRatio);
+
+ QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
+
+ // Non-local file path: @2x loading is not supported.
+ if (localFile.isEmpty())
+ return;
+
+ // Special case: the url in the QML source refers directly to an "@2x" file.
+ if (localFile.contains("@2x")) {
+ *sourceDevicePixelRatio = qreal(2.0);
+ return;
+ }
+
+ // Don't load @2x files non normal-dpi displays.
+ if (!(targetDevicePixelRatio > qreal(1.0)))
+ return;
+
+ // Look for an @2x version
+ QString localFile2x = image2xPath(localFile);
+ if (!QFile(localFile2x).exists())
+ return;
+
+ // @2x file found found: Change url and devicePixelRatio
+ *sourceUrl = QUrl::fromLocalFile(localFile2x);
+ *sourceDevicePixelRatio = qreal(2.0);
}
QT_END_NAMESPACE