diff options
| author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2023-11-09 09:38:00 +0100 |
|---|---|---|
| committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2023-11-15 07:57:48 +0100 |
| commit | d0cb311e0d3cd84c933bd993e6003f45be2ebdd8 (patch) | |
| tree | 965463aaef3922f88c3c44e8f77e5df9fc144136 /src | |
| parent | 6403d52d790b791a858663678c1e5de3dcf8f4df (diff) | |
Fix thin text decoration with fractional scaling
With fractional scales, 1 pixel thin underlines and other
text decoration get a lot of aliasing effects. Sometimes
it will disappear completely and other times it will
fill two pixels. The rendering depends on the fractional
position of the line, so any change that moves the text
may cause the line to render at a different width, causing
instability when resizing layouts for instance.
We were using rectangle nodes for this for convenience, but
even with antialiasing enabled, that does not look correct
for single-pixel lines. Instead, we use the new curve renderer
which can also draw nice antialiased straight lines.
Fixes: QTBUG-86977
Change-Id: I1367b1e2d25d167fac7d6284cb40a652ef4c3e9a
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/quick/items/qquicktextnodeengine.cpp | 2 | ||||
| -rw-r--r-- | src/quick/items/qsginternaltextnode.cpp | 27 | ||||
| -rw-r--r-- | src/quick/items/qsginternaltextnode_p.h | 1 |
3 files changed, 29 insertions, 1 deletions
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index cc69c96720..be6e01df1f 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -801,7 +801,7 @@ void QQuickTextNodeEngine::addToSceneGraph(QSGInternalTextNode *parentNode, ? m_selectedTextColor : textDecoration.color; - parentNode->addRectangleNode(textDecoration.rect, color); + parentNode->addDecorationNode(textDecoration.rect, color); } // Finally add the selected text on top of everything diff --git a/src/quick/items/qsginternaltextnode.cpp b/src/quick/items/qsginternaltextnode.cpp index c9200e1e3d..7a82f24a29 100644 --- a/src/quick/items/qsginternaltextnode.cpp +++ b/src/quick/items/qsginternaltextnode.cpp @@ -23,6 +23,10 @@ #include <private/qtextdocumentlayout_p.h> #include <qhash.h> +#include <private/qsgcurvefillnode_p.h> +#include <private/qsgcurvestrokenode_p.h> +#include <private/qsgcurveprocessor_p.h> + QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcVP) @@ -123,6 +127,29 @@ void QSGInternalTextNode::clearCursor() m_cursorNode = nullptr; } +void QSGInternalTextNode::addDecorationNode(const QRectF &rect, const QColor &color) +{ + QSGCurveStrokeNode *node = new QSGCurveStrokeNode; + node->setColor(color); + node->setStrokeWidth(rect.height()); + + QQuadPath path; + QPointF c = rect.center(); + path.moveTo(QVector2D(rect.left(), c.y())); + path.lineTo(QVector2D(rect.right(), c.y())); + + QSGCurveProcessor::processStroke(path, 2, rect.height(), Qt::MiterJoin, Qt::FlatCap, + [&node](const std::array<QVector2D, 3> &s, + const std::array<QVector2D, 3> &p, + const std::array<QVector2D, 3> &n, + bool isLine) { + Q_ASSERT(isLine); + node->appendTriangle(s, std::array<QVector2D, 2>{p.at(0), p.at(2)}, n); + }); + node->cookGeometry(); + appendChildNode(node); +} + void QSGInternalTextNode::addRectangleNode(const QRectF &rect, const QColor &color) { appendChildNode(m_renderContext->sceneGraphContext()->createInternalRectangleNode(rect, color)); diff --git a/src/quick/items/qsginternaltextnode_p.h b/src/quick/items/qsginternaltextnode_p.h index 082129c76e..d0bf52d09c 100644 --- a/src/quick/items/qsginternaltextnode_p.h +++ b/src/quick/items/qsginternaltextnode_p.h @@ -156,6 +156,7 @@ public: void clearCursor(); void addRectangleNode(const QRectF &rect, const QColor &color); + void addDecorationNode(const QRectF &rect, const QColor &color); void addImage(const QRectF &rect, const QImage &image); void deleteContent(); QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color, |
