use Cairo to render fonts

This commit is contained in:
Nikos Ntarmos 2007-10-16 02:20:03 +03:00 committed by Julien Danjou
parent 9360efb89e
commit 7ecbae334f
4 changed files with 46 additions and 27 deletions

59
draw.c
View File

@ -20,6 +20,7 @@
*/ */
#include <cairo.h> #include <cairo.h>
#include <cairo-ft.h>
#include <cairo-xlib.h> #include <cairo-xlib.h>
#include <math.h> #include <math.h>
#include "layout.h" #include "layout.h"
@ -32,19 +33,27 @@ drawtext(Display *disp, int screen, int x, int y, int w, int h, Drawable drawabl
int nw = 0; int nw = 0;
static char buf[256]; static char buf[256];
size_t len, olen; size_t len, olen;
XRenderColor xrcolor; cairo_font_face_t *font_face;
XftColor xftcolor; cairo_surface_t *surface;
XftDraw *xftdrawable; cairo_t *cr;
drawrectangle(disp, screen, x, y, w, h, drawable, dw, dh, True, color[ColBG]); drawrectangle(disp, screen, x, y, w, h, drawable, dw, dh, True, color[ColBG]);
if(!a_strlen(text)) if(!a_strlen(text))
return; return;
surface = cairo_xlib_surface_create(disp, drawable, DefaultVisual(disp, screen), dw, dh);
cr = cairo_create(surface);
font_face = (cairo_font_face_t *)cairo_ft_font_face_create_for_pattern(font->pattern);
cairo_set_font_face(cr, font_face);
cairo_set_font_size(cr, font->height);
cairo_set_source_rgb(cr, color[ColFG].red / 65535.0, color[ColFG].green / 65535.0, color[ColFG].blue / 65535.0);
olen = len = a_strlen(text); olen = len = a_strlen(text);
if(len >= sizeof(buf)) if(len >= sizeof(buf))
len = sizeof(buf) - 1; len = sizeof(buf) - 1;
memcpy(buf, text, len); memcpy(buf, text, len);
buf[len] = 0; buf[len] = 0;
while(len && (nw = textwidth(disp, font, buf, len)) > w - font->height) while(len && (nw = textwidth(disp, font, buf)) > w)
buf[--len] = 0; buf[--len] = 0;
if(nw > w) if(nw > w)
return; /* too long */ return; /* too long */
@ -57,17 +66,13 @@ drawtext(Display *disp, int screen, int x, int y, int w, int h, Drawable drawabl
if(len > 3) if(len > 3)
buf[len - 3] = '.'; buf[len - 3] = '.';
} }
xrcolor.red = color[ColFG].red;
xrcolor.green = color[ColFG].green; cairo_move_to(cr, x + font->height / 2, y + font->height);
xrcolor.blue = color[ColFG].blue; cairo_show_text(cr, buf);
XftColorAllocValue(disp, DefaultVisual(disp, screen), DefaultColormap(disp, screen), &xrcolor, &xftcolor);
xftdrawable = XftDrawCreate(disp, drawable, DefaultVisual(disp, screen), DefaultColormap(disp, screen)); cairo_font_face_destroy(font_face);
XftDrawStringUtf8(xftdrawable, &xftcolor, font, cairo_destroy(cr);
x + (font->height / 2), cairo_surface_destroy(surface);
y + (h / 2) - (font->height / 2) + font->ascent,
(XftChar8 *) buf, len);
XftColorFree(disp, DefaultVisual(disp, screen), DefaultColormap(disp, screen), &xftcolor);
XftDrawDestroy(xftdrawable);
} }
void void
@ -121,11 +126,27 @@ drawcircle(Display *disp, int screen, int x, int y, int r, Drawable drawable, in
} }
unsigned short unsigned short
textwidth(Display *disp, XftFont *font, char *text, ssize_t len) textwidth(Display *disp, XftFont *font, char *text)
{ {
XGlyphInfo gi; cairo_surface_t *surface;
XftTextExtentsUtf8(disp, font, (FcChar8 *) text, len, &gi); cairo_t *cr;
return gi.width; cairo_font_face_t *font_face;
cairo_text_extents_t te;
surface = cairo_xlib_surface_create(disp, DefaultScreen(disp),
DefaultVisual(disp, DefaultScreen(disp)),
DisplayWidth(disp, DefaultScreen(disp)),
DisplayHeight(disp, DefaultScreen(disp)));
cr = cairo_create(surface);
font_face = cairo_ft_font_face_create_for_pattern(font->pattern);
cairo_set_font_face(cr, font_face);
cairo_set_font_size(cr, font->height);
cairo_text_extents(cr, text, &te);
cairo_destroy(cr);
cairo_surface_destroy(surface);
cairo_font_face_destroy(font_face);
return MAX(te.x_advance, te.width) + font->height;
} }
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99

