From 27f6f4147bc30ce9c5124e552f004834a87ef94b Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 4 Apr 2024 10:56:49 +0300 Subject: [PATCH] [TextServer] Expose ICU title case string conversion to scripting. --- doc/classes/TextServer.xml | 10 ++++++++ doc/classes/TextServerExtension.xml | 9 +++++++ modules/text_server_adv/text_server_adv.cpp | 28 +++++++++++++++++++++ modules/text_server_adv/text_server_adv.h | 1 + modules/text_server_fb/text_server_fb.cpp | 4 +++ modules/text_server_fb/text_server_fb.h | 1 + servers/text/text_server_extension.cpp | 9 +++++++ servers/text/text_server_extension.h | 2 ++ servers/text_server.cpp | 1 + servers/text_server.h | 1 + 10 files changed, 66 insertions(+) diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index cd70316aa970..c0cd7f79e7e1 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -1736,6 +1736,16 @@ [b]Note:[/b] The result may be longer or shorter than the original. + + + + + + Returns the string converted to title case. + [b]Note:[/b] Casing is locale dependent and context sensitive if server support [constant FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION] feature (supported by [TextServerAdvanced]). + [b]Note:[/b] The result may be longer or shorter than the original. + + diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 9b7fc42ddf1e..06a0daece6d7 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -1913,6 +1913,15 @@ Returns the string converted to lowercase. + + + + + + [b]Optional.[/b] + Returns the string converted to title case. + + diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index f5174d7d46a5..cc1ceec41e69 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -6976,6 +6976,34 @@ String TextServerAdvanced::_string_to_lower(const String &p_string, const String return String::utf16(lower.ptr(), len); } +String TextServerAdvanced::_string_to_title(const String &p_string, const String &p_language) const { +#ifndef ICU_STATIC_DATA + if (!icu_data_loaded) { + return p_string.capitalize(); + } +#endif + + if (p_string.is_empty()) { + return p_string; + } + const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + + // Convert to UTF-16. + Char16String utf16 = p_string.utf16(); + + Vector upper; + UErrorCode err = U_ZERO_ERROR; + int32_t len = u_strToTitle(nullptr, 0, utf16.get_data(), -1, nullptr, lang.ascii().get_data(), &err); + ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err)); + upper.resize(len); + err = U_ZERO_ERROR; + u_strToTitle(upper.ptrw(), len, utf16.get_data(), -1, nullptr, lang.ascii().get_data(), &err); + ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err)); + + // Convert back to UTF-32. + return String::utf16(upper.ptr(), len); +} + PackedInt32Array TextServerAdvanced::_string_get_word_breaks(const String &p_string, const String &p_language, int64_t p_chars_per_line) const { const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; // Convert to UTF-16. diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 154fe670ebbb..160eb27528e7 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -991,6 +991,7 @@ class TextServerAdvanced : public TextServerExtension { MODBIND2RC(String, string_to_upper, const String &, const String &); MODBIND2RC(String, string_to_lower, const String &, const String &); + MODBIND2RC(String, string_to_title, const String &, const String &); MODBIND0(cleanup); diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 302bd677fe7c..1a0a4ec3564a 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -4439,6 +4439,10 @@ String TextServerFallback::_string_to_lower(const String &p_string, const String return p_string.to_lower(); } +String TextServerFallback::_string_to_title(const String &p_string, const String &p_language) const { + return p_string.capitalize(); +} + PackedInt32Array TextServerFallback::_string_get_word_breaks(const String &p_string, const String &p_language, int64_t p_chars_per_line) const { PackedInt32Array ret; diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 0db1f7318fc3..9fd5af8b5192 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -848,6 +848,7 @@ class TextServerFallback : public TextServerExtension { MODBIND2RC(String, string_to_upper, const String &, const String &); MODBIND2RC(String, string_to_lower, const String &, const String &); + MODBIND2RC(String, string_to_title, const String &, const String &); MODBIND0(cleanup); diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index eb9f1c148436..53e1d119fd2b 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -341,6 +341,7 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_string_to_upper, "string", "language"); GDVIRTUAL_BIND(_string_to_lower, "string", "language"); + GDVIRTUAL_BIND(_string_to_title, "string", "language"); GDVIRTUAL_BIND(_parse_structured_text, "parser_type", "args", "text"); @@ -1507,6 +1508,14 @@ String TextServerExtension::string_to_upper(const String &p_string, const String return p_string; } +String TextServerExtension::string_to_title(const String &p_string, const String &p_language) const { + String ret; + if (GDVIRTUAL_CALL(_string_to_title, p_string, p_language, ret)) { + return ret; + } + return p_string; +} + String TextServerExtension::string_to_lower(const String &p_string, const String &p_language) const { String ret; if (GDVIRTUAL_CALL(_string_to_lower, p_string, p_language, ret)) { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 84d68de4fa44..53d30abee423 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -566,8 +566,10 @@ class TextServerExtension : public TextServer { virtual String string_to_upper(const String &p_string, const String &p_language = "") const override; virtual String string_to_lower(const String &p_string, const String &p_language = "") const override; + virtual String string_to_title(const String &p_string, const String &p_language = "") const override; GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &); GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &); + GDVIRTUAL2RC(String, _string_to_title, const String &, const String &); TypedArray parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; GDVIRTUAL3RC(TypedArray, _parse_structured_text, StructuredTextParser, const Array &, const String &); diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 078ee2775376..fac9e32d01bf 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -491,6 +491,7 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL("")); ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL("")); + ClassDB::bind_method(D_METHOD("string_to_title", "string", "language"), &TextServer::string_to_title, DEFVAL("")); ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text); diff --git a/servers/text_server.h b/servers/text_server.h index 4a16ae64e8a7..396d7ca8e5e2 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -546,6 +546,7 @@ class TextServer : public RefCounted { // Other string operations. virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0; virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0; + virtual String string_to_title(const String &p_string, const String &p_language = "") const = 0; TypedArray parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;