diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/cmake/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/cmake/FindICU4C.cmake | 33 | ||||
| -rw-r--r-- | indra/cmake/ICU4C.cmake | 22 | ||||
| -rw-r--r-- | indra/llcommon/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llcommon/llstring.cpp | 26 | ||||
| -rw-r--r-- | indra/llcommon/llstring.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.cpp | 42 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.h | 12 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.cpp | 4 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llfontregistry.cpp | 150 | ||||
| -rw-r--r-- | indra/llrender/llfontregistry.h | 42 | ||||
| -rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/fonts.xml | 1 | ||||
| -rw-r--r-- | indra/win_crash_logger/CMakeLists.txt | 2 | 
15 files changed, 243 insertions, 101 deletions
| diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 84e1c5d6fd..d64c38b1b3 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -32,6 +32,7 @@ set(cmake_SOURCE_FILES      FindGLH.cmake      FindGoogleBreakpad.cmake      FindHUNSPELL.cmake +    FindICU4C.cmake      FindJsonCpp.cmake      FindNDOF.cmake      FindOpenJPEG.cmake @@ -49,6 +50,7 @@ set(cmake_SOURCE_FILES      GoogleMock.cmake      Havok.cmake      Hunspell.cmake +    ICU4C.cmake      JPEG.cmake      JsonCpp.cmake      LLAddBuildTest.cmake diff --git a/indra/cmake/FindICU4C.cmake b/indra/cmake/FindICU4C.cmake new file mode 100644 index 0000000000..327d761a88 --- /dev/null +++ b/indra/cmake/FindICU4C.cmake @@ -0,0 +1,33 @@ +# -*- cmake -*- + +# - Find ICU4C +# This module defines +#  ICU4C_INCLUDE_DIR, where to find headers +#  ICU4C_LIBRARY, the library needed to use ICU4C. +#  ICU4C_FOUND, If false, do not try to use ICU4C. + +find_path(ICU4C_INCLUDE_DIR uchar.h +  PATH_SUFFIXES unicode +  ) + +set(ICU4C_NAMES ${ICU4C_NAMES} icuuc) +find_library(ICU4C_LIBRARY +  NAMES ${ICU4C_NAMES} +  ) + +if (ICU4C_LIBRARY AND ICU4C_INCLUDE_DIR) +  set(ICU4C_FOUND "YES") +else (ICU4C_LIBRARY AND ICU4C_INCLUDE_DIR) +  set(ICU4C_FOUND "NO") +endif (ICU4C_LIBRARY AND ICU4C_INCLUDE_DIR) + +if (ICU4C_FOUND) +    message(STATUS "Found ICU4C: Library in '${ICU4C_LIBRARY}' and header in '${ICU4C_INCLUDE_DIR}' ") +else (ICU4C_FOUND) +    message(FATAL_ERROR " * * *\nCould not find ICU4C library! * * *") +endif (ICU4C_FOUND) + +mark_as_advanced( +  ICU4C_LIBRARY +  ICU4C_INCLUDE_DIR +  ) diff --git a/indra/cmake/ICU4C.cmake b/indra/cmake/ICU4C.cmake new file mode 100644 index 0000000000..007a9b6937 --- /dev/null +++ b/indra/cmake/ICU4C.cmake @@ -0,0 +1,22 @@ +# -*- cmake -*- +include(Prebuilt) + +set(ICU4C_FIND_QUIETLY ON) +set(ICU4C_FIND_REQUIRED ON) + +if (USESYSTEMLIBS) +  include(FindICU4C) +else (USESYSTEMLIBS) +  use_prebuilt_binary(icu4c) +  if (WINDOWS) +    set(ICU4C_LIBRARY icuuc) +  #elseif(DARWIN) +  #  set(ICU4C_LIBRARY ...) +  #elseif(LINUX) +  #  set(ICU4C_LIBRARY ...) +  else() +    message(FATAL_ERROR "Invalid platform") +  endif() +  set(ICU4C_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/unicode) +  use_prebuilt_binary(dictionaries) +endif (USESYSTEMLIBS) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index af41b9e460..ba87d93fec 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -4,6 +4,7 @@  project(llcommon)  include(00-Common) +include(ICU4C)  include(LLCommon)  include(Linking)  include(Boost) @@ -288,6 +289,7 @@ target_link_libraries(      ${APRUTIL_LIBRARIES}      ${APR_LIBRARIES}      ${EXPAT_LIBRARIES} +    ${ICU4C_LIBRARY}      ${JSONCPP_LIBRARIES}      ${ZLIB_LIBRARIES}      ${WINDOWS_LIBRARIES} diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 0174c411b4..b272728200 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -30,6 +30,7 @@  #include "llerror.h"  #include "llfasttimer.h"  #include "llsd.h" +#include <unicode/uchar.h>  #include <vector>  #if LL_WINDOWS @@ -888,6 +889,31 @@ std::string LLStringOps::sDayFormat;  std::string LLStringOps::sAM;  std::string LLStringOps::sPM; +// static +bool LLStringOps::isEmoji(llwchar wch) +{ +	switch (ublock_getCode(wch)) +	{ +		case UBLOCK_MISCELLANEOUS_SYMBOLS: +		case UBLOCK_DINGBATS: +		case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: +		case UBLOCK_EMOTICONS: +		case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS: +#if U_ICU_VERSION_MAJOR_NUM > 56 +		// Boost uses ICU so we can't update it independently +		case UBLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS: +#endif // U_ICU_VERSION_MAJOR_NUM > 56 +			return true; +		default: +#if U_ICU_VERSION_MAJOR_NUM > 56 +			return false; +#else +			// See https://en.wikipedia.org/wiki/Supplemental_Symbols_and_Pictographs +			return wch >= 0x1F900 && wch <= 0x1F9FF; +#endif // U_ICU_VERSION_MAJOR_NUM > 56 +	} +} +  S32	LLStringOps::collate(const llwchar* a, const llwchar* b)  {  diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index b619a9e48c..d31d0cafc7 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -193,6 +193,8 @@ public:  	static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }  	static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } +	static bool isEmoji(llwchar wch); +  	static S32	collate(const char* a, const char* b) { return strcoll(a, b); }  	static S32	collate(const llwchar* a, const llwchar* b); diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 7d66965e57..25740a5f87 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -175,7 +175,7 @@ void ft_close_cb(FT_Stream stream) {  }  #endif -BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool use_color, bool is_fallback, S32 face_n) +BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n)  {  	// Don't leak face objects.  This is also needed to deal with  	// changed font file names. @@ -345,14 +345,11 @@ void LLFontFreetype::clearFontStreams()  }  #endif -void LLFontFreetype::setFallbackFonts(const font_vector_t &font) +void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor)  { -	mFallbackFonts = font; -} - -const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const -{ -	return mFallbackFonts; +	// Insert functor fallbacks before generic fallbacks +	mFallbackFonts.insert((functor) ? std::find_if(mFallbackFonts.begin(), mFallbackFonts.end(), [](const fallback_font_t& fe) { return !fe.second; }) : mFallbackFonts.end(), +	                      std::make_pair(fallback_font, functor));  }  F32 LLFontFreetype::getLineHeight() const @@ -453,18 +450,31 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type  	FT_UInt glyph_index; +	// Fallback fonts with a functor have precedence over everything else +	fallback_font_vector_t::const_iterator it_fallback = mFallbackFonts.cbegin(); +	for (; it_fallback != mFallbackFonts.cend() && it_fallback->second; ++it_fallback) +	{ +		if (it_fallback->second(wch)) +		{ +			glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch); +			if (glyph_index) +			{ +				return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type); +			} +		} +	} +  	// Initialize char to glyph map  	glyph_index = FT_Get_Char_Index(mFTFace, wch);  	if (glyph_index == 0)  	{  		//LL_INFOS() << "Trying to add glyph from fallback font!" << LL_ENDL; -		font_vector_t::const_iterator iter; -		for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++) +		for (; it_fallback != mFallbackFonts.cend(); ++it_fallback)  		{ -			glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); +			glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);  			if (glyph_index)  			{ -				return addGlyphFromFont(*iter, wch, glyph_index, glyph_type); +				return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);  			}  		}  	} @@ -653,7 +663,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) co  void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)  {  	resetBitmapCache();  -	loadFace(mName, mPointSize, vert_dpi ,horz_dpi, true, mIsFallback, 0); +	loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0);  	if (!mIsFallback)  	{  		// This is the head of the list - need to rebuild ourself and all fallbacks. @@ -663,11 +673,9 @@ void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)  		}  		else  		{ -			for(font_vector_t::iterator it = mFallbackFonts.begin(); -				it != mFallbackFonts.end(); -				++it) +			for (fallback_font_vector_t::iterator it = mFallbackFonts.begin(); it != mFallbackFonts.end(); ++it)  			{ -				(*it)->reset(vert_dpi, horz_dpi); +				it->first->reset(vert_dpi, horz_dpi);  			}  		}  	} diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 8c2d2bc491..8afc5e3ed5 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -86,7 +86,7 @@ public:  	// is_fallback should be true for fallback fonts that aren't used  	// to render directly (Unicode backup, primarily) -	BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool use_color, bool is_fallback, S32 face_n); +	BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n);  	S32 getNumFaces(const std::string& filename); @@ -95,10 +95,8 @@ public:  	void clearFontStreams();  #endif -	typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t; - -	void setFallbackFonts(const font_vector_t &font); -	const font_vector_t &getFallbackFonts() const; +	typedef std::function<bool(llwchar)> char_functor_t; +	void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr);  	// Global font metrics - in units of pixels  	F32 getLineHeight() const; @@ -178,7 +176,9 @@ private:  #endif  	BOOL mIsFallback; -	font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) +	typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t; +	typedef std::vector<fallback_font_t> fallback_font_vector_t; +	fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)  	// *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)  	typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 78017ecb3d..4770f79395 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -89,14 +89,14 @@ void LLFontGL::destroyGL()  	mFontFreetype->destroyGL();  } -BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool use_color, bool is_fallback, S32 face_n) +BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n)  {  	if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))  	{  		mFontFreetype = new LLFontFreetype;  	} -	return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, use_color, is_fallback, face_n); +	return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, is_fallback, face_n);  }  S32 LLFontGL::getNumFaces(const std::string& filename) diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 68bf5db668..a60feb87cb 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -87,7 +87,7 @@ public:  	void destroyGL(); -	BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool use_color, bool is_fallback, S32 face_n); +	BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);  	S32 getNumFaces(const std::string& filename); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 426b10b016..ac2b695a3e 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -46,6 +46,10 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);  const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/"; +LLFontDescriptor::char_functor_map_t LLFontDescriptor::mCharFunctors({ +	{ "is_emoji", LLStringOps::isEmoji } +}); +  LLFontDescriptor::LLFontDescriptor():  	mStyle(0)  { @@ -54,22 +58,22 @@ LLFontDescriptor::LLFontDescriptor():  LLFontDescriptor::LLFontDescriptor(const std::string& name,  								   const std::string& size,   								   const U8 style, -								   const string_vec_t& file_names): +								   const font_file_info_vec_t& font_files):  	mName(name),  	mSize(size),  	mStyle(style), -	mFileNames(file_names) +	mFontFiles(font_files)  {  }  LLFontDescriptor::LLFontDescriptor(const std::string& name,  	const std::string& size,  	const U8 style, -	const string_vec_t& file_names, -	const string_vec_t& ft_collection_listections) : -	LLFontDescriptor(name, size, style, file_names) +	const font_file_info_vec_t& font_list, +	const font_file_info_vec_t& font_collection_files) : +	LLFontDescriptor(name, size, style, font_list)  { -	mFontCollectionsList = ft_collection_listections; +	mFontCollectionFiles = font_collection_files;  }  LLFontDescriptor::LLFontDescriptor(const std::string& name, @@ -81,7 +85,6 @@ LLFontDescriptor::LLFontDescriptor(const std::string& name,  {  } -  bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const  {  	if (mName < b.mName) @@ -174,7 +177,19 @@ LLFontDescriptor LLFontDescriptor::normalize() const  	if (removeSubString(new_name,"Italic"))  		new_style |= LLFontGL::ITALIC; -	return LLFontDescriptor(new_name,new_size,new_style,getFileNames(),getFontCollectionsList()); +	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)); +} + +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));  }  LLFontRegistry::LLFontRegistry(bool create_gl_textures) @@ -272,17 +287,24 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)  		if (child->hasName("file"))  		{  			std::string font_file_name = child->getTextContents(); -			desc.getFileNames().push_back(font_file_name); -			 +			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.getFontCollectionsList().push_back(font_file_name); +					desc.addFontCollectionFile(font_file_name, char_functor);  				}  			} + +			desc.addFontFile(font_file_name, char_functor);  		}  		else if (child->hasName("os"))  		{ @@ -325,19 +347,19 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)  					// 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. -					string_vec_t match_file_names = match_desc->getFileNames(); -					match_file_names.insert(match_file_names.begin(), -											desc.getFileNames().begin(), -											desc.getFileNames().end()); +					font_file_info_vec_t font_files = match_desc->getFontFiles(); +					font_files.insert(font_files.begin(), +									  desc.getFontFiles().begin(), +									  desc.getFontFiles().end()); -					string_vec_t collections_list = match_desc->getFontCollectionsList(); -					collections_list.insert(collections_list.begin(), -						desc.getFontCollectionsList().begin(), -						desc.getFontCollectionsList().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.getFileNames() = match_file_names; -					new_desc.getFontCollectionsList() = collections_list; +					new_desc.setFontFiles(font_files); +					new_desc.setFontCollectionFiles(font_collection_files);  					registry->mFontMap.erase(*match_desc);  					registry->mFontMap[new_desc] = NULL;  				} @@ -422,80 +444,78 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  	// Build list of font names to look for.  	// Files specified for this font come first, followed by those from the default descriptor. -	string_vec_t file_names = match_desc->getFileNames(); -	string_vec_t ft_collection_list = match_desc->getFontCollectionsList(); -	string_vec_t default_file_names; +	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)  	{ -		file_names.insert(file_names.end(), -						  match_default_desc->getFileNames().begin(), -						  match_default_desc->getFileNames().end()); -		ft_collection_list.insert(ft_collection_list.end(), -			match_default_desc->getFontCollectionsList().begin(), -			match_default_desc->getFontCollectionsList().end()); +		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. -	file_names.insert(file_names.end(), -					  getUltimateFallbackList().begin(), -					  getUltimateFallbackList().end()); +	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 (file_names.empty()) +	if (font_files.empty())  	{  		LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL;  		return NULL;  	} -	LLFontFreetype::font_vector_t fontlist;  	LLFontGL *result = NULL; -	// Snarf all fonts we can into fontlist.  First will get pulled -	// off the list and become the "head" font, set to non-fallback. +	// 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; -	std::string local_path = LLFontGL::getFontPathLocal(); -	std::string sys_path = LLFontGL::getFontPathSystem(); -	 +	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); +#endif +  	// The fontname string may contain multiple font file names separated by semicolons.  	// Break it apart and try loading each one, in order. -	for(string_vec_t::iterator file_name_it = file_names.begin(); -		file_name_it != file_names.end();  -		++file_name_it) +	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; -		string_vec_t font_paths; -		font_paths.push_back(local_path + *file_name_it); -		font_paths.push_back(sys_path + *file_name_it); -#if LL_DARWIN -		font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + *file_name_it); -#endif -		 -		bool is_ft_collection = (std::find(ft_collection_list.begin(), ft_collection_list.end(), *file_name_it) != ft_collection_list.end()); + +		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_paths_it = font_paths.begin(); -			font_paths_it != font_paths.end(); -			++font_paths_it) +		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_paths_it) : 1; +			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_paths_it, point_size_scale, -								 LLFontGL::sVertDPI, LLFontGL::sHorizDPI, true, is_fallback, i)) +				if (fontp->loadFace(font_path, point_size_scale, +								 LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i))  				{  					is_font_loaded = true;  					if (is_first_found) @@ -505,7 +525,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  					}  					else  					{ -						fontlist.push_back(fontp->mFontFreetype); +						result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor); +  						delete fontp;  						fontp = NULL;  					} @@ -520,17 +541,12 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  		}  		if(!is_font_loaded)  		{ -			LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it <<  LL_ENDL; +			LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName <<  LL_ENDL;  			delete fontp;  			fontp = NULL;  		}  	} -	if (result && !fontlist.empty()) -	{ -		result->mFontFreetype->setFallbackFonts(fontlist); -	} -  	if (result)  	{  		result->mFontDescriptor = desc; @@ -712,11 +728,11 @@ void LLFontRegistry::dump()  				<< " size=[" << desc.getSize() << "]"  				<< " fileNames="  				<< LL_ENDL; -		for (string_vec_t::const_iterator file_it=desc.getFileNames().begin(); -			 file_it != desc.getFileNames().end(); +		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 <<LL_ENDL; +			LL_INFOS() << "  file: " << file_it->FileName << LL_ENDL;  		}  	}  } diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index b1259ef4e7..b0ef72c5de 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -34,13 +34,32 @@ class LLFontGL;  typedef std::vector<std::string> string_vec_t; +struct LLFontFileInfo +{ +	LLFontFileInfo(const std::string& file_name, const std::function<bool(llwchar)>& char_functor = nullptr) +		: FileName(file_name) +		, CharFunctor(char_functor) +	{ +	} + +	LLFontFileInfo(const LLFontFileInfo& ffi) +		: FileName(ffi.FileName) +		, CharFunctor(ffi.CharFunctor) +	{ +	} + +	std::string FileName; +	std::function<bool(llwchar)> CharFunctor; +}; +typedef std::vector<LLFontFileInfo> font_file_info_vec_t; +  class LLFontDescriptor  {  public:  	LLFontDescriptor();  	LLFontDescriptor(const std::string& name, const std::string& size, const U8 style); -	LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names); -	LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names, const string_vec_t& font_collections); +	LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list); +	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_list);  	LLFontDescriptor normalize() const;  	bool operator<(const LLFontDescriptor& b) const; @@ -51,19 +70,26 @@ public:  	void setName(const std::string& name) { mName = name; }  	const std::string& getSize() const { return mSize; }  	void setSize(const std::string& size) { mSize = size; } -	const std::vector<std::string>& getFileNames() const { return mFileNames; } -	std::vector<std::string>& getFileNames() { return mFileNames; } -	const std::vector<std::string>& getFontCollectionsList() const { return mFontCollectionsList; } -	std::vector<std::string>& getFontCollectionsList() { return mFontCollectionsList; } + +	void addFontFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null); +	const font_file_info_vec_t & getFontFiles() const { return mFontFiles; } +	void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; } +	void addFontCollectionFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null); +	const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; } +	void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; } +  	const U8 getStyle() const { return mStyle; }  	void setStyle(U8 style) { mStyle = style; }  private:  	std::string mName;  	std::string mSize; -	string_vec_t mFileNames; -	string_vec_t mFontCollectionsList; +	font_file_info_vec_t mFontFiles; +	font_file_info_vec_t mFontCollectionFiles;  	U8 mStyle; + +	typedef std::map<std::string, std::function<bool(llwchar)>> char_functor_map_t; +	static char_functor_map_t mCharFunctors;  };  class LLFontRegistry diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b83d3afadd..f03dcb4066 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -21,6 +21,7 @@ include(EXPAT)  include(FMODEX)  include(GLOD)  include(Hunspell) +include(ICU4C)  include(JsonCpp)  include(LLAppearance)  include(LLAudio) @@ -2003,6 +2004,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}      ${NDOF_LIBRARY}      ${NVAPI_LIBRARY}      ${HUNSPELL_LIBRARY} +    ${ICU4C_LIBRARY}      ${viewer_LIBRARIES}      ${BOOST_PROGRAM_OPTIONS_LIBRARY}      ${BOOST_REGEX_LIBRARY} diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 2d5263b78f..6df666a700 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -3,6 +3,7 @@    <font name="default" comment="default font files (global fallbacks)">      <file>DejaVuSans.ttf</file> +    <file functor="is_emoji">Twemoji.ttf</file>      <os name="Windows">        <file>meiryo.TTC</file>        <file>MSGOTHIC.TTC</file> diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index 4fba26ab2f..d1de20a6a0 100644 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -3,6 +3,7 @@  project(win_crash_logger)  include(00-Common) +include(ICU4C)  include(LLCommon)  include(LLCoreHttp)  include(LLCrashLogger) @@ -74,6 +75,7 @@ add_executable(windows-crash-logger WIN32 ${win_crash_logger_SOURCE_FILES})  target_link_libraries(windows-crash-logger      ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} +    ${ICU4C_LIBRARY}      ${LLCRASHLOGGER_LIBRARIES}      ${LLWINDOW_LIBRARIES}      ${LLVFS_LIBRARIES} | 
