Add scalable font support.

This commit is contained in:
John Vogel 2015-05-26 22:29:18 -04:00
parent a9f285fd28
commit 4eba66912f
2 changed files with 92 additions and 8 deletions

View File

@ -6,7 +6,7 @@ lemonbar - Featherweight lemon-scented bar
=head1 SYNOPSIS =head1 SYNOPSIS
I<lemonbar> [-h | -g I<width>B<x>I<height>B<+>I<x>B<+>I<y> | -b | -d | -f I<font> | -p | -u I<pixel> | -B I<color> | -F I<color>] I<lemonbar> [-h | -g I<width>B<x>I<height>B<+>I<x>B<+>I<y> | -b | -d | -s | -f I<font> | -p | -u I<pixel> | -B I<color> | -F I<color>]
=head1 DESCRIPTION =head1 DESCRIPTION
@ -32,6 +32,10 @@ Dock the bar at the bottom of the screen.
Force docking without asking the window manager. This is needed if the window manager isn't EWMH compliant. Force docking without asking the window manager. This is needed if the window manager isn't EWMH compliant.
=item B<-s>
Scale fonts. Must be ahead of any I<font> that should be scaled. A way to scale some but not all fonts is to put unscaled fonts before using I<-s>, then place all scaled fonts after using I<-s>.
=item B<-f> I<font> =item B<-f> I<font>
Define the font to load into one of the five slots (the number of slots is hardcoded and can be tweaked by Define the font to load into one of the five slots (the number of slots is hardcoded and can be tweaked by

View File

@ -88,6 +88,7 @@ static monitor_t *monhead, *montail;
static font_t *font_list[MAX_FONT_COUNT]; static font_t *font_list[MAX_FONT_COUNT];
static int font_count = 0; static int font_count = 0;
static int font_index = -1; static int font_index = -1;
static int scale_fonts = 0;
static uint32_t attrs = 0; static uint32_t attrs = 0;
static bool dock = false; static bool dock = false;
static bool topbar = true; static bool topbar = true;
@ -609,6 +610,68 @@ parse (char *text)
} }
} }
char *
scale_font(const char *name)
{
char *newname;
size_t sz;
int i, j, field;
int res_x, res_y;
unsigned long pixel_size = 0L;
if (!name || !*name)
return NULL;
sz = strlen(name) * 2; /* make big enough to avoid overflows */
newname = malloc(sz+1);
if (!newname) {
fprintf(stderr, "Failed to allocate new scalable fontname\n");
exit(EXIT_FAILURE);
}
/* calculate our screen resolution in dots per inch */
res_x = scr->width_in_pixels / (scr->width_in_millimeters / 25.4);
res_y = scr->height_in_pixels / (scr->height_in_millimeters / 25.4);
/* copy the font name, changing the scalable fields as we go */
for (i = j = field = 0; name[i] && field <= 14; i++) {
newname[j++] = name[i];
if (name[i] == '-') {
field++;
switch (field) {
case 7: /* pixel size */
pixel_size = strtoul(&name[i+1], NULL, 10);
case 12: /* average width */
newname[j] = '*';
j++;
while (name[i+1] != '-' && name[i+1] != '\0') i++;
break;
case 8: /* point size */
snprintf(&newname[j], sz-j, "%ld", pixel_size * 10);
while (newname[j] != '\0') j++;
while (name[i+1] != '-' && name[i+1] != '\0') i++;
break;
case 9: /* x resolution */
case 10: /* y resolution */
/* change from an unspecified resolution to res_x or res_y */
snprintf(&newname[j], sz-j, "%d", (field == 9) ? res_x : res_y);
while (newname[j] != '\0') j++;
while (name[i+1] != '-' && name[i+1] != '\0') i++;
break;
}
}
}
if (field != 14) {
printf("font name has invalid number of fields(%d): %s\n", field, name);
return NULL;
}
newname[j] = '\0';
return newname;
}
void void
font_load (const char *pattern) font_load (const char *pattern)
{ {
@ -616,19 +679,32 @@ font_load (const char *pattern)
xcb_query_font_reply_t *font_info; xcb_query_font_reply_t *font_info;
xcb_void_cookie_t cookie; xcb_void_cookie_t cookie;
xcb_font_t font; xcb_font_t font;
int is_scaled = false;
char *fontname = NULL;
if (scale_fonts)
fontname = scale_font(pattern);
if (fontname)
is_scaled = true;
else
fontname = (char *)pattern;
font = xcb_generate_id(c); font = xcb_generate_id(c);
cookie = xcb_open_font_checked(c, font, strlen(pattern), pattern); cookie = xcb_open_font_checked(c, font, strlen(fontname), fontname);
if (xcb_request_check (c, cookie)) { if (xcb_request_check (c, cookie)) {
fprintf(stderr, "Could not load font \"%s\"\n", pattern); fprintf(stderr, "Could not load font \"%s\"\n", fontname);
if (is_scaled)
free(fontname);
return; return;
} }
font_t *ret = calloc(1, sizeof(font_t)); font_t *ret = calloc(1, sizeof(font_t));
if (!ret) {
if (!ret) fprintf(stderr, "Failed to allocate space for font\n");
return; exit(EXIT_FAILURE);
}
queryreq = xcb_query_font(c, font); queryreq = xcb_query_font(c, font);
font_info = xcb_query_font_reply(c, queryreq, NULL); font_info = xcb_query_font_reply(c, queryreq, NULL);
@ -648,6 +724,8 @@ font_load (const char *pattern)
} }
free(font_info); free(font_info);
if (is_scaled)
free(fontname);
font_list[font_count++] = ret; font_list[font_count++] = ret;
} }
@ -1214,15 +1292,16 @@ main (int argc, char **argv)
ugc = fgc; ugc = fgc;
while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { while ((ch = getopt(argc, argv, "hg:bdsf:a:pu:B:F:")) != -1) {
switch (ch) { switch (ch) {
case 'h': case 'h':
printf ("lemonbar version %s\n", VERSION); printf ("lemonbar version %s\n", VERSION);
printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -B | -F]\n" printf ("usage: %s [-h | -g | -b | -d | -s | -f | -a | -p | -u | -B | -F]\n"
"\t-h Show this help\n" "\t-h Show this help\n"
"\t-g Set the bar geometry {width}x{height}+{xoffset}+{yoffset}\n" "\t-g Set the bar geometry {width}x{height}+{xoffset}+{yoffset}\n"
"\t-b Put the bar at the bottom of the screen\n" "\t-b Put the bar at the bottom of the screen\n"
"\t-d Force docking (use this if your WM isn't EWMH compliant)\n" "\t-d Force docking (use this if your WM isn't EWMH compliant)\n"
"\t-s Scale fonts\n"
"\t-f Set the font name to use\n" "\t-f Set the font name to use\n"
"\t-p Don't close after the data ends\n" "\t-p Don't close after the data ends\n"
"\t-u Set the underline/overline height in pixels\n" "\t-u Set the underline/overline height in pixels\n"
@ -1233,6 +1312,7 @@ main (int argc, char **argv)
case 'p': permanent = true; break; case 'p': permanent = true; break;
case 'b': topbar = false; break; case 'b': topbar = false; break;
case 'd': dock = true; break; case 'd': dock = true; break;
case 's': scale_fonts = 1; break;
case 'f': font_load(optarg); break; case 'f': font_load(optarg); break;
case 'u': bu = strtoul(optarg, NULL, 10); break; case 'u': bu = strtoul(optarg, NULL, 10); break;
case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)scr->black_pixel); break; case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)scr->black_pixel); break;