Fix memory leaks in the FT font engine

The glyph returned by loadGlpyh() must be freed manually when caching
is not enabled (that is, QT_USE_FT_CACHE is not set).

This change and https://codereview.qt-project.org/#change,65672
together should stop QGLWidget::renderText() from leaking memory
extensively.

Task-number: QTBUG-32792
Change-Id: Iff7e1591a1ea994a97b6a56bc16c64bf544e6713
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
Laszlo Agocs 2013-09-17 10:14:36 +02:00 committed by The Qt Project
parent 31db0aec22
commit d18ccbb5be

View File

@ -1583,6 +1583,8 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true);
glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
: QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
if (!cacheEnabled)
delete g;
}
glyphs->advances_y[i] = 0;
}
@ -1621,6 +1623,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
xmax = qMax(xmax, x + g->width);
ymax = qMax(ymax, y + g->height);
overall.xoff += g->advance;
if (!cacheEnabled)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
@ -1662,6 +1666,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
overall.xoff = g->advance;
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
overall.xoff = overall.xoff.round();
if (!cacheEnabled)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
@ -1751,6 +1757,8 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
if (!glyphSet)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
@ -1799,6 +1807,7 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
};
QFontEngineFT::Glyph *glyph;
QScopedPointer<QFontEngineFT::Glyph> glyphGuard;
if (cacheEnabled) {
QFontEngineFT::QGlyphSet *gset = &defaultGlyphSet;
QFontEngine::HintStyle hintStyle = default_hint_style;
@ -1834,6 +1843,7 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
FT_Set_Transform(freetype->face, &m, 0);
freetype->matrix = m;
glyph = loadGlyph(0, glyphIndex, subPixelPosition, neededFormat);
glyphGuard.reset(glyph);
}
if (glyph == 0 || glyph->data == 0 || glyph->width == 0 || glyph->height == 0) {
@ -1861,6 +1871,8 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
*offset = QPoint(glyph->x, -glyph->y);
currentlyLockedAlphaMap = QImage(glyph->data, glyph->width, glyph->height, pitch, format);
if (!glyphGuard.isNull())
currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy();
Q_ASSERT(!currentlyLockedAlphaMap.isNull());
QImageData *data = currentlyLockedAlphaMap.data_ptr();
@ -1886,7 +1898,9 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
lockFace();
Glyph *glyph = loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono);
QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
if (cacheEnabled)
glyph.take();
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@ -1923,7 +1937,9 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
lockFace();
Glyph *glyph = loadGlyphFor(g, subPixelPosition, Format_A32);
QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
if (cacheEnabled)
glyph.take();
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);