diff options
Diffstat (limited to 'vgui2/src/Scheme.cpp')
| -rw-r--r-- | vgui2/src/Scheme.cpp | 1532 |
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; +} |