diff options
| author | Palmer <palmer@lindenlab.com> | 2009-08-06 14:51:11 -0700 | 
|---|---|---|
| committer | Palmer <palmer@lindenlab.com> | 2009-08-06 14:51:11 -0700 | 
| commit | b2632c50efc12eacdcadace64e6c0f1906b86ff6 (patch) | |
| tree | c32d7e9b29e37d5c30ac16dfac55733456d7eee0 /indra/llrender | |
| parent | 27cf39cdbf27fe52dcf9c70cfdadcc18ddf2e75c (diff) | |
| parent | a8d216e194327c7bee8a42c983f7f2ca01adb385 (diff) | |
Merge of my DEV-36732 work and all the main line login api work that went on.
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | indra/llrender/llfontbitmapcache.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.cpp | 630 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.h | 380 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.cpp | 865 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.h | 217 | ||||
| -rw-r--r-- | indra/llrender/llfontregistry.cpp | 59 | ||||
| -rw-r--r-- | indra/llrender/llfontregistry.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 113 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.h | 48 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 79 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 2 | ||||
| -rw-r--r-- | indra/llrender/lltexture.cpp | 37 | ||||
| -rw-r--r-- | indra/llrender/lltexture.h | 77 | 
14 files changed, 1771 insertions, 746 deletions
| diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 0bb835970f..aac650bec9 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -26,7 +26,7 @@ include_directories(  set(llrender_SOURCE_FILES      llcubemap.cpp -    llfont.cpp +    llfontfreetype.cpp      llfontgl.cpp      llfontbitmapcache.cpp      llfontregistry.cpp @@ -36,6 +36,7 @@ set(llrender_SOURCE_FILES      llpostprocess.cpp      llrendersphere.cpp      llshadermgr.cpp +    lltexture.cpp      llvertexbuffer.cpp      ) @@ -44,7 +45,7 @@ set(llrender_HEADER_FILES      llcubemap.h      llfontgl.h -    llfont.h +    llfontfreetype.h      llfontbitmapcache.h      llfontregistry.h      llgl.h @@ -58,6 +59,7 @@ set(llrender_HEADER_FILES      llrender.h      llrendersphere.h      llshadermgr.h +    lltexture.h      llvertexbuffer.h      ) diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 4beea0d026..4a57052b91 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -36,7 +36,7 @@  #include <vector>  // Maintain a collection of bitmaps containing rendered glyphs. -// Generalizes the single-bitmap logic from LLFont and LLFontGL. +// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.  class LLFontBitmapCache: public LLRefCount  {  public: diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp new file mode 100644 index 0000000000..62534969b7 --- /dev/null +++ b/indra/llrender/llfontfreetype.cpp @@ -0,0 +1,630 @@ +/**  + * @file llfontfreetype.cpp + * @brief Freetype font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfontfreetype.h" + +// Freetype stuff +#include <ft2build.h> + +// For some reason, this won't work if it's not wrapped in the ifdef +#ifdef FT_FREETYPE_H +#include FT_FREETYPE_H +#endif + +#include "llerror.h" +#include "llimage.h" +//#include "llimagej2c.h" +#include "llmath.h"	// Linden math +#include "llstring.h" +//#include "imdebug.h" +#include "llfontbitmapcache.h" +#include "llgl.h" + +FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; + +LLFontManager *gFontManagerp = NULL; + +FT_Library gFTLibrary = NULL; + +//static +void LLFontManager::initClass() +{ +	gFontManagerp = new LLFontManager; +} + +//static +void LLFontManager::cleanupClass() +{ +	delete gFontManagerp; +	gFontManagerp = NULL; +} + +LLFontManager::LLFontManager() +{ +	int error; +	error = FT_Init_FreeType(&gFTLibrary); +	if (error) +	{ +		// Clean up freetype libs. +		llerrs << "Freetype initialization failure!" << llendl; +		FT_Done_FreeType(gFTLibrary); +	} +} + +LLFontManager::~LLFontManager() +{ +	FT_Done_FreeType(gFTLibrary); +} + + +LLFontGlyphInfo::LLFontGlyphInfo(U32 index) +:	mGlyphIndex(index), +	mXBitmapOffset(0), 	// Offset to the origin in the bitmap +	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 +	mWidth(0),			// In pixels +	mHeight(0),			// In pixels +	mXAdvance(0.f),		// In pixels +	mYAdvance(0.f),		// In pixels +	mIsRendered(FALSE), +	mMetricsValid(FALSE) +{ +} + +LLFontFreetype::LLFontFreetype() +:	mFontBitmapCachep(new LLFontBitmapCache), +	mValid(FALSE), +	mAscender(0.f), +	mDescender(0.f), +	mLineHeight(0.f), +	mIsFallback(FALSE), +	mFTFace(NULL), +	mRenderGlyphCount(0), +	mAddGlyphCount(0), +	mPointSize(0) +{ +} + + +LLFontFreetype::~LLFontFreetype() +{ +	// Clean up freetype libs. +	if (mFTFace) +		FT_Done_Face(mFTFace); +	mFTFace = NULL; + +	// Delete glyph info +	std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); + +	// mFontBitmapCachep will be cleaned up by LLPointer destructor. +	// mFallbackFonts cleaned up by LLPointer destructor +} + +BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback) +{ +	// Don't leak face objects.  This is also needed to deal with +	// changed font file names. +	if (mFTFace) +	{ +		FT_Done_Face(mFTFace); +		mFTFace = NULL; +	} + +	int error; + +	error = FT_New_Face( gFTLibrary, +						 filename.c_str(), +						 0, +						 &mFTFace ); + +    if (error) +	{ +		return FALSE; +	} + +	mIsFallback = is_fallback; +	F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi + +	error = FT_Set_Char_Size(mFTFace,    /* handle to face object           */ +							0,       /* char_width in 1/64th of points  */ +							(S32)(point_size*64),   /* char_height in 1/64th of points */ +							(U32)horz_dpi,     /* horizontal device resolution    */ +							(U32)vert_dpi);   /* vertical device resolution      */ + +	if (error) +	{ +		// Clean up freetype libs. +		FT_Done_Face(mFTFace); +		mFTFace = NULL; +		return FALSE; +	} + +	F32 y_max, y_min, x_max, x_min; +	F32 ems_per_unit = 1.f/ mFTFace->units_per_EM; +	F32 pixels_per_unit = pixels_per_em * ems_per_unit; + +	// Get size of bbox in pixels +	y_max = mFTFace->bbox.yMax * pixels_per_unit; +	y_min = mFTFace->bbox.yMin * pixels_per_unit; +	x_max = mFTFace->bbox.xMax * pixels_per_unit; +	x_min = mFTFace->bbox.xMin * pixels_per_unit; +	mAscender = mFTFace->ascender * pixels_per_unit; +	mDescender = -mFTFace->descender * pixels_per_unit; +	mLineHeight = mFTFace->height * pixels_per_unit; + +	S32 max_char_width = llround(0.5f + (x_max - x_min)); +	S32 max_char_height = llround(0.5f + (y_max - y_min)); + +	mFontBitmapCachep->init(components, max_char_width, max_char_height); + +	if (!mFTFace->charmap) +	{ +		//llinfos << " no unicode encoding, set whatever encoding there is..." << llendl; +		FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); +	} + +	if (!mIsFallback) +	{ +		// Add the default glyph +		addGlyph(0, 0); +	} + +	mName = filename; +	mPointSize = point_size; + +	return TRUE; +} + +void LLFontFreetype::setFallbackFonts(const font_vector_t &font) +{ +	mFallbackFonts = font; +} + +const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const +{ +	return mFallbackFonts; +} + +F32 LLFontFreetype::getLineHeight() const +{ +	return mLineHeight; +} + +F32 LLFontFreetype::getAscenderHeight() const +{ +	return mAscender; +} + +F32 LLFontFreetype::getDescenderHeight() const +{ +	return mDescender; +} + +F32 LLFontFreetype::getXAdvance(llwchar wch) const +{ +	if (mFTFace == NULL) +		return 0.0; + +	//llassert(!mIsFallback); +	U32 glyph_index; + +	// Return existing info only if it is current +	LLFontGlyphInfo* gi = getGlyphInfo(wch); +	if (gi && gi->mMetricsValid) +	{ +		return gi->mXAdvance; +	} + +	const LLFontFreetype* fontp = this; +	 +	// Initialize char to glyph map +	glyph_index = FT_Get_Char_Index(mFTFace, wch); +	if (glyph_index == 0) +	{ +		font_vector_t::const_iterator iter; +		for(iter = mFallbackFonts.begin(); (iter != mFallbackFonts.end()) && (glyph_index == 0); iter++) +		{ +			glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); +			if(glyph_index) +			{ +				fontp = *iter; +			} +		} +	} +	 +	if (glyph_index) +	{ +		// This font has this glyph +		fontp->renderGlyph(glyph_index); + +		// Create the entry if it's not there +		char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch); +		if (iter2 == mCharGlyphInfoMap.end()) +		{ +			gi = new LLFontGlyphInfo(glyph_index); +			insertGlyphInfo(wch, gi); +		} +		else +		{ +			gi = iter2->second; +		} +		 +		gi->mWidth = fontp->mFTFace->glyph->bitmap.width; +		gi->mHeight = fontp->mFTFace->glyph->bitmap.rows; + +		// Convert these from 26.6 units to float pixels. +		gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; +		gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; +		gi->mMetricsValid = TRUE; +		return gi->mXAdvance; +	} +	else +	{ +		gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL); +		if (gi) +		{ +			return gi->mXAdvance; +		} +	} + +	// Last ditch fallback - no glyphs defined at all. +	return (F32)mFontBitmapCachep->getMaxCharWidth(); +} + +F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const +{ +	if (mFTFace == NULL) +		return 0.0; + +	//llassert(!mIsFallback); +	LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL); +	U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; +	// Kern this puppy. +	LLFontGlyphInfo* right_glyph_info = get_if_there(mCharGlyphInfoMap, char_right, (LLFontGlyphInfo*)NULL); +	U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0; + +	FT_Vector  delta; + +	llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta)); + +	return delta.x*(1.f/64.f); +} + +BOOL LLFontFreetype::hasGlyph(llwchar wch) const +{ +	llassert(!mIsFallback); +	const LLFontGlyphInfo* gi = getGlyphInfo(wch); +	if (gi && gi->mIsRendered) +	{ +		return TRUE; +	} +	else +	{ +		return FALSE; +	} +} + +BOOL LLFontFreetype::addChar(llwchar wch) const +{ +	if (mFTFace == NULL) +		return FALSE; + +	llassert(!mIsFallback); +	//lldebugs << "Adding new glyph for " << wch << " to font" << llendl; + +	FT_UInt glyph_index; + +	// Initialize char to glyph map +	glyph_index = FT_Get_Char_Index(mFTFace, wch); +	if (glyph_index == 0) +	{ +		//llinfos << "Trying to add glyph from fallback font!" << llendl +		font_vector_t::const_iterator iter; +		for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++) +		{ +			glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); +			if (glyph_index) +			{ +				addGlyphFromFont(*iter, wch, glyph_index); +				return TRUE; +			} +		} +	} +	 +	char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); +	if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered)) +	{ +		BOOL result = addGlyph(wch, glyph_index); +		return result; +	} +	return FALSE; +} + +BOOL LLFontFreetype::addGlyph(llwchar wch, U32 glyph_index) const +{ +	return addGlyphFromFont(this, wch, glyph_index); +} + +BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const +{ +	if (mFTFace == NULL) +		return FALSE; + +	llassert(!mIsFallback); +	fontp->renderGlyph(glyph_index); +	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); +	mAddGlyphCount++; + +	LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); +	gi->mXBitmapOffset = pos_x; +	gi->mYBitmapOffset = pos_y; +	gi->mBitmapNum = bitmap_num; +	gi->mWidth = width; +	gi->mHeight = height; +	gi->mXBearing = fontp->mFTFace->glyph->bitmap_left; +	gi->mYBearing = fontp->mFTFace->glyph->bitmap_top; +	// Convert these from 26.6 units to float pixels. +	gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; +	gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; +	gi->mIsRendered = TRUE; +	gi->mMetricsValid = TRUE; + +	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) +	{ +		U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer; +		S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; +		U8 *tmp_graydata = NULL; + +		if (fontp->mFTFace->glyph->bitmap.pixel_mode +		    == FT_PIXEL_MODE_MONO) +		{ +			// need to expand 1-bit bitmap to 8-bit graymap. +			tmp_graydata = new U8[width * height]; +			S32 xpos, ypos; +			for (ypos = 0; ypos < height; ++ypos) +			{ +				S32 bm_row_offset = buffer_row_stride * ypos; +				for (xpos = 0; xpos < width; ++xpos) +				{ +					U32 bm_col_offsetbyte = xpos / 8; +					U32 bm_col_offsetbit = 7 - (xpos % 8); +					U32 bit = +					!!(buffer_data[bm_row_offset +						       + bm_col_offsetbyte +					   ] & (1 << bm_col_offsetbit) ); +					tmp_graydata[width*ypos + xpos] = +						255 * bit; +				} +			} +			// use newly-built graymap. +			buffer_data = tmp_graydata; +			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; +		} + +		if (tmp_graydata) +			delete[] tmp_graydata; +	} else { +		// we don't know how to handle this pixel format from FreeType; +		// omit it from the font-image. +	} +	 +	return TRUE; +} + +LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const +{ +	char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); +	if (iter != mCharGlyphInfoMap.end()) +	{ +		return iter->second; +	} +	return NULL; +} + +void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const +{ +	char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); +	if (iter != mCharGlyphInfoMap.end()) +	{ +		delete iter->second; +		iter->second = gi; +	} +	else +	{ +		mCharGlyphInfoMap[wch] = gi; +	} +} + +void LLFontFreetype::renderGlyph(U32 glyph_index) const +{ +	if (mFTFace == NULL) +		return; + +	int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT ); +	llassert(!error); + +	error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode); + +	mRenderGlyphCount++; +	 +	llassert(!error); +} + +void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi) +{ +	if (!mIsFallback) +	{ +		// This is the head of the list - need to rebuild ourself and all fallbacks. +		loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback); + +		if (mFallbackFonts.empty()) +		{ +			llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; +		} +		else +		{ +			for(font_vector_t::iterator it = mFallbackFonts.begin(); +				it != mFallbackFonts.end(); +				++it) +			{ +				(*it)->reset(vert_dpi, horz_dpi); +			} +		} +	} +	resetBitmapCache();  +} + +void LLFontFreetype::resetBitmapCache() +{ +	// Iterate through glyphs and clear the mIsRendered flag +	for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin(); +		 iter != mCharGlyphInfoMap.end(); ++iter) +	{ +		iter->second->mIsRendered = FALSE; +		//FIXME: this is only strictly necessary when resetting the entire font,  +		//not just flushing the bitmap +		iter->second->mMetricsValid = FALSE; +	} +	mFontBitmapCachep->reset(); + +	// Add the empty glyph`5 +	addGlyph(0, 0); +} + +void LLFontFreetype::destroyGL() +{ +	mFontBitmapCachep->destroyGL(); +} + +BOOL LLFontFreetype::getIsFallback() const +{ +	return mIsFallback; +} + +const std::string &LLFontFreetype::getName() const +{ +	return mName; +} + +F32 LLFontFreetype::getPointSize() const +{ +	return mPointSize; +} + +const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const +{ +	return mFontBitmapCachep; +} + +void LLFontFreetype::setStyle(U8 style) +{ +	mStyle = style; +} + +U8 LLFontFreetype::getStyle() const +{ +	return mStyle; +} + +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); + +	llassert(!mIsFallback); +	llassert(image_raw && (image_raw->getComponents() == 2)); + +	 +	U8 *target = image_raw->getData(); + +	if (!data) +	{ +		return; +	} + +	if (0 == stride) +		stride = width; + +	U32 i, j; +	U32 to_offset; +	U32 from_offset; +	U32 target_width = image_raw->getWidth(); +	for (i = 0; i < height; i++) +	{ +		to_offset = (y + i)*target_width + x; +		from_offset = (height - 1 - i)*stride; +		for (j = 0; j < width; j++) +		{ +			*(target + to_offset*2 + 1) = *(data + from_offset); +			to_offset++; +			from_offset++; +		} +	} +} + diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h new file mode 100644 index 0000000000..0520ef2cd6 --- /dev/null +++ b/indra/llrender/llfontfreetype.h @@ -0,0 +1,380 @@ +/**  + * @file llfontfreetype.h + * @brief Font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFONTFREETYPE_H +#define LL_LLFONTFREETYPE_H + +#include <map> +#include "llpointer.h" +#include "llstl.h" + +#include "llimagegl.h" +#include "llfontbitmapcache.h" + +// Hack.  FT_Face is just a typedef for a pointer to a struct, +// but there's no simple forward declarations file for FreeType,  +// and the main include file is 200K.   +// We'll forward declare the struct here.  JC +struct FT_FaceRec_; +typedef struct FT_FaceRec_* LLFT_Face; + +class LLFontManager +{ +public: +	static void initClass(); +	static void cleanupClass(); + +private: +	LLFontManager(); +	~LLFontManager(); +}; + +class LLFontGlyphInfo +{ +public: +	LLFontGlyphInfo(U32 index); + +	U32 mGlyphIndex; + +	// Metrics +	S32 mWidth;			// In pixels +	S32 mHeight;		// In pixels +	F32 mXAdvance;		// In pixels +	F32 mYAdvance;		// In pixels +	BOOL mMetricsValid; // We have up-to-date metrics for this glyph + +	// Information for actually rendering +	BOOL mIsRendered;	// We actually have rendered this glyph +	S32 mXBitmapOffset; // Offset to the origin in the bitmap +	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 +}; + +extern LLFontManager *gFontManagerp; + +class LLFontFreetype : public LLRefCount +{ +public: +	LLFontFreetype(); +	~LLFontFreetype(); + +	// 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); + +	typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t; + +	void setFallbackFonts(const font_vector_t &font); +	const font_vector_t &getFallbackFonts() const; + +	// Global font metrics - in units of pixels +	F32 getLineHeight() const; +	F32 getAscenderHeight() const; +	F32 getDescenderHeight() const; + + +// For a lowercase "g": +// +//	------------------------------ +//	                     ^     ^ +//						 |     | +//				xxx x    |Ascender +//	           x   x     v     | +//	---------   xxxx-------------- Baseline +//	^		       x	       | +//  | Descender    x           | +//	v			xxxx           |LineHeight +//  -----------------------    | +//                             v +//	------------------------------ + +	enum +	{ +		FIRST_CHAR = 32,  +		NUM_CHARS = 127 - 32,  +		LAST_CHAR_BASIC = 127, + +		// Need full 8-bit ascii range for spanish +		NUM_CHARS_FULL = 255 - 32, +		LAST_CHAR_FULL = 255 +	}; + +	F32 getXAdvance(llwchar wc) const; +	F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + +	BOOL hasGlyph(llwchar wch) const;		// Has a glyph for this character +	BOOL addChar(llwchar wch) const;		// Add a new character to the font if necessary +	BOOL addGlyph(llwchar wch, U32 glyph_index) const;	// Add a new glyph to the existing font +	BOOL 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) + +	LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; + +	void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; +	void renderGlyph(U32 glyph_index) const; + +	void reset(F32 vert_dpi, F32 horz_dpi); +	void resetBitmapCache(); + +	void destroyGL(); + +	BOOL getIsFallback() const; + +	const std::string& getName() const; + +	F32 getPointSize() const; + +	const LLPointer<LLFontBitmapCache> getFontBitmapCache() const; + +	void setStyle(U8 style); +	U8 getStyle() const; + +private: +	void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const; + +	std::string mName; + +	U8 mStyle; + +	F32 mPointSize; +	F32 mAscender;			 +	F32 mDescender; +	F32 mLineHeight; + +	LLFT_Face mFTFace; + +	BOOL mIsFallback; +	font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + +	BOOL mValid; + +	typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; +	mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap + +	mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep; + +	mutable S32 mRenderGlyphCount; +	mutable S32 mAddGlyphCount; +}; + +#endif // LL_FONTFREETYPE_H +/**  + * @file llfontfreetype.h + * @brief Font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFONTFREETYPE_H +#define LL_LLFONTFREETYPE_H + +#include <map> +#include "llpointer.h" +#include "llstl.h" + +#include "llimagegl.h" +#include "llfontbitmapcache.h" + +// Hack.  FT_Face is just a typedef for a pointer to a struct, +// but there's no simple forward declarations file for FreeType,  +// and the main include file is 200K.   +// We'll forward declare the struct here.  JC +struct FT_FaceRec_; +typedef struct FT_FaceRec_* LLFT_Face; + +class LLFontManager +{ +public: +	static void initClass(); +	static void cleanupClass(); + +private: +	LLFontManager(); +	~LLFontManager(); +}; + +class LLFontGlyphInfo +{ +public: +	LLFontGlyphInfo(U32 index); + +	U32 mGlyphIndex; + +	// Metrics +	S32 mWidth;			// In pixels +	S32 mHeight;		// In pixels +	F32 mXAdvance;		// In pixels +	F32 mYAdvance;		// In pixels +	BOOL mMetricsValid; // We have up-to-date metrics for this glyph + +	// Information for actually rendering +	BOOL mIsRendered;	// We actually have rendered this glyph +	S32 mXBitmapOffset; // Offset to the origin in the bitmap +	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 +}; + +extern LLFontManager *gFontManagerp; + +class LLFontFreetype : public LLRefCount +{ +public: +	LLFontFreetype(); +	~LLFontFreetype(); + +	// 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); + +	typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t; + +	void setFallbackFonts(const font_vector_t &font); +	const font_vector_t &getFallbackFonts() const; + +	// Global font metrics - in units of pixels +	F32 getLineHeight() const; +	F32 getAscenderHeight() const; +	F32 getDescenderHeight() const; + + +// For a lowercase "g": +// +//	------------------------------ +//	                     ^     ^ +//						 |     | +//				xxx x    |Ascender +//	           x   x     v     | +//	---------   xxxx-------------- Baseline +//	^		       x	       | +//  | Descender    x           | +//	v			xxxx           |LineHeight +//  -----------------------    | +//                             v +//	------------------------------ + +	enum +	{ +		FIRST_CHAR = 32,  +		NUM_CHARS = 127 - 32,  +		LAST_CHAR_BASIC = 127, + +		// Need full 8-bit ascii range for spanish +		NUM_CHARS_FULL = 255 - 32, +		LAST_CHAR_FULL = 255 +	}; + +	F32 getXAdvance(llwchar wc) const; +	F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + +	BOOL hasGlyph(llwchar wch) const;		// Has a glyph for this character +	BOOL addChar(llwchar wch) const;		// Add a new character to the font if necessary +	BOOL addGlyph(llwchar wch, U32 glyph_index) const;	// Add a new glyph to the existing font +	BOOL 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) + +	LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; + +	void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; +	void renderGlyph(U32 glyph_index) const; + +	void reset(F32 vert_dpi, F32 horz_dpi); +	void resetBitmapCache(); + +	void destroyGL(); + +	BOOL getIsFallback() const; + +	const std::string& getName() const; + +	F32 getPointSize() const; + +	const LLPointer<LLFontBitmapCache> getFontBitmapCache() const; + +	void setStyle(U8 style); +	U8 getStyle() const; + +private: +	void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const; + +	std::string mName; + +	U8 mStyle; + +	F32 mPointSize; +	F32 mAscender;			 +	F32 mDescender; +	F32 mLineHeight; + +	LLFT_Face mFTFace; + +	BOOL mIsFallback; +	font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + +	BOOL mValid; + +	typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; +	mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap + +	mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep; + +	mutable S32 mRenderGlyphCount; +	mutable S32 mAddGlyphCount; +}; + +#endif // LL_FONTFREETYPE_H diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 048bfe8e0d..32a008047c 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -35,7 +35,7 @@  #include "llfontgl.h"  // Linden library includes -#include "llfont.h" +#include "llfontfreetype.h"  #include "llfontbitmapcache.h"  #include "llfontregistry.h"  #include "llgl.h" @@ -43,6 +43,7 @@  #include "llrender.h"  #include "llstl.h"  #include "v4color.h" +#include "lltexture.h"  // Third party library includes  #include <boost/tokenizer.hpp> @@ -72,54 +73,25 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;  const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture  const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -F32 llfont_round_x(F32 x) +static F32 llfont_round_x(F32 x)  {  	//return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;  	//return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;  	return x;  } -F32 llfont_round_y(F32 y) +static F32 llfont_round_y(F32 y)  {  	//return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;  	//return llfloor(y+0.5f);  	return y;  } -// static -U8 LLFontGL::getStyleFromString(const std::string &style) -{ -	S32 ret = 0; -	if (style.find("NORMAL") != style.npos) -	{ -		ret |= NORMAL; -	} -	if (style.find("BOLD") != style.npos) -	{ -		ret |= BOLD; -	} -	if (style.find("ITALIC") != style.npos) -	{ -		ret |= ITALIC; -	} -	if (style.find("UNDERLINE") != style.npos) -	{ -		ret |= UNDERLINE; -	} -	return ret; -} -  LLFontGL::LLFontGL() -	: LLFont()  {  	clearEmbeddedChars();  } -LLFontGL::LLFontGL(const LLFontGL &source) -{ -	llerrs << "Not implemented!" << llendl; -} -  LLFontGL::~LLFontGL()  {  	clearEmbeddedChars(); @@ -127,293 +99,26 @@ LLFontGL::~LLFontGL()  void LLFontGL::reset()  { -	if (!mIsFallback) -	{ -		// This is the head of the list - need to rebuild ourself and all fallbacks. -		loadFace(mName,mPointSize,sVertDPI,sHorizDPI,mFontBitmapCachep->getNumComponents(),mIsFallback); -		if (mFallbackFontp==NULL) -		{ -			llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; -		} -		else -		{ -			for (LLFontList::iterator it = mFallbackFontp->begin(); -				 it != mFallbackFontp->end(); -				 ++it) -			{ -				(*it)->reset(); -			} -		} -	} -	resetBitmapCache();  -} - -// static  -std::string LLFontGL::getFontPathSystem() -{ -	std::string system_path; - -	// Try to figure out where the system's font files are stored. -	char *system_root = NULL; -#if LL_WINDOWS -	system_root = getenv("SystemRoot");	/* Flawfinder: ignore */ -	if (!system_root) -	{ -		llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl; -	} -#endif - -	if (system_root) -	{ -		system_path = llformat("%s/fonts/", system_root); -	} -	else -	{ -#if LL_WINDOWS -		// HACK for windows 98/Me -		system_path = "/WINDOWS/FONTS/"; -#elif LL_DARWIN -		// HACK for Mac OS X -		system_path = "/System/Library/Fonts/"; -#endif -	} -	return system_path; -} - - -// static  -std::string LLFontGL::getFontPathLocal() -{ -	std::string local_path; - -	// Backup files if we can't load from system fonts directory. -	// We could store this in an end-user writable directory to allow -	// end users to switch fonts. -	if (LLFontGL::sAppDir.length()) -	{ -		// use specified application dir to look for fonts -		local_path = LLFontGL::sAppDir + "/fonts/"; -	} -	else -	{ -		// assume working directory is executable directory -		local_path = "./fonts/"; -	} -	return local_path; -} - -bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc) -{ -	// Don't delete existing fonts, if any, here, because they've -	// already been deleted by LLFontRegistry::clear() -	fontp = LLFontGL::getFont(desc); -	return (fontp != NULL); -} - -// static -void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, -								const std::string& app_dir, -								const std::vector<std::string>& xui_paths, -								bool create_gl_textures) -{ -	sVertDPI = (F32)llfloor(screen_dpi * y_scale); -	sHorizDPI = (F32)llfloor(screen_dpi * x_scale); -	sScaleX = x_scale; -	sScaleY = y_scale; -	sAppDir = app_dir; - -	// Font registry init -	if (!sFontRegistry) -	{ -		sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); -		sFontRegistry->parseFontInfo("fonts.xml"); -	} -	else -	{ -		sFontRegistry->reset(); -	} -} - -// 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 -// the viewer window on screen first. JC -// static -bool LLFontGL::loadDefaultFonts() -{ -	bool succ = true; -	succ &= (NULL != getFontSansSerifSmall()); -	succ &= (NULL != getFontSansSerif()); -	succ &= (NULL != getFontSansSerifBig()); -	succ &= (NULL != getFontSansSerifHuge()); -	succ &= (NULL != getFontSansSerifBold()); -	succ &= (NULL != getFontMonospace()); -	succ &= (NULL != getFontExtChar()); -	return succ; -} - - - -// static -void LLFontGL::destroyDefaultFonts() -{ -	// Remove the actual fonts. -	delete sFontRegistry; -	sFontRegistry = NULL; -} - -//static  -void LLFontGL::destroyAllGL() -{ -	if (sFontRegistry) -	{ -		sFontRegistry->destroyGL(); -	} +	mFontFreetype->reset(sVertDPI, sHorizDPI);  }  void LLFontGL::destroyGL()  { -	mFontBitmapCachep->destroyGL(); +	mFontFreetype->destroyGL();  } - - -LLFontGL &LLFontGL::operator=(const LLFontGL &source) +BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)  { -	llerrs << "Not implemented" << llendl; -	return *this; -} - -BOOL LLFontGL::loadFace(const std::string& filename, -						const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, -						const S32 components, BOOL is_fallback) -{ -	if (!LLFont::loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback)) +	if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))  	{ -		return FALSE; +		mFontFreetype = new LLFontFreetype;  	} -	return TRUE; -} -//static -LLFontGL* LLFontGL::getFontMonospace() -{ -	return getFont(LLFontDescriptor("Monospace","Monospace",0)); +	return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);  } -//static -LLFontGL* LLFontGL::getFontSansSerifSmall() -{ -	return getFont(LLFontDescriptor("SansSerif","Small",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerif() -{ -	return getFont(LLFontDescriptor("SansSerif","Medium",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifBig() -{ -	return getFont(LLFontDescriptor("SansSerif","Large",0)); -} - -//static  -LLFontGL* LLFontGL::getFontSansSerifHuge() -{ -	return getFont(LLFontDescriptor("SansSerif","Huge",0)); -} - -//static  -LLFontGL* LLFontGL::getFontSansSerifBold() -{ -	return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); -} - -//static -LLFontGL* LLFontGL::getFontExtChar() -{ -	return getFontSansSerif(); -} - -//static  -LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) -{ -	return sFontRegistry->getFont(desc); -} - -//static -LLFontGL* LLFontGL::getFontByName(const std::string& name) -{ -	// check for most common fonts first -	if (name == "SANSSERIF") -	{ -		return getFontSansSerif(); -	} -	else if (name == "SANSSERIF_SMALL") -	{ -		return getFontSansSerifSmall(); -	} -	else if (name == "SANSSERIF_BIG") -	{ -		return getFontSansSerifBig(); -	} -	else if (name == "SMALL" || name == "OCRA") -	{ -		// *BUG: Should this be "MONOSPACE"?  Do we use "OCRA" anymore? -		// Does "SMALL" mean "SERIF"? -		return getFontMonospace(); -	} -	else -	{ -		return NULL; -	} -} - -BOOL LLFontGL::addChar(const llwchar wch) const -{ -	if (!LLFont::addChar(wch)) -	{ -		return FALSE; -	} - -	stop_glerror(); - -	LLFontGlyphInfo *glyph_info = getGlyphInfo(wch); -	U32 bitmap_num = glyph_info->mBitmapNum; -	LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num); -	LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); -	image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); -	return TRUE; -} - - -S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset,  -					 const F32 x, const F32 y, -					 const LLColor4 &color, -					 const HAlign halign, const VAlign valign, -					 U8 style, -					 ShadowType shadow, -					 const S32 max_chars, const S32 max_pixels, -					 F32* right_x, -					 BOOL use_ellipses) const -{ -	LLWString wstr = utf8str_to_wstring(text); -	return render(wstr, offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); -} - -S32 LLFontGL::render(const LLWString &wstr,  -					 const S32 begin_offset, -					 const F32 x, const F32 y, -					 const LLColor4 &color, -					 const HAlign halign, const VAlign valign, -					 U8 style, -					 ShadowType shadow, -					 const S32 max_chars, S32 max_pixels, -					 F32* right_x, -					 BOOL use_embedded, -					 BOOL use_ellipses) const +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_embedded, BOOL use_ellipses) const  {  	if(!sDisplayFont) //do not display texts  	{ @@ -429,8 +134,9 @@ S32 LLFontGL::render(const LLWString &wstr,  	S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); -	// Strip off any style bits that are already accounted for by the font. -	style = style & (~getFontDesc().getStyle()); +	// determine which style flags need to be added programmatically by striping off the +	// style bits that are drawn by the underlying Freetype font +	U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();  	F32 drop_shadow_strength = 0.f;  	if (shadow != NO_SHADOW) @@ -482,13 +188,13 @@ S32 LLFontGL::render(const LLWString &wstr,  	switch (valign)  	{  	case TOP: -		cur_y -= mAscender; +		cur_y -= mFontFreetype->getAscenderHeight();  		break;  	case BOTTOM: -		cur_y += mDescender; +		cur_y += mFontFreetype->getDescenderHeight();  		break;  	case VCENTER: -		cur_y -= ((mAscender - mDescender)/2.f); +		cur_y -= ((mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight())/2.f);  		break;  	case BASELINE:  		// Baseline, do nothing. @@ -516,10 +222,12 @@ S32 LLFontGL::render(const LLWString &wstr,  	F32 start_x = cur_x; -	F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth(); -	F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight(); +	const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); + +	F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth(); +	F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight(); -	const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; +	const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;  	BOOL draw_ellipses = FALSE; @@ -575,11 +283,11 @@ S32 LLFontGL::render(const LLWString &wstr,  			// snap origin to whole screen pixel  			const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX)); -			const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight)); +			const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mFontFreetype->getAscenderHeight() - mFontFreetype->getLineHeight()));  			LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);  			LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); -			drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength); +			drawGlyph(screen_rect, uv_rect, LLColor4::white, style_to_add, shadow, drop_shadow_strength);  			if (!label.empty())  			{ @@ -608,19 +316,19 @@ S32 LLFontGL::render(const LLWString &wstr,  		}  		else  		{ -			if (!hasGlyph(wch)) +			if (!mFontFreetype->hasGlyph(wch))  			{  				addChar(wch);  			} -			const LLFontGlyphInfo* fgi= getGlyphInfo(wch); +			const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);  			if (!fgi)  			{  				llerrs << "Missing Glyph Info" << llendl;  				break;  			}  			// Per-glyph bitmap texture. -			LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum); +			LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum);  			if (last_bound_texture != image_gl)  			{  				gGL.getTexUnit(0)->bind(image_gl); @@ -645,7 +353,7 @@ S32 LLFontGL::render(const LLWString &wstr,  					    llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,  					    llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); -			drawGlyph(screen_rect, uv_rect, color, style, shadow, drop_shadow_strength); +			drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength);  			chars_drawn++;  			cur_x += fgi->mXAdvance; @@ -655,11 +363,11 @@ S32 LLFontGL::render(const LLWString &wstr,  			if (next_char && (next_char < LAST_CHARACTER))  			{  				// Kern this puppy. -				if (!hasGlyph(next_char)) +				if (!mFontFreetype->hasGlyph(next_char))  				{  					addChar(next_char);  				} -				cur_x += getXKerning(wch, next_char); +				cur_x += mFontFreetype->getXKerning(wch, next_char);  			}  			// Round after kerning. @@ -679,12 +387,14 @@ S32 LLFontGL::render(const LLWString &wstr,  		*right_x = cur_x / sScaleX;  	} -	if (style & UNDERLINE) +	if (style_to_add & UNDERLINE)  	{ +		F32 descender = mFontFreetype->getDescenderHeight(); +  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  		gGL.begin(LLRender::LINES); -		gGL.vertex2f(start_x, cur_y - (mDescender)); -		gGL.vertex2f(cur_x, cur_y - (mDescender)); +		gGL.vertex2f(start_x, cur_y - (descender)); +		gGL.vertex2f(cur_x, cur_y - (descender));  		gGL.end();  	} @@ -702,7 +412,7 @@ S32 LLFontGL::render(const LLWString &wstr,  				cur_x / sScaleX, (F32)y,  				color,  				LEFT, valign, -				style, +				style_to_add,  				shadow,  				S32_MAX, max_pixels,  				right_x, @@ -715,6 +425,41 @@ S32 LLFontGL::render(const LLWString &wstr,  	return chars_drawn;  } +S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const +{ +	return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, 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 +{ +	return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); +} + +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); +} + +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); +} + +// font metrics - override for LLFontFreetype that returns units of virtual pixels +F32 LLFontGL::getLineHeight() const +{  +	return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);  +} + +F32 LLFontGL::getAscenderHeight() const +{  +	return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);  +} + +F32 LLFontGL::getDescenderHeight() const +{  +	return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);  +}  S32 LLFontGL::getWidth(const std::string& utf8text) const  { @@ -727,13 +472,13 @@ S32 LLFontGL::getWidth(const llwchar* wchars) const  	return getWidth(wchars, 0, S32_MAX);  } -S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars) const +S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_chars) const  {  	LLWString wtext = utf8str_to_wstring(utf8text);  	return getWidth(wtext.c_str(), begin_offset, max_chars);  } -S32 LLFontGL::getWidth(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const +S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const  {  	F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded);  	return llround(width); @@ -750,15 +495,15 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars) const  	return getWidthF32(wchars, 0, S32_MAX);  } -F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars ) const +F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars ) const  {  	LLWString wtext = utf8str_to_wstring(utf8text);  	return getWidthF32(wtext.c_str(), begin_offset, max_chars);  } -F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const +F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const  { -	const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; +	const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;  	F32 cur_x = 0;  	const S32 max_index = begin_offset + max_chars; @@ -782,7 +527,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S  		}  		else  		{ -			cur_x += getXAdvance(wch); +			cur_x += mFontFreetype->getXAdvance(wch);  			llwchar next_char = wchars[i+1];  			if (((i + 1) < max_chars)  @@ -790,7 +535,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S  				&& (next_char < LAST_CHARACTER))  			{  				// Kern this puppy. -				cur_x += getXKerning(wch, next_char); +				cur_x += mFontFreetype->getXKerning(wch, next_char);  			}  		}  		// Round after kerning. @@ -800,12 +545,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S  	return cur_x / sScaleX;  } - -  // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels -S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, -							   BOOL end_on_word_boundary, const BOOL use_embedded, -							   F32* drawn_pixels) const +S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, BOOL end_on_word_boundary, BOOL use_embedded, F32* drawn_pixels) const  {  	if (!wchars || !wchars[0] || max_chars == 0)  	{ @@ -898,7 +639,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  				}  			} -			cur_x += getXAdvance(wch); +			cur_x += mFontFreetype->getXAdvance(wch);  			if (scaled_max_pixels < cur_x)  			{ @@ -909,7 +650,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  			if (((i+1) < max_chars) && wchars[i+1])  			{  				// Kern this puppy. -				cur_x += getXKerning(wch, wchars[i+1]); +				cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);  			}  		}  		// Round after kerning. @@ -928,7 +669,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  	return i;  } -  S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const  {  	if (!wchars || !wchars[0] || max_chars == 0) @@ -947,7 +687,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  		llwchar wch = wchars[i];  		const embedded_data_t* ext_data = getEmbeddedCharData(wch); -		F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch); +		F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : mFontFreetype->getXAdvance(wch);  		if( scaled_max_pixels < (total_width + char_width) )  		{ @@ -965,7 +705,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  		if ( i > 0 )  		{  			// kerning -			total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch); +			total_width += ext_data ? (EXT_KERNING * sScaleX) : mFontFreetype->getXKerning(wchars[i-1], wch);  		}  		// Round after kerning. @@ -975,8 +715,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  	return start_pos - drawable_chars;  } - -S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const +S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const  {  	if (!wchars || !wchars[0] || max_chars == 0)  	{ @@ -1040,7 +779,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,  		}  		else  		{ -			F32 char_width = getXAdvance(wch); +			F32 char_width = mFontFreetype->getXAdvance(wch);  			if (round)  			{ @@ -1069,7 +808,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,  			{  				llwchar next_char = wchars[i + 1];  				// Kern this puppy. -				cur_x += getXKerning(wch, next_char); +				cur_x += mFontFreetype->getXKerning(wch, next_char);  			}  			// Round after kerning. @@ -1080,60 +819,370 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,  	return pos;  } +void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label ) const +{ +	LLWString wlabel = utf8str_to_wstring(label); +	addEmbeddedChar(wc, image, wlabel); +} -const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(const llwchar wch) const +void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& wlabel ) const  { -	// Handle crappy embedded hack -	embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch); +	embedded_data_t* ext_data = new embedded_data_t(image->getGLTexture(), wlabel); +	mEmbeddedChars[wc] = ext_data; +} + +void LLFontGL::removeEmbeddedChar(llwchar wc) const +{ +	embedded_map_t::iterator iter = mEmbeddedChars.find(wc);  	if (iter != mEmbeddedChars.end())  	{ -		return iter->second; +		delete iter->second; +		mEmbeddedChars.erase(wc);  	} -	return NULL;  } +BOOL LLFontGL::addChar(llwchar wch) const +{ +	if (!mFontFreetype->addChar(wch)) +	{ +		return FALSE; +	} + +	stop_glerror(); -F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const +	LLFontGlyphInfo *glyph_info = mFontFreetype->getGlyphInfo(wch); +	U32 bitmap_num = glyph_info->mBitmapNum; + +	const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); +	LLImageGL *image_gl = font_bitmap_cache->getImageGL(bitmap_num); +	LLImageRaw *image_raw = font_bitmap_cache->getImageRaw(bitmap_num); +	image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); +	return TRUE; +} + +const LLFontDescriptor& LLFontGL::getFontDesc() const  { -	const LLWString& label = ext_data->mLabel; -	LLImageGL* ext_image = ext_data->mImage; +	return mFontDescriptor; +} -	F32 ext_width = (F32)ext_image->getWidth(); -	if( !label.empty() ) +// static +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures) +{ +	sVertDPI = (F32)llfloor(screen_dpi * y_scale); +	sHorizDPI = (F32)llfloor(screen_dpi * x_scale); +	sScaleX = x_scale; +	sScaleY = y_scale; +	sAppDir = app_dir; + +	// Font registry init +	if (!sFontRegistry)  	{ -		ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX; +		sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); +		sFontRegistry->parseFontInfo("fonts.xml"); +	} +	else +	{ +		sFontRegistry->reset();  	} +} -	return (EXT_X_BEARING * sScaleX) + ext_width; +// 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 +// the viewer window on screen first. JC +// static +bool LLFontGL::loadDefaultFonts() +{ +	bool succ = true; +	succ &= (NULL != getFontSansSerifSmall()); +	succ &= (NULL != getFontSansSerif()); +	succ &= (NULL != getFontSansSerifBig()); +	succ &= (NULL != getFontSansSerifHuge()); +	succ &= (NULL != getFontSansSerifBold()); +	succ &= (NULL != getFontMonospace()); +	succ &= (NULL != getFontExtChar()); +	return succ;  } +// static +void LLFontGL::destroyDefaultFonts() +{ +	// Remove the actual fonts. +	delete sFontRegistry; +	sFontRegistry = NULL; +} -void LLFontGL::clearEmbeddedChars() +//static  +void LLFontGL::destroyAllGL()  { -	for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); -	mEmbeddedChars.clear(); +	if (sFontRegistry) +	{ +		sFontRegistry->destroyGL(); +	}  } -void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) const +// static +U8 LLFontGL::getStyleFromString(const std::string &style)  { -	LLWString wlabel = utf8str_to_wstring(label); -	addEmbeddedChar(wc, image, wlabel); +	S32 ret = 0; +	if (style.find("NORMAL") != style.npos) +	{ +		ret |= NORMAL; +	} +	if (style.find("BOLD") != style.npos) +	{ +		ret |= BOLD; +	} +	if (style.find("ITALIC") != style.npos) +	{ +		ret |= ITALIC; +	} +	if (style.find("UNDERLINE") != style.npos) +	{ +		ret |= UNDERLINE; +	} +	return ret;  } -void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) const +// static +std::string LLFontGL::nameFromFont(const LLFontGL* fontp)  { -	embedded_data_t* ext_data = new embedded_data_t(image, wlabel); -	mEmbeddedChars[wc] = ext_data; +	return fontp->mFontDescriptor.getName();  } -void LLFontGL::removeEmbeddedChar( llwchar wc ) const +// static +std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align)  { -	embedded_map_t::iterator iter = mEmbeddedChars.find(wc); +	if (align == LEFT)			return std::string("left"); +	else if (align == RIGHT)	return std::string("right"); +	else if (align == HCENTER)	return std::string("center"); +	else return std::string(); +} + +// static +LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name) +{ +	LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; +	if (name == "left") +	{ +		gl_hfont_align = LLFontGL::LEFT; +	} +	else if (name == "right") +	{ +		gl_hfont_align = LLFontGL::RIGHT; +	} +	else if (name == "center") +	{ +		gl_hfont_align = LLFontGL::HCENTER; +	} +	//else leave left +	return gl_hfont_align; +} + +// static +std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align) +{ +	if (align == TOP)			return std::string("top"); +	else if (align == VCENTER)	return std::string("center"); +	else if (align == BASELINE)	return std::string("baseline"); +	else if (align == BOTTOM)	return std::string("bottom"); +	else return std::string(); +} + +// static +LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) +{ +	LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; +	if (name == "top") +	{ +		gl_vfont_align = LLFontGL::TOP; +	} +	else if (name == "center") +	{ +		gl_vfont_align = LLFontGL::VCENTER; +	} +	else if (name == "baseline") +	{ +		gl_vfont_align = LLFontGL::BASELINE; +	} +	else if (name == "bottom") +	{ +		gl_vfont_align = LLFontGL::BOTTOM; +	} +	//else leave baseline +	return gl_vfont_align; +} + +//static +LLFontGL* LLFontGL::getFontMonospace() +{ +	return getFont(LLFontDescriptor("Monospace","Monospace",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifSmall() +{ +	return getFont(LLFontDescriptor("SansSerif","Small",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerif() +{ +	return getFont(LLFontDescriptor("SansSerif","Medium",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifBig() +{ +	return getFont(LLFontDescriptor("SansSerif","Large",0)); +} + +//static  +LLFontGL* LLFontGL::getFontSansSerifHuge() +{ +	return getFont(LLFontDescriptor("SansSerif","Huge",0)); +} + +//static  +LLFontGL* LLFontGL::getFontSansSerifBold() +{ +	return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); +} + +//static +LLFontGL* LLFontGL::getFontExtChar() +{ +	return getFontSansSerif(); +} + +//static  +LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) +{ +	return sFontRegistry->getFont(desc); +} + +//static +LLFontGL* LLFontGL::getFontByName(const std::string& name) +{ +	// check for most common fonts first +	if (name == "SANSSERIF") +	{ +		return getFontSansSerif(); +	} +	else if (name == "SANSSERIF_SMALL") +	{ +		return getFontSansSerifSmall(); +	} +	else if (name == "SANSSERIF_BIG") +	{ +		return getFontSansSerifBig(); +	} +	else if (name == "SMALL" || name == "OCRA") +	{ +		// *BUG: Should this be "MONOSPACE"?  Do we use "OCRA" anymore? +		// Does "SMALL" mean "SERIF"? +		return getFontMonospace(); +	} +	else +	{ +		return NULL; +	} +} + +// static  +std::string LLFontGL::getFontPathSystem() +{ +	std::string system_path; + +	// Try to figure out where the system's font files are stored. +	char *system_root = NULL; +#if LL_WINDOWS +	system_root = getenv("SystemRoot");	/* Flawfinder: ignore */ +	if (!system_root) +	{ +		llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl; +	} +#endif + +	if (system_root) +	{ +		system_path = llformat("%s/fonts/", system_root); +	} +	else +	{ +#if LL_WINDOWS +		// HACK for windows 98/Me +		system_path = "/WINDOWS/FONTS/"; +#elif LL_DARWIN +		// HACK for Mac OS X +		system_path = "/System/Library/Fonts/"; +#endif +	} +	return system_path; +} + + +// static  +std::string LLFontGL::getFontPathLocal() +{ +	std::string local_path; + +	// Backup files if we can't load from system fonts directory. +	// We could store this in an end-user writable directory to allow +	// end users to switch fonts. +	if (LLFontGL::sAppDir.length()) +	{ +		// use specified application dir to look for fonts +		local_path = LLFontGL::sAppDir + "/fonts/"; +	} +	else +	{ +		// assume working directory is executable directory +		local_path = "./fonts/"; +	} +	return local_path; +} + +LLFontGL::LLFontGL(const LLFontGL &source) +{ +	llerrs << "Not implemented!" << llendl; +} + +LLFontGL &LLFontGL::operator=(const LLFontGL &source) +{ +	llerrs << "Not implemented" << llendl; +	return *this; +} + +const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(llwchar wch) const +{ +	// Handle crappy embedded hack +	embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch);  	if (iter != mEmbeddedChars.end())  	{ -		delete iter->second; -		mEmbeddedChars.erase(wc); +		return iter->second; +	} +	return NULL; +} + +F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const +{ +	const LLWString& label = ext_data->mLabel; +	LLImageGL* ext_image = ext_data->mImage; + +	F32 ext_width = (F32)ext_image->getWidth(); +	if( !label.empty() ) +	{ +		ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX;  	} + +	return (EXT_X_BEARING * sScaleX) + ext_width; +} + +void LLFontGL::clearEmbeddedChars() +{ +	for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); +	mEmbeddedChars.clear();  } @@ -1159,7 +1208,7 @@ void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F3  void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const  {  	F32 slant_offset; -	slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f); +	slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);  	gGL.begin(LLRender::QUADS);  	{ @@ -1229,71 +1278,3 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con  	}  	gGL.end();  } - -std::string LLFontGL::nameFromFont(const LLFontGL* fontp) -{ -	return fontp->getFontDesc().getName(); -} - -// static -std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align) -{ -	if (align == LEFT)			return std::string("left"); -	else if (align == RIGHT)	return std::string("right"); -	else if (align == HCENTER)	return std::string("center"); -	else return std::string(); -} - -// static -LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name) -{ -	LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; -	if (name == "left") -	{ -		gl_hfont_align = LLFontGL::LEFT; -	} -	else if (name == "right") -	{ -		gl_hfont_align = LLFontGL::RIGHT; -	} -	else if (name == "center") -	{ -		gl_hfont_align = LLFontGL::HCENTER; -	} -	//else leave left -	return gl_hfont_align; -} - -// static -std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align) -{ -	if (align == TOP)			return std::string("top"); -	else if (align == VCENTER)	return std::string("center"); -	else if (align == BASELINE)	return std::string("baseline"); -	else if (align == BOTTOM)	return std::string("bottom"); -	else return std::string(); -} - -// static -LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) -{ -	LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; -	if (name == "top") -	{ -		gl_vfont_align = LLFontGL::TOP; -	} -	else if (name == "center") -	{ -		gl_vfont_align = LLFontGL::VCENTER; -	} -	else if (name == "baseline") -	{ -		gl_vfont_align = LLFontGL::BASELINE; -	} -	else if (name == "bottom") -	{ -		gl_vfont_align = LLFontGL::BOTTOM; -	} -	//else leave baseline -	return gl_vfont_align; -} diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 204c6908af..42ed7a381f 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -35,21 +35,21 @@  #define LL_LLFONTGL_H  #include "llcoord.h" -#include "llfont.h"  #include "llfontregistry.h" +#include "llimagegl.h"  #include "llpointer.h"  #include "llrect.h"  #include "v2math.h"  class LLColor4; -class LLImageGL;  // Key used to request a font.  class LLFontDescriptor; +class LLFontFreetype;  // Structure used to store previously requested fonts.  class LLFontRegistry; -class LLFontGL : public LLFont +class LLFontGL  {  public:  	enum HAlign @@ -85,130 +85,72 @@ public:  		DROP_SHADOW,  		DROP_SHADOW_SOFT  	}; -	 -	// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" -	static U8 getStyleFromString(const std::string &style);  	LLFontGL(); -	LLFontGL(const LLFontGL &source);  	~LLFontGL(); -	void init(); // Internal init, or reinitialization -	void reset(); // Reset a font after GL cleanup.  ONLY works on an already loaded font. -	LLFontGL &operator=(const LLFontGL &source); - -	static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, -								 const std::string& app_dir, -								 const std::vector<std::string>& xui_paths, -								 bool create_gl_textures = true); +	void reset(); // Reset a font after GL cleanup.  ONLY works on an already loaded font. -	// Load sans-serif, sans-serif-small, etc. -	// Slow, requires multiple seconds to load fonts. -	static bool loadDefaultFonts(); -	static void	destroyDefaultFonts(); -	static void destroyAllGL();  	void destroyGL(); -	/* virtual*/ BOOL loadFace(const std::string& filename, -							    const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, -							    const S32 components, BOOL is_fallback); +	BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback); +	S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign = LEFT,  VAlign valign = BASELINE, U8 style = NORMAL, +	           ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, BOOL use_embedded = FALSE, BOOL use_ellipses = FALSE) const; +	S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; -	S32 renderUTF8(const std::string &text, const 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); -	} -	 -	S32 renderUTF8(const std::string &text, const S32 begin_offset, -				   S32 x, S32 y, -				   const LLColor4 &color, -				   HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const -	{ -		return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, -						  halign, valign, style, shadow, -						  S32_MAX, S32_MAX, NULL, FALSE); -	} -	  	// 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 render(const LLWString &text, const S32 begin_offset, -			   F32 x, F32 y, -			   const LLColor4 &color) const -	{ -		return render(text, begin_offset, x, y, color, -					  LEFT, BASELINE, NORMAL, NO_SHADOW, -					  S32_MAX, S32_MAX, NULL, FALSE, FALSE); -	} -	 +	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, 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; -	S32 render(const LLWString &text, -		S32 begin_offset, -		F32 x, F32 y, -		const LLColor4 &color, -		HAlign halign = LEFT,  -		VAlign valign = BASELINE, -		U8 style = NORMAL, -		ShadowType shadow = NO_SHADOW, -		S32 max_chars = S32_MAX, -		S32 max_pixels = S32_MAX,  -		F32* right_x=NULL, -		BOOL use_embedded = FALSE, -		BOOL use_ellipses = FALSE) const; - -	// font metrics - override for LLFont that returns units of virtual pixels -	/*virtual*/ F32 getLineHeight() const		{ return (F32)llround(mLineHeight / sScaleY); } -	/*virtual*/ F32 getAscenderHeight() const	{ return (F32)llround(mAscender / sScaleY); } -	/*virtual*/ F32 getDescenderHeight() const	{ return (F32)llround(mDescender / sScaleY); } -	 -	virtual S32 getWidth(const std::string& utf8text) const; -	virtual S32 getWidth(const llwchar* wchars) const; -	virtual S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const; -	virtual S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const; +	// font metrics - override for LLFontFreetype that returns units of virtual pixels +	F32 getLineHeight() const; +	F32 getAscenderHeight() const; +	F32 getDescenderHeight() const; -	virtual F32 getWidthF32(const std::string& utf8text) const; -	virtual F32 getWidthF32(const llwchar* wchars) const; -	virtual F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const; -	virtual F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const; +	S32 getWidth(const std::string& utf8text) const; +	S32 getWidth(const llwchar* wchars) const; +	S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars ) const; +	S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE) const; + +	F32 getWidthF32(const std::string& utf8text) const; +	F32 getWidthF32(const llwchar* wchars) const; +	F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const; +	F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE ) const;  	// The following are called often, frequently with large buffers, so do not use a string interface  	// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels -	virtual S32	maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, -								 BOOL end_on_word_boundary = FALSE, const BOOL use_embedded = FALSE, -								 F32* drawn_pixels = NULL) const; +	S32	maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, BOOL end_on_word_boundary = FALSE, BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const;  	// Returns the index of the first complete characters from text that can be drawn in max_pixels  	// given that the character at start_pos should be the last character (or as close to last as possible). -	virtual S32	firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; +	S32	firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;  	// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) -	virtual S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset, -									F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, -									BOOL round = TRUE, BOOL use_embedded = FALSE) const; +	S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const; + +	void addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label) const; +	void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; +	void removeEmbeddedChar( llwchar wc ) const; +	BOOL addChar(const llwchar wch) const; -	LLImageGL *getImageGL() const; +	const LLFontDescriptor& getFontDesc() const; -	void	   addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label) const; -	void	   addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& label) const; -	void	   removeEmbeddedChar( llwchar wc ) const; + +	static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures = true); + +	// Load sans-serif, sans-serif-small, etc. +	// Slow, requires multiple seconds to load fonts. +	static bool loadDefaultFonts(); +	static void	destroyDefaultFonts(); +	static void destroyAllGL(); + +	// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" +	static U8 getStyleFromString(const std::string &style);  	static std::string nameFromFont(const LLFontGL* fontp); @@ -218,28 +160,7 @@ public:  	static std::string nameFromVAlign(LLFontGL::VAlign align);  	static LLFontGL::VAlign vAlignFromName(const std::string& name); -	static void setFontDisplay(BOOL flag) { sDisplayFont = flag ; } - -protected: -	struct embedded_data_t -	{ -		embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} -		LLPointer<LLImageGL> mImage; -		LLWString			 mLabel; -	}; -	const embedded_data_t* getEmbeddedCharData(const llwchar wch) const; -	F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; -	void clearEmbeddedChars(); -	void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; -	void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; - -public: -	static F32 sVertDPI; -	static F32 sHorizDPI; -	static F32 sScaleX; -	static F32 sScaleY; -	static BOOL     sDisplayFont ; -	static std::string sAppDir;			// For loading fonts +	static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }  	static LLFontGL* getFontMonospace();  	static LLFontGL* getFontSansSerifSmall(); @@ -252,32 +173,50 @@ public:  	// Use with legacy names like "SANSSERIF_SMALL" or "OCRA"  	static LLFontGL* getFontByName(const std::string& name); +	static std::string getFontPathLocal(); +	static std::string getFontPathSystem(); + +	static LLCoordFont sCurOrigin; +	static std::vector<LLCoordFont> sOriginStack; +  	static LLColor4 sShadowColor; +	static F32 sVertDPI; +	static F32 sHorizDPI; +	static F32 sScaleX; +	static F32 sScaleY; +	static BOOL sDisplayFont ; +	static std::string sAppDir;			// For loading fonts + +private: +	friend class LLFontRegistry;  	friend class LLTextBillboard;  	friend class LLHUDText; -protected: -	/*virtual*/ BOOL addChar(const llwchar wch) const; +	LLFontGL(const LLFontGL &source); +	LLFontGL &operator=(const LLFontGL &source); + +	LLFontDescriptor mFontDescriptor; +	LLPointer<LLFontFreetype> mFontFreetype; + +	struct embedded_data_t +	{ +		embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} +		LLPointer<LLImageGL> mImage; +		LLWString			 mLabel; +	}; -protected:  	typedef std::map<llwchar,embedded_data_t*> embedded_map_t;  	mutable embedded_map_t mEmbeddedChars; -	 -	LLFontDescriptor mFontDesc; + +	const embedded_data_t* getEmbeddedCharData(llwchar wch) const; +	F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; +	void clearEmbeddedChars(); +	void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; +	void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;  	// Registry holds all instantiated fonts.  	static LLFontRegistry* sFontRegistry; - -public: -	static std::string getFontPathLocal(); -	static std::string getFontPathSystem(); - -	static LLCoordFont sCurOrigin; -	static std::vector<LLCoordFont> sOriginStack; - -	const LLFontDescriptor &getFontDesc() const { return mFontDesc; } -	void setFontDesc(const LLFontDescriptor& font_desc) { mFontDesc = font_desc; }  };  #endif diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 455a68ca81..553e7b8f9d 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -33,8 +33,9 @@  #include "linden_common.h"  #include "llgl.h" -#include "llfontregistry.h" +#include "llfontfreetype.h"  #include "llfontgl.h" +#include "llfontregistry.h"  #include <boost/tokenizer.hpp>  #include "llcontrol.h"  #include "lldir.h" @@ -104,7 +105,7 @@ bool removeSubString(std::string& str, const std::string& substr)  	size_t pos = str.find(substr);  	if (pos != string::npos)  	{ -		str.replace(pos,substr.length(), "", 0); +		str.erase(pos);  		return true;  	}  	return false; @@ -382,7 +383,14 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  	if (it != mFontMap.end())  	{  		llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; -		return it->second; +		 +		// copying underlying Freetype font, and storing in LLFontGL with requested font descriptor +		LLFontGL *font = new LLFontGL; +		font->mFontDescriptor = desc; +		font->mFontFreetype = it->second->mFontFreetype; +		mFontMap[desc] = font; + +		return font;  	}  	// Build list of font names to look for. @@ -410,10 +418,11 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  		llwarns << "createFont failed, no file names specified" << llendl;  		return NULL;  	} -	LLFontList *fontlistp = new LLFontList; + +	LLFontFreetype::font_vector_t fontlist;  	LLFontGL *result = NULL; -	// Snarf all fonts we can into fontlistp.  First will get pulled +	// Snarf all fonts we can into fontlist.  First will get pulled  	// off the list and become the "head" font, set to non-fallback.  	// Rest will consitute the fallback list.  	BOOL is_first_found = TRUE; @@ -455,23 +464,28 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  				is_first_found = false;  			}  			else -				fontlistp->addAtEnd(fontp); +			{ +				fontlist.push_back(fontp->mFontFreetype); +			}  		}  	} -	if (result && !fontlistp->empty()) + +	if (result && !fontlist.empty())  	{ -		result->setFallbackFont(fontlistp); +		result->mFontFreetype->setFallbackFonts(fontlist);  	} -	norm_desc.setStyle(match_desc->getStyle());  	if (result) -		result->setFontDesc(norm_desc); - -	if (!result) +	{ +		result->mFontFreetype->setStyle(match_desc->getStyle()); +		result->mFontDescriptor = desc; +	} +	else  	{  		llwarns << "createFont failed in some way" << llendl;  	} -	mFontMap[norm_desc] = result; + +	mFontMap[desc] = result;  	return result;  } @@ -511,21 +525,19 @@ void LLFontRegistry::destroyGL()  	}  } -LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& orig_desc) +LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc)  { -	LLFontDescriptor norm_desc = orig_desc.normalize(); - -	font_reg_map_t::iterator it = mFontMap.find(norm_desc); +	font_reg_map_t::iterator it = mFontMap.find(desc);  	if (it != mFontMap.end())  		return it->second;  	else  	{ -		LLFontGL *fontp = createFont(orig_desc); +		LLFontGL *fontp = createFont(desc);  		if (!fontp)  		{ -			llwarns << "getFont failed, name " << orig_desc.getName() -					<<" style=[" << ((S32) orig_desc.getStyle()) << "]" -					<< " size=[" << orig_desc.getSize() << "]" << llendl; +			llwarns << "getFont failed, name " << desc.getName() +					<<" style=[" << ((S32) desc.getStyle()) << "]" +					<< " size=[" << desc.getSize() << "]" << llendl;  		}  		return fontp;  	} @@ -653,3 +665,8 @@ void LLFontRegistry::dump()  		}  	}  } + +const string_vec_t& LLFontRegistry::getUltimateFallbackList() const  +{  +	return mUltimateFallbackList; +} diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index 198ca0b920..4da4ca48bb 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -98,7 +98,7 @@ public:  	void dump(); -	const string_vec_t& getUltimateFallbackList() const { return mUltimateFallbackList; } +	const string_vec_t& getUltimateFallbackList() const;  private:  	LLFontGL *createFont(const LLFontDescriptor& desc); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index e1231eeeb4..c3d1d9e894 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -46,7 +46,6 @@  //---------------------------------------------------------------------------- -  const F32 MIN_TEXTURE_LIFETIME = 10.f;  //statics @@ -61,7 +60,7 @@ S32 LLImageGL::sCount					= 0;  BOOL LLImageGL::sGlobalUseAnisotropic	= FALSE;  F32 LLImageGL::sLastFrameTime			= 0.f; - +LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;  std::set<LLImageGL*> LLImageGL::sImageList;  //************************************************************************************** @@ -264,6 +263,7 @@ void LLImageGL::restoreGL()  //---------------------------------------------------------------------------- +//for server side use only.  //static   BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, BOOL usemipmaps)  { @@ -271,12 +271,14 @@ BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, BOOL usemipmaps)  	return TRUE;  } +//for server side use only.  BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps)  {  	dest = new LLImageGL(width, height, components, usemipmaps);  	return TRUE;  } +//for server side use only.  BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps)  {  	dest = new LLImageGL(imageraw, usemipmaps); @@ -331,7 +333,6 @@ void LLImageGL::init(BOOL usemipmaps)  #endif  	mPickMask		  = NULL; -	mTextureState       = NO_DELETE ;  	mTextureMemory    = 0;  	mLastBindTime     = 0.f; @@ -351,8 +352,7 @@ void LLImageGL::init(BOOL usemipmaps)  	mComponents			= 0;  	mMaxDiscardLevel = MAX_DISCARD_LEVEL; -	mCurrentDiscardLevel = -1; -	mDontDiscard = FALSE; +	mCurrentDiscardLevel = -1;	  	mFormatInternal = -1;  	mFormatPrimary = (LLGLenum) 0; @@ -362,6 +362,7 @@ void LLImageGL::init(BOOL usemipmaps)  	mGLTextureCreated = FALSE ;  	mIsMask = FALSE; +	mNeedsAlphaAndPickMask = TRUE ;  }  void LLImageGL::cleanup() @@ -462,7 +463,7 @@ void LLImageGL::dump()  //---------------------------------------------------------------------------- -void LLImageGL::updateBindStats(void) const +BOOL LLImageGL::updateBindStats(S32 tex_mem) const  {	  	if (mTexName != 0)  	{ @@ -474,38 +475,18 @@ void LLImageGL::updateBindStats(void) const  		{  			// we haven't accounted for this texture yet this frame  			sUniqueCount++; -			updateBoundTexMem(mTextureMemory); +			updateBoundTexMem(tex_mem);  			mLastBindTime = sLastFrameTime; -			if(LLFastTimer::sMetricLog) -			{ -				updateTestStats() ; -			} +			return TRUE ;  		}  	} +	return FALSE ;  } -//virtual  -void LLImageGL::updateTestStats(void) const -{ -} - -//virtual -bool LLImageGL::bindError(const S32 stage) const -{ -	return false; -} - -//virtual -bool LLImageGL::bindDefaultImage(const S32 stage) const -{ -	return false; -} - -//virtual -void LLImageGL::forceImmediateUpdate() +F32 LLImageGL::getTimePassedSinceLastBound()  { -	return ; +	return sLastFrameTime - mLastBindTime ;  }  void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) @@ -1052,7 +1033,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_  	mTextureMemory = getMipBytes(discard_level);  	sGlobalTextureMemoryInBytes += mTextureMemory; -	setActive() ;  	// mark this as bound at this point, so we don't throw it out immediately  	mLastBindTime = sLastFrameTime; @@ -1068,12 +1048,7 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level)  	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);	 -	if (mDontDiscard) -	{ -		// don't discard! -		return FALSE; -	} -	else if (discard_level == mCurrentDiscardLevel) +	if (discard_level == mCurrentDiscardLevel)  	{  		// nothing to do  		return FALSE; @@ -1255,8 +1230,7 @@ void LLImageGL::destroyGLTexture()  		sGlobalTextureMemoryInBytes -= mTextureMemory;  		mTextureMemory = 0; -		LLImageGL::deleteTextures(1, &mTexName); -		mTextureState = DELETED ;		 +		LLImageGL::deleteTextures(1, &mTexName);			  		mTexName = 0;  		mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.  		mGLTextureCreated = FALSE ; @@ -1383,6 +1357,11 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b  void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)  { +	if(!mNeedsAlphaAndPickMask) +	{ +		return ; +	} +  	if (mFormatType != GL_UNSIGNED_BYTE)  	{  		llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; @@ -1440,60 +1419,14 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)  	}  } -BOOL LLImageGL::isDeleted()   -{  -	return mTextureState == DELETED ;  -} - -BOOL LLImageGL::isInactive()   -{  -	return mTextureState == INACTIVE ;  -} - -BOOL LLImageGL::isDeletionCandidate()   -{  -	return mTextureState == DELETION_CANDIDATE ;  -} - -void LLImageGL::setDeletionCandidate()   -{  -	if(mTexName && (mTextureState == INACTIVE)) -	{ -		mTextureState = DELETION_CANDIDATE ;		 -	} -} - -void LLImageGL::forceActive() -{ -	mTextureState = ACTIVE ;  -} - -void LLImageGL::setActive()  -{  -	if(mTextureState != NO_DELETE) -	{ -		mTextureState = ACTIVE ;  -	} -} - -//set the texture inactive -void LLImageGL::setInactive() +//---------------------------------------------------------------------------- +void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)  { -	if(mTexName && (mTextureState == ACTIVE) && !getBoundRecently()) +	if(!mNeedsAlphaAndPickMask)  	{ -		mTextureState = INACTIVE ;  +		return ;  	} -} -//set the texture to stay in memory -void LLImageGL::setNoDelete()  -{  -	mTextureState = NO_DELETE ; -} - -//---------------------------------------------------------------------------- -void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) -{  	if (mFormatType != GL_UNSIGNED_BYTE ||  		mFormatPrimary != GL_RGBA)  	{ diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 1775ae7de9..5f32b23356 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -57,8 +57,8 @@ public:  	static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);  	static S32 dataFormatComponents(S32 dataformat); -	void updateBindStats(void) const; -	virtual void updateTestStats(void) const; +	BOOL updateBindStats(S32 tex_mem) const ; +	F32 getTimePassedSinceLastBound();  	// needs to be called every frame  	static void updateStats(F32 current_time); @@ -71,13 +71,14 @@ public:  	static S32 updateBoundTexMem(const S32 delta);  	static bool checkSize(S32 width, S32 height); -	 + +	//for server side use only.  	// Not currently necessary for LLImageGL, but required in some derived classes,  	// so include for compatability  	static BOOL create(LLPointer<LLImageGL>& dest, BOOL usemipmaps = TRUE);  	static BOOL create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);  	static BOOL create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps = TRUE); -	 +		  public:  	LLImageGL(BOOL usemipmaps = TRUE);  	LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE); @@ -90,11 +91,9 @@ protected:  public:  	virtual void dump();	// debugging info to llinfos -	virtual bool bindError(const S32 stage = 0) const; -	virtual bool bindDefaultImage(const S32 stage = 0) const; -	virtual void forceImmediateUpdate() ; - +	  	void setSize(S32 width, S32 height, S32 ncomponents); +	void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}  	// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()   	// for tracking purposes and will be deprecated in the future @@ -116,7 +115,6 @@ public:  	void destroyGLTexture();  	void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); -	void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }  	S32	 getDiscardLevel() const		{ return mCurrentDiscardLevel; }  	S32	 getMaxDiscardLevel() const		{ return mMaxDiscardLevel; } @@ -145,9 +143,7 @@ public:  	void setGLTextureCreated (bool initialized) { mGLTextureCreated = initialized; }  	BOOL getUseMipMaps() const { return mUseMipMaps; } -	void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; } -	BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } -	BOOL getDontDiscard() const { return mDontDiscard; } +	void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }	  	BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ; @@ -168,19 +164,10 @@ public:  	void setFilteringOption(LLTexUnit::eTextureFilterOptions option);  	LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; } -	BOOL isDeleted() ; -	BOOL isInactive() ; -	BOOL isDeletionCandidate(); -	void setDeletionCandidate() ; -	void setInactive() ; -	void setActive() ; -	void forceActive() ; -	void setNoDelete() ; - -protected:  	void init(BOOL usemipmaps);  	virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized.  Be careful when using this in derived class destructors +	void setNeedsAlphaAndPickMask(BOOL need_mask) {mNeedsAlphaAndPickMask = need_mask;}  public:  	// Various GL/Rendering options  	S32 mTextureMemory; @@ -194,6 +181,7 @@ private:  	S8 mAutoGenMips;  	BOOL mIsMask; +	BOOL mNeedsAlphaAndPickMask;  	bool     mGLTextureCreated ;  	LLGLuint mTexName; @@ -210,28 +198,15 @@ protected:  	S8 mComponents;  	S8 mMaxDiscardLevel;	 -	S8 mDontDiscard;			// Keep full res version of this image (for UI, etc) - +	  	bool	mTexOptionsDirty;  	LLTexUnit::eTextureAddressMode		mAddressMode;	// Defaults to TAM_WRAP  	LLTexUnit::eTextureFilterOptions	mFilterOption;	// Defaults to TFO_TRILINEAR -  	LLGLint  mFormatInternal; // = GL internalformat  	LLGLenum mFormatPrimary;  // = GL format (pixel data format)  	LLGLenum mFormatType;  	BOOL	 mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1) - -protected: -	typedef enum  -	{ -		DELETED = 0,         //removed from memory -		DELETION_CANDIDATE,  //ready to be removed from memory -		INACTIVE,            //not be used for the last certain period (i.e., 30 seconds). -		ACTIVE,              //just being used, can become inactive if not being used for a certain time (10 seconds). -		NO_DELETE = 99       //stay in memory, can not be removed. -	} LLGLTexureState; -	LLGLTexureState  mTextureState ;  	// STATICS  public:	 @@ -249,6 +224,7 @@ public:  	static U32 sBindCount;					// Tracks number of texture binds for current frame  	static U32 sUniqueCount;				// Tracks number of unique texture binds for current frame  	static BOOL sGlobalUseAnisotropic; +	static LLImageGL* sDefaultGLTexture ;  #if DEBUG_MISS  	BOOL mMissed; // Missed on last bind? diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index d3a230b37b..d577daf3f4 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -38,6 +38,7 @@  #include "llcubemap.h"  #include "llimagegl.h"  #include "llrendertarget.h" +#include "lltexture.h"  LLRender gGL; @@ -177,20 +178,21 @@ void LLTexUnit::disable(void)  	}  } -bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) +bool LLTexUnit::bind(LLTexture* texture, bool forceBind)  {  	stop_glerror();  	if (mIndex < 0) return false;  	gGL.flush(); -	if (texture == NULL) +	LLImageGL* gl_tex = NULL ; +	if (texture == NULL || !(gl_tex = texture->getGLTexture()))  	{  		llwarns << "NULL LLTexUnit::bind texture" << llendl;  		return false;  	} -	if (!texture->getTexName()) //if texture does not exist +	if (!gl_tex->getTexName()) //if texture does not exist  	{  		//if deleted, will re-generate it immediately  		texture->forceImmediateUpdate() ; @@ -198,14 +200,57 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)  		return texture->bindDefaultImage(mIndex);  	} +	if ((mCurrTexture != gl_tex->getTexName()) || forceBind) +	{ +		activate(); +		enable(gl_tex->getTarget()); +		mCurrTexture = gl_tex->getTexName(); +		glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); +		if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) +		{ +			texture->setActive() ; +			texture->updateBindStatsForTester() ; +		} +		mHasMipMaps = gl_tex->mHasMipMaps; +		if (gl_tex->mTexOptionsDirty) +		{ +			gl_tex->mTexOptionsDirty = false; +			setTextureAddressMode(gl_tex->mAddressMode); +			setTextureFilteringOption(gl_tex->mFilterOption); +		} +	} +	return true; +} + +bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) +{ +	stop_glerror(); +	if (mIndex < 0) return false; + +	if(!texture) +	{ +		llwarns << "NULL LLTexUnit::bind texture" << llendl; +		return false; +	} + +	if(!texture->getTexName()) +	{ +		if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName()) +		{ +			return bind(LLImageGL::sDefaultGLTexture) ; +		} +		return false ; +	} + +	gGL.flush(); +  	if ((mCurrTexture != texture->getTexName()) || forceBind)  	{  		activate();  		enable(texture->getTarget());  		mCurrTexture = texture->getTexName();  		glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); -		texture->updateBindStats(); -		texture->setActive() ; +		texture->updateBindStats(texture->mTextureMemory);		  		mHasMipMaps = texture->mHasMipMaps;  		if (texture->mTexOptionsDirty)  		{ @@ -238,7 +283,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)  			mCurrTexture = cubeMap->mImages[0]->getTexName();  			glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);  			mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; -			cubeMap->mImages[0]->updateBindStats(); +			cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);  			if (cubeMap->mImages[0]->mTexOptionsDirty)  			{  				cubeMap->mImages[0]->mTexOptionsDirty = false; @@ -279,15 +324,21 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)  bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)  { -	if (mIndex < 0 || mCurrTexture == texture) return false; +	if (mIndex < 0)   +	{ +		return false; +	} -	gGL.flush(); -	 -	activate(); -	enable(type); -	mCurrTexture = texture; -	glBindTexture(sGLTextureType[type], texture); -	mHasMipMaps = hasMips; +	if(mCurrTexture != texture) +	{ +		gGL.flush(); +		 +		activate(); +		enable(type); +		mCurrTexture = texture; +		glBindTexture(sGLTextureType[type], texture); +		mHasMipMaps = hasMips; +	}  	return true;  } diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 31083d8286..74f87f6d40 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -51,6 +51,7 @@ class LLVertexBuffer;  class LLCubeMap;  class LLImageGL;  class LLRenderTarget; +class LLTexture ;  class LLTexUnit  { @@ -149,6 +150,7 @@ public:  	// Binds the LLImageGL to this texture unit   	// (automatically enables the unit for the LLImageGL's texture type)  	bool bind(LLImageGL* texture, bool forceBind = false); +	bool bind(LLTexture* texture, bool forceBind = false);  	// Binds a cubemap to this texture unit   	// (automatically enables the texture unit for cubemaps) diff --git a/indra/llrender/lltexture.cpp b/indra/llrender/lltexture.cpp new file mode 100644 index 0000000000..156ffb953c --- /dev/null +++ b/indra/llrender/lltexture.cpp @@ -0,0 +1,37 @@ +/**  + * @file lltexture.cpp + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + *  + * Copyright (c) 2000-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" +#include "lltexture.h" + +//virtual  +LLTexture::~LLTexture() +{ +} diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h new file mode 100644 index 0000000000..c18917b663 --- /dev/null +++ b/indra/llrender/lltexture.h @@ -0,0 +1,77 @@ +/**  + * @file lltexture.h + * @brief LLTexture definition + * + *	This class acts as a wrapper for OpenGL calls. + *	The goal of this class is to minimize the number of api calls due to legacy rendering + *	code, to define an interface for a multiple rendering API abstraction of the UI + *	rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + *  + * Copyright (c) 2001-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_TEXTURE_H +#define LL_TEXTURE_H + +#include "llrefcount.h" +class LLImageGL ; +class LLTexUnit ; +class LLFontGL ; + +// +//this is an abstract class as the parent for the class LLViewerTexture +//through the following virtual functions, the class LLViewerTexture can be reached from /llrender. +// +class LLTexture : public LLRefCount +{ +	friend class LLTexUnit ; +	friend class LLFontGL ; + +protected: +	virtual ~LLTexture(); + +public: +	LLTexture(){} + +	// +	//interfaces to access LLViewerTexture +	// +	virtual bool       bindDefaultImage(const S32 stage = 0) const = 0 ; +	virtual void       forceImmediateUpdate() = 0 ; +	virtual void       setActive() = 0 ; +	virtual S32	       getWidth(S32 discard_level = -1) const = 0 ; +	virtual S32	       getHeight(S32 discard_level = -1) const = 0 ; + +private: +	//note: do not make this function public. +	virtual LLImageGL* getGLTexture() const = 0 ; + +	virtual void updateBindStatsForTester() = 0 ; +}; +#endif + | 
