summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
diff options
context:
space:
mode:
authorRohan McGovern <rohan.mcgovern@nokia.com>2012-02-29 09:18:59 +1000
committerRohan McGovern <rohan.mcgovern@nokia.com>2012-02-29 09:23:14 +1000
commit98dd1781d9256f68025d2a2db408f4f5947f3214 (patch)
treedbe1424abd90014edb5546c920ca585ed62b46e3 /src/plugins/platforms/windows/qwindowsfontdatabase.cpp
parent6c1bdc1854a7700c2b3a345b95f6a2fdca84037d (diff)
parentfa1b9070af66edb81b2a3735c1951f78b22bd666 (diff)
Merge master -> api_changes
Includes fixes for tst_qfiledialog2, tst_qtextedit autotests on mac. Change-Id: I49cac26894d31291a8339ccc1eb80b6a940f0827
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsfontdatabase.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp179
1 files changed, 177 insertions, 2 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 1df985c8a7..fba7794a12 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -329,8 +329,183 @@ static inline QFontDatabase::WritingSystem writingSystemFromScript(const QString
return QFontDatabase::Any;
}
-extern bool localizedName(const QString &name);
-extern QString getEnglishName(const QString &familyName);
+#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;
+}
Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);