mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Add graphics wrapping functions
This will wrap text on-the-fly, since I will be introducing text that needs to be wrapped whose length we can't know in advance. (Or we can, but, that'd be stupid.) I took the algorithm from Dav999's localization branch, but it's not like it's a complicated algorithm in the first place. Plus I think it actually handles words that get too long to fit on a single line better than his localization branch. The only difference is that I removed all the STL, and made it more memory efficient (unlike his localization branch, it does not copy the entire string to make a version with newline separator characters).
This commit is contained in:
parent
ee02aa0499
commit
ed9cb4ca6d
2 changed files with 119 additions and 0 deletions
|
@ -515,6 +515,119 @@ void Graphics::PrintAlpha( int _x, int _y, std::string _s, int r, int g, int b,
|
|||
}
|
||||
}
|
||||
|
||||
bool Graphics::next_wrap(
|
||||
size_t* start,
|
||||
size_t* len,
|
||||
const char* str,
|
||||
const int maxwidth
|
||||
) {
|
||||
/* This function is UTF-8 aware. But start/len still are bytes. */
|
||||
size_t idx = 0;
|
||||
size_t lenfromlastspace = 0;
|
||||
size_t lastspace = 0;
|
||||
int linewidth = 0;
|
||||
*len = 0;
|
||||
|
||||
if (str[idx] == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* FIXME: This only checks one byte, not multiple! */
|
||||
if ((str[idx] & 0xC0) == 0x80)
|
||||
{
|
||||
/* Skip continuation byte. */
|
||||
goto next;
|
||||
}
|
||||
|
||||
linewidth += bfontlen(str[idx]);
|
||||
|
||||
switch (str[idx])
|
||||
{
|
||||
case ' ':
|
||||
lenfromlastspace = idx;
|
||||
lastspace = *start;
|
||||
break;
|
||||
case '\n':
|
||||
*start += 1;
|
||||
VVV_fallthrough;
|
||||
case '\0':
|
||||
return true;
|
||||
}
|
||||
|
||||
if (linewidth > maxwidth)
|
||||
{
|
||||
if (lenfromlastspace != 0)
|
||||
{
|
||||
*len = lenfromlastspace;
|
||||
*start = lastspace + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
next:
|
||||
idx += 1;
|
||||
*start += 1;
|
||||
*len += 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool Graphics::next_wrap_s(
|
||||
char buffer[],
|
||||
const size_t buffer_size,
|
||||
size_t* start,
|
||||
const char* str,
|
||||
const int maxwidth
|
||||
) {
|
||||
size_t len = 0;
|
||||
const size_t prev_start = *start;
|
||||
|
||||
const bool retval = next_wrap(start, &len, &str[*start], maxwidth);
|
||||
|
||||
if (retval)
|
||||
{
|
||||
/* Like next_split_s(), don't use SDL_strlcpy() here. */
|
||||
const size_t length = VVV_min(buffer_size - 1, len);
|
||||
SDL_memcpy(buffer, &str[prev_start], length);
|
||||
buffer[length] = '\0';
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Graphics::PrintWrap(
|
||||
const int x,
|
||||
int y,
|
||||
const char* str,
|
||||
const int r,
|
||||
const int g,
|
||||
const int b,
|
||||
const bool cen,
|
||||
const int linespacing,
|
||||
const int maxwidth
|
||||
) {
|
||||
/* Screen width is 320 pixels. The shortest a char can be is 6 pixels wide.
|
||||
* 320 / 6 is 54, rounded up. 4 bytes per char. */
|
||||
char buffer[54*4 + 1];
|
||||
size_t start = 0;
|
||||
|
||||
while (next_wrap_s(buffer, sizeof(buffer), &start, str, maxwidth))
|
||||
{
|
||||
Print(x, y, buffer, r, g, b, cen);
|
||||
|
||||
if (flipmode)
|
||||
{
|
||||
y -= linespacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
y += linespacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Graphics::bigprint( int _x, int _y, std::string _s, int r, int g, int b, bool cen, int sc )
|
||||
{
|
||||
|
|
|
@ -136,6 +136,12 @@ public:
|
|||
|
||||
void PrintAlpha(int _x, int _y, std::string _s, int r, int g, int b, int a, bool cen = false);
|
||||
|
||||
bool next_wrap(size_t* start, size_t* len, const char* str, int maxwidth);
|
||||
|
||||
bool next_wrap_s(char buffer[], size_t buffer_size, size_t* start, const char* str, int maxwidth);
|
||||
|
||||
void PrintWrap(int x, int y, const char* str, int r, int g, int b, bool cen, int linespacing, int maxwidth);
|
||||
|
||||
void PrintOffAlpha(int _x, int _y, std::string _s, int r, int g, int b, int a, bool cen = false);
|
||||
|
||||
void bprint(int x, int y, std::string t, int r, int g, int b, bool cen = false);
|
||||
|
|
Loading…
Reference in a new issue