From 12694cfc1693c1fd7bf89d6587666001ff15bb4d Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 6 Dec 2023 18:10:43 +0100 Subject: [PATCH] QIcon: clean up Windows and Android icon engines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use good old QString for the list of glyphs, and just render what we get. The use case where we need to draw multiple symbols on top of each other is (for now) academic, and we can support emojis just with QString. Proof the latter point by mapping "banana" to the respective emoji. Change-Id: I8005a99f015e6eb2a2a635f9d892163f2008a673 Reviewed-by: Tor Arne Vestbø Reviewed-by: Qt CI Bot --- .../android/qandroidplatformiconengine.cpp | 48 ++++++++--------- .../android/qandroidplatformiconengine.h | 12 +---- .../platforms/windows/qwindowsiconengine.cpp | 51 +++++++++---------- .../platforms/windows/qwindowsiconengine.h | 13 ++--- 4 files changed, 54 insertions(+), 70 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformiconengine.cpp b/src/plugins/platforms/android/qandroidplatformiconengine.cpp index 5c07de2319..fdf12f2c83 100644 --- a/src/plugins/platforms/android/qandroidplatformiconengine.cpp +++ b/src/plugins/platforms/android/qandroidplatformiconengine.cpp @@ -219,29 +219,31 @@ static QString fetchFont(const QString &query) } } -QAndroidPlatformIconEngine::Glyphs QAndroidPlatformIconEngine::glyphs() const +QString QAndroidPlatformIconEngine::glyphs() const { if (!QFontInfo(m_iconFont).exactMatch()) return {}; - static constexpr std::pair glyphMap[] = { - {u"edit-clear", 0xe872}, - {u"edit-copy", 0xe14d}, - {u"edit-cut", 0xe14e}, - {u"edit-delete", 0xe14a}, - {u"edit-find", 0xe8b6}, - {u"edit-find-replace", 0xe881}, - {u"edit-paste", 0xe14f}, - {u"edit-redo", 0xe15a}, - {u"edit-select-all", 0xe162}, - {u"edit-undo", 0xe166}, - {u"printer", 0xe8ad}, + static constexpr std::pair glyphMap[] = { + {QIcon::ThemeIcon::EditClear, u"\ue872"}, + {QIcon::ThemeIcon::EditCopy, u"\ue14d"}, + {QIcon::ThemeIcon::EditCut, u"\ue14e"}, + {QIcon::ThemeIcon::EditDelete, u"\ue14a"}, + {QIcon::ThemeIcon::EditFind, u"\ue8b6"}, + {QIcon::ThemeIcon::EditFindReplace, u"\ue881"}, + {QIcon::ThemeIcon::EditPaste, u"\ue14f"}, + {QIcon::ThemeIcon::EditRedo, u"\ue15a"}, + {QIcon::ThemeIcon::EditSelectAll, u"\ue162"}, + {QIcon::ThemeIcon::EditUndo, u"\ue166"}, + {QIcon::ThemeIcon::Printer, u"\ue8ad"}, + {QLatin1StringView("banana"), u"🍌"}, }; const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){ return c.first == m_iconName; }); - return it != std::end(glyphMap) ? it->second : Glyphs(); + return it != std::end(glyphMap) ? it->second.toString() + : (m_iconName.length() == 1 ? m_iconName : QString()); } QAndroidPlatformIconEngine::QAndroidPlatformIconEngine(const QString &iconName) @@ -284,7 +286,13 @@ QString QAndroidPlatformIconEngine::iconName() bool QAndroidPlatformIconEngine::isNull() { - return m_glyphs.isNull() || !QFontMetrics(m_iconFont).inFont(m_glyphs.codepoints[0]); + 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 QAndroidPlatformIconEngine::availableSizes(QIcon::Mode, QIcon::State) @@ -332,15 +340,7 @@ QPixmap QAndroidPlatformIconEngine::scaledPixmap(const QSize &size, QIcon::Mode } const QRect rect({0, 0}, size); - if (m_glyphs.codepoints[0] == QChar(0xffff)) { - painter.drawText(rect, Qt::AlignCenter, QString(m_glyphs.codepoints + 1, 2)); - } else { - for (const auto &glyph : m_glyphs.codepoints) { - if (glyph.isNull()) - break; - painter.drawText(rect, glyph); - } - } + painter.drawText(rect, Qt::AlignCenter, m_glyphs); m_cacheKey = cacheKey; } diff --git a/src/plugins/platforms/android/qandroidplatformiconengine.h b/src/plugins/platforms/android/qandroidplatformiconengine.h index 275c01a294..cac54481d9 100644 --- a/src/plugins/platforms/android/qandroidplatformiconengine.h +++ b/src/plugins/platforms/android/qandroidplatformiconengine.h @@ -30,19 +30,11 @@ private: { return (quint64(mode) << 32) | state; } - struct Glyphs - { - constexpr Glyphs(char16_t g1 = 0, char16_t g2 = 0, char16_t g3 = 0) noexcept - : codepoints{g1, g2, g3} - {} - constexpr bool isNull() const noexcept { return codepoints[0].isNull(); } - const QChar codepoints[3] = {}; - }; - Glyphs glyphs() const; + QString glyphs() const; const QString m_iconName; QFont m_iconFont; - const Glyphs m_glyphs; + const QString m_glyphs; mutable QPixmap m_pixmap; mutable quint64 m_cacheKey = {}; }; diff --git a/src/plugins/platforms/windows/qwindowsiconengine.cpp b/src/plugins/platforms/windows/qwindowsiconengine.cpp index 7e355b168b..e371af706b 100644 --- a/src/plugins/platforms/windows/qwindowsiconengine.cpp +++ b/src/plugins/platforms/windows/qwindowsiconengine.cpp @@ -12,31 +12,31 @@ QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -QWindowsIconEngine::Glyphs QWindowsIconEngine::glyphs() const +QString QWindowsIconEngine::glyphs() const { if (!QFontInfo(m_iconFont).exactMatch()) return {}; - static constexpr std::pair glyphMap[] = { - {u"edit-clear", 0xe894}, - {u"edit-copy", 0xe8c8}, - {u"edit-cut", 0xe8c6}, - {u"edit-delete", 0xe74d}, - {u"edit-find", 0xe721}, - {u"edit-find-replace", Glyphs(0xeb51, 0xeb52)}, - {u"edit-paste", 0xe77f}, - {u"edit-redo", 0xe7a6}, - {u"edit-select-all", 0xe8b3}, - {u"edit-undo", 0xe7a7}, - {u"printer", 0xe749}, - {u"red-heart", Glyphs(0x2764, 0xFE0F)}, - {u"banana", Glyphs(0xffff, 0xD83C, 0xDF4C)}, + static constexpr std::pair glyphMap[] = { + {QIcon::ThemeIcon::EditClear, u"\ue894"}, + {QIcon::ThemeIcon::EditCopy, u"\ue8c8"}, + {QIcon::ThemeIcon::EditCut, u"\ue8c6"}, + {QIcon::ThemeIcon::EditDelete, u"\ue74d"}, + {QIcon::ThemeIcon::EditFind, u"\ue721"}, + {QIcon::ThemeIcon::EditPaste, u"\ue77f"}, + {QIcon::ThemeIcon::EditRedo, u"\ue7a6"}, + {QIcon::ThemeIcon::EditSelectAll, u"\ue8b3"}, + {QIcon::ThemeIcon::EditUndo, u"\ue7a7"}, + {QIcon::ThemeIcon::Printer, u"\ue749"}, + {QLatin1StringView("banana"), u"🍌"}, }; const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){ return c.first == m_iconName; }); - return it != std::end(glyphMap) ? it->second : Glyphs(); + + return it != std::end(glyphMap) ? it->second.toString() + : (m_iconName.length() == 1 ? m_iconName : QString()); } namespace { @@ -74,7 +74,14 @@ QString QWindowsIconEngine::iconName() bool QWindowsIconEngine::isNull() { - return m_glyphs.isNull(); + 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 QWindowsIconEngine::availableSizes(QIcon::Mode, QIcon::State) @@ -122,15 +129,7 @@ QPixmap QWindowsIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QI } const QRect rect({0, 0}, size); - if (m_glyphs.codepoints[0] == QChar(0xffff)) { - painter.drawText(rect, Qt::AlignCenter, QString(m_glyphs.codepoints + 1, 2)); - } else { - for (const auto &glyph : m_glyphs.codepoints) { - if (glyph.isNull()) - break; - painter.drawText(rect, glyph); - } - } + painter.drawText(rect, Qt::AlignCenter, m_glyphs); m_cacheKey = cacheKey; } diff --git a/src/plugins/platforms/windows/qwindowsiconengine.h b/src/plugins/platforms/windows/qwindowsiconengine.h index ac16ff8073..3c6cbddb8b 100644 --- a/src/plugins/platforms/windows/qwindowsiconengine.h +++ b/src/plugins/platforms/windows/qwindowsiconengine.h @@ -32,19 +32,12 @@ private: { return (quint64(mode) << 32) | state; } - struct Glyphs - { - constexpr Glyphs(char16_t g1 = 0, char16_t g2 = 0, char16_t g3 = 0) noexcept - : codepoints{g1, g2, g3} - {} - constexpr bool isNull() const noexcept { return codepoints[0].isNull(); } - const QChar codepoints[3] = {}; - }; - Glyphs glyphs() const; + + QString glyphs() const; const QString m_iconName; const QFont m_iconFont; - const Glyphs m_glyphs; + const QString m_glyphs; mutable QPixmap m_pixmap; mutable quint64 m_cacheKey = {}; };