V_ScaledWordWrap

Moves WordWrap to the font/V_GetFontSpecification system.

Much healthier long-term for our purposes, including the possibility of changing fonts for various contexts freely.
This commit is contained in:
toaster 2023-07-11 14:37:42 +01:00
parent fb0fa9ac53
commit 277f7c51a3
7 changed files with 187 additions and 207 deletions

View file

@ -2281,7 +2281,24 @@ static void F_PreparePageText(char *pagetext)
if (promptpagetext)
Z_Free(promptpagetext);
promptpagetext = (pagetext && pagetext[0]) ? V_WordWrap(textx, textr, 0, pagetext) : Z_StrDup("");
if (pagetext && pagetext[0])
{
promptpagetext = Z_StrDup(pagetext);
V_ScaledWordWrap(
(textx - textr)<<FRACBITS,
FRACUNIT, FRACUNIT, FRACUNIT,
0, HU_FONT,
promptpagetext
);
}
else
{
// The original code I was replacing did this,
// And I'm not really interested enough to figure out
// if this is strictly necessary in the long term or
// if it was just an anti-crash doohickey. ~toast 110723
promptpagetext = Z_StrDup("");
}
F_NewCutscene(promptpagetext);
cutscene_textspeed = textprompts[cutnum]->page[scenenum].textspeed ? textprompts[cutnum]->page[scenenum].textspeed : TICRATE/5;

View file

@ -1270,56 +1270,21 @@ boolean HU_Responder(event_t *ev)
//======================================================================
// 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.
// Now a wrapper 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;
fixed_t scale = (vid.width < 640) ? FRACUNIT : FRACUNIT/2;
for (i = 0; i < slen; ++i)
{
c = newstring[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
continue;
V_ScaledWordWrap(
(w - x) << FRACBITS,
scale, scale, scale,
option,
HU_FONT,
newstring
);
if (c == '\n')
{
x = 0;
lastusablespace = 0;
continue;
}
if (!!(option & V_FORCEUPPERCASE))
c = toupper(c);
c -= HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !fontv[HU_FONT].font[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;
}

View file

@ -1515,7 +1515,7 @@ char *M_BuildConditionSetString(UINT16 unlockid)
size_t len = 1024, worklen;
static char message[1024] = "";
const char *work = NULL;
size_t max = 0, maxatstart = 0, start = 0, i;
size_t i;
boolean stopasap = false;
message[0] = '\0';
@ -1577,37 +1577,6 @@ char *M_BuildConditionSetString(UINT16 unlockid)
}
}
// Rudementary word wrapping.
// Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares.
for (i = 0; message[i]; i++)
{
if (message[i] == ' ')
{
start = i;
max += 4;
maxatstart = max;
}
else if (message[i] == '\n')
{
start = 0;
max = 0;
maxatstart = 0;
continue;
}
else if (message[i] & 0x80)
continue;
else
max += 8;
// Start trying to wrap if presumed length exceeds the space we have on-screen.
if (max >= DESCRIPTIONWIDTH && start > 0)
{
message[start] = '\n';
max -= maxatstart;
start = 0;
}
}
// Valid sentence capitalisation handling.
{
// Finds the first : character, indicating the end of the prefix.
@ -1634,6 +1603,15 @@ char *M_BuildConditionSetString(UINT16 unlockid)
}
}
// Finally, do a clean wordwrap!
V_ScaledWordWrap(
DESCRIPTIONWIDTH << FRACBITS,
FRACUNIT, FRACUNIT, FRACUNIT,
0,
HU_FONT,
message
);
return message;
}

View file

