[draw] Add support for bg in draw_text and use ellipsize from pango

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-04-25 15:50:36 +02:00
parent 16d98db666
commit 1185d8b156
4 changed files with 102 additions and 48 deletions

View File

@ -196,12 +196,12 @@ cfg_opt_t titlebar_opts[] =
CFG_INT((char *) "height", 0, CFGF_NONE), CFG_INT((char *) "height", 0, CFGF_NONE),
/** Text alignment. */ /** Text alignment. */
CFG_ALIGNMENT((char *) "text_align", (char *) "center", CFGF_NONE), CFG_ALIGNMENT((char *) "text_align", (char *) "center", CFGF_NONE),
/** Titlebar markup string for focused windows. */
CFG_STR((char *) "text_focus", (char *) "%t", CFGF_NONE),
/** Titlebar markup string for normal windows. */ /** Titlebar markup string for normal windows. */
CFG_STR((char *) "text_normal", (char *) "%t", CFGF_NONE), CFG_STR((char *) "text_normal", (char *) "<bg color=\"#444444\"/>%t", CFGF_NONE),
/** Titlebar markup string for focused windows. */
CFG_STR((char *) "text_focus", (char *) "<bg color=\"#535d6c\"/>%t", CFGF_NONE),
/** Titlebar markup string for urgent windows. */ /** Titlebar markup string for urgent windows. */
CFG_STR((char *) "text_urgent", (char *) "%t", CFGF_NONE), CFG_STR((char *) "text_urgent", (char *) "<bg color=\"#ff4500\"/>%t", CFGF_NONE),
CFG_AWESOME_END() CFG_AWESOME_END()
}; };
/** This section defines general options. */ /** This section defines general options. */

View File

