config: line-height, letter-spacing: values are in pt by default, but we allow px

If the value is specified without a unit, then the value is assumed to
be in points, subject to DPI scaling.

The value can optionally have a ‘px’ suffix, in which case the value
is treated as a raw pixel count.
This commit is contained in:
Daniel Eklöf 2021-01-07 17:00:58 +01:00
parent 4c9f593d91
commit a6fc8b5da4
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 97 additions and 61 deletions

View file

@ -2064,13 +2064,23 @@ box_drawing(const struct terminal *term, wchar_t wc)
};
draw_glyph(wc, &buf);
const struct config *conf = term->conf;
int x_ofs = conf->horizontal_letter_offset.px > 0
? conf->horizontal_letter_offset.px
: conf->horizontal_letter_offset.pt * term->font_dpi / 72.;
int y_ofs = conf->vertical_letter_offset.px > 0
? conf->vertical_letter_offset.px
: conf->vertical_letter_offset.pt * term->font_dpi / 72.;
struct fcft_glyph *glyph = xmalloc(sizeof(*glyph));
*glyph = (struct fcft_glyph){
.wc = wc,
.cols = 1,
.pix = pix,
.x = -term->conf->horizontal_letter_offset,
.y = term->conf->vertical_letter_offset + term->fonts[0]->ascent,
.x = -x_ofs,
.y = y_ofs + term->fonts[0]->ascent,
.width = width,
.height = height,
.advance = {

View file

@ -360,19 +360,6 @@ str_to_bool(const char *s)
strtoul(s, NULL, 0) > 0;
}
static bool
str_to_long(const char *s, int base, long *res)
{
if (s == NULL)
return false;
errno = 0;
char *end = NULL;
*res = strtol(s, &end, base);
return errno == 0 && *end == '\0';
}
static bool
str_to_ulong(const char *s, int base, unsigned long *res)
{
@ -422,6 +409,40 @@ str_to_color(const char *s, uint32_t *color, bool allow_alpha,
return true;
}
static bool
str_to_pt_or_px(const char *s, union pt_or_px *res, struct config *conf,
const char *path, int lineno, const char *section, const char *key)
{
size_t len = s != NULL ? strlen(s) : 0;
if (len >= 2 && s[len - 2] == 'p' && s[len - 1] == 'x') {
errno = 0;
char *end = NULL;
long value = strtol(s, &end, 10);
if (!(errno == 0 && end == s + len - 2)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [%s]: %s: "
"expected an integer directly followed by 'px', got '%s'",
path, lineno, section, key, s);
return false;
}
res->pt = 0;
res->px = value;
} else {
double value;
if (!str_to_double(s, &value)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [%s]: %s: expected a decimal value, got '%s'",
path, lineno, section, key, s);
return false;
}
res->pt = value;
res->px = 0;
}
return true;
}
static bool
parse_section_main(const char *key, const char *value, struct config *conf,
const char *path, unsigned lineno)
@ -572,47 +593,29 @@ parse_section_main(const char *key, const char *value, struct config *conf,
}
else if (strcmp(key, "line-height") == 0) {
unsigned long height;
if (!str_to_ulong(value, 10, &height)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [default]: line-height: expected an integer, got '%s'",
path, lineno, value);
if (!str_to_pt_or_px(value, &conf->line_height,
conf, path, lineno, "default", "line-height"))
return false;
}
conf->line_height = height;
}
else if (strcmp(key, "letter-spacing") == 0) {
long spacing;
if (!str_to_long(value, 10, &spacing)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [default]: letter-spacing: expected an integer, got '%s'",
path, lineno, value);
if (!str_to_pt_or_px(value, &conf->letter_spacing,
conf, path, lineno, "default", "letter-spacing"))
return false;
}
conf->letter_spacing = spacing;
}
else if (strcmp(key, "horizontal-letter-offset") == 0) {
long offset;
if (!str_to_long(value, 10, &offset)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [default]: horizontal-letter-offset: "
"expected an integer, got '%s'", path, lineno, value);
if (!str_to_pt_or_px(
value, &conf->horizontal_letter_offset,
conf, path, lineno, "default", "horizontal-letter-offset"))
return false;
}
conf->horizontal_letter_offset = offset;
}
else if (strcmp(key, "vertical-letter-offset") == 0) {
long offset;
if (!str_to_long(value, 10, &offset)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [default]: horizontal-letter-offset: "
"expected an integer, got '%s'", path, lineno, value);
if (!str_to_pt_or_px(
value, &conf->horizontal_letter_offset,
conf, path, lineno, "default", "vertical-letter-offset"))
return false;
}
conf->vertical_letter_offset = offset;
}
else if (strcmp(key, "dpi-aware") == 0) {
@ -2039,10 +2042,10 @@ config_load(struct config *conf, const char *conf_path,
.bell_action = BELL_ACTION_NONE,
.startup_mode = STARTUP_WINDOWED,
.fonts = {tll_init(), tll_init(), tll_init(), tll_init()},
.line_height = -1,
.letter_spacing = -1,
.horizontal_letter_offset = 0,
.vertical_letter_offset = 0,
.line_height = { .pt = 0, .px = -1, },
.letter_spacing = { .pt = 0, .px = 0, },
.horizontal_letter_offset = {.pt = 0, .px = 0, },
.vertical_letter_offset = {.pt = 0, .px = 0, },
.dpi_aware = DPI_AWARE_AUTO, /* DPI-aware when scaling-factor == 1 */
.scrollback = {
.lines = 1000,

View file

@ -54,6 +54,12 @@ struct config_mouse_binding {
} pipe;
};
/* If px == -1, neither px nor pt is valid. If px == 0, pt is valid, else px */
union pt_or_px {
int16_t px;
float pt;
};
struct config {
char *term;
char *shell;
@ -85,12 +91,12 @@ struct config {
config_font_list_t fonts[4];
/* Custom font metrics (-1 = use real font metrics) */
int16_t line_height;
int16_t letter_spacing;
union pt_or_px line_height;
union pt_or_px letter_spacing;
/* Adjusted letter x/y offsets */
int16_t horizontal_letter_offset;
int16_t vertical_letter_offset;
union pt_or_px horizontal_letter_offset;
union pt_or_px vertical_letter_offset;
struct {
int lines;

View file

@ -256,7 +256,7 @@ color_dim_for_search(pixman_color_t *color)
static inline int
font_baseline(const struct terminal *term)
{
return term->conf->vertical_letter_offset + term->fonts[0]->ascent;
return term->font_y_ofs + term->fonts[0]->ascent;
}
static void
@ -541,7 +541,7 @@ render_cell(struct terminal *term, pixman_image_t *pix,
pixman_image_t *clr_pix = pixman_image_create_solid_fill(&fg);
if (glyph != NULL) {
const int letter_x_ofs = term->conf->horizontal_letter_offset;
const int letter_x_ofs = term->font_x_ofs;
if (unlikely(pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8)) {
/* Glyph surface is a pre-rendered image (typically a color emoji...) */
@ -1693,7 +1693,7 @@ render_osd(struct terminal *term,
struct fcft_font *font = term->fonts[0];
pixman_color_t fg = color_hex_to_pixman(_fg);
const int x_ofs = term->conf->horizontal_letter_offset;
const int x_ofs = term->font_x_ofs;
for (size_t i = 0; i < wcslen(text); i++) {
const struct fcft_glyph *glyph = fcft_glyph_rasterize(
@ -2272,7 +2272,7 @@ render_search_box(struct terminal *term)
struct fcft_font *font = term->fonts[0];
const int x_left = width - visible_width + margin;
const int x_ofs = term->conf->horizontal_letter_offset;
const int x_ofs = term->font_x_ofs;
int x = x_left;
int y = margin;
pixman_color_t fg = color_hex_to_pixman(term->colors.table[0]);

View file

@ -629,15 +629,30 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
const int old_cell_width = term->cell_width;
const int old_cell_height = term->cell_height;
term->cell_width = (term->fonts[0]->space_advance.x > 0
? term->fonts[0]->space_advance.x
: term->fonts[0]->max_advance.x)
+ term->conf->letter_spacing;
const struct config *conf = term->conf;
term->cell_height = term->conf->line_height >= 0
? term->conf->line_height
term->cell_width =
(term->fonts[0]->space_advance.x > 0
? term->fonts[0]->space_advance.x
: term->fonts[0]->max_advance.x)
+ (conf->letter_spacing.px > 0
? conf->letter_spacing.px
: conf->letter_spacing.pt * term->font_dpi / 72.);
term->cell_height = conf->line_height.px >= 0
? (conf->line_height.px > 0
? conf->line_height.px
: conf->line_height.pt * term->font_dpi / 72.)
: max(term->fonts[0]->height,
term->fonts[0]->ascent + term->fonts[0]->descent);
term->font_x_ofs = conf->horizontal_letter_offset.px > 0
? conf->horizontal_letter_offset.px
: conf->horizontal_letter_offset.pt * term->font_dpi / 72.;
term->font_y_ofs = conf->vertical_letter_offset.px > 0
? conf->vertical_letter_offset.px
: conf->vertical_letter_offset.pt * term->font_dpi / 72.;
LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height);
if (term->cell_width < old_cell_width ||

View file

@ -265,6 +265,8 @@ struct terminal {
struct config_font *font_sizes[4];
float font_dpi;
int font_scale;
int16_t font_x_ofs;
int16_t font_y_ofs;
enum fcft_subpixel font_subpixel;
/*