diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/imports.pro | 2 | ||||
-rw-r--r-- | src/imports/pathitem/pathitem.pro | 31 | ||||
-rw-r--r-- | src/imports/pathitem/qmldir | 4 | ||||
-rw-r--r-- | src/imports/pathitem/qquickpathitem.cpp | 2258 | ||||
-rw-r--r-- | src/imports/shapes/plugin.cpp (renamed from src/imports/pathitem/plugin.cpp) | 20 | ||||
-rw-r--r-- | src/imports/shapes/plugins.qmltypes (renamed from src/imports/pathitem/plugins.qmltypes) | 48 | ||||
-rw-r--r-- | src/imports/shapes/qmldir | 4 | ||||
-rw-r--r-- | src/imports/shapes/qquicknvprfunctions.cpp (renamed from src/imports/pathitem/qquicknvprfunctions.cpp) | 7 | ||||
-rw-r--r-- | src/imports/shapes/qquicknvprfunctions_p.h (renamed from src/imports/pathitem/qquicknvprfunctions_p.h) | 22 | ||||
-rw-r--r-- | src/imports/shapes/qquicknvprfunctions_p_p.h (renamed from src/imports/pathitem/qquicknvprfunctions_p_p.h) | 0 | ||||
-rw-r--r-- | src/imports/shapes/qquickshape.cpp | 1485 | ||||
-rw-r--r-- | src/imports/shapes/qquickshape_p.h (renamed from src/imports/pathitem/qquickpathitem_p.h) | 62 | ||||
-rw-r--r-- | src/imports/shapes/qquickshape_p_p.h (renamed from src/imports/pathitem/qquickpathitem_p_p.h) | 94 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapegenericrenderer.cpp (renamed from src/imports/pathitem/qquickpathitemgenericrenderer.cpp) | 186 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapegenericrenderer_p.h (renamed from src/imports/pathitem/qquickpathitemgenericrenderer_p.h) | 112 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapenvprrenderer.cpp (renamed from src/imports/pathitem/qquickpathitemnvprrenderer.cpp) | 146 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapenvprrenderer_p.h (renamed from src/imports/pathitem/qquickpathitemnvprrenderer_p.h) | 68 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapesoftwarerenderer.cpp (renamed from src/imports/pathitem/qquickpathitemsoftwarerenderer.cpp) | 92 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapesoftwarerenderer_p.h (renamed from src/imports/pathitem/qquickpathitemsoftwarerenderer_p.h) | 46 | ||||
-rw-r--r-- | src/imports/shapes/shapes.pro | 31 | ||||
-rw-r--r-- | src/quick/util/qquickpath.cpp | 16 |
21 files changed, 1961 insertions, 2773 deletions
diff --git a/src/imports/imports.pro b/src/imports/imports.pro index df0ad01c06..3c7f96eff9 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -23,7 +23,7 @@ qtHaveModule(quick) { qtConfig(quick-particles): \ SUBDIRS += particles - SUBDIRS += pathitem + SUBDIRS += shapes } qtHaveModule(xmlpatterns) : SUBDIRS += xmllistmodel diff --git a/src/imports/pathitem/pathitem.pro b/src/imports/pathitem/pathitem.pro deleted file mode 100644 index d70bb6f203..0000000000 --- a/src/imports/pathitem/pathitem.pro +++ /dev/null @@ -1,31 +0,0 @@ -CXX_MODULE = qml -TARGET = qmlpathitemplugin -TARGETPATH = Qt/labs/pathitem -IMPORT_VERSION = 1.0 - -QT = core gui qml quick quick-private - -HEADERS += \ - qquickpathitem_p.h \ - qquickpathitem_p_p.h \ - qquickpathitemgenericrenderer_p.h \ - qquickpathitemsoftwarerenderer_p.h - -SOURCES += \ - plugin.cpp \ - qquickpathitem.cpp \ - qquickpathitemgenericrenderer.cpp \ - qquickpathitemsoftwarerenderer.cpp - -qtConfig(opengl) { - HEADERS += \ - qquicknvprfunctions_p.h \ - qquicknvprfunctions_p_p.h \ - qquickpathitemnvprrenderer_p.h - - SOURCES += \ - qquicknvprfunctions.cpp \ - qquickpathitemnvprrenderer.cpp -} - -load(qml_plugin) diff --git a/src/imports/pathitem/qmldir b/src/imports/pathitem/qmldir deleted file mode 100644 index 277b8a199b..0000000000 --- a/src/imports/pathitem/qmldir +++ /dev/null @@ -1,4 +0,0 @@ -module Qt.labs.pathitem -plugin qmlpathitemplugin -classname QmlPathItemPlugin -typeinfo plugins.qmltypes diff --git a/src/imports/pathitem/qquickpathitem.cpp b/src/imports/pathitem/qquickpathitem.cpp deleted file mode 100644 index 5255a55798..0000000000 --- a/src/imports/pathitem/qquickpathitem.cpp +++ /dev/null @@ -1,2258 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpathitem_p.h" -#include "qquickpathitem_p_p.h" -#include "qquickpathitemgenericrenderer_p.h" -#include "qquickpathitemnvprrenderer_p.h" -#include "qquickpathitemsoftwarerenderer_p.h" -#include <private/qsgtexture_p.h> -#include <private/qquicksvgparser_p.h> -#include <QtGui/private/qdrawhelper_p.h> -#include <QOpenGLFunctions> - -#include <private/qv4engine_p.h> -#include <private/qv4object_p.h> -#include <private/qv4qobjectwrapper_p.h> -#include <private/qv4mm_p.h> -#include <private/qqmlengine_p.h> - -QT_BEGIN_NAMESPACE - -QQuickPathItemStrokeFillParams::QQuickPathItemStrokeFillParams() - : strokeColor(Qt::white), - strokeWidth(1), - fillColor(Qt::white), - fillRule(QQuickVisualPath::OddEvenFill), - joinStyle(QQuickVisualPath::BevelJoin), - miterLimit(2), - capStyle(QQuickVisualPath::SquareCap), - strokeStyle(QQuickVisualPath::SolidLine), - dashOffset(0), - fillGradient(nullptr) -{ - dashPattern << 4 << 2; // 4 * strokeWidth dash followed by 2 * strokeWidth space -} - -QPainterPath QQuickPathItemPath::toPainterPath() const -{ - QPainterPath p; - int coordIdx = 0; - for (int i = 0; i < cmd.count(); ++i) { - switch (cmd[i]) { - case QQuickPathItemPath::MoveTo: - p.moveTo(coords[coordIdx], coords[coordIdx + 1]); - coordIdx += 2; - break; - case QQuickPathItemPath::LineTo: - p.lineTo(coords[coordIdx], coords[coordIdx + 1]); - coordIdx += 2; - break; - case QQuickPathItemPath::QuadTo: - p.quadTo(coords[coordIdx], coords[coordIdx + 1], - coords[coordIdx + 2], coords[coordIdx + 3]); - coordIdx += 4; - break; - case QQuickPathItemPath::CubicTo: - p.cubicTo(coords[coordIdx], coords[coordIdx + 1], - coords[coordIdx + 2], coords[coordIdx + 3], - coords[coordIdx + 4], coords[coordIdx + 5]); - coordIdx += 6; - break; - case QQuickPathItemPath::ArcTo: - // does not map to the QPainterPath API; reuse the helper code from QQuickSvgParser - QQuickSvgParser::pathArc(p, - coords[coordIdx], coords[coordIdx + 1], // radius - coords[coordIdx + 2], // xAxisRotation - !qFuzzyIsNull(coords[coordIdx + 6]), // useLargeArc - !qFuzzyIsNull(coords[coordIdx + 5]), // sweep flag - coords[coordIdx + 3], coords[coordIdx + 4], // end - p.currentPosition().x(), p.currentPosition().y()); - coordIdx += 7; - break; - default: - qWarning("Unknown JS path command: %d", cmd[i]); - break; - } - } - return p; -} - -/*! - \qmltype VisualPath - \instantiates QQuickVisualPath - \inqmlmodule QtQuick - \ingroup qtquick-paths - \ingroup qtquick-views - \inherits Object - \brief Describes a Path and associated properties for stroking and filling - \since 5.10 - - A PathItem contains one or more VisualPath elements. At least one - VisualPath is necessary in order to have a PathItem output anything - visible. A VisualPath in turn contains a Path and properties describing the - stroking and filling parameters, such as the stroke width and color, the - fill color or gradient, join and cap styles, and so on. Finally, the Path - object contains a list of path elements like PathMove, PathLine, PathCubic, - PathQuad, PathArc. - - Any property changes in these data sets will be bubble up and change the - output of the PathItem. This means that it is simple and easy to change, or - even animate, the starting and ending position, control points, or any - stroke or fill parameters using the usual QML bindings and animation types - like NumberAnimation. - - In the following example the line join style changes automatically based on - the value of joinStyleIndex: - - \code - VisualPath { - strokeColor: "black" - strokeWidth: 16 - fillColor: "transparent" - capStyle: VisualPath.RoundCap - - property int joinStyleIndex: 0 - property variant styles: [ VisualPath.BevelJoin, VisualPath.MiterJoin, VisualPath.RoundJoin ] - - joinStyle: styles[joinStyleIndex] - - Path { - startX: 30 - startY: 30 - PathLine { x: 100; y: 100 } - PathLine { x: 30; y: 100 } - } - } - \endcode - - Once associated with a PathItem, here is the output with a joinStyleIndex - of 2 (VisualPath.RoundJoin): - - \image visualpath-code-example.png - */ - -QQuickVisualPathPrivate::QQuickVisualPathPrivate() - : path(nullptr), - dirty(DirtyAll) -{ -} - -QQuickVisualPath::QQuickVisualPath(QObject *parent) - : QObject(*(new QQuickVisualPathPrivate), parent) -{ -} - -QQuickVisualPath::~QQuickVisualPath() -{ -} - -/*! - \qmlproperty Path QtQuick::VisualPath::path - - This property holds the Path object. - - \default - */ - -QQuickPath *QQuickVisualPath::path() const -{ - Q_D(const QQuickVisualPath); - return d->path; -} - -void QQuickVisualPath::setPath(QQuickPath *path) -{ - Q_D(QQuickVisualPath); - if (d->path == path) - return; - - if (d->path) - qmlobject_disconnect(d->path, QQuickPath, SIGNAL(changed()), - this, QQuickVisualPath, SLOT(_q_pathChanged())); - d->path = path; - qmlobject_connect(d->path, QQuickPath, SIGNAL(changed()), - this, QQuickVisualPath, SLOT(_q_pathChanged())); - - d->dirty |= QQuickVisualPathPrivate::DirtyPath; - emit pathChanged(); - emit changed(); -} - -void QQuickVisualPathPrivate::_q_pathChanged() -{ - Q_Q(QQuickVisualPath); - dirty |= DirtyPath; - emit q->changed(); -} - -/*! - \qmlproperty color QtQuick::VisualPath::strokeColor - - This property holds the stroking color. - - When set to \c transparent, no stroking occurs. - - The default value is \c white. - */ - -QColor QQuickVisualPath::strokeColor() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.strokeColor; -} - -void QQuickVisualPath::setStrokeColor(const QColor &color) -{ - Q_D(QQuickVisualPath); - if (d->sfp.strokeColor != color) { - d->sfp.strokeColor = color; - d->dirty |= QQuickVisualPathPrivate::DirtyStrokeColor; - emit strokeColorChanged(); - emit changed(); - } -} - -/*! - \qmlproperty color QtQuick::VisualPath::strokeWidth - - This property holds the stroke width. - - When set to a negative value, no stroking occurs. - - The default value is 1. - */ - -qreal QQuickVisualPath::strokeWidth() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.strokeWidth; -} - -void QQuickVisualPath::setStrokeWidth(qreal w) -{ - Q_D(QQuickVisualPath); - if (d->sfp.strokeWidth != w) { - d->sfp.strokeWidth = w; - d->dirty |= QQuickVisualPathPrivate::DirtyStrokeWidth; - emit strokeWidthChanged(); - emit changed(); - } -} - -/*! - \qmlproperty color QtQuick::VisualPath::fillColor - - This property holds the fill color. - - When set to \c transparent, no filling occurs. - - The default value is \c white. - */ - -QColor QQuickVisualPath::fillColor() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.fillColor; -} - -void QQuickVisualPath::setFillColor(const QColor &color) -{ - Q_D(QQuickVisualPath); - if (d->sfp.fillColor != color) { - d->sfp.fillColor = color; - d->dirty |= QQuickVisualPathPrivate::DirtyFillColor; - emit fillColorChanged(); - emit changed(); - } -} - -/*! - \qmlproperty enumeration QtQuick::VisualPath::fillRule - - This property holds the fill rule. The default value is - VisualPath.OddEvenFill. For an example on fill rules, see - QPainterPath::setFillRule(). - - \list - \li VisualPath.OddEvenFill - \li VisualPath.WindingFill - \endlist - */ - -QQuickVisualPath::FillRule QQuickVisualPath::fillRule() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.fillRule; -} - -void QQuickVisualPath::setFillRule(FillRule fillRule) -{ - Q_D(QQuickVisualPath); - if (d->sfp.fillRule != fillRule) { - d->sfp.fillRule = fillRule; - d->dirty |= QQuickVisualPathPrivate::DirtyFillRule; - emit fillRuleChanged(); - emit changed(); - } -} - -/*! - \qmlproperty enumeration QtQuick::VisualPath::joinStyle - - This property defines how joins between two connected lines are drawn. The - default value is VisualPath.BevelJoin. - - \list - \li VisualPath.MiterJoin - The outer edges of the lines are extended to meet at an angle, and this area is filled. - \li VisualPath.BevelJoin - The triangular notch between the two lines is filled. - \li VisualPath.RoundJoin - A circular arc between the two lines is filled. - \endlist - */ - -QQuickVisualPath::JoinStyle QQuickVisualPath::joinStyle() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.joinStyle; -} - -void QQuickVisualPath::setJoinStyle(JoinStyle style) -{ - Q_D(QQuickVisualPath); - if (d->sfp.joinStyle != style) { - d->sfp.joinStyle = style; - d->dirty |= QQuickVisualPathPrivate::DirtyStyle; - emit joinStyleChanged(); - emit changed(); - } -} - -/*! - \qmlproperty int QtQuick::VisualPath::miterLimit - - When VisualPath.joinStyle is set to VisualPath.MiterJoin, this property - specifies how far the miter join can extend from the join point. - - The default value is 2. - */ - -int QQuickVisualPath::miterLimit() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.miterLimit; -} - -void QQuickVisualPath::setMiterLimit(int limit) -{ - Q_D(QQuickVisualPath); - if (d->sfp.miterLimit != limit) { - d->sfp.miterLimit = limit; - d->dirty |= QQuickVisualPathPrivate::DirtyStyle; - emit miterLimitChanged(); - emit changed(); - } -} - -/*! - \qmlproperty enumeration QtQuick::VisualPath::capStyle - - This property defines how the end points of lines are drawn. The - default value is VisualPath.SquareCap. - - \list - \li VisualPath.FlatCap - A square line end that does not cover the end point of the line. - \li VisualPath.SquareCap - A square line end that covers the end point and extends beyond it by half the line width. - \li VisualPath.RoundCap - A rounded line end. - \endlist - */ - -QQuickVisualPath::CapStyle QQuickVisualPath::capStyle() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.capStyle; -} - -void QQuickVisualPath::setCapStyle(CapStyle style) -{ - Q_D(QQuickVisualPath); - if (d->sfp.capStyle != style) { - d->sfp.capStyle = style; - d->dirty |= QQuickVisualPathPrivate::DirtyStyle; - emit capStyleChanged(); - emit changed(); - } -} - -/*! - \qmlproperty enumeration QtQuick::VisualPath::strokeStyle - - This property defines the style of stroking. The default value is - VisualPath.SolidLine. - - \list - \li VisualPath.SolidLine - A plain line. - \li VisualPath.DashLine - Dashes separated by a few pixels. - \endlist - */ - -QQuickVisualPath::StrokeStyle QQuickVisualPath::strokeStyle() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.strokeStyle; -} - -void QQuickVisualPath::setStrokeStyle(StrokeStyle style) -{ - Q_D(QQuickVisualPath); - if (d->sfp.strokeStyle != style) { - d->sfp.strokeStyle = style; - d->dirty |= QQuickVisualPathPrivate::DirtyDash; - emit strokeStyleChanged(); - emit changed(); - } -} - -/*! - \qmlproperty real QtQuick::VisualPath::dashOffset - - This property defines the starting point on the dash pattern, measured in - units used to specify the dash pattern. - - The default value is 0. - - \sa QPen::setDashOffset() - */ - -qreal QQuickVisualPath::dashOffset() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.dashOffset; -} - -void QQuickVisualPath::setDashOffset(qreal offset) -{ - Q_D(QQuickVisualPath); - if (d->sfp.dashOffset != offset) { - d->sfp.dashOffset = offset; - d->dirty |= QQuickVisualPathPrivate::DirtyDash; - emit dashOffsetChanged(); - emit changed(); - } -} - -/*! - \qmlproperty list<real> QtQuick::VisualPath::dashPattern - - This property defines the dash pattern when VisualPath.strokeStyle is set - to VisualPath.DashLine. The pattern must be specified as an even number of - positive entries where the entries 1, 3, 5... are the dashes and 2, 4, 6... - are the spaces. The pattern is specified in units of the pen's width. - - The default value is (4, 2), meaning a dash of 4 * VisualPath.strokeWidth - pixels followed by a space of 2 * VisualPath.strokeWidth pixels. - - \sa QPen::setDashPattern() - */ - -QVector<qreal> QQuickVisualPath::dashPattern() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.dashPattern; -} - -void QQuickVisualPath::setDashPattern(const QVector<qreal> &array) -{ - Q_D(QQuickVisualPath); - if (d->sfp.dashPattern != array) { - d->sfp.dashPattern = array; - d->dirty |= QQuickVisualPathPrivate::DirtyDash; - emit dashPatternChanged(); - emit changed(); - } -} - -/*! - \qmlproperty PathGradient QtQuick::VisualPath::fillGradient - - This property defines the fill gradient. By default no gradient is enabled - and the value is \c null. In this case the fill uses a solid color based on - the value of VisuaLPath.fillColor. - - When set, VisualPath.fillColor is ignored and filling is done using one of - the PathGradient subtypes. - */ - -QQuickPathGradient *QQuickVisualPath::fillGradient() const -{ - Q_D(const QQuickVisualPath); - return d->sfp.fillGradient; -} - -void QQuickVisualPath::setFillGradient(QQuickPathGradient *gradient) -{ - Q_D(QQuickVisualPath); - if (d->sfp.fillGradient != gradient) { - if (d->sfp.fillGradient) - qmlobject_disconnect(d->sfp.fillGradient, QQuickPathGradient, SIGNAL(updated()), - this, QQuickVisualPath, SLOT(_q_fillGradientChanged())); - d->sfp.fillGradient = gradient; - if (d->sfp.fillGradient) - qmlobject_connect(d->sfp.fillGradient, QQuickPathGradient, SIGNAL(updated()), - this, QQuickVisualPath, SLOT(_q_fillGradientChanged())); - d->dirty |= QQuickVisualPathPrivate::DirtyFillGradient; - emit changed(); - } -} - -void QQuickVisualPathPrivate::_q_fillGradientChanged() -{ - Q_Q(QQuickVisualPath); - dirty |= DirtyFillGradient; - emit q->changed(); -} - -void QQuickVisualPath::resetFillGradient() -{ - setFillGradient(nullptr); -} - -/*! - \qmltype PathItem - \instantiates QQuickPathItem - \inqmlmodule QtQuick - \ingroup qtquick-paths - \ingroup qtquick-views - \inherits Item - \brief Renders a path - \since 5.10 - - Renders a path either by generating geometry via QPainterPath and manual - triangulation or by using a GPU vendor extension like \c{GL_NV_path_rendering}. - - This approach is different from rendering shapes via QQuickPaintedItem or - the 2D Canvas because the path never gets rasterized in software. Therefore - PathItem is suitable for creating shapes spreading over larger areas of the - screen, avoiding the performance penalty for texture uploads or framebuffer - blits. In addition, the declarative API allows manipulating, binding to, - and even animating the path element properties like starting and ending - position, the control points, etc. - - The types for specifying path elements are shared between \l PathView and - PathItem. However, not all PathItem implementations support all path - element types, while some may not make sense for PathView. PathItem's - currently supported subset is: PathMove, PathLine, PathQuad, PathCubic, - PathArc, PathSvg. - - See \l Path for a detailed overview of the supported path elements. - - \code - PathItem { - width: 200 - height: 150 - anchors.centerIn: parent - VisualPath { - strokeWidth: 4 - strokeColor: "red" - fillGradient: PathLinearGradient { - x1: 20; y1: 20 - x2: 180; y2: 130 - PathGradientStop { position: 0; color: "blue" } - PathGradientStop { position: 0.2; color: "green" } - PathGradientStop { position: 0.4; color: "red" } - PathGradientStop { position: 0.6; color: "yellow" } - PathGradientStop { position: 1; color: "cyan" } - } - strokeStyle: VisualPath.DashLine - dashPattern: [ 1, 4 ] - Path { - startX: 20; startY: 20 - PathLine { x: 180; y: 130 } - PathLine { x: 20; y: 130 } - PathLine { x: 20; y: 20 } - } - } - } - \endcode - - \image pathitem-code-example.png - - \note It is important to be aware of performance implications, in - particular when the application is running on the generic PathItem - implementation due to not having support for accelerated path rendering. - The geometry generation happens entirely on the CPU in this case, and this - is potentially expensive. Changing the set of path elements, changing the - properties of these elements, or changing certain properties of the - PathItem itself all lead to retriangulation on every change. Therefore, - applying animation to such properties can heavily affect performance on - less powerful systems. If animating properties other than stroke and fill - colors is a must, it is recommended to target systems providing - \c{GL_NV_path_rendering} where the cost of path property changes is much - smaller. - - The following list summarizes the available PathItem rendering approaches: - - \list - - \li When running with the default, OpenGL backend of Qt Quick, both the - generic, triangulation-based and the NVIDIA-specific - \c{GL_NV_path_rendering} methods are available. The choice is made at - runtime, depending on the graphics driver's capabilities. When this is not - desired, applications can force using the generic method by setting the - PathItem.enableVendorExtensions property to \c false. - - \li The \c software backend is fully supported. The path is rendered via - QPainter::strokePath() and QPainter::fillPath() in this case. - - \li The Direct 3D 12 backend is not currently supported. - - \li The OpenVG backend is not currently supported. - - \endlist - - \sa Path, PathMove, PathLine, PathQuad, PathCubic, PathArc, PathSvg -*/ - -QQuickPathItemPrivate::QQuickPathItemPrivate() - : componentComplete(true), - vpChanged(false), - rendererType(QQuickPathItem::UnknownRenderer), - async(false), - status(QQuickPathItem::Null), - renderer(nullptr), - enableVendorExts(true) -{ -} - -QQuickPathItemPrivate::~QQuickPathItemPrivate() -{ - delete renderer; -} - -void QQuickPathItemPrivate::_q_visualPathChanged() -{ - Q_Q(QQuickPathItem); - vpChanged = true; - q->polish(); -} - -void QQuickPathItemPrivate::setStatus(QQuickPathItem::Status newStatus) -{ - Q_Q(QQuickPathItem); - if (status != newStatus) { - status = newStatus; - emit q->statusChanged(); - } -} - -QQuickPathItem::QQuickPathItem(QQuickItem *parent) - : QQuickItem(*(new QQuickPathItemPrivate), parent) -{ - setFlag(ItemHasContents); -} - -QQuickPathItem::~QQuickPathItem() -{ -} - -/*! - \qmlproperty enumeration QtQuick::PathItem::rendererType - - This property determines which path rendering backend is active. - - \list - - \li PathItem.UnknownRenderer - The renderer is unknown. - - \li PathItem.GeometryRenderer - The generic, driver independent solution - for OpenGL. Uses the same CPU-based triangulation approach as QPainter's - OpenGL 2 paint engine. This is the default on non-NVIDIA hardware when the - default, OpenGL Qt Quick scenegraph backend is in use. - - \li PathItem.NvprRenderer - Path items are rendered by performing OpenGL - calls using the \c{GL_NV_path_rendering} extension. This is the default on - NVIDIA hardware when the default, OpenGL Qt Quick scenegraph backend is in - use. - - \li PathItem.SoftwareRenderer - Pure QPainter drawing using the raster - paint engine. This is the default, and only, option when the Qt Quick - scenegraph is running with the \c software backend. - - \endlist -*/ - -QQuickPathItem::RendererType QQuickPathItem::rendererType() const -{ - Q_D(const QQuickPathItem); - return d->rendererType; -} - -/*! - \qmlproperty bool QtQuick::PathItem::asynchronous - - When PathItem.rendererType is PathItem.GeometryRenderer, the input path is - triangulated on the CPU during the polishing phase of the PathItem. This is - potentially expensive. To offload this work to separate worker threads, set - this property to \c true. - - When enabled, making a PathItem visible will not wait for the content to - become available. Instead, the gui/main thread is not blocked and the - results of the path rendering are shown only when all the asynchronous work - has been finished. - - The default value is \c false. - */ - -bool QQuickPathItem::asynchronous() const -{ - Q_D(const QQuickPathItem); - return d->async; -} - -void QQuickPathItem::setAsynchronous(bool async) -{ - Q_D(QQuickPathItem); - if (d->async != async) { - d->async = async; - emit asynchronousChanged(); - if (d->componentComplete) - d->_q_visualPathChanged(); - } -} - -/*! - \qmlproperty bool QtQuick::PathItem::enableVendorExtensions - - This property controls the usage of non-standard OpenGL extensions like - GL_NV_path_rendering. To disable PathItem.NvprRenderer and force a uniform - behavior regardless of the graphics card and drivers, set this property to - \c false. - - The default value is \c true. - */ - -bool QQuickPathItem::enableVendorExtensions() const -{ - Q_D(const QQuickPathItem); - return d->enableVendorExts; -} - -void QQuickPathItem::setEnableVendorExtensions(bool enable) -{ - Q_D(QQuickPathItem); - if (d->enableVendorExts != enable) { - d->enableVendorExts = enable; - emit enableVendorExtensionsChanged(); - } -} - -/*! - \qmlproperty enumeration QtQuick::PathItem::status - - This property determines the status of the PathItem and is relevant when - PathItem.asynchronous is set to \c true. - - \list - - \li PathItem.Null - Not yet initialized. - - \li PathItem.Ready - The PathItem has finished processing. - - \li PathItem.Processing - The path is being processed. - - \endlist - */ - -QQuickPathItem::Status QQuickPathItem::status() const -{ - Q_D(const QQuickPathItem); - return d->status; -} - -static QQuickVisualPath *vpe_at(QQmlListProperty<QQuickVisualPath> *property, int index) -{ - QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(static_cast<QQuickPathItem *>(property->object)); - return d->qmlData.vp.at(index); -} - -static void vpe_append(QQmlListProperty<QQuickVisualPath> *property, QQuickVisualPath *obj) -{ - QQuickPathItem *item = static_cast<QQuickPathItem *>(property->object); - QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(item); - d->qmlData.vp.append(obj); - - if (d->componentComplete) { - QObject::connect(obj, SIGNAL(changed()), item, SLOT(_q_visualPathChanged())); - d->_q_visualPathChanged(); - } -} - -static int vpe_count(QQmlListProperty<QQuickVisualPath> *property) -{ - QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(static_cast<QQuickPathItem *>(property->object)); - return d->qmlData.vp.count(); -} - -static void vpe_clear(QQmlListProperty<QQuickVisualPath> *property) -{ - QQuickPathItem *item = static_cast<QQuickPathItem *>(property->object); - QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(item); - - for (QQuickVisualPath *p : d->qmlData.vp) - QObject::disconnect(p, SIGNAL(changed()), item, SLOT(_q_visualPathChanged())); - - d->qmlData.vp.clear(); - - if (d->componentComplete) - d->_q_visualPathChanged(); -} - -/*! - \qmlproperty list<VisualPath> QtQuick::PathItem::elements - - This property holds the VisualPath objects that define the contents of the - PathItem. - - \default - */ - -QQmlListProperty<QQuickVisualPath> QQuickPathItem::elements() -{ - return QQmlListProperty<QQuickVisualPath>(this, - nullptr, - vpe_append, - vpe_count, - vpe_at, - vpe_clear); -} - -void QQuickPathItem::classBegin() -{ - Q_D(QQuickPathItem); - d->componentComplete = false; -} - -void QQuickPathItem::componentComplete() -{ - Q_D(QQuickPathItem); - d->componentComplete = true; - - for (QQuickVisualPath *p : d->qmlData.vp) - connect(p, SIGNAL(changed()), this, SLOT(_q_visualPathChanged())); - - d->_q_visualPathChanged(); -} - -void QQuickPathItem::updatePolish() -{ - Q_D(QQuickPathItem); - - if (!d->vpChanged) - return; - - d->vpChanged = false; - - if (!d->renderer) { - d->createRenderer(); - if (!d->renderer) - return; - emit rendererChanged(); - } - - // endSync() is where expensive calculations may happen (or get kicked off - // on worker threads), depending on the backend. Therefore do this only - // when the item is visible. - if (isVisible()) - d->sync(); - - update(); -} - -void QQuickPathItem::itemChange(ItemChange change, const ItemChangeData &data) -{ - Q_D(QQuickPathItem); - - // sync may have been deferred; do it now if the item became visible - if (change == ItemVisibleHasChanged && data.boolValue) - d->_q_visualPathChanged(); - - QQuickItem::itemChange(change, data); -} - -QSGNode *QQuickPathItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) -{ - // Called on the render thread, with the gui thread blocked. We can now - // safely access gui thread data. - - Q_D(QQuickPathItem); - if (d->renderer) { - if (!node) - node = d->createNode(); - d->renderer->updateNode(); - } - return node; -} - -// the renderer object lives on the gui thread -void QQuickPathItemPrivate::createRenderer() -{ - Q_Q(QQuickPathItem); - QSGRendererInterface *ri = q->window()->rendererInterface(); - if (!ri) - return; - - switch (ri->graphicsApi()) { -#ifndef QT_NO_OPENGL - case QSGRendererInterface::OpenGL: - if (enableVendorExts && QQuickPathItemNvprRenderNode::isSupported()) { - rendererType = QQuickPathItem::NvprRenderer; - renderer = new QQuickPathItemNvprRenderer; - } else { - rendererType = QQuickPathItem::GeometryRenderer; - renderer = new QQuickPathItemGenericRenderer(q); - } - break; -#endif - case QSGRendererInterface::Software: - rendererType = QQuickPathItem::SoftwareRenderer; - renderer = new QQuickPathItemSoftwareRenderer; - break; - default: - qWarning("No path backend for this graphics API yet"); - break; - } -} - -// the node lives on the render thread -QSGNode *QQuickPathItemPrivate::createNode() -{ - Q_Q(QQuickPathItem); - QSGNode *node = nullptr; - if (!q->window()) - return node; - QSGRendererInterface *ri = q->window()->rendererInterface(); - if (!ri) - return node; - - switch (ri->graphicsApi()) { -#ifndef QT_NO_OPENGL - case QSGRendererInterface::OpenGL: - if (enableVendorExts && QQuickPathItemNvprRenderNode::isSupported()) { - node = new QQuickPathItemNvprRenderNode; - static_cast<QQuickPathItemNvprRenderer *>(renderer)->setNode( - static_cast<QQuickPathItemNvprRenderNode *>(node)); - } else { - node = new QQuickPathItemGenericNode; - static_cast<QQuickPathItemGenericRenderer *>(renderer)->setRootNode( - static_cast<QQuickPathItemGenericNode *>(node)); - } - break; -#endif - case QSGRendererInterface::Software: - node = new QQuickPathItemSoftwareRenderNode(q); - static_cast<QQuickPathItemSoftwareRenderer *>(renderer)->setNode( - static_cast<QQuickPathItemSoftwareRenderNode *>(node)); - break; - default: - qWarning("No path backend for this graphics API yet"); - break; - } - - return node; -} - -static void q_asyncPathItemReady(void *data) -{ - QQuickPathItemPrivate *self = static_cast<QQuickPathItemPrivate *>(data); - self->setStatus(QQuickPathItem::Ready); -} - -void QQuickPathItemPrivate::sync() -{ - const bool useAsync = async && renderer->flags().testFlag(QQuickAbstractPathRenderer::SupportsAsync); - if (useAsync) { - setStatus(QQuickPathItem::Processing); - renderer->setAsyncCallback(q_asyncPathItemReady, this); - } - - if (!jsData.isValid()) { - // Standard route: The path and stroke/fill parameters are provided via - // VisualPath and Path. - const int count = qmlData.vp.count(); - renderer->beginSync(count); - - for (int i = 0; i < count; ++i) { - QQuickVisualPath *p = qmlData.vp[i]; - int &dirty(QQuickVisualPathPrivate::get(p)->dirty); - - if (dirty & QQuickVisualPathPrivate::DirtyPath) - renderer->setPath(i, p->path()); - if (dirty & QQuickVisualPathPrivate::DirtyStrokeColor) - renderer->setStrokeColor(i, p->strokeColor()); - if (dirty & QQuickVisualPathPrivate::DirtyStrokeWidth) - renderer->setStrokeWidth(i, p->strokeWidth()); - if (dirty & QQuickVisualPathPrivate::DirtyFillColor) - renderer->setFillColor(i, p->fillColor()); - if (dirty & QQuickVisualPathPrivate::DirtyFillRule) - renderer->setFillRule(i, p->fillRule()); - if (dirty & QQuickVisualPathPrivate::DirtyStyle) { - renderer->setJoinStyle(i, p->joinStyle(), p->miterLimit()); - renderer->setCapStyle(i, p->capStyle()); - } - if (dirty & QQuickVisualPathPrivate::DirtyDash) - renderer->setStrokeStyle(i, p->strokeStyle(), p->dashOffset(), p->dashPattern()); - if (dirty & QQuickVisualPathPrivate::DirtyFillGradient) - renderer->setFillGradient(i, p->fillGradient()); - - dirty = 0; - } - - renderer->endSync(useAsync); - } else { - // Path and stroke/fill params provided from JavaScript. This avoids - // QObjects at the expense of not supporting changes afterwards. - const int count = jsData.paths.count(); - renderer->beginSync(count); - - for (int i = 0; i < count; ++i) { - renderer->setJSPath(i, jsData.paths[i]); - const QQuickPathItemStrokeFillParams sfp(jsData.sfp[i]); - renderer->setStrokeColor(i, sfp.strokeColor); - renderer->setStrokeWidth(i, sfp.strokeWidth); - renderer->setFillColor(i, sfp.fillColor); - renderer->setFillRule(i, sfp.fillRule); - renderer->setJoinStyle(i, sfp.joinStyle, sfp.miterLimit); - renderer->setCapStyle(i, sfp.capStyle); - renderer->setStrokeStyle(i, sfp.strokeStyle, sfp.dashOffset, sfp.dashPattern); - renderer->setFillGradient(i, sfp.fillGradient); - } - - renderer->endSync(useAsync); - } - - if (!useAsync) - setStatus(QQuickPathItem::Ready); -} - -// ***** gradient support ***** - -/*! - \qmltype PathGradientStop - \instantiates QQuickPathGradientStop - \inqmlmodule QtQuick - \ingroup qtquick-paths - \ingroup qtquick-views - \inherits Object - \brief Defines a color at a position in a gradient - \since 5.10 - */ - -QQuickPathGradientStop::QQuickPathGradientStop(QObject *parent) - : QObject(parent), - m_position(0), - m_color(Qt::black) -{ -} - -/*! - \qmlproperty real QtQuick::PathGradientStop::position - - The position and color properties describe the color used at a given - position in a gradient, as represented by a gradient stop. - - The default value is 0. - */ - -qreal QQuickPathGradientStop::position() const -{ - return m_position; -} - -void QQuickPathGradientStop::setPosition(qreal position) -{ - if (m_position != position) { - m_position = position; - if (QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(parent())) - emit grad->updated(); - } -} - -/*! - \qmlproperty real QtQuick::PathGradientStop::color - - The position and color properties describe the color used at a given - position in a gradient, as represented by a gradient stop. - - The default value is \c black. - */ - -QColor QQuickPathGradientStop::color() const -{ - return m_color; -} - -void QQuickPathGradientStop::setColor(const QColor &color) -{ - if (m_color != color) { - m_color = color; - if (QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(parent())) - emit grad->updated(); - } -} - -/*! - \qmltype PathGradient - \instantiates QQuickPathGradient - \inqmlmodule QtQuick - \ingroup qtquick-paths - \ingroup qtquick-views - \inherits Object - \brief Base type of PathItem fill gradients - \since 5.10 - - This is an abstract base class for gradients like PathLinearGradient and - cannot be created directly. - */ - -QQuickPathGradient::QQuickPathGradient(QObject *parent) - : QObject(parent), - m_spread(PadSpread) -{ -} - -int QQuickPathGradient::countStops(QQmlListProperty<QObject> *list) -{ - QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(list->object); - Q_ASSERT(grad); - return grad->m_stops.count(); -} - -QObject *QQuickPathGradient::atStop(QQmlListProperty<QObject> *list, int index) -{ - QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(list->object); - Q_ASSERT(grad); - return grad->m_stops.at(index); -} - -void QQuickPathGradient::appendStop(QQmlListProperty<QObject> *list, QObject *stop) -{ - QQuickPathGradientStop *sstop = qobject_cast<QQuickPathGradientStop *>(stop); - if (!sstop) { - qWarning("Gradient stop list only supports QQuickPathGradientStop elements"); - return; - } - QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(list->object); - Q_ASSERT(grad); - sstop->setParent(grad); - grad->m_stops.append(sstop); -} - -/*! - \qmlproperty list<Object> QtQuick::PathGradient::stops - \default - - The list of PathGradientStop objects defining the colors at given positions - in the gradient. - */ - -QQmlListProperty<QObject> QQuickPathGradient::stops() -{ - return QQmlListProperty<QObject>(this, nullptr, - &QQuickPathGradient::appendStop, - &QQuickPathGradient::countStops, - &QQuickPathGradient::atStop, - nullptr); -} - -QGradientStops QQuickPathGradient::sortedGradientStops() const -{ - QGradientStops result; - for (int i = 0; i < m_stops.count(); ++i) { - QQuickPathGradientStop *s = static_cast<QQuickPathGradientStop *>(m_stops[i]); - int j = 0; - while (j < result.count() && result[j].first < s->position()) - ++j; - result.insert(j, QGradientStop(s->position(), s->color())); - } - return result; -} - -/*! - \qmlproperty enumeration QtQuick::PathGradient::spred - - Specifies how the area outside the gradient area should be filled. The - default value is PathGradient.PadSpread. - - \list - \li PathGradient.PadSpread - The area is filled with the closest stop color. - \li PathGradient.RepeatSpread - The gradient is repeated outside the gradient area. - \li PathGradient.ReflectSpread - The gradient is reflected outside the gradient area. - \endlist - */ - -QQuickPathGradient::SpreadMode QQuickPathGradient::spread() const -{ - return m_spread; -} - -void QQuickPathGradient::setSpread(SpreadMode mode) -{ - if (m_spread != mode) { - m_spread = mode; - emit spreadChanged(); - emit updated(); - } -} - -/*! - \qmltype PathLinearGradient - \instantiates QQuickPathLinearGradient - \inqmlmodule QtQuick - \ingroup qtquick-paths - \ingroup qtquick-views - \inherits PathGradient - \brief Linear gradient - \since 5.10 - - Linear gradients interpolate colors between start and end points. Outside - these points the gradient is either padded, reflected or repeated depending - on the spread type. - - \sa QLinearGradient - */ - -QQuickPathLinearGradient::QQuickPathLinearGradient(QObject *parent) - : QQuickPathGradient(parent) -{ -} - -/*! - \qmlproperty real QtQuick::PathLinearGradient::x1 - \qmlproperty real QtQuick::PathLinearGradient::y1 - \qmlproperty real QtQuick::PathLinearGradient::x2 - \qmlproperty real QtQuick::PathLinearGradient::y2 - - These properties define the start and end points between which color - interpolation occurs. By default both the stard and end points are set to - (0, 0). - */ - -qreal QQuickPathLinearGradient::x1() const -{ - return m_start.x(); -} - -void QQuickPathLinearGradient::setX1(qreal v) -{ - if (m_start.x() != v) { - m_start.setX(v); - emit x1Changed(); - emit updated(); - } -} - -qreal QQuickPathLinearGradient::y1() const -{ - return m_start.y(); -} - -void QQuickPathLinearGradient::setY1(qreal v) -{ - if (m_start.y() != v) { - m_start.setY(v); - emit y1Changed(); - emit updated(); - } -} - -qreal QQuickPathLinearGradient::x2() const -{ - return m_end.x(); -} - -void QQuickPathLinearGradient::setX2(qreal v) -{ - if (m_end.x() != v) { - m_end.setX(v); - emit x2Changed(); - emit updated(); - } -} - -qreal QQuickPathLinearGradient::y2() const -{ - return m_end.y(); -} - -void QQuickPathLinearGradient::setY2(qreal v) -{ - if (m_end.y() != v) { - m_end.setY(v); - emit y2Changed(); - emit updated(); - } -} - -#ifndef QT_NO_OPENGL - -// contexts sharing with each other get the same cache instance -class QQuickPathItemGradientCacheWrapper -{ -public: - QQuickPathItemGradientCache *get(QOpenGLContext *context) - { - return m_resource.value<QQuickPathItemGradientCache>(context); - } - -private: - QOpenGLMultiGroupSharedResource m_resource; -}; - -QQuickPathItemGradientCache *QQuickPathItemGradientCache::currentCache() -{ - static QQuickPathItemGradientCacheWrapper qt_path_gradient_caches; - return qt_path_gradient_caches.get(QOpenGLContext::currentContext()); -} - -// let QOpenGLContext manage the lifetime of the cached textures -QQuickPathItemGradientCache::~QQuickPathItemGradientCache() -{ - m_cache.clear(); -} - -void QQuickPathItemGradientCache::invalidateResource() -{ - m_cache.clear(); -} - -void QQuickPathItemGradientCache::freeResource(QOpenGLContext *) -{ - qDeleteAll(m_cache); - m_cache.clear(); -} - -static void generateGradientColorTable(const QQuickPathItemGradientCache::GradientDesc &gradient, - uint *colorTable, int size, float opacity) -{ - int pos = 0; - const QGradientStops &s = gradient.stops; - const bool colorInterpolation = true; - - uint alpha = qRound(opacity * 256); - uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha); - qreal incr = 1.0 / qreal(size); - qreal fpos = 1.5 * incr; - colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); - - while (fpos <= s.first().first) { - colorTable[pos] = colorTable[pos - 1]; - pos++; - fpos += incr; - } - - if (colorInterpolation) - current_color = qPremultiply(current_color); - - const int sLast = s.size() - 1; - for (int i = 0; i < sLast; ++i) { - qreal delta = 1/(s[i+1].first - s[i].first); - uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha); - if (colorInterpolation) - next_color = qPremultiply(next_color); - - while (fpos < s[i+1].first && pos < size) { - int dist = int(256 * ((fpos - s[i].first) * delta)); - int idist = 256 - dist; - if (colorInterpolation) - colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); - else - colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); - ++pos; - fpos += incr; - } - current_color = next_color; - } - - Q_ASSERT(s.size() > 0); - - uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha))); - for ( ; pos < size; ++pos) - colorTable[pos] = last_color; - - colorTable[size-1] = last_color; -} - -QSGTexture *QQuickPathItemGradientCache::get(const GradientDesc &grad) -{ - QSGPlainTexture *tx = m_cache[grad]; - if (!tx) { - QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); - GLuint id; - f->glGenTextures(1, &id); - f->glBindTexture(GL_TEXTURE_2D, id); - static const uint W = 1024; // texture size is 1024x1 - uint buf[W]; - generateGradientColorTable(grad, buf, W, 1.0f); - f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); - tx = new QSGPlainTexture; - tx->setTextureId(id); - switch (grad.spread) { - case QQuickPathGradient::PadSpread: - tx->setHorizontalWrapMode(QSGTexture::ClampToEdge); - tx->setVerticalWrapMode(QSGTexture::ClampToEdge); - break; - case QQuickPathGradient::RepeatSpread: - tx->setHorizontalWrapMode(QSGTexture::Repeat); - tx->setVerticalWrapMode(QSGTexture::Repeat); - break; - case QQuickPathGradient::ReflectSpread: - tx->setHorizontalWrapMode(QSGTexture::MirroredRepeat); - tx->setVerticalWrapMode(QSGTexture::MirroredRepeat); - break; - default: - qWarning("Unknown gradient spread mode %d", grad.spread); - break; - } - m_cache[grad] = tx; - } - return tx; -} - -#endif // QT_NO_OPENGL - -// ***** JS-based alternative for creating static paths, (mostly) without QObjects ***** - -class QQuickPathItemJSEngineData : public QV8Engine::Deletable -{ -public: - QQuickPathItemJSEngineData(QV4::ExecutionEngine *engine); - - QV4::PersistentValue pathProto; - QV4::PersistentValue strokeFillParamsProto; -}; - -V4_DEFINE_EXTENSION(QQuickPathItemJSEngineData, engineData) - -namespace QV4 { -namespace Heap { - -struct QQuickPathItemJSPathPrototype : Object { - void init() { Object::init(); } -}; - -struct QQuickPathItemJSPath : Object { - void init() { Object::init(); } - QQuickPathItemPathObject *obj; -}; - -struct QQuickPathItemJSStrokeFillParamsPrototype : Object { - void init() { Object::init(); } -}; - -struct QQuickPathItemJSStrokeFillParams : Object { - void init() { Object::init(); } - QQuickPathItemStrokeFillParamsObject *obj; -}; - -} // namespace Heap -} // namespace QV4 - -struct QQuickPathItemJSPathPrototype : public QV4::Object -{ - V4_OBJECT2(QQuickPathItemJSPathPrototype, QV4::Object) -public: - static QV4::Heap::QQuickPathItemJSPathPrototype *create(QV4::ExecutionEngine *engine) - { - QV4::Scope scope(engine); - auto obj = engine->memoryManager->allocObject<QQuickPathItemJSPathPrototype>(); - QV4::Scoped<QQuickPathItemJSPathPrototype> o(scope, obj); - - o->defineDefaultProperty(QStringLiteral("clear"), method_clear, 0); - o->defineDefaultProperty(QStringLiteral("moveTo"), method_moveTo, 0); - o->defineDefaultProperty(QStringLiteral("lineTo"), method_lineTo, 0); - o->defineDefaultProperty(QStringLiteral("quadTo"), method_quadTo, 0); - o->defineDefaultProperty(QStringLiteral("cubicTo"), method_cubicTo, 0); - o->defineDefaultProperty(QStringLiteral("arcTo"), method_arcTo, 0); - - return o->d(); - } - - static void method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_moveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_lineTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_quadTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_cubicTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_arcTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); -}; - -DEFINE_OBJECT_VTABLE(QQuickPathItemJSPathPrototype); - -struct QQuickPathItemJSStrokeFillParamsPrototype : public QV4::Object -{ - V4_OBJECT2(QQuickPathItemJSStrokeFillParamsPrototype, QV4::Object) -public: - static QV4::Heap::QQuickPathItemJSStrokeFillParamsPrototype *create(QV4::ExecutionEngine *engine) - { - QV4::Scope scope(engine); - auto obj = engine->memoryManager->allocObject<QQuickPathItemJSStrokeFillParamsPrototype>(); - QV4::Scoped<QQuickPathItemJSStrokeFillParamsPrototype> o(scope, obj); - - o->defineDefaultProperty(QStringLiteral("clear"), method_clear, 0); - - return o->d(); - } - - static void method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); -}; - -DEFINE_OBJECT_VTABLE(QQuickPathItemJSStrokeFillParamsPrototype); - -struct QQuickPathItemJSPath : public QV4::Object -{ - V4_OBJECT2(QQuickPathItemJSPath, QV4::Object) -}; - -DEFINE_OBJECT_VTABLE(QQuickPathItemJSPath); - -struct QQuickPathItemJSStrokeFillParams : public QV4::Object -{ - V4_OBJECT2(QQuickPathItemJSStrokeFillParams, QV4::Object) - - static void method_get_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_get_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void method_set_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); -}; - -DEFINE_OBJECT_VTABLE(QQuickPathItemJSStrokeFillParams); - -void QQuickPathItemJSPathPrototype::method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>()); - - r->d()->obj->clear(); - - scope.result = callData->thisObject.asReturnedValue(); -} - -void QQuickPathItemJSPathPrototype::method_moveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>()); - - if (callData->argc >= 2) { - QQuickPathItemPathObject *p = r->d()->obj; - p->path.cmd.append(QQuickPathItemPath::MoveTo); - p->path.coords.append(callData->args[0].toNumber()); - p->path.coords.append(callData->args[1].toNumber()); - } - - scope.result = callData->thisObject.asReturnedValue(); -} - -void QQuickPathItemJSPathPrototype::method_lineTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>()); - - if (callData->argc >= 2) { - QQuickPathItemPathObject *p = r->d()->obj; - p->path.cmd.append(QQuickPathItemPath::LineTo); - p->path.coords.append(callData->args[0].toNumber()); - p->path.coords.append(callData->args[1].toNumber()); - } - - scope.result = callData->thisObject.asReturnedValue(); -} - -void QQuickPathItemJSPathPrototype::method_quadTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>()); - - if (callData->argc >= 4) { - QQuickPathItemPathObject *p = r->d()->obj; - p->path.cmd.append(QQuickPathItemPath::QuadTo); - const QV4::Value *v = callData->args; - p->path.coords.append(v[0].toNumber()); // cx - p->path.coords.append(v[1].toNumber()); // cy - p->path.coords.append(v[2].toNumber()); // x - p->path.coords.append(v[3].toNumber()); // y - } - - scope.result = callData->thisObject.asReturnedValue(); -} - -void QQuickPathItemJSPathPrototype::method_cubicTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>()); - - if (callData->argc >= 6) { - QQuickPathItemPathObject *p = r->d()->obj; - p->path.cmd.append(QQuickPathItemPath::CubicTo); - const QV4::Value *v = callData->args; - p->path.coords.append(v[0].toNumber()); // c1x - p->path.coords.append(v[1].toNumber()); // c1y - p->path.coords.append(v[2].toNumber()); // c2x - p->path.coords.append(v[3].toNumber()); // c2y - p->path.coords.append(v[4].toNumber()); // x - p->path.coords.append(v[5].toNumber()); // y - } - - scope.result = callData->thisObject.asReturnedValue(); -} - -void QQuickPathItemJSPathPrototype::method_arcTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>()); - - if (callData->argc >= 7) { - QQuickPathItemPathObject *p = r->d()->obj; - p->path.cmd.append(QQuickPathItemPath::ArcTo); - const QV4::Value *v = callData->args; - p->path.coords.append(v[0].toNumber()); // radiusX - p->path.coords.append(v[1].toNumber()); // radiusY - p->path.coords.append(v[2].toNumber()); // xAxisRotation - p->path.coords.append(v[3].toNumber()); // x - p->path.coords.append(v[4].toNumber()); // y - p->path.coords.append(v[5].toNumber()); // sweepFlag - p->path.coords.append(v[6].toNumber()); // largeArc - } - - scope.result = callData->thisObject.asReturnedValue(); -} - -void QQuickPathItemJSStrokeFillParamsPrototype::method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - r->d()->obj->clear(); - - scope.result = callData->thisObject.asReturnedValue(); -} - -Q_QUICK_PRIVATE_EXPORT QColor qt_color_from_string(const QV4::Value &name); // qquickcontext2d.cpp - -static inline QString qt_color_string(const QColor &color) -{ - if (color.alpha() == 255) - return color.name(); - QString alphaString = QString::number(color.alphaF(), 'f'); - while (alphaString.endsWith(QLatin1Char('0'))) - alphaString.chop(1); - if (alphaString.endsWith(QLatin1Char('.'))) - alphaString += QLatin1Char('0'); - return QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString); -} - -void QQuickPathItemJSStrokeFillParams::method_get_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = QV4::Encode(scope.engine->newString(qt_color_string(r->d()->obj->sfp.strokeColor))); -} - -void QQuickPathItemJSStrokeFillParams::method_set_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isString()) - r->d()->obj->sfp.strokeColor = qt_color_from_string(value); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.strokeWidth); -} - -void QQuickPathItemJSStrokeFillParams::method_set_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - r->d()->obj->sfp.strokeWidth = value->toNumber(); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = QV4::Encode(scope.engine->newString(qt_color_string(r->d()->obj->sfp.fillColor))); -} - -void QQuickPathItemJSStrokeFillParams::method_set_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isString()) - r->d()->obj->sfp.fillColor = qt_color_from_string(value); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.fillRule); -} - -void QQuickPathItemJSStrokeFillParams::method_set_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isInt32()) - r->d()->obj->sfp.fillRule = QQuickVisualPath::FillRule(value->integerValue()); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.joinStyle); -} - -void QQuickPathItemJSStrokeFillParams::method_set_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isInt32()) - r->d()->obj->sfp.joinStyle = QQuickVisualPath::JoinStyle(value->integerValue()); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.miterLimit); -} - -void QQuickPathItemJSStrokeFillParams::method_set_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - r->d()->obj->sfp.miterLimit = value->toNumber(); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.capStyle); -} - -void QQuickPathItemJSStrokeFillParams::method_set_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isInt32()) - r->d()->obj->sfp.capStyle = QQuickVisualPath::CapStyle(value->integerValue()); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.strokeStyle); -} - -void QQuickPathItemJSStrokeFillParams::method_set_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isInt32()) - r->d()->obj->sfp.strokeStyle = QQuickVisualPath::StrokeStyle(value->integerValue()); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = scope.engine->fromVariant(r->d()->obj->sfp.dashOffset); -} - -void QQuickPathItemJSStrokeFillParams::method_set_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - r->d()->obj->sfp.dashOffset = value->toNumber(); - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedArrayObject a(scope, scope.engine->newArrayObject()); - QQuickPathItemStrokeFillParamsObject *p = r->d()->obj; - a->arrayReserve(p->sfp.dashPattern.count()); - QV4::ScopedValue v(scope); - for (int i = 0; i < p->sfp.dashPattern.count(); ++i) - a->arrayPut(i, (v = scope.engine->fromVariant(p->sfp.dashPattern[i]))); - a->setArrayLengthUnchecked(p->sfp.dashPattern.count()); - - scope.result = a.asReturnedValue(); -} - -void QQuickPathItemJSStrokeFillParams::method_set_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - if (value->isObject()) { - QV4::Scoped<QV4::ArrayObject> ao(scope, value); - if (!!ao) { - QQuickPathItemStrokeFillParamsObject *p = r->d()->obj; - p->sfp.dashPattern.resize(ao->getLength()); - QV4::ScopedValue val(scope); - for (int i = 0; i < p->sfp.dashPattern.count(); ++i) { - val = ao->getIndexed(i); - p->sfp.dashPattern[i] = val->toNumber(); - } - } - } - - scope.result = QV4::Encode::undefined(); -} - -void QQuickPathItemJSStrokeFillParams::method_get_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - scope.result = r->d()->obj->v4fillGradient.value(); -} - -void QQuickPathItemJSStrokeFillParams::method_set_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) -{ - QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>()); - - QV4::ScopedValue value(scope, callData->argument(0)); - QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, value); - if (!!qobjectWrapper) { - if (QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(qobjectWrapper->object())) { - r->d()->obj->v4fillGradient.set(scope.engine, value); - r->d()->obj->sfp.fillGradient = grad; - } - } else { - r->d()->obj->v4fillGradient.set(scope.engine, nullptr); - r->d()->obj->sfp.fillGradient = nullptr; - } - - scope.result = QV4::Encode::undefined(); -} - -QQuickPathItemJSEngineData::QQuickPathItemJSEngineData(QV4::ExecutionEngine *v4) -{ - QV4::Scope scope(v4); - - QV4::ScopedObject proto(scope, QQuickPathItemJSPathPrototype::create(v4)); - pathProto = proto; - - proto = QV4::ScopedObject(scope, QQuickPathItemJSStrokeFillParamsPrototype::create(v4)); - - proto->defineAccessorProperty(QStringLiteral("strokeColor"), - QQuickPathItemJSStrokeFillParams::method_get_strokeColor, - QQuickPathItemJSStrokeFillParams::method_set_strokeColor); - proto->defineAccessorProperty(QStringLiteral("strokeWidth"), - QQuickPathItemJSStrokeFillParams::method_get_strokeWidth, - QQuickPathItemJSStrokeFillParams::method_set_strokeWidth); - proto->defineAccessorProperty(QStringLiteral("fillColor"), - QQuickPathItemJSStrokeFillParams::method_get_fillColor, - QQuickPathItemJSStrokeFillParams::method_set_fillColor); - proto->defineAccessorProperty(QStringLiteral("fillRule"), - QQuickPathItemJSStrokeFillParams::method_get_fillRule, - QQuickPathItemJSStrokeFillParams::method_set_fillRule); - proto->defineAccessorProperty(QStringLiteral("joinStyle"), - QQuickPathItemJSStrokeFillParams::method_get_joinStyle, - QQuickPathItemJSStrokeFillParams::method_set_joinStyle); - proto->defineAccessorProperty(QStringLiteral("miterLimit"), - QQuickPathItemJSStrokeFillParams::method_get_miterLimit, - QQuickPathItemJSStrokeFillParams::method_set_miterLimit); - proto->defineAccessorProperty(QStringLiteral("capStyle"), - QQuickPathItemJSStrokeFillParams::method_get_capStyle, - QQuickPathItemJSStrokeFillParams::method_set_capStyle); - proto->defineAccessorProperty(QStringLiteral("strokeStyle"), - QQuickPathItemJSStrokeFillParams::method_get_strokeStyle, - QQuickPathItemJSStrokeFillParams::method_set_strokeStyle); - proto->defineAccessorProperty(QStringLiteral("dashOffset"), - QQuickPathItemJSStrokeFillParams::method_get_dashOffset, - QQuickPathItemJSStrokeFillParams::method_set_dashOffset); - proto->defineAccessorProperty(QStringLiteral("dashPattern"), - QQuickPathItemJSStrokeFillParams::method_get_dashPattern, - QQuickPathItemJSStrokeFillParams::method_set_dashPattern); - proto->defineAccessorProperty(QStringLiteral("fillGradient"), - QQuickPathItemJSStrokeFillParams::method_get_fillGradient, - QQuickPathItemJSStrokeFillParams::method_set_fillGradient); - - strokeFillParamsProto = proto; -} - -void QQuickPathItemPathObject::setV4Engine(QV4::ExecutionEngine *engine) -{ - QQuickPathItemJSEngineData *ed = engineData(engine); - QV4::Scope scope(engine); - QV4::Scoped<QQuickPathItemJSPath> wrapper(scope, engine->memoryManager->allocObject<QQuickPathItemJSPath>()); - QV4::ScopedObject p(scope, ed->pathProto.value()); - wrapper->setPrototype(p); - wrapper->d()->obj = this; - m_v4value = wrapper; -} - -/*! - \qmltype JSPath - \inqmlmodule QtQuick - \ingroup qtquick-path - \brief Describes a path via a JavaScript API - */ - -/*! - \qmlmethod void QtQuick::JSPath::moveTo(x, y) - - Moves the path's position to the absolute position specified by (\a x, \a y). - */ - -/*! - \qmlmethod void QtQuick::JSPath::lineTo(x, y) - - Defines a straight line to the absolute position specified by (\a x, \a y). - */ - -/*! - \qmlmethod void QtQuick::JSPath::quadTo(cx, cy, x, y) - - Defines a quadratic Bezier curve with a control point (\a cx, \a cy) and an - end point of (\a x, \a y). - */ - -/*! - \qmlmethod void QtQuick::JSPath::cubicTo(c1x, c1y, c2x, c2y, x, y) - - Defines a cubic Bezier curve with two control points (\a c1x, \a c1y) and - (\a c2x, \a c2y), and an end point of (\a x, \a y). - */ - -/*! - \qmlmethod void QtQuick::JSPath::arcTo(radiusX, radiusY, xAxisRotation, x, y, sweepFlag, largeArc) - - Defines an elliptical arc, following the elliptical arc command in SVG. See - \l{https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands}{the - SVG path specification} for details on the parameters. - */ - -/*! - \qmlmethod void QtQuick::JSPath::clear() - - Clears the path object removing all path elements. This is more lightweight - than creating a new JSPath object. - */ - -void QQuickPathItemPathObject::clear() -{ - path = QQuickPathItemPath(); -} - -/*! - \qmltype StrokeFillParams - \inqmlmodule QtQuick - \ingroup qtquick-path - \brief Describes stroke and fill parameters via a JavaScript API - - The properties of StrokeFillParams objects correspond 1:1 to VisualPath - properties. The possible values for enumerations are the same as well, for - example: - - \code - sfp.strokeStyle = VisualPath.DashLine; - sfp.capStyle = VisualPath.RoundCap; - \endcode - */ - -/*! - \qmlproperty color QtQuick::StrokeFillParams::strokeColor - */ - -/*! - \qmlproperty real QtQuick::StrokeFillParams::strokeWidth - */ - -/*! - \qmlproperty color QtQuick::StrokeFillParams::fillColor - */ - -/*! - \qmlproperty enumeration QtQuick::StrokeFillParams::fillRule - */ - -/*! - \qmlproperty enumeration QtQuick::StrokeFillParams::joinStyle - */ - -/*! - \qmlproperty int QtQuick::StrokeFillParams::miterLimit - */ - -/*! - \qmlproperty enumeration QtQuick::StrokeFillParams::capStyle - */ - -/*! - \qmlproperty enumeration QtQuick::StrokeFillParams::strokeStyle - */ - -/*! - \qmlproperty real QtQuick::StrokeFillParams::dashOffset - */ - -/*! - \qmlproperty list<real> QtQuick::StrokeFillParams::dashPattern - - The dash pattern can be specified using JavaScript arrays. - - \code - sfp.dashPattern = [ 4, 2 ]; - \endcode - */ - -/*! - \qmlproperty object QtQuick::StrokeFillParams::fillGradient - - Sets the fill gradient. The default value is null. Gradients cannot be - created from JavaScript. Instead, reference a PathLinearGradient or other - item by id. - - \code - PathLinearGradient { id: grad; ... } - ... - sfp.fillGradient = grad; - \endcode - */ - -/*! - \qmlmethod void QtQuick::StrokeFillParams::clear() - - Resets all values to their defaults. This is more lightweight than creating - a new StrokeFillParams object. - */ - -void QQuickPathItemStrokeFillParamsObject::clear() -{ - sfp = QQuickPathItemStrokeFillParams(); - if (!v4fillGradient.isNullOrUndefined()) - v4fillGradient.set(v4fillGradient.engine(), nullptr); -} - -void QQuickPathItemStrokeFillParamsObject::setV4Engine(QV4::ExecutionEngine *engine) -{ - QQuickPathItemJSEngineData *ed = engineData(engine); - QV4::Scope scope(engine); - QV4::Scoped<QQuickPathItemJSStrokeFillParams> wrapper(scope, engine->memoryManager->allocObject<QQuickPathItemJSStrokeFillParams>()); - QV4::ScopedObject p(scope, ed->strokeFillParamsProto.value()); - wrapper->setPrototype(p); - wrapper->d()->obj = this; - m_v4value = wrapper; -} - -/*! - \qmlmethod JSPath QtQuick::PathItem::newPath() - - Creates and returns a new object that describes a path and offers a - JavaScript API. Paired with a stroke-fill parameter object it is - equivalent to a VisualPath. - - The following two snippets are equivalent when it comes to the end result: - - \code - var p = pathItem.newPath(); - var sfp = pathItem.newStrokeFillParams(); - sfp.fillColor = "white"; - sfp.strokeColor = "black"; - sfp.strokeWidth = 0.172; - p.moveTo(-122.304, 84.285); - p.cubicTo(-122.304, 84.285, -122.203, 86.179, -123.027, 86.16); - pathItem.appendVisualPath(p, sfp); - \endcode - - \code - PathItem { - VisualPath { - fillColor: "white" - strokeColor: "black" - strokeWidth: 0.172 - Path { - startX: -122.304; startY: 84.285 - PathCubic { control1X: -122.304; control1Y: 84.285; control2X: -122.203; control2Y: 86.179; x: -123.027; y: 86.16 } - } - } - } - \endcode - - The latter offers a full declarative API, with the possibility to binding - to and animating properties, while the former uses less resources due to - greatly reducing the number of QObject instances created. -*/ - -void QQuickPathItem::newPath(QQmlV4Function *args) -{ - QQuickPathItemPathObject *obj = new QQuickPathItemPathObject(this); - obj->setV4Engine(QQmlEnginePrivate::get(qmlEngine(this))->v4engine()); - args->setReturnValue(obj->v4value()); -} - -/*! - \qmlmethod StrokeFillParams QtQuick::PathItem::newStrokeFillParams() - - Creates and returns a new object that describes stroke and fill parameters - and offers a JavaScript API. Paired with a path object it is equivalent to - a VisualPath. - */ - -void QQuickPathItem::newStrokeFillParams(QQmlV4Function *args) -{ - QQuickPathItemStrokeFillParamsObject *obj = new QQuickPathItemStrokeFillParamsObject(this); - obj->setV4Engine(QQmlEnginePrivate::get(qmlEngine(this))->v4engine()); - args->setReturnValue(obj->v4value()); -} - -/*! - \qmlmethod void QtQuick::PathItem::clearVisualPaths() - - Clears the list of visual paths. - - \note This applies only to path and stroke-fill parameter objects registered - via appendVisualPaths(). - */ - -void QQuickPathItem::clearVisualPaths(QQmlV4Function *args) -{ - Q_UNUSED(args); - Q_D(QQuickPathItem); - d->jsData.paths.clear(); - d->jsData.sfp.clear(); -} - -/*! - \qmlmethod void QtQuick::PathItem::commitVisualPaths() - - Updates the PathItem. - - In order to avoid rendering a half-prepared PathItem, calling - PathItem.appendVisualPath() does not trigger any processing. Instead, - applications must call this function when all path and stroke-fill - parameter objects are registered. - */ - -void QQuickPathItem::commitVisualPaths(QQmlV4Function *args) -{ - Q_UNUSED(args); - Q_D(QQuickPathItem); - d->_q_visualPathChanged(); -} - -/*! - \qmlmethod void QtQuick::PathItem::appendVisualPath(object path, object strokeFillParams) - - Adds the visual path compoes of \a path and \a strokeFillParams into the - PathItem. - - \note The declarative and imprative (JavaScript) APIs of PathItem use - independent data structures. Calling this function has no effect on the - PathItem.elements property and vice versa. Once this function is called, - the PathItem will only consider the data registered via this function and - will ignore the declarative elements property. - */ - -void QQuickPathItem::appendVisualPath(QQmlV4Function *args) -{ - if (args->length() < 2) - return; - - Q_D(QQuickPathItem); - QV4::Scope scope(args->v4engine()); - QV4::Scoped<QQuickPathItemJSPath> jsp(scope, (*args)[0]); - QV4::Scoped<QQuickPathItemJSStrokeFillParams> jssfp(scope, (*args)[1]); - - const QQuickPathItemPath &path(jsp->d()->obj->path); - const QQuickPathItemStrokeFillParams &sfp(jssfp->d()->obj->sfp); - - d->jsData.paths.append(path); - d->jsData.sfp.append(sfp); -} - -QT_END_NAMESPACE - -#include "moc_qquickpathitem_p.cpp" diff --git a/src/imports/pathitem/plugin.cpp b/src/imports/shapes/plugin.cpp index 6b43e8f398..2f2f8c74d3 100644 --- a/src/imports/pathitem/plugin.cpp +++ b/src/imports/shapes/plugin.cpp @@ -40,32 +40,32 @@ #include <QtQml/qqmlextensionplugin.h> #include <QtQml/qqml.h> -#include "qquickpathitem_p.h" +#include "qquickshape_p.h" static void initResources() { #ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt_labs_pathitem); + Q_INIT_RESOURCE(qmake_QtQuick_Shapes); #endif } QT_BEGIN_NAMESPACE -class QmlPathItemPlugin : public QQmlExtensionPlugin +class QmlShapesPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - QmlPathItemPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + QmlShapesPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } void registerTypes(const char *uri) Q_DECL_OVERRIDE { - Q_ASSERT(QByteArray(uri) == QByteArray("Qt.labs.pathitem")); - qmlRegisterType<QQuickPathItem>(uri, 1, 0, "PathItem"); - qmlRegisterType<QQuickVisualPath>(uri, 1, 0, "VisualPath"); - qmlRegisterType<QQuickPathGradientStop>(uri, 1, 0, "PathGradientStop"); - qmlRegisterUncreatableType<QQuickPathGradient>(uri, 1, 0, "PathGradient", QQuickPathGradient::tr("PathGradient is an abstract base class")); - qmlRegisterType<QQuickPathLinearGradient>(uri, 1, 0, "PathLinearGradient"); + Q_ASSERT(QByteArray(uri) == QByteArray("QtQuick.Shapes")); + qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape"); + qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath"); + qmlRegisterType<QQuickShapeGradientStop>(uri, 1, 0, "ShapeGradientStop"); + qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class")); + qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "ShapeLinearGradient"); } }; diff --git a/src/imports/pathitem/plugins.qmltypes b/src/imports/shapes/plugins.qmltypes index 03f26e243c..28d8dd1f12 100644 --- a/src/imports/pathitem/plugins.qmltypes +++ b/src/imports/shapes/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable -noforceqtquick Qt.labs.pathitem 1.0' +// 'qmlplugindump -nonrelocatable -noforceqtquick QtQuick.Shapes 1.0' Module { dependencies: [] @@ -173,10 +173,10 @@ Module { } } Component { - name: "QQuickPathGradient" + name: "QQuickShapeGradient" defaultProperty: "stops" prototype: "QObject" - exports: ["Qt.labs.pathitem/PathGradient 1.0"] + exports: ["QtQuick.Shapes/ShapeGradient 1.0"] isCreatable: false exportMetaObjectRevisions: [0] Enum { @@ -192,18 +192,18 @@ Module { Signal { name: "updated" } } Component { - name: "QQuickPathGradientStop" + name: "QQuickShapeGradientStop" prototype: "QObject" - exports: ["Qt.labs.pathitem/PathGradientStop 1.0"] + exports: ["QtQuick.Shapes/ShapeGradientStop 1.0"] exportMetaObjectRevisions: [0] Property { name: "position"; type: "double" } Property { name: "color"; type: "QColor" } } Component { - name: "QQuickPathItem" + name: "QQuickShape" defaultProperty: "elements" prototype: "QQuickItem" - exports: ["Qt.labs.pathitem/PathItem 1.0"] + exports: ["QtQuick.Shapes/Shape 1.0"] exportMetaObjectRevisions: [0] Enum { name: "RendererType" @@ -226,33 +226,13 @@ Module { Property { name: "asynchronous"; type: "bool" } Property { name: "enableVendorExtensions"; type: "bool" } Property { name: "status"; type: "Status"; isReadonly: true } - Property { name: "elements"; type: "QQuickVisualPath"; isList: true; isReadonly: true } - Method { - name: "newPath" - Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } - } - Method { - name: "newStrokeFillParams" - Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } - } - Method { - name: "clearVisualPaths" - Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } - } - Method { - name: "commitVisualPaths" - Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } - } - Method { - name: "appendVisualPath" - Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } - } + Property { name: "elements"; type: "QQuickShapePath"; isList: true; isReadonly: true } } Component { - name: "QQuickPathLinearGradient" + name: "QQuickShapeLinearGradient" defaultProperty: "stops" - prototype: "QQuickPathGradient" - exports: ["Qt.labs.pathitem/PathLinearGradient 1.0"] + prototype: "QQuickShapeGradient" + exports: ["QtQuick.Shapes/ShapeLinearGradient 1.0"] exportMetaObjectRevisions: [0] Property { name: "x1"; type: "double" } Property { name: "y1"; type: "double" } @@ -260,10 +240,10 @@ Module { Property { name: "y2"; type: "double" } } Component { - name: "QQuickVisualPath" + name: "QQuickShapePath" defaultProperty: "path" prototype: "QObject" - exports: ["Qt.labs.pathitem/VisualPath 1.0"] + exports: ["QtQuick.Shapes/ShapePath 1.0"] exportMetaObjectRevisions: [0] Enum { name: "FillRule" @@ -306,7 +286,7 @@ Module { Property { name: "strokeStyle"; type: "StrokeStyle" } Property { name: "dashOffset"; type: "double" } Property { name: "dashPattern"; type: "QVector<qreal>" } - Property { name: "fillGradient"; type: "QQuickPathGradient"; isPointer: true } + Property { name: "fillGradient"; type: "QQuickShapeGradient"; isPointer: true } Signal { name: "changed" } } } diff --git a/src/imports/shapes/qmldir b/src/imports/shapes/qmldir new file mode 100644 index 0000000000..306ad1ecd7 --- /dev/null +++ b/src/imports/shapes/qmldir @@ -0,0 +1,4 @@ +module QtQuick.Shapes +plugin qmlshapesplugin +classname QmlShapesPlugin +typeinfo plugins.qmltypes diff --git a/src/imports/pathitem/qquicknvprfunctions.cpp b/src/imports/shapes/qquicknvprfunctions.cpp index 40eb2bb932..e9b93cf4a1 100644 --- a/src/imports/pathitem/qquicknvprfunctions.cpp +++ b/src/imports/shapes/qquicknvprfunctions.cpp @@ -231,9 +231,6 @@ bool QQuickNvprFunctionsPrivate::resolve() q->stencilFillPathInstanced = PROC(PFNGLSTENCILFILLPATHINSTANCEDNVPROC, glStencilFillPathInstancedNV); q->stencilStrokePathInstanced = PROC(PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC, glStencilStrokePathInstancedNV); q->pathCoverDepthFunc = PROC(PFNGLPATHCOVERDEPTHFUNCNVPROC, glPathCoverDepthFuncNV); - q->pathColorGen = PROC(PFNGLPATHCOLORGENNVPROC, glPathColorGenNV); - q->pathTexGen = PROC(PFNGLPATHTEXGENNVPROC, glPathTexGenNV); - q->pathFogGen = PROC(PFNGLPATHFOGGENNVPROC, glPathFogGenNV); q->coverFillPath = PROC(PFNGLCOVERFILLPATHNVPROC, glCoverFillPathNV); q->coverStrokePath = PROC(PFNGLCOVERSTROKEPATHNVPROC, glCoverStrokePathNV); q->coverFillPathInstanced = PROC(PFNGLCOVERFILLPATHINSTANCEDNVPROC, glCoverFillPathInstancedNV); @@ -246,10 +243,6 @@ bool QQuickNvprFunctionsPrivate::resolve() q->getPathMetrics = PROC(PFNGLGETPATHMETRICSNVPROC, glGetPathMetricsNV); q->getPathMetricRange = PROC(PFNGLGETPATHMETRICRANGENVPROC, glGetPathMetricRangeNV); q->getPathSpacing = PROC(PFNGLGETPATHSPACINGNVPROC, glGetPathSpacingNV); - q->getPathColorgeniv = PROC(PFNGLGETPATHCOLORGENIVNVPROC, glGetPathColorGenivNV); - q->getPathColorgenfv = PROC(PFNGLGETPATHCOLORGENFVNVPROC, glGetPathColorGenfvNV); - q->getPathTexGeniv = PROC(PFNGLGETPATHTEXGENIVNVPROC, glGetPathTexGenivNV); - q->getPathTexGenfv = PROC(PFNGLGETPATHTEXGENFVNVPROC, glGetPathTexGenfvNV); q->isPointInFillPath = PROC(PFNGLISPOINTINFILLPATHNVPROC, glIsPointInFillPathNV); q->isPointInStrokePath = PROC(PFNGLISPOINTINSTROKEPATHNVPROC, glIsPointInStrokePathNV); q->getPathLength = PROC(PFNGLGETPATHLENGTHNVPROC, glGetPathLengthNV); diff --git a/src/imports/pathitem/qquicknvprfunctions_p.h b/src/imports/shapes/qquicknvprfunctions_p.h index 7900388305..dd45dd7daa 100644 --- a/src/imports/pathitem/qquicknvprfunctions_p.h +++ b/src/imports/shapes/qquicknvprfunctions_p.h @@ -58,6 +58,9 @@ QT_BEGIN_NAMESPACE +// note: fixed pipeline specific functions are removed - modern ES ext +// headers have all this, but not the fixed stuff + #ifndef GL_NV_path_rendering #define GL_PATH_FORMAT_SVG_NV 0x9070 #define GL_PATH_FORMAT_PS_NV 0x9071 @@ -249,9 +252,6 @@ typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLi typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); typedef void (QOPENGLF_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func); -typedef void (QOPENGLF_APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs); -typedef void (QOPENGLF_APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs); -typedef void (QOPENGLF_APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode); typedef void (QOPENGLF_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode); typedef void (QOPENGLF_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode); typedef void (QOPENGLF_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); @@ -264,10 +264,6 @@ typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfl typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); -typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value); -typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value); -typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value); -typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value); typedef GLboolean (QOPENGLF_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); typedef GLboolean (QOPENGLF_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); typedef GLfloat (QOPENGLF_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments); @@ -297,6 +293,11 @@ typedef void (QOPENGLF_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint progra #define GL_INVERT 0x150A #endif +// this one originates from fixed pipeline so may not be in GLES ext headers, but we need it still +#ifndef GL_OBJECT_LINEAR_NV +#define GL_OBJECT_LINEAR_NV 0x2401 +#endif + #ifndef GL_EXT_direct_state_access typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m); typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode); @@ -353,9 +354,6 @@ public: PFNGLSTENCILFILLPATHINSTANCEDNVPROC stencilFillPathInstanced = nullptr; PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC stencilStrokePathInstanced = nullptr; PFNGLPATHCOVERDEPTHFUNCNVPROC pathCoverDepthFunc = nullptr; - PFNGLPATHCOLORGENNVPROC pathColorGen = nullptr; - PFNGLPATHTEXGENNVPROC pathTexGen = nullptr; - PFNGLPATHFOGGENNVPROC pathFogGen = nullptr; PFNGLCOVERFILLPATHNVPROC coverFillPath = nullptr; PFNGLCOVERSTROKEPATHNVPROC coverStrokePath = nullptr; PFNGLCOVERFILLPATHINSTANCEDNVPROC coverFillPathInstanced = nullptr; @@ -368,10 +366,6 @@ public: PFNGLGETPATHMETRICSNVPROC getPathMetrics = nullptr; PFNGLGETPATHMETRICRANGENVPROC getPathMetricRange = nullptr; PFNGLGETPATHSPACINGNVPROC getPathSpacing = nullptr; - PFNGLGETPATHCOLORGENIVNVPROC getPathColorgeniv = nullptr; - PFNGLGETPATHCOLORGENFVNVPROC getPathColorgenfv = nullptr; - PFNGLGETPATHTEXGENIVNVPROC getPathTexGeniv = nullptr; - PFNGLGETPATHTEXGENFVNVPROC getPathTexGenfv = nullptr; PFNGLISPOINTINFILLPATHNVPROC isPointInFillPath = nullptr; PFNGLISPOINTINSTROKEPATHNVPROC isPointInStrokePath = nullptr; PFNGLGETPATHLENGTHNVPROC getPathLength = nullptr; diff --git a/src/imports/pathitem/qquicknvprfunctions_p_p.h b/src/imports/shapes/qquicknvprfunctions_p_p.h index 6df20566af..6df20566af 100644 --- a/src/imports/pathitem/qquicknvprfunctions_p_p.h +++ b/src/imports/shapes/qquicknvprfunctions_p_p.h diff --git a/src/imports/shapes/qquickshape.cpp b/src/imports/shapes/qquickshape.cpp new file mode 100644 index 0000000000..e37addba07 --- /dev/null +++ b/src/imports/shapes/qquickshape.cpp @@ -0,0 +1,1485 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickshape_p.h" +#include "qquickshape_p_p.h" +#include "qquickshapegenericrenderer_p.h" +#include "qquickshapenvprrenderer_p.h" +#include "qquickshapesoftwarerenderer_p.h" +#include <private/qsgtexture_p.h> +#include <private/qquicksvgparser_p.h> +#include <QtGui/private/qdrawhelper_p.h> +#include <QOpenGLFunctions> + +#include <private/qv4engine_p.h> +#include <private/qv4object_p.h> +#include <private/qv4qobjectwrapper_p.h> +#include <private/qv4mm_p.h> +#include <private/qqmlengine_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmlmodule QtQuick.Shapes 1.0 + \title Qt Quick Shapes QML Types + \ingroup qmlmodules + \brief Provides QML types for drawing stroked and filled shapes + + To use the types in this module, import the module with the following line: + + \code + import QtQuick.Shapes 1.0 + \endcode +*/ + +QQuickShapeStrokeFillParams::QQuickShapeStrokeFillParams() + : strokeColor(Qt::white), + strokeWidth(1), + fillColor(Qt::white), + fillRule(QQuickShapePath::OddEvenFill), + joinStyle(QQuickShapePath::BevelJoin), + miterLimit(2), + capStyle(QQuickShapePath::SquareCap), + strokeStyle(QQuickShapePath::SolidLine), + dashOffset(0), + fillGradient(nullptr) +{ + dashPattern << 4 << 2; // 4 * strokeWidth dash followed by 2 * strokeWidth space +} + +QPainterPath QQuickShapePathCommands::toPainterPath() const +{ + QPainterPath p; + int coordIdx = 0; + for (int i = 0; i < cmd.count(); ++i) { + switch (cmd[i]) { + case QQuickShapePathCommands::MoveTo: + p.moveTo(coords[coordIdx], coords[coordIdx + 1]); + coordIdx += 2; + break; + case QQuickShapePathCommands::LineTo: + p.lineTo(coords[coordIdx], coords[coordIdx + 1]); + coordIdx += 2; + break; + case QQuickShapePathCommands::QuadTo: + p.quadTo(coords[coordIdx], coords[coordIdx + 1], + coords[coordIdx + 2], coords[coordIdx + 3]); + coordIdx += 4; + break; + case QQuickShapePathCommands::CubicTo: + p.cubicTo(coords[coordIdx], coords[coordIdx + 1], + coords[coordIdx + 2], coords[coordIdx + 3], + coords[coordIdx + 4], coords[coordIdx + 5]); + coordIdx += 6; + break; + case QQuickShapePathCommands::ArcTo: + // does not map to the QPainterPath API; reuse the helper code from QQuickSvgParser + QQuickSvgParser::pathArc(p, + coords[coordIdx], coords[coordIdx + 1], // radius + coords[coordIdx + 2], // xAxisRotation + !qFuzzyIsNull(coords[coordIdx + 6]), // useLargeArc + !qFuzzyIsNull(coords[coordIdx + 5]), // sweep flag + coords[coordIdx + 3], coords[coordIdx + 4], // end + p.currentPosition().x(), p.currentPosition().y()); + coordIdx += 7; + break; + default: + qWarning("Unknown JS path command: %d", cmd[i]); + break; + } + } + return p; +} + +/*! + \qmltype ShapePath + \instantiates QQuickShapePath + \inqmlmodule QtQuick.Shapes + \ingroup qtquick-paths + \ingroup qtquick-views + \inherits Object + \brief Describes a Path and associated properties for stroking and filling + \since 5.10 + + A Shape contains one or more ShapePath elements. At least one + ShapePath is necessary in order to have a Shape output anything + visible. A ShapeItem in turn contains a Path and properties describing the + stroking and filling parameters, such as the stroke width and color, the + fill color or gradient, join and cap styles, and so on. Finally, the Path + object contains a list of path elements like PathMove, PathLine, PathCubic, + PathQuad, PathArc. + + Any property changes in these data sets will be bubble up and change the + output of the Shape. This means that it is simple and easy to change, or + even animate, the starting and ending position, control points, or any + stroke or fill parameters using the usual QML bindings and animation types + like NumberAnimation. + + In the following example the line join style changes automatically based on + the value of joinStyleIndex: + + \code + ShapePath { + strokeColor: "black" + strokeWidth: 16 + fillColor: "transparent" + capStyle: ShapePath.RoundCap + + property int joinStyleIndex: 0 + property variant styles: [ ShapePath.BevelJoin, ShapePath.MiterJoin, ShapePath.RoundJoin ] + + joinStyle: styles[joinStyleIndex] + + Path { + startX: 30 + startY: 30 + PathLine { x: 100; y: 100 } + PathLine { x: 30; y: 100 } + } + } + \endcode + + Once associated with a Shape, here is the output with a joinStyleIndex + of 2 (ShapePath.RoundJoin): + + \image visualpath-code-example.png + */ + +QQuickShapePathPrivate::QQuickShapePathPrivate() + : path(nullptr), + dirty(DirtyAll) +{ +} + +QQuickShapePath::QQuickShapePath(QObject *parent) + : QObject(*(new QQuickShapePathPrivate), parent) +{ +} + +QQuickShapePath::~QQuickShapePath() +{ +} + +/*! + \qmlproperty Path QtQuick.Shapes::ShapePath::path + + This property holds the Path object. + + \default + */ + +QQuickPath *QQuickShapePath::path() const +{ + Q_D(const QQuickShapePath); + return d->path; +} + +void QQuickShapePath::setPath(QQuickPath *path) +{ + Q_D(QQuickShapePath); + if (d->path == path) + return; + + if (d->path) + qmlobject_disconnect(d->path, QQuickPath, SIGNAL(changed()), + this, QQuickShapePath, SLOT(_q_pathChanged())); + d->path = path; + qmlobject_connect(d->path, QQuickPath, SIGNAL(changed()), + this, QQuickShapePath, SLOT(_q_pathChanged())); + + d->dirty |= QQuickShapePathPrivate::DirtyPath; + emit pathChanged(); + emit changed(); +} + +void QQuickShapePathPrivate::_q_pathChanged() +{ + Q_Q(QQuickShapePath); + dirty |= DirtyPath; + emit q->changed(); +} + +/*! + \qmlproperty color QtQuick.Shapes::ShapePath::strokeColor + + This property holds the stroking color. + + When set to \c transparent, no stroking occurs. + + The default value is \c white. + */ + +QColor QQuickShapePath::strokeColor() const +{ + Q_D(const QQuickShapePath); + return d->sfp.strokeColor; +} + +void QQuickShapePath::setStrokeColor(const QColor &color) +{ + Q_D(QQuickShapePath); + if (d->sfp.strokeColor != color) { + d->sfp.strokeColor = color; + d->dirty |= QQuickShapePathPrivate::DirtyStrokeColor; + emit strokeColorChanged(); + emit changed(); + } +} + +/*! + \qmlproperty color QtQuick.Shapes::ShapePath::strokeWidth + + This property holds the stroke width. + + When set to a negative value, no stroking occurs. + + The default value is 1. + */ + +qreal QQuickShapePath::strokeWidth() const +{ + Q_D(const QQuickShapePath); + return d->sfp.strokeWidth; +} + +void QQuickShapePath::setStrokeWidth(qreal w) +{ + Q_D(QQuickShapePath); + if (d->sfp.strokeWidth != w) { + d->sfp.strokeWidth = w; + d->dirty |= QQuickShapePathPrivate::DirtyStrokeWidth; + emit strokeWidthChanged(); + emit changed(); + } +} + +/*! + \qmlproperty color QtQuick.Shapes::ShapePath::fillColor + + This property holds the fill color. + + When set to \c transparent, no filling occurs. + + The default value is \c white. + */ + +QColor QQuickShapePath::fillColor() const +{ + Q_D(const QQuickShapePath); + return d->sfp.fillColor; +} + +void QQuickShapePath::setFillColor(const QColor &color) +{ + Q_D(QQuickShapePath); + if (d->sfp.fillColor != color) { + d->sfp.fillColor = color; + d->dirty |= QQuickShapePathPrivate::DirtyFillColor; + emit fillColorChanged(); + emit changed(); + } +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::ShapePath::fillRule + + This property holds the fill rule. The default value is + ShapePath.OddEvenFill. For an example on fill rules, see + QPainterPath::setFillRule(). + + \list + \li ShapePath.OddEvenFill + \li ShapePath.WindingFill + \endlist + */ + +QQuickShapePath::FillRule QQuickShapePath::fillRule() const +{ + Q_D(const QQuickShapePath); + return d->sfp.fillRule; +} + +void QQuickShapePath::setFillRule(FillRule fillRule) +{ + Q_D(QQuickShapePath); + if (d->sfp.fillRule != fillRule) { + d->sfp.fillRule = fillRule; + d->dirty |= QQuickShapePathPrivate::DirtyFillRule; + emit fillRuleChanged(); + emit changed(); + } +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::ShapePath::joinStyle + + This property defines how joins between two connected lines are drawn. The + default value is ShapePath.BevelJoin. + + \list + \li ShapePath.MiterJoin - The outer edges of the lines are extended to meet at an angle, and this area is filled. + \li ShapePath.BevelJoin - The triangular notch between the two lines is filled. + \li ShapePath.RoundJoin - A circular arc between the two lines is filled. + \endlist + */ + +QQuickShapePath::JoinStyle QQuickShapePath::joinStyle() const +{ + Q_D(const QQuickShapePath); + return d->sfp.joinStyle; +} + +void QQuickShapePath::setJoinStyle(JoinStyle style) +{ + Q_D(QQuickShapePath); + if (d->sfp.joinStyle != style) { + d->sfp.joinStyle = style; + d->dirty |= QQuickShapePathPrivate::DirtyStyle; + emit joinStyleChanged(); + emit changed(); + } +} + +/*! + \qmlproperty int QtQuick.Shapes::ShapePath::miterLimit + + When ShapePath.joinStyle is set to ShapePath.MiterJoin, this property + specifies how far the miter join can extend from the join point. + + The default value is 2. + */ + +int QQuickShapePath::miterLimit() const +{ + Q_D(const QQuickShapePath); + return d->sfp.miterLimit; +} + +void QQuickShapePath::setMiterLimit(int limit) +{ + Q_D(QQuickShapePath); + if (d->sfp.miterLimit != limit) { + d->sfp.miterLimit = limit; + d->dirty |= QQuickShapePathPrivate::DirtyStyle; + emit miterLimitChanged(); + emit changed(); + } +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::ShapePath::capStyle + + This property defines how the end points of lines are drawn. The + default value is ShapePath.SquareCap. + + \list + \li ShapePath.FlatCap - A square line end that does not cover the end point of the line. + \li ShapePath.SquareCap - A square line end that covers the end point and extends beyond it by half the line width. + \li ShapePath.RoundCap - A rounded line end. + \endlist + */ + +QQuickShapePath::CapStyle QQuickShapePath::capStyle() const +{ + Q_D(const QQuickShapePath); + return d->sfp.capStyle; +} + +void QQuickShapePath::setCapStyle(CapStyle style) +{ + Q_D(QQuickShapePath); + if (d->sfp.capStyle != style) { + d->sfp.capStyle = style; + d->dirty |= QQuickShapePathPrivate::DirtyStyle; + emit capStyleChanged(); + emit changed(); + } +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::ShapePath::strokeStyle + + This property defines the style of stroking. The default value is + ShapePath.SolidLine. + + \list + \li ShapePath.SolidLine - A plain line. + \li ShapePath.DashLine - Dashes separated by a few pixels. + \endlist + */ + +QQuickShapePath::StrokeStyle QQuickShapePath::strokeStyle() const +{ + Q_D(const QQuickShapePath); + return d->sfp.strokeStyle; +} + +void QQuickShapePath::setStrokeStyle(StrokeStyle style) +{ + Q_D(QQuickShapePath); + if (d->sfp.strokeStyle != style) { + d->sfp.strokeStyle = style; + d->dirty |= QQuickShapePathPrivate::DirtyDash; + emit strokeStyleChanged(); + emit changed(); + } +} + +/*! + \qmlproperty real QtQuick.Shapes::ShapePath::dashOffset + + This property defines the starting point on the dash pattern, measured in + units used to specify the dash pattern. + + The default value is 0. + + \sa QPen::setDashOffset() + */ + +qreal QQuickShapePath::dashOffset() const +{ + Q_D(const QQuickShapePath); + return d->sfp.dashOffset; +} + +void QQuickShapePath::setDashOffset(qreal offset) +{ + Q_D(QQuickShapePath); + if (d->sfp.dashOffset != offset) { + d->sfp.dashOffset = offset; + d->dirty |= QQuickShapePathPrivate::DirtyDash; + emit dashOffsetChanged(); + emit changed(); + } +} + +/*! + \qmlproperty list<real> QtQuick.Shapes::ShapePath::dashPattern + + This property defines the dash pattern when ShapePath.strokeStyle is set + to ShapePath.DashLine. The pattern must be specified as an even number of + positive entries where the entries 1, 3, 5... are the dashes and 2, 4, 6... + are the spaces. The pattern is specified in units of the pen's width. + + The default value is (4, 2), meaning a dash of 4 * ShapePath.strokeWidth + pixels followed by a space of 2 * ShapePath.strokeWidth pixels. + + \sa QPen::setDashPattern() + */ + +QVector<qreal> QQuickShapePath::dashPattern() const +{ + Q_D(const QQuickShapePath); + return d->sfp.dashPattern; +} + +void QQuickShapePath::setDashPattern(const QVector<qreal> &array) +{ + Q_D(QQuickShapePath); + if (d->sfp.dashPattern != array) { + d->sfp.dashPattern = array; + d->dirty |= QQuickShapePathPrivate::DirtyDash; + emit dashPatternChanged(); + emit changed(); + } +} + +/*! + \qmlproperty ShapeGradient QtQuick.Shapes::ShapePath::fillGradient + + This property defines the fill gradient. By default no gradient is enabled + and the value is \c null. In this case the fill uses a solid color based on + the value of ShapePath.fillColor. + + When set, ShapePath.fillColor is ignored and filling is done using one of + the ShapeGradient subtypes. + */ + +QQuickShapeGradient *QQuickShapePath::fillGradient() const +{ + Q_D(const QQuickShapePath); + return d->sfp.fillGradient; +} + +void QQuickShapePath::setFillGradient(QQuickShapeGradient *gradient) +{ + Q_D(QQuickShapePath); + if (d->sfp.fillGradient != gradient) { + if (d->sfp.fillGradient) + qmlobject_disconnect(d->sfp.fillGradient, QQuickShapeGradient, SIGNAL(updated()), + this, QQuickShapePath, SLOT(_q_fillGradientChanged())); + d->sfp.fillGradient = gradient; + if (d->sfp.fillGradient) + qmlobject_connect(d->sfp.fillGradient, QQuickShapeGradient, SIGNAL(updated()), + this, QQuickShapePath, SLOT(_q_fillGradientChanged())); + d->dirty |= QQuickShapePathPrivate::DirtyFillGradient; + emit changed(); + } +} + +void QQuickShapePathPrivate::_q_fillGradientChanged() +{ + Q_Q(QQuickShapePath); + dirty |= DirtyFillGradient; + emit q->changed(); +} + +void QQuickShapePath::resetFillGradient() +{ + setFillGradient(nullptr); +} + +/*! + \qmltype Shape + \instantiates QQuickShape + \inqmlmodule QtQuick.Shapes + \ingroup qtquick-paths + \ingroup qtquick-views + \inherits Item + \brief Renders a path + \since 5.10 + + Renders a path either by generating geometry via QPainterPath and manual + triangulation or by using a GPU vendor extension like \c{GL_NV_path_rendering}. + + This approach is different from rendering shapes via QQuickPaintedItem or + the 2D Canvas because the path never gets rasterized in software. Therefore + Shape is suitable for creating shapes spreading over larger areas of the + screen, avoiding the performance penalty for texture uploads or framebuffer + blits. In addition, the declarative API allows manipulating, binding to, + and even animating the path element properties like starting and ending + position, the control points, etc. + + The types for specifying path elements are shared between \l PathView and + Shape. However, not all Shape implementations support all path + element types, while some may not make sense for PathView. Shape's + currently supported subset is: PathMove, PathLine, PathQuad, PathCubic, + PathArc, PathSvg. + + See \l Path for a detailed overview of the supported path elements. + + \code + Shape { + width: 200 + height: 150 + anchors.centerIn: parent + ShapePath { + strokeWidth: 4 + strokeColor: "red" + fillGradient: ShapeLinearGradient { + x1: 20; y1: 20 + x2: 180; y2: 130 + ShapeGradientStop { position: 0; color: "blue" } + ShapeGradientStop { position: 0.2; color: "green" } + ShapeGradientStop { position: 0.4; color: "red" } + ShapeGradientStop { position: 0.6; color: "yellow" } + ShapeGradientStop { position: 1; color: "cyan" } + } + strokeStyle: ShapePath.DashLine + dashPattern: [ 1, 4 ] + Path { + startX: 20; startY: 20 + PathLine { x: 180; y: 130 } + PathLine { x: 20; y: 130 } + PathLine { x: 20; y: 20 } + } + } + } + \endcode + + \image pathitem-code-example.png + + \note It is important to be aware of performance implications, in particular + when the application is running on the generic Shape implementation due to + not having support for accelerated path rendering. The geometry generation + happens entirely on the CPU in this case, and this is potentially + expensive. Changing the set of path elements, changing the properties of + these elements, or changing certain properties of the Shape itself all lead + to retriangulation of the affected elements on every change. Therefore, + applying animation to such properties can affect performance on less + powerful systems. If animating properties other than stroke and fill colors + is a must, it is recommended to target systems providing + \c{GL_NV_path_rendering} where the cost of path property changes is much + smaller. + + \note However, the data-driven, declarative nature of the Shape API often + means better cacheability for the underlying CPU and GPU resources. A + property change in one ShapePath will only lead to reprocessing the affected + ShapePath, leaving other parts of the Shape unchanged. Therefore, a heavily + changing (for example, animating) property can often result in a lower + overall system load than with imperative painting approaches (for example, + QPainter). + + The following list summarizes the available Shape rendering approaches: + + \list + + \li When running with the default, OpenGL backend of Qt Quick, both the + generic, triangulation-based and the NVIDIA-specific + \c{GL_NV_path_rendering} methods are available. The choice is made at + runtime, depending on the graphics driver's capabilities. When this is not + desired, applications can force using the generic method by setting the + Shape.enableVendorExtensions property to \c false. + + \li The \c software backend is fully supported. The path is rendered via + QPainter::strokePath() and QPainter::fillPath() in this case. + + \li The Direct 3D 12 backend is not currently supported. + + \li The OpenVG backend is not currently supported. + + \endlist + + \sa Path, PathMove, PathLine, PathQuad, PathCubic, PathArc, PathSvg +*/ + +QQuickShapePrivate::QQuickShapePrivate() + : componentComplete(true), + spChanged(false), + rendererType(QQuickShape::UnknownRenderer), + async(false), + status(QQuickShape::Null), + renderer(nullptr), + enableVendorExts(true) +{ +} + +QQuickShapePrivate::~QQuickShapePrivate() +{ + delete renderer; +} + +void QQuickShapePrivate::_q_shapePathChanged() +{ + Q_Q(QQuickShape); + spChanged = true; + q->polish(); +} + +void QQuickShapePrivate::setStatus(QQuickShape::Status newStatus) +{ + Q_Q(QQuickShape); + if (status != newStatus) { + status = newStatus; + emit q->statusChanged(); + } +} + +QQuickShape::QQuickShape(QQuickItem *parent) + : QQuickItem(*(new QQuickShapePrivate), parent) +{ + setFlag(ItemHasContents); +} + +QQuickShape::~QQuickShape() +{ +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::Shape::rendererType + + This property determines which path rendering backend is active. + + \list + + \li Shape.UnknownRenderer - The renderer is unknown. + + \li Shape.GeometryRenderer - The generic, driver independent solution + for OpenGL. Uses the same CPU-based triangulation approach as QPainter's + OpenGL 2 paint engine. This is the default on non-NVIDIA hardware when the + default, OpenGL Qt Quick scenegraph backend is in use. + + \li Shape.NvprRenderer - Path items are rendered by performing OpenGL + calls using the \c{GL_NV_path_rendering} extension. This is the default on + NVIDIA hardware when the default, OpenGL Qt Quick scenegraph backend is in + use. + + \li Shape.SoftwareRenderer - Pure QPainter drawing using the raster + paint engine. This is the default, and only, option when the Qt Quick + scenegraph is running with the \c software backend. + + \endlist +*/ + +QQuickShape::RendererType QQuickShape::rendererType() const +{ + Q_D(const QQuickShape); + return d->rendererType; +} + +/*! + \qmlproperty bool QtQuick.Shapes::Shape::asynchronous + + When Shape.rendererType is Shape.GeometryRenderer, the input path is + triangulated on the CPU during the polishing phase of the Shape. This is + potentially expensive. To offload this work to separate worker threads, set + this property to \c true. + + When enabled, making a Shape visible will not wait for the content to + become available. Instead, the gui/main thread is not blocked and the + results of the path rendering are shown only when all the asynchronous work + has been finished. + + The default value is \c false. + */ + +bool QQuickShape::asynchronous() const +{ + Q_D(const QQuickShape); + return d->async; +} + +void QQuickShape::setAsynchronous(bool async) +{ + Q_D(QQuickShape); + if (d->async != async) { + d->async = async; + emit asynchronousChanged(); + if (d->componentComplete) + d->_q_shapePathChanged(); + } +} + +/*! + \qmlproperty bool QtQuick.Shapes::Shape::enableVendorExtensions + + This property controls the usage of non-standard OpenGL extensions like + GL_NV_path_rendering. To disable Shape.NvprRenderer and force a uniform + behavior regardless of the graphics card and drivers, set this property to + \c false. + + The default value is \c true. + */ + +bool QQuickShape::enableVendorExtensions() const +{ + Q_D(const QQuickShape); + return d->enableVendorExts; +} + +void QQuickShape::setEnableVendorExtensions(bool enable) +{ + Q_D(QQuickShape); + if (d->enableVendorExts != enable) { + d->enableVendorExts = enable; + emit enableVendorExtensionsChanged(); + } +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::Shape::status + + This property determines the status of the Shape and is relevant when + Shape.asynchronous is set to \c true. + + \list + + \li Shape.Null - Not yet initialized. + + \li Shape.Ready - The Shape has finished processing. + + \li Shape.Processing - The path is being processed. + + \endlist + */ + +QQuickShape::Status QQuickShape::status() const +{ + Q_D(const QQuickShape); + return d->status; +} + +static QQuickShapePath *vpe_at(QQmlListProperty<QQuickShapePath> *property, int index) +{ + QQuickShapePrivate *d = QQuickShapePrivate::get(static_cast<QQuickShape *>(property->object)); + return d->qmlData.sp.at(index); +} + +static void vpe_append(QQmlListProperty<QQuickShapePath> *property, QQuickShapePath *obj) +{ + QQuickShape *item = static_cast<QQuickShape *>(property->object); + QQuickShapePrivate *d = QQuickShapePrivate::get(item); + d->qmlData.sp.append(obj); + + if (d->componentComplete) { + QObject::connect(obj, SIGNAL(changed()), item, SLOT(_q_shapePathChanged())); + d->_q_shapePathChanged(); + } +} + +static int vpe_count(QQmlListProperty<QQuickShapePath> *property) +{ + QQuickShapePrivate *d = QQuickShapePrivate::get(static_cast<QQuickShape *>(property->object)); + return d->qmlData.sp.count(); +} + +static void vpe_clear(QQmlListProperty<QQuickShapePath> *property) +{ + QQuickShape *item = static_cast<QQuickShape *>(property->object); + QQuickShapePrivate *d = QQuickShapePrivate::get(item); + + for (QQuickShapePath *p : d->qmlData.sp) + QObject::disconnect(p, SIGNAL(changed()), item, SLOT(_q_shapePathChanged())); + + d->qmlData.sp.clear(); + + if (d->componentComplete) + d->_q_shapePathChanged(); +} + +/*! + \qmlproperty list<ShapePath> QtQuick.Shapes::Shape::elements + + This property holds the ShapePath objects that define the contents of the + Shape. + + \default + */ + +QQmlListProperty<QQuickShapePath> QQuickShape::elements() +{ + return QQmlListProperty<QQuickShapePath>(this, + nullptr, + vpe_append, + vpe_count, + vpe_at, + vpe_clear); +} + +void QQuickShape::classBegin() +{ + Q_D(QQuickShape); + d->componentComplete = false; +} + +void QQuickShape::componentComplete() +{ + Q_D(QQuickShape); + d->componentComplete = true; + + for (QQuickShapePath *p : d->qmlData.sp) + connect(p, SIGNAL(changed()), this, SLOT(_q_shapePathChanged())); + + d->_q_shapePathChanged(); +} + +void QQuickShape::updatePolish() +{ + Q_D(QQuickShape); + + if (!d->spChanged) + return; + + d->spChanged = false; + + if (!d->renderer) { + d->createRenderer(); + if (!d->renderer) + return; + emit rendererChanged(); + } + + // endSync() is where expensive calculations may happen (or get kicked off + // on worker threads), depending on the backend. Therefore do this only + // when the item is visible. + if (isVisible()) + d->sync(); + + update(); +} + +void QQuickShape::itemChange(ItemChange change, const ItemChangeData &data) +{ + Q_D(QQuickShape); + + // sync may have been deferred; do it now if the item became visible + if (change == ItemVisibleHasChanged && data.boolValue) + d->_q_shapePathChanged(); + + QQuickItem::itemChange(change, data); +} + +QSGNode *QQuickShape::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) +{ + // Called on the render thread, with the gui thread blocked. We can now + // safely access gui thread data. + + Q_D(QQuickShape); + if (d->renderer) { + if (!node) + node = d->createNode(); + d->renderer->updateNode(); + } + return node; +} + +// the renderer object lives on the gui thread +void QQuickShapePrivate::createRenderer() +{ + Q_Q(QQuickShape); + QSGRendererInterface *ri = q->window()->rendererInterface(); + if (!ri) + return; + + switch (ri->graphicsApi()) { +#ifndef QT_NO_OPENGL + case QSGRendererInterface::OpenGL: + if (enableVendorExts && QQuickShapeNvprRenderNode::isSupported()) { + rendererType = QQuickShape::NvprRenderer; + renderer = new QQuickShapeNvprRenderer; + } else { + rendererType = QQuickShape::GeometryRenderer; + renderer = new QQuickShapeGenericRenderer(q); + } + break; +#endif + case QSGRendererInterface::Software: + rendererType = QQuickShape::SoftwareRenderer; + renderer = new QQuickShapeSoftwareRenderer; + break; + default: + qWarning("No path backend for this graphics API yet"); + break; + } +} + +// the node lives on the render thread +QSGNode *QQuickShapePrivate::createNode() +{ + Q_Q(QQuickShape); + QSGNode *node = nullptr; + if (!q->window()) + return node; + QSGRendererInterface *ri = q->window()->rendererInterface(); + if (!ri) + return node; + + switch (ri->graphicsApi()) { +#ifndef QT_NO_OPENGL + case QSGRendererInterface::OpenGL: + if (enableVendorExts && QQuickShapeNvprRenderNode::isSupported()) { + node = new QQuickShapeNvprRenderNode; + static_cast<QQuickShapeNvprRenderer *>(renderer)->setNode( + static_cast<QQuickShapeNvprRenderNode *>(node)); + } else { + node = new QQuickShapeGenericNode; + static_cast<QQuickShapeGenericRenderer *>(renderer)->setRootNode( + static_cast<QQuickShapeGenericNode *>(node)); + } + break; +#endif + case QSGRendererInterface::Software: + node = new QQuickShapeSoftwareRenderNode(q); + static_cast<QQuickShapeSoftwareRenderer *>(renderer)->setNode( + static_cast<QQuickShapeSoftwareRenderNode *>(node)); + break; + default: + qWarning("No path backend for this graphics API yet"); + break; + } + + return node; +} + +static void q_asyncShapeReady(void *data) +{ + QQuickShapePrivate *self = static_cast<QQuickShapePrivate *>(data); + self->setStatus(QQuickShape::Ready); +} + +void QQuickShapePrivate::sync() +{ + const bool useAsync = async && renderer->flags().testFlag(QQuickAbstractPathRenderer::SupportsAsync); + if (useAsync) { + setStatus(QQuickShape::Processing); + renderer->setAsyncCallback(q_asyncShapeReady, this); + } + + if (!jsData.isValid()) { + // Standard route: The path and stroke/fill parameters are provided via + // QML elements. + const int count = qmlData.sp.count(); + renderer->beginSync(count); + + for (int i = 0; i < count; ++i) { + QQuickShapePath *p = qmlData.sp[i]; + int &dirty(QQuickShapePathPrivate::get(p)->dirty); + + if (dirty & QQuickShapePathPrivate::DirtyPath) + renderer->setPath(i, p->path()); + if (dirty & QQuickShapePathPrivate::DirtyStrokeColor) + renderer->setStrokeColor(i, p->strokeColor()); + if (dirty & QQuickShapePathPrivate::DirtyStrokeWidth) + renderer->setStrokeWidth(i, p->strokeWidth()); + if (dirty & QQuickShapePathPrivate::DirtyFillColor) + renderer->setFillColor(i, p->fillColor()); + if (dirty & QQuickShapePathPrivate::DirtyFillRule) + renderer->setFillRule(i, p->fillRule()); + if (dirty & QQuickShapePathPrivate::DirtyStyle) { + renderer->setJoinStyle(i, p->joinStyle(), p->miterLimit()); + renderer->setCapStyle(i, p->capStyle()); + } + if (dirty & QQuickShapePathPrivate::DirtyDash) + renderer->setStrokeStyle(i, p->strokeStyle(), p->dashOffset(), p->dashPattern()); + if (dirty & QQuickShapePathPrivate::DirtyFillGradient) + renderer->setFillGradient(i, p->fillGradient()); + + dirty = 0; + } + + renderer->endSync(useAsync); + } else { + + // ### there is no public API to reach this code path atm + Q_UNREACHABLE(); + + // Path and stroke/fill params provided from JavaScript. This avoids + // QObjects at the expense of not supporting changes afterwards. + const int count = jsData.paths.count(); + renderer->beginSync(count); + + for (int i = 0; i < count; ++i) { + renderer->setJSPath(i, jsData.paths[i]); + const QQuickShapeStrokeFillParams sfp(jsData.sfp[i]); + renderer->setStrokeColor(i, sfp.strokeColor); + renderer->setStrokeWidth(i, sfp.strokeWidth); + renderer->setFillColor(i, sfp.fillColor); + renderer->setFillRule(i, sfp.fillRule); + renderer->setJoinStyle(i, sfp.joinStyle, sfp.miterLimit); + renderer->setCapStyle(i, sfp.capStyle); + renderer->setStrokeStyle(i, sfp.strokeStyle, sfp.dashOffset, sfp.dashPattern); + renderer->setFillGradient(i, sfp.fillGradient); + } + + renderer->endSync(useAsync); + } + + if (!useAsync) + setStatus(QQuickShape::Ready); +} + +// ***** gradient support ***** + +/*! + \qmltype ShapeGradientStop + \instantiates QQuickShapeGradientStop + \inqmlmodule QtQuick.Shapes + \ingroup qtquick-paths + \ingroup qtquick-views + \inherits Object + \brief Defines a color at a position in a gradient + \since 5.10 + */ + +QQuickShapeGradientStop::QQuickShapeGradientStop(QObject *parent) + : QObject(parent), + m_position(0), + m_color(Qt::black) +{ +} + +/*! + \qmlproperty real QtQuick.Shapes::ShapeGradientStop::position + + The position and color properties describe the color used at a given + position in a gradient, as represented by a gradient stop. + + The default value is 0. + */ + +qreal QQuickShapeGradientStop::position() const +{ + return m_position; +} + +void QQuickShapeGradientStop::setPosition(qreal position) +{ + if (m_position != position) { + m_position = position; + if (QQuickShapeGradient *grad = qobject_cast<QQuickShapeGradient *>(parent())) + emit grad->updated(); + } +} + +/*! + \qmlproperty real QtQuick.Shapes::ShapeGradientStop::color + + The position and color properties describe the color used at a given + position in a gradient, as represented by a gradient stop. + + The default value is \c black. + */ + +QColor QQuickShapeGradientStop::color() const +{ + return m_color; +} + +void QQuickShapeGradientStop::setColor(const QColor &color) +{ + if (m_color != color) { + m_color = color; + if (QQuickShapeGradient *grad = qobject_cast<QQuickShapeGradient *>(parent())) + emit grad->updated(); + } +} + +/*! + \qmltype ShapeGradient + \instantiates QQuickShapeGradient + \inqmlmodule QtQuick.Shapes + \ingroup qtquick-paths + \ingroup qtquick-views + \inherits Object + \brief Base type of Shape fill gradients + \since 5.10 + + This is an abstract base class for gradients like ShapeLinearGradient and + cannot be created directly. + */ + +QQuickShapeGradient::QQuickShapeGradient(QObject *parent) + : QObject(parent), + m_spread(PadSpread) +{ +} + +int QQuickShapeGradient::countStops(QQmlListProperty<QObject> *list) +{ + QQuickShapeGradient *grad = qobject_cast<QQuickShapeGradient *>(list->object); + Q_ASSERT(grad); + return grad->m_stops.count(); +} + +QObject *QQuickShapeGradient::atStop(QQmlListProperty<QObject> *list, int index) +{ + QQuickShapeGradient *grad = qobject_cast<QQuickShapeGradient *>(list->object); + Q_ASSERT(grad); + return grad->m_stops.at(index); +} + +void QQuickShapeGradient::appendStop(QQmlListProperty<QObject> *list, QObject *stop) +{ + QQuickShapeGradientStop *sstop = qobject_cast<QQuickShapeGradientStop *>(stop); + if (!sstop) { + qWarning("Gradient stop list only supports QQuickShapeGradientStop elements"); + return; + } + QQuickShapeGradient *grad = qobject_cast<QQuickShapeGradient *>(list->object); + Q_ASSERT(grad); + sstop->setParent(grad); + grad->m_stops.append(sstop); +} + +/*! + \qmlproperty list<Object> QtQuick.Shapes::ShapeGradient::stops + \default + + The list of ShapeGradientStop objects defining the colors at given positions + in the gradient. + */ + +QQmlListProperty<QObject> QQuickShapeGradient::stops() +{ + return QQmlListProperty<QObject>(this, nullptr, + &QQuickShapeGradient::appendStop, + &QQuickShapeGradient::countStops, + &QQuickShapeGradient::atStop, + nullptr); +} + +QGradientStops QQuickShapeGradient::sortedGradientStops() const +{ + QGradientStops result; + for (int i = 0; i < m_stops.count(); ++i) { + QQuickShapeGradientStop *s = static_cast<QQuickShapeGradientStop *>(m_stops[i]); + int j = 0; + while (j < result.count() && result[j].first < s->position()) + ++j; + result.insert(j, QGradientStop(s->position(), s->color())); + } + return result; +} + +/*! + \qmlproperty enumeration QtQuick.Shapes::ShapeGradient::spred + + Specifies how the area outside the gradient area should be filled. The + default value is ShapeGradient.PadSpread. + + \list + \li ShapeGradient.PadSpread - The area is filled with the closest stop color. + \li ShapeGradient.RepeatSpread - The gradient is repeated outside the gradient area. + \li ShapeGradient.ReflectSpread - The gradient is reflected outside the gradient area. + \endlist + */ + +QQuickShapeGradient::SpreadMode QQuickShapeGradient::spread() const +{ + return m_spread; +} + +void QQuickShapeGradient::setSpread(SpreadMode mode) +{ + if (m_spread != mode) { + m_spread = mode; + emit spreadChanged(); + emit updated(); + } +} + +/*! + \qmltype ShapeLinearGradient + \instantiates QQuickShapeLinearGradient + \inqmlmodule QtQuick.Shapes + \ingroup qtquick-paths + \ingroup qtquick-views + \inherits ShapeGradient + \brief Linear gradient + \since 5.10 + + Linear gradients interpolate colors between start and end points. Outside + these points the gradient is either padded, reflected or repeated depending + on the spread type. + + \sa QLinearGradient + */ + +QQuickShapeLinearGradient::QQuickShapeLinearGradient(QObject *parent) + : QQuickShapeGradient(parent) +{ +} + +/*! + \qmlproperty real QtQuick.Shapes::ShapeLinearGradient::x1 + \qmlproperty real QtQuick.Shapes::ShapeLinearGradient::y1 + \qmlproperty real QtQuick.Shapes::ShapeLinearGradient::x2 + \qmlproperty real QtQuick.Shapes::ShapeLinearGradient::y2 + + These properties define the start and end points between which color + interpolation occurs. By default both the stard and end points are set to + (0, 0). + */ + +qreal QQuickShapeLinearGradient::x1() const +{ + return m_start.x(); +} + +void QQuickShapeLinearGradient::setX1(qreal v) +{ + if (m_start.x() != v) { + m_start.setX(v); + emit x1Changed(); + emit updated(); + } +} + +qreal QQuickShapeLinearGradient::y1() const +{ + return m_start.y(); +} + +void QQuickShapeLinearGradient::setY1(qreal v) +{ + if (m_start.y() != v) { + m_start.setY(v); + emit y1Changed(); + emit updated(); + } +} + +qreal QQuickShapeLinearGradient::x2() const +{ + return m_end.x(); +} + +void QQuickShapeLinearGradient::setX2(qreal v) +{ + if (m_end.x() != v) { + m_end.setX(v); + emit x2Changed(); + emit updated(); + } +} + +qreal QQuickShapeLinearGradient::y2() const +{ + return m_end.y(); +} + +void QQuickShapeLinearGradient::setY2(qreal v) +{ + if (m_end.y() != v) { + m_end.setY(v); + emit y2Changed(); + emit updated(); + } +} + +#ifndef QT_NO_OPENGL + +// contexts sharing with each other get the same cache instance +class QQuickShapeGradientCacheWrapper +{ +public: + QQuickShapeGradientCache *get(QOpenGLContext *context) + { + return m_resource.value<QQuickShapeGradientCache>(context); + } + +private: + QOpenGLMultiGroupSharedResource m_resource; +}; + +QQuickShapeGradientCache *QQuickShapeGradientCache::currentCache() +{ + static QQuickShapeGradientCacheWrapper qt_path_gradient_caches; + return qt_path_gradient_caches.get(QOpenGLContext::currentContext()); +} + +// let QOpenGLContext manage the lifetime of the cached textures +QQuickShapeGradientCache::~QQuickShapeGradientCache() +{ + m_cache.clear(); +} + +void QQuickShapeGradientCache::invalidateResource() +{ + m_cache.clear(); +} + +void QQuickShapeGradientCache::freeResource(QOpenGLContext *) +{ + qDeleteAll(m_cache); + m_cache.clear(); +} + +static void generateGradientColorTable(const QQuickShapeGradientCache::GradientDesc &gradient, + uint *colorTable, int size, float opacity) +{ + int pos = 0; + const QGradientStops &s = gradient.stops; + const bool colorInterpolation = true; + + uint alpha = qRound(opacity * 256); + uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha); + qreal incr = 1.0 / qreal(size); + qreal fpos = 1.5 * incr; + colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); + + while (fpos <= s.first().first) { + colorTable[pos] = colorTable[pos - 1]; + pos++; + fpos += incr; + } + + if (colorInterpolation) + current_color = qPremultiply(current_color); + + const int sLast = s.size() - 1; + for (int i = 0; i < sLast; ++i) { + qreal delta = 1/(s[i+1].first - s[i].first); + uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha); + if (colorInterpolation) + next_color = qPremultiply(next_color); + + while (fpos < s[i+1].first && pos < size) { + int dist = int(256 * ((fpos - s[i].first) * delta)); + int idist = 256 - dist; + if (colorInterpolation) + colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + else + colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); + ++pos; + fpos += incr; + } + current_color = next_color; + } + + Q_ASSERT(s.size() > 0); + + uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha))); + for ( ; pos < size; ++pos) + colorTable[pos] = last_color; + + colorTable[size-1] = last_color; +} + +QSGTexture *QQuickShapeGradientCache::get(const GradientDesc &grad) +{ + QSGPlainTexture *tx = m_cache[grad]; + if (!tx) { + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + GLuint id; + f->glGenTextures(1, &id); + f->glBindTexture(GL_TEXTURE_2D, id); + static const uint W = 1024; // texture size is 1024x1 + uint buf[W]; + generateGradientColorTable(grad, buf, W, 1.0f); + f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + tx = new QSGPlainTexture; + tx->setTextureId(id); + switch (grad.spread) { + case QQuickShapeGradient::PadSpread: + tx->setHorizontalWrapMode(QSGTexture::ClampToEdge); + tx->setVerticalWrapMode(QSGTexture::ClampToEdge); + break; + case QQuickShapeGradient::RepeatSpread: + tx->setHorizontalWrapMode(QSGTexture::Repeat); + tx->setVerticalWrapMode(QSGTexture::Repeat); + break; + case QQuickShapeGradient::ReflectSpread: + tx->setHorizontalWrapMode(QSGTexture::MirroredRepeat); + tx->setVerticalWrapMode(QSGTexture::MirroredRepeat); + break; + default: + qWarning("Unknown gradient spread mode %d", grad.spread); + break; + } + m_cache[grad] = tx; + } + return tx; +} + +#endif // QT_NO_OPENGL + +QT_END_NAMESPACE + +#include "moc_qquickshape_p.cpp" diff --git a/src/imports/pathitem/qquickpathitem_p.h b/src/imports/shapes/qquickshape_p.h index c7c56fd5d8..5b3580dd1b 100644 --- a/src/imports/pathitem/qquickpathitem_p.h +++ b/src/imports/shapes/qquickshape_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQUICKPATHITEM_P_H -#define QQUICKPATHITEM_P_H +#ifndef QQUICKSHAPE_P_H +#define QQUICKSHAPE_P_H // // W A R N I N G @@ -60,17 +60,17 @@ QT_BEGIN_NAMESPACE -class QQuickVisualPathPrivate; -class QQuickPathItemPrivate; +class QQuickShapePathPrivate; +class QQuickShapePrivate; -class QQuickPathGradientStop : public QObject +class QQuickShapeGradientStop : public QObject { Q_OBJECT Q_PROPERTY(qreal position READ position WRITE setPosition) Q_PROPERTY(QColor color READ color WRITE setColor) public: - QQuickPathGradientStop(QObject *parent = nullptr); + QQuickShapeGradientStop(QObject *parent = nullptr); qreal position() const; void setPosition(qreal position); @@ -83,7 +83,7 @@ private: QColor m_color; }; -class QQuickPathGradient : public QObject +class QQuickShapeGradient : public QObject { Q_OBJECT Q_PROPERTY(QQmlListProperty<QObject> stops READ stops) @@ -98,7 +98,7 @@ public: }; Q_ENUM(SpreadMode) - QQuickPathGradient(QObject *parent = nullptr); + QQuickShapeGradient(QObject *parent = nullptr); QQmlListProperty<QObject> stops(); @@ -120,7 +120,7 @@ private: SpreadMode m_spread; }; -class QQuickPathLinearGradient : public QQuickPathGradient +class QQuickShapeLinearGradient : public QQuickShapeGradient { Q_OBJECT Q_PROPERTY(qreal x1 READ x1 WRITE setX1 NOTIFY x1Changed) @@ -130,7 +130,7 @@ class QQuickPathLinearGradient : public QQuickPathGradient Q_CLASSINFO("DefaultProperty", "stops") public: - QQuickPathLinearGradient(QObject *parent = nullptr); + QQuickShapeLinearGradient(QObject *parent = nullptr); qreal x1() const; void setX1(qreal v); @@ -152,7 +152,7 @@ private: QPointF m_end; }; -class QQuickVisualPath : public QObject +class QQuickShapePath : public QObject { Q_OBJECT @@ -169,7 +169,7 @@ class QQuickVisualPath : public QObject Q_PROPERTY(StrokeStyle strokeStyle READ strokeStyle WRITE setStrokeStyle NOTIFY strokeStyleChanged) Q_PROPERTY(qreal dashOffset READ dashOffset WRITE setDashOffset NOTIFY dashOffsetChanged) Q_PROPERTY(QVector<qreal> dashPattern READ dashPattern WRITE setDashPattern NOTIFY dashPatternChanged) - Q_PROPERTY(QQuickPathGradient *fillGradient READ fillGradient WRITE setFillGradient RESET resetFillGradient) + Q_PROPERTY(QQuickShapeGradient *fillGradient READ fillGradient WRITE setFillGradient RESET resetFillGradient) public: enum FillRule { @@ -198,8 +198,8 @@ public: }; Q_ENUM(StrokeStyle) - QQuickVisualPath(QObject *parent = nullptr); - ~QQuickVisualPath(); + QQuickShapePath(QObject *parent = nullptr); + ~QQuickShapePath(); QQuickPath *path() const; void setPath(QQuickPath *path); @@ -234,8 +234,8 @@ public: QVector<qreal> dashPattern() const; void setDashPattern(const QVector<qreal> &array); - QQuickPathGradient *fillGradient() const; - void setFillGradient(QQuickPathGradient *gradient); + QQuickShapeGradient *fillGradient() const; + void setFillGradient(QQuickShapeGradient *gradient); void resetFillGradient(); Q_SIGNALS: @@ -254,20 +254,20 @@ Q_SIGNALS: void fillGradientChanged(); private: - Q_DISABLE_COPY(QQuickVisualPath) - Q_DECLARE_PRIVATE(QQuickVisualPath) + Q_DISABLE_COPY(QQuickShapePath) + Q_DECLARE_PRIVATE(QQuickShapePath) Q_PRIVATE_SLOT(d_func(), void _q_pathChanged()) Q_PRIVATE_SLOT(d_func(), void _q_fillGradientChanged()) }; -class QQuickPathItem : public QQuickItem +class QQuickShape : public QQuickItem { Q_OBJECT Q_PROPERTY(RendererType renderer READ rendererType NOTIFY rendererChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) Q_PROPERTY(bool enableVendorExtensions READ enableVendorExtensions WRITE setEnableVendorExtensions NOTIFY enableVendorExtensionsChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(QQmlListProperty<QQuickVisualPath> elements READ elements) + Q_PROPERTY(QQmlListProperty<QQuickShapePath> elements READ elements) Q_CLASSINFO("DefaultProperty", "elements") public: @@ -286,8 +286,8 @@ public: }; Q_ENUM(Status) - QQuickPathItem(QQuickItem *parent = nullptr); - ~QQuickPathItem(); + QQuickShape(QQuickItem *parent = nullptr); + ~QQuickShape(); RendererType rendererType() const; @@ -299,13 +299,7 @@ public: Status status() const; - QQmlListProperty<QQuickVisualPath> elements(); - - Q_INVOKABLE void newPath(QQmlV4Function *args); - Q_INVOKABLE void newStrokeFillParams(QQmlV4Function *args); - Q_INVOKABLE void clearVisualPaths(QQmlV4Function *args); - Q_INVOKABLE void commitVisualPaths(QQmlV4Function *args); - Q_INVOKABLE void appendVisualPath(QQmlV4Function *args); + QQmlListProperty<QQuickShapePath> elements(); protected: QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override; @@ -321,13 +315,13 @@ Q_SIGNALS: void statusChanged(); private: - Q_DISABLE_COPY(QQuickPathItem) - Q_DECLARE_PRIVATE(QQuickPathItem) - Q_PRIVATE_SLOT(d_func(), void _q_visualPathChanged()) + Q_DISABLE_COPY(QQuickShape) + Q_DECLARE_PRIVATE(QQuickShape) + Q_PRIVATE_SLOT(d_func(), void _q_shapePathChanged()) }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QQuickPathItem) +QML_DECLARE_TYPE(QQuickShape) -#endif // QQUICKPATHITEM_P_H +#endif // QQUICKSHAPE_P_H diff --git a/src/imports/pathitem/qquickpathitem_p_p.h b/src/imports/shapes/qquickshape_p_p.h index 6dde314a30..7a503e36a9 100644 --- a/src/imports/pathitem/qquickpathitem_p_p.h +++ b/src/imports/shapes/qquickshape_p_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQUICKPATHITEM_P_P_H -#define QQUICKPATHITEM_P_P_H +#ifndef QQUICKSHAPE_P_P_H +#define QQUICKSHAPE_P_P_H // // W A R N I N G @@ -51,7 +51,7 @@ // We mean it. // -#include "qquickpathitem_p.h" +#include "qquickshape_p.h" #include <QtQuick/private/qquickitem_p.h> #include <QPainterPath> #include <QColor> @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QSGPlainTexture; -struct QQuickPathItemPath +struct QQuickShapePathCommands { enum Command { MoveTo, @@ -78,21 +78,21 @@ struct QQuickPathItemPath QPainterPath toPainterPath() const; }; -struct QQuickPathItemStrokeFillParams +struct QQuickShapeStrokeFillParams { - QQuickPathItemStrokeFillParams(); + QQuickShapeStrokeFillParams(); QColor strokeColor; qreal strokeWidth; QColor fillColor; - QQuickVisualPath::FillRule fillRule; - QQuickVisualPath::JoinStyle joinStyle; + QQuickShapePath::FillRule fillRule; + QQuickShapePath::JoinStyle joinStyle; int miterLimit; - QQuickVisualPath::CapStyle capStyle; - QQuickVisualPath::StrokeStyle strokeStyle; + QQuickShapePath::CapStyle capStyle; + QQuickShapePath::StrokeStyle strokeStyle; qreal dashOffset; QVector<qreal> dashPattern; - QQuickPathGradient *fillGradient; + QQuickShapeGradient *fillGradient; }; class QQuickAbstractPathRenderer @@ -113,17 +113,17 @@ public: // - QML API virtual void setPath(int index, const QQuickPath *path) = 0; // - JS API - virtual void setJSPath(int index, const QQuickPathItemPath &path) = 0; + virtual void setJSPath(int index, const QQuickShapePathCommands &path) = 0; // - stroke/fill parameters virtual void setStrokeColor(int index, const QColor &color) = 0; virtual void setStrokeWidth(int index, qreal w) = 0; virtual void setFillColor(int index, const QColor &color) = 0; - virtual void setFillRule(int index, QQuickVisualPath::FillRule fillRule) = 0; - virtual void setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) = 0; - virtual void setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) = 0; - virtual void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, + virtual void setFillRule(int index, QQuickShapePath::FillRule fillRule) = 0; + virtual void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) = 0; + virtual void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) = 0; + virtual void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) = 0; - virtual void setFillGradient(int index, QQuickPathGradient *gradient) = 0; + virtual void setFillGradient(int index, QQuickShapeGradient *gradient) = 0; // Render thread, with gui blocked virtual void updateNode() = 0; @@ -131,9 +131,9 @@ public: Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAbstractPathRenderer::Flags) -class QQuickVisualPathPrivate : public QObjectPrivate +class QQuickShapePathPrivate : public QObjectPrivate { - Q_DECLARE_PUBLIC(QQuickVisualPath) + Q_DECLARE_PUBLIC(QQuickShapePath) public: enum Dirty { @@ -149,66 +149,66 @@ public: DirtyAll = 0xFF }; - QQuickVisualPathPrivate(); + QQuickShapePathPrivate(); void _q_pathChanged(); void _q_fillGradientChanged(); - static QQuickVisualPathPrivate *get(QQuickVisualPath *p) { return p->d_func(); } + static QQuickShapePathPrivate *get(QQuickShapePath *p) { return p->d_func(); } QQuickPath *path; int dirty; - QQuickPathItemStrokeFillParams sfp; + QQuickShapeStrokeFillParams sfp; }; -class QQuickPathItemPrivate : public QQuickItemPrivate +class QQuickShapePrivate : public QQuickItemPrivate { - Q_DECLARE_PUBLIC(QQuickPathItem) + Q_DECLARE_PUBLIC(QQuickShape) public: - QQuickPathItemPrivate(); - ~QQuickPathItemPrivate(); + QQuickShapePrivate(); + ~QQuickShapePrivate(); void createRenderer(); QSGNode *createNode(); void sync(); - void _q_visualPathChanged(); - void setStatus(QQuickPathItem::Status newStatus); + void _q_shapePathChanged(); + void setStatus(QQuickShape::Status newStatus); - static QQuickPathItemPrivate *get(QQuickPathItem *item) { return item->d_func(); } + static QQuickShapePrivate *get(QQuickShape *item) { return item->d_func(); } bool componentComplete; - bool vpChanged; - QQuickPathItem::RendererType rendererType; + bool spChanged; + QQuickShape::RendererType rendererType; bool async; - QQuickPathItem::Status status; + QQuickShape::Status status; QQuickAbstractPathRenderer *renderer; struct { - QVector<QQuickVisualPath *> vp; + QVector<QQuickShapePath *> sp; } qmlData; struct { bool isValid() const { Q_ASSERT(paths.count() == sfp.count()); return !paths.isEmpty(); } - QVector<QQuickPathItemPath> paths; - QVector<QQuickPathItemStrokeFillParams> sfp; + QVector<QQuickShapePathCommands> paths; + QVector<QQuickShapeStrokeFillParams> sfp; } jsData; bool enableVendorExts; }; -class QQuickPathItemPathObject : public QObject +class QQuickShapePathObject : public QObject { Q_OBJECT public: - QQuickPathItemPathObject(QObject *parent = nullptr) : QObject(parent) { } + QQuickShapePathObject(QObject *parent = nullptr) : QObject(parent) { } void setV4Engine(QV4::ExecutionEngine *engine); QV4::ReturnedValue v4value() const { return m_v4value.value(); } - QQuickPathItemPath path; + QQuickShapePath path; void clear(); @@ -216,17 +216,17 @@ private: QV4::PersistentValue m_v4value; }; -class QQuickPathItemStrokeFillParamsObject : public QObject +class QQuickShapeStrokeFillParamsObject : public QObject { Q_OBJECT public: - QQuickPathItemStrokeFillParamsObject(QObject *parent = nullptr) : QObject(parent) { } + QQuickShapeStrokeFillParamsObject(QObject *parent = nullptr) : QObject(parent) { } void setV4Engine(QV4::ExecutionEngine *engine); QV4::ReturnedValue v4value() const { return m_v4value.value(); } - QQuickPathItemStrokeFillParams sfp; + QQuickShapeStrokeFillParams sfp; QV4::PersistentValue v4fillGradient; void clear(); @@ -237,14 +237,14 @@ private: #ifndef QT_NO_OPENGL -class QQuickPathItemGradientCache : public QOpenGLSharedResource +class QQuickShapeGradientCache : public QOpenGLSharedResource { public: struct GradientDesc { QGradientStops stops; QPointF start; QPointF end; - QQuickPathGradient::SpreadMode spread; + QQuickShapeGradient::SpreadMode spread; bool operator==(const GradientDesc &other) const { return start == other.start && end == other.end && spread == other.spread @@ -252,21 +252,21 @@ public: } }; - QQuickPathItemGradientCache(QOpenGLContext *context) : QOpenGLSharedResource(context->shareGroup()) { } - ~QQuickPathItemGradientCache(); + QQuickShapeGradientCache(QOpenGLContext *context) : QOpenGLSharedResource(context->shareGroup()) { } + ~QQuickShapeGradientCache(); void invalidateResource() override; void freeResource(QOpenGLContext *) override; QSGTexture *get(const GradientDesc &grad); - static QQuickPathItemGradientCache *currentCache(); + static QQuickShapeGradientCache *currentCache(); private: QHash<GradientDesc, QSGPlainTexture *> m_cache; }; -inline uint qHash(const QQuickPathItemGradientCache::GradientDesc &v, uint seed = 0) +inline uint qHash(const QQuickShapeGradientCache::GradientDesc &v, uint seed = 0) { uint h = seed; h += v.start.x() + v.end.y() + v.spread; diff --git a/src/imports/pathitem/qquickpathitemgenericrenderer.cpp b/src/imports/shapes/qquickshapegenericrenderer.cpp index 4e8fe55df2..ff226959eb 100644 --- a/src/imports/pathitem/qquickpathitemgenericrenderer.cpp +++ b/src/imports/shapes/qquickshapegenericrenderer.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "qquickpathitemgenericrenderer_p.h" +#include "qquickshapegenericrenderer_p.h" #include <QtGui/private/qtriangulator_p.h> #include <QtGui/private/qtriangulatingstroker_p.h> #include <QThreadPool> @@ -56,16 +56,16 @@ static const qreal TRI_SCALE = 1; struct ColoredVertex // must match QSGGeometry::ColoredPoint2D { float x, y; - QQuickPathItemGenericRenderer::Color4ub color; - void set(float nx, float ny, QQuickPathItemGenericRenderer::Color4ub ncolor) + QQuickShapeGenericRenderer::Color4ub color; + void set(float nx, float ny, QQuickShapeGenericRenderer::Color4ub ncolor) { x = nx; y = ny; color = ncolor; } }; -static inline QQuickPathItemGenericRenderer::Color4ub colorToColor4ub(const QColor &c) +static inline QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor &c) { - QQuickPathItemGenericRenderer::Color4ub color = { + QQuickShapeGenericRenderer::Color4ub color = { uchar(qRound(c.redF() * c.alphaF() * 255)), uchar(qRound(c.greenF() * c.alphaF() * 255)), uchar(qRound(c.blueF() * c.alphaF() * 255)), @@ -74,7 +74,7 @@ static inline QQuickPathItemGenericRenderer::Color4ub colorToColor4ub(const QCol return color; } -QQuickPathItemGenericStrokeFillNode::QQuickPathItemGenericStrokeFillNode(QQuickWindow *window) +QQuickShapeGenericStrokeFillNode::QQuickShapeGenericStrokeFillNode(QQuickWindow *window) : m_geometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0)), m_window(window), m_material(nullptr) @@ -86,24 +86,24 @@ QQuickPathItemGenericStrokeFillNode::QQuickPathItemGenericStrokeFillNode(QQuickW #endif } -QQuickPathItemGenericStrokeFillNode::~QQuickPathItemGenericStrokeFillNode() +QQuickShapeGenericStrokeFillNode::~QQuickShapeGenericStrokeFillNode() { delete m_geometry; } -void QQuickPathItemGenericStrokeFillNode::activateMaterial(Material m) +void QQuickShapeGenericStrokeFillNode::activateMaterial(Material m) { switch (m) { case MatSolidColor: // Use vertexcolor material. Items with different colors remain batchable // this way, at the expense of having to provide per-vertex color values. if (!m_solidColorMaterial) - m_solidColorMaterial.reset(QQuickPathItemGenericMaterialFactory::createVertexColor(m_window)); + m_solidColorMaterial.reset(QQuickShapeGenericMaterialFactory::createVertexColor(m_window)); m_material = m_solidColorMaterial.data(); break; case MatLinearGradient: if (!m_linearGradientMaterial) - m_linearGradientMaterial.reset(QQuickPathItemGenericMaterialFactory::createLinearGradient(m_window, this)); + m_linearGradientMaterial.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(m_window, this)); m_material = m_linearGradientMaterial.data(); break; default: @@ -148,9 +148,9 @@ static bool q_supportsElementIndexUint(QSGRendererInterface::GraphicsApi api) return elementIndexUint; } -QQuickPathItemGenericRenderer::~QQuickPathItemGenericRenderer() +QQuickShapeGenericRenderer::~QQuickShapeGenericRenderer() { - for (VisualPathData &d : m_vp) { + for (ShapePathData &d : m_sp) { if (d.pendingFill) d.pendingFill->orphaned = true; if (d.pendingStroke) @@ -161,95 +161,95 @@ QQuickPathItemGenericRenderer::~QQuickPathItemGenericRenderer() // sync, and so triangulation too, happens on the gui thread // - except when async is set, in which case triangulation is moved to worker threads -void QQuickPathItemGenericRenderer::beginSync(int totalCount) +void QQuickShapeGenericRenderer::beginSync(int totalCount) { - if (m_vp.count() != totalCount) { - m_vp.resize(totalCount); + if (m_sp.count() != totalCount) { + m_sp.resize(totalCount); m_accDirty |= DirtyList; } - for (VisualPathData &d : m_vp) + for (ShapePathData &d : m_sp) d.syncDirty = 0; } -void QQuickPathItemGenericRenderer::setPath(int index, const QQuickPath *path) +void QQuickShapeGenericRenderer::setPath(int index, const QQuickPath *path) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.path = path ? path->path() : QPainterPath(); d.syncDirty |= DirtyFillGeom | DirtyStrokeGeom; } -void QQuickPathItemGenericRenderer::setJSPath(int index, const QQuickPathItemPath &path) +void QQuickShapeGenericRenderer::setJSPath(int index, const QQuickShapePathCommands &path) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.path = path.toPainterPath(); d.syncDirty |= DirtyFillGeom | DirtyStrokeGeom; } -void QQuickPathItemGenericRenderer::setStrokeColor(int index, const QColor &color) +void QQuickShapeGenericRenderer::setStrokeColor(int index, const QColor &color) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.strokeColor = colorToColor4ub(color); d.syncDirty |= DirtyColor; } -void QQuickPathItemGenericRenderer::setStrokeWidth(int index, qreal w) +void QQuickShapeGenericRenderer::setStrokeWidth(int index, qreal w) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.strokeWidth = w; if (w >= 0.0f) d.pen.setWidthF(w); d.syncDirty |= DirtyStrokeGeom; } -void QQuickPathItemGenericRenderer::setFillColor(int index, const QColor &color) +void QQuickShapeGenericRenderer::setFillColor(int index, const QColor &color) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.fillColor = colorToColor4ub(color); d.syncDirty |= DirtyColor; } -void QQuickPathItemGenericRenderer::setFillRule(int index, QQuickVisualPath::FillRule fillRule) +void QQuickShapeGenericRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.fillRule = Qt::FillRule(fillRule); d.syncDirty |= DirtyFillGeom; } -void QQuickPathItemGenericRenderer::setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) +void QQuickShapeGenericRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.pen.setJoinStyle(Qt::PenJoinStyle(joinStyle)); d.pen.setMiterLimit(miterLimit); d.syncDirty |= DirtyStrokeGeom; } -void QQuickPathItemGenericRenderer::setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) +void QQuickShapeGenericRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.pen.setCapStyle(Qt::PenCapStyle(capStyle)); d.syncDirty |= DirtyStrokeGeom; } -void QQuickPathItemGenericRenderer::setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, +void QQuickShapeGenericRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.pen.setStyle(Qt::PenStyle(strokeStyle)); - if (strokeStyle == QQuickVisualPath::DashLine) { + if (strokeStyle == QQuickShapePath::DashLine) { d.pen.setDashPattern(dashPattern); d.pen.setDashOffset(dashOffset); } d.syncDirty |= DirtyStrokeGeom; } -void QQuickPathItemGenericRenderer::setFillGradient(int index, QQuickPathGradient *gradient) +void QQuickShapeGenericRenderer::setFillGradient(int index, QQuickShapeGradient *gradient) { - VisualPathData &d(m_vp[index]); + ShapePathData &d(m_sp[index]); d.fillGradientActive = gradient != nullptr; if (gradient) { d.fillGradient.stops = gradient->sortedGradientStops(); d.fillGradient.spread = gradient->spread(); - if (QQuickPathLinearGradient *g = qobject_cast<QQuickPathLinearGradient *>(gradient)) { + if (QQuickShapeLinearGradient *g = qobject_cast<QQuickShapeLinearGradient *>(gradient)) { d.fillGradient.start = QPointF(g->x1(), g->y1()); d.fillGradient.end = QPointF(g->x2(), g->y2()); } else { @@ -259,19 +259,19 @@ void QQuickPathItemGenericRenderer::setFillGradient(int index, QQuickPathGradien d.syncDirty |= DirtyFillGradient; } -void QQuickPathItemFillRunnable::run() +void QQuickShapeFillRunnable::run() { - QQuickPathItemGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices, &indexType, supportsElementIndexUint); + QQuickShapeGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices, &indexType, supportsElementIndexUint); emit done(this); } -void QQuickPathItemStrokeRunnable::run() +void QQuickShapeStrokeRunnable::run() { - QQuickPathItemGenericRenderer::triangulateStroke(path, pen, strokeColor, &strokeVertices, clipSize); + QQuickShapeGenericRenderer::triangulateStroke(path, pen, strokeColor, &strokeVertices, clipSize); emit done(this); } -void QQuickPathItemGenericRenderer::setAsyncCallback(void (*callback)(void *), void *data) +void QQuickShapeGenericRenderer::setAsyncCallback(void (*callback)(void *), void *data) { m_asyncCallback = callback; m_asyncCallbackData = data; @@ -285,12 +285,12 @@ static void deletePathWorkThreadPool() pathWorkThreadPool = nullptr; } -void QQuickPathItemGenericRenderer::endSync(bool async) +void QQuickShapeGenericRenderer::endSync(bool async) { bool didKickOffAsync = false; - for (int i = 0; i < m_vp.count(); ++i) { - VisualPathData &d(m_vp[i]); + for (int i = 0; i < m_sp.count(); ++i) { + ShapePathData &d(m_sp[i]); if (!d.syncDirty) continue; @@ -322,7 +322,7 @@ void QQuickPathItemGenericRenderer::endSync(bool async) if (m_api == QSGRendererInterface::Unknown) m_api = m_item->window()->rendererInterface()->graphicsApi(); if (async) { - QQuickPathItemFillRunnable *r = new QQuickPathItemFillRunnable; + QQuickShapeFillRunnable *r = new QQuickShapeFillRunnable; r->setAutoDelete(false); if (d.pendingFill) d.pendingFill->orphaned = true; @@ -330,13 +330,13 @@ void QQuickPathItemGenericRenderer::endSync(bool async) r->path = d.path; r->fillColor = d.fillColor; r->supportsElementIndexUint = q_supportsElementIndexUint(m_api); - // Unlikely in practice but in theory m_vp could be + // Unlikely in practice but in theory m_sp could be // resized. Therefore, capture 'i' instead of 'd'. - QObject::connect(r, &QQuickPathItemFillRunnable::done, qApp, [this, i](QQuickPathItemFillRunnable *r) { + QObject::connect(r, &QQuickShapeFillRunnable::done, qApp, [this, i](QQuickShapeFillRunnable *r) { // Bail out when orphaned (meaning either another run was // started after this one, or the renderer got destroyed). - if (!r->orphaned && i < m_vp.count()) { - VisualPathData &d(m_vp[i]); + if (!r->orphaned && i < m_sp.count()) { + ShapePathData &d(m_sp[i]); d.fillVertices = r->fillVertices; d.fillIndices = r->fillIndices; d.indexType = r->indexType; @@ -355,7 +355,7 @@ void QQuickPathItemGenericRenderer::endSync(bool async) if ((d.syncDirty & DirtyStrokeGeom) && d.strokeWidth >= 0.0f && d.strokeColor.a) { if (async) { - QQuickPathItemStrokeRunnable *r = new QQuickPathItemStrokeRunnable; + QQuickShapeStrokeRunnable *r = new QQuickShapeStrokeRunnable; r->setAutoDelete(false); if (d.pendingStroke) d.pendingStroke->orphaned = true; @@ -364,9 +364,9 @@ void QQuickPathItemGenericRenderer::endSync(bool async) r->pen = d.pen; r->strokeColor = d.strokeColor; r->clipSize = QSize(m_item->width(), m_item->height()); - QObject::connect(r, &QQuickPathItemStrokeRunnable::done, qApp, [this, i](QQuickPathItemStrokeRunnable *r) { - if (!r->orphaned && i < m_vp.count()) { - VisualPathData &d(m_vp[i]); + QObject::connect(r, &QQuickShapeStrokeRunnable::done, qApp, [this, i](QQuickShapeStrokeRunnable *r) { + if (!r->orphaned && i < m_sp.count()) { + ShapePathData &d(m_sp[i]); d.strokeVertices = r->strokeVertices; d.pendingStroke = nullptr; d.effectiveDirty |= DirtyStrokeGeom; @@ -387,9 +387,9 @@ void QQuickPathItemGenericRenderer::endSync(bool async) m_asyncCallback(m_asyncCallbackData); } -void QQuickPathItemGenericRenderer::maybeUpdateAsyncItem() +void QQuickShapeGenericRenderer::maybeUpdateAsyncItem() { - for (const VisualPathData &d : qAsConst(m_vp)) { + for (const ShapePathData &d : qAsConst(m_sp)) { if (d.pendingFill || d.pendingStroke) return; } @@ -401,7 +401,7 @@ void QQuickPathItemGenericRenderer::maybeUpdateAsyncItem() // the stroke/fill triangulation functions may be invoked either on the gui // thread or some worker thread and must thus be self-contained. -void QQuickPathItemGenericRenderer::triangulateFill(const QPainterPath &path, +void QQuickShapeGenericRenderer::triangulateFill(const QPainterPath &path, const Color4ub &fillColor, VertexContainerType *fillVertices, IndexContainerType *fillIndices, @@ -433,7 +433,7 @@ void QQuickPathItemGenericRenderer::triangulateFill(const QPainterPath &path, memcpy(fillIndices->data(), ts.indices.data(), indexByteSize); } -void QQuickPathItemGenericRenderer::triangulateStroke(const QPainterPath &path, +void QQuickShapeGenericRenderer::triangulateStroke(const QPainterPath &path, const QPen &pen, const Color4ub &strokeColor, VertexContainerType *strokeVertices, @@ -470,7 +470,7 @@ void QQuickPathItemGenericRenderer::triangulateStroke(const QPainterPath &path, vdst[i].set(vsrc[i * 2], vsrc[i * 2 + 1], strokeColor); } -void QQuickPathItemGenericRenderer::setRootNode(QQuickPathItemGenericNode *node) +void QQuickShapeGenericRenderer::setRootNode(QQuickShapeGenericNode *node) { if (m_rootNode != node) { m_rootNode = node; @@ -479,7 +479,7 @@ void QQuickPathItemGenericRenderer::setRootNode(QQuickPathItemGenericNode *node) } // on the render thread with gui blocked -void QQuickPathItemGenericRenderer::updateNode() +void QQuickShapeGenericRenderer::updateNode() { if (!m_rootNode || !m_accDirty) return; @@ -494,17 +494,17 @@ void QQuickPathItemGenericRenderer::updateNode() // ... // ... - QQuickPathItemGenericNode **nodePtr = &m_rootNode; - QQuickPathItemGenericNode *prevNode = nullptr; + QQuickShapeGenericNode **nodePtr = &m_rootNode; + QQuickShapeGenericNode *prevNode = nullptr; - for (VisualPathData &d : m_vp) { + for (ShapePathData &d : m_sp) { if (!*nodePtr) { - *nodePtr = new QQuickPathItemGenericNode; + *nodePtr = new QQuickShapeGenericNode; prevNode->m_next = *nodePtr; prevNode->appendChildNode(*nodePtr); } - QQuickPathItemGenericNode *node = *nodePtr; + QQuickShapeGenericNode *node = *nodePtr; if (m_accDirty & DirtyList) d.effectiveDirty |= DirtyFillGeom | DirtyStrokeGeom | DirtyColor | DirtyFillGradient; @@ -519,7 +519,7 @@ void QQuickPathItemGenericRenderer::updateNode() delete node->m_fillNode; node->m_fillNode = nullptr; } else if (!node->m_fillNode) { - node->m_fillNode = new QQuickPathItemGenericStrokeFillNode(m_item->window()); + node->m_fillNode = new QQuickShapeGenericStrokeFillNode(m_item->window()); if (node->m_strokeNode) node->removeChildNode(node->m_strokeNode); node->appendChildNode(node->m_fillNode); @@ -532,7 +532,7 @@ void QQuickPathItemGenericRenderer::updateNode() delete node->m_strokeNode; node->m_strokeNode = nullptr; } else if (!node->m_strokeNode) { - node->m_strokeNode = new QQuickPathItemGenericStrokeFillNode(m_item->window()); + node->m_strokeNode = new QQuickShapeGenericStrokeFillNode(m_item->window()); node->appendChildNode(node->m_strokeNode); d.effectiveDirty |= DirtyStrokeGeom; } @@ -555,7 +555,7 @@ void QQuickPathItemGenericRenderer::updateNode() m_accDirty = 0; } -void QQuickPathItemGenericRenderer::updateShadowDataInNode(VisualPathData *d, QQuickPathItemGenericStrokeFillNode *n) +void QQuickShapeGenericRenderer::updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n) { if (d->fillGradientActive) { if (d->effectiveDirty & DirtyFillGradient) @@ -563,7 +563,7 @@ void QQuickPathItemGenericRenderer::updateShadowDataInNode(VisualPathData *d, QQ } } -void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPathItemGenericNode *node) +void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node) { if (!node->m_fillNode) return; @@ -572,7 +572,7 @@ void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPath // Make a copy of the data that will be accessed by the material on // the render thread. This must be done even when we bail out below. - QQuickPathItemGenericStrokeFillNode *n = node->m_fillNode; + QQuickShapeGenericStrokeFillNode *n = node->m_fillNode; updateShadowDataInNode(d, n); QSGGeometry *g = n->m_geometry; @@ -585,7 +585,7 @@ void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPath } if (d->fillGradientActive) { - n->activateMaterial(QQuickPathItemGenericStrokeFillNode::MatLinearGradient); + n->activateMaterial(QQuickShapeGenericStrokeFillNode::MatLinearGradient); if (d->effectiveDirty & DirtyFillGradient) { // Gradients are implemented via a texture-based material. n->markDirty(QSGNode::DirtyMaterial); @@ -594,7 +594,7 @@ void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPath return; } } else { - n->activateMaterial(QQuickPathItemGenericStrokeFillNode::MatSolidColor); + n->activateMaterial(QQuickShapeGenericStrokeFillNode::MatSolidColor); // fast path for updating only color values when no change in vertex positions if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyFillGeom)) { ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData()); @@ -623,14 +623,14 @@ void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPath n->markDirty(QSGNode::DirtyGeometry); } -void QQuickPathItemGenericRenderer::updateStrokeNode(VisualPathData *d, QQuickPathItemGenericNode *node) +void QQuickShapeGenericRenderer::updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node) { if (!node->m_strokeNode) return; if (!(d->effectiveDirty & (DirtyStrokeGeom | DirtyColor))) return; - QQuickPathItemGenericStrokeFillNode *n = node->m_strokeNode; + QQuickShapeGenericStrokeFillNode *n = node->m_strokeNode; QSGGeometry *g = n->m_geometry; if (d->strokeVertices.isEmpty()) { if (g->vertexCount() || g->indexCount()) { @@ -660,7 +660,7 @@ void QQuickPathItemGenericRenderer::updateStrokeNode(VisualPathData *d, QQuickPa memcpy(g->vertexData(), d->strokeVertices.constData(), g->vertexCount() * g->sizeOfVertex()); } -QSGMaterial *QQuickPathItemGenericMaterialFactory::createVertexColor(QQuickWindow *window) +QSGMaterial *QQuickShapeGenericMaterialFactory::createVertexColor(QQuickWindow *window) { QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi(); @@ -673,14 +673,14 @@ QSGMaterial *QQuickPathItemGenericMaterialFactory::createVertexColor(QQuickWindo return nullptr; } -QSGMaterial *QQuickPathItemGenericMaterialFactory::createLinearGradient(QQuickWindow *window, - QQuickPathItemGenericStrokeFillNode *node) +QSGMaterial *QQuickShapeGenericMaterialFactory::createLinearGradient(QQuickWindow *window, + QQuickShapeGenericStrokeFillNode *node) { QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi(); #ifndef QT_NO_OPENGL if (api == QSGRendererInterface::OpenGL) // ### so much for "generic"... - return new QQuickPathItemLinearGradientMaterial(node); + return new QQuickShapeLinearGradientMaterial(node); #endif qWarning("Linear gradient material: Unsupported graphics API %d", api); @@ -689,9 +689,9 @@ QSGMaterial *QQuickPathItemGenericMaterialFactory::createLinearGradient(QQuickWi #ifndef QT_NO_OPENGL -QSGMaterialType QQuickPathItemLinearGradientShader::type; +QSGMaterialType QQuickShapeLinearGradientShader::type; -QQuickPathItemLinearGradientShader::QQuickPathItemLinearGradientShader() +QQuickShapeLinearGradientShader::QQuickShapeLinearGradientShader() { setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/lineargradient.vert")); @@ -699,7 +699,7 @@ QQuickPathItemLinearGradientShader::QQuickPathItemLinearGradientShader() QStringLiteral(":/qt-project.org/items/shaders/lineargradient.frag")); } -void QQuickPathItemLinearGradientShader::initialize() +void QQuickShapeLinearGradientShader::initialize() { m_opacityLoc = program()->uniformLocation("opacity"); m_matrixLoc = program()->uniformLocation("matrix"); @@ -707,9 +707,9 @@ void QQuickPathItemLinearGradientShader::initialize() m_gradEndLoc = program()->uniformLocation("gradEnd"); } -void QQuickPathItemLinearGradientShader::updateState(const RenderState &state, QSGMaterial *mat, QSGMaterial *) +void QQuickShapeLinearGradientShader::updateState(const RenderState &state, QSGMaterial *mat, QSGMaterial *) { - QQuickPathItemLinearGradientMaterial *m = static_cast<QQuickPathItemLinearGradientMaterial *>(mat); + QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(mat); if (state.isOpacityDirty()) program()->setUniformValue(m_opacityLoc, state.opacity()); @@ -717,33 +717,33 @@ void QQuickPathItemLinearGradientShader::updateState(const RenderState &state, Q if (state.isMatrixDirty()) program()->setUniformValue(m_matrixLoc, state.combinedMatrix()); - QQuickPathItemGenericStrokeFillNode *node = m->node(); + QQuickShapeGenericStrokeFillNode *node = m->node(); program()->setUniformValue(m_gradStartLoc, QVector2D(node->m_fillGradient.start)); program()->setUniformValue(m_gradEndLoc, QVector2D(node->m_fillGradient.end)); - QSGTexture *tx = QQuickPathItemGradientCache::currentCache()->get(node->m_fillGradient); + QSGTexture *tx = QQuickShapeGradientCache::currentCache()->get(node->m_fillGradient); tx->bind(); } -char const *const *QQuickPathItemLinearGradientShader::attributeNames() const +char const *const *QQuickShapeLinearGradientShader::attributeNames() const { static const char *const attr[] = { "vertexCoord", "vertexColor", nullptr }; return attr; } -int QQuickPathItemLinearGradientMaterial::compare(const QSGMaterial *other) const +int QQuickShapeLinearGradientMaterial::compare(const QSGMaterial *other) const { Q_ASSERT(other && type() == other->type()); - const QQuickPathItemLinearGradientMaterial *m = static_cast<const QQuickPathItemLinearGradientMaterial *>(other); + const QQuickShapeLinearGradientMaterial *m = static_cast<const QQuickShapeLinearGradientMaterial *>(other); - QQuickPathItemGenericStrokeFillNode *a = node(); - QQuickPathItemGenericStrokeFillNode *b = m->node(); + QQuickShapeGenericStrokeFillNode *a = node(); + QQuickShapeGenericStrokeFillNode *b = m->node(); Q_ASSERT(a && b); if (a == b) return 0; - const QQuickPathItemGradientCache::GradientDesc *ga = &a->m_fillGradient; - const QQuickPathItemGradientCache::GradientDesc *gb = &b->m_fillGradient; + const QQuickShapeGradientCache::GradientDesc *ga = &a->m_fillGradient; + const QQuickShapeGradientCache::GradientDesc *gb = &b->m_fillGradient; if (int d = ga->spread - gb->spread) return d; diff --git a/src/imports/pathitem/qquickpathitemgenericrenderer_p.h b/src/imports/shapes/qquickshapegenericrenderer_p.h index 70a9e88d2f..ba50f50309 100644 --- a/src/imports/pathitem/qquickpathitemgenericrenderer_p.h +++ b/src/imports/shapes/qquickshapegenericrenderer_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQUICKPATHITEMGENERICRENDERER_P_H -#define QQUICKPATHITEMGENERICRENDERER_P_H +#ifndef QQUICKSHAPEGENERICRENDERER_P_H +#define QQUICKSHAPEGENERICRENDERER_P_H // // W A R N I N G @@ -51,7 +51,7 @@ // We mean it. // -#include "qquickpathitem_p_p.h" +#include "qquickshape_p_p.h" #include <qsgnode.h> #include <qsggeometry.h> #include <qsgmaterial.h> @@ -60,12 +60,12 @@ QT_BEGIN_NAMESPACE -class QQuickPathItemGenericNode; -class QQuickPathItemGenericStrokeFillNode; -class QQuickPathItemFillRunnable; -class QQuickPathItemStrokeRunnable; +class QQuickShapeGenericNode; +class QQuickShapeGenericStrokeFillNode; +class QQuickShapeFillRunnable; +class QQuickShapeStrokeRunnable; -class QQuickPathItemGenericRenderer : public QQuickAbstractPathRenderer +class QQuickShapeGenericRenderer : public QQuickAbstractPathRenderer { public: enum Dirty { @@ -76,34 +76,34 @@ public: DirtyList = 0x10 // only for accDirty }; - QQuickPathItemGenericRenderer(QQuickItem *item) + QQuickShapeGenericRenderer(QQuickItem *item) : m_item(item), m_api(QSGRendererInterface::Unknown), m_rootNode(nullptr), m_accDirty(0), m_asyncCallback(nullptr) { } - ~QQuickPathItemGenericRenderer(); + ~QQuickShapeGenericRenderer(); void beginSync(int totalCount) override; void setPath(int index, const QQuickPath *path) override; - void setJSPath(int index, const QQuickPathItemPath &path) override; + void setJSPath(int index, const QQuickShapePathCommands &path) override; void setStrokeColor(int index, const QColor &color) override; void setStrokeWidth(int index, qreal w) override; void setFillColor(int index, const QColor &color) override; - void setFillRule(int index, QQuickVisualPath::FillRule fillRule) override; - void setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) override; - void setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) override; - void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, + void setFillRule(int index, QQuickShapePath::FillRule fillRule) override; + void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override; + void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override; + void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) override; - void setFillGradient(int index, QQuickPathGradient *gradient) override; + void setFillGradient(int index, QQuickShapeGradient *gradient) override; void endSync(bool async) override; void setAsyncCallback(void (*)(void *), void *) override; Flags flags() const override { return SupportsAsync; } void updateNode() override; - void setRootNode(QQuickPathItemGenericNode *node); + void setRootNode(QQuickShapeGenericNode *node); struct Color4ub { unsigned char r, g, b, a; }; typedef QVector<QSGGeometry::ColoredPoint2D> VertexContainerType; @@ -124,7 +124,7 @@ public: private: void maybeUpdateAsyncItem(); - struct VisualPathData { + struct ShapePathData { float strokeWidth; QPen pen; Color4ub strokeColor; @@ -132,31 +132,31 @@ private: Qt::FillRule fillRule; QPainterPath path; bool fillGradientActive; - QQuickPathItemGradientCache::GradientDesc fillGradient; + QQuickShapeGradientCache::GradientDesc fillGradient; VertexContainerType fillVertices; IndexContainerType fillIndices; QSGGeometry::Type indexType; VertexContainerType strokeVertices; int syncDirty; int effectiveDirty = 0; - QQuickPathItemFillRunnable *pendingFill = nullptr; - QQuickPathItemStrokeRunnable *pendingStroke = nullptr; + QQuickShapeFillRunnable *pendingFill = nullptr; + QQuickShapeStrokeRunnable *pendingStroke = nullptr; }; - void updateShadowDataInNode(VisualPathData *d, QQuickPathItemGenericStrokeFillNode *n); - void updateFillNode(VisualPathData *d, QQuickPathItemGenericNode *node); - void updateStrokeNode(VisualPathData *d, QQuickPathItemGenericNode *node); + void updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n); + void updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node); + void updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node); QQuickItem *m_item; QSGRendererInterface::GraphicsApi m_api; - QQuickPathItemGenericNode *m_rootNode; - QVector<VisualPathData> m_vp; + QQuickShapeGenericNode *m_rootNode; + QVector<ShapePathData> m_sp; int m_accDirty; void (*m_asyncCallback)(void *); void *m_asyncCallbackData; }; -class QQuickPathItemFillRunnable : public QObject, public QRunnable +class QQuickShapeFillRunnable : public QObject, public QRunnable { Q_OBJECT @@ -167,19 +167,19 @@ public: // input QPainterPath path; - QQuickPathItemGenericRenderer::Color4ub fillColor; + QQuickShapeGenericRenderer::Color4ub fillColor; bool supportsElementIndexUint; // output - QQuickPathItemGenericRenderer::VertexContainerType fillVertices; - QQuickPathItemGenericRenderer::IndexContainerType fillIndices; + QQuickShapeGenericRenderer::VertexContainerType fillVertices; + QQuickShapeGenericRenderer::IndexContainerType fillIndices; QSGGeometry::Type indexType; Q_SIGNALS: - void done(QQuickPathItemFillRunnable *self); + void done(QQuickShapeFillRunnable *self); }; -class QQuickPathItemStrokeRunnable : public QObject, public QRunnable +class QQuickShapeStrokeRunnable : public QObject, public QRunnable { Q_OBJECT @@ -191,21 +191,21 @@ public: // input QPainterPath path; QPen pen; - QQuickPathItemGenericRenderer::Color4ub strokeColor; + QQuickShapeGenericRenderer::Color4ub strokeColor; QSize clipSize; // output - QQuickPathItemGenericRenderer::VertexContainerType strokeVertices; + QQuickShapeGenericRenderer::VertexContainerType strokeVertices; Q_SIGNALS: - void done(QQuickPathItemStrokeRunnable *self); + void done(QQuickShapeStrokeRunnable *self); }; -class QQuickPathItemGenericStrokeFillNode : public QSGGeometryNode +class QQuickShapeGenericStrokeFillNode : public QSGGeometryNode { public: - QQuickPathItemGenericStrokeFillNode(QQuickWindow *window); - ~QQuickPathItemGenericStrokeFillNode(); + QQuickShapeGenericStrokeFillNode(QQuickWindow *window); + ~QQuickShapeGenericStrokeFillNode(); enum Material { MatSolidColor, @@ -217,7 +217,7 @@ public: QQuickWindow *window() const { return m_window; } // shadow data for custom materials - QQuickPathItemGradientCache::GradientDesc m_fillGradient; + QQuickShapeGradientCache::GradientDesc m_fillGradient; private: QSGGeometry *m_geometry; @@ -226,30 +226,30 @@ private: QScopedPointer<QSGMaterial> m_solidColorMaterial; QScopedPointer<QSGMaterial> m_linearGradientMaterial; - friend class QQuickPathItemGenericRenderer; + friend class QQuickShapeGenericRenderer; }; -class QQuickPathItemGenericNode : public QSGNode +class QQuickShapeGenericNode : public QSGNode { public: - QQuickPathItemGenericStrokeFillNode *m_fillNode = nullptr; - QQuickPathItemGenericStrokeFillNode *m_strokeNode = nullptr; - QQuickPathItemGenericNode *m_next = nullptr; + QQuickShapeGenericStrokeFillNode *m_fillNode = nullptr; + QQuickShapeGenericStrokeFillNode *m_strokeNode = nullptr; + QQuickShapeGenericNode *m_next = nullptr; }; -class QQuickPathItemGenericMaterialFactory +class QQuickShapeGenericMaterialFactory { public: static QSGMaterial *createVertexColor(QQuickWindow *window); - static QSGMaterial *createLinearGradient(QQuickWindow *window, QQuickPathItemGenericStrokeFillNode *node); + static QSGMaterial *createLinearGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node); }; #ifndef QT_NO_OPENGL -class QQuickPathItemLinearGradientShader : public QSGMaterialShader +class QQuickShapeLinearGradientShader : public QSGMaterialShader { public: - QQuickPathItemLinearGradientShader(); + QQuickShapeLinearGradientShader(); void initialize() override; void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; @@ -264,40 +264,40 @@ private: int m_gradEndLoc; }; -class QQuickPathItemLinearGradientMaterial : public QSGMaterial +class QQuickShapeLinearGradientMaterial : public QSGMaterial { public: - QQuickPathItemLinearGradientMaterial(QQuickPathItemGenericStrokeFillNode *node) + QQuickShapeLinearGradientMaterial(QQuickShapeGenericStrokeFillNode *node) : m_node(node) { // Passing RequiresFullMatrix is essential in order to prevent the // batch renderer from baking in simple, translate-only transforms into // the vertex data. The shader will rely on the fact that - // vertexCoord.xy is the PathItem-space coordinate and so no modifications + // vertexCoord.xy is the Shape-space coordinate and so no modifications // are welcome. setFlag(Blending | RequiresFullMatrix); } QSGMaterialType *type() const override { - return &QQuickPathItemLinearGradientShader::type; + return &QQuickShapeLinearGradientShader::type; } int compare(const QSGMaterial *other) const override; QSGMaterialShader *createShader() const override { - return new QQuickPathItemLinearGradientShader; + return new QQuickShapeLinearGradientShader; } - QQuickPathItemGenericStrokeFillNode *node() const { return m_node; } + QQuickShapeGenericStrokeFillNode *node() const { return m_node; } private: - QQuickPathItemGenericStrokeFillNode *m_node; + QQuickShapeGenericStrokeFillNode *m_node; }; #endif // QT_NO_OPENGL QT_END_NAMESPACE -#endif // QQUICKPATHITEMGENERICRENDERER_P_H +#endif // QQUICKSHAPEGENERICRENDERER_P_H diff --git a/src/imports/pathitem/qquickpathitemnvprrenderer.cpp b/src/imports/shapes/qquickshapenvprrenderer.cpp index f8504f9985..a3e9d31be5 100644 --- a/src/imports/pathitem/qquickpathitemnvprrenderer.cpp +++ b/src/imports/shapes/qquickshapenvprrenderer.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "qquickpathitemnvprrenderer_p.h" +#include "qquickshapenvprrenderer_p.h" #include <QOpenGLExtraFunctions> #include <QOpenGLFramebufferObject> #include <QOpenGLShaderProgram> @@ -46,98 +46,98 @@ QT_BEGIN_NAMESPACE -void QQuickPathItemNvprRenderer::beginSync(int totalCount) +void QQuickShapeNvprRenderer::beginSync(int totalCount) { - if (m_vp.count() != totalCount) { - m_vp.resize(totalCount); + if (m_sp.count() != totalCount) { + m_sp.resize(totalCount); m_accDirty |= DirtyList; } } -void QQuickPathItemNvprRenderer::setPath(int index, const QQuickPath *path) +void QQuickShapeNvprRenderer::setPath(int index, const QQuickPath *path) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); convertPath(path, &d); d.dirty |= DirtyPath; m_accDirty |= DirtyPath; } -void QQuickPathItemNvprRenderer::setJSPath(int index, const QQuickPathItemPath &path) +void QQuickShapeNvprRenderer::setJSPath(int index, const QQuickShapePathCommands &path) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); convertJSPath(path, &d); d.dirty |= DirtyPath; m_accDirty |= DirtyPath; } -void QQuickPathItemNvprRenderer::setStrokeColor(int index, const QColor &color) +void QQuickShapeNvprRenderer::setStrokeColor(int index, const QColor &color) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.strokeColor = color; d.dirty |= DirtyStyle; m_accDirty |= DirtyStyle; } -void QQuickPathItemNvprRenderer::setStrokeWidth(int index, qreal w) +void QQuickShapeNvprRenderer::setStrokeWidth(int index, qreal w) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.strokeWidth = w; d.dirty |= DirtyStyle; m_accDirty |= DirtyStyle; } -void QQuickPathItemNvprRenderer::setFillColor(int index, const QColor &color) +void QQuickShapeNvprRenderer::setFillColor(int index, const QColor &color) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.fillColor = color; d.dirty |= DirtyStyle; m_accDirty |= DirtyStyle; } -void QQuickPathItemNvprRenderer::setFillRule(int index, QQuickVisualPath::FillRule fillRule) +void QQuickShapeNvprRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.fillRule = fillRule; d.dirty |= DirtyFillRule; m_accDirty |= DirtyFillRule; } -void QQuickPathItemNvprRenderer::setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) +void QQuickShapeNvprRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.joinStyle = joinStyle; d.miterLimit = miterLimit; d.dirty |= DirtyStyle; m_accDirty |= DirtyStyle; } -void QQuickPathItemNvprRenderer::setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) +void QQuickShapeNvprRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.capStyle = capStyle; d.dirty |= DirtyStyle; m_accDirty |= DirtyStyle; } -void QQuickPathItemNvprRenderer::setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, +void QQuickShapeNvprRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) { - VisualPathGuiData &d(m_vp[index]); - d.dashActive = strokeStyle == QQuickVisualPath::DashLine; + ShapePathGuiData &d(m_sp[index]); + d.dashActive = strokeStyle == QQuickShapePath::DashLine; d.dashOffset = dashOffset; d.dashPattern = dashPattern; d.dirty |= DirtyDash; m_accDirty |= DirtyDash; } -void QQuickPathItemNvprRenderer::setFillGradient(int index, QQuickPathGradient *gradient) +void QQuickShapeNvprRenderer::setFillGradient(int index, QQuickShapeGradient *gradient) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.fillGradientActive = gradient != nullptr; if (gradient) { d.fillGradient.stops = gradient->sortedGradientStops(); d.fillGradient.spread = gradient->spread(); - if (QQuickPathLinearGradient *g = qobject_cast<QQuickPathLinearGradient *>(gradient)) { + if (QQuickShapeLinearGradient *g = qobject_cast<QQuickShapeLinearGradient *>(gradient)) { d.fillGradient.start = QPointF(g->x1(), g->y1()); d.fillGradient.end = QPointF(g->x2(), g->y2()); } else { @@ -148,11 +148,11 @@ void QQuickPathItemNvprRenderer::setFillGradient(int index, QQuickPathGradient * m_accDirty |= DirtyFillGradient; } -void QQuickPathItemNvprRenderer::endSync(bool) +void QQuickShapeNvprRenderer::endSync(bool) { } -void QQuickPathItemNvprRenderer::setNode(QQuickPathItemNvprRenderNode *node) +void QQuickShapeNvprRenderer::setNode(QQuickShapeNvprRenderNode *node) { if (m_node != node) { m_node = node; @@ -160,7 +160,7 @@ void QQuickPathItemNvprRenderer::setNode(QQuickPathItemNvprRenderNode *node) } } -QDebug operator<<(QDebug debug, const QQuickPathItemNvprRenderer::NvprPath &path) +QDebug operator<<(QDebug debug, const QQuickShapeNvprRenderer::NvprPath &path) { QDebugStateSaver saver(debug); debug.space().noquote(); @@ -229,7 +229,7 @@ static inline void appendControl2Coords(QVector<GLfloat> *v, QQuickPathCubic *c, v->append(p.y()); } -void QQuickPathItemNvprRenderer::convertPath(const QQuickPath *path, VisualPathGuiData *d) +void QQuickShapeNvprRenderer::convertPath(const QQuickPath *path, ShapePathGuiData *d) { d->path = NvprPath(); if (!path) @@ -283,7 +283,7 @@ void QQuickPathItemNvprRenderer::convertPath(const QQuickPath *path, VisualPathG d->path.str = QString(QStringLiteral("M %1 %2 ")).arg(pos.x()).arg(pos.y()).toUtf8(); d->path.str.append(o->path().toUtf8()); } else { - qWarning() << "PathItem/NVPR: unsupported Path element" << e; + qWarning() << "Shape/NVPR: unsupported Path element" << e; } } @@ -296,7 +296,7 @@ void QQuickPathItemNvprRenderer::convertPath(const QQuickPath *path, VisualPathG d->path.cmd.append(GL_CLOSE_PATH_NV); } -void QQuickPathItemNvprRenderer::convertJSPath(const QQuickPathItemPath &path, VisualPathGuiData *d) +void QQuickShapeNvprRenderer::convertJSPath(const QQuickShapePathCommands &path, ShapePathGuiData *d) { d->path = NvprPath(); if (path.cmd.isEmpty()) @@ -306,9 +306,9 @@ void QQuickPathItemNvprRenderer::convertJSPath(const QQuickPathItemPath &path, V QPointF pos(startPos); int coordIdx = 0; - for (QQuickPathItemPath::Command cmd : path.cmd) { + for (QQuickShapePathCommands::Command cmd : path.cmd) { switch (cmd) { - case QQuickPathItemPath::MoveTo: + case QQuickShapePathCommands::MoveTo: d->path.cmd.append(GL_MOVE_TO_NV); pos = QPointF(path.coords[coordIdx], path.coords[coordIdx + 1]); startPos = pos; @@ -316,14 +316,14 @@ void QQuickPathItemNvprRenderer::convertJSPath(const QQuickPathItemPath &path, V d->path.coord.append(pos.y()); coordIdx += 2; break; - case QQuickPathItemPath::LineTo: + case QQuickShapePathCommands::LineTo: d->path.cmd.append(GL_LINE_TO_NV); pos = QPointF(path.coords[coordIdx], path.coords[coordIdx + 1]); d->path.coord.append(pos.x()); d->path.coord.append(pos.y()); coordIdx += 2; break; - case QQuickPathItemPath::QuadTo: + case QQuickShapePathCommands::QuadTo: d->path.cmd.append(GL_QUADRATIC_CURVE_TO_NV); d->path.coord.append(path.coords[coordIdx]); d->path.coord.append(path.coords[coordIdx + 1]); @@ -332,7 +332,7 @@ void QQuickPathItemNvprRenderer::convertJSPath(const QQuickPathItemPath &path, V d->path.coord.append(pos.y()); coordIdx += 4; break; - case QQuickPathItemPath::CubicTo: + case QQuickShapePathCommands::CubicTo: d->path.cmd.append(GL_CUBIC_CURVE_TO_NV); d->path.coord.append(path.coords[coordIdx]); d->path.coord.append(path.coords[coordIdx + 1]); @@ -343,7 +343,7 @@ void QQuickPathItemNvprRenderer::convertJSPath(const QQuickPathItemPath &path, V d->path.coord.append(pos.y()); coordIdx += 6; break; - case QQuickPathItemPath::ArcTo: + case QQuickShapePathCommands::ArcTo: { const bool sweepFlag = !qFuzzyIsNull(path.coords[coordIdx + 5]); const bool useLargeArc = !qFuzzyIsNull(path.coords[coordIdx + 6]); @@ -378,7 +378,7 @@ static inline QVector4D qsg_premultiply(const QColor &c, float globalOpacity) return QVector4D(c.redF() * o, c.greenF() * o, c.blueF() * o, o); } -void QQuickPathItemNvprRenderer::updateNode() +void QQuickShapeNvprRenderer::updateNode() { // Called on the render thread with gui blocked -> update the node with its // own copy of all relevant data. @@ -386,14 +386,14 @@ void QQuickPathItemNvprRenderer::updateNode() if (!m_accDirty) return; - const int count = m_vp.count(); + const int count = m_sp.count(); const bool listChanged = m_accDirty & DirtyList; if (listChanged) - m_node->m_vp.resize(count); + m_node->m_sp.resize(count); for (int i = 0; i < count; ++i) { - VisualPathGuiData &src(m_vp[i]); - QQuickPathItemNvprRenderNode::VisualPathRenderData &dst(m_node->m_vp[i]); + ShapePathGuiData &src(m_sp[i]); + QQuickShapeNvprRenderNode::ShapePathRenderData &dst(m_node->m_sp[i]); int dirty = src.dirty; src.dirty = 0; @@ -412,13 +412,13 @@ void QQuickPathItemNvprRenderer::updateNode() dst.strokeColor = qsg_premultiply(src.strokeColor, 1.0f); dst.fillColor = qsg_premultiply(src.fillColor, 1.0f); switch (src.joinStyle) { - case QQuickVisualPath::MiterJoin: + case QQuickShapePath::MiterJoin: dst.joinStyle = GL_MITER_TRUNCATE_NV; break; - case QQuickVisualPath::BevelJoin: + case QQuickShapePath::BevelJoin: dst.joinStyle = GL_BEVEL_NV; break; - case QQuickVisualPath::RoundJoin: + case QQuickShapePath::RoundJoin: dst.joinStyle = GL_ROUND_NV; break; default: @@ -426,13 +426,13 @@ void QQuickPathItemNvprRenderer::updateNode() } dst.miterLimit = src.miterLimit; switch (src.capStyle) { - case QQuickVisualPath::FlatCap: + case QQuickShapePath::FlatCap: dst.capStyle = GL_FLAT; break; - case QQuickVisualPath::SquareCap: + case QQuickShapePath::SquareCap: dst.capStyle = GL_SQUARE_NV; break; - case QQuickVisualPath::RoundCap: + case QQuickShapePath::RoundCap: dst.capStyle = GL_ROUND_NV; break; default: @@ -442,10 +442,10 @@ void QQuickPathItemNvprRenderer::updateNode() if (dirty & DirtyFillRule) { switch (src.fillRule) { - case QQuickVisualPath::OddEvenFill: + case QQuickShapePath::OddEvenFill: dst.fillRule = GL_INVERT; break; - case QQuickVisualPath::WindingFill: + case QQuickShapePath::WindingFill: dst.fillRule = GL_COUNT_UP_NV; break; default: @@ -457,7 +457,7 @@ void QQuickPathItemNvprRenderer::updateNode() dst.dashOffset = src.dashOffset; if (src.dashActive) { dst.dashPattern.resize(src.dashPattern.count()); - // Multiply by strokeWidth because the PathItem API follows QPen + // Multiply by strokeWidth because the Shape API follows QPen // meaning the input dash pattern here is in width units. for (int i = 0; i < src.dashPattern.count(); ++i) dst.dashPattern[i] = GLfloat(src.dashPattern[i]) * src.strokeWidth; @@ -477,18 +477,18 @@ void QQuickPathItemNvprRenderer::updateNode() m_accDirty = 0; } -bool QQuickPathItemNvprRenderNode::nvprInited = false; -QQuickNvprFunctions QQuickPathItemNvprRenderNode::nvpr; -QQuickNvprMaterialManager QQuickPathItemNvprRenderNode::mtlmgr; +bool QQuickShapeNvprRenderNode::nvprInited = false; +QQuickNvprFunctions QQuickShapeNvprRenderNode::nvpr; +QQuickNvprMaterialManager QQuickShapeNvprRenderNode::mtlmgr; -QQuickPathItemNvprRenderNode::~QQuickPathItemNvprRenderNode() +QQuickShapeNvprRenderNode::~QQuickShapeNvprRenderNode() { releaseResources(); } -void QQuickPathItemNvprRenderNode::releaseResources() +void QQuickShapeNvprRenderNode::releaseResources() { - for (VisualPathRenderData &d : m_vp) { + for (ShapePathRenderData &d : m_sp) { if (d.path) { nvpr.deletePaths(d.path, 1); d.path = 0; @@ -579,9 +579,9 @@ QQuickNvprMaterialManager::MaterialDesc *QQuickNvprMaterialManager::activateMate return &mtl; } -void QQuickPathItemNvprRenderNode::updatePath(VisualPathRenderData *d) +void QQuickShapeNvprRenderNode::updatePath(ShapePathRenderData *d) { - if (d->dirty & QQuickPathItemNvprRenderer::DirtyPath) { + if (d->dirty & QQuickShapeNvprRenderer::DirtyPath) { if (!d->path) { d->path = nvpr.genPaths(1); Q_ASSERT(d->path != 0); @@ -594,7 +594,7 @@ void QQuickPathItemNvprRenderNode::updatePath(VisualPathRenderData *d) } } - if (d->dirty & QQuickPathItemNvprRenderer::DirtyStyle) { + if (d->dirty & QQuickShapeNvprRenderer::DirtyStyle) { nvpr.pathParameterf(d->path, GL_PATH_STROKE_WIDTH_NV, d->strokeWidth); nvpr.pathParameteri(d->path, GL_PATH_JOIN_STYLE_NV, d->joinStyle); nvpr.pathParameteri(d->path, GL_PATH_MITER_LIMIT_NV, d->miterLimit); @@ -602,7 +602,7 @@ void QQuickPathItemNvprRenderNode::updatePath(VisualPathRenderData *d) nvpr.pathParameteri(d->path, GL_PATH_DASH_CAPS_NV, d->capStyle); } - if (d->dirty & QQuickPathItemNvprRenderer::DirtyDash) { + if (d->dirty & QQuickShapeNvprRenderer::DirtyDash) { nvpr.pathParameterf(d->path, GL_PATH_DASH_OFFSET_NV, d->dashOffset); // count == 0 -> no dash nvpr.pathDashArray(d->path, d->dashPattern.count(), d->dashPattern.constData()); @@ -612,7 +612,7 @@ void QQuickPathItemNvprRenderNode::updatePath(VisualPathRenderData *d) d->fallbackValid = false; } -void QQuickPathItemNvprRenderNode::renderStroke(VisualPathRenderData *d, int strokeStencilValue, int writeMask) +void QQuickShapeNvprRenderNode::renderStroke(ShapePathRenderData *d, int strokeStencilValue, int writeMask) { QQuickNvprMaterialManager::MaterialDesc *mtl = mtlmgr.activateMaterial(QQuickNvprMaterialManager::MatSolid); f->glProgramUniform4f(mtl->prg, mtl->uniLoc[0], @@ -622,12 +622,12 @@ void QQuickPathItemNvprRenderNode::renderStroke(VisualPathRenderData *d, int str nvpr.stencilThenCoverStrokePath(d->path, strokeStencilValue, writeMask, GL_CONVEX_HULL_NV); } -void QQuickPathItemNvprRenderNode::renderFill(VisualPathRenderData *d) +void QQuickShapeNvprRenderNode::renderFill(ShapePathRenderData *d) { QQuickNvprMaterialManager::MaterialDesc *mtl = nullptr; if (d->fillGradientActive) { mtl = mtlmgr.activateMaterial(QQuickNvprMaterialManager::MatLinearGradient); - QSGTexture *tx = QQuickPathItemGradientCache::currentCache()->get(d->fillGradient); + QSGTexture *tx = QQuickShapeGradientCache::currentCache()->get(d->fillGradient); tx->bind(); // uv = vec2(coeff[0] * x + coeff[1] * y + coeff[2], coeff[3] * x + coeff[4] * y + coeff[5]) // where x and y are in path coordinate space, which is just what @@ -648,7 +648,7 @@ void QQuickPathItemNvprRenderNode::renderFill(VisualPathRenderData *d) nvpr.stencilThenCoverFillPath(d->path, d->fillRule, writeMask, GL_BOUNDING_BOX_NV); } -void QQuickPathItemNvprRenderNode::renderOffscreenFill(VisualPathRenderData *d) +void QQuickShapeNvprRenderNode::renderOffscreenFill(ShapePathRenderData *d) { if (d->fallbackValid && d->fallbackFbo) return; @@ -695,7 +695,7 @@ void QQuickPathItemNvprRenderNode::renderOffscreenFill(VisualPathRenderData *d) d->fallbackValid = true; } -void QQuickPathItemNvprRenderNode::setupStencilForCover(bool stencilClip, int sv) +void QQuickShapeNvprRenderNode::setupStencilForCover(bool stencilClip, int sv) { if (!stencilClip) { // Assume stencil buffer is cleared to 0 for each frame. @@ -708,7 +708,7 @@ void QQuickPathItemNvprRenderNode::setupStencilForCover(bool stencilClip, int sv } } -void QQuickPathItemNvprRenderNode::render(const RenderState *state) +void QQuickShapeNvprRenderNode::render(const RenderState *state) { f = QOpenGLContext::currentContext()->extraFunctions(); @@ -743,7 +743,7 @@ void QQuickPathItemNvprRenderNode::render(const RenderState *state) bool reloadMatrices = true; - for (VisualPathRenderData &d : m_vp) { + for (ShapePathRenderData &d : m_sp) { updatePath(&d); const bool hasFill = d.hasFill(); @@ -797,7 +797,7 @@ void QQuickPathItemNvprRenderNode::render(const RenderState *state) // With stencilCLip == true the read mask for the stencil test before the stencil step is 0x7F. // This assumes the clip stencil value is <= 127. if (sv >= strokeStencilValue) - qWarning("PathItem/NVPR: stencil clip ref value %d too large; expect rendering errors", sv); + qWarning("Shape/NVPR: stencil clip ref value %d too large; expect rendering errors", sv); } renderStroke(&d, strokeStencilValue, writeMask); @@ -812,17 +812,17 @@ void QQuickPathItemNvprRenderNode::render(const RenderState *state) f->glBindProgramPipeline(0); } -QSGRenderNode::StateFlags QQuickPathItemNvprRenderNode::changedStates() const +QSGRenderNode::StateFlags QQuickShapeNvprRenderNode::changedStates() const { return BlendState | StencilState | DepthState | ScissorState; } -QSGRenderNode::RenderingFlags QQuickPathItemNvprRenderNode::flags() const +QSGRenderNode::RenderingFlags QQuickShapeNvprRenderNode::flags() const { return DepthAwareRendering; // avoid hitting the less optimal no-opaque-batch path in the renderer } -bool QQuickPathItemNvprRenderNode::isSupported() +bool QQuickShapeNvprRenderNode::isSupported() { static const bool nvprDisabled = qEnvironmentVariableIntValue("QT_NO_NVPR") != 0; return !nvprDisabled && QQuickNvprFunctions::isSupported(); diff --git a/src/imports/pathitem/qquickpathitemnvprrenderer_p.h b/src/imports/shapes/qquickshapenvprrenderer_p.h index cfe1c7eab9..33007313d4 100644 --- a/src/imports/pathitem/qquickpathitemnvprrenderer_p.h +++ b/src/imports/shapes/qquickshapenvprrenderer_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQUICKPATHITEMNVPRRENDERER_P_H -#define QQUICKPATHITEMNVPRRENDERER_P_H +#ifndef QQUICKSHAPENVPRRENDERER_P_H +#define QQUICKSHAPENVPRRENDERER_P_H // // W A R N I N G @@ -51,7 +51,7 @@ // We mean it. // -#include "qquickpathitem_p_p.h" +#include "qquickshape_p_p.h" #include "qquicknvprfunctions_p.h" #include <qsgrendernode.h> #include <QColor> @@ -62,12 +62,12 @@ QT_BEGIN_NAMESPACE -class QQuickPathItemNvprRenderNode; +class QQuickShapeNvprRenderNode; class QOpenGLFramebufferObject; class QOpenGLBuffer; class QOpenGLExtraFunctions; -class QQuickPathItemNvprRenderer : public QQuickAbstractPathRenderer +class QQuickShapeNvprRenderer : public QQuickAbstractPathRenderer { public: enum Dirty { @@ -81,21 +81,21 @@ public: void beginSync(int totalCount) override; void setPath(int index, const QQuickPath *path) override; - void setJSPath(int index, const QQuickPathItemPath &path) override; + void setJSPath(int index, const QQuickShapePathCommands &path) override; void setStrokeColor(int index, const QColor &color) override; void setStrokeWidth(int index, qreal w) override; void setFillColor(int index, const QColor &color) override; - void setFillRule(int index, QQuickVisualPath::FillRule fillRule) override; - void setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) override; - void setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) override; - void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, + void setFillRule(int index, QQuickShapePath::FillRule fillRule) override; + void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override; + void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override; + void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) override; - void setFillGradient(int index, QQuickPathGradient *gradient) override; + void setFillGradient(int index, QQuickShapeGradient *gradient) override; void endSync(bool async) override; void updateNode() override; - void setNode(QQuickPathItemNvprRenderNode *node); + void setNode(QQuickShapeNvprRenderNode *node); struct NvprPath { QVector<GLubyte> cmd; @@ -104,33 +104,33 @@ public: }; private: - struct VisualPathGuiData { + struct ShapePathGuiData { int dirty = 0; NvprPath path; qreal strokeWidth; QColor strokeColor; QColor fillColor; - QQuickVisualPath::JoinStyle joinStyle; + QQuickShapePath::JoinStyle joinStyle; int miterLimit; - QQuickVisualPath::CapStyle capStyle; - QQuickVisualPath::FillRule fillRule; + QQuickShapePath::CapStyle capStyle; + QQuickShapePath::FillRule fillRule; bool dashActive; qreal dashOffset; QVector<qreal> dashPattern; bool fillGradientActive; - QQuickPathItemGradientCache::GradientDesc fillGradient; + QQuickShapeGradientCache::GradientDesc fillGradient; }; - void convertPath(const QQuickPath *path, VisualPathGuiData *d); - void convertJSPath(const QQuickPathItemPath &path, VisualPathGuiData *d); + void convertPath(const QQuickPath *path, ShapePathGuiData *d); + void convertJSPath(const QQuickShapePathCommands &path, ShapePathGuiData *d); - QQuickPathItemNvprRenderNode *m_node = nullptr; + QQuickShapeNvprRenderNode *m_node = nullptr; int m_accDirty = 0; - QVector<VisualPathGuiData> m_vp; + QVector<ShapePathGuiData> m_sp; }; -QDebug operator<<(QDebug debug, const QQuickPathItemNvprRenderer::NvprPath &path); +QDebug operator<<(QDebug debug, const QQuickShapeNvprRenderer::NvprPath &path); class QQuickNvprMaterialManager { @@ -175,10 +175,10 @@ private: QSize m_prevSize; }; -class QQuickPathItemNvprRenderNode : public QSGRenderNode +class QQuickShapeNvprRenderNode : public QSGRenderNode { public: - ~QQuickPathItemNvprRenderNode(); + ~QQuickShapeNvprRenderNode(); void render(const RenderState *state) override; void releaseResources() override; @@ -188,10 +188,10 @@ public: static bool isSupported(); private: - struct VisualPathRenderData { + struct ShapePathRenderData { GLuint path = 0; int dirty = 0; - QQuickPathItemNvprRenderer::NvprPath source; + QQuickShapeNvprRenderer::NvprPath source; GLfloat strokeWidth; QVector4D strokeColor; QVector4D fillColor; @@ -202,7 +202,7 @@ private: GLfloat dashOffset; QVector<GLfloat> dashPattern; bool fillGradientActive; - QQuickPathItemGradientCache::GradientDesc fillGradient; + QQuickShapeGradientCache::GradientDesc fillGradient; QOpenGLFramebufferObject *fallbackFbo = nullptr; bool fallbackValid = false; QSize fallbackSize; @@ -212,10 +212,10 @@ private: bool hasStroke() const { return strokeWidth >= 0.0f && !qFuzzyIsNull(strokeColor.w()); } }; - void updatePath(VisualPathRenderData *d); - void renderStroke(VisualPathRenderData *d, int strokeStencilValue, int writeMask); - void renderFill(VisualPathRenderData *d); - void renderOffscreenFill(VisualPathRenderData *d); + void updatePath(ShapePathRenderData *d); + void renderStroke(ShapePathRenderData *d, int strokeStencilValue, int writeMask); + void renderFill(ShapePathRenderData *d); + void renderOffscreenFill(ShapePathRenderData *d); void setupStencilForCover(bool stencilClip, int sv); static bool nvprInited; @@ -225,13 +225,13 @@ private: QQuickNvprBlitter m_fallbackBlitter; QOpenGLExtraFunctions *f = nullptr; - QVector<VisualPathRenderData> m_vp; + QVector<ShapePathRenderData> m_sp; - friend class QQuickPathItemNvprRenderer; + friend class QQuickShapeNvprRenderer; }; QT_END_NAMESPACE #endif // QT_NO_OPENGL -#endif // QQUICKPATHITEMNVPRRENDERER_P_H +#endif // QQUICKSHAPENVPRRENDERER_P_H diff --git a/src/imports/pathitem/qquickpathitemsoftwarerenderer.cpp b/src/imports/shapes/qquickshapesoftwarerenderer.cpp index b7aa93bf65..33d80be22c 100644 --- a/src/imports/pathitem/qquickpathitemsoftwarerenderer.cpp +++ b/src/imports/shapes/qquickshapesoftwarerenderer.cpp @@ -37,46 +37,46 @@ ** ****************************************************************************/ -#include "qquickpathitemsoftwarerenderer_p.h" +#include "qquickshapesoftwarerenderer_p.h" #include <private/qquickpath_p_p.h> QT_BEGIN_NAMESPACE -void QQuickPathItemSoftwareRenderer::beginSync(int totalCount) +void QQuickShapeSoftwareRenderer::beginSync(int totalCount) { - if (m_vp.count() != totalCount) { - m_vp.resize(totalCount); + if (m_sp.count() != totalCount) { + m_sp.resize(totalCount); m_accDirty |= DirtyList; } } -void QQuickPathItemSoftwareRenderer::setPath(int index, const QQuickPath *path) +void QQuickShapeSoftwareRenderer::setPath(int index, const QQuickPath *path) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.path = path ? path->path() : QPainterPath(); d.dirty |= DirtyPath; m_accDirty |= DirtyPath; } -void QQuickPathItemSoftwareRenderer::setJSPath(int index, const QQuickPathItemPath &path) +void QQuickShapeSoftwareRenderer::setJSPath(int index, const QQuickShapePathCommands &path) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.path = path.toPainterPath(); d.dirty |= DirtyPath; m_accDirty |= DirtyPath; } -void QQuickPathItemSoftwareRenderer::setStrokeColor(int index, const QColor &color) +void QQuickShapeSoftwareRenderer::setStrokeColor(int index, const QColor &color) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.pen.setColor(color); d.dirty |= DirtyPen; m_accDirty |= DirtyPen; } -void QQuickPathItemSoftwareRenderer::setStrokeWidth(int index, qreal w) +void QQuickShapeSoftwareRenderer::setStrokeWidth(int index, qreal w) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.strokeWidth = w; if (w >= 0.0f) d.pen.setWidthF(w); @@ -84,49 +84,49 @@ void QQuickPathItemSoftwareRenderer::setStrokeWidth(int index, qreal w) m_accDirty |= DirtyPen; } -void QQuickPathItemSoftwareRenderer::setFillColor(int index, const QColor &color) +void QQuickShapeSoftwareRenderer::setFillColor(int index, const QColor &color) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.fillColor = color; d.brush.setColor(color); d.dirty |= DirtyBrush; m_accDirty |= DirtyBrush; } -void QQuickPathItemSoftwareRenderer::setFillRule(int index, QQuickVisualPath::FillRule fillRule) +void QQuickShapeSoftwareRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.fillRule = Qt::FillRule(fillRule); d.dirty |= DirtyFillRule; m_accDirty |= DirtyFillRule; } -void QQuickPathItemSoftwareRenderer::setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) +void QQuickShapeSoftwareRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.pen.setJoinStyle(Qt::PenJoinStyle(joinStyle)); d.pen.setMiterLimit(miterLimit); d.dirty |= DirtyPen; m_accDirty |= DirtyPen; } -void QQuickPathItemSoftwareRenderer::setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) +void QQuickShapeSoftwareRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); d.pen.setCapStyle(Qt::PenCapStyle(capStyle)); d.dirty |= DirtyPen; m_accDirty |= DirtyPen; } -void QQuickPathItemSoftwareRenderer::setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, +void QQuickShapeSoftwareRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) { - VisualPathGuiData &d(m_vp[index]); + ShapePathGuiData &d(m_sp[index]); switch (strokeStyle) { - case QQuickVisualPath::SolidLine: + case QQuickShapePath::SolidLine: d.pen.setStyle(Qt::SolidLine); break; - case QQuickVisualPath::DashLine: + case QQuickShapePath::DashLine: d.pen.setStyle(Qt::CustomDashLine); d.pen.setDashPattern(dashPattern); d.pen.setDashOffset(dashOffset); @@ -138,21 +138,21 @@ void QQuickPathItemSoftwareRenderer::setStrokeStyle(int index, QQuickVisualPath: m_accDirty |= DirtyPen; } -void QQuickPathItemSoftwareRenderer::setFillGradient(int index, QQuickPathGradient *gradient) +void QQuickShapeSoftwareRenderer::setFillGradient(int index, QQuickShapeGradient *gradient) { - VisualPathGuiData &d(m_vp[index]); - if (QQuickPathLinearGradient *linearGradient = qobject_cast<QQuickPathLinearGradient *>(gradient)) { + ShapePathGuiData &d(m_sp[index]); + if (QQuickShapeLinearGradient *linearGradient = qobject_cast<QQuickShapeLinearGradient *>(gradient)) { QLinearGradient painterGradient(linearGradient->x1(), linearGradient->y1(), linearGradient->x2(), linearGradient->y2()); painterGradient.setStops(linearGradient->sortedGradientStops()); switch (gradient->spread()) { - case QQuickPathGradient::PadSpread: + case QQuickShapeGradient::PadSpread: painterGradient.setSpread(QGradient::PadSpread); break; - case QQuickPathGradient::RepeatSpread: + case QQuickShapeGradient::RepeatSpread: painterGradient.setSpread(QGradient::RepeatSpread); break; - case QQuickPathGradient::ReflectSpread: + case QQuickShapeGradient::ReflectSpread: painterGradient.setSpread(QGradient::ReflectSpread); break; default: @@ -166,11 +166,11 @@ void QQuickPathItemSoftwareRenderer::setFillGradient(int index, QQuickPathGradie m_accDirty |= DirtyBrush; } -void QQuickPathItemSoftwareRenderer::endSync(bool) +void QQuickShapeSoftwareRenderer::endSync(bool) { } -void QQuickPathItemSoftwareRenderer::setNode(QQuickPathItemSoftwareRenderNode *node) +void QQuickShapeSoftwareRenderer::setNode(QQuickShapeSoftwareRenderNode *node) { if (m_node != node) { m_node = node; @@ -178,21 +178,21 @@ void QQuickPathItemSoftwareRenderer::setNode(QQuickPathItemSoftwareRenderNode *n } } -void QQuickPathItemSoftwareRenderer::updateNode() +void QQuickShapeSoftwareRenderer::updateNode() { if (!m_accDirty) return; - const int count = m_vp.count(); + const int count = m_sp.count(); const bool listChanged = m_accDirty & DirtyList; if (listChanged) - m_node->m_vp.resize(count); + m_node->m_sp.resize(count); m_node->m_boundingRect = QRectF(); for (int i = 0; i < count; ++i) { - VisualPathGuiData &src(m_vp[i]); - QQuickPathItemSoftwareRenderNode::VisualPathRenderData &dst(m_node->m_vp[i]); + ShapePathGuiData &src(m_sp[i]); + QQuickShapeSoftwareRenderNode::ShapePathRenderData &dst(m_node->m_sp[i]); if (listChanged || (src.dirty & DirtyPath)) { dst.path = src.path; @@ -222,23 +222,23 @@ void QQuickPathItemSoftwareRenderer::updateNode() m_accDirty = 0; } -QQuickPathItemSoftwareRenderNode::QQuickPathItemSoftwareRenderNode(QQuickPathItem *item) +QQuickShapeSoftwareRenderNode::QQuickShapeSoftwareRenderNode(QQuickShape *item) : m_item(item) { } -QQuickPathItemSoftwareRenderNode::~QQuickPathItemSoftwareRenderNode() +QQuickShapeSoftwareRenderNode::~QQuickShapeSoftwareRenderNode() { releaseResources(); } -void QQuickPathItemSoftwareRenderNode::releaseResources() +void QQuickShapeSoftwareRenderNode::releaseResources() { } -void QQuickPathItemSoftwareRenderNode::render(const RenderState *state) +void QQuickShapeSoftwareRenderNode::render(const RenderState *state) { - if (m_vp.isEmpty()) + if (m_sp.isEmpty()) return; QSGRendererInterface *rif = m_item->window()->rendererInterface(); @@ -252,24 +252,24 @@ void QQuickPathItemSoftwareRenderNode::render(const RenderState *state) p->setTransform(matrix()->toTransform()); p->setOpacity(inheritedOpacity()); - for (const VisualPathRenderData &d : qAsConst(m_vp)) { + for (const ShapePathRenderData &d : qAsConst(m_sp)) { p->setPen(d.strokeWidth >= 0.0f && d.pen.color() != Qt::transparent ? d.pen : Qt::NoPen); p->setBrush(d.brush.color() != Qt::transparent ? d.brush : Qt::NoBrush); p->drawPath(d.path); } } -QSGRenderNode::StateFlags QQuickPathItemSoftwareRenderNode::changedStates() const +QSGRenderNode::StateFlags QQuickShapeSoftwareRenderNode::changedStates() const { return 0; } -QSGRenderNode::RenderingFlags QQuickPathItemSoftwareRenderNode::flags() const +QSGRenderNode::RenderingFlags QQuickShapeSoftwareRenderNode::flags() const { return BoundedRectRendering; // avoid fullscreen updates by saying we won't draw outside rect() } -QRectF QQuickPathItemSoftwareRenderNode::rect() const +QRectF QQuickShapeSoftwareRenderNode::rect() const { return m_boundingRect; } diff --git a/src/imports/pathitem/qquickpathitemsoftwarerenderer_p.h b/src/imports/shapes/qquickshapesoftwarerenderer_p.h index e76590bdfe..53982ce347 100644 --- a/src/imports/pathitem/qquickpathitemsoftwarerenderer_p.h +++ b/src/imports/shapes/qquickshapesoftwarerenderer_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQUICKPATHITEMSOFTWARERENDERER_P_H -#define QQUICKPATHITEMSOFTWARERENDERER_P_H +#ifndef QQUICKSHAPESOFTWARERENDERER_P_H +#define QQUICKSHAPESOFTWARERENDERER_P_H // // W A R N I N G @@ -51,16 +51,16 @@ // We mean it. // -#include "qquickpathitem_p_p.h" +#include "qquickshape_p_p.h" #include <qsgrendernode.h> #include <QPen> #include <QBrush> QT_BEGIN_NAMESPACE -class QQuickPathItemSoftwareRenderNode; +class QQuickShapeSoftwareRenderNode; -class QQuickPathItemSoftwareRenderer : public QQuickAbstractPathRenderer +class QQuickShapeSoftwareRenderer : public QQuickAbstractPathRenderer { public: enum Dirty { @@ -73,26 +73,26 @@ public: void beginSync(int totalCount) override; void setPath(int index, const QQuickPath *path) override; - void setJSPath(int index, const QQuickPathItemPath &path) override; + void setJSPath(int index, const QQuickShapePathCommands &path) override; void setStrokeColor(int index, const QColor &color) override; void setStrokeWidth(int index, qreal w) override; void setFillColor(int index, const QColor &color) override; - void setFillRule(int index, QQuickVisualPath::FillRule fillRule) override; - void setJoinStyle(int index, QQuickVisualPath::JoinStyle joinStyle, int miterLimit) override; - void setCapStyle(int index, QQuickVisualPath::CapStyle capStyle) override; - void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle, + void setFillRule(int index, QQuickShapePath::FillRule fillRule) override; + void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override; + void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override; + void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QVector<qreal> &dashPattern) override; - void setFillGradient(int index, QQuickPathGradient *gradient) override; + void setFillGradient(int index, QQuickShapeGradient *gradient) override; void endSync(bool async) override; void updateNode() override; - void setNode(QQuickPathItemSoftwareRenderNode *node); + void setNode(QQuickShapeSoftwareRenderNode *node); private: - QQuickPathItemSoftwareRenderNode *m_node = nullptr; + QQuickShapeSoftwareRenderNode *m_node = nullptr; int m_accDirty = 0; - struct VisualPathGuiData { + struct ShapePathGuiData { int dirty = 0; QPainterPath path; QPen pen; @@ -101,14 +101,14 @@ private: QBrush brush; Qt::FillRule fillRule; }; - QVector<VisualPathGuiData> m_vp; + QVector<ShapePathGuiData> m_sp; }; -class QQuickPathItemSoftwareRenderNode : public QSGRenderNode +class QQuickShapeSoftwareRenderNode : public QSGRenderNode { public: - QQuickPathItemSoftwareRenderNode(QQuickPathItem *item); - ~QQuickPathItemSoftwareRenderNode(); + QQuickShapeSoftwareRenderNode(QQuickShape *item); + ~QQuickShapeSoftwareRenderNode(); void render(const RenderState *state) override; void releaseResources() override; @@ -117,20 +117,20 @@ public: QRectF rect() const override; private: - QQuickPathItem *m_item; + QQuickShape *m_item; - struct VisualPathRenderData { + struct ShapePathRenderData { QPainterPath path; QPen pen; float strokeWidth; QBrush brush; }; - QVector<VisualPathRenderData> m_vp; + QVector<ShapePathRenderData> m_sp; QRectF m_boundingRect; - friend class QQuickPathItemSoftwareRenderer; + friend class QQuickShapeSoftwareRenderer; }; QT_END_NAMESPACE -#endif // QQUICKPATHITEMSOFTWARERENDERER_P_H +#endif // QQUICKSHAPESOFTWARERENDERER_P_H diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro new file mode 100644 index 0000000000..80e6a22142 --- /dev/null +++ b/src/imports/shapes/shapes.pro @@ -0,0 +1,31 @@ +CXX_MODULE = qml +TARGET = qmlshapesplugin +TARGETPATH = QtQuick/Shapes +IMPORT_VERSION = 1.0 + +QT = core gui qml quick quick-private + +HEADERS += \ + qquickshape_p.h \ + qquickshape_p_p.h \ + qquickshapegenericrenderer_p.h \ + qquickshapesoftwarerenderer_p.h + +SOURCES += \ + plugin.cpp \ + qquickshape.cpp \ + qquickshapegenericrenderer.cpp \ + qquickshapesoftwarerenderer.cpp + +qtConfig(opengl) { + HEADERS += \ + qquicknvprfunctions_p.h \ + qquicknvprfunctions_p_p.h \ + qquickshapenvprrenderer_p.h + + SOURCES += \ + qquicknvprfunctions.cpp \ + qquickshapenvprrenderer.cpp +} + +load(qml_plugin) diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index 84441e308f..085963be6c 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE \instantiates QQuickPath \inqmlmodule QtQuick \ingroup qtquick-animation-paths - \brief Defines a path for use by \l PathView and \l PathItem + \brief Defines a path for use by \l PathView and \l Shape A Path is composed of one or more path segments - PathLine, PathQuad, PathCubic, PathArc, PathCurve, PathSvg. @@ -80,16 +80,16 @@ QT_BEGIN_NAMESPACE along the path. Path and the other types for specifying path elements are shared between - \l PathView and \l PathItem. The following table provides an overview of the + \l PathView and \l Shape. The following table provides an overview of the applicability of the various path elements: \table \header \li Element \li PathView - \li PathItem - \li PathItem, GL_NV_path_rendering - \li PathItem, software + \li Shape + \li Shape, GL_NV_path_rendering + \li Shape, software \row \li PathMove \li N/A @@ -146,7 +146,7 @@ QT_BEGIN_NAMESPACE \li No \endtable - \sa PathView, PathItem, PathAttribute, PathPercent, PathLine, PathMove, PathQuad, PathCubic, PathArc, PathCurve, PathSvg + \sa PathView, Shape, PathAttribute, PathPercent, PathLine, PathMove, PathQuad, PathCubic, PathArc, PathCurve, PathSvg */ QQuickPath::QQuickPath(QObject *parent) : QObject(*(new QQuickPathPrivate), parent) @@ -1119,7 +1119,7 @@ void QQuickPathLine::addToPath(QPainterPath &path, const QQuickPathData &data) \ingroup qtquick-animation-paths \brief Moves the Path's position - While not relevant with PathView, for Path elements used with PathItem it + While not relevant with PathView, for Path elements used with Shape it is important to distinguish between the operations of drawing a straight line and moving the path position without drawing anything. @@ -1927,7 +1927,7 @@ void QQuickPathArc::addToPath(QPainterPath &path, const QQuickPathData &data) \note Mixing PathSvg with other type of elements is not always supported, therefore it is strongly recommended to avoid this. For example, when - \l PathItem is backed by \c{GL_NV_path_rendering}, a Path can contain one or + \l Shape is backed by \c{GL_NV_path_rendering}, a Path can contain one or more PathSvg elements, or one or more other type of elements, but not both. \sa Path, PathLine, PathQuad, PathCubic, PathArc, PathCurve |