Font.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Graphics/Font.h>
  14. #include <Engine/Base/Stream.h>
  15. #include <Engine/Graphics/Texture.h>
  16. #include <Engine/Graphics/Color.h>
  17. #include <Engine/Templates/Stock_CTextureData.h>
  18. // some default fonts
  19. CFontData *_pfdDisplayFont;
  20. CFontData *_pfdConsoleFont;
  21. // constructor deletes letter data
  22. CFontCharData::CFontCharData(void)
  23. {
  24. fcd_pixXOffset = 0;
  25. fcd_pixYOffset = 0;
  26. fcd_pixStart = 0;
  27. fcd_pixEnd = 0;
  28. }
  29. // simple stream functions
  30. void CFontCharData::Read_t( CTStream *inFile)
  31. {
  32. *inFile>>fcd_pixXOffset;
  33. *inFile>>fcd_pixYOffset;
  34. *inFile>>fcd_pixStart;
  35. *inFile>>fcd_pixEnd;
  36. }
  37. void CFontCharData::Write_t( CTStream *outFile)
  38. {
  39. *outFile<<fcd_pixXOffset;
  40. *outFile<<fcd_pixYOffset;
  41. *outFile<<fcd_pixStart;
  42. *outFile<<fcd_pixEnd;
  43. }
  44. CFontData::CFontData()
  45. {
  46. fd_ptdTextureData = NULL;
  47. fd_fnTexture = CTString("");
  48. }
  49. CFontData::~CFontData()
  50. {
  51. Clear();
  52. }
  53. void CFontData::Clear()
  54. {
  55. if( fd_ptdTextureData != NULL) {
  56. fd_fnTexture = CTString("");
  57. _pTextureStock->Release(fd_ptdTextureData);
  58. fd_ptdTextureData = NULL;
  59. }
  60. }
  61. void CFontData::Read_t( CTStream *inFile) // throw char *
  62. {
  63. // clear current font data (if needed)
  64. Clear();
  65. // read the filename of the corresponding texture file.
  66. inFile->ExpectID_t( CChunkID("FTTF"));
  67. *inFile >> fd_fnTexture;
  68. // read maximum width and height of all letters
  69. *inFile >> fd_pixCharWidth;
  70. *inFile >> fd_pixCharHeight;
  71. // read entire letter data table
  72. for( INDEX iLetterData=0; iLetterData<256; iLetterData ++) {
  73. fd_fcdFontCharData[ iLetterData].Read_t( inFile);
  74. }
  75. // load corresponding texture file
  76. fd_ptdTextureData = _pTextureStock->Obtain_t(fd_fnTexture);
  77. // reload corresponding texture if not loaded in largest mip-map
  78. fd_ptdTextureData->Force( TEX_CONSTANT);
  79. // initialize default font variables
  80. SetVariableWidth();
  81. SetCharSpacing(+1);
  82. SetLineSpacing(+1);
  83. SetSpaceWidth(0.5f);
  84. fd_fcdFontCharData[' '].fcd_pixStart = 0;
  85. }
  86. void CFontData::Write_t( CTStream *outFile) // throw char *
  87. {
  88. ASSERT( fd_ptdTextureData != NULL);
  89. // write the filename of the corresponding texture file
  90. outFile->WriteID_t( CChunkID("FTTF"));
  91. *outFile << fd_fnTexture;
  92. // write max letter width and height of all letters
  93. *outFile << fd_pixCharWidth;
  94. *outFile << fd_pixCharHeight;
  95. // write entire letter data table
  96. for( INDEX iLetterData=0; iLetterData<256; iLetterData ++) {
  97. fd_fcdFontCharData[ iLetterData].Write_t( outFile);
  98. }
  99. }
  100. /*
  101. * Function used for creating font data object
  102. */
  103. void CFontData::Make_t( const CTFileName &fnTexture, PIX pixCharWidth, PIX pixCharHeight,
  104. CTFileName &fnOrderFile, BOOL bUseAlpha)
  105. {
  106. // do it only if font has not been created already
  107. ASSERT( fd_ptdTextureData == NULL);
  108. // remember texture name
  109. fd_fnTexture = fnTexture;
  110. // load texture and cache width
  111. fd_ptdTextureData = _pTextureStock->Obtain_t(fd_fnTexture);
  112. fd_ptdTextureData->Force( TEX_STATIC|TEX_CONSTANT);
  113. PIX pixTexWidth = fd_ptdTextureData->GetPixWidth();
  114. // load ascii order file (no application path necessary)
  115. CTString strLettersOrder;
  116. IgnoreApplicationPath();
  117. strLettersOrder.Load_t( fnOrderFile);
  118. UseApplicationPath();
  119. // remember letter width and height
  120. fd_pixCharWidth = pixCharWidth;
  121. fd_pixCharHeight = pixCharHeight;
  122. // determine address in memory where font definition begins in its larger mip-map
  123. ULONG *pulFont = fd_ptdTextureData->td_pulFrames;
  124. ASSERT( pulFont!=NULL);
  125. // find number of letters in line (assuming that the 1st line represents the width of every line)
  126. INDEX iLettersInLine=0;
  127. while( (strLettersOrder[iLettersInLine]!='\n') && iLettersInLine<strlen(strLettersOrder)) iLettersInLine++;
  128. if( iLettersInLine<=0) FatalError( "Invalid font definition ASCII file.");
  129. // determine pixelcheck mast depending of alpha channel usage
  130. COLOR colPixMask = 0xFFFFFF00; // FC is because of small tolerance for black
  131. if( bUseAlpha) colPixMask = 0xFFFFFFFF;
  132. // how much we must add to jump to character down
  133. PIX pixFontCharModulo = pixTexWidth * fd_pixCharHeight;
  134. // for all letters in font (ranging from space to last letter that user defined)
  135. INDEX iLetter=0;
  136. INDEX iCurrentLetterLine = 0;
  137. while( iLetter<strlen(strLettersOrder))
  138. { // for letters in one line
  139. for( INDEX iCurrentLetterColumn=0; iCurrentLetterColumn<iLettersInLine; iCurrentLetterColumn++)
  140. { // test if we at the end of whole array
  141. if( iLetter>=strlen(strLettersOrder)) break;
  142. // get char params
  143. unsigned char chrLetter = strLettersOrder[iLetter++];
  144. // reset current letter's width
  145. PIX pixCurrentStart = fd_pixCharWidth;
  146. PIX pixCurrentEnd = 0;
  147. // for all of the letter's lines
  148. for( INDEX iPixelLine=0; iPixelLine<fd_pixCharHeight; iPixelLine++)
  149. { // for all of the letter's pixels
  150. for( INDEX iPixelColumn=0; iPixelColumn<fd_pixCharWidth; iPixelColumn++)
  151. { // calculate current pixel's adress in font's texture
  152. ULONG *puwPixel = (ULONG*)( pulFont + pixFontCharModulo * iCurrentLetterLine + // calc right letter line
  153. fd_pixCharWidth * iCurrentLetterColumn + // move to right letter column
  154. pixTexWidth * iPixelLine + // move trough pixel lines of one letter
  155. iPixelColumn); // move trough pixel columns of one letter
  156. // if we test alpha channel and alpha value is not 0
  157. if( ByteSwap(*puwPixel) & colPixMask) {
  158. // if examined pixel is narrower in letter than last opaque pixel found, remember it as left-most pixel
  159. if( iPixelColumn < pixCurrentStart) pixCurrentStart = iPixelColumn;
  160. // if examined pixel is wider in letter than last opaque pixel found, remember it as right-most pixel
  161. if( iPixelColumn > pixCurrentEnd) pixCurrentEnd = iPixelColumn;
  162. }
  163. }
  164. }
  165. // letter's data is stored into table on appropriate place
  166. fd_fcdFontCharData[chrLetter].fcd_pixXOffset = iCurrentLetterColumn * fd_pixCharWidth;
  167. fd_fcdFontCharData[chrLetter].fcd_pixYOffset = iCurrentLetterLine * fd_pixCharHeight;
  168. fd_fcdFontCharData[chrLetter].fcd_pixStart = pixCurrentStart;
  169. fd_fcdFontCharData[chrLetter].fcd_pixEnd = pixCurrentEnd +1;
  170. }
  171. // advance to next line in text file
  172. iCurrentLetterLine++;
  173. iLetter++; // skip carriage return
  174. }
  175. // set default space width
  176. fd_fcdFontCharData[' '].fcd_pixStart = 0;
  177. SetSpaceWidth(0.5f);
  178. // all done
  179. SetVariableWidth();
  180. _pTextureStock->Release( fd_ptdTextureData);
  181. }