Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgdefaultglyphnode.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
7
8#include <private/qrawfont_p.h>
9
11
12QSGDefaultGlyphNode::QSGDefaultGlyphNode(QSGRenderContext *context)
13 : m_context(context)
14 , m_glyphNodeType(RootGlyphNode)
15 , m_dirtyGeometry(false)
16 , m_preferredAntialiasingMode(DefaultAntialiasing)
17{
18 setFlag(UsePreprocess);
19}
20
21QSGDefaultGlyphNode::~QSGDefaultGlyphNode()
22{
23 if (m_glyphNodeType == SubGlyphNode)
24 return;
25
26 qDeleteAll(m_nodesToDelete);
27 m_nodesToDelete.clear();
28}
29
30void QSGDefaultGlyphNode::setPreferredAntialiasingMode(AntialiasingMode mode)
31{
32 m_preferredAntialiasingMode = mode;
33}
34
35void QSGDefaultGlyphNode::setMaterialColor(const QColor &color)
36{
37 static_cast<QSGTextMaskMaterial *>(m_material)->setColor(color);
38}
39
40void QSGDefaultGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
41{
42 QSGBasicGlyphNode::setGlyphs(position, glyphs);
43 m_dirtyGeometry = true;
44}
45
46void QSGDefaultGlyphNode::update()
47{
48 QRawFont font = m_glyphs.rawFont();
49 QMargins margins(0, 0, 0, 0);
50
51 const auto *fontEngine = QRawFontPrivate::get(font)->fontEngine;
52 const bool isColorFont = fontEngine->glyphFormat == QFontEngine::Format_ARGB;
53
54 if (m_style == QQuickText::Normal || isColorFont) {
55 QFontEngine::GlyphFormat glyphFormat;
56
57 // Don't try to override glyph format of color fonts
58 if (isColorFont) {
59 glyphFormat = QFontEngine::Format_None;
60 } else {
61 switch (m_preferredAntialiasingMode) {
62 case GrayAntialiasing:
63 glyphFormat = QFontEngine::Format_A8;
64 break;
65 case HighQualitySubPixelAntialiasing:
66 case LowQualitySubPixelAntialiasing:
67 glyphFormat = QFontEngine::Format_A32;
68 break;
69 default:
70 glyphFormat = QFontEngine::Format_None;
71 break;
72 }
73 }
74
75 const auto rgbColor = m_color.toRgb();
76 m_material = new QSGTextMaskMaterial(m_context, QVector4D(rgbColor.redF(), rgbColor.greenF(), rgbColor.blueF(), rgbColor.alphaF()), font, glyphFormat);
77 } else if (m_style == QQuickText::Outline) {
78 QSGOutlinedTextMaterial *material = new QSGOutlinedTextMaterial(m_context, font);
79 material->setStyleColor(m_styleColor);
80 m_material = material;
81 margins = QMargins(1, 1, 1, 1);
82 } else {
83 QSGStyledTextMaterial *material = new QSGStyledTextMaterial(m_context, font);
84 if (m_style == QQuickText::Sunken) {
85 material->setStyleShift(QVector2D(0, -1));
86 margins.setTop(1);
87 } else if (m_style == QQuickText::Raised) {
88 material->setStyleShift(QVector2D(0, 1));
89 margins.setBottom(1);
90 }
91 material->setStyleColor(m_styleColor);
92 m_material = material;
93 }
94
95 QSGTextMaskMaterial *textMaskMaterial = static_cast<QSGTextMaskMaterial *>(m_material);
96 textMaskMaterial->setColor(m_color);
97
98 QRectF boundingRect;
99 textMaskMaterial->populate(m_position, m_glyphs.glyphIndexes(), m_glyphs.positions(), geometry(),
100 &boundingRect, &m_baseLine, margins);
101 setBoundingRect(boundingRect);
102
103 setMaterial(m_material);
104 markDirty(DirtyGeometry);
105}
106
107void QSGDefaultGlyphNode::preprocess()
108{
109 qDeleteAll(m_nodesToDelete);
110 m_nodesToDelete.clear();
111
112 if (m_dirtyGeometry)
113 updateGeometry();
114}
115
116void QSGDefaultGlyphNode::updateGeometry()
117{
118 // Remove previously created sub glyph nodes
119 // We assume all the children are sub glyph nodes
120 QSGNode *subnode = firstChild();
121 while (subnode) {
122 // We can't delete the node now as it might be in the preprocess list
123 // It will be deleted in the next preprocess
124 m_nodesToDelete.append(subnode);
125 subnode = subnode->nextSibling();
126 }
127 removeAllChildNodes();
128
129 GlyphInfo glyphInfo;
130
131 const QList<quint32> indexes = m_glyphs.glyphIndexes();
132 const QList<QPointF> positions = m_glyphs.positions();
133
134 const int maxGlyphs = (USHRT_MAX + 1) / 4; // 16384
135 const int maxVertices = maxGlyphs * 4; // 65536
136 const int maxIndexes = maxGlyphs * 6; // 98304
137
138 for (int i = 0; i < indexes.size(); ++i) {
139 const int glyphIndex = indexes.at(i);
140 const QPointF position = positions.at(i);
141
142 // As we use UNSIGNED_SHORT indexing in the geometry, we overload the
143 // "glyphsInOtherNodes" concept as overflow for if there are more than
144 // 65536 (16384 * 4) vertices to render which would otherwise exceed
145 // the maximum index size. This will cause sub-nodes to be recursively
146 // created to handle any number of glyphs.
147 if (i >= maxGlyphs) {
148 glyphInfo.indexes.append(glyphIndex);
149 glyphInfo.positions.append(position);
150 continue;
151 }
152 }
153
154 if (!glyphInfo.indexes.isEmpty()) {
155 QGlyphRun subNodeGlyphRun(m_glyphs);
156 subNodeGlyphRun.setGlyphIndexes(glyphInfo.indexes);
157 subNodeGlyphRun.setPositions(glyphInfo.positions);
158
159 QSGDefaultGlyphNode *subNode = new QSGDefaultGlyphNode(m_context);
160 subNode->setGlyphNodeType(SubGlyphNode);
161 subNode->setColor(m_color);
162 subNode->setStyle(m_style);
163 subNode->setStyleColor(m_styleColor);
164 subNode->setGlyphs(m_position, subNodeGlyphRun);
165 subNode->update();
166 subNode->updateGeometry(); // we have to explicitly call this now as preprocess won't be called before it's rendered
167 appendChildNode(subNode);
168
169 QSGGeometry *g = geometry();
170
171 QSGGeometry::TexturedPoint2D *vertexData = g->vertexDataAsTexturedPoint2D();
172 quint16 *indexData = g->indexDataAsUShort();
173
174 QList<QSGGeometry::TexturedPoint2D> tempVertexData(maxVertices);
175 QList<quint16> tempIndexData(maxIndexes);
176
177 for (int i = 0; i < maxGlyphs; i++) {
178 tempVertexData[i * 4 + 0] = vertexData[i * 4 + 0];
179 tempVertexData[i * 4 + 1] = vertexData[i * 4 + 1];
180 tempVertexData[i * 4 + 2] = vertexData[i * 4 + 2];
181 tempVertexData[i * 4 + 3] = vertexData[i * 4 + 3];
182
183 tempIndexData[i * 6 + 0] = indexData[i * 6 + 0];
184 tempIndexData[i * 6 + 1] = indexData[i * 6 + 1];
185 tempIndexData[i * 6 + 2] = indexData[i * 6 + 2];
186 tempIndexData[i * 6 + 3] = indexData[i * 6 + 3];
187 tempIndexData[i * 6 + 4] = indexData[i * 6 + 4];
188 tempIndexData[i * 6 + 5] = indexData[i * 6 + 5];
189 }
190
191 g->allocate(maxVertices, maxIndexes);
192 vertexData = g->vertexDataAsTexturedPoint2D();
193 indexData = g->indexDataAsUShort();
194
195 for (int i = 0; i < maxGlyphs; i++) {
196 vertexData[i * 4 + 0] = tempVertexData[i * 4 + 0];
197 vertexData[i * 4 + 1] = tempVertexData[i * 4 + 1];
198 vertexData[i * 4 + 2] = tempVertexData[i * 4 + 2];
199 vertexData[i * 4 + 3] = tempVertexData[i * 4 + 3];
200
201 indexData[i * 6 + 0] = tempIndexData[i * 6 + 0];
202 indexData[i * 6 + 1] = tempIndexData[i * 6 + 1];
203 indexData[i * 6 + 2] = tempIndexData[i * 6 + 2];
204 indexData[i * 6 + 3] = tempIndexData[i * 6 + 3];
205 indexData[i * 6 + 4] = tempIndexData[i * 6 + 4];
206 indexData[i * 6 + 5] = tempIndexData[i * 6 + 5];
207 }
208 }
209
210 m_dirtyGeometry = false;
211}
212
213QT_END_NAMESPACE
\inmodule QtCore
Definition qmargins.h:27
constexpr void setTop(int top) noexcept
Sets the Top margin to Top.
Definition qmargins.h:148
constexpr void setBottom(int bottom) noexcept
Sets the bottom margin to bottom.
Definition qmargins.h:154
constexpr QMargins(int left, int top, int right, int bottom) noexcept
Constructs margins with the given left, top, right, and bottom.
Definition qmargins.h:126
The QRawFont class provides access to a single physical instance of a font.
Definition qrawfont.h:24
\inmodule QtQuick
void setStyleColor(const QColor &c)
void setColor(const QColor &c)
Combined button and popup list for selecting options.