[teklib-general] changeset in /hg/teklib/current: added basic xft support

Franciska Schulze fschulze at neoscientists.org
Mon Nov 26 16:23:22 CET 2007


changeset 9544c679baad in /hg/teklib/current
details: http://teklib.org:8001/hg/teklib/current?cmd=changeset;node=9544c679baad
description:
	added basic xft support

diffs (truncated from 615 to 300 lines):

diff -r 09f5a732c25d -r 9544c679baad src/visual/posix/visual_font.c
--- a/src/visual/posix/visual_font.c	Thu Sep 13 19:20:03 2007 +0200
+++ b/src/visual/posix/visual_font.c	Mon Sep 17 18:49:57 2007 +0200
@@ -1,16 +1,21 @@
 /*
-**	$Id: visual_host.c,v 1.3 2006/09/10 14:38:04 tmueller Exp $
-**	teklib/src/visual/posix/visual_font.c - xlib based font management
-**
-*/
+**	$Id: visual_font.c,v 1.3 2006/09/10 14:38:04 fschulze Exp $
+**	teklib/src/visual/posix/visual_font.c - x11 based font management
+**
+**	TODO:
+**	- implement xft version of drawtext2
+**	- convert pens to xftcolors
+*/
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
 
 #include <tek/debug.h>
 #include <tek/teklib.h>
 #include <tek/proto/hal.h>
 #include "visual_mod.h"
 
-#include <stdio.h>
-#include <string.h>
 #include "visual_host.h"
 #include "visual_font.h"
 
@@ -153,6 +158,9 @@ fqhdestroy(struct THook *hook, TAPTR obj
 }
 
 /*****************************************************************************/
