2022-09-23 17:49:49 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskStrokeNode.h"
|
|
|
|
#include <qsgflatcolormaterial.h>
|
|
|
|
|
|
|
|
QSK_QT_PRIVATE_BEGIN
|
|
|
|
#include <private/qsgnode_p.h>
|
|
|
|
#include <private/qtriangulatingstroker_p.h>
|
|
|
|
QSK_QT_PRIVATE_END
|
|
|
|
|
|
|
|
class QskStrokeNodePrivate final : public QSGGeometryNodePrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QskStrokeNodePrivate()
|
|
|
|
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
|
|
|
{
|
|
|
|
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
|
|
|
}
|
|
|
|
|
|
|
|
QSGGeometry geometry;
|
|
|
|
QSGFlatColorMaterial material;
|
|
|
|
};
|
|
|
|
|
|
|
|
QskStrokeNode::QskStrokeNode()
|
|
|
|
: QSGGeometryNode( *new QskStrokeNodePrivate )
|
|
|
|
{
|
|
|
|
Q_D( QskStrokeNode );
|
|
|
|
|
|
|
|
setGeometry( &d->geometry );
|
|
|
|
setMaterial( &d->material );
|
|
|
|
}
|
|
|
|
|
2022-09-29 17:26:15 +02:00
|
|
|
void QskStrokeNode::updateNode(
|
|
|
|
const QPainterPath& path, const QTransform& transform, const QPen& pen )
|
2022-09-23 17:49:49 +02:00
|
|
|
{
|
|
|
|
Q_D( QskStrokeNode );
|
|
|
|
|
2022-09-29 17:26:15 +02:00
|
|
|
if ( path.isEmpty() || ( pen.style() == Qt::NoPen ) ||
|
|
|
|
!pen.color().isValid() || ( pen.color().alpha() == 0 ) )
|
2022-09-23 17:49:49 +02:00
|
|
|
{
|
|
|
|
if ( d->geometry.vertexCount() > 0 )
|
|
|
|
{
|
|
|
|
d->geometry.allocate( 0 );
|
|
|
|
markDirty( QSGNode::DirtyGeometry );
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-23 17:49:49 +02:00
|
|
|
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, {}, {} );
|
2022-09-23 17:49:49 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-29 17:26:15 +02:00
|
|
|
constexpr QRectF clipRect; // empty rect: no clipping
|
|
|
|
|
2022-09-23 17:49:49 +02:00
|
|
|
QDashedStrokeProcessor dashStroker;
|
2022-09-30 15:09:52 +02:00
|
|
|
dashStroker.process( qtVectorPathForPath( scaledPath ), effectivePen, clipRect, {} );
|
2022-09-23 17:49:49 +02:00
|
|
|
|
|
|
|
const QVectorPath dashedVectorPath( dashStroker.points(),
|
|
|
|
dashStroker.elementCount(), dashStroker.elementTypes(), 0 );
|
|
|
|
|
2022-09-30 15:09:52 +02:00
|
|
|
stroker.process( dashedVectorPath, effectivePen, {}, {} );
|
2022-09-23 17:49:49 +02:00
|
|
|
}
|
|
|
|
|
2022-10-18 17:36:55 +02:00
|
|
|
// 2 vertices for each point
|
|
|
|
d->geometry.allocate( stroker.vertexCount() / 2 );
|
2022-09-23 17:49:49 +02:00
|
|
|
|
|
|
|
memcpy( d->geometry.vertexData(), stroker.vertices(),
|
|
|
|
stroker.vertexCount() * sizeof( float ) );
|
|
|
|
|
|
|
|
markDirty( QSGNode::DirtyGeometry );
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto color = pen.color().toRgb();
|
|
|
|
|
|
|
|
if ( d->material.color() != color )
|
|
|
|
{
|
|
|
|
d->material.setColor( color );
|
|
|
|
markDirty( QSGNode::DirtyMaterial );
|
|
|
|
}
|
|
|
|
}
|