diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c index f6b37753..ebcce07b 100644 --- a/cmd/wmii/x11.c +++ b/cmd/wmii/x11.c @@ -26,6 +26,8 @@ static MapEnt* abucket[137]; static int errorhandler(Display*, XErrorEvent*); static int (*xlib_errorhandler) (Display*, XErrorEvent*); +static XftColor* xftcolor(ulong); + /* Rectangles/Points */ XRectangle @@ -249,11 +251,20 @@ freeimage(Image *img) { assert(img->type == WImage); + if(img->xft) + XftDrawDestroy(img->xft); XFreePixmap(display, img->w); XFreeGC(display, img->gc); free(img); } +static XftDraw* +xftdrawable(Image *img) { + if(img->xft == nil) + img->xft = XftDrawCreate(display, img->w, scr.visual, scr.colormap); + return img->xft; +} + /* Windows */ Window* createwindow_visual(Window *parent, Rectangle r, @@ -309,6 +320,8 @@ void destroywindow(Window *w) { assert(w->type == WWindow); sethandler(w, nil); + if(w->xft) + XftDrawDestroy(w->xft); if(w->gc) XFreeGC(display, w->gc); XDestroyWindow(display, w->w); @@ -561,16 +574,25 @@ drawstring(Image *dst, Font *font, } setgccol(dst, col); - if(font->set) + switch(font->type) { + case FFontSet: Xutf8DrawString(display, dst->w, - font->set, dst->gc, + font->font.set, dst->gc, x, y, buf, len); - else { - XSetFont(display, dst->gc, font->xfont->fid); + break; + case FXft: + XftDrawStringUtf8(xftdrawable(dst), xftcolor(col), + font->font.xft, + x, y, (uchar*)buf, len); + break; + case FX11: + XSetFont(display, dst->gc, font->font.x11->fid); XDrawString(display, dst->w, dst->gc, - x, y, - buf, len); + x, y, buf, len); + break; + default: + die("Invalid font type."); } done: @@ -617,55 +639,98 @@ loadcolor(CTuple *c, char *str) { && namedcolor(buf+16, &c->border); } +static XftColor* +xftcolor(ulong col) { + XftColor *c; + + c = emallocz(sizeof *c); + *c = (XftColor) { + col, { + (col>>8) & 0xff00, + (col>>0) & 0xff00, + (col<<8) & 0xff00, + (col>>16) & 0xff00, + } + }; + return freelater(c); +} + /* Fonts */ Font* loadfont(char *name) { - Biobuf *b; - Font *f; XFontStruct **xfonts; char **missing, **font_names; + Biobuf *b; + Font *f; int n, i; missing = nil; f = emallocz(sizeof *f); f->name = estrdup(name); - f->set = XCreateFontSet(display, name, &missing, &n, nil); - if(missing) { - b = Bfdopen(dup(2), O_WRONLY); - Bprint(b, "%s: note: missing fontset%s for '%s':", argv0, - (n > 1 ? "s" : ""), name); - for(i = 0; i < n; i++) - Bprint(b, "%s %s", (i ? "," : ""), missing[i]); - Bprint(b, "\n"); - Bterm(b); - freestringlist(missing); - } + if(!strncmp(f->name, "xft:", 4)) { + f->type = FXft; - if(f->set) { - XFontsOfFontSet(f->set, &xfonts, &font_names); - f->ascent = xfonts[0]->ascent; - f->descent = xfonts[0]->descent; + f->font.xft = XftFontOpenXlfd(display, scr.screen, f->name + 4); + if(!f->font.xft) + f->font.xft = XftFontOpenName(display, scr.screen, f->name + 4); + if(!f->font.xft) + goto error; + + f->ascent = f->font.xft->ascent; + f->descent = f->font.xft->descent; }else { - f->xfont = XLoadQueryFont(display, name); - if(!f->xfont) { - fprint(2, "%s: cannot load font: %s\n", argv0, name); - freefont(f); - return nil; + f->font.set = XCreateFontSet(display, name, &missing, &n, nil); + if(missing) { + b = Bfdopen(dup(2), O_WRONLY); + Bprint(b, "%s: note: missing fontset%s for '%s':", argv0, + (n > 1 ? "s" : ""), name); + for(i = 0; i < n; i++) + Bprint(b, "%s %s", (i ? "," : ""), missing[i]); + Bprint(b, "\n"); + Bterm(b); + freestringlist(missing); } - f->ascent = f->xfont->ascent; - f->descent = f->xfont->descent; + if(f->font.set) { + f->type = FFontSet; + XFontsOfFontSet(f->font.set, &xfonts, &font_names); + f->ascent = xfonts[0]->ascent; + f->descent = xfonts[0]->descent; + }else { + f->type = FX11; + f->font.x11 = XLoadQueryFont(display, name); + if(!f->font.x11) + goto error; + + f->ascent = f->font.x11->ascent; + f->descent = f->font.x11->descent; + } } f->height = f->ascent + f->descent; return f; + +error: + fprint(2, "%s: cannot load font: %s\n", argv0, name); + f->type = 0; + freefont(f); + return nil; } void freefont(Font *f) { - if(f->set) - XFreeFontSet(display, f->set); - if(f->xfont) - XFreeFont(display, f->xfont); + switch(f->type) { + case FFontSet: + XFreeFontSet(display, f->font.set); + break; + case FXft: + XftFontClose(display, f->font.xft); + break; + case FX11: + XFreeFont(display, f->font.x11); + break; + default: + break; + } free(f->name); free(f); } @@ -673,12 +738,21 @@ freefont(Font *f) { uint textwidth_l(Font *font, char *text, uint len) { XRectangle r; + XGlyphInfo i; - if(font->set) { - Xutf8TextExtents(font->set, text, len, nil, &r); + switch(font->type) { + case FFontSet: + Xutf8TextExtents(font->font.set, text, len, nil, &r); return r.width; + case FXft: + XftTextExtentsUtf8(display, font->font.xft, (uchar*)text, len, &i); + return i.width; + case FX11: + return XTextWidth(font->font.x11, text, len); + default: + die("Invalid font type"); + return 0; /* shut up ken */ } - return XTextWidth(font->xfont, text, len); } uint diff --git a/config.mk b/config.mk index d97963fb..64019b7b 100644 --- a/config.mk +++ b/config.mk @@ -33,8 +33,8 @@ P9PATHS = ${PLAN9}:"'$${HOME}/plan9'":/usr/local/plan9:/usr/local/9:/opt/plan9:/ # are painfully slow, and should be avoided. #BINSH = /bin/ash -INCX11 = -I/usr/X11R6/include -LIBX11 = -L/usr/X11R6/lib -lX11 +INCX11 = $$(pkg-config --cflags xft) +LIBX11 = $$(pkg-config --libs xft) LIBICONV = # Leave blank if your libc includes iconv (glibc does) LIBIXP = $(LIBDIR)/libixp.a diff --git a/include/x11.h b/include/x11.h index 50d70768..ab1a18fe 100644 --- a/include/x11.h +++ b/include/x11.h @@ -6,6 +6,7 @@ #define Screen XScreen #include #include +#include #ifdef _X11_VISIBLE # include # include @@ -27,12 +28,20 @@ enum Align { Center = NEast | SWest, }; +enum FontType { + FX11 = 1, + FFontSet, + FXft, +}; + enum WindowType { WWindow, WImage, }; typedef enum Align Align; +typedef enum FontType FontType; +typedef enum WindowType WindowType; typedef XSetWindowAttributes WinAttr; @@ -76,12 +85,16 @@ struct Ewmh { }; struct Font { - XFontStruct *xfont; - XFontSet set; - int ascent; - int descent; - uint height; - char *name; + int type; + union { + XFontStruct* x11; + XFontSet set; + XftFont* xft; + } font; + int ascent; + int descent; + uint height; + char* name; }; struct Handlers { @@ -122,6 +135,7 @@ struct Window { int type; XID w; GC gc; + XftDraw* xft; Rectangle r; int border; Window* parent;