2
draw.h
View File

@ -27,6 +27,6 @@
void drawtext(Display *, int, int, int, int, int, Drawable, int, int, XftFont *, const char *, XColor []); void drawtext(Display *, int, int, int, int, int, Drawable, int, int, XftFont *, const char *, XColor []);
void drawrectangle(Display *, int, int, int, int, int, Drawable, int, int, Bool, XColor); void drawrectangle(Display *, int, int, int, int, int, Drawable, int, int, Bool, XColor);
void drawcircle(Display *, int, int, int, int, Drawable, int, int, Bool, XColor); void drawcircle(Display *, int, int, int, int, Drawable, int, int, Bool, XColor);
inline unsigned short textwidth(Display *, XftFont *, char *, ssize_t); unsigned short textwidth(Display *, XftFont *, char *);
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99

View File

@ -159,7 +159,7 @@ handle_event_buttonpress(XEvent * e, awesome_config *awesomeconf)
{ {
for(i = 0; i < awesomeconf[screen].ntags; i++) for(i = 0; i < awesomeconf[screen].ntags; i++)
{ {
x += textwidth(e->xany.display, awesomeconf[screen].font, awesomeconf[screen].tags[i].name, a_strlen(awesomeconf[screen].tags[i].name)) + awesomeconf[screen].font->height; x += textwidth(e->xany.display, awesomeconf[screen].font, awesomeconf[screen].tags[i].name);
if(ev->x < x) if(ev->x < x)
{ {
if(ev->button == Button1) if(ev->button == Button1)

View File

@ -53,8 +53,7 @@ drawstatusbar(awesome_config * awesomeconf)
for(i = 0; i < awesomeconf->ntags; i++) for(i = 0; i < awesomeconf->ntags; i++)
{ {
w = textwidth(awesomeconf->display, awesomeconf->font, w = textwidth(awesomeconf->display, awesomeconf->font,
awesomeconf->tags[i].name, a_strlen(awesomeconf->tags[i].name)) awesomeconf->tags[i].name);
+ awesomeconf->font->height;
if(awesomeconf->tags[i].selected) if(awesomeconf->tags[i].selected)
{ {
drawtext(awesomeconf->display, awesomeconf->phys_screen, drawtext(awesomeconf->display, awesomeconf->phys_screen,
@ -108,8 +107,7 @@ drawstatusbar(awesome_config * awesomeconf)
awesomeconf->font, awesomeconf->font,
awesomeconf->current_layout->symbol, awesomeconf->colors_normal); awesomeconf->current_layout->symbol, awesomeconf->colors_normal);
z = x + awesomeconf->statusbar.txtlayoutwidth; z = x + awesomeconf->statusbar.txtlayoutwidth;
w = textwidth(awesomeconf->display, awesomeconf->font, awesomeconf->statustext, a_strlen(awesomeconf->statustext)) w = textwidth(awesomeconf->display, awesomeconf->font, awesomeconf->statustext);
+ awesomeconf->font->height;
x = awesomeconf->statusbar.width - w; x = awesomeconf->statusbar.width - w;
if(x < z) if(x < z)
{ {
@ -184,7 +182,7 @@ initstatusbar(Display *disp, int screen, Statusbar *statusbar, Cursor cursor, Xf
ScreenInfo *si = get_screen_info(disp, screen, NULL); ScreenInfo *si = get_screen_info(disp, screen, NULL);
statusbar->width = si[screen].width; statusbar->width = si[screen].width;
statusbar->height = font->height + 2; statusbar->height = font->height * 1.5;
p_delete(&si); p_delete(&si);
statusbar->screen = screen; statusbar->screen = screen;
@ -212,7 +210,7 @@ initstatusbar(Display *disp, int screen, Statusbar *statusbar, Cursor cursor, Xf
for(i = 0; i < nlayouts; i++) for(i = 0; i < nlayouts; i++)
statusbar->txtlayoutwidth = MAX(statusbar->txtlayoutwidth, statusbar->txtlayoutwidth = MAX(statusbar->txtlayoutwidth,
(font->height + textwidth(disp, font, layouts[i].symbol, a_strlen(layouts[i].symbol)))); (textwidth(disp, font, layouts[i].symbol)));
} }
void void