Fix crash when doing many text layouts with superscript/subscript
Aftere109b8a0f3
, it is possible that the cache will be flushed as a result of inserting a new font rather than just when the timer event triggers. When doing superscript and subscript text layouts, we would first get a regular font engine, then a scaled one, and then reference the regular font engine *after* getting the scaled one. If the regular font engine was deleted as a result of inserting the scaled one, we would get a dangling pointer and crash. The situation was improved by49926bb9ef
. You would now to switch between 256 different fonts in the layout in order to trigger it. The test in the commit will trigger the crash even with this change. [ChangeLog][Qt Gui][Text] Fixed a crash that could happen if you were doing many different text layouts with different fonts and superscript or subscript alignment. Task-number: QTBUG-53911 Change-Id: Ia33108252e030eff25924ef1b7c10b9d59b5bc8c Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
422838685c
commit
462f6029ed
@ -2058,6 +2058,9 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
|
||||
font = font.resolve(fnt);
|
||||
}
|
||||
engine = font.d->engineForScript(script);
|
||||
if (engine)
|
||||
engine->ref.ref();
|
||||
|
||||
QTextCharFormat::VerticalAlignment valign = f.verticalAlignment();
|
||||
if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
|
||||
if (font.pointSize() != -1)
|
||||
@ -2065,16 +2068,14 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
|
||||
else
|
||||
font.setPixelSize((font.pixelSize() * 2) / 3);
|
||||
scaledEngine = font.d->engineForScript(script);
|
||||
if (scaledEngine)
|
||||
scaledEngine->ref.ref();
|
||||
}
|
||||
|
||||
if (engine)
|
||||
engine->ref.ref();
|
||||
if (feCache.prevFontEngine)
|
||||
releaseCachedFontEngine(feCache.prevFontEngine);
|
||||
feCache.prevFontEngine = engine;
|
||||
|
||||
if (scaledEngine)
|
||||
scaledEngine->ref.ref();
|
||||
if (feCache.prevScaledFontEngine)
|
||||
releaseCachedFontEngine(feCache.prevScaledFontEngine);
|
||||
feCache.prevScaledFontEngine = scaledEngine;
|
||||
|
@ -143,6 +143,7 @@ private slots:
|
||||
void cursorInNonStopChars();
|
||||
void nbsp();
|
||||
void noModificationOfInputString();
|
||||
void superscriptCrash_qtbug53911();
|
||||
|
||||
private:
|
||||
QFont testFont;
|
||||
@ -2209,5 +2210,61 @@ void tst_QTextLayout::noModificationOfInputString()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QTextLayout::superscriptCrash_qtbug53911()
|
||||
{
|
||||
static int fontSizes = 64;
|
||||
static QString layoutText = "THIS IS SOME EXAMPLE TEXT THIS IS SOME EXAMPLE TEXT";
|
||||
|
||||
QList<QTextLayout*> textLayouts;
|
||||
for (int i = 0; i < fontSizes; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
QTextLayout* newTextLayout = new QTextLayout();
|
||||
newTextLayout->setText(layoutText);
|
||||
QList<QTextLayout::FormatRange> formatRanges;
|
||||
QTextLayout::FormatRange formatRange;
|
||||
|
||||
formatRange.format.setFont(QFont());
|
||||
formatRange.format.setFontPointSize(i + 5);
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
formatRange.format.setFontWeight(QFont::Normal);
|
||||
formatRange.format.setFontItalic(false);
|
||||
break;
|
||||
case 1:
|
||||
formatRange.format.setFontWeight(QFont::Bold);
|
||||
formatRange.format.setFontItalic(false);
|
||||
break;
|
||||
case 2:
|
||||
formatRange.format.setFontWeight(QFont::Bold);
|
||||
formatRange.format.setFontItalic(true);
|
||||
break;
|
||||
case 3:
|
||||
formatRange.format.setFontWeight(QFont::Normal);
|
||||
formatRange.format.setFontItalic(true);
|
||||
break;
|
||||
}
|
||||
|
||||
formatRange.format.setVerticalAlignment( QTextCharFormat::AlignSuperScript);
|
||||
|
||||
formatRange.start = 0;
|
||||
formatRange.length = layoutText.size();
|
||||
formatRanges << formatRange;
|
||||
newTextLayout->setAdditionalFormats(formatRanges);
|
||||
|
||||
textLayouts.push_front(newTextLayout);
|
||||
}
|
||||
}
|
||||
|
||||
// This loop would crash before fix for QTBUG-53911
|
||||
foreach (QTextLayout *textLayout, textLayouts) {
|
||||
textLayout->beginLayout();
|
||||
while (textLayout->createLine().isValid());
|
||||
textLayout->endLayout();
|
||||
}
|
||||
|
||||
qDeleteAll(textLayouts);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTextLayout)
|
||||
#include "tst_qtextlayout.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user