mirror of https://github.com/qt/qtbase.git
Fix kerned advances in QRawFont on OS X and Windows
On Windows, the wrong value was used to calculate the design-to-device scale. The assumption has been that tmHeight in the TEXTMETRIC is the pixel size of the em square, but it is not, it's the height of the font (ascent + descent). The pixel size of the font is defined to be the em square size in pixels. On OS X, the kerning data was never actually read from the font. I've added a lazy initialization for this similar to the one in the FT engine. This was discovered when investigating QTBUG-48546, as it turned out that the kerning information extracted by Qt in this case was different from the one used by Harfbuzz. I've changed testfont.ttf to kern "_2" so that the digit is positioned directly on top of the underscore and constructed a test. [ChangeLog][QRawFont] Fixed kerning on advances in QRawFont for OS X and Windows. Change-Id: Ic9a321ad119ea880cef89b861c75a820ab8d3182 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
parent
0325842b99
commit
50cd0daf29
|
@ -215,6 +215,8 @@ void QCoreTextFontEngine::init()
|
|||
Q_ASSERT((void *)(&ctfont + 1) == (void *)&cgFont);
|
||||
faceData.user_data = &ctfont;
|
||||
faceData.get_font_table = ct_getSfntTable;
|
||||
|
||||
kerningPairsLoaded = false;
|
||||
}
|
||||
|
||||
glyph_t QCoreTextFontEngine::glyphIndex(uint ucs4) const
|
||||
|
@ -788,4 +790,17 @@ QFontEngine::Properties QCoreTextFontEngine::properties() const
|
|||
return result;
|
||||
}
|
||||
|
||||
void QCoreTextFontEngine::doKerning(QGlyphLayout *g, ShaperFlags flags) const
|
||||
{
|
||||
if (!kerningPairsLoaded) {
|
||||
kerningPairsLoaded = true;
|
||||
qreal emSquare = CTFontGetUnitsPerEm(ctfont);
|
||||
qreal scale = emSquare / CTFontGetSize(ctfont);
|
||||
|
||||
const_cast<QCoreTextFontEngine *>(this)->loadKerningPairs(QFixed::fromReal(scale));
|
||||
}
|
||||
|
||||
QFontEngine::doKerning(g, flags);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
|
||||
QFixed emSquareSize() const Q_DECL_OVERRIDE;
|
||||
void doKerning(QGlyphLayout *g, ShaperFlags flags) const Q_DECL_OVERRIDE;
|
||||
|
||||
bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
|
||||
|
||||
|
@ -134,6 +135,7 @@ private:
|
|||
CGAffineTransform transform;
|
||||
QFixed avgCharWidth;
|
||||
QFontEngine::FaceId face_id;
|
||||
mutable bool kerningPairsLoaded;
|
||||
};
|
||||
|
||||
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
|
||||
|
|
|
@ -197,7 +197,7 @@ void QWindowsFontEngine::getCMap()
|
|||
designToDevice = QFixed((int)otm->otmEMSquare)/QFixed::fromReal(fontDef.pixelSize);
|
||||
unitsPerEm = otm->otmEMSquare;
|
||||
x_height = (int)otm->otmsXHeight;
|
||||
loadKerningPairs(QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight));
|
||||
loadKerningPairs(designToDevice);
|
||||
_faceId.filename = QFile::encodeName(QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)));
|
||||
lineWidth = otm->otmsUnderscoreSize;
|
||||
fsType = otm->otmfsType;
|
||||
|
|
|
@ -93,6 +93,8 @@ private slots:
|
|||
void multipleRawFontsFromData();
|
||||
|
||||
void rawFontFromInvalidData();
|
||||
|
||||
void kernedAdvances();
|
||||
private:
|
||||
QString testFont;
|
||||
QString testFontBoldItalic;
|
||||
|
@ -954,6 +956,38 @@ void tst_QRawFont::rawFontFromInvalidData()
|
|||
QVERIFY(!font.isValid());
|
||||
}
|
||||
|
||||
#define FUZZY_LTEQ(X, Y) (X < Y || qFuzzyCompare(X, Y))
|
||||
|
||||
void tst_QRawFont::kernedAdvances()
|
||||
{
|
||||
const int emSquareSize = 1000;
|
||||
const qreal pixelSize = 16.0;
|
||||
const int underScoreAW = 500;
|
||||
const int underscoreTwoKerning = -500;
|
||||
const qreal errorMargin = 1.0 / 16.0; // Fixed point error margin
|
||||
|
||||
QRawFont font(testFont, pixelSize);
|
||||
QVERIFY(font.isValid());
|
||||
|
||||
QVector<quint32> glyphIndexes = font.glyphIndexesForString(QStringLiteral("__"));
|
||||
QCOMPARE(glyphIndexes.size(), 2);
|
||||
|
||||
QVector<QPointF> advances = font.advancesForGlyphIndexes(glyphIndexes, QRawFont::KernedAdvances);
|
||||
QCOMPARE(advances.size(), 2);
|
||||
|
||||
qreal expectedAdvanceWidth = pixelSize * underScoreAW / emSquareSize;
|
||||
QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin));
|
||||
|
||||
glyphIndexes = font.glyphIndexesForString(QStringLiteral("_2"));
|
||||
QCOMPARE(glyphIndexes.size(), 2);
|
||||
|
||||
advances = font.advancesForGlyphIndexes(glyphIndexes, QRawFont::KernedAdvances);
|
||||
QCOMPARE(advances.size(), 2);
|
||||
|
||||
expectedAdvanceWidth = pixelSize * (underScoreAW + underscoreTwoKerning) / emSquareSize;
|
||||
QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin));
|
||||
}
|
||||
|
||||
#endif // QT_NO_RAWFONT
|
||||
|
||||
QTEST_MAIN(tst_QRawFont)
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue