Merge branch 'contribution/emoji'

master
Kitty Barnett 2022-08-28 00:08:38 +02:00
commit 5440464a9c
38 changed files with 822 additions and 430 deletions

1
.gitignore vendored
View File

@ -46,6 +46,7 @@ indra/newview/dbghelp.dll
indra/newview/filters.xml
indra/newview/fmod.dll
indra/newview/fmod.log
indra/newview/fonts
indra/newview/mozilla-theme
indra/newview/mozilla-universal-darwin.tgz
indra/newview/pilot.txt

View File

@ -807,6 +807,36 @@
<key>version</key>
<string>2.01.07.555883</string>
</map>
<key>fonts</key>
<map>
<key>copyright</key>
<string>Copyright various</string>
<key>description</key>
<string>Viewer fonts</string>
<key>license</key>
<string>Various open source</string>
<key>license_file</key>
<string>LICENSES/fonts.txt</string>
<key>name</key>
<string>fonts</string>
<key>platforms</key>
<map>
<key>common</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>65b89f06d9b698b376e1736216dd5623</string>
<key>url</key>
<string>viewer_fonts-1.0-1.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
<string>1.0</string>
</map>
<key>fontconfig</key>
<map>
<key>copyright</key>
@ -916,9 +946,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>7ee200d6b5fa282c7f973ade5615aa86</string>
<string>d8f5b352176d5c582d91ce936a700b2c</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78594/744011/freetype-2.4.4.557047-windows-557047.tar.bz2</string>
<string>freetype-2.10.1.0-windows-72.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -928,9 +958,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>69307aaba16ac71531c9c4d930ace993</string>
<string>aa8be83cdfcd5cda0343ea72e7d662ca</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78593/744010/freetype-2.4.4.557047-windows64-557047.tar.bz2</string>
<string>freetype-2.10.1.0-windows64-72.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
@ -1401,6 +1431,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

