Freetype: Fix artificial oblique combined with other transforms
When applying an "obliquen" transformation with Freetype, this applies a 12 degree horizontal shear on the control points of the glyph you have loaded. However, any other transformation we set on the glyph will be applied when loading it. So if you have e.g. a rotation on the glyph as well, then this will be applied first and the rotated glyph would be obliquened instead, now along the wrong arbitrary axis in the rotated coordinate system. To fix this, we detect the case where a transform is applied and multiply in the obliquen in advance. It means we have to duplicate some code from FT_GlyphSlot_Oblique() which might get out of sync (if the slant angle changes in a newer version for instance). We limit this to the cases that are currently broken so that we avoid messing with any working use cases. [ChangeLog][Text] Fixed an issue where artificially obliquened text would look incorrect when other transformations were also applied and the Freetype backend was in use. Pick-to: 6.5 Fixes: QTBUG-97436 Change-Id: I61c5d007e9ea9be2beb283a8b8abbed7723bab38 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit db8230715aa115dc2da5177bb1824fb40c5f2569) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
d990f697b5
commit
3b9f202539
@ -1120,6 +1120,23 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
FT_Face face = freetype->face;
|
||||
|
||||
FT_Matrix matrix = freetype->matrix;
|
||||
bool transform = matrix.xx != 0x10000
|
||||
|| matrix.yy != 0x10000
|
||||
|| matrix.xy != 0
|
||||
|| matrix.yx != 0;
|
||||
if (obliquen && transform) {
|
||||
// We have to apply the obliquen transformation before any
|
||||
// other transforms. This means we need to duplicate Freetype's
|
||||
// obliquen matrix here and this has to be kept in sync.
|
||||
FT_Matrix slant;
|
||||
slant.xx = 0x10000L;
|
||||
slant.yx = 0;
|
||||
slant.xy = 0x0366A;
|
||||
slant.yy = 0x10000L;
|
||||
|
||||
FT_Matrix_Multiply(&matrix, &slant);
|
||||
matrix = slant;
|
||||
}
|
||||
|
||||
FT_Vector v;
|
||||
v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.x.value());
|
||||
@ -1130,11 +1147,6 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
int vfactor = 1;
|
||||
int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
|
||||
|
||||
bool transform = matrix.xx != 0x10000
|
||||
|| matrix.yy != 0x10000
|
||||
|| matrix.xy != 0
|
||||
|| matrix.yx != 0;
|
||||
|
||||
if (transform || obliquen || (format != Format_Mono && !isScalableBitmap()))
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
|
||||
@ -1166,7 +1178,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
|
||||
if (embolden)
|
||||
FT_GlyphSlot_Embolden(slot);
|
||||
if (obliquen) {
|
||||
if (obliquen && !transform) {
|
||||
FT_GlyphSlot_Oblique(slot);
|
||||
|
||||
// While Embolden alters the metrics of the slot, oblique does not, so we need
|
||||
|
@ -18,6 +18,7 @@ private slots:
|
||||
void tst_render_data();
|
||||
void tst_render();
|
||||
void tst_differentScriptsBackgrounds();
|
||||
void tst_synthesizedObliqueAndRotation();
|
||||
|
||||
private:
|
||||
QDir htmlDir;
|
||||
@ -102,6 +103,29 @@ void tst_Text::tst_differentScriptsBackgrounds()
|
||||
QBASELINE_CHECK(image, "tst_differentScriptsBackgrounds");
|
||||
}
|
||||
|
||||
void tst_Text::tst_synthesizedObliqueAndRotation()
|
||||
{
|
||||
QFont font(QString::fromLatin1("Abyssinica SIL"));
|
||||
font.setPixelSize(40);
|
||||
font.setItalic(true);
|
||||
|
||||
QImage image(800, 600, QImage::Format_ARGB32);
|
||||
image.fill(Qt::white);
|
||||
|
||||
{
|
||||
QPainter painter(&image);
|
||||
painter.setFont(font);
|
||||
|
||||
painter.save();
|
||||
painter.translate(200, 450);
|
||||
painter.rotate(270);
|
||||
painter.drawText(0, 0, QString::fromLatin1("Foobar"));
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
QBASELINE_CHECK(image, "tst_synthesizedObliqueAndRotation");
|
||||
}
|
||||
|
||||
|
||||
QBASELINETEST_MAIN(tst_Text)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user