REG: Fix nbsp in QTextLayout

At some point since Qt 4.8, the nbsp character has acquired
the whitespace attribute, causing it to be treated exactly
like an ordinary space. To account for this, we add an extra
check in the layout code to avoid breaking on non-breaking
spaces even if they have the whiteSpace flag set.

This is a temporary fix for the regression. The line breaking
algorithm needs to be refactored and support Unicode tr14
properly, which it currently doesn't.

[ChangeLog][Text] Fixed lines breaking on non-breaking spaces.

Task-number: QTBUG-39832
Change-Id: Ibd7e1a11ce4b82c611ecda1542c8638a67bf3cae
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2014-06-24 12:40:03 +02:00
parent 1c08a41cb9
commit b56a42be14
2 changed files with 34 additions and 1 deletions

View File

@ -1842,8 +1842,17 @@ void QTextLine::layout_helper(int maxGlyphs)
addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,
current, lbh.logClusters, lbh.glyphs);
// This is a hack to fix a regression caused by the introduction of the
// whitespace flag to non-breakable spaces and will cause the non-breakable
// spaces to behave as in previous Qt versions in the line breaking algorithm.
// The line breaks do not currently follow the Unicode specs, but fixing this would
// require refactoring the code and would cause behavioral regressions.
bool isBreakableSpace = lbh.currentPosition < eng->layoutData->string.length()
&& attributes[lbh.currentPosition].whiteSpace
&& eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak;
if (lbh.currentPosition >= eng->layoutData->string.length()
|| attributes[lbh.currentPosition].whiteSpace
|| isBreakableSpace
|| attributes[lbh.currentPosition].lineBreak) {
sb_or_ws = true;
break;

View File

@ -139,6 +139,7 @@ private slots:
void cursorInLigatureWithMultipleLines();
void xToCursorForLigatures();
void cursorInNonStopChars();
void nbsp();
private:
QFont testFont;
@ -2011,5 +2012,28 @@ void tst_QTextLayout::justifyTrailingSpaces()
QVERIFY(qFuzzyIsNull(layout.lineAt(0).cursorToX(0)));
}
void tst_QTextLayout::nbsp()
{
QString s = QString() + QChar(' ') + QChar('a') + QString(10, QChar::Nbsp) + QChar('a') + QChar(' ') + QChar('A');
QString text = s + s + s + s + s + s + s + s + s + s + s + s + s + s;
QTextLayout layout(text);
layout.setCacheEnabled(true);
layout.beginLayout();
layout.createLine();
layout.endLayout();
int naturalWidth = qCeil(layout.lineAt(0).naturalTextWidth());
int lineWidth = naturalWidth;
layout.beginLayout();
QTextLine line = layout.createLine();
while (lineWidth-- > naturalWidth / 2) {
line.setLineWidth(lineWidth);
QVERIFY(text.at(line.textLength()-1).unicode() != QChar::Nbsp);
}
layout.endLayout();
}
QTEST_MAIN(tst_QTextLayout)
#include "tst_qtextlayout.moc"