From a750ca7ec113859d03d46189e554dc5ff8dd7411 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 6 Oct 2022 14:30:50 +0300 Subject: [PATCH] Add split caret direction markers. Fix block/overtype caret size. --- scene/gui/line_edit.cpp | 13 +++++++++- scene/gui/text_edit.cpp | 20 +++++++++++++-- servers/text_server.cpp | 57 +++++++++++++++++++---------------------- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index be94337c899..eb34559a142 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -971,7 +971,18 @@ void LineEdit::_notification(int p_what) { } else { if (caret.l_caret != Rect2() && caret.l_dir == TextServer::DIRECTION_AUTO) { // Draw extra marker on top of mid caret. - Rect2 trect = Rect2(caret.l_caret.position.x - 3 * caret_width, caret.l_caret.position.y, 6 * caret_width, caret_width); + Rect2 trect = Rect2(caret.l_caret.position.x - 2.5 * caret_width, caret.l_caret.position.y, 6 * caret_width, caret_width); + trect.position += ofs; + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + } else if (caret.l_caret != Rect2() && caret.t_caret != Rect2() && caret.l_dir != caret.t_dir) { + // Draw extra direction marker on top of split caret. + float d = (caret.l_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; + Rect2 trect = Rect2(caret.l_caret.position.x + d * caret_width, caret.l_caret.position.y + caret.l_caret.size.y - caret_width, 3 * caret_width, caret_width); + trect.position += ofs; + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + + d = (caret.t_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; + trect = Rect2(caret.t_caret.position.x + d * caret_width, caret.t_caret.position.y, 3 * caret_width, caret_width); trect.position += ofs; RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index cc0fa200a66..b8973df1857 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1350,9 +1350,14 @@ void TextEdit::_notification(int p_what) { draw_rect(ts_caret.t_caret, caret_color, overtype_mode); if (ts_caret.l_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) { + // Draw split caret (leading part). ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.l_caret.size.x = caret_width; - draw_rect(ts_caret.l_caret, caret_color * Color(1, 1, 1, 0.5)); + draw_rect(ts_caret.l_caret, caret_color); + // Draw extra direction marker on top of split caret. + float d = (ts_caret.l_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; + Rect2 trect = Rect2(ts_caret.l_caret.position.x + d * caret_width, ts_caret.l_caret.position.y + ts_caret.l_caret.size.y - caret_width, 3 * caret_width, caret_width); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); } } else { // End of the line. if (gl_size > 0) { @@ -1383,7 +1388,18 @@ void TextEdit::_notification(int p_what) { // Normal caret. if (ts_caret.l_caret != Rect2() && ts_caret.l_dir == TextServer::DIRECTION_AUTO) { // Draw extra marker on top of mid caret. - Rect2 trect = Rect2(ts_caret.l_caret.position.x - 3 * caret_width, ts_caret.l_caret.position.y, 6 * caret_width, caret_width); + Rect2 trect = Rect2(ts_caret.l_caret.position.x - 2.5 * caret_width, ts_caret.l_caret.position.y, 6 * caret_width, caret_width); + trect.position += Vector2(char_margin + ofs_x, ofs_y); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + } else if (ts_caret.l_caret != Rect2() && ts_caret.t_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) { + // Draw extra direction marker on top of split caret. + float d = (ts_caret.l_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; + Rect2 trect = Rect2(ts_caret.l_caret.position.x + d * caret_width, ts_caret.l_caret.position.y + ts_caret.l_caret.size.y - caret_width, 3 * caret_width, caret_width); + trect.position += Vector2(char_margin + ofs_x, ofs_y); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + + d = (ts_caret.t_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; + trect = Rect2(ts_caret.t_caret.position.x + d * caret_width, ts_caret.t_caret.position.y, 3 * caret_width, caret_width); trect.position += Vector2(char_margin + ofs_x, ofs_y); RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); } diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 588c837a40b..dfeb5cb70c7 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -956,6 +956,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) { @@ -967,15 +972,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) { @@ -987,21 +988,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) { @@ -1014,15 +1016,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; @@ -1036,15 +1034,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; @@ -1058,22 +1053,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;