APIs fot creating text nodes changed

This commit is contained in:
Uwe Rathmann 2017-10-23 07:46:46 +02:00
parent d7d3047141
commit 610bc48931
12 changed files with 344 additions and 410 deletions

View File

@ -59,7 +59,7 @@ static inline QSGNode* qskFindNodeByFlag( QSGNode* parent, int nodeRole )
return nullptr; return nullptr;
} }
static inline QSGNode* qskUpdateGraphicNode( static inline QSGNode* qskUpdateGraphicNode(
const QskSkinnable* skinnable, QSGNode* node, const QskSkinnable* skinnable, QSGNode* node,
const QskGraphic& graphic, const QskColorFilter& colorFilter, const QskGraphic& graphic, const QskColorFilter& colorFilter,
const QRect& rect ) const QRect& rect )
@ -101,13 +101,13 @@ static inline QskTextColors qskTextColors(
*/ */
QskSkinHintStatus status; QskSkinHintStatus status;
QskTextColors c; QskTextColors c;
c.textColor = skinnable->color( subControl, &status ); c.textColor = skinnable->color( subControl, &status );
#if 1 #if 1
if ( !status.isValid() ) if ( !status.isValid() )
c.textColor = skinnable->color( subControl | QskAspect::TextColor ); c.textColor = skinnable->color( subControl | QskAspect::TextColor );
#endif #endif
c.styleColor = skinnable->color( subControl | StyleColor ); c.styleColor = skinnable->color( subControl | StyleColor );
c.linkColor = skinnable->color( subControl | LinkColor ); c.linkColor = skinnable->color( subControl | LinkColor );
@ -372,7 +372,7 @@ QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
} }
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl ) const QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
{ {
using namespace QskAspect; using namespace QskAspect;
@ -411,7 +411,7 @@ QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
} }
QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl ) const QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
{ {
using namespace QskAspect; using namespace QskAspect;
@ -445,7 +445,7 @@ QSGNode* QskSkinlet::updateTextNode(
const QskSkinnable* skinnable, QSGNode* node, const QskSkinnable* skinnable, QSGNode* node,
const QRectF& rect, Qt::Alignment alignment, const QRectF& rect, Qt::Alignment alignment,
const QString& text, const QskTextOptions& textOptions, const QString& text, const QskTextOptions& textOptions,
QskAspect::Subcontrol subControl ) const QskAspect::Subcontrol subControl )
{ {
if ( text.isEmpty() || rect.isEmpty() ) if ( text.isEmpty() || rect.isEmpty() )
return nullptr; return nullptr;
@ -510,9 +510,9 @@ QSGNode* QskSkinlet::updateGraphicNode(
const Qt::Alignment alignment = skinnable->flagHint< Qt::Alignment >( const Qt::Alignment alignment = skinnable->flagHint< Qt::Alignment >(
subcontrol | QskAspect::Alignment, Qt::AlignCenter ); subcontrol | QskAspect::Alignment, Qt::AlignCenter );
const auto colorFilter = skinnable->effectiveGraphicFilter( subcontrol ); const auto colorFilter = skinnable->effectiveGraphicFilter( subcontrol );
return updateGraphicNode( skinnable, node, return updateGraphicNode( skinnable, node,
graphic, colorFilter, rect, alignment ); graphic, colorFilter, rect, alignment );
} }
@ -520,7 +520,7 @@ QSGNode* QskSkinlet::updateGraphicNode(
QSGNode* QskSkinlet::updateGraphicNode( QSGNode* QskSkinlet::updateGraphicNode(
const QskSkinnable* skinnable, QSGNode* node, const QskSkinnable* skinnable, QSGNode* node,
const QskGraphic& graphic, const QskColorFilter& colorFilter, const QskGraphic& graphic, const QskColorFilter& colorFilter,
const QRectF& rect, Qt::Alignment alignment ) const const QRectF& rect, Qt::Alignment alignment )
{ {
if ( graphic.isNull() ) if ( graphic.isNull() )
return nullptr; return nullptr;
@ -537,13 +537,13 @@ QSGNode* QskSkinlet::updateGraphicNode(
QSGNode* QskSkinlet::updateGraphicNode( QSGNode* QskSkinlet::updateGraphicNode(
const QskSkinnable* skinnable, QSGNode* node, const QskSkinnable* skinnable, QSGNode* node,
const QskGraphic& graphic, const QskColorFilter& colorFilter, const QskGraphic& graphic, const QskColorFilter& colorFilter,
const QRectF& rect ) const const QRectF& rect )
{ {
if ( graphic.isNull() ) if ( graphic.isNull() )
return nullptr; return nullptr;
return qskUpdateGraphicNode( skinnable, node, return qskUpdateGraphicNode( skinnable, node,
graphic, colorFilter, rect.toAlignedRect() ); graphic, colorFilter, rect.toAlignedRect() );
} }
#include "moc_QskSkinlet.cpp" #include "moc_QskSkinlet.cpp"

View File

@ -66,33 +66,33 @@ protected:
QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*, QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
QskAspect::Subcontrol ) const; QskAspect::Subcontrol ) const;
QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*, static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, QskAspect::Subcontrol ) const; const QRectF&, QskAspect::Subcontrol );
QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*, QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*,
QskAspect::Subcontrol ) const; QskAspect::Subcontrol ) const;
QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*, static QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*,
const QRectF&, QskAspect::Subcontrol ) const; const QRectF&, QskAspect::Subcontrol );
QSGNode* updateTextNode( const QskSkinnable*, QSGNode*,
const QRectF&, Qt::Alignment, const QString&, const QskTextOptions&,
QskAspect::Subcontrol ) const;
QSGNode* updateTextNode( const QskSkinnable*, QSGNode*, QSGNode* updateTextNode( const QskSkinnable*, QSGNode*,
const QString&, const QskTextOptions&, QskAspect::Subcontrol ) const; const QString&, const QskTextOptions&, QskAspect::Subcontrol ) const;
static QSGNode* updateTextNode( const QskSkinnable*, QSGNode*,
const QRectF&, Qt::Alignment, const QString&, const QskTextOptions&,
QskAspect::Subcontrol );
QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*, QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*,
const QskGraphic&, QskAspect::Subcontrol ) const; const QskGraphic&, QskAspect::Subcontrol ) const;
// keeping the aspect ratio // keeping the aspect ratio
QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*, static QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*,
const QskGraphic&, const QskColorFilter&, const QskGraphic&, const QskColorFilter&,
const QRectF&, Qt::Alignment ) const; const QRectF&, Qt::Alignment );
// stretching to fit // stretching to fit
QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*, static QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*,
const QskGraphic&, const QskColorFilter&, const QRectF& ) const; const QskGraphic&, const QskColorFilter&, const QRectF& );
void insertRemoveNodes( QSGNode* parentNode, void insertRemoveNodes( QSGNode* parentNode,
QSGNode* oldNode, QSGNode* newNode, int nodeRole ) const; QSGNode* oldNode, QSGNode* newNode, int nodeRole ) const;