@ -29,6 +29,7 @@ set(cmake_SOURCE_FILES
FindBerkeleyDB.cmake
FindGLH.cmake
FindHUNSPELL.cmake
FindICU4C.cmake
FindJsonCpp.cmake
FindNDOF.cmake
FindOpenJPEG.cmake
@ -45,6 +46,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

@ -10,3 +10,4 @@ if (NOT USESYSTEMLIBS)
use_prebuilt_binary(slvoice)
endif(NOT USESYSTEMLIBS)
use_prebuilt_binary(fonts)

View File

@ -3,6 +3,7 @@
project(llcommon)
include(00-Common)
include(ICU4C)
include(LLCommon)
include(bugsplat)
include(Linking)
@ -289,6 +290,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
@ -872,6 +873,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

@ -187,6 +187,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

@ -30,152 +30,165 @@
#include "llfontbitmapcache.h"
LLFontBitmapCache::LLFontBitmapCache()
: LLTrace::MemTrackable<LLFontBitmapCache>("LLFontBitmapCache"),
mNumComponents(0),
mBitmapWidth(0),
mBitmapHeight(0),
mBitmapNum(-1),
mMaxCharWidth(0),
mMaxCharHeight(0),
mCurrentOffsetX(1),
mCurrentOffsetY(1)
: LLTrace::MemTrackable<LLFontBitmapCache>("LLFontBitmapCache")
, mBitmapWidth(0)
, mBitmapHeight(0)
, mMaxCharWidth(0)
, mMaxCharHeight(0)
{
// *TODO: simplify with initializer after VS2017
for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
mCurrentOffsetX[idx] = 1;
mCurrentOffsetY[idx] = 1;
}
}
LLFontBitmapCache::~LLFontBitmapCache()
{
}
void LLFontBitmapCache::init(S32 num_components,
S32 max_char_width,
void LLFontBitmapCache::init(S32 max_char_width,
S32 max_char_height)
{
reset();
mNumComponents = num_components;
mMaxCharWidth = max_char_width;
mMaxCharHeight = max_char_height;
}
LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const
{
if (bitmap_num >= mImageRawVec.size())
return NULL;
return mImageRawVec[bitmap_num];
}
LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const
{
if (bitmap_num >= mImageGLVec.size())
return NULL;
return mImageGLVec[bitmap_num];
}
BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32 &pos_x, S32 &pos_y, S32& bitmap_num)
{
if ((mBitmapNum<0) || (mCurrentOffsetX + width + 1) > mBitmapWidth)
S32 image_width = mMaxCharWidth * 20;
S32 pow_iw = 2;
while (pow_iw < image_width)
{
if ((mBitmapNum<0) || (mCurrentOffsetY + 2*mMaxCharHeight + 2) > mBitmapHeight)
pow_iw <<= 1;
}
image_width = pow_iw;
image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
mBitmapWidth = image_width;
mBitmapHeight = image_width;
}
LLImageRaw *LLFontBitmapCache::getImageRaw(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
const U32 bitmap_idx = static_cast<U32>(bitmap_type);
if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageRawVec[bitmap_idx].size())
return nullptr;
return mImageRawVec[bitmap_idx][bitmap_num];
}
LLImageGL *LLFontBitmapCache::getImageGL(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
const U32 bitmap_idx = static_cast<U32>(bitmap_type);
if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageGLVec[bitmap_idx].size())
return nullptr;
return mImageGLVec[bitmap_idx][bitmap_num];
}
BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyphType bitmap_type, U32& bitmap_num)
{
if (bitmap_type >= EFontGlyphType::Count)
{
return FALSE;
}
const U32 bitmap_idx = static_cast<U32>(bitmap_type);
if (mImageRawVec[bitmap_idx].empty() || (mCurrentOffsetX[bitmap_idx] + width + 1) > mBitmapWidth)
{
if ((mImageRawVec[bitmap_idx].empty()) || (mCurrentOffsetY[bitmap_idx] + 2*mMaxCharHeight + 2) > mBitmapHeight)
{
// We're out of space in the current image, or no image
// has been allocated yet. Make a new one.
mImageRawVec.push_back(new LLImageRaw);
mBitmapNum = mImageRawVec.size()-1;
LLImageRaw *image_raw = getImageRaw(mBitmapNum);
S32 num_components = getNumComponents(bitmap_type);
mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
bitmap_num = mImageRawVec[bitmap_idx].size() - 1;
LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
if (EFontGlyphType::Grayscale == bitmap_type)
{
image_raw->clear(255, 0);
}
// Make corresponding GL image.
mImageGLVec.push_back(new LLImageGL(FALSE));
LLImageGL *image_gl = getImageGL(mBitmapNum);
S32 image_width = mMaxCharWidth * 20;
S32 pow_iw = 2;
while (pow_iw < image_width)
{
pow_iw *= 2;
}
image_width = pow_iw;
image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
S32 image_height = image_width;
image_raw->resize(image_width, image_height, mNumComponents);
mBitmapWidth = image_width;
mBitmapHeight = image_height;
switch (mNumComponents)
{
case 1:
image_raw->clear();
break;
case 2:
image_raw->clear(255, 0);
break;
}
mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false));
LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
// Start at beginning of the new image.
mCurrentOffsetX = 1;
mCurrentOffsetY = 1;
mCurrentOffsetX[bitmap_idx] = 1;
mCurrentOffsetY[bitmap_idx] = 1;
// Attach corresponding GL texture.
image_gl->createGLTexture(0, image_raw);
// Attach corresponding GL texture. (*TODO: is this needed?)
gGL.getTexUnit(0)->bind(image_gl);
image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE);
claimMem(image_raw);
claimMem(image_gl);
}
else
{
// Move to next row in current image.
mCurrentOffsetX = 1;
mCurrentOffsetY += mMaxCharHeight + 1;
mCurrentOffsetX[bitmap_idx] = 1;
mCurrentOffsetY[bitmap_idx] += mMaxCharHeight + 1;
}
}
pos_x = mCurrentOffsetX;
pos_y = mCurrentOffsetY;
bitmap_num = mBitmapNum;
pos_x = mCurrentOffsetX[bitmap_idx];
pos_y = mCurrentOffsetY[bitmap_idx];
bitmap_num = getNumBitmaps(bitmap_type) - 1;
mCurrentOffsetX += width + 1;
mCurrentOffsetX[bitmap_idx] += width + 1;
return TRUE;
}
void LLFontBitmapCache::destroyGL()
{
for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec.begin();
it != mImageGLVec.end(); ++it)
for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
(*it)->destroyGLTexture();
for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec[idx].begin(); it != mImageGLVec[idx].end(); ++it)
{
(*it)->destroyGLTexture();
}
}
}
void LLFontBitmapCache::reset()
{
for (std::vector<LLPointer<LLImageRaw> >::iterator it = mImageRawVec.begin(), end_it = mImageRawVec.end();
it != end_it;
++it)
for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
disclaimMem(**it);
for (std::vector<LLPointer<LLImageRaw> >::iterator it = mImageRawVec[idx].begin(), end_it = mImageRawVec[idx].end(); it != end_it; ++it)
{
disclaimMem(**it);
}
mImageRawVec[idx].clear();
}
mImageRawVec.clear();
for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec.begin(), end_it = mImageGLVec.end();
it != end_it;
++it)
for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
disclaimMem(**it);
for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec[idx].begin(), end_it = mImageGLVec[idx].end(); it != end_it; ++it)
{
disclaimMem(**it);
}
mImageGLVec[idx].clear();
mCurrentOffsetX[idx] = 1;
mCurrentOffsetY[idx] = 1;
}
mImageGLVec.clear();
mBitmapWidth = 0;
mBitmapHeight = 0;
mBitmapNum = -1;
mCurrentOffsetX = 1;
mCurrentOffsetY = 1;
}
//static
U32 LLFontBitmapCache::getNumComponents(EFontGlyphType bitmap_type)
{
switch (bitmap_type)
{
case EFontGlyphType::Grayscale:
return 2;
case EFontGlyphType::Color:
return 4;
default:
llassert(false);
return 2;
}
}

View File

