[TextServer] Implement locale and context sensitive case conversion functions.

This commit is contained in:
bruvzg 2022-01-17 10:54:45 +02:00
parent 5d238468ea
commit e02a097280
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
11 changed files with 151 additions and 9 deletions

View File

@ -21,8 +21,8 @@
<argument index="1" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <argument index="1" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description> <description>
Creates new buffer for complex text layout, with the given [code]direction[/code] and [code]orientation[/code]. To free the resulting buffer, use [method free_rid] method. Creates new buffer for complex text layout, with the given [code]direction[/code] and [code]orientation[/code]. To free the resulting buffer, use [method free_rid] method.
[b]Note:[/b] Direction is ignored if server does not support [code]FEATURE_BIDI_LAYOUT[/code] feature. [b]Note:[/b] Direction is ignored if server does not support [constant FEATURE_BIDI_LAYOUT] feature (supported by [TextServerAdvanced]).
[b]Note:[/b] Orientation is ignored if server does not support [code]FEATURE_VERTICAL_LAYOUT[/code] feature. [b]Note:[/b] Orientation is ignored if server does not support [constant FEATURE_VERTICAL_LAYOUT] feature (supported by [TextServerAdvanced]).
</description> </description>
</method> </method>
<method name="draw_hex_code_box" qualifiers="const"> <method name="draw_hex_code_box" qualifiers="const">
@ -1263,7 +1263,7 @@
<argument index="1" name="direction" type="int" enum="TextServer.Direction" default="0" /> <argument index="1" name="direction" type="int" enum="TextServer.Direction" default="0" />
<description> <description>
Sets desired text direction. If set to [code]TEXT_DIRECTION_AUTO[/code], direction will be detected based on the buffer contents and current locale. Sets desired text direction. If set to [code]TEXT_DIRECTION_AUTO[/code], direction will be detected based on the buffer contents and current locale.
[b]Note:[/b] Direction is ignored if server does not support [code]FEATURE_BIDI_LAYOUT[/code] feature. [b]Note:[/b] Direction is ignored if server does not support [constant FEATURE_BIDI_LAYOUT] feature (supported by [TextServerAdvanced]).
</description> </description>
</method> </method>
<method name="shaped_text_set_orientation"> <method name="shaped_text_set_orientation">
@ -1272,7 +1272,7 @@
<argument index="1" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <argument index="1" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description> <description>
Sets desired text orientation. Sets desired text orientation.
[b]Note:[/b] Orientation is ignored if server does not support [code]FEATURE_VERTICAL_LAYOUT[/code] feature. [b]Note:[/b] Orientation is ignored if server does not support [constant FEATURE_VERTICAL_LAYOUT] feature (supported by [TextServerAdvanced]).
</description> </description>
</method> </method>
<method name="shaped_text_set_preserve_control"> <method name="shaped_text_set_preserve_control">
@ -1323,6 +1323,26 @@
Aligns shaped text to the given tab-stops. Aligns shaped text to the given tab-stops.
</description> </description>
</method> </method>
<method name="string_to_lower" qualifiers="const">
<return type="String" />
<argument index="0" name="string" type="String" />
<argument index="1" name="language" type="String" default="&quot;&quot;" />
<description>
Returns the string converted to lowercase.
[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.
</description>
</method>
<method name="string_to_upper" qualifiers="const">
<return type="String" />
<argument index="0" name="string" type="String" />
<argument index="1" name="language" type="String" default="&quot;&quot;" />
<description>
Returns the string converted to uppercase.
[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.
</description>
</method>
<method name="strip_diacritics" qualifiers="const"> <method name="strip_diacritics" qualifiers="const">
<return type="String" /> <return type="String" />
<argument index="0" name="string" type="String" /> <argument index="0" name="string" type="String" />
@ -1468,7 +1488,10 @@
<constant name="FEATURE_FONT_VARIABLE" value="64" enum="Feature"> <constant name="FEATURE_FONT_VARIABLE" value="64" enum="Feature">
TextServer supports variable fonts. TextServer supports variable fonts.
</constant> </constant>
<constant name="FEATURE_USE_SUPPORT_DATA" value="128" enum="Feature"> <constant name="FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION" value="128" enum="Feature">
TextServer supports locale dependent and context sensitive case conversion.
</constant>
<constant name="FEATURE_USE_SUPPORT_DATA" value="256" enum="Feature">
TextServer require external data file for some features. TextServer require external data file for some features.
</constant> </constant>
<constant name="CONTOUR_CURVE_TAG_ON" value="1" enum="ContourPointTag"> <constant name="CONTOUR_CURVE_TAG_ON" value="1" enum="ContourPointTag">

View File

@ -1348,6 +1348,22 @@
Updates justification opportunities (spaces, kashidas, etc.). Updates justification opportunities (spaces, kashidas, etc.).
</description> </description>
</method> </method>
<method name="_string_to_lower" qualifiers="virtual const">
<return type="String" />
<argument index="0" name="string" type="String" />
<argument index="1" name="language" type="String" />
<description>
Returns the string converted to lowercase. Casing is locale dependent and context sensitive. The result may be longer or shorter than the original.
</description>
</method>
<method name="_string_to_upper" qualifiers="virtual const">
<return type="String" />
<argument index="0" name="string" type="String" />
<argument index="1" name="language" type="String" />
<description>
Returns the string converted to uppercase. Casing is locale dependent and context sensitive. The result may be longer or shorter than the original.
</description>
</method>
<method name="_tag_to_name" qualifiers="virtual const"> <method name="_tag_to_name" qualifiers="virtual const">
<return type="String" /> <return type="String" />
<argument index="0" name="tag" type="int" /> <argument index="0" name="tag" type="int" />

View File

@ -322,7 +322,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
/*************************************************************************/ /*************************************************************************/
String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite"; String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite";
uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE; uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE | FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION;
bool TextServerAdvanced::has_feature(Feature p_feature) const { bool TextServerAdvanced::has_feature(Feature p_feature) const {
return (interface_features & p_feature) == p_feature; return (interface_features & p_feature) == p_feature;
@ -5229,6 +5229,40 @@ String TextServerAdvanced::strip_diacritics(const String &p_string) const {
return result; return result;
} }
String TextServerAdvanced::string_to_upper(const String &p_string, const String &p_language) const {
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
Char16String upper;
UErrorCode err = U_ZERO_ERROR;
int32_t len = u_strToUpper(nullptr, 0, utf16.ptr(), -1, p_language.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_strToUpper(upper.ptrw(), len, utf16.ptr(), -1, p_language.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);
}
String TextServerAdvanced::string_to_lower(const String &p_string, const String &p_language) const {
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
Char16String lower;
UErrorCode err = U_ZERO_ERROR;
int32_t len = u_strToLower(nullptr, 0, utf16.ptr(), -1, p_language.ascii().get_data(), &err);
ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err));
lower.resize(len);
err = U_ZERO_ERROR;
u_strToLower(lower.ptrw(), len, utf16.ptr(), -1, p_language.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(lower.ptr(), len);
}
TextServerAdvanced::TextServerAdvanced() { TextServerAdvanced::TextServerAdvanced() {
_insert_num_systems_lang(); _insert_num_systems_lang();
_insert_feature_sets(); _insert_feature_sets();

View File

@ -527,6 +527,9 @@ public:
virtual String strip_diacritics(const String &p_string) const override; virtual String strip_diacritics(const String &p_string) const override;
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;
TextServerAdvanced(); TextServerAdvanced();
~TextServerAdvanced(); ~TextServerAdvanced();
}; };

View File

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/string/print_string.h" #include "core/string/print_string.h"
#include "core/string/ucaps.h"
#include "modules/modules_enabled.gen.h" // For freetype, msdfgen. #include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
@ -3356,6 +3357,34 @@ float TextServerFallback::shaped_text_get_underline_thickness(RID p_shaped) cons
return sd->uthk; return sd->uthk;
} }
String TextServerFallback::string_to_upper(const String &p_string, const String &p_language) const {
String upper = p_string;
for (int i = 0; i < upper.size(); i++) {
const char32_t s = upper[i];
const char32_t t = _find_upper(s);
if (s != t) { // avoid copy on write
upper[i] = t;
}
}
return upper;
}
String TextServerFallback::string_to_lower(const String &p_string, const String &p_language) const {
String lower = p_string;
for (int i = 0; i < lower.size(); i++) {
const char32_t s = lower[i];
const char32_t t = _find_lower(s);
if (s != t) { // avoid copy on write
lower[i] = t;
}
}
return lower;
}
TextServerFallback::TextServerFallback() { TextServerFallback::TextServerFallback() {
_insert_feature_sets(); _insert_feature_sets();
}; };

View File

@ -430,6 +430,9 @@ public:
virtual float shaped_text_get_underline_position(RID p_shaped) const override; virtual float shaped_text_get_underline_position(RID p_shaped) const override;
virtual float shaped_text_get_underline_thickness(RID p_shaped) const override; virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
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;
TextServerFallback(); TextServerFallback();
~TextServerFallback(); ~TextServerFallback();
}; };