@ -2,6 +2,7 @@
// \brief MESSAGE BOX (aka: a hacked, cobbled together menu)
#include "../../k_menu.h"
#include "../../v_video.h" // V_ScaledWordWrap, HU_FONT
#include "../../z_zone.h"
// message prompt struct
@ -30,42 +31,18 @@ static inline size_t M_StringHeight(const char *string)
void M_StartMessage(const char *header, const char *string, void (*routine)(INT32), menumessagetype_t itemtype, const char *confirmstr, const char *defaultstr)
{
const UINT8 pid = 0;
size_t max = 0, maxatstart = 0, start = 0, strlines, i;
static char *message = NULL;
Z_Free(message);
message = Z_StrDup(string);
DEBFILE(message);
// Rudementary word wrapping.
// Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares.
for (i = 0; message[i]; i++)
{
if (message[i] == ' ')
{
start = i;
max += 4;
maxatstart = max;
}
else if (message[i] == '\n')
{
start = 0;
max = 0;
maxatstart = 0;
continue;
}
else if (message[i] & 0x80)
continue;
else
max += 8;
// Start trying to wrap if presumed length exceeds the screen width.
if (max >= BASEVIDWIDTH && start > 0)
{
message[start] = '\n';
max -= maxatstart;
start = 0;
}
}
V_ScaledWordWrap(
BASEVIDWIDTH << FRACBITS,
FRACUNIT, FRACUNIT, FRACUNIT,
0,
HU_FONT,
message
);
strncpy(menumessage.message, string, MAXMENUMESSAGE);
menumessage.header = header;
@ -77,9 +54,6 @@ void M_StartMessage(const char *header, const char *string, void (*routine)(INT3
menumessage.closing = 0;
menumessage.active = true;
start = 0;
max = 0;
if (!routine)
{
menumessage.flags = MM_NOTHING;
@ -108,29 +82,7 @@ void M_StartMessage(const char *header, const char *string, void (*routine)(INT3
}*/
//added : 06-02-98: now draw a textbox around the message
// compute lenght max and the numbers of lines
for (strlines = 0; *(message+start); strlines++)
{
for (i = 0; i < strlen(message+start);i++)
{
if (*(message+start+i) == '\n')
{
if (i > max)
max = i;
start += i;
i = (size_t)-1; //added : 07-02-98 : damned!
start++;
break;
}
}
if (i == strlen(message+start))
{
start += i;
if (i > max)
max = i;
}
}
// oogh my god this was replaced in 2023
menumessage.x = (8 * MAXSTRINGLENGTH) - 1;
menumessage.y = M_StringHeight(message);

View file

@ -305,6 +305,8 @@ static void I_ShowErrorMessageBox(const char *messagefordevelopers, boolean dump
// Rudementary word wrapping.
// Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares.
// We can't use V_ScaledWordWrap, which this shares DNA with, because no guarantee
// string character graphics exist as reference in the error handler...
{
size_t max = 0, maxatstart = 0, start = 0, width = 0, i;

View file

@ -2043,76 +2043,6 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
}
}
// 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_FORCEUPPERCASE))
c = toupper(c);
c -= HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !fontv[HU_FONT].font[c])
{
chw = spacewidth;
lastusablespace = i;
}
else
chw = (charwidth ? charwidth : fontv[HU_FONT].font[c]->width);
x += chw;
if (lastusablespace != 0 && x > w)
{
newstring[lastusablespace] = '\n';
i = lastusablespace;
lastusablespace = 0;
x = 0;
}
}
return newstring;
}
static inline fixed_t FixedCharacterDim(
fixed_t scale,
fixed_t chw,
@ -2684,6 +2614,136 @@ fixed_t V_StringScaledWidth(
return fullwidth;
}
// Modify a string to wordwrap at any given width.
void V_ScaledWordWrap(
fixed_t w,
fixed_t scale,
fixed_t spacescale,
fixed_t lfscale,
INT32 flags,
int fontno,
char *newstring)
{
INT32 hchw;/* half-width for centering */
INT32 dupx;
font_t *font;
boolean uppercase;
fixed_t cx;
fixed_t right;
fixed_t cw;
int c;
uppercase = ((flags & V_FORCEUPPERCASE) == V_FORCEUPPERCASE);
flags &= ~(V_FLIP);/* These two (V_FORCEUPPERCASE) share a bit. */
font = &fontv[fontno];
fontspec_t fontspec;
V_GetFontSpecification(fontno, flags, &fontspec);
hchw = fontspec.chw >> 1;
fontspec.chw <<= FRACBITS;
fontspec.spacew <<= FRACBITS;
#define Mul( id, scale ) ( id = FixedMul (scale, id) )
Mul (fontspec.chw, scale);
Mul (fontspec.spacew, scale);
Mul (fontspec.lfh, scale);
Mul (fontspec.spacew, spacescale);
Mul (fontspec.lfh, lfscale);
#undef Mul
if (( flags & V_NOSCALESTART ))
{
dupx = vid.dupx;
hchw *= dupx;
fontspec.chw *= dupx;
fontspec.spacew *= dupx;
fontspec.lfh *= vid.dupy;
}
else
{
dupx = 1;
}
cx = 0;
right = 0;
size_t i = 0, start = 0;
fixed_t cxatstart = 0;
for (; ( c = newstring[i] ); ++i)
{
switch (c)
{
case '\n':
cx = 0;
cxatstart = 0;
start = 0;
break;
default:
if (( c & 0x80 ))
continue;
if (uppercase)
{
c = toupper(c);
}
else if (V_CharacterValid(font, c - font->start) == false)
{
// Try the other case if it doesn't exist
if (c >= 'A' && c <= 'Z')
{
c = tolower(c);
}
else if (c >= 'a' && c <= 'z')
{
c = toupper(c);
}
}
c -= font->start;
if (V_CharacterValid(font, c) == true)
{
cw = SHORT (font->font[c]->width) * dupx;
// How bunched dims work is by incrementing cx slightly less than a full character width.
// This causes the next character to be drawn overlapping the previous.
// We need to count the full width to get the rightmost edge of the string though.
right = cx + (cw * scale);
(*fontspec.dim_fn)(scale, fontspec.chw, hchw, dupx, &cw);
cx += cw;
}
else
{
right = (cx += fontspec.spacew);
cxatstart = cx;
start = i;
}
}
// Start trying to wrap if presumed length exceeds the space we have on-screen.
if (start != 0 && right > w)
{
newstring[start] = '\n';
cx -= cxatstart;
start = 0;
}
}
}
void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string)
{
x -= V_StringWidth(string, option)/2;

View file

@ -273,9 +273,6 @@ UINT8 *V_GetStringColormap(INT32 colorflags);
INT32 V_LevelNameHeight(const char *string);
// wordwrap a string using the hu_font
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string);
// draw a string using a font
void V_DrawStringScaled(
fixed_t x,
@ -296,6 +293,15 @@ fixed_t V_StringScaledWidth(
int fontno,
const char *s);
void V_ScaledWordWrap(
fixed_t w,
fixed_t scale,
fixed_t spacescale,
fixed_t lfscale,
INT32 flags,
int fontno,
char *newstring);
// draw a string using the hu_font
#define V_DrawString( x,y,option,string ) \
V__DrawDupxString (x,y,FRACUNIT,option,NULL,HU_FONT,string)