@ -35,7 +35,7 @@
#include <iconv.h> #include <iconv.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include <math.h> #include <math.h>
#include "draw.h" #include "draw.h"
@ -47,7 +47,7 @@
* \return NULL if error, otherwise pointer to the new converted string * \return NULL if error, otherwise pointer to the new converted string
*/ */
static char * static char *
draw_iso2utf8(char *iso) draw_iso2utf8(const char *iso)
{ {
iconv_t iso2utf8; iconv_t iso2utf8;
size_t len, utf8len; size_t len, utf8len;
@ -74,7 +74,7 @@ draw_iso2utf8(char *iso)
utf8len = 2 * len + 1; utf8len = 2 * len + 1;
utf8 = utf8p = p_new(char, utf8len); utf8 = utf8p = p_new(char, utf8len);
if(iconv(iso2utf8, &iso, &len, &utf8, &utf8len) == (size_t) -1) if(iconv(iso2utf8, (char **) &iso, &len, &utf8, &utf8len) == (size_t) -1)
{ {
warn("text conversion failed: %s\n", strerror(errno)); warn("text conversion failed: %s\n", strerror(errno));
p_delete(&utf8p); p_delete(&utf8p);
@ -211,6 +211,60 @@ draw_font_delete(font_t **font)
p_delete(font); p_delete(font);
} }
static char *
draw_text_markup_expand(xcb_connection_t *conn,
int phys_screen,
const char *str, ssize_t slen,
xcolor_t **bg_color)
{
const char *ps;
char *bg, *bg_end, *bg_str, *color, *col_end, *col_str, *new;
ssize_t len;
int i = 0;
if((bg = strstr(str, "<bg "))
&& ((bg_end = strstr(bg, "/>"))))
{
len = bg_end - bg + 1;
bg_str = p_new(char, len);
/* strncpy(bg_str, len, bg + len of '<bg ', everything * exclude >) */
a_strncpy(bg_str, len, bg + 4, len - 5);
if(bg_color && (color = strstr(bg_str, "color=")))
{
color += 6;
if(color[0] == '"')
color++;
for(col_end = color; *col_end && (*col_end == '#' || isalnum(*col_end)); col_end++);
col_str = a_strndup(color, col_end - color);
if((len = a_strlen(col_str)))
{
if(col_str[len - 1] == '"')
col_str[--len] = '\0';
*bg_color = p_new(xcolor_t, 1);
if(!draw_color_new(conn, phys_screen, col_str, *bg_color))
p_delete(bg_color);
}
p_delete(&col_str);
}
/* copy string without <bg> */
new = p_new(char, slen - (bg_end - bg));
for(ps = str; *ps; ps++)
/* if before <bg and after /> */
if(ps < bg || ps > (bg_end + 1))
new[i++] = *ps;
p_delete(&bg_str);
}
else
new = a_strdup(str);
return new;
}
/** Draw text into a draw context /** Draw text into a draw context
* \param ctx DrawCtx to draw to * \param ctx DrawCtx to draw to
* \param area area to draw to * \param area area to draw to
@ -228,53 +282,41 @@ draw_text(DrawCtx *ctx,
area_t area, area_t area,
alignment_t align, alignment_t align,
int padding, int padding,
char *text, const char *text,
style_t style) style_t style)
{ {
int nw = 0, x, y; int x, y;
ssize_t len, olen; ssize_t len, olen;
char *buf = NULL, *utf8 = NULL; char *buf = NULL, *utf8 = NULL;
xcolor_t *bg_color = NULL;
PangoRectangle ext;
draw_rectangle(ctx, area, 1.0, true, style.bg); if(!(len = a_strlen(text)))
if(!(len = olen = a_strlen(text)))
return; return;
/* try to convert it to UTF-8 */ /* try to convert it to UTF-8 */
if((utf8 = draw_iso2utf8(text))) if((utf8 = draw_iso2utf8(text)))
{ len = a_strlen(utf8);
buf = utf8;
len = olen = a_strlen(buf);
}
else else
buf = a_strdup(text); utf8 = a_strdup(text);
/* check that the text is not too long */ buf = draw_text_markup_expand(ctx->connection, ctx->phys_screen,
while(len && (nw = (draw_text_extents(ctx->connection, ctx->default_screen, style.font, buf).width) + padding * 2) > area.width) utf8, len, &bg_color);
p_delete(&utf8);
len = olen = a_strlen(buf);
if(bg_color)
{ {
len--; draw_rectangle(ctx, area, 1.0, true, *bg_color);
/* we can't blindly null the char, we need to check if it's not part of p_delete(&bg_color);
* a multi byte char: if mbtowc return -1, we know that we must go back
* in the string to find the beginning of the multi byte char */
while(len && mbtowc(NULL, buf + len, a_strlen(buf + len)) < 0)
len--;
buf[len] = '\0';
}
/* check that text is not too long */
if(nw > area.width)
return;
if(len < olen)
{
if(len > 1)
buf[len - 1] = '.';
if(len > 2)
buf[len - 2] = '.';
if(len > 3)
buf[len - 3] = '.';
} }
pango_layout_set_width(ctx->layout, pango_units_from_double(area.width));
pango_layout_set_ellipsize(ctx->layout, PANGO_ELLIPSIZE_END);
pango_layout_set_markup(ctx->layout, buf, len); pango_layout_set_markup(ctx->layout, buf, len);
pango_layout_set_font_description(ctx->layout, style.font->desc); pango_layout_set_font_description(ctx->layout, style.font->desc);
pango_layout_get_pixel_extents(ctx->layout, NULL, &ext);
x = area.x + padding; x = area.x + padding;
/* + 1 is added for rounding, so that in any case of doubt we rather draw /* + 1 is added for rounding, so that in any case of doubt we rather draw
@ -285,15 +327,17 @@ draw_text(DrawCtx *ctx,
switch(align) switch(align)
{ {
case AlignCenter: case AlignCenter:
x += (area.width - nw) / 2; x += (area.width - ext.width) / 2;
break; break;
case AlignRight: case AlignRight:
x += area.width - nw; x += area.width - ext.width;
break; break;
default: default:
break; break;
} }
cairo_move_to(ctx->cr, x, y);
if(style.shadow_offset > 0) if(style.shadow_offset > 0)
{ {
cairo_set_source_rgb(ctx->cr, cairo_set_source_rgb(ctx->cr,
@ -309,7 +353,6 @@ draw_text(DrawCtx *ctx,
style.fg.red / 65535.0, style.fg.red / 65535.0,
style.fg.green / 65535.0, style.fg.green / 65535.0,
style.fg.blue / 65535.0); style.fg.blue / 65535.0);
cairo_move_to(ctx->cr, x, y);
pango_cairo_update_layout(ctx->cr, ctx->layout); pango_cairo_update_layout(ctx->cr, ctx->layout);
pango_cairo_show_layout(ctx->cr, ctx->layout); pango_cairo_show_layout(ctx->cr, ctx->layout);
@ -877,17 +920,30 @@ draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, cons
xcb_screen_t *s = xcb_aux_get_screen(conn, default_screen); xcb_screen_t *s = xcb_aux_get_screen(conn, default_screen);
area_t geom = { 0, 0, 0, 0, NULL, NULL }; area_t geom = { 0, 0, 0, 0, NULL, NULL };
ssize_t len; ssize_t len;
char *buf, *utf8;
if(!(len = a_strlen(text))) if(!(len = a_strlen(text)))
return geom; return geom;
/* try to convert it to UTF-8 */
if((utf8 = draw_iso2utf8(text)))
len = a_strlen(utf8);
else
utf8 = a_strdup(text);
buf = draw_text_markup_expand(conn, default_screen, utf8, len, NULL);
p_delete(&utf8);
len = a_strlen(buf);
surface = cairo_xcb_surface_create(conn, default_screen, surface = cairo_xcb_surface_create(conn, default_screen,
draw_screen_default_visual(s), draw_screen_default_visual(s),
s->width_in_pixels, s->width_in_pixels,
s->height_in_pixels); s->height_in_pixels);
cr = cairo_create(surface); cr = cairo_create(surface);
layout = pango_cairo_create_layout(cr); layout = pango_cairo_create_layout(cr);
pango_layout_set_markup(layout, text, len); pango_layout_set_markup(layout, buf, len);
pango_layout_set_font_description(layout, font->desc); pango_layout_set_font_description(layout, font->desc);
pango_layout_get_pixel_extents(layout, NULL, &ext); pango_layout_get_pixel_extents(layout, NULL, &ext);
g_object_unref(layout); g_object_unref(layout);
@ -897,6 +953,8 @@ draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, cons
geom.width = ext.width; geom.width = ext.width;
geom.height = ext.height * 1.5; geom.height = ext.height * 1.5;
p_delete(&buf);
return geom; return geom;
} }