View File

@ -6,7 +6,7 @@
#include "QskTextLabel.h" #include "QskTextLabel.h"
#include "QskAspect.h" #include "QskAspect.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskTextNode.h" #include "QskTextRenderer.h"
#include <QFontMetricsF> #include <QFontMetricsF>
#include <QtMath> #include <QtMath>
@ -173,7 +173,7 @@ QSizeF QskTextLabel::contentsSizeHint() const
if ( !m_data->text.isEmpty() ) if ( !m_data->text.isEmpty() )
{ {
const auto font = effectiveFont( Text ); const auto font = effectiveFont( Text );
return QskTextNode::textSize( return QskTextRenderer::textSize(
m_data->text, font, m_data->effectiveOptions() ); m_data->text, font, m_data->effectiveOptions() );
} }
@ -199,7 +199,8 @@ qreal QskTextLabel::heightForWidth( qreal width ) const
} }
QSizeF size( width, maxHeight ); QSizeF size( width, maxHeight );
size = QskTextNode::textSize( m_data->text, font, size, m_data->effectiveOptions() ); size = QskTextRenderer::textSize( m_data->text, font,
m_data->effectiveOptions(), size );
return qCeil( size.height() ); return qCeil( size.height() );
} }
@ -216,7 +217,8 @@ qreal QskTextLabel::widthForHeight( qreal height ) const
const qreal maxWidth = std::numeric_limits< qreal >::max(); const qreal maxWidth = std::numeric_limits< qreal >::max();
QSizeF size( maxWidth, height ); QSizeF size( maxWidth, height );
size = QskTextNode::textSize( m_data->text, font, size, m_data->effectiveOptions() ); size = QskTextRenderer::textSize( m_data->text, font,
m_data->effectiveOptions(), size );
return qCeil( size.width() ); return qCeil( size.width() );
} }

