aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util/qquickpath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/util/qquickpath.cpp')
-rw-r--r--src/quick/util/qquickpath.cpp234
1 files changed, 114 insertions, 120 deletions
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 5ac28f45d9..8995c64d0b 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquickpath_p.h"
#include "qquickpath_p_p.h"
@@ -89,79 +53,67 @@ QT_BEGIN_NAMESPACE
\li Element
\li PathView
\li Shape
- \li Shape, GL_NV_path_rendering
\li Shape, software
\row
\li PathMove
\li N/A
\li Yes
\li Yes
- \li Yes
\row
\li PathLine
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathPolyline
\li Yes
\li Yes
\li Yes
- \li Yes
+ \row
\li PathMultiLine
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathQuad
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathCubic
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathArc
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathAngleArc
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathSvg
\li Yes
\li Yes
\li Yes
- \li Yes
\row
\li PathAttribute
\li Yes
\li N/A
\li N/A
- \li N/A
\row
\li PathPercent
\li Yes
\li N/A
\li N/A
- \li N/A
\row
\li PathCurve
\li Yes
\li No
\li No
- \li No
\endtable
\note Path is a non-visual type; it does not display anything on its own.
@@ -191,7 +143,7 @@ QQuickPath::~QQuickPath()
qreal QQuickPath::startX() const
{
Q_D(const QQuickPath);
- return d->startX.isNull ? 0 : d->startX.value;
+ return d->startX.isValid() ? d->startX.value() : 0;
}
void QQuickPath::setStartX(qreal x)
@@ -213,7 +165,7 @@ bool QQuickPath::hasStartX() const
qreal QQuickPath::startY() const
{
Q_D(const QQuickPath);
- return d->startY.isNull ? 0 : d->startY.value;
+ return d->startY.isValid() ? d->startY.value() : 0;
}
void QQuickPath::setStartY(qreal y)
@@ -246,7 +198,7 @@ bool QQuickPath::isClosed() const
\qmlproperty list<PathElement> QtQuick::Path::pathElements
This property holds the objects composing the path.
- \default
+ \qmldefault
A path can contain the following path objects:
\list
@@ -319,7 +271,7 @@ qsizetype QQuickPath::pathElements_count(QQmlListProperty<QQuickPathElement> *pr
{
QQuickPathPrivate *d = privatePath(property->object);
- return d->_pathElements.count();
+ return d->_pathElements.size();
}
void QQuickPath::pathElements_clear(QQmlListProperty<QQuickPathElement> *property)
@@ -375,10 +327,10 @@ void QQuickPath::endpoint(const QString &name)
Q_D(QQuickPath);
const AttributePoint &first = d->_attributePoints.first();
qreal val = first.values.value(name);
- for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
+ for (int ii = d->_attributePoints.size() - 1; ii >= 0; ii--) {
const AttributePoint &point = d->_attributePoints.at(ii);
if (point.values.contains(name)) {
- for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
+ for (int jj = ii + 1; jj < d->_attributePoints.size(); ++jj) {
AttributePoint &setPoint = d->_attributePoints[jj];
setPoint.values.insert(name, val);
}
@@ -391,10 +343,10 @@ void QQuickPath::endpoint(QList<AttributePoint> &attributePoints, const QString
{
const AttributePoint &first = attributePoints.first();
qreal val = first.values.value(name);
- for (int ii = attributePoints.count() - 1; ii >= 0; ii--) {
+ for (int ii = attributePoints.size() - 1; ii >= 0; ii--) {
const AttributePoint &point = attributePoints.at(ii);
if (point.values.contains(name)) {
- for (int jj = ii + 1; jj < attributePoints.count(); ++jj) {
+ for (int jj = ii + 1; jj < attributePoints.size(); ++jj) {
AttributePoint &setPoint = attributePoints[jj];
setPoint.values.insert(name, val);
}
@@ -420,6 +372,9 @@ void QQuickPath::processPath()
d->_path = createPath(QPointF(), QPointF(), d->_attributes, d->pathLength, d->_attributePoints, &d->closed);
}
+ if (d->simplify)
+ d->_path = d->_path.simplified();
+
emit changed();
}
@@ -449,19 +404,19 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
QPainterPath path;
AttributePoint first;
- for (int ii = 0; ii < attributes.count(); ++ii)
+ for (int ii = 0; ii < attributes.size(); ++ii)
first.values[attributes.at(ii)] = 0;
attributePoints << first;
- qreal startX = d->startX.isValid() ? d->startX.value : startPoint.x();
- qreal startY = d->startY.isValid() ? d->startY.value : startPoint.y();
+ qreal startX = d->startX.isValid() ? d->startX.value() : startPoint.x();
+ qreal startY = d->startY.isValid() ? d->startY.value() : startPoint.y();
path.moveTo(startX, startY);
const QString percentString = QStringLiteral("_qfx_percent");
bool usesPercent = false;
int index = 0;
- for (QQuickPathElement *pathElement : qAsConst(d->_pathElements)) {
+ for (QQuickPathElement *pathElement : std::as_const(d->_pathElements)) {
if (QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement)) {
QQuickPathData data;
data.index = index;
@@ -475,11 +430,11 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
} else if (QQuickPathAttribute *attribute = qobject_cast<QQuickPathAttribute *>(pathElement)) {
AttributePoint &point = attributePoints.last();
point.values[attribute->name()] = attribute->value();
- interpolate(attributePoints, attributePoints.count() - 1, attribute->name(), attribute->value());
+ interpolate(attributePoints, attributePoints.size() - 1, attribute->name(), attribute->value());
} else if (QQuickPathPercent *percent = qobject_cast<QQuickPathPercent *>(pathElement)) {
AttributePoint &point = attributePoints.last();
point.values[percentString] = percent->value();
- interpolate(attributePoints, attributePoints.count() - 1, percentString, percent->value());
+ interpolate(attributePoints, attributePoints.size() - 1, percentString, percent->value());
usesPercent = true;
} else if (QQuickPathText *text = qobject_cast<QQuickPathText *>(pathElement)) {
text->addToPath(path);
@@ -488,13 +443,13 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
// Fixup end points
const AttributePoint &last = attributePoints.constLast();
- for (int ii = 0; ii < attributes.count(); ++ii) {
+ for (int ii = 0; ii < attributes.size(); ++ii) {
if (!last.values.contains(attributes.at(ii)))
endpoint(attributePoints, attributes.at(ii));
}
if (usesPercent && !last.values.contains(percentString)) {
d->_attributePoints.last().values[percentString] = 1;
- interpolate(d->_attributePoints.count() - 1, percentString, 1);
+ interpolate(d->_attributePoints.size() - 1, percentString, 1);
}
scalePath(path, d->scale);
@@ -502,7 +457,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
qreal length = path.length();
qreal prevpercent = 0;
qreal prevorigpercent = 0;
- for (int ii = 0; ii < attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < attributePoints.size(); ++ii) {
const AttributePoint &point = attributePoints.at(ii);
if (point.values.contains(percentString)) { //special string for QQuickPathPercent
if ( ii > 0) {
@@ -538,12 +493,12 @@ QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPoint
QPainterPath path;
- qreal startX = d->startX.isValid() ? d->startX.value : startPoint.x();
- qreal startY = d->startY.isValid() ? d->startY.value : startPoint.y();
+ qreal startX = d->startX.isValid() ? d->startX.value() : startPoint.x();
+ qreal startY = d->startY.isValid() ? d->startY.value() : startPoint.y();
path.moveTo(startX, startY);
int index = 0;
- for (QQuickCurve *curve : qAsConst(d->_pathCurves)) {
+ for (QQuickCurve *curve : std::as_const(d->_pathCurves)) {
QQuickPathData data;
data.index = index;
data.endPoint = endPoint;
@@ -552,7 +507,7 @@ QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPoint
++index;
}
- for (QQuickPathText *text : qAsConst(d->_pathTexts))
+ for (QQuickPathText *text : std::as_const(d->_pathTexts))
text->addToPath(path);
if (closed) {
@@ -598,7 +553,7 @@ void QQuickPath::gatherAttributes()
QSet<QString> attributes;
// First gather up all the attributes
- for (QQuickPathElement *pathElement : qAsConst(d->_pathElements)) {
+ for (QQuickPathElement *pathElement : std::as_const(d->_pathElements)) {
if (QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement))
d->_pathCurves.append(curve);
else if (QQuickPathText *text = qobject_cast<QQuickPathText *>(pathElement))
@@ -724,10 +679,10 @@ void QQuickPath::createPointCache() const
//find which set we are in
qreal prevPercent = 0;
qreal prevOrigPercent = 0;
- for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < d->_attributePoints.size(); ++ii) {
qreal percent = qreal(i)/segments;
const AttributePoint &point = d->_attributePoints.at(ii);
- if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
+ if (percent < point.percent || ii == d->_attributePoints.size() - 1) { //### || is special case for very last item
qreal elementPercent = (percent - prevPercent);
qreal spc = prevOrigPercent + elementPercent * point.scale;
@@ -760,6 +715,32 @@ void QQuickPath::invalidateSequentialHistory() const
d->prevBez.isValid = false;
}
+/*! \qmlproperty bool QtQuick::Path::simplify
+ \since 6.6
+
+ When set to true, the path will be simplified. This implies merging all subpaths that intersect,
+ creating a path where there are no self-intersections. Consecutive parallel lines will also be
+ merged. The simplified path is intended to be used with ShapePath.OddEvenFill. Bezier curves may
+ be flattened to line segments due to numerical instability of doing bezier curve intersections.
+*/
+void QQuickPath::setSimplify(bool s)
+{
+ Q_D(QQuickPath);
+ if (d->simplify == s)
+ return;
+
+ d->simplify = s;
+ processPath();
+
+ emit simplifyChanged();
+}
+
+bool QQuickPath::simplify() const
+{
+ Q_D(const QQuickPath);
+ return d->simplify;
+}
+
/*!
\qmlproperty size QtQuick::Path::scale
@@ -821,10 +802,10 @@ QPointF QQuickPath::forwardsPointAt(const QPainterPath &path, const qreal &pathL
//find which set we are in
qreal prevPercent = 0;
qreal prevOrigPercent = 0;
- for (int ii = 0; ii < attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < attributePoints.size(); ++ii) {
qreal percent = p;
const AttributePoint &point = attributePoints.at(ii);
- if (percent < point.percent || ii == attributePoints.count() - 1) {
+ if (percent < point.percent || ii == attributePoints.size() - 1) {
qreal elementPercent = (percent - prevPercent);
qreal spc = prevOrigPercent + elementPercent * point.scale;
@@ -875,7 +856,7 @@ QPointF QQuickPath::backwardsPointAt(const QPainterPath &path, const qreal &path
qreal prevLength = currLength - bezLength;
qreal epc = prevLength / pathLength;
- for (int ii = attributePoints.count() - 1; ii > 0; --ii) {
+ for (int ii = attributePoints.size() - 1; ii > 0; --ii) {
qreal percent = p;
const AttributePoint &point = attributePoints.at(ii);
const AttributePoint &prevPoint = attributePoints.at(ii-1);
@@ -976,7 +957,7 @@ qreal QQuickPath::attributeAt(const QString &name, qreal percent) const
if (percent < 0 || percent > 1)
return 0;
- for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < d->_attributePoints.size(); ++ii) {
const AttributePoint &point = d->_attributePoints.at(ii);
if (point.percent == percent) {
@@ -1000,12 +981,12 @@ qreal QQuickPath::attributeAt(const QString &name, qreal percent) const
qreal QQuickCurve::x() const
{
- return _x.isNull ? 0 : _x.value;
+ return _x.isValid() ? _x.value() : 0;
}
void QQuickCurve::setX(qreal x)
{
- if (_x.isNull || _x != x) {
+ if (!_x.isValid() || _x != x) {
_x = x;
emit xChanged();
emit changed();
@@ -1019,12 +1000,12 @@ bool QQuickCurve::hasX()
qreal QQuickCurve::y() const
{
- return _y.isNull ? 0 : _y.value;
+ return _y.isValid() ? _y.value() : 0;
}
void QQuickCurve::setY(qreal y)
{
- if (_y.isNull || _y != y) {
+ if (!_y.isValid() || _y != y) {
_y = y;
emit yChanged();
emit changed();
@@ -1043,7 +1024,7 @@ qreal QQuickCurve::relativeX() const
void QQuickCurve::setRelativeX(qreal x)
{
- if (_relativeX.isNull || _relativeX != x) {
+ if (!_relativeX.isValid() || _relativeX != x) {
_relativeX = x;
emit relativeXChanged();
emit changed();
@@ -1062,7 +1043,7 @@ qreal QQuickCurve::relativeY() const
void QQuickCurve::setRelativeY(qreal y)
{
- if (_relativeY.isNull || _relativeY != y) {
+ if (!_relativeY.isValid() || _relativeY != y) {
_relativeY = y;
emit relativeYChanged();
emit changed();
@@ -1421,7 +1402,7 @@ qreal QQuickPathQuad::relativeControlX() const
void QQuickPathQuad::setRelativeControlX(qreal x)
{
- if (_relativeControlX.isNull || _relativeControlX != x) {
+ if (!_relativeControlX.isValid() || _relativeControlX != x) {
_relativeControlX = x;
emit relativeControlXChanged();
emit changed();
@@ -1440,7 +1421,7 @@ qreal QQuickPathQuad::relativeControlY() const
void QQuickPathQuad::setRelativeControlY(qreal y)
{
- if (_relativeControlY.isNull || _relativeControlY != y) {
+ if (!_relativeControlY.isValid() || _relativeControlY != y) {
_relativeControlY = y;
emit relativeControlYChanged();
emit changed();
@@ -1605,7 +1586,7 @@ qreal QQuickPathCubic::relativeControl1X() const
void QQuickPathCubic::setRelativeControl1X(qreal x)
{
- if (_relativeControl1X.isNull || _relativeControl1X != x) {
+ if (!_relativeControl1X.isValid() || _relativeControl1X != x) {
_relativeControl1X = x;
emit relativeControl1XChanged();
emit changed();
@@ -1624,7 +1605,7 @@ qreal QQuickPathCubic::relativeControl1Y() const
void QQuickPathCubic::setRelativeControl1Y(qreal y)
{
- if (_relativeControl1Y.isNull || _relativeControl1Y != y) {
+ if (!_relativeControl1Y.isValid() || _relativeControl1Y != y) {
_relativeControl1Y = y;
emit relativeControl1YChanged();
emit changed();
@@ -1643,7 +1624,7 @@ qreal QQuickPathCubic::relativeControl2X() const
void QQuickPathCubic::setRelativeControl2X(qreal x)
{
- if (_relativeControl2X.isNull || _relativeControl2X != x) {
+ if (!_relativeControl2X.isValid() || _relativeControl2X != x) {
_relativeControl2X = x;
emit relativeControl2XChanged();
emit changed();
@@ -1662,7 +1643,7 @@ qreal QQuickPathCubic::relativeControl2Y() const
void QQuickPathCubic::setRelativeControl2Y(qreal y)
{
- if (_relativeControl2Y.isNull || _relativeControl2Y != y) {
+ if (!_relativeControl2Y.isValid() || _relativeControl2Y != y) {
_relativeControl2Y = y;
emit relativeControl2YChanged();
emit changed();
@@ -1759,17 +1740,17 @@ void QQuickPathCatmullRomCurve::addToPath(QPainterPath &path, const QQuickPathDa
} else {
prev = path.currentPosition();
bool prevFarSet = false;
- if (index == -1 && data.curves.count() > 1) {
- if (qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(data.curves.count()-1))) {
+ if (index == -1 && data.curves.size() > 1) {
+ if (qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(data.curves.size()-1))) {
//TODO: profile and optimize
QPointF pos = prev;
QQuickPathData loopData;
loopData.endPoint = data.endPoint;
loopData.curves = data.curves;
- for (int i = data.index; i < data.curves.count(); ++i) {
+ for (int i = data.index; i < data.curves.size(); ++i) {
loopData.index = i;
pos = positionForCurve(loopData, pos);
- if (i == data.curves.count()-2)
+ if (i == data.curves.size()-2)
prevFar = pos;
}
if (pos == QPointF(path.elementAt(0))) {
@@ -1788,7 +1769,7 @@ void QQuickPathCatmullRomCurve::addToPath(QPainterPath &path, const QQuickPathDa
//get next point
index = data.index + 1;
- if (index < data.curves.count() && qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(index))) {
+ if (index < data.curves.size() && qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(index))) {
QQuickPathData nextData;
nextData.index = index;
nextData.endPoint = data.endPoint;
@@ -2236,11 +2217,6 @@ void QQuickPathAngleArc::addToPath(QPainterPath &path, const QQuickPathData &)
\endqml
\endtable
- \note Mixing PathSvg with other type of elements is not always supported.
- For example, when \l Shape is backed by \c{GL_NV_path_rendering}, a
- ShapePath can contain one or more PathSvg elements, or one or more other
- type of elements, but not both.
-
\sa Path, PathLine, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve
*/
@@ -2702,22 +2678,21 @@ void QQuickPathMultiline::addToPath(QPainterPath &path, const QQuickPathData &)
*/
/*!
- \qmlproperty enumeration QtQuick::PathText::font.weight
+ \qmlproperty int QtQuick::PathText::font.weight
Sets the font's weight.
The weight can be one of:
- \list
- \li Font.Thin
- \li Font.Light
- \li Font.ExtraLight
- \li Font.Normal - the default
- \li Font.Medium
- \li Font.DemiBold
- \li Font.Bold
- \li Font.ExtraBold
- \li Font.Black
- \endlist
+
+ \value Font.Thin 100
+ \value Font.ExtraLight 200
+ \value Font.Light 300
+ \value Font.Normal 400 (default)
+ \value Font.Medium 500
+ \value Font.DemiBold 600
+ \value Font.Bold 700
+ \value Font.ExtraBold 800
+ \value Font.Black 900
\qml
PathText { text: "Hello"; font.weight: Font.DemiBold }
@@ -2781,13 +2756,12 @@ void QQuickPathMultiline::addToPath(QPainterPath &path, const QQuickPathData &)
Sets the capitalization for the text.
- \list
- \li Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
- \li Font.AllUppercase - This alters the text to be rendered in all uppercase type.
- \li Font.AllLowercase - This alters the text to be rendered in all lowercase type.
- \li Font.SmallCaps - This alters the text to be rendered in small-caps type.
- \li Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
- \endlist
+ \value Font.MixedCase no capitalization change is applied
+ \value Font.AllUppercase alters the text to be rendered in all uppercase type
+ \value Font.AllLowercase alters the text to be rendered in all lowercase type
+ \value Font.SmallCaps alters the text to be rendered in small-caps type
+ \value Font.Capitalize alters the text to be rendered with the first character of
+ each word as an uppercase character
\qml
PathText { text: "Hello"; font.capitalization: Font.AllLowercase }
@@ -2822,6 +2796,26 @@ void QQuickPathMultiline::addToPath(QPainterPath &path, const QQuickPathData &)
\endqml
*/
+/*!
+ \qmlproperty object QtQuick::PathText::font.variableAxes
+ \since 6.7
+
+ \include qquicktext.cpp qml-font-variable-axes
+*/
+
+/*!
+ \qmlproperty object QtQuick::PathText::font.features
+ \since 6.6
+
+ \include qquicktext.cpp qml-font-features
+*/
+
+/*!
+ \qmlproperty object QtQuick::PathText::font.contextFontMerging
+ \since 6.8
+
+ \include qquicktext.cpp qml-font-context-font-merging
+*/
void QQuickPathText::updatePath() const
{
if (!_path.isEmpty())