diff options
author | Erik Kundiman <erik@megapahit.org> | 2024-05-16 13:52:40 +0800 |
---|---|---|
committer | Erik Kundiman <erik@megapahit.org> | 2024-05-16 13:52:40 +0800 |
commit | 6d51e91895a7f2435c46a876410ccc6c63fe8c82 (patch) | |
tree | f2b48ebd99cb414227bf365f47665b8d4baa752b /indra/llrender/llfontregistry.cpp | |
parent | d1b5917bb9c92e4e47eba19b43781e4d1328b1ca (diff) | |
parent | 094dcc07f8c1d90ae723dbe60eddacb90a09eae8 (diff) |
Merge tag '7.1.7-release'
source for viewer 7.1.7.8974243247
Diffstat (limited to 'indra/llrender/llfontregistry.cpp')
-rw-r--r-- | indra/llrender/llfontregistry.cpp | 1156 |
1 files changed, 578 insertions, 578 deletions
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index d2c7e466e6..546211aac8 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llfontregistry.cpp * @author Brad Payne * @brief Storage for fonts. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -48,90 +48,90 @@ const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/"; const std::string MACOSX_FONT_SUPPLEMENTAL = "Supplemental/"; LLFontDescriptor::char_functor_map_t LLFontDescriptor::mCharFunctors({ - { "is_emoji", LLStringOps::isEmoji } + { "is_emoji", LLStringOps::isEmoji } }); LLFontDescriptor::LLFontDescriptor(): - mStyle(0) + mStyle(0) { } LLFontDescriptor::LLFontDescriptor(const std::string& name, - const std::string& size, - const U8 style, - const font_file_info_vec_t& font_files): - mName(name), - mSize(size), - mStyle(style), - mFontFiles(font_files) + const std::string& size, + const U8 style, + const font_file_info_vec_t& font_files): + mName(name), + mSize(size), + mStyle(style), + mFontFiles(font_files) { } LLFontDescriptor::LLFontDescriptor(const std::string& name, - const std::string& size, - const U8 style, - const font_file_info_vec_t& font_list, - const font_file_info_vec_t& font_collection_files) : - LLFontDescriptor(name, size, style, font_list) + const std::string& size, + const U8 style, + const font_file_info_vec_t& font_list, + const font_file_info_vec_t& font_collection_files) : + LLFontDescriptor(name, size, style, font_list) { - mFontCollectionFiles = font_collection_files; + mFontCollectionFiles = font_collection_files; } LLFontDescriptor::LLFontDescriptor(const std::string& name, - const std::string& size, - const U8 style): - mName(name), - mSize(size), - mStyle(style) + const std::string& size, + const U8 style): + mName(name), + mSize(size), + mStyle(style) { } bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const { - if (mName < b.mName) - return true; - else if (mName > b.mName) - return false; - - if (mStyle < b.mStyle) - return true; - else if (mStyle > b.mStyle) - return false; - - if (mSize < b.mSize) - return true; - else - return false; + if (mName < b.mName) + return true; + else if (mName > b.mName) + return false; + + if (mStyle < b.mStyle) + return true; + else if (mStyle > b.mStyle) + return false; + + if (mSize < b.mSize) + return true; + else + return false; } static const std::string s_template_string("TEMPLATE"); bool LLFontDescriptor::isTemplate() const { - return getSize() == s_template_string; + return getSize() == s_template_string; } // Look for substring match and remove substring if matched. bool removeSubString(std::string& str, const std::string& substr) { - size_t pos = str.find(substr); - if (pos != string::npos) - { - str.erase(pos, substr.size()); - return true; - } - return false; + size_t pos = str.find(substr); + if (pos != string::npos) + { + str.erase(pos, substr.size()); + return true; + } + return false; } // Check for substring match without modifying the source string. bool findSubString(std::string& str, const std::string& substr) { - size_t pos = str.find(substr); - if (pos != string::npos) - { - return true; - } - return false; + size_t pos = str.find(substr); + if (pos != string::npos) + { + return true; + } + return false; } @@ -145,618 +145,618 @@ bool findSubString(std::string& str, const std::string& substr) // - "SansSerifBold" would normalize to { "SansSerifBold", "Medium", BOLD } LLFontDescriptor LLFontDescriptor::normalize() const { - std::string new_name(mName); - std::string new_size(mSize); - U8 new_style(mStyle); - - // Only care about style to extent it can be picked up by font. - new_style &= (LLFontGL::BOLD | LLFontGL::ITALIC); - - // All these transformations are to support old-style font specifications. - if (removeSubString(new_name,"Small")) - new_size = "Small"; - if (removeSubString(new_name,"Big")) - new_size = "Large"; - if (removeSubString(new_name,"Medium")) - new_size = "Medium"; - if (removeSubString(new_name,"Large")) - new_size = "Large"; - if (removeSubString(new_name,"Huge")) - new_size = "Huge"; - - // HACK - Monospace is the only one we don't remove, so - // name "Monospace" doesn't get taken down to "" - // For other fonts, there's no ambiguity between font name and size specifier. - if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace")) - new_size = "Monospace"; - if (new_size.empty()) - new_size = "Medium"; - - if (removeSubString(new_name,"Bold")) - new_style |= LLFontGL::BOLD; - - if (removeSubString(new_name,"Italic")) - new_style |= LLFontGL::ITALIC; - - return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles()); + std::string new_name(mName); + std::string new_size(mSize); + U8 new_style(mStyle); + + // Only care about style to extent it can be picked up by font. + new_style &= (LLFontGL::BOLD | LLFontGL::ITALIC); + + // All these transformations are to support old-style font specifications. + if (removeSubString(new_name,"Small")) + new_size = "Small"; + if (removeSubString(new_name,"Big")) + new_size = "Large"; + if (removeSubString(new_name,"Medium")) + new_size = "Medium"; + if (removeSubString(new_name,"Large")) + new_size = "Large"; + if (removeSubString(new_name,"Huge")) + new_size = "Huge"; + + // HACK - Monospace is the only one we don't remove, so + // name "Monospace" doesn't get taken down to "" + // For other fonts, there's no ambiguity between font name and size specifier. + if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace")) + new_size = "Monospace"; + if (new_size.empty()) + new_size = "Medium"; + + if (removeSubString(new_name,"Bold")) + new_style |= LLFontGL::BOLD; + + if (removeSubString(new_name,"Italic")) + new_style |= LLFontGL::ITALIC; + + return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles()); } void LLFontDescriptor::addFontFile(const std::string& file_name, const std::string& char_functor) { - char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor); - mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr)); + char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor); + mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr)); } void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, const std::string& char_functor) { - char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor); - mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr)); + char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor); + mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr)); } LLFontRegistry::LLFontRegistry(bool create_gl_textures) -: mCreateGLTextures(create_gl_textures) +: mCreateGLTextures(create_gl_textures) { - // This is potentially a slow directory traversal, so we want to - // cache the result. - mUltimateFallbackList = LLWindow::getDynamicFallbackFontList(); + // This is potentially a slow directory traversal, so we want to + // cache the result. + mUltimateFallbackList = LLWindow::getDynamicFallbackFontList(); } LLFontRegistry::~LLFontRegistry() { - clear(); + clear(); } bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) { - bool success = false; // Succeed if we find and read at least one XUI file - const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename); - if (xml_paths.empty()) - { - // We didn't even find one single XUI file - return false; - } - - for (string_vec_t::const_iterator path_it = xml_paths.begin(); - path_it != xml_paths.end(); - ++path_it) - { - LLXMLNodePtr root; - bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL); - - if (!parsed_file) - continue; - - if ( root.isNull() || ! root->hasName( "fonts" ) ) - { - LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL; - continue; - } - - std::string root_name; - root->getAttributeString("name",root_name); - if (root->hasName("fonts")) - { - // Expect a collection of children consisting of "font" or "font_size" entries - bool init_succ = init_from_xml(this, root); - success = success || init_succ; - } - } - - //if (success) - // dump(); - - return success; + bool success = false; // Succeed if we find and read at least one XUI file + const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename); + if (xml_paths.empty()) + { + // We didn't even find one single XUI file + return false; + } + + for (string_vec_t::const_iterator path_it = xml_paths.begin(); + path_it != xml_paths.end(); + ++path_it) + { + LLXMLNodePtr root; + bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL); + + if (!parsed_file) + continue; + + if ( root.isNull() || ! root->hasName( "fonts" ) ) + { + LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL; + continue; + } + + std::string root_name; + root->getAttributeString("name",root_name); + if (root->hasName("fonts")) + { + // Expect a collection of children consisting of "font" or "font_size" entries + bool init_succ = init_from_xml(this, root); + success = success || init_succ; + } + } + + //if (success) + // dump(); + + return success; } std::string currentOsName() { #if LL_WINDOWS - return "Windows"; + return "Windows"; #elif LL_DARWIN - return "Mac"; + return "Mac"; #elif LL_LINUX - return "Linux"; + return "Linux"; #else - return ""; + return ""; #endif } bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc) { - if (node->hasName("font")) - { - std::string attr_name; - if (node->getAttributeString("name",attr_name)) - { - desc.setName(attr_name); - } - - std::string attr_style; - if (node->getAttributeString("font_style",attr_style)) - { - desc.setStyle(LLFontGL::getStyleFromString(attr_style)); - } - - desc.setSize(s_template_string); - } - - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - std::string child_name; - child->getAttributeString("name",child_name); - if (child->hasName("file")) - { - std::string font_file_name = child->getTextContents(); - std::string char_functor; - - if (child->hasAttribute("functor")) - { - child->getAttributeString("functor", char_functor); - } - - if (child->hasAttribute("load_collection")) - { - BOOL col = FALSE; - child->getAttributeBOOL("load_collection", col); - if (col) - { - desc.addFontCollectionFile(font_file_name, char_functor); - } - } - - desc.addFontFile(font_file_name, char_functor); - } - else if (child->hasName("os")) - { - if (child_name == currentOsName()) - { - font_desc_init_from_xml(child, desc); - } - } - } - return true; + if (node->hasName("font")) + { + std::string attr_name; + if (node->getAttributeString("name",attr_name)) + { + desc.setName(attr_name); + } + + std::string attr_style; + if (node->getAttributeString("font_style",attr_style)) + { + desc.setStyle(LLFontGL::getStyleFromString(attr_style)); + } + + desc.setSize(s_template_string); + } + + LLXMLNodePtr child; + for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) + { + std::string child_name; + child->getAttributeString("name",child_name); + if (child->hasName("file")) + { + std::string font_file_name = child->getTextContents(); + std::string char_functor; + + if (child->hasAttribute("functor")) + { + child->getAttributeString("functor", char_functor); + } + + if (child->hasAttribute("load_collection")) + { + BOOL col = FALSE; + child->getAttributeBOOL("load_collection", col); + if (col) + { + desc.addFontCollectionFile(font_file_name, char_functor); + } + } + + desc.addFontFile(font_file_name, char_functor); + } + else if (child->hasName("os")) + { + if (child_name == currentOsName()) + { + font_desc_init_from_xml(child, desc); + } + } + } + return true; } bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node) { - LLXMLNodePtr child; - - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - std::string child_name; - child->getAttributeString("name",child_name); - if (child->hasName("font")) - { - LLFontDescriptor desc; - bool font_succ = font_desc_init_from_xml(child, desc); - LLFontDescriptor norm_desc = desc.normalize(); - if (font_succ) - { - // if this is the first time we've seen this font name, - // create a new template map entry for it. - const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc); - if (match_desc == NULL) - { - // Create a new entry (with no corresponding font). - registry->mFontMap[norm_desc] = NULL; - } - // otherwise, find the existing entry and combine data. - else - { - // Prepend files from desc. - // A little roundabout because the map key is const, - // so we have to fetch it, make a new map key, and - // replace the old entry. - font_file_info_vec_t font_files = match_desc->getFontFiles(); - font_files.insert(font_files.begin(), - desc.getFontFiles().begin(), - desc.getFontFiles().end()); - - font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles(); - font_collection_files.insert(font_collection_files.begin(), - desc.getFontCollectionFiles().begin(), - desc.getFontCollectionFiles().end()); - - LLFontDescriptor new_desc = *match_desc; - new_desc.setFontFiles(font_files); - new_desc.setFontCollectionFiles(font_collection_files); - registry->mFontMap.erase(*match_desc); - registry->mFontMap[new_desc] = NULL; - } - } - } - else if (child->hasName("font_size")) - { - std::string size_name; - F32 size_value; - if (child->getAttributeString("name",size_name) && - child->getAttributeF32("size",size_value)) - { - registry->mFontSizes[size_name] = size_value; - } - - } - } - return true; + LLXMLNodePtr child; + + for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) + { + std::string child_name; + child->getAttributeString("name",child_name); + if (child->hasName("font")) + { + LLFontDescriptor desc; + bool font_succ = font_desc_init_from_xml(child, desc); + LLFontDescriptor norm_desc = desc.normalize(); + if (font_succ) + { + // if this is the first time we've seen this font name, + // create a new template map entry for it. + const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc); + if (match_desc == NULL) + { + // Create a new entry (with no corresponding font). + registry->mFontMap[norm_desc] = NULL; + } + // otherwise, find the existing entry and combine data. + else + { + // Prepend files from desc. + // A little roundabout because the map key is const, + // so we have to fetch it, make a new map key, and + // replace the old entry. + font_file_info_vec_t font_files = match_desc->getFontFiles(); + font_files.insert(font_files.begin(), + desc.getFontFiles().begin(), + desc.getFontFiles().end()); + + font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles(); + font_collection_files.insert(font_collection_files.begin(), + desc.getFontCollectionFiles().begin(), + desc.getFontCollectionFiles().end()); + + LLFontDescriptor new_desc = *match_desc; + new_desc.setFontFiles(font_files); + new_desc.setFontCollectionFiles(font_collection_files); + registry->mFontMap.erase(*match_desc); + registry->mFontMap[new_desc] = NULL; + } + } + } + else if (child->hasName("font_size")) + { + std::string size_name; + F32 size_value; + if (child->getAttributeString("name",size_name) && + child->getAttributeF32("size",size_value)) + { + registry->mFontSizes[size_name] = size_value; + } + + } + } + return true; } bool LLFontRegistry::nameToSize(const std::string& size_name, F32& size) { - font_size_map_t::iterator it = mFontSizes.find(size_name); - if (it != mFontSizes.end()) - { - size = it->second; - return true; - } - return false; + font_size_map_t::iterator it = mFontSizes.find(size_name); + if (it != mFontSizes.end()) + { + size = it->second; + return true; + } + return false; } LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) { - // Name should hold a font name recognized as a setting; the value - // of the setting should be a list of font files. - // Size should be a recognized string value - // Style should be a set of flags including any implied by the font name. - - // First decipher the requested size. - LLFontDescriptor norm_desc = desc.normalize(); - F32 point_size; - bool found_size = nameToSize(norm_desc.getSize(),point_size); - if (!found_size) - { - LL_WARNS() << "createFont unrecognized size " << norm_desc.getSize() << LL_ENDL; - return NULL; - } - LL_INFOS() << "createFont " << norm_desc.getName() << " size " << norm_desc.getSize() << " style " << ((S32) norm_desc.getStyle()) << LL_ENDL; - F32 fallback_scale = 1.0; - - // Find corresponding font template (based on same descriptor with no size specified) - LLFontDescriptor template_desc(norm_desc); - template_desc.setSize(s_template_string); - const LLFontDescriptor *match_desc = getClosestFontTemplate(template_desc); - if (!match_desc) - { - LL_WARNS() << "createFont failed, no template found for " - << norm_desc.getName() << " style [" << ((S32)norm_desc.getStyle()) << "]" << LL_ENDL; - return NULL; - } - - // See whether this best-match font has already been instantiated in the requested size. - LLFontDescriptor nearest_exact_desc = *match_desc; - nearest_exact_desc.setSize(norm_desc.getSize()); - font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc); - // If we fail to find a font in the fonts directory, it->second might be NULL. - // We shouldn't construcnt a font with a NULL mFontFreetype. - // This may not be the best solution, but it at least prevents a crash. - if (it != mFontMap.end() && it->second != NULL) - { - LL_INFOS() << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << LL_ENDL; - - // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor - LLFontGL *font = new LLFontGL; - font->mFontDescriptor = desc; - font->mFontFreetype = it->second->mFontFreetype; - mFontMap[desc] = font; - - return font; - } - - // Build list of font names to look for. - // Files specified for this font come first, followed by those from the default descriptor. - font_file_info_vec_t font_files = match_desc->getFontFiles(); - font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles(); - LLFontDescriptor default_desc("default",s_template_string,0); - const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc); - if (match_default_desc) - { - font_files.insert(font_files.end(), - match_default_desc->getFontFiles().begin(), - match_default_desc->getFontFiles().end()); - font_collection_files.insert(font_collection_files.end(), - match_default_desc->getFontCollectionFiles().begin(), - match_default_desc->getFontCollectionFiles().end()); - } - - // Add ultimate fallback list - generated dynamically on linux, - // null elsewhere. - std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files), - [](const std::string& file_name) { return LLFontFileInfo(file_name); }); - - // Load fonts based on names. - if (font_files.empty()) - { - LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL; - return NULL; - } - - LLFontGL *result = NULL; - - // The first font will get pulled will be the "head" font, set to non-fallback. - // Rest will consitute the fallback list. - BOOL is_first_found = TRUE; - - string_vec_t font_search_paths; - font_search_paths.push_back(LLFontGL::getFontPathLocal()); - font_search_paths.push_back(LLFontGL::getFontPathSystem()); + // Name should hold a font name recognized as a setting; the value + // of the setting should be a list of font files. + // Size should be a recognized string value + // Style should be a set of flags including any implied by the font name. + + // First decipher the requested size. + LLFontDescriptor norm_desc = desc.normalize(); + F32 point_size; + bool found_size = nameToSize(norm_desc.getSize(),point_size); + if (!found_size) + { + LL_WARNS() << "createFont unrecognized size " << norm_desc.getSize() << LL_ENDL; + return NULL; + } + LL_INFOS() << "createFont " << norm_desc.getName() << " size " << norm_desc.getSize() << " style " << ((S32) norm_desc.getStyle()) << LL_ENDL; + F32 fallback_scale = 1.0; + + // Find corresponding font template (based on same descriptor with no size specified) + LLFontDescriptor template_desc(norm_desc); + template_desc.setSize(s_template_string); + const LLFontDescriptor *match_desc = getClosestFontTemplate(template_desc); + if (!match_desc) + { + LL_WARNS() << "createFont failed, no template found for " + << norm_desc.getName() << " style [" << ((S32)norm_desc.getStyle()) << "]" << LL_ENDL; + return NULL; + } + + // See whether this best-match font has already been instantiated in the requested size. + LLFontDescriptor nearest_exact_desc = *match_desc; + nearest_exact_desc.setSize(norm_desc.getSize()); + font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc); + // If we fail to find a font in the fonts directory, it->second might be NULL. + // We shouldn't construcnt a font with a NULL mFontFreetype. + // This may not be the best solution, but it at least prevents a crash. + if (it != mFontMap.end() && it->second != NULL) + { + LL_INFOS() << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << LL_ENDL; + + // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor + LLFontGL *font = new LLFontGL; + font->mFontDescriptor = desc; + font->mFontFreetype = it->second->mFontFreetype; + mFontMap[desc] = font; + + return font; + } + + // Build list of font names to look for. + // Files specified for this font come first, followed by those from the default descriptor. + font_file_info_vec_t font_files = match_desc->getFontFiles(); + font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles(); + LLFontDescriptor default_desc("default",s_template_string,0); + const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc); + if (match_default_desc) + { + font_files.insert(font_files.end(), + match_default_desc->getFontFiles().begin(), + match_default_desc->getFontFiles().end()); + font_collection_files.insert(font_collection_files.end(), + match_default_desc->getFontCollectionFiles().begin(), + match_default_desc->getFontCollectionFiles().end()); + } + + // Add ultimate fallback list - generated dynamically on linux, + // null elsewhere. + std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files), + [](const std::string& file_name) { return LLFontFileInfo(file_name); }); + + // Load fonts based on names. + if (font_files.empty()) + { + LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL; + return NULL; + } + + LLFontGL *result = NULL; + + // The first font will get pulled will be the "head" font, set to non-fallback. + // Rest will consitute the fallback list. + BOOL is_first_found = TRUE; + + string_vec_t font_search_paths; + font_search_paths.push_back(LLFontGL::getFontPathLocal()); + font_search_paths.push_back(LLFontGL::getFontPathSystem()); #if LL_DARWIN - font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY); - font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL); - font_search_paths.push_back(LLFontGL::getFontPathSystem() + MACOSX_FONT_SUPPLEMENTAL); + font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY); + font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL); + font_search_paths.push_back(LLFontGL::getFontPathSystem() + MACOSX_FONT_SUPPLEMENTAL); #endif - // The fontname string may contain multiple font file names separated by semicolons. - // Break it apart and try loading each one, in order. - for(font_file_info_vec_t::iterator font_file_it = font_files.begin(); - font_file_it != font_files.end(); - ++font_file_it) - { - LLFontGL *fontp = NULL; - - bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(), - [&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end()); - - // *HACK: Fallback fonts don't render, so we can use that to suppress - // creation of OpenGL textures for test apps. JC - BOOL is_fallback = !is_first_found || !mCreateGLTextures; - F32 extra_scale = (is_fallback)?fallback_scale:1.0; - F32 point_size_scale = extra_scale * point_size; - bool is_font_loaded = false; - for(string_vec_t::iterator font_search_path_it = font_search_paths.begin(); - font_search_path_it != font_search_paths.end(); - ++font_search_path_it) - { - const std::string font_path = *font_search_path_it + font_file_it->FileName; - - fontp = new LLFontGL; - S32 num_faces = is_ft_collection ? fontp->getNumFaces(font_path) : 1; - for (S32 i = 0; i < num_faces; i++) - { - if (fontp == NULL) - { - fontp = new LLFontGL; - } - if (fontp->loadFace(font_path, point_size_scale, - LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i)) - { - is_font_loaded = true; - if (is_first_found) - { - result = fontp; - is_first_found = false; - } - else - { - result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor); - - delete fontp; - fontp = NULL; - } - } - else - { - delete fontp; - fontp = NULL; - } - } - if (is_font_loaded) break; - } - if(!is_font_loaded) - { - LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName << LL_ENDL; - delete fontp; - fontp = NULL; - } - } - - if (result) - { - result->mFontDescriptor = desc; - } - else - { - LL_WARNS() << "createFont failed in some way" << LL_ENDL; - } - - mFontMap[desc] = result; - return result; + // The fontname string may contain multiple font file names separated by semicolons. + // Break it apart and try loading each one, in order. + for(font_file_info_vec_t::iterator font_file_it = font_files.begin(); + font_file_it != font_files.end(); + ++font_file_it) + { + LLFontGL *fontp = NULL; + + bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(), + [&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end()); + + // *HACK: Fallback fonts don't render, so we can use that to suppress + // creation of OpenGL textures for test apps. JC + BOOL is_fallback = !is_first_found || !mCreateGLTextures; + F32 extra_scale = (is_fallback)?fallback_scale:1.0; + F32 point_size_scale = extra_scale * point_size; + bool is_font_loaded = false; + for(string_vec_t::iterator font_search_path_it = font_search_paths.begin(); + font_search_path_it != font_search_paths.end(); + ++font_search_path_it) + { + const std::string font_path = *font_search_path_it + font_file_it->FileName; + + fontp = new LLFontGL; + S32 num_faces = is_ft_collection ? fontp->getNumFaces(font_path) : 1; + for (S32 i = 0; i < num_faces; i++) + { + if (fontp == NULL) + { + fontp = new LLFontGL; + } + if (fontp->loadFace(font_path, point_size_scale, + LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i)) + { + is_font_loaded = true; + if (is_first_found) + { + result = fontp; + is_first_found = false; + } + else + { + result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor); + + delete fontp; + fontp = NULL; + } + } + else + { + delete fontp; + fontp = NULL; + } + } + if (is_font_loaded) break; + } + if(!is_font_loaded) + { + LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName << LL_ENDL; + delete fontp; + fontp = NULL; + } + } + + if (result) + { + result->mFontDescriptor = desc; + } + else + { + LL_WARNS() << "createFont failed in some way" << LL_ENDL; + } + + mFontMap[desc] = result; + return result; } void LLFontRegistry::reset() { - for (font_reg_map_t::iterator it = mFontMap.begin(); - it != mFontMap.end(); - ++it) - { - // Reset the corresponding font but preserve the entry. - if (it->second) - it->second->reset(); - } + for (font_reg_map_t::iterator it = mFontMap.begin(); + it != mFontMap.end(); + ++it) + { + // Reset the corresponding font but preserve the entry. + if (it->second) + it->second->reset(); + } } void LLFontRegistry::clear() { - for (font_reg_map_t::iterator it = mFontMap.begin(); - it != mFontMap.end(); - ++it) - { - LLFontGL *fontp = it->second; - delete fontp; - } - mFontMap.clear(); + for (font_reg_map_t::iterator it = mFontMap.begin(); + it != mFontMap.end(); + ++it) + { + LLFontGL *fontp = it->second; + delete fontp; + } + mFontMap.clear(); } void LLFontRegistry::destroyGL() { - for (font_reg_map_t::iterator it = mFontMap.begin(); - it != mFontMap.end(); - ++it) - { - // Reset the corresponding font but preserve the entry. - if (it->second) - it->second->destroyGL(); - } + for (font_reg_map_t::iterator it = mFontMap.begin(); + it != mFontMap.end(); + ++it) + { + // Reset the corresponding font but preserve the entry. + if (it->second) + it->second->destroyGL(); + } } LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc) { - font_reg_map_t::iterator it = mFontMap.find(desc); - if (it != mFontMap.end()) - return it->second; - else - { - LLFontGL *fontp = createFont(desc); - if (!fontp) - { - LL_WARNS() << "getFont failed, name " << desc.getName() - <<" style=[" << ((S32) desc.getStyle()) << "]" - << " size=[" << desc.getSize() << "]" << LL_ENDL; - } - else - { - //generate glyphs for ASCII chars to avoid stalls later - fontp->generateASCIIglyphs(); - } - return fontp; - } + font_reg_map_t::iterator it = mFontMap.find(desc); + if (it != mFontMap.end()) + return it->second; + else + { + LLFontGL *fontp = createFont(desc); + if (!fontp) + { + LL_WARNS() << "getFont failed, name " << desc.getName() + <<" style=[" << ((S32) desc.getStyle()) << "]" + << " size=[" << desc.getSize() << "]" << LL_ENDL; + } + else + { + //generate glyphs for ASCII chars to avoid stalls later + fontp->generateASCIIglyphs(); + } + return fontp; + } } const LLFontDescriptor *LLFontRegistry::getMatchingFontDesc(const LLFontDescriptor& desc) { - LLFontDescriptor norm_desc = desc.normalize(); + LLFontDescriptor norm_desc = desc.normalize(); - font_reg_map_t::iterator it = mFontMap.find(norm_desc); - if (it != mFontMap.end()) - return &(it->first); - else - return NULL; + font_reg_map_t::iterator it = mFontMap.find(norm_desc); + if (it != mFontMap.end()) + return &(it->first); + else + return NULL; } static U32 bitCount(U8 c) { - U32 count = 0; - if (c & 1) - count++; - if (c & 2) - count++; - if (c & 4) - count++; - if (c & 8) - count++; - if (c & 16) - count++; - if (c & 32) - count++; - if (c & 64) - count++; - if (c & 128) - count++; - return count; + U32 count = 0; + if (c & 1) + count++; + if (c & 2) + count++; + if (c & 4) + count++; + if (c & 8) + count++; + if (c & 16) + count++; + if (c & 32) + count++; + if (c & 64) + count++; + if (c & 128) + count++; + return count; } // Find nearest match for the requested descriptor. const LLFontDescriptor *LLFontRegistry::getClosestFontTemplate(const LLFontDescriptor& desc) { - const LLFontDescriptor *exact_match_desc = getMatchingFontDesc(desc); - if (exact_match_desc) - { - return exact_match_desc; - } - - LLFontDescriptor norm_desc = desc.normalize(); - - const LLFontDescriptor *best_match_desc = NULL; - for (font_reg_map_t::iterator it = mFontMap.begin(); - it != mFontMap.end(); - ++it) - { - const LLFontDescriptor* curr_desc = &(it->first); - - // Ignore if not a template. - if (!curr_desc->isTemplate()) - continue; - - // Ignore if font name is wrong. - if (curr_desc->getName() != norm_desc.getName()) - continue; - - // Reject font if it matches any bits we don't want - if (curr_desc->getStyle() & ~norm_desc.getStyle()) - { - continue; - } - - // Take if it's the first plausible candidate we've found. - if (!best_match_desc) - { - best_match_desc = curr_desc; - continue; - } - - // Take if it matches more bits than anything before. - U8 best_style_match_bits = - norm_desc.getStyle() & best_match_desc->getStyle(); - U8 curr_style_match_bits = - norm_desc.getStyle() & curr_desc->getStyle(); - if (bitCount(curr_style_match_bits) > bitCount(best_style_match_bits)) - { - best_match_desc = curr_desc; - continue; - } - - // Tie-breaker: take if it matches bold. - if (curr_style_match_bits & LLFontGL::BOLD) // Bold is requested and this descriptor matches it. - { - best_match_desc = curr_desc; - continue; - } - } - - // Nothing matched. - return best_match_desc; + const LLFontDescriptor *exact_match_desc = getMatchingFontDesc(desc); + if (exact_match_desc) + { + return exact_match_desc; + } + + LLFontDescriptor norm_desc = desc.normalize(); + + const LLFontDescriptor *best_match_desc = NULL; + for (font_reg_map_t::iterator it = mFontMap.begin(); + it != mFontMap.end(); + ++it) + { + const LLFontDescriptor* curr_desc = &(it->first); + + // Ignore if not a template. + if (!curr_desc->isTemplate()) + continue; + + // Ignore if font name is wrong. + if (curr_desc->getName() != norm_desc.getName()) + continue; + + // Reject font if it matches any bits we don't want + if (curr_desc->getStyle() & ~norm_desc.getStyle()) + { + continue; + } + + // Take if it's the first plausible candidate we've found. + if (!best_match_desc) + { + best_match_desc = curr_desc; + continue; + } + + // Take if it matches more bits than anything before. + U8 best_style_match_bits = + norm_desc.getStyle() & best_match_desc->getStyle(); + U8 curr_style_match_bits = + norm_desc.getStyle() & curr_desc->getStyle(); + if (bitCount(curr_style_match_bits) > bitCount(best_style_match_bits)) + { + best_match_desc = curr_desc; + continue; + } + + // Tie-breaker: take if it matches bold. + if (curr_style_match_bits & LLFontGL::BOLD) // Bold is requested and this descriptor matches it. + { + best_match_desc = curr_desc; + continue; + } + } + + // Nothing matched. + return best_match_desc; } void LLFontRegistry::dump() { - LL_INFOS() << "LLFontRegistry dump: " << LL_ENDL; - for (font_size_map_t::iterator size_it = mFontSizes.begin(); - size_it != mFontSizes.end(); - ++size_it) - { - LL_INFOS() << "Size: " << size_it->first << " => " << size_it->second << LL_ENDL; - } - for (font_reg_map_t::iterator font_it = mFontMap.begin(); - font_it != mFontMap.end(); - ++font_it) - { - const LLFontDescriptor& desc = font_it->first; - LL_INFOS() << "Font: name=" << desc.getName() - << " style=[" << ((S32)desc.getStyle()) << "]" - << " size=[" << desc.getSize() << "]" - << " fileNames=" - << LL_ENDL; - for (font_file_info_vec_t::const_iterator file_it=desc.getFontFiles().begin(); - file_it != desc.getFontFiles().end(); - ++file_it) - { - LL_INFOS() << " file: " << file_it->FileName << LL_ENDL; - } - } + LL_INFOS() << "LLFontRegistry dump: " << LL_ENDL; + for (font_size_map_t::iterator size_it = mFontSizes.begin(); + size_it != mFontSizes.end(); + ++size_it) + { + LL_INFOS() << "Size: " << size_it->first << " => " << size_it->second << LL_ENDL; + } + for (font_reg_map_t::iterator font_it = mFontMap.begin(); + font_it != mFontMap.end(); + ++font_it) + { + const LLFontDescriptor& desc = font_it->first; + LL_INFOS() << "Font: name=" << desc.getName() + << " style=[" << ((S32)desc.getStyle()) << "]" + << " size=[" << desc.getSize() << "]" + << " fileNames=" + << LL_ENDL; + for (font_file_info_vec_t::const_iterator file_it=desc.getFontFiles().begin(); + file_it != desc.getFontFiles().end(); + ++file_it) + { + LL_INFOS() << " file: " << file_it->FileName << LL_ENDL; + } + } } void LLFontRegistry::dumpTextures() { - for (const auto& fontEntry : mFontMap) - { - if (fontEntry.second) - { - fontEntry.second->dumpTextures(); - } - } + for (const auto& fontEntry : mFontMap) + { + if (fontEntry.second) + { + fontEntry.second->dumpTextures(); + } + } } -const string_vec_t& LLFontRegistry::getUltimateFallbackList() const -{ - return mUltimateFallbackList; +const string_vec_t& LLFontRegistry::getUltimateFallbackList() const +{ + return mUltimateFallbackList; } |