@ -30,6 +30,14 @@
#include <vector>
#include "lltrace.h"
enum class EFontGlyphType : U32
{
Grayscale = 0,
Color,
Count,
Unspecified,
};
// Maintain a collection of bitmaps containing rendered glyphs.
// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.
class LLFontBitmapCache : public LLTrace::MemTrackable<LLFontBitmapCache>
@ -39,35 +47,35 @@ public:
~LLFontBitmapCache();
// Need to call this once, before caching any glyphs.
void init(S32 num_components,
S32 max_char_width,
void init(S32 max_char_width,
S32 max_char_height);
void reset();
BOOL nextOpenPos(S32 width, S32 &posX, S32 &posY, S32 &bitmapNum);
BOOL nextOpenPos(S32 width, S32& posX, S32& posY, EFontGlyphType bitmapType, U32& bitmapNum);
void destroyGL();
LLImageRaw *getImageRaw(U32 bitmapNum = 0) const;
LLImageGL *getImageGL(U32 bitmapNum = 0) const;
LLImageRaw* getImageRaw(EFontGlyphType bitmapType, U32 bitmapNum) const;
LLImageGL* getImageGL(EFontGlyphType bitmapType, U32 bitmapNum) const;
S32 getMaxCharWidth() const { return mMaxCharWidth; }
S32 getNumComponents() const { return mNumComponents; }
U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? mImageRawVec[static_cast<U32>(bitmapType)].size() : 0; }
S32 getBitmapWidth() const { return mBitmapWidth; }
S32 getBitmapHeight() const { return mBitmapHeight; }
protected:
static U32 getNumComponents(EFontGlyphType bitmap_type);
private:
S32 mNumComponents;
S32 mBitmapWidth;
S32 mBitmapHeight;
S32 mBitmapNum;
S32 mCurrentOffsetX[static_cast<U32>(EFontGlyphType::Count)];
S32 mCurrentOffsetY[static_cast<U32>(EFontGlyphType::Count)];
S32 mMaxCharWidth;
S32 mMaxCharHeight;
S32 mCurrentOffsetX;
S32 mCurrentOffsetY;
std::vector<LLPointer<LLImageRaw> > mImageRawVec;
std::vector<LLPointer<LLImageGL> > mImageGLVec;
std::vector<LLPointer<LLImageRaw>> mImageRawVec[static_cast<U32>(EFontGlyphType::Count)];
std::vector<LLPointer<LLImageGL>> mImageGLVec[static_cast<U32>(EFontGlyphType::Count)];
};
#endif //LL_LLFONTBITMAPCACHE_H

View File

