Patch to use double width font (xft) in xterm

Zarick Lau <[email protected]>
Newsgroups gmane.comp.xfree86.internationalization
Message-ID <1072754636.1422.5.camel@localhost>
Hi,

I have made a patch on xterm so that, it can accept one more option /
resource, to utilize two fonts when using xft.

Originally, -fa option will make xterm to use xft instead of XFontSet,
but however, in most cases, this option is broken, as most CJK TTF fonts
can't have good (acceptable) monospaced appearance. Hence, I add one
more option '-fd' to accpet another font for 'double width' char.

Regards,
Zarick Lau
xterm-xftboldfont.patch (text/x-patch, 8.7 KB)
diff -u xterm/charproc.c xterm-new/charproc.c
--- xterm/charproc.c	2003-11-28 08:49:17.000000000 +0800
+++ xterm-new/charproc.c	2003-12-17 14:43:24.000000000 +0800
@@ -625,6 +625,7 @@
 #ifdef XRENDERFONT
     Ires(XtNfaceSize, XtCFaceSize, misc.face_size, DEFFACESIZE),
     Sres(XtNfaceName, XtCFaceName, misc.face_name, DEFFACENAME),
+    Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.face_wide_name, DEFFACENAME),
 #endif
 };
 
@@ -4948,6 +4949,8 @@
 #ifdef XRENDERFONT
     wnew->screen.renderFont = 0;
     wnew->screen.renderFontBold = 0;
+    wnew->screen.renderFontWide = 0;
+    wnew->screen.renderFontWideBold = 0;
     wnew->screen.renderDraw = 0;
 #endif
 
diff -u xterm/fontutils.c xterm-new/fontutils.c
--- xterm/fontutils.c	2003-10-29 07:11:58.000000000 +0800
+++ xterm-new/fontutils.c	2003-12-22 12:06:33.000000000 +0800
@@ -1130,6 +1130,27 @@
 	    if (!screen->renderFontBold && match)
 		XftPatternDestroy(match);
 
+	    if (!screen->renderFontWide && term->misc.face_wide_name) {
+		screen->renderFontWide = XftFontOpen (dpy, DefaultScreen (dpy),
+					   XFT_FAMILY,
+					   XftTypeString,
+					   term->misc.face_wide_name,
+					   XFT_PIXEL_SIZE,
+					   XftTypeInteger,
+				    screen->renderFont->max_advance_width * 2,
+					    (void *) 0);
+		screen->renderFontWideBold = NULL;
+	    }
+	    else {
+		screen->renderFontWide = XftFontOpen (dpy, DefaultScreen (dpy),
+			    XFT_FAMILY, XftTypeString, "mono",
+			    XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD,
+			    XFT_PIXEL_SIZE, XftTypeInteger,
+				    screen->renderFont->max_advance_width * 2,
+			    (void *) 0);
+		screen->renderFontWideBold = NULL;
+	    }
+
 	    /*
 	     * FIXME:  just assume that the corresponding font has no graphics
 	     * characters.
diff -u xterm/main.c xterm-new/main.c
--- xterm/main.c	2003-11-25 09:54:43.000000000 +0800
+++ xterm-new/main.c	2003-12-17 14:49:58.000000000 +0800
@@ -778,6 +778,7 @@
 #endif /* NO_ACTIVE_ICON */
 #ifdef XRENDERFONT
 {"-fa",		"*faceName",	XrmoptionSepArg,	(caddr_t) NULL},
+{"-fd",	"*faceNameDoublesize",	XrmoptionSepArg,	(caddr_t) NULL},
 {"-fs",		"*faceSize",	XrmoptionSepArg,	(caddr_t) NULL},
 #endif
 #if OPT_WIDE_CHARS
@@ -925,6 +926,7 @@
 { "-/+fbx",                "turn off/on linedrawing characters"},
 #ifdef XRENDERFONT
 { "-fa pattern",           "FreeType font-selection pattern" },
+{ "-fd pattern",           "FreeType Doublesize font-selection pattern" },
 { "-fs size",              "FreeType font-size" },
 #endif
 #if OPT_WIDE_CHARS
diff -u xterm/os2main.c xterm-new/os2main.c
--- xterm/os2main.c	2003-05-22 06:59:13.000000000 +0800
+++ xterm-new/os2main.c	2003-12-17 14:48:48.000000000 +0800
@@ -344,6 +344,7 @@
 #endif /* NO_ACTIVE_ICON */
 #ifdef XRENDERFONT
 {"-fa",		"*faceName",	XrmoptionSepArg,	(caddr_t) NULL},
