qskinny/src/nodes/QskShapeNode.cpp

144 lines
4.0 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 "QskShapeNode.h"
2022-10-31 14:42:08 +01:00
#include "QskGradient.h"
#include "QskGradientDirection.h"
#include "QskVertex.h"
2023-11-15 11:47:56 +01:00
#include "QskFillNodePrivate.h"
QSK_QT_PRIVATE_BEGIN
#include <private/qvectorpath_p.h>
#include <private/qtriangulator_p.h>
QSK_QT_PRIVATE_END
2024-09-25 07:51:02 +02:00
#if 0
// keeping the index list
2022-09-29 16:50:46 +02:00
static void qskUpdateGeometry( const QPainterPath& path,
const QTransform& transform, QSGGeometry& geometry )
{
2022-09-29 16:50:46 +02:00
const auto ts = qTriangulate( path, transform, 1, false );
geometry.allocate( ts.vertices.size(), ts.indices.size() );
2022-09-26 17:50:07 +02:00
auto vertexData = reinterpret_cast< float* >( geometry.vertexData() );
const auto points = ts.vertices.constData();
for ( int i = 0; i < ts.vertices.size(); i++ )
vertexData[i] = points[i];
memcpy( geometry.indexData(), ts.indices.data(),
ts.indices.size() * sizeof( quint16 ) );
2024-09-25 07:51:02 +02:00
}
#endif
static void qskUpdateGeometry( const QPainterPath& path,
const QTransform& transform, const QColor& color, QSGGeometry& geometry )
2024-09-25 07:51:02 +02:00
{
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.
2024-09-25 07:51:02 +02:00
As we have to iterate over the vertex buffer to copy qreal to float
2024-09-25 07:51:02 +02:00
anyway we reorder according to the index buffer and drop
the index buffer.
QTriangleSet:
vertices: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ...
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], ...]
*/
2024-09-25 07:51:02 +02:00
const auto points = ts.vertices.constData();
const auto indices = reinterpret_cast< const quint16* >( ts.indices.data() );
geometry.allocate( ts.indices.size() );
if ( color.isValid() )
{
const QskVertex::Color c = color;
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] );
}
}
}
2023-11-15 11:47:56 +01:00
class QskShapeNodePrivate final : public QskFillNodePrivate
{
public:
/*
Is there a better way to find out if the path has changed
beside storing a copy ( even, when internally with Copy On Write ) ?
*/
QPainterPath path;
QTransform transform;
};
QskShapeNode::QskShapeNode()
2023-11-15 11:47:56 +01:00
: QskFillNode( *new QskShapeNodePrivate )
{
2023-11-15 11:47:56 +01:00
geometry()->setDrawingMode( QSGGeometry::DrawTriangles );
}
2023-04-12 12:17:38 +02:00
QskShapeNode::~QskShapeNode()
{
}
2022-09-29 16:50:46 +02:00
void QskShapeNode::updateNode( const QPainterPath& path,
2022-10-31 14:42:08 +01:00
const QTransform& transform, const QRectF& rect, const QskGradient& gradient )
{
Q_D( QskShapeNode );
2022-10-31 14:42:08 +01:00
if ( path.isEmpty() || !gradient.isVisible() )
2022-09-29 12:40:22 +02:00
{
d->path = QPainterPath();
2022-12-05 13:05:13 +01:00
d->transform = QTransform();
2023-11-15 11:47:56 +01:00
resetGeometry();
2022-09-29 12:40:22 +02:00
return;
}
QColor c;
if ( gradient.isMonochrome() && hasHint( PreferColoredGeometry ) )
c = gradient.startColor();
const bool isDirty = ( isGeometryColored() != c.isValid() );
if ( c.isValid() )
setColoring( QskFillNode::Polychrome );
else
setColoring( rect, gradient );
2023-11-15 11:47:56 +01:00
if ( isDirty || ( transform != d->transform ) || ( path != d->path ) )
{
d->path = path;
d->transform = transform;
qskUpdateGeometry( path, transform, c, *geometry() );
2023-11-15 11:47:56 +01:00
geometry()->markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry );
}
}