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 via email to