summaryrefslogtreecommitdiff
path: root/vgui2/src/Scheme.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/src/Scheme.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'vgui2/src/Scheme.cpp')
-rw-r--r--vgui2/src/Scheme.cpp1532
1 files changed, 1532 insertions, 0 deletions
diff --git a/vgui2/src/Scheme.cpp b/vgui2/src/Scheme.cpp
new file mode 100644
index 0000000..f41a695
--- /dev/null
+++ b/vgui2/src/Scheme.cpp
@@ -0,0 +1,1532 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include <stdio.h>
+#include <math.h>
+
+#include <vgui/VGUI.h>
+#include <vgui/IScheme.h>
+#include <KeyValues.h>
+#include <vgui/ISurface.h>
+#include <vgui/IPanel.h>
+#include <vgui/ISystem.h>
+#include <vstdlib/IKeyValuesSystem.h>
+#include <vgui/IVGui.h>
+
+#include "tier1/utlvector.h"
+#include "tier1/utlrbtree.h"
+#include "tier1/utldict.h"
+#include "VGUI_Border.h"
+#include "ScalableImageBorder.h"
+#include "ImageBorder.h"
+#include "vgui_internal.h"
+#include "bitmap.h"
+#include "filesystem.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+#define FONT_ALIAS_NAME_LENGTH 64
+
+//-----------------------------------------------------------------------------
+// Purpose: Implementation of global scheme interface
+//-----------------------------------------------------------------------------
+class CScheme : public IScheme
+{
+public:
+ CScheme();
+
+ // gets a string from the default settings section
+ virtual const char *GetResourceString(const char *stringName);
+
+ // returns a pointer to an existing border
+ virtual IBorder *GetBorder(const char *borderName);
+
+ // returns a pointer to an existing font
+ virtual HFont GetFont(const char *fontName, bool proportional);
+
+ // m_pkvColors
+ virtual Color GetColor( const char *colorName, Color defaultColor);
+
+
+ void Shutdown( bool full );
+ void LoadFromFile( VPANEL sizingPanel, const char *filename, const char *tag, KeyValues *inKeys );
+
+ // Gets at the scheme's name
+ const char *GetName() { return tag; }
+ const char *GetFileName() { return fileName; }
+
+ char const *GetFontName( const HFont& font );
+
+ void ReloadFontGlyphs();
+
+ VPANEL GetSizingPanel() { return m_SizingPanel; }
+
+ void SpewFonts();
+
+ bool GetFontRange( const char *fontname, int &nMin, int &nMax );
+ void SetFontRange( const char *fontname, int nMin, int nMax );
+
+ // Get the number of borders
+ virtual int GetBorderCount() const;
+
+ // Get the border at the given index
+ virtual IBorder *GetBorderAtIndex( int iIndex );
+
+ // Get the number of fonts
+ virtual int GetFontCount() const;
+
+ // Get the font at the given index
+ virtual HFont GetFontAtIndex( int iIndex );
+
+ // Get color data
+ virtual const KeyValues *GetColorData() const;
+
+private:
+ const char *LookupSchemeSetting(const char *pchSetting);
+ const char *GetMungedFontName( const char *fontName, const char *scheme, bool proportional);
+ void LoadFonts();
+ void LoadBorders();
+ HFont FindFontInAliasList( const char *fontName );
+ int GetMinimumFontHeightForCurrentLanguage();
+
+ char fileName[256];
+ char tag[64];
+
+ KeyValues *m_pData;
+ KeyValues *m_pkvBaseSettings;
+ KeyValues *m_pkvColors;
+ int m_nColorCount;
+
+ struct SchemeBorder_t
+ {
+ IBorder *border;
+ int borderSymbol;
+ bool bSharedBorder;
+ };
+ CUtlVector<SchemeBorder_t> m_BorderList;
+ IBorder *m_pBaseBorder; // default border to use if others not found
+ KeyValues *m_pkvBorders;
+#pragma pack(1)
+ struct fontalias_t
+ {
+ CUtlSymbol _trueFontName;
+ unsigned short _font : 15;
+ unsigned short m_bProportional : 1;
+ };
+#pragma pack()
+ friend struct fontalias_t;
+
+ CUtlDict< fontalias_t, int > m_FontAliases;
+ VPANEL m_SizingPanel;
+ int m_nScreenWide;
+ int m_nScreenTall;
+
+ struct fontrange_t
+ {
+ int _min;
+ int _max;
+ };
+ CUtlDict< fontrange_t, int > m_FontRanges;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Implementation of global scheme interface
+//-----------------------------------------------------------------------------
+class CSchemeManager : public ISchemeManager
+{
+public:
+ CSchemeManager();
+ ~CSchemeManager();
+
+ // loads a scheme from a file
+ // first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that
+ // tag is friendly string representing the name of the loaded scheme
+ virtual HScheme LoadSchemeFromFile(const char *fileName, const char *tag);
+ // first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that
+ virtual HScheme LoadSchemeFromFileEx( VPANEL sizingPanel, const char *fileName, const char *tag);
+
+ // reloads the schemes from the file
+ virtual void ReloadSchemes();
+ virtual void ReloadFonts();
+
+ // returns a handle to the default (first loaded) scheme
+ virtual HScheme GetDefaultScheme();
+
+ // returns a handle to the scheme identified by "tag"
+ virtual HScheme GetScheme(const char *tag);
+
+ // returns a pointer to an image
+ virtual IImage *GetImage(const char *imageName, bool hardwareFiltered);
+ virtual HTexture GetImageID(const char *imageName, bool hardwareFiltered);
+
+ virtual IScheme *GetIScheme( HScheme scheme );
+
+ virtual void Shutdown( bool full );
+
+ // gets the proportional coordinates for doing screen-size independant panel layouts
+ // use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
+ virtual int GetProportionalScaledValue(int normalizedValue);
+ virtual int GetProportionalNormalizedValue(int scaledValue);
+
+ // gets the proportional coordinates for doing screen-size independant panel layouts
+ // use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
+ virtual int GetProportionalScaledValueEx( HScheme scheme, int normalizedValue );
+ virtual int GetProportionalNormalizedValueEx( HScheme scheme, int scaledValue );
+
+ virtual bool DeleteImage( const char *pImageName );
+
+ // gets the proportional coordinates for doing screen-size independant panel layouts
+ // use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
+ int GetProportionalScaledValueEx( CScheme *pScheme, int normalizedValue );
+ int GetProportionalNormalizedValueEx( CScheme *pScheme, int scaledValue );
+
+ void SpewFonts();
+
+private:
+
+ int GetProportionalScaledValue_( int rootWide, int rootTall, int normalizedValue );
+ int GetProportionalNormalizedValue_( int rootWide, int rootTall, int scaledValue );
+
+ // Search for already-loaded schemes
+ HScheme FindLoadedScheme(const char *fileName);
+
+ CUtlVector<CScheme *> m_Schemes;
+
+ static const char *s_pszSearchString;
+ struct CachedBitmapHandle_t
+ {
+ Bitmap *pBitmap;
+ };
+ static bool BitmapHandleSearchFunc(const CachedBitmapHandle_t &, const CachedBitmapHandle_t &);
+ CUtlRBTree<CachedBitmapHandle_t, int> m_Bitmaps;
+};
+
+const char *CSchemeManager::s_pszSearchString = NULL;
+
+//-----------------------------------------------------------------------------
+// Purpose: search function for stored bitmaps
+//-----------------------------------------------------------------------------
+bool CSchemeManager::BitmapHandleSearchFunc(const CachedBitmapHandle_t &lhs, const CachedBitmapHandle_t &rhs)
+{
+ // a NULL bitmap indicates to use the search string instead
+ if (lhs.pBitmap && rhs.pBitmap)
+ {
+ return stricmp(lhs.pBitmap->GetName(), rhs.pBitmap->GetName()) > 0;
+ }
+ else if (lhs.pBitmap)
+ {
+ return stricmp(lhs.pBitmap->GetName(), s_pszSearchString) > 0;
+ }
+ return stricmp(s_pszSearchString, rhs.pBitmap->GetName()) > 0;
+}
+
+
+
+CSchemeManager g_Scheme;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CSchemeManager, ISchemeManager, VGUI_SCHEME_INTERFACE_VERSION, g_Scheme);
+
+
+namespace vgui
+{
+vgui::ISchemeManager *g_pScheme = &g_Scheme;
+} // namespace vgui
+
+CON_COMMAND( vgui_spew_fonts, "" )
+{
+ g_Scheme.SpewFonts();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CSchemeManager::CSchemeManager()
+{
+ // 0th element is null, since that would be an invalid handle
+ CScheme *nullScheme = new CScheme();
+ m_Schemes.AddToTail(nullScheme);
+ m_Bitmaps.SetLessFunc(&BitmapHandleSearchFunc);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CSchemeManager::~CSchemeManager()
+{
+ int i;
+ for ( i = 0; i < m_Schemes.Count(); i++ )
+ {
+ delete m_Schemes[i];
+ }
+ m_Schemes.RemoveAll();
+
+ for ( i = 0; i < m_Bitmaps.MaxElement(); i++ )
+ {
+ if (m_Bitmaps.IsValidIndex(i))
+ {
+ delete m_Bitmaps[i].pBitmap;
+ }
+ }
+ m_Bitmaps.RemoveAll();
+
+ Shutdown( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Reload the fonts in all schemes
+//-----------------------------------------------------------------------------
+void CSchemeManager::ReloadFonts()
+{
+ for (int i = 1; i < m_Schemes.Count(); i++)
+ {
+ m_Schemes[i]->ReloadFontGlyphs();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Converts the handle into an interface
+//-----------------------------------------------------------------------------
+IScheme *CSchemeManager::GetIScheme( HScheme scheme )
+{
+ if ( scheme >= (unsigned long)m_Schemes.Count() )
+ {
+ AssertOnce( !"Invalid scheme requested." );
+ return NULL;
+ }
+ else
+ {
+ return m_Schemes[scheme];
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CSchemeManager::Shutdown( bool full )
+{
+ // Full shutdown kills the null scheme
+ for( int i = full ? 0 : 1; i < m_Schemes.Count(); i++ )
+ {
+ m_Schemes[i]->Shutdown( full );
+ }
+
+ if ( full )
+ {
+ m_Schemes.RemoveAll();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: loads a scheme from disk
+//-----------------------------------------------------------------------------
+HScheme CSchemeManager::FindLoadedScheme(const char *fileName)
+{
+ // Find the scheme in the list of already loaded schemes
+ for (int i = 1; i < m_Schemes.Count(); i++)
+ {
+ char const *schemeFileName = m_Schemes[i]->GetFileName();
+ if (!stricmp(schemeFileName, fileName))
+ return i;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CScheme::CScheme()
+{
+ fileName[ 0 ] = 0;
+ tag[ 0 ] = 0;
+
+ m_pData = NULL;
+ m_pkvBaseSettings = NULL;
+ m_pkvColors = NULL;
+ m_nColorCount = 0;
+
+ m_pBaseBorder = NULL; // default border to use if others not found
+ m_pkvBorders = NULL;
+ m_SizingPanel = 0;
+ m_nScreenWide = -1;
+ m_nScreenTall = -1;
+}
+
+// first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that
+HScheme CSchemeManager::LoadSchemeFromFileEx( VPANEL sizingPanel, const char *fileName, const char *tag)
+{
+ // Look to see if we've already got this scheme...
+ HScheme hScheme = FindLoadedScheme(fileName);
+ if (hScheme != 0)
+ {
+ CScheme *pScheme = static_cast< CScheme * >( GetIScheme( hScheme ) );
+ if ( IsPC() && pScheme )
+ {
+ pScheme->ReloadFontGlyphs();
+ }
+ return hScheme;
+ }
+
+ KeyValues *data;
+ data = new KeyValues("Scheme");
+
+ data->UsesEscapeSequences( true ); // VGUI uses this
+
+ // Look first in game directory
+ bool result = data->LoadFromFile( g_pFullFileSystem, fileName, "GAME" );
+ if ( !result )
+ {
+ // look in any directory
+ result = data->LoadFromFile( g_pFullFileSystem, fileName, NULL );
+ }
+
+ if (!result)
+ {
+ data->deleteThis();
+ return 0;
+ }
+
+ if ( IsX360() )
+ {
+ data->ProcessResolutionKeys( g_pSurface->GetResolutionKey() );
+ }
+ if ( IsPC() )
+ {
+ ConVarRef cl_hud_minmode( "cl_hud_minmode", true );
+ if ( cl_hud_minmode.IsValid() && cl_hud_minmode.GetBool() )
+ {
+ data->ProcessResolutionKeys( "_minmode" );
+ }
+ }
+ if( g_pIVgui->GetVRMode() )
+ {
+ data->ProcessResolutionKeys( "_vrmode" );
+ }
+
+ CScheme *newScheme = new CScheme();
+ newScheme->LoadFromFile( sizingPanel, fileName, tag, data );
+
+ return m_Schemes.AddToTail(newScheme);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: loads a scheme from disk
+//-----------------------------------------------------------------------------
+HScheme CSchemeManager::LoadSchemeFromFile(const char *fileName, const char *tag)
+{
+ return LoadSchemeFromFileEx( 0, fileName, tag );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Table of scheme file entries, translation from old goldsrc schemes to new src schemes
+//-----------------------------------------------------------------------------
+struct SchemeEntryTranslation_t
+{
+ const char *pchNewEntry;
+ const char *pchOldEntry;
+ const char *pchDefaultValue;
+};
+SchemeEntryTranslation_t g_SchemeTranslation[] =
+{
+ { "Border.Bright", "BorderBright", "200 200 200 196" }, // the lit side of a control
+ { "Border.Dark" "BorderDark", "40 40 40 196" }, // the dark/unlit side of a control
+ { "Border.Selection" "BorderSelection", "0 0 0 196" }, // the additional border color for displaying the default/selected button
+
+ { "Button.TextColor", "ControlFG", "White" },
+ { "Button.BgColor", "ControlBG", "Blank" },
+ { "Button.ArmedTextColor", "ControlFG" },
+ { "Button.ArmedBgColor", "ControlBG" },
+ { "Button.DepressedTextColor", "ControlFG" },
+ { "Button.DepressedBgColor", "ControlBG" },
+ { "Button.FocusBorderColor", "0 0 0 255" },
+
+ { "CheckButton.TextColor", "BaseText" },
+ { "CheckButton.SelectedTextColor", "BrightControlText" },
+ { "CheckButton.BgColor", "CheckBgColor" },
+ { "CheckButton.Border1", "CheckButtonBorder1" },
+ { "CheckButton.Border2", "CheckButtonBorder2" },
+ { "CheckButton.Check", "CheckButtonCheck" },
+
+ { "ComboBoxButton.ArrowColor", "LabelDimText" },
+ { "ComboBoxButton.ArmedArrowColor", "MenuButton/ArmedArrowColor" },
+ { "ComboBoxButton.BgColor", "MenuButton/ButtonBgColor" },
+ { "ComboBoxButton.DisabledBgColor", "ControlBG" },
+
+ { "Frame.TitleTextInsetX", NULL, "32" },
+ { "Frame.ClientInsetX", NULL, "8" },
+ { "Frame.ClientInsetY", NULL, "6" },
+ { "Frame.BgColor", "BgColor" },
+ { "Frame.OutOfFocusBgColor", "BgColor" },
+ { "Frame.FocusTransitionEffectTime",NULL, "0" },
+ { "Frame.TransitionEffectTime", NULL, "0" },
+ { "Frame.AutoSnapRange", NULL, "8" },
+ { "FrameGrip.Color1", "BorderBright" },
+ { "FrameGrip.Color2", "BorderSelection" },
+ { "FrameTitleButton.FgColor", "TitleButtonFgColor" },
+ { "FrameTitleButton.BgColor", "TitleButtonBgColor" },
+ { "FrameTitleButton.DisabledFgColor", "TitleButtonDisabledFgColor" },
+ { "FrameTitleButton.DisabledBgColor", "TitleButtonDisabledBgColor" },
+ { "FrameSystemButton.FgColor", "TitleBarBgColor" },
+ { "FrameSystemButton.BgColor", "TitleBarBgColor" },
+ { "FrameSystemButton.Icon", "TitleBarIcon" },
+ { "FrameSystemButton.DisabledIcon", "TitleBarDisabledIcon" },
+ { "FrameTitleBar.Font", NULL, "Default" },
+ { "FrameTitleBar.TextColor", "TitleBarFgColor" },
+ { "FrameTitleBar.BgColor", "TitleBarBgColor" },
+ { "FrameTitleBar.DisabledTextColor","TitleBarDisabledFgColor" },
+ { "FrameTitleBar.DisabledBgColor", "TitleBarDisabledBgColor" },
+
+ { "GraphPanel.FgColor", "BrightControlText" },
+ { "GraphPanel.BgColor", "WindowBgColor" },
+
+ { "Label.TextDullColor", "LabelDimText" },
+ { "Label.TextColor", "BaseText" },
+ { "Label.TextBrightColor", "BrightControlText" },
+ { "Label.SelectedTextColor", "BrightControlText" },
+ { "Label.BgColor", "LabelBgColor" },
+ { "Label.DisabledFgColor1", "DisabledFgColor1" },
+ { "Label.DisabledFgColor2", "DisabledFgColor2" },
+
+ { "ListPanel.TextColor", "WindowFgColor" },
+ { "ListPanel.TextBgColor", "Menu/ArmedBgColor" },
+ { "ListPanel.BgColor", "ListBgColor" },
+ { "ListPanel.SelectedTextColor", "ListSelectionFgColor" },
+ { "ListPanel.SelectedBgColor", "Menu/ArmedBgColor" },
+ { "ListPanel.SelectedOutOfFocusBgColor","SelectionBG2" },
+ { "ListPanel.EmptyListInfoTextColor", "LabelDimText" },
+ { "ListPanel.DisabledTextColor", "LabelDimText" },
+ { "ListPanel.DisabledSelectedTextColor","ListBgColor" },
+
+ { "Menu.TextColor", "Menu/FgColor" },
+ { "Menu.BgColor", "Menu/BgColor" },
+ { "Menu.ArmedTextColor", "Menu/ArmedFgColor" },
+ { "Menu.ArmedBgColor", "Menu/ArmedBgColor" },
+ { "Menu.TextInset", NULL, "6" },
+
+ { "Panel.FgColor", "FgColor" },
+ { "Panel.BgColor", "BgColor" },
+
+ { "ProgressBar.FgColor", "BrightControlText" },
+ { "ProgressBar.BgColor", "WindowBgColor" },
+
+ { "PropertySheet.TextColor", "FgColorDim" },
+ { "PropertySheet.SelectedTextColor", "BrightControlText" },
+ { "PropertySheet.TransitionEffectTime", NULL, "0" },
+
+ { "RadioButton.TextColor", "FgColor" },
+ { "RadioButton.SelectedTextColor", "BrightControlText" },
+
+ { "RichText.TextColor", "WindowFgColor" },
+ { "RichText.BgColor", "WindowBgColor" },
+ { "RichText.SelectedTextColor", "SelectionFgColor" },
+ { "RichText.SelectedBgColor", "SelectionBgColor" },
+
+ { "ScrollBar.Wide", NULL, "19" },
+
+ { "ScrollBarButton.FgColor", "DimBaseText" },
+ { "ScrollBarButton.BgColor", "ControlBG" },
+ { "ScrollBarButton.ArmedFgColor", "BaseText" },
+ { "ScrollBarButton.ArmedBgColor", "ControlBG" },
+ { "ScrollBarButton.DepressedFgColor", "BaseText" },
+ { "ScrollBarButton.DepressedBgColor", "ControlBG" },
+
+ { "ScrollBarSlider.FgColor", "ScrollBarSlider/ScrollBarSliderFgColor" },
+ { "ScrollBarSlider.BgColor", "ScrollBarSlider/ScrollBarSliderBgColor" },
+
+ { "SectionedListPanel.HeaderTextColor", "SectionTextColor" },
+ { "SectionedListPanel.HeaderBgColor", "BuddyListBgColor" },
+ { "SectionedListPanel.DividerColor", "SectionDividerColor" },
+ { "SectionedListPanel.TextColor", "BuddyButton/FgColor1" },
+ { "SectionedListPanel.BrightTextColor", "BuddyButton/ArmedFgColor1" },
+ { "SectionedListPanel.BgColor", "BuddyListBgColor" },
+ { "SectionedListPanel.SelectedTextColor", "BuddyButton/ArmedFgColor1" },
+ { "SectionedListPanel.SelectedBgColor", "BuddyButton/ArmedBgColor" },
+ { "SectionedListPanel.OutOfFocusSelectedTextColor", "BuddyButton/ArmedFgColor2" },
+ { "SectionedListPanel.OutOfFocusSelectedBgColor", "SelectionBG2" },
+
+ { "Slider.NobColor", "SliderTickColor" },
+ { "Slider.TextColor", "Slider/SliderFgColor" },
+ { "Slider.TrackColor", "SliderTrackColor"},
+ { "Slider.DisabledTextColor1", "DisabledFgColor1" },
+ { "Slider.DisabledTextColor2", "DisabledFgColor2" },
+
+ { "TextEntry.TextColor", "WindowFgColor" },
+ { "TextEntry.BgColor", "WindowBgColor" },
+ { "TextEntry.CursorColor", "TextCursorColor" },
+ { "TextEntry.DisabledTextColor","WindowDisabledFgColor" },
+ { "TextEntry.DisabledBgColor", "ControlBG" },
+ { "TextEntry.SelectedTextColor","SelectionFgColor" },
+ { "TextEntry.SelectedBgColor", "SelectionBgColor" },
+ { "TextEntry.OutOfFocusSelectedBgColor", "SelectionBG2" },
+ { "TextEntry.FocusEdgeColor", "BorderSelection" },
+
+ { "ToggleButton.SelectedTextColor", "BrightControlText" },
+
+ { "Tooltip.TextColor", "BorderSelection" },
+ { "Tooltip.BgColor", "SelectionBG" },
+
+ { "TreeView.BgColor", "ListBgColor" },
+
+ { "WizardSubPanel.BgColor", "SubPanelBgColor" },
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: loads a scheme from from disk into memory
+//-----------------------------------------------------------------------------
+void CScheme::LoadFromFile( VPANEL sizingPanel, const char *inFilename, const char *inTag, KeyValues *inKeys )
+{
+ COM_TimestampedLog( "CScheme::LoadFromFile( %s )", inFilename );
+
+ Q_strncpy(fileName, inFilename, sizeof(fileName) );
+
+ m_SizingPanel = sizingPanel;
+
+ m_pData = inKeys;
+ m_pkvBaseSettings = m_pData->FindKey("BaseSettings", true);
+ m_pkvColors = m_pData->FindKey("Colors", true);
+
+ // override the scheme name with the tag name
+ KeyValues *name = m_pData->FindKey("Name", true);
+ name->SetString("Name", inTag);
+
+ if ( inTag )
+ {
+ Q_strncpy( tag, inTag, sizeof( tag ) );
+ }
+ else
+ {
+ Assert( "You need to name the scheme!" );
+ Q_strncpy( tag, "default", sizeof( tag ) );
+ }
+
+ // translate format from goldsrc scheme to new scheme
+ for (int i = 0; i < ARRAYSIZE(g_SchemeTranslation); i++)
+ {
+ if (!m_pkvBaseSettings->FindKey(g_SchemeTranslation[i].pchNewEntry, false))
+ {
+ const char *pchColor;
+
+ if (g_SchemeTranslation[i].pchOldEntry)
+ {
+ pchColor = LookupSchemeSetting(g_SchemeTranslation[i].pchOldEntry);
+ }
+ else
+ {
+ pchColor = g_SchemeTranslation[i].pchDefaultValue;
+ }
+
+ Assert( pchColor );
+
+ m_pkvBaseSettings->SetString(g_SchemeTranslation[i].pchNewEntry, pchColor);
+ }
+ }
+
+ // need to copy tag before loading fonts
+ LoadFonts();
+ LoadBorders();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CScheme::GetFontRange( const char *fontname, int &nMin, int &nMax )
+{
+ int i = m_FontRanges.Find( fontname );
+ if ( i != m_FontRanges.InvalidIndex() )
+ {
+ nMin = m_FontRanges[i]._min;
+ nMax = m_FontRanges[i]._max;
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CScheme::SetFontRange( const char *fontname, int nMin, int nMax )
+{
+ int i = m_FontRanges.Find( fontname );
+ if ( i != m_FontRanges.InvalidIndex() )
+ {
+ m_FontRanges[i]._min = nMin;
+ m_FontRanges[i]._max = nMax;
+ return;
+ }
+
+ // not already in our list
+ int iNew = m_FontRanges.Insert( fontname );
+
+ m_FontRanges[iNew]._min = nMin;
+ m_FontRanges[iNew]._max = nMax;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: adds all the font specifications to the surface
+//-----------------------------------------------------------------------------
+void CScheme::LoadFonts()
+{
+ bool bValid = false;
+ char language[64];
+ memset( language, 0, sizeof( language ) );
+
+ // get our language
+ if ( IsPC() )
+ {
+ bValid = vgui::g_pSystem->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Source\\Language", language, sizeof( language ) - 1 );
+ }
+ else
+ {
+ Q_strncpy( language, XBX_GetLanguageString(), sizeof( language ) );
+ bValid = true;
+ }
+
+ if ( !bValid )
+ {
+ Q_strncpy( language, "english", sizeof( language ) );
+ }
+
+ // add our custom fonts
+ for (KeyValues *kv = m_pData->FindKey("CustomFontFiles", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
+ {
+ const char *fontFile = kv->GetString();
+ if (fontFile && *fontFile)
+ {
+ g_pSurface->AddCustomFontFile( NULL, fontFile );
+ }
+ else
+ {
+ // we have a block to read
+ int nRangeMin = 0, nRangeMax = 0;
+ const char *pszName = NULL;
+ bool bUseRange = false;
+
+ for ( KeyValues *pData = kv->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
+ {
+ const char *pszKey = pData->GetName();
+ if ( !Q_stricmp( pszKey, "font" ) )
+ {
+ fontFile = pData->GetString();
+ }
+ else if ( !Q_stricmp( pszKey, "name" ) )
+ {
+ pszName = pData->GetString();
+ }
+ else
+ {
+ // we must have a language
+ if ( Q_stricmp( language, pszKey ) == 0 ) // matches the language we're running?
+ {
+ // get the range
+ KeyValues *pRange = pData->FindKey( "range" );
+ if ( pRange )
+ {
+ bUseRange = true;
+ sscanf( pRange->GetString(), "%x %x", &nRangeMin, &nRangeMax );
+
+ if ( nRangeMin > nRangeMax )
+ {
+ int nTemp = nRangeMin;
+ nRangeMin = nRangeMax;
+ nRangeMax = nTemp;
+ }
+ }
+ }
+ }
+ }
+
+ if ( fontFile && *fontFile )
+ {
+ g_pSurface->AddCustomFontFile( pszName, fontFile );
+
+ if ( bUseRange )
+ {
+ SetFontRange( pszName, nRangeMin, nRangeMax );
+ }
+ }
+ }
+ }
+
+ // add bitmap fonts
+ for (KeyValues *kv = m_pData->FindKey("BitmapFontFiles", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
+ {
+ const char *fontFile = kv->GetString();
+ if (fontFile && *fontFile)
+ {
+ bool bSuccess = g_pSurface->AddBitmapFontFile( fontFile );
+ if ( bSuccess )
+ {
+ // refer to the font by a user specified symbol
+ g_pSurface->SetBitmapFontName( kv->GetName(), fontFile );
+ }
+ }
+ }
+
+ // create the fonts
+ for (KeyValues *kv = m_pData->FindKey("Fonts", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
+ {
+ for ( int i = 0; i < 2; i++ )
+ {
+ // create the base font
+ bool proportionalFont = static_cast<bool>( i );
+ const char *fontName = GetMungedFontName( kv->GetName(), tag, proportionalFont ); // first time it adds a normal font, and then a proportional one
+ HFont font = g_pSurface->CreateFont();
+
+ int j = m_FontAliases.Insert( fontName );
+ m_FontAliases[j]._trueFontName = kv->GetName();
+ m_FontAliases[j]._font = font;
+ m_FontAliases[j].m_bProportional = proportionalFont;
+ }
+ }
+
+ // load in the font glyphs
+ ReloadFontGlyphs();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Reloads all scheme fonts
+//-----------------------------------------------------------------------------
+void CScheme::ReloadFontGlyphs()
+{
+ COM_TimestampedLog( "ReloadFontGlyphs(): Start" );
+
+ // get our current resolution
+ if ( m_SizingPanel != 0 )
+ {
+ g_pIPanel->GetSize( m_SizingPanel, m_nScreenWide, m_nScreenTall );
+ }
+ else
+ {
+ g_pSurface->GetScreenSize( m_nScreenWide, m_nScreenTall );
+ }
+
+ // check our language; some have minimum sizes
+ int minimumFontHeight = GetMinimumFontHeightForCurrentLanguage();
+
+ // add the data to all the fonts
+ KeyValues *fonts = m_pData->FindKey("Fonts", true);
+ FOR_EACH_DICT_FAST( m_FontAliases, i )
+ {
+ KeyValues *kv = fonts->FindKey( m_FontAliases[i]._trueFontName.String(), true );
+
+ // walk through creating adding the first matching glyph set to the font
+ for (KeyValues *fontdata = kv->GetFirstSubKey(); fontdata != NULL; fontdata = fontdata->GetNextKey())
+ {
+ // skip over fonts not meant for this resolution
+ int fontYResMin = 0, fontYResMax = 0;
+ sscanf(fontdata->GetString("yres", ""), "%d %d", &fontYResMin, &fontYResMax);
+ if (fontYResMin)
+ {
+ if (!fontYResMax)
+ {
+ fontYResMax = fontYResMin;
+ }
+ // check the range
+ if (m_nScreenTall < fontYResMin || m_nScreenTall > fontYResMax)
+ continue;
+ }
+
+ int flags = 0;
+ if (fontdata->GetInt( "italic" ))
+ {
+ flags |= ISurface::FONTFLAG_ITALIC;
+ }
+ if (fontdata->GetInt( "underline" ))
+ {
+ flags |= ISurface::FONTFLAG_UNDERLINE;
+ }
+ if (fontdata->GetInt( "strikeout" ))
+ {
+ flags |= ISurface::FONTFLAG_STRIKEOUT;
+ }
+ if (fontdata->GetInt( "symbol" ))
+ {
+ flags |= ISurface::FONTFLAG_SYMBOL;
+ }
+ if (fontdata->GetInt( "antialias" ) && g_pSurface->SupportsFeature(ISurface::ANTIALIASED_FONTS))
+ {
+ flags |= ISurface::FONTFLAG_ANTIALIAS;
+ }
+ if (fontdata->GetInt( "dropshadow" ) && g_pSurface->SupportsFeature(ISurface::DROPSHADOW_FONTS))
+ {
+ flags |= ISurface::FONTFLAG_DROPSHADOW;
+ }
+ if (fontdata->GetInt( "outline" ) && g_pSurface->SupportsFeature(ISurface::OUTLINE_FONTS))
+ {
+ flags |= ISurface::FONTFLAG_OUTLINE;
+ }
+ if (fontdata->GetInt( "custom" ))
+ {
+ flags |= ISurface::FONTFLAG_CUSTOM;
+ }
+ if (fontdata->GetInt( "bitmap" ))
+ {
+ flags |= ISurface::FONTFLAG_BITMAP;
+ }
+ if (fontdata->GetInt( "rotary" ))
+ {
+ flags |= ISurface::FONTFLAG_ROTARY;
+ }
+ if (fontdata->GetInt( "additive" ))
+ {
+ flags |= ISurface::FONTFLAG_ADDITIVE;
+ }
+
+ int tall = fontdata->GetInt( "tall" );
+ int blur = fontdata->GetInt( "blur" );
+ int scanlines = fontdata->GetInt( "scanlines" );
+ float scalex = fontdata->GetFloat( "scalex", 1.0f );
+ float scaley = fontdata->GetFloat( "scaley", 1.0f );
+
+ // only grow this font if it doesn't have a resolution filter specified
+ if ( ( !fontYResMin && !fontYResMax ) && m_FontAliases[i].m_bProportional )
+ {
+ tall = g_Scheme.GetProportionalScaledValueEx( this, tall );
+ blur = g_Scheme.GetProportionalScaledValueEx( this, blur );
+ scanlines = g_Scheme.GetProportionalScaledValueEx( this, scanlines );
+ scalex = g_Scheme.GetProportionalScaledValueEx( this, scalex * 10000.0f ) * 0.0001f;
+ scaley = g_Scheme.GetProportionalScaledValueEx( this, scaley * 10000.0f ) * 0.0001f;
+ }
+
+ // clip the font size so that fonts can't be too big
+ if ( tall > 127 )
+ {
+ tall = 127;
+ }
+
+ // check our minimum font height
+ if ( tall < minimumFontHeight )
+ {
+ tall = minimumFontHeight;
+ }
+
+ if ( flags & ISurface::FONTFLAG_BITMAP )
+ {
+ // add the new set
+ g_pSurface->SetBitmapFontGlyphSet(
+ m_FontAliases[i]._font,
+ g_pSurface->GetBitmapFontName( fontdata->GetString( "name" ) ),
+ scalex,
+ scaley,
+ flags);
+ }
+ else
+ {
+ int nRangeMin, nRangeMax;
+
+ if ( GetFontRange( fontdata->GetString( "name" ), nRangeMin, nRangeMax ) )
+ {
+ // add the new set
+ g_pSurface->SetFontGlyphSet(
+ m_FontAliases[i]._font,
+ fontdata->GetString( "name" ),
+ tall,
+ fontdata->GetInt( "weight" ),
+ blur,
+ scanlines,
+ flags,
+ nRangeMin,
+ nRangeMax);
+ }
+ else
+ {
+ // add the new set
+ g_pSurface->SetFontGlyphSet(
+ m_FontAliases[i]._font,
+ fontdata->GetString( "name" ),
+ tall,
+ fontdata->GetInt( "weight" ),
+ blur,
+ scanlines,
+ flags);
+ }
+ }
+
+ // don't add any more
+ break;
+ }
+ }
+
+ COM_TimestampedLog( "ReloadFontGlyphs(): End" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: create the Border objects from the scheme data
+//-----------------------------------------------------------------------------
+void CScheme::LoadBorders()
+{
+ m_pkvBorders = m_pData->FindKey("Borders", true);
+ {for ( KeyValues *kv = m_pkvBorders->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
+ {
+ if (kv->GetDataType() == KeyValues::TYPE_STRING)
+ {
+ // it's referencing another border, ignore for now
+ }
+ else
+ {
+ int i = m_BorderList.AddToTail();
+
+ IBorder *border = NULL;
+ const char *pszBorderType = kv->GetString( "bordertype", NULL );
+ if ( pszBorderType && pszBorderType[0] )
+ {
+ if ( !stricmp(pszBorderType,"image") )
+ {
+ border = new ImageBorder();
+ }
+ else if ( !stricmp(pszBorderType,"scalable_image") )
+ {
+ border = new ScalableImageBorder();
+ }
+ else
+ {
+ Assert(0);
+ // Fall back to the base border type. See below.
+ pszBorderType = NULL;
+ }
+ }
+
+ if ( !pszBorderType || !pszBorderType[0] )
+ {
+ border = new Border();
+ }
+
+ border->SetName(kv->GetName());
+ border->ApplySchemeSettings(this, kv);
+
+ m_BorderList[i].border = border;
+ m_BorderList[i].bSharedBorder = false;
+ m_BorderList[i].borderSymbol = kv->GetNameSymbol();
+ }
+ }}
+
+ // iterate again to get the border references
+ for ( KeyValues *kv = m_pkvBorders->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
+ {
+ if (kv->GetDataType() == KeyValues::TYPE_STRING)
+ {
+ // it's referencing another border, find it
+ Border *border = (Border *)GetBorder(kv->GetString());
+// const char *str = kv->GetName();
+ Assert(border);
+
+ // add an entry that just references the existing border
+ int i = m_BorderList.AddToTail();
+ m_BorderList[i].border = border;
+ m_BorderList[i].bSharedBorder = true;
+ m_BorderList[i].borderSymbol = kv->GetNameSymbol();
+ }
+ }
+
+ m_pBaseBorder = GetBorder("BaseBorder");
+}
+
+void CScheme::SpewFonts( void )
+{
+ Msg( "Scheme: %s (%s)\n", GetName(), GetFileName() );
+ FOR_EACH_DICT_FAST( m_FontAliases, i )
+ {
+ const fontalias_t& FontAlias = m_FontAliases[ i ];
+ uint32 Font = FontAlias._font;
+ const char *szFontName = g_pSurface->GetFontName( Font );
+ const char *szFontFamilyName = g_pSurface->GetFontFamilyName( Font );
+ const char *szTrueFontName = FontAlias._trueFontName.String();
+ const char *szFontAlias = m_FontAliases.GetElementName( i );
+
+ Msg( " %2d: HFont:0x%8.8x, %s, %s, font:%s, tall:%d(%d). %s\n",
+ i,
+ Font,
+ szTrueFontName ? szTrueFontName : "??",
+ szFontAlias ? szFontAlias : "??",
+ szFontName ? szFontName : "??",
+ g_pSurface->GetFontTall( Font ),
+ g_pSurface->GetFontTallRequested( Font ),
+ szFontFamilyName ? szFontFamilyName : "" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: reloads the scheme from the file
+//-----------------------------------------------------------------------------
+void CSchemeManager::ReloadSchemes()
+{
+ int count = m_Schemes.Count();
+ Shutdown( false );
+
+ // reload the scheme
+ for (int i = 1; i < count; i++)
+ {
+ LoadSchemeFromFile(m_Schemes[i]->GetFileName(), m_Schemes[i]->GetName());
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: kills all the schemes
+//-----------------------------------------------------------------------------
+void CScheme::Shutdown( bool full )
+{
+ for (int i = 0; i < m_BorderList.Count(); i++)
+ {
+ // delete if it's not shared
+ if (!m_BorderList[i].bSharedBorder)
+ {
+ IBorder *border = m_BorderList[i].border;
+ delete border;
+ }
+ }
+
+ m_pBaseBorder = NULL;
+ m_BorderList.RemoveAll();
+ m_pkvBorders = NULL;
+
+ if (full && m_pData)
+ {
+ m_pData->deleteThis();
+ m_pData = NULL;
+ delete this;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a handle to the default (first loaded) scheme
+//-----------------------------------------------------------------------------
+HScheme CSchemeManager::GetDefaultScheme()
+{
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a handle to the scheme identified by "tag"
+//-----------------------------------------------------------------------------
+HScheme CSchemeManager::GetScheme(const char *tag)
+{
+ for (int i=1;i<m_Schemes.Count();i++)
+ {
+ if ( !stricmp(tag,m_Schemes[i]->GetName()) )
+ {
+ return i;
+ }
+ }
+ return 1; // default scheme
+}
+
+int CSchemeManager::GetProportionalScaledValue_( int rootWide, int rootTall, int normalizedValue )
+{
+ int proH, proW;
+ g_pSurface->GetProportionalBase( proW, proH );
+ double scale = (double)rootTall / (double)proH;
+
+ return (int)( normalizedValue * scale );
+}
+
+int CSchemeManager::GetProportionalNormalizedValue_( int rootWide, int rootTall, int scaledValue )
+{
+ int proH, proW;
+ g_pSurface->GetProportionalBase( proW, proH );
+ float scale = (float)rootTall / (float)proH;
+
+ return (int)( scaledValue / scale );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: converts a value into proportional mode
+//-----------------------------------------------------------------------------
+int CSchemeManager::GetProportionalScaledValue(int normalizedValue)
+{
+ int wide, tall;
+ g_pSurface->GetScreenSize( wide, tall );
+ return GetProportionalScaledValue_( wide, tall, normalizedValue );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: converts a value out of proportional mode
+//-----------------------------------------------------------------------------
+int CSchemeManager::GetProportionalNormalizedValue(int scaledValue)
+{
+ int wide, tall;
+ g_pSurface->GetScreenSize( wide, tall );
+ return GetProportionalNormalizedValue_( wide, tall, scaledValue );
+}
+
+// gets the proportional coordinates for doing screen-size independant panel layouts
+// use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
+int CSchemeManager::GetProportionalScaledValueEx( CScheme *pScheme, int normalizedValue )
+{
+ VPANEL sizing = pScheme->GetSizingPanel();
+ if ( !sizing )
+ {
+ return GetProportionalScaledValue( normalizedValue );
+ }
+
+ int w, h;
+ g_pIPanel->GetSize( sizing, w, h );
+ return GetProportionalScaledValue_( w, h, normalizedValue );
+}
+
+int CSchemeManager::GetProportionalNormalizedValueEx( CScheme *pScheme, int scaledValue )
+{
+ VPANEL sizing = pScheme->GetSizingPanel();
+ if ( !sizing )
+ {
+ return GetProportionalNormalizedValue( scaledValue );
+ }
+
+ int w, h;
+ g_pIPanel->GetSize( sizing, w, h );
+ return GetProportionalNormalizedValue_( w, h, scaledValue );
+}
+
+int CSchemeManager::GetProportionalScaledValueEx( HScheme scheme, int normalizedValue )
+{
+ IScheme *pscheme = GetIScheme( scheme );
+ if ( !pscheme )
+ {
+ Assert( 0 );
+ return GetProportionalScaledValue( normalizedValue );
+ }
+
+ CScheme *p = static_cast< CScheme * >( pscheme );
+ return GetProportionalScaledValueEx( p, normalizedValue );
+}
+
+int CSchemeManager::GetProportionalNormalizedValueEx( HScheme scheme, int scaledValue )
+{
+ IScheme *pscheme = GetIScheme( scheme );
+ if ( !pscheme )
+ {
+ Assert( 0 );
+ return GetProportionalNormalizedValue( scaledValue );
+ }
+
+ CScheme *p = static_cast< CScheme * >( pscheme );
+ return GetProportionalNormalizedValueEx( p, scaledValue );
+}
+
+void CSchemeManager::SpewFonts( void )
+{
+ for ( int i = 1; i < m_Schemes.Count(); i++ )
+ {
+ m_Schemes[i]->SpewFonts();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *CScheme::GetResourceString(const char *stringName)
+{
+ return m_pkvBaseSettings->GetString(stringName);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to an image
+//-----------------------------------------------------------------------------
+IImage *CSchemeManager::GetImage(const char *imageName, bool hardwareFiltered)
+{
+ if ( !imageName || strlen(imageName) <= 0 ) // frame icons and the like are in the scheme file and may not be defined, so if this is null then fail silently
+ {
+ return NULL;
+ }
+
+ // set up to search for the bitmap
+ CachedBitmapHandle_t searchBitmap;
+ searchBitmap.pBitmap = NULL;
+
+ // Prepend 'vgui/'. Resource files try to load images assuming they live in the vgui directory.
+ // Used to do this in Bitmap::Bitmap, moved so that the s_pszSearchString is searching for the
+ // filename with 'vgui/' already added.
+ char szFileName[MAX_PATH];
+
+ //if ( Q_IsAbsolutePath(imageName) )
+ //{
+ // Q_strncpy( szFileName, imageName, sizeof(szFileName) );
+ //}
+ //else
+ {
+ if ( Q_stristr( imageName, ".pic" ) )
+ {
+ Q_snprintf( szFileName, sizeof(szFileName), "%s", imageName );
+ }
+ else
+ {
+ Q_snprintf( szFileName, sizeof(szFileName), "vgui/%s", imageName );
+ }
+ }
+
+ s_pszSearchString = szFileName;
+ int i = m_Bitmaps.Find( searchBitmap );
+ if (m_Bitmaps.IsValidIndex( i ) )
+ {
+ return m_Bitmaps[i].pBitmap;
+ }
+
+ // couldn't find the image, try and load it
+ CachedBitmapHandle_t hBitmap = { new Bitmap( szFileName, hardwareFiltered ) };
+ m_Bitmaps.Insert( hBitmap );
+ return hBitmap.pBitmap;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+HTexture CSchemeManager::GetImageID(const char *imageName, bool hardwareFiltered)
+{
+ IImage *img = GetImage(imageName, hardwareFiltered);
+ return ((Bitmap *)img)->GetID();
+}
+
+//-----------------------------------------------------------------------------
+// Delete a managed image
+//-----------------------------------------------------------------------------
+bool CSchemeManager::DeleteImage( const char *pImageName )
+{
+ if ( !pImageName )
+ {
+ // nothing to do
+ return false;
+ }
+
+ // set up to search for the bitmap
+ CachedBitmapHandle_t searchBitmap;
+ searchBitmap.pBitmap = NULL;
+
+ // Prepend 'vgui/'. Resource files try to load images assuming they live in the vgui directory.
+ // Used to do this in Bitmap::Bitmap, moved so that the s_pszSearchString is searching for the
+ // filename with 'vgui/' already added.
+ char szFileName[256];
+ if ( Q_stristr( pImageName, ".pic" ) )
+ {
+ Q_snprintf( szFileName, sizeof(szFileName), "%s", pImageName );
+ }
+ else
+ {
+ Q_snprintf( szFileName, sizeof(szFileName), "vgui/%s", pImageName );
+ }
+ s_pszSearchString = szFileName;
+
+ int i = m_Bitmaps.Find( searchBitmap );
+ if ( !m_Bitmaps.IsValidIndex( i ) )
+ {
+ // not found
+ return false;
+ }
+
+ // no way to know if eviction occured, assume it does
+ m_Bitmaps[i].pBitmap->Evict();
+ delete m_Bitmaps[i].pBitmap;
+ m_Bitmaps.RemoveAt( i );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to an existing border
+//-----------------------------------------------------------------------------
+IBorder *CScheme::GetBorder(const char *borderName)
+{
+ int symbol = KeyValuesSystem()->GetSymbolForString(borderName);
+ for (int i = 0; i < m_BorderList.Count(); i++)
+ {
+ if (m_BorderList[i].borderSymbol == symbol)
+ {
+ return m_BorderList[i].border;
+ }
+ }
+
+ return m_pBaseBorder;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the number of borders
+//-----------------------------------------------------------------------------
+int CScheme::GetBorderCount() const
+{
+ return m_BorderList.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the border at the given index
+//-----------------------------------------------------------------------------
+IBorder *CScheme::GetBorderAtIndex( int iIndex )
+{
+ if ( !m_BorderList.IsValidIndex( iIndex ) )
+ return NULL;
+
+ return m_BorderList[ iIndex ].border;
+}
+
+//-----------------------------------------------------------------------------
+// Finds a font in the alias list
+//-----------------------------------------------------------------------------
+HFont CScheme::FindFontInAliasList( const char *fontName )
+{
+ int i = m_FontAliases.Find( fontName );
+ if ( i != m_FontAliases.InvalidIndex() )
+ {
+ return m_FontAliases[i]._font;
+ }
+
+ // No dice
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : font -
+// Output : char const
+//-----------------------------------------------------------------------------
+char const *CScheme::GetFontName( const HFont& font )
+{
+ for (int i = m_FontAliases.Count(); --i >= 0; )
+ {
+ HFont fnt = (HFont)m_FontAliases[i]._font;
+ if ( fnt == font )
+ return m_FontAliases[i]._trueFontName.String();
+ }
+
+ return "<Unknown font>";
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to an existing font, proportional=false means use default
+//-----------------------------------------------------------------------------
+HFont CScheme::GetFont( const char *fontName, bool proportional )
+{
+ // First look in the list of aliases...
+ return FindFontInAliasList( GetMungedFontName( fontName, tag, proportional ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:Get the number of fonts
+//-----------------------------------------------------------------------------
+int CScheme::GetFontCount() const
+{
+ return m_FontAliases.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the font at the given index
+//-----------------------------------------------------------------------------
+HFont CScheme::GetFontAtIndex( int iIndex )
+{
+ if ( !m_FontAliases.IsValidIndex( iIndex ) )
+ return INVALID_FONT;
+
+ return m_FontAliases[ iIndex ]._font;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a char string of the munged name this font is stored as in the font manager
+//-----------------------------------------------------------------------------
+const char *CScheme::GetMungedFontName( const char *fontName, const char *scheme, bool proportional )
+{
+ static char mungeBuffer[ 64 ];
+ if ( scheme )
+ {
+ Q_snprintf( mungeBuffer, sizeof( mungeBuffer ), "%s%s-%s", fontName, scheme, proportional ? "p" : "no" );
+ }
+ else
+ {
+ Q_snprintf( mungeBuffer, sizeof( mungeBuffer ), "%s-%s", fontName, proportional ? "p" : "no" ); // we don't want the "(null)" snprintf appends
+ }
+ return mungeBuffer;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets a color from the scheme file
+//-----------------------------------------------------------------------------
+Color CScheme::GetColor(const char *colorName, Color defaultColor)
+{
+ const char *pchT = LookupSchemeSetting(colorName);
+ if (!pchT)
+ return defaultColor;
+
+ int r = 0, g = 0, b = 0, a = 0;
+ if (sscanf(pchT, "%d %d %d %d", &r, &g, &b, &a) >= 3)
+ return Color(r, g, b, a);
+
+ return defaultColor;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the color at the given index
+//-----------------------------------------------------------------------------
+const KeyValues *CScheme::GetColorData() const
+{
+ return m_pkvColors;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: recursively looks up a setting
+//-----------------------------------------------------------------------------
+const char *CScheme::LookupSchemeSetting(const char *pchSetting)
+{
+ // try parse out the color
+ int r, g, b, a = 0;
+ int res = sscanf(pchSetting, "%d %d %d %d", &r, &g, &b, &a);
+ if (res >= 3)
+ {
+ return pchSetting;
+ }
+
+ // check the color area first
+ const char *colStr = m_pkvColors->GetString(pchSetting, NULL);
+ if (colStr)
+ return colStr;
+
+ // check base settings
+ colStr = m_pkvBaseSettings->GetString(pchSetting, NULL);
+ if (colStr)
+ {
+ return LookupSchemeSetting(colStr);
+ }
+
+ return pchSetting;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: gets the minimum font height for the current language
+//-----------------------------------------------------------------------------
+int CScheme::GetMinimumFontHeightForCurrentLanguage()
+{
+ char language[64];
+ bool bValid;
+ if ( IsPC() )
+ {
+ bValid = vgui::g_pSystem->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Source\\Language", language, sizeof(language)-1 );
+ }
+ else
+ {
+ Q_strncpy( language, XBX_GetLanguageString(), sizeof( language ) );
+ bValid = true;
+ }
+
+ if ( bValid )
+ {
+ if (!stricmp(language, "korean")
+ || !stricmp(language, "tchinese")
+ || !stricmp(language, "schinese")
+ || !stricmp(language, "japanese"))
+ {
+ // the bitmap-based fonts for these languages simply don't work with a pt. size of less than 9 (13 pixels)
+ return 13;
+ }
+
+ if ( !stricmp(language, "thai" ) )
+ {
+ // thai has problems below 18 pts
+ return 18;
+ }
+ }
+
+ // no special minimum height required
+ return 0;
+}