1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-23 06:44:38 +01:00

Fix more string functions

This commit is contained in:
Ted John
2020-10-15 22:12:41 +01:00
parent 711ac76753
commit 157c984d4c
3 changed files with 79 additions and 66 deletions

View File

@@ -41,30 +41,34 @@ static int32_t ttf_get_string_width(std::string_view text);
*
* rct2: 0x006C23B1
*/
int32_t gfx_get_string_width_new_lined(utf8* text)
int32_t gfx_get_string_width_new_lined(std::string_view text)
{
utf8* ch = text;
utf8* firstCh = text;
utf8* nextCh;
utf8 backup;
int32_t codepoint;
thread_local std::string buffer;
buffer.clear();
int32_t maxWidth = 0;
while ((codepoint = utf8_get_next(ch, const_cast<const utf8**>(&nextCh))) != 0)
std::optional<int32_t> maxWidth;
FmtString fmt(text);
for (const auto& token : fmt)
{
if (codepoint == FORMAT_NEWLINE || codepoint == FORMAT_NEWLINE_SMALLER)
if (token.kind == FORMAT_NEWLINE || token.kind == FORMAT_NEWLINE_SMALLER)
{
backup = *nextCh;
*nextCh = 0;
maxWidth = std::max(maxWidth, gfx_get_string_width(firstCh));
*nextCh = backup;
firstCh = nextCh;
auto width = gfx_get_string_width(buffer);
if (!maxWidth || maxWidth > width)
{
maxWidth = width;
}
buffer.clear();
}
else
{
buffer.append(token.text);
}
ch = nextCh;
}
maxWidth = std::max(maxWidth, gfx_get_string_width(firstCh));
return maxWidth;
if (!maxWidth)
{
maxWidth = gfx_get_string_width(buffer);
}
return *maxWidth;
}
/**
@@ -87,65 +91,62 @@ int32_t gfx_get_string_width(std::string_view text)
*/
int32_t gfx_clip_string(utf8* text, int32_t width)
{
int32_t clippedWidth;
if (width < 6)
{
*text = 0;
return 0;
}
clippedWidth = gfx_get_string_width(text);
// If width of the full string is less than allowed width then we don't need to clip
auto clippedWidth = gfx_get_string_width(text);
if (clippedWidth <= width)
{
return clippedWidth;
}
utf8 backup[4];
utf8* ch = text;
utf8* nextCh = text;
utf8* clipCh = text;
int32_t codepoint;
while ((codepoint = utf8_get_next(ch, const_cast<const utf8**>(&nextCh))) != 0)
// Append each character 1 by 1 with an ellipsis on the end until width is exceeded
thread_local std::string buffer;
buffer.clear();
size_t bestLength = 0;
int32_t bestWidth = 0;
FmtString fmt(text);
for (const auto& token : fmt)
{
if (utf8_is_format_code(codepoint))
CodepointView codepoints(token.text);
for (auto codepoint : codepoints)
{
ch = nextCh;
ch += utf8_get_format_code_arg_length(codepoint);
continue;
}
// Add the ellipsis before checking the width
buffer.append("...");
for (int32_t i = 0; i < 4; i++)
{
backup[i] = nextCh[i];
};
for (int32_t i = 0; i < 3; i++)
{
nextCh[i] = '.';
}
nextCh[3] = 0;
int32_t queryWidth = gfx_get_string_width(text);
if (queryWidth < width)
{
clipCh = nextCh;
clippedWidth = queryWidth;
}
else
{
for (int32_t i = 0; i < 3; i++)
auto currentWidth = gfx_get_string_width(text);
if (currentWidth < width)
{
clipCh[i] = '.';
}
clipCh[3] = 0;
return clippedWidth;
}
bestLength = buffer.size();
bestWidth = currentWidth;
for (int32_t i = 0; i < 4; i++)
{
nextCh[i] = backup[i];
};
ch = nextCh;
// Trim the ellipsis
buffer.resize(bestLength - 3);
}
else
{
// Width exceeded, rollback to best length and put ellipsis back
buffer.resize(bestLength);
for (auto i = static_cast<int32_t>(bestLength) - 1; i >= 0 && i >= bestLength - 3; i--)
{
buffer[bestLength - i] = '.';
}
// Copy buffer back to input text buffer
std::strcpy(text, buffer.c_str());
return bestWidth;
}
char cb[8]{};
utf8_write_codepoint(cb, codepoint);
buffer.append(cb);
}
}
return gfx_get_string_width(text);
}
@@ -182,7 +183,9 @@ int32_t gfx_wrap_string(utf8* text, int32_t width, int32_t* outNumLines, int32_t
CodepointView codepoints(token.text);
for (auto codepoint : codepoints)
{
buffer.push_back(codepoint);
char cb[8]{};
utf8_write_codepoint(cb, codepoint);
buffer.append(cb);
auto lineWidth = gfx_get_string_width(&buffer[currentLineIndex]);
if (lineWidth <= width || splitIndex == NULL_INDEX)

View File

@@ -758,7 +758,7 @@ void gfx_draw_string_with_y_offsets(
int32_t gfx_wrap_string(char* buffer, int32_t width, int32_t* num_lines, int32_t* font_height);
int32_t gfx_get_string_width(std::string_view text);
int32_t gfx_get_string_width_new_lined(char* buffer);
int32_t gfx_get_string_width_new_lined(std::string_view text);
int32_t string_get_height_raw(char* buffer);
int32_t gfx_clip_string(char* buffer, int32_t width);
void shorten_path(utf8* buffer, size_t bufferSize, const utf8* path, int32_t availableWidth);

View File

@@ -79,7 +79,11 @@ namespace OpenRCT2
return;
}
if (str[i] == '{' && i + 1 < str.size() && str[i + 1] != '{')
if (str[i] == '\n' || str[i] == '\r')
{
i++;
}
else if (str[i] == '{' && i + 1 < str.size() && str[i + 1] != '{')
{
// Move to end brace
auto startIndex = i;
@@ -127,7 +131,7 @@ namespace OpenRCT2
do
{
i++;
} while (i < str.size() && str[i] != '{');
} while (i < str.size() && str[i] != '{' && str[i] != '\n' && str[i] != '\r');
}
current = CreateToken(i - index);
}
@@ -150,6 +154,10 @@ namespace OpenRCT2
auto kind = format_get_code(sztoken.substr(1, len - 2));
return token(kind, sztoken);
}
else if (sztoken == "\n" || sztoken == "\r")
{
return token(FORMAT_NEWLINE, sztoken);
}
return token(0, sztoken);
}
@@ -566,6 +574,8 @@ namespace OpenRCT2
bool CanFormatToken(FormatToken t)
{
if (t == FORMAT_PUSH16 || t == FORMAT_POP16)
return false;
return t == FORMAT_COMMA1DP16 || (t >= FORMAT_ARGUMENT_CODE_START && t <= FORMAT_ARGUMENT_CODE_END);
}
@@ -656,7 +666,7 @@ namespace OpenRCT2
}
argIndex++;
}
else
else if (token.kind != FORMAT_PUSH16 && token.kind != FORMAT_POP16)
{
ss << token.text;
}