Closed ensiform closed 8 years ago
Fixed in my working copy; major rewrite of text rendering/width functions. Just waiting on OpenJK changes to font code.
You're expecting that to happen before first release? What's the point of the customfont anyway? Can't you specify the correct handle directly?
I've already made the changes, I'm waiting for you to get on IRC to approve them :p customFont is so e.g. a JPLua plugin can register a font and get its own raw asset handle. When customFont is false, you use the regular FONT_SMALL etc indices, which is then translated to the asset handle. It goes through that translation process because menus can override the big/medium/small fonts to use, it has to be resolved at draw time.
You can register as many fonts as you like with trap_RegisterFont those are just the ones shared and have MenuFontToHandle or whatever. I hide from IRC because soz.
Yep, and that's what the customFont parameter allows you to pass.
Here's a slightly outdated diff on the engine's API/font changes
commit 3e15f18d87d15815564f78cf8e3eec0ed309d79f
Author: Razish <mrrazish@gmail.com>
Date: Tue Oct 27 01:26:17 2015 +1100
[MP] Add font aspect-ratio correction and expose floating point width calculation to engine/cgame/ui
Bumps CGAME_API_VERSION, UI_API_VERSION, REF_API_VERSION
diff --git a/codemp/cgame/cg_main.c b/codemp/cgame/cg_main.c
index c6703a1..dab4883 100644
--- a/codemp/cgame/cg_main.c
+++ b/codemp/cgame/cg_main.c
@@ -2372,6 +2372,8 @@ void CG_LoadHudMenu()
cgDC.stopCinematic = &CG_StopCinematic;
cgDC.drawCinematic = &CG_DrawCinematic;
cgDC.runCinematicFrame = &CG_RunCinematicFrame;
+ cgDC.ext.Font_StrLenPixels = trap->ext.R_Font_StrLenPixels;
+
Init_Display(&cgDC);
diff --git a/codemp/cgame/cg_public.h b/codemp/cgame/cg_public.h
index 8b32ca6..36a273b 100644
--- a/codemp/cgame/cg_public.h
+++ b/codemp/cgame/cg_public.h
@@ -23,7 +23,7 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#pragma once
-#define CGAME_API_VERSION 1
+#define CGAME_API_VERSION 2
#define CMD_BACKUP 64
#define CMD_MASK (CMD_BACKUP - 1)
@@ -713,6 +713,10 @@ typedef struct cgameImport_s {
void (*G2API_CleanEntAttachments) ( void );
qboolean (*G2API_OverrideServer) ( void *serverInstance );
void (*G2API_GetSurfaceName) ( void *ghoul2, int surfNumber, int modelIndex, char *fillBuf );
+
+ struct {
+ float (*R_Font_StrLenPixels) ( const char *text, const int iFontIndex, const float scale );
+ } ext;
} cgameImport_t;
typedef struct cgameExport_s {
diff --git a/codemp/cgame/cg_syscalls.c b/codemp/cgame/cg_syscalls.c
index 36b1069..bb056ed 100644
--- a/codemp/cgame/cg_syscalls.c
+++ b/codemp/cgame/cg_syscalls.c
@@ -219,7 +219,12 @@ qhandle_t trap_R_RegisterShaderNoMip( const char *name ) {
qhandle_t trap_R_RegisterFont( const char *fontName ) {
return Q_syscall( CG_R_REGISTERFONT, fontName);
}
-int trap_R_Font_StrLenPixels(const char *text, const int iFontIndex, const float scale) {
+int trap_R_Font_StrLenPixels(const char *text, const int iFontIndex, const float scale) {
+ //HACK! RE_Font_StrLenPixels works better with 1.0f scale
+ float width = (float)Q_syscall( CG_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(1.0f));
+ return width * scale;
+}
+float trap_R_Font_StrLenPixelsFloat(const char *text, const int iFontIndex, const float scale) {
//HACK! RE_Font_StrLenPixels works better with 1.0f scale
float width = (float)Q_syscall( CG_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(1.0f));
return width * scale;
@@ -228,7 +233,8 @@ int trap_R_Font_StrLenChars(const char *text) {
return Q_syscall( CG_R_FONT_STRLENCHARS, text);
}
int trap_R_Font_HeightPixels(const int iFontIndex, const float scale) {
- return Q_syscall( CG_R_FONT_STRHEIGHTPIXELS, iFontIndex, PASSFLOAT(scale));
+ float height = (float)Q_syscall( CG_R_FONT_STRHEIGHTPIXELS, iFontIndex, PASSFLOAT(1.0f) );
+ return height * scale;
}
void trap_R_Font_DrawString(int ox, int oy, const char *text, const float *rgba, const int setIndex, int iCharLimit, const float scale) {
Q_syscall( CG_R_FONT_DRAWSTRING, ox, oy, text, rgba, setIndex, iCharLimit, PASSFLOAT(scale));
@@ -936,4 +942,6 @@ static void TranslateSyscalls( void ) {
trap->G2API_CleanEntAttachments = trap_G2API_CleanEntAttachments;
trap->G2API_OverrideServer = trap_G2API_OverrideServer;
trap->G2API_GetSurfaceName = trap_G2API_GetSurfaceName;
+
+ trap->ext.R_Font_StrLenPixels = trap_R_Font_StrLenPixelsFloat;
}
diff --git a/codemp/client/cl_cgameapi.cpp b/codemp/client/cl_cgameapi.cpp
index 48e33de..4d1d0bb 100644
--- a/codemp/client/cl_cgameapi.cpp
+++ b/codemp/client/cl_cgameapi.cpp
@@ -1858,6 +1858,8 @@ void CL_BindCGame( void ) {
cgi.G2API_OverrideServer = CL_G2API_OverrideServer;
cgi.G2API_GetSurfaceName = CL_G2API_GetSurfaceName;
+ cgi.ext.R_Font_StrLenPixels = re->ext.Font_StrLenPixels;
+
GetCGameAPI = (GetCGameAPI_t)cgvm->GetModuleAPI;
ret = GetCGameAPI( CGAME_API_VERSION, &cgi );
if ( !ret ) {
diff --git a/codemp/client/cl_uiapi.cpp b/codemp/client/cl_uiapi.cpp
index 8921aa6..70cfab4 100644
--- a/codemp/client/cl_uiapi.cpp
+++ b/codemp/client/cl_uiapi.cpp
@@ -1194,6 +1194,8 @@ void CL_BindUI( void ) {
uii.G2API_GetSurfaceName = CL_G2API_GetSurfaceName;
uii.G2API_AttachG2Model = CL_G2API_AttachG2Model;
+ uii.ext.R_Font_StrLenPixels = re->ext.Font_StrLenPixels;
+
GetUIAPI = (GetUIAPI_t)uivm->GetModuleAPI;
ret = GetUIAPI( UI_API_VERSION, &uii );
if ( !ret ) {
diff --git a/codemp/rd-common/tr_font.cpp b/codemp/rd-common/tr_font.cpp
index 8c33625..152423f 100644
--- a/codemp/rd-common/tr_font.cpp
+++ b/codemp/rd-common/tr_font.cpp
@@ -1355,17 +1355,10 @@ CFontInfo *GetFont(int index)
return pFont;
}
-
-int RE_Font_StrLenPixels(const char *psText, const int iFontHandle, const float fScale)
-{
- float fMaxWidth = 0.0f;
- float fThisWidth = 0.0f;
- CFontInfo *curfont;
-
- curfont = GetFont(iFontHandle);
- if(!curfont)
- {
- return(0);
+float RE_Font_StrLenPixelsNew( const char *psText, const int iFontHandle, const float fScale ) {
+ CFontInfo *curfont = GetFont(iFontHandle);
+ if ( !curfont ) {
+ return 0.0f;
}
float fScaleAsian = fScale;
@@ -1374,42 +1367,44 @@ int RE_Font_StrLenPixels(const char *psText, const int iFontHandle, const float
fScaleAsian = fScale * 0.75f;
}
- while(*psText)
- {
+ float maxLineWidth = 0.0f;
+ float thisLineWidth = 0.0f;
+ while ( *psText ) {
int iAdvanceCount;
unsigned int uiLetter = AnyLanguage_ReadCharFromString( psText, &iAdvanceCount, NULL );
psText += iAdvanceCount;
- if (uiLetter == '^' )
- {
- if (*psText >= '0' &&
- *psText <= '9')
- {
+ if ( uiLetter == '^' ) {
+ if ( *psText >= '0' && *psText <= '9' ) {
uiLetter = AnyLanguage_ReadCharFromString( psText, &iAdvanceCount, NULL );
psText += iAdvanceCount;
continue;
}
}
- if (uiLetter == 0x0A)
- {
- fThisWidth = 0.0f;
+ if ( uiLetter == '\n' ) {
+ thisLineWidth = 0.0f;
}
- else
- {
- int iPixelAdvance = curfont->GetLetterHorizAdvance( uiLetter );
+ else {
+ float iPixelAdvance = (float)curfont->GetLetterHorizAdvance( uiLetter );
float fValue = iPixelAdvance * ((uiLetter > (unsigned)g_iNonScaledCharRange) ? fScaleAsian : fScale);
- fThisWidth += curfont->mbRoundCalcs ? Round( fValue ) : fValue;
- if (fThisWidth > fMaxWidth)
- {
- fMaxWidth = fThisWidth;
+ thisLineWidth += curfont->mbRoundCalcs ? roundf( fValue ) : fValue;
+ if ( thisLineWidth > maxLineWidth ) {
+ maxLineWidth = thisLineWidth;
}
}
}
+ if ( r_aspectCorrectFonts->integer ) {
+ return maxLineWidth * ((float)(SCREEN_WIDTH * glConfig.vidHeight) / (float)(SCREEN_HEIGHT * glConfig.vidWidth));
+ }
+ else {
+ return maxLineWidth;
+ }
+}
- // using ceil because we need to make sure that all the text is contained within the integer pixel width we're returning
- return (int)ceilf(fMaxWidth);
+int RE_Font_StrLenPixels( const char *psText, const int iFontHandle, const float fScale ) {
+ return (int)ceilf( RE_Font_StrLenPixelsNew( psText, iFontHandle, fScale ) );
}
// not really a font function, but keeps naming consistant...
@@ -1652,8 +1647,17 @@ void RE_Font_DrawString(int ox, int oy, const char *psText, const float *rgba, c
//lastcolour.c,
hShader // qhandle_t hShader
);
-
- fx += fAdvancePixels;
+ if ( r_aspectCorrectFonts->integer == 1 ) {
+ fx += fAdvancePixels
+ * ((float)(SCREEN_WIDTH * glConfig.vidHeight) / (float)(SCREEN_HEIGHT * glConfig.vidWidth));
+ }
+ else if ( r_aspectCorrectFonts->integer == 2 ) {
+ fx += ceilf( fAdvancePixels
+ * ((float)(SCREEN_WIDTH * glConfig.vidHeight) / (float)(SCREEN_HEIGHT * glConfig.vidWidth)) );
+ }
+ else {
+ fx += fAdvancePixels;
+ }
}
break;
}
diff --git a/codemp/rd-common/tr_font.h b/codemp/rd-common/tr_font.h
index 0017e18..d8e073d 100644
--- a/codemp/rd-common/tr_font.h
+++ b/codemp/rd-common/tr_font.h
@@ -33,7 +33,8 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
void R_ShutdownFonts(void);
void R_InitFonts(void);
int RE_RegisterFont(const char *psName);
-int RE_Font_StrLenPixels(const char *psText, const int iFontHandle, const float fScale = 1.0f);
+float RE_Font_StrLenPixelsNew( const char *psText, const int iFontHandle, const float fScale = 1.0f );
+int RE_Font_StrLenPixels( const char *psText, const int iFontHandle, const float fScale = 1.0f );
int RE_Font_StrLenChars(const char *psText);
int RE_Font_HeightPixels(const int iFontHandle, const float fScale = 1.0f);
void RE_Font_DrawString(int ox, int oy, const char *psText, const float *rgba, const int iFontHandle, int iMaxPixelWidth, const float fScale = 1.0f);
diff --git a/codemp/rd-common/tr_public.h b/codemp/rd-common/tr_public.h
index ac62599..9da97ca 100644
--- a/codemp/rd-common/tr_public.h
+++ b/codemp/rd-common/tr_public.h
@@ -30,7 +30,7 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "../qcommon/qcommon.h"
#include "../ghoul2/ghoul2_shared.h"
-#define REF_API_VERSION 7
+#define REF_API_VERSION 8
//
// these are the functions exported by the refresh module
@@ -239,7 +239,12 @@ typedef struct refexport_s {
int (*G2API_GetNumGoreMarks) ( CGhoul2Info_v& ghoul2, int modelIndex );
void (*G2API_AddSkinGore) ( CGhoul2Info_v &ghoul2, SSkinGoreData &gore );
void (*G2API_ClearSkinGore) ( CGhoul2Info_v &ghoul2 );
- #endif // _SOF2
+ #endif // _G2_GORE
+
+ struct {
+ float (*Font_StrLenPixels) ( const char *text, const int iFontIndex, const float scale );
+ } ext;
+
} refexport_t;
//
diff --git a/codemp/rd-vanilla/tr_init.cpp b/codemp/rd-vanilla/tr_init.cpp
index 22bc593..a9aeb5a 100644
--- a/codemp/rd-vanilla/tr_init.cpp
+++ b/codemp/rd-vanilla/tr_init.cpp
@@ -164,6 +164,8 @@ cvar_t *r_debugSort;
cvar_t *r_marksOnTriangleMeshes;
+cvar_t *r_aspectCorrectFonts;
+
// the limits apply to the sum of all scenes in a frame --
// the main view, all the 3D icons, etc
#define DEFAULT_MAX_POLYS 600
@@ -1646,6 +1648,7 @@ void R_Register( void )
r_shadows = ri->Cvar_Get( "cg_shadows", "1", CVAR_NONE );
r_shadowRange = ri->Cvar_Get( "r_shadowRange", "1000", CVAR_NONE );
r_marksOnTriangleMeshes = ri->Cvar_Get( "r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE );
+ r_aspectCorrectFonts = ri->Cvar_Get( "r_aspectCorrectFonts", "0", CVAR_ARCHIVE );
r_maxpolys = ri->Cvar_Get( "r_maxpolys", XSTRING( DEFAULT_MAX_POLYS ), CVAR_NONE );
r_maxpolyverts = ri->Cvar_Get( "r_maxpolyverts", XSTRING( DEFAULT_MAX_POLYVERTS ), CVAR_NONE );
/*
@@ -2129,6 +2132,8 @@ Q_EXPORT refexport_t* QDECL GetRefAPI( int apiVersion, refimport_t *rimp ) {
// this is set in R_Init
//re.G2VertSpaceServer = G2VertSpaceServer;
+ re.ext.Font_StrLenPixels = RE_Font_StrLenPixelsNew;
+
return &re;
}
diff --git a/codemp/rd-vanilla/tr_local.h b/codemp/rd-vanilla/tr_local.h
index 6c47877..da275d2 100644
--- a/codemp/rd-vanilla/tr_local.h
+++ b/codemp/rd-vanilla/tr_local.h
@@ -1225,6 +1225,8 @@ extern cvar_t *r_debugSort;
extern cvar_t *r_marksOnTriangleMeshes;
+extern cvar_t *r_aspectCorrectFonts;
+
/*
Ghoul2 Insert Start
*/
diff --git a/codemp/ui/ui_main.c b/codemp/ui/ui_main.c
index 21f28b1..6d9515a 100644
--- a/codemp/ui/ui_main.c
+++ b/codemp/ui/ui_main.c
@@ -9898,6 +9898,7 @@ void UI_Init( qboolean inGameLoad ) {
uiInfo.uiDC.stopCinematic = &UI_StopCinematic;
uiInfo.uiDC.drawCinematic = &UI_DrawCinematic;
uiInfo.uiDC.runCinematicFrame = &UI_RunCinematicFrame;
+ uiInfo.uiDC.ext.Font_StrLenPixels = trap->ext.R_Font_StrLenPixels;
Init_Display(&uiInfo.uiDC);
diff --git a/codemp/ui/ui_public.h b/codemp/ui/ui_public.h
index d033051..4a1f2d7 100644
--- a/codemp/ui/ui_public.h
+++ b/codemp/ui/ui_public.h
@@ -23,7 +23,7 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#pragma once
-#define UI_API_VERSION 1
+#define UI_API_VERSION 2
#define UI_LEGACY_API_VERSION 7
typedef struct uiClientState_s {
@@ -370,6 +370,10 @@ typedef struct uiImport_s {
void (*G2API_GetSurfaceName) ( void *ghoul2, int surfNumber, int modelIndex, char *fillBuf );
qboolean (*G2API_SetSkin) ( void *ghoul2, int modelIndex, qhandle_t customSkin, qhandle_t renderSkin );
qboolean (*G2API_AttachG2Model) ( void *ghoul2From, int modelIndexFrom, void *ghoul2To, int toBoltIndex, int toModel );
+
+ struct {
+ float (*R_Font_StrLenPixels) ( const char *text, const int iFontIndex, const float scale );
+ } ext;
} uiImport_t;
typedef struct uiExport_s {
diff --git a/codemp/ui/ui_shared.h b/codemp/ui/ui_shared.h
index 005e56c..5e74993 100644
--- a/codemp/ui/ui_shared.h
+++ b/codemp/ui/ui_shared.h
@@ -485,6 +485,10 @@ typedef struct displayContextDef_s {
qhandle_t gradientImage;
qhandle_t cursor;
float FPS;
+
+ struct {
+ float (*Font_StrLenPixels) ( const char *text, const int iFontIndex, const float scale );
+ } ext;
} displayContextDef_t;
diff --git a/codemp/ui/ui_syscalls.c b/codemp/ui/ui_syscalls.c
index aac79ff..3841266 100644
--- a/codemp/ui/ui_syscalls.c
+++ b/codemp/ui/ui_syscalls.c
@@ -113,13 +113,21 @@ qhandle_t trap_R_RegisterFont( const char *fontName ) {
return Q_syscall( UI_R_REGISTERFONT, fontName);
}
int trap_R_Font_StrLenPixels(const char *text, const int iFontIndex, const float scale) {
- return Q_syscall( UI_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(scale));
+ //HACK! RE_Font_StrLenPixels works better with 1.0f scale
+ float width = (float)Q_syscall( UI_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(1.0f));
+ return width * scale;
+}
+float trap_R_Font_StrLenPixelsFloat(const char *text, const int iFontIndex, const float scale) {
+ //HACK! RE_Font_StrLenPixels works better with 1.0f scale
+ float width = (float)Q_syscall( UI_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(1.0f));
+ return width * scale;
}
int trap_R_Font_StrLenChars(const char *text) {
return Q_syscall( UI_R_FONT_STRLENCHARS, text);
}
int trap_R_Font_HeightPixels(const int iFontIndex, const float scale) {
- return Q_syscall( UI_R_FONT_STRHEIGHTPIXELS, iFontIndex, PASSFLOAT(scale));
+ float height = (float)Q_syscall( UI_R_FONT_STRHEIGHTPIXELS, iFontIndex, PASSFLOAT( 1.0f ) );
+ return height * scale;
}
void trap_R_Font_DrawString(int ox, int oy, const char *text, const float *rgba, const int setIndex, int iCharLimit, const float scale) {
Q_syscall( UI_R_FONT_DRAWSTRING, ox, oy, text, rgba, setIndex, iCharLimit, PASSFLOAT(scale));
@@ -627,4 +635,6 @@ static void TranslateSyscalls( void ) {
trap->G2API_IKMove = trap_G2API_IKMove;
trap->G2API_GetSurfaceName = trap_G2API_GetSurfaceName;
trap->G2API_AttachG2Model = trap_G2API_AttachG2Model;
+
+ trap->ext.R_Font_StrLenPixels = trap_R_Font_StrLenPixelsFloat;
}
I would also like to see https://github.com/ioquake/ioq3/commit/da29118ae04c7a597d6371e41512834ff17a6b6a / https://github.com/ioquake/ioq3/commit/0bdf52e2fbad72dff27724cff020590de504ab5d if the option to do this would be possible with new changes. This would allow the chat box in JA++ to work as it does in OJK.
CG_Text_Paint etc have an extra parameter and the DC->drawText expects without the extra parameter.