D:/Zythum/DinoKod/Render/Font.cpp

00001 //---------------------------------------------------------------------------------------------
00002 //      This file is a part of "DinoKod".
00003 //      Copyright © 2003 Dino Productions. All Rights Reserved.
00004 //      
00005 //      File                    : Font.cpp
00006 //      Author                  : Sebastien LEIX        sebastien.leix@wanadoo.fr
00007 //      Date                    : 09/09/2002
00008 //      Modification    :
00009 //
00010 //---------------------------------------------------------------------------------------------
00011 #include "Common/Assert.h"
00012 #include "Common/Error.h"
00013 #include "Render/Texture.h"
00014 #include "Render/Render.h"
00015 
00016 #include "Render/Font.h"
00017 
00018 //--------------------------------------------------------------------------------------------------------------------------
00019 KFont::KFont( KRender* pRender, char* pFontName )
00020 {
00021         m_pRender               = pRender;
00022         m_RatioX                = 1.0f;
00023         m_SpaceX                = 0.0f;
00024         m_hShader               = KSHADER_NO;
00025         m_pShaderName   = pFontName ? strdup( pFontName ) : strdup( "Terminal" );
00026 }
00027 
00028 //--------------------------------------------------------------------------------------------------------------------------
00029 KFont::~KFont()
00030 {
00031         if( m_pShaderName )
00032                 Freep( m_pShaderName );
00033 }
00034 
00035 //--------------------------------------------------------------------------------------------------------------------------
00036 bool KFont::Init()
00037 {
00038         KShader*        pShader;
00039         KTexture*       pTexture;
00040         KTEXTURE        hTexture;
00041 
00042         // Creation du shader
00043         m_hShader       = m_pRender->GetpShaderBank()->LoadShader( m_pShaderName );
00044         pShader         = m_pRender->GetpShaderBank()->GetpShader( m_hShader );
00045 
00046         // Le shader existe ? sinon, on le crée a partir d'une fonte Windows
00047         if( ( pShader->GetnStages() == 0 ) && ( pShader->m_hTexture == KTEXTURE_NO ) )
00048         {
00049                 // Creation de la texture
00050                 hTexture        = m_pRender->GetpTextureBank()->CreateTexture( FONT_BITMAP_WIDTH, FONT_BITMAP_HEIGHT, 1, true );
00051                 pTexture        = m_pRender->GetpTextureBank()->GetpTexture( hTexture );
00052 
00053                 // Ajoute la texture au shader
00054                 KShaderStage*   pStage          = new KShaderStage();
00055                 pStage->m_pTextureList          = new KTEXTURE[1];
00056                 pStage->m_pTextureList[0]       = hTexture;
00057                 pStage->m_nTextures                     = 1 ;
00058                 pStage->m_StageFlags            = KSSF_BLEND;
00059                 pStage->m_BlendSrc                      = KRBLEND_SRCALPHA;
00060                 pStage->m_BlendDst                      = KRBLEND_INVSRCALPHA;
00061                 pShader->m_StageList.Add( pStage );
00062 
00063                 // Creation de la font GDI
00064                 HFONT   hFont;
00065 
00066                 hFont = CreateFont( FONT_HEIGHT,                        // height of font
00067                                                         FONT_WIDTH / 2,                 // average character width
00068                                                         0,                                              // angle of escapement
00069                                                         0,                                              // base-line orientation angle
00070                                                         FW_NORMAL,                              // font weight
00071                                                         FALSE,                                  // italic attribute option
00072                                                         FALSE,                                  // underline attribute option
00073                                                         FALSE,                                  // strikeout attribute option
00074                                                         DEFAULT_CHARSET,                // character set identifier
00075                                                         OUT_DEFAULT_PRECIS,             // output precision
00076                                                         CLIP_DEFAULT_PRECIS,    // clipping precision
00077                                                         ANTIALIASED_QUALITY,//PROOF_QUALITY,            // output quality
00078                                                         DEFAULT_PITCH,                  // pitch and family
00079         //                                              "Small fonts"   );              // typeface name
00080         //                                              "Terminal"      );              // typeface name
00081         //                                              "Comic Sans MS" );              // typeface name
00082         //                                              "Tahoma"        );              // typeface name
00083         //                                              "Verdana"       );              // typeface name
00084         //                                              "Arial" );              // typeface name
00085                                                         m_pShaderName   );              // typeface name
00086 
00087 
00088                 // Creation du Device Context de la bitmap
00089                 HDC             hDC;
00090                 HDC             hBitmapDC;
00091 
00092                 hDC = GetDC( m_pRender->GetWindow() );
00093                 hBitmapDC = CreateCompatibleDC( hDC );
00094                 ReleaseDC( m_pRender->GetWindow(), hDC );
00095 
00096                 // Creation de la bitmap
00097                 HBITMAP hBitmap;
00098 
00099                 hBitmap = CreateCompatibleBitmap( hBitmapDC, FONT_BITMAP_WIDTH, FONT_BITMAP_HEIGHT );
00100                 SelectObject( hBitmapDC, hBitmap );
00101 
00102                 // Affiche la font dans la bitmap
00103                 char    Char;
00104                 RECT    Rect;
00105 
00106                 SetBkColor( hBitmapDC, RGB( 0, 0, 0 ) );
00107                 SetTextColor( hBitmapDC, RGB( 255, 255, 255 ) );
00108                 SelectObject( hBitmapDC, hFont );
00109 
00110                 for( s32 fy = 0; fy < FONT_NHEIGHT; fy ++ )
00111                 {
00112                         for( s32 fx = 0; fx < FONT_NWIDTH; fx ++ )
00113                         {
00114                                 Char = (char)(fy * FONT_NWIDTH + fx);
00115 //                              TextOut( hBitmapDC, fx * FONT_WIDTH + 1, fy * FONT_HEIGHT, &Char, 1 ); 
00116                                 Rect.left       = fx * FONT_WIDTH;
00117                                 Rect.top        = fy * FONT_HEIGHT; 
00118                                 Rect.right      = Rect.left + FONT_WIDTH; 
00119                                 Rect.bottom     = Rect.top + FONT_HEIGHT; 
00120                                 DrawText( hBitmapDC, &Char, 1, &Rect, 0 );
00121                         }
00122                 }
00123 
00124                 // Copie la bitmap vers la texture
00125                 COLORREF        ColorRef;
00126                 u32                     r, g, b, a;
00127 
00128                 pTexture->Lock();
00129 
00130                 for( u32 y = 0; y < FONT_BITMAP_HEIGHT; y ++ )
00131                 {
00132                         for( u32 x = 0; x < FONT_BITMAP_WIDTH; x ++ )
00133                         {
00134                                 ColorRef = GetPixel( hBitmapDC, x, y );
00135                                 r = ( ColorRef & 0x000000FF );
00136                                 g = (( ColorRef & 0x0000FF00 ) >> 8 );
00137                                 b = (( ColorRef & 0x00FF0000 ) >> 16 );
00138                                 a = (r + g + b) ? 255 : 0;
00139                                 pTexture->SetPixel( x, y, KRGBA( r, g, b, a ) );
00140                         }
00141                 }
00142 
00143                 pTexture->Unlock();
00144         }
00145 
00146         GenerateCropTable();
00147 
00148         return true;
00149 }
00150 
00151 //--------------------------------------------------------------------------------------------------------------------------
00152 void KFont::End()
00153 {
00154         KASSERT( m_pRender );
00155 
00156         m_pRender->GetpShaderBank()->UnloadShader( m_hShader );
00157 }
00158 
00159 //--------------------------------------------------------------------------------------------------------------------------
00160 bool KFont::CheckAlphaPixel( KTexture* pTexture, u32 x, u32 y, u8* pBits )
00161 {
00162         u8*             pPixel;
00163 
00164         // Recherche si le pixel a un alpha > 0
00165         if( ( x < 0 ) || ( x > pTexture->GetWidth() ) || ( y < 0 ) || ( y > pTexture->GetHeight() ) )
00166         {
00167                 KError::Error( m_pRender->GetWindow(), "KFont::CheckAlphaPixel(...) : Value out of range : x:%i/%i - y:%i/%i", x, FONT_BITMAP_WIDTH, y, FONT_BITMAP_HEIGHT );
00168                 return false;
00169         }
00170 
00171         switch( pTexture->GetFormat() )
00172         {
00173         case KTF_A4R4G4B4:
00174                 pPixel = &pBits[(pTexture->GetWidth() * y + x) * 2];
00175                 return (*((u16*)pPixel) & 0xF000) ? true : false;
00176 
00177         case KTF_A8R8G8B8:
00178                 pPixel = &pBits[(pTexture->GetWidth() * y + x) * 4];
00179                 return (*((u32*)pPixel) & 0xFF000000) ? true : false;
00180 
00181         default:
00182                 KError::Error( m_pRender->GetWindow(), "KFont::CheckAlphaPixel(...) : Font texture format not implemented" );
00183         }
00184 
00185         return false;
00186 }
00187 
00188 //--------------------------------------------------------------------------------------------------------------------------
00189 void KFont::GenerateCropTable()
00190 {
00191         KShader*        pShader;
00192         KTexture*       pTexture;
00193         u8*                     pBits = NULL;
00194         bool            bAlpha;
00195 
00196         // Generation d'une table de découpage pour permettre de coller les caracteres en supprimant les espaces
00197         pShader         = m_pRender->GetpShaderBank()->GetpShader( m_hShader );
00198         KASSERT( pShader );
00199         if( ( !pShader->GetnStages() ) || ( !pShader->m_StageList[0] ) || ( pShader->m_StageList[0]->m_pTextureList[0] == KTEXTURE_NO ) )
00200         {
00201                 KError::Error( m_pRender->GetWindow(), "KFont::GenerateCropTable(...) : The font shader need a font bitmap in first stage" );
00202                 return;
00203         }
00204 
00205         pTexture        = m_pRender->GetpTextureBank()->GetpTexture( pShader->m_StageList[0]->m_pTextureList[0] );
00206         
00207         pTexture->Lock( (void**)&pBits );
00208 
00209         for( u32 c = 0; c < 256; c ++ )
00210         {
00211                 m_CropTable[c].x1 = 0;
00212                 m_CropTable[c].x2 = FONT_WIDTH - 1;
00213                 m_CropTable[c].y1 = 0;
00214                 m_CropTable[c].y2 = FONT_HEIGHT - 1;
00215 
00216                 // Supprime l'espace gauche
00217                 m_CropTable[c].x1 = 0;
00218                 for( u32 x1 = 0; x1 < FONT_WIDTH; x1 ++ )
00219                 {
00220                         bAlpha = false;
00221                         for( u32 y = 0; y < FONT_HEIGHT; y ++ )
00222                         {
00223                                 if( CheckAlphaPixel(    pTexture,
00224                                                                                 ( ( c * FONT_WIDTH ) % FONT_BITMAP_WIDTH ) + x1,
00225                                                                                 ( ( c * FONT_WIDTH ) / FONT_BITMAP_WIDTH ) * FONT_HEIGHT + y,
00226                                                                                 pBits ) )
00227                                 {
00228                                         bAlpha = true;
00229                                         break;
00230                                 }
00231                         }
00232                         if( bAlpha )
00233                         {
00234                                 m_CropTable[c].x1 = x1;
00235                                 break;
00236                         }
00237                 }
00238 
00239                 // Supprime l'espace droit
00240                 m_CropTable[c].x2 = FONT_HEIGHT - 1;
00241                 for( u32 x2 = FONT_WIDTH - 1; x2 > 0; x2 -- )
00242                 {
00243                         bAlpha = false;
00244                         for( u32 y = 0; y < FONT_HEIGHT; y ++ )
00245                         {
00246                                 if( CheckAlphaPixel(    pTexture,
00247                                                                                 ( ( c * FONT_WIDTH ) % FONT_BITMAP_WIDTH ) + x2,
00248                                                                                 ( ( c * FONT_WIDTH ) / FONT_BITMAP_WIDTH ) * FONT_HEIGHT + y,
00249                                                                                 pBits ) )
00250                                 {
00251                                         bAlpha = true;
00252                                         break;
00253                                 }
00254                         }
00255                         if( bAlpha )
00256                         {
00257                                 m_CropTable[c].x2 = x2 + 1;
00258                                 break;
00259                         }
00260                 }
00261 
00262                 //  Laisse un ecart maximum ( bug de l'espace par exemple )
00263                 if( !bAlpha )
00264                 {
00265                         m_CropTable[c].x1 = 0;
00266                         m_CropTable[c].x2 = FONT_SPACE_WIDTH;
00267                 }
00268         }
00269 
00270         pTexture->Unlock();
00271 }
00272 
00273 //--------------------------------------------------------------------------------------------------------------------------
00274 KPt KFont::GetCharSize( char Car, float FontSize )
00275 {
00276         if( Car < 32 )
00277                 return KPt( 0, 0 );
00278 
00279 //      FontSize /= 2.0f;
00280 
00281         s32     SizeX = s32( (float)(m_CropTable[Car].x2 - m_CropTable[Car].x1 + 1) * m_RatioX * FontSize );
00282         s32     SizeY = s32( (float)(m_CropTable[Car].y2 - m_CropTable[Car].y1 + 1) * FontSize );
00283 
00284 //      return KPt( (s32)((float)(m_CropTable[Car].x2 - m_CropTable[Car].x1 + 1) * m_RatioX + m_SpaceX), (s32)(m_CropTable[Car].y2 - m_CropTable[Car].y1 ) );
00285         return KPt( SizeX, SizeY );
00286 }
00287 
00288 //--------------------------------------------------------------------------------------------------------------------------
00289 KPt KFont::GetTextSize( char* pText, float FontSize )
00290 {
00291         KPt             Size( 0, 0 );
00292         KPt             Tmp;
00293 
00294         if( pText )
00295         {
00296                 for( u32 i = 0; i < strlen( pText ); i ++ )
00297                 {
00298                         Tmp = GetCharSize( pText[i], FontSize );
00299                         Size.x += Tmp.x + (s32)m_SpaceX;
00300                         if( Tmp.y > Size.y )
00301                                 Size.y = Tmp.y;
00302                 }
00303         }
00304 
00305         return Size;
00306 }
00307 
00308 //--------------------------------------------------------------------------------------------------------------------------
00309 void KFont::Print( KPt& Pos, char* pText, float FontSize, KFONTALIGN FontAlign, KCOLOR Color )
00310 {
00311         KASSERT( pText );
00312 
00313         KTLVertex                       vVertex[4];
00314         unsigned char           Car;
00315         int                                     Length = (int)strlen( pText );
00316         float                           Italic = 0.0f;
00317         KPt                                     PosOffset;
00318         KPt                                     CarPos = KPt( 0, 0 );
00319 
00320 //      FontSize /= 2.0f;
00321 
00322         switch( FontAlign )
00323         {
00324         case KFA_LEFT:
00325                 PosOffset = Pos;
00326                 break;
00327         case KFA_RIGHT:
00328                 PosOffset = Pos - KFont::GetTextSize( pText );
00329                 break;
00330         case KFA_CENTER:
00331                 PosOffset = Pos + (KFont::GetTextSize( pText )) / 2;
00332                 break;
00333         }
00334 
00335         CarPos = CarPos + PosOffset;
00336 
00337         for(int i = 0;i < Length;i ++)
00338         {
00339                 if( (u8)pText[i] < 32 )
00340                         continue;
00341 
00342                 Car = pText[i];
00343                 
00344                 float           posx = (float)(Car % (FONT_BITMAP_WIDTH / FONT_WIDTH));
00345                 float           posy = (float)(Car / (FONT_BITMAP_WIDTH / FONT_WIDTH));
00346 
00347                 float           minx = (float)(posx * FONT_WIDTH)                       / FONT_BITMAP_WIDTH;
00348                 float           maxx = (float)((posx + 1) * FONT_WIDTH)         / FONT_BITMAP_WIDTH;
00349                 float           miny = (float)(posy * FONT_HEIGHT)                      / FONT_BITMAP_HEIGHT;
00350                 float           maxy = (float)((posy + 1) * FONT_HEIGHT)        / FONT_BITMAP_HEIGHT;
00351 //              float           FontWidth       = FONT_WIDTH * FontSize;
00352 //              float           FontHeight      = FONT_HEIGHT * FontSize;
00353                 float           dtexelu = 0.5f / FONT_BITMAP_WIDTH;
00354                 float           dtexelv = 0.5f / FONT_BITMAP_HEIGHT;
00355 
00356 //              m_CropTable[Car].x1 = 0;
00357 //              m_CropTable[Car].x2 = 2;
00358 //              minx = 0.0f;
00359         
00360 
00361                 maxx = minx + (float)(m_CropTable[Car].x2+1) / FONT_BITMAP_WIDTH;
00362                 minx += m_CropTable[Car].x1 / (float)FONT_BITMAP_WIDTH;
00363                 
00364                 minx += dtexelu;
00365                 maxx += dtexelu;
00366                 miny += dtexelv;
00367                 maxy += dtexelv;
00368         
00369                 float                   tu[4] = { minx, maxx, minx, maxx };
00370                 float                   tv[4] = { miny, miny, maxy, maxy };
00371 
00372                 s32     SizeX = s32( (float)(m_CropTable[Car].x2 - m_CropTable[Car].x1 + 1) * m_RatioX * FontSize );
00373                 s32     SizeY = s32( (float)(m_CropTable[Car].y2 - m_CropTable[Car].y1 + 1) * FontSize );
00374 
00375                 m_pRender->DrawQuad(    CarPos.x, 
00376                                                                 PosOffset.y,
00377                                                                 SizeX,
00378                                                                 SizeY,
00379                                                                 m_hShader,
00380                                                                 Color,
00381                                                                 KRGBA( 0, 0, 0, 0 ),
00382                                                                 KRM_NORMAL,
00383                                                                 tu,
00384                                                                 tv );
00385 
00386                 CarPos.x += SizeX + (s32)m_SpaceX;
00387         }
00388 
00389         float                   dtexel = 0.5f / FONT_BITMAP_WIDTH;
00390         float                   max = 1.0f + dtexel;
00391         float                   min = 0.0f + dtexel;
00392         float                   pTU[4] = {min, max, min, max};
00393         float                   pTV[4] = {min, min, max, max};
00394 
00395 //      m_pRender->DrawQuad( 0, 0, FONT_BITMAP_WIDTH, FONT_BITMAP_HEIGHT, m_hShader, KRGB( 255, 255, 255 ), KRGB( 0, 0, 0 ), KRM_NORMAL, pTU, pTV );
00396 }
00397 
00398 
00399 
00400 
00401 

Generated on Sun Mar 25 20:02:15 2007 for Zythum Project by  doxygen 1.5.1-p1