QskSkinRenderer removed

This commit is contained in:
Uwe Rathmann 2017-10-20 20:26:39 +02:00
parent a7a5d53821
commit d7d3047141
18 changed files with 320 additions and 402 deletions

View File

@ -3,6 +3,8 @@
#include <QskAspect.h> #include <QskAspect.h>
#include <QskRgbValue.h> #include <QskRgbValue.h>
#include <QskBoxShapeMetrics.h>
#include <QskGradient.h>
#include <QskAnimationHint.h> #include <QskAnimationHint.h>
QSK_SUBCONTROL( Slider, Scale ) QSK_SUBCONTROL( Slider, Scale )
@ -15,7 +17,15 @@ Slider::Slider( QQuickItem* parentItem ):
setMetric( QskSlider::Handle | Size, 80 ); setMetric( QskSlider::Handle | Size, 80 );
setColor( Fill, QskRgbValue::Grey700 ); #if 0
const QskGradient fillGradient( QskGradient::Horizontal,
QskRgbValue::Grey700, QskRgbValue::Grey500 );
#else
const QskGradient fillGradient( QskRgbValue::Grey700 );
#endif
setBoxShapeHint( Fill, 0 );
setGradientHint( Fill, fillGradient );
setColor( Scale, qRgb( 178, 178, 178 ) ); // for the ticks setColor( Scale, qRgb( 178, 178, 178 ) ); // for the ticks
setColor( QskSlider::Handle, QskRgbValue::Grey800 ); setColor( QskSlider::Handle, QskRgbValue::Grey800 );

View File

@ -8,12 +8,12 @@
#include <QskAspect.h> #include <QskAspect.h>
#include <QskSlider.h> #include <QskSlider.h>
#include <QskPlainTextRenderer.h>
#include <QskRgbValue.h> #include <QskRgbValue.h>
#include <QskTextNode.h>
#include <QskTextOptions.h>
#include <QskTextColors.h>
#include <QSGTransformNode>
#include <QSGFlatColorMaterial> #include <QSGFlatColorMaterial>
#include <QSGSimpleRectNode>
#include <QFontMetricsF> #include <QFontMetricsF>
#include <cmath> #include <cmath>
@ -58,7 +58,7 @@ public:
setMaterial( &m_material ); setMaterial( &m_material );
} }
void update( const QRectF& rect, qreal peak, const QColor& color ) void update( const QRectF& rect, qreal peakPos, const QColor& color )
{ {
if ( color != m_color ) if ( color != m_color )
{ {
@ -68,15 +68,15 @@ public:
markDirty( QSGNode::DirtyMaterial ); markDirty( QSGNode::DirtyMaterial );
} }
if ( rect != m_rect || peak != m_peak ) if ( rect != m_rect || peakPos != m_peakPos )
{ {
QSGGeometry::Point2D* p = QSGGeometry::Point2D* p =
reinterpret_cast< QSGGeometry::Point2D* >( m_geometry.vertexData() ); reinterpret_cast< QSGGeometry::Point2D* >( m_geometry.vertexData() );
const qreal y0 = rect.y() + qskPeak; const qreal y0 = rect.y() + qskPeak;
setLine( p, peak, peak, rect.y() ); setLine( p, peakPos, peakPos, rect.y() );
setLine( p + 2, peak - 5, peak + 5, y0 ); setLine( p + 2, peakPos - 5, peakPos + 5, y0 );
// corners manually "rounded" by 3 pixels // corners manually "rounded" by 3 pixels
@ -88,7 +88,7 @@ public:
setLine( p + 14, rect.left() + 2, rect.right() - 2, rect.bottom() ); setLine( p + 14, rect.left() + 2, rect.right() - 2, rect.bottom() );
m_rect = rect; m_rect = rect;
m_peak = peak; m_peakPos = peakPos;
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
} }
} }
@ -104,7 +104,7 @@ private:
} }
QRectF m_rect; QRectF m_rect;
qreal m_peak; qreal m_peakPos;
QColor m_color; QColor m_color;
QSGFlatColorMaterial m_material; QSGFlatColorMaterial m_material;
@ -164,7 +164,7 @@ QSGNode* SliderSkinlet::updateSubNode(
return updateDecorationNode( slider, node ); return updateDecorationNode( slider, node );
case FillRole: case FillRole:
return updateFillNode( slider, node ); return Inherited::updateSubNode( skinnable, nodeRole, node );
case HandleRole: case HandleRole:
return updateHandleNode( slider, node ); return updateHandleNode( slider, node );
@ -224,12 +224,6 @@ QRectF SliderSkinlet::handleRect( const QskSlider* slider ) const
return handleRect; return handleRect;
} }
QSGNode* SliderSkinlet::updateGrooveNode( const QskSlider*, QSGNode* ) const
{
// we don't have a groove
return nullptr;
}
QSGNode* SliderSkinlet::updateScaleNode( QSGNode* SliderSkinlet::updateScaleNode(
const QskSlider* slider, QSGNode* node ) const const QskSlider* slider, QSGNode* node ) const
{ {
@ -284,7 +278,7 @@ QSGNode* SliderSkinlet::updateDecorationNode(
const int tickCount = std::floor( slider->range() / slider->stepSize() ) + 1; const int tickCount = std::floor( slider->range() / slider->stepSize() ) + 1;
auto labelNode = static_cast< QSGTransformNode* >( decorationNode->firstChild() ); auto labelNode = static_cast< QskTextNode* >( decorationNode->firstChild() );
auto stepStride = slider->stepSize() / slider->range() * decorationRect.width(); auto stepStride = slider->stepSize() / slider->range() * decorationRect.width();
@ -295,24 +289,17 @@ QSGNode* SliderSkinlet::updateDecorationNode(
{ {
if ( labelNode == nullptr ) if ( labelNode == nullptr )
{ {
labelNode = new QSGTransformNode; labelNode = new QskTextNode;
decorationNode->appendChildNode( labelNode ); decorationNode->appendChildNode( labelNode );
} }
auto labelText = QString::number( slider->minimum() + slider->stepSize() * i, 'f', 0 ); auto labelText = QString::number( slider->minimum() + slider->stepSize() * i, 'f', 0 );
QskPlainTextRenderer renderer; labelNode->setTextData( slider, labelText, QRectF( x, y, 0, 0 ),
renderer.setFont( qskLabelFont ); qskLabelFont, QskTextOptions(), QskTextColors( QskRgbValue::Grey700 ),
renderer.setAlignment( Qt::AlignHCenter ); Qt::AlignHCenter, Qsk::Normal );
renderer.updateNode( slider, QRectF(), labelText, labelNode,
QskRgbValue::Grey700, Qsk::Normal, Qt::transparent );
QMatrix4x4 matrix;
matrix.translate( x, y );
labelNode->setMatrix( matrix );
labelNode = static_cast< decltype( labelNode ) >( labelNode->nextSibling() ); labelNode = static_cast< decltype( labelNode ) >( labelNode->nextSibling() );
x += 100 * stepStride; x += 100 * stepStride;
} }
@ -328,28 +315,6 @@ QSGNode* SliderSkinlet::updateDecorationNode(
return decorationNode; return decorationNode;
} }
QSGNode* SliderSkinlet::updateFillNode(
const QskSlider* slider, QSGNode* node ) const
{
const QRectF fillRect = subControlRect( slider, QskSlider::Fill );
if ( fillRect.isEmpty() )
return nullptr;
QSGSimpleRectNode* fillNode = static_cast< QSGSimpleRectNode* >( node );
if ( fillNode == nullptr )
{
fillNode = new QSGSimpleRectNode;
fillNode->setFlags( QSGNode::OwnedByParent );
fillNode->setColor( slider->color( QskSlider::Fill ) );
}
fillNode->setRect( fillRect );
fillNode->markDirty( QSGNode::DirtyForceUpdate );
return fillNode;
}
QSGNode* SliderSkinlet::updateHandleNode( QSGNode* SliderSkinlet::updateHandleNode(
const QskSlider* slider, QSGNode* node ) const const QskSlider* slider, QSGNode* node ) const
{ {
@ -367,31 +332,26 @@ QSGNode* SliderSkinlet::updateHandleNode(
slider->color( QskSlider::Handle ) ); slider->color( QskSlider::Handle ) );
// finally the value label // finally the value label
auto labelNode = static_cast< QSGTransformNode* >( handleNode->firstChild() ); auto labelNode = static_cast< QskTextNode* >( handleNode->firstChild() );
if ( labelNode == nullptr ) if ( labelNode == nullptr )
{ {
labelNode = new QSGTransformNode; labelNode = new QskTextNode;
handleNode->appendChildNode( labelNode ); handleNode->appendChildNode( labelNode );
} }
QFont font( QStringLiteral( "Roboto" ) ); QFont font( QStringLiteral( "Roboto" ) );
font.setPixelSize( 26 ); font.setPixelSize( 26 );
QskPlainTextRenderer renderer;
renderer.setFont( font );
renderer.setAlignment( Qt::AlignHCenter );
renderer.updateNode( slider, handleRect.size(),
QString::number( slider->value(), 'f', 0 ),
labelNode, Qt::white, Qsk::Normal, Qt::transparent );
#if 1
const qreal h = QFontMetrics( font ).height(); const qreal h = QFontMetrics( font ).height();
qreal y = handleRect.bottom() - 0.5 * ( handleRect.height() - qskPeak + h );
QMatrix4x4 matrix; auto textRect = handleRect;
matrix.translate( handleRect.x(), y ); textRect.setTop( textRect.bottom() - 0.5 * ( textRect.height() - qskPeak + h ) );
labelNode->setMatrix( matrix );
#endif const QString text = QString::number( slider->value(), 'f', 0 );
labelNode->setTextData( slider, text, textRect,
font, QskTextOptions(), QskTextColors( Qt::white ),
Qt::AlignHCenter, Qsk::Normal );
return handleNode; return handleNode;
} }

View File

@ -17,7 +17,7 @@ class SliderSkinlet : public QskSliderSkinlet
public: public:
enum NodeRole enum NodeRole
{ {
// we have a scale instead of the groove // we have a scale instead of a groove
ScaleRole = QskSliderSkinlet::HandleRole + 1, ScaleRole = QskSliderSkinlet::HandleRole + 1,
DecorationRole DecorationRole
}; };
@ -32,20 +32,15 @@ protected:
virtual QSGNode* updateSubNode( virtual QSGNode* updateSubNode(
const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override; const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override;
virtual QSGNode* updateScaleNode( const QskSlider*, QSGNode* ) const;
virtual QSGNode* updateDecorationNode( const QskSlider*, QSGNode* ) const;
QSGNode* updateFillNode( const QskSlider*, QSGNode* ) const;
QSGNode* updateHandleNode( const QskSlider*, QSGNode* ) const;
QSGNode* updateGrooveNode( const QskSlider*, QSGNode* ) const;
private: private:
QSGNode* updateScaleNode( const QskSlider*, QSGNode* ) const;
QSGNode* updateDecorationNode( const QskSlider*, QSGNode* ) const;
QSGNode* updateHandleNode( const QskSlider*, QSGNode* ) const;
QRectF fillRect( const QskSlider* ) const; QRectF fillRect( const QskSlider* ) const;
QRectF scaleRect( const QskSlider* ) const; QRectF scaleRect( const QskSlider* ) const;
QRectF decorationRect( const QskSlider* ) const; QRectF decorationRect( const QskSlider* ) const;
QRectF handleRect( const QskSlider* ) const; QRectF handleRect( const QskSlider* ) const;
void updateHandleLabel( const QskSlider*, QSGTransformNode* ) const;
}; };
#endif #endif

View File

@ -10,7 +10,6 @@
#include "QskAspect.h" #include "QskAspect.h"
#include "QskSkin.h" #include "QskSkin.h"
#include "QskSkinRenderer.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskTextNode.h" #include "QskTextNode.h"
#include "QskBoxNode.h" #include "QskBoxNode.h"
@ -146,6 +145,7 @@ QSGNode* QskInputPanelSkinlet::updatePanelNode(
const auto rowIndex = &keyRow - panelKeyData; const auto rowIndex = &keyRow - panelKeyData;
auto& frames = panelNode->frames[ rowIndex ]; auto& frames = panelNode->frames[ rowIndex ];
auto& glyphs = panelNode->glyphs[ rowIndex ]; auto& glyphs = panelNode->glyphs[ rowIndex ];
for ( const auto& keyData : keyRow ) for ( const auto& keyData : keyRow )
{ {
const auto colIndex = &keyData - keyRow; const auto colIndex = &keyData - keyRow;
@ -217,10 +217,8 @@ QSGNode* QskInputPanelSkinlet::updateKeyGlyphNode(
const auto alignment = textNode->flagHint< Qt::Alignment >( const auto alignment = textNode->flagHint< Qt::Alignment >(
QskInputPanel::KeyGlyph | QskAspect::Alignment, Qt::AlignCenter ); QskInputPanel::KeyGlyph | QskAspect::Alignment, Qt::AlignCenter );
QskSkinRenderer::updateText( textNode, rect, alignment, return updateTextNode( panel, textNode, rect, alignment,
panel->textForKey( key ), options, textNode, QskInputPanel::KeyGlyph ); panel->textForKey( key ), options, QskInputPanel::KeyGlyph );
return textNode;
} }
#include "moc_QskInputPanelSkinlet.cpp" #include "moc_QskInputPanelSkinlet.cpp"

View File

@ -6,7 +6,6 @@
#include "QskListViewSkinlet.h" #include "QskListViewSkinlet.h"
#include "QskListView.h" #include "QskListView.h"
#include "QskAspect.h" #include "QskAspect.h"
#include "QskSkinRenderer.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskTextNode.h" #include "QskTextNode.h"
#include "QskGraphic.h" #include "QskGraphic.h"

View File

@ -1,152 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskSkinRenderer.h"
#include "QskSkinnable.h"
#include "QskControl.h"
#include "QskTextRenderer.h"
#include "QskPlainTextRenderer.h"
#include "QskTextNode.h"
#include <QMatrix4x4>
QSizeF QskSkinRenderer::textSize( const QskSkinnable* skinnable,
const QString& text, const QskTextOptions& options,
QskAspect::Subcontrol subControl )
{
using namespace QskAspect;
auto font = skinnable->effectiveFont( subControl );
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 QskSkinRenderer::textSize( const QskSkinnable* skinnable,
const QSizeF& boundingSize, const QString& text,
const QskTextOptions& options, QskAspect::Subcontrol subControl )
{
const auto font = skinnable->effectiveFont( subControl );
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();
}
}
void QskSkinRenderer::updateText( const QskSkinnable* skinnable,
const QRectF& bounds, Qt::Alignment alignment,
const QString& text, const QskTextOptions& options,
QskTextNode* textNode, QskAspect::Subcontrol subControl )
{
using namespace QskAspect;
QMatrix4x4 matrix;
matrix.translate( bounds.left(), bounds.top() );
textNode->setMatrix( matrix );
QskSkinHintStatus status;
auto textColor = skinnable->color( subControl, &status );
if ( !status.isValid() )
textColor = skinnable->color( subControl | QskAspect::TextColor );
auto font = skinnable->effectiveFont( subControl );
auto styleColor = skinnable->color( subControl | StyleColor );
auto textStyle = Qsk::Normal;
if ( styleColor.alpha() == 0 )
{
textStyle = skinnable->flagHint< Qsk::TextStyle >(
subControl | Style, Qsk::Normal );
}
const auto isPlainText = options.effectiveFormat( text ) == QskTextOptions::PlainText;
// doesn't work - we end up with a black rectangle TODO ...
#if 0
// Optimization: only update the color if that is all that has changed
if ( isPlainText && color_is_dirty )
{
QskPlainTextRenderer::updateNodeColor( parentNode, textRgb,
fontOptions.textStyle, styleRgb );
return;
}
#endif
switch ( options.fontSizeMode() )
{
case QskTextOptions::FixedSize:
break;
case QskTextOptions::HorizontalFit:
Q_UNIMPLEMENTED();
break;
case QskTextOptions::VerticalFit:
font.setPixelSize( bounds.height() * 0.5 );
break;
case QskTextOptions::Fit:
Q_UNIMPLEMENTED();
break;
}
QColor linkColor;
if ( !isPlainText )
linkColor = skinnable->color( subControl | LinkColor );
if ( textNode->setTextData( text, bounds.size(), font,
options, alignment, textStyle, textColor, styleColor, linkColor ) )
{
if ( isPlainText )
{
QskPlainTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
renderer.setAlignment( alignment );
renderer.updateNode( skinnable->owningControl(), bounds.size(),
text, textNode, textColor, textStyle, styleColor );
}
else
{
QskTextRenderer renderer;
renderer.setFont( font );
renderer.setOptions( options );
renderer.setAlignment( alignment );
renderer.updateNode( skinnable->owningControl(), bounds.size(),
text, textNode, textColor, textStyle, styleColor, linkColor );
}
}
}

View File

@ -1,41 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_SKIN_RENDERER_H
#define QSK_SKIN_RENDERER_H
#include "QskGlobal.h"
#include "QskAspect.h"
#include <Qt>
class QskSkinnable;
class QskTextOptions;
class QskTextNode;
class QPointF;
class QRectF;
class QSizeF;
class QString;
namespace QskSkinRenderer
{
// a loose collection of functions, waiting to be
// organized somehow. TODO ...
QSK_EXPORT void updateText( const QskSkinnable*,
const QRectF&, Qt::Alignment,
const QString&, const QskTextOptions&,
QskTextNode*, QskAspect::Subcontrol );
QSK_EXPORT QSizeF textSize( const QskSkinnable*,
const QString&, const QskTextOptions&, QskAspect::Subcontrol );
QSK_EXPORT QSizeF textSize( const QskSkinnable*,
const QSizeF& boundingSize, const QString&,
const QskTextOptions&, QskAspect::Subcontrol );
}
#endif

View File

@ -13,10 +13,11 @@
#include "QskBoxBorderMetrics.h" #include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h" #include "QskBoxBorderColors.h"
#include "QskGradient.h" #include "QskGradient.h"
#include "QskSkinRenderer.h"
#include "QskBoxNode.h" #include "QskBoxNode.h"
#include "QskBoxClipNode.h" #include "QskBoxClipNode.h"
#include "QskTextNode.h" #include "QskTextNode.h"
#include "QskTextColors.h"
#include "QskTextOptions.h"
#include "QskGraphicNode.h" #include "QskGraphicNode.h"
#include "QskGraphicTextureFactory.h" #include "QskGraphicTextureFactory.h"
#include "QskFunctions.h" #include "QskFunctions.h"
@ -89,6 +90,31 @@ static inline bool qskIsBoxVisible( const QskBoxBorderMetrics& borderMetrics,
return !borderMetrics.isNull() && borderColors.isVisible(); return !borderMetrics.isNull() && borderColors.isVisible();
} }
static inline QskTextColors qskTextColors(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl )
{
using namespace QskAspect;
/*
Would be more efficient to have QskTextColors hints instead of
storing the colors as seperated hints. TODO ...
*/
QskSkinHintStatus status;
QskTextColors c;
c.textColor = skinnable->color( subControl, &status );
#if 1
if ( !status.isValid() )
c.textColor = skinnable->color( subControl | QskAspect::TextColor );
#endif
c.styleColor = skinnable->color( subControl | StyleColor );
c.linkColor = skinnable->color( subControl | LinkColor );
return c;
}
class QskSkinlet::PrivateData class QskSkinlet::PrivateData
{ {
public: public:
@ -428,8 +454,37 @@ QSGNode* QskSkinlet::updateTextNode(
if ( textNode == nullptr ) if ( textNode == nullptr )
textNode = new QskTextNode(); textNode = new QskTextNode();
QskSkinRenderer::updateText( skinnable, rect, alignment, auto colors = qskTextColors( skinnable, subControl );
text, textOptions, textNode, subControl );
auto textStyle = Qsk::Normal;
if ( colors.styleColor.alpha() == 0 )
{
textStyle = skinnable->flagHint< Qsk::TextStyle >(
subControl | QskAspect::Style, Qsk::Normal );
}
auto font = skinnable->effectiveFont( subControl );
switch ( textOptions.fontSizeMode() )
{
case QskTextOptions::FixedSize:
break;
case QskTextOptions::HorizontalFit:
Q_UNIMPLEMENTED();
break;
case QskTextOptions::VerticalFit:
font.setPixelSize( rect.height() * 0.5 );
break;
case QskTextOptions::Fit:
Q_UNIMPLEMENTED();
break;
}
textNode->setTextData( skinnable->owningControl(),
text, rect, font, textOptions, colors, alignment, textStyle );
return textNode; return textNode;
} }

View File

@ -16,7 +16,6 @@
#include "QskControl.h" #include "QskControl.h"
#include "QskColorFilter.h" #include "QskColorFilter.h"
#include "QskSkinTransition.h" #include "QskSkinTransition.h"
#include "QskSkinRenderer.h"
#include <QFont> #include <QFont>
#include <QElapsedTimer> #include <QElapsedTimer>

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 "QskSkinRenderer.h" #include "QskTextNode.h"
#include <QFontMetricsF> #include <QFontMetricsF>
#include <QtMath> #include <QtMath>
@ -172,8 +172,9 @@ QSizeF QskTextLabel::contentsSizeHint() const
{ {
if ( !m_data->text.isEmpty() ) if ( !m_data->text.isEmpty() )
{ {
return QskSkinRenderer::textSize( this, m_data->text, const auto font = effectiveFont( Text );
m_data->effectiveOptions(), QskTextLabel::Text ); return QskTextNode::textSize(
m_data->text, font, m_data->effectiveOptions() );
} }
return QSizeF( 0, 0 ); return QSizeF( 0, 0 );
@ -181,7 +182,8 @@ QSizeF QskTextLabel::contentsSizeHint() const
qreal QskTextLabel::heightForWidth( qreal width ) const qreal QskTextLabel::heightForWidth( qreal width ) const
{ {
const qreal lineHeight = QFontMetricsF( effectiveFont( Text ) ).height(); const auto font = effectiveFont( Text );
const qreal lineHeight = QFontMetricsF( font ).height();
if ( m_data->text.isEmpty() || if ( m_data->text.isEmpty() ||
( m_data->textOptions.wrapMode() == QskTextOptions::NoWrap ) ) ( m_data->textOptions.wrapMode() == QskTextOptions::NoWrap ) )
@ -196,9 +198,8 @@ qreal QskTextLabel::heightForWidth( qreal width ) const
maxHeight = m_data->textOptions.maximumLineCount() * lineHeight; maxHeight = m_data->textOptions.maximumLineCount() * lineHeight;
} }
const QSizeF size = QskSkinRenderer::textSize( this, QSizeF size( width, maxHeight );
QSizeF( width, maxHeight ), m_data->text, size = QskTextNode::textSize( m_data->text, font, size, m_data->effectiveOptions() );
m_data->effectiveOptions(), QskTextLabel::Text );
return qCeil( size.height() ); return qCeil( size.height() );
} }
@ -211,11 +212,11 @@ qreal QskTextLabel::widthForHeight( qreal height ) const
return Inherited::widthForHeight( height ); return Inherited::widthForHeight( height );
} }
const auto font = effectiveFont( Text );
const qreal maxWidth = std::numeric_limits< qreal >::max(); const qreal maxWidth = std::numeric_limits< qreal >::max();
const QSizeF size = QskSkinRenderer::textSize( this, QSizeF size( maxWidth, height );
QSizeF( maxWidth, height ), m_data->text, size = QskTextNode::textSize( m_data->text, font, size, m_data->effectiveOptions() );
m_data->effectiveOptions(), QskTextLabel::Text );
return qCeil( size.width() ); return qCeil( size.width() );
} }

