Merge pull request #65073 from bruvzg/trim_spaces
[TextServer] Add support for trimming edge spaces on line break.
This commit is contained in:
commit
89f0886425
9 changed files with 124 additions and 21 deletions
|
@ -1624,6 +1624,10 @@
|
||||||
Break the line between any unconnected graphemes.
|
Break the line between any unconnected graphemes.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BREAK_ADAPTIVE" value="8" enum="LineBreakFlag" is_bitfield="true">
|
<constant name="BREAK_ADAPTIVE" value="8" enum="LineBreakFlag" is_bitfield="true">
|
||||||
|
Should be used only in conjunction with [constant BREAK_WORD_BOUND], break the line between any unconnected graphemes, if it's impossible to break it between the words.
|
||||||
|
</constant>
|
||||||
|
<constant name="BREAK_TRIM_EDGE_SPACES" value="16" enum="LineBreakFlag" is_bitfield="true">
|
||||||
|
Remove edge spaces from the broken line segments.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="VC_CHARS_BEFORE_SHAPING" value="0" enum="VisibleCharactersBehavior">
|
<constant name="VC_CHARS_BEFORE_SHAPING" value="0" enum="VisibleCharactersBehavior">
|
||||||
Trims text before the shaping. e.g, increasing [member Label.visible_characters] or [member RichTextLabel.visible_characters] value is visually identical to typing the text.
|
Trims text before the shaping. e.g, increasing [member Label.visible_characters] or [member RichTextLabel.visible_characters] value is visually identical to typing the text.
|
||||||
|
|
|
@ -486,8 +486,9 @@ void Label3D::_shape() {
|
||||||
case TextServer::AUTOWRAP_OFF:
|
case TextServer::AUTOWRAP_OFF:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
|
autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
|
||||||
|
|
||||||
|
PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
|
||||||
float max_line_w = 0.0;
|
float max_line_w = 0.0;
|
||||||
for (int i = 0; i < line_breaks.size(); i = i + 2) {
|
for (int i = 0; i < line_breaks.size(); i = i + 2) {
|
||||||
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
|
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
|
||||||
|
|
|
@ -544,7 +544,7 @@ void Button::_bind_methods() {
|
||||||
|
|
||||||
Button::Button(const String &p_text) {
|
Button::Button(const String &p_text) {
|
||||||
text_buf.instantiate();
|
text_buf.instantiate();
|
||||||
text_buf->set_break_flags(TextServer::BREAK_MANDATORY);
|
text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_TRIM_EDGE_SPACES);
|
||||||
set_mouse_filter(MOUSE_FILTER_STOP);
|
set_mouse_filter(MOUSE_FILTER_STOP);
|
||||||
|
|
||||||
set_text(p_text);
|
set_text(p_text);
|
||||||
|
|
|
@ -45,7 +45,7 @@ void ItemList::_shape(int p_idx) {
|
||||||
}
|
}
|
||||||
item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
|
item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
|
||||||
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
||||||
item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
|
item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
|
||||||
} else {
|
} else {
|
||||||
item.text_buf->set_break_flags(TextServer::BREAK_NONE);
|
item.text_buf->set_break_flags(TextServer::BREAK_NONE);
|
||||||
}
|
}
|
||||||
|
@ -532,7 +532,7 @@ void ItemList::set_max_text_lines(int p_lines) {
|
||||||
max_text_lines = p_lines;
|
max_text_lines = p_lines;
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
||||||
items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
|
items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
|
||||||
items.write[i].text_buf->set_max_lines_visible(p_lines);
|
items.write[i].text_buf->set_max_lines_visible(p_lines);
|
||||||
} else {
|
} else {
|
||||||
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
|
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
|
||||||
|
@ -582,7 +582,7 @@ void ItemList::set_icon_mode(IconMode p_mode) {
|
||||||
icon_mode = p_mode;
|
icon_mode = p_mode;
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
||||||
items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
|
items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
|
||||||
} else {
|
} else {
|
||||||
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
|
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,8 +143,9 @@ void Label::_shape() {
|
||||||
case TextServer::AUTOWRAP_OFF:
|
case TextServer::AUTOWRAP_OFF:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
|
autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
|
||||||
|
|
||||||
|
PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
|
||||||
for (int i = 0; i < line_breaks.size(); i = i + 2) {
|
for (int i = 0; i < line_breaks.size(); i = i + 2) {
|
||||||
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
|
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
|
||||||
lines_rid.push_back(line);
|
lines_rid.push_back(line);
|
||||||
|
|
|
@ -453,6 +453,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
|
||||||
case TextServer::AUTOWRAP_OFF:
|
case TextServer::AUTOWRAP_OFF:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
|
||||||
|
|
||||||
// Clear cache.
|
// Clear cache.
|
||||||
l.text_buf->clear();
|
l.text_buf->clear();
|
||||||
|
|
|
@ -77,7 +77,7 @@ void TextParagraph::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_break_flags", "flags"), &TextParagraph::set_break_flags);
|
ClassDB::bind_method(D_METHOD("set_break_flags", "flags"), &TextParagraph::set_break_flags);
|
||||||
ClassDB::bind_method(D_METHOD("get_break_flags"), &TextParagraph::get_break_flags);
|
ClassDB::bind_method(D_METHOD("get_break_flags"), &TextParagraph::get_break_flags);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "break_flags", PROPERTY_HINT_FLAGS, "Mandatory,Word Bound,Grapheme Bound,Adaptive"), "set_break_flags", "get_break_flags");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "break_flags", PROPERTY_HINT_FLAGS, "Mandatory,Word Bound,Grapheme Bound,Adaptive,Trim Spaces"), "set_break_flags", "get_break_flags");
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_justification_flags", "flags"), &TextParagraph::set_justification_flags);
|
ClassDB::bind_method(D_METHOD("set_justification_flags", "flags"), &TextParagraph::set_justification_flags);
|
||||||
ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextParagraph::get_justification_flags);
|
ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextParagraph::get_justification_flags);
|
||||||
|
|
|
@ -498,6 +498,7 @@ void TextServer::_bind_methods() {
|
||||||
BIND_BITFIELD_FLAG(BREAK_WORD_BOUND);
|
BIND_BITFIELD_FLAG(BREAK_WORD_BOUND);
|
||||||
BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
|
BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
|
||||||
BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
|
BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
|
||||||
|
BIND_BITFIELD_FLAG(BREAK_TRIM_EDGE_SPACES);
|
||||||
|
|
||||||
/* VisibleCharactersBehavior */
|
/* VisibleCharactersBehavior */
|
||||||
BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
|
BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
|
||||||
|
@ -680,6 +681,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
||||||
|
|
||||||
real_t width = 0.f;
|
real_t width = 0.f;
|
||||||
int line_start = MAX(p_start, range.x);
|
int line_start = MAX(p_start, range.x);
|
||||||
|
int prev_safe_break = 0;
|
||||||
int last_safe_break = -1;
|
int last_safe_break = -1;
|
||||||
int chunk = 0;
|
int chunk = 0;
|
||||||
|
|
||||||
|
@ -688,13 +690,29 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
||||||
|
|
||||||
for (int i = 0; i < l_size; i++) {
|
for (int i = 0; i < l_size; i++) {
|
||||||
if (l_gl[i].start < p_start) {
|
if (l_gl[i].start < p_start) {
|
||||||
|
prev_safe_break = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (l_gl[i].count > 0) {
|
if (l_gl[i].count > 0) {
|
||||||
if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
|
if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
|
||||||
lines.push_back(line_start);
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
||||||
lines.push_back(l_gl[last_safe_break].end);
|
int start_pos = prev_safe_break;
|
||||||
|
int end_pos = last_safe_break;
|
||||||
|
|
||||||
|
while ((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);
|
||||||
|
} else {
|
||||||
|
lines.push_back(line_start);
|
||||||
|
lines.push_back(l_gl[last_safe_break].end);
|
||||||
|
}
|
||||||
line_start = 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;
|
i = last_safe_break;
|
||||||
last_safe_break = -1;
|
last_safe_break = -1;
|
||||||
width = 0;
|
width = 0;
|
||||||
|
@ -709,9 +727,24 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
||||||
}
|
}
|
||||||
if (p_break_flags.has_flag(BREAK_MANDATORY)) {
|
if (p_break_flags.has_flag(BREAK_MANDATORY)) {
|
||||||
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
|
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
|
||||||
lines.push_back(line_start);
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
||||||
lines.push_back(l_gl[i].end);
|
int start_pos = prev_safe_break;
|
||||||
|
int end_pos = i;
|
||||||
|
|
||||||
|
while ((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);
|
||||||
|
} else {
|
||||||
|
lines.push_back(line_start);
|
||||||
|
lines.push_back(l_gl[i].end);
|
||||||
|
}
|
||||||
line_start = l_gl[i].end;
|
line_start = l_gl[i].end;
|
||||||
|
prev_safe_break = i + 1;
|
||||||
last_safe_break = -1;
|
last_safe_break = -1;
|
||||||
width = 0;
|
width = 0;
|
||||||
chunk = 0;
|
chunk = 0;
|
||||||
|
@ -734,9 +767,23 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l_size > 0) {
|
if (l_size > 0) {
|
||||||
if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
|
if (lines.size() == 0 || (lines[lines.size() - 1] < range.y && prev_safe_break < l_size)) {
|
||||||
lines.push_back(line_start);
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
||||||
lines.push_back(range.y);
|
int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1;
|
||||||
|
int end_pos = l_size - 1;
|
||||||
|
|
||||||
|
while ((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);
|
||||||
|
} else {
|
||||||
|
lines.push_back(line_start);
|
||||||
|
lines.push_back(range.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lines.push_back(0);
|
lines.push_back(0);
|
||||||
|
@ -754,6 +801,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
||||||
|
|
||||||
double width = 0.f;
|
double width = 0.f;
|
||||||
int line_start = MAX(p_start, range.x);
|
int line_start = MAX(p_start, range.x);
|
||||||
|
int prev_safe_break = 0;
|
||||||
int last_safe_break = -1;
|
int last_safe_break = -1;
|
||||||
int word_count = 0;
|
int word_count = 0;
|
||||||
|
|
||||||
|
@ -762,13 +810,30 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
||||||
|
|
||||||
for (int i = 0; i < l_size; i++) {
|
for (int i = 0; i < l_size; i++) {
|
||||||
if (l_gl[i].start < p_start) {
|
if (l_gl[i].start < p_start) {
|
||||||
|
prev_safe_break = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (l_gl[i].count > 0) {
|
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 ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
|
||||||
lines.push_back(line_start);
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
||||||
lines.push_back(l_gl[last_safe_break].end);
|
int start_pos = prev_safe_break;
|
||||||
|
int end_pos = last_safe_break;
|
||||||
|
|
||||||
|
while ((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;
|
||||||
|
}
|
||||||
|
//printf("%s", vformat("BRK TRIM(W): %d..%d -> %d..%d\n", line_start, l_gl[last_safe_break].end, l_gl[start_pos].start, l_gl[end_pos].end).utf8().get_data());
|
||||||
|
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[last_safe_break].end);
|
||||||
|
}
|
||||||
line_start = 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;
|
i = last_safe_break;
|
||||||
last_safe_break = -1;
|
last_safe_break = -1;
|
||||||
width = 0;
|
width = 0;
|
||||||
|
@ -777,9 +842,25 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
||||||
}
|
}
|
||||||
if (p_break_flags.has_flag(BREAK_MANDATORY)) {
|
if (p_break_flags.has_flag(BREAK_MANDATORY)) {
|
||||||
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
|
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
|
||||||
lines.push_back(line_start);
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
||||||
lines.push_back(l_gl[i].end);
|
int start_pos = prev_safe_break;
|
||||||
|
int end_pos = i;
|
||||||
|
|
||||||
|
while ((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);
|
||||||
|
//printf("%s", vformat("BRK TRIM(M): %d..%d -> %d..%d\n", line_start, l_gl[i].end, l_gl[start_pos].start, l_gl[end_pos].end).utf8().get_data());
|
||||||
|
} else {
|
||||||
|
lines.push_back(line_start);
|
||||||
|
lines.push_back(l_gl[i].end);
|
||||||
|
}
|
||||||
line_start = l_gl[i].end;
|
line_start = l_gl[i].end;
|
||||||
|
prev_safe_break = i + 1;
|
||||||
last_safe_break = -1;
|
last_safe_break = -1;
|
||||||
width = 0;
|
width = 0;
|
||||||
continue;
|
continue;
|
||||||
|
@ -802,9 +883,23 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l_size > 0) {
|
if (l_size > 0) {
|
||||||
if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
|
if (lines.size() == 0 || (lines[lines.size() - 1] < range.y && prev_safe_break < l_size)) {
|
||||||
lines.push_back(line_start);
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
||||||
lines.push_back(range.y);
|
int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1;
|
||||||
|
int end_pos = l_size - 1;
|
||||||
|
|
||||||
|
while ((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);
|
||||||
|
} else {
|
||||||
|
lines.push_back(line_start);
|
||||||
|
lines.push_back(range.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lines.push_back(0);
|
lines.push_back(0);
|
||||||
|
|
|
@ -103,6 +103,7 @@ public:
|
||||||
BREAK_WORD_BOUND = 1 << 1,
|
BREAK_WORD_BOUND = 1 << 1,
|
||||||
BREAK_GRAPHEME_BOUND = 1 << 2,
|
BREAK_GRAPHEME_BOUND = 1 << 2,
|
||||||
BREAK_ADAPTIVE = 1 << 3,
|
BREAK_ADAPTIVE = 1 << 3,
|
||||||
|
BREAK_TRIM_EDGE_SPACES = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OverrunBehavior {
|
enum OverrunBehavior {
|
||||||
|
|
Loading…
Reference in a new issue