Optimize AreaRenderer

Use QPainterPath method from PointRenderer to improve AreaRenderer
performance. Also fixes bugged lower spline behavior.

Task-number: QTBUG-129768
Change-Id: I738abeecd620ed4897e2f77301bc9e47dc0d39e8
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Reviewed-by: Owais Akhtar <owais.akhtar@qt.io>
(cherry picked from commit 6c643a7d41)
This commit is contained in:
Jere Tuliniemi 2024-10-10 13:15:14 +03:00
parent f72417979f
commit 5502bd0b0e
2 changed files with 27 additions and 92 deletions

View File

@ -76,27 +76,10 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
auto group = m_groups.value(series); auto group = m_groups.value(series);
if (upper->points().count() < 2) { if (upper->points().count() < 2 || (lower && lower->points().count() < 2)) {
auto pathElements = group->shapePath->pathElements(); auto painterPath = group->painterPath;
pathElements.clear(&pathElements); painterPath.clear();
group->shapePath->setPath(painterPath);
for (auto path : group->paths)
path->deleteLater();
group->paths.clear();
return;
}
if (lower && lower->points().count() < 2) {
auto pathElements = group->shapePath->pathElements();
pathElements.clear(&pathElements);
for (auto path : group->paths)
path->deleteLater();
group->paths.clear();
return; return;
} }
@ -116,42 +99,8 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
/ m_graph->m_axisRenderer->m_axisHorizontalValueRange) / m_graph->m_axisRenderer->m_axisHorizontalValueRange)
* m_areaWidth; * m_areaWidth;
qsizetype pointCount = upper->points().size(); auto &painterPath = group->painterPath;
qsizetype currentSize = group->paths.size(); painterPath.clear();
qsizetype extraCount = lower ? lower->points().size() : 2;
for (qsizetype i = currentSize; i < pointCount + extraCount; ++i) {
QQuickCurve *path = nullptr;
if (!lower || (lower && i < pointCount - 1)) {
if (upper->type() == QAbstractSeries::SeriesType::Line || (!lower && i >= pointCount - 1))
path = new QQuickPathLine(group->shapePath);
else if (upper->type() == QAbstractSeries::SeriesType::Spline)
path = new QQuickPathCubic(group->shapePath);
} else if (lower && (i == pointCount - 1 || i == pointCount + extraCount - 1)) {
path = new QQuickPathLine(group->shapePath);
} else {
if (lower->type() == QAbstractSeries::SeriesType::Line)
path = new QQuickPathLine(group->shapePath);
else if (lower->type() == QAbstractSeries::SeriesType::Spline)
path = new QQuickPathCubic(group->shapePath);
}
if (path && series->isVisible()) {
auto pathElements = group->shapePath->pathElements();
pathElements.append(&pathElements, path);
group->paths << path;
}
}
auto pathElements = group->shapePath->pathElements();
if (!series->isVisible() && pathElements.count(&pathElements) > 0) {
pathElements.clear(&pathElements);
for (auto path : group->paths)
path->deleteLater();
group->paths.clear();
}
if (group->colorIndex < 0) { if (group->colorIndex < 0) {
group->colorIndex = m_graph->graphSeriesCount(); group->colorIndex = m_graph->graphSeriesCount();
@ -204,15 +153,10 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
calculateRenderCoordinates(upperPoints[i].x(), upperPoints[i].y(), &x, &y); calculateRenderCoordinates(upperPoints[i].x(), upperPoints[i].y(), &x, &y);
if (i == 0) { if (i == 0) {
group->shapePath->setStartX(x); painterPath.moveTo(x, y);
group->shapePath->setStartY(y);
} else { } else {
group->paths[i - 1]->setX(x); if (i < upper->points().size()
group->paths[i - 1]->setY(y); && upper->type() == QAbstractSeries::SeriesType::Spline) {
auto *cubicPath = qobject_cast<QQuickPathCubic *>(group->paths[i - 1]);
if (cubicPath) {
qreal x1, y1, x2, y2; qreal x1, y1, x2, y2;
calculateRenderCoordinates(fittedPoints[j - 1].x(), calculateRenderCoordinates(fittedPoints[j - 1].x(),
fittedPoints[j - 1].y(), fittedPoints[j - 1].y(),
@ -220,12 +164,10 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
&y1); &y1);
calculateRenderCoordinates(fittedPoints[j].x(), fittedPoints[j].y(), &x2, &y2); calculateRenderCoordinates(fittedPoints[j].x(), fittedPoints[j].y(), &x2, &y2);
painterPath.cubicTo(x1, y1, x2, y2, x, y);
++j; ++j;
} else {
cubicPath->setControl2X(x2); painterPath.lineTo(x, y);
cubicPath->setControl1X(x1);
cubicPath->setControl2Y(y2);
cubicPath->setControl1Y(y1);
} }
} }
} }
@ -234,8 +176,8 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
if (lower && series->isVisible()) { if (lower && series->isVisible()) {
auto &&lowerPoints = lower->points(); auto &&lowerPoints = lower->points();
QList<QPointF> fittedPoints; QList<QPointF> fittedPoints;
if (upper->type() == QAbstractSeries::SeriesType::Spline) if (lower->type() == QAbstractSeries::SeriesType::Spline)
fittedPoints = qobject_cast<QSplineSeries *>(upper)->getControlPoints(); fittedPoints = qobject_cast<QSplineSeries *>(lower)->getControlPoints();
for (int i = 0, j = 0; i < lowerPoints.size(); ++i, ++j) { for (int i = 0, j = 0; i < lowerPoints.size(); ++i, ++j) {
qreal x, y; qreal x, y;
@ -244,13 +186,7 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
&x, &x,
&y); &y);
group->paths[upperPoints.size() + i - 1]->setX(x); if (i > 0 && lower->type() == QAbstractSeries::SeriesType::Spline) {
group->paths[upperPoints.size() + i - 1]->setY(y);
auto *cubicPath = qobject_cast<QQuickPathCubic *>(
group->paths[upperPoints.size() + i - 1]);
if (cubicPath) {
qreal x1, y1, x2, y2; qreal x1, y1, x2, y2;
calculateRenderCoordinates(fittedPoints[fittedPoints.size() - 1 - j + 1].x(), calculateRenderCoordinates(fittedPoints[fittedPoints.size() - 1 - j + 1].x(),
fittedPoints[fittedPoints.size() - 1 - j + 1].y(), fittedPoints[fittedPoints.size() - 1 - j + 1].y(),
@ -261,21 +197,20 @@ void AreaRenderer::handlePolish(QAreaSeries *series)
&x2, &x2,
&y2); &y2);
painterPath.cubicTo(x1, y1, x2, y2, x, y);
++j; ++j;
} else {
cubicPath->setControl2X(x2); painterPath.lineTo(x, y);
cubicPath->setControl1X(x1);
cubicPath->setControl2Y(y2);
cubicPath->setControl1Y(y1);
} }
} }
qreal x, y; qreal x, y;
calculateRenderCoordinates(upperPoints[0].x(), upperPoints[0].y(), &x, &y); calculateRenderCoordinates(upperPoints[0].x(), upperPoints[0].y(), &x, &y);
painterPath.lineTo(x, y);
group->paths[upperPoints.size() + lowerPoints.size() - 1]->setX(x);
group->paths[upperPoints.size() + lowerPoints.size() - 1]->setY(y);
} }
group->shapePath->setPath(painterPath);
QList<QLegendData> legendDataList = {{color, borderColor, series->name()}}; QList<QLegendData> legendDataList = {{color, borderColor, series->name()}};
series->d_func()->setLegendData(legendDataList); series->d_func()->setLegendData(legendDataList);
} }
@ -287,10 +222,9 @@ void AreaRenderer::afterPolish(QList<QAbstractSeries *> &cleanupSeries)
if (areaSeries && m_groups.contains(areaSeries)) { if (areaSeries && m_groups.contains(areaSeries)) {
auto group = m_groups.value(areaSeries); auto group = m_groups.value(areaSeries);
if (group->shapePath) { auto painterPath = group->painterPath;
auto pathElements = group->shapePath->pathElements(); painterPath.clear();
pathElements.clear(&pathElements); group->shapePath->setPath(painterPath);
}
delete group; delete group;
m_groups.remove(areaSeries); m_groups.remove(areaSeries);

View File

@ -14,6 +14,7 @@
// //
// We mean it. // We mean it.
#include <QPainterPath>
#include <QQuickItem> #include <QQuickItem>
#include <QtQuickShapes/private/qquickshape_p.h> #include <QtQuickShapes/private/qquickshape_p.h>
@ -45,7 +46,7 @@ private:
{ {
QAreaSeries *series = nullptr; QAreaSeries *series = nullptr;
QQuickShapePath *shapePath = nullptr; QQuickShapePath *shapePath = nullptr;
QList<QQuickCurve *> paths; QPainterPath painterPath;
qsizetype colorIndex = -1; qsizetype colorIndex = -1;
qsizetype borderColorIndex = -1; qsizetype borderColorIndex = -1;
bool hover = false; bool hover = false;