use only special character to find font for scripts

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-01-20 15:58:42 +02:00
parent 91cea5ea78
commit a07858920e
3 changed files with 49 additions and 231 deletions

View file

@ -74,16 +74,9 @@ bool QtFontFamily::operator<(const QtFontFamily &other) const
return (preference >= other.preference); return (preference >= other.preference);
} }
class QFontDatabasePrivate typedef QVector<QtFontFamily> QtFontFamilyList;
{
public:
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
QString systemLang;
#endif
QVector<QtFontFamily> families;
};
Q_GLOBAL_STATIC(QFontDatabasePrivate, qGlobalFontDatabase) Q_GLOBAL_STATIC(QtFontFamilyList, qGlobalFontDatabase)
Q_GLOBAL_STATIC(QMutex, qGlobalFontDatabaseMutex) Q_GLOBAL_STATIC(QMutex, qGlobalFontDatabaseMutex)
/*! /*!
@ -224,7 +217,9 @@ static inline QString styleStringHelper(const QString &family, int weight, QFont
} }
if (result.isEmpty()) { if (result.isEmpty()) {
foreach (const QtFontFamily &fontfamily, qGlobalFontDatabase()->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(family, Qt::CaseInsensitive) != 0) { if (fontfamily.family.compare(family, Qt::CaseInsensitive) != 0) {
continue; continue;
} }
@ -320,8 +315,8 @@ QFontDatabase::QFontDatabase()
{ {
QMutexLocker locker(qGlobalFontDatabaseMutex()); QMutexLocker locker(qGlobalFontDatabaseMutex());
d = qGlobalFontDatabase(); QtFontFamilyList* db = qGlobalFontDatabase();
if (!d || d->families.size() > 0) if (!db || db->size() > 0)
return; return;
#ifndef QT_NO_FONTCONFIG #ifndef QT_NO_FONTCONFIG
@ -341,24 +336,14 @@ QFontDatabase::QFontDatabase()
"QFontDatabase", "New scripts have been added."); "QFontDatabase", "New scripts have been added.");
FcFontSet *fonts; FcFontSet *fonts;
FcObjectSet *os = FcObjectSetCreate();
FcPattern *pattern = FcPatternCreate(); FcPattern *pattern = FcPatternCreate();
FcDefaultSubstitute(pattern); for (qint16 i = 0; i < PatternPropertiesTblSize; i++) {
FcChar8 *lang = nullptr; FcObjectSetAdd(os, PatternPropertiesTbl[i]);
if (FcPatternGetString(pattern, FC_LANG, 0, &lang) == FcResultMatch)
d->systemLang = QString::fromUtf8((const char *) lang);
FcPatternDestroy(pattern);
{
FcObjectSet *os = FcObjectSetCreate();
FcPattern *pattern = FcPatternCreate();
for (qint16 i = 0; i < PatternPropertiesTblSize; i++) {
FcObjectSetAdd(os, PatternPropertiesTbl[i]);
}
fonts = FcFontList(0, pattern, os);
FcObjectSetDestroy(os);
FcPatternDestroy(pattern);
} }
fonts = FcFontList(0, pattern, os);
FcObjectSetDestroy(os);
FcPatternDestroy(pattern);
for (int i = 0; i < fonts->nfont; i++) { for (int i = 0; i < fonts->nfont; i++) {
FcChar8 *family_value = nullptr; FcChar8 *family_value = nullptr;
@ -411,12 +396,12 @@ QFontDatabase::QFontDatabase()
fontfamily.preference += 800; fontfamily.preference += 800;
} }
d->families.append(fontfamily); db->append(fontfamily);
} }
FcFontSetDestroy(fonts); FcFontSetDestroy(fonts);
qStableSort(d->families); qStableSort(db->begin(), db->end());
#ifdef QFONTDATABASE_DEBUG #ifdef QFONTDATABASE_DEBUG
FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(elapsedtimer.elapsed())); FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(elapsedtimer.elapsed()));
@ -438,7 +423,9 @@ QStringList QFontDatabase::families() const
{ {
QStringList result; QStringList result;
QMap<QString,QStringList> familieswithfoundry; QMap<QString,QStringList> familieswithfoundry;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
familieswithfoundry[fontfamily.family].append(fontfamily.foundry); familieswithfoundry[fontfamily.family].append(fontfamily.foundry);
} }
foreach (const QString &family, familieswithfoundry.keys()) { foreach (const QString &family, familieswithfoundry.keys()) {
@ -473,7 +460,9 @@ QStringList QFontDatabase::styles(const QString &family) const
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
QStringList result; QStringList result;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)) { || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)) {
continue; continue;
@ -495,7 +484,9 @@ bool QFontDatabase::isFixedPitch(const QString &family, const QString &style) co
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
bool result = false; bool result = false;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| (!style.isEmpty() && !isStyleMatch(fontfamily.style, style))) { || (!style.isEmpty() && !isStyleMatch(fontfamily.style, style))) {
@ -521,7 +512,9 @@ bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &sty
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
bool result = false; bool result = false;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| (!style.isEmpty() && !isStyleMatch(fontfamily.style, style))) { || (!style.isEmpty() && !isStyleMatch(fontfamily.style, style))) {
@ -558,7 +551,9 @@ QList<int> QFontDatabase::pointSizes(const QString &family, const QString &style
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
QList<int> result; QList<int> result;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| !isStyleMatch(fontfamily.style, style)) { || !isStyleMatch(fontfamily.style, style)) {
@ -584,7 +579,9 @@ QFont QFontDatabase::font(const QString &family, const QString &style,
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
QFont result = QApplication::font(); QFont result = QApplication::font();
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| !isStyleMatch(fontfamily.style, style)) { || !isStyleMatch(fontfamily.style, style)) {
@ -615,7 +612,9 @@ QList<int> QFontDatabase::smoothSizes(const QString &family, const QString &styl
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
QList<int> result; QList<int> result;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| !isStyleMatch(fontfamily.style, style)) { || !isStyleMatch(fontfamily.style, style)) {
@ -671,7 +670,9 @@ bool QFontDatabase::italic(const QString &family, const QString &style) const
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
bool result = false; bool result = false;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| !isStyleMatch(fontfamily.style, style)) { || !isStyleMatch(fontfamily.style, style)) {
@ -696,7 +697,9 @@ bool QFontDatabase::bold(const QString &family, const QString &style) const
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
bool result = false; bool result = false;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| !isStyleMatch(fontfamily.style, style)) { || !isStyleMatch(fontfamily.style, style)) {
@ -722,7 +725,9 @@ int QFontDatabase::weight(const QString &family, const QString &style) const
parseFontName(family, parsedfoundry, parsedfamily); parseFontName(family, parsedfoundry, parsedfamily);
int result = -1; int result = -1;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(parsedfamily, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0) || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)
|| !isStyleMatch(fontfamily.style, style)) { || !isStyleMatch(fontfamily.style, style)) {
@ -747,7 +752,9 @@ bool QFontDatabase::hasFamily(const QString &family) const
const QString familyalias = resolveFontFamilyAlias(parsedfamily); const QString familyalias = resolveFontFamilyAlias(parsedfamily);
bool result = false; bool result = false;
foreach (const QtFontFamily &fontfamily, d->families) { const QtFontFamilyList* db = qGlobalFontDatabase();
for (int i = 0; i < db->size(); i++) {
const QtFontFamily &fontfamily = db->at(i);
if (fontfamily.family.compare(familyalias, Qt::CaseInsensitive) != 0 if (fontfamily.family.compare(familyalias, Qt::CaseInsensitive) != 0
|| (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)) { || (!parsedfoundry.isEmpty() && fontfamily.foundry.compare(parsedfoundry, Qt::CaseInsensitive) != 0)) {
continue; continue;
@ -785,4 +792,3 @@ bool QFontDatabase::supportsThreadedFontRendering()
QT_END_NAMESPACE QT_END_NAMESPACE
#include "moc_qfontdatabase.h" #include "moc_qfontdatabase.h"

View file

@ -34,8 +34,6 @@ class QStringList;
template <class T> class QList; template <class T> class QList;
class QFontEngine; class QFontEngine;
class QFontDatabasePrivate;
class Q_GUI_EXPORT QFontDatabase class Q_GUI_EXPORT QFontDatabase
{ {
Q_GADGET Q_GADGET
@ -74,8 +72,6 @@ private:
friend class QFontPrivate; friend class QFontPrivate;
friend class QFontDialog; friend class QFontDialog;
friend class QFontDialogPrivate; friend class QFontDialogPrivate;
QFontDatabasePrivate *d;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View file

@ -147,172 +147,6 @@ QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request)
return fontDef; return fontDef;
} }
// values are from likelySubtags.xml distributed with Unicode CLDR data
static const char *specialLanguagesTbl[] = {
"en", // Common
"ff-gn", // Adlam
"aho-in", // Ahom
"hlu-tr", // AnatolianHieroglyphs
"ar", // Arabic
"hy", // Armenian
"ae-ir", // Avestan
"ban-id", // Balinese
"bax-cm", // Bamum
"bsq-lr", // BassaVah
"bbc-id", // Batak
"bn", // Bengali
"sa-in", // Bhaiksuki
"zh-tw", // Bopomofo
"pka-in", // Brahmi
"fr-fr", // Braille
"bug-id", // Buginese
"bku-ph", // Buhid
"en-ca", // CanadianAboriginal
"xcr-tr", // Carian
"sq", // CaucasianAlbanian
"ccp-bd", // Chakma
"cjm-vn", // Cham
"chr-us", // Cherokee
"xco-uz", // Chorasmian
"cop-eg", // Coptic
"akk-iq", // Cuneiform
"grc-cy", // Cypriot
0, // CyproMinoan
"ru", // Cyrillic
0, // Deseret
"hi", // Devanagari
"dv-mv", // DivesAkuru
"doi-in", // Dogra
"fr-fr", // Duployan
"ar-eg", // EgyptianHieroglyphs
"sq-al", // Elbasan
"arc-ir", // Elymaic
0, // Ethiopic
"ka", // Georgian
"cu-bg", // Glagolitic
"got-ua", // Gothic
"sa-in", // Grantha
"el", // Greek
"gu", // Gujarati
"wsg-in", // GunjalaGondi
"pa", // Gurmukhi
"zh-tw", // Han
"ko", // Hangul
"rhg-mm", // HanifiRohingya
"hnn-ph", // Hanunoo
"mis-iq", // Hatran
"he", // Hebrew
"ja-jp", // Hiragana
"arc-ir", // ImperialAramaic
0, // Inherited
"pal-ir", // InscriptionalPahlavi
"xpr-ir", // InscriptionalParthian
"jv-id", // Javanese
"bho-in", // Kaithi
"kn", // Kannada
"ja-jp", // Katakana
"eky-mm", // KayahLi
"pra-pk", // Kharoshthi
"zkt-cn", // KhitanSmallScript
"km", // Khmer
"sd-in", // Khojki
"sd-in", // Khudawadi
"lo", // Lao
"la", // Latin
"lep-in", // Lepcha
"lif", // Limbu
"lab-gr", // LinearA
"lab-gr", // LinearB
"lis-cn", // Lisu
"xlc-tr", // Lycian
"xld-tr", // Lydian
"hi-in", // Mahajani
"mak-id", // Makasar
"ml", // Malayalam
"myz-ir", // Mandaic
"xmn-cn", // Manichaean
"bo-cn", // Marchen
"esg-in", // MasaramGondi
"mis-ng", // Medefaidrin
"mni-in", // MeeteiMayek
0, // MendeKikakui
"xmr-sd", // MeroiticCursive
"xmr-sd", // MeroiticHieroglyphs
"hmd-cn", // Miao
"mr-in", // Modi
"mn", // Mongolian
"mro-bd", // Mro
"skr-pk", // Multani
"my", // Myanmar
"arc-jo", // Nabataean
"sa-in", // Nandinagari
"new-np", // Newa
"khb-cn", // NewTaiLue
"nqo-gn", // Nko
"zhx-cn", // Nushu
"mww-us", // NyiakengPuachueHmong
"sga-ie", // Ogham
"sat-in", // OlChiki
"hu-hu", // OldHungarian
"ett-it", // OldItalic
"ar", // OldNorthArabian
"kv-ru", // OldPermic
"peo-ir", // OldPersian
"sog-uz", // OldSogdian
"ar", // OldSouthArabian
"otk-mn", // OldTurkic
"ug-cn", // OldUyghur
"or", // Oriya
"osa-us", // Osage
"so-so", // Osmanya
"hnj-la", // PahawhHmong
"arc-sy", // Palmyrene
"ctd-mm", // PauCinHau
"lzh-cn", // PhagsPa
"phn-lb", // Phoenician
"pal-cn", // PsalterPahlavi
"rej-id", // Rejang
"non-se", // Runic
"smp-il", // Samaritan
"saz-in", // Saurashtra
"sa-in", // Sharada
"en-gb", // Shavian
"sa-in", // Siddham
"ase-us", // SignWriting
"si", // Sinhala
"sog-uz", // Sogdian
"srb-in", // SoraSompeng
"cmg-mn", // Soyombo
"su-id", // Sundanese
"syl-bd", // SylotiNagri
"syr", // Syriac
"tl-ph", // Tagalog
"tbw-ph", // Tagbanwa
"tdd-cn", // TaiLe
0, // TaiTham
"blt-vn", // TaiViet
"doi-in", // Takri
"ta", // Tamil
"ntm-in", // Tangsa
"txg-cn", // Tangut
"te", // Telugu
"div", // Thaana
"th", // Thai
"bo", // Tibetan
0, // Tifinagh
"mai-in", // Tirhuta
"txo-in", // Toto
"uga-sy", // Ugaritic
"vai-lr", // Vai
"sq-al", // Vithkuqi
"npp-in", // Wancho
0, // WarangCiti
"ku-ge", // Yezidi
"yi", // Yi
"cmg-mn", // ZanabazarSquare
};
enum { SpecialLanguageCount = sizeof(specialLanguagesTbl) / sizeof(const char *) };
// values obtained via genutf script // values obtained via genutf script
static const uint specialCharsTbl[] = { static const uint specialCharsTbl[] = {
0x0, // Common 0x0, // Common
@ -504,15 +338,6 @@ static void qt_addPatternProps(FcPattern *pattern, int screen, QUnicodeTables::S
FcPatternDel(pattern, FC_PIXEL_SIZE); FcPatternDel(pattern, FC_PIXEL_SIZE);
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value); FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
if (script != QUnicodeTables::Common && specialLanguagesTbl[script]) {
Q_ASSERT(script < QUnicodeTables::ScriptCount);
FcLangSet *ls = FcLangSetCreate();
FcLangSetAdd(ls, (const FcChar8*)specialLanguagesTbl[script]);
FcPatternDel(pattern, FC_LANG);
FcPatternAddLangSet(pattern, FC_LANG, ls);
FcLangSetDestroy(ls);
}
if (!request.styleName.isEmpty()) { if (!request.styleName.isEmpty()) {
QByteArray cs = request.styleName.toUtf8(); QByteArray cs = request.styleName.toUtf8();
FcPatternAddString(pattern, FC_STYLE, (const FcChar8 *) cs.constData()); FcPatternAddString(pattern, FC_STYLE, (const FcChar8 *) cs.constData());
@ -622,17 +447,8 @@ static QFontEngine *tryPatternLoad(FcPattern *match, int screen,
return nullptr; return nullptr;
if (script != QUnicodeTables::Common) { if (script != QUnicodeTables::Common) {
// skip font if it doesn't support the language we want // need to check the charset, as the langset doesn't work for some scripts
if (specialLanguagesTbl[script]){
FcLangSet *langSet = 0;
if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch)
goto special_char;
if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguagesTbl[script]) != FcLangEqual)
goto special_char;
}
special_char:
if (specialCharsTbl[script]) { if (specialCharsTbl[script]) {
// need to check the charset, as the langset doesn't work for some scripts
FcCharSet *cs; FcCharSet *cs;
if (FcPatternGetCharSet(match, FC_CHARSET, 0, &cs) != FcResultMatch) if (FcPatternGetCharSet(match, FC_CHARSET, 0, &cs) != FcResultMatch)
return nullptr; return nullptr;