diff options
Diffstat (limited to 'src/gui/image/qiconloader.cpp')
-rw-r--r-- | src/gui/image/qiconloader.cpp | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 324f13a17b..d72c05a3c5 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -47,6 +47,7 @@ #include <qpa/qplatformtheme.h> #include <QtGui/QIconEngine> #include <QtGui/QPalette> +#include <QtCore/qmath.h> #include <QtCore/QList> #include <QtCore/QDir> #include <QtCore/QSettings> @@ -347,6 +348,10 @@ QIconTheme::QIconTheme(const QString &themeName) dirInfo.maxSize = indexReader.value(directoryKey + QLatin1String("/MaxSize"), size).toInt(); + + dirInfo.scale = indexReader.value(directoryKey + + QLatin1String("/Scale"), + 1).toInt(); m_keyList.append(dirInfo); } } @@ -553,8 +558,11 @@ void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect, * This algorithm is defined by the freedesktop spec: * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html */ -static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize) +static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize, int iconscale) { + if (dir.scale != iconscale) + return false; + if (dir.type == QIconDirInfo::Fixed) { return dir.size == iconsize; @@ -575,24 +583,25 @@ static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize) * This algorithm is defined by the freedesktop spec: * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html */ -static int directorySizeDistance(const QIconDirInfo &dir, int iconsize) +static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int iconscale) { + const int scaledIconSize = iconsize * iconscale; if (dir.type == QIconDirInfo::Fixed) { - return qAbs(dir.size - iconsize); + return qAbs(dir.size * dir.scale - scaledIconSize); } else if (dir.type == QIconDirInfo::Scalable) { - if (iconsize < dir.minSize) - return dir.minSize - iconsize; - else if (iconsize > dir.maxSize) - return iconsize - dir.maxSize; + if (scaledIconSize < dir.minSize * dir.scale) + return dir.minSize * dir.scale - scaledIconSize; + else if (scaledIconSize > dir.maxSize * dir.scale) + return scaledIconSize - dir.maxSize * dir.scale; else return 0; } else if (dir.type == QIconDirInfo::Threshold) { - if (iconsize < dir.size - dir.threshold) - return dir.minSize - iconsize; - else if (iconsize > dir.size + dir.threshold) - return iconsize - dir.maxSize; + if (scaledIconSize < (dir.size - dir.threshold) * dir.scale) + return dir.minSize * dir.scale - scaledIconSize; + else if (scaledIconSize > (dir.size + dir.threshold) * dir.scale) + return scaledIconSize - dir.maxSize * dir.scale; else return 0; } @@ -600,7 +609,7 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize) return INT_MAX; } -QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size) +QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int scale) { int iconsize = qMin(size.width(), size.height()); @@ -612,7 +621,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size) // Search for exact matches first for (int i = 0; i < numEntries; ++i) { QIconLoaderEngineEntry *entry = m_info.entries.at(i); - if (directoryMatchesSize(entry->dir, iconsize)) { + if (directoryMatchesSize(entry->dir, iconsize, scale)) { return entry; } } @@ -622,7 +631,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size) QIconLoaderEngineEntry *closestMatch = 0; for (int i = 0; i < numEntries; ++i) { QIconLoaderEngineEntry *entry = m_info.entries.at(i); - int distance = directorySizeDistance(entry->dir, iconsize); + int distance = directorySizeDistance(entry->dir, iconsize, scale); if (distance < minimalSize) { minimalSize = distance; closestMatch = entry; @@ -665,6 +674,8 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st basePixmap.load(filename); QSize actualSize = basePixmap.size(); + // If the size of the best match we have (basePixmap) is larger than the + // requested size, we downscale it to match. if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height())) actualSize.scale(size, Qt::KeepAspectRatio); @@ -748,6 +759,15 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) *reinterpret_cast<bool*>(data) = m_info.entries.isEmpty(); } break; + case QIconEngine::ScaledPixmapHook: + { + QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast<QIconEngine::ScaledPixmapArgument*>(data); + // QIcon::pixmap() multiplies size by the device pixel ratio. + const int integerScale = qCeil(arg.scale); + QIconLoaderEngineEntry *entry = entryForSize(arg.size / integerScale, integerScale); + arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap(); + } + break; default: QIconEngine::virtual_hook(id, data); } |