Team Fortress 2 Source Code as on 22/4/2020
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.

324 lines
9.8 KiB

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