summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorjian liang <jianliang79@gmail.com>2012-02-13 21:26:28 +0800
committerQt by Nokia <qt-info@nokia.com>2012-02-16 04:23:20 +0100
commit0347ac1982477923ce93722ddd52bb9cb700961f (patch)
treee92e717472ac55c112356e717ee556ede82db553 /src
parentdfddabe1157bc6d826612b82d5bfb301205e7ad5 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/gui/text/qfontdatabase.cpp24
-rw-r--r--src/gui/text/qfontdatabase_qpa.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp193
4 files changed, 238 insertions, 12 deletions
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index fa9cae4359..77262d66f0 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -349,6 +349,7 @@ struct QtFontFamily
#endif
QString name;
+ QStringList aliases;
int count;
QtFontFoundry **foundries;
@@ -996,6 +997,25 @@ unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
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
@@ -1045,9 +1065,7 @@ static void match(int script, const QFontDef &request,
test.family = db->families[x];
test.familyIndex = x;
- if (!family_name.isEmpty()
- && test.family->name.compare(family_name, Qt::CaseInsensitive) != 0
- )
+ if (!matchFamilyName(family_name, test.family))
continue;
if (family_name.isEmpty())
diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp
index c3d7529c2e..2a9c37fb13 100644
--- a/src/gui/text/qfontdatabase_qpa.cpp
+++ b/src/gui/text/qfontdatabase_qpa.cpp
@@ -87,6 +87,22 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &fou
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)
{
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index fa95f4f529..1df985c8a7 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -329,6 +329,11 @@ static inline QFontDatabase::WritingSystem writingSystemFromScript(const QString
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,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
@@ -365,10 +370,10 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
<< " stretch=" << stretch;
}
-/* Fixme: omitted for the moment
- if(ttf && localizedName(familyName) && family->english_name.isEmpty())
- family->english_name = getEnglishName(familyName);
-*/
+ QString englishName;
+ if (ttf && localizedName(familyName))
+ englishName = getEnglishName(familyName);
+
QSupportedWritingSystems writingSystems;
if (type & TRUETYPE_FONTTYPE) {
quint32 unicodeRange[4] = {
@@ -405,6 +410,10 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
if (weight <= QFont::DemiBold && style != QFont::StyleItalic)
QPlatformFontDatabase::registerFont(familyName, foundryName, QFont::Bold,
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
+
+ if (!englishName.isEmpty())
+ qt_registerAliasToFontFamily(familyName, englishName);
+
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 8455e9e6d0..6b6d1a294a 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -100,6 +100,184 @@ static inline QFont::Weight weightFromInteger(long weight)
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)
{
FontFile *fontFile = new FontFile;
@@ -108,6 +286,8 @@ static FontFile * createFontFile(const QString &fileName, int index)
return fontFile;
}
+Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
+
static bool addFontToDatabase(QString familyName, const QString &scriptName,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
@@ -151,10 +331,10 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
<< " stretch=" << stretch;
}
-/* Fixme: omitted for the moment
- if(ttf && localizedName(faceName) && family->english_name.isEmpty())
- family->english_name = getEnglishName(faceName);
-*/
+ QString englishName;
+ if (ttf && localizedName(faceName))
+ englishName = getEnglishName(faceName);
+
QSupportedWritingSystems writingSystems;
if (type & TRUETYPE_FONTTYPE) {
quint32 unicodeRange[4] = {
@@ -204,7 +384,7 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
const FontKey &fontKey = allFonts.at(k);
for (int i = 0; i < fontKey.second.length(); ++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();
index = i;
break;
@@ -236,6 +416,9 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName,
QPlatformFontDatabase::registerFont(faceName, foundryName, QFont::Bold, QFont::StyleItalic, stretch,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
+ if (!englishName.isEmpty())
+ qt_registerAliasToFontFamily(faceName, englishName);
+
return true;
}