package main /* #cgo pkg-config: xft xrender x11 fontconfig #include #include #include #include static Display *_dpy; static XftDraw *_drw; static XftFont *_ft; static Visual *_vis; static Colormap _cmap; static XftColor _fg; static int _scr; static int wm_xft_init(const char *pattern) { int event_basep, error_basep; _dpy = XOpenDisplay(NULL); if (!_dpy) return -1; if (!XRenderQueryExtension(_dpy, &event_basep, &error_basep)) return -3; XftInit(NULL); _scr = DefaultScreen(_dpy); _vis = DefaultVisual(_dpy, _scr); _cmap = DefaultColormap(_dpy, _scr); _ft = XftFontOpenName(_dpy, _scr, pattern); if (!_ft) return -2; return 0; } static void wm_xft_setfg(unsigned int px) { XRenderColor c; c.red = ((px >> 16) & 0xff) << 8; c.green = ((px >> 8) & 0xff) << 8; c.blue = (px & 0xff) << 8; c.alpha = 0xffff; XftColorAllocValue(_dpy, _vis, _cmap, &c, &_fg); } static int wm_xft_width(const char *s, int n) { XGlyphInfo gi; XftTextExtentsUtf8(_dpy, _ft, (const FcChar8 *)s, n, &gi); return gi.xOff; } static void wm_xft_draw(unsigned int win, int x, int y, const char *s, int n, unsigned int fg) { if (!_dpy || !_ft || !win) return; if (!_drw) _drw = XftDrawCreate(_dpy, (Drawable)win, _vis, _cmap); if (!_drw) return; XftDrawChange(_drw, (Drawable)win); wm_xft_setfg(fg); XftDrawStringUtf8(_drw, &_fg, _ft, x, y, (const FcChar8 *)s, n); XSync(_dpy, False); } static int wm_xft_ascent(void) { return _ft ? _ft->ascent : 0; } static int wm_xft_descent(void) { return _ft ? _ft->descent : 0; } */ import "C" import ( "unsafe" "github.com/BurntSushi/xgb/xproto" ) var xftOK bool func xftInit(pattern string) error { cp := C.CString(pattern) defer C.free(unsafe.Pointer(cp)) switch rc := int(C.wm_xft_init(cp)); rc { case 0: xftOK = true return nil case -1: return errXftNoDisplay case -2: return errXftNoFont default: return errXftNoRender } } var ( errXftNoDisplay = errXft("xft: cannot open display") errXftNoFont = errXft("xft: cannot load font pattern") errXftNoRender = errXft("xft: no RENDER extension") ) type errXft string func (e errXft) Error() string { return string(e) } func xftTextWidth(s string) int { if !xftOK { return 0 } cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) return int(C.wm_xft_width(cs, C.int(len(s)))) } func xftDrawText(win xproto.Window, x, baseline int, s string, fg uint32) { if !xftOK || win == 0 { return } cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) C.wm_xft_draw(C.uint(win), C.int(x), C.int(baseline), cs, C.int(len(s)), C.uint(fg)) } func xftMetrics() (ascent, descent int) { if !xftOK { return 0, 0 } return int(C.wm_xft_ascent()), int(C.wm_xft_descent()) }