Improve underline drawing for fonts in QPainter
In the underline drawing code in QPainter there were some issues causing First of all, if an underline was very thick, then we would still just offset the drawing by 0.5 (as if it were 1 pixel wide) causing part of the underline to appear on top of the text. The shift here is intended to move the top edge of the underline to the top edge of the pixel where we want to draw it, so we need to offset it by half of the actual line thickness. In addition, fractional line widths look bad when drawn with aliased painting, which is the default. Depending on where the text would be, the thickness of a line might vary. Even if it's very close to an integer, e.g. 1.04 as in one case, then it will still sometimes fill two pixels if it happens to be placed directly between them. To ensure that we always fill the same number of pixels, we round the line thickness to nearest integer when antialiasing is not enabled. Pick-to: 6.8 Fixes: QTBUG-134626 Change-Id: I95bae3ac16010fc133995e5f9b6c2e5d022e3743 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> (cherry picked from commit 2b5533af920726723479557356f56d0778bcabd3) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
13aac36f69
commit
af31f1f2c3
@ -6039,11 +6039,16 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
|
||||
painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
|
||||
painter->restore();
|
||||
} else if (underlineStyle != QTextCharFormat::NoUnderline) {
|
||||
const bool isAntialiasing = painter->renderHints().testFlag(QPainter::Antialiasing);
|
||||
if (!isAntialiasing)
|
||||
pen.setWidthF(qMax(fe->lineThickness().round(), QFixed(1)).toReal());
|
||||
const qreal lineThicknessOffset = pen.widthF() / 2.0;
|
||||
|
||||
// Deliberately ceil the offset to avoid the underline coming too close to
|
||||
// the text above it, but limit it to stay within descent.
|
||||
qreal adjustedUnderlineOffset = std::ceil(underlineOffset) + 0.5;
|
||||
qreal adjustedUnderlineOffset = std::ceil(underlineOffset) + lineThicknessOffset;
|
||||
if (underlineOffset <= fe->descent().toReal())
|
||||
adjustedUnderlineOffset = qMin(adjustedUnderlineOffset, fe->descent().toReal() - qreal(0.5));
|
||||
adjustedUnderlineOffset = qMin(adjustedUnderlineOffset, fe->descent().toReal() - lineThicknessOffset);
|
||||
const qreal underlinePos = pos.y() + adjustedUnderlineOffset;
|
||||
QColor uc = charFormat.underlineColor();
|
||||
if (uc.isValid())
|
||||
@ -6056,6 +6061,9 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
|
||||
textEngine->addUnderline(painter, underline);
|
||||
else
|
||||
painter->drawLine(underline);
|
||||
|
||||
if (!isAntialiasing)
|
||||
pen.setWidthF(fe->lineThickness().toReal());
|
||||
}
|
||||
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
|
@ -8,7 +8,8 @@
|
||||
# Collect test data
|
||||
file(GLOB_RECURSE test_data_glob
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
scripts/*)
|
||||
scripts/*
|
||||
fonts/* )
|
||||
list(APPEND test_data ${test_data_glob})
|
||||
|
||||
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||
|
BIN
tests/baseline/painting/fonts/QtUnderlineTest-Regular.ttf
Normal file
BIN
tests/baseline/painting/fonts/QtUnderlineTest-Regular.ttf
Normal file
Binary file not shown.
BIN
tests/baseline/painting/fonts/QtUnderlineTest2-Regular.ttf
Normal file
BIN
tests/baseline/painting/fonts/QtUnderlineTest2-Regular.ttf
Normal file
Binary file not shown.
@ -196,4 +196,30 @@ save
|
||||
drawText 0 20 "All the effects text drawing"
|
||||
restore
|
||||
|
||||
translate 0 35
|
||||
save
|
||||
setPen black
|
||||
setFont "QtUnderlineTest" 20 normal normal default underline
|
||||
drawText 0 20 "1234"
|
||||
restore
|
||||
|
||||
translate 0 35.5
|
||||
save
|
||||
setPen black
|
||||
setFont "QtUnderlineTest2" 18 normal normal default underline
|
||||
drawText 0 20 "1234"
|
||||
restore
|
||||
|
||||
translate 0 35.5
|
||||
save
|
||||
setPen black
|
||||
setFont "QtUnderlineTest2" 12 normal normal default underline
|
||||
drawText 0 20 "1234"
|
||||
restore
|
||||
|
||||
translate 0 35.5
|
||||
save
|
||||
setPen black
|
||||
setFont "QtUnderlineTest2" 12 normal normal default underline
|
||||
drawText 0 20 "1234"
|
||||
restore
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <QOpenGLPaintDevice>
|
||||
#endif
|
||||
|
||||
#include <QFontDatabase>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef GL_RGB10
|
||||
@ -129,6 +131,16 @@ void tst_Lancelot::initTestCase()
|
||||
scriptChecksums.insert(fileName, qChecksum(cont));
|
||||
}
|
||||
|
||||
QString underlineTestFont1 = QFINDTESTDATA("fonts/QtUnderlineTest-Regular.ttf");
|
||||
QVERIFY(!underlineTestFont1.isEmpty());
|
||||
int id = QFontDatabase::addApplicationFont(underlineTestFont1);
|
||||
QVERIFY(id >= 0);
|
||||
|
||||
QString underlineTestFont2 = QFINDTESTDATA("fonts/QtUnderlineTest2-Regular.ttf");
|
||||
QVERIFY(!underlineTestFont2.isEmpty());
|
||||
id = QFontDatabase::addApplicationFont(underlineTestFont2);
|
||||
QVERIFY(id >= 0);
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
initOpenGL();
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user