From c5fa9eb1cb02d979502e2c9918d752c6708fb406 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 9 Aug 2010 10:31:16 +0200 Subject: Fix scrollbar randomly popping up in QPlainTextEdit When a line break was detected, we would retain the value of the right bearing for the character after the break instead of resetting it to the right bearing of the previous value. This could in some cases cause the bounding rect of the text to be wrong, and could cause unnecessary horizontal scrollbars to pop up. It was especially visible when using WrapAnywhere. Visible e.g. in the compile output in Creator. Done-by: mae Reviewed-by: Eskil Reviewed-by: Lars --- src/gui/text/qtextlayout.cpp | 21 +++++++++++++++++---- tests/auto/qtextlayout/tst_qtextlayout.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 5a11c87..da43913 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1709,14 +1709,18 @@ namespace { return glyphs.glyphs[logClusters[currentPosition - 1]]; } + inline void adjustRightBearing(glyph_t glyph) + { + qreal rb; + fontEngine->getGlyphBearings(glyph, 0, &rb); + rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + } + inline void adjustRightBearing() { if (currentPosition <= 0) return; - - qreal rb; - fontEngine->getGlyphBearings(currentGlyph(), 0, &rb); - rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + adjustRightBearing(currentGlyph()); } inline void resetRightBearing() @@ -1901,6 +1905,9 @@ void QTextLine::layout_helper(int maxGlyphs) } else { lbh.whiteSpaceOrObject = false; bool sb_or_ws = false; + glyph_t previousGlyph = 0; + if (lbh.currentPosition > 0 && lbh.logClusters[lbh.currentPosition - 1] line.width) lbh.adjustRightBearing(); if (lbh.checkFullOtherwiseExtend(line)) { + // we are too wide, fix right bearing + if (rightBearing <= 0) + lbh.rightBearing = rightBearing; // take from cache + else if (previousGlyph > 0) + lbh.adjustRightBearing(previousGlyph); if (!breakany) { line.textWidth += lbh.softHyphenWidth; } diff --git a/tests/auto/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp index f798faf..659ba1a 100644 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/qtextlayout/tst_qtextlayout.cpp @@ -122,6 +122,7 @@ private slots: void smallTextLengthWrapAtWordBoundaryOrAnywhere(); void testLineBreakingAllSpaces(); void lineWidthFromBOM(); + void textWidthVsWIdth(); private: @@ -1359,5 +1360,34 @@ void tst_QTextLayout::glyphLessItems() } } +void tst_QTextLayout::textWidthVsWIdth() +{ + QTextLayout layout; + QTextOption opt; + opt.setWrapMode(QTextOption::WrapAnywhere); + layout.setTextOption(opt); + layout.setText(QString::fromLatin1( + "g++ -c -m64 -pipe -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -W -D_REENTRANT -fPIC -DCORE_LIBRARY -DIDE_LIBRARY_BASENAME=\"lib\" -DWITH_TESTS " + "-DQT_NO_CAST_TO_ASCII -DQT_USE_FAST_OPERATOR_PLUS -DQT_USE_FAST_CONCATENATION -DQT_PLUGIN -DQT_TESTLIB_LIB -DQT_SCRIPT_LIB -DQT_SVG_LIB -DQT_SQL_LIB -DQT_XM" + "L_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../../qt-qml/mkspecs/linux-g++-64 -I. -I../../../../qt-qml/include/QtCore -I../../../." + "./qt-qml/include/QtNetwork -I../../../../qt-qml/include/QtGui -I../../../../qt-qml/include/QtXml -I../../../../qt-qml/include/QtSql -I../../../../qt-qml/inc" + "lude/QtSvg -I../../../../qt-qml/include/QtScript -I../../../../qt-qml/include/QtTest -I../../../../qt-qml/include -I../../../../qt-qml/include/QtHelp -I../." + "./libs -I/home/ettrich/dev/creator/tools -I../../plugins -I../../shared/scriptwrapper -I../../libs/3rdparty/botan/build -Idialogs -Iactionmanager -Ieditorma" + "nager -Iprogressmanager -Iscriptmanager -I.moc/debug-shared -I.uic -o .obj/debug-shared/sidebar.o sidebar.cpp")); + + // textWidth includes right bearing, but it should never be LARGER than width if there is space for at least one character + for (int width = 100; width < 1000; ++width) { + layout.beginLayout(); + QTextLine line = layout.createLine(); + line.setLineWidth(width); + layout.endLayout(); + + qreal textWidthIsLargerBy = qMax(qreal(0), line.naturalTextWidth() - line.width()); + qreal thisMustBeZero = 0; + QCOMPARE(textWidthIsLargerBy, thisMustBeZero); + } +} + + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" -- cgit v0.12