radial arcs added

This commit is contained in:
Uwe Rathmann 2024-06-12 12:10:57 +02:00
parent 929b7a43fd
commit ac68b66b4e
10 changed files with 240 additions and 273 deletions

View File

@ -9,153 +9,10 @@
#include <QskIntervalF.h>
#include <QskArcMetrics.h>
#include <QskArcNode.h>
#include <QskArcRenderNode.h>
#include <qpainterpath.h>
#include <qmath.h>
#define PAINTED_NODE 0
#if PAINTED_NODE
/*
This is a fallback implementation for a user who is using an outdated
version of QSkinny where only shaders for linear gradients are available.
*/
#include <QskPaintedNode.h>
#include <qpainter.h>
#include <qpainterpath.h>
#include <qpen.h>
#include <qbrush.h>
namespace
{
QConicalGradient qskQConicalGradient(
const QskGradientStops& stops, qreal startAngle, qreal spanAngle )
{
QskGradientStops scaledStops;
scaledStops.reserve( stops.size() );
const auto ratio = qAbs( spanAngle ) / 360.0;
if ( spanAngle > 0.0 )
{
for ( auto it = stops.cbegin(); it != stops.cend(); ++it )
scaledStops += { ratio * it->position(), it->color() };
}
else
{
for ( auto it = stops.crbegin(); it != stops.crend(); ++it )
scaledStops += { 1.0 - ratio * it->position(), it->color() };
}
QConicalGradient qGradient( QPointF(), startAngle );
qGradient.setStops( qskToQGradientStops( scaledStops ) );
return qGradient;
}
class PaintedArcNode : public QskPaintedNode
{
public:
void setArcData( const QRectF&, const QskArcMetrics&,
qreal, const QColor&, const QskGradient&, QQuickWindow* );
protected:
void paint( QPainter*, const QSize&, const void* nodeData ) override;
QskHashValue hash( const void* nodeData ) const override;
private:
QskHashValue arcHash( const QRectF&, const QskArcMetrics&,
qreal, const QColor&, const QskGradient& ) const;
QBrush fillBrush( const QskGradient&, const QRectF&, qreal, qreal ) const;
struct ArcData
{
QPointF translation;
QPen pen;
QBrush brush;
QPainterPath path;
QskHashValue hash;
};
};
void PaintedArcNode::setArcData(
const QRectF& rect, const QskArcMetrics& metrics,
qreal borderWidth, const QColor& borderColor,
const QskGradient& gradient, QQuickWindow* window )
{
const auto hash = arcHash( rect, metrics, borderWidth, borderColor, gradient );
const auto brush = fillBrush( gradient, rect,
metrics.startAngle(), metrics.spanAngle() );
QPen pen( borderColor, borderWidth );
if ( borderWidth <= 0.0 )
pen.setStyle( Qt::NoPen );
const auto path = metrics.painterPath( rect );
const auto r = path.controlPointRect();
const ArcData arcData { r.topLeft(), pen, brush, path, hash };
update( window, r, QSizeF(), &arcData );
}
void PaintedArcNode::paint( QPainter* painter, const QSize&, const void* nodeData )
{
const auto arcData = reinterpret_cast< const ArcData* >( nodeData );
painter->setRenderHint( QPainter::Antialiasing, true );
painter->translate( -arcData->translation );
painter->setPen( arcData->pen );
painter->setBrush( arcData->brush );
painter->drawPath( arcData->path );
}
QskHashValue PaintedArcNode::hash( const void* nodeData ) const
{
const auto arcData = reinterpret_cast< const ArcData* >( nodeData );
return arcData->hash;
}
QBrush PaintedArcNode::fillBrush( const QskGradient& gradient,
const QRectF& rect, qreal startAngle, qreal spanAngle ) const
{
const auto qGradient = qskQConicalGradient(
gradient.stops(), startAngle, spanAngle );
const qreal sz = qMax( rect.width(), rect.height() );
const qreal sx = rect.width() / sz;
const qreal sy = rect.height() / sz;
QTransform t;
t.scale( sx, sy );
t.translate( rect.center().x() / sx, rect.center().y() / sy );
QBrush brush( qGradient );
brush.setTransform( t );
return brush;
}
inline QskHashValue PaintedArcNode::arcHash(
const QRectF& rect, const QskArcMetrics& metrics, qreal borderWidth,
const QColor& borderColor, const QskGradient& gradient ) const
{
auto hash = metrics.hash( 6753 );
hash = qHashBits( &rect, sizeof( rect ), hash );
hash = qHash( borderWidth, hash );
hash = qHash( borderColor.rgba(), hash );
hash = gradient.hash( hash );
return hash;
}
}
#endif // PAINTED_NODE
namespace
{
inline QskArcMetrics segmentMetrics(
@ -334,38 +191,16 @@ QSGNode* CircularChartSkinlet::updateSampleNode( const QskSkinnable* skinnable,
return nullptr;
}
QSGNode* CircularChartSkinlet::updateArcSegmentNode( const QskSkinnable* skinnable,
QSGNode* CircularChartSkinlet::updateArcSegmentNode( const QskSkinnable*,
QSGNode* node, qreal borderWidth, const QColor& borderColor,
const QskGradient& gradient, const QskArcMetrics& metrics ) const
{
#if PAINTED_NODE
auto arcNode = static_cast< PaintedArcNode* >( node );
auto arcNode = static_cast< QskArcRenderNode* >( node );
if ( arcNode == nullptr )
arcNode = new PaintedArcNode();
arcNode = new QskArcRenderNode();
const auto chart = static_cast< const CircularChart* >( skinnable );
arcNode->setArcData( m_data->closedArcRect, metrics,
borderWidth, borderColor, gradient, chart->window() );
#else
Q_UNUSED( skinnable )
auto fillGradient = gradient;
if ( fillGradient.type() == QskGradient::Stops )
{
fillGradient.setStretchMode( QskGradient::StretchToSize );
fillGradient.setConicDirection( 0.5, 0.5,
metrics.startAngle(), metrics.spanAngle() );
}
auto arcNode = static_cast< QskArcNode* >( node );
if ( arcNode == nullptr )
arcNode = new QskArcNode();
arcNode->setArcData( m_data->closedArcRect, metrics,
borderWidth, borderColor, fillGradient );
#endif
arcNode->updateNode( m_data->closedArcRect, metrics, true,
borderWidth, borderColor, gradient );
return arcNode;
}

View File

@ -71,7 +71,8 @@ namespace
{ 0.75, Qt::darkBlue },
{ 0.75, Qt::darkRed }
};
#else
#endif
#if 0
const QskGradientStops stops =
{
{ 0.1, Qt::darkRed },
@ -80,6 +81,16 @@ namespace
{ 1.0, Qt::darkRed }
};
#endif
#if 1
QskGradientStops stops;
for ( int i = 0; i < 100; i++ )
{
const auto pos = i * 1.0 / 100;
stops += { pos, ( i % 2 ) ? Qt::darkRed : Qt::darkBlue };
stops += { pos, ( i % 2 ) ? Qt::darkBlue : Qt::darkRed };
}
#endif
setFillGradient( stops );
}

View File

@ -21,6 +21,83 @@ static void qskRegisterArcMetrics()
Q_CONSTRUCTOR_FUNCTION( qskRegisterArcMetrics )
static inline QPainterPath qskRadialPathPath(
const QRectF& rect, qreal startAngle, qreal spanAngle, qreal width )
{
const auto sz = qMin( rect.width(), rect.height() );
const auto tx = width * rect.width() / sz;
const auto ty = width * rect.height() / sz;
const auto innerRect = rect.adjusted( tx, ty, -tx, -ty );
QPainterPath path;
if ( innerRect.isEmpty() )
{
if ( qAbs( spanAngle ) >= 360.0 )
{
path.addEllipse( rect );
}
else
{
// pie
path.arcMoveTo( rect, startAngle );
path.arcTo( rect, startAngle, spanAngle );
path.lineTo( rect.center() );
path.closeSubpath();
}
}
else
{
if ( qAbs( spanAngle ) >= 360.0 )
{
path.addEllipse( rect );
QPainterPath innerPath;
innerPath.addEllipse( innerRect );
path -= innerPath;
}
else
{
/*
We need the end point of the inner arc to add the line that connects
the inner/outer arcs. As QPainterPath does not offer such a method
we insert a dummy arcMoveTo and grab the calculated position.
*/
path.arcMoveTo( innerRect, startAngle + spanAngle );
const auto pos = path.currentPosition();
path.arcMoveTo( rect, startAngle ); // replaces the dummy arcMoveTo above
path.arcTo( rect, startAngle, spanAngle );
path.lineTo( pos );
path.arcTo( innerRect, startAngle + spanAngle, -spanAngle );
path.closeSubpath();
}
}
return path;
}
static inline QPainterPath qskOrthogonalPath(
const QRectF& rect, qreal startAngle, qreal spanAngle, qreal width )
{
const auto t2 = 0.5 * width;
const auto r = rect.adjusted( t2, t2, -t2, -t2 );
QPainterPath arcPath;
arcPath.arcMoveTo( r, startAngle );
arcPath.arcTo( r, startAngle, spanAngle );
QPainterPathStroker stroker;
stroker.setCapStyle( Qt::FlatCap );
stroker.setWidth( width );
return stroker.createStroke( arcPath );
}
static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio )
{
return from + ( to - from ) * ratio;
@ -97,6 +174,11 @@ QVariant QskArcMetrics::interpolate(
return QVariant::fromValue( from.interpolated( to, progress ) );
}
QskArcMetrics QskArcMetrics::toAbsolute( const QSizeF& size ) const noexcept
{
return toAbsolute( 0.5 * size.width(), 0.5 * size.height() );
}
QskArcMetrics QskArcMetrics::toAbsolute( qreal radiusX, qreal radiusY ) const noexcept
{
if ( radiusX < 0.0 )
@ -117,59 +199,30 @@ QskArcMetrics QskArcMetrics::toAbsolute( qreal radius ) const noexcept
return QskArcMetrics( m_startAngle, m_spanAngle, t, Qt::AbsoluteSize );
}
QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const
QPainterPath QskArcMetrics::painterPath( const QRectF& rect, bool radial ) const
{
qreal t = m_thickness;
if ( m_relativeSize )
{
const auto sz = qMin( ellipseRect.width(), ellipseRect.height() );
t = qskEffectiveThickness( 0.5 * sz, t );
}
if ( t <= 0.0 || qFuzzyIsNull( m_spanAngle ) )
return QPainterPath();
#if 0
/*
We do not have a proper solution for situations, where
the width leads to overlapping upper/lower or left/right parts.
*/
const auto innerRect = ellipseRect.adjusted( t, t, -t, -t );
if ( innerRect.isEmpty() )
{
QPainterPath path;
if ( qAbs( m_spanAngle ) >= 360.0 )
{
path.addEllipse( ellipseRect );
}
else
{
// pie
path.arcMoveTo( ellipseRect, m_startAngle );
path.arcTo( ellipseRect, m_startAngle, m_spanAngle );
path.lineTo( ellipseRect.center() );
path.closeSubpath();
}
return path;
}
#endif
const auto t2 = 0.5 * t;
const auto r = ellipseRect.adjusted( t2, t2, -t2, -t2 );
QPainterPath path;
path.arcMoveTo( r, m_startAngle ); // replaces the dummy arcMoveTo above
path.arcTo( r, m_startAngle, m_spanAngle );
QPainterPathStroker stroker;
stroker.setCapStyle( Qt::FlatCap );
stroker.setWidth( t );
if ( !qFuzzyIsNull( m_spanAngle ) )
{
qreal t = m_thickness;
return stroker.createStroke( path );
if ( m_relativeSize )
{
const auto sz = qMin( rect.width(), rect.height() );
t = qskEffectiveThickness( 0.5 * sz, t );
}
if ( t > 0.0 )
{
if ( radial )
path = qskRadialPathPath( rect, m_startAngle, m_spanAngle, t );
else
path = qskOrthogonalPath( rect, m_startAngle, m_spanAngle, t );
}
}
return path;
}
QRectF QskArcMetrics::boundingRect( const QRectF& ellipseRect ) const

View File

@ -58,10 +58,26 @@ class QSK_EXPORT QskArcMetrics
QskArcMetrics interpolated( const QskArcMetrics&,
qreal value ) const noexcept;
QskArcMetrics toAbsolute( const QSizeF& ) const noexcept;
QskArcMetrics toAbsolute( qreal radiusX, qreal radiusY ) const noexcept;
QskArcMetrics toAbsolute( qreal radius ) const noexcept;
QPainterPath painterPath( const QRectF& ellipseRect ) const;
/*
The arc is interpolated by pairs of points, where one point is on
the outer and the other on the inner side of the arc. The length between
these points depends on the thickness.
When radial is set the inner point lies on the line between the outer point
and the center of the arc. This corresponds to the lines of a conic gradient.
Otherwise the line between the inner and outer point is orthogonal to the
tangent at the point in the middle of the arc. This is how the width
of the pen is expanded by QPainter::drawArc.
Note, that the radial flag is irrelevant for circular arcs as the tangent
is always orthogonal to any point on the circle.
*/
QPainterPath painterPath( const QRectF& ellipseRect, bool radial = false ) const;
QRectF boundingRect( const QRectF& ellipseRect ) const;
QSizeF boundingSize( const QSizeF& ellipseSize ) const;

View File

@ -56,20 +56,6 @@ static inline QskGradient qskEffectiveGradient(
return gradient;
}
static inline QskArcMetrics qskEffectiveMetrics(
const QskArcMetrics& metrics, const QRectF& rect )
{
if ( metrics.sizeMode() == Qt::RelativeSize )
{
const auto rx = 0.5 * rect.width();
const auto ry = 0.5 * rect.height();
return metrics.toAbsolute( rx, ry );
}
return metrics;
}
static inline QRectF qskEffectiveRect(
const QRectF& rect, const qreal borderWidth )
{
@ -112,7 +98,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
const qreal borderWidth, const QColor& borderColor, const QskGradient& gradient,
const QColor& shadowColor, const QskShadowMetrics& shadowMetrics )
{
const auto metricsArc = qskEffectiveMetrics( arcMetrics, rect );
const auto metricsArc = arcMetrics.toAbsolute( rect.size() );
auto shadowNode = static_cast< QskArcShadowNode* >(
QskSGNode::findChildNode( this, ShadowRole ) );
@ -136,7 +122,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
return;
}
const auto isFillNodeVisible = gradient.isVisible() && !metricsArc.isNull();
const auto isFillNodeVisible = gradient.isVisible();
const auto isStrokeNodeVisible = ( borderWidth > 0.0 ) && ( borderColor.alpha() > 0 );
const auto isShadowNodeVisible = isFillNodeVisible &&
shadowColor.isValid() && ( shadowColor.alpha() > 0.0 );
@ -184,7 +170,8 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
QskSGNode::setNodeRole( arcNode, ArcRole );
}
arcNode->updateNode( arcRect, metricsArc, gradient );
arcNode->updateNode( arcRect, metricsArc, false,
borderWidth, QColor(), gradient );
}
else
{

View File

@ -6,18 +6,14 @@
#ifndef QSK_ARC_NODE_H
#define QSK_ARC_NODE_H
#include "QskShapeNode.h"
#include "QskGlobal.h"
#include <qsgnode.h>
class QskArcMetrics;
class QskGradient;
class QskShadowMetrics;
/*
For the moment a QPainterPath/QskShapeNode.
But we can do better by creatig vertex lists manually
like what is done by the box renderer. TODO ...
*/
class QSK_EXPORT QskArcNode : public QskShapeNode
class QSK_EXPORT QskArcNode : public QSGNode
{
public:
QskArcNode();

View File

@ -52,21 +52,23 @@ QskArcRenderNode::QskArcRenderNode()
void QskArcRenderNode::updateNode( const QRectF& rect,
const QskArcMetrics& metrics, const QskGradient& gradient )
{
updateNode( rect, metrics, 0.0, QColor(), gradient );
updateNode( rect, metrics, false, 0.0, QColor(), gradient );
}
void QskArcRenderNode::updateNode( const QRectF& rect,
const QskArcMetrics& metrics, qreal borderWidth, const QColor& borderColor )
{
updateNode( rect, metrics, borderWidth, borderColor, QskGradient() );
updateNode( rect, metrics, false, borderWidth, borderColor, QskGradient() );
}
void QskArcRenderNode::updateNode(
const QRectF& rect, const QskArcMetrics& metrics, qreal borderWidth,
const QColor& borderColor, const QskGradient& gradient )
const QRectF& rect, const QskArcMetrics& arcMetrics, bool radial,
qreal borderWidth, const QColor& borderColor, const QskGradient& gradient )
{
Q_D( QskArcRenderNode );
const auto metrics = arcMetrics.toAbsolute( rect.size() );
bool visible = !( rect.isEmpty() || metrics.isNull() );
if ( visible )
{
@ -93,21 +95,22 @@ void QskArcRenderNode::updateNode(
hash = qHash( borderColor.rgba(), hash );
hash = metrics.hash( hash );
hash = gradient.hash( hash );
hash = qHash( radial, hash );
if ( hash != d->hash )
{
d->hash = hash;
#if 0
if ( borderWidth > 0.0 )
{
QskArcRenderer::renderBorder(
rect, metrics, borderWidth, borderColor, *geometry() );
}
else
{
QskArcRenderer::renderFillGeometry(
rect, metrics, borderWidth, gradient, *geometry() );
rect, metrics, borderWidth, radial, borderColor, *geometry() );
}
#endif
QskArcRenderer::renderFillGeometry(
rect, metrics, radial, borderWidth, gradient, *geometry() );
markDirty( QSGNode::DirtyGeometry );
markDirty( QSGNode::DirtyMaterial );

View File

@ -25,8 +25,8 @@ class QSK_EXPORT QskArcRenderNode : public QSGGeometryNode
void updateNode( const QRectF&, const QskArcMetrics&, qreal borderWidth,
const QColor& borderColor );
void updateNode( const QRectF&, const QskArcMetrics&, qreal borderWidth,
const QColor& borderColor, const QskGradient& );
void updateNode( const QRectF&, const QskArcMetrics&, bool radial,
qreal borderWidth, const QColor& borderColor, const QskGradient& );
private:
Q_DECLARE_PRIVATE( QskArcRenderNode )

View File

@ -31,7 +31,7 @@ namespace
class EllipseStroker
{
public:
EllipseStroker( const QRectF&, const QskArcMetrics&,
EllipseStroker( const QRectF&, const QskArcMetrics&, bool orthogonal,
qreal borderWidth, const QskGradient& );
int fillCount() const;
@ -44,10 +44,14 @@ namespace
int arcLineCount() const;
qreal radiansAt( qreal progress ) const;
void setFillLine( const qreal radians,
void setOrthogonalLine( const qreal radians,
const QskVertex::Color, QskVertex::ColoredLine& ) const;
void setRadialLine( const qreal radians,
const QskVertex::Color, QskVertex::ColoredLine& ) const;
const qreal m_extent;
const bool m_orthogonal;
// radius
const qreal m_rx;
@ -60,13 +64,14 @@ namespace
const qreal m_radians1;
const qreal m_radians2;
const QskGradient& m_gradient;
};
EllipseStroker::EllipseStroker( const QRectF& rect,
const QskArcMetrics& m, qreal borderWidth, const QskGradient& gradient )
const QskArcMetrics& m, bool orthogonal, qreal borderWidth,
const QskGradient& gradient )
: m_extent( 0.5 * ( m.thickness() - borderWidth ) )
, m_orthogonal( orthogonal )
, m_rx( 0.5 * rect.width() - m_extent )
, m_ry( 0.5 * rect.height() - m_extent )
, m_cx( rect.center().x() )
@ -107,7 +112,7 @@ namespace
return 0;
}
inline void EllipseStroker::setFillLine( const qreal radians,
inline void EllipseStroker::setOrthogonalLine( const qreal radians,
const QskVertex::Color color, QskVertex::ColoredLine& line ) const
{
const auto cos = qFastCos( radians );
@ -151,6 +156,34 @@ namespace
line.setLine( x + dx, y - dy, x - dx, y + dy, color );
}
inline void EllipseStroker::setRadialLine( const qreal radians,
const QskVertex::Color color, QskVertex::ColoredLine& line ) const
{
const auto cos = qFastCos( radians );
const auto sin = qFastSin( radians );
const auto t = 2.0 * m_extent;
const auto w = 2.0 * m_rx + t;
const auto h = 2.0 * m_ry + t;
const auto x1 = 0.5 * w * cos;
const auto y1 = 0.5 * h * sin;
const auto sz = qMin( w, h );
const auto tx = t * w / sz;
const auto ty = t * h / sz;
const auto w2 = w - 2 * tx;
const auto h2 = h - 2 * ty;
const auto x2 = 0.5 * w2 * cos;
const auto y2 = 0.5 * h2 * sin;
line.setLine( m_cx + x1, m_cy - y1, m_cx + x2, m_cy - y2, color );
}
int EllipseStroker::setFillLines( QskVertex::ColoredLine* lines ) const
{
auto l = lines;
@ -177,12 +210,20 @@ namespace
while( !it.isDone() && ( it.position() < progress ) )
{
setFillLine( radiansAt( it.position() ), it.color(), *l++ );
if ( m_orthogonal )
setOrthogonalLine( radiansAt( it.position() ), it.color(), *l++ );
else
setRadialLine( radiansAt( it.position() ), it.color(), *l++ );
it.advance();
}
const auto color = it.colorAt( progress );
setFillLine( m_radians1 + i * stepSize, color, *l++ );
if ( m_orthogonal )
setOrthogonalLine( m_radians1 + i * stepSize, color, *l++ );
else
setRadialLine( m_radians1 + i * stepSize, color, *l++ );
}
return l - lines;
@ -203,12 +244,16 @@ bool QskArcRenderer::isGradientSupported( const QskGradient& gradient )
}
void QskArcRenderer::renderFillGeometry( const QRectF& rect,
const QskArcMetrics& metrics, qreal borderWidth,
const QskArcMetrics& metrics, bool radial, qreal borderWidth,
const QskGradient& gradient, QSGGeometry& geometry )
{
#if 1
// TODO ...
borderWidth = 0.0;
#endif
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
EllipseStroker stroker( rect, metrics, borderWidth, gradient );
EllipseStroker stroker( rect, metrics, !radial, borderWidth, gradient );
const auto lineCount = stroker.fillCount();
@ -236,11 +281,11 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect,
}
void QskArcRenderer::renderBorder( const QRectF& rect, const QskArcMetrics& metrics,
qreal borderWidth, const QColor& borderColor, QSGGeometry& geometry )
bool radial, qreal borderWidth, const QColor& borderColor, QSGGeometry& geometry )
{
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
EllipseStroker stroker( rect, metrics, borderWidth, QskGradient() );
EllipseStroker stroker( rect, metrics, !radial, borderWidth, QskGradient() );
const auto lineCount = stroker.borderCount();
@ -254,3 +299,24 @@ void QskArcRenderer::renderBorder( const QRectF& rect, const QskArcMetrics& metr
}
}
}
void QskArcRenderer::renderBorderGeometry( const QRectF& rect,
const QskArcMetrics& metrics, bool radial, qreal borderWidth, QSGGeometry& geometry )
{
Q_UNUSED( rect );
Q_UNUSED( metrics );
Q_UNUSED( radial );
Q_UNUSED( borderWidth );
Q_UNUSED( geometry );
}
void QskArcRenderer::renderFillGeometry( const QRectF& rect,
const QskArcMetrics& metrics, bool radial, qreal borderWidth, QSGGeometry& geometry )
{
Q_UNUSED( rect );
Q_UNUSED( metrics );
Q_UNUSED( radial );
Q_UNUSED( borderWidth );
Q_UNUSED( geometry );
}

View File

@ -26,10 +26,10 @@ namespace QskArcRenderer
*/
QSK_EXPORT void renderBorderGeometry( const QRectF&,
const QskArcMetrics&, qreal borderWidth, QSGGeometry& );
const QskArcMetrics&, bool radial, qreal borderWidth, QSGGeometry& );
QSK_EXPORT void renderFillGeometry( const QRectF&,
const QskArcMetrics&, qreal borderWidth, QSGGeometry& );
const QskArcMetrics&, bool radial, qreal borderWidth, QSGGeometry& );
/*
Filling the geometry with color information:
@ -38,10 +38,10 @@ namespace QskArcRenderer
QSK_EXPORT bool isGradientSupported( const QskGradient& );
QSK_EXPORT void renderBorder( const QRectF&, const QskArcMetrics&,
qreal borderWidth, const QColor& borderColor, QSGGeometry& );
bool radial, qreal borderWidth, const QColor& borderColor, QSGGeometry& );
QSK_EXPORT void renderFillGeometry( const QRectF&, const QskArcMetrics&,
qreal borderWidth, const QskGradient&, QSGGeometry& );
bool radial, qreal borderWidth, const QskGradient&, QSGGeometry& );
}
#endif