diff options
author | Phil Jones <philj56@gmail.com> | 2022-08-05 17:25:27 +0100 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2022-08-05 19:21:11 +0100 |
commit | c9f1daea03a41c0cad56453e1dcc50f6133f19c6 (patch) | |
tree | a609e8a6145f2027d78876a2a775d48c06aafabc /src/entry_backend/pango.c | |
parent | 15f831bbb6f27d5a11879dd07f383400e83c97e3 (diff) |
Correct selection background for slanted fonts.
Previously the selection background didn't really wrap text correctly,
especially if the font was very slanted. This fixes that, so the width
is tightly wrapped around any font.
Diffstat (limited to 'src/entry_backend/pango.c')
-rw-r--r-- | src/entry_backend/pango.c | 77 |
1 files changed, 52 insertions, 25 deletions
diff --git a/src/entry_backend/pango.c b/src/entry_backend/pango.c index 575bba2..3173d6f 100644 --- a/src/entry_backend/pango.c +++ b/src/entry_backend/pango.c @@ -57,6 +57,12 @@ static bool size_overflows(struct entry *entry, uint32_t width, uint32_t height) return false; } +/* + * This is pretty much a direct translation of the corresponding function in + * the harfbuzz backend. As that's the one that I care about most, there are + * more explanatory comments than there are here, so go look at that if you + * want to understand how tofi's text rendering works. + */ void entry_backend_pango_update(struct entry *entry) { cairo_t *cr = entry->cairo[entry->index].cr; @@ -71,18 +77,18 @@ void entry_backend_pango_update(struct entry *entry) pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); - int width; - int height; - pango_layout_get_pixel_size(entry->pango.layout, &width, NULL); - cairo_translate(cr, width, 0); + PangoRectangle ink_rect; + PangoRectangle logical_rect; + pango_layout_get_pixel_extents(entry->pango.layout, &ink_rect, &logical_rect); + cairo_translate(cr, logical_rect.width + logical_rect.x, 0); /* Render the entry text */ pango_layout_set_text(layout, entry->input_mb, -1); pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &width, &height); - width = MAX(width, (int)entry->input_width * PANGO_SCALE); + pango_layout_get_pixel_extents(entry->pango.layout, &ink_rect, &logical_rect); + logical_rect.width = MAX(logical_rect.width, (int)entry->input_width); uint32_t num_results; if (entry->num_results == 0) { @@ -94,9 +100,9 @@ void entry_backend_pango_update(struct entry *entry) size_t i; for (i = 0; i < num_results; i++) { if (entry->horizontal) { - cairo_translate(cr, (int)(width / PANGO_SCALE) + entry->result_spacing, 0); + cairo_translate(cr, logical_rect.x + logical_rect.width + entry->result_spacing, 0); } else { - cairo_translate(cr, 0, (int)(height / PANGO_SCALE) + entry->result_spacing); + cairo_translate(cr, 0, logical_rect.height + entry->result_spacing); } if (entry->num_results == 0) { if (size_overflows(entry, 0, 0)) { @@ -126,21 +132,21 @@ void entry_backend_pango_update(struct entry *entry) if (entry->num_results > 0) { pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &width, &height); + pango_layout_get_pixel_extents(entry->pango.layout, &ink_rect, &logical_rect); } else if (!entry->horizontal) { - if (size_overflows(entry, 0, height / PANGO_SCALE)) { + if (size_overflows(entry, 0, logical_rect.height)) { entry->num_results_drawn = i; break; } else { pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &width, &height); + pango_layout_get_pixel_extents(entry->pango.layout, &ink_rect, &logical_rect); } } else { cairo_push_group(cr); pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &width, &height); + pango_layout_get_pixel_extents(entry->pango.layout, &ink_rect, &logical_rect); cairo_pattern_t *group = cairo_pop_group(cr); - if (size_overflows(entry, width / PANGO_SCALE, 0)) { + if (size_overflows(entry, logical_rect.width, 0)) { entry->num_results_drawn = i; cairo_pattern_destroy(group); break; @@ -154,12 +160,18 @@ void entry_backend_pango_update(struct entry *entry) } } else { ssize_t prematch_len = -1; + ssize_t postmatch_len = -1; size_t match_len = entry->input_mb_length; - int32_t subwidth; + PangoRectangle ink_subrect; + PangoRectangle logical_subrect; if (entry->input_mb_length > 0 && entry->selection_highlight_color.a != 0) { char *match_pos = strcasestr(str, entry->input_mb); if (match_pos != NULL) { prematch_len = (match_pos - str); + postmatch_len = strlen(str) - prematch_len - match_len; + if (postmatch_len <= 0) { + postmatch_len = -1; + } } } @@ -170,27 +182,43 @@ void entry_backend_pango_update(struct entry *entry) pango_layout_set_text(layout, str, prematch_len); pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &subwidth, &height); - width = subwidth; + pango_layout_get_pixel_extents(entry->pango.layout, &ink_subrect, &logical_subrect); + ink_rect = ink_subrect; + logical_rect = logical_subrect; if (prematch_len != -1) { - cairo_translate(cr, (int)(subwidth / PANGO_SCALE), 0); + cairo_translate(cr, logical_subrect.x + logical_subrect.width, 0); color = entry->selection_highlight_color; cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); pango_layout_set_text(layout, &str[prematch_len], match_len); pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &subwidth, &height); - width += subwidth; + pango_layout_get_pixel_extents(entry->pango.layout, &ink_subrect, &logical_subrect); + if (prematch_len == 0) { + ink_rect = ink_subrect; + logical_rect = logical_subrect; + } else { + ink_rect.width = logical_rect.width + - ink_rect.x + + ink_subrect.x + + ink_subrect.width; + logical_rect.width += logical_subrect.x + logical_subrect.width; + } + } - cairo_translate(cr, (int)(subwidth / PANGO_SCALE), 0); + if (postmatch_len != -1) { + cairo_translate(cr, logical_subrect.x + logical_subrect.width, 0); color = entry->selection_foreground_color; cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); pango_layout_set_text(layout, &str[prematch_len + match_len], -1); pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); - pango_layout_get_size(layout, &subwidth, &height); - width += subwidth; + pango_layout_get_pixel_extents(entry->pango.layout, &ink_subrect, &logical_subrect); + ink_rect.width = logical_rect.width + - ink_rect.x + + ink_subrect.x + + ink_subrect.width; + logical_rect.width += logical_subrect.x + logical_subrect.width; } @@ -202,9 +230,8 @@ void entry_backend_pango_update(struct entry *entry) if (pad < 0) { pad = entry->clip_width; } - cairo_translate(cr, -pad, 0); - cairo_rectangle(cr, 0, 0, (int)(width / PANGO_SCALE) + pad * 2, (int)(height / PANGO_SCALE)); - cairo_translate(cr, pad, 0); + cairo_translate(cr, floor(-pad + ink_rect.x), 0); + cairo_rectangle(cr, 0, 0, ceil(ink_rect.width + pad * 2), ceil(logical_rect.height)); cairo_fill(cr); cairo_restore(cr); cairo_paint(cr); |