View File

@ -4,8 +4,8 @@
*****************************************************************************/ *****************************************************************************/
#include "QskPlainTextRenderer.h" #include "QskPlainTextRenderer.h"
#include "QskSkinlet.h"
#include "QskTextColors.h" #include "QskTextColors.h"
#include "QskTextOptions.h"
#include <QFontMetrics> #include <QFontMetrics>
#include <QGuiApplication> #include <QGuiApplication>
@ -27,45 +27,20 @@ QSK_QT_PRIVATE_END
#define GlyphFlag static_cast< QSGNode::Flag >( 0x800 ) #define GlyphFlag static_cast< QSGNode::Flag >( 0x800 )
QskPlainTextRenderer::QskPlainTextRenderer(): QSizeF QskPlainTextRenderer::textSize( const QString& text,
m_fontMetrics( m_font ) const QFont& font, const QskTextOptions& options )
{
}
QskPlainTextRenderer::~QskPlainTextRenderer()
{
}
void QskPlainTextRenderer::setFont( const QFont& font )
{
m_font = font;
m_fontMetrics = QFontMetricsF( m_font );
}
void QskPlainTextRenderer::setOptions( const QskTextOptions& options )
{
m_options = options;
}
void QskPlainTextRenderer::setAlignment( Qt::Alignment alignment )
{
m_alignment = alignment;
}
QSizeF QskPlainTextRenderer::textSize( const QString& text ) const
{ {
// result differs from QskTextRenderer::implicitSizeHint ??? // result differs from QskTextRenderer::implicitSizeHint ???
return textRect( QSizeF( 10e6, 10e6 ), text ).size(); return textRect( text, font, options, QSizeF( 10e6, 10e6 ) ).size();
} }
QRectF QskPlainTextRenderer::textRect( const QSizeF& size, const QString& text ) const QRectF QskPlainTextRenderer::textRect( const QString& text,
const QFont& font, const QskTextOptions& options, const QSizeF& size )
{ {
return m_fontMetrics.boundingRect( { QPointF(), size }, flags(), text ); const QFontMetricsF fm( font );
} const QRect r( 0, 0, size.width(), size.height() );
int QskPlainTextRenderer::flags() const return fm.boundingRect( r, options.textFlags(), text );
{
return m_options.textFlags() | m_alignment;
} }
static qreal qskLayoutText( QTextLayout* layout, const QPointF& position, qreal lineWidth, static qreal qskLayoutText( QTextLayout* layout, const QPointF& position, qreal lineWidth,
@ -177,39 +152,32 @@ static void qskRenderText(
} }
void QskPlainTextRenderer::updateNode( const QString& text, void QskPlainTextRenderer::updateNode( const QString& text,
const QRectF& rect, Qsk::TextStyle style, const QskTextColors& colors, const QFont& font, const QskTextOptions& options,
Qsk::TextStyle style, const QskTextColors& colors,
Qt::Alignment alignment, const QRectF& rect,
const QQuickItem* item, QSGTransformNode* node ) const QQuickItem* item, QSGTransformNode* node )
{ {
QTextOption textOption( m_alignment ); QTextOption textOption( alignment );
textOption.setWrapMode( static_cast< QTextOption::WrapMode >( m_options.wrapMode() ) ); textOption.setWrapMode( static_cast< QTextOption::WrapMode >( options.wrapMode() ) );
QTextLayout layout; QTextLayout layout;
layout.setFont( m_font ); layout.setFont( font );
layout.setTextOption( textOption ); layout.setTextOption( textOption );
layout.setText( text ); layout.setText( text );
layout.beginLayout(); layout.beginLayout();
QPointF position; QPointF position;
position.ry() += qskLayoutText( &layout, position, rect.width(), m_options ); position.ry() += qskLayoutText( &layout, position, rect.width(), options );
layout.endLayout(); layout.endLayout();
position.setX( 0 ); position.setX( 0 );
position.setY( m_fontMetrics.ascent() position.setY( QFontMetricsF( font ).ascent()
+ ( m_alignment & Qt::AlignVCenter + ( alignment & Qt::AlignVCenter ? ( rect.height() - position.y() ) * 0.5 : 0 ) );
? ( rect.height() - position.y() ) * 0.5 : 0 ) );
qskRenderText( const_cast< QQuickItem* >( item ), node, &layout, position, qskRenderText( const_cast< QQuickItem* >( item ), node, &layout, position,
colors.textColor, static_cast< QQuickText::TextStyle >( style ), colors.styleColor ); colors.textColor, static_cast< QQuickText::TextStyle >( style ), colors.styleColor );
} }
void QskPlainTextRenderer::updateNode( const QString& text,
const QSizeF& size, Qsk::TextStyle style, const QskTextColors& colors,
const QQuickItem* item, QSGTransformNode* node )
{
const QRectF textRect( 0, 0, size.width(), size.height() );
updateNode( text, textRect, style, colors, item, node );
}
void QskPlainTextRenderer::updateNodeColor( QSGNode* parentNode, const QColor& textColor, void QskPlainTextRenderer::updateNodeColor( QSGNode* parentNode, const QColor& textColor,
Qsk::TextStyle style, const QColor& styleColor ) Qsk::TextStyle style, const QColor& styleColor )
{ {

View File

@ -8,50 +8,32 @@
#include "QskGlobal.h" #include "QskGlobal.h"
#include "QskNamespace.h" #include "QskNamespace.h"
#include "QskTextOptions.h" #include <Qt>
#include <QFont>
#include <QFontMetricsF>
class QskTextColors; class QskTextColors;
class QskTextOptions;
class QSGNode; class QString;
class QFont;
class QRectF;
class QSizeF;
class QQuickItem; class QQuickItem;
class QColor; class QColor;
class QSGTransformNode; class QSGTransformNode;
class QQuickItem; class QSGNode;
class QSK_EXPORT QskPlainTextRenderer namespace QskPlainTextRenderer
{ {
public: QSK_EXPORT void updateNode( const QString&, const QFont&, const QskTextOptions&,
QskPlainTextRenderer(); Qsk::TextStyle, const QskTextColors&, Qt::Alignment, const QRectF&,
~QskPlainTextRenderer();
void setFont( const QFont& );
void setOptions( const QskTextOptions& );
void setAlignment( Qt::Alignment );
void updateNode( const QString&, const QSizeF&,
Qsk::TextStyle, const QskTextColors&,
const QQuickItem*, QSGTransformNode* ); const QQuickItem*, QSGTransformNode* );
void updateNode( const QString&, const QRectF&, QSK_EXPORT void updateNodeColor( QSGNode* parentNode,
Qsk::TextStyle, const QskTextColors&,
const QQuickItem*, QSGTransformNode* );
static void updateNodeColor( QSGNode* parentNode,
const QColor& textColor, Qsk::TextStyle, const QColor& styleColor ); const QColor& textColor, Qsk::TextStyle, const QColor& styleColor );
QSizeF textSize( const QString& ) const; QSK_EXPORT QSizeF textSize( const QString&, const QFont&, const QskTextOptions& );
QRectF textRect( const QSizeF&, const QString& ) const; QSK_EXPORT QRectF textRect( const QString&, const QFont&,
const QskTextOptions&, const QSizeF& );
private: }
int flags() const;
QFont m_font;
QFontMetricsF m_fontMetrics;
QskTextOptions m_options;
Qt::Alignment m_alignment;
};
#endif #endif

View File

@ -0,0 +1,195 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskRichTextRenderer.h"
#include "QskTextColors.h"
#include "QskTextOptions.h"
#include <QQuickWindow>
QSK_QT_PRIVATE_BEGIN
#include <private/qquicktext_p.h>
#include <private/qquicktext_p_p.h>
QSK_QT_PRIVATE_END
#include <limits>
namespace
{
class TextItem final : public QQuickText
{
public:
TextItem()
{
// fonts are supposed to be defined in the application skin and we
// probably don't want to have them scaled
setFontSizeMode( QQuickText::FixedSize );
#if 0
setAntialiasing( true );
setRenderType( QQuickText::QtRendering );
setPadding( 0 );
setMinimumPixelSize();
setMinimumPointSize();
// also something, that should be defined in an application skin
setLineHeightMode( ... );
setLineHeight();
#endif
}
inline void setAlignment( Qt::Alignment alignment )
{
setHAlign( ( QQuickText::HAlignment ) ( int( alignment ) & 0x0f ) );
setVAlign( ( QQuickText::VAlignment ) ( int( alignment ) & 0xf0 ) );
}
inline void setOptions( const QskTextOptions& options )
{
// what about Qt::TextShowMnemonic ???
setTextFormat( ( QQuickText::TextFormat ) options.format() );
setElideMode( ( QQuickText::TextElideMode ) options.elideMode() );
setMaximumLineCount( options.maximumLineCount() );
setWrapMode( static_cast< QQuickText::WrapMode >( options.wrapMode() ) );
}
void refWindow( QQuickWindow* window );
void derefWindow();
void begin() { classBegin(); }
void end() { componentComplete(); }
QRectF layedOutTextRect() const
{
auto that = const_cast< TextItem* >( this );
return QQuickTextPrivate::get( that )->layedOutTextRect;
}
void updateTextNode( QQuickWindow* window, QSGNode* parentNode )
{
QQuickItemPrivate::get( this )->refWindow( window );
while ( parentNode->firstChild() )
delete parentNode->firstChild();
auto node = QQuickText::updatePaintNode( nullptr, nullptr );
node->reparentChildNodesTo( parentNode );
delete node;
QQuickItemPrivate::get( this )->derefWindow();
}
protected:
virtual QSGNode* updatePaintNode(
QSGNode*, UpdatePaintNodeData* ) override final
{
Q_ASSERT( false );
return nullptr;
}
};
}
/*
size requests and rendering might be from different threads and we
better use different items as we might end up in events internally
being sent, that leads to crashes because of it
*/
static TextItem* qskRenderHelper = nullptr;
static TextItem* qskLayoutHelper = nullptr;
QSizeF QskRichTextRenderer::textSize( const QString& text,
const QFont& font, const QskTextOptions& options )
{
if ( qskLayoutHelper == NULL )
qskLayoutHelper = new TextItem();
auto& item = *qskLayoutHelper;
item.begin();
item.setFont( font );
item.setOptions( options );
item.setWidth( -1 );
item.setText( text );
item.end();
return QSizeF( item.implicitWidth(), item.implicitHeight() );
}
QRectF QskRichTextRenderer::textRect( const QString& text,
const QFont& font, const QskTextOptions& options, const QSizeF& size )
{
if ( qskLayoutHelper == NULL )
qskLayoutHelper = new TextItem();
auto& textItem = *qskLayoutHelper;
textItem.begin();
textItem.setFont( font );
textItem.setOptions( options );
textItem.setAlignment( Qt::Alignment() );
textItem.setWidth( size.width() );
textItem.setHeight( size.height() );
textItem.setText( text );
textItem.end();
return textItem.layedOutTextRect();
}
void QskRichTextRenderer::updateNode( const QString& text,
const QFont& font, const QskTextOptions& options,
Qsk::TextStyle style, const QskTextColors& colors,
Qt::Alignment alignment, const QRectF& rect,
const QQuickItem* item, QSGTransformNode* node )
{
// are we killing internal caches of QQuickText, when always using
// the same item for the creation the text nodes. TODO ...
if ( qskRenderHelper == NULL )
qskRenderHelper = new TextItem();
auto& textItem = *qskRenderHelper;
textItem.begin();
textItem.setFont( font );
textItem.setOptions( options );
textItem.setAlignment( alignment );
#if 0
// the position of textItem seems to have no effect
// on the position of the node. We do it by translation later.
textItem.setX( rect.x() );
textItem.setY( rect.y() );
#endif
if ( rect.width() != item->width() ||
rect.height() != item->height() )
{
textItem.setWidth( rect.width() );
textItem.setHeight( rect.height() );
textItem.doLayout();
}
textItem.setColor( colors.textColor );
textItem.setStyle( static_cast< QQuickText::TextStyle >( style ) );
textItem.setStyleColor( colors.styleColor );
textItem.setLinkColor( colors.linkColor );
textItem.setText( text );
textItem.end();
textItem.updateTextNode( item->window(), node );
textItem.setText( QString::null );
}

View File

@ -0,0 +1,35 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_RICH_TEXT_RENDERER_H
#define QSK_RICH_TEXT_RENDERER_H
#include "QskGlobal.h"
#include "QskNamespace.h"
#include <Qt>
class QskTextColors;
class QskTextOptions;
class QString;
class QFont;
class QRectF;
class QSizeF;
class QQuickItem;
class QSGTransformNode;
namespace QskRichTextRenderer
{
QSK_EXPORT void updateNode( const QString&, const QFont&, const QskTextOptions&,
Qsk::TextStyle, const QskTextColors&, Qt::Alignment, const QRectF&,
const QQuickItem*, QSGTransformNode* );
QSK_EXPORT QSizeF textSize( const QString&, const QFont&, const QskTextOptions& );
QSK_EXPORT QRectF textRect( const QString&, const QFont&,
const QskTextOptions&, const QSizeF& );
}
#endif

View File

@ -7,7 +7,6 @@
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskTextColors.h" #include "QskTextColors.h"
#include "QskTextRenderer.h" #include "QskTextRenderer.h"
#include "QskPlainTextRenderer.h"
#include <QFont> #include <QFont>
#include <QColor> #include <QColor>
@ -64,75 +63,11 @@ void QskTextNode::setTextData( const QQuickItem* item,
const QRectF textRect( 0, 0, rect.width(), rect.height() ); const QRectF textRect( 0, 0, rect.width(), rect.height() );
if ( options.format() == QskTextOptions::PlainText ) /*
{ In case of having color changes only we would could
#if 0 go a faster update path: see QskPlainTextRenderer::updateNodeColor.
if ( colors_only ) TODO ...
{ */
// doesn't work - we end up with a black rectangle TODO ... QskTextRenderer::updateNode( text, font, options, textStyle,
colors, alignment, textRect, item, this );
QskPlainTextRenderer::updateNodeColor( parentNode, textRgb,
fontOptions.textStyle, styleRgb );
return;
}
#endif
QskPlainTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
renderer.setAlignment( alignment );
renderer.updateNode( text, textRect, textStyle, colors, item, this );
}
else
{
QskTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
renderer.setAlignment( alignment );
renderer.updateNode( text, textRect, textStyle, colors, item, this );
}
} }
QSizeF QskTextNode::textSize( const QString& text,
const QFont& font, const QskTextOptions& options )
{
if ( options.effectiveFormat( text ) == QskTextOptions::PlainText )
{
QskPlainTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
return renderer.textSize( text );
}
else
{
QskTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
return renderer.textSize( text );
}
}
QSizeF QskTextNode::textSize( const QString& text, const QFont& font,
const QSizeF& boundingSize, const QskTextOptions& options )
{
if ( options.effectiveFormat( text ) == QskTextOptions::PlainText )
{
QskPlainTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
return renderer.textRect( boundingSize, text ).size();
}
else
{
QskTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
return renderer.textRect( boundingSize, text ).size();
}
}

