Razish / japp

JA++ server and client modification for Jedi Academy
GNU General Public License v2.0
44 stars 30 forks source link

CG display context has the wrong function pointer signature for drawText #337

Closed ensiform closed 8 years ago

ensiform commented 8 years ago

CG_Text_Paint etc have an extra parameter and the DC->drawText expects without the extra parameter.

Razish commented 8 years ago

Fixed in my working copy; major rewrite of text rendering/width functions. Just waiting on OpenJK changes to font code.

ensiform commented 8 years ago

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?

Razish commented 8 years ago

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.

ensiform commented 8 years ago

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.

Razish commented 8 years ago

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;
 }
ensiform commented 8 years ago

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.