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

View File

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

View File

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

View File

@ -4,8 +4,8 @@
*****************************************************************************/
#include "QskPlainTextRenderer.h"
#include "QskSkinlet.h"
#include "QskTextColors.h"
#include "QskTextOptions.h"
#include <QFontMetrics>
#include <QGuiApplication>
@ -27,45 +27,20 @@ QSK_QT_PRIVATE_END
#define GlyphFlag static_cast< QSGNode::Flag >( 0x800 )
QskPlainTextRenderer::QskPlainTextRenderer():
m_fontMetrics( m_font )
{
}
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
QSizeF QskPlainTextRenderer::textSize( const QString& text,
const QFont& font, const QskTextOptions& options )
{
// 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 m_options.textFlags() | m_alignment;
return fm.boundingRect( r, options.textFlags(), text );
}
static qreal qskLayoutText( QTextLayout* layout, const QPointF& position, qreal lineWidth,
@ -177,39 +152,32 @@ static void qskRenderText(
}
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 )
{
QTextOption textOption( m_alignment );
textOption.setWrapMode( static_cast< QTextOption::WrapMode >( m_options.wrapMode() ) );
QTextOption textOption( alignment );
textOption.setWrapMode( static_cast< QTextOption::WrapMode >( options.wrapMode() ) );
QTextLayout layout;
layout.setFont( m_font );
layout.setFont( font );
layout.setTextOption( textOption );
layout.setText( text );
layout.beginLayout();
QPointF position;
position.ry() += qskLayoutText( &layout, position, rect.width(), m_options );
position.ry() += qskLayoutText( &layout, position, rect.width(), options );
layout.endLayout();
position.setX( 0 );
position.setY( m_fontMetrics.ascent()
+ ( m_alignment & Qt::AlignVCenter
? ( rect.height() - position.y() ) * 0.5 : 0 ) );
position.setY( QFontMetricsF( font ).ascent()
+ ( alignment & Qt::AlignVCenter ? ( rect.height() - position.y() ) * 0.5 : 0 ) );
qskRenderText( const_cast< QQuickItem* >( item ), node, &layout, position,
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,
Qsk::TextStyle style, const QColor& styleColor )
{

View File

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

@ -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 "QskTextColors.h"
#include "QskTextRenderer.h"
#include "QskPlainTextRenderer.h"
#include <QFont>
#include <QColor>
@ -64,75 +63,11 @@ void QskTextNode::setTextData( const QQuickItem* item,
const QRectF textRect( 0, 0, rect.width(), rect.height() );
if ( options.format() == QskTextOptions::PlainText )
{
#if 0
if ( colors_only )
{
// doesn't work - we end up with a black rectangle TODO ...
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 );
}
/*
In case of having color changes only we would could
go a faster update path: see QskPlainTextRenderer::updateNodeColor.
TODO ...
*/
QskTextRenderer::updateNode( text, font, options, textStyle,
colors, alignment, textRect, 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&,
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:
QRectF m_rect;
uint m_hash;

View File

@ -4,201 +4,44 @@
*****************************************************************************/
#include "QskTextRenderer.h"
#include "QskTextColors.h"
#include "QskRichTextRenderer.h"
#include "QskPlainTextRenderer.h"
#include "QskTextOptions.h"
#include <QQuickWindow>
#include <QRectF>
QSK_QT_PRIVATE_BEGIN
#include <private/qquicktext_p.h>
#include <private/qquicktext_p_p.h>
QSK_QT_PRIVATE_END
#include <limits>
class QskTextHelperItem final : public QQuickText
QSizeF QskTextRenderer::textSize( const QString& text,
const QFont& font, const QskTextOptions& options )
{
public:
void refWindow( QQuickWindow* window );
void derefWindow();
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;
if ( options.effectiveFormat( text ) == QskTextOptions::PlainText )
return QskPlainTextRenderer::textSize( text, font, options );
else
return QskRichTextRenderer::textSize( text, font, options );
}
void QskTextRenderer::setOptions( const QskTextOptions& options )
QSizeF QskTextRenderer::textSize( const QString& text,
const QFont& font, const QskTextOptions& options, const QSizeF& size )
{
m_options = options;
}
void QskTextRenderer::setAlignment( Qt::Alignment alignment )
{
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
if ( options.effectiveFormat( text ) == QskTextOptions::PlainText )
return QskPlainTextRenderer::textRect( text, font, options, size ).size();
else
return QskRichTextRenderer::textRect( text, font, options, size ).size();
}
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 )
{
// 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 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() )
if ( options.format() == QskTextOptions::PlainText )
{
textItem.setWidth( rect.width() );
textItem.setHeight( rect.height() );
textItem.doLayout();
QskPlainTextRenderer::updateNode( text, font, options, style,
colors, alignment, rect, item, node );
}
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 "QskNamespace.h"
#include "QskTextOptions.h"
#include <Qt>
#include <QFont>
#include <QRectF>
class QskTextHelperItem;
class QskTextColors;
class QskTextOptions;
class QString;
class QFont;
class QRectF;
class QSizeF;
class QQuickItem;
class QQuickWindow;
class QSGTransformNode;
class QColor;
// Hacking a QQuickTextNode using a QQuickText helper item
// How to create the nodes in a better way needs further
// investigations
class QSK_EXPORT QskTextRenderer
namespace QskTextRenderer
{
public:
void setFont( const QFont& font );
void setOptions( const QskTextOptions& );
void setAlignment( Qt::Alignment );
void updateNode( const QString&, const QSizeF&,
Qsk::TextStyle, const QskTextColors&,
QSK_EXPORT void updateNode( const QString&, const QFont&, const QskTextOptions&,
Qsk::TextStyle, const QskTextColors&, Qt::Alignment, const QRectF&,
const QQuickItem*, QSGTransformNode* );
void updateNode( const QString&, const QRectF&,
Qsk::TextStyle, const QskTextColors&,
const QQuickItem*, QSGTransformNode* );
QSK_EXPORT QSizeF textSize( const QString&, const QFont&, const QskTextOptions& );
QSizeF textSize( const QString& ) const;
QRectF textRect( const QSizeF&, const QString& ) const;
private:
void setupItem( QskTextHelperItem* ) const;
QFont m_font;
QskTextOptions m_options;
Qt::Alignment m_alignment;
};
QSK_EXPORT QSizeF textSize( const QString&, const QFont&,
const QskTextOptions&, const QSizeF& );
}
#endif

View File

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