mirror of https://github.com/qt/qtgraphs.git
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:
parent
f72417979f
commit
5502bd0b0e
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue