From 77ea03a62c6925a49192a516489a17aa6eeafab3 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Fri, 3 Feb 2023 08:51:16 +0300 Subject: [PATCH] engine: client: introduce bare-bones font manager and text drawing manager * wire hud_fontscale so HUD font scaling can be used independently from hud_scale * allow small optimizatinons, like optional UTF-8 decoding, or not calling SetRenderMode for each character * even less copypasted code in text drawing between client code and console * get rid of direct DrawCharacter calls when it can be just DrawString * fix net_speeds, r_speeds with scaled console fonts * try to fix MobilityAPI's pfnDrawCharacterScaled * center keyboard keys in OSK code --- engine/client/cl_font.c | 291 ++++++++++++++++++++++++++++ engine/client/cl_game.c | 137 +++++-------- engine/client/cl_gameui.c | 22 +-- engine/client/cl_mobile.c | 37 ++-- engine/client/cl_netgraph.c | 20 +- engine/client/cl_scrn.c | 47 +---- engine/client/client.h | 50 +++-- engine/client/console.c | 372 ++++-------------------------------- engine/client/keys.c | 15 +- 9 files changed, 469 insertions(+), 522 deletions(-) create mode 100644 engine/client/cl_font.c diff --git a/engine/client/cl_font.c b/engine/client/cl_font.c new file mode 100644 index 00000000..3445f40d --- /dev/null +++ b/engine/client/cl_font.c @@ -0,0 +1,291 @@ +/* +cl_font.c - bare bones engine font manager +Copyright (C) 2023 Alibek Omarov + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#include "common.h" +#include "filesystem.h" +#include "client.h" +#include "qfont.h" + +qboolean CL_FixedFont( cl_font_t *font ) +{ + return font && font->valid && font->type == FONT_FIXED; +} + +static int CL_LoadFontTexture( const char *fontname, uint texFlags, int *width ) +{ + int font_width; + int tex; + + if( !g_fsapi.FileExists( fontname, false )) + return 0; + + tex = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, texFlags ); + if( !tex ) + return 0; + + font_width = REF_GET_PARM( PARM_TEX_WIDTH, tex ); + if( !font_width ) + { + ref.dllFuncs.GL_FreeTexture( tex ); + return 0; + } + + *width = font_width; + return tex; +} + +qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags ) +{ + int font_width, i; + + if( font->valid ) + return true; // already loaded + + font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width ); + if( !font->hFontTexture ) + return false; + + font->type = FONT_FIXED; + font->valid = true; + font->scale = scale; + font->nearest = FBitSet( texFlags, TF_NEAREST ); + font->rendermode = rendermode; + font->charHeight = Q_rint( font_width / 16 * scale ); + + for( i = 0; i < ARRAYSIZE( font->fontRc ); i++ ) + { + font->fontRc[i].left = ( i * font_width / 16 ) % font_width; + font->fontRc[i].right = font->fontRc[i].left + font_width / 16; + font->fontRc[i].top = ( i / 16 ) * ( font_width / 16 ); + font->fontRc[i].bottom = font->fontRc[i].top + font_width / 16; + + font->charWidths[i] = Q_rint( font_width / 16 * scale ); + } + + return true; +} + +qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags ) +{ + qfont_t src; + file_t *fd; + int font_width, i; + + if( font->valid ) + return true; + + fd = g_fsapi.Open( fontname, "r", false ); + if( !fd ) + return false; + + if( g_fsapi.Read( fd, &src, sizeof( qfont_t )) != sizeof( qfont_t )) + { + g_fsapi.Close( fd ); + return false; + } + + g_fsapi.Close( fd ); + + font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width ); + if( !font->hFontTexture ) + return false; + + font->type = FONT_VARIABLE; + font->valid = true; + font->scale = scale; + font->nearest = FBitSet( texFlags, TF_NEAREST ); + font->rendermode = rendermode; + font->charHeight = Q_rint( src.rowheight * scale ); + + for( i = 0; i < ARRAYSIZE( font->fontRc ); i++ ) + { + const charinfo *ci = &src.fontinfo[i]; + + font->fontRc[i].left = (word)ci->startoffset % font_width; + font->fontRc[i].right = font->fontRc[i].left + ci->charwidth; + font->fontRc[i].top = (word)ci->startoffset / font_width; + font->fontRc[i].bottom = font->fontRc[i].top + src.rowheight; + + font->charWidths[i] = Q_rint( src.fontinfo[i].charwidth * scale ); + } + + return true; +} + +void CL_FreeFont( cl_font_t *font ) +{ + if( !font || !font->valid ) + return; + + ref.dllFuncs.GL_FreeTexture( font->hFontTexture ); + memset( font, 0, sizeof( *font )); +} + +int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags ) +{ + wrect_t *rc; + float w, h; + float s1, t1, s2, t2, half = 0.5f; + int texw, texh; + + if( !font || !font->valid || y < -font->charHeight ) + return 0; + + if( FBitSet( flags, FONT_DRAW_UTF8 )) + number = Con_UtfProcessChar( number & 255 ); + else number &= 255; + + if( !number || !font->charWidths[number]) + return 0; + + R_GetTextureParms( &texw, &texh, font->hFontTexture ); + if( !texw || !texh ) + return 0; + + rc = &font->fontRc[number]; + if( font->nearest ) + half = 0; + + s1 = ((float)rc->left + half ) / texw; + t1 = ((float)rc->top + half ) / texh; + s2 = ((float)rc->right - half ) / texw; + t2 = ((float)rc->bottom - half ) / texh; + w = ( rc->right - rc->left ) * font->scale; + h = ( rc->bottom - rc->top ) * font->scale; + + if( FBitSet( flags, FONT_DRAW_HUD )) + SPR_AdjustSize( &x, &y, &w, &h ); + + if( !FBitSet( flags, FONT_DRAW_NORENDERMODE )) + ref.dllFuncs.GL_SetRenderMode( font->rendermode ); + + // don't apply color to fixed fonts it's already colored + if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8 + ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] ); + else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] ); + ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, font->hFontTexture ); + ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); // don't forget reset color + + return font->charWidths[number]; +} + +int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags ) +{ + rgba_t current_color; + int draw_len = 0; + + if( !font || !font->valid ) + return 0; + + if( FBitSet( flags, FONT_DRAW_UTF8 )) + Con_UtfProcessChar( 0 ); // clear utf state + + if( !FBitSet( flags, FONT_DRAW_NORENDERMODE )) + ref.dllFuncs.GL_SetRenderMode( font->rendermode ); + + Vector4Copy( color, current_color ); + + while( *s ) + { + if( *s == '\n' ) + { + s++; + + if( !*s ) + break; + + draw_len = 0; + y += font->charHeight; + } + + if( IsColorString( s )) + { + if( FBitSet( flags, FONT_DRAW_FORCECOL )) + VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color ); + + s += 2; + continue; + } + + // skip setting rendermode, it was changed for this string already + draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, color, font, flags | FONT_DRAW_NORENDERMODE ); + + s++; + } + + return draw_len; +} + +void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height ) +{ + if( !font || !font->valid ) return; + if( width ) *width = font->charWidths[number & 255]; + if( height ) *height = font->charHeight; +} + +void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags ) +{ + int draw_len = 0; + + if( !font || !font->valid ) + return; + + if( height ) + *height = font->charHeight; + + if( width ) + *width = 0; + + if( !COM_CheckString( s )) + return; + + if( FBitSet( flags, FONT_DRAW_UTF8 )) + Con_UtfProcessChar( 0 ); // reset utf state + + while( *s ) + { + int number; + + if( *s == '\n' ) + { + // BUG: no check for end string here + // but high chances somebody's relying on this + s++; + draw_len = 0; + if( height ) + *height += font->charHeight; + } + + if( IsColorString( s )) + { + s += 2; + continue; + } + + if( FBitSet( flags, FONT_DRAW_UTF8 )) + number = Con_UtfProcessChar( (byte)*s ); + else number = (byte)*s; + + if( number ) + { + draw_len += font->charWidths[*s]; + + if( draw_len > *width ) + *width = draw_len; + } + + s++; + } +} diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 3e65c516..a1549f4a 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -306,9 +306,7 @@ print centerscreen message */ void CL_CenterPrint( const char *text, float y ) { - int length = 0; - int width = 0; - char *s; + cl_font_t *font = Con_GetCurFont(); if( !COM_CheckString( text )) return; @@ -317,24 +315,13 @@ void CL_CenterPrint( const char *text, float y ) clgame.centerPrint.totalWidth = 0; clgame.centerPrint.time = cl.mtime[0]; // allow pause for centerprint Q_strncpy( clgame.centerPrint.message, text, sizeof( clgame.centerPrint.message )); - s = clgame.centerPrint.message; - // count the number of lines for centering - while( *s ) - { - if( *s == '\n' ) - { - clgame.centerPrint.lines++; - if( width > clgame.centerPrint.totalWidth ) - clgame.centerPrint.totalWidth = width; - width = 0; - } - else width += clgame.scrInfo.charWidths[*s]; - s++; - length++; - } + CL_DrawStringLen( font, + clgame.centerPrint.message, + &clgame.centerPrint.totalWidth, + &clgame.centerPrint.totalHeight, + FONT_DRAW_HUD | FONT_DRAW_UTF8 ); - clgame.centerPrint.totalHeight = ( clgame.centerPrint.lines * clgame.scrInfo.iCharHeight ); clgame.centerPrint.y = CL_AdjustYPos( y, clgame.centerPrint.totalHeight ); } @@ -502,6 +489,7 @@ called each frame */ void CL_DrawCenterPrint( void ) { + cl_font_t *font = Con_GetCurFont(); char *pText; int i, j, x, y; int width, lineLength; @@ -521,8 +509,10 @@ void CL_DrawCenterPrint( void ) y = clgame.centerPrint.y; // start y colorDefault = g_color_table[7]; pText = clgame.centerPrint.message; - Con_DrawCharacterLen( 0, NULL, &charHeight ); + CL_DrawCharacterLen( font, 0, NULL, &charHeight ); + + ref.dllFuncs.GL_SetRenderMode( font->rendermode ); for( i = 0; i < clgame.centerPrint.lines; i++ ) { lineLength = 0; @@ -532,7 +522,7 @@ void CL_DrawCenterPrint( void ) { byte c = *pText; line[lineLength] = c; - Con_DrawCharacterLen( c, &charWidth, NULL ); + CL_DrawCharacterLen( font, c, &charWidth, NULL ); width += charWidth; lineLength++; pText++; @@ -549,7 +539,7 @@ void CL_DrawCenterPrint( void ) for( j = 0; j < lineLength; j++ ) { if( x >= 0 && y >= 0 && x <= refState.width ) - x += Con_DrawCharacter( x, y, line[j], colorDefault ); + x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_UTF8 | FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE ); } y += charHeight; } @@ -1600,6 +1590,14 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo ) { float scale_factor = hud_scale->value; + if( FBitSet( hud_fontscale->flags, FCVAR_CHANGED )) + { + CL_FreeFont( &cls.creditsFont ); + SCR_LoadCreditsFont(); + + ClearBits( hud_fontscale->flags, FCVAR_CHANGED ); + } + // setup screen info clgame.scrInfo.iSize = sizeof( clgame.scrInfo ); clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH; @@ -1844,24 +1842,13 @@ returns drawed chachter width (in real screen pixels) */ static int GAME_EXPORT pfnDrawCharacter( int x, int y, int number, int r, int g, int b ) { - if( !cls.creditsFont.valid ) - return 0; + rgba_t color = { r, g, b, 255 }; + int flags = FONT_DRAW_HUD; if( hud_utf8->value ) - number = Con_UtfProcessChar( number ); - - number &= 255; - - if( number < 32 ) return 0; - if( y < -clgame.scrInfo.iCharHeight ) - return 0; - - clgame.ds.adjust_size = true; - pfnPIC_Set( cls.creditsFont.hFontTexture, r, g, b, 255 ); - pfnPIC_DrawAdditive( x, y, -1, -1, &cls.creditsFont.fontRc[number] ); - clgame.ds.adjust_size = false; + flags |= FONT_DRAW_UTF8; - return clgame.scrInfo.charWidths[number]; + return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags ); } /* @@ -1873,20 +1860,12 @@ drawing string like a console string */ int GAME_EXPORT pfnDrawConsoleString( int x, int y, char *string ) { - int drawLen; - - if( !COM_CheckString( string )) - return 0; // silent ignore - Con_SetFont( con_fontsize->value ); - - clgame.ds.adjust_size = true; - drawLen = Con_DrawString( x, y, string, clgame.ds.textColor ); - MakeRGBA( clgame.ds.textColor, 255, 255, 255, 255 ); - clgame.ds.adjust_size = false; - - Con_RestoreFont(); + cl_font_t *font = Con_GetFont( con_fontsize->value ); + rgba_t color; + Vector4Copy( clgame.ds.textColor, color ); + Vector4Set( clgame.ds.textColor, 255, 255, 255, 255 ); - return (x + drawLen); // exclude color prexfixes + return x + CL_DrawString( x, y, string, color, font, FONT_DRAW_UTF8 | FONT_DRAW_HUD ); } /* @@ -1914,9 +1893,9 @@ compute string length in screen pixels */ void GAME_EXPORT pfnDrawConsoleStringLen( const char *pText, int *length, int *height ) { - Con_SetFont( con_fontsize->value ); - Con_DrawStringLen( pText, length, height ); - Con_RestoreFont(); + cl_font_t *font = Con_GetFont( con_fontsize->value ); + + CL_DrawStringLen( font, pText, length, height, FONT_DRAW_UTF8 | FONT_DRAW_HUD ); } /* @@ -2839,23 +2818,7 @@ pfnVGUI2DrawCharacter */ static int GAME_EXPORT pfnVGUI2DrawCharacter( int x, int y, int number, unsigned int font ) { - if( !cls.creditsFont.valid ) - return 0; - - number &= 255; - - number = Con_UtfProcessChar( number ); - - if( number < 32 ) return 0; - if( y < -clgame.scrInfo.iCharHeight ) - return 0; - - clgame.ds.adjust_size = true; - gameui.ds.gl_texturenum = cls.creditsFont.hFontTexture; - pfnPIC_DrawAdditive( x, y, -1, -1, &cls.creditsFont.fontRc[number] ); - clgame.ds.adjust_size = false; - - return clgame.scrInfo.charWidths[number]; + return pfnDrawCharacter( x, y, number, 255, 255, 255 ); } /* @@ -2866,9 +2829,6 @@ pfnVGUI2DrawCharacterAdditive */ static int GAME_EXPORT pfnVGUI2DrawCharacterAdditive( int x, int y, int ch, int r, int g, int b, unsigned int font ) { - if( !hud_utf8->value ) - ch = Con_UtfProcessChar( ch ); - return pfnDrawCharacter( x, y, ch, r, g, b ); } @@ -2880,16 +2840,13 @@ pfnDrawString */ static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b ) { - int iWidth = 0; - Con_UtfProcessChar(0); + rgba_t color = { r, g, b, 255 }; + int flags = FONT_DRAW_HUD; - // draw the string until we hit the null character or a newline character - for ( ; *str != 0 && *str != '\n'; str++ ) - { - iWidth += pfnVGUI2DrawCharacterAdditive( x + iWidth, y, (unsigned char)*str, r, g, b, 0 ); - } + if( hud_utf8->value ) + SetBits( flags, FONT_DRAW_UTF8 ); - return iWidth; + return CL_DrawString( x, y, str, color, &cls.creditsFont, flags ); } /* @@ -2900,11 +2857,19 @@ pfnDrawStringReverse */ static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b ) { - // find the end of the string - char *szIt; - for( szIt = (char*)str; *szIt != 0; szIt++ ) - x -= clgame.scrInfo.charWidths[ (unsigned char) *szIt ]; - return pfnDrawString( x, y, str, r, g, b ); + rgba_t color = { r, g, b, 255 }; + int flags = FONT_DRAW_HUD; + int width, height; + + if( hud_utf8->value ) + SetBits( flags, FONT_DRAW_UTF8 ); + + CL_DrawStringLen( &cls.creditsFont, str, &width, &height, flags ); + + x -= width; + y -= height; + + return CL_DrawString( x, y, str, color, &cls.creditsFont, flags ); } /* diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index 440afa32..e641cbbd 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -487,22 +487,10 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const if( prc ) { // calc user-defined rectangle - s1 = prc->left; - t1 = prc->top; - s2 = prc->right; - t2 = prc->bottom; - - if( clgame.ds.adjust_size ) - { - SPR_AdjustTexCoords( w, h, &s1, &t1, &s2, &t2 ); - } - else - { - s1 /= (float)w; - t1 /= (float)h; - s2 /= (float)w; - t2 /= (float)h; - } + s1 = prc->left / (float)w; + t1 = prc->top / (float)h; + s2 = prc->right / (float)w; + t2 = prc->bottom / (float)h; if( width == -1 && height == -1 ) { @@ -526,8 +514,6 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 )) return; - if( clgame.ds.adjust_size ) - SPR_AdjustSize( &x, &y, &width, &height ); ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, gameui.ds.gl_texturenum ); ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); } diff --git a/engine/client/cl_mobile.c b/engine/client/cl_mobile.c index 3e59b85a..db8791c5 100644 --- a/engine/client/cl_mobile.c +++ b/engine/client/cl_mobile.c @@ -25,6 +25,9 @@ mobile_engfuncs_t *gMobileEngfuncs; convar_t *vibration_length; convar_t *vibration_enable; +static cl_font_t g_scaled_font; +static float g_font_scale; + static void pfnVibrate( float life, char flags ) { if( !vibration_enable->value ) @@ -60,28 +63,28 @@ static void pfnEnableTextInput( int enable ) static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b, float scale ) { - int width = clgame.scrInfo.charWidths[number] * scale * hud_scale->value; - int height = clgame.scrInfo.iCharHeight * scale * hud_scale->value; - - if( !cls.creditsFont.valid ) - return 0; - - x *= hud_scale->value; - y *= hud_scale->value; + // this call is very ineffective and possibly broken! + rgba_t color = { r, g, b, 255 }; + int flags = FONT_DRAW_HUD; - number &= 255; - number = Con_UtfProcessChar( number ); + if( hud_utf8->value ) + SetBits( flags, FONT_DRAW_UTF8 ); - if( number < 32 ) - return 0; + if( fabs( g_font_scale - scale ) > 0.1f || + g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture ) + { + int i; - if( y < -height ) - return 0; + g_scaled_font = cls.creditsFont; + g_scaled_font.scale *= scale; + g_scaled_font.charHeight *= scale; + for( i = 0; i < ARRAYSIZE( g_scaled_font.charWidths ); i++ ) + g_scaled_font.charWidths[i] *= scale; - pfnPIC_Set( cls.creditsFont.hFontTexture, r, g, b, 255 ); - pfnPIC_DrawAdditive( x, y, width, height, &cls.creditsFont.fontRc[number] ); + g_font_scale = scale; + } - return width; + return CL_DrawCharacter( x, y, number, color, &g_scaled_font, flags ); } static void *pfnGetNativeObject( const char *obj ) diff --git a/engine/client/cl_netgraph.c b/engine/client/cl_netgraph.c index 51c5a4e5..484adc1b 100644 --- a/engine/client/cl_netgraph.c +++ b/engine/client/cl_netgraph.c @@ -364,6 +364,7 @@ NetGraph_DrawTextFields static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke, int graphtype ) { static int lastout; + cl_font_t *font = Con_GetFont( 0 ); rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; int ptx = Q_max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 ); int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 ); @@ -385,16 +386,17 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun // move rolling average framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate; - Con_SetFont( 0 ); + + ref.dllFuncs.GL_SetRenderMode( font->rendermode ); if( framerate > 0.0f ) { y -= net_graphheight->value; - Con_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors ); + CL_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors, font, FONT_DRAW_NORENDERMODE ); if( avg > 1.0f ) - Con_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors ); + CL_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors, font, FONT_DRAW_NORENDERMODE ); y += 15; @@ -402,10 +404,10 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun if( !out ) out = lastout; else lastout = out; - Con_DrawString( x, y, va( "in : %i %.2f kb/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors ); + CL_DrawString( x, y, va( "in : %i %.2f kb/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors, font, FONT_DRAW_NORENDERMODE ); y += 15; - Con_DrawString( x, y, va( "out: %i %.2f kb/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors ); + CL_DrawString( x, y, va( "out: %i %.2f kb/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors, font, FONT_DRAW_NORENDERMODE ); y += 15; if( graphtype > 2 ) @@ -413,16 +415,14 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01f ); int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01f ); - Con_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors ); + CL_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors, font, FONT_DRAW_NORENDERMODE ); } } if( graphtype < 3 ) - Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors ); - - Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors ); + CL_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors, font, FONT_DRAW_NORENDERMODE ); - Con_RestoreFont(); + CL_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors, font, FONT_DRAW_NORENDERMODE ); } /* diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index e4e99eab..db343ce4 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -160,6 +160,7 @@ void SCR_NetSpeeds( void ) static int max_clfps = 0; int cur_clfps = 0; rgba_t color; + cl_font_t *font = Con_GetCurFont(); if( !host.allow_console ) return; @@ -196,25 +197,11 @@ void SCR_NetSpeeds( void ) Q_memprint( cls.netchan.total_sended ) ); - x = refState.width - 320; + x = refState.width - 320 * font->scale; y = 384; - Con_DrawStringLen( NULL, NULL, &height ); MakeRGBA( color, 255, 255, 255, 255 ); - - p = start = msg; - - do - { - end = Q_strchr( p, '\n' ); - if( end ) msg[end-start] = '\0'; - - Con_DrawString( x, y, p, color ); - y += height; - - if( end ) p = end + 1; - else break; - } while( 1 ); + CL_DrawString( x, y, msg, color, font, 0 ); } /* @@ -234,28 +221,13 @@ void SCR_RSpeeds( void ) int x, y, height; char *p, *start, *end; rgba_t color; + cl_font_t *font = Con_GetCurFont(); - x = refState.width - 340; + x = refState.width - 340 * font->scale; y = 64; - Con_DrawStringLen( NULL, NULL, &height ); MakeRGBA( color, 255, 255, 255, 255 ); - - p = start = msg; - do - { - end = Q_strchr( p, '\n' ); - if( end ) msg[end-start] = '\0'; - - Con_DrawString( x, y, p, color ); - y += height; - - // handle '\n\n' - if( *p == '\n' ) - y += height; - if( end ) p = end + 1; - else break; - } while( 1 ); + CL_DrawString( x, y, msg, color, font, 0 ); } } @@ -588,6 +560,7 @@ void SCR_LoadCreditsFont( void ) { cl_font_t *const font = &cls.creditsFont; qboolean success = false; + float scale = hud_fontscale->value; dword crc = 0; // replace default gfx.wad textures by current charset's font @@ -599,15 +572,15 @@ void SCR_LoadCreditsFont( void ) "creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 ) { if( FS_FileExists( charsetFnt, false )) - success = Con_LoadVariableWidthFont( charsetFnt, font, 1.0f, TF_FONT ); + success = Con_LoadVariableWidthFont( charsetFnt, font, scale, kRenderTransAdd, TF_FONT ); } } if( !success ) - success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, 1.0f, TF_FONT ); + success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, kRenderTransAdd, TF_FONT ); if( !success ) - success = Con_LoadFixedWidthFont( "gfx/conchars", font, 1.0f, TF_FONT ); + success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransAdd, TF_FONT ); // copy font size for client.dll if( success ) diff --git a/engine/client/client.h b/engine/client/client.h index ba84a9ab..370da0f2 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -318,17 +318,25 @@ typedef struct pfnEventHook func; // user-defined function } cl_user_event_t; -#define FONT_FIXED 0 -#define FONT_VARIABLE 1 +#define FONT_FIXED 0 +#define FONT_VARIABLE 1 + +#define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale +#define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar +#define FONT_DRAW_FORCECOL BIT( 2 ) // ignore colorcodes +#define FONT_DRAW_NORENDERMODE BIT( 3 ) // ignore font's default rendermode typedef struct { - int hFontTexture; // handle to texture - wrect_t fontRc[256]; // rectangles - byte charWidths[256]; - int charHeight; - int type; - qboolean valid; // all rectangles are valid + int hFontTexture; // handle to texture + wrect_t fontRc[256]; // tex coords + float scale; // scale factor + byte charWidths[256]; // scaled widths + int charHeight; // scaled height + int type; // fixed width font or variable + int rendermode; // default rendermode + qboolean nearest; // nearest filtering enabled + qboolean valid; // all rectangles are valid } cl_font_t; typedef struct @@ -342,7 +350,6 @@ typedef struct int scissor_width; int scissor_height; qboolean scissor_test; - qboolean adjust_size; // allow to adjust scale for fonts int renderMode; // override kRenderMode from TriAPI TRICULLSTYLE cullMode; // override CULL FACE from TriAPI @@ -796,6 +803,19 @@ void CL_ResetEvent( event_info_t *ei ); word CL_EventIndex( const char *name ); void CL_FireEvents( void ); +// +// cl_font.c +// +qboolean CL_FixedFont( cl_font_t *font ); +qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags ); +qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags ); +void CL_FreeFont( cl_font_t *font ); +int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags ); +int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags ); +void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height ); +void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags ); + + // // cl_game.c // @@ -1030,13 +1050,13 @@ int Con_UtfProcessChar( int in ); int Con_UtfProcessCharForce( int in ); int Con_UtfMoveLeft( char *str, int pos ); int Con_UtfMoveRight( char *str, int pos, int length ); -void Con_DrawStringLen( const char *pText, int *length, int *height ); -int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); -int Con_DrawCharacter( int x, int y, int number, rgba_t color ); -void Con_DrawCharacterLen( int number, int *width, int *height ); void Con_DefaultColor( int r, int g, int b ); void Con_InvalidateFonts( void ); -void Con_SetFont( int fontNum ); +cl_font_t *Con_GetCurFont( void ); +cl_font_t *Con_GetFont( int num ); +void Con_DrawCharacterLen( int number, int *width, int *height ); +int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c +void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c void Con_CharEvent( int key ); void Con_RestoreFont( void ); void Key_Console( int key ); @@ -1046,8 +1066,6 @@ void Con_Bottom( void ); void Con_Top( void ); void Con_PageDown( int lines ); void Con_PageUp( int lines ); -qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, uint texFlags ); -qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, uint texFlags ); // // s_main.c diff --git a/engine/client/console.c b/engine/client/console.c index 03823b52..2267b44c 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -116,7 +116,7 @@ typedef struct // console fonts cl_font_t chars[CON_NUMFONTS];// fonts.wad/font1.fnt - cl_font_t *curFont, *lastUsedFont; + cl_font_t *curFont; // console input field_t input; @@ -555,90 +555,9 @@ Con_FixedFont */ qboolean Con_FixedFont( void ) { - if( con.curFont && con.curFont->valid && con.curFont->type == FONT_FIXED ) - return true; - return false; + return CL_FixedFont( con.curFont ); } -qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, uint texFlags ) -{ - int fontWidth; - int i; - - if( font->valid ) - return true; // already loaded - - if( !FS_FileExists( fontname, false )) - return false; - - font->hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, texFlags ); - R_GetTextureParms( &fontWidth, NULL, font->hFontTexture ); - - if( font->hFontTexture && fontWidth != 0 ) - { - font->charHeight = fontWidth / 16 * scale; - font->type = FONT_FIXED; - - // build fixed rectangles - for( i = 0; i < 256; i++ ) - { - font->fontRc[i].left = (i * (fontWidth / 16)) % fontWidth; - font->fontRc[i].right = font->fontRc[i].left + fontWidth / 16; - font->fontRc[i].top = (i / 16) * (fontWidth / 16); - font->fontRc[i].bottom = font->fontRc[i].top + fontWidth / 16; - font->charWidths[i] = fontWidth / 16 * scale; - } - font->valid = true; - } - - return true; -} - -qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, uint texFlags ) -{ - fs_offset_t length; - qfont_t *src; - byte *buffer; - int fontWidth; - int i; - - if( font->valid ) - return true; // already loaded - - if( !FS_FileExists( fontname, false )) - return false; - - font->hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, texFlags ); - R_GetTextureParms( &fontWidth, NULL, font->hFontTexture ); - - // setup consolefont - if( font->hFontTexture && fontWidth != 0 ) - { - // half-life font with variable chars witdh - buffer = FS_LoadFile( fontname, &length, false ); - - if( buffer && length >= sizeof( qfont_t )) - { - src = (qfont_t *)buffer; - font->charHeight = src->rowheight * scale; - font->type = FONT_VARIABLE; - - // build rectangles - for( i = 0; i < 256; i++ ) - { - font->fontRc[i].left = (word)src->fontinfo[i].startoffset % fontWidth; - font->fontRc[i].right = font->fontRc[i].left + src->fontinfo[i].charwidth; - font->fontRc[i].top = (word)src->fontinfo[i].startoffset / fontWidth; - font->fontRc[i].bottom = font->fontRc[i].top + src->rowheight; - font->charWidths[i] = src->fontinfo[i].charwidth * scale; - } - font->valid = true; - } - if( buffer ) Mem_Free( buffer ); - } - - return true; -} /* ================ @@ -650,6 +569,7 @@ INTERNAL RESOURCE static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font ) { qboolean success = false; + float scale = con_fontscale->value; if( font->valid ) return; // already loaded @@ -657,7 +577,7 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font ) // loading conchars if( Sys_CheckParm( "-oldfont" )) { - success = Con_LoadVariableWidthFont( "gfx/conchars.fnt", font, con_fontscale->value, TF_FONT|TF_NEAREST ); + success = Con_LoadVariableWidthFont( "gfx/conchars.fnt", font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST ); } else { @@ -670,14 +590,14 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font ) if( Q_snprintf( path, sizeof( path ), "font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" )) > 0 ) { - success = Con_LoadVariableWidthFont( path, font, con_fontscale->value, TF_FONT|TF_NEAREST ); + success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST ); } } if( !success ) { Q_snprintf( path, sizeof( path ), "fonts/font%i", fontNumber ); - success = Con_LoadVariableWidthFont( path, font, con_fontscale->value, TF_FONT|TF_NEAREST ); + success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST ); } } @@ -685,7 +605,7 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font ) { // quake fixed font as fallback // keep source to print directly into conback image - if( !Con_LoadFixedWidthFont( "gfx/conchars", font, con_fontscale->value, TF_FONT|TF_KEEP_SOURCE )) + if( !Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransTexture, TF_FONT|TF_KEEP_SOURCE )) Con_DPrintf( S_ERROR "failed to load console font\n" ); } } @@ -716,7 +636,7 @@ static void Con_LoadConchars( void ) fontSize = CON_NUMFONTS - 1; // sets the current font - con.lastUsedFont = con.curFont = &con.chars[fontSize]; + con.curFont = &con.chars[fontSize]; } // CP1251 table @@ -889,129 +809,25 @@ static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest ) /* ==================== -Con_TextAdjustSize - -draw charcters routine -==================== -*/ -static void Con_TextAdjustSize( int *x, int *y, int *w, int *h ) -{ - float xscale, yscale; - - if( !x && !y && !w && !h ) return; - - // scale for screen sizes - xscale = (float)refState.width / (float)clgame.scrInfo.iWidth; - yscale = (float)refState.height / (float)clgame.scrInfo.iHeight; - - if( x ) *x *= xscale; - if( y ) *y *= yscale; - if( w ) *w *= xscale; - if( h ) *h *= yscale; -} - -/* -==================== -Con_DrawGenericChar - -draw console single character -==================== -*/ -static int Con_DrawGenericChar( int x, int y, int number, rgba_t color ) -{ - int width, height; - float s1, t1, s2, t2; - wrect_t *rc; - - number &= 255; - - if( !con.curFont || !con.curFont->valid ) - return 0; - - number = Con_UtfProcessChar( number ); - if( !number ) - return 0; - - if( y < -con.curFont->charHeight ) - return 0; - - rc = &con.curFont->fontRc[number]; - R_GetTextureParms( &width, &height, con.curFont->hFontTexture ); - - if( !width || !height ) - return con.curFont->charWidths[number]; - - // don't apply color to fixed fonts it's already colored - if( con.curFont->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, con.curFont->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8 - ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] ); - else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] ); - - // calc rectangle - s1 = (float)rc->left / width; - t1 = (float)rc->top / height; - s2 = (float)rc->right / width; - t2 = (float)rc->bottom / height; - width = ( rc->right - rc->left ) * con_fontscale->value; - height = ( rc->bottom - rc->top ) * con_fontscale->value; - - if( clgame.ds.adjust_size ) - Con_TextAdjustSize( &x, &y, &width, &height ); - ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, con.curFont->hFontTexture ); - ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); // don't forget reset color - - return con.curFont->charWidths[number]; -} - -/* -==================== -Con_SetFont - -choose font size -==================== -*/ -void Con_SetFont( int fontNum ) -{ - fontNum = bound( 0, fontNum, CON_NUMFONTS - 1 ); - con.curFont = &con.chars[fontNum]; -} - -/* -==================== -Con_RestoreFont - -restore auto-selected console font -(that based on screen resolution) -==================== -*/ -void Con_RestoreFont( void ) -{ - con.curFont = con.lastUsedFont; -} - -/* -==================== -Con_DrawCharacter +Con_GetFont -client version of routine ==================== */ -int Con_DrawCharacter( int x, int y, int number, rgba_t color ) +cl_font_t *Con_GetFont( int num ) { - ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture ); - return Con_DrawGenericChar( x, y, number, color ); + num = bound( 0, num, CON_NUMFONTS - 1 ); + return &con.chars[num]; } /* ==================== -Con_DrawCharacterLen +Con_GetCurFont -returns character sizes in screen pixels ==================== */ -void Con_DrawCharacterLen( int number, int *width, int *height ) +cl_font_t *Con_GetCurFont( void ) { - if( width && con.curFont ) *width = con.curFont->charWidths[number]; - if( height && con.curFont ) *height = con.curFont->charHeight; + return con.curFont; } /* @@ -1023,105 +839,7 @@ compute string width and height in screen pixels */ void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ) { - int curLength = 0; - - if( !con.curFont ) - return; - if( height ) - *height = con.curFont->charHeight; - if (!length) - return; - - *length = 0; - - while( *pText ) - { - byte c = *pText; - - if( *pText == '\n' ) - { - pText++; - curLength = 0; - } - - // skip color strings they are not drawing - if( IsColorString( pText )) - { - pText += 2; - continue; - } - - - // Convert to unicode - c = Con_UtfProcessChar( c ); - - if( c ) - curLength += con.curFont->charWidths[c]; - - pText++; - - if( curLength > *length ) - *length = curLength; - } -} - -/* -================== -Con_DrawString - -Draws a multi-colored string, optionally forcing -to a fixed color. -================== -*/ -int Con_DrawGenericString( int x, int y, const char *string, rgba_t setColor, qboolean forceColor, int hideChar ) -{ - rgba_t color; - int drawLen = 0; - int numDraws = 0; - const char *s; - - if( !con.curFont ) return 0; // no font set - - Con_UtfProcessChar( 0 ); - - // draw the colored text - memcpy( color, setColor, sizeof( color )); - s = string; - - while( *s ) - { - if( *s == '\n' ) - { - s++; - if( !*s ) break; // at end the string - drawLen = 0; // begin new row - y += con.curFont->charHeight; - } - - if( IsColorString( s )) - { - if( !forceColor ) - { - memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color )); - color[3] = setColor[3]; - } - - s += 2; - numDraws++; - continue; - } - - // hide char for overstrike mode - if( hideChar == numDraws ) - drawLen += con.curFont->charWidths[*s]; - else drawLen += Con_DrawCharacter( x + drawLen, y, *s, color ); - - numDraws++; - s++; - } - - ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); - return drawLen; + return CL_DrawStringLen( con.curFont, pText, length, height, FONT_DRAW_UTF8 ); } /* @@ -1133,10 +851,9 @@ client version of routine */ int Con_DrawString( int x, int y, const char *string, rgba_t setColor ) { - return Con_DrawGenericString( x, y, string, setColor, false, -1 ); + return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 ); } - /* ================ Con_Init @@ -1628,7 +1345,7 @@ Field_DrawInputLine void Field_DrawInputLine( int x, int y, field_t *edit ) { int len, cursorChar; - int drawLen, hideChar = -1; + int drawLen; int prestep, curPos; char str[MAX_SYSPATH]; byte *colorDefault; @@ -1665,35 +1382,23 @@ void Field_DrawInputLine( int x, int y, field_t *edit ) // save char for overstrike cursorChar = str[edit->cursor - prestep]; - if( host.key_overstrike && cursorChar && !((int)( host.realtime * 4 ) & 1 )) - hideChar = edit->cursor - prestep; // skip this char - // draw it - Con_DrawGenericString( x, y, str, colorDefault, false, hideChar ); + CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 ); // draw the cursor if((int)( host.realtime * 4 ) & 1 ) return; // off blink // calc cursor position str[edit->cursor - prestep] = 0; - Con_DrawStringLen( str, &curPos, NULL ); - Con_UtfProcessChar( 0 ); + CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 ); - if( host.key_overstrike && cursorChar ) + if( host.key_overstrike ) { - // overstrike cursor -#if 0 - pglEnable( GL_BLEND ); - pglDisable( GL_ALPHA_TEST ); - pglBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA ); - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); -#endif - Con_DrawGenericChar( x + curPos, y, cursorChar, colorDefault ); + CL_DrawCharacter( x + curPos, y, '|', colorDefault, con.curFont, 0 ); } else { - Con_UtfProcessChar( 0 ); - Con_DrawCharacter( x + curPos, y, '_', colorDefault ); + CL_DrawCharacter( x + curPos, y, '_', colorDefault, con.curFont, 0 ); } } @@ -1997,7 +1702,7 @@ void Con_DrawInput( int lines ) return; y = lines - ( con.curFont->charHeight * 2 ); - Con_DrawCharacter( con.curFont->charWidths[' '], y, ']', g_color_table[7] ); + CL_DrawCharacter( con.curFont->charWidths[' '], y, ']', g_color_table[7], con.curFont, 0 ); Field_DrawInputLine( con.curFont->charWidths[' ']*2, y, &con.input ); } @@ -2142,7 +1847,11 @@ int Con_DrawConsoleLine( int y, int lineno ) return 0; // this string will be shown only at notify if( y >= con.curFont->charHeight ) - Con_DrawGenericString( con.curFont->charWidths[' '], y, li->start, g_color_table[7], false, -1 ); + { + float x = con.curFont->charWidths[' ']; + + CL_DrawString( x, y, li->start, g_color_table[7], con.curFont, FONT_DRAW_UTF8 ); + } return con.curFont->charHeight; } @@ -2212,14 +1921,12 @@ void Con_DrawSolidConsole( int lines ) Q_snprintf( curbuild, MAX_STRING, XASH_ENGINE_NAME " %i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); - start = refState.width - stringLen; - stringLen = Con_StringLength( curbuild ); + start = refState.width - stringLen; fraction = lines / (float)refState.height; color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number - for( i = 0; i < stringLen; i++ ) - width += Con_DrawCharacter( start + width, 0, curbuild[i], color ); + Con_DrawString( start, 0, curbuild, color ); // draw the text if( CON_LINES_COUNT > 0 ) @@ -2236,7 +1943,7 @@ void Con_DrawSolidConsole( int lines ) // draw red arrows to show the buffer is backscrolled for( x = 0; x < con.linewidth; x += 4 ) - Con_DrawCharacter(( x + 1 ) * start, y, '^', g_color_table[1] ); + CL_DrawCharacter( ( x + 1 ) * start, y, '^', g_color_table[1], con.curFont, 0 ); y -= con.curFont->charHeight; } x = lastline; @@ -2339,7 +2046,7 @@ void Con_DrawVersion( void ) { // draws the current build byte *color = g_color_table[7]; - int i, stringLen, width = 0, charH = 0; + int stringLen, charH = 0; int start, height = refState.height; qboolean draw_version = false; string curbuild; @@ -2370,8 +2077,7 @@ void Con_DrawVersion( void ) stringLen = Con_StringLength( curbuild ); height -= charH * 1.05f; - for( i = 0; i < stringLen; i++ ) - width += Con_DrawCharacter( start + width, height, curbuild[i], color ); + Con_DrawString( start, height, curbuild, color ); } /* @@ -2414,7 +2120,7 @@ void Con_RunConsole( void ) if( FBitSet( con_charset->flags, FCVAR_CHANGED ) || FBitSet( con_fontscale->flags, FCVAR_CHANGED ) || FBitSet( con_fontnum->flags, FCVAR_CHANGED ) || - FBitSet( cl_charset->flags, FCVAR_CHANGED ) ) + FBitSet( cl_charset->flags, FCVAR_CHANGED )) { // update codepage parameters if( !Q_stricmp( con_charset->string, "cp1251" )) @@ -2436,8 +2142,6 @@ void Con_RunConsole( void ) g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" ); Con_InvalidateFonts(); Con_LoadConchars(); - cls.creditsFont.valid = false; - SCR_LoadCreditsFont(); ClearBits( con_charset->flags, FCVAR_CHANGED ); ClearBits( con_fontnum->flags, FCVAR_CHANGED ); ClearBits( con_fontscale->flags, FCVAR_CHANGED ); @@ -2576,8 +2280,10 @@ Con_InvalidateFonts */ void Con_InvalidateFonts( void ) { - memset( con.chars, 0, sizeof( con.chars )); - con.curFont = con.lastUsedFont = NULL; + int i; + for( i = 0; i < ARRAYSIZE( con.chars ); i++ ) + CL_FreeFont( &con.chars[i] ); + con.curFont = NULL; } /* diff --git a/engine/client/keys.c b/engine/client/keys.c index a1e696c8..80c45ba2 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -1148,7 +1148,7 @@ Draw button with symbol on it */ static void OSK_DrawSymbolButton( int symb, float x, float y, float width, float height ) { - char str[] = {symb & 255, 0}; + cl_font_t *font = Con_GetCurFont(); byte color[] = { 255, 255, 255, 255 }; int x1 = x * refState.width, y1 = y * refState.height, @@ -1156,14 +1156,15 @@ static void OSK_DrawSymbolButton( int symb, float x, float y, float width, float h = height * refState.height; if( symb == osk.curbutton.val ) - { ref.dllFuncs.FillRGBABlend( x1, y1, w, h, 255, 160, 0, 100 ); - } if( !symb || symb == ' ' || (symb >= OSK_TAB && symb < OSK_SPECKEY_LAST ) ) return; - Con_DrawCharacter( x1 + 1, y1, symb, color ); + CL_DrawCharacter( + x1 + width * 0.4 * refState.width, + y1 + height * 0.4 * refState.height, + symb, color, font, 0 ); } /* @@ -1177,7 +1178,11 @@ static void OSK_DrawSpecialButton( const char *name, float x, float y, float wid { byte color[] = { 0, 255, 0, 255 }; - Con_DrawString( x * refState.width, y * refState.height, name, color ); + Con_DrawString( + x * refState.width + width * 0.4 * refState.width, + y * refState.height + height * 0.4 * refState.height, + name, + color ); }