diff options
Diffstat (limited to 'src/quick/scenegraph/qsgcurveglyphnode.cpp')
-rw-r--r-- | src/quick/scenegraph/qsgcurveglyphnode.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/quick/scenegraph/qsgcurveglyphnode.cpp b/src/quick/scenegraph/qsgcurveglyphnode.cpp new file mode 100644 index 0000000000..c5252083d3 --- /dev/null +++ b/src/quick/scenegraph/qsgcurveglyphnode.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qsgcurveglyphnode_p.h" +#include "qsgcurveglyphatlas_p.h" +#include "qsgcurvefillnode_p.h" +#include "qsgcurvestrokenode_p.h" + +#include <private/qsgcurveabstractnode_p.h> +#include <private/qsgcontext_p.h> +#include <private/qsgtexturematerial_p.h> + +#include <private/qrawfont_p.h> +#include <QtGui/qcolor.h> + +QT_BEGIN_NAMESPACE + +QSGCurveGlyphNode::QSGCurveGlyphNode(QSGRenderContext *context) + : m_context(context) + , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0) + , m_dirtyGeometry(false) +{ + setFlag(UsePreprocess); + setFlag(OwnsMaterial); + + // #### To avoid asserts: we should probably merge this with QSGCurveFillNode + setGeometry(&m_geometry); + setMaterial(new QSGTextureMaterial); +} + +QSGCurveGlyphNode::~QSGCurveGlyphNode() +{ +} + +void QSGCurveGlyphNode::setPreferredAntialiasingMode(AntialiasingMode mode) +{ + Q_UNUSED(mode); +} + +void QSGCurveGlyphNode::setColor(const QColor &color) +{ + m_color = color; + if (m_glyphNode != nullptr) + m_glyphNode->setColor(color); +} + +void QSGCurveGlyphNode::setStyleColor(const QColor &styleColor) +{ + m_styleColor = styleColor; + if (m_styleNode != nullptr) + m_styleNode->setColor(styleColor); +} + +void QSGCurveGlyphNode::setStyle(QQuickText::TextStyle style) +{ + if (m_style != style) { + m_style = style; + m_dirtyGeometry = true; + update(); + } +} + +void QSGCurveGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs) +{ + m_glyphs = glyphs; + + QRawFont font = glyphs.rawFont(); + m_fontSize = font.pixelSize(); + m_position = QPointF(position.x(), position.y() - font.ascent()); + + + m_dirtyGeometry = true; + +#ifdef QSG_RUNTIME_DESCRIPTION + qsgnode_set_description(this, QString::number(glyphs.glyphIndexes().count()) + + QStringLiteral(" curve glyphs: ") + + m_glyphs.rawFont().familyName() + + QStringLiteral(" ") + + QString::number(m_glyphs.rawFont().pixelSize())); +#endif +} + +void QSGCurveGlyphNode::update() +{ + markDirty(DirtyGeometry); +} + +void QSGCurveGlyphNode::preprocess() +{ + if (m_dirtyGeometry) + updateGeometry(); +} + +void QSGCurveGlyphNode::updateGeometry() +{ + delete m_glyphNode; + m_glyphNode = nullptr; + + delete m_styleNode; + m_styleNode = nullptr; + + QSGCurveGlyphAtlas *curveGlyphAtlas = m_context->curveGlyphAtlas(m_glyphs.rawFont()); + curveGlyphAtlas->populate(m_glyphs.glyphIndexes()); + + m_glyphNode = new QSGCurveFillNode; + m_glyphNode->setColor(m_color); + + QPointF offset; + + float fontScale = float(m_fontSize / curveGlyphAtlas->fontSize()); + QSGCurveFillNode *raisedSunkenStyleNode = nullptr; + QSGCurveStrokeNode *outlineNode = nullptr; + if (m_style == QQuickText::Raised || m_style == QQuickText::Sunken) { + raisedSunkenStyleNode = new QSGCurveFillNode; + raisedSunkenStyleNode ->setColor(m_styleColor); + + offset = m_style == QQuickText::Raised ? QPointF(0.0f, 1.0f) : QPointF(0.0f, -1.0f); + m_styleNode = raisedSunkenStyleNode; + } else if (m_style == QQuickText::Outline) { + outlineNode = new QSGCurveStrokeNode; + outlineNode->setColor(m_styleColor); + outlineNode->setStrokeWidth(2 / fontScale); + outlineNode->setLocalScale(fontScale); + + m_styleNode = outlineNode; + } + + const QVector<quint32> indexes = m_glyphs.glyphIndexes(); + const QVector<QPointF> positions = m_glyphs.positions(); + for (qsizetype i = 0; i < indexes.size(); ++i) { + if (i == 0) + m_baseLine = positions.at(i); + curveGlyphAtlas->addGlyph(m_glyphNode, + indexes.at(i), + m_position + positions.at(i), + m_fontSize); + if (raisedSunkenStyleNode != nullptr) { + curveGlyphAtlas->addGlyph(raisedSunkenStyleNode, + indexes.at(i), + m_position + positions.at(i) + offset, + m_fontSize); + } + if (outlineNode != nullptr) { + // Since the stroke node will scale everything by fontScale internally (the + // shader does not support pre-transforming the vertices), we have to also first + // do the inverse scale on the glyph position to get the correct position. + curveGlyphAtlas->addStroke(outlineNode, + indexes.at(i), + (m_position + positions.at(i)) / fontScale); + } + } + + if (m_styleNode != nullptr) { + m_styleNode->cookGeometry(); + appendChildNode(m_styleNode); + } + + m_glyphNode->cookGeometry(); + appendChildNode(m_glyphNode); + + m_dirtyGeometry = false; +} + +QT_END_NAMESPACE |