137 lines
3.7 KiB
C++
137 lines
3.7 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) The authors
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*****************************************************************************/
|
|
|
|
#include "QskStrokeNode.h"
|
|
#include "QskVertex.h"
|
|
#include "QskGradient.h"
|
|
#include "QskRgbValue.h"
|
|
|
|
#include <qpainterpath.h>
|
|
|
|
QSK_QT_PRIVATE_BEGIN
|
|
#include <private/qtriangulatingstroker_p.h>
|
|
QSK_QT_PRIVATE_END
|
|
|
|
static inline bool qskIsPenVisible( const QPen& pen )
|
|
{
|
|
if ( pen.style() == Qt::NoPen )
|
|
return false;
|
|
|
|
if ( pen.brush().gradient() )
|
|
{
|
|
// TODO ...
|
|
}
|
|
else
|
|
{
|
|
if ( !QskRgb::isVisible( pen.color() ) )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
QskStrokeNode::QskStrokeNode()
|
|
{
|
|
}
|
|
|
|
QskStrokeNode::~QskStrokeNode() = default;
|
|
|
|
void QskStrokeNode::updatePath( const QPainterPath& path, const QPen& pen )
|
|
{
|
|
updatePath( path, QTransform(), pen );
|
|
}
|
|
|
|
void QskStrokeNode::updatePath(
|
|
const QPainterPath& path, const QTransform& transform, const QPen& pen )
|
|
{
|
|
if ( path.isEmpty() || !qskIsPenVisible( pen ) )
|
|
{
|
|
resetGeometry();
|
|
return;
|
|
}
|
|
|
|
if ( auto qGradient = pen.brush().gradient() )
|
|
{
|
|
const auto r = transform.mapRect( path.boundingRect() );
|
|
|
|
QskGradient gradient( *qGradient );
|
|
gradient.setStretchMode( QskGradient::StretchToSize );
|
|
|
|
setColoring( r, gradient );
|
|
}
|
|
else
|
|
setColoring( pen.color() );
|
|
|
|
if ( true ) // For the moment we always update the geometry. TODO ...
|
|
{
|
|
/*
|
|
Unfortunately QTriangulatingStroker does not offer on the fly
|
|
transformations - like with qTriangulate. TODO ...
|
|
*/
|
|
const auto scaledPath = transform.map( path );
|
|
|
|
auto effectivePen = pen;
|
|
|
|
if ( !effectivePen.isCosmetic() )
|
|
{
|
|
const auto scaleFactor = qMin( transform.m11(), transform.m22() );
|
|
if ( scaleFactor != 1.0 )
|
|
{
|
|
effectivePen.setWidth( effectivePen.widthF() * scaleFactor );
|
|
effectivePen.setCosmetic( false );
|
|
}
|
|
}
|
|
|
|
QTriangulatingStroker stroker;
|
|
|
|
if ( pen.style() == Qt::SolidLine )
|
|
{
|
|
// clipRect, renderHint are ignored in QTriangulatingStroker::process
|
|
stroker.process( qtVectorPathForPath( scaledPath ), effectivePen, {}, {} );
|
|
}
|
|
else
|
|
{
|
|
constexpr QRectF clipRect; // empty rect: no clipping
|
|
|
|
QDashedStrokeProcessor dashStroker;
|
|
dashStroker.process( qtVectorPathForPath( scaledPath ),
|
|
effectivePen, clipRect, {} );
|
|
|
|
const QVectorPath dashedVectorPath( dashStroker.points(),
|
|
dashStroker.elementCount(), dashStroker.elementTypes(), 0 );
|
|
|
|
stroker.process( dashedVectorPath, effectivePen, {}, {} );
|
|
}
|
|
|
|
auto& geometry = *this->geometry();
|
|
|
|
// 2 vertices for each point
|
|
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
|
geometry.allocate( stroker.vertexCount() / 2 );
|
|
|
|
if ( isGeometryColored() )
|
|
{
|
|
const QskVertex::Color c( pen.color() );
|
|
|
|
const auto v = stroker.vertices();
|
|
auto points = geometry.vertexDataAsColoredPoint2D();
|
|
|
|
for ( int i = 0; i < geometry.vertexCount(); i++ )
|
|
{
|
|
const auto j = 2 * i;
|
|
points[i].set( v[j], v[j + 1], c.r, c.g, c.b, c.a );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy( geometry.vertexData(), stroker.vertices(),
|
|
stroker.vertexCount() * sizeof( float ) );
|
|
}
|
|
|
|
geometry.markVertexDataDirty();
|
|
markDirty( QSGNode::DirtyGeometry );
|
|
}
|
|
}
|