@ -40,8 +40,10 @@
#include FT_FREETYPE_H
#endif
#include "lldir.h"
#include "llerror.h"
#include "llimage.h"
#include "llimagepng.h"
//#include "llimagej2c.h"
#include "llmath.h" // Linden math
#include "llstring.h"
@ -89,8 +91,9 @@ LLFontManager::~LLFontManager()
}
LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
LLFontGlyphInfo::LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type)
: mGlyphIndex(index),
mGlyphType(glyph_type),
mWidth(0), // In pixels
mHeight(0), // In pixels
mXAdvance(0.f), // In pixels
@ -99,10 +102,25 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
mYBitmapOffset(0), // Offset to the origin in the bitmap
mXBearing(0), // Distance from baseline to left in pixels
mYBearing(0), // Distance from baseline to top in pixels
mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph
mBitmapEntry(std::make_pair(EFontGlyphType::Unspecified, -1)) // Which bitmap in the bitmap cache contains this glyph
{
}
LLFontGlyphInfo::LLFontGlyphInfo(const LLFontGlyphInfo& fgi)
: mGlyphIndex(fgi.mGlyphIndex)
, mGlyphType(fgi.mGlyphType)
, mWidth(fgi.mWidth)
, mHeight(fgi.mHeight)
, mXAdvance(fgi.mXAdvance)
, mYAdvance(fgi.mYAdvance)
, mXBitmapOffset(fgi.mXBitmapOffset)
, mYBitmapOffset(fgi.mYBitmapOffset)
, mXBearing(fgi.mXBearing)
, mYBearing(fgi.mYBearing)
{
mBitmapEntry = fgi.mBitmapEntry;
}
LLFontFreetype::LLFontFreetype()
: LLTrace::MemTrackable<LLFontFreetype>("LLFontFreetype"),
mFontBitmapCachep(new LLFontBitmapCache),
@ -157,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, S32 components, 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.
@ -221,7 +239,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
S32 max_char_width = ll_round(0.5f + (x_max - x_min));
S32 max_char_height = ll_round(0.5f + (y_max - y_min));
mFontBitmapCachep->init(components, max_char_width, max_char_height);
mFontBitmapCachep->init(max_char_width, max_char_height);
claimMem(mFontBitmapCachep);
@ -234,7 +252,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if (!mIsFallback)
{
// Add the default glyph
addGlyphFromFont(this, 0, 0);
addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale);
}
mName = filename;
@ -327,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
@ -358,7 +373,7 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
return 0.0;
// Return existing info only if it is current
LLFontGlyphInfo* gi = getGlyphInfo(wch);
LLFontGlyphInfo* gi = getGlyphInfo(wch, EFontGlyphType::Unspecified);
if (gi)
{
return gi->mXAdvance;
@ -390,10 +405,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
return 0.0;
//llassert(!mIsFallback);
LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left);;
LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left, EFontGlyphType::Unspecified);;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
// Kern this puppy.
LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right, EFontGlyphType::Unspecified);
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
@ -424,59 +439,90 @@ BOOL LLFontFreetype::hasGlyph(llwchar wch) const
return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
}
LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type) const
{
if (mFTFace == NULL)
return FALSE;
llassert(!mIsFallback);
llassert(glyph_type < EFontGlyphType::Count);
//LL_DEBUGS() << "Adding new glyph for " << wch << " to font" << LL_ENDL;
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);
return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
}
}
}
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter == mCharGlyphInfoMap.end())
std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
char_glyph_info_map_t::iterator iter =
std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; });
if (iter == range_it.second)
{
return addGlyphFromFont(this, wch, glyph_index);
return addGlyphFromFont(this, wch, glyph_index, glyph_type);
}
return NULL;
}
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const
{
if (mFTFace == NULL)
return NULL;
llassert(!mIsFallback);
fontp->renderGlyph(glyph_index);
fontp->renderGlyph(requested_glyph_type, glyph_index);
EFontGlyphType bitmap_glyph_type = EFontGlyphType::Unspecified;
switch (fontp->mFTFace->glyph->bitmap.pixel_mode)
{
case FT_PIXEL_MODE_MONO:
case FT_PIXEL_MODE_GRAY:
bitmap_glyph_type = EFontGlyphType::Grayscale;
break;
case FT_PIXEL_MODE_BGRA:
bitmap_glyph_type = EFontGlyphType::Color;
break;
default:
llassert_always(true);
break;
}
S32 width = fontp->mFTFace->glyph->bitmap.width;
S32 height = fontp->mFTFace->glyph->bitmap.rows;
S32 pos_x, pos_y;
S32 bitmap_num;
mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num);
U32 bitmap_num;
mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_glyph_type, bitmap_num);
mAddGlyphCount++;
LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index);
LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index, requested_glyph_type);
gi->mXBitmapOffset = pos_x;
gi->mYBitmapOffset = pos_y;
gi->mBitmapNum = bitmap_num;
gi->mBitmapEntry = std::make_pair(bitmap_glyph_type, bitmap_num);
gi->mWidth = width;
gi->mHeight = height;
gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
@ -487,8 +533,12 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
insertGlyphInfo(wch, gi);
llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
|| fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
if (requested_glyph_type != bitmap_glyph_type)
{
LLFontGlyphInfo* gi_temp = new LLFontGlyphInfo(*gi);
gi_temp->mGlyphType = bitmap_glyph_type;
insertGlyphInfo(wch, gi_temp);
}
if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
|| fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
@ -523,62 +573,63 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
buffer_row_stride = width;
}
switch (mFontBitmapCachep->getNumComponents())
{
case 1:
mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x,
pos_y,
width,
height,
buffer_data,
buffer_row_stride,
TRUE);
break;
case 2:
setSubImageLuminanceAlpha(pos_x,
pos_y,
bitmap_num,
width,
height,
buffer_data,
buffer_row_stride);
break;
default:
break;
}
setSubImageLuminanceAlpha(pos_x,
pos_y,
bitmap_num,
width,
height,
buffer_data,
buffer_row_stride);
if (tmp_graydata)
delete[] tmp_graydata;
}
else if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
{
setSubImageBGRA(pos_x,
pos_y,
bitmap_num,
fontp->mFTFace->glyph->bitmap.width,
fontp->mFTFace->glyph->bitmap.rows,
fontp->mFTFace->glyph->bitmap.buffer,
llabs(fontp->mFTFace->glyph->bitmap.pitch));
} else {
// we don't know how to handle this pixel format from FreeType;
// omit it from the font-image.
llassert(false);
}
LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num);
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num);
image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
return gi;
}
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const
{
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter != mCharGlyphInfoMap.end())
std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
char_glyph_info_map_t::iterator iter = (EFontGlyphType::Unspecified != glyph_type)
? std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; })
: range_it.first;
if (iter != range_it.second)
{
return iter->second;
}
else
{
// this glyph doesn't yet exist, so render it and return the result
return addGlyph(wch);
return addGlyph(wch, (EFontGlyphType::Unspecified != glyph_type) ? glyph_type : EFontGlyphType::Grayscale);
}
}
void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
{
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter != mCharGlyphInfoMap.end())
llassert(gi->mGlyphType < EFontGlyphType::Count);
std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
char_glyph_info_map_t::iterator iter =
std::find_if(range_it.first, range_it.second, [&gi](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == gi->mGlyphType; });
if (iter != range_it.second)
{
delete iter->second;
iter->second = gi;
@ -586,16 +637,23 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
else
{
claimMem(gi);
mCharGlyphInfoMap[wch] = gi;
mCharGlyphInfoMap.insert(std::make_pair(wch, gi));
}
}
void LLFontFreetype::renderGlyph(U32 glyph_index) const
void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const
{
if (mFTFace == NULL)
return;
llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT) );
FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT;
if (EFontGlyphType::Color == bitmap_type)
{
// We may not actually get a color render so our caller should always examine mFTFace->glyph->bitmap.pixel_mode
load_flags |= FT_LOAD_COLOR;
}
llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, load_flags) );
llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) );
@ -605,7 +663,7 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
resetBitmapCache();
loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
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.
@ -615,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);
}
}
}
@ -643,7 +699,7 @@ void LLFontFreetype::resetBitmapCache()
if(!mIsFallback)
{
// Add the empty glyph
addGlyphFromFont(this, 0, 0);
addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale);
}
}
@ -657,6 +713,34 @@ const std::string &LLFontFreetype::getName() const
return mName;
}
static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_name)
{
LLPointer<LLImagePNG> tmpImage = new LLImagePNG();
if ( (tmpImage->encode(image_raw, 0.0f)) && (tmpImage->save(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name))) )
{
LL_INFOS("Font") << "Successfully saved " << file_name << LL_ENDL;
}
else
{
LL_WARNS("Font") << "Failed to save " << file_name << LL_ENDL;
}
}
void LLFontFreetype::dumpFontBitmaps() const
{
// Dump all the regular bitmaps (if any)
for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Grayscale); idx < cnt; idx++)
{
dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
}
// Dump all the color bitmaps (if any)
for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Color); idx < cnt; idx++)
{
dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, idx), llformat("%s_%d_%d_%d_clr.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
}
}
const LLFontBitmapCache* LLFontFreetype::getFontBitmapCache() const
{
return mFontBitmapCachep;
@ -672,9 +756,38 @@ U8 LLFontFreetype::getStyle() const
return mStyle;
}
bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const
{
LLImageRaw* image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, bitmap_num);
llassert(!mIsFallback);
llassert(image_raw && (image_raw->getComponents() == 4));
// NOTE: inspired by LLImageRaw::setSubImage()
U32* image_data = (U32*)image_raw->getData();
if (!image_data)
{
return false;
}
for (U32 idxRow = 0; idxRow < height; idxRow++)
{
const U32 nSrcRow = height - 1 - idxRow;
const U32 nSrcOffset = nSrcRow * width * image_raw->getComponents();
const U32 nDstOffset = (y + idxRow) * image_raw->getWidth() + x;
for (U32 idxCol = 0; idxCol < width; idxCol++)
{
U32 nTemp = nSrcOffset + idxCol * 4;
image_data[nDstOffset + idxCol] = data[nTemp + 3] << 24 | data[nTemp] << 16 | data[nTemp + 1] << 8 | data[nTemp + 2];
}
}
return true;
}
void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
{
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, bitmap_num);
llassert(!mIsFallback);
llassert(image_raw && (image_raw->getComponents() == 2));

