From dae8e3e1481db52a1f19e7a2b8f2dc2d13c1f8ac Mon Sep 17 00:00:00 2001 From: dkf Date: Sat, 10 Oct 2009 19:38:27 +0000 Subject: [Bug 1961455]: Draw underlines and overstrikes when using Xft for font rendering --- ChangeLog | 6 ++++++ unix/tkUnixRFont.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2951d7c..38e829f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-10 Donal K. Fellows + + * unix/tkUnixRFont.c (InitFont,TkpGetFontFromAttributes,Tk_DrawChars): + [Bug 1961455]: Draw underlines and overstrikes when using Xft for font + rendering. + 2009-10-08 Donal K. Fellows * library/tkfbox.tcl (::tk::IconList_Create): [Patch 2870648]: diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c index b3d5ce4..f580b2f 100644 --- a/unix/tkUnixRFont.c +++ b/unix/tkUnixRFont.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkUnixRFont.c,v 1.24.2.1 2009/09/10 12:47:15 dkf Exp $ + * RCS: @(#) $Id: tkUnixRFont.c,v 1.24.2.2 2009/10/10 19:38:27 dkf Exp $ */ #include "tkUnixInt.h" @@ -35,7 +35,6 @@ typedef struct { XftDraw *ftDraw; XftColor color; } UnixFtFont; - /* * Package initialization: @@ -261,6 +260,44 @@ InitFont( GetTkFontAttributes(ftFont, &fontPtr->font.fa); GetTkFontMetrics(ftFont, &fontPtr->font.fm); + /* + * Fontconfig can't report any information about the position or thickness + * of underlines or overstrikes. Thus, we use some defaults that are + * hacked around from backup defaults in tkUnixFont.c, which are in turn + * based on recommendations in the X manual. The comments from that file + * leading to these computations were: + * + * If the XA_UNDERLINE_POSITION property does not exist, the X manual + * recommends using half the descent. + * + * If the XA_UNDERLINE_THICKNESS property does not exist, the X + * manual recommends using the width of the stem on a capital letter. + * I don't know of a way to get the stem width of a letter, so guess + * and use 1/3 the width of a capital I. + * + * Note that nothing corresponding to *either* property is reported by + * Fontconfig at all. [Bug 1961455] + */ + + { + TkFont *fPtr = &fontPtr->font; + int iWidth; + + fPtr->underlinePos = fPtr->fm.descent / 2; + Tk_MeasureChars((Tk_Font) fPtr, "I", 1, -1, 0, &iWidth); + fPtr->underlineHeight = iWidth / 3; + if (fPtr->underlineHeight == 0) { + fPtr->underlineHeight = 1; + } + if (fPtr->underlineHeight + fPtr->underlinePos > fPtr->fm.descent) { + fPtr->underlineHeight = fPtr->fm.descent - fPtr->underlinePos; + if (fPtr->underlineHeight == 0) { + fPtr->underlinePos--; + fPtr->underlineHeight = 1; + } + } + } + return fontPtr; } @@ -404,6 +441,9 @@ TkpGetFontFromAttributes( FcPatternDestroy(pattern); return NULL; } + + fontPtr->font.fa.underline = faPtr->underline; + fontPtr->font.fa.overstrike = faPtr->overstrike; return &fontPtr->font; } @@ -671,7 +711,7 @@ Tk_DrawChars( UnixFtFont *fontPtr = (UnixFtFont *) tkfont; XGCValues values; XColor xcolor; - int clen, nspec; + int clen, nspec, xStart = x; XftGlyphFontSpec specs[NUM_SPEC]; XGlyphInfo metrics; @@ -711,7 +751,7 @@ Tk_DrawChars( * This should not happen, but it can. */ - return; + goto doUnderlineStrikeout; } source += clen; numBytes -= clen; @@ -737,4 +777,17 @@ Tk_DrawChars( if (nspec) { XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec); } + + doUnderlineStrikeout: + if (fontPtr->font.fa.underline != 0) { + XFillRectangle(display, drawable, gc, xStart, + y + fontPtr->font.underlinePos, (unsigned) (x - xStart), + (unsigned) fontPtr->font.underlineHeight); + } + if (fontPtr->font.fa.overstrike != 0) { + y -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10; + XFillRectangle(display, drawable, gc, xStart, y, + (unsigned) (x - xStart), + (unsigned) fontPtr->font.underlineHeight); + } } -- cgit v0.12