[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