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;
}
int Graphics::textwidth(String str)
int Graphics::textwidth(const String &str)
{
int x = 0;
String::value_type const *s = str.c_str();
for (; *s; s++)
for (size_t i = 0; i < str.length(); i++)
{
if(*s=='\b')
if (str[i] == '\b')
{
if(!s[1]) break;
s++;
continue;
} else if(*s == '\x0F') {
if(!s[1] || !s[2] || !s[3]) break;
s+=3;
if (str.length() <= i+1)
break;
i++;
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;
}
@ -469,83 +472,24 @@ int Graphics::CharWidth(String::value_type c)
return FontReader(c).GetWidth();
}
int Graphics::textnwidth(String str, int n)
int Graphics::textwidthx(const String &str, int w)
{
int x = 0;
String::value_type const *s = str.c_str();
for (; *s; s++)
int x = 0,n = 0,cw = 0;
for (size_t i = 0; i < str.length(); i++)
{
if (!n)
break;
if(*s=='\b')
if (str[i] == '\b')
{
if(!s[1]) break;
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) {
if (str.length() <= i+1)
break;
}
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++;
i++;
continue;
} else if (*s == '\x0F')
{
if(!s[1] || !s[2] || !s[3]) break;
s+=3;
} else if (str[i] == '\x0F') {
if (str.length() <= i+3)
break;
i += 3;
continue;
}
cw = FontReader(*s).GetWidth();
cw += FontReader(str[i]).GetWidth();
if (x+(cw/2) >= w)
break;
x += cw;
@ -554,56 +498,7 @@ int Graphics::textwidthx(String str, int w)
return n;
}
int Graphics::textwrapheight(String str, int width)
{
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)
void Graphics::textsize(const String &str, int & width, int & height)
{
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;
String::value_type const *s = str.c_str();
for (; *s; s++)
for (size_t i = 0; i < str.length(); i++)
{
if (*s == '\n')
if (str[i] == '\n')
{
cWidth = 0;
cHeight += FONT_H;
}
else if (*s == '\x0F')
else if (str[i] == '\x0F')
{
if(!s[1] || !s[2] || !s[3]) break;
s+=3;
if (str.length() <= i+3)
break;
i += 3;
}
else if (*s == '\b')
else if (str[i] == '\b')
{
if(!s[1]) break;
s++;
if (str.length() <= i+1)
break;
i++;
}
else
{
cWidth += FontReader(*s).GetWidth();
cWidth += FontReader(str[i]).GetWidth();
if(cWidth>lWidth)
lWidth = cWidth;
}

View File

@ -91,12 +91,9 @@ public:
//Font/text metrics
static int CharWidth(String::value_type c);
static int textnwidth(String s, int n);
static void textnpos(String s, int n, int w, int *cx, int *cy);
static int textwidthx(String s, int w);
static int textwrapheight(String s, int width);
static int textwidth(String s);
static void textsize(String s, int & width, int & height);
static int textwidthx(const String &s, int w);
static int textwidth(const String &s);
static void textsize(const String &s, int & width, int & height);
VideoBuffer DumpFrame();
@ -108,8 +105,8 @@ public:
void Clear();
void Finalise();
//
int drawtext_outline(int x, int y, 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_outline(int x, int y, const 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 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 "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);
@ -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);
}
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())
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 characterX = x, characterY = y;
int startX = characterX;
String::value_type const *s = str.c_str();
for (; *s; s++)
for (size_t i = 0; i < str.length(); i++)
{
if (*s == '\n')
if (str[i] == '\n')
{
characterX = startX;
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;
oG = g;
oB = b;
r = (unsigned char)s[1];
g = (unsigned char)s[2];
b = (unsigned char)s[3];
s += 3;
r = (unsigned char)str[i + 1];
g = (unsigned char)str[i + 2];
b = (unsigned char)str[i + 3];
i += 3;
}
else if (*s == '\x0E')
else if (str[i] == '\x0E')
{
r = oR;
g = oG;
b = oB;
}
else if (*s == '\x01')
else if (str[i] == '\x01')
{
invert = !invert;
r = 255-r;
g = 255-g;
b = 255-b;
}
else if (*s == '\b')
else if (str[i] == '\b')
{
if(!s[1]) break;
switch (s[1])
if (str.length() <= i + 1)
break;
switch (str[i + 1])
{
case 'w': r = 255; g = 255; b = 255; 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;
b = 255-b;
}
s++;
i++;
}
else
{
characterX = drawchar(characterX, characterY, *s, r, g, b, a);
characterX = drawchar(characterX, characterY, str[i], r, g, b, a);
}
}
return x;

View File

@ -102,8 +102,8 @@ public:
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(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, 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 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
{
void OnTryExit(ExitMethod method)
void OnTryExit(ExitMethod method) override
{
CloseActiveWindow();
SelfDestruct();
}
void OnDraw()
void OnDraw() override
{
Graphics * g = GetGraphics();