summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-06-03 14:29:08 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-08-02 14:33:37 +0000
commit65f5a7558a14841e35ffbd9606ed55608c1e9439 (patch)
treed3a46642a43291ff7db9f817c3293ee20988b8cb /src
parentfcbbd7bc3d1f7ba9dc2dec1dc3222d0b63660ba5 (diff)
Cleanup canonical font name lookup
Changes the lookup of the canonical "english" font name, so that also corresponding style-name and preferred names can be found. This patch does not use that extra information, and should not change any behavior. Change-Id: I40805f81e6b35dcc98f9459c5cf96f13a8d789f2 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp213
1 files changed, 136 insertions, 77 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 0e00ee6910..5e75cbf37e 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -742,50 +742,115 @@ static inline quint16 getUShort(const unsigned char *p)
return val;
}
-static QString getEnglishName(const uchar *table, quint32 bytes)
+namespace {
+
+struct FontNames {
+ QString name; // e.g. "DejaVu Sans Condensed"
+ QString style; // e.g. "Italic"
+ QString preferredName; // e.g. "DejaVu Sans"
+ QString preferredStyle; // e.g. "Condensed Italic"
+};
+
+static QString readName(bool unicode, const uchar *string, int length)
{
- QString i18n_name;
- enum {
- NameRecordSize = 12,
- FamilyId = 1,
- MS_LangIdEnglish = 0x009
- };
+ QString out;
+ if (unicode) {
+ // utf16
+
+ length /= 2;
+ out.resize(length);
+ QChar *uc = out.data();
+ for (int i = 0; i < length; ++i)
+ uc[i] = getUShort(string + 2*i);
+ } else {
+ // Apple Roman
+
+ out.resize(length);
+ QChar *uc = out.data();
+ for (int i = 0; i < length; ++i)
+ uc[i] = QLatin1Char(char(string[i]));
+ }
+ return out;
+}
+
+enum FieldTypeValue {
+ FamilyId = 1,
+ StyleId = 2,
+ PreferredFamilyId = 16,
+ PreferredStyleId = 17,
+};
+
+enum PlatformFieldValue {
+ PlatformId_Unicode = 0,
+ PlatformId_Apple = 1,
+ PlatformId_Microsoft = 3
+};
+
+static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
+{
+ FontNames out;
+ const int NameRecordSize = 12;
+ const int 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 (bytes < 8)
+ return out;
if (getUShort(table) != 0)
- goto error;
+ return out;
count = getUShort(table+2);
string_offset = getUShort(table+4);
names = table + 6;
if (string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
- goto error;
+ return out;
+
+ enum PlatformIdType {
+ NotFound = 0,
+ Unicode = 1,
+ Apple = 2,
+ Microsoft = 3
+ };
+
+ PlatformIdType idStatus[4] = { NotFound, NotFound, NotFound, NotFound };
+ int ids[4] = { -1, -1, -1, -1 };
for (int i = 0; i < count; ++i) {
- // search for the correct name entry
+ // search for the correct name entries
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;
+ PlatformIdType *idType = nullptr;
+ int *id = nullptr;
- enum {
- PlatformId_Unicode = 0,
- PlatformId_Apple = 1,
- PlatformId_Microsoft = 3
- };
+ switch (name_id) {
+ case FamilyId:
+ idType = &idStatus[0];
+ id = &ids[0];
+ break;
+ case StyleId:
+ idType = &idStatus[1];
+ id = &ids[1];
+ break;
+ case PreferredFamilyId:
+ idType = &idStatus[2];
+ id = &ids[2];
+ break;
+ case PreferredStyleId:
+ idType = &idStatus[3];
+ id = &ids[3];
+ break;
+ default:
+ continue;
+ }
quint16 length = getUShort(names + 8 + i*NameRecordSize);
quint16 offset = getUShort(names + 10 + i*NameRecordSize);
@@ -795,63 +860,52 @@ static QString getEnglishName(const uchar *table, quint32 bytes)
if ((platform_id == PlatformId_Microsoft
&& (encoding_id == 0 || encoding_id == 1))
&& (language_id & 0x3ff) == MS_LangIdEnglish
- && microsoft_id == -1)
- microsoft_id = i;
+ && *idType < Microsoft) {
+ *id = i;
+ *idType = Microsoft;
+ }
// 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;
+ else if (platform_id == PlatformId_Unicode && encoding_id < 4 && *idType < Unicode) {
+ *id = i;
+ *idType = Unicode;
}
- 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 = const_cast<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 = const_cast<QChar *>(i18n_name.unicode());
- const unsigned char *string = table + string_offset + offset;
- for (int i = 0; i < length; ++i)
- uc[i] = QLatin1Char(char(string[i]));
- }
+ else if (platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0 && *idType < Apple) {
+ *id = i;
+ *idType = Apple;
}
}
-error:
- //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
- return i18n_name;
+
+ QString strings[4];
+ for (int i = 0; i < 4; ++i) {
+ if (idStatus[0] == NotFound)
+ continue;
+ int id = ids[i];
+ quint16 length = getUShort(names + 8 + id * NameRecordSize);
+ quint16 offset = getUShort(names + 10 + id * NameRecordSize);
+ const unsigned char *string = table + string_offset + offset;
+ strings[i] = readName(idStatus[i] != Apple, string, length);
+ }
+
+ out.name = strings[0];
+ out.style = strings[1];
+ out.preferredName = strings[2];
+ out.preferredStyle = strings[3];
+ return out;
}
+} // namespace
+
QString getEnglishName(const QString &familyName)
{
QString i18n_name;
+ QString faceName = familyName;
+ faceName.truncate(LF_FACESIZE - 1);
HDC hdc = GetDC( 0 );
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
- memcpy(lf.lfFaceName, familyName.utf16(), qMin(familyName.length(), LF_FACESIZE - 1) * sizeof(wchar_t));
+ faceName.toWCharArray(lf.lfFaceName);
+ lf.lfFaceName[faceName.size()] = 0;
lf.lfCharSet = DEFAULT_CHARSET;
HFONT hfont = CreateFontIndirect(&lf);
@@ -879,7 +933,7 @@ QString getEnglishName(const QString &familyName)
if ( bytes == GDI_ERROR )
goto error;
- i18n_name = getEnglishName(table, bytes);
+ i18n_name = getCanonicalFontNames(table, bytes).name;
error:
delete [] table;
SelectObject( hdc, oldobj );
@@ -1337,7 +1391,7 @@ static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag,
}
static void getFamiliesAndSignatures(const QByteArray &fontData,
- QStringList *families,
+ QList<FontNames> *families,
QVector<FONTSIGNATURE> *signatures)
{
const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
@@ -1353,11 +1407,11 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
if (!table)
continue;
- QString name = getEnglishName(table, length);
- if (name.isEmpty())
+ FontNames names = getCanonicalFontNames(table, length);
+ if (names.name.isEmpty())
continue;
- families->append(name);
+ families->append(qMove(names));
if (signatures) {
FONTSIGNATURE signature;
@@ -1384,12 +1438,13 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
WinApplicationFont font;
font.fileName = fileName;
QVector<FONTSIGNATURE> signatures;
- QStringList families;
+ QList<FontNames> families;
+ QStringList familyNames;
if (!fontData.isEmpty()) {
getFamiliesAndSignatures(fontData, &families, &signatures);
if (families.isEmpty())
- return families;
+ return familyNames;
DWORD dummy = 0;
font.handle =
@@ -1400,7 +1455,8 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
// Memory fonts won't show up in enumeration, so do add them the hard way.
for (int j = 0; j < families.count(); ++j) {
- const QString familyName = families.at(j);
+ const QString familyName = families.at(j).name;
+ familyNames << familyName;
HDC hdc = GetDC(0);
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
@@ -1422,13 +1478,13 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
} else {
QFile f(fileName);
if (!f.open(QIODevice::ReadOnly))
- return families;
+ return QStringList();
QByteArray data = f.readAll();
f.close();
getFamiliesAndSignatures(data, &families, 0);
if (families.isEmpty())
- return families;
+ return QStringList();
if (AddFontResourceExW((wchar_t*)fileName.utf16(), FR_PRIVATE, 0) == 0)
return QStringList();
@@ -1436,13 +1492,16 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
font.handle = 0;
// Fonts based on files are added via populate, as they will show up in font enumeration.
- for (int j = 0; j < families.count(); ++j)
- populateFamily(families.at(j), true);
+ for (int j = 0; j < families.count(); ++j) {
+ const QString familyName = families.at(j).name;
+ familyNames << familyName;
+ populateFamily(familyName, true);
+ }
}
m_applicationFonts << font;
- return families;
+ return familyNames;
}
void QWindowsFontDatabase::removeApplicationFonts()