qskinny/src/nodes/QskStrokeNode.cpp

137 lines
3.7 KiB
C++
Raw Normal View History

/******************************************************************************
2024-01-17 14:31:45 +01:00
* QSkinny - Copyright (C) The authors
2023-04-06 09:23:37 +02:00
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskStrokeNode.h"
#include "QskVertex.h"
2023-11-15 11:47:56 +01:00
#include "QskGradient.h"
2024-09-24 10:14:26 +02:00
#include "QskRgbValue.h"
#include <qpainterpath.h>
QSK_QT_PRIVATE_BEGIN
#include <private/qtriangulatingstroker_p.h>
QSK_QT_PRIVATE_END
2023-11-15 11:47:56 +01:00
static inline bool qskIsPenVisible( const QPen& pen )
{
2023-11-15 11:47:56 +01:00
if ( pen.style() == Qt::NoPen )
return false;
2023-11-15 11:47:56 +01:00
if ( pen.brush().gradient() )
{
2023-11-15 11:47:56 +01:00
// TODO ...
}
else
{
2024-09-24 10:14:26 +02:00
if ( !QskRgb::isVisible( pen.color() ) )
2023-11-15 11:47:56 +01:00
return false;
}
2023-11-15 11:47:56 +01:00
return true;
}
QskStrokeNode::QskStrokeNode()
{
}
2023-05-17 14:21:40 +02:00
QskStrokeNode::~QskStrokeNode() = default;
void QskStrokeNode::updatePath( const QPainterPath& path, const QPen& pen )
{
updatePath( path, QTransform(), pen );
}
void QskStrokeNode::updatePath(
2023-11-15 11:47:56 +01:00
const QPainterPath& path, const QTransform& transform, const QPen& pen )
{
2023-11-15 11:47:56 +01:00
if ( path.isEmpty() || !qskIsPenVisible( pen ) )
{
resetGeometry();
return;
}
2023-11-15 11:47:56 +01:00
if ( auto qGradient = pen.brush().gradient() )
{
2023-11-15 11:47:56 +01:00
const auto r = transform.mapRect( path.boundingRect() );
2023-11-15 11:47:56 +01:00
QskGradient gradient( *qGradient );
gradient.setStretchMode( QskGradient::StretchToSize );
setColoring( r, gradient );
}
2023-11-15 11:47:56 +01:00
else
setColoring( pen.color() );
if ( true ) // For the moment we always update the geometry. TODO ...
{
2022-09-29 17:26:15 +02:00
/*
Unfortunately QTriangulatingStroker does not offer on the fly
transformations - like with qTriangulate. TODO ...
*/
const auto scaledPath = transform.map( path );
2022-09-30 15:09:52 +02:00
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
2022-09-30 15:09:52 +02:00
stroker.process( qtVectorPathForPath( scaledPath ), effectivePen, {}, {} );
}
else
{
2022-09-29 17:26:15 +02:00
constexpr QRectF clipRect; // empty rect: no clipping
QDashedStrokeProcessor dashStroker;
2023-11-15 11:47:56 +01:00
dashStroker.process( qtVectorPathForPath( scaledPath ),
effectivePen, clipRect, {} );
const QVectorPath dashedVectorPath( dashStroker.points(),
dashStroker.elementCount(), dashStroker.elementTypes(), 0 );
2022-09-30 15:09:52 +02:00
stroker.process( dashedVectorPath, effectivePen, {}, {} );
}
2023-11-15 11:47:56 +01:00
auto& geometry = *this->geometry();
2022-10-18 17:36:55 +02:00
// 2 vertices for each point
2023-11-15 11:47:56 +01:00
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
geometry.allocate( stroker.vertexCount() / 2 );
2023-11-15 11:47:56 +01:00
if ( isGeometryColored() )
{
const QskVertex::Color c( pen.color() );
const auto v = stroker.vertices();
2023-11-15 11:47:56 +01:00
auto points = geometry.vertexDataAsColoredPoint2D();
2023-11-15 11:47:56 +01:00
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
{
2023-11-15 11:47:56 +01:00
memcpy( geometry.vertexData(), stroker.vertices(),
stroker.vertexCount() * sizeof( float ) );
}
2023-11-15 11:47:56 +01:00
geometry.markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry );
}
}