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.

885 lines
25 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #define SUPPORT_CUSTOM_FONT_FORMAT
  8. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  9. #define _WIN32_WINNT 0x0500
  10. #endif
  11. #include "gameuischeme.h"
  12. #include "gameuisystemsurface.h"
  13. #include "vgui/ISystem.h"
  14. #include "tier1/utlbuffer.h"
  15. #include "gameuisystemmgr.h"
  16. #include "tier1/KeyValues.h"
  17. #include "vgui_surfacelib/fontmanager.h"
  18. #include "vgui/isurface.h"
  19. #include "vgui_controls/controls.h" // has system()
  20. #if defined( _X360 )
  21. #include "xbox/xbox_win32stubs.h"
  22. #endif
  23. #include "xbox/xboxstubs.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include "tier0/memdbgon.h"
  26. #define FONT_ALIAS_NAME_LENGTH 64
  27. CGameUISchemeManager g_GameUISchemeManager;
  28. CGameUISchemeManager *g_pGameUISchemeManager = &g_GameUISchemeManager;
  29. //-----------------------------------------------------------------------------
  30. // Helper function for getting the language the game ui should use.
  31. //-----------------------------------------------------------------------------
  32. static void HelperGetLanguage( char *pLanguageBuf, int bufSize )
  33. {
  34. bool bValid = false;
  35. if ( IsPC() )
  36. {
  37. bValid = vgui::system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", pLanguageBuf, bufSize - 1 );
  38. }
  39. else
  40. {
  41. Q_strncpy( pLanguageBuf, XBX_GetLanguageString(), bufSize );
  42. bValid = true;
  43. }
  44. if ( !bValid )
  45. {
  46. Q_strncpy( pLanguageBuf, "english", bufSize );
  47. }
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Constructor
  51. //-----------------------------------------------------------------------------
  52. CGameUISchemeManager::CGameUISchemeManager()
  53. {
  54. // 0th element is null, since that would be an invalid handle
  55. CGameUIScheme *nullScheme = new CGameUIScheme();
  56. m_Schemes.AddToTail(nullScheme);
  57. Assert( g_pGameUISystemSurface );
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose: Destructor
  61. //-----------------------------------------------------------------------------
  62. CGameUISchemeManager::~CGameUISchemeManager()
  63. {
  64. int i;
  65. for ( i = 0; i < m_Schemes.Count(); i++ )
  66. {
  67. delete m_Schemes[i];
  68. m_Schemes[i] = NULL;
  69. }
  70. m_Schemes.RemoveAll();
  71. Shutdown( false );
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose: Reloads the schemes from the files
  75. //-----------------------------------------------------------------------------
  76. void CGameUISchemeManager::ReloadSchemes()
  77. {
  78. int count = m_Schemes.Count();
  79. Shutdown( false );
  80. // reload the scheme
  81. for (int i = 1; i < count; i++)
  82. {
  83. LoadSchemeFromFile( m_Schemes[i]->GetFileName(), m_Schemes[i]->GetName() );
  84. }
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Purpose: Reload the fonts in all schemes
  88. //-----------------------------------------------------------------------------
  89. void CGameUISchemeManager::ReloadFonts( int inScreenTall )
  90. {
  91. for (int i = 1; i < m_Schemes.Count(); i++)
  92. {
  93. m_Schemes[i]->ReloadFontGlyphs( inScreenTall );
  94. }
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose:
  98. //-----------------------------------------------------------------------------
  99. void CGameUISchemeManager::Shutdown( bool full )
  100. {
  101. // Full shutdown kills the null scheme
  102. for( int i = full ? 0 : 1; i < m_Schemes.Count(); i++ )
  103. {
  104. m_Schemes[i]->Shutdown( full );
  105. }
  106. if ( full )
  107. {
  108. m_Schemes.RemoveAll();
  109. }
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Purpose: Find an already loaded scheme
  113. //-----------------------------------------------------------------------------
  114. IGameUIScheme * CGameUISchemeManager::FindLoadedScheme( const char *pFilename )
  115. {
  116. // Find the scheme in the list of already loaded schemes
  117. for ( int i = 1; i < m_Schemes.Count(); i++ )
  118. {
  119. char const *schemeFileName = m_Schemes[i]->GetFileName();
  120. if ( !stricmp( schemeFileName, pFilename ) )
  121. return m_Schemes[i];
  122. }
  123. return NULL;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // First scheme loaded becomes the default scheme,
  127. // and all subsequent loaded scheme are derivatives of that
  128. //-----------------------------------------------------------------------------
  129. IGameUIScheme * CGameUISchemeManager::LoadSchemeFromFileEx( const char *pFilename, const char *tag )
  130. {
  131. // Look to see if we've already got this scheme...
  132. CGameUIScheme * hScheme = ( CGameUIScheme * ) FindLoadedScheme( pFilename );
  133. if ( hScheme )
  134. {
  135. if ( hScheme->IsActive() )
  136. {
  137. if ( IsPC() )
  138. {
  139. hScheme->ReloadFontGlyphs();
  140. }
  141. return hScheme;
  142. }
  143. }
  144. else
  145. {
  146. hScheme = new CGameUIScheme();
  147. m_Schemes.AddToTail( hScheme );
  148. }
  149. KeyValues *data;
  150. data = new KeyValues("Scheme");
  151. data->UsesEscapeSequences( true ); // VGUI uses this
  152. // look first in skins directory
  153. bool result = data->LoadFromFile( g_pFullFileSystem, pFilename, "SKIN" );
  154. if (!result)
  155. {
  156. result = data->LoadFromFile( g_pFullFileSystem, pFilename, "GAME" );
  157. if ( !result )
  158. {
  159. // look in any directory
  160. result = data->LoadFromFile( g_pFullFileSystem, pFilename, NULL );
  161. }
  162. }
  163. if (!result)
  164. {
  165. data->deleteThis();
  166. return 0;
  167. }
  168. if ( IsPC() )
  169. {
  170. ConVarRef cl_hud_minmode( "cl_hud_minmode", true );
  171. if ( cl_hud_minmode.IsValid() && cl_hud_minmode.GetBool() )
  172. {
  173. data->ProcessResolutionKeys( "_minmode" );
  174. }
  175. }
  176. hScheme->SetActive( true );
  177. hScheme->LoadFromFile( pFilename, tag, data );
  178. return hScheme;
  179. }
  180. //-----------------------------------------------------------------------------
  181. // Purpose: loads a scheme from disk
  182. //-----------------------------------------------------------------------------
  183. IGameUIScheme * CGameUISchemeManager::LoadSchemeFromFile( const char *fileName, const char *tag )
  184. {
  185. return LoadSchemeFromFileEx( fileName, tag );
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Purpose: returns a handle to the default (first loaded) scheme
  189. //-----------------------------------------------------------------------------
  190. IGameUIScheme * CGameUISchemeManager::GetDefaultScheme()
  191. {
  192. if ( m_Schemes.Count() >= 2 )
  193. return m_Schemes[1];
  194. else if ( m_Schemes.Count() > 0 )
  195. return m_Schemes[0];
  196. else
  197. return NULL;
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose: returns a handle to the scheme identified by "tag"
  201. //-----------------------------------------------------------------------------
  202. IGameUIScheme * CGameUISchemeManager::GetScheme( const char *tag )
  203. {
  204. for ( int i=1; i<m_Schemes.Count(); i++ )
  205. {
  206. if ( !stricmp( tag, m_Schemes[i]->GetName() ) )
  207. {
  208. return m_Schemes[i];
  209. }
  210. }
  211. return GetDefaultScheme(); // default scheme
  212. }
  213. //-----------------------------------------------------------------------------
  214. // gets the proportional coordinates for doing screen-size independant panel layouts
  215. // use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
  216. //-----------------------------------------------------------------------------
  217. int CGameUISchemeManager::GetProportionalScaledValueEx( CGameUIScheme *pScheme, int normalizedValue, int screenTall )
  218. {
  219. return GetProportionalScaledValue( normalizedValue, screenTall );
  220. }
  221. //-----------------------------------------------------------------------------
  222. // Purpose: converts a value into proportional mode
  223. //-----------------------------------------------------------------------------
  224. int CGameUISchemeManager::GetProportionalScaledValue( int normalizedValue, int screenTall )
  225. {
  226. int tall;
  227. if ( screenTall == -1 )
  228. {
  229. g_pGameUISystemMgrImpl->GetScreenHeightForFontLoading( tall );
  230. }
  231. else
  232. {
  233. tall = screenTall;
  234. }
  235. return GetProportionalScaledValue_( tall, normalizedValue );
  236. }
  237. //-----------------------------------------------------------------------------
  238. //
  239. //-----------------------------------------------------------------------------
  240. int CGameUISchemeManager::GetProportionalScaledValue_( int screenTall, int normalizedValue )
  241. {
  242. int baseWide, baseTall;
  243. g_pGameUISystemSurface->GetProportionalBase( baseWide, baseTall );
  244. double scale = (double)screenTall / (double)baseTall;
  245. return (int)( normalizedValue * scale );
  246. }
  247. //-----------------------------------------------------------------------------
  248. //
  249. //-----------------------------------------------------------------------------
  250. void CGameUISchemeManager::SpewFonts( void )
  251. {
  252. for ( int i = 1; i < m_Schemes.Count(); i++ )
  253. {
  254. m_Schemes[i]->SpewFonts();
  255. }
  256. }
  257. //-----------------------------------------------------------------------------
  258. //
  259. //-----------------------------------------------------------------------------
  260. void CGameUISchemeManager::SetLanguage( const char *pLanguage )
  261. {
  262. g_pGameUISystemSurface->SetLanguage( pLanguage );
  263. }
  264. //-----------------------------------------------------------------------------
  265. //
  266. //-----------------------------------------------------------------------------
  267. const char *CGameUISchemeManager::GetLanguage()
  268. {
  269. return g_pGameUISystemSurface->GetLanguage();
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Constructor
  273. //-----------------------------------------------------------------------------
  274. CGameUIScheme::CGameUIScheme()
  275. {
  276. m_pFileName = "";
  277. m_pTag = "";
  278. m_pData = NULL;
  279. SetActive( false );
  280. }
  281. CGameUIScheme::~CGameUIScheme()
  282. {
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Purpose: loads a scheme from from disk into memory
  286. //-----------------------------------------------------------------------------
  287. void CGameUIScheme::LoadFromFile( const char *pFilename, const char *inTag, KeyValues *inKeys )
  288. {
  289. COM_TimestampedLog( "CScheme::LoadFromFile( %s )", pFilename );
  290. m_pFileName = pFilename;
  291. m_pData = inKeys;
  292. // override the scheme name with the tag name
  293. KeyValues *name = m_pData->FindKey( "Name", true );
  294. name->SetString("Name", inTag);
  295. if ( inTag )
  296. {
  297. m_pTag = inTag;
  298. }
  299. else
  300. {
  301. Error( "You need to name the scheme (%s)!", m_pFileName.Get() );
  302. m_pTag = "default";
  303. }
  304. LoadFonts();
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Purpose: Set the range of character values this font can be used on
  308. //-----------------------------------------------------------------------------
  309. bool CGameUIScheme::GetFontRange( const char *fontname, int &nMin, int &nMax )
  310. {
  311. for ( int i = 0 ; i < m_FontRanges.Count() ; i++ )
  312. {
  313. if ( Q_stricmp( m_FontRanges[i]._fontName.String(), fontname ) == 0 )
  314. {
  315. nMin = m_FontRanges[i]._min;
  316. nMax = m_FontRanges[i]._max;
  317. return true;
  318. }
  319. }
  320. return false;
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose: Get the range of character values this font can be used on
  324. //-----------------------------------------------------------------------------
  325. void CGameUIScheme::SetFontRange( const char *fontname, int nMin, int nMax )
  326. {
  327. for ( int i = 0 ; i < m_FontRanges.Count() ; i++ )
  328. {
  329. if ( Q_stricmp( m_FontRanges[i]._fontName.String(), fontname ) == 0 )
  330. {
  331. m_FontRanges[i]._min = nMin;
  332. m_FontRanges[i]._max = nMax;
  333. return;
  334. }
  335. }
  336. // not already in our list
  337. int iIndex = m_FontRanges.AddToTail();
  338. m_FontRanges[iIndex]._fontName = fontname;
  339. m_FontRanges[iIndex]._min = nMin;
  340. m_FontRanges[iIndex]._max = nMax;
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Purpose: adds all the font specifications to the surface
  344. //-----------------------------------------------------------------------------
  345. void CGameUIScheme::LoadFonts()
  346. {
  347. // get our language
  348. const char *pLanguage = g_GameUISchemeManager.GetLanguage();
  349. // add our custom fonts
  350. for ( KeyValues *kv = m_pData->FindKey("CustomFontFiles", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey() )
  351. {
  352. const char *fontFile = kv->GetString();
  353. if (fontFile && *fontFile)
  354. {
  355. g_pGameUISystemSurface->AddCustomFontFile( fontFile );
  356. }
  357. else
  358. {
  359. // we have a block to read
  360. int nRangeMin = 0, nRangeMax = 0;
  361. const char *pszName = NULL;
  362. bool bUseRange = false;
  363. for ( KeyValues *pData = kv->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
  364. {
  365. const char *pszKey = pData->GetName();
  366. if ( !Q_stricmp( pszKey, "font" ) )
  367. {
  368. fontFile = pData->GetString();
  369. }
  370. else if ( !Q_stricmp( pszKey, "name" ) )
  371. {
  372. pszName = pData->GetString();
  373. }
  374. else
  375. {
  376. // we must have a language
  377. if ( Q_stricmp( pLanguage, pszKey ) == 0 ) // matches the language we're running?
  378. {
  379. // get the range
  380. KeyValues *pRange = pData->FindKey( "range" );
  381. if ( pRange )
  382. {
  383. bUseRange = true;
  384. sscanf( pRange->GetString(), "%x %x", &nRangeMin, &nRangeMax );
  385. if ( nRangeMin > nRangeMax )
  386. {
  387. int nTemp = nRangeMin;
  388. nRangeMin = nRangeMax;
  389. nRangeMax = nTemp;
  390. }
  391. }
  392. }
  393. }
  394. }
  395. if ( fontFile && *fontFile )
  396. {
  397. g_pGameUISystemSurface->AddCustomFontFile( fontFile );
  398. if ( bUseRange )
  399. {
  400. SetFontRange( pszName, nRangeMin, nRangeMax );
  401. }
  402. }
  403. }
  404. }
  405. // add bitmap fonts
  406. for ( KeyValues *kv = m_pData->FindKey("BitmapFontFiles", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey() )
  407. {
  408. const char *fontFile = kv->GetString();
  409. if (fontFile && *fontFile)
  410. {
  411. bool bSuccess = g_pGameUISystemSurface->AddBitmapFontFile( fontFile );
  412. if ( bSuccess )
  413. {
  414. // refer to the font by a user specified symbol
  415. g_pGameUISystemSurface->SetBitmapFontName( kv->GetName(), fontFile );
  416. }
  417. }
  418. }
  419. // create the fonts
  420. for (KeyValues *kv = m_pData->FindKey("Fonts", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
  421. {
  422. for ( int i = 0; i < 2; i++ )
  423. {
  424. // create the base font
  425. bool proportionalFont = i ? true : false;
  426. const char *fontName = GetMungedFontName( kv->GetName(), m_pTag.Get(), proportionalFont ); // first time it adds a normal font, and then a proportional one
  427. FontHandle_t font = g_pGameUISystemSurface->CreateFont();
  428. int j = m_FontAliases.AddToTail();
  429. m_FontAliases[j]._fontName = fontName;
  430. m_FontAliases[j]._trueFontName = kv->GetName();
  431. m_FontAliases[j]._font = font;
  432. m_FontAliases[j].m_bProportional = proportionalFont;
  433. }
  434. }
  435. // load in the font glyphs
  436. ReloadFontGlyphs();
  437. }
  438. //-----------------------------------------------------------------------------
  439. // Purpose: Reloads all scheme fonts
  440. // Supply a language if you don't want to use the one in the registry.
  441. //-----------------------------------------------------------------------------
  442. void CGameUIScheme::ReloadFontGlyphs( int inScreenTall )
  443. {
  444. int screenTall;
  445. // get our current resolution
  446. if ( inScreenTall == -1 )
  447. {
  448. //int screenWide;
  449. g_pGameUISystemMgrImpl->GetScreenHeightForFontLoading( screenTall );
  450. }
  451. else // this will make fonts be the correct size in the editor, where the stage size is the screen size.
  452. {
  453. screenTall = inScreenTall;
  454. }
  455. // check our language; some have minimum sizes
  456. int minimumFontHeight = GetMinimumFontHeightForCurrentLanguage( g_GameUISchemeManager.GetLanguage() );
  457. // add the data to all the fonts
  458. KeyValues *fonts = m_pData->FindKey( "Fonts", true );
  459. for (int i = 0; i < m_FontAliases.Count(); i++)
  460. {
  461. KeyValues *kv = fonts->FindKey( m_FontAliases[i]._trueFontName.String(), true );
  462. // walk through creating adding the first matching glyph set to the font
  463. for ( KeyValues *fontdata = kv->GetFirstSubKey(); fontdata != NULL; fontdata = fontdata->GetNextKey() )
  464. {
  465. // skip over fonts not meant for this resolution
  466. int fontYResMin = 0, fontYResMax = 0;
  467. sscanf( fontdata->GetString( "yres", "" ), "%d %d", &fontYResMin, &fontYResMax );
  468. if ( fontYResMin )
  469. {
  470. if ( !fontYResMax )
  471. {
  472. fontYResMax = fontYResMin;
  473. }
  474. // check the range
  475. if ( screenTall < fontYResMin || screenTall > fontYResMax )
  476. continue;
  477. }
  478. int flags = 0;
  479. if (fontdata->GetInt( "italic" ))
  480. {
  481. flags |= FONTFLAG_ITALIC;
  482. }
  483. if (fontdata->GetInt( "underline" ))
  484. {
  485. flags |= FONTFLAG_UNDERLINE;
  486. }
  487. if (fontdata->GetInt( "strikeout" ))
  488. {
  489. flags |= FONTFLAG_STRIKEOUT;
  490. }
  491. if (fontdata->GetInt( "symbol" ))
  492. {
  493. flags |= FONTFLAG_SYMBOL;
  494. }
  495. if (fontdata->GetInt( "antialias" ) && g_pGameUISystemSurface->SupportsFontFeature( FONT_FEATURE_ANTIALIASED_FONTS ) )
  496. {
  497. flags |= FONTFLAG_ANTIALIAS;
  498. }
  499. if (fontdata->GetInt( "dropshadow" ) && g_pGameUISystemSurface->SupportsFontFeature( FONT_FEATURE_DROPSHADOW_FONTS ) )
  500. {
  501. flags |= FONTFLAG_DROPSHADOW;
  502. }
  503. if (fontdata->GetInt( "outline" ) && g_pGameUISystemSurface->SupportsFontFeature( FONT_FEATURE_OUTLINE_FONTS ) )
  504. {
  505. flags |= FONTFLAG_OUTLINE;
  506. }
  507. if (fontdata->GetInt( "custom" ))
  508. {
  509. flags |= FONTFLAG_CUSTOM;
  510. }
  511. if (fontdata->GetInt( "bitmap" ))
  512. {
  513. flags |= FONTFLAG_BITMAP;
  514. }
  515. if (fontdata->GetInt( "rotary" ))
  516. {
  517. flags |= FONTFLAG_ROTARY;
  518. }
  519. if (fontdata->GetInt( "additive" ))
  520. {
  521. flags |= FONTFLAG_ADDITIVE;
  522. }
  523. int fontTall = fontdata->GetInt( "tall" );
  524. int blur = fontdata->GetInt( "blur" );
  525. int scanlines = fontdata->GetInt( "scanlines" );
  526. float scalex = fontdata->GetFloat( "scalex", 1.0f );
  527. float scaley = fontdata->GetFloat( "scaley", 1.0f );
  528. // only grow this font if it doesn't have a resolution filter specified
  529. if ( ( !fontYResMin && !fontYResMax ) && m_FontAliases[i].m_bProportional )
  530. {
  531. fontTall = g_GameUISchemeManager.GetProportionalScaledValueEx( this, fontTall, screenTall );
  532. blur = g_GameUISchemeManager.GetProportionalScaledValueEx( this, blur );
  533. scanlines = g_GameUISchemeManager.GetProportionalScaledValueEx( this, scanlines );
  534. scalex = g_GameUISchemeManager.GetProportionalScaledValueEx( this, scalex * 10000.0f ) * 0.0001f;
  535. scaley = g_GameUISchemeManager.GetProportionalScaledValueEx( this, scaley * 10000.0f ) * 0.0001f;
  536. }
  537. // clip the font size so that fonts can't be too big
  538. if ( fontTall > 127 )
  539. {
  540. fontTall = 127;
  541. }
  542. // check our minimum font height
  543. if ( fontTall < minimumFontHeight )
  544. {
  545. fontTall = minimumFontHeight;
  546. }
  547. if ( flags & FONTFLAG_BITMAP )
  548. {
  549. // add the new set
  550. g_pGameUISystemSurface->SetBitmapFontGlyphSet(
  551. m_FontAliases[i]._font,
  552. g_pGameUISystemSurface->GetBitmapFontName( fontdata->GetString( "name" ) ),
  553. scalex,
  554. scaley,
  555. flags);
  556. }
  557. else
  558. {
  559. int nRangeMin, nRangeMax;
  560. if ( GetFontRange( fontdata->GetString( "name" ), nRangeMin, nRangeMax ) )
  561. {
  562. // add the new set
  563. g_pGameUISystemSurface->SetFontGlyphSet(
  564. m_FontAliases[i]._font, fontdata->GetString( "name" ),
  565. fontTall, fontdata->GetInt( "weight" ), blur, scanlines, flags, nRangeMin, nRangeMax);
  566. }
  567. else
  568. {
  569. // add the new set
  570. g_pGameUISystemSurface->SetFontGlyphSet( m_FontAliases[i]._font, fontdata->GetString( "name" ),
  571. fontTall, fontdata->GetInt( "weight" ), blur, scanlines, flags);
  572. }
  573. }
  574. // don't add any more
  575. break;
  576. }
  577. }
  578. }
  579. //-----------------------------------------------------------------------------
  580. //
  581. //-----------------------------------------------------------------------------
  582. void CGameUIScheme::SpewFonts( void )
  583. {
  584. Msg( "Game UI Scheme: %s (%s)\n", GetName(), GetFileName() );
  585. for ( int i = 0; i < m_FontAliases.Count(); i++ )
  586. {
  587. Msg( " %2d: HFont:0x%8.8x, %s, %s, font:%s, tall:%d\n",
  588. i,
  589. m_FontAliases[i]._font,
  590. m_FontAliases[i]._trueFontName.String(),
  591. m_FontAliases[i]._fontName.String(),
  592. g_pGameUISystemSurface->GetFontName( m_FontAliases[i]._font ),
  593. g_pGameUISystemSurface->GetFontTall( m_FontAliases[i]._font ) );
  594. }
  595. }
  596. //-----------------------------------------------------------------------------
  597. // Purpose: Kills the scheme
  598. //-----------------------------------------------------------------------------
  599. void CGameUIScheme::Shutdown( bool full )
  600. {
  601. SetActive( false );
  602. m_FontRanges.RemoveAll();
  603. if (m_pData)
  604. {
  605. m_pData->deleteThis();
  606. m_pData = NULL;
  607. }
  608. if ( full )
  609. {
  610. delete this;
  611. }
  612. }
  613. //-----------------------------------------------------------------------------
  614. // Finds a font in the alias list
  615. //-----------------------------------------------------------------------------
  616. FontHandle_t CGameUIScheme::FindFontInAliasList( const char *fontName )
  617. {
  618. // FIXME: Slow!!!
  619. for (int i = m_FontAliases.Count(); --i >= 0; )
  620. {
  621. if ( !strnicmp( fontName, m_FontAliases[i]._fontName.String(), FONT_ALIAS_NAME_LENGTH ) )
  622. return m_FontAliases[i]._font;
  623. }
  624. // No dice
  625. return 0;
  626. }
  627. //-----------------------------------------------------------------------------
  628. // Purpose:
  629. // Input : font -
  630. // Output : char const
  631. //-----------------------------------------------------------------------------
  632. char const *CGameUIScheme::GetFontName( const FontHandle_t &font )
  633. {
  634. for (int i = m_FontAliases.Count(); --i >= 0; )
  635. {
  636. FontHandle_t fnt = ( FontHandle_t )m_FontAliases[i]._font;
  637. if ( fnt == font )
  638. return m_FontAliases[i]._trueFontName.String();
  639. }
  640. return "<Unknown font>";
  641. }
  642. //-----------------------------------------------------------------------------
  643. // material Setting methods
  644. //-----------------------------------------------------------------------------
  645. FontHandle_t CGameUIScheme::GetFont( const char *fontName, bool proportional )
  646. {
  647. // First look in the list of aliases...
  648. return FindFontInAliasList( GetMungedFontName( fontName, m_pTag.Get(), proportional ) );
  649. }
  650. //-----------------------------------------------------------------------------
  651. // Return the vgui name of the font that is the same truefont name and one size up.
  652. // bUp is if true you want the next size up or the next size down.
  653. //-----------------------------------------------------------------------------
  654. FontHandle_t CGameUIScheme::GetFontNextSize( bool bUp, const char *fontName, bool proportional )
  655. {
  656. FontHandle_t currentFontHandle = GetFont( fontName, proportional );
  657. // Current font name wasn't found.
  658. if ( currentFontHandle == 0 )
  659. {
  660. return currentFontHandle;
  661. }
  662. int currentFontTall = g_pGameUISystemSurface->GetFontTall( currentFontHandle );
  663. const char* pCurrentFontName = g_pGameUISystemSurface->GetFontName( currentFontHandle );
  664. // Now find the closest font with this name that is the smallest size up
  665. int sizeDifference = INT_MAX;
  666. FontHandle_t closestFontHandle = 0;
  667. for (int i = m_FontAliases.Count(); --i > 0; )
  668. {
  669. if ( proportional != m_FontAliases[i].m_bProportional )
  670. continue;
  671. FontHandle_t testFontHandle = m_FontAliases[i]._font;
  672. const char* pTestFontName = g_pGameUISystemSurface->GetFontName( testFontHandle );
  673. if ( currentFontHandle != testFontHandle )
  674. {
  675. if ( !Q_stricmp( pCurrentFontName, pTestFontName ) ) // font name is the same.
  676. {
  677. int thisFontTall = g_pGameUISystemSurface->GetFontTall( testFontHandle );
  678. int diff;
  679. if ( bUp ) // get next size up
  680. {
  681. diff = thisFontTall - currentFontTall;
  682. }
  683. else // get next size down.
  684. {
  685. diff = currentFontTall - thisFontTall;
  686. }
  687. if ( diff > 0 && diff < sizeDifference )
  688. {
  689. sizeDifference = diff;
  690. closestFontHandle = testFontHandle;
  691. }
  692. }
  693. }
  694. }
  695. if ( closestFontHandle != 0 )
  696. {
  697. return closestFontHandle;
  698. }
  699. else
  700. {
  701. return currentFontHandle;
  702. }
  703. }
  704. //-----------------------------------------------------------------------------
  705. // Purpose: returns a char string of the munged name this font is stored as in the font manager
  706. //-----------------------------------------------------------------------------
  707. const char *CGameUIScheme::GetMungedFontName( const char *fontName, const char *scheme, bool proportional )
  708. {
  709. static char mungeBuffer[ 64 ];
  710. if ( scheme )
  711. {
  712. Q_snprintf( mungeBuffer, sizeof( mungeBuffer ), "%s%s-%s", fontName, scheme, proportional ? "p" : "no" );
  713. }
  714. else
  715. {
  716. Q_snprintf( mungeBuffer, sizeof( mungeBuffer ), "%s-%s", fontName, proportional ? "p" : "no" ); // we don't want the "(null)" snprintf appends
  717. }
  718. return mungeBuffer;
  719. }
  720. //-----------------------------------------------------------------------------
  721. // Purpose: gets the minimum font height for the current language
  722. //-----------------------------------------------------------------------------
  723. int CGameUIScheme::GetMinimumFontHeightForCurrentLanguage( const char *pLanguage )
  724. {
  725. char language[64];
  726. bool bValid;
  727. if ( IsPC() )
  728. {
  729. if ( pLanguage )
  730. {
  731. Q_strncpy( language, pLanguage, sizeof(language)-1 );
  732. bValid = true;
  733. }
  734. else
  735. {
  736. bValid = vgui::system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", language, sizeof(language)-1 );
  737. }
  738. }
  739. else
  740. {
  741. Q_strncpy( language, XBX_GetLanguageString(), sizeof( language ) );
  742. bValid = true;
  743. }
  744. if ( bValid )
  745. {
  746. if (!stricmp(language, "korean")
  747. || !stricmp(language, "koreana")
  748. || !stricmp(language, "tchinese")
  749. || !stricmp(language, "schinese")
  750. || !stricmp(language, "japanese"))
  751. {
  752. // the bitmap-based fonts for these languages simply don't work with a pt. size of less than 9 (13 pixels)
  753. return 13;
  754. }
  755. if ( !stricmp(language, "thai" ) )
  756. {
  757. // thai has problems below 18 pts
  758. return 18;
  759. }
  760. }
  761. // no special minimum height required
  762. return 0;
  763. }
  764. void CGameUIScheme::SetActive( bool bActive )
  765. {
  766. m_bActive = bActive;
  767. }
  768. bool CGameUIScheme::IsActive() const
  769. {
  770. return m_bActive;
  771. }