Refactor shared code of font-based icon engines
Add private QFontIconEngine that renders the glyphs; the specialized engines have to specify the font, and implement the mapping of icon name to glyph sequence (i.e. a QString). Use it for the Android and Windows icon engines. Task-number: QTBUG-102346 Change-Id: I6b0f0d6bc0378ed6918ea7cfb9dcce12ac86e8ab Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
parent
176816f213
commit
2af58490b3
@ -68,6 +68,7 @@ qt_internal_add_module(Gui
|
||||
image/qabstractfileiconprovider.cpp image/qabstractfileiconprovider.h image/qabstractfileiconprovider_p.h
|
||||
image/qbitmap.cpp image/qbitmap.h
|
||||
image/qbmphandler.cpp image/qbmphandler_p.h
|
||||
image/qfonticonengine.cpp image/qfonticonengine_p.h
|
||||
image/qicon.cpp image/qicon.h image/qicon_p.h
|
||||
image/qiconengine.cpp image/qiconengine.h image/qiconengine_p.h
|
||||
image/qiconengineplugin.cpp image/qiconengineplugin.h
|
||||
|
118
src/gui/image/qfonticonengine.cpp
Normal file
118
src/gui/image/qfonticonengine.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qfonticonengine_p.h"
|
||||
|
||||
#ifndef QT_NO_ICON
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qfile.h>
|
||||
#include <QtCore/qset.h>
|
||||
|
||||
#include <QtGui/qfontdatabase.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
#include <QtGui/qpalette.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
QFontIconEngine::QFontIconEngine(const QString &iconName, const QFont &font)
|
||||
: m_iconName(iconName)
|
||||
, m_iconFont(font)
|
||||
{
|
||||
}
|
||||
|
||||
QFontIconEngine::~QFontIconEngine() = default;
|
||||
|
||||
QString QFontIconEngine::iconName()
|
||||
{
|
||||
return m_iconName;
|
||||
}
|
||||
|
||||
bool QFontIconEngine::isNull()
|
||||
{
|
||||
const QString text = string();
|
||||
if (text.isEmpty())
|
||||
return true;
|
||||
const QChar c0 = text.at(0);
|
||||
const QFontMetrics fontMetrics(m_iconFont);
|
||||
if (c0.category() == QChar::Other_Surrogate && text.size() > 1)
|
||||
return !fontMetrics.inFontUcs4(QChar::surrogateToUcs4(c0, text.at(1)));
|
||||
return !fontMetrics.inFont(c0);
|
||||
}
|
||||
|
||||
QList<QSize> QFontIconEngine::availableSizes(QIcon::Mode, QIcon::State)
|
||||
{
|
||||
return {{16, 16}, {24, 24}, {48, 48}, {128, 128}};
|
||||
}
|
||||
|
||||
QSize QFontIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return QIconEngine::actualSize(size, mode, state);
|
||||
}
|
||||
|
||||
QPixmap QFontIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return scaledPixmap(size, mode, state, 1.0);
|
||||
}
|
||||
|
||||
QPixmap QFontIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
|
||||
{
|
||||
const quint64 cacheKey = calculateCacheKey(mode, state);
|
||||
if (cacheKey != m_pixmapCacheKey || m_pixmap.size() != size
|
||||
|| m_pixmap.devicePixelRatio() != scale) {
|
||||
m_pixmap = QPixmap(size * scale);
|
||||
m_pixmap.fill(Qt::transparent);
|
||||
m_pixmap.setDevicePixelRatio(scale);
|
||||
|
||||
if (!m_pixmap.isNull()) {
|
||||
QPainter painter(&m_pixmap);
|
||||
paint(&painter, QRect(QPoint(), size), mode, state);
|
||||
}
|
||||
|
||||
m_pixmapCacheKey = cacheKey;
|
||||
}
|
||||
|
||||
return m_pixmap;
|
||||
}
|
||||
|
||||
void QFontIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
Q_UNUSED(state);
|
||||
|
||||
painter->save();
|
||||
QFont renderFont(m_iconFont);
|
||||
renderFont.setPixelSize(rect.height());
|
||||
painter->setFont(renderFont);
|
||||
|
||||
QPalette palette;
|
||||
switch (mode) {
|
||||
case QIcon::Active:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Normal:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Disabled:
|
||||
painter->setPen(palette.color(QPalette::Disabled, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Selected:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::HighlightedText));
|
||||
break;
|
||||
}
|
||||
|
||||
const QString text = string();
|
||||
|
||||
painter->drawText(rect, Qt::AlignCenter, text);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QString QFontIconEngine::string() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_ICON
|
59
src/gui/image/qfonticonengine_p.h
Normal file
59
src/gui/image/qfonticonengine_p.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QFONTICONENGINE_H
|
||||
#define QFONTICONENGINE_H
|
||||
|
||||
#include <QtGui/qiconengine.h>
|
||||
|
||||
#ifndef QT_NO_ICON
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtGui/qfont.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_GUI_EXPORT QFontIconEngine : public QIconEngine
|
||||
{
|
||||
public:
|
||||
QFontIconEngine(const QString &iconName, const QFont &font);
|
||||
~QFontIconEngine();
|
||||
|
||||
QString iconName() override;
|
||||
bool isNull() override;
|
||||
|
||||
QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
|
||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
|
||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
||||
|
||||
protected:
|
||||
virtual QString string() const;
|
||||
|
||||
private:
|
||||
static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return (quint64(mode) << 32) | state;
|
||||
}
|
||||
|
||||
const QString m_iconName;
|
||||
const QFont m_iconFont;
|
||||
mutable QPixmap m_pixmap;
|
||||
mutable quint64 m_pixmapCacheKey = {};
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_ICON
|
||||
|
||||
#endif // QFONTICONENGINE_H
|
@ -2,6 +2,9 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qandroidplatformiconengine.h"
|
||||
|
||||
#ifndef QT_NO_ICON
|
||||
|
||||
#include "androidjnimain.h"
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
@ -214,13 +217,45 @@ static QString fetchFont(const QString &query)
|
||||
triedFonts[query] = fontFamily;
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
static QFont selectFont()
|
||||
{
|
||||
QString fontFamily;
|
||||
// The MaterialIcons-*.ttf and MaterialSymbols* font files are available from
|
||||
// https://github.com/google/material-design-icons/tree/master. If one of them is
|
||||
// packaged as a resource with the application, then we use it. We prioritize
|
||||
// a variable font.
|
||||
const QStringList fontCandidates = {
|
||||
"MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf",
|
||||
"MaterialSymbolsRounded[FILL,GRAD,opsz,wght].ttf",
|
||||
"MaterialSymbolsSharp[FILL,GRAD,opsz,wght].ttf",
|
||||
"MaterialIcons-Regular.ttf",
|
||||
"MaterialIconsOutlined-Regular.otf",
|
||||
"MaterialIconsRound-Regular.otf",
|
||||
"MaterialIconsSharp-Regular.otf",
|
||||
"MaterialIconsTwoTone-Regular.otf",
|
||||
};
|
||||
for (const auto &fontCandidate : fontCandidates) {
|
||||
fontFamily = FontProvider::fetchFont(u":/qt-project.org/icons/%1"_s.arg(fontCandidate));
|
||||
if (!fontFamily.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise we try to download the Outlined version of Material Symbols
|
||||
const QString key = qEnvironmentVariable("QT_GOOGLE_FONTS_KEY");
|
||||
if (fontFamily.isEmpty() && !key.isEmpty())
|
||||
fontFamily = FontProvider::fetchFont(u"key=%1&name=Material+Symbols+Outlined"_s.arg(key));
|
||||
|
||||
// last resort - use any Material Icons
|
||||
if (fontFamily.isEmpty())
|
||||
fontFamily = u"Material Icons"_s;
|
||||
return QFont(fontFamily);
|
||||
}
|
||||
|
||||
QString QAndroidPlatformIconEngine::glyphs() const
|
||||
{
|
||||
if (!QFontInfo(m_iconFont).exactMatch())
|
||||
return {};
|
||||
} // namespace FontProvider
|
||||
|
||||
static QString getGlyphs(QStringView iconName)
|
||||
{
|
||||
static constexpr std::pair<QLatin1StringView, QStringView> glyphMap[] = {
|
||||
{"address-book-new"_L1, u"\ue0e0"},
|
||||
{"application-exit"_L1, u"\ue5cd"},
|
||||
@ -477,139 +512,38 @@ QString QAndroidPlatformIconEngine::glyphs() const
|
||||
{"weather-storm"_L1, u"\uf070"},
|
||||
};
|
||||
|
||||
const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){
|
||||
return c.first == m_iconName;
|
||||
const auto it = std::find_if(std::begin(glyphMap),
|
||||
std::end(glyphMap), [iconName](const auto &c){
|
||||
return c.first == iconName;
|
||||
});
|
||||
return it != std::end(glyphMap) ? it->second.toString()
|
||||
: (m_iconName.length() == 1 ? m_iconName : QString());
|
||||
: (iconName.length() == 1 ? iconName.toString() : QString());
|
||||
}
|
||||
|
||||
QAndroidPlatformIconEngine::QAndroidPlatformIconEngine(const QString &iconName)
|
||||
: m_iconName(iconName)
|
||||
, m_glyphs(glyphs())
|
||||
: QFontIconEngine(iconName, FontProvider::selectFont())
|
||||
, m_glyphs(getGlyphs(iconName))
|
||||
{
|
||||
QString fontFamily;
|
||||
// The MaterialIcons-*.ttf and MaterialSymbols* font files are available from
|
||||
// https://github.com/google/material-design-icons/tree/master. If one of them is
|
||||
// packaged as a resource with the application, then we use it. We prioritize
|
||||
// a variable font.
|
||||
const QStringList fontCandidates = {
|
||||
"MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf",
|
||||
"MaterialSymbolsRounded[FILL,GRAD,opsz,wght].ttf",
|
||||
"MaterialSymbolsSharp[FILL,GRAD,opsz,wght].ttf",
|
||||
"MaterialIcons-Regular.ttf",
|
||||
"MaterialIconsOutlined-Regular.otf",
|
||||
"MaterialIconsRound-Regular.otf",
|
||||
"MaterialIconsSharp-Regular.otf",
|
||||
"MaterialIconsTwoTone-Regular.otf",
|
||||
};
|
||||
for (const auto &fontCandidate : fontCandidates) {
|
||||
fontFamily = FontProvider::fetchFont(u":/qt-project.org/icons/%1"_s.arg(fontCandidate));
|
||||
if (!fontFamily.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise we try to download the Outlined version of Material Symbols
|
||||
const QString key = qEnvironmentVariable("QT_GOOGLE_FONTS_KEY");
|
||||
if (fontFamily.isEmpty() && !key.isEmpty())
|
||||
fontFamily = FontProvider::fetchFont(u"key=%1&name=Material+Symbols+Outlined"_s.arg(key));
|
||||
|
||||
// last resort - use any Material Icons
|
||||
if (fontFamily.isEmpty())
|
||||
fontFamily = u"Material Icons"_s;
|
||||
m_iconFont = QFont(fontFamily);
|
||||
}
|
||||
|
||||
QAndroidPlatformIconEngine::~QAndroidPlatformIconEngine()
|
||||
{}
|
||||
|
||||
QIconEngine *QAndroidPlatformIconEngine::clone() const
|
||||
{
|
||||
return new QAndroidPlatformIconEngine(m_iconName);
|
||||
}
|
||||
QAndroidPlatformIconEngine::~QAndroidPlatformIconEngine() = default;
|
||||
|
||||
QString QAndroidPlatformIconEngine::key() const
|
||||
{
|
||||
return u"QAndroidPlatformIconEngine"_s;
|
||||
}
|
||||
|
||||
QString QAndroidPlatformIconEngine::iconName()
|
||||
QIconEngine *QAndroidPlatformIconEngine::clone() const
|
||||
{
|
||||
return m_iconName;
|
||||
QAndroidPlatformIconEngine *that = const_cast<QAndroidPlatformIconEngine *>(this);
|
||||
return new QAndroidPlatformIconEngine(that->iconName());
|
||||
}
|
||||
|
||||
bool QAndroidPlatformIconEngine::isNull()
|
||||
QString QAndroidPlatformIconEngine::string() const
|
||||
{
|
||||
if (m_glyphs.isEmpty())
|
||||
return true;
|
||||
const QChar c0 = m_glyphs.at(0);
|
||||
const QFontMetrics fontMetrics(m_iconFont);
|
||||
if (c0.category() == QChar::Other_Surrogate && m_glyphs.size() > 1)
|
||||
return !fontMetrics.inFontUcs4(QChar::surrogateToUcs4(c0, m_glyphs.at(1)));
|
||||
return !fontMetrics.inFont(c0);
|
||||
}
|
||||
|
||||
QList<QSize> QAndroidPlatformIconEngine::availableSizes(QIcon::Mode, QIcon::State)
|
||||
{
|
||||
return {{16, 16}, {24, 24}, {48, 48}, {128, 128}};
|
||||
}
|
||||
|
||||
QSize QAndroidPlatformIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return QIconEngine::actualSize(size, mode, state);
|
||||
}
|
||||
|
||||
QPixmap QAndroidPlatformIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return scaledPixmap(size, mode, state, 1.0);
|
||||
}
|
||||
|
||||
QPixmap QAndroidPlatformIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
|
||||
{
|
||||
const quint64 cacheKey = calculateCacheKey(mode, state);
|
||||
if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
|
||||
m_pixmap = QPixmap(size * scale);
|
||||
m_pixmap.fill(Qt::transparent);
|
||||
m_pixmap.setDevicePixelRatio(scale);
|
||||
|
||||
if (!m_pixmap.isNull()) {
|
||||
QPainter painter(&m_pixmap);
|
||||
paint(&painter, QRect(QPoint(), size), mode, state);
|
||||
}
|
||||
|
||||
m_cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
return m_pixmap;
|
||||
}
|
||||
|
||||
void QAndroidPlatformIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
Q_UNUSED(state);
|
||||
|
||||
painter->save();
|
||||
QFont renderFont(m_iconFont);
|
||||
renderFont.setPixelSize(rect.height());
|
||||
painter->setFont(renderFont);
|
||||
|
||||
QPalette palette;
|
||||
switch (mode) {
|
||||
case QIcon::Active:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Normal:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Disabled:
|
||||
painter->setPen(palette.color(QPalette::Disabled, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Selected:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::HighlightedText));
|
||||
break;
|
||||
}
|
||||
|
||||
painter->drawText(rect, Qt::AlignCenter, m_glyphs);
|
||||
painter->restore();
|
||||
return m_glyphs;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_ICON
|
||||
|
@ -4,41 +4,30 @@
|
||||
#ifndef QANDROIDPLATFORMICONENGINE_H
|
||||
#define QANDROIDPLATFORMICONENGINE_H
|
||||
|
||||
#include <QtGui/qiconengine.h>
|
||||
#include <QtGui/qfont.h>
|
||||
#include <QtGui/private/qfonticonengine_p.h>
|
||||
|
||||
#ifndef QT_NO_ICON
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformIconEngine : public QIconEngine
|
||||
class QAndroidPlatformIconEngine : public QFontIconEngine
|
||||
{
|
||||
public:
|
||||
QAndroidPlatformIconEngine(const QString &iconName);
|
||||
~QAndroidPlatformIconEngine();
|
||||
QIconEngine *clone() const override;
|
||||
QString key() const override;
|
||||
QString iconName() override;
|
||||
bool isNull() override;
|
||||
|
||||
QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
|
||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
|
||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
||||
QString key() const override;
|
||||
QIconEngine *clone() const override;
|
||||
|
||||
protected:
|
||||
QString string() const override;
|
||||
|
||||
private:
|
||||
static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return (quint64(mode) << 32) | state;
|
||||
}
|
||||
QString glyphs() const;
|
||||
|
||||
const QString m_iconName;
|
||||
QFont m_iconFont;
|
||||
const QString m_glyphs;
|
||||
mutable QPixmap m_pixmap;
|
||||
mutable quint64 m_cacheKey = {};
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_ICON
|
||||
|
||||
#endif // QANDROIDPLATFORMICONENGINE_H
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "qwindowsiconengine.h"
|
||||
|
||||
#ifndef QT_NO_ICON
|
||||
|
||||
#include <QtCore/qoperatingsystemversion.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
@ -12,11 +14,8 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
QString QWindowsIconEngine::glyphs() const
|
||||
static QString getGlyphs(QStringView iconName)
|
||||
{
|
||||
if (!QFontInfo(m_iconFont).exactMatch())
|
||||
return {};
|
||||
|
||||
static constexpr std::pair<QLatin1StringView, QStringView> glyphMap[] = {
|
||||
{"address-book-new"_L1, u"\ue780"},
|
||||
{"application-exit"_L1, u"\ue8bb"},
|
||||
@ -277,16 +276,17 @@ QString QWindowsIconEngine::glyphs() const
|
||||
//{"weather-storm"_L1, u"\uf070"},
|
||||
};
|
||||
|
||||
const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){
|
||||
return c.first == m_iconName;
|
||||
const auto it = std::find_if(std::begin(glyphMap),
|
||||
std::end(glyphMap), [iconName](const auto &c){
|
||||
return c.first == iconName;
|
||||
});
|
||||
|
||||
return it != std::end(glyphMap) ? it->second.toString()
|
||||
: (m_iconName.length() == 1 ? m_iconName : QString());
|
||||
: (iconName.length() == 1 ? iconName.toString() : QString());
|
||||
}
|
||||
|
||||
namespace {
|
||||
auto iconFontFamily()
|
||||
static auto iconFontFamily()
|
||||
{
|
||||
static const bool isWindows11 = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
|
||||
return isWindows11 ? u"Segoe Fluent Icons"_s
|
||||
@ -295,102 +295,30 @@ auto iconFontFamily()
|
||||
}
|
||||
|
||||
QWindowsIconEngine::QWindowsIconEngine(const QString &iconName)
|
||||
: m_iconName(iconName), m_iconFont(iconFontFamily())
|
||||
, m_glyphs(glyphs())
|
||||
: QFontIconEngine(iconName, iconFontFamily())
|
||||
, m_glyphs(getGlyphs(iconName))
|
||||
{
|
||||
}
|
||||
|
||||
QWindowsIconEngine::~QWindowsIconEngine()
|
||||
{}
|
||||
|
||||
QIconEngine *QWindowsIconEngine::clone() const
|
||||
{
|
||||
return new QWindowsIconEngine(m_iconName);
|
||||
}
|
||||
|
||||
QString QWindowsIconEngine::key() const
|
||||
{
|
||||
return u"QWindowsIconEngine"_s;
|
||||
}
|
||||
|
||||
QString QWindowsIconEngine::iconName()
|
||||
QIconEngine *QWindowsIconEngine::clone() const
|
||||
{
|
||||
return m_iconName;
|
||||
QWindowsIconEngine *that = const_cast<QWindowsIconEngine *>(this);
|
||||
return new QWindowsIconEngine(that->iconName());
|
||||
}
|
||||
|
||||
bool QWindowsIconEngine::isNull()
|
||||
QString QWindowsIconEngine::string() const
|
||||
{
|
||||
if (m_glyphs.isEmpty())
|
||||
return true;
|
||||
|
||||
const QChar c0 = m_glyphs.at(0);
|
||||
const QFontMetrics fontMetrics(m_iconFont);
|
||||
if (c0.category() == QChar::Other_Surrogate && m_glyphs.size() > 1)
|
||||
return !fontMetrics.inFontUcs4(QChar::surrogateToUcs4(c0, m_glyphs.at(1)));
|
||||
return !fontMetrics.inFont(c0);
|
||||
}
|
||||
|
||||
QList<QSize> QWindowsIconEngine::availableSizes(QIcon::Mode, QIcon::State)
|
||||
{
|
||||
return {{16, 16}, {24, 24}, {48, 48}, {128, 128}};
|
||||
}
|
||||
|
||||
QSize QWindowsIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return QIconEngine::actualSize(size, mode, state);
|
||||
}
|
||||
|
||||
QPixmap QWindowsIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return scaledPixmap(size, mode, state, 1.0);
|
||||
}
|
||||
|
||||
QPixmap QWindowsIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
|
||||
{
|
||||
const quint64 cacheKey = calculateCacheKey(mode, state);
|
||||
if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
|
||||
m_pixmap = QPixmap(size * scale);
|
||||
m_pixmap.fill(Qt::transparent);
|
||||
m_pixmap.setDevicePixelRatio(scale);
|
||||
|
||||
if (!m_pixmap.isNull()) {
|
||||
QPainter painter(&m_pixmap);
|
||||
paint(&painter, QRect(QPoint(), size), mode, state);
|
||||
}
|
||||
|
||||
m_cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
return m_pixmap;
|
||||
}
|
||||
|
||||
void QWindowsIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
Q_UNUSED(state);
|
||||
|
||||
painter->save();
|
||||
QFont renderFont(m_iconFont);
|
||||
renderFont.setPixelSize(rect.height());
|
||||
painter->setFont(renderFont);
|
||||
|
||||
QPalette palette;
|
||||
switch (mode) {
|
||||
case QIcon::Active:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Normal:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Disabled:
|
||||
painter->setPen(palette.color(QPalette::Disabled, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Selected:
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::HighlightedText));
|
||||
break;
|
||||
}
|
||||
|
||||
painter->drawText(rect, Qt::AlignCenter, m_glyphs);
|
||||
painter->restore();
|
||||
return m_glyphs;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif //QT_NO_ICON
|
||||
|
@ -4,44 +4,30 @@
|
||||
#ifndef QWINDOWSICONENGINE_H
|
||||
#define QWINDOWSICONENGINE_H
|
||||
|
||||
#include <QtCore/qt_windows.h>
|
||||
#include <QtGui/private/qfonticonengine_p.h>
|
||||
|
||||
#include <QtGui/qfont.h>
|
||||
#include <QtGui/qiconengine.h>
|
||||
#ifndef QT_NO_ICON
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWindowsIconEngine : public QIconEngine
|
||||
class QWindowsIconEngine : public QFontIconEngine
|
||||
{
|
||||
public:
|
||||
QWindowsIconEngine(const QString &iconName);
|
||||
~QWindowsIconEngine();
|
||||
QIconEngine *clone() const override;
|
||||
QString key() const override;
|
||||
QString iconName() override;
|
||||
bool isNull() override;
|
||||
|
||||
QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
|
||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
|
||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
||||
QString key() const override;
|
||||
QIconEngine *clone() const override;
|
||||
|
||||
protected:
|
||||
QString string() const override;
|
||||
|
||||
private:
|
||||
static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return (quint64(mode) << 32) | state;
|
||||
}
|
||||
|
||||
QString glyphs() const;
|
||||
|
||||
const QString m_iconName;
|
||||
const QFont m_iconFont;
|
||||
const QString m_glyphs;
|
||||
mutable QPixmap m_pixmap;
|
||||
mutable quint64 m_cacheKey = {};
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_ICON
|
||||
|
||||
#endif // QWINDOWSICONENGINE_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user