00001
00002
00003
00004
00005
00006
00007
00008
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
00043 m_hShader = m_pRender->GetpShaderBank()->LoadShader( m_pShaderName );
00044 pShader = m_pRender->GetpShaderBank()->GetpShader( m_hShader );
00045
00046
00047 if( ( pShader->GetnStages() == 0 ) && ( pShader->m_hTexture == KTEXTURE_NO ) )
00048 {
00049
00050 hTexture = m_pRender->GetpTextureBank()->CreateTexture( FONT_BITMAP_WIDTH, FONT_BITMAP_HEIGHT, 1, true );
00051 pTexture = m_pRender->GetpTextureBank()->GetpTexture( hTexture );
00052
00053
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
00064 HFONT hFont;
00065
00066 hFont = CreateFont( FONT_HEIGHT,
00067 FONT_WIDTH / 2,
00068 0,
00069 0,
00070 FW_NORMAL,
00071 FALSE,
00072 FALSE,
00073 FALSE,
00074 DEFAULT_CHARSET,
00075 OUT_DEFAULT_PRECIS,
00076 CLIP_DEFAULT_PRECIS,
00077 ANTIALIASED_QUALITY,
00078 DEFAULT_PITCH,
00079
00080
00081
00082
00083
00084
00085 m_pShaderName );
00086
00087
00088
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
00097 HBITMAP hBitmap;
00098
00099 hBitmap = CreateCompatibleBitmap( hBitmapDC, FONT_BITMAP_WIDTH, FONT_BITMAP_HEIGHT );
00100 SelectObject( hBitmapDC, hBitmap );
00101
00102
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
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
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
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
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
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
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
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
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
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
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
00352
00353 float dtexelu = 0.5f / FONT_BITMAP_WIDTH;
00354 float dtexelv = 0.5f / FONT_BITMAP_HEIGHT;
00355
00356
00357
00358
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
00396 }
00397
00398
00399
00400
00401