diff options
Diffstat (limited to 'servers/text_server.cpp')
| -rw-r--r-- | servers/text_server.cpp | 105 |
1 files changed, 98 insertions, 7 deletions
diff --git a/servers/text_server.cpp b/servers/text_server.cpp index b67a698615..562f2df411 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -29,6 +29,8 @@ /**************************************************************************/ #include "servers/text_server.h" +#include "text_server.compat.inc" + #include "core/variant/typed_array.h" #include "servers/rendering_server.h" @@ -234,6 +236,9 @@ void TextServer::_bind_methods() { 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_disable_embedded_bitmaps", "font_rid", "disable_embedded_bitmaps"), &TextServer::font_set_disable_embedded_bitmaps); + ClassDB::bind_method(D_METHOD("font_get_disable_embedded_bitmaps", "font_rid"), &TextServer::font_get_disable_embedded_bitmaps); + 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); @@ -432,7 +437,7 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range); ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND)); ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND)); - ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION)); + ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags", "skip_grapheme_flags"), &TextServer::shaped_text_get_word_breaks, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION), DEFVAL(GRAPHEME_IS_VIRTUAL)); ClassDB::bind_method(D_METHOD("shaped_text_get_trim_pos", "shaped"), &TextServer::shaped_text_get_trim_pos); ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_pos", "shaped"), &TextServer::shaped_text_get_ellipsis_pos); @@ -443,6 +448,8 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shaped_text_get_objects", "shaped"), &TextServer::shaped_text_get_objects); ClassDB::bind_method(D_METHOD("shaped_text_get_object_rect", "shaped", "key"), &TextServer::shaped_text_get_object_rect); + ClassDB::bind_method(D_METHOD("shaped_text_get_object_range", "shaped", "key"), &TextServer::shaped_text_get_object_range); + ClassDB::bind_method(D_METHOD("shaped_text_get_object_glyph", "shaped", "key"), &TextServer::shaped_text_get_object_glyph); ClassDB::bind_method(D_METHOD("shaped_text_get_size", "shaped"), &TextServer::shaped_text_get_size); ClassDB::bind_method(D_METHOD("shaped_text_get_ascent", "shaped"), &TextServer::shaped_text_get_ascent); @@ -486,6 +493,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); @@ -535,6 +543,7 @@ void TextServer::_bind_methods() { BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND); BIND_BITFIELD_FLAG(BREAK_ADAPTIVE); BIND_BITFIELD_FLAG(BREAK_TRIM_EDGE_SPACES); + BIND_BITFIELD_FLAG(BREAK_TRIM_INDENT); /* VisibleCharactersBehavior */ BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING); @@ -636,6 +645,48 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(FIXED_SIZE_SCALE_ENABLED); } +_FORCE_INLINE_ int32_t ot_tag_from_string(const char *p_str, int p_len) { + char tag[4]; + uint32_t i; + + if (!p_str || !p_len || !*p_str) { + return OT_TAG(0, 0, 0, 0); + } + + if (p_len < 0 || p_len > 4) { + p_len = 4; + } + for (i = 0; i < (uint32_t)p_len && p_str[i]; i++) { + tag[i] = p_str[i]; + } + + for (; i < 4; i++) { + tag[i] = ' '; + } + + return OT_TAG(tag[0], tag[1], tag[2], tag[3]); +} + +int64_t TextServer::name_to_tag(const String &p_name) const { + // No readable name, use tag string. + return ot_tag_from_string(p_name.replace("custom_", "").ascii().get_data(), -1); +} + +_FORCE_INLINE_ void ot_tag_to_string(int32_t p_tag, char *p_buf) { + p_buf[0] = (char)(uint8_t)(p_tag >> 24); + p_buf[1] = (char)(uint8_t)(p_tag >> 16); + p_buf[2] = (char)(uint8_t)(p_tag >> 8); + p_buf[3] = (char)(uint8_t)(p_tag >> 0); +} + +String TextServer::tag_to_name(int64_t p_tag) const { + // No readable name, use tag string. + char name[5]; + memset(name, 0, 5); + ot_tag_to_string(p_tag, name); + return String("custom_") + String(name); +} + Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const { int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)); int sp = MAX(0, w - 1); @@ -750,13 +801,28 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped int l_size = shaped_text_get_glyph_count(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); + double indent = 0.0; + if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) { + for (int i = 0; i < l_size; i++) { + if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + indent += l_gl[i].advance * l_gl[i].repeat; + } else { + break; + } + } + } + for (int i = 0; i < l_size; i++) { + double l_width = p_width[chunk]; + if (l_width > indent) { + l_width -= indent; + } 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)) { + if ((l_width > 0) && (width + l_gl[i].advance > l_width) && (last_safe_break >= 0)) { if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = prev_safe_break; int end_pos = last_safe_break; @@ -891,13 +957,25 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do int l_size = shaped_text_get_glyph_count(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); + double indent = 0.0; + if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) { + for (int i = 0; i < l_size; i++) { + if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + indent += l_gl[i].advance * l_gl[i].repeat; + } else { + break; + } + } + } + + double l_width = p_width; 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)) { + if ((l_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > l_width) && (last_safe_break >= 0)) { if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = prev_safe_break; int end_pos = last_safe_break; @@ -910,6 +988,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do if (last_end <= l_gl[start_pos].start) { lines.push_back(l_gl[start_pos].start); lines.push_back(l_gl[end_pos].end); + if (p_width > indent) { + l_width = p_width - indent; + } last_end = l_gl[end_pos].end; } trim_next = true; @@ -917,6 +998,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do if (last_end <= line_start) { lines.push_back(line_start); lines.push_back(l_gl[last_safe_break].end); + if (p_width > indent) { + l_width = p_width - indent; + } last_end = l_gl[last_safe_break].end; } } @@ -943,12 +1027,18 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do if (last_end <= l_gl[start_pos].start) { lines.push_back(l_gl[start_pos].start); lines.push_back(l_gl[end_pos].end); + if (p_width > indent) { + l_width = p_width - indent; + } last_end = l_gl[end_pos].end; } } else { if (last_end <= line_start) { lines.push_back(line_start); lines.push_back(l_gl[i].end); + if (p_width > indent) { + l_width = p_width - indent; + } last_end = l_gl[i].end; } } @@ -1006,7 +1096,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, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const { +PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags, BitField<TextServer::GraphemeFlag> p_skip_grapheme_flags) const { PackedInt32Array words; const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped); @@ -1019,10 +1109,11 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, Bi for (int i = 0; i < l_size; i++) { if (l_gl[i].count > 0) { - if ((l_gl[i].flags & p_grapheme_flags) != 0) { - if (word_start != l_gl[i].start) { + if ((l_gl[i].flags & p_grapheme_flags) != 0 && (l_gl[i].flags & p_skip_grapheme_flags) == 0) { + int next = (i == 0) ? l_gl[i].start : l_gl[i - 1].end; + if (word_start < next) { words.push_back(word_start); - words.push_back(l_gl[i].start); + words.push_back(next); } word_start = l_gl[i].end; } |