View File

@ -56,9 +56,11 @@ private:
struct LLFontGlyphInfo
{
LLFontGlyphInfo(U32 index);
LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type);
LLFontGlyphInfo(const LLFontGlyphInfo& fgi);
U32 mGlyphIndex;
EFontGlyphType mGlyphType;
// Metrics
S32 mWidth; // In pixels
@ -71,7 +73,7 @@ struct LLFontGlyphInfo
S32 mYBitmapOffset; // Offset to the origin in the bitmap
S32 mXBearing; // Distance from baseline to left in pixels
S32 mYBearing; // Distance from baseline to top in pixels
S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph
std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
};
extern LLFontManager *gFontManagerp;
@ -84,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, S32 components, BOOL is_fallback, S32 face_n = 0);
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);
@ -93,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;
@ -135,7 +135,7 @@ public:
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
LLFontGlyphInfo* getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const;
void reset(F32 vert_dpi, F32 horz_dpi);
@ -143,6 +143,7 @@ public:
const std::string& getName() const;
void dumpFontBitmaps() const;
const LLFontBitmapCache* getFontBitmapCache() const;
void setStyle(U8 style);
@ -151,10 +152,11 @@ public:
private:
void resetBitmapCache();
void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
LLFontGlyphInfo* addGlyph(llwchar wch) const; // Add a new character to the font if necessary
LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(U32 glyph_index) const;
LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
std::string mName;
@ -174,9 +176,12 @@ 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)
typedef boost::unordered_map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
// *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;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLFontBitmapCache* mFontBitmapCachep;

View File

