summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qicon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image/qicon.cpp')
-rw-r--r--src/gui/image/qicon.cpp81
1 files changed, 56 insertions, 25 deletions
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 73b25fd584..0bbc4005a0 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -180,9 +180,28 @@ void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode
static inline int area(const QSize &s) { return s.width() * s.height(); }
-// returns the smallest of the two that is still larger than or equal to size.
-static QPixmapIconEngineEntry *bestSizeMatch( const QSize &size, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
-{
+// Returns the smallest of the two that is still larger than or equal to size.
+// Pixmaps at the correct scale are preferred, pixmaps at lower scale are
+// used as fallbacks. We assume that the pixmap set is complete, in the sense
+// that no 2x pixmap is going to be a better match than a 3x pixmap for the the
+// target scale of 3 (It's OK if 3x pixmaps are missing - we'll fall back to
+// the 2x pixmaps then.)
+static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
+{
+
+ // scale: we can only differentiate on scale if the scale differs
+ if (pa->scale != pb->scale) {
+
+ // Score the pixmaps: 0 is an exact scale match, postive
+ // scores have more detail than requested, negative scores
+ // have less detail than rquested.
+ qreal ascore = pa->scale - scale;
+ qreal bscore = pb->scale - scale;
+
+ // Take the one closest to 0
+ return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
+ }
+
int s = area(size);
if (pa->size == QSize() && pa->pixmap.isNull()) {
pa->pixmap = QPixmap(pa->fileName);
@@ -204,13 +223,13 @@ static QPixmapIconEngineEntry *bestSizeMatch( const QSize &size, QPixmapIconEngi
return pb;
}
-QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state)
+QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
{
QPixmapIconEngineEntry *pe = nullptr;
for (int i = 0; i < pixmaps.count(); ++i)
if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
if (pe)
- pe = bestSizeMatch(size, &pixmaps[i], pe);
+ pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe);
else
pe = &pixmaps[i];
}
@@ -218,42 +237,42 @@ QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, QIcon::Mo
}
-QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly)
+QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state, bool sizeOnly)
{
- QPixmapIconEngineEntry *pe = tryMatch(size, mode, state);
+ QPixmapIconEngineEntry *pe = tryMatch(size, scale, mode, state);
while (!pe){
QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On;
if (mode == QIcon::Disabled || mode == QIcon::Selected) {
QIcon::Mode oppositeMode = (mode == QIcon::Disabled) ? QIcon::Selected : QIcon::Disabled;
- if ((pe = tryMatch(size, QIcon::Normal, state)))
+ if ((pe = tryMatch(size, scale, QIcon::Normal, state)))
break;
- if ((pe = tryMatch(size, QIcon::Active, state)))
+ if ((pe = tryMatch(size, scale, QIcon::Active, state)))
break;
- if ((pe = tryMatch(size, mode, oppositeState)))
+ if ((pe = tryMatch(size, scale, mode, oppositeState)))
break;
- if ((pe = tryMatch(size, QIcon::Normal, oppositeState)))
+ if ((pe = tryMatch(size, scale, QIcon::Normal, oppositeState)))
break;
- if ((pe = tryMatch(size, QIcon::Active, oppositeState)))
+ if ((pe = tryMatch(size, scale, QIcon::Active, oppositeState)))
break;
- if ((pe = tryMatch(size, oppositeMode, state)))
+ if ((pe = tryMatch(size, scale, oppositeMode, state)))
break;
- if ((pe = tryMatch(size, oppositeMode, oppositeState)))
+ if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
break;
} else {
QIcon::Mode oppositeMode = (mode == QIcon::Normal) ? QIcon::Active : QIcon::Normal;
- if ((pe = tryMatch(size, oppositeMode, state)))
+ if ((pe = tryMatch(size, scale, oppositeMode, state)))
break;
- if ((pe = tryMatch(size, mode, oppositeState)))
+ if ((pe = tryMatch(size, scale, mode, oppositeState)))
break;
- if ((pe = tryMatch(size, oppositeMode, oppositeState)))
+ if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
break;
- if ((pe = tryMatch(size, QIcon::Disabled, state)))
+ if ((pe = tryMatch(size, scale, QIcon::Disabled, state)))
break;
- if ((pe = tryMatch(size, QIcon::Selected, state)))
+ if ((pe = tryMatch(size, scale, QIcon::Selected, state)))
break;
- if ((pe = tryMatch(size, QIcon::Disabled, oppositeState)))
+ if ((pe = tryMatch(size, scale, QIcon::Disabled, oppositeState)))
break;
- if ((pe = tryMatch(size, QIcon::Selected, oppositeState)))
+ if ((pe = tryMatch(size, scale, QIcon::Selected, oppositeState)))
break;
}
@@ -272,8 +291,14 @@ QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, QIcon::M
QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
{
+ return scaledPixmap(size, mode, state, 1.0);
+}
+
+QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
+{
+
QPixmap pm;
- QPixmapIconEngineEntry *pe = bestMatch(size, mode, state, false);
+ QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state, false);
if (pe)
pm = pe->pixmap;
@@ -332,7 +357,13 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
{
QSize actualSize;
- if (QPixmapIconEngineEntry *pe = bestMatch(size, mode, state, true))
+
+ // The returned actiual size is the size in device independent pixels,
+ // so we limit the search to scale 1 and assume that e.g. @2x versions
+ // does not proviode extra actual sizes not also provided by the 1x versions.
+ qreal scale = 1;
+
+ if (QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state, true))
actualSize = pe->size;
if (actualSize.isNull())
@@ -361,8 +392,8 @@ QList<QSize> QPixmapIconEngine::availableSizes(QIcon::Mode mode, QIcon::State st
void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
{
if (!pixmap.isNull()) {
- QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), mode, state);
- if(pe && pe->size == pixmap.size()) {
+ QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), pixmap.devicePixelRatio(), mode, state);
+ if (pe && pe->size == pixmap.size() && pe->scale == pixmap.devicePixelRatio()) {
pe->pixmap = pixmap;
pe->fileName.clear();
} else {