Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

847 lines
25 KiB

//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include <locale.h>
#include "vgui_surfacelib/BitmapFont.h"
#include "vgui_surfacelib/fontmanager.h"
#include "convar.h"
#include <vgui/ISurface.h>
#include <tier0/dbg.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
static CFontManager s_FontManager;
#ifdef WIN32
extern bool s_bSupportsUnicode;
#endif
#if !defined( _X360 )
#define MAX_INITIAL_FONTS 100
#else
#define MAX_INITIAL_FONTS 1
#endif
//-----------------------------------------------------------------------------
// Purpose: singleton accessor
//-----------------------------------------------------------------------------
CFontManager &FontManager()
{
return s_FontManager;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CFontManager::CFontManager()
{
// add a single empty font, to act as an invalid font handle 0
m_FontAmalgams.EnsureCapacity( MAX_INITIAL_FONTS );
m_FontAmalgams.AddToTail();
m_Win32Fonts.EnsureCapacity( MAX_INITIAL_FONTS );
#ifdef LINUX
FT_Error error = FT_Init_FreeType( &library );
if ( error )
Error( "Unable to initalize freetype library, is it installed?" );
pFontDataHelper = NULL;
#endif
// setup our text locale
setlocale( LC_CTYPE, "" );
setlocale( LC_TIME, "" );
setlocale( LC_COLLATE, "" );
setlocale( LC_MONETARY, "" );
m_pFileSystem = NULL;
m_pMaterialSystem = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: language setting for font fallbacks
//-----------------------------------------------------------------------------
void CFontManager::SetLanguage(const char *language)
{
Q_strncpy(m_szLanguage, language, sizeof(m_szLanguage));
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
const char *CFontManager::GetLanguage()
{
return m_szLanguage;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CFontManager::~CFontManager()
{
ClearAllFonts();
#ifdef LINUX
FT_Done_FreeType( library );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: frees the fonts
//-----------------------------------------------------------------------------
void CFontManager::ClearAllFonts()
{
// free the fonts
for (int i = 0; i < m_Win32Fonts.Count(); i++)
{
delete m_Win32Fonts[i];
}
m_Win32Fonts.RemoveAll();
m_FontAmalgams.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
vgui::HFont CFontManager::CreateFont()
{
int i = m_FontAmalgams.AddToTail();
return i;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the valid glyph ranges for a font created by CreateFont()
//-----------------------------------------------------------------------------
bool CFontManager::SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags)
{
return SetFontGlyphSet( font, windowsFontName, tall, weight, blur, scanlines, flags, 0, 0);
}
//-----------------------------------------------------------------------------
// Purpose: Sets the valid glyph ranges for a font created by CreateFont()
//-----------------------------------------------------------------------------
bool CFontManager::SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin, int nRangeMax)
{
// ignore all but the first font added
// need to rev vgui versions and change the name of this function
if ( m_FontAmalgams[font].GetCount() > 0 )
{
// clear any existing fonts
m_FontAmalgams[font].RemoveAll();
}
bool bForceSingleFont = false;
if ( IsX360() )
{
//-----//
// 360 //
//-----//
// AV - The 360 must use the same size font for 0-255 and 256-0xFFFF regardless of the font since the
// fontAmalgam can only deal with a consistent font height for all fonts in a single amalgam. We
// could change this if we forced all fonts within a single amalgam to have the same height with
// the font baselines aligned, but even then the fonts wouldn't look great, because different
// fonts set to the same size don't necessarily have the same height visually. We need to revisit
// this before shipping l4d2 on the PC!
bForceSingleFont = true;
// discovered xbox only allows glyphs from these languages from the foreign fallback font
// prefer to have the entire range of chars from the font so UI doesn't suffer from glyph disparity
if ( !V_stricmp( windowsFontName, "toolbox" ) || !V_stricmp( windowsFontName, "courier new" ) )
{
// toolbox stays as-is
// courier new is an internal debug font, not part of customer UI, need it stay as is
}
else
{
bool bUseFallback = false;
if ( !V_stricmp( m_szLanguage, "portuguese" ) ||
!V_stricmp( m_szLanguage, "polish" ) )
{
static ConVarRef mat_xbox_iswidescreen( "mat_xbox_iswidescreen" );
static ConVarRef mat_xbox_ishidef( "mat_xbox_ishidef" );
// we can support these languages with our desired fonts in hidef/widescreen modes only
// we must fallback to the more legible font in the lowdef or non-widescreen
bUseFallback = !( mat_xbox_iswidescreen.GetBool() && mat_xbox_ishidef.GetBool() );
}
if ( bUseFallback ||
!V_stricmp( m_szLanguage, "japanese" ) ||
!V_stricmp( m_szLanguage, "korean" ) ||
!V_stricmp( m_szLanguage, "schinese" ) ||
!V_stricmp( m_szLanguage, "tchinese" ) ||
!V_stricmp( m_szLanguage, "russian" ) )
{
// these languages must use the font that has their glyphs
// these language require a high degree of legibility
windowsFontName = GetForeignFallbackFontName();
}
}
}
else
{
//----//
// PC //
//----//
// AV - The PC has the same issues caused by multiple fonts in a single amalgam with different font
// heights...see comment above. Given the available languages in Steam, the languages below
// were illegible at 1024x768. Resolutions of 800x600 and 640x480 are a complete mess for all
// languages, including English. We probably need to fallback to Tahoma for all languages when
// the vertical resolution < 720. This will probably be the next check-in, but we need to evaluate
// this further tomorrow.
if ( !V_stricmp( windowsFontName, "toolbox" ) || !V_stricmp( windowsFontName, "courier new" ) )
{
// toolbox stays as-is
// courier new is an internal debug font, not part of customer UI, need it stay as is
}
else
{
// These languages are illegible @ vertical resolutions <= 768
if ( !V_stricmp( m_szLanguage, "korean" ) ||
!V_stricmp( m_szLanguage, "schinese" ) ||
!V_stricmp( m_szLanguage, "tchinese" ) ||
!V_stricmp( m_szLanguage, "russian" ) ||
!V_stricmp( m_szLanguage, "thai" ) ||
!V_stricmp( m_szLanguage, "japanese" ) ||
!V_stricmp( m_szLanguage, "czech" ) )
{
windowsFontName = GetForeignFallbackFontName();
bForceSingleFont = true;
}
}
}
// AV - If we actually want to support multiple fonts within an amalgam, we need a change here. Currently,
// the code will use winFont for 0-255 and pExtendedFont for 256-0xFFFF! But since the functions for
// getting the font height from the amalgam can only return one height, the heights of the two fonts
// need to be identical. This isn't trivial because even if we query both fonts for their height
// first, that won't force their baselines within the font pages to be aligned. So we would have to
// do something much more complicated where we loop over all characters in each font to find the
// absolute ascent and descent above/below the baseline and then when we create the font, align both
// fonts to the shared baseline with a shared height. But even with the font baselines aligned with a
// shared height, the fonts still wouldn't look great, because different fonts set to the same size
// don't necessarily have the same height visually. We need to revisit this before shipping l4d2 on the PC!
// And there are still issues with what I'm suggesting here because when we ask the font API what
// the maxHeight, maxAscent, maxDescent is, we get inconsistent results, so I'm not even sure we could
// successfully align the baseline of two fonts in the font pages.
font_t *winFont = CreateOrFindWin32Font( windowsFontName, tall, weight, blur, scanlines, flags );
// cycle until valid english/extended font support has been created
do
{
// add to the amalgam
if ( bForceSingleFont || IsFontForeignLanguageCapable( windowsFontName ) )
{
if ( winFont )
{
// font supports the full range of characters
m_FontAmalgams[font].AddFont( winFont, 0x0000, 0xFFFF );
return true;
}
}
else
{
// font cannot provide glyphs and just supports the normal range
// redirect to a font that can supply glyps
const char *localizedFontName = GetForeignFallbackFontName();
if ( winFont && !stricmp( localizedFontName, windowsFontName ) )
{
// it's the same font and can support the full range
m_FontAmalgams[font].AddFont( winFont, 0x0000, 0xFFFF );
return true;
}
// create the extended support font
font_t *pExtendedFont = CreateOrFindWin32Font( localizedFontName, tall, weight, blur, scanlines, flags );
if ( winFont && pExtendedFont )
{
// use the normal font for english characters, and the extended font for the rest
int nMin = 0x0000, nMax = 0x00FF;
// did we specify a range?
if ( nRangeMin > 0 || nRangeMax > 0 )
{
nMin = nRangeMin;
nMax = nRangeMax;
// make sure they're in the correct order
if ( nMin > nMax )
{
int nTemp = nMin;
nMin = nMax;
nMax = nTemp;
}
}
if ( nMin > 0 )
{
m_FontAmalgams[font].AddFont( pExtendedFont, 0x0000, nMin - 1 );
}
m_FontAmalgams[font].AddFont( winFont, nMin, nMax );
if ( nMax < 0xFFFF )
{
m_FontAmalgams[font].AddFont( pExtendedFont, nMax + 1, 0xFFFF );
}
return true;
}
else if ( pExtendedFont )
{
// the normal font failed to create
// just use the extended font for the full range
m_FontAmalgams[font].AddFont( pExtendedFont, 0x0000, 0xFFFF );
return true;
}
}
// no valid font has been created, so fallback to a different font and try again
}
while ( NULL != ( windowsFontName = GetFallbackFontName( windowsFontName ) ) );
// nothing successfully created
return false;
}
//-----------------------------------------------------------------------------
// Purpose: adds glyphs to a font created by CreateFont()
//-----------------------------------------------------------------------------
bool CFontManager::SetBitmapFontGlyphSet(HFont font, const char *windowsFontName, float scalex, float scaley, int flags)
{
if ( m_FontAmalgams[font].GetCount() > 0 )
{
// clear any existing fonts
m_FontAmalgams[font].RemoveAll();
}
CBitmapFont *winFont = CreateOrFindBitmapFont( windowsFontName, scalex, scaley, flags );
if ( winFont )
{
// bitmap fonts are only 0-255
m_FontAmalgams[font].AddFont( winFont, 0x0000, 0x00FF );
return true;
}
// nothing successfully created
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Creates a new win32 font, or reuses one if possible
//-----------------------------------------------------------------------------
font_t *CFontManager::CreateOrFindWin32Font(const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags)
{
// see if we already have the win32 font
font_t *winFont = NULL;
int i;
for (i = 0; i < m_Win32Fonts.Count(); i++)
{
if (m_Win32Fonts[i]->IsEqualTo(windowsFontName, tall, weight, blur, scanlines, flags))
{
winFont = m_Win32Fonts[i];
break;
}
}
// create the new win32font if we didn't find it
if (!winFont)
{
MEM_ALLOC_CREDIT();
i = m_Win32Fonts.AddToTail();
#ifdef LINUX
int memSize = 0;
void *pchFontData = pFontDataHelper( windowsFontName, memSize );
if ( pchFontData )
{
m_Win32Fonts[i] = new font_t();
if (m_Win32Fonts[i]->CreateFromMemory( windowsFontName, pchFontData, memSize, tall, weight, blur, scanlines, flags))
{
// add to the list
winFont = m_Win32Fonts[i];
}
else
{
// failed to create, remove
delete m_Win32Fonts[i];
m_Win32Fonts.Remove(i);
return NULL;
}
}
else
{
#endif
m_Win32Fonts[i] = new font_t();
if (m_Win32Fonts[i]->Create(windowsFontName, tall, weight, blur, scanlines, flags))
{
// add to the list
winFont = m_Win32Fonts[i];
}
else
{
// failed to create, remove
delete m_Win32Fonts[i];
m_Win32Fonts.Remove(i);
return NULL;
}
#ifdef LINUX
}
#endif
}
return winFont;
}
//-----------------------------------------------------------------------------
// Purpose: Creates a new win32 font, or reuses one if possible
//-----------------------------------------------------------------------------
CBitmapFont *CFontManager::CreateOrFindBitmapFont(const char *windowsFontName, float scalex, float scaley, int flags)
{
// see if we already have the font
CBitmapFont *winFont = NULL;
int i;
for ( i = 0; i < m_Win32Fonts.Count(); i++ )
{
font_t *font = m_Win32Fonts[i];
// Only looking for bitmap fonts
int testflags = font->GetFlags();
if ( !( testflags & FONTFLAG_BITMAP ) )
{
continue;
}
CBitmapFont *bitmapFont = reinterpret_cast< CBitmapFont* >( font );
if ( bitmapFont->IsEqualTo( windowsFontName, scalex, scaley, flags ) )
{
winFont = bitmapFont;
break;
}
}
// create the font if we didn't find it
if ( !winFont )
{
MEM_ALLOC_CREDIT();
i = m_Win32Fonts.AddToTail();
CBitmapFont *bitmapFont = new CBitmapFont();
if ( bitmapFont->Create( windowsFontName, scalex, scaley, flags ) )
{
// add to the list
m_Win32Fonts[i] = bitmapFont;
winFont = bitmapFont;
}
else
{
// failed to create, remove
delete bitmapFont;
m_Win32Fonts.Remove(i);
return NULL;
}
}
return winFont;
}
//-----------------------------------------------------------------------------
// Purpose: sets the scale of a bitmap font
//-----------------------------------------------------------------------------
void CFontManager::SetFontScale(vgui::HFont font, float sx, float sy)
{
m_FontAmalgams[font].SetFontScale( sx, sy );
}
const char *CFontManager::GetFontName( HFont font )
{
// ignore the amalgam of disparate char ranges, assume the first font
return m_FontAmalgams[font].GetFontName( 0 );
}
//-----------------------------------------------------------------------------
// Purpose: gets the windows font for the particular font in the amalgam
//-----------------------------------------------------------------------------
font_t *CFontManager::GetFontForChar( vgui::HFont font, wchar_t wch )
{
return m_FontAmalgams[font].GetFontForChar(wch);
}
//-----------------------------------------------------------------------------
// Purpose: returns the abc widths of a single character
//-----------------------------------------------------------------------------
void CFontManager::GetCharABCwide(HFont font, int ch, int &a, int &b, int &c)
{
font_t *winFont = m_FontAmalgams[font].GetFontForChar(ch);
if (winFont)
{
winFont->GetCharABCWidths(ch, a, b, c);
}
else
{
// no font for this range, just use the default width
a = c = 0;
b = m_FontAmalgams[font].GetFontMaxWidth();
}
}
//-----------------------------------------------------------------------------
// Purpose: returns the max height of a font
//-----------------------------------------------------------------------------
int CFontManager::GetFontTall(HFont font)
{
return m_FontAmalgams[font].GetFontHeight();
}
//-----------------------------------------------------------------------------
// Purpose: returns the ascent of a font
//-----------------------------------------------------------------------------
int CFontManager::GetFontAscent(HFont font, wchar_t wch)
{
font_t *winFont = m_FontAmalgams[font].GetFontForChar(wch);
if ( winFont )
{
return winFont->GetAscent();
}
else
{
return 0;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CFontManager::IsFontAdditive(HFont font)
{
return ( m_FontAmalgams[font].GetFlags( 0 ) & FONTFLAG_ADDITIVE ) ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CFontManager::IsBitmapFont(HFont font)
{
// A FontAmalgam is either some number of non-bitmap fonts, or a single bitmap font - so this check is valid
return ( m_FontAmalgams[font].GetFlags( 0 ) & FONTFLAG_BITMAP ) ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose: returns the pixel width of a single character
//-----------------------------------------------------------------------------
int CFontManager::GetCharacterWidth(HFont font, int ch)
{
if ( !iswcntrl( ch ) )
{
int a, b, c;
GetCharABCwide(font, ch, a, b, c);
return (a + b + c);
}
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: returns the area of a text string, including newlines
//-----------------------------------------------------------------------------
void CFontManager::GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall)
{
wide = 0;
tall = 0;
if (!text)
return;
// AV - Calling GetFontTall() for an amalgam with multiple fonts will return
// the font height of the first font only! We should be doing something like:
//
// tall = FontManager().GetFontForChar( font, text[0] )->GetHeight();
//
// but that's a little hacky since we're only looking at the first character!
// Same goes for the calls to GetFontTall() in the for loop below
tall = GetFontTall(font);
float xx = 0;
char chBefore = 0;
char chAfter = 0;
for (int i = 0; ; i++)
{
wchar_t ch = text[i];
if (ch == 0)
{
break;
}
chAfter = text[i+1];
if (ch == '\n')
{
// AV - See note above about calling this instead: tall += FontManager().GetFontForChar( font, text[0] )->GetHeight();
tall += GetFontTall(font);
xx=0;
}
else if (ch == '&')
{
// underscore character, so skip
}
else
{
float flWide, flabcA, flabcC;
GetKernedCharWidth( font, ch, chBefore, chAfter, flWide, flabcA, flabcC );
xx += flWide;
if (xx > wide)
{
wide = ceil(xx);
}
}
chBefore = ch;
}
}
// font validation functions
struct FallbackFont_t
{
const char *font;
const char *fallbackFont;
};
const char *g_szValidAsianFonts[] = {
#ifdef WIN32
"Marlett",
#else
"Helvetica",
#endif
NULL };
// list of how fonts fallback
FallbackFont_t g_FallbackFonts[] =
{
{ "Times New Roman", "Courier New" },
{ "Courier New", "Courier" },
{ "Verdana", "Arial" },
{ "Trebuchet MS", "Arial" },
#ifdef WIN32
{ "Tahoma", NULL },
{ NULL, "Tahoma" }, // every other font falls back to this
#else
{ "Tahoma", "Helvetica" },
{ "Helvetica", NULL },
{ NULL, "Helvetica" } // every other font falls back to this
#endif
};
//-----------------------------------------------------------------------------
// Purpose: returns true if the font is in the list of OK asian fonts
//-----------------------------------------------------------------------------
bool CFontManager::IsFontForeignLanguageCapable(const char *windowsFontName)
{
if ( IsX360() )
{
return false;
}
for (int i = 0; g_szValidAsianFonts[i] != NULL; i++)
{
if (!stricmp(g_szValidAsianFonts[i], windowsFontName))
return true;
}
// typeface isn't supported by asian languages
return false;
}
//-----------------------------------------------------------------------------
// Purpose: fallback fonts
//-----------------------------------------------------------------------------
const char *CFontManager::GetFallbackFontName(const char *windowsFontName)
{
int i;
for ( i = 0; g_FallbackFonts[i].font != NULL; i++ )
{
if (!stricmp(g_FallbackFonts[i].font, windowsFontName))
return g_FallbackFonts[i].fallbackFont;
}
// the ultimate fallback
return g_FallbackFonts[i].fallbackFont;
}
struct Win98ForeignFallbackFont_t
{
const char *language;
const char *fallbackFont;
};
// list of how fonts fallback
Win98ForeignFallbackFont_t g_Win98ForeignFallbackFonts[] =
{
{ "russian", "system" },
{ "japanese", "win98japanese" },
{ "thai", "system" },
#ifdef WIN32
{ NULL, "Tahoma" }, // every other font falls back to this
#else
{ NULL, "Helvetica" }, // every other font falls back to this
#endif
};
//-----------------------------------------------------------------------------
// Purpose: specialized fonts
//-----------------------------------------------------------------------------
const char *CFontManager::GetForeignFallbackFontName()
{
#ifdef WIN32
if ( s_bSupportsUnicode )
{
if ( IsX360() )
{
return "arial unicode ms";
}
// tahoma has all the necessary characters for asian/russian languages for winXP/2K+
return "Tahoma";
}
#endif
int i;
for (i = 0; g_Win98ForeignFallbackFonts[i].language != NULL; i++)
{
if (!stricmp(g_Win98ForeignFallbackFonts[i].language, m_szLanguage))
return g_Win98ForeignFallbackFonts[i].fallbackFont;
}
// the ultimate fallback
return g_Win98ForeignFallbackFonts[i].fallbackFont;
}
#if defined( _X360 )
bool CFontManager::GetCachedXUIMetrics( const char *pFontName, int tall, int style, XUIFontMetrics *pFontMetrics, XUICharMetrics charMetrics[256] )
{
// linear lookup is good enough
CUtlSymbol fontSymbol = pFontName;
bool bFound = false;
int i;
for ( i = 0; i < m_XUIMetricCache.Count(); i++ )
{
if ( m_XUIMetricCache[i].fontSymbol == fontSymbol && m_XUIMetricCache[i].tall == tall && m_XUIMetricCache[i].style == style )
{
bFound = true;
break;
}
}
if ( !bFound )
{
return false;
}
// get from the cache
*pFontMetrics = m_XUIMetricCache[i].fontMetrics;
V_memcpy( charMetrics, m_XUIMetricCache[i].charMetrics, 256 * sizeof( XUICharMetrics ) );
return true;
}
#endif
#if defined( _X360 )
void CFontManager::SetCachedXUIMetrics( const char *pFontName, int tall, int style, XUIFontMetrics *pFontMetrics, XUICharMetrics charMetrics[256] )
{
MEM_ALLOC_CREDIT();
int i = m_XUIMetricCache.AddToTail();
m_XUIMetricCache[i].fontSymbol = pFontName;
m_XUIMetricCache[i].tall = tall;
m_XUIMetricCache[i].style = style;
m_XUIMetricCache[i].fontMetrics = *pFontMetrics;
V_memcpy( m_XUIMetricCache[i].charMetrics, charMetrics, 256 * sizeof( XUICharMetrics ) );
}
#endif
void CFontManager::ClearTemporaryFontCache()
{
#if defined( _X360 )
COM_TimestampedLog( "ClearTemporaryFontCache(): Start" );
m_XUIMetricCache.Purge();
// many fonts are blindly precached by vgui and never used
// font will re-open if glyph is actually requested
for ( int i = 0; i < m_Win32Fonts.Count(); i++ )
{
m_Win32Fonts[i]->CloseResource();
}
COM_TimestampedLog( "ClearTemporaryFontCache(): Finish" );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: returns the max height of a font
//-----------------------------------------------------------------------------
bool CFontManager::GetFontUnderlined( HFont font )
{
return m_FontAmalgams[font].GetUnderlined();
}
void CFontManager::GetKernedCharWidth( vgui::HFont font, wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &flabcA, float &flabcC )
{
wide = 0.0f;
flabcA = 0.0f;
Assert( font != vgui::INVALID_FONT );
if ( font == vgui::INVALID_FONT )
return;
font_t *pFont = m_FontAmalgams[font].GetFontForChar(ch);
if ( !pFont )
{
// no font for this range, just use the default width
flabcA = 0.0f;
wide = m_FontAmalgams[font].GetFontMaxWidth();
return;
}
if ( m_FontAmalgams[font].GetFontForChar( chBefore ) != pFont )
chBefore = 0;
if ( m_FontAmalgams[font].GetFontForChar( chAfter ) != pFont )
chAfter = 0;
pFont->GetKernedCharWidth( ch, chBefore, chAfter, wide, flabcA, flabcC );
}
#ifdef DBGFLAG_VALIDATE
//-----------------------------------------------------------------------------
// Purpose: Ensure that all of our internal structures are consistent, and
// account for all memory that we've allocated.
// Input: validator - Our global validator object
// pchName - Our name (typically a member var in our container)
//-----------------------------------------------------------------------------
void CFontManager::Validate( CValidator &validator, char *pchName )
{
validator.Push( "CFontManager", this, pchName );
ValidateObj( m_FontAmalgams );
for ( int iFont = 0; iFont < m_FontAmalgams.Count(); iFont++ )
{
ValidateObj( m_FontAmalgams[iFont] );
}
ValidateObj( m_Win32Fonts );
for ( int iWin32Font = 0; iWin32Font < m_Win32Fonts.Count(); iWin32Font++ )
{
ValidatePtr( m_Win32Fonts[ iWin32Font ] );
}
validator.Pop();
}
#endif // DBGFLAG_VALIDATE