@ -89,14 +89,14 @@ void LLFontGL::destroyGL()
mFontFreetype->destroyGL();
}
BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, 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, components, 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)
@ -112,14 +112,14 @@ S32 LLFontGL::getNumFaces(const std::string& filename)
static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts");
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
LLRectf rect_float(rect.mLeft, rect.mTop, rect.mRight, rect.mBottom);
return render(wstr, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses);
return render(wstr, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color);
}
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
F32 x = rect.mLeft;
F32 y = 0.f;
@ -140,12 +140,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec
y = rect.mBottom;
break;
}
return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses);
return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses, use_color);
}
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_FONTS);
@ -280,7 +280,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
LLColor4U text_color(color);
S32 bitmap_num = -1;
std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
S32 glyph_count = 0;
for (i = begin_offset; i < begin_offset + length; i++)
{
@ -290,7 +290,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
fgi = mFontFreetype->getGlyphInfo(wch, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
}
if (!fgi)
{
@ -298,8 +298,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
break;
}
// Per-glyph bitmap texture.
S32 next_bitmap_num = fgi->mBitmapNum;
if (next_bitmap_num != bitmap_num)
std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry;
if (next_bitmap_entry != bitmap_entry)
{
// Actually draw the queued glyphs before switching their texture;
// otherwise the queued glyphs will be taken from wrong textures.
@ -313,8 +313,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
glyph_count = 0;
}
bitmap_num = next_bitmap_num;
LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num);
bitmap_entry = next_bitmap_entry;
LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
gGL.getTexUnit(0)->bind(font_image);
}
@ -347,7 +347,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
glyph_count = 0;
}
drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength);
drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, (bitmap_entry.first == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, style_to_add, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
@ -357,7 +357,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
next_glyph = mFontFreetype->getGlyphInfo(next_char);
next_glyph = mFontFreetype->getGlyphInfo(next_char, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
@ -411,7 +411,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
shadow,
S32_MAX, max_pixels,
right_x,
FALSE);
FALSE,
use_color);
gGL.popUIMatrix();
}
@ -425,19 +426,19 @@ S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, cons
return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses);
return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE);
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE, FALSE);
}
// font metrics - override for LLFontFreetype that returns units of virtual pixels
@ -514,7 +515,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
}
F32 advance = mFontFreetype->getXAdvance(fgi);
@ -534,7 +535,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
&& (next_char < LAST_CHARACTER))
{
// Kern this puppy.
next_glyph = mFontFreetype->getGlyphInfo(next_char);
next_glyph = mFontFreetype->getGlyphInfo(next_char, EFontGlyphType::Unspecified);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@ -616,7 +617,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
if (NULL == fgi)
{
@ -641,7 +642,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if (((i+1) < max_chars) && wchars[i+1])
{
// Kern this puppy.
next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1], EFontGlyphType::Unspecified);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
@ -688,7 +689,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
{
llwchar wch = wchars[i];
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
// last character uses character width, since the whole character needs to be visible
// other characters just use advance
@ -763,7 +764,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
next_glyph = NULL;
if(!glyph)
{
glyph = mFontFreetype->getGlyphInfo(wch);
glyph = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
}
F32 char_width = mFontFreetype->getXAdvance(glyph);
@ -793,7 +794,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
&& (wchars[(pos + 1)]))
{
// Kern this puppy.
next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1], EFontGlyphType::Unspecified);
cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
}
@ -831,6 +832,26 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
}
}
void LLFontGL::dumpTextures()
{
if (mFontFreetype.notNull())
{
mFontFreetype->dumpFontBitmaps();
}
}
// static
void LLFontGL::dumpFonts()
{
sFontRegistry->dump();
}
// static
void LLFontGL::dumpFontTextures()
{
sFontRegistry->dumpTextures();
}
// Force standard fonts to get generated up front.
// This is primarily for error detection purposes.
// Don't do this during initClass because it can be slow and we want to get

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, const S32 components, BOOL is_fallback, S32 face_n = 0);
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);
@ -98,7 +98,8 @@ public:
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
BOOL use_ellipses = FALSE) const;
BOOL use_ellipses = FALSE,
BOOL use_color = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset,
const LLRectf& rect,
@ -107,7 +108,8 @@ public:
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
BOOL use_ellipses = FALSE) const;
BOOL use_ellipses = FALSE,
BOOL use_color = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset,
F32 x, F32 y,
@ -116,12 +118,13 @@ public:
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x=NULL,
BOOL use_ellipses = FALSE) const;
BOOL use_ellipses = FALSE,
BOOL use_color = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
// renderUTF8 does a conversion, so is slower!
S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
@ -163,6 +166,10 @@ public:
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true);
void dumpTextures();
static void dumpFonts();
static void dumpFontTextures();
// Load sans-serif, sans-serif-small, etc.
// Slow, requires multiple seconds to load fonts.
static bool loadDefaultFonts();

View File

@ -47,6 +47,10 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
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 }
});
LLFontDescriptor::LLFontDescriptor():
mStyle(0)
{
@ -55,22 +59,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,
@ -82,7 +86,6 @@ LLFontDescriptor::LLFontDescriptor(const std::string& name,
{
}
bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const
{
if (mName < b.mName)
@ -175,7 +178,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)
@ -273,17 +288,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"))
{
@ -326,19 +348,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;
}
@ -423,82 +445,80 @@ 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);
font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL + *file_name_it);
font_paths.push_back(sys_path + MACOSX_FONT_SUPPLEMENTAL + *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, 2, 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)
@ -508,7 +528,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;
}
@ -523,17 +544,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;
@ -715,11 +731,22 @@ 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;
}
}
}
void LLFontRegistry::dumpTextures()
{
for (const auto& fontEntry : mFontMap)
{
if (fontEntry.second)
{
fontEntry.second->dumpTextures();
}
}
}

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
@ -94,6 +120,7 @@ public:
bool nameToSize(const std::string& size_name, F32& size);
void dump();
void dumpTextures();
const string_vec_t& getUltimateFallbackList() const;

View File

@ -875,7 +875,7 @@ void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y
//
font->renderUTF8(mLabel, 0, x, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, TRUE);
S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, /*use_ellipses*/TRUE, /*use_color*/FALSE);
}
void LLFolderViewItem::draw()
@ -954,7 +954,7 @@ void LLFolderViewItem::draw()
{
font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, S32_MAX, &right_x, FALSE );
S32_MAX, S32_MAX, &right_x, /*use_ellipses*/FALSE, /*use_color*/FALSE );
}
//--------------------------------------------------------------------------------//
@ -967,7 +967,7 @@ void LLFolderViewItem::draw()
F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
font->renderUTF8( combined_string, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
filter_string_length, S32_MAX, &right_x, FALSE );
filter_string_length, S32_MAX, &right_x, /*use_ellipses*/FALSE, /*use_color*/FALSE );
}
//Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to

View File