View File

@ -83,6 +83,7 @@ void Label::_shape() {
int width = (get_size().width - style->get_minimum_size().width); int width = (get_size().width - style->get_minimum_size().width);
if (dirty) { if (dirty) {
String lang = (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale();
TS->shaped_text_clear(text_rid); TS->shaped_text_clear(text_rid);
if (text_direction == Control::TEXT_DIRECTION_INHERITED) { if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
TS->shaped_text_set_direction(text_rid, is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); TS->shaped_text_set_direction(text_rid, is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
@ -92,11 +93,11 @@ void Label::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font")); const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size")); int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null()); ERR_FAIL_COND(font.is_null());
String text = (uppercase) ? xl_text.to_upper() : xl_text; String text = (uppercase) ? TS->string_to_upper(xl_text, lang) : xl_text;
if (visible_chars >= 0 && visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) { if (visible_chars >= 0 && visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
text = text.substr(0, visible_chars); text = text.substr(0, visible_chars);
} }
TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, lang);
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text)); TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text));
dirty = false; dirty = false;
lines_dirty = true; lines_dirty = true;

View File

@ -271,6 +271,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_format_number, "string", "language"); GDVIRTUAL_BIND(_format_number, "string", "language");
GDVIRTUAL_BIND(_parse_number, "string", "language"); GDVIRTUAL_BIND(_parse_number, "string", "language");
GDVIRTUAL_BIND(_percent_sign, "language"); GDVIRTUAL_BIND(_percent_sign, "language");
GDVIRTUAL_BIND(_string_to_upper, "string", "language");
GDVIRTUAL_BIND(_string_to_lower, "string", "language");
} }
bool TextServerExtension::has_feature(Feature p_feature) const { bool TextServerExtension::has_feature(Feature p_feature) const {
@ -1365,6 +1368,22 @@ String TextServerExtension::percent_sign(const String &p_language) const {
return TextServer::percent_sign(p_language); return TextServer::percent_sign(p_language);
} }
String TextServerExtension::string_to_upper(const String &p_string, const String &p_language) const {
String ret;
if (GDVIRTUAL_CALL(_string_to_upper, 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)) {
return ret;
}
return p_string;
}
TextServerExtension::TextServerExtension() { TextServerExtension::TextServerExtension() {
//NOP //NOP
} }

View File

@ -449,6 +449,11 @@ public:
GDVIRTUAL2RC(String, _parse_number, const String &, const String &); GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
GDVIRTUAL1RC(String, _percent_sign, const String &); GDVIRTUAL1RC(String, _percent_sign, const String &);
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;
GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &);
GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &);
TextServerExtension(); TextServerExtension();
~TextServerExtension(); ~TextServerExtension();
}; };

