Merge branch 'master' into features/arcrenderer
This commit is contained in:
commit
5f796bed48
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <QskGradient.h>
|
#include <QskGradient.h>
|
||||||
#include <QskGradientDirection.h>
|
#include <QskGradientDirection.h>
|
||||||
|
#include <QskBoxRenderer.h>
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
|
||||||
|
@ -54,10 +55,10 @@ namespace
|
||||||
{
|
{
|
||||||
QQuickShapeGradient* shapeGradient = nullptr;
|
QQuickShapeGradient* shapeGradient = nullptr;
|
||||||
|
|
||||||
auto effectiveGradient = gradient.effectiveGradient();
|
auto effectiveGradient = QskBoxRenderer::effectiveGradient( gradient );
|
||||||
effectiveGradient.stretchTo( rect );
|
effectiveGradient.stretchTo( rect );
|
||||||
|
|
||||||
switch( static_cast< int >( gradient.type() ) )
|
switch( static_cast< int >( effectiveGradient.type() ) )
|
||||||
{
|
{
|
||||||
case QskGradient::Linear:
|
case QskGradient::Linear:
|
||||||
{
|
{
|
||||||
|
|
|
@ -722,21 +722,6 @@ void QskGradient::resetDirection()
|
||||||
m_values[0] = m_values[1] = m_values[2] = m_values[3] = m_values[4] = 0.0;
|
m_values[0] = m_values[1] = m_values[2] = m_values[3] = m_values[4] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskGradient QskGradient::effectiveGradient() const
|
|
||||||
{
|
|
||||||
if ( ( m_type == QskGradient::Stops ) || isMonochrome() )
|
|
||||||
{
|
|
||||||
// the shader for linear gradients is the fastest
|
|
||||||
|
|
||||||
QskGradient g = *this;
|
|
||||||
g.setDirection( QskGradient::Linear );
|
|
||||||
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
QGradient QskGradient::toQGradient() const
|
QGradient QskGradient::toQGradient() const
|
||||||
{
|
{
|
||||||
QGradient g;
|
QGradient g;
|
||||||
|
|
|
@ -152,8 +152,6 @@ class QSK_EXPORT QskGradient
|
||||||
QskGradient stretchedTo( const QSizeF& ) const;
|
QskGradient stretchedTo( const QSizeF& ) const;
|
||||||
QskGradient stretchedTo( const QRectF& ) const;
|
QskGradient stretchedTo( const QRectF& ) const;
|
||||||
|
|
||||||
QskGradient effectiveGradient() const;
|
|
||||||
|
|
||||||
static QVariant interpolate( const QskGradient&,
|
static QVariant interpolate( const QskGradient&,
|
||||||
const QskGradient&, qreal progress );
|
const QskGradient&, qreal progress );
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ int QskSelectionSubWindow::selectedRow() const
|
||||||
QString QskSelectionSubWindow::selectedEntry() const
|
QString QskSelectionSubWindow::selectedEntry() const
|
||||||
{
|
{
|
||||||
if ( auto listBox = qskListBox( this ) )
|
if ( auto listBox = qskListBox( this ) )
|
||||||
listBox->selectedEntry();
|
return listBox->selectedEntry();
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ int QskSelectionWindow::selectedRow() const
|
||||||
QString QskSelectionWindow::selectedEntry() const
|
QString QskSelectionWindow::selectedEntry() const
|
||||||
{
|
{
|
||||||
if ( auto listBox = qskListBox( this ) )
|
if ( auto listBox = qskListBox( this ) )
|
||||||
listBox->selectedEntry();
|
return listBox->selectedEntry();
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,8 +104,17 @@ void QskArcRenderNode::updateFilling( const QRectF& rect,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool coloredGeometry = hasHint( PreferColoredGeometry )
|
bool coloredGeometry = hasHint( PreferColoredGeometry );
|
||||||
&& QskArcRenderer::isGradientSupported( rect, metrics, gradient );
|
if ( coloredGeometry )
|
||||||
|
{
|
||||||
|
// not all gradients are supported by the renderer
|
||||||
|
coloredGeometry = QskArcRenderer::isGradientSupported( rect, metrics, gradient );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// QskGradient::Stops is specific for QskArcRenderer
|
||||||
|
coloredGeometry = ( gradient.type() == QskGradient::Stops );
|
||||||
|
}
|
||||||
|
|
||||||
bool dirtyGeometry = d->updateMetrics( rect, metrics, radial, borderWidth );
|
bool dirtyGeometry = d->updateMetrics( rect, metrics, radial, borderWidth );
|
||||||
bool dirtyMaterial = d->updateColors( QColor(), gradient );
|
bool dirtyMaterial = d->updateColors( QColor(), gradient );
|
||||||
|
|
|
@ -458,6 +458,7 @@ bool QskArcRenderer::isGradientSupported( const QRectF& rect,
|
||||||
}
|
}
|
||||||
case QskGradient::Conic:
|
case QskGradient::Conic:
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
const auto direction = gradient.conicDirection();
|
const auto direction = gradient.conicDirection();
|
||||||
if ( direction.center() == rect.center() )
|
if ( direction.center() == rect.center() )
|
||||||
{
|
{
|
||||||
|
@ -470,6 +471,7 @@ bool QskArcRenderer::isGradientSupported( const QRectF& rect,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -572,7 +574,7 @@ void QskArcRenderer::setBorderLines( const QRectF& rect,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Renderer renderer( rect, metrics, radial, QskGradient(), 0 );
|
const Renderer renderer( rect, metrics, radial, QskGradient(), QskRgb::Black );
|
||||||
|
|
||||||
const auto lines = qskAllocateLines( geometry, renderer.borderCount() );
|
const auto lines = qskAllocateLines( geometry, renderer.borderCount() );
|
||||||
if ( lines )
|
if ( lines )
|
||||||
|
|
|
@ -103,7 +103,7 @@ void QskBoxRectangleNode::updateFilling( const QRectF& rect,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto fillGradient = gradient.effectiveGradient();
|
const auto fillGradient = QskBoxRenderer::effectiveGradient( gradient );
|
||||||
const auto shape = shapeMetrics.toAbsolute( rect.size() );
|
const auto shape = shapeMetrics.toAbsolute( rect.size() );
|
||||||
|
|
||||||
const bool coloredGeometry = hasHint( PreferColoredGeometry )
|
const bool coloredGeometry = hasHint( PreferColoredGeometry )
|
||||||
|
@ -211,13 +211,13 @@ void QskBoxRectangleNode::updateBox( const QRectF& rect,
|
||||||
if ( isDirty )
|
if ( isDirty )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
For monochrome border/fiiling with the same color we might be
|
For monochrome border/filling with the same color we might be
|
||||||
able to do QskFillNode::Monochrome. However this is not implemeted in
|
able to do QskFillNode::Monochrome. However this is not implemeted in
|
||||||
QskBoxRenderer yet. TODO ...
|
QskBoxRenderer yet. TODO ...
|
||||||
*/
|
*/
|
||||||
setColoring( QskFillNode::Polychrome );
|
setColoring( QskFillNode::Polychrome );
|
||||||
|
|
||||||
auto fillGradient = gradient.effectiveGradient();
|
auto fillGradient = QskBoxRenderer::effectiveGradient( gradient );
|
||||||
if ( !QskBoxRenderer::isGradientSupported( fillGradient ) )
|
if ( !QskBoxRenderer::isGradientSupported( fillGradient ) )
|
||||||
{
|
{
|
||||||
qWarning() << "QskBoxRenderer does not support radial/conic gradients";
|
qWarning() << "QskBoxRenderer does not support radial/conic gradients";
|
||||||
|
|
|
@ -231,3 +231,18 @@ void QskBoxRenderer::setColoredBorderAndFillLines( const QRectF& rect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskGradient QskBoxRenderer::effectiveGradient( const QskGradient& gradient )
|
||||||
|
{
|
||||||
|
if ( ( gradient.type() == QskGradient::Stops ) || gradient.isMonochrome() )
|
||||||
|
{
|
||||||
|
// the shader for linear gradients is the fastest
|
||||||
|
|
||||||
|
auto g = gradient;
|
||||||
|
g.setDirection( QskGradient::Linear );
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gradient;
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ namespace QskBoxRenderer
|
||||||
QSK_EXPORT void setColoredBorderAndFillLines( const QRectF&,
|
QSK_EXPORT void setColoredBorderAndFillLines( const QRectF&,
|
||||||
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
|
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
|
||||||
const QskBoxBorderColors&, const QskGradient&, QSGGeometry& );
|
const QskBoxBorderColors&, const QskGradient&, QSGGeometry& );
|
||||||
|
|
||||||
|
QSK_EXPORT QskGradient effectiveGradient( const QskGradient& );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -136,10 +136,12 @@ void QskFillNode::setColoring( const QColor& color )
|
||||||
{
|
{
|
||||||
setColoring( Monochrome );
|
setColoring( Monochrome );
|
||||||
|
|
||||||
|
const auto colorRgb = color.toRgb();
|
||||||
|
|
||||||
auto mat = static_cast< QSGFlatColorMaterial* >( material() );
|
auto mat = static_cast< QSGFlatColorMaterial* >( material() );
|
||||||
if ( mat->color() != color )
|
if ( mat->color() != colorRgb )
|
||||||
{
|
{
|
||||||
mat->setColor( color );
|
mat->setColor( colorRgb );
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,16 +150,25 @@ void QskFillNode::setColoring( const QRectF& rect, const QskGradient& gradient )
|
||||||
{
|
{
|
||||||
if ( gradient.isMonochrome() )
|
if ( gradient.isMonochrome() )
|
||||||
{
|
{
|
||||||
setColoring( gradient.startColor().toRgb() );
|
setColoring( gradient.startColor() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto effectiveGradient = gradient.effectiveGradient();
|
if ( gradient.type() == QskGradient::Stops )
|
||||||
setColoring( qskColoring( effectiveGradient.type() ) );
|
{
|
||||||
|
qWarning() << "QskFillNode::setColoring:"
|
||||||
|
<< "QskGradient::Stops is not supported, using the first color instead.";
|
||||||
|
|
||||||
auto mat = static_cast< QskGradientMaterial* >( material() );
|
setColoring( gradient.startColor() );
|
||||||
if ( mat->updateGradient( rect, effectiveGradient ) )
|
}
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
else
|
||||||
|
{
|
||||||
|
setColoring( qskColoring( gradient.type() ) );
|
||||||
|
|
||||||
|
auto mat = static_cast< QskGradientMaterial* >( material() );
|
||||||
|
if ( mat->updateGradient( rect, gradient ) )
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "QskShapeNode.h"
|
#include "QskShapeNode.h"
|
||||||
#include "QskGradient.h"
|
#include "QskGradient.h"
|
||||||
#include "QskGradientDirection.h"
|
#include "QskGradientDirection.h"
|
||||||
|
#include "QskVertex.h"
|
||||||
#include "QskFillNodePrivate.h"
|
#include "QskFillNodePrivate.h"
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
@ -13,27 +14,40 @@ QSK_QT_PRIVATE_BEGIN
|
||||||
#include <private/qtriangulator_p.h>
|
#include <private/qtriangulator_p.h>
|
||||||
QSK_QT_PRIVATE_END
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
// keeping the index list
|
||||||
static void qskUpdateGeometry( const QPainterPath& path,
|
static void qskUpdateGeometry( const QPainterPath& path,
|
||||||
const QTransform& transform, QSGGeometry& geometry )
|
const QTransform& transform, QSGGeometry& geometry )
|
||||||
{
|
{
|
||||||
const auto ts = qTriangulate( path, transform, 1, false );
|
const auto ts = qTriangulate( path, transform, 1, false );
|
||||||
|
|
||||||
#if 1
|
|
||||||
geometry.allocate( ts.vertices.size(), ts.indices.size() );
|
geometry.allocate( ts.vertices.size(), ts.indices.size() );
|
||||||
|
|
||||||
auto vertexData = reinterpret_cast< float* >( geometry.vertexData() );
|
auto vertexData = reinterpret_cast< float* >( geometry.vertexData() );
|
||||||
const auto points = ts.vertices.constData();
|
const auto points = ts.vertices.constData();
|
||||||
|
|
||||||
for ( int i = 0; i < ts.vertices.count(); i++ )
|
for ( int i = 0; i < ts.vertices.size(); i++ )
|
||||||
vertexData[i] = points[i];
|
vertexData[i] = points[i];
|
||||||
|
|
||||||
memcpy( geometry.indexData(), ts.indices.data(),
|
memcpy( geometry.indexData(), ts.indices.data(),
|
||||||
ts.indices.size() * sizeof( quint16 ) );
|
ts.indices.size() * sizeof( quint16 ) );
|
||||||
#else
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void qskUpdateGeometry( const QPainterPath& path,
|
||||||
|
const QTransform& transform, const QColor& color, QSGGeometry& geometry )
|
||||||
|
{
|
||||||
|
const auto ts = qTriangulate( path, transform, 1, false );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
The triangulation of a random path usually does not lead to index lists
|
||||||
|
that allow substantially reducing the number of vertices.
|
||||||
|
|
||||||
As we have to iterate over the vertex buffer to copy qreal to float
|
As we have to iterate over the vertex buffer to copy qreal to float
|
||||||
anyway we could reorder according to the index buffer and drop
|
anyway we reorder according to the index buffer and drop
|
||||||
the index buffer then ???
|
the index buffer.
|
||||||
|
|
||||||
QTriangleSet:
|
QTriangleSet:
|
||||||
|
|
||||||
|
@ -41,18 +55,32 @@ static void qskUpdateGeometry( const QPainterPath& path,
|
||||||
QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
|
QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
|
||||||
QVector<quint16> indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...]
|
QVector<quint16> indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const auto points = ts.vertices.constData();
|
const auto points = ts.vertices.constData();
|
||||||
const auto indices = reinterpret_cast< const quint16* >( ts.indices.data() );
|
const auto indices = reinterpret_cast< const quint16* >( ts.indices.data() );
|
||||||
|
|
||||||
geometry.allocate( ts.indices.size() );
|
geometry.allocate( ts.indices.size() );
|
||||||
|
|
||||||
auto vertexData = geometry.vertexDataAsPoint2D();
|
if ( color.isValid() )
|
||||||
for ( int i = 0; i < ts.indices.size(); i++ )
|
|
||||||
{
|
{
|
||||||
const int j = 2 * indices[i];
|
const QskVertex::Color c = color;
|
||||||
vertexData[i].set( points[j], points[j + 1] );
|
|
||||||
|
auto vertexData = geometry.vertexDataAsColoredPoint2D();
|
||||||
|
for ( int i = 0; i < ts.indices.size(); i++ )
|
||||||
|
{
|
||||||
|
const int j = 2 * indices[i];
|
||||||
|
vertexData[i].set( points[j], points[j + 1], c.r, c.g, c.b, c.a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto vertexData = geometry.vertexDataAsPoint2D();
|
||||||
|
for ( int i = 0; i < ts.indices.size(); i++ )
|
||||||
|
{
|
||||||
|
const int j = 2 * indices[i];
|
||||||
|
vertexData[i].set( points[j], points[j + 1] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class QskShapeNodePrivate final : public QskFillNodePrivate
|
class QskShapeNodePrivate final : public QskFillNodePrivate
|
||||||
|
@ -69,7 +97,6 @@ class QskShapeNodePrivate final : public QskFillNodePrivate
|
||||||
QskShapeNode::QskShapeNode()
|
QskShapeNode::QskShapeNode()
|
||||||
: QskFillNode( *new QskShapeNodePrivate )
|
: QskFillNode( *new QskShapeNodePrivate )
|
||||||
{
|
{
|
||||||
setColoring( Monochrome );
|
|
||||||
geometry()->setDrawingMode( QSGGeometry::DrawTriangles );
|
geometry()->setDrawingMode( QSGGeometry::DrawTriangles );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,14 +118,24 @@ void QskShapeNode::updateNode( const QPainterPath& path,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setColoring( rect, gradient );
|
QColor c;
|
||||||
|
|
||||||
if ( ( transform != d->transform ) || ( path != d->path ) )
|
if ( gradient.isMonochrome() && hasHint( PreferColoredGeometry ) )
|
||||||
|
c = gradient.startColor();
|
||||||
|
|
||||||
|
const bool isDirty = ( isGeometryColored() != c.isValid() );
|
||||||
|
|
||||||
|
if ( c.isValid() )
|
||||||
|
setColoring( QskFillNode::Polychrome );
|
||||||
|
else
|
||||||
|
setColoring( rect, gradient );
|
||||||
|
|
||||||
|
if ( isDirty || ( transform != d->transform ) || ( path != d->path ) )
|
||||||
{
|
{
|
||||||
d->path = path;
|
d->path = path;
|
||||||
d->transform = transform;
|
d->transform = transform;
|
||||||
|
|
||||||
qskUpdateGeometry( path, transform, *geometry() );
|
qskUpdateGeometry( path, transform, c, *geometry() );
|
||||||
|
|
||||||
geometry()->markVertexDataDirty();
|
geometry()->markVertexDataDirty();
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
|
Loading…
Reference in New Issue