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;