Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarley Acheson <harley.acheson@gmail.com>2022-09-25 21:25:31 +0300
committerHarley Acheson <harley.acheson@gmail.com>2022-09-25 21:25:31 +0300
commitb3714b1e85fd81d4f7db3c562483232fd6a89807 (patch)
treee2758ecd3624bd7670df77df2c65c004cc510ea5
parentc8ee70c96200548699a2d038a93208c5723f91e7 (diff)
BLF: Refactor of blf_font_boundbox_foreach_glyph
Refactor of `BLF_boundbox_foreach_glyph` and simplification of its usage by only passing translated glyph bounds to callbacks. See D15765 for more details. Differential Revision: https://developer.blender.org/D15765 Reviewed by Campbell Barton
-rw-r--r--source/blender/blenfont/BLF_api.h27
-rw-r--r--source/blender/blenfont/intern/blf.c37
-rw-r--r--source/blender/blenfont/intern/blf_font.c116
-rw-r--r--source/blender/blenfont/intern/blf_internal.h18
-rw-r--r--source/blender/editors/interface/interface_handlers.c38
-rw-r--r--source/blender/editors/interface/interface_widgets.c59
6 files changed, 148 insertions, 147 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index af2e4fd1784..01b6d1d8942 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -118,10 +118,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth) ATTR_
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
size_t str_step_ofs,
- const struct rcti *glyph_step_bounds,
- int glyph_advance_x,
- const struct rcti *glyph_bounds,
- const int glyph_bearing[2],
+ const struct rcti *bounds,
void *user_data);
/**
@@ -132,12 +129,6 @@ typedef bool (*BLF_GlyphBoundsFn)(const char *str,
*
* \note The font position, clipping, matrix and rotation are not applied.
*/
-void BLF_boundbox_foreach_glyph_ex(int fontid,
- const char *str,
- size_t str_len,
- BLF_GlyphBoundsFn user_fn,
- void *user_data,
- struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox_foreach_glyph(int fontid,
const char *str,
size_t str_len,
@@ -145,6 +136,22 @@ void BLF_boundbox_foreach_glyph(int fontid,
void *user_data) ATTR_NONNULL(2);
/**
+ * Get the byte offset within a string, selected by mouse at a horizontal location.
+ */
+size_t BLF_str_offset_from_cursor_position(int fontid,
+ const char *str,
+ size_t str_len,
+ int location_x);
+
+/**
+ * Return bounds of the glyph rect at the string offset.
+ */
+bool BLF_str_offset_to_glyph_bounds(int fontid,
+ const char *str,
+ size_t str_offset,
+ struct rcti *glyph_bounds);
+
+/**
* Get the string byte offset that fits within a given width.
*/
size_t BLF_width_to_strlen(
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index df8a9734c9a..57c1e280e8d 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -563,32 +563,45 @@ int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
return columns;
}
-void BLF_boundbox_foreach_glyph_ex(int fontid,
- const char *str,
- size_t str_len,
- BLF_GlyphBoundsFn user_fn,
- void *user_data,
- struct ResultBLF *r_info)
+void BLF_boundbox_foreach_glyph(
+ int fontid, const char *str, size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data)
{
FontBLF *font = blf_get(fontid);
- BLF_RESULT_CHECK_INIT(r_info);
-
if (font) {
if (font->flags & BLF_WORD_WRAP) {
/* TODO: word-wrap support. */
BLI_assert(0);
}
else {
- blf_font_boundbox_foreach_glyph(font, str, str_len, user_fn, user_data, r_info);
+ blf_font_boundbox_foreach_glyph(font, str, str_len, user_fn, user_data);
}
}
}
-void BLF_boundbox_foreach_glyph(
- int fontid, const char *str, const size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data)
+size_t BLF_str_offset_from_cursor_position(int fontid,
+ const char *str,
+ size_t str_len,
+ int location_x)
{
- BLF_boundbox_foreach_glyph_ex(fontid, str, str_len, user_fn, user_data, NULL);
+ FontBLF *font = blf_get(fontid);
+ if (font) {
+ return blf_str_offset_from_cursor_position(font, str, str_len, location_x);
+ }
+ return 0;
+}
+
+bool BLF_str_offset_to_glyph_bounds(int fontid,
+ const char *str,
+ size_t str_offset,
+ rcti *glyph_bounds)
+{
+ FontBLF *font = blf_get(fontid);
+ if (font) {
+ blf_str_offset_to_glyph_bounds(font, str, str_offset, glyph_bounds);
+ return true;
+ }
+ return false;
}
size_t BLF_width_to_strlen(
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 9ea7e529df2..cbf656289b5 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -901,25 +901,23 @@ float blf_font_fixed_width(FontBLF *font)
return width;
}
-static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
- GlyphCacheBLF *gc,
- const char *str,
- const size_t str_len,
- BLF_GlyphBoundsFn user_fn,
- void *user_data,
- struct ResultBLF *r_info,
- ft_pix pen_y)
+void blf_font_boundbox_foreach_glyph(FontBLF *font,
+ const char *str,
+ const size_t str_len,
+ BLF_GlyphBoundsFn user_fn,
+ void *user_data)
{
GlyphBLF *g, *g_prev = NULL;
ft_pix pen_x = 0;
size_t i = 0, i_curr;
- rcti gbox_px;
if (str_len == 0 || str[0] == 0) {
/* early output. */
return;
}
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+
while ((i < str_len) && str[i]) {
i_curr = i;
g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
@@ -928,44 +926,88 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
continue;
}
pen_x += blf_kerning(font, g_prev, g);
- const ft_pix pen_x_next = ft_pix_round_advance(pen_x, g->advance_x);
-
- gbox_px.xmin = ft_pix_to_int_floor(pen_x);
- gbox_px.xmax = ft_pix_to_int_ceil(pen_x_next);
- gbox_px.ymin = ft_pix_to_int_floor(pen_y);
- gbox_px.ymax = gbox_px.ymin - g->dims[1];
- const int advance_x_px = gbox_px.xmax - gbox_px.xmin;
-
- pen_x = pen_x_next;
- rcti box_px;
- box_px.xmin = ft_pix_to_int_floor(g->box_xmin);
- box_px.xmax = ft_pix_to_int_ceil(g->box_xmax);
- box_px.ymin = ft_pix_to_int_floor(g->box_ymin);
- box_px.ymax = ft_pix_to_int_ceil(g->box_ymax);
+ rcti bounds;
+ bounds.xmin = ft_pix_to_int_floor(pen_x) + ft_pix_to_int_floor(g->box_xmin);
+ bounds.xmax = ft_pix_to_int_floor(pen_x) + ft_pix_to_int_ceil(g->box_xmax);
+ bounds.ymin = ft_pix_to_int_floor(g->box_ymin);
+ bounds.ymax = ft_pix_to_int_ceil(g->box_ymax);
- if (user_fn(str, i_curr, &gbox_px, advance_x_px, &box_px, g->pos, user_data) == false) {
+ if (user_fn(str, i_curr, &bounds, user_data) == false) {
break;
}
-
+ pen_x = ft_pix_round_advance(pen_x, g->advance_x);
g_prev = g;
}
- if (r_info) {
- r_info->lines = 1;
- r_info->width = ft_pix_to_int(pen_x);
+ blf_glyph_cache_release(font);
+}
+
+typedef struct CursorPositionForeachGlyph_Data {
+ /** Horizontal position to test. */
+ int location_x;
+ /** Write the character offset here. */
+ size_t r_offset;
+} CursorPositionForeachGlyph_Data;
+
+static bool blf_cursor_position_foreach_glyph(const char *UNUSED(str),
+ const size_t str_step_ofs,
+ const rcti *bounds,
+ void *user_data)
+{
+ CursorPositionForeachGlyph_Data *data = user_data;
+ if (data->location_x < (bounds->xmin + bounds->xmax) / 2) {
+ data->r_offset = str_step_ofs;
+ return false;
}
+ return true;
}
-void blf_font_boundbox_foreach_glyph(FontBLF *font,
- const char *str,
- const size_t str_len,
- BLF_GlyphBoundsFn user_fn,
- void *user_data,
- struct ResultBLF *r_info)
+
+size_t blf_str_offset_from_cursor_position(struct FontBLF *font,
+ const char *str,
+ size_t str_len,
+ int location_x)
{
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_boundbox_foreach_glyph_ex(font, gc, str, str_len, user_fn, user_data, r_info, 0);
- blf_glyph_cache_release(font);
+ CursorPositionForeachGlyph_Data data = {
+ .location_x = location_x,
+ .r_offset = (size_t)-1,
+ };
+ blf_font_boundbox_foreach_glyph(font, str, str_len, blf_cursor_position_foreach_glyph, &data);
+ if (data.r_offset == (size_t)-1) {
+ data.r_offset = BLI_strnlen(str, str_len);
+ }
+ return data.r_offset;
+}
+
+typedef struct StrOffsetToGlyphBounds_Data {
+ size_t str_offset;
+ rcti bounds;
+} StrOffsetToGlyphBounds_Data;
+
+static bool blf_str_offset_foreach_glyph(const char *UNUSED(str),
+ const size_t str_step_ofs,
+ const rcti *bounds,
+ void *user_data)
+{
+ StrOffsetToGlyphBounds_Data *data = user_data;
+ if (data->str_offset == str_step_ofs) {
+ data->bounds = *bounds;
+ return false;
+ }
+ return true;
+}
+
+void blf_str_offset_to_glyph_bounds(struct FontBLF *font,
+ const char *str,
+ size_t str_offset,
+ rcti *glyph_bounds)
+{
+ StrOffsetToGlyphBounds_Data data = {
+ .str_offset = str_offset,
+ .bounds = {0},
+ };
+ blf_font_boundbox_foreach_glyph(font, str, str_offset + 1, blf_str_offset_foreach_glyph, &data);
+ *glyph_bounds = data.bounds;
}
/** \} */
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 28f433a3018..2f3f7b52233 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -141,13 +141,19 @@ void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
size_t str_len,
bool (*user_fn)(const char *str,
size_t str_step_ofs,
- const struct rcti *glyph_step_bounds,
- int glyph_advance_x,
- const struct rcti *glyph_bounds,
- const int glyph_bearing[2],
+ const struct rcti *bounds,
void *user_data),
- void *user_data,
- struct ResultBLF *r_info);
+ void *user_data);
+
+size_t blf_str_offset_from_cursor_position(struct FontBLF *font,
+ const char *str,
+ size_t str_len,
+ int location_x);
+
+void blf_str_offset_to_glyph_bounds(struct FontBLF *font,
+ const char *str,
+ size_t str_offset,
+ struct rcti *glyph_bounds);
void blf_font_free(struct FontBLF *font);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index a6c700bdc2f..56b550995be 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3017,23 +3017,6 @@ 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 rcti *glyph_bounds,
- const int UNUSED(glyph_bearing[2]),
- void *user_data)
-{
- int *cursor_data = user_data;
- const int center = glyph_step_bounds->xmin + (BLI_rcti_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
*
@@ -3064,7 +3047,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
startx += UI_DPI_ICON_SIZE / aspect;
}
}
- startx += (UI_TEXT_MARGIN_X * U.widget_unit) / aspect;
+ startx += (UI_TEXT_MARGIN_X * U.widget_unit - U.pixelsize) / aspect;
/* mouse dragged outside the widget to the left */
if (x < startx) {
@@ -3088,23 +3071,8 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
}
/* mouse inside the widget, mouse coords mapped in widget space */
else {
- str_last = &str[but->ofs];
- const int str_last_len = strlen(str_last);
- const 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;
+ but->pos = but->ofs + BLF_str_offset_from_cursor_position(
+ fstyle.uifont_id, str + but->ofs, INT_MAX, (int)(x - startx));
}
ui_but_text_password_hide(password_str, but, true);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 1b13632b131..6ba80e2e0d9 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1858,33 +1858,6 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle,
}
#endif /* WITH_INPUT_IME */
-struct UnderlineData {
- size_t str_offset; /* The string offset of the underlined character. */
- int width_px; /* The underline width in pixels. */
- int r_offset_px[2]; /* Write the X,Y offset here. */
-};
-
-static bool widget_draw_text_underline_calc_position(const char *UNUSED(str),
- const size_t str_step_ofs,
- const rcti *glyph_step_bounds,
- const int UNUSED(glyph_advance_x),
- const rcti *glyph_bounds,
- const int UNUSED(glyph_bearing[2]),
- void *user_data)
-{
- struct UnderlineData *ul_data = user_data;
- if (ul_data->str_offset == str_step_ofs) {
- /* Full width of this glyph including both bearings. */
- const int width = glyph_bounds->xmin + BLI_rcti_size_x(glyph_bounds) + glyph_bounds->xmin;
- ul_data->r_offset_px[0] = glyph_step_bounds->xmin + ((width - ul_data->width_px) / 2);
- /* One line-width below the lower glyph bounds. */
- ul_data->r_offset_px[1] = glyph_bounds->ymin - U.pixelsize;
- /* Early exit. */
- return false;
- }
- return true;
-}
-
static void widget_draw_text(const uiFontStyle *fstyle,
const uiWidgetColors *wcol,
uiBut *but,
@@ -2150,26 +2123,18 @@ static void widget_draw_text(const uiFontStyle *fstyle,
}
if (ul_index != -1) {
- int ul_width = round_fl_to_int(BLF_width(fstyle->uifont_id, "_", 2));
-
- struct UnderlineData ul_data = {
- .str_offset = ul_index,
- .width_px = ul_width,
- };
-
- BLF_boundbox_foreach_glyph(fstyle->uifont_id,
- drawstr_ofs,
- ul_index + 1,
- widget_draw_text_underline_calc_position,
- &ul_data);
-
- const int pos_x = rect->xmin + font_xofs + ul_data.r_offset_px[0];
- const int pos_y = rect->ymin + font_yofs + ul_data.r_offset_px[1];
-
- /* Use text output because direct drawing doesn't always work. See T89246. */
- BLF_position(fstyle->uifont_id, pos_x, pos_y, 0.0f);
- BLF_color4ubv(fstyle->uifont_id, wcol->text);
- BLF_draw(fstyle->uifont_id, "_", 2);
+ rcti bounds;
+ if (BLF_str_offset_to_glyph_bounds(fstyle->uifont_id, drawstr_ofs, ul_index, &bounds) &&
+ !BLI_rcti_is_empty(&bounds)) {
+ int ul_width = round_fl_to_int(BLF_width(fstyle->uifont_id, "_", 2));
+ int pos_x = rect->xmin + font_xofs + bounds.xmin +
+ (bounds.xmax - bounds.xmin - ul_width) / 2;
+ int pos_y = rect->ymin + font_yofs + bounds.ymin - U.pixelsize;
+ /* Use text output because direct drawing doesn't always work. See T89246. */
+ BLF_position(fstyle->uifont_id, (float)pos_x, pos_y, 0.0f);
+ BLF_color4ubv(fstyle->uifont_id, wcol->text);
+ BLF_draw(fstyle->uifont_id, "_", 2);
+ }
}
}
}