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
squeen
Moderator
Moderator
Posts: 2931
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 11: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

xfthello.c

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>
#endif

#define DEFAULT_BDWIDTH 1 /* border width */

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

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;
#else
   GC                      gc;
   XGCValues               gcvals;
   XFontStruct             *font;
#endif
   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" );
#else   
   font = XLoadQueryFont( dpy, "-*-helvetica-medium-r-normal--20-*-*-*-p-100-iso8859-1" );
#endif
   
   /* 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;
#else   
   ytext = font->max_bounds.ascent + font->max_bounds.descent;
   wtext = font->max_bounds.width / 2 + XTextWidth( font, text, strlen(text) + 4 );
#endif   
   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 );
#else                 
   /* create graphics context */
   gcvals.font = font->fid;
   gcvals.foreground = fgpix;
   gcvals.background = bgpix;
   gc = XCreateGC( dpy, mainW, (GCFont|GCForeground|GCBackground), &gcvals );
#endif   
   
   /* 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 )
                     break;
                  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) );
#else
                  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) );
#endif           
                  force_expose = 0;
               }
               break;
            case ButtonPress:
               Done = 1;
               printf("good-bye!\n");
               break;
            default:
               break;
         }
      }
   }

   /* 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 );
#else
   XFreeGC( dpy, gc );
#endif
   XDestroyWindow( dpy, mainW );
   XCloseDisplay( dpy );
             
   return(0);
}



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
XFTLIBS = -lXft
 
%.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 
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.

Image

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

Cheers!

User avatar
dj
Posts: 326
Joined: Tue Nov 01, 2005 12:35 pm
Location: california

Unread postby dj » Tue Jan 24, 2006 9: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
squeen
Moderator
Moderator
Posts: 2931
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 5:11 am

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

User avatar
PymbleSoftware
Posts: 1887
Joined: Tue Jul 15, 2008 5:48 pm
Location: P.O. Box 121, Pymble, Sydney, NSW 2073, Australia.
Contact:

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

Unread postby PymbleSoftware » Mon Jan 09, 2012 11: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...

R.
死の神はりんごだけ食べる

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

: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.

@PymbleSoftware
Current Apps -> https://itunes.apple.com/au/artist/pymb ... d553990081
Cortex ---> http://www.facebook.com/pages/Cortex-th ... 11?sk=info
Minnie ---> http://www.facebook.com/pages/Minnie-th ... 02?sk=info
Github ---> https://github.com/pymblesoftware
Visit http://www.pymblesoftware.com
Search for "Pymble", "InstaElf", "CryWhy" or "Cricket Score Sheet" in the iPad App store or search for "Pymble" or "CryWhy" in the iPhone App store.

User avatar
smj
Posts: 1409
Joined: Mon Nov 12, 2007 8:54 pm
Location: Berkeley, CA, USA, NA, Earth, Sol
Contact:

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

Unread postby smj » Tue Jan 10, 2012 3: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 1 guest