586 lines
19 KiB
C++
586 lines
19 KiB
C++
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||
//
|
||
// Purpose:
|
||
//
|
||
// $NoKeywords: $
|
||
//=============================================================================//
|
||
|
||
#if !defined( _GAMECONSOLE ) && defined( _WIN32 )
|
||
#define WIN32_LEAN_AND_MEAN
|
||
#include <windows.h>
|
||
#endif
|
||
|
||
#include "vgui_surfacelib/fonttexturecache.h"
|
||
#include "tier1/keyvalues.h"
|
||
#include "materialsystem/itexture.h"
|
||
#include "materialsystem/imaterial.h"
|
||
#include "tier1/utlbuffer.h"
|
||
#include "fmtstr.h"
|
||
#include "vgui_surfacelib/texturedictionary.h"
|
||
|
||
// memdbgon must be the last include file in a .cpp file!!!
|
||
#include "tier0/memdbgon.h"
|
||
|
||
|
||
#define TEXTURE_PAGE_WIDTH 256
|
||
#define TEXTURE_PAGE_HEIGHT 256
|
||
|
||
|
||
ConVar vgui_show_glyph_miss( "vgui_show_glyph_miss", "0", FCVAR_DEVELOPMENTONLY );
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Constructor
|
||
//-----------------------------------------------------------------------------
|
||
CFontTextureCache::CFontTextureCache() : m_CharCache( 0, 256, CacheEntryLessFunc )
|
||
{
|
||
V_memset( m_CommonCharCache, 0, sizeof( m_CommonCharCache ) );
|
||
Clear();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Destructor
|
||
//-----------------------------------------------------------------------------
|
||
CFontTextureCache::~CFontTextureCache()
|
||
{
|
||
Clear();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
//-----------------------------------------------------------------------------
|
||
void CFontTextureCache::SetPrefix( const char *pTexturePagePrefix )
|
||
{
|
||
m_TexturePagePrefix = pTexturePagePrefix;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Resets the cache
|
||
//-----------------------------------------------------------------------------
|
||
void CFontTextureCache::Clear()
|
||
{
|
||
// remove all existing data
|
||
m_CharCache.RemoveAll();
|
||
|
||
for ( int i = 0; i < m_PageList.Count(); ++i )
|
||
{
|
||
if ( m_PageList[i].pPackedFontTextureCache )
|
||
{
|
||
delete m_PageList[i].pPackedFontTextureCache;
|
||
}
|
||
}
|
||
m_PageList.RemoveAll();
|
||
|
||
m_CurrPage = -1;
|
||
|
||
m_FontPages.RemoveAll();
|
||
m_FontPages.SetLessFunc( DefLessFunc( FontHandle_t ) );
|
||
|
||
for ( int i = 0; i < ARRAYSIZE( m_CommonCharCache ); i++ )
|
||
{
|
||
delete m_CommonCharCache[i];
|
||
m_CommonCharCache[i] = 0;
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: comparison function for cache entries
|
||
//-----------------------------------------------------------------------------
|
||
bool CFontTextureCache::CacheEntryLessFunc( CacheEntry_t const &lhs, CacheEntry_t const &rhs )
|
||
{
|
||
uint64 lhsLookupID = ( ((uint64)lhs.font) << 32 ) | ((uint64)lhs.wch);
|
||
uint64 rhsLookupID = ( ((uint64)rhs.font) << 32 ) | ((uint64)rhs.wch);
|
||
|
||
return lhsLookupID < rhsLookupID;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: returns the texture info for the given char & font
|
||
//-----------------------------------------------------------------------------
|
||
bool CFontTextureCache::GetTextureForChar( FontHandle_t font, FontDrawType_t type, wchar_t wch, int *textureID, float **texCoords )
|
||
{
|
||
// Ask for just one character
|
||
return GetTextureForChars( font, type, &wch, textureID, texCoords, 1 );
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: returns the texture info for the given char & font
|
||
// This function copies in the texcoords out from the static into a preallocated passed in arg.
|
||
//-----------------------------------------------------------------------------
|
||
bool CFontTextureCache::GetTextureAndCoordsForChar( FontHandle_t font, FontDrawType_t type, wchar_t wch, int *textureID, float *texCoords )
|
||
{
|
||
// Ask for just one character
|
||
float *textureCoords = NULL;
|
||
bool bSuccess = GetTextureForChars( font, type, &wch, textureID, &textureCoords, 1 );
|
||
if ( textureCoords )
|
||
{
|
||
texCoords[0] = textureCoords[0];
|
||
texCoords[1] = textureCoords[1];
|
||
texCoords[2] = textureCoords[2];
|
||
texCoords[3] = textureCoords[3];
|
||
}
|
||
|
||
return bSuccess;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: returns the texture info for the given chars & font
|
||
//-----------------------------------------------------------------------------
|
||
bool CFontTextureCache::GetTextureForChars( FontHandle_t hFont, FontDrawType_t type, wchar_t *wch, int *textureID, float **texCoords, int numChars )
|
||
{
|
||
Assert( wch && textureID && texCoords );
|
||
Assert( numChars >= 1 );
|
||
|
||
if ( type == FONT_DRAW_DEFAULT )
|
||
{
|
||
type = FontManager().IsFontAdditive( hFont ) ? FONT_DRAW_ADDITIVE : FONT_DRAW_NONADDITIVE;
|
||
}
|
||
|
||
int typePage = (int)type - 1;
|
||
typePage = clamp( typePage, 0, (int)FONT_DRAW_TYPE_COUNT - 1 );
|
||
|
||
if ( FontManager().IsBitmapFont( hFont ) )
|
||
{
|
||
const int MAX_BITMAP_CHARS = 256;
|
||
if ( numChars > MAX_BITMAP_CHARS )
|
||
{
|
||
// Increase MAX_BITMAP_CHARS
|
||
Assert( 0 );
|
||
return false;
|
||
}
|
||
|
||
for ( int i = 0; i < numChars; i++ )
|
||
{
|
||
static float sTexCoords[ 4*MAX_BITMAP_CHARS ];
|
||
CBitmapFont *pWinFont;
|
||
float left, top, right, bottom;
|
||
int index;
|
||
Page_t *pPage;
|
||
|
||
pWinFont = reinterpret_cast< CBitmapFont* >( FontManager().GetFontForChar( hFont, wch[i] ) );
|
||
if ( !pWinFont )
|
||
{
|
||
// bad font handle
|
||
return false;
|
||
}
|
||
|
||
// get the texture coords
|
||
pWinFont->GetCharCoords( wch[i], &left, &top, &right, &bottom );
|
||
sTexCoords[i*4 + 0] = left;
|
||
sTexCoords[i*4 + 1] = top;
|
||
sTexCoords[i*4 + 2] = right;
|
||
sTexCoords[i*4 + 3] = bottom;
|
||
|
||
// find font handle in our list of ready pages
|
||
index = m_FontPages.Find( hFont );
|
||
if ( index == m_FontPages.InvalidIndex() )
|
||
{
|
||
// not found, create the texture id and its materials
|
||
index = m_FontPages.Insert( hFont );
|
||
pPage = &m_FontPages.Element( index );
|
||
|
||
for (int type = 0; type < FONT_DRAW_TYPE_COUNT; ++type )
|
||
{
|
||
pPage->textureID[type] = TextureDictionary()->CreateTexture( false );
|
||
}
|
||
CreateFontMaterials( *pPage, pWinFont->GetTexturePage(), true );
|
||
}
|
||
|
||
texCoords[i] = &(sTexCoords[ i*4 ]);
|
||
textureID[i] = m_FontPages.Element( index ).textureID[typePage];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
font_t *pWinFont = FontManager().GetFontForChar( hFont, wch[0] );
|
||
if ( !pWinFont )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
struct newPageEntry_t
|
||
{
|
||
int page; // The font page a new character will go in
|
||
int drawX; // X location within the font page
|
||
int drawY; // Y location within the font page
|
||
};
|
||
|
||
// Determine how many characters need to have their texture generated
|
||
newChar_t *newChars = (newChar_t *)stackalloc( numChars*sizeof( newChar_t ) );
|
||
newPageEntry_t *newEntries = (newPageEntry_t *)stackalloc( numChars*sizeof( newPageEntry_t ) );
|
||
int numNewChars = 0;
|
||
int maxNewCharTexels = 0;
|
||
int totalNewCharTexels = 0;
|
||
|
||
for ( int i = 0; i < numChars; i++ )
|
||
{
|
||
wchar_t wideChar = wch[i];
|
||
|
||
int *pCachePage;
|
||
float *pCacheCoords;
|
||
|
||
// profiling dicatated that avoiding the naive font/char RB lookup was beneficial
|
||
// instead waste a little memory to get all the western language chars to be direct
|
||
if ( IsGameConsole() && wideChar < MAX_COMMON_CHARS && hFont < ARRAYSIZE( m_CommonCharCache ) )
|
||
{
|
||
// dominant amount of simple chars are instant direct lookup
|
||
CommonChar_t *pCommonChars = m_CommonCharCache[hFont];
|
||
if ( !pCommonChars )
|
||
{
|
||
// missing
|
||
if ( pWinFont != FontManager().GetFontForChar( hFont, wideChar ) )
|
||
{
|
||
// all characters in string must come out of the same font
|
||
return false;
|
||
}
|
||
|
||
// init and insert
|
||
pCommonChars = new CommonChar_t;
|
||
memset( pCommonChars, 0, sizeof( CommonChar_t ) );
|
||
m_CommonCharCache[hFont] = pCommonChars;
|
||
}
|
||
pCachePage = &pCommonChars->details[wideChar].page;
|
||
pCacheCoords = pCommonChars->details[wideChar].texCoords;
|
||
}
|
||
else
|
||
{
|
||
// for console only, either more fonts than expected (> 256 fonts!) or not a simple integer
|
||
// want to keep this a direct lookup and not a search (which defeats the perf gain)
|
||
AssertMsgOnce( !IsGameConsole() || hFont < ARRAYSIZE( m_CommonCharCache ), "CFontTextureCache: Unexpected hFont out-of-range\n" );
|
||
|
||
// extended chars are a costlier lookup
|
||
// page and char form a unique key to find in cache
|
||
CacheEntry_t cacheItem;
|
||
cacheItem.font = hFont;
|
||
cacheItem.wch = wideChar;
|
||
HCacheEntry cacheHandle = m_CharCache.Find( cacheItem );
|
||
if ( !m_CharCache.IsValidIndex( cacheHandle ) )
|
||
{
|
||
// missing
|
||
if ( pWinFont != FontManager().GetFontForChar( hFont, wideChar ) )
|
||
{
|
||
// all characters in string must come out of the same font
|
||
return false;
|
||
}
|
||
|
||
// init and insert
|
||
cacheItem.texCoords[0] = 0;
|
||
cacheItem.texCoords[1] = 0;
|
||
cacheItem.texCoords[2] = 0;
|
||
cacheItem.texCoords[3] = 0;
|
||
cacheHandle = m_CharCache.Insert( cacheItem );
|
||
Assert( m_CharCache.IsValidIndex( cacheHandle ) );
|
||
}
|
||
pCachePage = &m_CharCache[cacheHandle].page;
|
||
pCacheCoords = m_CharCache[cacheHandle].texCoords;
|
||
}
|
||
|
||
if ( pCacheCoords[2] == 0 && pCacheCoords[3] == 0 )
|
||
{
|
||
// invalid page, setup for page allocation
|
||
// get the char details
|
||
int a, b, c;
|
||
pWinFont->GetCharABCWidths( wideChar, a, b, c );
|
||
int fontWide = MAX( b, 1 );
|
||
int fontTall = MAX( pWinFont->GetHeight(), 1 );
|
||
if ( pWinFont->GetUnderlined() )
|
||
{
|
||
fontWide += ( a + c );
|
||
}
|
||
|
||
// Get a texture to render into
|
||
int page, drawX, drawY, twide, ttall;
|
||
if ( !AllocatePageForChar( fontWide, fontTall, page, drawX, drawY, twide, ttall ) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// accumulate data to pass to GetCharsRGBA below
|
||
newEntries[numNewChars].page = page;
|
||
newEntries[numNewChars].drawX = drawX;
|
||
newEntries[numNewChars].drawY = drawY;
|
||
newChars[numNewChars].wch = wideChar;
|
||
newChars[numNewChars].fontWide = fontWide;
|
||
newChars[numNewChars].fontTall = fontTall;
|
||
newChars[numNewChars].offset = 4*totalNewCharTexels;
|
||
totalNewCharTexels += fontWide*fontTall;
|
||
maxNewCharTexels = MAX( maxNewCharTexels, fontWide*fontTall );
|
||
numNewChars++;
|
||
|
||
// the 0.5 texel offset is done in CMatSystemTexture::SetMaterial()
|
||
pCacheCoords[0] = (float)( (double)drawX / ((double)twide) );
|
||
pCacheCoords[1] = (float)( (double)drawY / ((double)ttall) );
|
||
pCacheCoords[2] = (float)( (double)(drawX + fontWide) / (double)twide );
|
||
pCacheCoords[3] = (float)( (double)(drawY + fontTall) / (double)ttall );
|
||
|
||
*pCachePage = page;
|
||
}
|
||
|
||
// give data to caller
|
||
textureID[i] = m_PageList[*pCachePage].textureID[typePage];
|
||
texCoords[i] = pCacheCoords;
|
||
}
|
||
|
||
// Generate texture data for all newly-encountered characters
|
||
if ( numNewChars > 0 )
|
||
{
|
||
if ( vgui_show_glyph_miss.GetBool() )
|
||
{
|
||
char *pMissString = (char *)stackalloc( numNewChars * sizeof( char ) );
|
||
char *pString = pMissString;
|
||
for ( int i = 0; i < numNewChars; i++ )
|
||
{
|
||
// build a string representative enough for debugging puproses
|
||
wchar_t wch = newChars[i].wch;
|
||
if ( V_isprint( wch ) )
|
||
{
|
||
*pString++ = (char)wch;
|
||
}
|
||
else
|
||
{
|
||
*pString++ = '?';
|
||
}
|
||
}
|
||
*pString = '\0';
|
||
|
||
const char *pMsg = CFmtStr( "Glyph Miss: FontHandle_t:0x%8.8x (%s), %s (0x%x)\n", (int)hFont, pWinFont->GetName(), pMissString, pMissString[0] );
|
||
if ( IsGameConsole() )
|
||
{
|
||
// valid on xbox, and really want this spew treated like console spew
|
||
Warning( "%s", pMsg );
|
||
}
|
||
else
|
||
{
|
||
// debugger output only, to prevent any reentrant glyph miss as a result of spewing
|
||
Plat_DebugString( pMsg );
|
||
}
|
||
}
|
||
|
||
if ( IsGameConsole() && numNewChars > 1 )
|
||
{
|
||
MEM_ALLOC_CREDIT();
|
||
|
||
// Use the 360 fast path that generates multiple characters at once
|
||
int newCharDataSize = totalNewCharTexels*4;
|
||
CUtlBuffer newCharData( 0, newCharDataSize, CUtlBuffer::READ_ONLY );
|
||
unsigned char *pRGBA = (unsigned char *)newCharData.Base();
|
||
#if defined( _X360 ) || defined( _PS3 )
|
||
pWinFont->GetCharsRGBA( newChars, numNewChars, pRGBA );
|
||
#endif
|
||
// Copy the data into our font pages
|
||
for ( int i = 0; i < numNewChars; i++ )
|
||
{
|
||
newChar_t &newChar = newChars[i];
|
||
newPageEntry_t &newEntry = newEntries[i];
|
||
|
||
// upload the new sub texture
|
||
// NOTE: both textureIDs reference the same ITexture, so we're ok
|
||
unsigned char *characterRGBA = pRGBA + newChar.offset;
|
||
TextureDictionary()->SetSubTextureRGBA( m_PageList[newEntry.page].textureID[typePage], newEntry.drawX, newEntry.drawY, characterRGBA, newChar.fontWide, newChar.fontTall );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// create a buffer for new characters to be rendered into
|
||
int nByteCount = maxNewCharTexels * 4;
|
||
unsigned char *pRGBA = (unsigned char *)stackalloc( nByteCount * sizeof( unsigned char ) );
|
||
|
||
// Generate characters individually
|
||
for ( int i = 0; i < numNewChars; i++ )
|
||
{
|
||
newChar_t &newChar = newChars[i];
|
||
newPageEntry_t &newEntry = newEntries[i];
|
||
|
||
// render the character into the buffer
|
||
Q_memset( pRGBA, 0, nByteCount );
|
||
pWinFont->GetCharRGBA( newChar.wch, newChar.fontWide, newChar.fontTall, pRGBA );
|
||
|
||
// Make the char white if we are in source 2
|
||
if ( !g_pMaterialSystem )
|
||
{
|
||
for ( int i = 0; i < nByteCount; i += 4 )
|
||
{
|
||
pRGBA[i+0] = pRGBA[i+1] = pRGBA[i+2] = 255;
|
||
}
|
||
}
|
||
|
||
// upload the new sub texture
|
||
// NOTE: both textureIDs reference the same ITexture, so we're ok
|
||
TextureDictionary()->SetSubTextureRGBA( m_PageList[newEntry.page].textureID[typePage], newEntry.drawX, newEntry.drawY, pRGBA, newChar.fontWide, newChar.fontTall );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Creates font materials
|
||
//-----------------------------------------------------------------------------
|
||
void CFontTextureCache::CreateFontMaterials( Page_t &page, ITexture *pFontTexture, bool bitmapFont )
|
||
{
|
||
// The normal material
|
||
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
|
||
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
|
||
pVMTKeyValues->SetInt( "$ignorez", 1 );
|
||
pVMTKeyValues->SetInt( "$no_fullbright", 1 );
|
||
pVMTKeyValues->SetInt( "$translucent", 1 );
|
||
pVMTKeyValues->SetString( "$basetexture", pFontTexture->GetName() );
|
||
CUtlString materialName = m_TexturePagePrefix + "__fontpage";
|
||
Assert( g_pMaterialSystem );
|
||
IMaterial *pMaterial = g_pMaterialSystem->CreateMaterial( materialName, pVMTKeyValues );
|
||
pMaterial->Refresh();
|
||
|
||
int typePageNonAdditive = (int)FONT_DRAW_NONADDITIVE-1;
|
||
TextureDictionary()->BindTextureToMaterial( page.textureID[typePageNonAdditive], pMaterial );
|
||
pMaterial->DecrementReferenceCount();
|
||
|
||
// The additive material
|
||
pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
|
||
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
|
||
pVMTKeyValues->SetInt( "$ignorez", 1 );
|
||
pVMTKeyValues->SetInt( "$no_fullbright", 1 );
|
||
pVMTKeyValues->SetInt( "$translucent", 1 );
|
||
pVMTKeyValues->SetInt( "$additive", 1 );
|
||
pVMTKeyValues->SetString( "$basetexture", pFontTexture->GetName() );
|
||
|
||
CUtlString addmaterialName = m_TexturePagePrefix + "__fontpage_additive";
|
||
pMaterial = g_pMaterialSystem->CreateMaterial( addmaterialName.String(), pVMTKeyValues );
|
||
pMaterial->Refresh();
|
||
|
||
int typePageAdditive = (int)FONT_DRAW_ADDITIVE-1;
|
||
if ( bitmapFont )
|
||
{
|
||
TextureDictionary()->BindTextureToMaterial( page.textureID[typePageAdditive], pMaterial );
|
||
}
|
||
else
|
||
{
|
||
TextureDictionary()->BindTextureToMaterialReference( page.textureID[typePageAdditive], page.textureID[typePageNonAdditive], pMaterial);
|
||
}
|
||
pMaterial->DecrementReferenceCount();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: allocates a new page for a given character
|
||
//-----------------------------------------------------------------------------
|
||
bool CFontTextureCache::AllocatePageForChar( int charWide, int charTall, int &pageIndex, int &drawX, int &drawY, int &twide, int &ttall )
|
||
{
|
||
// Catch the case where the glyph is too tall for the page
|
||
if ( charTall > TEXTURE_PAGE_HEIGHT )
|
||
return false;
|
||
|
||
// See if there is room in the last page for this character
|
||
pageIndex = m_CurrPage;
|
||
|
||
bool bNeedsNewPage = true;
|
||
int nodeIndex = -1;
|
||
Rect_t glpyhRect;
|
||
glpyhRect.x = 0;
|
||
glpyhRect.y = 0;
|
||
glpyhRect.width = charWide;
|
||
glpyhRect.height = charTall;
|
||
|
||
if ( pageIndex > -1 )
|
||
{
|
||
// Let's use r/b tree to find a good spot.
|
||
nodeIndex = m_PageList[pageIndex].pPackedFontTextureCache->InsertRect( glpyhRect );
|
||
bNeedsNewPage = ( nodeIndex == -1 );
|
||
}
|
||
|
||
if ( bNeedsNewPage )
|
||
{
|
||
// allocate a new page
|
||
pageIndex = m_PageList.AddToTail();
|
||
Page_t &newPage = m_PageList[pageIndex];
|
||
m_CurrPage = pageIndex;
|
||
|
||
for (int i = 0; i < FONT_DRAW_TYPE_COUNT; ++i )
|
||
{
|
||
newPage.textureID[i] = TextureDictionary()->CreateTexture( true );
|
||
}
|
||
newPage.pPackedFontTextureCache = new CTexturePacker( TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_HEIGHT, ( IsGameConsole() ? 0 : 1 ) );
|
||
|
||
nodeIndex = newPage.pPackedFontTextureCache->InsertRect( glpyhRect );
|
||
Assert( nodeIndex != -1 );
|
||
|
||
|
||
static int nFontPageId = 0;
|
||
char pTextureName[64];
|
||
Q_snprintf( pTextureName, 64, "%s__font_page_%d", m_TexturePagePrefix.String(), nFontPageId );
|
||
++nFontPageId;
|
||
|
||
MEM_ALLOC_CREDIT();
|
||
if ( g_pMaterialSystem )
|
||
{
|
||
ITexture *pTexture = AllocateNewPage( pTextureName );
|
||
CreateFontMaterials( newPage, pTexture );
|
||
pTexture->DecrementReferenceCount();
|
||
}
|
||
|
||
if ( IsPC() || !IsDebug() )
|
||
{
|
||
// clear the texture from the inital checkerboard to black
|
||
// allocate for 32bpp format
|
||
int nByteCount = TEXTURE_PAGE_WIDTH * TEXTURE_PAGE_HEIGHT * 4;
|
||
CUtlMemory<unsigned char> mRGBA;
|
||
mRGBA.EnsureCapacity( nByteCount );
|
||
|
||
//Q_memset( mRGBA.Base(), 0, nByteCount );
|
||
|
||
// Clear to white, full alpha.
|
||
for ( int i = 0; i < nByteCount; i += 4 )
|
||
{
|
||
mRGBA[i+0] = mRGBA[i+1] = mRGBA[i+2] = 255;
|
||
mRGBA[i+3] = 0;
|
||
}
|
||
|
||
int typePageNonAdditive = (int)(FONT_DRAW_NONADDITIVE)-1;
|
||
TextureDictionary()->SetTextureRGBAEx( newPage.textureID[typePageNonAdditive], ( const char* )mRGBA.Base(),
|
||
TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_HEIGHT, IMAGE_FORMAT_RGBA8888, k_ETextureScalingPointSample );
|
||
|
||
|
||
// Note, in rendersystem2 we do not have materials, as we actually have 2 diff textures.
|
||
if ( !g_pMaterialSystem )
|
||
{
|
||
int typePageAdditive = (int)(FONT_DRAW_ADDITIVE)-1;
|
||
newPage.textureID[typePageAdditive] = newPage.textureID[typePageNonAdditive];
|
||
}
|
||
}
|
||
}
|
||
|
||
// output the position
|
||
Page_t &page = m_PageList[ pageIndex ];
|
||
Assert( nodeIndex != -1 );
|
||
const CTexturePacker::TreeEntry_t &newEntry = page.pPackedFontTextureCache->GetEntry( nodeIndex );
|
||
drawX = newEntry.rc.x;
|
||
drawY = newEntry.rc.y;
|
||
twide = TEXTURE_PAGE_WIDTH;
|
||
ttall = TEXTURE_PAGE_HEIGHT;
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: allocates a new page
|
||
//-----------------------------------------------------------------------------
|
||
ITexture *CFontTextureCache::AllocateNewPage( char *pTextureName )
|
||
{
|
||
Assert( g_pMaterialSystem );
|
||
ITexture *pTexture = g_pMaterialSystem->CreateProceduralTexture(
|
||
pTextureName,
|
||
TEXTURE_GROUP_VGUI,
|
||
TEXTURE_PAGE_WIDTH,
|
||
TEXTURE_PAGE_HEIGHT,
|
||
IMAGE_FORMAT_RGBA8888,
|
||
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT |
|
||
TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
|
||
|
||
return pTexture;
|
||
}
|
||
|