Read font selection flags and use them when querying for metrics
Certain fonts with multiple styles have the same family name. When loading these as application fonts we were not specific enough when querying for the text metrics. This meant that e.g. the bold version in a font family would get the metrics of the regular one. Fixes: QTBUG-67273 Change-Id: Ic988d62cddde0a1f77ddcaf2891cadc21c9b31e6 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>bb10
parent
d23d146175
commit
17ced070fd
|
|
@ -1490,7 +1490,8 @@ static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag,
|
|||
|
||||
static void getFamiliesAndSignatures(const QByteArray &fontData,
|
||||
QList<QFontNames> *families,
|
||||
QVector<FONTSIGNATURE> *signatures)
|
||||
QVector<FONTSIGNATURE> *signatures,
|
||||
QVector<QFontValues> *values)
|
||||
{
|
||||
const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
|
||||
|
||||
|
|
@ -1511,9 +1512,25 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
|
|||
|
||||
families->append(qMove(names));
|
||||
|
||||
if (values || signatures)
|
||||
getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
|
||||
|
||||
if (values) {
|
||||
QFontValues fontValues;
|
||||
if (table && length >= 64) {
|
||||
// Read in some details about the font, offset calculated based on the specification
|
||||
fontValues.weight = qFromBigEndian<quint16>(table + 4);
|
||||
|
||||
quint16 fsSelection = qFromBigEndian<quint16>(table + 62);
|
||||
fontValues.isItalic = (fsSelection & 1) != 0;
|
||||
fontValues.isUnderlined = (fsSelection & (1 << 1)) != 0;
|
||||
fontValues.isOverstruck = (fsSelection & (1 << 4)) != 0;
|
||||
}
|
||||
values->append(std::move(fontValues));
|
||||
}
|
||||
|
||||
if (signatures) {
|
||||
FONTSIGNATURE signature;
|
||||
getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
|
||||
if (table && length >= 86) {
|
||||
// Offsets taken from OS/2 table in the TrueType spec
|
||||
signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
|
||||
|
|
@ -1536,11 +1553,12 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
|
|||
WinApplicationFont font;
|
||||
font.fileName = fileName;
|
||||
QVector<FONTSIGNATURE> signatures;
|
||||
QVector<QFontValues> fontValues;
|
||||
QList<QFontNames> families;
|
||||
QStringList familyNames;
|
||||
|
||||
if (!fontData.isEmpty()) {
|
||||
getFamiliesAndSignatures(fontData, &families, &signatures);
|
||||
getFamiliesAndSignatures(fontData, &families, &signatures, &fontValues);
|
||||
if (families.isEmpty())
|
||||
return familyNames;
|
||||
|
||||
|
|
@ -1553,14 +1571,23 @@ 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).name;
|
||||
const QString styleName = families.at(j).style;
|
||||
const auto &family = families.at(j);
|
||||
const QString &familyName = family.name;
|
||||
const QString &styleName = family.style;
|
||||
familyNames << familyName;
|
||||
HDC hdc = GetDC(0);
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size()));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
const QFontValues &values = fontValues.at(j);
|
||||
lf.lfWeight = values.weight;
|
||||
if (values.isItalic)
|
||||
lf.lfItalic = TRUE;
|
||||
if (values.isOverstruck)
|
||||
lf.lfStrikeOut = TRUE;
|
||||
if (values.isUnderlined)
|
||||
lf.lfUnderline = TRUE;
|
||||
HFONT hfont = CreateFontIndirect(&lf);
|
||||
HGDIOBJ oldobj = SelectObject(hdc, hfont);
|
||||
|
||||
|
|
@ -1581,7 +1608,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
|
|||
QByteArray data = f.readAll();
|
||||
f.close();
|
||||
|
||||
getFamiliesAndSignatures(data, &families, 0);
|
||||
getFamiliesAndSignatures(data, &families, nullptr, nullptr);
|
||||
if (families.isEmpty())
|
||||
return QStringList();
|
||||
|
||||
|
|
|
|||
|
|
@ -177,6 +177,14 @@ struct QFontNames
|
|||
QString preferredStyle; // e.g. "Condensed Italic"
|
||||
};
|
||||
|
||||
struct QFontValues
|
||||
{
|
||||
quint16 weight = 0;
|
||||
bool isItalic = false;
|
||||
bool isOverstruck = false;
|
||||
bool isUnderlined = false;
|
||||
};
|
||||
|
||||
bool qt_localizedName(const QString &name);
|
||||
QString qt_getEnglishName(const QString &familyName, bool includeStyle = false);
|
||||
QFontNames qt_getCanonicalFontNames(const LOGFONT &lf);
|
||||
|
|
|
|||
|
|
@ -3,5 +3,6 @@
|
|||
<file>LED_REAL.TTF</file>
|
||||
<file alias="testfont.ttf">../../../shared/resources/testfont.ttf</file>
|
||||
<file alias="testfont_condensed.ttf">../../../shared/resources/testfont_condensed.ttf</file>
|
||||
<file alias="testfont_italic.ttf">../../../shared/resources/testfont_italic.ttf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ private slots:
|
|||
void addAppFont_data();
|
||||
void addAppFont();
|
||||
|
||||
void addTwoAppFontsFromFamily();
|
||||
|
||||
void aliases();
|
||||
void fallbackFonts();
|
||||
|
||||
|
|
@ -75,6 +77,7 @@ private:
|
|||
QString m_ledFont;
|
||||
QString m_testFont;
|
||||
QString m_testFontCondensed;
|
||||
QString m_testFontItalic;
|
||||
};
|
||||
|
||||
tst_QFontDatabase::tst_QFontDatabase()
|
||||
|
|
@ -86,9 +89,11 @@ void tst_QFontDatabase::initTestCase()
|
|||
m_ledFont = QFINDTESTDATA("LED_REAL.TTF");
|
||||
m_testFont = QFINDTESTDATA("testfont.ttf");
|
||||
m_testFontCondensed = QFINDTESTDATA("testfont_condensed.ttf");
|
||||
m_testFontItalic = QFINDTESTDATA("testfont_italic.ttf");
|
||||
QVERIFY(!m_ledFont.isEmpty());
|
||||
QVERIFY(!m_testFont.isEmpty());
|
||||
QVERIFY(!m_testFontCondensed.isEmpty());
|
||||
QVERIFY(!m_testFontItalic.isEmpty());
|
||||
}
|
||||
|
||||
void tst_QFontDatabase::styles_data()
|
||||
|
|
@ -259,6 +264,30 @@ void tst_QFontDatabase::addAppFont()
|
|||
QCOMPARE(db.families(), oldFamilies);
|
||||
}
|
||||
|
||||
void tst_QFontDatabase::addTwoAppFontsFromFamily()
|
||||
{
|
||||
int regularId = QFontDatabase::addApplicationFont(m_testFont);
|
||||
if (regularId == -1)
|
||||
QSKIP("Skip the test since app fonts are not supported on this system");
|
||||
|
||||
int italicId = QFontDatabase::addApplicationFont(m_testFontItalic);
|
||||
QVERIFY(italicId != -1);
|
||||
|
||||
QVERIFY(!QFontDatabase::applicationFontFamilies(regularId).isEmpty());
|
||||
QVERIFY(!QFontDatabase::applicationFontFamilies(italicId).isEmpty());
|
||||
|
||||
QString regularFontName = QFontDatabase::applicationFontFamilies(regularId).first();
|
||||
QString italicFontName = QFontDatabase::applicationFontFamilies(italicId).first();
|
||||
QCOMPARE(regularFontName, italicFontName);
|
||||
|
||||
QFont italicFont = QFontDatabase().font(italicFontName,
|
||||
QString::fromLatin1("Italic"), 14);
|
||||
QVERIFY(italicFont.italic());
|
||||
|
||||
QFontDatabase::removeApplicationFont(regularId);
|
||||
QFontDatabase::removeApplicationFont(italicId);
|
||||
}
|
||||
|
||||
void tst_QFontDatabase::aliases()
|
||||
{
|
||||
QFontDatabase db;
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue