Hello Xft -- an anti-aliased font rendering example

IRIX/Nekoware development, porting and related topics.
Forum rules
Any posts concerning pirated software or offering to buy/sell/trade commercial software are subject to removal.
User avatar
Posts: 2932
Joined: Fri May 09, 2003 6:10 am
Location: Maryland, USA

Hello Xft -- an anti-aliased font rendering example

Unread postby squeen » Mon Jan 23, 2006 10:33 am

I finally found a sliver of time to do something I've been itchin' to try. I wrote a very small app that uses libXft and freetype2 to draw anti-aliased text in a X window. It is pure X and doesn't require Xt or any toolkit like Motif, GTK+ or Qt. Basically, Keith Packard has replaced the core X font calls with equivalents. Here's the little app, which I post here because there doesn't seem to be anything like it on the web. The closest is here: http://www.keithp.com/~keithp/render/Xft.tutorial


Code: Select all

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef HAVE_XFT
#include <Xft/Xft.h>

#define DEFAULT_BDWIDTH 1 /* border width */

#ifdef HAVE_XFT
char *text = "Hello Xft";
char *text = "Hello X11";

Display *dpy;

int main( int argc, char *argv[] )
   int                     ytext, wtext, htext, gravity, geo_mask;
   int                     Done = 0, highlight = 0, force_expose = 0;
   XSizeHints              xsh;
   XWMHints                xwmh;
   unsigned long           fgpix, bgpix;
   Window                  mainW;
   XSetWindowAttributes    xswa;
#ifdef HAVE_XFT
   XftFont                 *font;
   XftDraw                 *xftdraw;
   XRenderColor            xrcolor;
   XftColor                xftcolor, hlcolor;
   XGlyphInfo              extents;
   GC                      gc;
   XGCValues               gcvals;
   XFontStruct             *font;
   XEvent                  event;
   char                    user_geo[80];
   /* open connection to X display */
   dpy = XOpenDisplay( NULL );
   /* set up font */
#ifdef HAVE_XFT
   font = XftFontOpenName( dpy, DefaultScreen( dpy ), "morpheus-18" );
   font = XLoadQueryFont( dpy, "-*-helvetica-medium-r-normal--20-*-*-*-p-100-iso8859-1" );
   /* colors */
   fgpix = BlackPixel( dpy, DefaultScreen( dpy ) );
   bgpix = WhitePixel( dpy, DefaultScreen( dpy ) );
   /* position and size of top window (XSizeHints) */
#ifdef HAVE_XFT
   XftTextExtents8( dpy, font, (XftChar8 *)text, strlen(text), &extents );
   ytext = extents.height - extents.y;
   wtext = extents.width - extents.x;
   ytext = font->max_bounds.ascent + font->max_bounds.descent;
   wtext = font->max_bounds.width / 2 + XTextWidth( font, text, strlen(text) + 4 );
   htext = ytext + 4;   
   xsh.flags = ( PPosition | PSize | PMinSize );
   xsh.height = htext + 10;
   xsh.min_height = xsh.height;
   xsh.width = wtext;
   xsh.min_width = xsh.width;
   xsh.x = 50;
   xsh.y = 50;
   /* construct a geometry string */
   sprintf( user_geo, "%dx%d+%d+%d", xsh.width, xsh.height, xsh.x, xsh.y );
   /* process geometry specification */
   geo_mask = XWMGeometry( dpy, DefaultScreen(dpy), user_geo, NULL/*def_geo*/,
                  DEFAULT_BDWIDTH, &xsh, &xsh.x, &xsh.y, &xsh.width, &xsh.height,
                  &gravity );
   /* check geometry bitmask and set size hints */
   if ( geo_mask & (XValue|YValue) ) xsh.flags |= USPosition;
   if ( geo_mask & (WidthValue|HeightValue) ) xsh.flags |= USSize;
   /* create top level window */
   mainW = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), xsh.x, xsh.y,
               xsh.width, xsh.height, DEFAULT_BDWIDTH, fgpix, bgpix );
   /* set window manager properties */
   XSetStandardProperties( dpy, mainW, "xhello", "xhello", None, argv, argc, &xsh );
   /* set window manager hints */
   xwmh.flags = (InputHint|StateHint);
   xwmh.input = False;
   xwmh.initial_state = NormalState;
   XSetWMHints( dpy, mainW, &xwmh );

