forked from external/yambar
config: add inheritable option “font-shaping”
This patch adds an inheritable option, “font-shaping”, that controls whether a particle that renders text should enable font-shaping or not. The option works similar to the ‘font’ option: one can set it at the top-level, and it gets inherited down through all modules and to their particles. Or, you can set it on a module and it gets inherited to all its particles, but not to other modules’ particles. Finally, you can set it on individual particles, in which case it only applies to them (or “child” particles). When font-shaping is enabled (the default), the string particle shapes full text runs using the fcft_rasterize_text_run_utf32() API. In fcft, this results in HarfBuzz being used to shape the string. When disabled, the string particle instead uses the simpler fcft_rasterize_char_utf32() API, which rasterizes individual characters. This gives user greater control over the font rendering. One example is bitmap fonts, which HarfBuzz often doesn’t get right. Closes #159
This commit is contained in:
parent
265188ca4c
commit
ffccabbb13
17 changed files with 106 additions and 8 deletions
|
@ -17,6 +17,9 @@
|
|||
* overline: new decoration
|
||||
(https://codeberg.org/dnkl/yambar/issues/153).
|
||||
* i3/sway: boolean option `strip-workspace-numbers`.
|
||||
* font-shaping: new inheritable configuration option, allowing you to
|
||||
configure whether strings should be _shaped_ using HarfBuzz, or not
|
||||
(https://codeberg.org/dnkl/yambar/issues/159).
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../color.h"
|
||||
#include "../font-shaping.h"
|
||||
#include "../module.h"
|
||||
|
||||
struct bar {
|
||||
|
@ -26,6 +27,7 @@ struct bar_config {
|
|||
const char *monitor;
|
||||
enum bar_layer layer;
|
||||
enum bar_location location;
|
||||
enum font_shaping font_shaping;
|
||||
int height;
|
||||
int left_spacing, right_spacing;
|
||||
int left_margin, right_margin;
|
||||
|
|
|
@ -228,6 +228,13 @@ conf_verify_font(keychain_t *chain, const struct yml_node *node)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
conf_verify_font_shaping(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
return conf_verify_enum(
|
||||
chain, node, (const char *[]){"full", /*"graphemes",*/ "none"}, 2);
|
||||
}
|
||||
|
||||
bool
|
||||
conf_verify_decoration(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
|
@ -450,6 +457,7 @@ conf_verify_bar(const struct yml_node *bar)
|
|||
|
||||
{"border", false, &verify_bar_border},
|
||||
{"font", false, &conf_verify_font},
|
||||
{"font-shaping", false, &conf_verify_font_shaping},
|
||||
{"foreground", false, &conf_verify_color},
|
||||
|
||||
{"left", false, &verify_module_list},
|
||||
|
|
|
@ -45,6 +45,7 @@ bool conf_verify_dict(keychain_t *chain, const struct yml_node *node,
|
|||
bool conf_verify_on_click(keychain_t *chain, const struct yml_node *node);
|
||||
bool conf_verify_color(keychain_t *chain, const struct yml_node *node);
|
||||
bool conf_verify_font(keychain_t *chain, const struct yml_node *node);
|
||||
bool conf_verify_font_shaping(keychain_t *chain, const struct yml_node *node);
|
||||
|
||||
bool conf_verify_particle(keychain_t *chain, const struct yml_node *node);
|
||||
bool conf_verify_particle_list_items(keychain_t *chain, const struct yml_node *node);
|
||||
|
|
56
config.c
56
config.c
|
@ -101,6 +101,44 @@ conf_to_font(const struct yml_node *node)
|
|||
return ret;
|
||||
}
|
||||
|
||||
enum font_shaping
|
||||
conf_to_font_shaping(const struct yml_node *node)
|
||||
{
|
||||
const char *v = yml_value_as_string(node);
|
||||
|
||||
if (strcmp(v, "none") == 0)
|
||||
return FONT_SHAPE_NONE;
|
||||
|
||||
else if (strcmp(v, "graphemes") == 0) {
|
||||
static bool have_warned = false;
|
||||
|
||||
if (!have_warned &&
|
||||
!(fcft_capabilities() & FCFT_CAPABILITY_GRAPHEME_SHAPING))
|
||||
{
|
||||
have_warned = true;
|
||||
LOG_WARN("cannot enable grapheme shaping; no support in fcft");
|
||||
}
|
||||
return FONT_SHAPE_GRAPHEMES;
|
||||
}
|
||||
|
||||
else if (strcmp(v, "full") == 0) {
|
||||
static bool have_warned = false;
|
||||
|
||||
if (!have_warned &&
|
||||
!(fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING))
|
||||
{
|
||||
have_warned = true;
|
||||
LOG_WARN("cannot enable full text shaping; no support in fcft");
|
||||
}
|
||||
return FONT_SHAPE_FULL;
|
||||
}
|
||||
|
||||
else {
|
||||
assert(false);
|
||||
return FONT_SHAPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
struct deco *
|
||||
conf_to_deco(const struct yml_node *node)
|
||||
{
|
||||
|
@ -144,7 +182,8 @@ particle_simple_list_from_config(const struct yml_node *node,
|
|||
}
|
||||
|
||||
struct particle *common = particle_common_new(
|
||||
0, 0, NULL, fcft_clone(inherited.font), inherited.foreground, NULL);
|
||||
0, 0, NULL, fcft_clone(inherited.font), inherited.font_shaping,
|
||||
inherited.foreground, NULL);
|
||||
|
||||
return particle_list_new(common, parts, count, 0, 2);
|
||||
}
|
||||
|
@ -163,6 +202,7 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
|
|||
const struct yml_node *right_margin = yml_get_value(pair.value, "right-margin");
|
||||
const struct yml_node *on_click = yml_get_value(pair.value, "on-click");
|
||||
const struct yml_node *font_node = yml_get_value(pair.value, "font");
|
||||
const struct yml_node *font_shaping_node = yml_get_value(pair.value, "font-shaping");
|
||||
const struct yml_node *foreground_node = yml_get_value(pair.value, "foreground");
|
||||
const struct yml_node *deco_node = yml_get_value(pair.value, "deco");
|
||||
|
||||
|
@ -215,12 +255,14 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
|
|||
*/
|
||||
struct fcft_font *font = font_node != NULL
|
||||
? conf_to_font(font_node) : fcft_clone(inherited.font);
|
||||
enum font_shaping font_shaping = font_shaping_node != NULL
|
||||
? conf_to_font_shaping(font_shaping_node) : inherited.font_shaping;
|
||||
pixman_color_t foreground = foreground_node != NULL
|
||||
? conf_to_color(foreground_node) : inherited.foreground;
|
||||
|
||||
/* Instantiate base/common particle */
|
||||
struct particle *common = particle_common_new(
|
||||
left, right, on_click_templates, font, foreground, deco);
|
||||
left, right, on_click_templates, font, font_shaping, foreground, deco);
|
||||
|
||||
const struct particle_iface *iface = plugin_load_particle(type);
|
||||
|
||||
|
@ -237,6 +279,7 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
|
|||
struct bar_config conf = {
|
||||
.backend = backend,
|
||||
.layer = BAR_LAYER_BOTTOM,
|
||||
.font_shaping = FONT_SHAPE_FULL,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -359,6 +402,7 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
|
|||
* foreground color at top-level.
|
||||
*/
|
||||
struct fcft_font *font = fcft_from_name(1, &(const char *){"sans"}, NULL);
|
||||
enum font_shaping font_shaping = FONT_SHAPE_FULL;
|
||||
pixman_color_t foreground = {0xffff, 0xffff, 0xffff, 0xffff}; /* White */
|
||||
|
||||
const struct yml_node *font_node = yml_get_value(bar, "font");
|
||||
|
@ -367,12 +411,17 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
|
|||
font = conf_to_font(font_node);
|
||||
}
|
||||
|
||||
const struct yml_node *font_shaping_node = yml_get_value(bar, "font-shaping");
|
||||
if (font_shaping_node != NULL)
|
||||
font_shaping = conf_to_font_shaping(font_shaping_node);
|
||||
|
||||
const struct yml_node *foreground_node = yml_get_value(bar, "foreground");
|
||||
if (foreground_node != NULL)
|
||||
foreground = conf_to_color(foreground_node);
|
||||
|
||||
struct conf_inherit inherited = {
|
||||
.font = font,
|
||||
.font_shaping = font_shaping,
|
||||
.foreground = foreground,
|
||||
};
|
||||
|
||||
|
@ -402,12 +451,15 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
|
|||
* applied to all its particles.
|
||||
*/
|
||||
const struct yml_node *mod_font = yml_get_value(m.value, "font");
|
||||
const struct yml_node *mod_font_shaping = yml_get_value(m.value, "font-shaping");
|
||||
const struct yml_node *mod_foreground = yml_get_value(
|
||||
m.value, "foreground");
|
||||
|
||||
struct conf_inherit mod_inherit = {
|
||||
.font = mod_font != NULL
|
||||
? conf_to_font(mod_font) : inherited.font,
|
||||
.font_shaping = mod_font_shaping != NULL
|
||||
? conf_to_font_shaping(mod_font_shaping) : inherited.font_shaping,
|
||||
.foreground = mod_foreground != NULL
|
||||
? conf_to_color(mod_foreground) : inherited.foreground,
|
||||
};
|
||||
|
|
3
config.h
3
config.h
|
@ -3,6 +3,7 @@
|
|||
#include <fcft/fcft.h>
|
||||
#include "yml.h"
|
||||
#include "bar/bar.h"
|
||||
#include "font-shaping.h"
|
||||
|
||||
struct bar;
|
||||
struct particle;
|
||||
|
@ -16,9 +17,11 @@ struct bar *conf_to_bar(const struct yml_node *bar, enum bar_backend backend);
|
|||
|
||||
pixman_color_t conf_to_color(const struct yml_node *node);
|
||||
struct fcft_font *conf_to_font(const struct yml_node *node);
|
||||
enum font_shaping conf_to_font_shaping(const struct yml_node *node);
|
||||
|
||||
struct conf_inherit {
|
||||
const struct fcft_font *font;
|
||||
enum font_shaping font_shaping;
|
||||
pixman_color_t foreground;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,12 @@ following attributes are supported by all particles:
|
|||
: Font to use. Note that this is an inherited attribute; i.e. you can
|
||||
set it on e.g. a _list_ particle, and it will apply to all
|
||||
particles in the list.
|
||||
| font-shaping
|
||||
: enum
|
||||
: no
|
||||
: font-shaping; one of _full_ or _none_. When set to _full_ (the
|
||||
default), strings will be "shaped" using HarfBuzz. Requires support
|
||||
in fcft.
|
||||
| foreground
|
||||
: color
|
||||
: no
|
||||
|
|
|
@ -130,6 +130,12 @@ types that are frequently used:
|
|||
the primary font, and the rest fallback fonts. These are yambar
|
||||
custom fallback fonts that will be searched before the fontconfig
|
||||
provided fallback list.
|
||||
| font-shaping
|
||||
: enum
|
||||
: no
|
||||
: Default setting for font-shaping, for use in particles. One of
|
||||
_full_ or _none_. When set to _full_ (the default), strings will be
|
||||
"shaped" using HarfBuzz. Requires support in fcft.
|
||||
| foreground
|
||||
: color
|
||||
: no
|
||||
|
|
7
font-shaping.h
Normal file
7
font-shaping.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
enum font_shaping {
|
||||
FONT_SHAPE_NONE,
|
||||
FONT_SHAPE_GRAPHEMES,
|
||||
FONT_SHAPE_FULL,
|
||||
};
|
|
@ -116,6 +116,7 @@ yambar = executable(
|
|||
'config-verify.c', 'config-verify.h',
|
||||
'config.c', 'config.h',
|
||||
'decoration.h',
|
||||
'font-shaping.h',
|
||||
'log.c', 'log.h',
|
||||
'main.c',
|
||||
'module.c', 'module.h',
|
||||
|
|
|
@ -31,14 +31,15 @@ particle_default_destroy(struct particle *particle)
|
|||
struct particle *
|
||||
particle_common_new(int left_margin, int right_margin,
|
||||
const char **on_click_templates,
|
||||
struct fcft_font *font, pixman_color_t foreground,
|
||||
struct deco *deco)
|
||||
struct fcft_font *font, enum font_shaping font_shaping,
|
||||
pixman_color_t foreground, struct deco *deco)
|
||||
{
|
||||
struct particle *p = calloc(1, sizeof(*p));
|
||||
p->left_margin = left_margin;
|
||||
p->right_margin = right_margin;
|
||||
p->foreground = foreground;
|
||||
p->font = font;
|
||||
p->font_shaping = font_shaping;
|
||||
p->deco = deco;
|
||||
|
||||
if (on_click_templates != NULL) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "color.h"
|
||||
#include "decoration.h"
|
||||
#include "font-shaping.h"
|
||||
#include "tag.h"
|
||||
|
||||
enum mouse_event {
|
||||
|
@ -35,6 +36,7 @@ struct particle {
|
|||
|
||||
pixman_color_t foreground;
|
||||
struct fcft_font *font;
|
||||
enum font_shaping font_shaping;
|
||||
struct deco *deco;
|
||||
|
||||
void (*destroy)(struct particle *particle);
|
||||
|
@ -61,7 +63,8 @@ struct exposable {
|
|||
|
||||
struct particle *particle_common_new(
|
||||
int left_margin, int right_margin, const char *on_click_templates[],
|
||||
struct fcft_font *font, pixman_color_t foreground, struct deco *deco);
|
||||
struct fcft_font *font, enum font_shaping font_shaping,
|
||||
pixman_color_t foreground, struct deco *deco);
|
||||
|
||||
void particle_default_destroy(struct particle *particle);
|
||||
|
||||
|
@ -82,6 +85,7 @@ void exposable_default_on_mouse(
|
|||
{"right-margin", false, &conf_verify_unsigned}, \
|
||||
{"on-click", false, &conf_verify_on_click}, \
|
||||
{"font", false, &conf_verify_font}, \
|
||||
{"font-shaping", false, &conf_verify_font_shaping}, \
|
||||
{"foreground", false, &conf_verify_color}, \
|
||||
{"deco", false, &conf_verify_decoration}, \
|
||||
{NULL, false, NULL}
|
||||
|
|
|
@ -197,7 +197,7 @@ from_conf(const struct yml_node *node, struct particle *common)
|
|||
yml_list_next(&it), idx++)
|
||||
{
|
||||
parts[idx] = conf_to_particle(
|
||||
it.node, (struct conf_inherit){common->font, common->foreground});
|
||||
it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground});
|
||||
}
|
||||
|
||||
return particle_list_new(common, parts, count, left_spacing, right_spacing);
|
||||
|
|
|
@ -215,6 +215,7 @@ from_conf(const struct yml_node *node, struct particle *common)
|
|||
|
||||
struct conf_inherit inherited = {
|
||||
.font = common->font,
|
||||
.font_shaping = common->font_shaping,
|
||||
.foreground = common->foreground
|
||||
};
|
||||
|
||||
|
|
|
@ -304,6 +304,7 @@ from_conf(const struct yml_node *node, struct particle *common)
|
|||
|
||||
struct conf_inherit inherited = {
|
||||
.font = common->font,
|
||||
.font_shaping = common->font_shaping,
|
||||
.foreground = common->foreground,
|
||||
};
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ from_conf(const struct yml_node *node, struct particle *common)
|
|||
yml_list_next(&it), idx++)
|
||||
{
|
||||
parts[idx] = conf_to_particle(
|
||||
it.node, (struct conf_inherit){common->font, common->foreground});
|
||||
it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground});
|
||||
}
|
||||
|
||||
long min_v = min != NULL ? yml_value_as_int(min) : 0;
|
||||
|
|
|
@ -202,7 +202,9 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
|||
|
||||
e->kern_x = calloc(chars, sizeof(e->kern_x[0]));
|
||||
|
||||
if (fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) {
|
||||
if (particle->font_shaping == FONT_SHAPE_FULL &&
|
||||
fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING)
|
||||
{
|
||||
struct fcft_text_run *run = fcft_rasterize_text_run_utf32(
|
||||
font, chars, wtext, FCFT_SUBPIXEL_NONE);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue