From 5366eb89c6eb4057edfdf16eb42f31d34f6a0ba4 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Sun, 3 May 2020 16:52:41 +1000 Subject: UI: improve widget text cursor position Use BLF_boundbox_foreach_glyph for more accurate cursor placement. --- .../blender/editors/interface/interface_handlers.c | 80 ++++++++++------------ .../blender/editors/interface/interface_widgets.c | 9 +-- 2 files changed, 41 insertions(+), 48 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9a7e189406c..4d215105858 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2848,6 +2848,23 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data) return changed; } +static bool ui_textedit_set_cursor_pos_foreach_glyph(const char *UNUSED(str), + const size_t str_step_ofs, + const rcti *glyph_step_bounds, + const int UNUSED(glyph_advance_x), + const rctf *glyph_bounds, + const float UNUSED(glyph_bearing[2]), + void *user_data) +{ + int *cursor_data = user_data; + float center = glyph_step_bounds->xmin + (BLI_rctf_size_x(glyph_bounds) / 2.0f); + if (cursor_data[0] < center) { + cursor_data[1] = str_step_ofs; + return false; + } + return true; +} + /** * \param x: Screen space cursor location - #wmEvent.x * @@ -2883,8 +2900,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con startx += UI_DPI_ICON_SIZE / aspect; } } - /* But this extra .05 makes clicks in between characters feel nicer. */ - startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect; + startx += (UI_TEXT_MARGIN_X * U.widget_unit) / aspect; /* mouse dragged outside the widget to the left */ if (x < startx) { @@ -2907,48 +2923,24 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con but->pos = but->ofs; } /* mouse inside the widget, mouse coords mapped in widget space */ - else { /* (x >= startx) */ - int pos_i; - - /* keep track of previous distance from the cursor to the char */ - float cdist, cdist_prev = 0.0f; - short pos_prev; - - str_last = &str[strlen(str)]; - - but->pos = pos_prev = ((str_last - str) - but->ofs); - - while (true) { - cdist = startx + BLF_width(fstyle.uifont_id, str + but->ofs, (str_last - str) - but->ofs); - - /* check if position is found */ - if (cdist < x) { - /* check is previous location was in fact closer */ - if ((x - cdist) > (cdist_prev - x)) { - but->pos = pos_prev; - } - break; - } - cdist_prev = cdist; - pos_prev = but->pos; - /* done with tricky distance checks */ - - pos_i = but->pos; - if (but->pos <= 0) { - break; - } - if (BLI_str_cursor_step_prev_utf8(str + but->ofs, but->ofs, &pos_i)) { - but->pos = pos_i; - str_last = &str[but->pos + but->ofs]; - } - else { - break; /* unlikely but possible */ - } - } - but->pos += but->ofs; - if (but->pos < 0) { - but->pos = 0; - } + else { + str_last = &str[but->ofs]; + const int str_last_len = strlen(str_last); + int x_pos = (int)(x - startx); + int glyph_data[2] = { + x_pos, /* horizontal position to test. */ + -1, /* Write the character offset here. */ + }; + BLF_boundbox_foreach_glyph(fstyle.uifont_id, + str + but->ofs, + INT_MAX, + ui_textedit_set_cursor_pos_foreach_glyph, + glyph_data); + /* If value untouched then we are to the right. */ + if (glyph_data[1] == -1) { + glyph_data[1] = str_last_len; + } + but->pos = glyph_data[1] + but->ofs; } if (fstyle.kerning == 1) { diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index e927d259926..e0ea760d7bd 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2097,15 +2097,16 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle, static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str), const size_t str_step_ofs, const rcti *glyph_step_bounds, - const int glyph_advance_x, - const rctf *UNUSED(glyph_bounds), - const float UNUSED(glyph_bearing[2]), + const int UNUSED(glyph_advance_x), + const rctf *glyph_bounds, + const float glyph_bearing[2], void *user_data) { /* The index of the character to get, set to the x-position. */ int *ul_data = user_data; if (ul_data[0] == (int)str_step_ofs) { - ul_data[1] = glyph_step_bounds->xmin + (glyph_advance_x / 2); + ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] + + (BLI_rctf_size_x(glyph_bounds) / 2.0f); /* Early exit. */ return false; } -- cgit v1.2.3