View File

@ -29,15 +29,6 @@ public:
const QskTextOptions&, const QskTextColors&, const QskTextOptions&, const QskTextColors&,
Qt::Alignment, Qsk::TextStyle ); Qt::Alignment, Qsk::TextStyle );
#if 1
// for the moment here TODO ...
static QSizeF textSize( const QString&,
const QFont&, const QskTextOptions& );
static QSizeF textSize( const QString&, const QFont&,
const QSizeF&, const QskTextOptions& );
#endif
private: private:
QRectF m_rect; QRectF m_rect;
uint m_hash; uint m_hash;

View File

@ -4,201 +4,44 @@
*****************************************************************************/ *****************************************************************************/
#include "QskTextRenderer.h" #include "QskTextRenderer.h"
#include "QskTextColors.h" #include "QskRichTextRenderer.h"
#include "QskPlainTextRenderer.h"
#include "QskTextOptions.h"
#include <QQuickWindow> #include <QRectF>
QSK_QT_PRIVATE_BEGIN QSizeF QskTextRenderer::textSize( const QString& text,
#include <private/qquicktext_p.h> const QFont& font, const QskTextOptions& options )
#include <private/qquicktext_p_p.h>
QSK_QT_PRIVATE_END
#include <limits>
class QskTextHelperItem final : public QQuickText
{ {
public: if ( options.effectiveFormat( text ) == QskTextOptions::PlainText )
void refWindow( QQuickWindow* window ); return QskPlainTextRenderer::textSize( text, font, options );
void derefWindow(); else
return QskRichTextRenderer::textSize( text, font, options );
void begin() { classBegin(); }
void end() { componentComplete(); }
QRectF layedOutTextRect() const
{
auto that = const_cast< QskTextHelperItem* >( this );
return QQuickTextPrivate::get( that )->layedOutTextRect;
}
void updateTextNode( QQuickWindow* window, QSGNode* parentNode )
{
QQuickItemPrivate::get( this )->refWindow( window );
while ( parentNode->firstChild() )
delete parentNode->firstChild();
auto node = QQuickText::updatePaintNode( nullptr, nullptr );
node->reparentChildNodesTo( parentNode );
delete node;
QQuickItemPrivate::get( this )->derefWindow();
}
protected:
virtual QSGNode* updatePaintNode(
QSGNode*, UpdatePaintNodeData* ) override final
{
// should never be called
return nullptr;
}
};
/*
size requests and rendering might be from different threads and we
better use different items as we might end up in events internally
being sent, that leads to crashes because of it
*/
static QskTextHelperItem* qskRenderHelper = nullptr;
static QskTextHelperItem* qskLayoutHelper = nullptr;
void QskTextRenderer::setFont( const QFont& font )
{
m_font = font;
} }
void QskTextRenderer::setOptions( const QskTextOptions& options ) QSizeF QskTextRenderer::textSize( const QString& text,
const QFont& font, const QskTextOptions& options, const QSizeF& size )
{ {
m_options = options; if ( options.effectiveFormat( text ) == QskTextOptions::PlainText )
} return QskPlainTextRenderer::textRect( text, font, options, size ).size();
else
void QskTextRenderer::setAlignment( Qt::Alignment alignment ) return QskRichTextRenderer::textRect( text, font, options, size ).size();
{
m_alignment = alignment;
}
QSizeF QskTextRenderer::textSize( const QString& text ) const
{
if ( qskLayoutHelper == NULL )
qskLayoutHelper = new QskTextHelperItem();
QskTextHelperItem& textItem = *qskLayoutHelper;
textItem.begin();
setupItem( &textItem );
textItem.setWidth( -1 );
textItem.setText( text );
textItem.end();
return QSizeF( textItem.implicitWidth(), textItem.implicitHeight() );
}
QRectF QskTextRenderer::textRect( const QSizeF& size, const QString& text ) const
{
if ( qskLayoutHelper == NULL )
qskLayoutHelper = new QskTextHelperItem();
QskTextHelperItem& textItem = *qskLayoutHelper;
textItem.begin();
setupItem( &textItem );
textItem.setWidth( size.width() );
textItem.setHeight( size.height() );
textItem.setText( text );
textItem.end();
return textItem.layedOutTextRect();
}
void QskTextRenderer::setupItem( QskTextHelperItem* textItem ) const
{
#if 0
textItem->setAntialiasing( true );
textItem->setRenderType( QQuickText::QtRendering );
textItem->setPadding( 0 );
#endif
textItem->setHAlign( ( QQuickText::HAlignment ) ( int( m_alignment ) & 0x0f ) );
textItem->setVAlign( ( QQuickText::VAlignment ) ( int( m_alignment ) & 0xf0 ) );
// fonts are supposed to be defined in the application skin and we
// probably don't want to have them scaled
textItem->setFont( m_font );
textItem->setFontSizeMode( QQuickText::FixedSize );
#if 0
textItem->setMinimumPixelSize();
textItem->setMinimumPointSize();
#endif
textItem->setTextFormat( ( QQuickText::TextFormat ) m_options.format() );
textItem->setElideMode( ( QQuickText::TextElideMode ) m_options.elideMode() );
textItem->setMaximumLineCount( m_options.maximumLineCount() );
textItem->setWrapMode( static_cast< QQuickText::WrapMode >( m_options.wrapMode() ) );
// what about Qt::TextShowMnemonic ???
#if 0
// also something, that should be defined in an application skin
textItem->setLineHeightMode( ... );
textItem->setLineHeight();
#endif
} }
void QskTextRenderer::updateNode( const QString& text, void QskTextRenderer::updateNode( const QString& text,
const QRectF& rect, Qsk::TextStyle style, const QskTextColors& colors, const QFont& font, const QskTextOptions& options,
Qsk::TextStyle style, const QskTextColors& colors,
Qt::Alignment alignment, const QRectF& rect,
const QQuickItem* item, QSGTransformNode* node ) const QQuickItem* item, QSGTransformNode* node )
{ {
// are we killing internal caches of QQuickText, when always using if ( options.format() == QskTextOptions::PlainText )
// the same item for the creation the text nodes. TODO ...
if ( qskRenderHelper == NULL )
qskRenderHelper = new QskTextHelperItem();
QskTextHelperItem& textItem = *qskRenderHelper;
textItem.begin();
setupItem( &textItem );
#if 0
// the position of textItem seems to have no effect
// on the position of the node. We do it by translation later.
textItem.setX( rect.x() );
textItem.setY( rect.y() );
#endif
if ( rect.width() != textItem.width() ||
rect.height() != textItem.height() )
{ {
textItem.setWidth( rect.width() ); QskPlainTextRenderer::updateNode( text, font, options, style,
textItem.setHeight( rect.height() ); colors, alignment, rect, item, node );
textItem.doLayout(); }
else
{
QskRichTextRenderer::updateNode( text, font, options, style,
colors, alignment, rect, item, node );
} }
textItem.setColor( colors.textColor );
textItem.setStyle( static_cast< QQuickText::TextStyle >( style ) );
textItem.setStyleColor( colors.styleColor );
textItem.setLinkColor( colors.linkColor );
textItem.setText( text );
textItem.end();
textItem.updateTextNode( item->window(), node );
textItem.setText( QString::null );
}
void QskTextRenderer::updateNode( const QString& text,
const QSizeF& size, Qsk::TextStyle style, const QskTextColors& colors,
const QQuickItem* item, QSGTransformNode* node )
{
const QRectF textRect( 0, 0, size.width(), size.height() );
updateNode( text, textRect, style, colors, item, node );
} }

View File

@ -8,47 +8,28 @@
#include "QskGlobal.h" #include "QskGlobal.h"
#include "QskNamespace.h" #include "QskNamespace.h"
#include "QskTextOptions.h" #include <Qt>
#include <QFont>
#include <QRectF>
class QskTextHelperItem;
class QskTextColors; class QskTextColors;
class QskTextOptions;
class QString;
class QFont;
class QRectF;
class QSizeF;
class QQuickItem; class QQuickItem;
class QQuickWindow;
class QSGTransformNode; class QSGTransformNode;
class QColor;
// Hacking a QQuickTextNode using a QQuickText helper item namespace QskTextRenderer
// How to create the nodes in a better way needs further
// investigations
class QSK_EXPORT QskTextRenderer
{ {
public: QSK_EXPORT void updateNode( const QString&, const QFont&, const QskTextOptions&,
void setFont( const QFont& font ); Qsk::TextStyle, const QskTextColors&, Qt::Alignment, const QRectF&,
void setOptions( const QskTextOptions& );
void setAlignment( Qt::Alignment );
void updateNode( const QString&, const QSizeF&,
Qsk::TextStyle, const QskTextColors&,
const QQuickItem*, QSGTransformNode* ); const QQuickItem*, QSGTransformNode* );
void updateNode( const QString&, const QRectF&, QSK_EXPORT QSizeF textSize( const QString&, const QFont&, const QskTextOptions& );
Qsk::TextStyle, const QskTextColors&,
const QQuickItem*, QSGTransformNode* );
QSizeF textSize( const QString& ) const; QSK_EXPORT QSizeF textSize( const QString&, const QFont&,
QRectF textRect( const QSizeF&, const QString& ) const; const QskTextOptions&, const QSizeF& );
}
private:
void setupItem( QskTextHelperItem* ) const;
QFont m_font;
QskTextOptions m_options;
Qt::Alignment m_alignment;
};
#endif #endif

View File

@ -93,8 +93,9 @@ HEADERS += \
nodes/QskBoxRendererColorMap.h \ nodes/QskBoxRendererColorMap.h \
nodes/QskGraphicNode.h \ nodes/QskGraphicNode.h \
nodes/QskPlainTextRenderer.h \ nodes/QskPlainTextRenderer.h \
nodes/QskTextNode.h \ nodes/QskRichTextRenderer.h \
nodes/QskTextRenderer.h \ nodes/QskTextRenderer.h \
nodes/QskTextNode.h \
nodes/QskTextureNode.h \ nodes/QskTextureNode.h \
nodes/QskVertex.h nodes/QskVertex.h
@ -106,8 +107,9 @@ SOURCES += \
nodes/QskBoxRendererDEllipse.cpp \ nodes/QskBoxRendererDEllipse.cpp \
nodes/QskGraphicNode.cpp \ nodes/QskGraphicNode.cpp \
nodes/QskPlainTextRenderer.cpp \ nodes/QskPlainTextRenderer.cpp \
nodes/QskTextNode.cpp \ nodes/QskRichTextRenderer.cpp \
nodes/QskTextRenderer.cpp \ nodes/QskTextRenderer.cpp \
nodes/QskTextNode.cpp \
nodes/QskTextureNode.cpp \ nodes/QskTextureNode.cpp \
nodes/QskVertex.cpp nodes/QskVertex.cpp