@ -161,9 +161,11 @@ LLTextBase::Params::Params()
line_spacing("line_spacing"),
max_text_length("max_length", 255),
font_shadow("font_shadow"),
text_valign("text_valign"),
wrap("wrap"),
trusted_content("trusted_content", true),
use_ellipses("use_ellipses", false),
use_color("use_color", false),
parse_urls("parse_urls", false),
force_urls_external("force_urls_external", false),
parse_highlights("parse_highlights", false)
@ -206,6 +208,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mVPad(p.v_pad),
mHAlign(p.font_halign),
mVAlign(p.font_valign),
mTextVAlign(p.text_valign.isProvided() ? p.text_valign : p.font_valign),
mLineSpacingMult(p.line_spacing.multiple),
mLineSpacingPixels(p.line_spacing.pixels),
mClip(p.clip),
@ -219,6 +222,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mPlainText ( p.plain_text ),
mWordWrap(p.wrap),
mUseEllipses( p.use_ellipses ),
mUseColor(p.use_color),
mParseHTML(p.parse_urls),
mForceUrlsExternal(p.force_urls_external),
mParseHighlights(p.parse_highlights),
@ -515,7 +519,7 @@ void LLTextBase::drawCursor()
fontp = segmentp->getStyle()->getFont();
fontp->render(text, mCursorPos, cursor_rect,
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
LLFontGL::LEFT, mVAlign,
LLFontGL::LEFT, mTextVAlign,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
1);
@ -1920,8 +1924,6 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
text_len = mLabel.getWString().length();
}
if (index > text_len) { return mSegments.end(); }
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
@ -1945,8 +1947,6 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i
text_len = mLabel.getWString().length();
}
if (index > text_len) { return mSegments.end(); }
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
@ -3239,12 +3239,13 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
color,
LLFontGL::LEFT, mEditor.mVAlign,
LLFontGL::LEFT, mEditor.mTextVAlign,
LLFontGL::NORMAL,
mStyle->getShadowType(),
length,
&right_x,
mEditor.getUseEllipses());
mEditor.getUseEllipses(),
mEditor.getUseColor());
}
rect.mLeft = right_x;
@ -3258,12 +3259,13 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
mStyle->getSelectedColor().get(),
LLFontGL::LEFT, mEditor.mVAlign,
LLFontGL::LEFT, mEditor.mTextVAlign,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
length,
&right_x,
mEditor.getUseEllipses());
mEditor.getUseEllipses(),
mEditor.getUseColor());
}
rect.mLeft = right_x;
if( selection_end < seg_end )
@ -3275,12 +3277,13 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
color,
LLFontGL::LEFT, mEditor.mVAlign,
LLFontGL::LEFT, mEditor.mTextVAlign,
LLFontGL::NORMAL,
mStyle->getShadowType(),
length,
&right_x,
mEditor.getUseEllipses());
mEditor.getUseEllipses(),
mEditor.getUseColor());
}
return right_x;
}

View File

@ -316,6 +316,7 @@ public:
plain_text,
wrap,
use_ellipses,
use_color,
parse_urls,
force_urls_external,
parse_highlights,
@ -334,6 +335,8 @@ public:
Optional<LLFontGL::ShadowType> font_shadow;
Optional<LLFontGL::VAlign> text_valign;
Params();
};
@ -391,6 +394,7 @@ public:
// used by LLTextSegment layout code
bool getWordWrap() { return mWordWrap; }
bool getUseEllipses() { return mUseEllipses; }
bool getUseColor() { return mUseColor; }
bool truncate(); // returns true of truncation occurred
bool isContentTrusted() {return mTrustedContent;}
@ -680,8 +684,9 @@ protected:
// configuration
S32 mHPad; // padding on left of text
S32 mVPad; // padding above text
LLFontGL::HAlign mHAlign;
LLFontGL::VAlign mVAlign;
LLFontGL::HAlign mHAlign; // horizontal alignment of the document in its entirety
LLFontGL::VAlign mVAlign; // vertical alignment of the document in its entirety
LLFontGL::VAlign mTextVAlign; // vertical alignment of a text segment within a single line of text
F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding)
S32 mLineSpacingPixels; // padding between lines
bool mBorderVisible;
@ -690,6 +695,7 @@ protected:
bool mParseHighlights; // highlight user-defined keywords
bool mWordWrap;
bool mUseEllipses;
bool mUseColor;
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
bool mReadOnly;
bool mBGVisible; // render background?

View File

@ -1325,7 +1325,7 @@ void LLView::drawDebugRect()
debug_rect.getWidth(), debug_rect.getHeight());
LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, S32_MAX, NULL, FALSE);
S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
}
}
LLUI::popMatrix();

View File

@ -18,6 +18,7 @@ include(EXPAT)
include(FMODSTUDIO)
include(GLOD)
include(Hunspell)
include(ICU4C)
include(JsonCpp)
include(LLAppearance)
include(LLAudio)
@ -1497,6 +1498,12 @@ if (WINDOWS)
set(viewer_SOURCE_FILES "${viewer_SOURCE_FILES}" llviewerprecompiledheaders.cpp)
endif(USE_PRECOMPILED_HEADERS)
message("Copying fonts")
file(GLOB FONT_FILE_GLOB_LIST
"${AUTOBUILD_INSTALL_DIR}/fonts/*"
)
file(COPY ${FONT_FILE_GLOB_LIST} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/fonts")
# Replace the icons with the appropriate ones for the channel
# ('test' is the default)
set(ICON_PATH "test")
@ -2042,6 +2049,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

@ -1,99 +0,0 @@
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
Bitstream Vera Fonts Copyright
------------------------------
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute the
Font Software, including without limitation the rights to use, copy, merge,
publish, distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to the
following conditions:
The above copyright and trademark notices and this permission notice shall
be included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular
the designs of glyphs or characters in the Fonts may be modified and
additional glyphs or characters may be added to the Fonts, only if the fonts
are renamed to names not containing either the words "Bitstream" or the word
"Vera".
This License becomes null and void to the extent applicable to Fonts or Font
Software that has been modified and is distributed under the "Bitstream
Vera" names.
The Font Software may be sold as part of a larger software package but no
copy of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font Software
without prior written authorization from the Gnome Foundation or Bitstream
Inc., respectively. For further information, contact: fonts at gnome dot
org.
Arev Fonts Copyright
------------------------------
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and
associated documentation files (the "Font Software"), to reproduce
and distribute the modifications to the Bitstream Vera Font Software,
including without limitation the rights to use, copy, merge, publish,
distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to
the following conditions:
The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.
The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Tavmjong Bah" or the word "Arev".
This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Tavmjong Bah Arev" names.
The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the name of Tavmjong Bah shall not
be used in advertising or otherwise to promote the sale, use or other
dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr.
$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $

Binary file not shown.

View File

@ -88,7 +88,7 @@ public:
mStyle->getShadowType(),
end - start, draw_rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
mEditor.getUseEllipses(), mEditor.getUseColor());
return right_x;
}
/*virtual*/ bool canEdit() const { return false; }

