summaryrefslogtreecommitdiff
path: root/servers/text_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/text_server.cpp')
-rw-r--r--servers/text_server.cpp511
1 files changed, 363 insertions, 148 deletions
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index fe5ade88a1..027109b67d 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -1,34 +1,35 @@
-/*************************************************************************/
-/* text_server.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* text_server.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "servers/text_server.h"
+#include "core/variant/typed_array.h"
#include "servers/rendering_server.h"
TextServerManager *TextServerManager::singleton = nullptr;
@@ -103,8 +104,8 @@ Ref<TextServer> TextServerManager::find_interface(const String &p_name) const {
return interfaces[idx];
}
-Array TextServerManager::get_interfaces() const {
- Array ret;
+TypedArray<Dictionary> TextServerManager::get_interfaces() const {
+ TypedArray<Dictionary> ret;
for (int i = 0; i < interfaces.size(); i++) {
Dictionary iface_info;
@@ -222,8 +223,14 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name);
ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name);
- ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
- ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
+ ClassDB::bind_method(D_METHOD("font_set_weight", "font_rid", "weight"), &TextServer::font_set_weight);
+ ClassDB::bind_method(D_METHOD("font_get_weight", "font_rid"), &TextServer::font_get_weight);
+
+ ClassDB::bind_method(D_METHOD("font_set_stretch", "font_rid", "weight"), &TextServer::font_set_stretch);
+ ClassDB::bind_method(D_METHOD("font_get_stretch", "font_rid"), &TextServer::font_get_stretch);
+
+ ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing);
+ ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing);
ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps);
ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps);
@@ -240,6 +247,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_fixed_size", "font_rid", "fixed_size"), &TextServer::font_set_fixed_size);
ClassDB::bind_method(D_METHOD("font_get_fixed_size", "font_rid"), &TextServer::font_get_fixed_size);
+ ClassDB::bind_method(D_METHOD("font_set_allow_system_fallback", "font_rid", "allow_system_fallback"), &TextServer::font_set_allow_system_fallback);
+ ClassDB::bind_method(D_METHOD("font_is_allow_system_fallback", "font_rid"), &TextServer::font_is_allow_system_fallback);
+
ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font_rid", "force_autohinter"), &TextServer::font_set_force_autohinter);
ClassDB::bind_method(D_METHOD("font_is_force_autohinter", "font_rid"), &TextServer::font_is_force_autohinter);
@@ -280,9 +290,6 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_scale", "font_rid", "size", "scale"), &TextServer::font_set_scale);
ClassDB::bind_method(D_METHOD("font_get_scale", "font_rid", "size"), &TextServer::font_get_scale);
- ClassDB::bind_method(D_METHOD("font_set_spacing", "font_rid", "size", "spacing", "value"), &TextServer::font_set_spacing);
- ClassDB::bind_method(D_METHOD("font_get_spacing", "font_rid", "size", "spacing"), &TextServer::font_get_spacing);
-
ClassDB::bind_method(D_METHOD("font_get_texture_count", "font_rid", "size"), &TextServer::font_get_texture_count);
ClassDB::bind_method(D_METHOD("font_clear_textures", "font_rid", "size"), &TextServer::font_clear_textures);
ClassDB::bind_method(D_METHOD("font_remove_texture", "font_rid", "size", "texture_index"), &TextServer::font_remove_texture);
@@ -383,9 +390,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_preserve_control", "shaped", "enabled"), &TextServer::shaped_text_set_preserve_control);
ClassDB::bind_method(D_METHOD("shaped_text_get_preserve_control", "shaped"), &TextServer::shaped_text_get_preserve_control);
+ ClassDB::bind_method(D_METHOD("shaped_text_set_spacing", "shaped", "spacing", "value"), &TextServer::shaped_text_set_spacing);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_spacing", "shaped", "spacing"), &TextServer::shaped_text_get_spacing);
+
ClassDB::bind_method(D_METHOD("shaped_text_add_string", "shaped", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextServer::shaped_text_add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
+ ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length", "baseline"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align", "baseline"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("shaped_get_span_count", "shaped"), &TextServer::shaped_get_span_count);
ClassDB::bind_method(D_METHOD("shaped_get_span_meta", "shaped", "index"), &TextServer::shaped_get_span_meta);
@@ -444,31 +454,48 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("percent_sign", "language"), &TextServer::percent_sign, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language", "chars_per_line"), &TextServer::string_get_word_breaks, DEFVAL(""), DEFVAL(0));
+
+ ClassDB::bind_method(D_METHOD("is_confusable", "string", "dict"), &TextServer::is_confusable);
+ ClassDB::bind_method(D_METHOD("spoof_check", "string"), &TextServer::spoof_check);
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
+ ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier);
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("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text);
+ /* Font AA */
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE);
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY);
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD);
+
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_MAX);
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
BIND_ENUM_CONSTANT(DIRECTION_RTL);
+ BIND_ENUM_CONSTANT(DIRECTION_INHERITED);
/* Orientation */
BIND_ENUM_CONSTANT(ORIENTATION_HORIZONTAL);
BIND_ENUM_CONSTANT(ORIENTATION_VERTICAL);
/* JustificationFlag */
- BIND_ENUM_CONSTANT(JUSTIFICATION_NONE);
- BIND_ENUM_CONSTANT(JUSTIFICATION_KASHIDA);
- BIND_ENUM_CONSTANT(JUSTIFICATION_WORD_BOUND);
- BIND_ENUM_CONSTANT(JUSTIFICATION_TRIM_EDGE_SPACES);
- BIND_ENUM_CONSTANT(JUSTIFICATION_AFTER_LAST_TAB);
- BIND_ENUM_CONSTANT(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_NONE);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_KASHIDA);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_WORD_BOUND);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_TRIM_EDGE_SPACES);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_AFTER_LAST_TAB);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
/* AutowrapMode */
BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
@@ -477,11 +504,12 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
/* LineBreakFlag */
- BIND_ENUM_CONSTANT(BREAK_NONE);
- BIND_ENUM_CONSTANT(BREAK_MANDATORY);
- BIND_ENUM_CONSTANT(BREAK_WORD_BOUND);
- BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND);
- BIND_ENUM_CONSTANT(BREAK_WORD_BOUND_ADAPTIVE);
+ BIND_BITFIELD_FLAG(BREAK_NONE);
+ BIND_BITFIELD_FLAG(BREAK_MANDATORY);
+ BIND_BITFIELD_FLAG(BREAK_WORD_BOUND);
+ BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
+ BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
+ BIND_BITFIELD_FLAG(BREAK_TRIM_EDGE_SPACES);
/* VisibleCharactersBehavior */
BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
@@ -498,25 +526,26 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS);
/* TextOverrunFlag */
- BIND_ENUM_CONSTANT(OVERRUN_NO_TRIM);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY);
- BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_JUSTIFICATION_AWARE);
+ BIND_BITFIELD_FLAG(OVERRUN_NO_TRIM);
+ BIND_BITFIELD_FLAG(OVERRUN_TRIM);
+ BIND_BITFIELD_FLAG(OVERRUN_TRIM_WORD_ONLY);
+ BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS);
+ BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS);
+ BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE);
/* GraphemeFlag */
- BIND_ENUM_CONSTANT(GRAPHEME_IS_VALID);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_SPACE);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_HARD);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_SOFT);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_TAB);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_ELONGATION);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_PUNCTUATION);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_UNDERSCORE);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_RTL);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_VIRTUAL);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SPACE);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_HARD);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_SOFT);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_TAB);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_ELONGATION);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_PUNCTUATION);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_UNDERSCORE);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL);
/* Hinting */
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -545,6 +574,8 @@ void TextServer::_bind_methods() {
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_UNICODE_IDENTIFIERS);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_SECURITY);
/* FT Contour Point Types */
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
@@ -556,11 +587,12 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACING_SPACE);
BIND_ENUM_CONSTANT(SPACING_TOP);
BIND_ENUM_CONSTANT(SPACING_BOTTOM);
+ BIND_ENUM_CONSTANT(SPACING_MAX);
/* Font Style */
- BIND_ENUM_CONSTANT(FONT_BOLD);
- BIND_ENUM_CONSTANT(FONT_ITALIC);
- BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH);
+ BIND_BITFIELD_FLAG(FONT_BOLD);
+ BIND_BITFIELD_FLAG(FONT_ITALIC);
+ BIND_BITFIELD_FLAG(FONT_FIXED_WIDTH);
/* Structured text parser */
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
@@ -568,7 +600,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_GDSCRIPT);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
}
@@ -650,7 +682,7 @@ void TextServer::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Ve
}
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array lines;
ERR_FAIL_COND_V(p_width.is_empty(), lines);
@@ -660,24 +692,44 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
real_t width = 0.f;
int line_start = MAX(p_start, range.x);
+ int prev_safe_break = 0;
int last_safe_break = -1;
+ int word_count = 0;
int chunk = 0;
+ bool trim_next = false;
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
+ prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
- lines.push_back(line_start);
- lines.push_back(l_gl[last_safe_break].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = last_safe_break;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ trim_next = true;
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
+ }
line_start = l_gl[last_safe_break].end;
+ prev_safe_break = last_safe_break + 1;
i = last_safe_break;
last_safe_break = -1;
width = 0;
+ word_count = 0;
chunk++;
if (chunk >= p_width.size()) {
chunk = 0;
@@ -687,11 +739,26 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
}
continue;
}
- if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
+ if (p_break_flags.has_flag(BREAK_MANDATORY)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(line_start);
- lines.push_back(l_gl[i].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = i;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ trim_next = false;
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
+ }
line_start = l_gl[i].end;
+ prev_safe_break = i + 1;
last_safe_break = -1;
width = 0;
chunk = 0;
@@ -701,12 +768,13 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
continue;
}
}
- if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
+ if (p_break_flags.has_flag(BREAK_WORD_BOUND)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
+ word_count++;
}
}
- if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND) && word_count == 0) {
last_safe_break = i;
}
}
@@ -714,8 +782,17 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
}
if (l_size > 0) {
- if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
- lines.push_back(line_start);
+ if (lines.size() == 0 || (lines[lines.size() - 1] < range.y && prev_safe_break < l_size)) {
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1;
+ int end_pos = l_size - 1;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ } else {
+ lines.push_back(line_start);
+ }
lines.push_back(range.y);
}
} else {
@@ -726,7 +803,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
@@ -734,47 +811,80 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
double width = 0.f;
int line_start = MAX(p_start, range.x);
+ int prev_safe_break = 0;
int last_safe_break = -1;
int word_count = 0;
+ bool trim_next = false;
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
+ prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
- lines.push_back(line_start);
- lines.push_back(l_gl[last_safe_break].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = last_safe_break;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ trim_next = true;
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
+ }
line_start = l_gl[last_safe_break].end;
+ prev_safe_break = last_safe_break + 1;
i = last_safe_break;
last_safe_break = -1;
width = 0;
word_count = 0;
continue;
}
- if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
+ if (p_break_flags.has_flag(BREAK_MANDATORY)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(line_start);
- lines.push_back(l_gl[i].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = i;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ trim_next = false;
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
+ }
line_start = l_gl[i].end;
+ prev_safe_break = i + 1;
last_safe_break = -1;
width = 0;
continue;
}
}
- if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
+ if (p_break_flags.has_flag(BREAK_WORD_BOUND)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
word_count++;
}
+ if (p_break_flags.has_flag(BREAK_ADAPTIVE) && word_count == 0) {
+ last_safe_break = i;
+ }
}
- if (((p_break_flags & BREAK_WORD_BOUND_ADAPTIVE) == BREAK_WORD_BOUND_ADAPTIVE) && word_count == 0) {
- last_safe_break = i;
- }
- if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) {
last_safe_break = i;
}
}
@@ -782,8 +892,17 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
}
if (l_size > 0) {
- if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
- lines.push_back(line_start);
+ if (lines.size() == 0 || (lines[lines.size() - 1] < range.y && prev_safe_break < l_size)) {
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1;
+ int end_pos = l_size - 1;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ } else {
+ lines.push_back(line_start);
+ }
lines.push_back(range.y);
}
} else {
@@ -794,7 +913,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
+PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const {
PackedInt32Array words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
@@ -847,6 +966,11 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
if (glyphs[i].count > 0) {
// Caret before grapheme (top / left).
if (p_position == glyphs[i].start && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
+ real_t advance = 0.f;
+ for (int j = 0; j < glyphs[i].count; j++) {
+ advance += glyphs[i + j].advance * glyphs[i + j].repeat;
+ }
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
if (glyphs[i].start == range.x) {
@@ -858,15 +982,11 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
caret.t_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.x += advance;
+ cr.size.x = -char_adv;
} else {
caret.t_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.size.x = char_adv;
}
} else {
if (glyphs[i].start == range.x) {
@@ -878,21 +998,22 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
caret.t_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.y += advance;
+ cr.size.y = -char_adv;
} else {
caret.t_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.size.y = char_adv;
}
}
caret.t_caret = cr;
}
// Caret after grapheme (bottom / right).
if (p_position == glyphs[i].end && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
+ real_t advance = 0.f;
+ for (int j = 0; j < glyphs[i].count; j++) {
+ advance += glyphs[i + j].advance * glyphs[i + j].repeat;
+ }
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
if (glyphs[i].end == range.y) {
@@ -905,15 +1026,11 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
caret.l_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.x += advance;
+ cr.size.x = -char_adv;
} else {
caret.l_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.size.x = char_adv;
}
} else {
cr.size.y = 1.0f;
@@ -927,15 +1044,12 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
caret.l_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.y += advance;
+ cr.size.y = -char_adv;
} else {
caret.l_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.x += advance;
+ cr.size.y = char_adv;
}
}
caret.l_caret = cr;
@@ -949,22 +1063,24 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
- cr.size.x = 1.0f;
cr.size.y = height * 2;
cr.position.y = -ascent;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
cr.position.x = off + char_adv * (glyphs[i].end - p_position);
+ cr.size.x = -char_adv;
} else {
cr.position.x = off + char_adv * (p_position - glyphs[i].start);
+ cr.size.x = char_adv;
}
} else {
- cr.size.y = 1.0f;
cr.size.x = height * 2;
cr.position.x = -ascent;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
cr.position.y = off + char_adv * (glyphs[i].end - p_position);
+ cr.size.y = -char_adv;
} else {
cr.position.y = off + char_adv * (p_position - glyphs[i].start);
+ cr.size.y = char_adv;
}
}
caret.t_caret = cr;
@@ -1577,22 +1693,22 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
-Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- Array ret;
+TypedArray<Vector3i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector3i> ret;
switch (p_parser_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
if (prev != i) {
- ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_FILE: {
@@ -1600,14 +1716,14 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
if (prev != i) {
- ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_EMAIL: {
@@ -1616,19 +1732,19 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '@') && local) { // Add full "local" as single context.
local = false;
- ret.push_back(Vector2i(prev, i));
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
- } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
+ } else if (!local && (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
if (prev != i) {
- ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_LIST: {
@@ -1637,25 +1753,104 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
int prev = 0;
for (int i = 0; i < tags.size(); i++) {
if (prev != i) {
- ret.push_back(Vector2i(prev, prev + tags[i].length()));
+ ret.push_back(Vector3i(prev, prev + tags[i].length(), TextServer::DIRECTION_INHERITED));
}
- ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
+ ret.push_back(Vector3i(prev + tags[i].length(), prev + tags[i].length() + 1, TextServer::DIRECTION_INHERITED));
prev = prev + tags[i].length() + 1;
}
}
} break;
+ case STRUCTURED_TEXT_GDSCRIPT: {
+ bool in_string_literal = false;
+ bool in_string_literal_single = false;
+ bool in_id = false;
+
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ char32_t c = p_text[i];
+ if (in_string_literal) {
+ if (c == '\\') {
+ i++;
+ continue; // Skip escaped chars.
+ } else if (c == '\"') {
+ // String literal end, push string and ".
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal = false;
+ }
+ } else if (in_string_literal_single) {
+ if (c == '\\') {
+ i++;
+ continue; // Skip escaped chars.
+ } else if (c == '\'') {
+ // String literal end, push string and '.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal_single = false;
+ }
+ } else if (in_id) {
+ if (!is_unicode_identifier_continue(c)) {
+ // End of id, push id.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i;
+ in_id = false;
+ }
+ } else if (is_unicode_identifier_start(c)) {
+ // Start of new id, push prev element.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i;
+ in_id = true;
+ } else if (c == '\"') {
+ // String literal start, push prev element and ".
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal = true;
+ } else if (c == '\'') {
+ // String literal start, push prev element and '.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal_single = true;
+ } else if (c == '#') {
+ // Start of comment, push prev element and #, skip the rest of the text.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ break;
+ }
+ }
+ if (prev < p_text.length()) {
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
+ }
+ } break;
case STRUCTURED_TEXT_CUSTOM:
- case STRUCTURED_TEXT_NONE:
case STRUCTURED_TEXT_DEFAULT:
default: {
- ret.push_back(Vector2i(0, p_text.length()));
+ ret.push_back(Vector3i(0, p_text.length(), TextServer::DIRECTION_INHERITED));
}
}
return ret;
}
-Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
- Array ret;
+TypedArray<Dictionary> TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
+ TypedArray<Dictionary> ret;
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
int gl_size = shaped_text_get_glyph_count(p_shaped);
@@ -1679,7 +1874,7 @@ Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
return ret;
}
-Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
+TypedArray<Dictionary> TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
Array ret;
const Glyph *glyphs = shaped_text_sort_logical(p_shaped);
@@ -1704,8 +1899,8 @@ Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
return ret;
}
-Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
- Array ret;
+TypedArray<Dictionary> TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
+ TypedArray<Dictionary> ret;
const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
int gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
@@ -1729,6 +1924,26 @@ Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped)
return ret;
}
+bool TextServer::is_valid_identifier(const String &p_string) const {
+ const char32_t *str = p_string.ptr();
+ int len = p_string.length();
+
+ if (len == 0) {
+ return false; // Empty string.
+ }
+
+ if (!is_unicode_identifier_start(str[0])) {
+ return false;
+ }
+
+ for (int i = 1; i < len; i++) {
+ if (!is_unicode_identifier_continue(str[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
TextServer::TextServer() {
_init_diacritics_map();
}