summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorKitty Barnett <develop@catznip.com>2019-10-28 23:40:41 +0200
committerKitty Barnett <develop@catznip.com>2019-10-28 23:40:41 +0200
commit9cfdb278de30e4a22d5d38fd08305fd40a905d80 (patch)
treee0f69acc1f102108be1cf2a89fa84c120833a798 /indra
parent05566ce7a7e1895a5b3ab2f9df2587dac63429e1 (diff)
Support for COLR/CPAL fonts
Diffstat (limited to 'indra')
-rw-r--r--indra/llrender/llfontbitmapcache.cpp175
-rw-r--r--indra/llrender/llfontbitmapcache.h34
-rw-r--r--indra/llrender/llfontfreetype.cpp148
-rw-r--r--indra/llrender/llfontfreetype.h8
-rw-r--r--indra/llrender/llfontgl.cpp16
-rw-r--r--indra/llrender/llfontgl.h2
-rw-r--r--indra/llrender/llfontregistry.cpp2
7 files changed, 222 insertions, 163 deletions
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp
index f128636ab2..754adb14cb 100644
--- a/indra/llrender/llfontbitmapcache.cpp
+++ b/indra/llrender/llfontbitmapcache.cpp
@@ -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;
+
+ S32 image_width = mMaxCharWidth * 20;
+ S32 pow_iw = 2;
+ while (pow_iw < image_width)
+ {
+ 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(U32 bitmap_num) const
+LLImageRaw *LLFontBitmapCache::getImageRaw(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
- if (bitmap_num >= mImageRawVec.size())
- return NULL;
+ 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_num];
+ return mImageRawVec[bitmap_idx][bitmap_num];
}
-LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const
+LLImageGL *LLFontBitmapCache::getImageGL(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
- if (bitmap_num >= mImageGLVec.size())
- return NULL;
+ 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_num];
+ return mImageGLVec[bitmap_idx][bitmap_num];
}
-BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32 &pos_x, S32 &pos_y, S32& bitmap_num)
+BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyphType bitmap_type, U32& bitmap_num)
{
- if ((mBitmapNum<0) || (mCurrentOffsetX + width + 1) > mBitmapWidth)
+ if (bitmap_type >= EFontGlyphType::Count)
{
- if ((mBitmapNum<0) || (mCurrentOffsetY + 2*mMaxCharHeight + 2) > mBitmapHeight)
+ 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;
- // 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)
+ LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
+ if (EFontGlyphType::Grayscale == bitmap_type)
{
- pow_iw *= 2;
+ image_raw->clear(255, 0);
}
- 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;
- }
+ // Make corresponding GL image.
+ 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;
+ }
+}
diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h
index 7e0e905756..f68af0d2b6 100644
--- a/indra/llrender/llfontbitmapcache.h
+++ b/indra/llrender/llfontbitmapcache.h
@@ -30,6 +30,13 @@
#include <vector>
#include "lltrace.h"
+enum class EFontGlyphType : U32
+{
+ Grayscale = 0,
+ Color,
+ Count
+};
+
// Maintain a collection of bitmaps containing rendered glyphs.
// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.
class LLFontBitmapCache : public LLTrace::MemTrackable<LLFontBitmapCache>
@@ -39,36 +46,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 getNumBitmaps() const { return mImageRawVec.size(); }
- 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
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));
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index a25cc18fcf..7b7b3faaf0 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -71,6 +71,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
+ EFontGlyphType mBitmapType; // Specifies the bitmap type in the bitmap cache
S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph
};
@@ -84,7 +85,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 use_color, bool is_fallback, S32 face_n);
S32 getNumFaces(const std::string& filename);
@@ -152,10 +153,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* 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;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 990a3e8281..6fee34d3eb 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -89,14 +89,14 @@ void LLFontGL::destroyGL()
mFontFreetype->destroyGL();
}
-BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, 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 use_color, 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, use_color, is_fallback, face_n);
}
S32 LLFontGL::getNumFaces(const std::string& filename)
@@ -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++)
{
@@ -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 = std::make_pair(fgi->mBitmapType, fgi->mBitmapNum);
+ 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(fgi->mBitmapType, 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, (fgi->mBitmapType == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, style_to_add, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index b1a433f97d..5028ccc770 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -87,7 +87,7 @@ public:
void destroyGL();
- BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, 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 use_color, bool is_fallback, S32 face_n);
S32 getNumFaces(const std::string& filename);
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 5ab2ab046e..426b10b016 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -495,7 +495,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
fontp = new LLFontGL;
}
if (fontp->loadFace(*font_paths_it, point_size_scale,
- LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback, i))
+ LLFontGL::sVertDPI, LLFontGL::sHorizDPI, true, is_fallback, i))
{
is_font_loaded = true;
if (is_first_found)