+{"-fd",		"*faceNameDoublesize",	XrmoptionSepArg,	(caddr_t) NULL},
 {"-fs",		"*faceSize",	XrmoptionSepArg,	(caddr_t) NULL},
 #endif
 #if OPT_WIDE_CHARS
@@ -484,6 +485,7 @@
 { "-/+fbx",                "turn off/on linedrawing characters"},
 #ifdef XRENDERFONT
 { "-fa pattern",           "FreeType font-selection pattern" },
+{ "-fd pattern",           "FreeType Doublesize font-selection pattern" },
 { "-fs size",              "FreeType font-size" },
 #endif
 #if OPT_WIDE_CHARS
diff -u xterm/ptyx.h xterm-new/ptyx.h
--- xterm/ptyx.h	2003-10-27 09:07:57.000000000 +0800
+++ xterm-new/ptyx.h	2003-12-17 10:02:29.000000000 +0800
@@ -1376,6 +1376,8 @@
 #ifdef XRENDERFONT
 	XftFont		*renderFont;
 	XftFont		*renderFontBold;
+	XftFont		*renderFontWide;
+	XftFont		*renderFontWideBold;
 	XftDraw		*renderDraw;
 #endif
 #if OPT_INPUT_METHOD
@@ -1513,6 +1515,7 @@
 #endif
 #ifdef XRENDERFONT
     char *face_name;
+    char *face_wide_name;
     int face_size;
 #endif
 } Misc;
diff -u xterm/util.c xterm-new/util.c
--- xterm/util.c	2003-10-27 09:07:57.000000000 +0800
+++ xterm-new/util.c	2003-12-22 12:04:34.000000000 +0800
@@ -1411,6 +1411,7 @@
 xtermXftDrawString(XftDraw * draw,
 		   XftColor * color,
 		   XftFont * font,
+		   XftFont * wfont,
 		   int x,
 		   int y,
 		   PAIRED_CHARS(Char * text, Char * text2),
@@ -1419,28 +1420,60 @@
 		   int *deltax)
 {
 #if OPT_WIDE_CHARS && defined(HAVE_TYPE_XFTCHARSPEC)
-    static XftCharSpec *sbuf;
-    static unsigned slen;
     int n;
     int ncells = 0;		/* # of 'half-width' charcells */
+    static XftCharSpec * specs;
+    static int	nspecs   = 0;
+    XftFont *	lastFont = 0;
+    XftFont *	currFont = 0;
+    int		start	 = 0;
+    int		charWidth;
+    FcChar32	wc;
+
+    if ((int) nspecs < len) {
+	nspecs = (len + 1) * 2;
+	specs  = (XftCharSpec *) XtRealloc((char *) specs,
+					    nspecs * sizeof(XftCharSpec));
+    }
+
+    if (len == 0 || !(*text || *text2)) {
+	return;
+    }
+
+    if (text2)
+	wc = *text++ | (*text2++ << 8);
+    else
+	wc = *text++;
+
+    specs[0].ucs4 = wc;
+    specs[0].x    = x + fwidth * ncells;
+    specs[0].y    = y;
+    charWidth = my_wcwidth(wc);
+    lastFont  = (charWidth == 2) ? wfont : font;
+    ncells    += charWidth;
+    start     = 0;
 
-    if ((int) slen < len) {
-	slen = (len + 1) * 2;
-	sbuf = (XftCharSpec *) XtRealloc((char *) sbuf,
-					 slen * sizeof(XftCharSpec));
-    }
-    for (n = 0; n < len; n++) {
-	FcChar32 wc;
+    for (n = 1; n < len; n++) {
 	if (text2)
 	    wc = *text++ | (*text2++ << 8);
 	else
 	    wc = *text++;
-	sbuf[n].ucs4 = wc;
-	sbuf[n].x = x + fwidth * ncells;
-	ncells += my_wcwidth(wc);
-	sbuf[n].y = y;
+	specs[n].ucs4 = wc;
+	if (wc == 0xFFFF)
+	    continue;
+	specs[n].x = x + fwidth * ncells;
+	specs[n].y = y;
+	charWidth = my_wcwidth(wc);
+	currFont = (charWidth == 2) ? wfont : font;
+	ncells += charWidth;
+	if (lastFont != currFont) {
+	    XftDrawCharSpec (draw, color, lastFont, specs + start, n - start);
+	    start = n;
+	    lastFont = currFont;
+	}
     }
-    XftDrawCharSpec(draw, color, font, sbuf, len);
+    XftDrawCharSpec (draw, color, lastFont, specs + start, n - start);
+
     if (deltax)
 	*deltax = ncells * fwidth;
 #else
@@ -1519,7 +1552,7 @@
 #ifdef XRENDERFONT
     if (screen->renderFont) {
 	Display *dpy = screen->display;
-	XftFont *font;
+	XftFont *font, *wfont;
 	XGCValues values;
 
 	if (!screen->renderDraw) {
@@ -1533,10 +1566,14 @@
 					       DefaultColormap(dpy, scr));
 	}
 	if ((flags & (BOLD | BLINK))
-	    && screen->renderFontBold)
+	    && screen->renderFontBold) {
 	    font = screen->renderFontBold;
-	else
+	    wfont = screen->renderFontWideBold;
+	}
+	else {
 	    font = screen->renderFont;
+	    wfont = screen->renderFontWide;
+	}
 	XGetGCValues(dpy, gc, GCForeground | GCBackground, &values);
 	if (!(flags & NOBACKGROUND))
 	    XftDrawRect(screen->renderDraw,
@@ -1571,7 +1608,7 @@
 		    if (last > first) {
 			xtermXftDrawString(screen->renderDraw,
 					   getColor(values.foreground),
-					   font, curX, y,
+					   font, wfont, curX, y,
 					   PAIRED_CHARS(text + first,
 							text2 + first),
 					   last - first, FontWidth(screen),
@@ -1593,7 +1630,7 @@
 	    if (last > first) {
 		xtermXftDrawString(screen->renderDraw,
 				   getColor(values.foreground),
-				   font, curX, y,
+				   font, wfont, curX, y,
 				   PAIRED_CHARS(text + first, text2 + first),
 				   last - first, FontWidth(screen), NULL);
 	    }
@@ -1602,7 +1639,7 @@
 	{
 	    xtermXftDrawString(screen->renderDraw,
 			       getColor(values.foreground),
-			       font, x, y, PAIRED_CHARS(text, text2),
+			       font, wfont, x, y, PAIRED_CHARS(text, text2),
 			       len, FontWidth(screen), NULL);
 	}
 
diff -u xterm/xterm.h xterm-new/xterm.h
--- xterm/xterm.h	2003-12-19 05:12:16.000000000 +0800
+++ xterm-new/xterm.h	2003-12-17 14:44:14.000000000 +0800
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/xterm/xterm.h,v 3.93 2003/12/18 21:12:16 dickey Exp $ */
+/* $XFree86: xc/programs/xterm/xterm.h,v 3.93 2003/10/27 01:07:58 dickey Exp $ */
 
 /************************************************************
 
@@ -317,6 +317,7 @@
 #define XtNeightBitInput	"eightBitInput"
 #define XtNeightBitOutput	"eightBitOutput"
 #define XtNfaceName		"faceName"
+#define XtNfaceNameDoublesize	"faceNameDoublesize"
 #define XtNfaceSize		"faceSize"
 #define XtNfont1		"font1"
 #define XtNfont2		"font2"
@@ -433,6 +434,7 @@
 #define XtCEightBitInput	"EightBitInput"
 #define XtCEightBitOutput	"EightBitOutput"
 #define XtCFaceName		"FaceName"
+#define XtCFaceNameDoublesize		"FaceNameDoublesize"
 #define XtCFaceSize		"FaceSize"
 #define XtCFont1		"Font1"
 #define XtCFont2		"Font2"
@@ -775,7 +777,7 @@
 		(Char *)(((long)SCRN_BUF_FLAGS(screen, row + screen->topline) | LINEWRAPPED))
 
 #define ScrnTstWrapped(screen, row) \
-	((row + screen->topline) >= 0 && ((long)SCRN_BUF_FLAGS(screen, row + screen->topline) & LINEWRAPPED) != 0)
+	(((long)SCRN_BUF_FLAGS(screen, row + screen->topline) & LINEWRAPPED) != 0)
 
 /* scrollbar.c */
 extern void DoResizeScreen (XtermWidget xw);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.