Avoid synthesizing stretch on condensed font families

If an entire font family is condensed or stretched and we match by
family name, the default stretch factor of 100 will make the font
engine try to synthesize it back to medium stretched font.

The existing code is already made to deal with a stretch of 0 that is
no longer used. This patch reintroduces 0 stretch to indicate no
specific stretch has been requested. Specifically setting stretch to
100 on a QFont will introduce the old behavior.

[ChangeLog][QtGui][QFont] The default value of QFont::stretch() is
now 0 to indicate any default stretch is acceptable.

Task-number: QTBUG-48043
Change-Id: I574747f980fd4f9893df828818aae99a07b41623
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2015-08-31 22:13:08 +02:00 committed by Eskil Abrahamsen Blomfeldt
parent 5d1c35e21d
commit 131eee5cd7
7 changed files with 42 additions and 16 deletions

View File

@ -1376,6 +1376,7 @@ void QFont::setStyleStrategy(StyleStrategy s)
Predefined stretch values that follow the CSS naming convention. The higher
the value, the more stretched the text is.
\value AnyStretch 0 Accept any stretch matched using the other QFont properties (added in Qt 5.8)
\value UltraCondensed 50
\value ExtraCondensed 62
\value Condensed 75
@ -1402,20 +1403,25 @@ int QFont::stretch() const
/*!
Sets the stretch factor for the font.
The stretch factor changes the width of all characters in the font
by \a factor percent. For example, setting \a factor to 150
The stretch factor matches a condensed or expanded version of the font or
applies a stretch transform that changes the width of all characters
in the font by \a factor percent. For example, setting \a factor to 150
results in all characters in the font being 1.5 times (ie. 150%)
wider. The default stretch factor is 100. The minimum stretch
factor is 1, and the maximum stretch factor is 4000.
wider. The minimum stretch factor is 1, and the maximum stretch factor
is 4000. The default stretch factor is \c AnyStretch, which will accept
any stretch factor and not apply any transform on the font.
The stretch factor is only applied to outline fonts. The stretch
factor is ignored for bitmap fonts.
\note When matching a font with a native non-default stretch factor,
requesting a stretch of 100 will stretch it back to a medium width font.
\sa stretch(), QFont::Stretch
*/
void QFont::setStretch(int factor)
{
if (factor < 1 || factor > 4000) {
if (factor < 0 || factor > 4000) {
qWarning("QFont::setStretch: Parameter '%d' out of range", factor);
return;
}

View File

@ -113,6 +113,7 @@ public:
};
enum Stretch {
AnyStretch = 0,
UltraCondensed = 50,
ExtraCondensed = 62,
Condensed = 75,

View File

@ -71,7 +71,7 @@ struct QFontDef
inline QFontDef()
: pointSize(-1.0), pixelSize(-1),
styleStrategy(QFont::PreferDefault), styleHint(QFont::AnyStyle),
weight(50), fixedPitch(false), style(QFont::StyleNormal), stretch(100),
weight(50), fixedPitch(false), style(QFont::StyleNormal), stretch(QFont::AnyStretch),
hintingPreference(QFont::PreferDefaultHinting), ignorePitch(true),
fixedPitchComputed(0), reserved(0)
{

View File

@ -951,12 +951,14 @@ QFontEngine *loadSingleEngine(int script,
}
}
// If the font data's native stretch matches the requested stretch we need to set stretch to 100
// to avoid the fontengine synthesizing stretch. If they didn't match exactly we need to calculate
// the new stretch factor. This only done if not matched by styleName.
// To avoid synthesized stretch we need a matching stretch to be 100 after this point.
// If stretch didn't match exactly we need to calculate the new stretch factor.
// This only done if not matched by styleName.
if (style->key.stretch != 0 && request.stretch != 0
&& (request.styleName.isEmpty() || request.styleName != style->styleName)) {
def.stretch = (request.stretch * 100 + 50) / style->key.stretch;
def.stretch = (request.stretch * 100 + style->key.stretch / 2) / style->key.stretch;
} else {
def.stretch = 100;
}
engine = pfdb->fontEngine(def, size->handle);
@ -1219,7 +1221,8 @@ static int match(int script, const QFontDef &request,
QtFontStyle::Key styleKey;
styleKey.style = request.style;
styleKey.weight = request.weight;
styleKey.stretch = request.stretch;
// Prefer a stretch closest to 100.
styleKey.stretch = request.stretch ? request.stretch : 100;
char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
@ -2740,8 +2743,6 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
}
if (req.pointSize < 0)
req.pointSize = req.pixelSize*72.0/d->dpi;
if (req.stretch == 0)
req.stretch = 100;
// respect the fallback families that might be passed through the request
const QStringList fallBackFamilies = familyList(req);

View File

@ -172,7 +172,7 @@ QFontEngine::GlyphFormat QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef)
{
CGAffineTransform transform = CGAffineTransformIdentity;
if (fontDef.stretch != 100)
if (fontDef.stretch && fontDef.stretch != 100)
transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
return transform;
}

View File

@ -101,8 +101,6 @@ void tst_QFontCache::engineData()
}
if (req.pointSize < 0)
req.pointSize = req.pixelSize*72.0/d->dpi;
if (req.stretch == 0)
req.stretch = 100;
req.family = cacheKey;

View File

@ -64,6 +64,8 @@ private slots:
void aliases();
void fallbackFonts();
void liberationFont();
private:
const QString m_testFont;
};
@ -275,5 +277,23 @@ void tst_QFontDatabase::fallbackFonts()
}
}
void tst_QFontDatabase::liberationFont()
{
QString libSans("Liberation Sans");
QString libSansNarrow("Liberation Sans Narrow");
QFontDatabase db;
if (!db.hasFamily(libSans) || !db.hasFamily(libSansNarrow))
QSKIP("Requires Liberation Sans installed");
QFont fontLS(libSans);
QFont fontLSN(libSansNarrow);
QFontMetrics fmLS(fontLS);
QFontMetrics fmLSN(fontLSN);
QVERIFY(fmLS.width(QStringLiteral("foo bar")) > fmLSN.width(QStringLiteral("foo bar")));
}
QTEST_MAIN(tst_QFontDatabase)
#include "tst_qfontdatabase.moc"