Fix application font removal when using FontConfig
This patch fixes an issue when a font that was added with QFontDatabase::addApplicationFont can not be removed any more. The reason for that is that QFontconfigDatabase::addApplicationFont adds the font to the FontConfig application set from where it cannot be removed any more and is picked up every time the font database is repopulated (e.g. after a call to QFontDatabase::removeApplicationFont). This also fixes the QFontDatabase autotest which unfortunately does not fail on linux, because it tries to add "FreeMono" (which in most cases is already there as a system font). So this patch removes FreeMono and adds LED_REAL as test font. Change-Id: I2fa5f4df0ad2099ac28673760ea25234c725dfc6 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>bb10
parent
22ec4ed866
commit
a4ff400e25
|
|
@ -331,10 +331,8 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style)
|
|||
return stylehint;
|
||||
}
|
||||
|
||||
void QFontconfigDatabase::populateFontDatabase()
|
||||
static void populateFromPattern(FcPattern *pattern)
|
||||
{
|
||||
FcFontSet *fonts;
|
||||
|
||||
QString familyName;
|
||||
FcChar8 *value = 0;
|
||||
int weight_value;
|
||||
|
|
@ -348,6 +346,110 @@ void QFontconfigDatabase::populateFontDatabase()
|
|||
FcBool scalable;
|
||||
FcBool antialias;
|
||||
|
||||
if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
|
||||
return;
|
||||
|
||||
familyName = QString::fromUtf8((const char *)value);
|
||||
|
||||
slant_value = FC_SLANT_ROMAN;
|
||||
weight_value = FC_WEIGHT_REGULAR;
|
||||
spacing_value = FC_PROPORTIONAL;
|
||||
file_value = 0;
|
||||
indexValue = 0;
|
||||
scalable = FcTrue;
|
||||
|
||||
|
||||
if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
|
||||
slant_value = FC_SLANT_ROMAN;
|
||||
if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
|
||||
weight_value = FC_WEIGHT_REGULAR;
|
||||
if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
|
||||
width_value = FC_WIDTH_NORMAL;
|
||||
if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
|
||||
spacing_value = FC_PROPORTIONAL;
|
||||
if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
|
||||
file_value = 0;
|
||||
if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
|
||||
indexValue = 0;
|
||||
if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
|
||||
scalable = FcTrue;
|
||||
if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
|
||||
foundry_value = 0;
|
||||
if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
|
||||
style_value = 0;
|
||||
if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
|
||||
antialias = true;
|
||||
|
||||
QSupportedWritingSystems writingSystems;
|
||||
FcLangSet *langset = 0;
|
||||
FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
|
||||
if (res == FcResultMatch) {
|
||||
bool hasLang = false;
|
||||
for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
|
||||
const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
|
||||
if (lang) {
|
||||
FcLangResult langRes = FcLangSetHasLang(langset, lang);
|
||||
if (langRes != FcLangDifferentLang) {
|
||||
writingSystems.setSupported(QFontDatabase::WritingSystem(j));
|
||||
hasLang = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasLang)
|
||||
// none of our known languages, add it to the other set
|
||||
writingSystems.setSupported(QFontDatabase::Other);
|
||||
} else {
|
||||
// we set Other to supported for symbol fonts. It makes no
|
||||
// sense to merge these with other ones, as they are
|
||||
// special in a way.
|
||||
writingSystems.setSupported(QFontDatabase::Other);
|
||||
}
|
||||
|
||||
#if FC_VERSION >= 20297
|
||||
for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
|
||||
if (writingSystems.supported(QFontDatabase::WritingSystem(j))
|
||||
&& requiresOpenType(j) && openType[j]) {
|
||||
FcChar8 *cap;
|
||||
res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap);
|
||||
if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
|
||||
writingSystems.setSupported(QFontDatabase::WritingSystem(j),false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FontFile *fontFile = new FontFile;
|
||||
fontFile->fileName = QLatin1String((const char *)file_value);
|
||||
fontFile->indexValue = indexValue;
|
||||
|
||||
QFont::Style style = (slant_value == FC_SLANT_ITALIC)
|
||||
? QFont::StyleItalic
|
||||
: ((slant_value == FC_SLANT_OBLIQUE)
|
||||
? QFont::StyleOblique
|
||||
: QFont::StyleNormal);
|
||||
// Note: weight should really be an int but registerFont incorrectly uses an enum
|
||||
QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
|
||||
|
||||
double pixel_size = 0;
|
||||
if (!scalable)
|
||||
FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
|
||||
|
||||
bool fixedPitch = spacing_value >= FC_MONO;
|
||||
// Note: stretch should really be an int but registerFont incorrectly uses an enum
|
||||
QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
|
||||
QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
|
||||
QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
|
||||
// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
|
||||
|
||||
for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k)
|
||||
QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
|
||||
|
||||
}
|
||||
|
||||
void QFontconfigDatabase::populateFontDatabase()
|
||||
{
|
||||
FcInitReinitialize();
|
||||
FcFontSet *fonts;
|
||||
|
||||
{
|
||||
FcObjectSet *os = FcObjectSetCreate();
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
|
|
@ -371,103 +473,8 @@ void QFontconfigDatabase::populateFontDatabase()
|
|||
FcPatternDestroy(pattern);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fonts->nfont; i++) {
|
||||
if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
|
||||
continue;
|
||||
// capitalize(value);
|
||||
familyName = QString::fromUtf8((const char *)value);
|
||||
slant_value = FC_SLANT_ROMAN;
|
||||
weight_value = FC_WEIGHT_REGULAR;
|
||||
spacing_value = FC_PROPORTIONAL;
|
||||
file_value = 0;
|
||||
indexValue = 0;
|
||||
scalable = FcTrue;
|
||||
|
||||
|
||||
if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch)
|
||||
slant_value = FC_SLANT_ROMAN;
|
||||
if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch)
|
||||
weight_value = FC_WEIGHT_REGULAR;
|
||||
if (FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width_value) != FcResultMatch)
|
||||
width_value = FC_WIDTH_NORMAL;
|
||||
if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch)
|
||||
spacing_value = FC_PROPORTIONAL;
|
||||
if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch)
|
||||
file_value = 0;
|
||||
if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch)
|
||||
indexValue = 0;
|
||||
if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch)
|
||||
scalable = FcTrue;
|
||||
if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
|
||||
foundry_value = 0;
|
||||
if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch)
|
||||
style_value = 0;
|
||||
if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch)
|
||||
antialias = true;
|
||||
|
||||
QSupportedWritingSystems writingSystems;
|
||||
FcLangSet *langset = 0;
|
||||
FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset);
|
||||
if (res == FcResultMatch) {
|
||||
bool hasLang = false;
|
||||
for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
|
||||
const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
|
||||
if (lang) {
|
||||
FcLangResult langRes = FcLangSetHasLang(langset, lang);
|
||||
if (langRes != FcLangDifferentLang) {
|
||||
writingSystems.setSupported(QFontDatabase::WritingSystem(j));
|
||||
hasLang = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasLang)
|
||||
// none of our known languages, add it to the other set
|
||||
writingSystems.setSupported(QFontDatabase::Other);
|
||||
} else {
|
||||
// we set Other to supported for symbol fonts. It makes no
|
||||
// sense to merge these with other ones, as they are
|
||||
// special in a way.
|
||||
writingSystems.setSupported(QFontDatabase::Other);
|
||||
}
|
||||
|
||||
#if FC_VERSION >= 20297
|
||||
for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
|
||||
if (writingSystems.supported(QFontDatabase::WritingSystem(j))
|
||||
&& requiresOpenType(j) && openType[j]) {
|
||||
FcChar8 *cap;
|
||||
res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap);
|
||||
if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
|
||||
writingSystems.setSupported(QFontDatabase::WritingSystem(j),false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FontFile *fontFile = new FontFile;
|
||||
fontFile->fileName = QLatin1String((const char *)file_value);
|
||||
fontFile->indexValue = indexValue;
|
||||
|
||||
QFont::Style style = (slant_value == FC_SLANT_ITALIC)
|
||||
? QFont::StyleItalic
|
||||
: ((slant_value == FC_SLANT_OBLIQUE)
|
||||
? QFont::StyleOblique
|
||||
: QFont::StyleNormal);
|
||||
// Note: weight should really be an int but registerFont incorrectly uses an enum
|
||||
QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
|
||||
|
||||
double pixel_size = 0;
|
||||
if (!scalable)
|
||||
FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size);
|
||||
|
||||
bool fixedPitch = spacing_value >= FC_MONO;
|
||||
// Note: stretch should really be an int but registerFont incorrectly uses an enum
|
||||
QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
|
||||
QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
|
||||
QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
|
||||
// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
|
||||
|
||||
for (int k = 1; FcPatternGetString(fonts->fonts[i], FC_FAMILY, k, &value) == FcResultMatch; ++k)
|
||||
QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
|
||||
}
|
||||
for (int i = 0; i < fonts->nfont; i++)
|
||||
populateFromPattern(fonts->fonts[i]);
|
||||
|
||||
FcFontSetDestroy (fonts);
|
||||
|
||||
|
|
@ -515,14 +522,12 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc
|
|||
return 0;
|
||||
QFontDef fontDef = f;
|
||||
|
||||
QFontEngineFT *engine;
|
||||
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
|
||||
QFontEngine::FaceId fid;
|
||||
fid.filename = QFile::encodeName(fontfile->fileName);
|
||||
fid.index = fontfile->indexValue;
|
||||
|
||||
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
|
||||
engine = new QFontEngineFT(fontDef);
|
||||
|
||||
QFontEngineFT::GlyphFormat format;
|
||||
// try and get the pattern
|
||||
|
|
@ -543,7 +548,19 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc
|
|||
|
||||
FcResult result;
|
||||
FcPattern *match = FcFontMatch(0, pattern, &result);
|
||||
|
||||
QFontEngineFT *engine = new QFontEngineFT(fontDef);
|
||||
|
||||
if (match) {
|
||||
//Respect the file and index of the font config match
|
||||
FcChar8 *file_value;
|
||||
int indexValue;
|
||||
|
||||
if (FcPatternGetString(match, FC_FILE, 0, &file_value) == FcResultMatch)
|
||||
fid.filename = (const char *)file_value;
|
||||
if (FcPatternGetInteger(match, FC_INDEX, 0, &indexValue) == FcResultMatch)
|
||||
fid.index = indexValue;
|
||||
|
||||
QFontEngineFT::HintStyle default_hint_style;
|
||||
if (f.hintingPreference != QFont::PreferDefaultHinting) {
|
||||
switch (f.hintingPreference) {
|
||||
|
|
@ -620,12 +637,14 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc
|
|||
format = subpixelType == QFontEngineFT::Subpixel_None
|
||||
? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32;
|
||||
engine->subpixelType = subpixelType;
|
||||
} else
|
||||
} else {
|
||||
format = QFontEngineFT::Format_Mono;
|
||||
}
|
||||
|
||||
FcPatternDestroy(match);
|
||||
} else
|
||||
} else {
|
||||
format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;
|
||||
}
|
||||
|
||||
FcPatternDestroy(pattern);
|
||||
|
||||
|
|
@ -748,6 +767,7 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id,
|
|||
QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
|
||||
{
|
||||
QStringList families;
|
||||
|
||||
FcFontSet *set = FcConfigGetFonts(0, FcSetApplication);
|
||||
if (!set) {
|
||||
FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent");
|
||||
|
|
@ -760,28 +780,24 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData,
|
|||
FcBlanks *blanks = FcConfigGetBlanks(0);
|
||||
int count = 0;
|
||||
|
||||
FcPattern *pattern = 0;
|
||||
FcPattern *pattern;
|
||||
do {
|
||||
pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(),
|
||||
fontData, id, blanks, &count);
|
||||
if (!pattern)
|
||||
return families;
|
||||
|
||||
FcPatternDel(pattern, FC_FILE);
|
||||
QByteArray cs = fileName.toUtf8();
|
||||
FcPatternAddString(pattern, FC_FILE, (const FcChar8 *) cs.constData());
|
||||
|
||||
FcChar8 *fam = 0;
|
||||
if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
|
||||
QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
|
||||
families << family;
|
||||
}
|
||||
populateFromPattern(pattern);
|
||||
|
||||
if (!FcFontSetAdd(set, pattern))
|
||||
return families;
|
||||
FcFontSetAdd(set, pattern);
|
||||
|
||||
++id;
|
||||
} while (pattern && id < count);
|
||||
} while (id < count);
|
||||
|
||||
return families;
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,34 @@
|
|||
Font: LED Real (led_real.ttf)
|
||||
Created By: Matthew Welch
|
||||
E-Mail: daffy-duck@worldnet.att.net
|
||||
Web Address: http://home.att.net/~daffy-duck
|
||||
(PGP public key available here)
|
||||
|
||||
LED Real, like all of my fonts, is free. You can use it for most
|
||||
personal or business uses you'd like, and I ask for no money. I
|
||||
would, however, like to hear from you. If you use my fonts for
|
||||
something please send me a postcard or e-mail letting me know how
|
||||
you used it. Send me a copy if you can or let me know where I can
|
||||
find your work.
|
||||
|
||||
You may use this font for graphical or printed work, but you may not
|
||||
sell it or include it in a collection of fonts (on CD or otherwise)
|
||||
being sold. You can redistribute this font as long as you charge
|
||||
nothing to receive it. If you redistribute it include this text file
|
||||
with it as is (without modifications).
|
||||
|
||||
If you use this font for commercial purposes please credit me in
|
||||
at least some little way.
|
||||
|
||||
About the font:
|
||||
|
||||
Unlike most LED/LCD style fonts mine could be recreated with an
|
||||
actual LED. I created this font working from memories of the good
|
||||
old Speak and Spell display. Since I don't have an actual Speak
|
||||
and Spell to work from I had to just do as well as I could in its
|
||||
spirit. Be warned that some characters look just like others. The
|
||||
( and the <, for instance. Also C and [. Most of these will be
|
||||
pretty clear in context. To see all the sections of the LED "lit
|
||||
up" at once use character 127 (hold down alt and type 0127 on the
|
||||
numeric keypad). This font is, of course, monospaced.
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ private:
|
|||
};
|
||||
|
||||
tst_QFontDatabase::tst_QFontDatabase()
|
||||
: m_testFont(QFINDTESTDATA("FreeMono.ttf"))
|
||||
: m_testFont(QFINDTESTDATA("LED_REAL.TTF"))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue