MythTV master
mythfontmanager.cpp
Go to the documentation of this file.
1#include <QDir>
2#include <QFileInfo>
3#include <QFontDatabase>
4#include <QList>
5#include <QMutexLocker>
6
8
9#include "mythfontmanager.h"
10
11static MythFontManager *gFontManager = nullptr;
12
13#define LOC QString("MythFontManager: ")
14static constexpr int8_t MAX_DIRS { 100 };
15
29void MythFontManager::LoadFonts(const QString &directory,
30 const QString &registeredFor)
31{
32 int maxDirs = MAX_DIRS;
33 LoadFonts(directory, registeredFor, &maxDirs);
34
35#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
36 QFontDatabase database;
37 QStringList families = database.families();
38#else
39 QStringList families = QFontDatabase::families();
40#endif
41 for (const QString & family : std::as_const(families))
42 {
43 QString result = QString("Font Family '%1': ").arg(family);
44#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
45 QStringList styles = database.styles(family);
46#else
47 QStringList styles = QFontDatabase::styles(family);
48#endif
49 for (const QString & style : std::as_const(styles))
50 {
51 result += QString("%1(").arg(style);
52
53 QString sizes;
54#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
55 QList<int> pointList = database.smoothSizes(family, style);
56#else
57 QList<int> pointList = QFontDatabase::smoothSizes(family, style);
58#endif
59 for (int points : std::as_const(pointList))
60 sizes += QString::number(points) + ' ';
61
62 result += QString("%1) ").arg(sizes.trimmed());
63 }
64
65 LOG(VB_GUI, LOG_DEBUG, LOC + result.trimmed());
66 }
67}
68
81void MythFontManager::LoadFonts(const QString &directory,
82 const QString &registeredFor, int *maxDirs)
83{
84 if (directory.isEmpty() || directory == "/" || registeredFor.isEmpty())
85 return;
86 (*maxDirs)--;
87 if (*maxDirs < 1)
88 {
89 LOG(VB_GENERAL, LOG_WARNING, LOC +
90 "Reached the maximum directory depth "
91 "for a font directory structure. Terminating font scan.");
92 return;
93 }
94
95 // Load the font files from this directory
96 LoadFontsFromDirectory(directory, registeredFor);
97 // Recurse through subdirectories
98 QDir dir(directory);
99 QFileInfoList files = dir.entryInfoList();
100 for (const auto& info : std::as_const(files))
101 {
102 // Skip '.' and '..' and other files starting with "." by checking
103 // baseName()
104 if (!info.baseName().isEmpty() && info.isDir())
105 LoadFonts(info.absoluteFilePath(), registeredFor, maxDirs);
106 if (*maxDirs <= 0)
107 break;
108 }
109}
110
117void MythFontManager::ReleaseFonts(const QString &registeredFor)
118{
119 if (registeredFor.isEmpty())
120 return;
121
122 QMutexLocker locker(&m_lock);
123 for (FontPathToReference::iterator it = m_fontPathToReference.begin();
124 it != m_fontPathToReference.end();)
125 {
126 MythFontReference *fontRef = it.value();
127 if (registeredFor == fontRef->GetRegisteredFor())
128 {
129 LOG(VB_FILE, LOG_DEBUG, LOC +
130 QString("Removing application font '%1'")
131 .arg(fontRef->GetFontPath()));
132
133 it = m_fontPathToReference.erase(it);
134 if (!IsFontFileLoaded(fontRef->GetFontPath()))
135 {
136 if (QFontDatabase::removeApplicationFont(fontRef->GetFontID()))
137 {
138 LOG(VB_FILE, LOG_DEBUG, LOC +
139 QString("Successfully removed application font '%1'")
140 .arg(fontRef->GetFontPath()));
141 }
142 else
143 {
144 LOG(VB_GENERAL, LOG_WARNING, LOC +
145 QString("Unable to remove application font '%1'")
146 .arg(fontRef->GetFontPath()));
147 }
148 }
149 delete fontRef;
150 }
151 else
152 {
153 ++it;
154 }
155 }
156}
157
167void MythFontManager::LoadFontsFromDirectory(const QString &directory,
168 const QString &registeredFor)
169{
170 if (directory.isEmpty() || directory == "/" || registeredFor.isEmpty())
171 return;
172
173 LOG(VB_FILE, LOG_DEBUG, LOC +
174 QString("Scanning directory '%1' for font files.").arg(directory));
175
176 QDir dir(directory);
177 QStringList nameFilters = QStringList() << "*.ttf" << "*.otf" << "*.ttc";
178 QFileInfoList fontFileInfos = dir.entryInfoList(nameFilters);
179 for (const auto & info : std::as_const(fontFileInfos)) {
180 LoadFontFile(info.absoluteFilePath(), registeredFor);
181 }
182}
183
190void MythFontManager::LoadFontFile(const QString &fontPath,
191 const QString &registeredFor)
192{
193 if (fontPath.isEmpty() || fontPath == "/" || registeredFor.isEmpty())
194 return;
195
196 QMutexLocker locker(&m_lock);
197 if (IsFontFileLoaded(fontPath))
198 {
199 LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
200 QString("Font file '%1' already loaded")
201 .arg(fontPath));
202
203 if (!RegisterFont(fontPath, registeredFor))
204 {
205 LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
206 QString("Unable to load font(s) in file '%1'")
207 .arg(fontPath));
208 }
209 }
210 else
211 {
212 LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
213 QString("Loading font file: '%1'").arg(fontPath));
214
215 int result = QFontDatabase::addApplicationFont(fontPath);
216 if (result > -1)
217 {
218 LOG(VB_GUI | VB_FILE, LOG_DEBUG, LOC +
219 QString("In file '%1', found font(s) '%2'")
220 .arg(fontPath,
221 QFontDatabase::applicationFontFamilies(result)
222 .join(", ")));
223
224 if (!RegisterFont(fontPath, registeredFor, result))
225 {
226 LOG(VB_GENERAL, LOG_WARNING, LOC +
227 QString("Unable to register font(s) in file '%1'")
228 .arg(fontPath));
229 }
230 }
231 else
232 {
233 LOG(VB_GENERAL, LOG_WARNING, LOC +
234 QString("Unable to load font(s) in file '%1'")
235 .arg(fontPath));
236 }
237 }
238}
239
248bool MythFontManager::RegisterFont(const QString &fontPath,
249 const QString &registeredFor,
250 const int fontID)
251{
252 int id = fontID;
253 if (id == -1)
254 {
255 QList<MythFontReference*> values;
256 values = m_fontPathToReference.values(fontPath);
257 if (values.isEmpty())
258 return false;
259 MythFontReference *ref = values.first();
260 if (ref == nullptr)
261 return false;
262 id = ref->GetFontID();
263 }
264 auto *fontReference = new MythFontReference(fontPath, registeredFor, id);
265 m_fontPathToReference.insert(fontPath, fontReference);
266 return true;
267}
268
274bool MythFontManager::IsFontFileLoaded(const QString &fontPath)
275{
276 QList<MythFontReference*> values = m_fontPathToReference.values(fontPath);
277 return !values.isEmpty();
278}
279
281{
282 if (!gFontManager)
284 return gFontManager;
285}
286
288{
290}
291
292/* vim: set expandtab tabstop=4 shiftwidth=4: */
void ReleaseFonts(const QString &registeredFor)
Removes the font references for registeredFor, and unloads the application font if it's no longer in ...
bool IsFontFileLoaded(const QString &fontPath)
Checks whether the specified font file has already been loaded.
void LoadFontFile(const QString &fontPath, const QString &registeredFor)
Loads fonts from the file specified in fontPath.
static MythFontManager * GetGlobalFontManager(void)
void LoadFontsFromDirectory(const QString &directory, const QString &registeredFor)
Loads fonts from font files in the specified directory.
FontPathToReference m_fontPathToReference
void LoadFonts(const QString &directory, const QString &registeredFor)
Loads the fonts in font files within the given directory structure.
bool RegisterFont(const QString &fontPath, const QString &registeredFor, int fontID=-1)
Registers the font as being used by registeredFor.
MythFontManager()=default
int GetFontID(void) const
QString GetRegisteredFor(void) const
QString GetFontPath(void) const
#define LOC
static constexpr int8_t MAX_DIRS
MythFontManager * GetGlobalFontManager(void)
static MythFontManager * gFontManager
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
dictionary info
Definition: azlyrics.py:7