* Clip the text in buffer to width, add ellipsis and return the new width of the clipped string * * rct2: 0x006C2460 * buffer (esi) * width (edi) */
| 72 | * width (edi) |
| 73 | */ |
| 74 | int32_t clipString(utf8* text, int32_t width, FontStyle fontStyle) |
| 75 | { |
| 76 | if (width < 6) |
| 77 | { |
| 78 | *text = 0; |
| 79 | return 0; |
| 80 | } |
| 81 | |
| 82 | // If width of the full string is less than allowed width then we don't need to clip |
| 83 | auto clippedWidth = getStringWidth(text, fontStyle); |
| 84 | if (clippedWidth <= width) |
| 85 | { |
| 86 | return clippedWidth; |
| 87 | } |
| 88 | |
| 89 | // Append each character 1 by 1 with an ellipsis on the end until width is exceeded |
| 90 | thread_local std::string buffer; |
| 91 | buffer.clear(); |
| 92 | |
| 93 | size_t bestLength = 0; |
| 94 | int32_t bestWidth = 0; |
| 95 | |
| 96 | FmtString fmt(text); |
| 97 | for (const auto& token : fmt) |
| 98 | { |
| 99 | CodepointView codepoints(token.text); |
| 100 | for (auto codepoint : codepoints) |
| 101 | { |
| 102 | // Add the ellipsis before checking the width |
| 103 | buffer.append("..."); |
| 104 | |
| 105 | auto currentWidth = getStringWidth(buffer, fontStyle); |
| 106 | if (currentWidth < width) |
| 107 | { |
| 108 | bestLength = buffer.size(); |
| 109 | bestWidth = currentWidth; |
| 110 | |
| 111 | // Trim the ellipsis |
| 112 | buffer.resize(bestLength - 3); |
| 113 | } |
| 114 | else |
| 115 | { |
| 116 | // Width exceeded, rollback to best length and put ellipsis back |
| 117 | buffer.resize(bestLength); |
| 118 | for (auto i = static_cast<int32_t>(bestLength) - 1; i >= 0 && i >= static_cast<int32_t>(bestLength) - 3; |
| 119 | i--) |
| 120 | { |
| 121 | buffer[i] = '.'; |
| 122 | } |
| 123 | |
| 124 | // Copy buffer back to input text buffer |
| 125 | std::strcpy(text, buffer.c_str()); |
| 126 | return bestWidth; |
| 127 | } |
| 128 | |
| 129 | char cb[8]{}; |
| 130 | UTF8WriteCodepoint(cb, codepoint); |
| 131 | buffer.append(cb); |
no test coverage detected