Refactor: BLF Extract Function BLF_str_offset_to_cursor #120622

Merged
Harley Acheson merged 5 commits from Harley/blender:Offset2Cursor into main 2024-04-15 18:29:36 +02:00
5 changed files with 74 additions and 60 deletions

View File

@ -184,6 +184,12 @@ bool BLF_str_offset_to_glyph_bounds(int fontid,
size_t str_offset,
rcti *glyph_bounds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2, 4);
/**
* Return left edge of text cursor (caret), given a character offset and cursor width.
*/
int BLF_str_offset_to_cursor(
int fontid, const char *str, size_t str_len, size_t str_offset, float cursor_width);
/**
* Get the string byte offset that fits within a given width.
*/

View File

@ -652,6 +652,16 @@ bool BLF_str_offset_to_glyph_bounds(int fontid,
return false;
}
int BLF_str_offset_to_cursor(
int fontid, const char *str, size_t str_len, size_t str_offset, float cursor_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
return blf_str_offset_to_cursor(font, str, str_len, str_offset, cursor_width);
}
return 0;
}
size_t BLF_width_to_strlen(
int fontid, const char *str, const size_t str_len, float width, float *r_width)
{

View File

@ -1075,6 +1075,50 @@ void blf_str_offset_to_glyph_bounds(FontBLF *font,
*glyph_bounds = data.bounds;
}
int blf_str_offset_to_cursor(
FontBLF *font, const char *str, size_t str_len, size_t str_offset, float cursor_width)
{
if (!str || !str[0]) {
return 0;
}
/* Right edge of the previous character, if available. */
rcti prev = {0};
if (str_offset > 0) {
blf_str_offset_to_glyph_bounds(font, str, str_offset - 1, &prev);
}
/* Left edge of the next character, if available. */
rcti next = {0};
if (str_offset < strlen(str)) {
blf_str_offset_to_glyph_bounds(font, str, str_offset, &next);
}
if ((prev.xmax == prev.xmin) && next.xmax) {
/* Nothing (or a space) to the left, so align to right character. */
return next.xmin - int(cursor_width);
}
else if ((prev.xmax != prev.xmin) && !next.xmax) {
/* End of string, so align to last character. */
return prev.xmax;
}
else if (prev.xmax && next.xmax) {
/* Between two characters, so use the center. */
if (next.xmin >= prev.xmax) {
return int((float(prev.xmax + next.xmin) - cursor_width) / 2.0f);
}
/* A nicer center if reversed order - RTL. */
return int((float(next.xmax + prev.xmin) - cursor_width) / 2.0f);
}
else if (!str_offset) {
/* Start of string. */
return 0 - int(cursor_width);
}
else {
return int(blf_font_width(font, str, str_len, nullptr));
}
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -144,6 +144,9 @@ void blf_str_offset_to_glyph_bounds(FontBLF *font,
size_t str_offset,
rcti *glyph_bounds);
int blf_str_offset_to_cursor(
FontBLF *font, const char *str, size_t str_len, size_t str_offset, float cursor_width);
void blf_font_free(FontBLF *font);
GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font);

View File

@ -1988,54 +1988,12 @@ static void widget_draw_text(const uiFontStyle *fstyle,
/* Draw text cursor (caret). */
if (but->pos >= but->ofs) {
int t = 0;
if (drawstr[0] != 0) {
const int pos = but_pos_ofs - but->ofs;
rcti bounds;
/* Find right edge of previous character if available. */
int prev_right_edge = 0;
bool has_prev = false;
if (pos > 0) {
if (BLF_str_offset_to_glyph_bounds(
fstyle->uifont_id, drawstr + but->ofs, pos - 1, &bounds))
{
if (bounds.xmax > bounds.xmin) {
prev_right_edge = bounds.xmax;
}
else {
/* Some characters, like space, have empty bounds. */
prev_right_edge = BLF_width(fstyle->uifont_id, drawstr + but->ofs, pos);
}
has_prev = true;
}
}
/* Find left edge of next character if available. */
int next_left_edge = 0;
bool has_next = false;
if (pos < strlen(drawstr + but->ofs)) {
if (BLF_str_offset_to_glyph_bounds(fstyle->uifont_id, drawstr + but->ofs, pos, &bounds))
{
next_left_edge = bounds.xmin;
has_next = true;
}
}
if (has_next && !has_prev) {
/* Left of the first character. */
t = next_left_edge - U.pixelsize;
}
else if (has_prev && !has_next) {
/* Right of the last character. */
t = prev_right_edge + U.pixelsize;
}
else if (has_prev && has_next) {
/* Middle of the string, so in between. */
t = (prev_right_edge + next_left_edge) / 2;
}
}
int t = BLF_str_offset_to_cursor(fstyle->uifont_id,
drawstr + but->ofs,
UI_MAX_DRAW_STR,
but_pos_ofs - but->ofs,
U.pixelsize + U.pixelsize);
/* We are drawing on top of widget bases. Flush cache. */
GPU_blend(GPU_BLEND_ALPHA);
@ -2048,19 +2006,12 @@ static void widget_draw_text(const uiFontStyle *fstyle,
immUniformThemeColor(TH_WIDGET_TEXT_CURSOR);
/* Shape of the cursor for drawing. */
rcti but_cursor_shape;
but_cursor_shape.xmin = (rect->xmin + t) - U.pixelsize;
but_cursor_shape.ymin = rect->ymin + U.pixelsize;
but_cursor_shape.xmax = (rect->xmin + t) + U.pixelsize;
but_cursor_shape.ymax = rect->ymax - U.pixelsize;
/* draw cursor */
immRecti(pos,
but_cursor_shape.xmin,
but_cursor_shape.ymin,
but_cursor_shape.xmax,
but_cursor_shape.ymax);
rect->xmin + t,
rect->ymin + U.pixelsize,
rect->xmin + t + int(2.0f * U.pixelsize),
rect->ymax - U.pixelsize);
immUnbindProgram();
@ -2068,8 +2019,8 @@ static void widget_draw_text(const uiFontStyle *fstyle,
/* IME candidate window uses cursor position. */
if (!ime_reposition_window) {
ime_reposition_window = true;
ime_win_x = but_cursor_shape.xmax + 5;
ime_win_y = but_cursor_shape.ymin + 3;
ime_win_x = rect->xmin + t + 5;
ime_win_y = rect->ymin + 3;
}
#endif
}