summaryrefslogtreecommitdiff
path: root/indra/llrender/llfontregistry.cpp
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2024-05-16 13:52:40 +0800
committerErik Kundiman <erik@megapahit.org>2024-05-16 13:52:40 +0800
commit6d51e91895a7f2435c46a876410ccc6c63fe8c82 (patch)
treef2b48ebd99cb414227bf365f47665b8d4baa752b /indra/llrender/llfontregistry.cpp
parentd1b5917bb9c92e4e47eba19b43781e4d1328b1ca (diff)
parent094dcc07f8c1d90ae723dbe60eddacb90a09eae8 (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.cpp1156
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;
}