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.cpp150
1 files changed, 125 insertions, 25 deletions
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 2bf0837d88..660247839c 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#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,8 @@ 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_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);
@@ -457,6 +458,17 @@ void TextServer::_bind_methods() {
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);
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
@@ -486,6 +498,7 @@ void TextServer::_bind_methods() {
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);
@@ -668,24 +681,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;
@@ -697,9 +730,24 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
}
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;
@@ -712,9 +760,10 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
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_GRAPHEME_BOUND)) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND) && word_count == 0) {
last_safe_break = i;
}
}
@@ -722,8 +771,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 {
@@ -742,21 +800,39 @@ 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;
@@ -765,9 +841,24 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
}
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;
@@ -790,8 +881,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 {
@@ -1585,8 +1685,8 @@ 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<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector2i> ret;
switch (p_parser_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
@@ -1627,7 +1727,7 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector2i(i, i + 1));
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));
}
@@ -1662,8 +1762,8 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
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);
@@ -1687,7 +1787,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);
@@ -1712,8 +1812,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);