diff --git a/src/kiconengine.h b/src/kiconengine.h --- a/src/kiconengine.h +++ b/src/kiconengine.h @@ -84,6 +84,8 @@ private: //TODO KF6: move those into the d-pointer + QPixmap createPixmap(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state); + QString mIconName; QStringList mOverlays; QPointer mIconLoader; diff --git a/src/kiconengine.cpp b/src/kiconengine.cpp --- a/src/kiconengine.cpp +++ b/src/kiconengine.cpp @@ -80,38 +80,52 @@ painter->drawPixmap(rect, pixmap(rect.size() * dpr, mode, state)); } -QPixmap KIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +QPixmap KIconEngine::createPixmap(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state) { Q_UNUSED(state) + if (scale < 1) { + scale = 1; + } + if (size.isEmpty()) { return QPixmap(); } + QSize scaledSize = size / scale; + if (!mIconLoader) { QPixmap pm(size); + pm.setDevicePixelRatio(scale); pm.fill(Qt::transparent); return pm; } - const int kstate = qIconModeToKIconState(mode); - const int iconSize = qMin(size.width(), size.height()); - QPixmap pix = mIconLoader.data()->loadIcon(mIconName, KIconLoader::Desktop, iconSize, kstate, mOverlays); + const int iconSize = qMin(scaledSize.width(), scaledSize.height()); + QPixmap pix = mIconLoader.data()->loadIcon(mIconName, KIconLoader::Desktop, scale, iconSize, kstate, mOverlays); if (pix.size() == size) { return pix; } - QPixmap pix2(size); + // FIXME this stuff down here is broken, either X "Maximum allowed requested length exceeded" with dpr >= 3 + // or the pixmap is just broken (too small, wrongly positioned etc) + QPixmap pix2(size * scale); + pix2.setDevicePixelRatio(scale); pix2.fill(QColor(0, 0, 0, 0)); QPainter painter(&pix2); painter.drawPixmap(QPoint((pix2.width() - pix.width()) / 2, (pix2.height() - pix.height()) / 2), pix); return pix2; } +QPixmap KIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + return createPixmap(size, 1, mode, state); +} + QString KIconEngine::iconName() const { if (!mIconLoader || !mIconLoader->hasIcon(mIconName)) { @@ -166,5 +180,12 @@ #endif *reinterpret_cast(data) = !mIconLoader || !mIconLoader->hasIcon(mIconName); } +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + if (id == QIconEngine::ScaledPixmapHook) { + auto *info = reinterpret_cast(data); + info->pixmap = createPixmap(info->size, info->scale, info->mode, info->state); + return; + } +#endif QIconEngine::virtual_hook(id, data); } diff --git a/src/kiconloader.h b/src/kiconloader.h --- a/src/kiconloader.h +++ b/src/kiconloader.h @@ -244,6 +244,12 @@ QString *path_store = nullptr, bool canReturnNull = false) const; + // FIXME docs + QPixmap loadIcon(const QString &name, KIconLoader::Group group, qreal scale, int size = 0, + int state = KIconLoader::DefaultState, const QStringList &overlays = QStringList(), + QString *path_store = nullptr, + bool canReturnNull = false) const; + /** * Loads an icon for a mimetype. * This is basically like loadIcon except that extra desktop themes are loaded if necessary. diff --git a/src/kiconloader.cpp b/src/kiconloader.cpp --- a/src/kiconloader.cpp +++ b/src/kiconloader.cpp @@ -319,7 +319,7 @@ * icon metadata. Ensure the metadata is normalized first. */ QString makeCacheKey(const QString &name, KIconLoader::Group group, const QStringList &overlays, - int size, int state) const; + int size, qreal scale, int state) const; /** * @internal @@ -336,7 +336,7 @@ * @p size is only used for scalable images, but if non-zero non-scalable * images will be resized anyways. */ - QImage createIconImage(const QString &path, int size = 0, KIconLoader::States state = KIconLoader::DefaultState); + QImage createIconImage(const QString &path, int size = 0, qreal scale = 1.0, KIconLoader::States state = KIconLoader::DefaultState); /** * @internal @@ -848,7 +848,7 @@ } QString KIconLoaderPrivate::makeCacheKey(const QString &name, KIconLoader::Group group, - const QStringList &overlays, int size, int state) const + const QStringList &overlays, int size, qreal scale, int state) const { // The KSharedDataCache is shared so add some namespacing. The following code // uses QStringBuilder (new in Qt 4.6) @@ -859,6 +859,8 @@ % name % QLatin1Char('_') % QString::number(size) + % QLatin1Char('@') + % QString::number(scale) % QLatin1Char('_') % overlays.join(QStringLiteral("_")) % (group >= 0 ? mpEffect.fingerprint(group, state) @@ -918,7 +920,7 @@ return processedContents; } -QImage KIconLoaderPrivate::createIconImage(const QString &path, int size, KIconLoader::States state) +QImage KIconLoaderPrivate::createIconImage(const QString &path, int size, qreal scale, KIconLoader::States state) { //TODO: metadata in the theme to make it do this only if explicitly supported? QScopedPointer reader; @@ -936,7 +938,7 @@ } if (size != 0) { - reader->setScaledSize(QSize(size, size)); + reader->setScaledSize(QSize(size * scale, size * scale)); } return reader->read(); @@ -1242,6 +1244,13 @@ int state, const QStringList &overlays, QString *path_store, bool canReturnNull) const { + return loadIcon(_name, group, 1.0 /*scale*/, size, state, overlays, path_store, canReturnNull); +} + +QPixmap KIconLoader::loadIcon(const QString &_name, KIconLoader::Group group, qreal scale, int size, + int state, const QStringList &overlays, + QString *path_store, bool canReturnNull) const +{ QString name = _name; bool favIconOverlay = false; @@ -1280,12 +1289,14 @@ d->normalizeIconMetadata(group, size, state); // See if the image is already cached. - QString key = d->makeCacheKey(name, group, overlays, size, state); + QString key = d->makeCacheKey(name, group, overlays, size, scale, state); QPixmap pix; + pix.setDevicePixelRatio(scale); + bool iconWasUnknown = false; QString path; - if (d->findCachedPixmapWithPath(key, pix, path)) { + if (d->findCachedPixmapWithPath(key, pix, path)) {// skip cache if (path_store) { *path_store = path; } @@ -1333,7 +1344,7 @@ QImage img; if (!path.isEmpty()) { - img = d->createIconImage(path, size, (KIconLoader::States)state); + img = d->createIconImage(path, size, scale, (KIconLoader::States)state); } if (group >= 0) {