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/qabstractfileiconprovider.cpp image/qabstractfileiconprovider.h image/qabstractfileiconprovider_p.h
|
||||||
image/qbitmap.cpp image/qbitmap.h
|
image/qbitmap.cpp image/qbitmap.h
|
||||||
image/qbmphandler.cpp image/qbmphandler_p.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/qicon.cpp image/qicon.h image/qicon_p.h
|
||||||
image/qiconengine.cpp image/qiconengine.h image/qiconengine_p.h
|
image/qiconengine.cpp image/qiconengine.h image/qiconengine_p.h
|
||||||
image/qiconengineplugin.cpp image/qiconengineplugin.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
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
#include "qandroidplatformiconengine.h"
|
#include "qandroidplatformiconengine.h"
|
||||||
|
|
||||||
|
#ifndef QT_NO_ICON
|
||||||
|
|
||||||
#include "androidjnimain.h"
|
#include "androidjnimain.h"
|
||||||
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
@ -214,13 +217,45 @@ static QString fetchFont(const QString &query)
|
|||||||
triedFonts[query] = fontFamily;
|
triedFonts[query] = fontFamily;
|
||||||
return 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
|
} // namespace FontProvider
|
||||||
{
|
|
||||||
if (!QFontInfo(m_iconFont).exactMatch())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
|
static QString getGlyphs(QStringView iconName)
|
||||||
|
{
|
||||||
static constexpr std::pair<QLatin1StringView, QStringView> glyphMap[] = {
|
static constexpr std::pair<QLatin1StringView, QStringView> glyphMap[] = {
|
||||||
{"address-book-new"_L1, u"\ue0e0"},
|
{"address-book-new"_L1, u"\ue0e0"},
|
||||||
{"application-exit"_L1, u"\ue5cd"},
|
{"application-exit"_L1, u"\ue5cd"},
|
||||||
@ -477,139 +512,38 @@ QString QAndroidPlatformIconEngine::glyphs() const
|
|||||||
{"weather-storm"_L1, u"\uf070"},
|
{"weather-storm"_L1, u"\uf070"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){
|
const auto it = std::find_if(std::begin(glyphMap),
|
||||||
return c.first == m_iconName;
|
std::end(glyphMap), [iconName](const auto &c){
|
||||||
|
return c.first == iconName;
|
||||||
});
|
});
|
||||||
return it != std::end(glyphMap) ? it->second.toString()
|
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)
|
QAndroidPlatformIconEngine::QAndroidPlatformIconEngine(const QString &iconName)
|
||||||
: m_iconName(iconName)
|
: QFontIconEngine(iconName, FontProvider::selectFont())
|
||||||
, m_glyphs(glyphs())
|
, 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()
|
QAndroidPlatformIconEngine::~QAndroidPlatformIconEngine() = default;
|
||||||
{}
|
|
||||||
|
|
||||||
QIconEngine *QAndroidPlatformIconEngine::clone() const
|
|
||||||
{
|
|
||||||
return new QAndroidPlatformIconEngine(m_iconName);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QAndroidPlatformIconEngine::key() const
|
QString QAndroidPlatformIconEngine::key() const
|
||||||
{
|
{
|
||||||
return u"QAndroidPlatformIconEngine"_s;
|
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 m_glyphs;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QT_NO_ICON
|
||||||
|
@ -4,41 +4,30 @@
|
|||||||
#ifndef QANDROIDPLATFORMICONENGINE_H
|
#ifndef QANDROIDPLATFORMICONENGINE_H
|
||||||
#define QANDROIDPLATFORMICONENGINE_H
|
#define QANDROIDPLATFORMICONENGINE_H
|
||||||
|
|
||||||
#include <QtGui/qiconengine.h>
|
#include <QtGui/private/qfonticonengine_p.h>
|
||||||
#include <QtGui/qfont.h>
|
|
||||||
|
#ifndef QT_NO_ICON
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QAndroidPlatformIconEngine : public QIconEngine
|
class QAndroidPlatformIconEngine : public QFontIconEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QAndroidPlatformIconEngine(const QString &iconName);
|
QAndroidPlatformIconEngine(const QString &iconName);
|
||||||
~QAndroidPlatformIconEngine();
|
~QAndroidPlatformIconEngine();
|
||||||
QIconEngine *clone() const override;
|
|
||||||
QString key() const override;
|
|
||||||
QString iconName() override;
|
|
||||||
bool isNull() override;
|
|
||||||
|
|
||||||
QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
|
QString key() const override;
|
||||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
QIconEngine *clone() const 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;
|
protected:
|
||||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
QString string() const override;
|
||||||
|
|
||||||
private:
|
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;
|
const QString m_glyphs;
|
||||||
mutable QPixmap m_pixmap;
|
|
||||||
mutable quint64 m_cacheKey = {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QT_NO_ICON
|
||||||
|
|
||||||
#endif // QANDROIDPLATFORMICONENGINE_H
|
#endif // QANDROIDPLATFORMICONENGINE_H
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "qwindowsiconengine.h"
|
#include "qwindowsiconengine.h"
|
||||||
|
|
||||||
|
#ifndef QT_NO_ICON
|
||||||
|
|
||||||
#include <QtCore/qoperatingsystemversion.h>
|
#include <QtCore/qoperatingsystemversion.h>
|
||||||
#include <QtGui/qguiapplication.h>
|
#include <QtGui/qguiapplication.h>
|
||||||
#include <QtGui/qpainter.h>
|
#include <QtGui/qpainter.h>
|
||||||
@ -12,11 +14,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
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[] = {
|
static constexpr std::pair<QLatin1StringView, QStringView> glyphMap[] = {
|
||||||
{"address-book-new"_L1, u"\ue780"},
|
{"address-book-new"_L1, u"\ue780"},
|
||||||
{"application-exit"_L1, u"\ue8bb"},
|
{"application-exit"_L1, u"\ue8bb"},
|
||||||
@ -277,16 +276,17 @@ QString QWindowsIconEngine::glyphs() const
|
|||||||
//{"weather-storm"_L1, u"\uf070"},
|
//{"weather-storm"_L1, u"\uf070"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){
|
const auto it = std::find_if(std::begin(glyphMap),
|
||||||
return c.first == m_iconName;
|
std::end(glyphMap), [iconName](const auto &c){
|
||||||
|
return c.first == iconName;
|
||||||
});
|
});
|
||||||
|
|
||||||
return it != std::end(glyphMap) ? it->second.toString()
|
return it != std::end(glyphMap) ? it->second.toString()
|
||||||
: (m_iconName.length() == 1 ? m_iconName : QString());
|
: (iconName.length() == 1 ? iconName.toString() : QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
auto iconFontFamily()
|
static auto iconFontFamily()
|
||||||
{
|
{
|
||||||
static const bool isWindows11 = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
|
static const bool isWindows11 = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
|
||||||
return isWindows11 ? u"Segoe Fluent Icons"_s
|
return isWindows11 ? u"Segoe Fluent Icons"_s
|
||||||
@ -295,102 +295,30 @@ auto iconFontFamily()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QWindowsIconEngine::QWindowsIconEngine(const QString &iconName)
|
QWindowsIconEngine::QWindowsIconEngine(const QString &iconName)
|
||||||
: m_iconName(iconName), m_iconFont(iconFontFamily())
|
: QFontIconEngine(iconName, iconFontFamily())
|
||||||
, m_glyphs(glyphs())
|
, m_glyphs(getGlyphs(iconName))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindowsIconEngine::~QWindowsIconEngine()
|
QWindowsIconEngine::~QWindowsIconEngine()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
QIconEngine *QWindowsIconEngine::clone() const
|
|
||||||
{
|
|
||||||
return new QWindowsIconEngine(m_iconName);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QWindowsIconEngine::key() const
|
QString QWindowsIconEngine::key() const
|
||||||
{
|
{
|
||||||
return u"QWindowsIconEngine"_s;
|
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 m_glyphs;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif //QT_NO_ICON
|
||||||
|
@ -4,44 +4,30 @@
|
|||||||
#ifndef QWINDOWSICONENGINE_H
|
#ifndef QWINDOWSICONENGINE_H
|
||||||
#define QWINDOWSICONENGINE_H
|
#define QWINDOWSICONENGINE_H
|
||||||
|
|
||||||
#include <QtCore/qt_windows.h>
|
#include <QtGui/private/qfonticonengine_p.h>
|
||||||
|
|
||||||
#include <QtGui/qfont.h>
|
#ifndef QT_NO_ICON
|
||||||
#include <QtGui/qiconengine.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QWindowsIconEngine : public QIconEngine
|
class QWindowsIconEngine : public QFontIconEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QWindowsIconEngine(const QString &iconName);
|
QWindowsIconEngine(const QString &iconName);
|
||||||
~QWindowsIconEngine();
|
~QWindowsIconEngine();
|
||||||
QIconEngine *clone() const override;
|
|
||||||
QString key() const override;
|
|
||||||
QString iconName() override;
|
|
||||||
bool isNull() override;
|
|
||||||
|
|
||||||
QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
|
QString key() const override;
|
||||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
QIconEngine *clone() const 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;
|
protected:
|
||||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
QString string() const override;
|
||||||
|
|
||||||
private:
|
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;
|
const QString m_glyphs;
|
||||||
mutable QPixmap m_pixmap;
|
|
||||||
mutable quint64 m_cacheKey = {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QT_NO_ICON
|
||||||
|
|
||||||
#endif // QWINDOWSICONENGINE_H
|
#endif // QWINDOWSICONENGINE_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user