View File

@ -10,6 +10,7 @@
#include "QskBoxBorderMetrics.h" #include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h" #include "QskBoxBorderColors.h"
#include "QskGradient.h" #include "QskGradient.h"
#include "QskTextColors.h"
// Even if we don't use the standard Qt animation system we // Even if we don't use the standard Qt animation system we
// use its registry of interpolators: why adding our own ... // use its registry of interpolators: why adding our own ...
@ -26,6 +27,7 @@ static void qskRegisterInterpolator()
qRegisterAnimationInterpolator<QskBoxShapeMetrics>( QskBoxShapeMetrics::interpolate ); qRegisterAnimationInterpolator<QskBoxShapeMetrics>( QskBoxShapeMetrics::interpolate );
qRegisterAnimationInterpolator<QskBoxBorderMetrics>( QskBoxBorderMetrics::interpolate ); qRegisterAnimationInterpolator<QskBoxBorderMetrics>( QskBoxBorderMetrics::interpolate );
qRegisterAnimationInterpolator<QskBoxBorderColors>( QskBoxBorderColors::interpolate ); qRegisterAnimationInterpolator<QskBoxBorderColors>( QskBoxBorderColors::interpolate );
qRegisterAnimationInterpolator<QskTextColors>( QskTextColors::interpolate );
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterInterpolator ) Q_CONSTRUCTOR_FUNCTION( qskRegisterInterpolator )

