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