1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsgcurveglyphnode_p.h"
5#include "qsgcurveglyphatlas_p.h"
6#include "qsgcurvefillnode_p.h"
7#include "qsgcurvestrokenode_p.h"
8
9#include <private/qsgcurveabstractnode_p.h>
10#include <private/qsgcontext_p.h>
11#include <private/qsgtexturematerial_p.h>
12
13#include <private/qrawfont_p.h>
14#include <QtGui/qcolor.h>
15
16QT_BEGIN_NAMESPACE
17
18QSGCurveGlyphNode::QSGCurveGlyphNode(QSGRenderContext *context)
19 : m_context(context)
20 , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
21 , m_dirtyGeometry(false)
22{
23 setFlag(UsePreprocess);
24 setFlag(OwnsMaterial);
25
26 // #### To avoid asserts: we should probably merge this with QSGCurveFillNode
27 setGeometry(&m_geometry);
28 setMaterial(new QSGTextureMaterial);
29}
30
31QSGCurveGlyphNode::~QSGCurveGlyphNode()
32{
33}
34
35void QSGCurveGlyphNode::setPreferredAntialiasingMode(AntialiasingMode mode)
36{
37 Q_UNUSED(mode);
38}
39
40void QSGCurveGlyphNode::setColor(const QColor &color)
41{
42 m_color = color;
43 if (m_glyphNode != nullptr)
44 m_glyphNode->setColor(color);
45}
46
47void QSGCurveGlyphNode::setStyleColor(const QColor &styleColor)
48{
49 m_styleColor = styleColor;
50 if (m_styleNode != nullptr)
51 m_styleNode->setColor(styleColor);
52}
53
54void QSGCurveGlyphNode::setStyle(QQuickText::TextStyle style)
55{
56 if (m_style != style) {
57 m_style = style;
58 m_dirtyGeometry = true;
59 update();
60 }
61}
62
63void QSGCurveGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
64{
65 m_glyphs = glyphs;
66
67 QRawFont font = glyphs.rawFont();
68 m_fontSize = font.pixelSize();
69 m_position = QPointF(position.x(), position.y() - font.ascent());
70
71
72 m_dirtyGeometry = true;
73
74#ifdef QSG_RUNTIME_DESCRIPTION
75 qsgnode_set_description(node: this, description: QString::number(glyphs.glyphIndexes().count())
76 + QStringLiteral(" curve glyphs: ")
77 + m_glyphs.rawFont().familyName()
78 + QStringLiteral(" ")
79 + QString::number(m_glyphs.rawFont().pixelSize()));
80#endif
81}
82
83void QSGCurveGlyphNode::update()
84{
85 markDirty(bits: DirtyGeometry);
86}
87
88void QSGCurveGlyphNode::preprocess()
89{
90 if (m_dirtyGeometry)
91 updateGeometry();
92}
93
94void QSGCurveGlyphNode::updateGeometry()
95{
96 delete m_glyphNode;
97 m_glyphNode = nullptr;
98
99 delete m_styleNode;
100 m_styleNode = nullptr;
101
102 QSGCurveGlyphAtlas *curveGlyphAtlas = m_context->curveGlyphAtlas(font: m_glyphs.rawFont());
103 curveGlyphAtlas->populate(glyphs: m_glyphs.glyphIndexes());
104
105 m_glyphNode = new QSGCurveFillNode;
106 m_glyphNode->setColor(m_color);
107
108 QPointF offset;
109
110 float fontScale = float(m_fontSize / curveGlyphAtlas->fontSize());
111 QSGCurveFillNode *raisedSunkenStyleNode = nullptr;
112 QSGCurveStrokeNode *outlineNode = nullptr;
113 if (m_style == QQuickText::Raised || m_style == QQuickText::Sunken) {
114 raisedSunkenStyleNode = new QSGCurveFillNode;
115 raisedSunkenStyleNode ->setColor(m_styleColor);
116
117 offset = m_style == QQuickText::Raised ? QPointF(0.0f, 1.0f) : QPointF(0.0f, -1.0f);
118 m_styleNode = raisedSunkenStyleNode;
119 } else if (m_style == QQuickText::Outline) {
120 outlineNode = new QSGCurveStrokeNode;
121 outlineNode->setColor(m_styleColor);
122 outlineNode->setStrokeWidth(2 / fontScale);
123 outlineNode->setLocalScale(fontScale);
124
125 m_styleNode = outlineNode;
126 }
127
128 const QVector<quint32> indexes = m_glyphs.glyphIndexes();
129 const QVector<QPointF> positions = m_glyphs.positions();
130 for (qsizetype i = 0; i < indexes.size(); ++i) {
131 if (i == 0)
132 m_baseLine = positions.at(i);
133 curveGlyphAtlas->addGlyph(node: m_glyphNode,
134 glyph: indexes.at(i),
135 position: m_position + positions.at(i),
136 pixelSize: m_fontSize);
137 if (raisedSunkenStyleNode != nullptr) {
138 curveGlyphAtlas->addGlyph(node: raisedSunkenStyleNode,
139 glyph: indexes.at(i),
140 position: m_position + positions.at(i) + offset,
141 pixelSize: m_fontSize);
142 }
143 if (outlineNode != nullptr) {
144 // Since the stroke node will scale everything by fontScale internally (the
145 // shader does not support pre-transforming the vertices), we have to also first
146 // do the inverse scale on the glyph position to get the correct position.
147 curveGlyphAtlas->addStroke(node: outlineNode,
148 glyph: indexes.at(i),
149 position: (m_position + positions.at(i)) / fontScale);
150 }
151 }
152
153 if (m_styleNode != nullptr) {
154 m_styleNode->cookGeometry();
155 appendChildNode(node: m_styleNode);
156 }
157
158 m_glyphNode->cookGeometry();
159 appendChildNode(node: m_glyphNode);
160
161 m_dirtyGeometry = false;
162}
163
164QT_END_NAMESPACE
165

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdeclarative/src/quick/scenegraph/qsgcurveglyphnode.cpp