Browse Source

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
pull/2/head
Alibek Omarov 2 years ago
parent
commit
77ea03a62c
  1. 291
      engine/client/cl_font.c
  2. 137
      engine/client/cl_game.c
  3. 22
      engine/client/cl_gameui.c
  4. 37
      engine/client/cl_mobile.c
  5. 20
      engine/client/cl_netgraph.c
  6. 47
      engine/client/cl_scrn.c
  7. 42
      engine/client/client.h
  8. 372
      engine/client/console.c
  9. 15
      engine/client/keys.c

291
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++;
}
}

137
engine/client/cl_game.c

@ -306,9 +306,7 @@ print centerscreen message
*/ */
void CL_CenterPrint( const char *text, float y ) void CL_CenterPrint( const char *text, float y )
{ {
int length = 0; cl_font_t *font = Con_GetCurFont();
int width = 0;
char *s;
if( !COM_CheckString( text )) if( !COM_CheckString( text ))
return; return;
@ -317,24 +315,13 @@ void CL_CenterPrint( const char *text, float y )
clgame.centerPrint.totalWidth = 0; clgame.centerPrint.totalWidth = 0;
clgame.centerPrint.time = cl.mtime[0]; // allow pause for centerprint clgame.centerPrint.time = cl.mtime[0]; // allow pause for centerprint
Q_strncpy( clgame.centerPrint.message, text, sizeof( clgame.centerPrint.message )); Q_strncpy( clgame.centerPrint.message, text, sizeof( clgame.centerPrint.message ));
s = clgame.centerPrint.message;
// count the number of lines for centering CL_DrawStringLen( font,
while( *s ) clgame.centerPrint.message,
{ &clgame.centerPrint.totalWidth,
if( *s == '\n' ) &clgame.centerPrint.totalHeight,
{ FONT_DRAW_HUD | FONT_DRAW_UTF8 );
clgame.centerPrint.lines++;
if( width > clgame.centerPrint.totalWidth )
clgame.centerPrint.totalWidth = width;
width = 0;
}
else width += clgame.scrInfo.charWidths[*s];
s++;
length++;
}
clgame.centerPrint.totalHeight = ( clgame.centerPrint.lines * clgame.scrInfo.iCharHeight );
clgame.centerPrint.y = CL_AdjustYPos( y, clgame.centerPrint.totalHeight ); clgame.centerPrint.y = CL_AdjustYPos( y, clgame.centerPrint.totalHeight );
} }
@ -502,6 +489,7 @@ called each frame
*/ */
void CL_DrawCenterPrint( void ) void CL_DrawCenterPrint( void )
{ {
cl_font_t *font = Con_GetCurFont();
char *pText; char *pText;
int i, j, x, y; int i, j, x, y;
int width, lineLength; int width, lineLength;
@ -521,8 +509,10 @@ void CL_DrawCenterPrint( void )
y = clgame.centerPrint.y; // start y y = clgame.centerPrint.y; // start y
colorDefault = g_color_table[7]; colorDefault = g_color_table[7];
pText = clgame.centerPrint.message; 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++ ) for( i = 0; i < clgame.centerPrint.lines; i++ )
{ {
lineLength = 0; lineLength = 0;
@ -532,7 +522,7 @@ void CL_DrawCenterPrint( void )
{ {
byte c = *pText; byte c = *pText;
line[lineLength] = c; line[lineLength] = c;
Con_DrawCharacterLen( c, &charWidth, NULL ); CL_DrawCharacterLen( font, c, &charWidth, NULL );
width += charWidth; width += charWidth;
lineLength++; lineLength++;
pText++; pText++;
@ -549,7 +539,7 @@ void CL_DrawCenterPrint( void )
for( j = 0; j < lineLength; j++ ) for( j = 0; j < lineLength; j++ )
{ {
if( x >= 0 && y >= 0 && x <= refState.width ) 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; y += charHeight;
} }
@ -1600,6 +1590,14 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
{ {
float scale_factor = hud_scale->value; 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 // setup screen info
clgame.scrInfo.iSize = sizeof( clgame.scrInfo ); clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH; 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 ) static int GAME_EXPORT pfnDrawCharacter( int x, int y, int number, int r, int g, int b )
{ {
if( !cls.creditsFont.valid ) rgba_t color = { r, g, b, 255 };
return 0; int flags = FONT_DRAW_HUD;
if( hud_utf8->value ) if( hud_utf8->value )
number = Con_UtfProcessChar( number ); flags |= FONT_DRAW_UTF8;
number &= 255;
if( number < 32 ) return 0;
if( y < -clgame.scrInfo.iCharHeight )
return 0;
clgame.ds.adjust_size = true; return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags );
pfnPIC_Set( cls.creditsFont.hFontTexture, r, g, b, 255 );
pfnPIC_DrawAdditive( x, y, -1, -1, &cls.creditsFont.fontRc[number] );
clgame.ds.adjust_size = false;
return clgame.scrInfo.charWidths[number];
} }
/* /*
@ -1873,20 +1860,12 @@ drawing string like a console string
*/ */
int GAME_EXPORT pfnDrawConsoleString( int x, int y, char *string ) int GAME_EXPORT pfnDrawConsoleString( int x, int y, char *string )
{ {
int drawLen; cl_font_t *font = Con_GetFont( con_fontsize->value );
rgba_t color;
if( !COM_CheckString( string )) Vector4Copy( clgame.ds.textColor, color );
return 0; // silent ignore Vector4Set( clgame.ds.textColor, 255, 255, 255, 255 );
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(); return x + CL_DrawString( x, y, string, color, font, FONT_DRAW_UTF8 | FONT_DRAW_HUD );
return (x + drawLen); // exclude color prexfixes
} }
/* /*
@ -1914,9 +1893,9 @@ compute string length in screen pixels
*/ */
void GAME_EXPORT pfnDrawConsoleStringLen( const char *pText, int *length, int *height ) void GAME_EXPORT pfnDrawConsoleStringLen( const char *pText, int *length, int *height )
{ {
Con_SetFont( con_fontsize->value ); cl_font_t *font = Con_GetFont( con_fontsize->value );
Con_DrawStringLen( pText, length, height );
Con_RestoreFont(); 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 ) static int GAME_EXPORT pfnVGUI2DrawCharacter( int x, int y, int number, unsigned int font )
{ {
if( !cls.creditsFont.valid ) return pfnDrawCharacter( x, y, number, 255, 255, 255 );
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];
} }
/* /*
@ -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 ) 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 ); 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 ) static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b )
{ {
int iWidth = 0; rgba_t color = { r, g, b, 255 };
Con_UtfProcessChar(0); int flags = FONT_DRAW_HUD;
// draw the string until we hit the null character or a newline character if( hud_utf8->value )
for ( ; *str != 0 && *str != '\n'; str++ ) SetBits( flags, FONT_DRAW_UTF8 );
{
iWidth += pfnVGUI2DrawCharacterAdditive( x + iWidth, y, (unsigned char)*str, r, g, b, 0 );
}
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 ) static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b )
{ {
// find the end of the string rgba_t color = { r, g, b, 255 };
char *szIt; int flags = FONT_DRAW_HUD;
for( szIt = (char*)str; *szIt != 0; szIt++ ) int width, height;
x -= clgame.scrInfo.charWidths[ (unsigned char) *szIt ];
return pfnDrawString( x, y, str, r, g, b ); 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 );
} }
/* /*

22
engine/client/cl_gameui.c

@ -487,22 +487,10 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const
if( prc ) if( prc )
{ {
// calc user-defined rectangle // calc user-defined rectangle
s1 = prc->left; s1 = prc->left / (float)w;
t1 = prc->top; t1 = prc->top / (float)h;
s2 = prc->right; s2 = prc->right / (float)w;
t2 = prc->bottom; t2 = prc->bottom / (float)h;
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;
}
if( width == -1 && height == -1 ) 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 )) if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
return; 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.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, gameui.ds.gl_texturenum );
ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
} }

37
engine/client/cl_mobile.c

@ -25,6 +25,9 @@ mobile_engfuncs_t *gMobileEngfuncs;
convar_t *vibration_length; convar_t *vibration_length;
convar_t *vibration_enable; convar_t *vibration_enable;
static cl_font_t g_scaled_font;
static float g_font_scale;
static void pfnVibrate( float life, char flags ) static void pfnVibrate( float life, char flags )
{ {
if( !vibration_enable->value ) 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 ) 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; // this call is very ineffective and possibly broken!
int height = clgame.scrInfo.iCharHeight * scale * hud_scale->value; rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD;
if( !cls.creditsFont.valid )
return 0;
x *= hud_scale->value;
y *= hud_scale->value;
number &= 255; if( hud_utf8->value )
number = Con_UtfProcessChar( number ); SetBits( flags, FONT_DRAW_UTF8 );
if( number < 32 ) if( fabs( g_font_scale - scale ) > 0.1f ||
return 0; g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture )
{
int i;
if( y < -height ) g_scaled_font = cls.creditsFont;
return 0; 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 ); g_font_scale = scale;
pfnPIC_DrawAdditive( x, y, width, height, &cls.creditsFont.fontRc[number] ); }
return width; return CL_DrawCharacter( x, y, number, color, &g_scaled_font, flags );
} }
static void *pfnGetNativeObject( const char *obj ) static void *pfnGetNativeObject( const char *obj )

20
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 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; static int lastout;
cl_font_t *font = Con_GetFont( 0 );
rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; 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 ptx = Q_max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 );
int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 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 // move rolling average
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate; 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 ) if( framerate > 0.0f )
{ {
y -= net_graphheight->value; 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 ) 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; 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; if( !out ) out = lastout;
else lastout = out; 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; 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; y += 15;
if( graphtype > 2 ) 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 loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01f );
int choke = (int)(( packet_choke + PACKETCHOKE_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 ) if( graphtype < 3 )
Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors ); CL_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors, font, FONT_DRAW_NORENDERMODE );
Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors );
Con_RestoreFont(); CL_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors, font, FONT_DRAW_NORENDERMODE );
} }
/* /*

47
engine/client/cl_scrn.c

@ -160,6 +160,7 @@ void SCR_NetSpeeds( void )
static int max_clfps = 0; static int max_clfps = 0;
int cur_clfps = 0; int cur_clfps = 0;
rgba_t color; rgba_t color;
cl_font_t *font = Con_GetCurFont();
if( !host.allow_console ) if( !host.allow_console )
return; return;
@ -196,25 +197,11 @@ void SCR_NetSpeeds( void )
Q_memprint( cls.netchan.total_sended ) Q_memprint( cls.netchan.total_sended )
); );
x = refState.width - 320; x = refState.width - 320 * font->scale;
y = 384; y = 384;
Con_DrawStringLen( NULL, NULL, &height );
MakeRGBA( color, 255, 255, 255, 255 ); MakeRGBA( color, 255, 255, 255, 255 );
CL_DrawString( x, y, msg, color, font, 0 );
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 );
} }
/* /*
@ -234,28 +221,13 @@ void SCR_RSpeeds( void )
int x, y, height; int x, y, height;
char *p, *start, *end; char *p, *start, *end;
rgba_t color; rgba_t color;
cl_font_t *font = Con_GetCurFont();
x = refState.width - 340; x = refState.width - 340 * font->scale;
y = 64; y = 64;
Con_DrawStringLen( NULL, NULL, &height );
MakeRGBA( color, 255, 255, 255, 255 ); MakeRGBA( color, 255, 255, 255, 255 );
CL_DrawString( x, y, msg, color, font, 0 );
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 );
} }
} }
@ -588,6 +560,7 @@ void SCR_LoadCreditsFont( void )
{ {
cl_font_t *const font = &cls.creditsFont; cl_font_t *const font = &cls.creditsFont;
qboolean success = false; qboolean success = false;
float scale = hud_fontscale->value;
dword crc = 0; dword crc = 0;
// replace default gfx.wad textures by current charset's font // 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 ) "creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 )
{ {
if( FS_FileExists( charsetFnt, false )) 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 ) 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 ) 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 // copy font size for client.dll
if( success ) if( success )

42
engine/client/client.h

@ -321,13 +321,21 @@ typedef struct
#define FONT_FIXED 0 #define FONT_FIXED 0
#define FONT_VARIABLE 1 #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 typedef struct
{ {
int hFontTexture; // handle to texture int hFontTexture; // handle to texture
wrect_t fontRc[256]; // rectangles wrect_t fontRc[256]; // tex coords
byte charWidths[256]; float scale; // scale factor
int charHeight; byte charWidths[256]; // scaled widths
int type; 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 qboolean valid; // all rectangles are valid
} cl_font_t; } cl_font_t;
@ -342,7 +350,6 @@ typedef struct
int scissor_width; int scissor_width;
int scissor_height; int scissor_height;
qboolean scissor_test; qboolean scissor_test;
qboolean adjust_size; // allow to adjust scale for fonts
int renderMode; // override kRenderMode from TriAPI int renderMode; // override kRenderMode from TriAPI
TRICULLSTYLE cullMode; // override CULL FACE 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 ); word CL_EventIndex( const char *name );
void CL_FireEvents( void ); 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 // cl_game.c
// //
@ -1030,13 +1050,13 @@ int Con_UtfProcessChar( int in );
int Con_UtfProcessCharForce( int in ); int Con_UtfProcessCharForce( int in );
int Con_UtfMoveLeft( char *str, int pos ); int Con_UtfMoveLeft( char *str, int pos );
int Con_UtfMoveRight( char *str, int pos, int length ); 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_DefaultColor( int r, int g, int b );
void Con_InvalidateFonts( void ); 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_CharEvent( int key );
void Con_RestoreFont( void ); void Con_RestoreFont( void );
void Key_Console( int key ); void Key_Console( int key );
@ -1046,8 +1066,6 @@ void Con_Bottom( void );
void Con_Top( void ); void Con_Top( void );
void Con_PageDown( int lines ); void Con_PageDown( int lines );
void Con_PageUp( 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 // s_main.c

372
engine/client/console.c

@ -116,7 +116,7 @@ typedef struct
// console fonts // console fonts
cl_font_t chars[CON_NUMFONTS];// fonts.wad/font1.fnt cl_font_t chars[CON_NUMFONTS];// fonts.wad/font1.fnt
cl_font_t *curFont, *lastUsedFont; cl_font_t *curFont;
// console input // console input
field_t input; field_t input;
@ -555,90 +555,9 @@ Con_FixedFont
*/ */
qboolean Con_FixedFont( void ) qboolean Con_FixedFont( void )
{ {
if( con.curFont && con.curFont->valid && con.curFont->type == FONT_FIXED ) return CL_FixedFont( con.curFont );
return true;
return false;
} }
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 ) static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
{ {
qboolean success = false; qboolean success = false;
float scale = con_fontscale->value;
if( font->valid ) if( font->valid )
return; // already loaded return; // already loaded
@ -657,7 +577,7 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
// loading conchars // loading conchars
if( Sys_CheckParm( "-oldfont" )) 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 else
{ {
@ -670,14 +590,14 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
if( Q_snprintf( path, sizeof( path ), if( Q_snprintf( path, sizeof( path ),
"font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" )) > 0 ) "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 ) if( !success )
{ {
Q_snprintf( path, sizeof( path ), "fonts/font%i", fontNumber ); 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 // quake fixed font as fallback
// keep source to print directly into conback image // 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" ); Con_DPrintf( S_ERROR "failed to load console font\n" );
} }
} }
@ -716,7 +636,7 @@ static void Con_LoadConchars( void )
fontSize = CON_NUMFONTS - 1; fontSize = CON_NUMFONTS - 1;
// sets the current font // sets the current font
con.lastUsedFont = con.curFont = &con.chars[fontSize]; con.curFont = &con.chars[fontSize];
} }
// CP1251 table // CP1251 table
@ -889,129 +809,25 @@ static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
/* /*
==================== ====================
Con_TextAdjustSize Con_GetFont
draw charcters routine
==================== ====================
*/ */
static void Con_TextAdjustSize( int *x, int *y, int *w, int *h ) cl_font_t *Con_GetFont( int num )
{ {
float xscale, yscale; num = bound( 0, num, CON_NUMFONTS - 1 );
return &con.chars[num];
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 Con_GetCurFont
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
client version of routine
==================== ====================
*/ */
int Con_DrawCharacter( int x, int y, int number, rgba_t color ) cl_font_t *Con_GetCurFont( void )
{ {
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture ); return con.curFont;
return Con_DrawGenericChar( x, y, number, color );
}
/*
====================
Con_DrawCharacterLen
returns character sizes in screen pixels
====================
*/
void Con_DrawCharacterLen( int number, int *width, int *height )
{
if( width && con.curFont ) *width = con.curFont->charWidths[number];
if( height && con.curFont ) *height = con.curFont->charHeight;
} }
/* /*
@ -1023,105 +839,7 @@ compute string width and height in screen pixels
*/ */
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ) void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height )
{ {
int curLength = 0; return CL_DrawStringLen( con.curFont, pText, length, height, FONT_DRAW_UTF8 );
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;
} }
/* /*
@ -1133,10 +851,9 @@ client version of routine
*/ */
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ) 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 Con_Init
@ -1628,7 +1345,7 @@ Field_DrawInputLine
void Field_DrawInputLine( int x, int y, field_t *edit ) void Field_DrawInputLine( int x, int y, field_t *edit )
{ {
int len, cursorChar; int len, cursorChar;
int drawLen, hideChar = -1; int drawLen;
int prestep, curPos; int prestep, curPos;
char str[MAX_SYSPATH]; char str[MAX_SYSPATH];
byte *colorDefault; byte *colorDefault;
@ -1665,35 +1382,23 @@ void Field_DrawInputLine( int x, int y, field_t *edit )
// save char for overstrike // save char for overstrike
cursorChar = str[edit->cursor - prestep]; cursorChar = str[edit->cursor - prestep];
if( host.key_overstrike && cursorChar && !((int)( host.realtime * 4 ) & 1 ))
hideChar = edit->cursor - prestep; // skip this char
// draw it // draw it
Con_DrawGenericString( x, y, str, colorDefault, false, hideChar ); CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
// draw the cursor // draw the cursor
if((int)( host.realtime * 4 ) & 1 ) return; // off blink if((int)( host.realtime * 4 ) & 1 ) return; // off blink
// calc cursor position // calc cursor position
str[edit->cursor - prestep] = 0; str[edit->cursor - prestep] = 0;
Con_DrawStringLen( str, &curPos, NULL ); CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
Con_UtfProcessChar( 0 );
if( host.key_overstrike && cursorChar ) if( host.key_overstrike )
{ {
// overstrike cursor CL_DrawCharacter( x + curPos, y, '|', colorDefault, con.curFont, 0 );
#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 );
} }
else else
{ {
Con_UtfProcessChar( 0 ); CL_DrawCharacter( x + curPos, y, '_', colorDefault, con.curFont, 0 );
Con_DrawCharacter( x + curPos, y, '_', colorDefault );
} }
} }
@ -1997,7 +1702,7 @@ void Con_DrawInput( int lines )
return; return;
y = lines - ( con.curFont->charHeight * 2 ); 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 ); 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 return 0; // this string will be shown only at notify
if( y >= con.curFont->charHeight ) 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; 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( )); 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 ); Con_DrawStringLen( curbuild, &stringLen, &charH );
start = refState.width - stringLen;
stringLen = Con_StringLength( curbuild );
start = refState.width - stringLen;
fraction = lines / (float)refState.height; fraction = lines / (float)refState.height;
color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number
for( i = 0; i < stringLen; i++ ) Con_DrawString( start, 0, curbuild, color );
width += Con_DrawCharacter( start + width, 0, curbuild[i], color );
// draw the text // draw the text
if( CON_LINES_COUNT > 0 ) if( CON_LINES_COUNT > 0 )
@ -2236,7 +1943,7 @@ void Con_DrawSolidConsole( int lines )
// draw red arrows to show the buffer is backscrolled // draw red arrows to show the buffer is backscrolled
for( x = 0; x < con.linewidth; x += 4 ) 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; y -= con.curFont->charHeight;
} }
x = lastline; x = lastline;
@ -2339,7 +2046,7 @@ void Con_DrawVersion( void )
{ {
// draws the current build // draws the current build
byte *color = g_color_table[7]; byte *color = g_color_table[7];
int i, stringLen, width = 0, charH = 0; int stringLen, charH = 0;
int start, height = refState.height; int start, height = refState.height;
qboolean draw_version = false; qboolean draw_version = false;
string curbuild; string curbuild;
@ -2370,8 +2077,7 @@ void Con_DrawVersion( void )
stringLen = Con_StringLength( curbuild ); stringLen = Con_StringLength( curbuild );
height -= charH * 1.05f; height -= charH * 1.05f;
for( i = 0; i < stringLen; i++ ) Con_DrawString( start, height, curbuild, color );
width += Con_DrawCharacter( start + width, height, curbuild[i], color );
} }
/* /*
@ -2414,7 +2120,7 @@ void Con_RunConsole( void )
if( FBitSet( con_charset->flags, FCVAR_CHANGED ) || if( FBitSet( con_charset->flags, FCVAR_CHANGED ) ||
FBitSet( con_fontscale->flags, FCVAR_CHANGED ) || FBitSet( con_fontscale->flags, FCVAR_CHANGED ) ||
FBitSet( con_fontnum->flags, FCVAR_CHANGED ) || FBitSet( con_fontnum->flags, FCVAR_CHANGED ) ||
FBitSet( cl_charset->flags, FCVAR_CHANGED ) ) FBitSet( cl_charset->flags, FCVAR_CHANGED ))
{ {
// update codepage parameters // update codepage parameters
if( !Q_stricmp( con_charset->string, "cp1251" )) if( !Q_stricmp( con_charset->string, "cp1251" ))
@ -2436,8 +2142,6 @@ void Con_RunConsole( void )
g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" ); g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" );
Con_InvalidateFonts(); Con_InvalidateFonts();
Con_LoadConchars(); Con_LoadConchars();
cls.creditsFont.valid = false;
SCR_LoadCreditsFont();
ClearBits( con_charset->flags, FCVAR_CHANGED ); ClearBits( con_charset->flags, FCVAR_CHANGED );
ClearBits( con_fontnum->flags, FCVAR_CHANGED ); ClearBits( con_fontnum->flags, FCVAR_CHANGED );
ClearBits( con_fontscale->flags, FCVAR_CHANGED ); ClearBits( con_fontscale->flags, FCVAR_CHANGED );
@ -2576,8 +2280,10 @@ Con_InvalidateFonts
*/ */
void Con_InvalidateFonts( void ) void Con_InvalidateFonts( void )
{ {
memset( con.chars, 0, sizeof( con.chars )); int i;
con.curFont = con.lastUsedFont = NULL; for( i = 0; i < ARRAYSIZE( con.chars ); i++ )
CL_FreeFont( &con.chars[i] );
con.curFont = NULL;
} }
/* /*

15
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 ) 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 }; byte color[] = { 255, 255, 255, 255 };
int x1 = x * refState.width, int x1 = x * refState.width,
y1 = y * refState.height, 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; h = height * refState.height;
if( symb == osk.curbutton.val ) if( symb == osk.curbutton.val )
{
ref.dllFuncs.FillRGBABlend( x1, y1, w, h, 255, 160, 0, 100 ); ref.dllFuncs.FillRGBABlend( x1, y1, w, h, 255, 160, 0, 100 );
}
if( !symb || symb == ' ' || (symb >= OSK_TAB && symb < OSK_SPECKEY_LAST ) ) if( !symb || symb == ' ' || (symb >= OSK_TAB && symb < OSK_SPECKEY_LAST ) )
return; 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 }; 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 );
} }

Loading…
Cancel
Save