Freetype: Fix transforming bitmap fonts

Freetype itself does not support transforming bitmap fonts, so
FT_Set_Transform() is just ignored in this case. This causes
problems in particular for fonts rotated at 90 degree multiples
when used as tab labels. So we need to rotate the actual glyph
images after they have been rasterized instead.

Since we do have most of the mechanisms in place for this when
using the regular glyph cache, we set cacheEnabled to false
for all non-scalable fonts to ensure we take the correct code
path.

In addition, we need to transform the alpha maps before
returning them.

Note: This changes the glyph format to alpha8 for the glyphs
when they are transformed. This is a simplification because
the mono code path requires that glyph widths are aligned
to 8, so there would be more adaptation needed if we wanted
to use this code path. This will only affect non-antialiased
fonts that are drawn with a transform.

[ChangeLog][QtGui][Text] Fixed an issue with the Freetype
backend where rotations would not be applied correctly to
bitmap fonts.

Fixes: QTBUG-81540
Change-Id: Ia68815b425ca1776a5ff81d26d227569467095cf
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2022-10-17 10:41:20 +02:00
parent 30077d462d
commit 6ba003f732

View File

@ -805,10 +805,9 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
line_thickness = 2;
underline_position = ((line_thickness * 2) + 3) / 6;
if (isScalableBitmap()) {
cacheEnabled = false;
if (isScalableBitmap())
glyphFormat = defaultFormat = GlyphFormat::Format_ARGB;
cacheEnabled = false;
}
}
if (line_thickness < 1)
line_thickness = 1;
@ -1828,6 +1827,10 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph,
// When rendering glyphs into a cache via the alphaMap* functions, we disable
// outline drawing. To ensure the bounding box matches the rendered glyph, we
// need to do the same here.
const bool needsImageTransform = !FT_IS_SCALABLE(freetype->face) && !matrix.isIdentity();
if (needsImageTransform && format == QFontEngine::Format_Mono)
format = QFontEngine::Format_A8;
Glyph *g = loadGlyphFor(glyph, subPixelPosition, format, matrix, true, true);
glyph_metrics_t overall;
@ -1854,7 +1857,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph,
unlockFace();
}
if (isScalableBitmap())
if (isScalableBitmap() || needsImageTransform)
overall = scaledBitmapMetrics(overall, matrix);
return overall;
}
@ -1954,12 +1957,16 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g,
const QFixedPoint &subPixelPosition,
const QTransform &t)
{
const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono;
const bool needsImageTransform = !FT_IS_SCALABLE(freetype->face) && !t.isIdentity();
const GlyphFormat neededFormat = antialias || needsImageTransform ? Format_A8 : Format_Mono;
Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t, false, true);
QImage img = alphaMapFromGlyphData(glyph, neededFormat);
img = img.copy();
if (needsImageTransform)
img = img.transformed(t, Qt::SmoothTransformation);
else
img = img.copy();
if (!cacheEnabled && glyph != &emptyGlyph)
delete glyph;