Use english name to match font in windows platform
In windows platform, simplified chinese envrionment, the default font family name is "SimSun" which is not in the font list generated by EnumFontFamiliesEx(), this will cause chinese font can't be displayed. This patch will generate font's english name during font enumeration in windows platform, and take font's english name into consideration in font matching. The english name generation code is taken from Qt4.8 Change-Id: Ie939ec0c8c08c628a835c7a53fb22d0545626d9c Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
parent
dfddabe115
commit
0347ac1982
@ -349,6 +349,7 @@ struct QtFontFamily
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
|
QStringList aliases;
|
||||||
int count;
|
int count;
|
||||||
QtFontFoundry **foundries;
|
QtFontFoundry **foundries;
|
||||||
|
|
||||||
@ -996,6 +997,25 @@ unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
|
|||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
|
||||||
|
{
|
||||||
|
if (familyName.isEmpty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (f->name.compare(familyName, Qt::CaseInsensitive) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QStringList::const_iterator it = f->aliases.constBegin();
|
||||||
|
while (it != f->aliases.constEnd()) {
|
||||||
|
if ((*it).compare(familyName, Qt::CaseInsensitive) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
|
|
||||||
@ -1045,9 +1065,7 @@ static void match(int script, const QFontDef &request,
|
|||||||
test.family = db->families[x];
|
test.family = db->families[x];
|
||||||
test.familyIndex = x;
|
test.familyIndex = x;
|
||||||
|
|
||||||
if (!family_name.isEmpty()
|
if (!matchFamilyName(family_name, test.family))
|
||||||
&& test.family->name.compare(family_name, Qt::CaseInsensitive) != 0
|
|
||||||
)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (family_name.isEmpty())
|
if (family_name.isEmpty())
|
||||||
|
@ -87,6 +87,22 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &fou
|
|||||||
size->handle = handle;
|
size->handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
|
||||||
|
{
|
||||||
|
if (alias.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QFontDatabasePrivate *d = privateDb();
|
||||||
|
QtFontFamily *f = d->family(familyName, false);
|
||||||
|
if (!f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (f->aliases.contains(alias, Qt::CaseInsensitive))
|
||||||
|
return;
|
||||||
|
|
||||||
|
f->aliases.push_back(alias);
|
||||||
|
}
|
||||||
|
|
||||||
static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script)
|
static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script)
|
||||||
{
|
{
|
||||||
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
|
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
|
||||||
|
@ -329,6 +329,11 @@ static inline QFontDatabase::WritingSystem writingSystemFromScript(const QString
|
|||||||
return QFontDatabase::Any;
|
return QFontDatabase::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern bool localizedName(const QString &name);
|
||||||
|
extern QString getEnglishName(const QString &familyName);
|
||||||
|
|
||||||
|
Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
|
||||||
|
|
||||||
static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
||||||
const TEXTMETRIC *textmetric,
|
const TEXTMETRIC *textmetric,
|
||||||
const FONTSIGNATURE *signature,
|
const FONTSIGNATURE *signature,
|
||||||
@ -365,10 +370,10 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
|||||||
<< " stretch=" << stretch;
|
<< " stretch=" << stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fixme: omitted for the moment
|
QString englishName;
|
||||||
if(ttf && localizedName(familyName) && family->english_name.isEmpty())
|
if (ttf && localizedName(familyName))
|
||||||
family->english_name = getEnglishName(familyName);
|
englishName = getEnglishName(familyName);
|
||||||
*/
|
|
||||||
QSupportedWritingSystems writingSystems;
|
QSupportedWritingSystems writingSystems;
|
||||||
if (type & TRUETYPE_FONTTYPE) {
|
if (type & TRUETYPE_FONTTYPE) {
|
||||||
quint32 unicodeRange[4] = {
|
quint32 unicodeRange[4] = {
|
||||||
@ -405,6 +410,10 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
|||||||
if (weight <= QFont::DemiBold && style != QFont::StyleItalic)
|
if (weight <= QFont::DemiBold && style != QFont::StyleItalic)
|
||||||
QPlatformFontDatabase::registerFont(familyName, foundryName, QFont::Bold,
|
QPlatformFontDatabase::registerFont(familyName, foundryName, QFont::Bold,
|
||||||
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
|
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
|
||||||
|
|
||||||
|
if (!englishName.isEmpty())
|
||||||
|
qt_registerAliasToFontFamily(familyName, englishName);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,184 @@ static inline QFont::Weight weightFromInteger(long weight)
|
|||||||
return QFont::Black;
|
return QFont::Black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAKE_TAG
|
||||||
|
#undef MAKE_TAG
|
||||||
|
#endif
|
||||||
|
// GetFontData expects the tags in little endian ;(
|
||||||
|
#define MAKE_TAG(ch1, ch2, ch3, ch4) (\
|
||||||
|
(((quint32)(ch4)) << 24) | \
|
||||||
|
(((quint32)(ch3)) << 16) | \
|
||||||
|
(((quint32)(ch2)) << 8) | \
|
||||||
|
((quint32)(ch1)) \
|
||||||
|
)
|
||||||
|
|
||||||
|
bool localizedName(const QString &name)
|
||||||
|
{
|
||||||
|
const QChar *c = name.unicode();
|
||||||
|
for (int i = 0; i < name.length(); ++i) {
|
||||||
|
if (c[i].unicode() >= 0x100)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline quint16 getUShort(const unsigned char *p)
|
||||||
|
{
|
||||||
|
quint16 val;
|
||||||
|
val = *p++ << 8;
|
||||||
|
val |= *p;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString getEnglishName(const uchar *table, quint32 bytes)
|
||||||
|
{
|
||||||
|
QString i18n_name;
|
||||||
|
enum {
|
||||||
|
NameRecordSize = 12,
|
||||||
|
FamilyId = 1,
|
||||||
|
MS_LangIdEnglish = 0x009
|
||||||
|
};
|
||||||
|
|
||||||
|
// get the name table
|
||||||
|
quint16 count;
|
||||||
|
quint16 string_offset;
|
||||||
|
const unsigned char *names;
|
||||||
|
|
||||||
|
int microsoft_id = -1;
|
||||||
|
int apple_id = -1;
|
||||||
|
int unicode_id = -1;
|
||||||
|
|
||||||
|
if (getUShort(table) != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
count = getUShort(table+2);
|
||||||
|
string_offset = getUShort(table+4);
|
||||||
|
names = table + 6;
|
||||||
|
|
||||||
|
if (string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
// search for the correct name entry
|
||||||
|
|
||||||
|
quint16 platform_id = getUShort(names + i*NameRecordSize);
|
||||||
|
quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize);
|
||||||
|
quint16 language_id = getUShort(names + 4 + i*NameRecordSize);
|
||||||
|
quint16 name_id = getUShort(names + 6 + i*NameRecordSize);
|
||||||
|
|
||||||
|
if (name_id != FamilyId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PlatformId_Unicode = 0,
|
||||||
|
PlatformId_Apple = 1,
|
||||||
|
PlatformId_Microsoft = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
quint16 length = getUShort(names + 8 + i*NameRecordSize);
|
||||||
|
quint16 offset = getUShort(names + 10 + i*NameRecordSize);
|
||||||
|
if (DWORD(string_offset + offset + length) >= bytes)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((platform_id == PlatformId_Microsoft
|
||||||
|
&& (encoding_id == 0 || encoding_id == 1))
|
||||||
|
&& (language_id & 0x3ff) == MS_LangIdEnglish
|
||||||
|
&& microsoft_id == -1)
|
||||||
|
microsoft_id = i;
|
||||||
|
// not sure if encoding id 4 for Unicode is utf16 or ucs4...
|
||||||
|
else if (platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1)
|
||||||
|
unicode_id = i;
|
||||||
|
else if (platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0)
|
||||||
|
apple_id = i;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool unicode = false;
|
||||||
|
int id = -1;
|
||||||
|
if (microsoft_id != -1) {
|
||||||
|
id = microsoft_id;
|
||||||
|
unicode = true;
|
||||||
|
} else if (apple_id != -1) {
|
||||||
|
id = apple_id;
|
||||||
|
unicode = false;
|
||||||
|
} else if (unicode_id != -1) {
|
||||||
|
id = unicode_id;
|
||||||
|
unicode = true;
|
||||||
|
}
|
||||||
|
if (id != -1) {
|
||||||
|
quint16 length = getUShort(names + 8 + id*NameRecordSize);
|
||||||
|
quint16 offset = getUShort(names + 10 + id*NameRecordSize);
|
||||||
|
if (unicode) {
|
||||||
|
// utf16
|
||||||
|
|
||||||
|
length /= 2;
|
||||||
|
i18n_name.resize(length);
|
||||||
|
QChar *uc = (QChar *) i18n_name.unicode();
|
||||||
|
const unsigned char *string = table + string_offset + offset;
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
uc[i] = getUShort(string + 2*i);
|
||||||
|
} else {
|
||||||
|
// Apple Roman
|
||||||
|
|
||||||
|
i18n_name.resize(length);
|
||||||
|
QChar *uc = (QChar *) i18n_name.unicode();
|
||||||
|
const unsigned char *string = table + string_offset + offset;
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
uc[i] = QLatin1Char(string[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
//qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
|
||||||
|
return i18n_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getEnglishName(const QString &familyName)
|
||||||
|
{
|
||||||
|
QString i18n_name;
|
||||||
|
|
||||||
|
HDC hdc = GetDC( 0 );
|
||||||
|
LOGFONT lf;
|
||||||
|
memset(&lf, 0, sizeof(LOGFONT));
|
||||||
|
memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t));
|
||||||
|
lf.lfCharSet = DEFAULT_CHARSET;
|
||||||
|
HFONT hfont = CreateFontIndirect(&lf);
|
||||||
|
|
||||||
|
if (!hfont) {
|
||||||
|
ReleaseDC(0, hdc);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
HGDIOBJ oldobj = SelectObject( hdc, hfont );
|
||||||
|
|
||||||
|
const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' );
|
||||||
|
|
||||||
|
// get the name table
|
||||||
|
unsigned char *table = 0;
|
||||||
|
|
||||||
|
DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 );
|
||||||
|
if ( bytes == GDI_ERROR ) {
|
||||||
|
// ### Unused variable
|
||||||
|
// int err = GetLastError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
table = new unsigned char[bytes];
|
||||||
|
GetFontData(hdc, name_tag, 0, table, bytes);
|
||||||
|
if ( bytes == GDI_ERROR )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
i18n_name = getEnglishName(table, bytes);
|
||||||
|
error:
|
||||||
|
delete [] table;
|
||||||
|
SelectObject( hdc, oldobj );
|
||||||
|
DeleteObject( hfont );
|
||||||
|
ReleaseDC( 0, hdc );
|
||||||
|
|
||||||
|
//qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
|
||||||
|
return i18n_name;
|
||||||
|
}
|
||||||
|
|
||||||
static FontFile * createFontFile(const QString &fileName, int index)
|
static FontFile * createFontFile(const QString &fileName, int index)
|
||||||
{
|
{
|
||||||
FontFile *fontFile = new FontFile;
|
FontFile *fontFile = new FontFile;
|
||||||
@ -108,6 +286,8 @@ static FontFile * createFontFile(const QString &fileName, int index)
|
|||||||
return fontFile;
|
return fontFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
|
||||||
|
|
||||||
static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
||||||
const TEXTMETRIC *textmetric,
|
const TEXTMETRIC *textmetric,
|
||||||
const FONTSIGNATURE *signature,
|
const FONTSIGNATURE *signature,
|
||||||
@ -151,10 +331,10 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
|||||||
<< " stretch=" << stretch;
|
<< " stretch=" << stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fixme: omitted for the moment
|
QString englishName;
|
||||||
if(ttf && localizedName(faceName) && family->english_name.isEmpty())
|
if (ttf && localizedName(faceName))
|
||||||
family->english_name = getEnglishName(faceName);
|
englishName = getEnglishName(faceName);
|
||||||
*/
|
|
||||||
QSupportedWritingSystems writingSystems;
|
QSupportedWritingSystems writingSystems;
|
||||||
if (type & TRUETYPE_FONTTYPE) {
|
if (type & TRUETYPE_FONTTYPE) {
|
||||||
quint32 unicodeRange[4] = {
|
quint32 unicodeRange[4] = {
|
||||||
@ -204,7 +384,7 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
|||||||
const FontKey &fontKey = allFonts.at(k);
|
const FontKey &fontKey = allFonts.at(k);
|
||||||
for (int i = 0; i < fontKey.second.length(); ++i) {
|
for (int i = 0; i < fontKey.second.length(); ++i) {
|
||||||
const QString &font = fontKey.second.at(i);
|
const QString &font = fontKey.second.at(i);
|
||||||
if (font == faceName || (faceName != fullName && fullName == font)) {
|
if (font == faceName || fullName == font || englishName == font) {
|
||||||
value = fontRegistry.value(fontKey.first).toString();
|
value = fontRegistry.value(fontKey.first).toString();
|
||||||
index = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
@ -236,6 +416,9 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
|
|||||||
QPlatformFontDatabase::registerFont(faceName, foundryName, QFont::Bold, QFont::StyleItalic, stretch,
|
QPlatformFontDatabase::registerFont(faceName, foundryName, QFont::Bold, QFont::StyleItalic, stretch,
|
||||||
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
||||||
|
|
||||||
|
if (!englishName.isEmpty())
|
||||||
|
qt_registerAliasToFontFamily(faceName, englishName);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user