From 53365fa887e3038636bc21add1ab9cc1bc1c2e1a Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Tue, 7 Aug 2012 20:28:39 +0200 Subject: [PATCH] libi3: Rework draw_text We now have two versions of draw_text draw_text: Now takes an i3String draw_text_ascii: Designed for static strings in plain ASCII --- i3-config-wizard/main.c | 2 +- i3-input/main.c | 8 +++-- i3-nagbar/main.c | 6 ++-- i3bar/src/xcb.c | 6 ++-- include/libi3.h | 14 +++++--- libi3/font.c | 72 +++++++++++++++++++++++------------------ src/sighandler.c | 2 +- src/x.c | 4 +-- 8 files changed, 65 insertions(+), 49 deletions(-) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index be042673..4c04a6d2 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -128,7 +128,7 @@ static int handle_expose() { set_font(&font); #define txt(x, row, text) \ - draw_text(text, strlen(text), false, pixmap, pixmap_gc,\ + draw_text_ascii(text, pixmap, pixmap_gc,\ x, (row - 1) * font.height + 4, 300 - x * 2) if (current_step == STEP_WELCOME) { diff --git a/i3-input/main.c b/i3-input/main.c index 9ab40aec..6f5ad78a 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -98,11 +98,15 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t /* draw the prompt … */ if (prompt != NULL) { - draw_text((char *)i3string_as_ucs2(prompt), i3string_get_num_glyphs(prompt), true, pixmap, pixmap_gc, 4, 4, 492); + draw_text(prompt, pixmap, pixmap_gc, 4, 4, 492); } /* … and the text */ if (input_position > 0) - draw_text((char *)glyphs_ucs, input_position, true, pixmap, pixmap_gc, 4, 4 + prompt_offset, 492 - prompt_offset); + { + i3String *input = i3string_from_ucs2(glyphs_ucs, input_position); + draw_text(input, pixmap, pixmap_gc, 4, 4, 492); + i3string_free(input); + } /* Copy the contents of the pixmap to the real window */ xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, /* */ 500, font.height + 8); diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index 7a09b99d..26a282f6 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -132,7 +132,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* restore font color */ set_font_colors(pixmap_gc, color_text, color_background); - draw_text((char *)i3string_as_ucs2(prompt), i3string_get_num_glyphs(prompt), true, pixmap, pixmap_gc, + draw_text(prompt, pixmap, pixmap_gc, 4 + 4, 4 + 4, rect.width - 4 - 4); /* render close button */ @@ -159,7 +159,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { values[0] = 1; set_font_colors(pixmap_gc, color_text, color_button_background); - draw_text("X", 1, false, pixmap, pixmap_gc, y - w - line_width + w / 2 - 4, + draw_text_ascii("X", pixmap, pixmap_gc, y - w - line_width + w / 2 - 4, 4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4); y -= w; @@ -190,7 +190,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { values[0] = color_text; values[1] = color_button_background; set_font_colors(pixmap_gc, color_text, color_button_background); - draw_text((char *)i3string_as_ucs2(buttons[c].label), i3string_get_num_glyphs(buttons[c].label), true, pixmap, pixmap_gc, + draw_text(buttons[c].label, pixmap, pixmap_gc, y - w - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6); y -= w; diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index be3ca35a..729803e1 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -144,8 +144,7 @@ void refresh_statusline() { uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg); set_font_colors(statusline_ctx, colorpixel, colors.bar_bg); - draw_text((char *)i3string_as_ucs2(block->full_text), i3string_get_num_glyphs(block->full_text), - true, statusline_pm, statusline_ctx, x, 0, block->width); + draw_text(block->full_text, statusline_pm, statusline_ctx, x, 0, block->width); x += block->width; if (TAILQ_NEXT(block, blocks) != NULL) { @@ -1519,8 +1518,7 @@ void draw_bars() { 1, &rect); set_font_colors(outputs_walk->bargc, fg_color, bg_color); - draw_text((char*)i3string_as_ucs2(ws_walk->name), i3string_get_num_glyphs(ws_walk->name), true, - outputs_walk->buffer, outputs_walk->bargc, i + 5, 2, ws_walk->name_width); + draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc, i + 5, 2, ws_walk->name_width); i += 10 + ws_walk->name_width + 1; } diff --git a/include/libi3.h b/include/libi3.h index 97383ba3..29b8c107 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -297,13 +297,17 @@ void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background * specified coordinates (from the top left corner of the leftmost, uppermost * glyph) and using the provided gc. * - * Text can be specified as UCS-2 or UTF-8. If it's specified as UCS-2, then - * text_len must be the number of glyphs in the string. If it's specified as - * UTF-8, then text_len must be the number of bytes in the string (not counting - * the null terminator). + * Text must be specified as an i3String. * */ -void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawable, +void draw_text(i3String *text, xcb_drawable_t drawable, + xcb_gcontext_t gc, int x, int y, int max_width); + +/** + * ASCII version of draw_text to print static strings. + * + */ +void draw_text_ascii(const char *text, xcb_drawable_t drawable, xcb_gcontext_t gc, int x, int y, int max_width); /** diff --git a/libi3/font.c b/libi3/font.c index 0b276b0b..853e5f92 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -105,45 +105,21 @@ void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background xcb_change_gc(conn, gc, mask, values); } -/* - * Draws text onto the specified X drawable (normally a pixmap) at the - * specified coordinates (from the top left corner of the leftmost, uppermost - * glyph) and using the provided gc. - * - * Text can be specified as UCS-2 or UTF-8. If it's specified as UCS-2, then - * text_len must be the number of glyphs in the string. If it's specified as - * UTF-8, then text_len must be the number of bytes in the string (not counting - * the null terminator). - * - */ -void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawable, +static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawable_t drawable, xcb_gcontext_t gc, int x, int y, int max_width) { - assert(savedFont != NULL); - assert(text_len != 0); - /* X11 coordinates for fonts start at the baseline */ int pos_y = y + savedFont->info->font_ascent; - /* As an optimization, check if we can bypass conversion */ - if (!is_ucs2 && text_len <= 255) { - xcb_image_text_8(conn, text_len, drawable, gc, x, pos_y, text); - return; - } - - /* Convert the text into UCS-2 so we can do basic pointer math */ - char *input = (is_ucs2 ? text : (char*)convert_utf8_to_ucs2(text, &text_len)); - /* The X11 protocol limits text drawing to 255 chars, so we may need * multiple calls */ - int pos_x = x; int offset = 0; for (;;) { /* Calculate the size of this chunk */ int chunk_size = (text_len > 255 ? 255 : text_len); - xcb_char2b_t *chunk = (xcb_char2b_t*)input + offset; + const xcb_char2b_t *chunk = text + offset; /* Draw it */ - xcb_image_text_16(conn, chunk_size, drawable, gc, pos_x, pos_y, chunk); + xcb_image_text_16(conn, chunk_size, drawable, gc, x, pos_y, chunk); /* Advance the offset and length of the text to draw */ offset += chunk_size; @@ -154,12 +130,46 @@ void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawabl break; /* Advance pos_x based on the predicted text width */ - pos_x += predict_text_width((char*)chunk, chunk_size, true); + x += predict_text_width((char*)chunk, chunk_size, true); } +} - /* If we had to convert, free the converted string */ - if (!is_ucs2) - free(input); +/* + * Draws text onto the specified X drawable (normally a pixmap) at the + * specified coordinates (from the top left corner of the leftmost, uppermost + * glyph) and using the provided gc. + * + * Text must be specified as an i3String. + * + */ +void draw_text(i3String *text, xcb_drawable_t drawable, + xcb_gcontext_t gc, int x, int y, int max_width) { + assert(savedFont != NULL); + + draw_text_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text), + drawable, gc, x, y, max_width); +} + +/* + * ASCII version of draw_text to print static strings. + * + */ +void draw_text_ascii(const char *text, xcb_drawable_t drawable, + xcb_gcontext_t gc, int x, int y, int max_width) { + assert(savedFont != NULL); + + size_t text_len = strlen(text); + if (text_len > 255) { + /* The text is too long to draw it directly to X */ + i3String *str = i3string_from_utf8(text); + draw_text(str, drawable, gc, x, y, max_width); + i3string_free(str); + } else { + /* X11 coordinates for fonts start at the baseline */ + int pos_y = y + savedFont->info->font_ascent; + + xcb_image_text_8(conn, text_len, drawable, gc, x, pos_y, text); + } } static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) { diff --git a/src/sighandler.c b/src/sighandler.c index 2c53333d..e9a4e9bf 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -52,7 +52,7 @@ static int sig_draw_window(xcb_window_t win, int width, int height, int font_hei set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); for (int i = 0; crash_text_i3strings[i] != NULL; ++i) { - draw_text((char *)i3string_as_ucs2(crash_text_i3strings[i]), i3string_get_num_glyphs(crash_text_i3strings[i]), true, pixmap, pixmap_gc, + draw_text(crash_text_i3strings[i], pixmap, pixmap_gc, 8, 5 + i * font_height, width - 16); } diff --git a/src/x.c b/src/x.c index 864949e5..24fd0eac 100644 --- a/src/x.c +++ b/src/x.c @@ -484,7 +484,7 @@ void x_draw_decoration(Con *con) { if (win == NULL || win->name == NULL) { /* this is a non-leaf container, we need to make up a good description */ // TODO: use a good description instead of just "another container" - draw_text("another container", strlen("another container"), false, + draw_text_ascii("another container", parent->pixmap, parent->pm_gc, con->deco_rect.x + 2, con->deco_rect.y + text_offset_y, con->deco_rect.width - 2); @@ -508,7 +508,7 @@ void x_draw_decoration(Con *con) { //DLOG("indent_level = %d, indent_mult = %d\n", indent_level, indent_mult); int indent_px = (indent_level * 5) * indent_mult; - draw_text((char *)i3string_as_ucs2(win->name), i3string_get_num_glyphs(win->name), true, + draw_text(win->name, parent->pixmap, parent->pm_gc, con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y, con->deco_rect.width - 2 - indent_px); -- 2.39.5