6#include "QskPlainTextRenderer.h"
7#include "QskTextColors.h"
8#include "QskTextOptions.h"
10#include <qfontmetrics.h>
15#include <private/qquickitem_p.h>
18#define GlyphFlag static_cast< QSGNode::Flag >( 0x800 )
20QSizeF QskPlainTextRenderer::textSize(
21 const QString& text,
const QFont& font,
const QskTextOptions& options )
24 return textRect( text, font, options, QSizeF( 10e6, 10e6 ) ).size();
27QRectF QskPlainTextRenderer::textRect(
28 const QString& text,
const QFont& font,
const QskTextOptions& options,
31 const QFontMetricsF fm( font );
32 const QRectF r( 0, 0, size.width(), size.height() );
34 return fm.boundingRect( r, options.textFlags(), text );
37static qreal qskLayoutText( QTextLayout* layout,
40 if ( layout->text().isEmpty() )
45 const auto elideMode = options.effectiveElideMode();
47 if ( elideMode == Qt::ElideNone )
49 for (
int i = 0; i < options.maximumLineCount(); i++ )
51 auto line = layout->createLine();
52 if ( !line.isValid() )
55 line.setPosition( QPointF( 0, y ) );
56 line.setLineWidth( lineWidth );
58 y += line.leading() + line.height();
63 const auto engine = layout->engine();
65 auto text = engine->elidedText(
66 elideMode, QFixed::fromReal( lineWidth ),
67 Qt::TextShowMnemonic, 0 );
70 text = text.leftJustified( engine->text.length() );
73 auto line = layout->createLine();
83 auto option = layout->textOption();
84 option.setWrapMode( QTextOption::WrapAnywhere );
85 layout->setTextOption( option );
87 line.setPosition( QPointF( 0, y ) );
88 line.setLineWidth( lineWidth );
90 y += line.leading() + line.height();
97static void qskRenderText(
98 QQuickItem* item, QSGNode* parentNode,
const QTextLayout& layout, qreal baseLine,
99 const QColor& color, QQuickText::TextStyle style,
const QColor& styleColor )
101 auto renderContext = QQuickItemPrivate::get(item)->sceneGraphRenderContext();
102 auto sgContext = renderContext->sceneGraphContext();
105 QSGNode* node = parentNode->firstChild();
108 auto sibling = node->nextSibling();
109 if ( !( node->flags() & GlyphFlag ) )
111 parentNode->removeChildNode( node );
117 auto glyphNode =
static_cast< QSGGlyphNode*
>( parentNode->firstChild() );
119 const QPointF position( 0, baseLine );
121 for (
int i = 0; i < layout.lineCount(); ++i )
123 const auto glyphRuns = layout.lineAt( i ).glyphRuns();
125 for (
const auto& glyphRun : glyphRuns )
127 if ( glyphNode ==
nullptr )
129 const bool preferNativeGlyphNode =
false;
130 constexpr int renderQuality = -1;
132#if QT_VERSION >= QT_VERSION_CHECK( 6, 7, 0 )
133 const auto renderType = preferNativeGlyphNode
134 ? QSGTextNode::QtRendering : QSGTextNode::NativeRendering;
135 glyphNode = sgContext->createGlyphNode(
136 renderContext, renderType, renderQuality );
137#elif QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
138 glyphNode = sgContext->createGlyphNode(
139 renderContext, preferNativeGlyphNode, renderQuality );
141 Q_UNUSED( renderQuality );
142 glyphNode = sgContext->createGlyphNode(
143 renderContext, preferNativeGlyphNode );
146#if QT_VERSION < QT_VERSION_CHECK( 6, 7, 0 )
147 glyphNode->setOwnerElement( item );
150 glyphNode->setFlags( QSGNode::OwnedByParent | GlyphFlag );
153 glyphNode->setStyle( style );
154 glyphNode->setColor( color );
155 glyphNode->setStyleColor( styleColor );
156 glyphNode->setGlyphs( position, glyphRun );
159 if ( glyphNode->parent() != parentNode )
160 parentNode->appendChildNode( glyphNode );
162 glyphNode =
static_cast< QSGGlyphNode*
>( glyphNode->nextSibling() );
169 auto sibling = glyphNode->nextSibling();
170 if ( glyphNode->flags() & GlyphFlag )
172 parentNode->removeChildNode( glyphNode );
175 glyphNode =
static_cast< QSGGlyphNode*
>( sibling );
179void QskPlainTextRenderer::updateNode(
const QString& text,
182 Qt::Alignment alignment,
const QRectF& rect,
183 const QQuickItem* item, QSGTransformNode* node )
185 QTextOption textOption( alignment );
186 textOption.setWrapMode(
static_cast< QTextOption::WrapMode
>( options.wrapMode() ) );
191 const int pos = tmp.indexOf( QLatin1Char(
'\x9c' ) );
196 tmp = tmp.mid( 0, pos );
197 tmp.replace( QLatin1Char(
'\n' ), QChar::LineSeparator );
201 if ( tmp.contains( QLatin1Char(
'\n' ) ) )
203 tmp.replace( QLatin1Char(
'\n'), QChar::LineSeparator );
208 layout.setFont( font );
209 layout.setTextOption( textOption );
210 layout.setText( tmp );
212 layout.beginLayout();
213 const qreal textHeight = qskLayoutText( &layout, rect.width(), options );
216 const qreal y0 = QFontMetricsF( font ).ascent();
218 qreal yBaseline = y0;
220 if ( alignment & Qt::AlignVCenter )
222 yBaseline += ( rect.height() - textHeight ) * 0.5;
224 else if ( alignment & Qt::AlignBottom )
226 yBaseline += rect.height() - textHeight;
229 if ( yBaseline != y0 )
237 const int bh = int( layout.boundingRect().height() );
238 yBaseline = ( bh % 2 ) ? qFloor( yBaseline ) : qCeil( yBaseline );
242 const_cast< QQuickItem*
>( item ), node, layout, yBaseline,
243 colors.textColor,
static_cast< QQuickText::TextStyle
>( style ),
247void QskPlainTextRenderer::updateNodeColor(
248 QSGNode* parentNode,
const QColor& textColor,
249 Qsk::TextStyle style,
const QColor& styleColor )
251 auto glyphNode =
static_cast< QSGGlyphNode*
>( parentNode->firstChild() );
254 if ( glyphNode->flags() & GlyphFlag )
256 glyphNode->setColor( textColor );
257 glyphNode->setStyle(
static_cast< QQuickText::TextStyle
>( style ) );
258 glyphNode->setStyleColor( styleColor );
261 glyphNode =
static_cast< QSGGlyphNode*
>( glyphNode->nextSibling() );