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

340 lines
9.8 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: XBox Compiled Bitmap Fonts
  4. //
  5. //=============================================================================//
  6. // conversion from 'double' to 'float', possible loss of data
  7. #pragma warning( disable : 4244 )
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #if !defined( _PS3 )
  13. #include <malloc.h>
  14. #endif // ! _PS3
  15. #include "vgui_surfacelib/BitmapFont.h"
  16. #include "vgui_surfacelib/fontmanager.h"
  17. #include "tier0/dbg.h"
  18. #include "vgui_surfacelib/ifontsurface.h"
  19. #include "tier0/mem.h"
  20. #include "utlbuffer.h"
  21. #include "filesystem.h"
  22. #include "materialsystem/itexture.h"
  23. #include "rendersystem/irenderdevice.h"
  24. #include "resourcesystem/stronghandle.h"
  25. // memdbgon must be the last include file in a .cpp file!!!
  26. #include "tier0/memdbgon.h"
  27. struct BitmapFontTable_t
  28. {
  29. BitmapFontTable_t()
  30. {
  31. m_szName = UTL_INVAL_SYMBOL;
  32. m_pBitmapFont = NULL;
  33. m_pBitmapGlyphs = NULL;
  34. m_pTexture = NULL;
  35. }
  36. CUtlSymbol m_szName;
  37. BitmapFont_t *m_pBitmapFont;
  38. BitmapGlyph_t *m_pBitmapGlyphs;
  39. ITexture *m_pTexture;
  40. HRenderTextureStrong m_pTexture2;
  41. };
  42. static CUtlVector< BitmapFontTable_t > g_BitmapFontTable( 1, 4 );
  43. //-----------------------------------------------------------------------------
  44. // Purpose: Constructor
  45. //-----------------------------------------------------------------------------
  46. CBitmapFont::CBitmapFont()
  47. {
  48. m_scalex = 1.0f;
  49. m_scaley = 1.0f;
  50. m_bitmapFontHandle = g_BitmapFontTable.InvalidIndex();
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose: Destructor
  54. //-----------------------------------------------------------------------------
  55. CBitmapFont::~CBitmapFont()
  56. {
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Purpose: creates the font. returns false if the font cannot be mounted.
  60. //-----------------------------------------------------------------------------
  61. bool CBitmapFont::Create( const char *pFontFilename, float scalex, float scaley, int flags )
  62. {
  63. MEM_ALLOC_CREDIT();
  64. if ( !pFontFilename || !pFontFilename[0] )
  65. {
  66. return false;
  67. }
  68. CUtlSymbol symbol;
  69. char fontName[MAX_PATH];
  70. Q_FileBase( pFontFilename, fontName, MAX_PATH );
  71. Q_strlower( fontName );
  72. symbol = fontName;
  73. // find a match that can use same entries
  74. BitmapFontTable_t *pFontTable = NULL;
  75. for ( int i=0; i<g_BitmapFontTable.Count(); i++ )
  76. {
  77. if ( symbol == g_BitmapFontTable[i].m_szName )
  78. {
  79. m_bitmapFontHandle = i;
  80. pFontTable = &g_BitmapFontTable[m_bitmapFontHandle];
  81. break;
  82. }
  83. }
  84. if ( !pFontTable )
  85. {
  86. void *pBuf = NULL;
  87. int nLength;
  88. nLength = FontManager().FileSystem()->ReadFileEx( pFontFilename, "GAME", &pBuf );
  89. if ( nLength <= 0 || !pBuf )
  90. {
  91. // not found
  92. return false;
  93. }
  94. if ( ((BitmapFont_t*)pBuf)->m_id != LittleLong( BITMAPFONT_ID ) || ((BitmapFont_t*)pBuf)->m_Version != LittleLong( BITMAPFONT_VERSION ) )
  95. {
  96. // bad version
  97. return false;
  98. }
  99. if ( IsGameConsole() )
  100. {
  101. CByteswap swap;
  102. swap.ActivateByteSwapping( true );
  103. swap.SwapFieldsToTargetEndian( (BitmapFont_t*)pBuf );
  104. swap.SwapFieldsToTargetEndian( (BitmapGlyph_t*)((char*)pBuf + sizeof( BitmapFont_t )), ((BitmapFont_t*)pBuf)->m_NumGlyphs );
  105. }
  106. // create it
  107. m_bitmapFontHandle = g_BitmapFontTable.AddToTail();
  108. pFontTable = &g_BitmapFontTable[m_bitmapFontHandle];
  109. pFontTable->m_szName = fontName;
  110. pFontTable->m_pBitmapFont = new BitmapFont_t;
  111. memcpy( pFontTable->m_pBitmapFont, pBuf, sizeof( BitmapFont_t ) );
  112. pFontTable->m_pBitmapGlyphs = new BitmapGlyph_t[pFontTable->m_pBitmapFont->m_NumGlyphs];
  113. memcpy( pFontTable->m_pBitmapGlyphs, (unsigned char*)pBuf + sizeof(BitmapFont_t), pFontTable->m_pBitmapFont->m_NumGlyphs*sizeof(BitmapGlyph_t) );
  114. FontManager().FileSystem()->FreeOptimalReadBuffer( pBuf );
  115. // load the art resources
  116. char textureName[MAX_PATH];
  117. Q_snprintf( textureName, MAX_PATH, "vgui/fonts/%s", fontName );
  118. if ( g_pMaterialSystem )
  119. {
  120. pFontTable->m_pTexture = FontManager().MaterialSystem()->FindTexture( textureName, TEXTURE_GROUP_VGUI );
  121. #if defined( DEVELOPMENT_ONLY ) || defined( ALLOW_TEXT_MODE )
  122. static bool s_bTextMode = CommandLine()->HasParm( "-textmode" );
  123. #else
  124. const bool s_bTextMode = false;
  125. #endif
  126. #if defined( _DEBUG ) && !defined( POSIX )
  127. if ( ( pFontTable->m_pBitmapFont->m_PageWidth != pFontTable->m_pTexture->GetActualWidth() ||
  128. pFontTable->m_pBitmapFont->m_PageHeight != pFontTable->m_pTexture->GetActualHeight() ) && !s_bTextMode )
  129. {
  130. // font is out of sync with its art
  131. Assert( 0 );
  132. return false;
  133. }
  134. #endif
  135. // the font texture lives forever, ensure it doesn't get purged
  136. pFontTable->m_pTexture->IncrementReferenceCount();
  137. }
  138. else
  139. {
  140. Assert(0); // TODO add support for materialsystem2
  141. }
  142. }
  143. // setup font properties
  144. m_scalex = scalex;
  145. m_scaley = scaley;
  146. // flags are derived from the baked font
  147. m_iFlags = FONTFLAG_BITMAP;
  148. int bitmapFlags = pFontTable->m_pBitmapFont->m_Flags;
  149. if ( bitmapFlags & BF_ANTIALIASED )
  150. {
  151. m_iFlags |= FONTFLAG_ANTIALIAS;
  152. }
  153. if ( bitmapFlags & BF_ITALIC )
  154. {
  155. m_iFlags |= FONTFLAG_ITALIC;
  156. }
  157. if ( bitmapFlags & BF_BLURRED )
  158. {
  159. m_iFlags |= FONTFLAG_GAUSSIANBLUR;
  160. m_iBlur = 1;
  161. }
  162. if ( bitmapFlags & BF_SCANLINES )
  163. {
  164. m_iScanLines = 1;
  165. }
  166. if ( bitmapFlags & BF_OUTLINED )
  167. {
  168. m_iFlags |= FONTFLAG_OUTLINE;
  169. m_iOutlineSize = 1;
  170. }
  171. if ( bitmapFlags & BF_DROPSHADOW )
  172. {
  173. m_iFlags |= FONTFLAG_DROPSHADOW;
  174. m_iDropShadowOffset = 1;
  175. }
  176. if ( flags & FONTFLAG_ADDITIVE )
  177. {
  178. m_bAdditive = true;
  179. m_iFlags |= FONTFLAG_ADDITIVE;
  180. }
  181. m_iMaxCharWidth = (float)pFontTable->m_pBitmapFont->m_MaxCharWidth * m_scalex;
  182. m_iHeight = (float)pFontTable->m_pBitmapFont->m_MaxCharHeight * m_scaley;
  183. m_iAscent = (float)pFontTable->m_pBitmapFont->m_Ascent * m_scaley;
  184. // mark as valid
  185. m_szName = fontName;
  186. return true;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // Purpose: returns true if the font is equivalent to that specified
  190. //-----------------------------------------------------------------------------
  191. bool CBitmapFont::IsEqualTo( const char *windowsFontName, float scalex, float scaley, int flags )
  192. {
  193. char fontname[MAX_PATH];
  194. Q_FileBase( windowsFontName, fontname, MAX_PATH );
  195. if ( !Q_stricmp( fontname, m_szName.String() ) &&
  196. m_scalex == scalex &&
  197. m_scaley == scaley )
  198. {
  199. int commonFlags = m_iFlags & flags;
  200. if ( commonFlags & FONTFLAG_ADDITIVE )
  201. {
  202. // an exact match
  203. return true;
  204. }
  205. }
  206. return false;
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose: sets the scale for a font
  210. //-----------------------------------------------------------------------------
  211. void CBitmapFont::SetScale( float sx, float sy )
  212. {
  213. m_scalex = sx;
  214. m_scaley = sy;
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Purpose: gets the abc widths for a character
  218. //-----------------------------------------------------------------------------
  219. void CBitmapFont::GetCharABCWidths( int ch, int &a, int &b, int &c )
  220. {
  221. Assert( IsValid() && ch >= 0 && ch <= 255 );
  222. BitmapFontTable_t *pFont = &g_BitmapFontTable[m_bitmapFontHandle];
  223. ch = pFont->m_pBitmapFont->m_TranslateTable[ch];
  224. a = (float)pFont->m_pBitmapGlyphs[ch].a * m_scalex;
  225. b = (float)pFont->m_pBitmapGlyphs[ch].b * m_scalex;
  226. c = (float)pFont->m_pBitmapGlyphs[ch].c * m_scalex;
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose: gets the abc widths for a character
  230. //-----------------------------------------------------------------------------
  231. void CBitmapFont::GetKernedCharWidth( wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &abcA, float &abcC )
  232. {
  233. int a, b, c;
  234. GetCharABCWidths( ch, a, b, c );
  235. wide = a+b+c;
  236. abcA = a;
  237. abcC = c;
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Purpose: gets the texcoords for a character
  241. //-----------------------------------------------------------------------------
  242. void CBitmapFont::GetCharCoords( int ch, float *left, float *top, float *right, float *bottom )
  243. {
  244. Assert( IsValid() && ch >= 0 && ch <= 255 );
  245. BitmapFontTable_t *pFont = &g_BitmapFontTable[m_bitmapFontHandle];
  246. ch = pFont->m_pBitmapFont->m_TranslateTable[ch];
  247. *left = (float)pFont->m_pBitmapGlyphs[ch].x/(float)pFont->m_pBitmapFont->m_PageWidth;
  248. *top = (float)pFont->m_pBitmapGlyphs[ch].y/(float)pFont->m_pBitmapFont->m_PageHeight;
  249. *right = (float)(pFont->m_pBitmapGlyphs[ch].x+pFont->m_pBitmapGlyphs[ch].w)/(float)pFont->m_pBitmapFont->m_PageWidth;
  250. *bottom = (float)(pFont->m_pBitmapGlyphs[ch].y+pFont->m_pBitmapGlyphs[ch].h)/(float)pFont->m_pBitmapFont->m_PageHeight;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose: gets the texture page
  254. //-----------------------------------------------------------------------------
  255. ITexture *CBitmapFont::GetTexturePage()
  256. {
  257. if ( g_pMaterialSystem )
  258. {
  259. Assert( IsValid() );
  260. return g_BitmapFontTable[m_bitmapFontHandle].m_pTexture;
  261. }
  262. else
  263. {
  264. return NULL;
  265. }
  266. }
  267. BEGIN_BYTESWAP_DATADESC( BitmapGlyph_t )
  268. DEFINE_FIELD( x, FIELD_SHORT ),
  269. DEFINE_FIELD( y, FIELD_SHORT ),
  270. DEFINE_FIELD( w, FIELD_SHORT ),
  271. DEFINE_FIELD( h, FIELD_SHORT ),
  272. DEFINE_FIELD( a, FIELD_SHORT ),
  273. DEFINE_FIELD( b, FIELD_SHORT ),
  274. DEFINE_FIELD( c, FIELD_SHORT ),
  275. END_BYTESWAP_DATADESC()
  276. BEGIN_BYTESWAP_DATADESC( BitmapFont_t )
  277. DEFINE_FIELD( m_id, FIELD_INTEGER ),
  278. DEFINE_FIELD( m_Version, FIELD_INTEGER ),
  279. DEFINE_FIELD( m_PageWidth, FIELD_SHORT ),
  280. DEFINE_FIELD( m_PageHeight, FIELD_SHORT ),
  281. DEFINE_FIELD( m_MaxCharWidth, FIELD_SHORT ),
  282. DEFINE_FIELD( m_MaxCharHeight, FIELD_SHORT ),
  283. DEFINE_FIELD( m_Flags, FIELD_SHORT ),
  284. DEFINE_FIELD( m_Ascent, FIELD_SHORT ),
  285. DEFINE_FIELD( m_NumGlyphs, FIELD_SHORT ),
  286. DEFINE_ARRAY( m_TranslateTable, FIELD_CHARACTER, 256 ),
  287. END_BYTESWAP_DATADESC()