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
This commit is contained in:
Quentin Glidic 2012-08-07 20:28:39 +02:00
parent 284294e9c2
commit 53365fa887
8 changed files with 65 additions and 49 deletions

View File

@ -128,7 +128,7 @@ static int handle_expose() {
set_font(&font); set_font(&font);
#define txt(x, row, text) \ #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) x, (row - 1) * font.height + 4, 300 - x * 2)
if (current_step == STEP_WELCOME) { if (current_step == STEP_WELCOME) {

View File

@ -98,11 +98,15 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t
/* draw the prompt … */ /* draw the prompt … */
if (prompt != NULL) { 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 */ /* … and the text */
if (input_position > 0) 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 */ /* 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); xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, /* */ 500, font.height + 8);

View File

@ -132,7 +132,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
/* restore font color */ /* restore font color */
set_font_colors(pixmap_gc, color_text, color_background); 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); 4 + 4, 4 + 4, rect.width - 4 - 4);
/* render close button */ /* render close button */
@ -159,7 +159,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
values[0] = 1; values[0] = 1;
set_font_colors(pixmap_gc, color_text, color_button_background); 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); 4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4);
y -= w; y -= w;
@ -190,7 +190,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
values[0] = color_text; values[0] = color_text;
values[1] = color_button_background; values[1] = color_button_background;
set_font_colors(pixmap_gc, color_text, 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 - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6);
y -= w; y -= w;

View File

@ -144,8 +144,7 @@ void refresh_statusline() {
uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg); uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg);
set_font_colors(statusline_ctx, colorpixel, colors.bar_bg); 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), draw_text(block->full_text, statusline_pm, statusline_ctx, x, 0, block->width);
true, statusline_pm, statusline_ctx, x, 0, block->width);
x += block->width; x += block->width;
if (TAILQ_NEXT(block, blocks) != NULL) { if (TAILQ_NEXT(block, blocks) != NULL) {
@ -1519,8 +1518,7 @@ void draw_bars() {
1, 1,
&rect); &rect);
set_font_colors(outputs_walk->bargc, fg_color, bg_color); 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, draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc, i + 5, 2, ws_walk->name_width);
outputs_walk->buffer, outputs_walk->bargc, i + 5, 2, ws_walk->name_width);
i += 10 + ws_walk->name_width + 1; i += 10 + ws_walk->name_width + 1;
} }

View File

@ -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 * specified coordinates (from the top left corner of the leftmost, uppermost
* glyph) and using the provided gc. * 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 must be specified as an i3String.
* 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, 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); xcb_gcontext_t gc, int x, int y, int max_width);
/** /**

View File

@ -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); xcb_change_gc(conn, gc, mask, values);
} }
/* static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawable_t drawable,
* 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,
xcb_gcontext_t gc, int x, int y, int max_width) { 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 */ /* X11 coordinates for fonts start at the baseline */
int pos_y = y + savedFont->info->font_ascent; 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 /* The X11 protocol limits text drawing to 255 chars, so we may need
* multiple calls */ * multiple calls */
int pos_x = x;
int offset = 0; int offset = 0;
for (;;) { for (;;) {
/* Calculate the size of this chunk */ /* Calculate the size of this chunk */
int chunk_size = (text_len > 255 ? 255 : text_len); 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 */ /* 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 */ /* Advance the offset and length of the text to draw */
offset += chunk_size; offset += chunk_size;
@ -154,12 +130,46 @@ void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawabl
break; break;
/* Advance pos_x based on the predicted text width */ /* 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) * Draws text onto the specified X drawable (normally a pixmap) at the
free(input); * 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) { static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {

View File

@ -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")); set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000"));
for (int i = 0; crash_text_i3strings[i] != NULL; ++i) { 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); 8, 5 + i * font_height, width - 16);
} }

View File

@ -484,7 +484,7 @@ void x_draw_decoration(Con *con) {
if (win == NULL || win->name == NULL) { if (win == NULL || win->name == NULL) {
/* this is a non-leaf container, we need to make up a good description */ /* this is a non-leaf container, we need to make up a good description */
// TODO: use a good description instead of just "another container" // 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, parent->pixmap, parent->pm_gc,
con->deco_rect.x + 2, con->deco_rect.y + text_offset_y, con->deco_rect.x + 2, con->deco_rect.y + text_offset_y,
con->deco_rect.width - 2); 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); //DLOG("indent_level = %d, indent_mult = %d\n", indent_level, indent_mult);
int indent_px = (indent_level * 5) * 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, parent->pixmap, parent->pm_gc,
con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y, con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y,
con->deco_rect.width - 2 - indent_px); con->deco_rect.width - 2 - indent_px);