Fallback fonts can have first crack at adding an unknown character + set Twemoji as the viewer's fallback for all emoji blocks

master
Kitty Barnett 2019-11-07 17:15:21 +01:00
parent 418308bc7c
commit 5a6ddb2ea6
16 changed files with 333 additions and 101 deletions

View File

@ -1519,6 +1519,96 @@
<key>version</key>
<string>2012.1-2</string>
</map>
<key>icu4c</key>
<map>
<key>copyright</key>
<string>Copyright (c) 1995-2011 International Business Machines Corporation and others &lt;http://source.icu-project.org&gt;</string>
<key>description</key>
<string>ICU is a mature, widely used set of C/C++ and Java libraries providing Unicode and Globalization support for software applications. ICU is widely portable and gives applications the same results on all platforms and between C/C++ and Java software.</string>
<key>license</key>
<string>ICU, permissive non-copyleft free software license</string>
<key>license_file</key>
<string>LICENSES/icu.txt</string>
<key>name</key>
<string>icu4c</string>
<key>platforms</key>
<map>
<key>darwin</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>910edfc0b936389bc8804c42d1008aa8</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/icu4c_3p-update-icu4c/rev/295486/arch/Darwin/installer/icu4c-4.8.1-darwin-295486.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>2c34cb4e62d1f155d5dad798e69d03c8</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/466/1005/icu4c-4.8.1-darwin64-500388.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>0a4423cfd26409f33ae81fb9806a9972</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-icu4c/rev/314152/arch/Linux/installer/icu4c-4.8.1-linux-314152.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
<key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>b327031733c36efe2eee4582aefb2d66</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/462/995/icu4c-4.8.1-linux64-500388.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>af354f6ab6d2cecf266c79031977e3e0</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/492/1078/icu4c-4.8.1-windows-500388.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>e8b20cea748b90ea18bb63dfba06e059</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/491/1075/icu4c-4.8.1-windows64-500388.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>4.8.1</string>
</map>
<key>jpeglib</key>
<map>
<key>copyright</key>

View File

@ -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

View File

@ -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
)

22
indra/cmake/ICU4C.cmake Normal file
View File

@ -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)

View File

@ -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}

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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}

View File

@ -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>

View File

@ -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}