mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2026-01-30 01:48:15 +03:00
Move wordwrapping functions and len to Font.cpp/font:: namespace
The following functions were moved directly: - next_wrap - next_wrap_s - string_wordwrap - string_wordwrap_balanced - string_unwordwrap These ones will probably still need get a flags argument, except for string_unwordwrap (since they need to know what font we're talking about. The implementation of graphics.len has also been moved to Font.cpp, but graphics.len still exists for now and is deprecated.
This commit is contained in:
committed by
Misa Elizabeth Kai
parent
1d8494db8d
commit
159c70dade
@@ -354,92 +354,6 @@ void Graphics::PrintAlpha( int x, int y, const std::string& text, int r, int g,
|
||||
font::print(PR_ALPHA(a), x, y, text, r, g, 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 += font::get_advance(&font::temp_bfont, str[idx]);
|
||||
|
||||
switch (str[idx])
|
||||
{
|
||||
case ' ':
|
||||
if (loc::get_langmeta()->autowordwrap)
|
||||
{
|
||||
lenfromlastspace = idx;
|
||||
lastspace = *start;
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
case '|':
|
||||
*start += 1;
|
||||
SDL_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 = SDL_min(buffer_size - 1, len);
|
||||
SDL_memcpy(buffer, &str[prev_start], length);
|
||||
buffer[length] = '\0';
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Graphics::PrintWrap(
|
||||
const int x,
|
||||
int y,
|
||||
@@ -481,142 +395,8 @@ void Graphics::bigbprint(int x, int y, const std::string& text, int r, int g, in
|
||||
|
||||
int Graphics::len(const std::string& t)
|
||||
{
|
||||
int text_len = 0;
|
||||
std::string::const_iterator iter = t.begin();
|
||||
while (iter != t.end()) {
|
||||
int cur = utf8::unchecked::next(iter);
|
||||
text_len += font::get_advance(&font::temp_bfont, cur);
|
||||
}
|
||||
return text_len;
|
||||
}
|
||||
|
||||
std::string Graphics::string_wordwrap(const std::string& s, int maxwidth, short *lines /*= NULL*/)
|
||||
{
|
||||
// Return a string wordwrapped to a maximum limit by adding newlines.
|
||||
// CJK will need to have autowordwrap disabled and have manually inserted newlines.
|
||||
|
||||
if (lines != NULL)
|
||||
{
|
||||
*lines = 1;
|
||||
}
|
||||
|
||||
const char* orig = s.c_str();
|
||||
|
||||
std::string result;
|
||||
size_t start = 0;
|
||||
bool first = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t len = 0;
|
||||
const char* part = &orig[start];
|
||||
|
||||
const bool retval = next_wrap(&start, &len, part, maxwidth);
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back('\n');
|
||||
|
||||
if (lines != NULL)
|
||||
{
|
||||
(*lines)++;
|
||||
}
|
||||
}
|
||||
result.append(part, len);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Graphics::string_wordwrap_balanced(const std::string& s, int maxwidth)
|
||||
{
|
||||
// Return a string wordwrapped to a limit of maxwidth by adding newlines.
|
||||
// Try to fill the lines as far as possible, and return result where lines are most filled.
|
||||
// Goal is to have all lines in textboxes be about as long and to avoid wrapping just one word to a new line.
|
||||
// CJK will need to have autowordwrap disabled and have manually inserted newlines.
|
||||
|
||||
if (!loc::get_langmeta()->autowordwrap)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
short lines;
|
||||
string_wordwrap(s, maxwidth, &lines);
|
||||
|
||||
int bestwidth = maxwidth;
|
||||
if (lines > 1)
|
||||
{
|
||||
for (int curlimit = maxwidth; curlimit > 1; curlimit -= 8)
|
||||
{
|
||||
short try_lines;
|
||||
string_wordwrap(s, curlimit, &try_lines);
|
||||
|
||||
if (try_lines > lines)
|
||||
{
|
||||
bestwidth = curlimit + 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string_wordwrap(s, bestwidth);
|
||||
}
|
||||
|
||||
std::string Graphics::string_unwordwrap(const std::string& s)
|
||||
{
|
||||
/* Takes a string wordwrapped by newlines, and turns it into a single line, undoing the wrapping.
|
||||
* Also trims any leading/trailing whitespace and collapses multiple spaces into one (to undo manual centering)
|
||||
* Only applied to English, so langmeta.autowordwrap isn't used here (it'd break looking up strings) */
|
||||
|
||||
std::string result;
|
||||
std::back_insert_iterator<std::string> inserter = std::back_inserter(result);
|
||||
std::string::const_iterator iter = s.begin();
|
||||
bool latest_was_space = true; // last character was a space (or the beginning, don't want leading whitespace)
|
||||
int consecutive_newlines = 0; // number of newlines currently encountered in a row (multiple newlines should stay!)
|
||||
while (iter != s.end())
|
||||
{
|
||||
uint32_t ch = utf8::unchecked::next(iter);
|
||||
|
||||
if (ch == '\n')
|
||||
{
|
||||
if (consecutive_newlines == 0)
|
||||
{
|
||||
ch = ' ';
|
||||
}
|
||||
else if (consecutive_newlines == 1)
|
||||
{
|
||||
// The last character was already a newline, so change it back from the space we thought it should have become.
|
||||
result[result.size()-1] = '\n';
|
||||
}
|
||||
consecutive_newlines++;
|
||||
}
|
||||
else
|
||||
{
|
||||
consecutive_newlines = 0;
|
||||
}
|
||||
|
||||
if (ch != ' ' || !latest_was_space)
|
||||
{
|
||||
utf8::unchecked::append(ch, inserter);
|
||||
}
|
||||
|
||||
latest_was_space = (ch == ' ' || ch == '\n');
|
||||
}
|
||||
|
||||
// We could have one trailing space
|
||||
if (!result.empty() && result[result.size()-1] == ' ')
|
||||
{
|
||||
result.erase(result.end()-1);
|
||||
}
|
||||
|
||||
return result;
|
||||
// DEPRECATED
|
||||
return font::len(0, t);
|
||||
}
|
||||
|
||||
void Graphics::bprint( int x, int y, const std::string& text, int r, int g, int b, bool cen /*= false*/ ) {
|
||||
@@ -2058,12 +1838,12 @@ void Graphics::drawtrophytext(void)
|
||||
short lines;
|
||||
if (top_text != NULL)
|
||||
{
|
||||
string_wordwrap(top_text, 304, &lines);
|
||||
font::string_wordwrap(top_text, 304, &lines);
|
||||
PrintWrap(-1, 11-(lines-1)*5, top_text, temp, temp2, temp3, true);
|
||||
}
|
||||
if (bottom_text != NULL)
|
||||
{
|
||||
string_wordwrap(bottom_text, 304, &lines);
|
||||
font::string_wordwrap(bottom_text, 304, &lines);
|
||||
PrintWrap(-1, 221-(lines-1)*5, bottom_text, temp, temp2, temp3, true);
|
||||
}
|
||||
}
|
||||
@@ -3337,7 +3117,7 @@ int Graphics::textboxwrap(int pad)
|
||||
vlog_error("textboxwrap() has no first line!");
|
||||
return 16;
|
||||
}
|
||||
std::string wrapped = string_wordwrap_balanced(textboxes[m].lines[0], 36*8 - pad*8);
|
||||
std::string wrapped = font::string_wordwrap_balanced(textboxes[m].lines[0], 36*8 - pad*8);
|
||||
textboxes[m].lines.clear();
|
||||
|
||||
size_t startline = 0;
|
||||
|
||||
Reference in New Issue
Block a user