From f3e9df4a97e5e88b66e527d6792d35f9782858ed Mon Sep 17 00:00:00 2001 From: Grayson MacKenzie Date: Tue, 22 Jul 2014 14:47:41 -0400 Subject: [PATCH 1/5] Added support for greater than two fonts. --- bar.c | 90 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/bar.c b/bar.c index 1f8c5cf..26826e4 100644 --- a/bar.c +++ b/bar.c @@ -70,13 +70,14 @@ static xcb_gcontext_t gc[GC_MAX]; static xcb_visualid_t visual; static xcb_colormap_t colormap; static monitor_t *monhead, *montail; -static font_t *main_font, *alt_font; +#define MAX_FONT_COUNT 5 +static font_t *all_fonts[MAX_FONT_COUNT]; +static char *all_fonts_str[MAX_FONT_COUNT]; static uint32_t attrs = 0; static bool dock = false; static bool topbar = true; static int bw = -1, bh = -1, bx = 0, by = 0; static int bu = 1; /* Underline height */ -static char *mfont, *afont; static uint32_t fgc, bgc, ugc; static uint32_t dfgc, dbgc; static area_stack_t astack; @@ -98,10 +99,6 @@ fill_rect (xcb_drawable_t d, xcb_gcontext_t gc, int x, int y, int width, int hei int draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) { - /* In the unlikely case that the font doesn't have the glyph wanted just do nothing */ - if (ch < cur_font->char_min || ch > cur_font->char_max) - return 0; - int ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width; switch (align) { @@ -295,6 +292,17 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x return true; } +/* returns NULL if character cannot be printed */ +font_t * +select_drawable_font (uint16_t c) +{ + int i = 0; + while (all_fonts[i] != NULL && (c < all_fonts[i]->char_min || c > all_fonts[i]->char_max)) + i++; + + return all_fonts[i]; +} + void parse (char *text) { @@ -399,8 +407,9 @@ parse (char *text) p += 1; } - /* If the character is outside the main font charset use the alternate font */ - cur_font = (ucs < main_font->char_min || ucs > main_font->char_max) ? alt_font : main_font; + cur_font = select_drawable_font(ucs); + if (cur_font == NULL) + continue; xcb_change_gc(c, gc[GC_DRAW] , XCB_GC_FONT, (const uint32_t []){ cur_font->ptr }); @@ -590,11 +599,13 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) height = h; } + /* TODO replace constants here and in init() with #defines */ + if (bw < 0) bw = width - bx; if (bh < 0 || bh > height) - bh = main_font->height + bu + 2; + bh = all_fonts[0]->height + bu + 2; /* Check the geometry */ if (bx + bw > width || by + bh > height) { @@ -799,16 +810,30 @@ void init (void) { /* Load the fonts */ - main_font = font_load(mfont ? mfont : "fixed"); - if (!main_font) + int i = 0; + while (all_fonts_str[i]) { + all_fonts[i] = font_load(all_fonts_str[i]); + if (!all_fonts[i]) + exit(EXIT_FAILURE); + i++; + } + + if (all_fonts[0] == NULL) + all_fonts[0] = font_load("fixed"); + + if (!all_fonts[0]) exit(EXIT_FAILURE); - alt_font = font_load(afont ? afont : "fixed"); - if (!alt_font) - exit(EXIT_FAILURE); + /* To make the alignment uniform, find maximum height */ + int maxh = all_fonts[0]->height; + i = 0; + while (all_fonts[++i]) + maxh = max(maxh, all_fonts[i]->height); - /* To make the alignment uniform */ - main_font->height = alt_font->height = max(main_font->height, alt_font->height); + /* Set maximum height to all fonts */ + i = 0; + while (all_fonts[i]) + all_fonts[i++]->height = maxh; /* Generate a list of screens */ const xcb_query_extension_reply_t *qe_reply; @@ -837,13 +862,15 @@ init (void) } if (!monhead) { + /* TODO replace constants here and in monitor_create_chain() with #defines */ + /* If I fits I sits */ if (bw < 0) bw = scr->width_in_pixels - bx; /* Adjust the height */ if (bh < 0 || bh > scr->height_in_pixels) - bh = main_font->height + bu + 2; + bh = maxh + bu + 2; /* Check the geometry */ if (bx + bw > scr->width_in_pixels || by + bh > scr->height_in_pixels) { @@ -883,14 +910,11 @@ init (void) void cleanup (void) { - if (main_font) { - xcb_close_font(c, main_font->ptr); - free(main_font); - } - - if (alt_font) { - xcb_close_font(c, alt_font->ptr); - free(alt_font); + int i = 0; + while (all_fonts[i]) { + xcb_close_font(c, all_fonts[i]->ptr); + free(all_fonts[i]); + all_fonts[i++] = NULL; } while (monhead) { @@ -980,13 +1004,17 @@ parse_font_list (char *str) return; tok = strtok(str, ","); - if (tok) - mfont = tok; - tok = strtok(NULL, ","); - if (tok) - afont = tok; - return; + int i = 0; + while (tok) { + if (i >= MAX_FONT_COUNT) { + fprintf(stderr, "Too many fonts; maximum %i\n", MAX_FONT_COUNT); + return; + } + + all_fonts_str[i++] = tok; + tok = strtok(NULL, ","); + } } int From d22cd1561bd8073414c42002f35f4d5dcbdd7a5e Mon Sep 17 00:00:00 2001 From: Grayson MacKenzie Date: Tue, 22 Jul 2014 15:20:21 -0400 Subject: [PATCH 2/5] Fixed #68 --- bar.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bar.c b/bar.c index 26826e4..29859a4 100644 --- a/bar.c +++ b/bar.c @@ -296,8 +296,12 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x font_t * select_drawable_font (uint16_t c) { + /* if the font is null, stop and return it, if it is outside of the character + * set or has a width of zero then move on; it cannot display the character. + */ int i = 0; - while (all_fonts[i] != NULL && (c < all_fonts[i]->char_min || c > all_fonts[i]->char_max)) + while (all_fonts[i] != NULL && (c < all_fonts[i]->char_min || c > all_fonts[i]->char_max + || all_fonts[i]->width_lut[c - all_fonts[i]->char_min].character_width == 0)) i++; return all_fonts[i]; From 128e212c14fb0a184700acb3dab4db99a1c98ecb Mon Sep 17 00:00:00 2001 From: Grayson MacKenzie Date: Tue, 22 Jul 2014 16:14:48 -0400 Subject: [PATCH 3/5] General style cleanups. --- bar.c | 73 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/bar.c b/bar.c index 29859a4..94ec1e8 100644 --- a/bar.c +++ b/bar.c @@ -64,15 +64,16 @@ enum { GC_MAX }; +#define MAX_FONT_COUNT 5 + static xcb_connection_t *c; static xcb_screen_t *scr; static xcb_gcontext_t gc[GC_MAX]; static xcb_visualid_t visual; static xcb_colormap_t colormap; static monitor_t *monhead, *montail; -#define MAX_FONT_COUNT 5 -static font_t *all_fonts[MAX_FONT_COUNT]; -static char *all_fonts_str[MAX_FONT_COUNT]; +static font_t *font_list[MAX_FONT_COUNT]; +static char *font_names[MAX_FONT_COUNT]; static uint32_t attrs = 0; static bool dock = false; static bool topbar = true; @@ -296,15 +297,17 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x font_t * select_drawable_font (uint16_t c) { - /* if the font is null, stop and return it, if it is outside of the character - * set or has a width of zero then move on; it cannot display the character. + /* if the end is reached without finding an apropriate font, return NULL. + * If the font can draw the character, return it. */ - int i = 0; - while (all_fonts[i] != NULL && (c < all_fonts[i]->char_min || c > all_fonts[i]->char_max - || all_fonts[i]->width_lut[c - all_fonts[i]->char_min].character_width == 0)) - i++; + for (int i = 0; font_list[i] != NULL; i++) { + font_t *font = font_list[i]; + if (c > font->char_min && c < font->char_max && + font->width_lut[c - font->char_min].character_width != 0) + return font; + } - return all_fonts[i]; + return NULL; } void @@ -350,7 +353,7 @@ parse (char *text) case 'c': pos_x = 0; align = ALIGN_C; break; case 'r': pos_x = 0; align = ALIGN_R; break; - case 'A': + case 'A': button = XCB_BUTTON_INDEX_1; /* The range is 1-5 */ if (isdigit(*p) && (*p > '0' && *p < '6')) @@ -412,7 +415,7 @@ parse (char *text) } cur_font = select_drawable_font(ucs); - if (cur_font == NULL) + if (!cur_font) continue; xcb_change_gc(c, gc[GC_DRAW] , XCB_GC_FONT, (const uint32_t []){ cur_font->ptr }); @@ -603,13 +606,11 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) height = h; } - /* TODO replace constants here and in init() with #defines */ - if (bw < 0) bw = width - bx; if (bh < 0 || bh > height) - bh = all_fonts[0]->height + bu + 2; + bh = font_list[0]->height + bu + 2; /* Check the geometry */ if (bx + bw > width || by + bh > height) { @@ -814,30 +815,26 @@ void init (void) { /* Load the fonts */ - int i = 0; - while (all_fonts_str[i]) { - all_fonts[i] = font_load(all_fonts_str[i]); - if (!all_fonts[i]) + for (int i = 0; font_names[i]; i++) { + font_list[i] = font_load(font_names[i]); + if (!font_list[i]) exit(EXIT_FAILURE); - i++; } - if (all_fonts[0] == NULL) - all_fonts[0] = font_load("fixed"); + if (!font_list[0]) + font_list[0] = font_load("fixed"); - if (!all_fonts[0]) + if (!font_list[0]) exit(EXIT_FAILURE); /* To make the alignment uniform, find maximum height */ - int maxh = all_fonts[0]->height; - i = 0; - while (all_fonts[++i]) - maxh = max(maxh, all_fonts[i]->height); + int maxh = font_list[0]->height; + for (int i = 1; font_list[i]; i++) + maxh = max(maxh, font_list[i]->height); /* Set maximum height to all fonts */ - i = 0; - while (all_fonts[i]) - all_fonts[i++]->height = maxh; + for (int i = 0; font_list[i]; i++) + font_list[i]->height = maxh; /* Generate a list of screens */ const xcb_query_extension_reply_t *qe_reply; @@ -866,8 +863,6 @@ init (void) } if (!monhead) { - /* TODO replace constants here and in monitor_create_chain() with #defines */ - /* If I fits I sits */ if (bw < 0) bw = scr->width_in_pixels - bx; @@ -914,11 +909,10 @@ init (void) void cleanup (void) { - int i = 0; - while (all_fonts[i]) { - xcb_close_font(c, all_fonts[i]->ptr); - free(all_fonts[i]); - all_fonts[i++] = NULL; + for (int i = 0; font_list[i]; i++) { + xcb_close_font(c, font_list[i]->ptr); + free(font_list[i]); + font_list[i] = NULL; } while (monhead) { @@ -1009,14 +1003,13 @@ parse_font_list (char *str) tok = strtok(str, ","); - int i = 0; - while (tok) { + for (int i = 0; tok; i++) { if (i >= MAX_FONT_COUNT) { fprintf(stderr, "Too many fonts; maximum %i\n", MAX_FONT_COUNT); return; } - all_fonts_str[i++] = tok; + font_names[i] = tok; tok = strtok(NULL, ","); } } From 1c106dbfd0dde69a014752d13747054a024daec4 Mon Sep 17 00:00:00 2001 From: Grayson MacKenzie Date: Tue, 22 Jul 2014 17:23:56 -0400 Subject: [PATCH 4/5] Added font caching --- bar.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bar.c b/bar.c index 94ec1e8..9ed5e60 100644 --- a/bar.c +++ b/bar.c @@ -65,6 +65,8 @@ enum { }; #define MAX_FONT_COUNT 5 +/* 0 <= FONT_CACHE_SIZE <= 65536 */ +#define FONT_CACHE_SIZE 256 static xcb_connection_t *c; static xcb_screen_t *scr; @@ -74,6 +76,7 @@ static xcb_colormap_t colormap; static monitor_t *monhead, *montail; static font_t *font_list[MAX_FONT_COUNT]; static char *font_names[MAX_FONT_COUNT]; +static font_t *font_cache[FONT_CACHE_SIZE]; static uint32_t attrs = 0; static bool dock = false; static bool topbar = true; @@ -306,10 +309,19 @@ select_drawable_font (uint16_t c) font->width_lut[c - font->char_min].character_width != 0) return font; } - return NULL; } +/* returns NULL if character cannot be printed */ +font_t * +select_drawable_font_cache (uint16_t c) +{ + if (c < FONT_CACHE_SIZE) + return font_cache[c]; + else + return select_drawable_font(c); +} + void parse (char *text) { @@ -827,6 +839,10 @@ init (void) if (!font_list[0]) exit(EXIT_FAILURE); + for (uint16_t i = 0; i < FONT_CACHE_SIZE; i++) { + font_cache[i] = select_drawable_font(i); + } + /* To make the alignment uniform, find maximum height */ int maxh = font_list[0]->height; for (int i = 1; font_list[i]; i++) From 02627e76095f05620ba641ef5efa84bbfe68b6b0 Mon Sep 17 00:00:00 2001 From: Grayson MacKenzie Date: Tue, 22 Jul 2014 18:35:21 -0400 Subject: [PATCH 5/5] Minor syntax cleanup. Changed parameter of select_drawable_font() to const --- bar.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bar.c b/bar.c index 9ed5e60..3dac275 100644 --- a/bar.c +++ b/bar.c @@ -298,7 +298,7 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x /* returns NULL if character cannot be printed */ font_t * -select_drawable_font (uint16_t c) +select_drawable_font (const uint16_t c) { /* if the end is reached without finding an apropriate font, return NULL. * If the font can draw the character, return it. @@ -839,9 +839,8 @@ init (void) if (!font_list[0]) exit(EXIT_FAILURE); - for (uint16_t i = 0; i < FONT_CACHE_SIZE; i++) { + for (uint16_t i = 0; i < FONT_CACHE_SIZE; i++) font_cache[i] = select_drawable_font(i); - } /* To make the alignment uniform, find maximum height */ int maxh = font_list[0]->height;