3e7013f
From 589a94ddb30499b0f3ecaf909a5b291d64d02dc7 Mon Sep 17 00:00:00 2001
9c291e4
From: Jiang Jiang <jiang.jiang@nokia.com>
9c291e4
Date: Mon, 20 Jun 2011 13:47:01 +0200
9c291e4
Subject: [PATCH] Fix fontconfig usage in X11 font database
9c291e4
9c291e4
We should do FcConfigSubstitute(0, pattern, FcMatchFont) on a
9c291e4
FcPattern for query because the family list in it will contain
9c291e4
almost all the families after FcConfigSubstitute(0, pattern,
9c291e4
FcMatchPattern), then the test in <match target="font"> will
9c291e4
almost always succeed. In general, FcMatchFont substitute
9c291e4
should only be done on the FcPattern that we got after
9c291e4
FcFontMatch() or FcFontRenderPrepare().
9c291e4
9c291e4
Based on the suggestion of fontconfig author Behdad Esfahbod,
9c291e4
this patch reorganized the tryPatternLoad logic so that it only
9c291e4
does the QFontEngine creation part, FcPattern *match is retrieved
9c291e4
outside of that function. In this way, the match pattern we got
9c291e4
can be either from FcFontMatch() or after FcFontRenderPrepare()
9c291e4
on one of the fonts we got from qt_fontSetForPattern(). Then we
9c291e4
don't need to duplicate the pattern and add all criterias back
9c291e4
with qt_addPatternProps(). It not only simplified the code a lot
9c291e4
but also fix the way we apply FcMatchFont substitution. This
9c291e4
substitution will either be done by FcFontMatch() or
9c291e4
FcFontRenderPrepare, both implicitly.
9c291e4
9c291e4
Task-number: QTBUG-2148, QTBUG-19947
9c291e4
Reviewed-by: Eskil
9c291e4
---
9c291e4
 src/gui/text/qfontdatabase_x11.cpp |   55 +++++++++++++++---------------------
3e7013f
 src/gui/text/qfontengine_x11.cpp   |   28 +++++-------------
3e7013f
 2 files changed, 31 insertions(+), 52 deletions(-)
9c291e4
9c291e4
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
9c291e4
index 754334c..958daa2 100644
9c291e4
--- a/src/gui/text/qfontdatabase_x11.cpp
9c291e4
+++ b/src/gui/text/qfontdatabase_x11.cpp
9c291e4
@@ -1566,9 +1566,8 @@ static FcPattern *getFcPattern(const QFontPrivate *fp, int script, const QFontDe
9c291e4
 
9c291e4
     qt_addPatternProps(pattern, fp->screen, script, request);
d8fc052
 
9c291e4
-    FcDefaultSubstitute(pattern);
d8fc052
     FcConfigSubstitute(0, pattern, FcMatchPattern);
d8fc052
-    FcConfigSubstitute(0, pattern, FcMatchFont);
9c291e4
+    FcDefaultSubstitute(pattern);
d8fc052
 
d8fc052
     // these should only get added to the pattern _after_ substitution
d8fc052
     // append the default fallback font for the specified script
9c291e4
@@ -1606,35 +1605,20 @@ static void FcFontSetRemove(FcFontSet *fs, int at)
d8fc052
         memmove(fs->fonts + at, fs->fonts + at + 1, len);
d8fc052
 }
d8fc052
 
