Improvements to curly underline

This commit tried to improves the look of curly underline implemented
in 5ab23a96 by replacing arcs with quadratic Bezier curves. The
performance of the render is mostly unaltered.

Enabling antialiasing provides an even better result, but the
performance impact is too relevant.
This commit is contained in:
Luca Carlon
2025-09-19 19:27:30 +02:00
parent 82799b4be8
commit 4522bfae90

View File

@@ -24,6 +24,7 @@
#include <QDebug> #include <QDebug>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
#include <QPen> #include <QPen>
#include <QRect> #include <QRect>
#include <QRegion> #include <QRegion>
@@ -915,24 +916,30 @@ void TerminalPainter::drawAboveText(QPainter &painter,
painter.drawLine(QLineF(x1, y, x2, y)); painter.drawLine(QLineF(x1, y, x2, y));
if (underline == RE_UNDERLINE_DOUBLE || underline == RE_UNDERLINE_CURL) { if (underline == RE_UNDERLINE_DOUBLE || underline == RE_UNDERLINE_CURL) {
const int fontHeight = m_parentDisplay->terminalFont()->fontHeight(); const int fontHeight = m_parentDisplay->terminalFont()->fontHeight();
const int amplitude = fontHeight / 8; const qreal amplitude = fontHeight / 8;
if (underline == RE_UNDERLINE_DOUBLE) { if (underline == RE_UNDERLINE_DOUBLE) {
if (amplitude) if (amplitude)
painter.drawLine(x1, y - amplitude, x2, y - amplitude); painter.drawLine(x1, y - amplitude, x2, y - amplitude);
} else { } else {
y = std::max(static_cast<qreal>(0), y - amplitude); y = std::max(static_cast<qreal>(0), y - amplitude / 2);
assert(underline == RE_UNDERLINE_CURL); assert(underline == RE_UNDERLINE_CURL);
const int len = x2 - x1; const int len = x2 - x1;
if (len > 0) { if (len > 0) {
const int halfPeriodsPerGlyph = 2; const qreal desiredWavelength = fontWidth / 1.2;
const int numHalfPeriods = len * halfPeriodsPerGlyph / fontWidth; const int cycles = std::max(1, static_cast<int>(len / desiredWavelength));
for (int j = 0; j < numHalfPeriods; j++) { const qreal wavelength = static_cast<qreal>(len) / cycles;
const int begin = j * len / numHalfPeriods; const qreal halfWavelength = wavelength / 2.0;
const int end = (j + 1) * len / numHalfPeriods; const qreal quarterWavelength = halfWavelength / 2.0;
const qreal angle1 = 0.0; const qreal threeQuarterWavelength = 3 * quarterWavelength;
const qreal angle2 = 360.0 * 16.0 * ((j % 2 == 0) ? 0.5 : -0.5); QPainterPath segment;
painter.drawArc(x1 + begin, y, end-begin, amplitude, angle1, angle2); segment.moveTo(0, 0);
} segment.quadTo(quarterWavelength, -amplitude, halfWavelength, 0);
segment.quadTo(threeQuarterWavelength, amplitude, wavelength, 0);
QPainterPath path;
path.moveTo(x1, y);
for (int i = 0; i < cycles; ++i)
path.addPath(segment.translated(x1 + i * wavelength, y));
painter.drawPath(path);
} }
} }
} }