#ifdef HAVE_XFT
   /* Xft draw context */
   xftdraw = XftDrawCreate( dpy, mainW, DefaultVisual(dpy,DefaultScreen(dpy)),
               DefaultColormap( dpy, DefaultScreen(dpy) ) );
   /* Xft text color */
   xrcolor.red = 0x0;
   xrcolor.green = 0x0;
   xrcolor.blue = 0x0;
   xrcolor.alpha = 0xffff;
   XftColorAllocValue( dpy, DefaultVisual(dpy,DefaultScreen(dpy)),
               DefaultColormap( dpy, DefaultScreen(dpy) ), &xrcolor, &xftcolor );
   /* Xft highlight color */
   xrcolor.red = 0xafff;
   xrcolor.green = 0xafff;
   xrcolor.blue = 0xffff;
   xrcolor.alpha = 0xffff;
   XftColorAllocValue( dpy, DefaultVisual(dpy,DefaultScreen(dpy)),
               DefaultColormap( dpy, DefaultScreen(dpy) ), &xrcolor, &hlcolor );
   /* create graphics context */
   gcvals.font = font->fid;
   gcvals.foreground = fgpix;
   gcvals.background = bgpix;
   gc = XCreateGC( dpy, mainW, (GCFont|GCForeground|GCBackground), &gcvals );
   /* set window attributes */
   xswa.colormap = DefaultColormap( dpy, DefaultScreen(dpy) );
   xswa.bit_gravity = CenterGravity;
   XChangeWindowAttributes( dpy, mainW, (CWColormap|CWBitGravity), &xswa );
   /* select inputs */
   XSelectInput( dpy, mainW, ExposureMask|ButtonPressMask|EnterWindowMask|LeaveWindowMask );
   /* make window visible */
   XMapWindow( dpy, mainW );
   printf("click on the window to exit\n");
   /* retrieve and process events */
   while ( !Done ) {
      XNextEvent( dpy, &event );
      if ( event.xany.window == mainW ) {
         switch ( event.type ) {
            case EnterNotify:
            case LeaveNotify:
               if ( event.type==EnterNotify) highlight = 1;
               else highlight = 0;
               force_expose = 1;
            case Expose:
               if ( event.xexpose.count == 0 || force_expose ) {
                  int            x, y, itmp;
                  unsigned int   w, h, utmp;
                  Window         wtmp;

                  if ( XGetGeometry( dpy, mainW, &wtmp, &itmp, &itmp, &w, &h, &utmp, &utmp )==0 )
                  XClearWindow( dpy, mainW );
#ifdef HAVE_XFT
                  x = ( w - extents.width ) / 2;
                  y = htext + ( h - htext + extents.height )/2;
                  if (highlight) XftDrawRect( xftdraw, &hlcolor, x, y-extents.height, wtext, extents.height  );
                  XftDrawString8( xftdraw, &xftcolor, font, x, y, (XftChar8 *)text, strlen(text) );
                  x = ( w - XTextWidth( font, text, strlen(text) ) ) / 2;
                  y = htext + ( h - htext + font->max_bounds.ascent - font->max_bounds.descent )/2;
                  XDrawString( dpy, mainW, gc, x, y, text, strlen(text) );
                  force_expose = 0;
            case ButtonPress:
               Done = 1;

   /* close connection to display */
#ifdef HAVE_XFT
   XftDrawDestroy( xftdraw );
   XftColorFree( dpy, DefaultVisual(dpy,DefaultScreen(dpy)),
               DefaultColormap( dpy, DefaultScreen(dpy) ), &xftcolor );
   XftColorFree( dpy, DefaultVisual(dpy,DefaultScreen(dpy)),
               DefaultColormap( dpy, DefaultScreen(dpy) ), &hlcolor );
   XFreeGC( dpy, gc );
   XDestroyWindow( dpy, mainW );
   XCloseDisplay( dpy );

and the (GNU) Makefile that will built it.

Code: Select all

SHELL = /bin/sh

CFLAGS = -O0 -g -Wall
CPPFLAGS = -I. -I/usr/X11R6/include -L/usr/X11R6/lib
XFTFLAGS = -DHAVE_XFT -I/usr/nekoware/include -I/usr/nekoware/include/freetype2 -I/usr/nekoware/include/X11 -L/usr/nekoware/lib -Wl,-rpath -Wl,/usr/nekoware/lib

# uncomment for Apple OS X
#XFTFLAGS = -DHAVE_XFT -I/usr/X11R6/include/X11 -I/usr/X11R6/include/freetype2

LDFLAGS =  -L.  -L..
LIBS = -lX11
%.o: %.c
   $(CC) -c $(CFLAGS) $(CPPFLAGS) $(XM) -o $@ $<

.PHONY: all
all: xhello xfthello

xhello: $(OBJS) xhello.c
   $(CC) $(CFLAGS) $(CPPFLAGS) xhello.c -o xhello $(LDFLAGS) $(LIBS);   

xfthello: $(OBJS) xhello.c
   $(CC) $(CFLAGS) $(CPPFLAGS) $(XFTFLAGS) xhello.c -o xfthello  $(LDFLAGS) $(XFTLIBS) $(LIBS);   

.PHONY: clean 
   rm -f ./*.o; rm -f ./xhello ./xfthello;

Note: you have to uncomment one line if you want to build it on the Mac. Also, it builds two versions. The old X11 style fonts (xhello) and the new Xft anti-alised fonts (xfthello). Have a peek at the results.


What am I going to do with this newly acquired knowledge?....Only time will let! :twisted:


User avatar
Posts: 326
Joined: Tue Nov 01, 2005 11:35 am
Location: california

Unread postby dj » Tue Jan 24, 2006 8:54 am

Nice! Works under linux too :).

Back when I first started my djv project, I had a couple alpha versions just using raw xlib and freetype for fonts. Lot's of fun. For various reasons I ended up going with qt, but more than once have regretted that decision :).

User avatar
Posts: 2932
Joined: Fri May 09, 2003 6:10 am
Location: Maryland, USA

Re: Hello Xft -- an anti-aliased font rendering example

Unread postby squeen » Mon Jan 09, 2012 4:11 am

I just googled my own post to try and remember how I did this. :)

User avatar
Posts: 1887
Joined: Tue Jul 15, 2008 5:48 pm
Location: P.O. Box 529, Gordon, Sydney, NSW 2072, Australia.

Re: Hello Xft -- an anti-aliased font rendering example

Unread postby PymbleSoftware » Mon Jan 09, 2012 10:55 am

Douglas A Young was an SGI employee who wrote a few books on Xt, Motif, etc programming, his code has always compiled on IRIX.

http://www.amazon.com/Douglas-A.-Young/ ... 187&sr=8-3

I have this book and the source code built on one of my machines here.. somewhere.

There is more example in IRIX itself in insight and those soft copy Oreilly books optional installs in IRIX 6.5... Volume 6B, etc...

You might want to change the file name to xhello.c or change the target and remember to put tabs not spaces before the $(CC) and rm lines...


開いた括弧は必ず閉じる -- あるプログラマー

:Tezro: :Tezro: :Onyx2R: :Onyx2RE: :Onyx2: :O3x04R: :O3x0: :O200: :Octane: :Octane2: :O2: :O2: :Indigo2IMP: :PI: :PI: :1600SW: :1600SW: :Indy: :Indy: :Indy: :Indy: :Indy:
:hpserv: J5600, 2 x Mac, 3 x SUN, Alpha DS20E, Alpha 800 5/550, 3 x RS/6000, Amiga 4000 VideoToaster, Amiga4000 -030, 733MHz Sam440 AmigaOS 4.1 update 1.

Sold: :Indy: :Indy: :Indy: :Indigo: Tandem Himalaya S-Series Nonstop S72000 ServerNet.

Twitter @PymbleSoftware
Current Apps (iOS) -> https://itunes.apple.com/au/artist/pymb ... d553990081
(Android) https://play.google.com/store/apps/deve ... +Ltd&hl=en
(Onyx2) Cortex ---> http://www.facebook.com/pages/Cortex-th ... 11?sk=info
(0300s) Minnie ---> http://www.facebook.com/pages/Minnie-th ... 02?sk=info
Github ---> https://github.com/pymblesoftware

User avatar
Posts: 1490
Joined: Mon Nov 12, 2007 7:54 pm
Location: Berkeley, CA, USA, NA, Earth, Sol

Re: Hello Xft -- an anti-aliased font rendering example

Unread postby smj » Tue Jan 10, 2012 2:21 pm

squeen wrote:I just googled my own post to try and remember how I did this. :)
Those are the times when I'm glad I try to capture/document things as I go. :D Or, all too often, they are the times I wail and lament that I'm not more consistent in capturing/documenting things as I go...
Then? :IRIS3130: ... Now? :O3x02L: :A3504L:- :A3502L: :1600SW:+MLA :Fuel: :Octane2: :Octane: :Indigo2IMP: ... Other: DEC :BA213: :BA123: Sun, DG AViiON, NeXT :Cube:

Return to “SGI: Development”

Who is online

Users browsing this forum: No registered users and 2 guests