|
@@ -827,7 +827,12 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
continue;
|
|
|
}
|
|
|
if (l_gl[i].count > 0) {
|
|
|
- if ((l_width > 0) && (width + l_gl[i].advance > l_width) && (last_safe_break >= 0)) {
|
|
|
+ float adv = 0.0;
|
|
|
+ for (int j = i; j < l_size && l_gl[i].end == l_gl[j].end && l_gl[i].start == l_gl[j].start; j++) {
|
|
|
+ adv += l_gl[j].advance * l_gl[j].repeat;
|
|
|
+ }
|
|
|
+ if ((l_width > 0) && (width + adv > l_width) && (last_safe_break >= 0)) {
|
|
|
+ int cur_safe_brk = last_safe_break;
|
|
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
|
|
int start_pos = prev_safe_break;
|
|
|
int end_pos = last_safe_break;
|
|
@@ -840,6 +845,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
if (last_end <= l_gl[start_pos].start) {
|
|
|
lines.push_back(l_gl[start_pos].start);
|
|
|
lines.push_back(l_gl[end_pos].end);
|
|
|
+ cur_safe_brk = end_pos;
|
|
|
last_end = l_gl[end_pos].end;
|
|
|
}
|
|
|
trim_next = true;
|
|
@@ -850,9 +856,12 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
last_end = 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;
|
|
|
+ line_start = l_gl[cur_safe_brk].end;
|
|
|
+ prev_safe_break = cur_safe_brk + 1;
|
|
|
+ while (prev_safe_break < l_size && l_gl[prev_safe_break].end == line_start) {
|
|
|
+ prev_safe_break++;
|
|
|
+ }
|
|
|
+ i = cur_safe_brk;
|
|
|
last_safe_break = -1;
|
|
|
width = 0;
|
|
|
word_count = 0;
|
|
@@ -867,6 +876,7 @@ 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) {
|
|
|
+ int cur_safe_brk = i;
|
|
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
|
|
int start_pos = prev_safe_break;
|
|
|
int end_pos = i;
|
|
@@ -880,6 +890,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
lines.push_back(l_gl[start_pos].start);
|
|
|
lines.push_back(l_gl[end_pos].end);
|
|
|
last_end = l_gl[end_pos].end;
|
|
|
+ cur_safe_brk = end_pos;
|
|
|
}
|
|
|
trim_next = false;
|
|
|
} else {
|
|
@@ -889,8 +900,11 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
last_end = l_gl[i].end;
|
|
|
}
|
|
|
}
|
|
|
- line_start = l_gl[i].end;
|
|
|
- prev_safe_break = i + 1;
|
|
|
+ line_start = l_gl[cur_safe_brk].end;
|
|
|
+ prev_safe_break = cur_safe_brk + 1;
|
|
|
+ while (prev_safe_break < l_size && l_gl[prev_safe_break].end == line_start) {
|
|
|
+ prev_safe_break++;
|
|
|
+ }
|
|
|
last_safe_break = -1;
|
|
|
width = 0;
|
|
|
chunk = 0;
|
|
@@ -905,7 +919,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
if ((l_gl[i].flags & GRAPHEME_IS_SOFT_HYPHEN) == GRAPHEME_IS_SOFT_HYPHEN) {
|
|
|
uint32_t gl = font_get_glyph_index(l_gl[i].font_rid, l_gl[i].font_size, 0x00ad, 0);
|
|
|
float w = font_get_glyph_advance(l_gl[i].font_rid, l_gl[i].font_size, gl)[(orientation == ORIENTATION_HORIZONTAL) ? 0 : 1];
|
|
|
- if (width + l_gl[i].advance + w <= p_width[chunk]) {
|
|
|
+ if (width + adv + w <= p_width[chunk]) {
|
|
|
last_safe_break = i;
|
|
|
word_count++;
|
|
|
}
|
|
@@ -919,20 +933,24 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
|
|
|
last_safe_break = i;
|
|
|
}
|
|
|
}
|
|
|
- width += l_gl[i].advance;
|
|
|
+ width += l_gl[i].advance * l_gl[i].repeat;
|
|
|
}
|
|
|
|
|
|
if (l_size > 0) {
|
|
|
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;
|
|
|
+ if (last_end <= l_gl[start_pos].start) {
|
|
|
+ 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(last_end);
|
|
|
}
|
|
|
- lines.push_back(l_gl[start_pos].start);
|
|
|
} else {
|
|
|
- lines.push_back(line_start);
|
|
|
+ lines.push_back(MAX(last_end, line_start));
|
|
|
}
|
|
|
lines.push_back(range.y);
|
|
|
}
|
|
@@ -980,7 +998,12 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
continue;
|
|
|
}
|
|
|
if (l_gl[i].count > 0) {
|
|
|
- if ((l_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > l_width) && (last_safe_break >= 0)) {
|
|
|
+ float adv = 0.0;
|
|
|
+ for (int j = i; j < l_size && l_gl[i].end == l_gl[j].end && l_gl[i].start == l_gl[j].start; j++) {
|
|
|
+ adv += l_gl[j].advance * l_gl[j].repeat;
|
|
|
+ }
|
|
|
+ if ((l_width > 0) && (width + adv > l_width) && (last_safe_break >= 0)) {
|
|
|
+ int cur_safe_brk = last_safe_break;
|
|
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
|
|
int start_pos = prev_safe_break;
|
|
|
int end_pos = last_safe_break;
|
|
@@ -996,6 +1019,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
if (p_width > indent) {
|
|
|
l_width = p_width - indent;
|
|
|
}
|
|
|
+ cur_safe_brk = end_pos;
|
|
|
last_end = l_gl[end_pos].end;
|
|
|
}
|
|
|
trim_next = true;
|
|
@@ -1009,9 +1033,12 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
last_end = 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;
|
|
|
+ line_start = l_gl[cur_safe_brk].end;
|
|
|
+ prev_safe_break = cur_safe_brk + 1;
|
|
|
+ while (prev_safe_break < l_size && l_gl[prev_safe_break].end == line_start) {
|
|
|
+ prev_safe_break++;
|
|
|
+ }
|
|
|
+ i = cur_safe_brk;
|
|
|
last_safe_break = -1;
|
|
|
width = 0;
|
|
|
word_count = 0;
|
|
@@ -1019,6 +1046,7 @@ 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) {
|
|
|
+ int cur_safe_brk = i;
|
|
|
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
|
|
|
int start_pos = prev_safe_break;
|
|
|
int end_pos = i;
|
|
@@ -1036,6 +1064,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
l_width = p_width - indent;
|
|
|
}
|
|
|
last_end = l_gl[end_pos].end;
|
|
|
+ cur_safe_brk = end_pos;
|
|
|
}
|
|
|
} else {
|
|
|
if (last_end <= line_start) {
|
|
@@ -1047,8 +1076,11 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
last_end = l_gl[i].end;
|
|
|
}
|
|
|
}
|
|
|
- line_start = l_gl[i].end;
|
|
|
- prev_safe_break = i + 1;
|
|
|
+ line_start = l_gl[cur_safe_brk].end;
|
|
|
+ prev_safe_break = cur_safe_brk + 1;
|
|
|
+ while (prev_safe_break < l_size && l_gl[prev_safe_break].end == line_start) {
|
|
|
+ prev_safe_break++;
|
|
|
+ }
|
|
|
last_safe_break = -1;
|
|
|
width = 0;
|
|
|
continue;
|
|
@@ -1059,7 +1091,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
if ((l_gl[i].flags & GRAPHEME_IS_SOFT_HYPHEN) == GRAPHEME_IS_SOFT_HYPHEN) {
|
|
|
uint32_t gl = font_get_glyph_index(l_gl[i].font_rid, l_gl[i].font_size, 0x00AD, 0);
|
|
|
float w = font_get_glyph_advance(l_gl[i].font_rid, l_gl[i].font_size, gl)[(orientation == ORIENTATION_HORIZONTAL) ? 0 : 1];
|
|
|
- if (width + l_gl[i].advance + w <= p_width) {
|
|
|
+ if (width + adv + w <= p_width) {
|
|
|
last_safe_break = i;
|
|
|
word_count++;
|
|
|
}
|
|
@@ -1083,13 +1115,17 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
|
|
|
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;
|
|
|
+ if (last_end <= l_gl[start_pos].start) {
|
|
|
+ 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(last_end);
|
|
|
}
|
|
|
- lines.push_back(l_gl[start_pos].start);
|
|
|
} else {
|
|
|
- lines.push_back(line_start);
|
|
|
+ lines.push_back(MAX(last_end, line_start));
|
|
|
}
|
|
|
lines.push_back(range.y);
|
|
|
}
|
|
@@ -1808,6 +1844,71 @@ void TextServer::shaped_text_draw_outline(const RID &p_shaped, const RID &p_canv
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+
|
|
|
+void TextServer::debug_print_glyph(int p_idx, const Glyph &p_glyph) const {
|
|
|
+ String flags;
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_VALID) {
|
|
|
+ flags += "v";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_RTL) {
|
|
|
+ flags += "R";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_VIRTUAL) {
|
|
|
+ flags += "V";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_SPACE) {
|
|
|
+ flags += "w";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_BREAK_HARD) {
|
|
|
+ flags += "h";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_BREAK_SOFT) {
|
|
|
+ flags += "s";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_TAB) {
|
|
|
+ flags += "t";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_ELONGATION) {
|
|
|
+ flags += "e";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_PUNCTUATION) {
|
|
|
+ flags += "p";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_UNDERSCORE) {
|
|
|
+ flags += "u";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_CONNECTED) {
|
|
|
+ flags += "C";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL) {
|
|
|
+ flags += "S";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_EMBEDDED_OBJECT) {
|
|
|
+ flags += "E";
|
|
|
+ }
|
|
|
+ if (p_glyph.flags & GRAPHEME_IS_SOFT_HYPHEN) {
|
|
|
+ flags += "h";
|
|
|
+ }
|
|
|
+ print_line(vformat(" %d => range: %d-%d cnt:%d index:%x font:%x(%d) offset:%fx%f adv:%f rep:%d flags:%s", p_idx, p_glyph.start, p_glyph.end, p_glyph.count, p_glyph.index, p_glyph.font_rid.get_id(), p_glyph.font_size, p_glyph.x_off, p_glyph.y_off, p_glyph.advance, p_glyph.repeat, flags));
|
|
|
+}
|
|
|
+
|
|
|
+void TextServer::shaped_text_debug_print(const RID &p_shaped) const {
|
|
|
+ int ellipsis_pos = shaped_text_get_ellipsis_pos(p_shaped);
|
|
|
+ int trim_pos = shaped_text_get_trim_pos(p_shaped);
|
|
|
+ const Vector2i &range = shaped_text_get_range(p_shaped);
|
|
|
+ int v_size = shaped_text_get_glyph_count(p_shaped);
|
|
|
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
|
|
|
+
|
|
|
+ print_line(vformat("%x: range: %d-%d glyps: %d trim: %d ellipsis: %d", p_shaped.get_id(), range.x, range.y, v_size, trim_pos, ellipsis_pos));
|
|
|
+
|
|
|
+ for (int i = 0; i < v_size; i++) {
|
|
|
+ debug_print_glyph(i, glyphs[i]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#endif // DEBUG_ENABLED
|
|
|
+
|
|
|
void TextServer::_diacritics_map_add(const String &p_from, char32_t p_to) {
|
|
|
for (int i = 0; i < p_from.size(); i++) {
|
|
|
diacritics_map[p_from[i]] = p_to;
|