From 05566ce7a7e1895a5b3ab2f9df2587dac63429e1 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 27 Oct 2019 16:41:38 +0200 Subject: Font debugging aid to dump descriptors + individual textures --- indra/llrender/llfontfreetype.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'indra/llrender/llfontfreetype.cpp') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index c41730ebaa..78bc6ac433 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -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" @@ -657,6 +659,37 @@ const std::string &LLFontFreetype::getName() const return mName; } +static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_name) +{ + LLPointer 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 + for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(); idx < cnt; idx++) + { + dumpFontBitmap(mFontBitmapCachep->getImageRaw(idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx)); + } + +// // Dump all the color bitmaps (if any) +// if (mFontColorBitmapCachep) +// { +// for (int idxBitmap = 0, cntBitmap = mFontColorBitmapCachep->getNumBitmaps(); idxBitmap < cntBitmap; idxBitmap++) +// { +// dumpFontBitmap(mFontColorBitmapCachep->getImageRaw(idxBitmap), llformat("%s_%d_%d_clr_%d.png", mFTFace->family_name, (int)mPointSize, mStyle, idxBitmap)); +// } +// } +} + const LLFontBitmapCache* LLFontFreetype::getFontBitmapCache() const { return mFontBitmapCachep; -- cgit v1.2.3 From 9cfdb278de30e4a22d5d38fd08305fd40a905d80 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Mon, 28 Oct 2019 23:40:41 +0200 Subject: Support for COLR/CPAL fonts --- indra/llrender/llfontfreetype.cpp | 148 ++++++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 55 deletions(-) (limited to 'indra/llrender/llfontfreetype.cpp') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 78bc6ac433..57154feeec 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -101,6 +101,7 @@ 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 + mBitmapType(EFontGlyphType::Grayscale), mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph { } @@ -159,7 +160,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 use_color, bool is_fallback, S32 face_n) { // Don't leak face objects. This is also needed to deal with // changed font file names. @@ -223,7 +224,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); @@ -236,7 +237,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; @@ -447,7 +448,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); if (glyph_index) { - return addGlyphFromFont(*iter, wch, glyph_index); + return addGlyphFromFont(*iter, wch, glyph_index, EFontGlyphType::Color); } } } @@ -455,29 +456,43 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); if (iter == mCharGlyphInfoMap.end()) { - return addGlyphFromFont(this, wch, glyph_index); + return addGlyphFromFont(this, wch, glyph_index, EFontGlyphType::Color); } 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 bitmap_type) const { if (mFTFace == NULL) return NULL; llassert(!mIsFallback); - fontp->renderGlyph(glyph_index); + fontp->renderGlyph(bitmap_type, glyph_index); + switch (fontp->mFTFace->glyph->bitmap.pixel_mode) + { + case FT_PIXEL_MODE_MONO: + case FT_PIXEL_MODE_GRAY: + bitmap_type = EFontGlyphType::Grayscale; + break; + case FT_PIXEL_MODE_BGRA: + bitmap_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_type, bitmap_num); mAddGlyphCount++; LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); gi->mXBitmapOffset = pos_x; gi->mYBitmapOffset = pos_y; + gi->mBitmapType = bitmap_type; gi->mBitmapNum = bitmap_num; gi->mWidth = width; gi->mHeight = height; @@ -489,9 +504,6 @@ 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 (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { @@ -525,39 +537,32 @@ 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_type, bitmap_num); + LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_type, bitmap_num); image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); return gi; @@ -592,12 +597,19 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const } } -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) ); @@ -607,7 +619,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, true, mIsFallback, 0); if (!mIsFallback) { // This is the head of the list - need to rebuild ourself and all fallbacks. @@ -645,7 +657,7 @@ void LLFontFreetype::resetBitmapCache() if(!mIsFallback) { // Add the empty glyph - addGlyphFromFont(this, 0, 0); + addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale); } } @@ -674,20 +686,17 @@ static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_ void LLFontFreetype::dumpFontBitmaps() const { - // Dump all the regular bitmaps - for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(); idx < cnt; idx++) + // Dump all the regular bitmaps (if any) + for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Grayscale); idx < cnt; idx++) { - dumpFontBitmap(mFontBitmapCachep->getImageRaw(idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, 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) -// if (mFontColorBitmapCachep) -// { -// for (int idxBitmap = 0, cntBitmap = mFontColorBitmapCachep->getNumBitmaps(); idxBitmap < cntBitmap; idxBitmap++) -// { -// dumpFontBitmap(mFontColorBitmapCachep->getImageRaw(idxBitmap), llformat("%s_%d_%d_clr_%d.png", mFTFace->family_name, (int)mPointSize, mStyle, idxBitmap)); -// } -// } + // 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 @@ -705,9 +714,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)); -- cgit v1.2.3 From 418308bc7ce4e9924d6280f784222ba45172eea4 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 6 Nov 2019 12:34:26 +0100 Subject: Characters can have more than one representation in LLFontFreetype * By default all viewer text will use B/W glyphs * Added temporary use_color attribute to LLTextBase for testing --- indra/llrender/llfontfreetype.cpp | 90 +++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 28 deletions(-) (limited to 'indra/llrender/llfontfreetype.cpp') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 57154feeec..7d66965e57 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -91,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 @@ -101,11 +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 - mBitmapType(EFontGlyphType::Grayscale), - 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"), mFontBitmapCachep(new LLFontBitmapCache), @@ -361,7 +376,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; @@ -393,10 +408,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; @@ -427,12 +442,13 @@ 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; @@ -448,34 +464,38 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); if (glyph_index) { - return addGlyphFromFont(*iter, wch, glyph_index, EFontGlyphType::Color); + return addGlyphFromFont(*iter, wch, glyph_index, glyph_type); } } } - char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); - if (iter == mCharGlyphInfoMap.end()) + std::pair 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, EFontGlyphType::Color); + return addGlyphFromFont(this, wch, glyph_index, glyph_type); } return NULL; } -LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) 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(bitmap_type, 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_type = EFontGlyphType::Grayscale; + bitmap_glyph_type = EFontGlyphType::Grayscale; break; case FT_PIXEL_MODE_BGRA: - bitmap_type = EFontGlyphType::Color; + bitmap_glyph_type = EFontGlyphType::Color; break; default: llassert_always(true); @@ -486,14 +506,13 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l S32 pos_x, pos_y; U32 bitmap_num; - mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_type, 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->mBitmapType = bitmap_type; - 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; @@ -504,6 +523,13 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l insertGlyphInfo(wch, gi); + 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) { @@ -561,31 +587,39 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l llassert(false); } - LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_type, bitmap_num); - LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_type, 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 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 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; @@ -593,7 +627,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const else { claimMem(gi); - mCharGlyphInfoMap[wch] = gi; + mCharGlyphInfoMap.insert(std::make_pair(wch, gi)); } } -- cgit v1.2.3 From 5a6ddb2ea666e895890d3cb690cce5101cf12652 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 7 Nov 2019 17:15:21 +0100 Subject: Fallback fonts can have first crack at adding an unknown character + set Twemoji as the viewer's fallback for all emoji blocks --- indra/llrender/llfontfreetype.cpp | 42 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'indra/llrender/llfontfreetype.cpp') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 7d66965e57..25740a5f87 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -175,7 +175,7 @@ void ft_close_cb(FT_Stream stream) { } #endif -BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool use_color, bool is_fallback, S32 face_n) +BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n) { // Don't leak face objects. This is also needed to deal with // changed font file names. @@ -345,14 +345,11 @@ void LLFontFreetype::clearFontStreams() } #endif -void LLFontFreetype::setFallbackFonts(const font_vector_t &font) +void LLFontFreetype::addFallbackFont(const LLPointer& 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); } } } -- cgit v1.2.3 From 24bd7b2311e6fdd8bcf0a223d6dafaf4266ca4c7 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 6 Nov 2022 16:25:35 +0100 Subject: Add support for OT-SVG fonts --- indra/llrender/llfontfreetype.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'indra/llrender/llfontfreetype.cpp') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 25740a5f87..d3a49339da 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -34,6 +34,7 @@ #ifdef LL_WINDOWS #include #endif +#include "llfontfreetypesvg.h" // For some reason, this won't work if it's not wrapped in the ifdef #ifdef FT_FREETYPE_H @@ -51,6 +52,8 @@ #include "llfontbitmapcache.h" #include "llgl.h" +#define ENABLE_OT_SVG_SUPPORT + FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; LLFontManager *gFontManagerp = NULL; @@ -83,6 +86,16 @@ LLFontManager::LLFontManager() LL_ERRS() << "Freetype initialization failure!" << LL_ENDL; FT_Done_FreeType(gFTLibrary); } + +#ifdef ENABLE_OT_SVG_SUPPORT + SVG_RendererHooks hooks = { + LLFontFreeTypeSvgRenderer::OnInit, + LLFontFreeTypeSvgRenderer::OnFree, + LLFontFreeTypeSvgRenderer::OnRender, + LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot, + }; + FT_Property_Set(gFTLibrary, "ot-svg", "svg-hooks", &hooks); +#endif } LLFontManager::~LLFontManager() -- cgit v1.2.3