From 9215ca0f01f7d155191d11fd9caa2574387c6f84 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 8 Sep 2018 16:19:31 +1000 Subject: [PATCH] Align titles to baseline This does the following: * Adds a baseline argument to get_text_size (the baseline is the distance from the top of the texture to the baseline). * Stores the baseline in the container when calculating the title height. * Takes the baseline into account when calculating the config's max font height. * When rendering, pads the textures according to the baseline so they line up. --- common/pango.c | 5 ++++- include/pango.h | 2 +- include/sway/config.h | 1 + include/sway/tree/container.h | 1 + sway/config.c | 21 +++++++++++++++------ sway/debug-tree.c | 2 +- sway/desktop/render.c | 12 ++++++------ sway/tree/container.c | 10 ++++++---- sway/tree/view.c | 3 ++- swaybar/render.c | 14 +++++++------- swaynag/render.c | 10 +++++----- 11 files changed, 49 insertions(+), 32 deletions(-) diff --git a/common/pango.c b/common/pango.c index 92703f804..ea71ac4a8 100644 --- a/common/pango.c +++ b/common/pango.c @@ -103,7 +103,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, } void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, - double scale, bool markup, const char *fmt, ...) { + int *baseline, double scale, bool markup, const char *fmt, ...) { static char buf[2048]; va_list args; @@ -116,6 +116,9 @@ void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, width, height); + if (baseline) { + *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; + } g_object_unref(layout); } diff --git a/include/pango.h b/include/pango.h index 4492f01e0..09a535a50 100644 --- a/include/pango.h +++ b/include/pango.h @@ -20,7 +20,7 @@ int escape_markup_text(const char *src, char *dest, int dest_length); PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, double scale, bool markup); void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, - double scale, bool markup, const char *fmt, ...); + int *baseline, double scale, bool markup, const char *fmt, ...); void pango_printf(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...); diff --git a/include/sway/config.h b/include/sway/config.h index 2fef0081a..b52bb681d 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -349,6 +349,7 @@ struct sway_config { enum sway_container_layout default_layout; char *font; size_t font_height; + size_t font_baseline; bool pango_markup; size_t urgent_timeout; enum sway_fowa focus_on_window_activation; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 6efecf7cd..2735daa32 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -117,6 +117,7 @@ struct sway_container { struct wlr_texture *title_unfocused; struct wlr_texture *title_urgent; size_t title_height; + size_t title_baseline; struct { struct wl_signal destroy; diff --git a/sway/config.c b/sway/config.c index 89701640e..6ff4da037 100644 --- a/sway/config.c +++ b/sway/config.c @@ -807,22 +807,31 @@ int workspace_output_cmp_workspace(const void *a, const void *b) { return lenient_strcmp(wsa->workspace, wsb->workspace); } -static void find_font_height_iterator(struct sway_container *container, - void *data) { +static void find_font_height_iterator(struct sway_container *con, void *data) { + size_t amount_below_baseline = con->title_height - con->title_baseline; + size_t extended_height = config->font_baseline + amount_below_baseline; + if (extended_height > config->font_height) { + config->font_height = extended_height; + } +} + +static void find_baseline_iterator(struct sway_container *con, void *data) { bool *recalculate = data; if (*recalculate) { - container_calculate_title_height(container); + container_calculate_title_height(con); } - if (container->title_height > config->font_height) { - config->font_height = container->title_height; + if (con->title_baseline > config->font_baseline) { + config->font_baseline = con->title_baseline; } } void config_update_font_height(bool recalculate) { size_t prev_max_height = config->font_height; config->font_height = 0; + config->font_baseline = 0; - root_for_each_container(find_font_height_iterator, &recalculate); + root_for_each_container(find_baseline_iterator, &recalculate); + root_for_each_container(find_font_height_iterator, NULL); if (config->font_height != prev_max_height) { arrange_root(); diff --git a/sway/debug-tree.c b/sway/debug-tree.c index 973c6d883..9644f4e5b 100644 --- a/sway/debug-tree.c +++ b/sway/debug-tree.c @@ -84,7 +84,7 @@ static int draw_node(cairo_t *cairo, struct sway_node *node, struct sway_node *focus, int x, int y) { int text_width, text_height; char *buffer = get_string(node); - get_text_size(cairo, "monospace", &text_width, &text_height, + get_text_size(cairo, "monospace", &text_width, &text_height, NULL, 1, false, buffer); cairo_save(cairo); cairo_rectangle(cairo, x + 2, y, text_width - 2, text_height); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index ecac262ef..8a6f63aa6 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -466,12 +466,12 @@ static void render_titlebar(struct sway_output *output, &texture_box.width, &texture_box.height); title_ob_width = texture_box.width; - // The title texture might be shorter than the config->font_height, in - // which case we need to pad it as evenly as possible above and below. - int ob_padding_total = config->font_height * output_scale - - texture_box.height; - int ob_padding_above = floor(ob_padding_total / 2); - int ob_padding_below = ceil(ob_padding_total / 2); + // The title texture might be shorter than the config->font_height, + // in which case we need to pad it above and below. + int ob_padding_above = (config->font_baseline - con->title_baseline) + * output_scale; + int ob_padding_below = (config->font_height - con->title_height) + * output_scale - ob_padding_above; // Render texture texture_box.x = (x - output_x + TITLEBAR_H_PADDING) * output_scale; diff --git a/sway/tree/container.c b/sway/tree/container.c index cbbb1f56a..ccd79f0e7 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -455,8 +455,8 @@ static void update_title_texture(struct sway_container *con, int height = con->title_height * scale; cairo_t *c = cairo_create(NULL); - get_text_size(c, config->font, &width, NULL, scale, config->pango_markup, - "%s", con->formatted_title); + get_text_size(c, config->font, &width, NULL, NULL, scale, + config->pango_markup, "%s", con->formatted_title); cairo_destroy(c); cairo_surface_t *surface = cairo_image_surface_create( @@ -505,10 +505,12 @@ void container_calculate_title_height(struct sway_container *container) { } cairo_t *cairo = cairo_create(NULL); int height; - get_text_size(cairo, config->font, NULL, &height, 1, config->pango_markup, - "%s", container->formatted_title); + int baseline; + get_text_size(cairo, config->font, NULL, &height, &baseline, 1, + config->pango_markup, "%s", container->formatted_title); cairo_destroy(cairo); container->title_height = height; + container->title_baseline = baseline; } /** diff --git a/sway/tree/view.c b/sway/tree/view.c index 312c62d1f..53215b40b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -935,7 +935,8 @@ static void update_marks_texture(struct sway_view *view, int height = view->container->title_height * scale; cairo_t *c = cairo_create(NULL); - get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer); + get_text_size(c, config->font, &width, NULL, NULL, scale, false, + "%s", buffer); cairo_destroy(c); cairo_surface_t *surface = cairo_image_surface_create( diff --git a/swaybar/render.c b/swaybar/render.c index 702e863c7..7303e70ff 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -33,8 +33,8 @@ static uint32_t render_status_line_error(cairo_t *cairo, int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; int text_width, text_height; - get_text_size(cairo, config->font, - &text_width, &text_height, output->scale, false, "%s", error); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, + output->scale, false, "%s", error); uint32_t ideal_height = text_height + ws_vertical_padding * 2; uint32_t ideal_surface_height = ideal_height / output->scale; @@ -63,7 +63,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, config->colors.focused_statusline : config->colors.statusline); int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, + get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, config->pango_markup, "%s", text); int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; @@ -126,7 +126,7 @@ static uint32_t render_status_block(cairo_t *cairo, uint32_t height = surface_height * output->scale; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, + get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, block->markup, "%s", block->full_text); int margin = 3 * output->scale; @@ -157,7 +157,7 @@ static uint32_t render_status_block(cairo_t *cairo, int sep_width, sep_height; if (!edge) { if (config->sep_symbol) { - get_text_size(cairo, config->font, &sep_width, &sep_height, + get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, output->scale, false, "%s", config->sep_symbol); uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; uint32_t _ideal_surface_height = _ideal_height / output->scale; @@ -297,7 +297,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t height = surface_height * output->scale; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, + get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, config->mode_pango_markup, "%s", mode); @@ -379,7 +379,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t height = surface_height * output->scale; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, + get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, config->pango_markup, "%s", name); int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; diff --git a/swaynag/render.c b/swaynag/render.c index 766409e46..7db9fe60a 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -12,7 +12,7 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { height -= swaynag->type->bar_border_thickness * swaynag->scale; int text_width, text_height; - get_text_size(cairo, swaynag->type->font, &text_width, &text_height, + get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, swaynag->scale, true, "%s", swaynag->message); int padding = swaynag->type->message_padding * swaynag->scale; @@ -34,7 +34,7 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { static void render_details_scroll_button(cairo_t *cairo, struct swaynag *swaynag, struct swaynag_button *button) { int text_width, text_height; - get_text_size(cairo, swaynag->type->font, &text_width, &text_height, + get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, swaynag->scale, true, "%s", button->text); int border = swaynag->type->button_border_thickness * swaynag->scale; @@ -60,10 +60,10 @@ static void render_details_scroll_button(cairo_t *cairo, static int get_detailed_scroll_button_width(cairo_t *cairo, struct swaynag *swaynag) { int up_width, down_width, temp_height; - get_text_size(cairo, swaynag->type->font, &up_width, &temp_height, + get_text_size(cairo, swaynag->type->font, &up_width, &temp_height, NULL, swaynag->scale, true, "%s", swaynag->details.button_up.text); - get_text_size(cairo, swaynag->type->font, &down_width, &temp_height, + get_text_size(cairo, swaynag->type->font, &down_width, &temp_height, NULL, swaynag->scale, true, "%s", swaynag->details.button_down.text); @@ -179,7 +179,7 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, struct swaynag_button *button = swaynag->buttons->items[button_index]; int text_width, text_height; - get_text_size(cairo, swaynag->type->font, &text_width, &text_height, + get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, swaynag->scale, true, "%s", button->text); int border = swaynag->type->button_border_thickness * swaynag->scale;