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