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.

624 lines
19 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "vgui_surfacelib/linuxfont.h"
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #include <malloc.h>
  13. #include <tier0/dbg.h>
  14. #include <vgui/ISurface.h>
  15. #include <utlbuffer.h>
  16. #include <fontconfig/fontconfig.h>
  17. #include "materialsystem/imaterialsystem.h"
  18. #include "vgui_surfacelib/fontmanager.h"
  19. #include "FontEffects.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. namespace {
  23. //Due to different font rendering approaches on different platforms, we have
  24. //to apply custom tweaks to fonts on Linux to make them render as desired.
  25. struct MetricsTweaks_t
  26. {
  27. const char *m_windowsFontName;
  28. int m_tallAdjust;
  29. };
  30. MetricsTweaks_t GetFontMetricsTweaks(const char* windowsFontName)
  31. {
  32. static const MetricsTweaks_t FontMetricTweaks[] =
  33. {
  34. { "Stubble bold", -5 },
  35. };
  36. for( int i = 0; i != Q_ARRAYSIZE( FontMetricTweaks ); ++i )
  37. {
  38. if ( !Q_stricmp( windowsFontName, FontMetricTweaks[i].m_windowsFontName ) )
  39. {
  40. return FontMetricTweaks[i];
  41. }
  42. }
  43. static const MetricsTweaks_t DefaultMetricTweaks = { NULL, 0 };
  44. return DefaultMetricTweaks;
  45. }
  46. // Freetype uses a lot of fixed float values that are 26.6 splits of a 32 bit word.
  47. // to make it an int, shift down the 6 bits and round up if the high bit of the 6
  48. // bits was set.
  49. inline int32_t FIXED6_2INT(int32_t x) { return ( (x>>6) + ( (x&0x20) ? (x<0 ? -1 : 1) : 0) ); }
  50. inline float FIXED6_2FLOAT(int32_t x) { return (float)x / 64.0f; }
  51. inline int32_t INT_2FIXED6(int32_t x) { return x << 6; }
  52. }
  53. bool CLinuxFont::ms_bSetFriendlyNameCacheLessFunc = false;
  54. CUtlRBTree< CLinuxFont::font_name_entry > CLinuxFont::m_FriendlyNameCache;
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Constructor
  57. //-----------------------------------------------------------------------------
  58. CLinuxFont::CLinuxFont() : m_ExtendedABCWidthsCache(256, 0, &ExtendedABCWidthsCacheLessFunc),
  59. m_ExtendedKernedABCWidthsCache( 256, 0, &ExtendedKernedABCWidthsCacheLessFunc )
  60. {
  61. m_iTall = 0;
  62. m_iWeight = 0;
  63. m_iFlags = 0;
  64. m_iMaxCharWidth = 0;
  65. m_bAntiAliased = false;
  66. m_bUnderlined = false;
  67. m_iBlur = 0;
  68. m_pGaussianDistribution = NULL;
  69. m_iScanLines = 0;
  70. m_bRotary = false;
  71. m_bAdditive = false;
  72. if ( !ms_bSetFriendlyNameCacheLessFunc )
  73. {
  74. ms_bSetFriendlyNameCacheLessFunc = true;
  75. SetDefLessFunc( m_FriendlyNameCache );
  76. }
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Destructor
  80. //-----------------------------------------------------------------------------
  81. CLinuxFont::~CLinuxFont()
  82. {
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose: build a map of friendly (char *) name to crazy ATSU bytestream, so we can ask for "Tahoma" and actually load it
  86. //-----------------------------------------------------------------------------
  87. void CLinuxFont::CreateFontList()
  88. {
  89. if ( m_FriendlyNameCache.Count() > 0 )
  90. return;
  91. if(!FcInit())
  92. return;
  93. FcConfig *config;
  94. FcPattern *pat;
  95. FcObjectSet *os;
  96. FcFontSet *fontset;
  97. int i;
  98. char *file;
  99. const char *name;
  100. config = FcConfigGetCurrent();
  101. FcConfigAppFontAddDir(config, "platform/vgui/fonts");
  102. pat = FcPatternCreate();
  103. os = FcObjectSetCreate();
  104. FcObjectSetAdd(os, FC_FILE);
  105. FcObjectSetAdd(os, FC_FULLNAME);
  106. FcObjectSetAdd(os, FC_FAMILY);
  107. FcObjectSetAdd(os, FC_SCALABLE);
  108. fontset = FcFontList(config, pat, os);
  109. if(!fontset)
  110. return;
  111. for(i = 0; i < fontset->nfont; i++)
  112. {
  113. FcBool scalable;
  114. if ( FcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable) == FcResultMatch && !scalable )
  115. continue;
  116. if ( FcPatternGetString(fontset->fonts[i], FC_FAMILY, 0, (FcChar8**)&name) != FcResultMatch )
  117. continue;
  118. if ( FcPatternGetString(fontset->fonts[i], FC_FILE, 0, (FcChar8**)&file) != FcResultMatch )
  119. continue;
  120. font_name_entry entry;
  121. entry.m_pchFile = (char *)malloc( Q_strlen(file) + 1 );
  122. entry.m_pchFriendlyName = (char *)malloc( Q_strlen(name) +1);
  123. Q_memcpy( entry.m_pchFile, file, Q_strlen(file) + 1 );
  124. Q_memcpy( entry.m_pchFriendlyName, name, Q_strlen(name) +1);
  125. m_FriendlyNameCache.Insert( entry );
  126. // substitute Vera Sans for Tahoma on X
  127. if ( !V_stricmp( name, "Bitstream Vera Sans" ) )
  128. {
  129. name = "Tahoma";
  130. entry.m_pchFile = (char *)malloc( Q_strlen(file) + 1 );
  131. entry.m_pchFriendlyName = (char *)malloc( Q_strlen(name) +1);
  132. Q_memcpy( entry.m_pchFile, file, Q_strlen(file) + 1 );
  133. Q_memcpy( entry.m_pchFriendlyName, name, Q_strlen(name) +1);
  134. m_FriendlyNameCache.Insert( entry );
  135. name = "Verdana";
  136. entry.m_pchFile = (char *)malloc( Q_strlen(file) + 1 );
  137. entry.m_pchFriendlyName = (char *)malloc( Q_strlen(name) +1);
  138. Q_memcpy( entry.m_pchFile, file, Q_strlen(file) + 1 );
  139. Q_memcpy( entry.m_pchFriendlyName, name, Q_strlen(name) +1);
  140. m_FriendlyNameCache.Insert( entry );
  141. name = "Lucidia Console";
  142. entry.m_pchFile = (char *)malloc( Q_strlen(file) + 1 );
  143. entry.m_pchFriendlyName = (char *)malloc( Q_strlen(name) +1);
  144. Q_memcpy( entry.m_pchFile, file, Q_strlen(file) + 1 );
  145. Q_memcpy( entry.m_pchFriendlyName, name, Q_strlen(name) +1);
  146. m_FriendlyNameCache.Insert( entry );
  147. }
  148. }
  149. FcFontSetDestroy(fontset);
  150. FcObjectSetDestroy(os);
  151. FcPatternDestroy(pat);
  152. }
  153. static FcPattern* FontMatch(const char* type, FcType vtype, const void* value,
  154. ...)
  155. {
  156. va_list ap;
  157. va_start(ap, value);
  158. FcPattern* pattern = FcPatternCreate();
  159. for (;;) {
  160. FcValue fcvalue;
  161. fcvalue.type = vtype;
  162. switch (vtype) {
  163. case FcTypeString:
  164. fcvalue.u.s = (FcChar8*) value;
  165. break;
  166. case FcTypeInteger:
  167. fcvalue.u.i = (int) value;
  168. break;
  169. default:
  170. Assert(!"FontMatch unhandled type");
  171. }
  172. FcPatternAdd(pattern, type, fcvalue, 0);
  173. type = va_arg(ap, const char *);
  174. if (!type)
  175. break;
  176. // FcType is promoted to int when passed through ...
  177. vtype = static_cast<FcType>(va_arg(ap, int));
  178. value = va_arg(ap, const void *);
  179. };
  180. va_end(ap);
  181. FcConfigSubstitute(0, pattern, FcMatchPattern);
  182. FcDefaultSubstitute(pattern);
  183. FcResult result;
  184. FcPattern* match = FcFontMatch(0, pattern, &result);
  185. FcPatternDestroy(pattern);
  186. return match;
  187. }
  188. bool CLinuxFont::CreateFromMemory(const char *windowsFontName, void *data, int size, int tall, int weight, int blur, int scanlines, int flags)
  189. {
  190. // setup font properties
  191. m_szName = windowsFontName;
  192. m_iTall = tall;
  193. m_iWeight = weight;
  194. m_iFlags = flags;
  195. m_bAntiAliased = flags & FONTFLAG_ANTIALIAS;
  196. m_bUnderlined = flags & FONTFLAG_UNDERLINE;
  197. m_iDropShadowOffset = (flags & FONTFLAG_DROPSHADOW) ? 1 : 0;
  198. m_iOutlineSize = (flags & FONTFLAG_OUTLINE) ? 1 : 0;
  199. m_iBlur = blur;
  200. m_iScanLines = scanlines;
  201. m_bRotary = flags & FONTFLAG_ROTARY;
  202. m_bAdditive = flags & FONTFLAG_ADDITIVE;
  203. FT_Error error = FT_New_Memory_Face( FontManager().GetFontLibraryHandle(), (FT_Byte *)data, size, 0, &face );
  204. if ( error == FT_Err_Unknown_File_Format )
  205. {
  206. return false;
  207. }
  208. else if ( error )
  209. {
  210. return false;
  211. }
  212. InitMetrics();
  213. return true;
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose: creates the font from windows. returns false if font does not exist in the OS.
  217. //-----------------------------------------------------------------------------
  218. bool CLinuxFont::Create(const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags)
  219. {
  220. // setup font properties
  221. m_szName = windowsFontName;
  222. m_iTall = tall;
  223. m_iWeight = weight;
  224. m_iFlags = flags;
  225. m_bAntiAliased = flags & FONTFLAG_ANTIALIAS;
  226. m_bUnderlined = flags & FONTFLAG_UNDERLINE;
  227. m_iDropShadowOffset = (flags & FONTFLAG_DROPSHADOW) ? 1 : 0;
  228. m_iOutlineSize = (flags & FONTFLAG_OUTLINE) ? 1 : 0;
  229. m_iBlur = blur;
  230. m_iScanLines = scanlines;
  231. m_bRotary = flags & FONTFLAG_ROTARY;
  232. m_bAdditive = flags & FONTFLAG_ADDITIVE;
  233. CreateFontList();
  234. const char *pchFontName = windowsFontName;
  235. if ( !Q_stricmp( pchFontName, "Tahoma" ) )
  236. pchFontName = "Bitstream Vera Sans";
  237. const int italic = flags & FONTFLAG_ITALIC ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
  238. FcPattern* match = FontMatch(FC_FAMILY, FcTypeString, pchFontName,
  239. FC_WEIGHT, FcTypeInteger, FC_WEIGHT_NORMAL,
  240. FC_SLANT, FcTypeInteger, italic,
  241. NULL);
  242. if (!match)
  243. {
  244. AssertMsg1( false, "Unable to find font named %s\n", windowsFontName );
  245. m_szName = "";
  246. return false;
  247. }
  248. else
  249. {
  250. FcChar8* filename;
  251. if ( FcPatternGetString(match, FC_FILE, 0, &filename) != FcResultMatch )
  252. {
  253. AssertMsg1( false, "Unable to find font named %s\n", windowsFontName );
  254. m_szName = "";
  255. FcPatternDestroy(match);
  256. return false;
  257. }
  258. FT_Error error = FT_New_Face( FontManager().GetFontLibraryHandle(), (const char *)filename, 0, &face );
  259. // Only destroy the pattern at this point so that "filename" is pointing
  260. // to valid memory
  261. FcPatternDestroy(match);
  262. if ( error == FT_Err_Unknown_File_Format )
  263. {
  264. return false;
  265. }
  266. else if ( error )
  267. {
  268. return false;
  269. }
  270. if ( face->charmap == nullptr )
  271. {
  272. FT_Error error = FT_Select_Charmap( face, FT_ENCODING_APPLE_ROMAN );
  273. if ( error )
  274. {
  275. FT_Done_Face( face );
  276. face = NULL;
  277. Msg( "Font %s has no valid charmap\n", windowsFontName );
  278. return false;
  279. }
  280. }
  281. }
  282. InitMetrics();
  283. return true;
  284. }
  285. void CLinuxFont::InitMetrics()
  286. {
  287. const MetricsTweaks_t metricTweaks = GetFontMetricsTweaks( m_szName );
  288. FT_Set_Pixel_Sizes( face, 0, m_iTall + metricTweaks.m_tallAdjust );
  289. m_iAscent = FIXED6_2INT( face->size->metrics.ascender );
  290. m_iMaxCharWidth = FIXED6_2INT( face->size->metrics.max_advance );
  291. const int fxpHeight = face->size->metrics.height + INT_2FIXED6( m_iDropShadowOffset + 2 * m_iOutlineSize );
  292. m_iHeight = FIXED6_2INT( fxpHeight );
  293. // calculate our gaussian distribution for if we're blurred
  294. if (m_iBlur > 1)
  295. {
  296. m_pGaussianDistribution = new float[m_iBlur * 2 + 1];
  297. double sigma = 0.683 * m_iBlur;
  298. for (int x = 0; x <= (m_iBlur * 2); x++)
  299. {
  300. int val = x - m_iBlur;
  301. m_pGaussianDistribution[x] = (float)(1.0f / sqrt(2 * 3.14 * sigma * sigma)) * pow(2.7, -1 * (val * val) / (2 * sigma * sigma));
  302. // brightening factor
  303. m_pGaussianDistribution[x] *= 1;
  304. }
  305. }
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose: writes the char into the specified 32bpp texture
  309. //-----------------------------------------------------------------------------
  310. void CLinuxFont::GetCharRGBA(wchar_t ch, int rgbaWide, int rgbaTall, unsigned char *prgba )
  311. {
  312. bool bShouldAntialias = m_bAntiAliased;
  313. // filter out
  314. if ( ch > 0x00FF && !(m_iFlags & FONTFLAG_CUSTOM) )
  315. {
  316. bShouldAntialias = false;
  317. }
  318. FT_Error error = FT_Load_Char( face,ch, FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL);
  319. if ( error )
  320. return;
  321. int glyph_index = FT_Get_Char_Index( face, ch );
  322. error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );
  323. if ( error )
  324. {
  325. fprintf( stderr, "Error in FL_Load_Glyph: %x\n", error );
  326. return;
  327. }
  328. FT_GlyphSlot slot = face->glyph;
  329. uint32 nSkipRows = ( m_iAscent - slot->bitmap_top );
  330. if ( nSkipRows )
  331. nSkipRows--;
  332. if ( nSkipRows > rgbaTall )
  333. return;
  334. unsigned char *rgba = prgba + ( nSkipRows * rgbaWide * 4 );
  335. FT_Bitmap bitmap = face->glyph->bitmap;
  336. Assert( bitmap.rows <= rgbaTall );
  337. Assert( rgbaWide >= bitmap.width + m_iBlur );
  338. if ( bitmap.width == 0 )
  339. return;
  340. /* now draw to our target surface */
  341. for ( int y = 0; y < MIN( bitmap.rows, rgbaTall ); y++ )
  342. {
  343. for ( int x = 0; x < bitmap.width; x++ )
  344. {
  345. int rgbaOffset = 4*(x + m_iBlur); // +(rgbaTall-y-1)*rgbaWide*4
  346. rgba[ rgbaOffset] = 255;
  347. rgba[ rgbaOffset+1] = 255;
  348. rgba[ rgbaOffset+2] = 255;
  349. rgba[ rgbaOffset+3] = bitmap.buffer[ x + y*bitmap.width ];
  350. }
  351. rgba += ( rgbaWide*4 );
  352. }
  353. // apply requested effects in specified order
  354. ApplyDropShadowToTexture( rgbaWide, rgbaTall, prgba, m_iDropShadowOffset );
  355. ApplyOutlineToTexture( rgbaWide, rgbaTall, prgba, m_iOutlineSize );
  356. ApplyGaussianBlurToTexture( rgbaWide, rgbaTall, prgba, m_iBlur );
  357. ApplyScanlineEffectToTexture( rgbaWide, rgbaTall, prgba, m_iScanLines );
  358. ApplyRotaryEffectToTexture( rgbaWide, rgbaTall, prgba, m_bRotary );
  359. }
  360. void CLinuxFont::GetKernedCharWidth( wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &abcA, float &abcC )
  361. {
  362. abcA = abcC = wide = 0.0f;
  363. // look for it in the cache
  364. kerned_abc_cache_t finder = { ch, chBefore, chAfter };
  365. unsigned short iKerned = m_ExtendedKernedABCWidthsCache.Find(finder);
  366. if (m_ExtendedKernedABCWidthsCache.IsValidIndex(iKerned))
  367. {
  368. abcA = 0; //$ NYI. m_ExtendedKernedABCWidthsCache[iKerned].abc.abcA;
  369. abcC = 0; //$ NYI. m_ExtendedKernedABCWidthsCache[iKerned].abc.abcC;
  370. wide = m_ExtendedKernedABCWidthsCache[iKerned].abc.wide;
  371. return;
  372. }
  373. FT_UInt glyph_index;
  374. FT_Bool use_kerning;
  375. FT_UInt previous;
  376. int32_t iFxpPenX;
  377. iFxpPenX = 0;
  378. wide = 0;
  379. use_kerning = FT_HAS_KERNING( face );
  380. previous = chBefore;
  381. /* convert character code to glyph index */
  382. glyph_index = FT_Get_Char_Index( face, ch );
  383. /* retrieve kerning distance and move pen position */
  384. if ( use_kerning && previous && glyph_index )
  385. {
  386. FT_Vector delta;
  387. FT_Get_Kerning( face, previous, glyph_index,
  388. FT_KERNING_DEFAULT, &delta );
  389. iFxpPenX += delta.x;
  390. }
  391. /* load glyph image into the slot (erase previous one) */
  392. int error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
  393. if ( error )
  394. {
  395. fprintf( stderr, "Error in FL_Load_Glyph: %x\n", error );
  396. }
  397. FT_GlyphSlot slot = face->glyph;
  398. iFxpPenX += slot->advance.x;
  399. if ( FIXED6_2INT(iFxpPenX) > wide )
  400. wide = FIXED6_2INT(iFxpPenX);
  401. //$ NYI: finder.abc.abcA = abcA;
  402. //$ NYI: finder.abc.abcC = abcC;
  403. finder.abc.wide = wide;
  404. m_ExtendedKernedABCWidthsCache.Insert(finder);
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Purpose: gets the abc widths for a character
  408. //-----------------------------------------------------------------------------
  409. void CLinuxFont::GetCharABCWidths(int ch, int &a, int &b, int &c)
  410. {
  411. Assert(IsValid());
  412. // look for it in the cache
  413. abc_cache_t finder = { (wchar_t)ch };
  414. unsigned short i = m_ExtendedABCWidthsCache.Find(finder);
  415. if (m_ExtendedABCWidthsCache.IsValidIndex(i))
  416. {
  417. a = m_ExtendedABCWidthsCache[i].abc.a;
  418. b = m_ExtendedABCWidthsCache[i].abc.b;
  419. c = m_ExtendedABCWidthsCache[i].abc.c;
  420. return;
  421. }
  422. a = b = c = 0;
  423. FT_Error error = FT_Load_Char( face,ch, 0 );
  424. if ( error )
  425. return;
  426. FT_Glyph_Metrics metrics = face->glyph->metrics;
  427. finder.abc.a = metrics.horiBearingX/64 - m_iBlur - m_iOutlineSize;
  428. finder.abc.b = metrics.width/64 + ((m_iBlur + m_iOutlineSize) * 2) + m_iDropShadowOffset;
  429. finder.abc.c = (metrics.horiAdvance-metrics.horiBearingX-metrics.width)/64 - m_iBlur - m_iDropShadowOffset - m_iOutlineSize;
  430. m_ExtendedABCWidthsCache.Insert(finder);
  431. a = finder.abc.a;
  432. b = finder.abc.b;
  433. c = finder.abc.c;
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Purpose: returns true if the font is equivalent to that specified
  437. //-----------------------------------------------------------------------------
  438. bool CLinuxFont::IsEqualTo(const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags)
  439. {
  440. if (!Q_stricmp(windowsFontName, m_szName.String() )
  441. && m_iTall == tall
  442. && m_iWeight == weight
  443. && m_iBlur == blur
  444. && m_iFlags == flags)
  445. return true;
  446. return false;
  447. }
  448. //-----------------------------------------------------------------------------
  449. // Purpose: returns true only if this font is valid for use
  450. //-----------------------------------------------------------------------------
  451. bool CLinuxFont::IsValid()
  452. {
  453. if ( !m_szName.IsEmpty() )
  454. return true;
  455. return false;
  456. }
  457. //-----------------------------------------------------------------------------
  458. // Purpose: returns the height of the font, in pixels
  459. //-----------------------------------------------------------------------------
  460. int CLinuxFont::GetHeight()
  461. {
  462. assert(IsValid());
  463. return m_iHeight;
  464. }
  465. //-----------------------------------------------------------------------------
  466. // Purpose: returns the ascent of the font, in pixels (ascent=units above the base line)
  467. //-----------------------------------------------------------------------------
  468. int CLinuxFont::GetAscent()
  469. {
  470. assert(IsValid());
  471. return m_iAscent;
  472. }
  473. //-----------------------------------------------------------------------------
  474. // Purpose: returns the maximum width of a character, in pixels
  475. //-----------------------------------------------------------------------------
  476. int CLinuxFont::GetMaxCharWidth()
  477. {
  478. assert(IsValid());
  479. return m_iMaxCharWidth;
  480. }
  481. //-----------------------------------------------------------------------------
  482. // Purpose: returns the flags used to make this font, used by the dynamic resizing code
  483. //-----------------------------------------------------------------------------
  484. int CLinuxFont::GetFlags()
  485. {
  486. return m_iFlags;
  487. }
  488. //-----------------------------------------------------------------------------
  489. // Purpose: Comparison function for abc widths storage
  490. //-----------------------------------------------------------------------------
  491. bool CLinuxFont::ExtendedABCWidthsCacheLessFunc(const abc_cache_t &lhs, const abc_cache_t &rhs)
  492. {
  493. return lhs.wch < rhs.wch;
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Purpose: Comparison function for abc widths storage
  497. //-----------------------------------------------------------------------------
  498. bool CLinuxFont::ExtendedKernedABCWidthsCacheLessFunc(const kerned_abc_cache_t &lhs, const kerned_abc_cache_t &rhs)
  499. {
  500. return lhs.wch < rhs.wch || ( lhs.wch == rhs.wch && lhs.wchBefore < rhs.wchBefore )
  501. || ( lhs.wch == rhs.wch && lhs.wchBefore == rhs.wchBefore && lhs.wchAfter < rhs.wchAfter );
  502. }
  503. void *CLinuxFont::SetAsActiveFont( void *cglContext )
  504. {
  505. Assert( false );
  506. return NULL;
  507. }
  508. #ifdef DBGFLAG_VALIDATE
  509. //-----------------------------------------------------------------------------
  510. // Purpose: Ensure that all of our internal structures are consistent, and
  511. // account for all memory that we've allocated.
  512. // Input: validator - Our global validator object
  513. // pchName - Our name (typically a member var in our container)
  514. //-----------------------------------------------------------------------------
  515. void CLinuxFont::Validate( CValidator &validator, const char *pchName )
  516. {
  517. validator.Push( "CLinuxFont", this, pchName );
  518. m_ExtendedABCWidthsCache.Validate( validator, "m_ExtendedABCWidthsCache" );
  519. m_ExtendedKernedABCWidthsCache.Validate( validator, "m_ExtendedKernedABCWidthsCache" );
  520. validator.ClaimMemory( m_pGaussianDistribution );
  521. validator.Pop();
  522. }
  523. #endif // DBGFLAG_VALIDATE