u16 CGameFont::SplitByWidth( u16 * puBuffer , u16 uBufferSize , float fTargetWidth , const char * pszText ) { VERIFY( puBuffer && uBufferSize && pszText ); wide_char wsStr[ MAX_MB_CHARS ] , wsPos[ MAX_MB_CHARS ]; float fCurWidth = 0.0f , fDelta = 0.0f; u16 nLines = 0; u16 len = mbhMulti2Wide( wsStr , wsPos , MAX_MB_CHARS , pszText ); for ( u16 i = 1 ; i <= len ; i++ ) { fDelta = GetCharTC( wsStr[ i ] ).z - 2; if ( IsNeedSpaceCharacter( wsStr[ i ] ) ) fDelta += fXStep; if ( ( ( fCurWidth + fDelta ) > fTargetWidth ) && // overlength ( ! IsBadStartCharacter( wsStr[ i ] ) ) && // can start with this character ( i < len ) && // is not the last character ( ( i > 1 ) && ( ! IsBadEndCharacter( wsStr[ i - 1 ] ) ) ) // && // do not stop the string on a "bad" character // ( ( i > 1 ) && ( ! ( ( IsAlphaCharacter( wsStr[ i - 1 ] ) ) && ( IsAlphaCharacter( wsStr[ i ] ) ) ) ) ) // do not split numbers or words ) { fCurWidth = fDelta; VERIFY( nLines < uBufferSize ); puBuffer[ nLines++ ] = wsPos[ i - 1 ]; } else fCurWidth += fDelta; } return nLines; }
float CGameFont::SizeOf_(LPCSTR s,float size) { if (s&&s[0]){ int len = xr_strlen(s); float X = 0; if (len) for (int j=0; j<len; j++) X += GetCharTC(s[j]).z; return (X*vInterval.x/**vTS.x*/); } return 0; }
float CGameFont::SizeOf_( const wide_char *wsStr ) { if ( ! ( wsStr && wsStr[ 0 ] ) ) return 0; unsigned int len = wsStr[ 0 ]; float X = 0.0f , fDelta = 0.0f; if ( len ) for ( unsigned int j=1 ; j <= len ; j++ ) { fDelta = GetCharTC( wsStr[ j ] ).z - 2; if ( IsNeedSpaceCharacter( wsStr[ j ] ) ) fDelta += fXStep; X += fDelta; } return ( X * vInterval.x ); }
float CGameFont::SizeOf_( LPCSTR s ) { if ( ! ( s && s[ 0 ] ) ) return 0; if ( IsMultibyte() ) { wide_char wsStr[ MAX_MB_CHARS ]; mbhMulti2Wide( wsStr , NULL , MAX_MB_CHARS , s ); return SizeOf_( wsStr ); } int len = xr_strlen(s); float X = 0; if (len) for (int j=0; j<len; j++) X += GetCharTC( ( u16 ) ( u8 ) s[ j ] ).z; return (X*vInterval.x); }
u16 CGameFont::GetCutLengthPos( float fTargetWidth , const char * pszText ) { VERIFY( pszText ); wide_char wsStr[ MAX_MB_CHARS ], wsPos[ MAX_MB_CHARS ]; float fCurWidth = 0.0f , fDelta = 0.0f; u16 len = mbhMulti2Wide( wsStr , wsPos , MAX_MB_CHARS , pszText ); for ( u16 i = 1 ; i <= len ; i++ ) { fDelta = GetCharTC( wsStr[ i ] ).z - 2; if ( IsNeedSpaceCharacter( wsStr[ i ] ) ) fDelta += fXStep; if ( ( fCurWidth + fDelta ) > fTargetWidth ) break; else fCurWidth += fDelta; } return wsPos[ i - 1 ]; }
float CGameFont::SizeOf_( const char cChar ) { return ( GetCharTC( ( u16 ) ( u8 ) ( ( ( IsMultibyte() && cChar == ' ' ) ) ? 0 : cChar) ).z * vInterval.x ); }
float CGameFont::SizeOf_(char s,float size) { return ( GetCharTC(s).z*vInterval.x/* *vTS.x*/ ); }
void CGameFont::OnRender() { VERIFY (g_bRendering); if (pShader) RCache.set_Shader (pShader); if (!(uFlags&fsValid)){ CTexture* T = RCache.get_ActiveTexture(0); vTS.set ((int)T->get_Width(),(int)T->get_Height()); /* vHalfPixel.set (0.5f/float(vTS.x),0.5f/float(vTS.y)); for (int i=0; i<256; i++){ Fvector& tc = TCMap[i]; tc.x /= float(vTS.x); tc.y /= float(vTS.y); tc.z /= float(vTS.x); } fTCHeight = fHeight/float(vTS.y); uFlags |= fsValid; */ fTCHeight = fHeight/float(vTS.y); uFlags |= fsValid; } for (u32 i=0; i<strings.size(); ){ // calculate first-fit int count = 1; int length = xr_strlen(strings[i].string); while ((i+count)<strings.size()) { int L = xr_strlen(strings[i+count].string); if ((L+length)<MAX_CHARS){ count ++; length += L; } else break; } // lock AGP memory u32 vOffset; FVF::TL* v = (FVF::TL*)RCache.Vertex.Lock (length*4,pGeom.stride(),vOffset); FVF::TL* start = v; // fill vertices u32 last = i+count; for (; i<last; i++) { String &PS = strings[i]; int len = xr_strlen(PS.string); if (len) { float X = float(iFloor(PS.x)); float Y = float(iFloor(PS.y)); float S = PS.height*g_current_font_scale.y; float Y2 = Y+S; switch(PS.align) { case alCenter: X -= ( iFloor(SizeOf_(PS.string,PS.height)*.5f) ) * g_current_font_scale.x; break; case alRight: X -= iFloor(SizeOf_(PS.string,PS.height)); break; } u32 clr,clr2; clr2 = clr = PS.c; if (uFlags&fsGradient){ u32 _R = color_get_R (clr)/2; u32 _G = color_get_G (clr)/2; u32 _B = color_get_B (clr)/2; u32 _A = color_get_A (clr); clr2 = color_rgba (_R,_G,_B,_A); } float tu,tv; for (int j=0; j<len; j++) { int c = GetCharRM (PS.string[j]); Fvector l = GetCharTC (PS.string[j]); float scw = l.z * g_current_font_scale.x; //. float scw = vTS.x * l.z * g_current_font_scale.x; float fTCWidth = l.z/vTS.x; if ((c>=0)&&!fis_zero(l.z)) { tu = l.x/vTS.x;//+vHalfPixel.x; tv = l.y/vTS.y;//+vHalfPixel.y; v->set (X-0.5f, Y2-0.5f, clr2,tu, tv+fTCHeight); v++; v->set (X-0.5f, Y-0.5f, clr, tu, tv); v++; v->set (X+scw-0.5f, Y2-0.5f, clr2,tu+fTCWidth, tv+fTCHeight); v++; v->set (X+scw-0.5f, Y-0.5f, clr, tu+fTCWidth, tv); v++; } X+=scw*vInterval.x; } } } // Unlock and draw u32 vCount = (u32)(v-start); RCache.Vertex.Unlock (vCount,pGeom.stride()); if (vCount){ RCache.set_Geometry (pGeom); RCache.Render (D3DPT_TRIANGLELIST,vOffset,0,vCount,0,vCount/2); } } strings.clear_not_free (); }