From e955a14dd0bf7ed23a9e42f28a93e3357643300c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 07:41:57 +0200 Subject: [PATCH 1/4] wayland: calculate a single, scaled DPI value Previously, we calculated the monitors horizontal and vertical PPI values. For font sizing, we used the vertical PPI value. It seems however, that using the diagonal PPI value, i.e. diagonal_px / diagonal_inch, gives more consistent results. This is still a PPI value, but since it is intended to be used as a FontConfig DPI value, name it 'dpi'. --- wayland.c | 13 +++++++++++-- wayland.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 70d5e0f1..bb7405a2 100644 --- a/wayland.c +++ b/wayland.c @@ -294,11 +294,18 @@ output_update_ppi(struct monitor *mon) int x_inches = mon->dim.mm.width * 0.03937008; int y_inches = mon->dim.mm.height * 0.03937008; + mon->ppi.real.x = mon->dim.px_real.width / x_inches; mon->ppi.real.y = mon->dim.px_real.height / y_inches; mon->ppi.scaled.x = mon->dim.px_scaled.width / x_inches; mon->ppi.scaled.y = mon->dim.px_scaled.height / y_inches; + + float px_diag = sqrt( + pow(mon->dim.px_scaled.width, 2) + + pow(mon->dim.px_scaled.height, 2)); + + mon->dpi = px_diag / mon->inch * mon->scale; } static void @@ -343,6 +350,7 @@ output_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct monitor *mon = data; mon->scale = factor; + output_update_ppi(mon); } static const struct wl_output_listener output_listener = { @@ -1029,13 +1037,14 @@ wayl_init(const struct config *conf, struct fdm *fdm) tll_foreach(wayl->monitors, it) { LOG_INFO( - "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical)", + "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical), DPI=%.2f", it->item.name, it->item.dim.px_real.width, it->item.dim.px_real.height, it->item.x, it->item.y, (int)round(it->item.refresh), it->item.model != NULL ? it->item.model : it->item.description, it->item.inch, it->item.scale, it->item.ppi.real.x, it->item.ppi.real.y, - it->item.ppi.scaled.x, it->item.ppi.scaled.y); + it->item.ppi.scaled.x, it->item.ppi.scaled.y, + it->item.dpi); } wayl->fd = wl_display_get_fd(wayl->display); diff --git a/wayland.h b/wayland.h index dbf63c1b..88be3d71 100644 --- a/wayland.h +++ b/wayland.h @@ -236,6 +236,8 @@ struct monitor { } scaled; } ppi; + float dpi; + int scale; float refresh; enum wl_output_subpixel subpixel; From b08db1ef973bdb20d00e606b6dbb1aa5955eda66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 07:45:03 +0200 Subject: [PATCH 2/4] term: store current font DPI as a float instead of an integer FontConfig's DPI is a double, and using a float instead of an integer results in higher resolution. --- terminal.c | 22 +++++++++++----------- terminal.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/terminal.c b/terminal.c index 86672f06..d7f05c30 100644 --- a/terminal.c +++ b/terminal.c @@ -559,7 +559,7 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) return true; } -static unsigned +static float get_font_dpi(const struct terminal *term) { /* @@ -584,7 +584,7 @@ get_font_dpi(const struct terminal *term) */ /* Use highest DPI from outputs we're mapped on */ - unsigned dpi = 0; + double dpi = 0.0; assert(term->window != NULL); tll_foreach(term->window->on_outputs, it) { if (it->item->ppi.scaled.y > dpi) @@ -592,7 +592,7 @@ get_font_dpi(const struct terminal *term) } /* If we're not mapped, use DPI from first monitor. Hopefully this is where we'll get mapped later... */ - if (dpi == 0) { + if (dpi == 0.) { tll_foreach(term->wl->monitors, it) { dpi = it->item.ppi.scaled.y * term->scale; break; @@ -601,7 +601,7 @@ get_font_dpi(const struct terminal *term) if (dpi == 0) { /* No monitors? */ - dpi = 96; + dpi = 96.; } return dpi; @@ -692,10 +692,10 @@ reload_fonts(struct terminal *term) } char attrs0[256], attrs1[256], attrs2[256], attrs3[256]; - snprintf(attrs0, sizeof(attrs0), "dpi=%u", term->font_dpi); - snprintf(attrs1, sizeof(attrs1), "dpi=%u:weight=bold", term->font_dpi); - snprintf(attrs2, sizeof(attrs2), "dpi=%u:slant=italic", term->font_dpi); - snprintf(attrs3, sizeof(attrs3), "dpi=%u:weight=bold:slant=italic", term->font_dpi); + snprintf(attrs0, sizeof(attrs0), "dpi=%.2f", term->font_dpi); + snprintf(attrs1, sizeof(attrs1), "dpi=%.2f:weight=bold", term->font_dpi); + snprintf(attrs2, sizeof(attrs2), "dpi=%.2f:slant=italic", term->font_dpi); + snprintf(attrs3, sizeof(attrs3), "dpi=%.2f:weight=bold:slant=italic", term->font_dpi); struct fcft_font *fonts[4]; struct font_load_data data[4] = { @@ -836,7 +836,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .ptmx = ptmx, .ptmx_buffer = tll_init(), .font_sizes = malloc(sizeof(term->font_sizes[0]) * tll_length(conf->fonts)), - .font_dpi = 0, + .font_dpi = 0., .font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */ ? FCFT_SUBPIXEL_DEFAULT : FCFT_SUBPIXEL_NONE), @@ -1490,11 +1490,11 @@ term_font_size_reset(struct terminal *term) bool term_font_dpi_changed(struct terminal *term) { - unsigned dpi = get_font_dpi(term); + float dpi = get_font_dpi(term); if (dpi == term->font_dpi) return true; - LOG_DBG("DPI changed (%u -> %u): reloading fonts", term->font_dpi, dpi); + LOG_DBG("DPI changed (%.2f -> %.2f): reloading fonts", term->font_dpi, dpi); term->font_dpi = dpi; return reload_fonts(term); diff --git a/terminal.h b/terminal.h index 85f89abf..d82e3e93 100644 --- a/terminal.h +++ b/terminal.h @@ -223,7 +223,7 @@ struct terminal { struct fcft_font *fonts[4]; struct config_font *font_sizes; - int font_dpi; + float font_dpi; enum fcft_subpixel font_subpixel; tll(struct ptmx_buffer) ptmx_buffer; From 6e909d5cd3e996f4d7800fa9539060aa0d037df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 07:45:55 +0200 Subject: [PATCH 3/4] term: use the monitors diagonal DPI value, instead of it's vertical PPI value --- terminal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terminal.c b/terminal.c index d7f05c30..1a560ef2 100644 --- a/terminal.c +++ b/terminal.c @@ -587,14 +587,14 @@ get_font_dpi(const struct terminal *term) double dpi = 0.0; assert(term->window != NULL); tll_foreach(term->window->on_outputs, it) { - if (it->item->ppi.scaled.y > dpi) - dpi = it->item->ppi.scaled.y * term->scale; + if (it->item->dpi > dpi) + dpi = it->item->dpi; } /* If we're not mapped, use DPI from first monitor. Hopefully this is where we'll get mapped later... */ if (dpi == 0.) { tll_foreach(term->wl->monitors, it) { - dpi = it->item.ppi.scaled.y * term->scale; + dpi = it->item.dpi; break; } } From df758806726e25f5b26187a0b3e1e798c43a9a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 20:00:32 +0200 Subject: [PATCH 4/4] changelog: improved font size consistency across monitors with different DPI --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df304262..7bb7f4fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ ### Fixed * Crash in scrollback search +* Improved font size consistency across multiple monitors with + different DPI (https://codeberg.org/dnkl/foot/issues/47). ### Security