diff options
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/llfontbitmapcache.cpp | 175 | ||||
| -rw-r--r-- | indra/llrender/llfontbitmapcache.h | 34 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.cpp | 148 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.h | 8 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.cpp | 16 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llfontregistry.cpp | 2 | 
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) | 
