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.

1484 lines
38 KiB

  1. //-----------------------------------------------------------------------------
  2. // Name: Glyphs.cpp
  3. //
  4. // Desc: Functions and global variables for keeping track of font glyphs
  5. //
  6. // Hist: 09.06.02 - Revised Fontmaker sample
  7. //
  8. // Copyright (c) Microsoft Corporation. All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "Glyphs.h"
  12. #include "FontMaker.h"
  13. const COLORREF COLOR_WHITE = RGB(255,255,255);
  14. const COLORREF COLOR_BLACK = RGB( 0, 0, 0);
  15. const COLORREF COLOR_BLUE = RGB( 0, 0,255);
  16. //-----------------------------------------------------------------------------
  17. // Name: CTextureFont()
  18. // Desc: Constructor
  19. //-----------------------------------------------------------------------------
  20. CTextureFont::CTextureFont()
  21. {
  22. ZeroMemory( this, sizeof( *this ) );
  23. m_bIncludeNullCharacter = TRUE;
  24. m_bAntialiasEffect = TRUE;
  25. // Texture info
  26. m_dwTextureWidth = 256;
  27. m_dwTextureHeight = 256;
  28. // Default glyph range
  29. WORD wStartGlyph = 32;
  30. WORD wEndGlyph = 255;
  31. ExtractValidGlyphsFromRange( wStartGlyph, wEndGlyph );
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Name: ~CTextureFont()
  35. // Desc: Destructor
  36. //-----------------------------------------------------------------------------
  37. CTextureFont::~CTextureFont()
  38. {
  39. DestroyObjects();
  40. if ( m_hFont )
  41. DeleteObject( m_hFont );
  42. if ( m_pBits )
  43. delete[] m_pBits;
  44. m_pBits = NULL;
  45. m_hFont = NULL;
  46. }
  47. //-----------------------------------------------------------------------------
  48. // ClearFont
  49. //-----------------------------------------------------------------------------
  50. void CTextureFont::ClearFont()
  51. {
  52. DestroyObjects();
  53. ZeroMemory( &m_LogFont, sizeof(LOGFONT) );
  54. m_strFontName[0] = '\0';
  55. m_hFont = NULL;
  56. m_dwTextureWidth = 256;
  57. m_dwTextureHeight = 256;
  58. m_bAntialiasEffect = FALSE;
  59. m_bShadowEffect = FALSE;
  60. m_bOutlineEffect = FALSE;
  61. m_nBlur = 0;
  62. m_nScanlines = 0;
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Name: DestroyObjects()
  66. // Desc: Cleans up all allocated resources for the class
  67. //-----------------------------------------------------------------------------
  68. VOID CTextureFont::DestroyObjects()
  69. {
  70. if ( m_pGlyphs )
  71. delete[] m_pGlyphs;
  72. if ( m_ValidGlyphs )
  73. delete[] m_ValidGlyphs;
  74. if ( m_TranslatorTable )
  75. delete[] m_TranslatorTable;
  76. if ( m_pCustomFilename )
  77. {
  78. TL_Free( (void*)m_pCustomFilename );
  79. m_pCustomFilename = NULL;
  80. for (DWORD i=0; i<m_dwNumGlyphs; i++)
  81. {
  82. if ( m_pCustomGlyphFiles[i] )
  83. {
  84. TL_Free( m_pCustomGlyphFiles[i] );
  85. m_pCustomGlyphFiles[i] = NULL;
  86. }
  87. }
  88. }
  89. m_cMaxGlyph = 0;
  90. m_dwNumGlyphs = 0;
  91. m_pGlyphs = NULL;
  92. m_ValidGlyphs = NULL;
  93. m_TranslatorTable = NULL;
  94. }
  95. //-----------------------------------------------------------------------------
  96. //-----------------------------------------------------------------------------
  97. HRESULT CTextureFont::InsertGlyph( WORD wGlyph )
  98. {
  99. m_cMaxGlyph = 0;
  100. m_dwNumGlyphs = 0;
  101. m_ValidGlyphs[wGlyph] = 1;
  102. for ( DWORD c=0; c<=65535; c++ )
  103. {
  104. if ( m_ValidGlyphs[c] )
  105. {
  106. m_dwNumGlyphs++;
  107. m_cMaxGlyph = (WCHAR)c;
  108. }
  109. }
  110. BuildTranslatorTable();
  111. theApp.CalculateAndRenderGlyphs();
  112. return S_OK;
  113. }
  114. //-----------------------------------------------------------------------------
  115. //-----------------------------------------------------------------------------
  116. HRESULT CTextureFont::DeleteGlyph( WORD wGlyph )
  117. {
  118. m_cMaxGlyph = 0;
  119. m_dwNumGlyphs = 0;
  120. m_ValidGlyphs[wGlyph] = 0;
  121. for ( DWORD c=0; c<=65535; c++ )
  122. {
  123. if ( m_ValidGlyphs[c] )
  124. {
  125. m_dwNumGlyphs++;
  126. m_cMaxGlyph = (WCHAR)c;
  127. }
  128. }
  129. BuildTranslatorTable();
  130. theApp.CalculateAndRenderGlyphs();
  131. return S_OK;
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Name: ExtractValidGlyphsFromRange()
  135. // Desc: Set global variables to indicate we will be drawing all glyphs in the
  136. // range specified.
  137. //-----------------------------------------------------------------------------
  138. HRESULT CTextureFont::ExtractValidGlyphsFromRange( WORD wStartGlyph, WORD wEndGlyph )
  139. {
  140. // Cleanup any previous entries
  141. if( m_ValidGlyphs )
  142. delete[] m_ValidGlyphs;
  143. m_cMaxGlyph = 0;
  144. m_dwNumGlyphs = 0;
  145. m_ValidGlyphs = NULL;
  146. // Allocate memory for the array of vaild glyphs
  147. m_ValidGlyphs = new BYTE[65536];
  148. ZeroMemory( m_ValidGlyphs, 65536 );
  149. for( DWORD c=(DWORD)wStartGlyph; c<=(DWORD)wEndGlyph; c++ )
  150. {
  151. m_ValidGlyphs[c] = 1;
  152. m_dwNumGlyphs++;
  153. }
  154. m_cMaxGlyph = wEndGlyph;
  155. BuildTranslatorTable();
  156. return S_OK;
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Name: ExtractValidGlyphsFromRange()
  160. // Desc: Set global variables to indicate we will be drawing all glyphs that
  161. // are present in the specified text file.
  162. //-----------------------------------------------------------------------------
  163. HRESULT CTextureFont::ExtractValidGlyphsFromFile( const CHAR* strFileName )
  164. {
  165. // Open the file
  166. FILE* file = fopen( strFileName, "rb" );
  167. if( NULL == file )
  168. return E_FAIL;
  169. // Cleanup any previous entries
  170. if( m_ValidGlyphs )
  171. delete[] m_ValidGlyphs;
  172. m_cMaxGlyph = 0;
  173. m_dwNumGlyphs = 0;
  174. m_ValidGlyphs = NULL;
  175. // Allocate memory for the array of vaild glyphs
  176. m_ValidGlyphs = new BYTE[65536];
  177. ZeroMemory( m_ValidGlyphs, 65536 );
  178. // Skip the unicode marker
  179. BOOL bIsUnicode = (fgetwc(file) == 0xfeff) ? TRUE : FALSE;
  180. if( bIsUnicode == FALSE )
  181. rewind( file );
  182. // Record which glyphs are valid
  183. WCHAR c;
  184. while( (WCHAR)EOF != ( c = bIsUnicode ? fgetwc(file) : fgetc(file) ) )
  185. {
  186. while( c == L'\\' )
  187. {
  188. c = bIsUnicode ? fgetwc(file) : fgetc(file);
  189. // Handle octal-coded characters
  190. if( isdigit(c) )
  191. {
  192. int code = (c - L'0');
  193. c = bIsUnicode ? fgetwc(file) : fgetc(file);
  194. if( isdigit(c) )
  195. {
  196. code = code*8 + (c - L'0');
  197. c = bIsUnicode ? fgetwc(file) : fgetc(file);
  198. if( isdigit(c) )
  199. {
  200. code = code*8 + (c - L'0');
  201. c = bIsUnicode ? fgetwc(file) : fgetc(file);
  202. }
  203. }
  204. if( m_ValidGlyphs[code] == 0 )
  205. {
  206. if( code > m_cMaxGlyph )
  207. m_cMaxGlyph = (WCHAR)code;
  208. m_dwNumGlyphs++;
  209. m_ValidGlyphs[code] = 2;
  210. }
  211. }
  212. else
  213. {
  214. // Add the backslash character
  215. if( L'\\' > m_cMaxGlyph )
  216. m_cMaxGlyph = L'\\';
  217. if( m_ValidGlyphs[L'\\'] == 0 )
  218. {
  219. m_dwNumGlyphs++;
  220. m_ValidGlyphs[L'\\'] = 1;
  221. }
  222. }
  223. }
  224. if( m_ValidGlyphs[c] == 0 )
  225. {
  226. // If the character is a printable one, add it
  227. if( c != L'\n' && c != L'\r' && c != 0xffff )
  228. {
  229. m_dwNumGlyphs++;
  230. m_ValidGlyphs[c] = 1;
  231. if( c > m_cMaxGlyph )
  232. m_cMaxGlyph = c;
  233. }
  234. }
  235. }
  236. // Done with the file
  237. fclose( file );
  238. BuildTranslatorTable();
  239. return S_OK;
  240. }
  241. //-----------------------------------------------------------------------------
  242. // Name: BuildTranslatorTable()
  243. // Desc: Builds a table to translate from a WCHAR to a glyph index.
  244. //-----------------------------------------------------------------------------
  245. HRESULT CTextureFont::BuildTranslatorTable()
  246. {
  247. if ( m_TranslatorTable )
  248. delete[] m_TranslatorTable;
  249. // Insure the \0 is there
  250. if ( m_bIncludeNullCharacter && 0 == m_ValidGlyphs[0] )
  251. {
  252. m_dwNumGlyphs++;
  253. m_ValidGlyphs[0] = 1;
  254. }
  255. // Fill the string of all valid glyphs and build the translator table
  256. m_TranslatorTable = new WORD[m_cMaxGlyph+1];
  257. ZeroMemory( m_TranslatorTable, sizeof(WORD)*(m_cMaxGlyph+1) );
  258. if ( !m_pCustomFilename )
  259. {
  260. // ttf has glyphs that are sequential
  261. DWORD dwGlyph = 0;
  262. for ( DWORD i=0; i<65536; i++ )
  263. {
  264. if ( m_ValidGlyphs[i] )
  265. {
  266. m_TranslatorTable[i] = (WORD)dwGlyph;
  267. dwGlyph++;
  268. }
  269. }
  270. }
  271. else
  272. {
  273. // custom font has glyphs that are scattered
  274. DWORD dwGlyph = 0;
  275. for ( DWORD i=0; i<m_dwNumGlyphs; i++ )
  276. {
  277. if ( !i && m_bIncludeNullCharacter )
  278. {
  279. m_TranslatorTable[0] = 0;
  280. dwGlyph++;
  281. continue;
  282. }
  283. m_TranslatorTable[m_customGlyphs[i-1]] = (WORD)dwGlyph;
  284. dwGlyph++;
  285. }
  286. }
  287. return S_OK;
  288. }
  289. void StripQuotedToken( char *pToken )
  290. {
  291. int len = strlen( pToken );
  292. if ( !len )
  293. return;
  294. if ( pToken[0] == '\"' && pToken[len-1] == '\"' )
  295. {
  296. memcpy( pToken, pToken+1, len-1 );
  297. pToken[len-2] = '\0';
  298. }
  299. }
  300. //-----------------------------------------------------------------------------
  301. // ReadCustomFontFile
  302. //-----------------------------------------------------------------------------
  303. HRESULT CTextureFont::ReadCustomFontFile( CHAR* strFileName )
  304. {
  305. char *pToken;
  306. char fontName[128];
  307. bool bSuccess;
  308. unsigned char glyphs[256];
  309. char *glyphFiles[512];
  310. char basePath[MAX_PATH];
  311. int numGlyphs;
  312. char filename[MAX_PATH];
  313. bSuccess = false;
  314. numGlyphs = 0;
  315. ClearFont();
  316. TL_LoadScriptFile( strFileName );
  317. strcpy( basePath, strFileName );
  318. TL_StripFilename( basePath );
  319. TL_AddSeperatorToPath( basePath, basePath );
  320. fontName[0] = '\0';
  321. while ( 1 )
  322. {
  323. pToken = TL_GetToken( true );
  324. if ( !pToken || !pToken[0] )
  325. break;
  326. StripQuotedToken( pToken );
  327. // get font name
  328. if ( !stricmp( pToken, "fontName" ) )
  329. {
  330. pToken = TL_GetToken( true );
  331. if ( !pToken || !pToken[0] )
  332. goto cleanUp;
  333. StripQuotedToken( pToken );
  334. strcpy( fontName, pToken );
  335. continue;
  336. }
  337. // get glyph
  338. if ( strlen( pToken ) != 1 )
  339. goto cleanUp;
  340. glyphs[numGlyphs] = pToken[0];
  341. // get glyph file
  342. pToken = TL_GetToken( true );
  343. if ( !pToken || !pToken[0] )
  344. goto cleanUp;
  345. StripQuotedToken( pToken );
  346. sprintf( filename, "%s%s", basePath, pToken );
  347. glyphFiles[numGlyphs] = TL_CopyString( filename );
  348. numGlyphs++;
  349. if ( numGlyphs >= 256 )
  350. break;
  351. }
  352. if ( numGlyphs == 0 )
  353. goto cleanUp;
  354. m_pCustomFilename = TL_CopyString( strFileName );
  355. strcpy ( m_strFontName, fontName );
  356. m_dwTextureWidth = 256;
  357. m_dwTextureHeight = 256;
  358. m_ValidGlyphs = new BYTE[65536];
  359. ZeroMemory( m_ValidGlyphs, 65536 );
  360. m_dwNumGlyphs = numGlyphs;
  361. m_cMaxGlyph = 0;
  362. for (int i=0; i<numGlyphs; i++)
  363. {
  364. m_ValidGlyphs[glyphs[i]] = 1;
  365. if ( m_cMaxGlyph < glyphs[i] )
  366. m_cMaxGlyph = glyphs[i];
  367. m_customGlyphs[i] = glyphs[i];
  368. m_pCustomGlyphFiles[i] = glyphFiles[i];
  369. }
  370. BuildTranslatorTable();
  371. bSuccess = true;
  372. cleanUp:
  373. TL_FreeScriptFile();
  374. return bSuccess ? S_OK : E_FAIL;
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Name: ReadFontInfoFile()
  378. // Desc: Loads the font's glyph info from a file
  379. //-----------------------------------------------------------------------------
  380. HRESULT CTextureFont::ReadFontInfoFile( CHAR* strFileName )
  381. {
  382. BitmapFont_t bitmapFont;
  383. // open the info file
  384. FILE* file = fopen( strFileName, "rb" );
  385. if ( NULL == file )
  386. return E_FAIL;
  387. memset( &bitmapFont, 0, sizeof( BitmapFont_t ) );
  388. fread( &bitmapFont, 1, sizeof( BitmapFont_t ), file );
  389. if ( bitmapFont.m_id != BITMAPFONT_ID || bitmapFont.m_Version != BITMAPFONT_VERSION )
  390. {
  391. return E_FAIL;
  392. }
  393. theApp.SetTextureSize( bitmapFont.m_PageWidth, bitmapFont.m_PageHeight );
  394. ZeroMemory( m_ValidGlyphs, 65536 );
  395. m_dwNumGlyphs = 0;
  396. m_cMaxGlyph = 0;
  397. for (int i=0; i<256; i++)
  398. {
  399. if ( bitmapFont.m_TranslateTable[i] )
  400. {
  401. m_ValidGlyphs[i] = 1;
  402. m_cMaxGlyph = i;
  403. m_dwNumGlyphs++;
  404. }
  405. }
  406. BuildTranslatorTable();
  407. // success
  408. fclose( file );
  409. theApp.OnGlyphsCustom();
  410. theApp.CalculateAndRenderGlyphs();
  411. return S_OK;
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Name: WriteFontInfoFile()
  415. // Desc: Writes the font's glyph info to a file
  416. //-----------------------------------------------------------------------------
  417. HRESULT CTextureFont::WriteFontInfoFile( CHAR* strFileName )
  418. {
  419. BitmapFont_t bitmapFont;
  420. BitmapGlyph_t bitmapGlyph;
  421. // Create the info file
  422. FILE* file = fopen( strFileName, "wb" );
  423. if ( NULL == file )
  424. return E_FAIL;
  425. bitmapFont.m_id = BITMAPFONT_ID;
  426. bitmapFont.m_Version = BITMAPFONT_VERSION;
  427. bitmapFont.m_PageWidth = (short)m_dwTextureWidth;
  428. bitmapFont.m_PageHeight = (short)m_dwTextureHeight;
  429. bitmapFont.m_Ascent = 0;
  430. bitmapFont.m_NumGlyphs = (short)m_dwNumGlyphs;
  431. // generate flags
  432. bitmapFont.m_Flags = 0;
  433. if ( m_bAntialiasEffect )
  434. {
  435. bitmapFont.m_Flags |= BF_ANTIALIASED;
  436. }
  437. if ( m_bShadowEffect )
  438. {
  439. bitmapFont.m_Flags |= BF_DROPSHADOW;
  440. }
  441. if ( m_bOutlineEffect )
  442. {
  443. bitmapFont.m_Flags |= BF_OUTLINED;
  444. }
  445. if ( m_nBlur )
  446. {
  447. bitmapFont.m_Flags |= BF_BLURRED;
  448. }
  449. if ( m_nScanlines )
  450. {
  451. bitmapFont.m_Flags |= BF_SCANLINES;
  452. }
  453. if ( m_LogFont.lfItalic )
  454. {
  455. bitmapFont.m_Flags |= BF_ITALIC;
  456. }
  457. if ( m_LogFont.lfWeight > 400 )
  458. {
  459. bitmapFont.m_Flags |= BF_BOLD;
  460. }
  461. if ( m_pCustomFilename )
  462. {
  463. bitmapFont.m_Flags |= BF_CUSTOM;
  464. }
  465. // determine max char width from all glyphs
  466. bitmapFont.m_MaxCharWidth = 0;
  467. for (unsigned int i=0; i<m_dwNumGlyphs; i++ )
  468. {
  469. if ( bitmapFont.m_MaxCharWidth < m_pGlyphs[i].w )
  470. {
  471. bitmapFont.m_MaxCharWidth = m_pGlyphs[i].w;
  472. }
  473. }
  474. bitmapFont.m_MaxCharHeight = 0;
  475. for (unsigned int i=0; i<m_dwNumGlyphs; i++ )
  476. {
  477. if ( bitmapFont.m_MaxCharHeight < m_pGlyphs[i].h )
  478. {
  479. bitmapFont.m_MaxCharHeight = m_pGlyphs[i].h;
  480. }
  481. }
  482. // maps a char index to its actual glyph
  483. for (int i=0; i<256; i++)
  484. {
  485. if ( i <= m_cMaxGlyph )
  486. {
  487. bitmapFont.m_TranslateTable[i] = (unsigned char)m_TranslatorTable[i];
  488. }
  489. else
  490. {
  491. bitmapFont.m_TranslateTable[i] = 0;
  492. }
  493. }
  494. // write out the header
  495. fwrite( &bitmapFont, sizeof( BitmapFont_t ), 1, file );
  496. // Write out the vertical padding caused by effects
  497. // FLOAT fTopPadding = ( m_bOutlineEffect ? 1.0f : 0.0f );
  498. // FLOAT fBottomPadding = ( m_bOutlineEffect ? ( m_bShadowEffect ? 2.0f : 1.0f ) : ( m_bShadowEffect ? 2.0f : 0.0f ) );
  499. // FLOAT fFontYAdvance = fFontHeight - fTopPadding - fBottomPadding;
  500. // Write the glyph attributes to the file
  501. for (unsigned int i=0; i<m_dwNumGlyphs; i++ )
  502. {
  503. bitmapGlyph.x = m_pGlyphs[i].x;
  504. bitmapGlyph.y = m_pGlyphs[i].y;
  505. bitmapGlyph.w = m_pGlyphs[i].w;
  506. bitmapGlyph.h = m_pGlyphs[i].h;
  507. bitmapGlyph.a = m_pGlyphs[i].a;
  508. bitmapGlyph.b = m_pGlyphs[i].b;
  509. bitmapGlyph.c = m_pGlyphs[i].c;
  510. fwrite( &bitmapGlyph, sizeof( BitmapGlyph_t ), 1, file );
  511. }
  512. // success
  513. fclose( file );
  514. return S_OK;
  515. }
  516. //-----------------------------------------------------------------------------
  517. // Name: WriteTargaFile()
  518. // Desc: Writes 32-bit RGBA data to a .tga file
  519. //-----------------------------------------------------------------------------
  520. HRESULT WriteTargaFile( CHAR* strFileName, DWORD dwWidth, DWORD dwHeight,
  521. DWORD* pRGBAData )
  522. {
  523. struct TargaHeader
  524. {
  525. BYTE IDLength;
  526. BYTE ColormapType;
  527. BYTE ImageType;
  528. BYTE ColormapSpecification[5];
  529. WORD XOrigin;
  530. WORD YOrigin;
  531. WORD ImageWidth;
  532. WORD ImageHeight;
  533. BYTE PixelDepth;
  534. BYTE ImageDescriptor;
  535. } tga;
  536. // Create the file
  537. FILE* file = fopen( strFileName, "wb" );
  538. if( NULL == file )
  539. return E_FAIL;
  540. // Write the TGA header
  541. ZeroMemory( &tga, sizeof(tga) );
  542. tga.IDLength = 0;
  543. tga.ImageType = 2;
  544. tga.ImageWidth = (WORD)dwWidth;
  545. tga.ImageHeight = (WORD)dwHeight;
  546. tga.PixelDepth = 32;
  547. tga.ImageDescriptor = 0x28;
  548. fwrite( &tga, sizeof(TargaHeader), 1, file );
  549. // Write the pixels
  550. fwrite( pRGBAData, sizeof(DWORD), dwHeight*dwWidth, file );
  551. // Close the file and return okay
  552. fclose( file );
  553. return S_OK;
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Name: WriteFontImageFile()
  557. // Desc: Writes 32-bit RGBA data to a .tga file
  558. //-----------------------------------------------------------------------------
  559. HRESULT CTextureFont::WriteFontImageFile( CHAR* strFileName, bool bAdditiveMode, bool bCustomFont )
  560. {
  561. // Convert the bits to have an alpha channel
  562. DWORD* pRGBAData = new DWORD[m_dwTextureWidth*m_dwTextureHeight];
  563. FLOAT l;
  564. for ( DWORD i=0; i<m_dwTextureWidth*m_dwTextureHeight; i++ )
  565. {
  566. FLOAT a = ( ( 0xff000000 & m_pBits[i] ) >> 24L ) / 255.0f;
  567. FLOAT r = ( ( 0x00ff0000 & m_pBits[i] ) >> 16L ) / 255.0f;
  568. FLOAT g = ( ( 0x0000ff00 & m_pBits[i] ) >> 8L ) / 255.0f;
  569. FLOAT b = ( ( 0x000000ff & m_pBits[i] ) >> 0L ) / 255.0f;
  570. if ( bCustomFont )
  571. {
  572. if ( a == 0.0f && b == 1.0f )
  573. {
  574. // pure transluscent
  575. a = 0;
  576. r = g = b = 0.0f;
  577. }
  578. int red = (int)(r * 255.0f);
  579. int green = (int)(g * 255.0f);
  580. int blue = (int)(b * 255.0f);
  581. int alpha = (int)(a * 255.0f);
  582. pRGBAData[i] = (alpha<<24L) | (red<<16L) | (green<<8L) | (blue<<0L);
  583. }
  584. else
  585. {
  586. if ( bAdditiveMode )
  587. {
  588. // all channels should be same
  589. if (( r != g ) || ( r != b ))
  590. {
  591. }
  592. l = r;
  593. a = 1.0f;
  594. }
  595. else
  596. {
  597. a = r + (1-b);
  598. if ( a )
  599. l = r / a;
  600. else
  601. l = 1;
  602. }
  603. DWORD alpha = (DWORD)( a * 255.0f );
  604. DWORD lum = (DWORD)( l * 255.0f );
  605. pRGBAData[i] = (alpha<<24L) | (lum<<16L) | (lum<<8L) | (lum<<0L);
  606. }
  607. }
  608. // Write the file
  609. HRESULT hr = WriteTargaFile( strFileName, m_dwTextureWidth,
  610. m_dwTextureHeight, pRGBAData );
  611. // Cleanup and return
  612. delete[] pRGBAData;
  613. return hr;
  614. }
  615. void GetBitmapBits2( HBITMAP hBitmap, int width, int height, void *pBits )
  616. {
  617. memset( pBits, 0, width*height*4 );
  618. HDC hDC = CreateCompatibleDC( NULL );
  619. BITMAPINFO bitmapInfo = {0};
  620. bitmapInfo.bmiHeader.biSize = sizeof( bitmapInfo.bmiHeader );
  621. bitmapInfo.bmiHeader.biWidth = width;
  622. bitmapInfo.bmiHeader.biHeight = -height;
  623. bitmapInfo.bmiHeader.biPlanes = 1;
  624. bitmapInfo.bmiHeader.biBitCount = 32;
  625. bitmapInfo.bmiHeader.biCompression = BI_RGB;
  626. GetDIBits( hDC, hBitmap, 0, height, pBits, &bitmapInfo ,DIB_RGB_COLORS );
  627. DeleteDC( hDC );
  628. }
  629. void SetBitmapBits2( HBITMAP hBitmap, int width, int height, void *pBits )
  630. {
  631. HDC hDC = CreateCompatibleDC( NULL );
  632. BITMAPINFO bitmapInfo = {0};
  633. bitmapInfo.bmiHeader.biSize = sizeof( bitmapInfo.bmiHeader );
  634. bitmapInfo.bmiHeader.biWidth = width;
  635. bitmapInfo.bmiHeader.biHeight = -height;
  636. bitmapInfo.bmiHeader.biPlanes = 1;
  637. bitmapInfo.bmiHeader.biBitCount = 32;
  638. bitmapInfo.bmiHeader.biCompression = BI_RGB;
  639. SetDIBits( hDC, hBitmap, 0, height, pBits, &bitmapInfo ,DIB_RGB_COLORS );
  640. DeleteDC( hDC );
  641. }
  642. //-----------------------------------------------------------------------------
  643. // SetTextureBits
  644. //
  645. // Blit the rect back into the bitmap
  646. //-----------------------------------------------------------------------------
  647. void SetTextureBits( HBITMAP hBitmap, int bitmapWidth, int bitmapHeight, int x, int y, int w, int h, unsigned char *pRGBA )
  648. {
  649. // get the enitre bitmap
  650. unsigned char *pBitmapBits = (unsigned char *)malloc( bitmapWidth * bitmapHeight * 4);
  651. GetBitmapBits2( hBitmap, bitmapWidth, bitmapHeight, pBitmapBits );
  652. // copy into bitmap bits
  653. unsigned char *pSrc = pRGBA;
  654. for (int yy=y; yy<y+h; yy++)
  655. {
  656. if ( yy >= bitmapHeight )
  657. {
  658. // past end of bitmap
  659. break;
  660. }
  661. unsigned char *pDst = pBitmapBits + (yy*bitmapWidth + x)*4;
  662. for (int xx=0; xx<w; xx++)
  663. {
  664. if ( xx+x < bitmapWidth )
  665. {
  666. pDst[0] = pSrc[0];
  667. pDst[1] = pSrc[1];
  668. pDst[2] = pSrc[2];
  669. pDst[3] = pSrc[3];
  670. }
  671. pSrc += 4;
  672. pDst += 4;
  673. }
  674. }
  675. SetBitmapBits2( hBitmap, bitmapWidth, bitmapHeight, pBitmapBits );
  676. free( pBitmapBits );
  677. }
  678. //-----------------------------------------------------------------------------
  679. // GetTextureBits
  680. //
  681. // Blit the rect out of the bitmap
  682. //-----------------------------------------------------------------------------
  683. unsigned char *GetTextureBits( HBITMAP hBitmap, int bitmapWidth, int bitmapHeight, int x, int y, int w, int h )
  684. {
  685. // get the enitre bitmap
  686. unsigned char *pBitmapBits = new unsigned char[bitmapWidth * bitmapHeight * 4];
  687. GetBitmapBits2( hBitmap, bitmapWidth, bitmapHeight, pBitmapBits );
  688. unsigned char *pRGBA = new unsigned char[w * h * 4];
  689. memset( pRGBA, 0, w*h*4 );
  690. // copy out bits
  691. unsigned char *pDst = pRGBA;
  692. for (int yy=y; yy<y+h; yy++)
  693. {
  694. if ( yy >= bitmapHeight )
  695. {
  696. // past last row of bitmap
  697. break;
  698. }
  699. unsigned char *pSrc = pBitmapBits + (yy*bitmapWidth + x)*4;
  700. for (int xx=0; xx<w; xx++)
  701. {
  702. if ( xx + x < bitmapWidth )
  703. {
  704. pDst[0] = pSrc[0];
  705. pDst[1] = pSrc[1];
  706. pDst[2] = pSrc[2];
  707. pDst[3] = pSrc[3];
  708. }
  709. pSrc += 4;
  710. pDst += 4;
  711. }
  712. }
  713. delete [] pBitmapBits;
  714. return pRGBA;
  715. }
  716. int g_blur;
  717. float *g_pGaussianDistribution;
  718. //-----------------------------------------------------------------------------
  719. // Purpose: Gets the blur value for a single pixel
  720. //-----------------------------------------------------------------------------
  721. void GetBlurValueForPixel(unsigned char *src, int blur, float *gaussianDistribution, int srcX, int srcY, int srcWide, int srcTall, unsigned char *dest)
  722. {
  723. int r = 0, g = 0, b = 0, a = 0;
  724. float accum = 0.0f;
  725. // scan the positive x direction
  726. int maxX = min(srcX + blur, srcWide);
  727. int minX = max(srcX - blur, 0);
  728. for (int x = minX; x <= maxX; x++)
  729. {
  730. int maxY = min(srcY + blur, srcTall - 1);
  731. int minY = max(srcY - blur, 0);
  732. for (int y = minY; y <= maxY; y++)
  733. {
  734. unsigned char *srcPos = src + ((x + (y * srcWide)) * 4);
  735. unsigned char red = srcPos[2];
  736. unsigned char green = srcPos[1];
  737. unsigned char blue = srcPos[0];
  738. // muliply by the value matrix
  739. float weight = gaussianDistribution[x - srcX + blur];
  740. float weight2 = gaussianDistribution[y - srcY + blur];
  741. accum += (red * (weight * weight2));
  742. }
  743. }
  744. // blurring decreased the range, for xbox kick some back
  745. accum *= 1.30f;
  746. // all the values are the same for fonts, just use the calculated alpha
  747. r = g = b = (int)accum;
  748. dest[0] = min(b, 255);
  749. dest[1] = min(g, 255);
  750. dest[2] = min(r, 255);
  751. }
  752. //-----------------------------------------------------------------------------
  753. // ApplyGaussianBlurToTexture
  754. //-----------------------------------------------------------------------------
  755. void ApplyGaussianBlurToTexture( int blur, int rgbaX, int rgbaY, int rgbaWide, int rgbaTall, unsigned char *rgba)
  756. {
  757. // calculate our gaussian distribution for if we're blurred
  758. if ( blur > 1 && blur != g_blur )
  759. {
  760. g_blur = blur;
  761. g_pGaussianDistribution = new float[blur * 2 + 1];
  762. double sigma = 0.683f * blur;
  763. for (int x = 0; x <= (blur * 2); x++)
  764. {
  765. int val = x - blur;
  766. g_pGaussianDistribution[x] = (float)((1.0 / sqrt(2.0 * 3.14 * sigma * sigma)) * pow(2.7, -1.0 * (val * val) / (2.0 * sigma * sigma)));
  767. // brightening factor
  768. g_pGaussianDistribution[x] *= 1;
  769. }
  770. }
  771. // alloc a new buffer
  772. unsigned char *src = (unsigned char *)_alloca(rgbaWide * rgbaTall * 4);
  773. memcpy(src, rgba, rgbaWide * rgbaTall * 4);
  774. unsigned char *dest = rgba;
  775. for (int y = 0; y < rgbaTall; y++)
  776. {
  777. for (int x = 0; x < rgbaWide; x++)
  778. {
  779. // scan the source pixel
  780. GetBlurValueForPixel(src, blur, g_pGaussianDistribution, x, y, rgbaWide, rgbaTall, dest);
  781. // move to the next
  782. dest += 4;
  783. }
  784. }
  785. }
  786. //-----------------------------------------------------------------------------
  787. // ApplyScanlineEffectToTexture
  788. //-----------------------------------------------------------------------------
  789. void ApplyScanlineEffectToTexture( int scanLines, int rgbaX, int rgbaY, int rgbaWide, int rgbaTall, unsigned char *rgba)
  790. {
  791. if (scanLines < 2)
  792. return;
  793. float scale;
  794. scale = 0;
  795. // darken all the areas except the scanlines
  796. for (int y = 0; y < rgbaTall; y++)
  797. {
  798. // skip the scan lines
  799. if (y % scanLines == 0)
  800. continue;
  801. DWORD *pBits = (DWORD*)&rgba[(rgbaX + ((y + rgbaY) * rgbaWide)) * 4];
  802. // darken the other lines
  803. for (int x = 0; x < rgbaWide; x++, pBits++)
  804. {
  805. FLOAT r = ( ( 0x00ff0000 & pBits[0] ) >> 16L ) / 255.0f;
  806. FLOAT g = ( ( 0x0000ff00 & pBits[0] ) >> 8L ) / 255.0f;
  807. FLOAT b = ( ( 0x000000ff & pBits[0] ) >> 0L ) / 255.0f;
  808. r *= scale;
  809. g *= scale;
  810. b *= scale;
  811. pBits[0] = (((int)(r * 255.0f))<<16) | (((int)(g * 255.0f))<<8) | ((int)(b * 255.0f));
  812. pBits[0] |= 0xFF000000;
  813. }
  814. }
  815. }
  816. //-----------------------------------------------------------------------------
  817. // Name: RenderTTFGlyphs()
  818. // Desc: Draws the list of font glyphs in the scroll view
  819. //-----------------------------------------------------------------------------
  820. GLYPH_ATTR* CTextureFont::RenderTTFGlyphs( HFONT hFont, HBITMAP hBitmap,
  821. DWORD dwTextureWidth, DWORD dwTextureHeight,
  822. BOOL bOutlineEffect, BOOL bShadowEffect,
  823. int nScanlineEffect, int nBlurEffect,
  824. BOOL bAntialias,
  825. BYTE* ValidGlyphs, DWORD dwNumGlyphs )
  826. {
  827. // Create a DC
  828. HDC hDC = CreateCompatibleDC( NULL );
  829. // Associate the drawing surface
  830. SelectObject( hDC, hBitmap );
  831. // Create a clip region
  832. HRGN rgn = CreateRectRgn( 0, 0, dwTextureWidth, dwTextureHeight );
  833. SelectClipRgn( hDC, rgn );
  834. // Setup the DC for the font
  835. SetTextColor( hDC, COLOR_WHITE );
  836. SelectObject( hDC, hFont );
  837. SetTextAlign( hDC, TA_LEFT|TA_TOP|TA_UPDATECP );
  838. SetMapMode( hDC, MM_TEXT );
  839. SetBkMode( hDC, TRANSPARENT );
  840. if ( nScanlineEffect || nBlurEffect )
  841. {
  842. SetBkColor( hDC, COLOR_BLACK );
  843. if ( nBlurEffect < 2 )
  844. nBlurEffect = 2;
  845. if ( nScanlineEffect < 2 )
  846. nScanlineEffect = 2;
  847. }
  848. else
  849. {
  850. SetBkColor( hDC, COLOR_BLUE );
  851. }
  852. // Fill the background in blue
  853. RECT rect;
  854. SetRect( &rect, 0, 0, dwTextureWidth, dwTextureHeight );
  855. ExtTextOut( hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL );
  856. // Get the effective font height
  857. WCHAR str[2] = L"A";
  858. SIZE size;
  859. GetTextExtentPoint32W( hDC, str, 1, &size );
  860. DWORD dwLeftOrigin = 1;
  861. DWORD dwTopOrigin = 1;
  862. GLYPH_ATTR* pGlyphs = new GLYPH_ATTR[dwNumGlyphs];
  863. memset( pGlyphs, 0, dwNumGlyphs*sizeof( GLYPH_ATTR ) );
  864. // Loop through all printable character and output them to the bitmap..
  865. // Meanwhile, keep track of the corresponding tex coords for each character.
  866. DWORD x = dwLeftOrigin;
  867. DWORD y = dwTopOrigin;
  868. int sx;
  869. int sy;
  870. int numGlyphs = 0;
  871. for( DWORD i=0; i<65536; i++ )
  872. {
  873. if ( 0 == ValidGlyphs[i])
  874. continue;
  875. str[0] = (WCHAR)i;
  876. if ( i==0 && ValidGlyphs[i] == 1 )
  877. {
  878. // account for unprintable, but don't render it
  879. numGlyphs++;
  880. continue;
  881. }
  882. GetTextExtentPoint32W( hDC, str, 1, &size );
  883. // Get char width a different way
  884. int charwidth;
  885. GetCharWidth32( hDC, str[0], str[0], &charwidth );
  886. // Get the ABC widths for the letter
  887. ABC abc;
  888. if ( FALSE == GetCharABCWidthsW( hDC, str[0], str[0], &abc ) )
  889. {
  890. abc.abcA = 0;
  891. abc.abcB = size.cx;
  892. abc.abcC = 0;
  893. }
  894. int w = abc.abcB;
  895. int h = size.cy;
  896. // Determine padding for effects
  897. int left_padding = 0;
  898. int right_padding = 0;
  899. int top_padding = 0;
  900. int bottom_padding = 0;
  901. if ( bOutlineEffect || bShadowEffect )
  902. {
  903. if ( bOutlineEffect )
  904. left_padding = 1;
  905. if ( bOutlineEffect )
  906. {
  907. if ( bShadowEffect )
  908. right_padding = 2;
  909. else
  910. right_padding = 1;
  911. }
  912. else
  913. {
  914. if ( bShadowEffect )
  915. right_padding = 2;
  916. else
  917. right_padding = 0;
  918. }
  919. if ( bOutlineEffect )
  920. top_padding = 1;
  921. if ( bOutlineEffect )
  922. {
  923. if ( bShadowEffect )
  924. bottom_padding = 2;
  925. else
  926. bottom_padding = 1;
  927. }
  928. else
  929. {
  930. if ( bShadowEffect )
  931. bottom_padding = 2;
  932. else
  933. bottom_padding = 0;
  934. }
  935. }
  936. else if ( nBlurEffect )
  937. {
  938. left_padding = nBlurEffect;
  939. right_padding = nBlurEffect;
  940. }
  941. if ( ValidGlyphs[i] == 2 )
  942. {
  943. // Handle special characters
  944. // Advance to the next line, if necessary
  945. if ( x + h + left_padding + right_padding >= (int)dwTextureWidth )
  946. {
  947. x = dwLeftOrigin;
  948. y += h + top_padding + bottom_padding + 1;
  949. }
  950. sx = x;
  951. sy = y;
  952. // Draw a square box for a placeholder for custom glyph graphics
  953. w = h + left_padding + right_padding;
  954. h = h + top_padding + bottom_padding;
  955. abc.abcA = 0;
  956. abc.abcB = w;
  957. abc.abcC = 0;
  958. RECT rect;
  959. SetRect( &rect, x, y, x+w, y+h );
  960. SetBkColor( hDC, COLOR_BLACK );
  961. ExtTextOut( hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL );
  962. }
  963. else
  964. {
  965. // Hack to adjust for Kanji
  966. if ( str[0] > 0x1000 )
  967. {
  968. w = h;
  969. }
  970. // Advance to the next line, if necessary
  971. if ( x + w + left_padding + right_padding + 1 >= (int)dwTextureWidth )
  972. {
  973. x = dwLeftOrigin;
  974. y += h + top_padding + bottom_padding + 1;
  975. }
  976. sx = x;
  977. sy = y;
  978. // Adjust ccordinates to account for the leading edge
  979. if ( abc.abcA >= 0 )
  980. x += abc.abcA;
  981. else
  982. sx -= abc.abcA;
  983. // Hack to adjust for Kanji
  984. if ( str[0] > 0x1000 )
  985. {
  986. sx += abc.abcA;
  987. }
  988. // Add padding to the width and height
  989. w += left_padding + right_padding;
  990. h += top_padding + bottom_padding;
  991. abc.abcA -= left_padding;
  992. abc.abcB += left_padding + right_padding;
  993. abc.abcC -= right_padding;
  994. if ( bOutlineEffect || bShadowEffect )
  995. {
  996. if ( bOutlineEffect )
  997. {
  998. SetTextColor( hDC, COLOR_BLACK );
  999. MoveToEx( hDC, sx+0, sy+0, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1000. MoveToEx( hDC, sx+1, sy+0, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1001. MoveToEx( hDC, sx+2, sy+0, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1002. MoveToEx( hDC, sx+0, sy+1, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1003. MoveToEx( hDC, sx+2, sy+1, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1004. MoveToEx( hDC, sx+0, sy+2, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1005. MoveToEx( hDC, sx+1, sy+2, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1006. MoveToEx( hDC, sx+2, sy+2, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1007. if ( bShadowEffect )
  1008. {
  1009. MoveToEx( hDC, sx+3, sy+3, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1010. }
  1011. // Output the letter
  1012. SetTextColor( hDC, COLOR_WHITE );
  1013. MoveToEx( hDC, sx+1, sy+1, NULL ); ExtTextOutW( hDC, sx, sy, ETO_OPAQUE, NULL, str, 1, NULL );
  1014. }
  1015. else
  1016. {
  1017. if ( bShadowEffect )
  1018. {
  1019. SetTextColor( hDC, COLOR_BLACK );
  1020. MoveToEx( hDC, sx+2, sy+2, NULL ); ExtTextOutW( hDC, 0, 0, ETO_OPAQUE, NULL, str, 1, NULL );
  1021. }
  1022. // Output the letter
  1023. SetTextColor( hDC, COLOR_WHITE );
  1024. MoveToEx( hDC, sx, sy, NULL ); ExtTextOutW( hDC, sx, sy, ETO_OPAQUE, NULL, str, 1, NULL );
  1025. }
  1026. }
  1027. else if ( nBlurEffect )
  1028. {
  1029. // blur effect
  1030. SetTextColor( hDC, COLOR_WHITE );
  1031. MoveToEx( hDC, sx + nBlurEffect, sy, NULL );
  1032. ExtTextOutW( hDC, sx, sy, ETO_OPAQUE, NULL, str, 1, NULL );
  1033. // apply blur effect
  1034. unsigned char *pBGRA = GetTextureBits( hBitmap, dwTextureWidth, dwTextureHeight, x, y, w, h );
  1035. if ( pBGRA )
  1036. {
  1037. ApplyGaussianBlurToTexture( nBlurEffect, 0, 0, w, h, pBGRA );
  1038. SetTextureBits( hBitmap, dwTextureWidth, dwTextureHeight, x, y, w, h, pBGRA );
  1039. delete [] pBGRA;
  1040. }
  1041. }
  1042. else
  1043. {
  1044. // normal, no effect
  1045. // Output the letter
  1046. SetTextColor( hDC, COLOR_WHITE );
  1047. MoveToEx( hDC, sx, sy, NULL );
  1048. ExtTextOutW( hDC, sx, sy, ETO_OPAQUE, NULL, str, 1, NULL );
  1049. }
  1050. // apply scanline effect
  1051. if ( nScanlineEffect )
  1052. {
  1053. unsigned char *pBGRA = GetTextureBits( hBitmap, dwTextureWidth, dwTextureHeight, x, y, w, h );
  1054. if ( pBGRA )
  1055. {
  1056. ApplyScanlineEffectToTexture( nScanlineEffect, 0, 0, w, h, pBGRA );
  1057. SetTextureBits( hBitmap, dwTextureWidth, dwTextureHeight, x, y, w, h, pBGRA );
  1058. delete [] pBGRA;
  1059. }
  1060. }
  1061. // Hack for extended characters (like Kanji) that don't seem to report
  1062. // correct ABC widths. In this case, use the width calculated from
  1063. // drawing the glyph.
  1064. if( str[0] > 0x1000 )
  1065. {
  1066. POINT pos;
  1067. GetCurrentPositionEx( hDC, &pos );
  1068. abc.abcB = pos.x - sx;
  1069. if( abc.abcC < 0 )
  1070. abc.abcB -= abc.abcC;
  1071. w = abc.abcB;
  1072. }
  1073. }
  1074. // Store the glyph attributes
  1075. pGlyphs[numGlyphs].x = x;
  1076. pGlyphs[numGlyphs].y = y;
  1077. pGlyphs[numGlyphs].w = w;
  1078. pGlyphs[numGlyphs].h = h;
  1079. pGlyphs[numGlyphs].a = abc.abcA;
  1080. pGlyphs[numGlyphs].b = abc.abcB;
  1081. pGlyphs[numGlyphs].c = abc.abcC;
  1082. pGlyphs[numGlyphs].fLeft = ((FLOAT)(x+0)) / dwTextureWidth;
  1083. pGlyphs[numGlyphs].fTop = ((FLOAT)(y+0)) / dwTextureHeight;
  1084. pGlyphs[numGlyphs].fRight = ((FLOAT)(x+w)) / dwTextureWidth;
  1085. pGlyphs[numGlyphs].fBottom = ((FLOAT)(y+h)) / dwTextureHeight;
  1086. numGlyphs++;
  1087. // Advance the cursor to the next position
  1088. x += w + 1;
  1089. }
  1090. SelectClipRgn( hDC, NULL );
  1091. DeleteObject( rgn );
  1092. DeleteDC( hDC );
  1093. return pGlyphs;
  1094. }
  1095. //-----------------------------------------------------------------------------
  1096. // Name: RenderCustomGlyphs()
  1097. // Desc: Draws the list of font glyphs in the scroll view
  1098. //-----------------------------------------------------------------------------
  1099. GLYPH_ATTR* CTextureFont::RenderCustomGlyphs( HBITMAP hBitmap )
  1100. {
  1101. int i;
  1102. int w;
  1103. int h;
  1104. byte_t *pTGAPixels;
  1105. m_maxCustomCharHeight = 0;
  1106. // Create a DC
  1107. HDC hDC = CreateCompatibleDC( NULL );
  1108. // Associate the drawing surface
  1109. SelectObject( hDC, hBitmap );
  1110. // Create a clip region
  1111. HRGN rgn = CreateRectRgn( 0, 0, m_dwTextureWidth, m_dwTextureHeight );
  1112. SelectClipRgn( hDC, rgn );
  1113. // clear the background
  1114. unsigned char *pBGRA = GetTextureBits( hBitmap, m_dwTextureWidth, m_dwTextureHeight, 0, 0, m_dwTextureWidth, m_dwTextureHeight );
  1115. for (i=0; i<(int)(m_dwTextureHeight*m_dwTextureWidth); i++)
  1116. {
  1117. pBGRA[i*4+0] = 0xFF;
  1118. pBGRA[i*4+1] = 0x00;
  1119. pBGRA[i*4+2] = 0x00;
  1120. pBGRA[i*4+3] = 0x00;
  1121. }
  1122. SetTextureBits( hBitmap, m_dwTextureWidth, m_dwTextureHeight, 0, 0, m_dwTextureWidth, m_dwTextureHeight, pBGRA );
  1123. // build the glyph table
  1124. GLYPH_ATTR* pGlyphs = new GLYPH_ATTR[m_dwNumGlyphs];
  1125. memset( pGlyphs, 0, m_dwNumGlyphs*sizeof( GLYPH_ATTR ) );
  1126. int x = 0;
  1127. int y = 0;
  1128. int maxHeight = 0;
  1129. for( DWORD i=0; i<m_dwNumGlyphs; i++ )
  1130. {
  1131. if ( !i )
  1132. {
  1133. // account for null
  1134. continue;
  1135. }
  1136. else if ( TL_Exists( m_pCustomGlyphFiles[i-1] ) )
  1137. {
  1138. TL_LoadTGA( m_pCustomGlyphFiles[i-1], &pTGAPixels, &w, &h );
  1139. // convert to expected order
  1140. for (int j=0; j<h*w; j++)
  1141. {
  1142. int r = pTGAPixels[j*4+0];
  1143. int g = pTGAPixels[j*4+1];
  1144. int b = pTGAPixels[j*4+2];
  1145. pTGAPixels[j*4+0] = b;
  1146. pTGAPixels[j*4+1] = g;
  1147. pTGAPixels[j*4+2] = r;
  1148. }
  1149. }
  1150. else
  1151. {
  1152. // build a "bad" symbol
  1153. pTGAPixels = (byte_t*)TL_Malloc( 32*32*4 );
  1154. w = 32;
  1155. h = 32;
  1156. for (int j=0; j<32*32; j++)
  1157. {
  1158. pTGAPixels[j*4+0] = 0x00;
  1159. pTGAPixels[j*4+1] = 0x00;
  1160. pTGAPixels[j*4+2] = 0xFF;
  1161. pTGAPixels[j*4+3] = 0xFF;
  1162. }
  1163. }
  1164. if ( m_maxCustomCharHeight < h )
  1165. {
  1166. m_maxCustomCharHeight = h;
  1167. }
  1168. if ( maxHeight < h )
  1169. {
  1170. maxHeight = h;
  1171. }
  1172. if ( x + w > (int)m_dwTextureWidth )
  1173. {
  1174. // skip to new row
  1175. y += maxHeight;
  1176. x = 0;
  1177. maxHeight = h;
  1178. }
  1179. SetTextureBits( hBitmap, m_dwTextureWidth, m_dwTextureHeight, x, y, w, h, pTGAPixels );
  1180. TL_Free( pTGAPixels );
  1181. // Store the glyph attributes
  1182. pGlyphs[i].x = x;
  1183. pGlyphs[i].y = y;
  1184. pGlyphs[i].w = w;
  1185. pGlyphs[i].h = h;
  1186. pGlyphs[i].a = 0;
  1187. pGlyphs[i].b = w;
  1188. pGlyphs[i].c = 0;
  1189. pGlyphs[i].fLeft = ((FLOAT)(x+0)) / m_dwTextureWidth;
  1190. pGlyphs[i].fTop = ((FLOAT)(y+0)) / m_dwTextureHeight;
  1191. pGlyphs[i].fRight = ((FLOAT)(x+w)) / m_dwTextureWidth;
  1192. pGlyphs[i].fBottom = ((FLOAT)(y+h)) / m_dwTextureHeight;
  1193. x += w;
  1194. }
  1195. SelectClipRgn( hDC, NULL );
  1196. DeleteObject( rgn );
  1197. DeleteDC( hDC );
  1198. delete [] pBGRA;
  1199. return pGlyphs;
  1200. }
  1201. //-----------------------------------------------------------------------------
  1202. // Name: CalculateAndRenderGlyphs()
  1203. // Desc: Draws the list of font glyphs
  1204. //-----------------------------------------------------------------------------
  1205. HRESULT CTextureFont::CalculateAndRenderGlyphs()
  1206. {
  1207. // Create a bitmap
  1208. HBITMAP hBitmap = CreateBitmap( m_dwTextureWidth, m_dwTextureHeight, 1, 32, NULL );
  1209. if ( m_pGlyphs )
  1210. delete[] m_pGlyphs;
  1211. if ( m_pCustomFilename )
  1212. {
  1213. m_pGlyphs = RenderCustomGlyphs( hBitmap );
  1214. }
  1215. else
  1216. {
  1217. // Create a font
  1218. if ( m_hFont )
  1219. {
  1220. DeleteObject( m_hFont );
  1221. }
  1222. if ( m_bAntialiasEffect )
  1223. {
  1224. m_LogFont.lfQuality = ANTIALIASED_QUALITY;
  1225. }
  1226. else
  1227. {
  1228. m_LogFont.lfQuality = NONANTIALIASED_QUALITY;
  1229. }
  1230. m_hFont = CreateFontIndirect( &m_LogFont );
  1231. m_pGlyphs = RenderTTFGlyphs(
  1232. m_hFont,
  1233. hBitmap,
  1234. m_dwTextureWidth,
  1235. m_dwTextureHeight,
  1236. m_bOutlineEffect,
  1237. m_bShadowEffect,
  1238. m_nScanlines,
  1239. m_nBlur,
  1240. m_bAntialiasEffect,
  1241. m_ValidGlyphs,
  1242. m_dwNumGlyphs );
  1243. }
  1244. // Store the resulting bits
  1245. if ( m_pBits )
  1246. delete[] m_pBits;
  1247. m_pBits = new DWORD[ m_dwTextureWidth * m_dwTextureHeight ];
  1248. GetBitmapBits2( hBitmap, m_dwTextureWidth, m_dwTextureHeight, m_pBits );
  1249. DeleteObject( hBitmap );
  1250. return S_OK;
  1251. }