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 
11 static MythFontManager *gFontManager = nullptr;
12 
13 #define LOC QString("MythFontManager: ")
14 static constexpr int8_t MAX_DIRS { 100 };
15 
29 void 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 
81 void 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 
117 void 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 
167 void 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  QStringList fontFiles = dir.entryList(nameFilters);
179  for (const auto & path : std::as_const(fontFiles))
180  LoadFontFile(dir.absoluteFilePath(path), registeredFor);
181 }
182 
189 void MythFontManager::LoadFontFile(const QString &fontPath,
190  const QString &registeredFor)
191 {
192  if (fontPath.isEmpty() || fontPath == "/" || registeredFor.isEmpty())
193  return;
194 
195  QMutexLocker locker(&m_lock);
196  if (IsFontFileLoaded(fontPath))
197  {
198  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
199  QString("Font file '%1' already loaded")
200  .arg(fontPath));
201 
202  if (!RegisterFont(fontPath, registeredFor))
203  {
204  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
205  QString("Unable to load font(s) in file '%1'")
206  .arg(fontPath));
207  }
208  }
209  else
210  {
211  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
212  QString("Loading font file: '%1'").arg(fontPath));
213 
214  int result = QFontDatabase::addApplicationFont(fontPath);
215  if (result > -1)
216  {
217  LOG(VB_GUI | VB_FILE, LOG_DEBUG, LOC +
218  QString("In file '%1', found font(s) '%2'")
219  .arg(fontPath,
220  QFontDatabase::applicationFontFamilies(result)
221  .join(", ")));
222 
223  if (!RegisterFont(fontPath, registeredFor, result))
224  {
225  LOG(VB_GENERAL, LOG_WARNING, LOC +
226  QString("Unable to register font(s) in file '%1'")
227  .arg(fontPath));
228  }
229  }
230  else
231  {
232  LOG(VB_GENERAL, LOG_WARNING, LOC +
233  QString("Unable to load font(s) in file '%1'")
234  .arg(fontPath));
235  }
236  }
237 }
238 
247 bool MythFontManager::RegisterFont(const QString &fontPath,
248  const QString &registeredFor,
249  const int fontID)
250 {
251  int id = fontID;
252  if (id == -1)
253  {
254  QList<MythFontReference*> values;
255  values = m_fontPathToReference.values(fontPath);
256  if (values.isEmpty())
257  return false;
258  MythFontReference *ref = values.first();
259  if (ref == nullptr)
260  return false;
261  id = ref->GetFontID();
262  }
263  auto *fontReference = new MythFontReference(fontPath, registeredFor, id);
264  m_fontPathToReference.insert(fontPath, fontReference);
265  return true;
266 }
267 
273 bool MythFontManager::IsFontFileLoaded(const QString &fontPath)
274 {
275  QList<MythFontReference*> values = m_fontPathToReference.values(fontPath);
276  return !values.isEmpty();
277 }
278 
280 {
281  if (!gFontManager)
283  return gFontManager;
284 }
285 
287 {
289 }
290 
291 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MythFontManager
Definition: mythfontmanager.h:17
LOC
#define LOC
Definition: mythfontmanager.cpp:13
MythFontManager::IsFontFileLoaded
bool IsFontFileLoaded(const QString &fontPath)
Checks whether the specified font file has already been loaded.
Definition: mythfontmanager.cpp:273
MythFontManager::m_lock
QMutex m_lock
Definition: mythfontmanager.h:37
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
mythfontmanager.h
mythlogging.h
MAX_DIRS
static constexpr int8_t MAX_DIRS
Definition: mythfontmanager.cpp:14
MythFontManager::MythFontManager
MythFontManager()=default
GetGlobalFontManager
MythFontManager * GetGlobalFontManager(void)
Definition: mythfontmanager.cpp:286
MythFontManager::RegisterFont
bool RegisterFont(const QString &fontPath, const QString &registeredFor, int fontID=-1)
Registers the font as being used by registeredFor.
Definition: mythfontmanager.cpp:247
gFontManager
static MythFontManager * gFontManager
Definition: mythfontmanager.cpp:11
MythFontManager::LoadFonts
void LoadFonts(const QString &directory, const QString &registeredFor)
Loads the fonts in font files within the given directory structure.
Definition: mythfontmanager.cpp:29
MythFontManager::LoadFontsFromDirectory
void LoadFontsFromDirectory(const QString &directory, const QString &registeredFor)
Loads fonts from font files in the specified directory.
Definition: mythfontmanager.cpp:167
MythFontReference::GetFontPath
QString GetFontPath(void) const
Definition: mythfontmanager.h:53
MythFontManager::m_fontPathToReference
FontPathToReference m_fontPathToReference
Definition: mythfontmanager.h:38
MythFontReference::GetFontID
int GetFontID(void) const
Definition: mythfontmanager.h:55
MythFontManager::ReleaseFonts
void ReleaseFonts(const QString &registeredFor)
Removes the font references for registeredFor, and unloads the application font if it's no longer in ...
Definition: mythfontmanager.cpp:117
MythFontReference::GetRegisteredFor
QString GetRegisteredFor(void) const
Definition: mythfontmanager.h:54
MythFontManager::GetGlobalFontManager
static MythFontManager * GetGlobalFontManager(void)
Definition: mythfontmanager.cpp:279
MythFontManager::LoadFontFile
void LoadFontFile(const QString &fontPath, const QString &registeredFor)
Loads fonts from the file specified in fontPath.
Definition: mythfontmanager.cpp:189
MythFontReference
Definition: mythfontmanager.h:44