View File

@ -125,7 +125,7 @@ void draw_context_delete(DrawCtx **);
font_t *draw_font_new(xcb_connection_t *, int, char *); font_t *draw_font_new(xcb_connection_t *, int, char *);
void draw_font_delete(font_t **); void draw_font_delete(font_t **);
void draw_text(DrawCtx *, area_t, alignment_t, int, char *, style_t); void draw_text(DrawCtx *, area_t, alignment_t, int, const char *, style_t);
void draw_rectangle(DrawCtx *, area_t, float, bool, xcolor_t); void draw_rectangle(DrawCtx *, area_t, float, bool, xcolor_t);
void draw_rectangle_gradient(DrawCtx *, area_t, float, bool, area_t, xcolor_t *, xcolor_t *, xcolor_t *); void draw_rectangle_gradient(DrawCtx *, area_t, float, bool, area_t, xcolor_t *, xcolor_t *, xcolor_t *);

View File

@ -113,11 +113,7 @@ taglist_draw(widget_t *widget,
area.y = widget->area.y; area.y = widget->area.y;
area.width = w; area.width = w;
area.height = widget->statusbar->height; area.height = widget->statusbar->height;
draw_text(ctx, area, draw_text(ctx, area, AlignCenter, 0, tag->name, style);
AlignCenter,
style.font->height / 2,
tag->name,
style);
if(isoccupied(tag)) if(isoccupied(tag))
{ {