Fix string handling in text drawing / width functions

Allows passing in null bytes, which allows 0s to be used with \x0F color codes
Also unrelated, fix two warnings in OptionsView.cpp
This commit is contained in:
jacob1 2022-10-25 22:35:43 -04:00
parent a3a874f4d6
commit 8fd6db56d1
No known key found for this signature in database
GPG Key ID: 4E58A32D510E1995
5 changed files with 65 additions and 171 deletions

View File

@ -443,23 +443,26 @@ pixel *Graphics::rescale_img(pixel *src, int sw, int sh, int *qw, int *qh, int f
return q; return q;
} }
int Graphics::textwidth(String str) int Graphics::textwidth(const String &str)
{ {
int x = 0; int x = 0;
String::value_type const *s = str.c_str(); for (size_t i = 0; i < str.length(); i++)
for (; *s; s++)
{ {
if(*s=='\b') if (str[i] == '\b')
{ {
if(!s[1]) break; if (str.length() <= i+1)
s++; break;
continue; i++;
} else if(*s == '\x0F') {
if(!s[1] || !s[2] || !s[3]) break;
s+=3;
continue; continue;
} }
x += FontReader(*s).GetWidth(); else if (str[i] == '\x0F')
{
if (str.length() <= i+3)
break;
i += 3;
continue;
}
x += FontReader(str[i]).GetWidth();
} }
return x-1; return x-1;
} }
@ -469,83 +472,24 @@ int Graphics::CharWidth(String::value_type c)
return FontReader(c).GetWidth(); return FontReader(c).GetWidth();
} }
int Graphics::textnwidth(String str, int n) int Graphics::textwidthx(const String &str, int w)
{ {
int x = 0; int x = 0,n = 0,cw = 0;
String::value_type const *s = str.c_str(); for (size_t i = 0; i < str.length(); i++)
for (; *s; s++)
{ {
if (!n) if (str[i] == '\b')
break;
if(*s=='\b')
{ {
if(!s[1]) break; if (str.length() <= i+1)
s++;
continue;
} else if(*s == '\x0F') {
if(!s[1] || !s[2] || !s[3]) break;
s+=3;
continue;
}
x += FontReader(*s).GetWidth();
n--;
}
return x-1;
}
void Graphics::textnpos(String str, int n, int w, int *cx, int *cy)
{
int x = 0;
int y = 0;
int wordlen, charspace;
String::value_type const *s = str.c_str();
while (*s&&n)
{
wordlen = 0;
while(*s && String(" .,!?\n").Contains(*s))
s++;
charspace = textwidthx(s, w-x);
if (charspace<wordlen && wordlen && w-x<w/3)
{
x = 0;
y += FONT_H;
}
for (; *s && --wordlen>=-1; s++)
{
if (!n) {
break; break;
} i++;
x += FontReader(*s).GetWidth();
if (x>=w)
{
x = 0;
y += FONT_H;
}
n--;
}
}
*cx = x-1;
*cy = y;
}
int Graphics::textwidthx(String str, int w)
{
int x=0,n=0,cw;
String::value_type const *s = str.c_str();
for (; *s; s++)
{
if(*s == '\b')
{
if(!s[1]) break;
s++;
continue; continue;
} else if (*s == '\x0F') } else if (str[i] == '\x0F') {
{ if (str.length() <= i+3)
if(!s[1] || !s[2] || !s[3]) break; break;
s+=3; i += 3;
continue; continue;
} }
cw = FontReader(*s).GetWidth(); cw += FontReader(str[i]).GetWidth();
if (x+(cw/2) >= w) if (x+(cw/2) >= w)
break; break;
x += cw; x += cw;
@ -554,56 +498,7 @@ int Graphics::textwidthx(String str, int w)
return n; return n;
} }
int Graphics::textwrapheight(String str, int width) void Graphics::textsize(const String &str, int & width, int & height)
{
int x=0, height=FONT_H, cw;
int wordlen;
int charspace;
String::value_type const *s = str.c_str();
while (*s)
{
wordlen = 0;
while(*s && String(" .,!?\n").Contains(*s))
s++;
charspace = textwidthx(s, width-x);
if (charspace<wordlen && wordlen && width-x<width/3)
{
x = 0;
height += FONT_H;
}
for (; *s && --wordlen>=-1; s++)
{
if (*s == '\n')
{
x = 0;
height += FONT_H;
}
else if (*s == '\b')
{
if(!s[1]) break;
s++;
}
else if (*s == '\x0F')
{
if(!s[1] || !s[2] || !s[3]) break;
s+=3;
}
else
{
cw = FontReader(*s).GetWidth();
if (x+cw>=width)
{
x = 0;
height += FONT_H;
}
x += cw;
}
}
}
return height;
}
void Graphics::textsize(String str, int & width, int & height)
{ {
if(!str.size()) if(!str.size())
{ {
@ -613,27 +508,28 @@ void Graphics::textsize(String str, int & width, int & height)
} }
int cHeight = FONT_H-2, cWidth = 0, lWidth = 0; int cHeight = FONT_H-2, cWidth = 0, lWidth = 0;
String::value_type const *s = str.c_str(); for (size_t i = 0; i < str.length(); i++)
for (; *s; s++)
{ {
if (*s == '\n') if (str[i] == '\n')
{ {
cWidth = 0; cWidth = 0;
cHeight += FONT_H; cHeight += FONT_H;
} }
else if (*s == '\x0F') else if (str[i] == '\x0F')
{ {
if(!s[1] || !s[2] || !s[3]) break; if (str.length() <= i+3)
s+=3; break;
i += 3;
} }
else if (*s == '\b') else if (str[i] == '\b')
{ {
if(!s[1]) break; if (str.length() <= i+1)
s++; break;
i++;
} }
else else
{ {
cWidth += FontReader(*s).GetWidth(); cWidth += FontReader(str[i]).GetWidth();
if(cWidth>lWidth) if(cWidth>lWidth)
lWidth = cWidth; lWidth = cWidth;
} }

View File

@ -91,12 +91,9 @@ public:
//Font/text metrics //Font/text metrics
static int CharWidth(String::value_type c); static int CharWidth(String::value_type c);
static int textnwidth(String s, int n); static int textwidthx(const String &s, int w);
static void textnpos(String s, int n, int w, int *cx, int *cy); static int textwidth(const String &s);
static int textwidthx(String s, int w); static void textsize(const String &s, int & width, int & height);
static int textwrapheight(String s, int width);
static int textwidth(String s);
static void textsize(String s, int & width, int & height);
VideoBuffer DumpFrame(); VideoBuffer DumpFrame();
@ -108,8 +105,8 @@ public:
void Clear(); void Clear();
void Finalise(); void Finalise();
// //
int drawtext_outline(int x, int y, String s, int r, int g, int b, int a); int drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a);
int drawtext(int x, int y, String s, int r, int g, int b, int a); int drawtext(int x, int y, const String &s, int r, int g, int b, int a);
int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a); int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a);
int addchar(int x, int y, String::value_type c, int r, int g, int b, int a); int addchar(int x, int y, String::value_type c, int r, int g, int b, int a);

View File

@ -1,7 +1,7 @@
#include <cmath> #include <cmath>
#include "FontReader.h" #include "FontReader.h"
int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, String s, int r, int g, int b, int a) int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a)
{ {
drawtext(x-1, y-1, s, 0, 0, 0, 120); drawtext(x-1, y-1, s, 0, 0, 0, 120);
drawtext(x+1, y+1, s, 0, 0, 0, 120); drawtext(x+1, y+1, s, 0, 0, 0, 120);
@ -12,7 +12,7 @@ int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, String s, int r, int g, i
return drawtext(x, y, s, r, g, b, a); return drawtext(x, y, s, r, g, b, a);
} }
int PIXELMETHODS_CLASS::drawtext(int x, int y, String str, int r, int g, int b, int a) int PIXELMETHODS_CLASS::drawtext(int x, int y, const String &str, int r, int g, int b, int a)
{ {
if(!str.size()) if(!str.size())
return 0; return 0;
@ -21,42 +21,43 @@ int PIXELMETHODS_CLASS::drawtext(int x, int y, String str, int r, int g, int b,
int oR = r, oG = g, oB = b; int oR = r, oG = g, oB = b;
int characterX = x, characterY = y; int characterX = x, characterY = y;
int startX = characterX; int startX = characterX;
String::value_type const *s = str.c_str(); for (size_t i = 0; i < str.length(); i++)
for (; *s; s++)
{ {
if (*s == '\n') if (str[i] == '\n')
{ {
characterX = startX; characterX = startX;
characterY += FONT_H; characterY += FONT_H;
} }
else if (*s == '\x0F') else if (str[i] == '\x0F')
{ {
if(!s[1] || !s[2] || !s[3]) break; if (str.length() <= i+3)
break;
oR = r; oR = r;
oG = g; oG = g;
oB = b; oB = b;
r = (unsigned char)s[1]; r = (unsigned char)str[i + 1];
g = (unsigned char)s[2]; g = (unsigned char)str[i + 2];
b = (unsigned char)s[3]; b = (unsigned char)str[i + 3];
s += 3; i += 3;
} }
else if (*s == '\x0E') else if (str[i] == '\x0E')
{ {
r = oR; r = oR;
g = oG; g = oG;
b = oB; b = oB;
} }
else if (*s == '\x01') else if (str[i] == '\x01')
{ {
invert = !invert; invert = !invert;
r = 255-r; r = 255-r;
g = 255-g; g = 255-g;
b = 255-b; b = 255-b;
} }
else if (*s == '\b') else if (str[i] == '\b')
{ {
if(!s[1]) break; if (str.length() <= i + 1)
switch (s[1]) break;
switch (str[i + 1])
{ {
case 'w': r = 255; g = 255; b = 255; break; case 'w': r = 255; g = 255; b = 255; break;
case 'g': r = 192; g = 192; b = 192; break; case 'g': r = 192; g = 192; b = 192; break;
@ -73,11 +74,11 @@ int PIXELMETHODS_CLASS::drawtext(int x, int y, String str, int r, int g, int b,
g = 255-g; g = 255-g;
b = 255-b; b = 255-b;
} }
s++; i++;
} }
else else
{ {
characterX = drawchar(characterX, characterY, *s, r, g, b, a); characterX = drawchar(characterX, characterY, str[i], r, g, b, a);
} }
} }
return x; return x;

View File

@ -102,8 +102,8 @@ public:
void draw_icon(int x, int y, Icon icon); void draw_icon(int x, int y, Icon icon);
int drawtext_outline(int x, int y, String s, int r, int g, int b, int a); int drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a);
int drawtext(int x, int y, String s, int r, int g, int b, int a); int drawtext(int x, int y, const String &s, int r, int g, int b, int a);
int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a); int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a);
int addchar(int x, int y, String::value_type c, int r, int g, int b, int a); int addchar(int x, int y, String::value_type c, int r, int g, int b, int a);

View File

@ -148,13 +148,13 @@ OptionsView::OptionsView():
class GravityWindow : public ui::Window class GravityWindow : public ui::Window
{ {
void OnTryExit(ExitMethod method) void OnTryExit(ExitMethod method) override
{ {
CloseActiveWindow(); CloseActiveWindow();
SelfDestruct(); SelfDestruct();
} }
void OnDraw() void OnDraw() override
{ {
Graphics * g = GetGraphics(); Graphics * g = GetGraphics();