View File

@ -422,6 +422,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics); ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
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(""));
/* Direction */ /* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO); BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR); BIND_ENUM_CONSTANT(DIRECTION_LTR);
@ -480,6 +483,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_BREAK_ITERATORS); BIND_ENUM_CONSTANT(FEATURE_BREAK_ITERATORS);
BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM); BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM);
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE); BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION);
BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA); BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA);
/* FT Contour Point Types */ /* FT Contour Point Types */

View File

@ -109,7 +109,8 @@ public:
FEATURE_BREAK_ITERATORS = 1 << 4, FEATURE_BREAK_ITERATORS = 1 << 4,
FEATURE_FONT_SYSTEM = 1 << 5, FEATURE_FONT_SYSTEM = 1 << 5,
FEATURE_FONT_VARIABLE = 1 << 6, FEATURE_FONT_VARIABLE = 1 << 6,
FEATURE_USE_SUPPORT_DATA = 1 << 7 FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 7,
FEATURE_USE_SUPPORT_DATA = 1 << 8,
}; };
enum ContourPointTag { enum ContourPointTag {
@ -457,6 +458,10 @@ public:
virtual String strip_diacritics(const String &p_string) const; virtual String strip_diacritics(const String &p_string) const;
// 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;
TextServer(); TextServer();
~TextServer(); ~TextServer();
}; };