+/* allocate a fontquerynode and fill in properties derived from
+** a x11 fontname
+*/
 LOCAL struct FontQueryNode *
 fnt_getfqnode(TMOD_VIS *mod, TSTRPTR fontname)
 {
@@ -380,6 +388,88 @@ fnt_getfnnodes(TMOD_VIS *mod, struct TLi
 
 LOCAL TAPTR
 vis_hostopenfont(TMOD_VIS *mod, TTAGITEM *tags)
+{
+	TAPTR font = TNULL;
+	GLOBAL *g = mod->vis_HostGlobal;
+
+	if (g->use_xft == TTRUE)
+		font = hostopenfont_xft(mod, tags);
+	else
+		font = hostopenfont_xlib(mod, tags);
+
+	return font;
+}
+
+LOCAL TAPTR
+hostopenfont_xft(TMOD_VIS *mod, TTAGITEM *tags)
+{
+	GLOBAL *g = mod->vis_HostGlobal;
+	TINT fpxsize;
+	TBOOL fitalic, fbold, fscale;
+	TAPTR font = TNULL;
+	TSTRPTR fname = TNULL;
+	struct FontNode *fn;
+	TAPTR exec = TGetExecBase(mod);
+
+	/* fetch user specified attributes */
+	fname = (TSTRPTR) TGetTag(tags, TVisual_FontName, (TTAG) FNT_DEFNAME);
+	fpxsize = (TINT) TGetTag(tags, TVisual_FontPxSize, (TTAG) FNT_DEFPXSIZE);
+	fitalic = (TBOOL) TGetTag(tags, TVisual_FontItalic, (TTAG) TFALSE);
+	fbold = (TBOOL) TGetTag(tags, TVisual_FontBold, (TTAG) TFALSE);
+	fscale = (TBOOL) TGetTag(tags, TVisual_FontScaleable, (TTAG) TFALSE);
+
+	if (fname)
+	{
+		TExecLock(exec, g->lock);
+
+		/* allocate new font node */
+		fn = TExecAlloc0(exec, mod->vis_MMU, sizeof(struct FontNode));
+		if (fn)
+		{
+			fn->xftfont = (*g->xftiface.XftFontOpen)(g->display, g->screen,
+				XFT_FAMILY, XftTypeString, fname,
+				XFT_PIXEL_SIZE, XftTypeDouble, (TFLOAT)fpxsize,
+				XFT_SLANT, XftTypeInteger, (fitalic ? XFT_SLANT_ITALIC : XFT_SLANT_ROMAN),
+				XFT_WEIGHT, XftTypeInteger, (fbold ? XFT_WEIGHT_BOLD : XFT_WEIGHT_MEDIUM),
+				XFT_SCALABLE, XftTypeBool, fscale,
+				XFT_ENCODING, XftTypeString, FNT_DEFREGENC,
+				XFT_ANTIALIAS, XftTypeBool, TTRUE, NULL);
+
+			if (fn->xftfont)
+			{
+				/* save font attributes */
+				fn->pxsize = fpxsize;
+				if (fitalic)
+					fn->attr = FNT_ITALIC;
+				if (fbold)
+					fn->attr |= FNT_BOLD;
+
+				/* append to the list of open fonts */
+				TDBPRINTF(10, ("O '%s'\n", fname));
+				TAddTail(&g->fm.openfonts, &fn->node);
+				font = (TAPTR)fn;
+			}
+			else
+			{
+				/* query failed, return pointer to default font */
+				TDBPRINTF(10, ("! unable to load '%s'\n", fname));
+				TDBPRINTF(10, ("! defaulting to '%s'\n", DEFFONTNAME));
+				TExecFree(exec, fn);
+				font = g->fm.deffont;
+				g->fm.defref++;
+			}
+		}
+
+		TExecUnlock(exec, g->lock);
+	}
+	else
+		TDBPRINTF(20, ("invalid fontname '%s' specified\n", fname));
+
+	return font;
+}
+
+LOCAL TAPTR
+hostopenfont_xlib(TMOD_VIS *mod, TTAGITEM *tags)
 {
 	GLOBAL *g = mod->vis_HostGlobal;
 	TINT fpxsize;
@@ -666,14 +756,18 @@ setfont(TMOD_VIS *mod, TAPTR font)
 setfont(TMOD_VIS *mod, TAPTR font)
 {
 	VISUAL *v = mod->vis_HostVisual;
+	GLOBAL *g = mod->vis_HostGlobal;
 
 	if (font)
 	{
-		XGCValues gcv;
-		struct FontNode *fn = (struct FontNode *) font;
-
-		gcv.font = fn->font->fid;
-		XChangeGC(v->display, v->gc, GCFont, &gcv);
+		if (!g->use_xft)
+		{
+			XGCValues gcv;
+			struct FontNode *fn = (struct FontNode *) font;
+
+			gcv.font = fn->font->fid;
+			XChangeGC(v->display, v->gc, GCFont, &gcv);
+		}
 		v->curfont = font;
 	}
 	else
@@ -779,6 +873,17 @@ vis_hostclosefont(TMOD_VIS *mod, TAPTR f
 		fn->font = TNULL;
 	}
 
+	/* free xftfont */
+	if (fn->xftfont)
+	{
+		/* FIXME: it seems that libxft is not properly handling font
+		   references, this yields to fonts being freed twice and
+		   the X server answers with a RenderBadGlyphSet */
+
+		//(*g->xftiface.XftFontClose)(g->display, fn->xftfont);
+		//fn->xftfont = TNULL;
+	}
+
 	/* remove from openfonts list */
 	TRemove(&fn->node);
 
@@ -812,7 +917,17 @@ vis_hosttextsize(TMOD_VIS *mod, TAPTR fo
 	GLOBAL *g = mod->vis_HostGlobal;
 	struct FontNode *fn = (struct FontNode *) font;
 	TExecLock(exec, g->lock);
-	len = XTextWidth(fn->font, text, strlen(text));
+
+	if (g->use_xft == TTRUE)
+	{
+		XGlyphInfo extents;
+		(*g->xftiface.XftTextExtentsUtf8)(g->display, fn->xftfont,
+			(FcChar8 *)text, strlen(text), &extents);
+		len = extents.width;
+	}
+	else
+		len = XTextWidth(fn->font, text, strlen(text));
+
 	TExecUnlock(exec, g->lock);
 	return len;
 }
@@ -854,13 +969,13 @@ vis_hostgetfattrfunc(struct THook *hook,
 vis_hostgetfattrfunc(struct THook *hook, TAPTR obj, TTAG msg)
 {
 	struct attrdata *data = hook->thk_Data;
+	GLOBAL *g = data->mod->vis_HostGlobal;
 	TTAGITEM *item = obj;
 	struct FontNode *fn = (struct FontNode *) data->font;
 
 	switch (item->tti_Tag)
 	{
 		default:
-
 			return TTRUE;
 
 		case TVisual_FontPxSize:
@@ -876,28 +991,80 @@ vis_hostgetfattrfunc(struct THook *hook,
 			break;
 
 		case TVisual_FontAscent:
-			*((TINT *) item->tti_Value) = fn->font->ascent;
+			*((TINT *) item->tti_Value) = g->use_xft ?
+				fn->xftfont->ascent : fn->font->ascent;
 			break;
 
 		case TVisual_FontDescent:
-			*((TINT *) item->tti_Value) = fn->font->descent;
+			*((TINT *) item->tti_Value) = g->use_xft ?
+				fn->xftfont->descent : fn->xftfont->descent;
 			break;
 
 		case TVisual_FontHeight:
-			*((TINT *) item->tti_Value) = fn->font->ascent + fn->font->descent;
+			*((TINT *) item->tti_Value) = g->use_xft ?
+				fn->xftfont->ascent + fn->xftfont->descent :
+				fn->font->ascent + fn->font->descent;
 			break;
 
 		case TVisual_FontUlPosition:
-			if (!XGetFontProperty(fn->font, XA_UNDERLINE_POSITION,
-				(unsigned long *)item->tti_Value))
-				*((TINT *) item->tti_Value) = fn->font->descent / 2;
-			break;
-
+		{
+			if (g->use_xft)
+			{
+				TFLOAT scale;
+    			TFLOAT ulp = fn->xftfont->descent / 2;
+				FT_Face face = (*g->xftiface.XftLockFace)(fn->xftfont);
+
+				if (face)
+				{
+					if (face->units_per_EM != 0)
+					{
+						scale = (TFLOAT)fn->xftfont->height / face->units_per_EM;
+						ulp = (TFLOAT)(face->underline_position) * scale;
+						/* FIXME: result is possibly (always?) negative;
+					   	   not sure if it can be handled this way */
+						ulp = fabs(ulp);
+					}
+					(*g->xftiface.XftUnlockFace)(fn->xftfont);
+				}
+
+    			*((TINT *) item->tti_Value) = (TINT)ulp;
+			}
+			else
+			{
+				if (!XGetFontProperty(fn->font, XA_UNDERLINE_POSITION,
+					(unsigned long *)item->tti_Value))
+					*((TINT *) item->tti_Value) = fn->font->descent / 2;
+			}
+			break;
+		}
 		case TVisual_FontUlThickness:
-			if (!XGetFontProperty(fn->font, XA_UNDERLINE_THICKNESS,
-				(unsigned long *)item->tti_Value))
-				*((TINT *) item->tti_Value) = 1;
-			break;
+		{
+			if (g->use_xft)
+			{
+				TFLOAT scale;
+				TFLOAT ult = 1;
+				FT_Face face = (*g->xftiface.XftLockFace)(fn->xftfont);
+
+				if (face)
+				{
+					if (face->units_per_EM != 0)
+					{
+						scale = (TFLOAT)fn->xftfont->height / face->units_per_EM;
+						ult = (TFLOAT)(face->underline_thickness) * scale;
+					}
+					(*g->xftiface.XftUnlockFace)(fn->xftfont);
+				}
+
+				*((TINT *) item->tti_Value) = (TINT)ult;
+			}
+			else
+			{
+				if (!XGetFontProperty(fn->font, XA_UNDERLINE_THICKNESS,
+					(unsigned long *)item->tti_Value))
+					*((TINT *) item->tti_Value) = 1;
+			}
+			break;
+		}
 
 		/* ... */
 	}
diff -r 09f5a732c25d -r 9544c679baad src/visual/posix/visual_font.h


More information about the teklib-general mailing list