Fix memory corruption on scaled emojis
Bitmap glyphs are returned prescaled, which means we should include the transform in their bounding box. Additionally painting them should stick the smallest rect to avoid writing outside the allocated area, and assert in debug builds. Task-number: QTBUG-64239 Change-Id: I5f877d36566891323f528018f910798344ba4ce2 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>bb10
parent
c8fa698e99
commit
7df4dcff2c
|
|
@ -318,11 +318,12 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
Q_ASSERT(mask.width() <= c.w && mask.height() <= c.h);
|
||||
|
||||
if (m_format == QFontEngine::Format_A32
|
||||
|| m_format == QFontEngine::Format_ARGB) {
|
||||
QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()),
|
||||
qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(),
|
||||
qMin(mask.width(), c.w), qMin(mask.height(), c.h), m_image.bytesPerLine(),
|
||||
m_image.format());
|
||||
QPainter p(&ref);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
|
|
|||
|
|
@ -1776,15 +1776,25 @@ QFixed QFontEngineFT::scaledBitmapMetrics(QFixed m) const
|
|||
return m * scalableBitmapScaleFactor;
|
||||
}
|
||||
|
||||
glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m) const
|
||||
glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &t) const
|
||||
{
|
||||
QTransform trans(t);
|
||||
const qreal scaleFactor = scalableBitmapScaleFactor.toReal();
|
||||
trans.scale(scaleFactor, scaleFactor);
|
||||
|
||||
QRectF rect(m.x.toReal(), m.y.toReal(), m.width.toReal(), m.height.toReal());
|
||||
QPointF offset(m.xoff.toReal(), m.yoff.toReal());
|
||||
|
||||
rect = trans.mapRect(rect);
|
||||
offset = trans.map(offset);
|
||||
|
||||
glyph_metrics_t metrics;
|
||||
metrics.x = scaledBitmapMetrics(m.x);
|
||||
metrics.y = scaledBitmapMetrics(m.y);
|
||||
metrics.width = scaledBitmapMetrics(m.width);
|
||||
metrics.height = scaledBitmapMetrics(m.height);
|
||||
metrics.xoff = scaledBitmapMetrics(m.xoff);
|
||||
metrics.yoff = scaledBitmapMetrics(m.yoff);
|
||||
metrics.x = QFixed::fromReal(rect.x());
|
||||
metrics.y = QFixed::fromReal(rect.y());
|
||||
metrics.width = QFixed::fromReal(rect.width());
|
||||
metrics.height = QFixed::fromReal(rect.height());
|
||||
metrics.xoff = QFixed::fromReal(offset.x());
|
||||
metrics.yoff = QFixed::fromReal(offset.y());
|
||||
return metrics;
|
||||
}
|
||||
|
||||
|
|
@ -1878,7 +1888,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
|
|||
unlockFace();
|
||||
|
||||
if (isScalableBitmap())
|
||||
overall = scaledBitmapMetrics(overall);
|
||||
overall = scaledBitmapMetrics(overall, QTransform());
|
||||
return overall;
|
||||
}
|
||||
|
||||
|
|
@ -1917,7 +1927,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
|
|||
unlockFace();
|
||||
|
||||
if (isScalableBitmap())
|
||||
overall = scaledBitmapMetrics(overall);
|
||||
overall = scaledBitmapMetrics(overall, QTransform());
|
||||
return overall;
|
||||
}
|
||||
|
||||
|
|
@ -1955,7 +1965,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
|
|||
}
|
||||
|
||||
if (isScalableBitmap())
|
||||
overall = scaledBitmapMetrics(overall);
|
||||
overall = scaledBitmapMetrics(overall, matrix);
|
||||
return overall;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ private:
|
|||
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
|
||||
bool shouldUseDesignMetrics(ShaperFlags flags) const;
|
||||
QFixed scaledBitmapMetrics(QFixed m) const;
|
||||
glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m) const;
|
||||
glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &matrix) const;
|
||||
|
||||
GlyphFormat defaultFormat;
|
||||
FT_Matrix matrix;
|
||||
|
|
|
|||
Loading…
Reference in New Issue