summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsfontdatabase.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp257
1 files changed, 148 insertions, 109 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 314da702eb..9f2d0c8a33 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -43,7 +43,7 @@
#include "qwindowsintegration.h"
#include "qwindowsfontengine.h"
#include "qwindowsfontenginedirectwrite.h"
-#include "qtwindows_additional.h"
+#include <QtCore/qt_windows.h>
#include <QtGui/QFont>
#include <QtGui/QGuiApplication>
@@ -58,10 +58,6 @@
#include <wchar.h>
-#ifdef Q_OS_WINCE
-# include "qplatformfunctions_wince.h"
-#endif
-
#if !defined(QT_NO_DIRECTWRITE)
# if defined(QT_USE_DIRECTWRITE2)
# include <dwrite_2.h>
@@ -759,116 +755,170 @@ 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);
- if (DWORD(string_offset + offset + length) >= bytes)
+ 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;
+ && *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[i] == 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);
@@ -896,7 +946,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 );
@@ -907,7 +957,7 @@ error:
return i18n_name;
}
-static bool addFontToDatabase(const QString &familyName, uchar charSet,
+static bool addFontToDatabase(const QString &familyName, const QString &styleName, uchar charSet,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
int type,
@@ -960,17 +1010,6 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
quint32 codePageRange[2] = {
signature->fsCsb[0], signature->fsCsb[1]
};
-#ifdef Q_OS_WINCE
- if (signature->fsUsb[0] == 0) {
- // If the unicode ranges bit mask is zero then
- // EnumFontFamiliesEx failed to determine it properly.
- // In this case we just pretend that the font supports all languages.
- unicodeRange[0] = 0xbfffffff; // second most significant bit must be zero
- unicodeRange[1] = 0xffffffff;
- unicodeRange[2] = 0xffffffff;
- unicodeRange[3] = 0xffffffff;
- }
-#endif
writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
// ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains
// the symbol for Baht, and Windows thus reports that it supports the Thai script.
@@ -986,16 +1025,16 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
writingSystems.setSupported(ws);
}
- QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
+ QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
style, stretch, antialias, scalable, size, fixed, writingSystems, 0);
// add fonts windows can generate for us:
- if (weight <= QFont::DemiBold)
+ if (weight <= QFont::DemiBold && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
style, stretch, antialias, scalable, size, fixed, writingSystems, 0);
- if (style != QFont::StyleItalic)
+ if (style != QFont::StyleItalic && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
- if (weight <= QFont::DemiBold && style != QFont::StyleItalic)
+ if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
@@ -1010,6 +1049,7 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
{
const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
+ const QString styleName = QString::fromWCharArray(f->elfStyle);
const uchar charSet = f->elfLogFont.lfCharSet;
const bool registerAlias = bool(lParam);
@@ -1019,7 +1059,7 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
const FONTSIGNATURE *signature = Q_NULLPTR;
if (type & TRUETYPE_FONTTYPE)
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
- addFontToDatabase(familyName, charSet, textmetric, signature, type, registerAlias);
+ addFontToDatabase(familyName, styleName, charSet, textmetric, signature, type, registerAlias);
// keep on enumerating
return 1;
@@ -1130,9 +1170,8 @@ QWindowsFontEngineDataPtr sharedFontData()
}
#endif // QT_NO_THREAD
-#ifndef Q_OS_WINCE
extern Q_GUI_EXPORT bool qt_needs_a8_gamma_correction;
-#endif
+
QWindowsFontDatabase::QWindowsFontDatabase()
{
// Properties accessed by QWin32PrintEngine (Qt Print Support)
@@ -1146,9 +1185,7 @@ QWindowsFontDatabase::QWindowsFontDatabase()
qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: "
<< data->clearTypeEnabled << "gamma: " << data->fontSmoothingGamma;
}
-#ifndef Q_OS_WINCE
qt_needs_a8_gamma_correction = true;
-#endif
}
QWindowsFontDatabase::~QWindowsFontDatabase()
@@ -1364,7 +1401,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());
@@ -1380,11 +1417,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;
@@ -1411,12 +1448,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 =
@@ -1427,7 +1465,9 @@ 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;
+ const QString styleName = families.at(j).style;
+ familyNames << familyName;
HDC hdc = GetDC(0);
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
@@ -1439,7 +1479,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
TEXTMETRIC textMetrics;
GetTextMetrics(hdc, &textMetrics);
- addFontToDatabase(familyName, lf.lfCharSet, &textMetrics, &signatures.at(j),
+ addFontToDatabase(familyName, styleName, lf.lfCharSet, &textMetrics, &signatures.at(j),
TRUETYPE_FONTTYPE, true);
SelectObject(hdc, oldobj);
@@ -1449,13 +1489,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();
@@ -1463,13 +1503,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()
@@ -1595,14 +1638,12 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
int strat = OUT_DEFAULT_PRECIS;
if (request.styleStrategy & QFont::PreferBitmap) {
strat = OUT_RASTER_PRECIS;
-#ifndef Q_OS_WINCE
} else if (request.styleStrategy & QFont::PreferDevice) {
strat = OUT_DEVICE_PRECIS;
} else if (request.styleStrategy & QFont::PreferOutline) {
strat = OUT_OUTLINE_PRECIS;
} else if (request.styleStrategy & QFont::ForceOutline) {
strat = OUT_TT_ONLY_PRECIS;
-#endif
}
lf.lfOutPrecision = strat;
@@ -1611,10 +1652,8 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
if (request.styleStrategy & QFont::PreferMatch)
qual = DRAFT_QUALITY;
-#ifndef Q_OS_WINCE
else if (request.styleStrategy & QFont::PreferQuality)
qual = PROOF_QUALITY;
-#endif
if (request.styleStrategy & QFont::PreferAntialias) {
if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && !(request.styleStrategy & QFont::NoSubpixelAntialias)) {