QFontDatabase (Windows): Sanitize font requests early

After the windows font engine was no longer marking everything as
scalable we started limiting the font size of requests to the maximum
of Courier when it was requested. This was a regression from 5.8 and not
in agreement with our documentation.

The problem is that we would only make the switch from Courier to
Courier New after having already gone through the foundry-lookup and
found a closest-available font size for Courier.

With this sanitization step in the backend we can make these changes
early enough that we haven't yet adjusted e.g. the font size.

Pick-to: 6.2 5.15
Fixes: QTBUG-58995
Change-Id: I319e93e6b78c7c3c5539964ac5ab4e05f8902ab6
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Mårten Nordheim 2021-12-02 17:14:18 +01:00
parent eba9196304
commit 6f542f19bf
4 changed files with 65 additions and 11 deletions

View File

@ -62,6 +62,10 @@
#include <qtgui_tracepoints_p.h>
#ifdef Q_OS_WIN
#include <QtGui/private/qwindowsfontdatabasebase_p.h>
#endif
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcFontDb, "qt.text.font.db")
@ -2350,7 +2354,7 @@ bool QFontDatabase::removeAllApplicationFonts()
/*!
\internal
*/
QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &request,
QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
int script,
bool preferScriptOverFamily)
{
@ -2361,6 +2365,14 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &request,
QFontEngine *engine;
#ifdef Q_OS_WIN
const QFontDef request = static_cast<QWindowsFontDatabaseBase *>(
QGuiApplicationPrivate::platformIntegration()->fontDatabase())
->sanitizeRequest(req);
#else
const QFontDef &request = req;
#endif
#if defined(QT_BUILD_INTERNAL)
// For testing purpose only, emulates an exact-matching monospace font
if (qt_enable_test_font && request.families.first() == QLatin1String("__Qt__Box__Engine__")) {

View File

@ -696,16 +696,6 @@ LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, cons
fam.truncate(LF_FACESIZE - 1);
}
if (fam.isEmpty())
fam = QStringLiteral("MS Sans Serif");
if (fam == QLatin1String("MS Sans Serif")
&& (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) {
fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale
}
if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
fam = QStringLiteral("Courier New");
memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t));
return lf;
@ -947,4 +937,23 @@ QStringList QWindowsFontDatabaseBase::extraTryFontsForFamily(const QString &fami
return result;
}
QFontDef QWindowsFontDatabaseBase::sanitizeRequest(QFontDef request) const
{
QFontDef req = request;
const QString fam = request.families.front();
if (fam.isEmpty())
req.families[0] = QStringLiteral("MS Sans Serif");
if (fam == QLatin1String("MS Sans Serif")) {
int height = -qRound(request.pixelSize);
// MS Sans Serif has bearing problems in italic, and does not scale
if (request.style == QFont::StyleItalic || (height > 18 && height != 24))
req.families[0] = QStringLiteral("Arial");
}
if (!(request.styleStrategy & QFont::StyleStrategy::PreferBitmap) && fam == u"Courier")
req.families[0] = QStringLiteral("Courier New");
return req;
}
QT_END_NAMESPACE

View File

@ -122,6 +122,8 @@ public:
QByteArray m_fontData;
};
QFontDef sanitizeRequest(QFontDef request) const;
protected:
#if QT_CONFIG(directwrite)

View File

@ -84,6 +84,10 @@ private slots:
void stretchRespected();
#ifdef Q_OS_WIN
void findCourier();
#endif
private:
QString m_ledFont;
QString m_testFont;
@ -500,5 +504,32 @@ void tst_QFontDatabase::registerOpenTypePreferredNamesApplication()
QFontDatabase::removeApplicationFont(id);
}
#ifdef Q_OS_WIN
void tst_QFontDatabase::findCourier()
{
QFont font = QFontDatabase::font(u"Courier"_qs, u""_qs, 16);
QFontInfo info(font);
QCOMPARE(info.family(), u"Courier New"_qs);
QCOMPARE(info.pointSize(), 16);
font = QFontDatabase::font("Courier", "", 64);
info = font;
QCOMPARE(info.family(), u"Courier New"_qs);
QCOMPARE(info.pointSize(), 64);
// By setting "PreferBitmap" we should get Courier itself.
font.setStyleStrategy(QFont::PreferBitmap);
info = font;
QCOMPARE(info.family(), u"Courier"_qs);
// Which has an upper bound on point size
QCOMPARE(info.pointSize(), 19);
font.setStyleStrategy(QFont::PreferDefault);
info = font;
QCOMPARE(info.family(), u"Courier New"_qs);
QCOMPARE(info.pointSize(), 64);
}
#endif
QTEST_MAIN(tst_QFontDatabase)
#include "tst_qfontdatabase.moc"