Qt ForkAwesome 0.1.0
Library that bundles ForkAwesome for use within Qt applications
renderer.cpp
Go to the documentation of this file.
1#include "./renderer.h"
2
3#include "resources/config.h"
4
5#include <QFontDatabase>
6#include <QGuiApplication>
7#include <QHash>
8#include <QIcon>
9#include <QPainter>
10
12namespace QtForkAwesome {
13
15
16struct IconOverride {
17 void setIcon(const QIcon &icon);
18 void addIconName(const QString &iconName);
19 const QIcon &locateIcon();
20
21private:
22 QStringList iconNames;
23 QIcon cachedIcon;
24};
25
26void IconOverride::setIcon(const QIcon &icon)
27{
28 iconNames.clear();
29 cachedIcon = icon;
30}
31
32void IconOverride::addIconName(const QString &iconName)
33{
34 iconNames.append(iconName);
35 if (!cachedIcon.isNull()) {
36 cachedIcon = QIcon();
37 }
38}
39
40const QIcon &IconOverride::locateIcon()
41{
42 if (!cachedIcon.isNull()) {
43 return cachedIcon;
44 }
45 for (const auto &iconName : iconNames) {
46 cachedIcon = QIcon::fromTheme(iconName);
47 if (!cachedIcon.isNull()) {
48 return cachedIcon;
49 }
50 }
51 return cachedIcon;
52}
53
54struct Renderer::InternalData {
55 explicit InternalData(int id);
56 static constexpr int invalidId = -1;
57
58 int id;
59 QStringList fontFamilies;
60 QHash<QChar, IconOverride> overrides;
61};
62
63Renderer::InternalData::InternalData(int id)
64 : id(id)
65 , fontFamilies(id != invalidId ? QFontDatabase::applicationFontFamilies(id) : QStringList())
66{
67}
68
70
81Renderer::Renderer(const QString &fontFileName)
82 : m_d(std::make_unique<InternalData>(
83 QFontDatabase::addApplicationFont(fontFileName.isEmpty() ? QStringLiteral(":/" META_FONT_FILE_NAME) : fontFileName)))
84{
85}
86
90Renderer::Renderer(const QByteArray &fontData)
91 : m_d(std::make_unique<InternalData>(QFontDatabase::addApplicationFont(fontData)))
92{
93}
94
99{
100 if (QCoreApplication::instance() && m_d->id != InternalData::invalidId) {
101 QFontDatabase::removeApplicationFont(m_d->id);
102 }
103}
104
108Renderer::operator bool() const
109{
110 return !m_d->fontFamilies.empty();
111}
112
114static void renderInternally(QChar character, QPainter *painter, QFont &&font, const QRect &rect, const QColor &color)
115{
116 font.setPixelSize(rect.height());
117 painter->save();
118 painter->setFont(font);
119 painter->setPen(color);
120 painter->drawText(rect, QString(character), QTextOption(Qt::AlignCenter));
121 painter->restore();
122}
124
128void QtForkAwesome::Renderer::render(QChar character, QPainter *painter, const QRect &rect, const QColor &color) const
129{
130 if (auto override = m_d->overrides.find(character); override != m_d->overrides.end()) {
131 if (const auto &overrideIcon = override->locateIcon(); !overrideIcon.isNull()) {
132 painter->drawPixmap(rect, overrideIcon.pixmap(rect.size(), QIcon::Normal, QIcon::On));
133 return;
134 }
135 }
136 if (*this) {
137 renderInternally(character, painter, QFont(m_d->fontFamilies.front()), rect, color);
138 }
139}
140
144QPixmap QtForkAwesome::Renderer::pixmap(QChar icon, const QSize &size, const QColor &color) const
145{
146 if (auto override = m_d->overrides.find(icon); override != m_d->overrides.end()) {
147 if (const auto &overrideIcon = override->locateIcon(); !overrideIcon.isNull()) {
148 return overrideIcon.pixmap(size, QIcon::Normal, QIcon::On);
149 }
150 }
151
152 const auto scaleFactor =
153#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
154 !QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? 1.0 :
155#endif
156 qGuiApp->devicePixelRatio();
157 const auto scaledSize = QSize(size * scaleFactor);
158 auto pm = QPixmap(scaledSize);
159 pm.fill(QColor(Qt::transparent));
160 if (*this) {
161 auto painter = QPainter(&pm);
162 renderInternally(icon, &painter, QFont(m_d->fontFamilies.front()), QRect(QPoint(), scaledSize), color);
163 }
164 pm.setDevicePixelRatio(scaleFactor);
165 return pm;
166}
167
171QPixmap Renderer::pixmap(Icon icon, const QSize &size, const QColor &color) const
172{
173 return pixmap(QChar(static_cast<IconBaseType>(icon)), size, color);
174}
175
179void Renderer::addThemeOverride(QChar character, const QString &iconNameInTheme)
180{
181 m_d->overrides[character].addIconName(iconNameInTheme);
182}
183
187void Renderer::addOverride(QChar character, const QIcon &override)
188{
189 m_d->overrides[character].setIcon(override);
190}
191
196{
197 m_d->overrides.clear();
198}
199
204{
205 static auto globalRenderer = Renderer();
206 return globalRenderer;
207}
208
209} // namespace QtForkAwesome
Allows rendering a QtForkAwesome::Icon (or an arbitrary QChar using an arbitrary font file).
Definition: renderer.h:21
Renderer(const QString &fontFileName=QString())
Constructs a new renderer with the given fontFileName.
Definition: renderer.cpp:81
static Renderer & global()
Returns the global instance (which is so far only used by the icon engine plugin).
Definition: renderer.cpp:203
void clearOverrides()
Clears all overrides added via addThemeOverride() or addOverride().
Definition: renderer.cpp:195
void addThemeOverride(QChar character, const QString &iconNameInTheme)
Uses the icon from the current icon theme obtained via QIcon::fromTheme() for character if it exists.
Definition: renderer.cpp:179
void addOverride(QChar character, const QIcon &override)
Uses the specified override icon for character if it is not null.
Definition: renderer.cpp:187
~Renderer()
Destructs the renderer.
Definition: renderer.cpp:98
QPixmap pixmap(QChar icon, const QSize &size, const QColor &color) const
Renders the specified character as pixmap of the specified size.
Definition: renderer.cpp:144
void render(QChar character, QPainter *painter, const QRect &rect, const QColor &color) const
Renders the specified icon using the specified painter.
Definition: renderer.cpp:128
Contains classes provided by the QtForkAwesome library.
Definition: renderer.h:19
Icon
The Icon enum specifies a ForkAwesome icon for calling QtForkAwesome::Renderer::render().
Definition: icon.h:11
std::remove_reference_t< decltype(QChar().unicode())> IconBaseType
Definition: iconfwd.h:10