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.

404 lines
14 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Xbox 360 support for TrueType Fonts. The only cuurent solution is to use XUI
  4. // to mount the TTF, and rasterize glyph into a render target. XUI does not support
  5. // rasterization directly to a system memory region.
  6. //
  7. //=====================================================================================//
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <math.h>
  11. #include <malloc.h>
  12. #include <tier0/dbg.h>
  13. #include <vgui/ISurface.h>
  14. #include <tier0/mem.h>
  15. #include <utlbuffer.h>
  16. #include "filesystem.h"
  17. #include "materialsystem/imaterialsystem.h"
  18. #include "FontEffects.h"
  19. #include "vgui_surfacelib/vguifont.h"
  20. #include "vgui_surfacelib/FontManager.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. bool s_bSupportsUnicode = true;
  24. //-----------------------------------------------------------------------------
  25. // Determine possible style from parameters.
  26. //-----------------------------------------------------------------------------
  27. int GetStyleFromParameters( int iFlags, int iWeight )
  28. {
  29. // Available xbox TTF styles are very restricted.
  30. int style = XUI_FONT_STYLE_NORMAL;
  31. if ( iFlags & FONTFLAG_ITALIC )
  32. style |= XUI_FONT_STYLE_ITALIC;
  33. if ( iFlags & FONTFLAG_UNDERLINE )
  34. style |= XUI_FONT_STYLE_UNDERLINE;
  35. if ( iWeight > 400 )
  36. style |= XUI_FONT_STYLE_BOLD;
  37. return style;
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Constructor
  41. //-----------------------------------------------------------------------------
  42. CWin32Font::CWin32Font() : m_ExtendedABCWidthsCache( 256, 0, &ExtendedABCWidthsCacheLessFunc )
  43. {
  44. m_szName = UTL_INVAL_SYMBOL;
  45. m_iTall = 0;
  46. m_iWeight = 0;
  47. m_iHeight = 0;
  48. m_iAscent = 0;
  49. m_iFlags = 0;
  50. m_iMaxCharWidth = 0;
  51. m_hFont = NULL;
  52. m_hDC = NULL;
  53. m_bAntiAliased = false;
  54. m_bUnderlined = false;
  55. m_iBlur = 0;
  56. m_iScanLines = 0;
  57. m_bRotary = false;
  58. m_bAdditive = false;
  59. m_rgiBitmapSize[0] = 0;
  60. m_rgiBitmapSize[1] = 0;
  61. s_bSupportsUnicode = true;
  62. Q_memset( m_ABCWidthsCache, 0, sizeof( m_ABCWidthsCache ) );
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Destructor
  66. //-----------------------------------------------------------------------------
  67. CWin32Font::~CWin32Font()
  68. {
  69. CloseResource();
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose: Creates the font.
  73. //-----------------------------------------------------------------------------
  74. bool CWin32Font::Create( const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags )
  75. {
  76. // setup font properties
  77. m_iTall = tall;
  78. m_iWeight = weight;
  79. m_iFlags = flags;
  80. m_bAntiAliased = (flags & FONTFLAG_ANTIALIAS) ? 1 : 0;
  81. m_bUnderlined = (flags & FONTFLAG_UNDERLINE) ? 1 : 0;
  82. m_iDropShadowOffset = (flags & FONTFLAG_DROPSHADOW) ? 1 : 0;
  83. m_iOutlineSize = (flags & FONTFLAG_OUTLINE) ? 1 : 0;
  84. m_iBlur = blur;
  85. m_iScanLines = scanlines;
  86. m_bRotary = (flags & FONTFLAG_ROTARY) ? 1 : 0;
  87. m_bAdditive = (flags & FONTFLAG_ADDITIVE) ? 1 : 0;
  88. int style = GetStyleFromParameters( flags, weight );
  89. // must support > 128, there are characters in this range in the custom fonts
  90. COMPILE_TIME_ASSERT( ABCWIDTHS_CACHE_SIZE == 256 );
  91. XUIFontMetrics fontMetrics;
  92. XUICharMetrics charMetrics[256];
  93. // many redundant requests are made that are actually the same font metrics
  94. // find it in the metric cache first based on the true specific keys
  95. if ( !FontManager().GetCachedXUIMetrics( windowsFontName, tall, style, &fontMetrics, charMetrics ) )
  96. {
  97. m_hFont = FontManager().MaterialSystem()->OpenTrueTypeFont( windowsFontName, tall, style );
  98. if ( !m_hFont )
  99. {
  100. return false;
  101. }
  102. // get the predominant font metrics now [1-255], the extended set [256-65535] is on-demand
  103. FontManager().MaterialSystem()->GetTrueTypeFontMetrics( m_hFont, 1, 255, &fontMetrics, &charMetrics[1] );
  104. // getting the metrics is an expensive i/o operation, cache results
  105. FontManager().SetCachedXUIMetrics( windowsFontName, tall, style, &fontMetrics, charMetrics );
  106. }
  107. m_szName = windowsFontName;
  108. m_iHeight = fontMetrics.fMaxHeight + m_iDropShadowOffset + 2 * m_iOutlineSize;
  109. m_iMaxCharWidth = fontMetrics.fMaxWidth;
  110. m_iAscent = fontMetrics.fMaxAscent;
  111. // determine cell bounds
  112. m_rgiBitmapSize[0] = m_iMaxCharWidth + m_iOutlineSize * 2;
  113. m_rgiBitmapSize[1] = m_iHeight;
  114. // get char spacing
  115. // a is space before character (can be negative)
  116. // b is the width of the character
  117. // c is the space after the character
  118. Assert( ABCWIDTHS_CACHE_SIZE <= 256 );
  119. Q_memset( m_ABCWidthsCache, 0, sizeof( m_ABCWidthsCache ) );
  120. for ( int i = 1; i < ABCWIDTHS_CACHE_SIZE; i++ )
  121. {
  122. int a,b,c;
  123. // Determine real a,b,c mapping from XUI Character Metrics
  124. a = charMetrics[i].fMinX - 1; // Add one column of padding to make up for font rendering blurring into left column (and adjust in b)
  125. b = charMetrics[i].fMaxX - charMetrics[i].fMinX + 1;
  126. c = charMetrics[i].fAdvance - charMetrics[i].fMaxX; // NOTE: We probably should add a column here, but it's rarely needed in our current fonts so we're opting to save memory instead
  127. // Widen for blur, outline, and shadow. Need to widen b and reduce a and c.
  128. m_ABCWidthsCache[i].a = a - m_iBlur - m_iOutlineSize;
  129. m_ABCWidthsCache[i].b = b + ( ( m_iBlur + m_iOutlineSize ) * 2 ) + m_iDropShadowOffset;
  130. m_ABCWidthsCache[i].c = c - m_iBlur - m_iDropShadowOffset - m_iOutlineSize;
  131. }
  132. return true;
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Purpose: generates texture data (written into appropriate font page subrects) for multiple chars
  136. //-----------------------------------------------------------------------------
  137. void CWin32Font::GetCharsRGBA( newChar_t *newChars, int numNewChars, unsigned char *pRGBA )
  138. {
  139. if ( !m_hFont )
  140. {
  141. // demand request for font glyph, re-create font
  142. int style = GetStyleFromParameters( m_iFlags, m_iWeight );
  143. m_hFont = FontManager().MaterialSystem()->OpenTrueTypeFont( GetName(), m_iTall, style );
  144. }
  145. wchar_t *pWch = (wchar_t *)_alloca( numNewChars*sizeof(wchar_t) );
  146. int *pOffsetX = (int *)_alloca( numNewChars*sizeof(int) );
  147. int *pOffsetY = (int *)_alloca( numNewChars*sizeof(int) );
  148. int *pWidth = (int *)_alloca( numNewChars*sizeof(int) );
  149. int *pHeight = (int *)_alloca( numNewChars*sizeof(int) );
  150. int *pRGBAOffset = (int *)_alloca( numNewChars*sizeof(int) );
  151. for ( int i = 0; i < numNewChars; i++ )
  152. {
  153. int a, c, wide;
  154. GetCharABCWidths( newChars[i].wch, a, wide, c );
  155. pWch[i] = newChars[i].wch;
  156. pOffsetX[i] = -a;
  157. pOffsetY[i] = 0;
  158. pWidth[i] = newChars[i].fontWide;
  159. pHeight[i] = newChars[i].fontTall;
  160. pRGBAOffset[i] = newChars[i].offset;
  161. }
  162. if ( !FontManager().MaterialSystem()->GetTrueTypeGlyphs( m_hFont, numNewChars, pWch, pOffsetX, pOffsetY, pWidth, pHeight, pRGBA, pRGBAOffset ) )
  163. {
  164. // failure
  165. return;
  166. }
  167. for ( int i = 0; i < numNewChars; i++ )
  168. {
  169. // apply requested effects in specified order
  170. unsigned char *pCharRGBA = pRGBA + newChars[i].offset;
  171. ApplyDropShadowToTexture( newChars[i].fontWide, newChars[i].fontTall, pCharRGBA, m_iDropShadowOffset );
  172. ApplyOutlineToTexture( newChars[i].fontWide, newChars[i].fontTall, pCharRGBA, m_iOutlineSize );
  173. ApplyGaussianBlurToTexture( newChars[i].fontWide, newChars[i].fontTall, pCharRGBA, m_iBlur );
  174. ApplyScanlineEffectToTexture( newChars[i].fontWide, newChars[i].fontTall, pCharRGBA, m_iScanLines );
  175. ApplyRotaryEffectToTexture( newChars[i].fontWide, newChars[i].fontTall, pCharRGBA, m_bRotary );
  176. }
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose: writes the char into the specified 32bpp texture at specified rect
  180. //-----------------------------------------------------------------------------
  181. void CWin32Font::GetCharRGBA( wchar_t ch, int rgbaWide, int rgbaTall, unsigned char *pRGBA )
  182. {
  183. newChar_t newChar;
  184. newChar.wch = ch;
  185. newChar.fontWide = rgbaWide;
  186. newChar.fontTall = rgbaTall;
  187. newChar.offset = 0;
  188. GetCharsRGBA( &newChar, 1, pRGBA );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose: returns true if the font is equivalent to that specified
  192. //-----------------------------------------------------------------------------
  193. bool CWin32Font::IsEqualTo(const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags)
  194. {
  195. // do an true comparison that accounts for non-supported behaviors that gets remapped
  196. // avoids creating fonts that are graphically equivalent, though specified differently
  197. if ( !stricmp( windowsFontName, m_szName.String() ) &&
  198. m_iTall == tall &&
  199. m_iBlur == blur &&
  200. m_iScanLines == scanlines )
  201. {
  202. // only these flags affect the font glyphs
  203. int validFlags = FONTFLAG_DROPSHADOW |
  204. FONTFLAG_OUTLINE |
  205. FONTFLAG_ROTARY |
  206. FONTFLAG_ITALIC |
  207. FONTFLAG_UNDERLINE;
  208. if ( ( m_iFlags & validFlags ) == ( flags & validFlags ) )
  209. {
  210. if ( GetStyleFromParameters( m_iFlags, m_iWeight ) == GetStyleFromParameters( flags, weight ) )
  211. {
  212. // the font is equivalent
  213. return true;
  214. }
  215. }
  216. }
  217. return false;
  218. }
  219. //-----------------------------------------------------------------------------
  220. // Purpose: returns true only if this font is valid for use
  221. //-----------------------------------------------------------------------------
  222. bool CWin32Font::IsValid()
  223. {
  224. if ( m_szName != UTL_INVAL_SYMBOL )
  225. return true;
  226. return false;
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose: set the font to be the one to currently draw with in the gdi
  230. //-----------------------------------------------------------------------------
  231. void CWin32Font::SetAsActiveFont( HDC hdc )
  232. {
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose: gets the abc widths for a character
  236. //-----------------------------------------------------------------------------
  237. void CWin32Font::GetCharABCWidths( int ch, int &a, int &b, int &c )
  238. {
  239. Assert( IsValid() );
  240. if ( ch < ABCWIDTHS_CACHE_SIZE )
  241. {
  242. // use the cache entry
  243. a = m_ABCWidthsCache[ch].a;
  244. b = m_ABCWidthsCache[ch].b;
  245. c = m_ABCWidthsCache[ch].c;
  246. }
  247. else
  248. {
  249. // look for it in the extended cache
  250. abc_cache_t finder = { (wchar_t)ch };
  251. unsigned short i = m_ExtendedABCWidthsCache.Find( finder );
  252. if ( m_ExtendedABCWidthsCache.IsValidIndex( i ) )
  253. {
  254. a = m_ExtendedABCWidthsCache[i].abc.a;
  255. b = m_ExtendedABCWidthsCache[i].abc.b;
  256. c = m_ExtendedABCWidthsCache[i].abc.c;
  257. return;
  258. }
  259. // not in the cache, get from system
  260. // getting the metrics is an expensive i/o operation
  261. if ( !m_hFont )
  262. {
  263. // demand request for font metrics, re-open font
  264. int style = GetStyleFromParameters( m_iFlags, m_iWeight );
  265. m_hFont = FontManager().MaterialSystem()->OpenTrueTypeFont( GetName(), m_iTall, style );
  266. }
  267. if ( m_hFont )
  268. {
  269. XUIFontMetrics fontMetrics;
  270. XUICharMetrics charMetrics;
  271. FontManager().MaterialSystem()->GetTrueTypeFontMetrics( m_hFont, ch, ch, &fontMetrics, &charMetrics );
  272. // Determine real a,b,c mapping from XUI Character Metrics
  273. a = charMetrics.fMinX - 1; // Add one column of padding to make up for font rendering blurring into left column (and adjust in b)
  274. b = charMetrics.fMaxX - charMetrics.fMinX + 1;
  275. c = charMetrics.fAdvance - charMetrics.fMaxX; // NOTE: We probably should add a column here, but it's rarely needed in our current fonts so we're opting to save memory instead
  276. // Widen for blur, outline, and shadow. Need to widen b and reduce a and c.
  277. a = a - m_iBlur - m_iOutlineSize;
  278. b = b + ( ( m_iBlur + m_iOutlineSize ) * 2 ) + m_iDropShadowOffset;
  279. c = c - m_iBlur - m_iDropShadowOffset - m_iOutlineSize;
  280. }
  281. else
  282. {
  283. a = 0;
  284. b = 0;
  285. c = 0;
  286. }
  287. // add to the cache
  288. finder.abc.a = a;
  289. finder.abc.b = b;
  290. finder.abc.c = c;
  291. m_ExtendedABCWidthsCache.Insert( finder );
  292. }
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Purpose: returns the height of the font, in pixels
  296. //-----------------------------------------------------------------------------
  297. int CWin32Font::GetHeight()
  298. {
  299. Assert( IsValid() );
  300. return m_iHeight;
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: returns the ascent of the font, in pixels (ascent=units above the base line)
  304. //-----------------------------------------------------------------------------
  305. int CWin32Font::GetAscent()
  306. {
  307. Assert( IsValid() );
  308. return m_iAscent;
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose: returns the maximum width of a character, in pixels
  312. //-----------------------------------------------------------------------------
  313. int CWin32Font::GetMaxCharWidth()
  314. {
  315. Assert( IsValid() );
  316. return m_iMaxCharWidth;
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Purpose: returns the flags used to make this font, used by the dynamic resizing code
  320. //-----------------------------------------------------------------------------
  321. int CWin32Font::GetFlags()
  322. {
  323. Assert( IsValid() );
  324. return m_iFlags;
  325. }
  326. void CWin32Font::CloseResource()
  327. {
  328. if ( !m_hFont )
  329. {
  330. return;
  331. }
  332. // many fonts are blindly precached by vgui and never used
  333. // save memory and don't hold font open, re-open if glyph actually requested used during draw
  334. FontManager().MaterialSystem()->CloseTrueTypeFont( m_hFont );
  335. m_hFont = NULL;
  336. }
  337. //-----------------------------------------------------------------------------
  338. // Purpose: Comparison function for abc widths storage
  339. //-----------------------------------------------------------------------------
  340. bool CWin32Font::ExtendedABCWidthsCacheLessFunc( const abc_cache_t &lhs, const abc_cache_t &rhs )
  341. {
  342. return lhs.wch < rhs.wch;
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Purpose: Get the kerned size of a char, for win32 just pass thru for now
  346. //-----------------------------------------------------------------------------
  347. void CWin32Font::GetKernedCharWidth( wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &abcA, float &abcC )
  348. {
  349. int a,b,c;
  350. GetCharABCWidths(ch, a, b, c );
  351. wide = ( a + b + c);
  352. abcA = a;
  353. abcC = c;
  354. }