00001 #include <QDir>
00002 #include <QFileInfo>
00003 #include <QFontDatabase>
00004 #include <QList>
00005 #include <QMutexLocker>
00006
00007 #include "mythfontmanager.h"
00008 #include "mythlogging.h"
00009
00010 static MythFontManager *gFontManager = NULL;
00011
00012 #define LOC QString("MythFontManager: ")
00013 #define MAX_DIRS 100
00014
00028 void MythFontManager::LoadFonts(const QString &directory,
00029 const QString ®isteredFor)
00030 {
00031 int maxDirs = MAX_DIRS;
00032 LoadFonts(directory, registeredFor, &maxDirs);
00033 }
00034
00047 void MythFontManager::LoadFonts(const QString &directory,
00048 const QString ®isteredFor, int *maxDirs)
00049 {
00050 if (directory.isEmpty() || directory == "/" || registeredFor.isEmpty())
00051 return;
00052 (*maxDirs)--;
00053 if (*maxDirs < 1)
00054 {
00055 LOG(VB_GENERAL, LOG_WARNING, LOC +
00056 "Reached the maximum directory depth "
00057 "for a font directory structure. Terminating font scan.");
00058 return;
00059 }
00060
00061
00062 LoadFontsFromDirectory(directory, registeredFor);
00063
00064 QDir dir(directory);
00065 QFileInfoList files = dir.entryInfoList();
00066 QFileInfo info;
00067 for (QFileInfoList::const_iterator it = files.begin();
00068 ((it != files.end()) && (*maxDirs > 0)); ++it)
00069 {
00070 info = *it;
00071
00072
00073 if (!info.baseName().isEmpty() && info.isDir())
00074 LoadFonts(info.absoluteFilePath(), registeredFor, maxDirs);
00075 }
00076 }
00077
00084 void MythFontManager::ReleaseFonts(const QString ®isteredFor)
00085 {
00086 if (registeredFor.isEmpty())
00087 return;
00088
00089 QMutexLocker locker(&m_lock);
00090 for (FontPathToReference::iterator it = m_fontPathToReference.begin();
00091 it != m_fontPathToReference.end();)
00092 {
00093 MythFontReference *fontRef = it.value();
00094 if (registeredFor == fontRef->GetRegisteredFor())
00095 {
00096 LOG(VB_FILE, LOG_DEBUG, LOC +
00097 QString("Removing application font '%1'")
00098 .arg(fontRef->GetFontPath()));
00099
00100 it = m_fontPathToReference.erase(it);
00101 if (!IsFontFileLoaded(fontRef->GetFontPath()))
00102 {
00103 if (QFontDatabase::removeApplicationFont(fontRef->GetFontID()))
00104 {
00105 LOG(VB_FILE, LOG_DEBUG, LOC +
00106 QString("Successfully removed application font '%1'")
00107 .arg(fontRef->GetFontPath()));
00108 }
00109 else
00110 {
00111 LOG(VB_GENERAL, LOG_WARNING, LOC +
00112 QString("Unable to remove application font '%1'")
00113 .arg(fontRef->GetFontPath()));
00114 }
00115 }
00116 delete fontRef;
00117 }
00118 else
00119 {
00120 ++it;
00121 }
00122 }
00123 }
00124
00134 void MythFontManager::LoadFontsFromDirectory(const QString &directory,
00135 const QString ®isteredFor)
00136 {
00137 if (directory.isEmpty() || directory == "/" || registeredFor.isEmpty())
00138 return;
00139
00140 LOG(VB_FILE, LOG_DEBUG, LOC +
00141 QString("Scanning directory '%1' for font files.").arg(directory));
00142
00143 QDir dir(directory);
00144 QStringList nameFilters = QStringList() << "*.ttf" << "*.otf" << "*.ttc";
00145 QStringList fontFiles = dir.entryList(nameFilters);
00146 for (QStringList::const_iterator it = fontFiles.begin();
00147 it != fontFiles.end(); ++it)
00148 {
00149 LoadFontFile(dir.absoluteFilePath(*it), registeredFor);
00150 }
00151 }
00152
00159 void MythFontManager::LoadFontFile(const QString &fontPath,
00160 const QString ®isteredFor)
00161 {
00162 if (fontPath.isEmpty() || fontPath == "/" || registeredFor.isEmpty())
00163 return;
00164
00165 QMutexLocker locker(&m_lock);
00166 if (IsFontFileLoaded(fontPath))
00167 {
00168 LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
00169 QString("Font file '%1' already loaded")
00170 .arg(fontPath));
00171
00172 if (!RegisterFont(fontPath, registeredFor))
00173 {
00174 LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
00175 QString("Unable to load font(s) in file '%1'")
00176 .arg(fontPath));
00177 }
00178 }
00179 else
00180 {
00181 LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
00182 QString("Loading font file: '%1'").arg(fontPath));
00183
00184 int result = QFontDatabase::addApplicationFont(fontPath);
00185 if (result > -1)
00186 {
00187 LOG(VB_GUI | VB_FILE, LOG_DEBUG, LOC +
00188 QString("In file '%1', found font(s) '%2'")
00189 .arg(fontPath)
00190 .arg(QFontDatabase::applicationFontFamilies(result)
00191 .join(", ")));
00192
00193 if (!RegisterFont(fontPath, registeredFor, result))
00194 {
00195 LOG(VB_GENERAL, LOG_WARNING, LOC +
00196 QString("Unable to register font(s) in file '%1'")
00197 .arg(fontPath));
00198 }
00199 }
00200 else
00201 {
00202 LOG(VB_GENERAL, LOG_WARNING, LOC +
00203 QString("Unable to load font(s) in file '%1'")
00204 .arg(fontPath));
00205 }
00206 }
00207 }
00208
00215 bool MythFontManager::RegisterFont(const QString &fontPath,
00216 const QString ®isteredFor,
00217 const int fontID)
00218 {
00219 int id = fontID;
00220 if (id == -1)
00221 {
00222 QList<MythFontReference*> values;
00223 values = m_fontPathToReference.values(fontPath);
00224 if (values.isEmpty())
00225 return false;
00226 MythFontReference *ref = values.first();
00227 if (ref == NULL)
00228 return false;
00229 else
00230 id = ref->GetFontID();
00231 }
00232 MythFontReference *fontReference;
00233 fontReference = new MythFontReference(fontPath, registeredFor, id);
00234 m_fontPathToReference.insert(fontPath, fontReference);
00235 return true;
00236 }
00237
00243 bool MythFontManager::IsFontFileLoaded(const QString &fontPath)
00244 {
00245 QList<MythFontReference*> values = m_fontPathToReference.values(fontPath);
00246 return !values.isEmpty();
00247 }
00248
00249 MythFontManager *MythFontManager::GetGlobalFontManager(void)
00250 {
00251 if (!gFontManager)
00252 gFontManager = new MythFontManager();
00253 return gFontManager;
00254 }
00255
00256 MythFontManager *GetGlobalFontManager(void)
00257 {
00258 return MythFontManager::GetGlobalFontManager();
00259 }
00260
00261 MythFontReference::MythFontReference(const QString &fontPath,
00262 const QString ®isteredFor,
00263 const int fontID) :
00264 m_fontPath(fontPath), m_registeredFor(registeredFor), m_fontID(fontID)
00265 {
00266 }
00267
00268