View File

@ -5,6 +5,7 @@
#include "QskPlainTextRenderer.h" #include "QskPlainTextRenderer.h"
#include "QskSkinlet.h" #include "QskSkinlet.h"
#include "QskTextColors.h"
#include <QFontMetrics> #include <QFontMetrics>
#include <QGuiApplication> #include <QGuiApplication>
@ -175,9 +176,9 @@ static void qskRenderText(
} }
} }
void QskPlainTextRenderer::updateNode( void QskPlainTextRenderer::updateNode( const QString& text,
const QQuickItem* item, const QRectF& rect, const QString& text, QSGNode* parentNode, const QRectF& rect, Qsk::TextStyle style, const QskTextColors& colors,
const QColor& textColor, Qsk::TextStyle style, const QColor& styleColor ) const QQuickItem* item, QSGTransformNode* node )
{ {
QTextOption textOption( m_alignment ); QTextOption textOption( m_alignment );
textOption.setWrapMode( static_cast< QTextOption::WrapMode >( m_options.wrapMode() ) ); textOption.setWrapMode( static_cast< QTextOption::WrapMode >( m_options.wrapMode() ) );
@ -197,8 +198,16 @@ void QskPlainTextRenderer::updateNode(
+ ( m_alignment & Qt::AlignVCenter + ( m_alignment & Qt::AlignVCenter
? ( rect.height() - position.y() ) * 0.5 : 0 ) ); ? ( rect.height() - position.y() ) * 0.5 : 0 ) );
qskRenderText( const_cast< QQuickItem* >( item ), parentNode, &layout, position, qskRenderText( const_cast< QQuickItem* >( item ), node, &layout, position,
textColor, static_cast< QQuickText::TextStyle >( style ), 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,

View File

@ -13,9 +13,13 @@
#include <QFont> #include <QFont>
#include <QFontMetricsF> #include <QFontMetricsF>
class QskTextColors;
class QSGNode; class QSGNode;
class QQuickItem; class QQuickItem;
class QColor; class QColor;
class QSGTransformNode;
class QQuickItem;
class QSK_EXPORT QskPlainTextRenderer class QSK_EXPORT QskPlainTextRenderer
{ {
@ -27,13 +31,13 @@ public:
void setOptions( const QskTextOptions& ); void setOptions( const QskTextOptions& );
void setAlignment( Qt::Alignment ); void setAlignment( Qt::Alignment );
void updateNode( void updateNode( const QString&, const QSizeF&,
const QQuickItem*, const QRectF&, const QString&, QSGNode* parentNode, Qsk::TextStyle, const QskTextColors&,
const QColor& textColor, Qsk::TextStyle, const QColor& styleColor ); const QQuickItem*, QSGTransformNode* );
void updateNode( void updateNode( const QString&, const QRectF&,
const QQuickItem*, const QSizeF& size, const QString&, QSGNode* parentNode, Qsk::TextStyle, const QskTextColors&,
const QColor& textColor, Qsk::TextStyle, const QColor& styleColor ); const QQuickItem*, QSGTransformNode* );
static void updateNodeColor( QSGNode* parentNode, static void updateNodeColor( QSGNode* parentNode,
const QColor& textColor, Qsk::TextStyle, const QColor& styleColor ); const QColor& textColor, Qsk::TextStyle, const QColor& styleColor );
@ -50,12 +54,4 @@ private:
Qt::Alignment m_alignment; Qt::Alignment m_alignment;
}; };
inline void QskPlainTextRenderer::updateNode(
const QQuickItem* item, const QSizeF& size, const QString& text, QSGNode* parentNode,
const QColor& textColor, Qsk::TextStyle style, const QColor& styleColor )
{
updateNode( item, QRectF( QPointF(), size ),
text, parentNode, textColor, style, styleColor );
}
#endif #endif

View File

@ -5,11 +5,32 @@
#include "QskTextNode.h" #include "QskTextNode.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskTextColors.h"
#include "QskTextRenderer.h"
#include "QskPlainTextRenderer.h"
#include <QFont> #include <QFont>
#include <QColor> #include <QColor>
#include <QString> #include <QString>
static inline uint qskHash(
const QString& text, const QSizeF& size, const QFont& font,
const QskTextOptions& options, const QskTextColors& colors,
Qt::Alignment alignment, Qsk::TextStyle textStyle )
{
uint hash = 11000;
hash = qHash( text, hash );
hash = qHash( font, hash );
hash = qHash( options, hash );
hash = qHash( alignment, hash );
hash = qHash( textStyle, hash );
hash = colors.hash( hash );
hash = qHashBits( &size, sizeof( QSizeF ), hash );
return hash;
}
QskTextNode::QskTextNode(): QskTextNode::QskTextNode():
m_hash( 0 ) m_hash( 0 )
{ {
@ -19,26 +40,99 @@ QskTextNode::~QskTextNode()
{ {
} }
bool QskTextNode::setTextData( void QskTextNode::setTextData( const QQuickItem* item,
const QString& text, const QSizeF& size, const QFont& font, const QString& text, const QRectF& rect, const QFont& font,
const QskTextOptions& options, Qt::Alignment alignment, Qsk::TextStyle textStyle, const QskTextOptions& options, const QskTextColors& colors,
const QColor& textColor, const QColor& styleColor, const QColor& linkColor ) Qt::Alignment alignment, Qsk::TextStyle textStyle )
{ {
uint hash; if ( m_rect != rect )
{
QMatrix4x4 matrix;
matrix.translate( rect.left(), rect.top() );
hash = qHash( text, 0 ); if ( matrix != this->matrix() ) // avoid setting DirtyMatrix accidently
hash = qHash( font, hash ); setMatrix( matrix );
hash = qHash( options, hash ); }
hash = qHash( alignment, hash );
hash = qHash( textStyle, hash ); const uint hash = qskHash( text, rect.size(), font,
hash = qHash( textColor.rgba(), hash ); options, colors, alignment, textStyle );
hash = qHash( styleColor.rgba(), hash );
hash = qHash( linkColor.rgba(), hash );
hash = qHashBits( &size, sizeof( QSizeF ), hash );
if ( hash == m_hash ) if ( hash == m_hash )
return false; return;
m_hash = hash; m_hash = hash;
return true;
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 );
}
} }
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

@ -10,10 +10,13 @@
#include "QskNamespace.h" #include "QskNamespace.h"
#include <QSGTransformNode> #include <QSGTransformNode>
#include <Qt> #include <QRectF>
class QskTextOptions; class QskTextOptions;
class QskTextColors;
class QString; class QString;
class QFont;
class QQuickItem;
class QSK_EXPORT QskTextNode : public QSGTransformNode class QSK_EXPORT QskTextNode : public QSGTransformNode
{ {
@ -21,10 +24,22 @@ public:
QskTextNode(); QskTextNode();
virtual ~QskTextNode(); virtual ~QskTextNode();
bool setTextData( const QString& text, const QSizeF&, const QFont&, void setTextData( const QQuickItem* item,
const QskTextOptions&, Qt::Alignment, Qsk::TextStyle, const QString& text, const QRectF&, const QFont&,
const QColor& textColor, const QColor& styleColor, const QColor& linkColor ); 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: private:
QRectF m_rect;
uint m_hash; uint m_hash;
}; };

View File

@ -4,6 +4,8 @@
*****************************************************************************/ *****************************************************************************/
#include "QskTextRenderer.h" #include "QskTextRenderer.h"
#include "QskTextColors.h"
#include <QQuickWindow> #include <QQuickWindow>
QSK_QT_PRIVATE_BEGIN QSK_QT_PRIVATE_BEGIN
@ -16,63 +18,40 @@ QSK_QT_PRIVATE_END
class QskTextHelperItem final : public QQuickText class QskTextHelperItem final : public QQuickText
{ {
public: public:
QskTextHelperItem();
void refWindow( QQuickWindow* window ); void refWindow( QQuickWindow* window );
void derefWindow(); void derefWindow();
void begin(); void begin() { classBegin(); }
void end(); void end() { componentComplete(); }
QRectF layedOutTextRect() const; QRectF layedOutTextRect() const
void updateTextNode( QQuickWindow*, QSGNode* ); {
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: protected:
virtual QSGNode* updatePaintNode( virtual QSGNode* updatePaintNode(
QSGNode*, UpdatePaintNodeData* ) override final; QSGNode*, UpdatePaintNodeData* ) override final
{
// should never be called
return nullptr;
}
}; };
QskTextHelperItem::QskTextHelperItem():
QQuickText( nullptr )
{
}
QRectF QskTextHelperItem::layedOutTextRect() const
{
auto that = const_cast< QskTextHelperItem* >( this );
return QQuickTextPrivate::get( that )->layedOutTextRect;
}
void QskTextHelperItem::updateTextNode( QQuickWindow* window, QSGNode* parentNode )
{
QQuickItemPrivate::get( this )->refWindow( window );
while ( parentNode->firstChild() )
delete parentNode->firstChild(); // This is done in QQuickText::updatePaintNode anyway
auto node = QQuickText::updatePaintNode( nullptr, nullptr );
node->reparentChildNodesTo( parentNode );
delete node;
QQuickItemPrivate::get( this )->derefWindow();
}
void QskTextHelperItem::begin()
{
classBegin();
}
void QskTextHelperItem::end()
{
componentComplete();
}
QSGNode* QskTextHelperItem::updatePaintNode( QSGNode*, UpdatePaintNodeData* )
{
// should never be called
return nullptr;
}
/* /*
size requests and rendering might be from different threads and we size requests and rendering might be from different threads and we
better use different items as we might end up in events internally better use different items as we might end up in events internally
@ -171,13 +150,12 @@ void QskTextRenderer::setupItem( QskTextHelperItem* textItem ) const
#endif #endif
} }
void QskTextRenderer::updateNode( const QQuickItem* item, void QskTextRenderer::updateNode( const QString& text,
const QRectF& rect, const QString& text, QSGTransformNode* parentNode, const QRectF& rect, Qsk::TextStyle style, const QskTextColors& colors,
const QColor& textColor, Qsk::TextStyle style, const QColor& styleColor, const QQuickItem* item, QSGTransformNode* node )
const QColor& linkColor )
{ {
// are we killing internal caches of QQuickText, when always using // are we killing internal caches of QQuickText, when always using
// the same item for the creation the text nodes ??? // the same item for the creation the text nodes. TODO ...
if ( qskRenderHelper == NULL ) if ( qskRenderHelper == NULL )
qskRenderHelper = new QskTextHelperItem(); qskRenderHelper = new QskTextHelperItem();
@ -204,16 +182,23 @@ void QskTextRenderer::updateNode( const QQuickItem* item,
textItem.doLayout(); textItem.doLayout();
} }
textItem.setColor( textColor ); textItem.setColor( colors.textColor );
textItem.setStyle( static_cast< QQuickText::TextStyle >( style ) ); textItem.setStyle( static_cast< QQuickText::TextStyle >( style ) );
textItem.setStyleColor( styleColor ); textItem.setStyleColor( colors.styleColor );
textItem.setLinkColor( linkColor ); textItem.setLinkColor( colors.linkColor );
textItem.setText( text ); textItem.setText( text );
textItem.end(); textItem.end();
textItem.updateTextNode( item->window(), parentNode ); textItem.updateTextNode( item->window(), node );
textItem.setText( QString::null ); 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

@ -14,6 +14,7 @@
#include <QRectF> #include <QRectF>
class QskTextHelperItem; class QskTextHelperItem;
class QskTextColors;
class QQuickItem; class QQuickItem;
class QQuickWindow; class QQuickWindow;
@ -31,13 +32,13 @@ public:
void setOptions( const QskTextOptions& ); void setOptions( const QskTextOptions& );
void setAlignment( Qt::Alignment ); void setAlignment( Qt::Alignment );
void updateNode( const QQuickItem*, const QSizeF&, const QString&, void updateNode( const QString&, const QSizeF&,
QSGTransformNode*, const QColor& textColor, Qsk::TextStyle, const QskTextColors&,
Qsk::TextStyle, const QColor& styleColor, const QColor& linkColor ); const QQuickItem*, QSGTransformNode* );
void updateNode( const QQuickItem*, const QRectF&, const QString&, void updateNode( const QString&, const QRectF&,
QSGTransformNode*, const QColor& textColor, Qsk::TextStyle, Qsk::TextStyle, const QskTextColors&,
const QColor& styleColor, const QColor& linkColor ); const QQuickItem*, QSGTransformNode* );
QSizeF textSize( const QString& ) const; QSizeF textSize( const QString& ) const;
QRectF textRect( const QSizeF&, const QString& ) const; QRectF textRect( const QSizeF&, const QString& ) const;
@ -50,12 +51,4 @@ private:
Qt::Alignment m_alignment; Qt::Alignment m_alignment;
}; };
inline void QskTextRenderer::updateNode( const QQuickItem* item, const QSizeF& size,
const QString& text, QSGTransformNode* node, const QColor& textColor,
Qsk::TextStyle style, const QColor& styleColor, const QColor& linkColor )
{
updateNode( item, QRectF( 0, 0, size.width(), size.height() ), text, node,
textColor, style, styleColor, linkColor );
}
#endif #endif

View File

@ -44,6 +44,7 @@ HEADERS += \
common/QskNamespace.h \ common/QskNamespace.h \
common/QskObjectCounter.h \ common/QskObjectCounter.h \
common/QskSizePolicy.h \ common/QskSizePolicy.h \
common/QskTextColors.h \
common/QskTextOptions.h common/QskTextOptions.h
SOURCES += \ SOURCES += \
@ -58,6 +59,7 @@ SOURCES += \
common/QskModule.cpp \ common/QskModule.cpp \
common/QskObjectCounter.cpp \ common/QskObjectCounter.cpp \
common/QskSizePolicy.cpp \ common/QskSizePolicy.cpp \
common/QskTextColors.cpp \
common/QskTextOptions.cpp common/QskTextOptions.cpp
HEADERS += \ HEADERS += \
@ -154,7 +156,6 @@ HEADERS += \
controls/QskSkinHintTable.h \ controls/QskSkinHintTable.h \
controls/QskSkinlet.h \ controls/QskSkinlet.h \
controls/QskSkinnable.h \ controls/QskSkinnable.h \
controls/QskSkinRenderer.h \
controls/QskSkinTransition.h \ controls/QskSkinTransition.h \
controls/QskSlider.h \ controls/QskSlider.h \
controls/QskSliderSkinlet.h \ controls/QskSliderSkinlet.h \
@ -218,7 +219,6 @@ SOURCES += \
controls/QskSkinFactory.cpp \ controls/QskSkinFactory.cpp \
controls/QskSkinlet.cpp \ controls/QskSkinlet.cpp \
controls/QskSkinnable.cpp \ controls/QskSkinnable.cpp \
controls/QskSkinRenderer.cpp \
controls/QskSkinTransition.cpp \ controls/QskSkinTransition.cpp \
controls/QskSlider.cpp \ controls/QskSlider.cpp \
controls/QskSliderSkinlet.cpp \ controls/QskSliderSkinlet.cpp \