[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Xft-related bug in Qt 3.2.3



Hello.

Seems that I've found a bug in how Qt 3.2.3 interoperates with Xft.

Initial symptom was that after I upgraded my Debian SID system some time 
ago, my KDE desktop became somewhat broken: cyrillic characters were 
displayed in a different font than latin characters in the same string; 
and in terminal windows cyrillic characters were displayed in 
non-monospace fonts, causing really ugly effects.

It was obvious that after upgrade Qt lost some fonts.

After some investigation I found that is was caused by fontconfig package 
upgrade, exactly - by adding /usr/local/share/fonts to default font search 
directories. In that directory, I have a subdirectory with X11 fonts 
without unicode characters - they are used by xfs to feed really slow X 
terminals that become unacceptably slow if unicode fonts are available.

Moving that subdir away (and running fc-cache) returned normal fonts.
Moving that dir back and leaving there a single iso8859-1 fixed font (and 
running fc-cache) caused the problem again.

At last I've got some time to debug the issue. It is Qt problem, caused by 
the following code in kernel/qfontdatabase_x11.cpp, function loadXft():

#ifdef QT_XFT2
	if (! family->xftScriptCheck) {
	    FcCharSet *charset = 0;
	    FcResult res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, 
&charset);
	    if (res == FcResultMatch) {
		for (int i = 0; i < QFont::LastPrivateScript; ++i) {
		    QChar ch = sampleCharacter((QFont::Script) i);

		    if (ch.unicode() != 0 &&
			FcCharSetHasChar(charset, ch.unicode())) {
			family->scripts[i] = QtFontFamily::Supported;
		    } else {
			family->scripts[i] |= QtFontFamily::UnSupported_Xft;
		    }
		}
		family->xftScriptCheck = TRUE;
	    }
	}
#endif // QT_XFT2

This code assumes that all fonts with the same family have same scripts 
available. So if Xft returnes Fixed iso8895-1 font earlier that Fixed 
iso10646-1 font, Qt records that "Fixed" family has no cyrillic 
characters! Which is definitly not true.

Qt is very complex and I'm not familiar with it enough to fix the problem. 
However, I was able to workaround it by the following:

#ifdef QT_XFT2
//	if (! family->xftScriptCheck) {
	    FcCharSet *charset = 0;
	    FcResult res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, 
&charset);
	    if (res == FcResultMatch) {
		for (int i = 0; i < QFont::LastPrivateScript; ++i) {
		    QChar ch = sampleCharacter((QFont::Script) i);

		    if (!family->xftScriptCheck || family->scripts[i] != 
QtFontFamily::Supported) {
		      if (ch.unicode() != 0 &&
			FcCharSetHasChar(charset, ch.unicode())) {
			family->scripts[i] = QtFontFamily::Supported;
		      } else {
			family->scripts[i] |= QtFontFamily::UnSupported_Xft;
		      }
		    }
		}
		family->xftScriptCheck = TRUE;
	    }
//	}
#endif // QT_XFT2

This makes it to check all fonts of the family, and mark a script as 
supported if there is a font providing it.



Reply to: