// Load SpriteFont from TTF file with custom parameters // NOTE: You can pass an array with desired characters, those characters should be available in the font // if array is NULL, default char set is selected 32..126 SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars) { SpriteFont spriteFont = { 0 }; if (strcmp(GetExtension(fileName),"ttf") == 0) { if ((fontChars == NULL) || (numChars == 0)) { int totalChars = 95; // Default charset [32..126] int *defaultFontChars = (int *)malloc(totalChars*sizeof(int)); for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32] spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars); } else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars); } if (spriteFont.texture.id == 0) { TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName); spriteFont = GetDefaultFont(); } return spriteFont; }
void GUIFontManager::LoadFonts(const TiXmlNode* fontNode) { while (fontNode) { std::string fontName; std::string fileName; int iSize = 20; float aspect = 1.0f; float lineSpacing = 1.0f; color_t shadowColor = 0; color_t textColor = 0; int iStyle = FONT_STYLE_NORMAL; XMLUtils::GetString(fontNode, "name", fontName); XMLUtils::GetInt(fontNode, "size", iSize); XMLUtils::GetFloat(fontNode, "linespacing", lineSpacing); XMLUtils::GetFloat(fontNode, "aspect", aspect); CGUIControlFactory::GetColor(fontNode, "shadow", shadowColor); CGUIControlFactory::GetColor(fontNode, "color", textColor); XMLUtils::GetString(fontNode, "filename", fileName); GetStyle(fontNode, iStyle); if (!fontName.empty() && URIUtils::HasExtension(fileName, ".ttf")) { // TODO: Why do we tolower() this shit? std::string strFontFileName = fileName; StringUtils::ToLower(strFontFileName); LoadTTF(fontName, strFontFileName, textColor, shadowColor, iSize, iStyle, false, lineSpacing, aspect); } fontNode = fontNode->NextSibling("font"); } }
CGUIFont* GUIFontManager::GetDefaultFont(bool border) { // first find "font13" or "__defaultborder__" size_t font13index = m_vecFonts.size(); CGUIFont *font13border = NULL; for (unsigned int i = 0; i < m_vecFonts.size(); i++) { CGUIFont* font = m_vecFonts[i]; if (font->GetFontName() == "font13") font13index = i; else if (font->GetFontName() == "__defaultborder__") font13border = font; } // no "font13" means no default font is found - use the first font found. if (font13index == m_vecFonts.size()) { if (m_vecFonts.empty()) return NULL; font13index = 0; } if (border) { if (!font13border) { // create it CGUIFont *font13 = m_vecFonts[font13index]; OrigFontInfo fontInfo = m_vecFontInfo[font13index]; font13border = LoadTTF("__defaultborder__", fontInfo.fileName, 0xFF000000, 0, fontInfo.size, font13->GetStyle(), true, 1.0f, fontInfo.aspect, &fontInfo.sourceRes, fontInfo.preserveAspect); } return font13border; } return m_vecFonts[font13index]; }
CGUIFont* GUIFontManager::LoadTTF(const std::string& strFontName, const std::string& strFilename, color_t textColor, color_t shadowColor, const int iSize, const int iStyle, bool border, float lineSpacing, float aspect, const RESOLUTION_INFO *sourceRes, bool preserveAspect) { float originalAspect = aspect; //check if font already exists CGUIFont* pFont = GetFont(strFontName, false); if (pFont) return pFont; if (!sourceRes) // no source res specified, so assume the skin res sourceRes = &m_skinResolution; float newSize = (float)iSize; RescaleFontSizeAndAspect(&newSize, &aspect, *sourceRes, preserveAspect); // First try to load the font from the skin std::string strPath; if (!CURL::IsFullPath(strFilename)) { strPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), "fonts"); strPath = URIUtils::AddFileToFolder(strPath, strFilename); } else strPath = strFilename; #ifdef TARGET_POSIX strPath = CSpecialProtocol::TranslatePathConvertCase(strPath); #endif // Check if the file exists, otherwise try loading it from the global media dir std::string file = URIUtils::GetFileName(strFilename); if (!CheckFont(strPath,"special://home/media/Fonts",file)) CheckFont(strPath,"special://xbmc/media/Fonts",file); // check if we already have this font file loaded (font object could differ only by color or style) std::string TTFfontName = StringUtils::Format("%s_%f_%f%s", strFilename.c_str(), newSize, aspect, border ? "_border" : ""); CGUIFontTTFBase* pFontFile = GetFontFile(TTFfontName); if (!pFontFile) { pFontFile = new CGUIFontTTF(TTFfontName); bool bFontLoaded = pFontFile->Load(strPath, newSize, aspect, 1.0f, border); if (!bFontLoaded) { delete pFontFile; // font could not be loaded - try Arial.ttf, which we distribute if (strFilename != "arial.ttf") { CLog::Log(LOGERROR, "Couldn't load font name: %s(%s), trying to substitute arial.ttf", strFontName.c_str(), strFilename.c_str()); return LoadTTF(strFontName, "arial.ttf", textColor, shadowColor, iSize, iStyle, border, lineSpacing, originalAspect); } CLog::Log(LOGERROR, "Couldn't load font name:%s file:%s", strFontName.c_str(), strPath.c_str()); return NULL; } m_vecFontFiles.push_back(pFontFile); } // font file is loaded, create our CGUIFont CGUIFont *pNewFont = new CGUIFont(strFontName, iStyle, textColor, shadowColor, lineSpacing, (float)iSize, pFontFile); m_vecFonts.push_back(pNewFont); // Store the original TTF font info in case we need to reload it in a different resolution OrigFontInfo fontInfo; fontInfo.size = iSize; fontInfo.aspect = originalAspect; fontInfo.fontFilePath = strPath; fontInfo.fileName = strFilename; fontInfo.sourceRes = *sourceRes; fontInfo.preserveAspect = preserveAspect; fontInfo.border = border; m_vecFontInfo.push_back(fontInfo); return pNewFont; }