From 8e7658a135ae05c790094f2b1b681c7f64f05cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 17 Nov 2020 17:59:31 +0100 Subject: [PATCH] =?UTF-8?q?config:=20add=20=E2=80=98dpi-aware=E2=80=99=20o?= =?UTF-8?q?ption,=20defaulting=20to=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When disabled, foot no longers uses outputs’ DPI to scale the font. Instead, it uses the outputs’ scaling factor. That is, instead of appending “:dpi=123” to the fontconfig string, modify the “:pixelsize” or “:size” attribute. Closes #206 --- CHANGELOG.md | 4 +++ config.c | 4 +++ config.h | 1 + doc/foot.ini.5.scd | 15 ++++++++++ foot.ini | 1 + terminal.c | 72 +++++++++++++++++++++++++++++++++++++++------- terminal.h | 1 + 7 files changed, 87 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a15ad01..79065f02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,10 @@ * **bold-text-in-bright** option to `foot.ini`. When enabled, bold text is rendered in a brighter color (https://codeberg.org/dnkl/foot/issues/199). +* **dpi-aware** option to `foot.ini`. The default, **enabled**, + implements foot's old font sizing behavior. But, when **disabled**, + foot will ignore the monitors' DPI and instead size fonts using the + scale factor alone (https://codeberg.org/dnkl/foot/issues/206). ### Changed diff --git a/config.c b/config.c index 3e47179b..4a4a6820 100644 --- a/config.c +++ b/config.c @@ -578,6 +578,9 @@ parse_section_main(const char *key, const char *value, struct config *conf, free(copy); } + else if (strcmp(key, "dpi-aware") == 0) + conf->dpi_aware = str_to_bool(value); + else if (strcmp(key, "workers") == 0) { unsigned long count; if (!str_to_ulong(value, 10, &count)) { @@ -2024,6 +2027,7 @@ config_load(struct config *conf, const char *conf_path, .bell_is_urgent = false, .startup_mode = STARTUP_WINDOWED, .fonts = {tll_init(), tll_init(), tll_init(), tll_init()}, + .dpi_aware = true, /* Use DPI by default, not scale factor */ .scrollback = { .lines = 1000, .indicator = { diff --git a/config.h b/config.h index a173015f..2c57850c 100644 --- a/config.h +++ b/config.h @@ -84,6 +84,7 @@ struct config { enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode; + bool dpi_aware; config_font_list_t fonts[4]; struct { diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index cfa5b667..98a4ce54 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -45,6 +45,21 @@ in this order: Default: _monospace_ (*font*), _not set_ (*font-bold*, *font-italic*, *font-bold-italic*). +*dpi-aware* + Boolean. When enabled, fonts are sized using the monitor's DPI, + making a font of a given size have the same physical size, + regardless of monitor. In other words, if you drag a foot window + between different monitors, the font size remains the same. + + In this mode, the monitor's scale factor is ignored; doubling the + scale factor will *not* double the font size. + + When disabled, the monitor's DPI is ignored. The font is instead + sized using the monitor's scale factor; doubling the scale factor + *does* double the font size. + + Default: _yes_ + *pad* Padding between border and glyphs, in pixels (subject to output scaling), on the form _XxY_. Default: _2x2_. diff --git a/foot.ini b/foot.ini index 7ab950c5..abf1353d 100644 --- a/foot.ini +++ b/foot.ini @@ -4,6 +4,7 @@ # font-bold= # font-italic= # font-bold-italic= +# dpi-aware=yes # initial-window-size-pixels=700x500 # Or, # initial-window-size-chars= # initial-window-mode=windowed diff --git a/terminal.c b/terminal.c index d117bf9c..bfd5ca58 100644 --- a/terminal.c +++ b/terminal.c @@ -701,6 +701,31 @@ get_font_dpi(const struct terminal *term) return dpi; } +static int +get_font_scale(const struct terminal *term) +{ + /* Same as get_font_dpi(), but returns output scale factor instead */ + int scale = 0; + + assert(term->window != NULL); + tll_foreach(term->window->on_outputs, it) { + if (it->item->scale > scale) + scale = it->item->scale; + } + + if (scale == 0) { + tll_foreach(term->wl->monitors, it) { + scale = it->item.scale; + break; + } + } + + if (scale == 0) + scale = 1; + + return scale; +} + static enum fcft_subpixel get_font_subpixel(const struct terminal *term) { @@ -781,10 +806,14 @@ reload_fonts(struct terminal *term) bool use_px_size = term->font_sizes[i][j].px_size > 0; char size[64]; + const int scale = term->conf->dpi_aware ? 1 : term->scale; + if (use_px_size) - snprintf(size, sizeof(size), ":pixelsize=%d", term->font_sizes[i][j].px_size); + snprintf(size, sizeof(size), ":pixelsize=%d", + term->font_sizes[i][j].px_size * scale); else - snprintf(size, sizeof(size), ":size=%.2f", term->font_sizes[i][j].pt_size); + snprintf(size, sizeof(size), ":size=%.2f", + term->font_sizes[i][j].pt_size * (double)scale); size_t len = strlen(it->item.pattern) + strlen(size) + 1; names[i][j] = xmalloc(len); @@ -813,14 +842,24 @@ reload_fonts(struct terminal *term) const size_t count_bold_italic = custom_bold_italic ? counts[3] : counts[0]; const char **names_bold_italic = (const char **)(custom_bold_italic ? names[3] : names[0]); + const bool use_dpi = term->conf->dpi_aware; + char *attrs[4] = {NULL}; int attr_len[4] = {-1, -1, -1, -1}; /* -1, so that +1 (below) results in 0 */ for (size_t i = 0; i < 2; i++) { - attr_len[0] = snprintf(attrs[0], attr_len[0] + 1, "dpi=%.2f", term->font_dpi); - attr_len[1] = snprintf(attrs[1], attr_len[1] + 1, "dpi=%.2f:%s", term->font_dpi, !custom_bold ? "weight=bold" : ""); - attr_len[2] = snprintf(attrs[2], attr_len[2] + 1, "dpi=%.2f:%s", term->font_dpi, !custom_italic ? "slant=italic" : ""); - attr_len[3] = snprintf(attrs[3], attr_len[3] + 1, "dpi=%.2f:%s", term->font_dpi, !custom_bold_italic ? "weight=bold:slant=italic" : ""); + attr_len[0] = snprintf( + attrs[0], attr_len[0] + 1, "dpi=%.2f", + use_dpi ? term->font_dpi : 75); + attr_len[1] = snprintf( + attrs[1], attr_len[1] + 1, "dpi=%.2f:%s", + use_dpi ? term->font_dpi : 75, !custom_bold ? "weight=bold" : ""); + attr_len[2] = snprintf( + attrs[2], attr_len[2] + 1, "dpi=%.2f:%s", + use_dpi ? term->font_dpi : 75, !custom_italic ? "slant=italic" : ""); + attr_len[3] = snprintf( + attrs[3], attr_len[3] + 1, "dpi=%.2f:%s", + use_dpi ? term->font_dpi : 75, !custom_bold_italic ? "weight=bold:slant=italic" : ""); if (i > 0) continue; @@ -973,6 +1012,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, xmalloc(sizeof(term->font_sizes[3][0]) * tll_length(conf->fonts[3])), }, .font_dpi = 0., + .font_scale = 0, .font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */ ? FCFT_SUBPIXEL_DEFAULT : FCFT_SUBPIXEL_NONE), @@ -1619,12 +1659,22 @@ term_font_size_reset(struct terminal *term) bool term_font_dpi_changed(struct terminal *term) { - float dpi = get_font_dpi(term); - if (dpi == term->font_dpi) - return true; + if (term->conf->dpi_aware) { + float dpi = get_font_dpi(term); + if (dpi == term->font_dpi) + return true; - LOG_DBG("DPI changed (%.2f -> %.2f): reloading fonts", term->font_dpi, dpi); - term->font_dpi = dpi; + LOG_DBG("DPI changed (%.2f -> %.2f): reloading fonts", term->font_dpi, dpi); + term->font_dpi = dpi; + } else { + int scale = get_font_scale(term); + if (scale == term->font_scale) + return true; + + LOG_DBG("scale factor changed (%d -> %d): reloading fonts", + term->font_scale, scale); + term->font_scale = scale; + } return reload_fonts(term); } diff --git a/terminal.h b/terminal.h index 5c7a9501..752057fd 100644 --- a/terminal.h +++ b/terminal.h @@ -227,6 +227,7 @@ struct terminal { struct fcft_font *fonts[4]; struct config_font *font_sizes[4]; float font_dpi; + int font_scale; enum fcft_subpixel font_subpixel; bool is_sending_paste_data;