View File

@ -1601,7 +1601,7 @@ void LLOverlapPanel::draw()
LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5
LLView::sDrawPreviewHighlights = FALSE;
LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text, 0, 0, 0, text_color,
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
}
else
{
@ -1619,7 +1619,7 @@ void LLOverlapPanel::draw()
std::string current_selection = std::string(current_selection_text + LLView::sPreviewClickedElement->getName() + " (no elements overlap)");
S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(current_selection) + 10;
LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection, 0, 0, 0, text_color,
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
// widen panel enough to fit this text
LLRect rect = getRect();
setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop));
@ -1685,7 +1685,7 @@ void LLOverlapPanel::draw()
// draw currently-selected element at top of overlappers
LLUI::translate(0,-mSpacing);
LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text + LLView::sPreviewClickedElement->getName(), 0, 0, 0, text_color,
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
LLUI::translate(0,-mSpacing-LLView::sPreviewClickedElement->getRect().getHeight()); // skip spacing distance + height
LLView::sPreviewClickedElement->draw();
@ -1700,7 +1700,7 @@ void LLOverlapPanel::draw()
// draw name
LLUI::translate(0,-mSpacing);
LLFontGL::getFontSansSerifSmall()->renderUTF8(overlapper_text + viewp->getName(), 0, 0, 0, text_color,
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
// draw element
LLUI::translate(0,-mSpacing-viewp->getRect().getHeight()); // skip spacing distance + height

View File

@ -612,7 +612,7 @@ void LLGLTexMemBar::draw()
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP,
LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX,
&x_right, FALSE);
&x_right, /*use_ellipses*/FALSE, /*use_color*/FALSE);
F32Kilobits bandwidth(LLAppViewer::getTextureFetch()->getTextureBandwidth());
F32Kilobits max_bandwidth(gSavedSettings.getF32("ThrottleBandwidthKBPS"));

View File

@ -9302,6 +9302,10 @@ void initialize_menus()
//Develop (clear cache immediately)
commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
// Develop (Fonts debugging)
commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts));
commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures));
// Admin >Object
view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");

View File

@ -1007,7 +1007,7 @@ public:
const Line& line = *iter;
LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
LLFontGL::LEFT, LLFontGL::TOP,
LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
}
}

View File

@ -469,7 +469,8 @@ void LLWorldMapView::draw()
S32_MAX, //max_chars
sMapScale, //max_pixels
NULL,
TRUE); //use ellipses
/*use_ellipses*/TRUE,
/*use_color*/FALSE);
}
}
}

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

@ -159,6 +159,32 @@
parameter="ui_preview" />
</menu_item_call>
<menu_item_separator />
<menu
create_jump_keys="true"
label="Fonts"
name="Fonts"
tear_off="true">
<menu_item_call
label="Show Font Test"
name="Show Font Test">
<menu_item_call.on_click
function="Floater.Show"
parameter="font_test" />
</menu_item_call>
<menu_item_separator />
<menu_item_call
label="Dump Fonts"
name="Dump Fonts">
<menu_item_call.on_click
function="Develop.Fonts.Dump" />
</menu_item_call>
<menu_item_call
label="Dump Font Textures"
name="Dump Font Textures">
<menu_item_call.on_click
function="Develop.Fonts.DumpTextures" />
</menu_item_call>
</menu>
<menu
create_jump_keys="true"
label="UI Tests"

View File

@ -3448,6 +3448,18 @@ function="World.EnvPreset"
function="Advanced.WebContentTest"
parameter="https://cryptic-ridge-1632.herokuapp.com/"/>
</menu_item_call>
<menu_item_call
label="Dump Fonts"
name="Dump Fonts">
<menu_item_call.on_click
function="Develop.Fonts.Dump" />
</menu_item_call>
<menu_item_call
label="Dump Font Textures"
name="Dump Font Textures">
<menu_item_call.on_click
function="Develop.Fonts.DumpTextures" />
</menu_item_call>
<menu_item_call
label="Dump SelectMgr"
name="Dump SelectMgr">

View File

@ -140,7 +140,7 @@ class ViewerManifest(LLManifest):
self.path("*.tga")
# Include our fonts
with self.prefix(src_dst="fonts"):
with self.prefix(src="../packages/fonts"):
self.path("*.ttf")
self.path("*.txt")