From 3c1bdcd20140fcd3d374818b9defb80c12c39163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Rodrigues=20Guimar=C3=A3es?= Date: Sun, 19 Apr 2020 10:51:01 -0300 Subject: [PATCH] Create a compile-time table for converting color codepoints to utf8 (#11349) For this to be possible, the function to convert a codepoint to urf8 was moved to the header and made constexpr. Now it's not necessary to store a std::string just to serve as a buffer for holding this string. All the computation is done at compile time. --- src/openrct2/localisation/Language.h | 31 +++++++++++++++++++++++++++- src/openrct2/localisation/UTF8.cpp | 30 --------------------------- src/openrct2/world/Banner.cpp | 30 ++++++++++++++++++++++----- src/openrct2/world/Banner.h | 1 - 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/src/openrct2/localisation/Language.h b/src/openrct2/localisation/Language.h index 7bdc8385cd..11ab1e9969 100644 --- a/src/openrct2/localisation/Language.h +++ b/src/openrct2/localisation/Language.h @@ -95,7 +95,6 @@ const char* language_get_string(rct_string_id id); bool language_open(int32_t id); uint32_t utf8_get_next(const utf8* char_ptr, const utf8** nextchar_ptr); -utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint); int32_t utf8_insert_codepoint(utf8* dst, uint32_t codepoint); bool utf8_is_codepoint_start(const utf8* text); void utf8_remove_format_codes(utf8* text, bool allowcolours); @@ -109,4 +108,34 @@ void language_free_object_string(rct_string_id stringId); rct_string_id language_get_object_override_string_id(const char* identifier, uint8_t index); rct_string_id language_allocate_object_string(const std::string& target); +constexpr utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint) +{ + if (codepoint <= 0x7F) + { + dst[0] = (utf8)codepoint; + return dst + 1; + } + else if (codepoint <= 0x7FF) + { + dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F); + dst[1] = 0x80 | (codepoint & 0x3F); + return dst + 2; + } + else if (codepoint <= 0xFFFF) + { + dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F); + dst[1] = 0x80 | ((codepoint >> 6) & 0x3F); + dst[2] = 0x80 | (codepoint & 0x3F); + return dst + 3; + } + else + { + dst[0] = 0xF0 | ((codepoint >> 18) & 0x07); + dst[1] = 0x80 | ((codepoint >> 12) & 0x3F); + dst[2] = 0x80 | ((codepoint >> 6) & 0x3F); + dst[3] = 0x80 | (codepoint & 0x3F); + return dst + 4; + } +} + #endif diff --git a/src/openrct2/localisation/UTF8.cpp b/src/openrct2/localisation/UTF8.cpp index a1b3f8b61d..4049e6a372 100644 --- a/src/openrct2/localisation/UTF8.cpp +++ b/src/openrct2/localisation/UTF8.cpp @@ -49,36 +49,6 @@ uint32_t utf8_get_next(const utf8* char_ptr, const utf8** nextchar_ptr) return result; } -utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint) -{ - if (codepoint <= 0x7F) - { - dst[0] = (utf8)codepoint; - return dst + 1; - } - else if (codepoint <= 0x7FF) - { - dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F); - dst[1] = 0x80 | (codepoint & 0x3F); - return dst + 2; - } - else if (codepoint <= 0xFFFF) - { - dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F); - dst[1] = 0x80 | ((codepoint >> 6) & 0x3F); - dst[2] = 0x80 | (codepoint & 0x3F); - return dst + 3; - } - else - { - dst[0] = 0xF0 | ((codepoint >> 18) & 0x07); - dst[1] = 0x80 | ((codepoint >> 12) & 0x3F); - dst[2] = 0x80 | ((codepoint >> 6) & 0x3F); - dst[3] = 0x80 | (codepoint & 0x3F); - return dst + 4; - } -} - /** * Inserts the given codepoint at the given address, shifting all characters after along. * @returns the size of the inserted codepoint. diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 0ba4476616..b495e55b96 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -33,6 +33,30 @@ static Banner _banners[MAX_BANNERS]; +namespace +{ + template struct CodePointToUtf8 + { + constexpr CodePointToUtf8() + { + for (uint32_t i = TFrom; i <= TTo; ++i) + { + utf8_write_codepoint(m_colors[i - TFrom], i); + } + } + + constexpr auto operator()(uint8_t colourId) const + { + return m_colors[colourId]; + } + + using Utf8Colour = utf8[5]; // A 32bit codepoint uses at most 4 bytes in utf8 + Utf8Colour m_colors[TTo - TFrom + 1]{}; + }; +} // namespace + +static constexpr CodePointToUtf8 colourToUtf8; + std::string Banner::GetText() const { uint8_t args[32]{}; @@ -47,14 +71,10 @@ size_t Banner::FormatTextTo(void* argsV, bool addColour) const int numColourArgs = 0; if (addColour) { - textColourUtf8.resize(5); // one code point in utf8 takes at most 4 bytes - auto terminator = utf8_write_codepoint(textColourUtf8.data(), FORMAT_COLOUR_CODE_START + text_colour); - *terminator = '\0'; - set_format_arg_on(args, numColourArgs, rct_string_id, STR_STRING_STRINGID); numColourArgs += sizeof(rct_string_id); - set_format_arg_on(args, numColourArgs, const char*, textColourUtf8.data()); + set_format_arg_on(args, numColourArgs, const char*, colourToUtf8(text_colour)); numColourArgs += sizeof(const char*); args += numColourArgs; diff --git a/src/openrct2/world/Banner.h b/src/openrct2/world/Banner.h index af53d3371b..644b038086 100644 --- a/src/openrct2/world/Banner.h +++ b/src/openrct2/world/Banner.h @@ -34,7 +34,6 @@ struct Banner uint8_t colour{}; ride_id_t ride_index{}; uint8_t text_colour{}; - mutable std::string textColourUtf8; TileCoordsXY position; bool IsNull() const