From df9065d1593991b62c23584fe78c3b66e6e02751 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 6 Mar 2023 15:05:46 +0100 Subject: [PATCH] Clean up character drawing & word wrapping --- src/hu_stuff.c | 63 +-------------- src/v_video.c | 210 +++++++++++++++++++++---------------------------- src/v_video.h | 18 +++-- 3 files changed, 104 insertions(+), 187 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 2e9aad62a..ae16078ef 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1197,67 +1197,10 @@ boolean HU_Responder(event_t *ev) #ifndef NONET -// Precompile a wordwrapped string to any given width. -// This is a muuuch better method than V_WORDWRAP. -// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. -// this one is simplified for the chat drawer. -static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) -{ - INT32 c; - size_t chw, i, lastusablespace = 0; - size_t slen; - char *newstring = Z_StrDup(string); - INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4; - - slen = strlen(string); - x = 0; - - for (i = 0; i < slen; ++i) - { - c = newstring[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 - continue; - - if (c == '\n') - { - x = 0; - lastusablespace = 0; - continue; - } - - if (!(option & V_ALLOWLOWERCASE)) - c = toupper(c); - c -= FONTSTART; - - if (c < 0 || c >= FONTSIZE || !hu_font.chars[c]) - { - chw = spacewidth; - lastusablespace = i; - } - else - chw = charwidth; - - x += chw; - - if (lastusablespace != 0 && x > w) - { - //CONS_Printf("Wrap at index %d\n", i); - newstring[lastusablespace] = '\n'; - i = lastusablespace+1; - lastusablespace = 0; - x = 0; - } - } - return newstring; -} - - // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. INT16 chatx = 13, chaty = 169; // let's use this as our coordinates -// chat stuff by VincyTM LOL XD! - // HU_DrawMiniChat static void HU_drawMiniChat(void) @@ -1281,7 +1224,7 @@ static void HU_drawMiniChat(void) for (; i>0; i--) { - char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + char *msg = V_ChatWordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); size_t j = 0; INT32 linescount = 0; @@ -1348,7 +1291,7 @@ static void HU_drawMiniChat(void) INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. size_t j = 0; - char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + char *msg = V_ChatWordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; while(msg[j]) // iterate through msg @@ -1448,7 +1391,7 @@ static void HU_drawChatLog(INT32 offset) { INT32 clrflag = 0; INT32 j = 0; - char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it. + char *msg = V_ChatWordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; while(msg[j]) // iterate through msg { diff --git a/src/v_video.c b/src/v_video.c index b879838e3..a9fbceb3d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1940,125 +1940,6 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color) *buf = promptbgmap[*buf]; } -// Writes a single character (draw WHITE if bit 7 set) -// -void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) -{ - INT32 w, flags; - const UINT8 *colormap = V_GetStringColormap(c); - - flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); - c &= 0x7f; - if (lowercaseallowed) - c -= FONTSTART; - else - c = toupper(c) - FONTSTART; - if (c < 0 || c >= FONTSIZE || !hu_font.chars[c]) - return; - - w = hu_font.chars[c]->width; - if (x + w > vid.width) - return; - - if (colormap != NULL) - V_DrawMappedPatch(x, y, flags, hu_font.chars[c], colormap); - else - V_DrawScaledPatch(x, y, flags, hu_font.chars[c]); -} - -// Writes a single character for the chat. (draw WHITE if bit 7 set) -// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge.. -// -void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap) -{ - INT32 w, flags; - //const UINT8 *colormap = V_GetStringColormap(c); - - flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); - c &= 0x7f; - if (lowercaseallowed) - c -= FONTSTART; - else - c = toupper(c) - FONTSTART; - if (c < 0 || c >= FONTSIZE || !hu_font.chars[c]) - return; - - w = (vid.width < 640 ) ? ((hu_font.chars[c]->width / 2)) : (hu_font.chars[c]->width); // use normal sized characters if we're using a terribly low resolution. - if (x + w > vid.width) - return; - - V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font.chars[c], colormap); -} - -// Precompile a wordwrapped string to any given width. -// This is a muuuch better method than V_WORDWRAP. -char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) -{ - int c; - size_t chw, i, lastusablespace = 0; - size_t slen; - char *newstring = Z_StrDup(string); - INT32 spacewidth = 4, charwidth = 0; - - slen = strlen(string); - - if (w == 0) - w = BASEVIDWIDTH; - w -= x; - x = 0; - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 8; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 8; - break; - case V_6WIDTHSPACE: - spacewidth = 6; - default: - break; - } - - for (i = 0; i < slen; ++i) - { - c = newstring[i]; - if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 - continue; - - if (c == '\n') - { - x = 0; - lastusablespace = 0; - continue; - } - - if (!(option & V_ALLOWLOWERCASE)) - c = toupper(c); - c -= FONTSTART; - - if (c < 0 || c >= FONTSIZE || !hu_font.chars[c]) - { - chw = spacewidth; - lastusablespace = i; - } - else - chw = (charwidth ? charwidth : hu_font.chars[c]->width); - - x += chw; - - if (lastusablespace != 0 && x > w) - { - newstring[lastusablespace] = '\n'; - i = lastusablespace; - lastusablespace = 0; - x = 0; - } - } - return newstring; -} - // Gets string colormap, used for 0x80 color codes // UINT8 *V_GetStringColormap(INT32 colorflags) @@ -2100,6 +1981,97 @@ UINT8 *V_GetStringColormap(INT32 colorflags) } } +// Generalized character drawing function, combining console & chat functionality with a specified font. +// +void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font) +{ + INT32 w, flags; + const UINT8 *color = colormap ? colormap : V_GetStringColormap(c); + + flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); + c &= 0x7f; + if (lowercaseallowed) + c -= FONTSTART; + else + c = toupper(c) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) + return; + + w = FixedMul(font.chars[c]->width / 2, scale); // use normal sized characters if we're using a terribly low resolution. + if (x + w > vid.width) + return; + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, scale, flags, font.chars[c], color); +} + +// Precompile a wordwrapped string to any given width, using a specified font. +// +char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font) +{ + int c; + size_t chw, i, lastusablespace = 0; + size_t slen; + char *newstring = Z_StrDup(string); + INT32 spacewidth = font.spacewidth, charwidth = 0; + + slen = strlen(string); + + if (w == 0) + w = BASEVIDWIDTH; + w -= x; + x = 0; + + switch (option & V_SPACINGMASK) + { + case V_MONOSPACE: + spacewidth = font.spacewidth*2; + /* FALLTHRU */ + case V_OLDSPACING: + charwidth = font.spacewidth*2; + break; + case V_6WIDTHSPACE: + spacewidth = 6; + default: + break; + } + + for (i = 0; i < slen; ++i) + { + c = newstring[i]; + if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 + continue; + + if (c == '\n') + { + x = 0; + lastusablespace = 0; + continue; + } + + if (!(option & V_ALLOWLOWERCASE)) + c = toupper(c); + c -= FONTSTART; + + if (c < 0 || c >= FONTSIZE || !font.chars[c]) + { + chw = spacewidth; + lastusablespace = i; + } + else + chw = (charwidth ? charwidth : font.chars[c]->width); + + x += FixedMul(chw, scale); + + if (lastusablespace != 0 && x > w) + { + newstring[lastusablespace] = '\n'; + i = lastusablespace; + lastusablespace = x = 0; + } + } + return newstring; +} + // Draw a string, using a supplied font and scale. // NOTE: The text is centered for screens larger than the base width. void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font) diff --git a/src/v_video.h b/src/v_video.h index b454da748..0a5bbfc51 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -195,16 +195,18 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U void V_DrawFadeConsBack(INT32 plines); void V_DrawPromptBack(INT32 boxheight, INT32 color); - -// draw a single character -void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); -// draw a single character, but for the chat -void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap); - -// wordwrap a string using the hu_font -char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string); UINT8 *V_GetStringColormap(INT32 colorflags); +// Generalized character drawing function, combining console & chat functionality with a specified font. +void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font); +#define V_DrawCharacter(x,y,c,l) V_DrawFontCharacter(x,y,c,l,FRACUNIT,NULL,hu_font) +#define V_DrawChatCharacter(x,y,c,l,cm) V_DrawFontCharacter(x,y,c,l,FRACUNIT/2,cm,hu_font) + +// Precompile a wordwrapped string to any given width, using a specified font. +char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font); +#define V_WordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT, str, hu_font) +#define V_ChatWordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT/2, str, hu_font) + // Draw a string, using a supplied font and scale. void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font); void V_DrawCenteredFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);