106 QRawFont font = glyphs.rawFont();
107 m_originalPosition = position;
108 m_position = QPointF(position.x(), position.y() - font.ascent());
111 m_dirtyGeometry =
true;
112 m_dirtyMaterial =
true;
113 setFlag(UsePreprocess);
115 QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
116 m_glyph_cache = m_context->distanceFieldGlyphCache(m_glyphs.rawFont(), m_renderTypeQuality);
118 if (m_glyphNodeType == SubGlyphNode)
121 if (m_glyph_cache != oldCache) {
123 oldCache->unregisterGlyphNode(
this);
126 m_glyph_cache->registerGlyphNode(
this);
129 m_glyph_cache->populate(glyphs.glyphIndexes());
131 const QList<quint32> glyphIndexes = m_glyphs.glyphIndexes();
132 for (
int i = 0; i < glyphIndexes.size(); ++i)
133 m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
134 qCDebug(lcSgText,
"inserting %" PRIdQSIZETYPE
" glyphs, %" PRIdQSIZETYPE
" unique",
136 m_allGlyphIndexesLookup.size());
137#ifdef QSG_RUNTIME_DESCRIPTION
138 qsgnode_set_description(
this, QString::number(glyphs.glyphIndexes().count()) + QStringLiteral(
" DF glyphs: ") +
139 m_glyphs.rawFont().familyName() + QStringLiteral(
" ") + QString::number(m_glyphs.rawFont().pixelSize()));
194 QSGNode *subnode = firstChild();
195 QSGNode *nextNode =
nullptr;
197 nextNode = subnode->nextSibling();
202 QSGGeometry *g = geometry();
204 Q_ASSERT(g->indexType() == QSGGeometry::UnsignedShortType);
205 m_glyphsInOtherTextures.clear();
207 const QList<quint32> indexes = m_glyphs.glyphIndexes();
208 const QList<QPointF> positions = m_glyphs.positions();
209 qreal fontPixelSize = m_glyphs.rawFont().pixelSize();
213 QVarLengthArray<QSGGeometry::TexturedPoint2D, 256> vp;
214 QVarLengthArray<ushort, 384> ip;
215 const qsizetype maxIndexCount = (std::numeric_limits<quint16>::max() - 1) / 4;
216 const qsizetype maxVertexCount = maxIndexCount * 4;
217 const auto likelyGlyphCount = qMin(indexes.size(), maxIndexCount);
218 vp.reserve(likelyGlyphCount * 4);
219 ip.reserve(likelyGlyphCount * 6);
221 qreal maxTexMargin = m_glyph_cache->distanceFieldRadius();
222 qreal fontScale = m_glyph_cache->fontScale(fontPixelSize);
224 qreal texMargin = margin / fontScale;
225 if (texMargin > maxTexMargin) {
226 texMargin = maxTexMargin;
227 margin = maxTexMargin * fontScale;
230 for (
int i = 0; i < indexes.size(); ++i) {
231 const int glyphIndex = indexes.at(i);
232 QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
237 const QPointF position = positions.at(i);
239 const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex);
240 if (texture->texture && !m_texture)
252 if (m_texture != texture || vp.size() >= maxVertexCount) {
253 if (m_glyphNodeType == RootGlyphNode && texture->texture) {
254 GlyphInfo &glyphInfo = m_glyphsInOtherTextures[texture];
255 glyphInfo.indexes.append(glyphIndex);
256 glyphInfo.positions.append(position);
257 }
else if (vp.size() >= maxVertexCount && m_glyphNodeType == SubGlyphNode) {
263 QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex, fontPixelSize);
265 if (!metrics.isNull() && !c.isNull()) {
266 metrics.width += margin * 2;
267 metrics.height += margin * 2;
268 metrics.baselineX -= margin;
269 metrics.baselineY += margin;
270 c.xMargin -= texMargin;
271 c.yMargin -= texMargin;
272 c.width += texMargin * 2;
273 c.height += texMargin * 2;
276 qreal x = position.x() + metrics.baselineX + m_position.x();
277 qreal y = position.y() - metrics.baselineY + m_position.y();
279 m_boundingRect |= QRectF(x, y, metrics.width, metrics.height);
282 float cx2 = x + metrics.width;
284 float cy2 = y + metrics.height;
286 float tx1 = c.x + c.xMargin;
287 float tx2 = tx1 + c.width;
288 float ty1 = c.y + c.yMargin;
289 float ty2 = ty1 + c.height;
291 if (m_baseLine.isNull())
292 m_baseLine = position;
296 QSGGeometry::TexturedPoint2D v1;
297 v1.set(cx1, cy1, tx1, ty1);
298 QSGGeometry::TexturedPoint2D v2;
299 v2.set(cx2, cy1, tx2, ty1);
300 QSGGeometry::TexturedPoint2D v3;
301 v3.set(cx1, cy2, tx1, ty2);
302 QSGGeometry::TexturedPoint2D v4;
303 v4.set(cx2, cy2, tx2, ty2);
317 if (m_glyphNodeType == SubGlyphNode) {
318 Q_ASSERT(m_glyphsInOtherTextures.isEmpty());
320 if (!m_glyphsInOtherTextures.isEmpty())
321 qCDebug(lcSgText,
"%" PRIdQSIZETYPE
" 'other' textures", m_glyphsInOtherTextures.size());
322 QHash<
const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = m_glyphsInOtherTextures.constBegin();
323 while (ite != m_glyphsInOtherTextures.constEnd()) {
324 QGlyphRun subNodeGlyphRun(m_glyphs);
325 for (
int i = 0; i < ite->indexes.size(); i += maxIndexCount) {
326 int len = qMin(maxIndexCount, ite->indexes.size() - i);
327 subNodeGlyphRun.setRawData(ite->indexes.constData() + i, ite->positions.constData() + i, len);
328 qCDebug(lcSgText) <<
"subNodeGlyphRun has" << len <<
"positions:"
329 << *(ite->positions.constData() + i) <<
"->" << *(ite->positions.constData() + i + len - 1);
332 subNode->setGlyphNodeType(SubGlyphNode);
333 subNode->setColor(m_color);
334 subNode->setStyle(m_style);
335 subNode->setStyleColor(m_styleColor);
336 subNode->setPreferredAntialiasingMode(m_antialiasingMode);
337 subNode->setGlyphs(m_originalPosition, subNodeGlyphRun);
340 appendChildNode(subNode);
346 s_totalAllocation += vp.size() *
sizeof(QSGGeometry::TexturedPoint2D) + ip.size() *
sizeof(quint16);
347 qCDebug(lcSgText) <<
"allocating for" << vp.size() <<
"vtx (reserved" << likelyGlyphCount * 4 <<
"):" << vp.size() *
sizeof(QSGGeometry::TexturedPoint2D)
348 <<
"bytes;" << ip.size() <<
"idx:" << ip.size() *
sizeof(quint16) <<
"bytes; total bytes so far" << s_totalAllocation;
349 g->allocate(vp.size(), ip.size());
350 memcpy(g->vertexDataAsTexturedPoint2D(), vp.constData(), vp.size() *
sizeof(QSGGeometry::TexturedPoint2D));
351 memcpy(g->indexDataAsUShort(), ip.constData(), ip.size() *
sizeof(quint16));
353 setBoundingRect(m_boundingRect);
354 markDirty(DirtyGeometry);
355 m_dirtyGeometry =
false;
357 m_material->setTexture(m_texture);