d8fc052
-static QFontEngine *tryPatternLoad(FcPattern *p, int screen,
d8fc052
-                                   const QFontDef &request, int script, FcPattern **matchedPattern = 0)
d8fc052
+static QFontEngine *tryPatternLoad(FcPattern *match, int screen,
d8fc052
+                                   const QFontDef &request, int script)
d8fc052
 {
d8fc052
 #ifdef FONT_MATCH_DEBUG
d8fc052
     FcChar8 *fam;
d8fc052
-    FcPatternGetString(p, FC_FAMILY, 0, &fam;;
d8fc052
+    FcPatternGetString(match, FC_FAMILY, 0, &fam;;
d8fc052
     FM_DEBUG("==== trying %s\n", fam);
d8fc052
 #endif
d8fc052
     FM_DEBUG("passes charset test\n");
d8fc052
-    FcPattern *pattern = FcPatternDuplicate(p);
d8fc052
-    // add properties back in as the font selected from the
d8fc052
-    // list doesn't contain them.
d8fc052
-    qt_addPatternProps(pattern, screen, script, request);
d8fc052
-
d8fc052
-    FcConfigSubstitute(0, pattern, FcMatchPattern);
d8fc052
-    FcDefaultSubstitute(pattern);
d8fc052
-    FcResult res;
d8fc052
-    FcPattern *match = FcFontMatch(0, pattern, &res;;
d8fc052
-
d8fc052
-    if (matchedPattern)
d8fc052
-	*matchedPattern = 0;
d8fc052
 
d8fc052
     QFontEngineX11FT *engine = 0;
d8fc052
     if (!match) // probably no fonts available.
d8fc052
         goto done;
d8fc052
 
d8fc052
-    if (matchedPattern)
d8fc052
-	*matchedPattern = FcPatternDuplicate(match);
d8fc052
-
d8fc052
     if (script != QUnicodeTables::Common) {
d8fc052
         // skip font if it doesn't support the language we want
d8fc052
         if (specialChars[script]) {
9c291e4
@@ -1673,11 +1657,6 @@ static QFontEngine *tryPatternLoad(FcPattern *p, int screen,
d8fc052
         }
d8fc052
     }
d8fc052
 done:
d8fc052
-    FcPatternDestroy(pattern);
d8fc052
-    if (!engine && matchedPattern && *matchedPattern) {
d8fc052
-        FcPatternDestroy(*matchedPattern);
d8fc052
-        *matchedPattern = 0;
d8fc052
-    }
d8fc052
     return engine;
d8fc052
 }
d8fc052
 
9c291e4
@@ -1726,14 +1705,26 @@ static QFontEngine *loadFc(const QFontPrivate *fp, int script, const QFontDef &r
d8fc052
 #endif
d8fc052
 
d8fc052
     QFontEngine *fe = 0;
d8fc052
-    FcPattern *matchedPattern = 0;
d8fc052
-    fe = tryPatternLoad(pattern, fp->screen, request, script, &matchedPattern);
d8fc052
+    FcResult res;
d8fc052
+    FcPattern *match = FcFontMatch(0, pattern, &res;;
d8fc052
+    fe = tryPatternLoad(match, fp->screen, request, script);
d8fc052
     if (!fe) {
d8fc052
         FcFontSet *fs = qt_fontSetForPattern(pattern, request);
d8fc052
 
9c291e4
+        if (match) {
9c291e4
+            FcPatternDestroy(match);
9c291e4
+            match = 0;
9c291e4
+        }
9c291e4
+
d8fc052
         if (fs) {
d8fc052
-            for (int i = 0; !fe && i < fs->nfont; ++i)
d8fc052
-                fe = tryPatternLoad(fs->fonts[i], fp->screen, request, script, &matchedPattern);
9c291e4
+            for (int i = 0; !fe && i < fs->nfont; ++i) {
9c291e4
+                match = FcFontRenderPrepare(NULL, pattern, fs->fonts[i]);
d8fc052
+                fe = tryPatternLoad(match, fp->screen, request, script);
d8fc052
+                if (fe)
d8fc052
+                    break;
9c291e4
+                FcPatternDestroy(match);
d8fc052
+                match = 0;
d8fc052
+            }
d8fc052
             FcFontSetDestroy(fs);
d8fc052
         }
d8fc052
         FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)");
9c291e4
@@ -1741,11 +1732,11 @@ static QFontEngine *loadFc(const QFontPrivate *fp, int script, const QFontDef &r
d8fc052
     if (fe
d8fc052
         && script == QUnicodeTables::Common
d8fc052
         && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) {
d8fc052
-        fe = new QFontEngineMultiFT(fe, matchedPattern, pattern, fp->screen, request);
9c291e4
+        fe = new QFontEngineMultiFT(fe, match, pattern, fp->screen, request);
d8fc052
     } else {
d8fc052
         FcPatternDestroy(pattern);
d8fc052
-        if (matchedPattern)
d8fc052
-            FcPatternDestroy(matchedPattern);
d8fc052
+        if (match)
d8fc052
+            FcPatternDestroy(match);
d8fc052
     }
d8fc052
     return fe;
d8fc052
 }
9c291e4
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
3e7013f
index e3bfa5d..490866c 100644
9c291e4
--- a/src/gui/text/qfontengine_x11.cpp
9c291e4
+++ b/src/gui/text/qfontengine_x11.cpp
9c291e4
@@ -863,11 +863,8 @@ glyph_t QFontEngineXLFD::glyphIndexToFreetypeGlyphIndex(glyph_t g) const
d8fc052
 // Multi FT engine
d8fc052
 // ------------------------------------------------------------------
d8fc052
 
d8fc052
-static QFontEngine *engineForPattern(FcPattern *pattern, const QFontDef &request,
9c291e4
-                                     int screen)
9c291e4
+static QFontEngine *engineForPattern(FcPattern *match, const QFontDef &request, int screen)
d8fc052
 {
d8fc052
-    FcResult res;
d8fc052
-    FcPattern *match = FcFontMatch(0, pattern, &res;;
d8fc052
     QFontEngineX11FT *engine = new QFontEngineX11FT(match, request, screen);
d8fc052
     if (!engine->invalid())
d8fc052
         return engine;
9c291e4
@@ -879,9 +876,9 @@ static QFontEngine *engineForPattern(FcPattern *pattern, const QFontDef &request
d8fc052
 }
d8fc052
 
9c291e4
 QFontEngineMultiFT::QFontEngineMultiFT(QFontEngine *fe, FcPattern *matchedPattern, FcPattern *p, int s, const QFontDef &req)
d8fc052
-    : QFontEngineMulti(2), request(req), pattern(p), firstEnginePattern(matchedPattern), fontSet(0), screen(s)
d8fc052
+    : QFontEngineMulti(2), request(req), pattern(p), fontSet(0), screen(s)
d8fc052
 {
9c291e4
-
9c291e4
+    firstEnginePattern = FcPatternDuplicate(matchedPattern);
d8fc052
     engines[0] = fe;
9c291e4
     engines.at(0)->ref.ref();
9c291e4
     fontDef = engines[0]->fontDef;
9c291e4
@@ -907,8 +904,6 @@ void QFontEngineMultiFT::loadEngine(int at)
d8fc052
     extern QMutex *qt_fontdatabase_mutex();
d8fc052
     QMutexLocker locker(qt_fontdatabase_mutex());
d8fc052
 
d8fc052
-    extern void qt_addPatternProps(FcPattern *pattern, int screen, int script,
d8fc052
-                                   const QFontDef &request);
d8fc052
     extern QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &);
d8fc052
     extern FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request);
d8fc052
 
3e7013f
@@ -940,22 +935,18 @@ void QFontEngineMultiFT::loadEngine(int at)
d8fc052
     Q_ASSERT(at < engines.size());
d8fc052
     Q_ASSERT(engines.at(at) == 0);
d8fc052
 
d8fc052
-    FcPattern *pattern = FcPatternDuplicate(fontSet->fonts[at + firstFontIndex - 1]);
d8fc052
-    qt_addPatternProps(pattern, screen, QUnicodeTables::Common, request);
9c291e4
-
d8fc052
-    QFontDef fontDef = qt_FcPatternToQFontDef(pattern, this->request);
9c291e4
+    FcPattern *match = FcFontRenderPrepare(NULL, pattern, fontSet->fonts[at + firstFontIndex - 1]);
d8fc052
+    QFontDef fontDef = qt_FcPatternToQFontDef(match, this->request);
d8fc052
 
d8fc052
     // note: we use -1 for the script to make sure that we keep real
d8fc052
     // FT engines separate from Multi engines in the font cache
d8fc052
     QFontCache::Key key(fontDef, -1, screen);
d8fc052
     QFontEngine *fontEngine = QFontCache::instance()->findEngine(key);
d8fc052
     if (!fontEngine) {
d8fc052
-        FcConfigSubstitute(0, pattern, FcMatchPattern);
d8fc052
-        FcDefaultSubstitute(pattern);
d8fc052
-        fontEngine = engineForPattern(pattern, request, screen);
d8fc052
+        fontEngine = engineForPattern(match, request, screen);
d8fc052
         QFontCache::instance()->insertEngine(key, fontEngine);
d8fc052
     }
d8fc052
-    FcPatternDestroy(pattern);
3e7013f
+    FcPatternDestroy(match);
d8fc052
     fontEngine->ref.ref();
d8fc052
     engines[at] = fontEngine;
d8fc052
 }
3e7013f
@@ -1123,17 +1114,14 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
3e7013f
     }
3e7013f
 #endif
3e7013f
 
3e7013f
-    if (!init(face_id, antialias, defaultFormat)) {
3e7013f
-        FcPatternDestroy(pattern);
3e7013f
+    if (!init(face_id, antialias, defaultFormat))
3e7013f
         return;
3e7013f
-    }
3e7013f
 
3e7013f
     if (!freetype->charset) {
3e7013f
         FcCharSet *cs;
3e7013f
         FcPatternGetCharSet (pattern, FC_CHARSET, 0, &cs);
3e7013f
         freetype->charset = FcCharSetCopy(cs);
3e7013f
     }
3e7013f
-    FcPatternDestroy(pattern);
3e7013f
 }
3e7013f
 
3e7013f
 QFontEngineX11FT::~QFontEngineX11FT()
9c291e4
-- 
9c291e4
1.7.4.1