APIs fot creating text nodes changed
This commit is contained in:
parent
d7d3047141
commit
610bc48931
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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() );
|
||||
}
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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
|
||||
|
195
src/nodes/QskRichTextRenderer.cpp
Normal file
195
src/nodes/QskRichTextRenderer.cpp
Normal 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 );
|
||||
}
|
35
src/nodes/QskRichTextRenderer.h
Normal file
35
src/nodes/QskRichTextRenderer.h
Normal 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
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user