From 15eed6371853e211970b68b5d613f14d8dd454b7 2016-02-09 16:43:05 From: Andy Shaw Date: 2016-02-09 16:43:05 Subject: [PATCH] Add support for reversed axis when useOpenGL is true Change-Id: If8b6690585c767b65eaa4a43e179c86183903637 Reviewed-by: Miikka Heikkinen --- diff --git a/src/charts/chartdataset.cpp b/src/charts/chartdataset.cpp index 33857b0..cbc4dfb 100644 --- a/src/charts/chartdataset.cpp +++ b/src/charts/chartdataset.cpp @@ -280,7 +280,7 @@ bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis) series->d_ptr->initializeAxes(); axis->d_ptr->initializeDomain(domain); - + connect(axis, &QAbstractAxis::reverseChanged, this, &ChartDataSet::reverseChanged); foreach (AbstractDomain *blockedDomain, blockedDomains) blockedDomain->blockRangeSignals(false); @@ -319,7 +319,7 @@ bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis) domain->detachAxis(axis); series->d_ptr->m_axes.removeAll(axis); axis->d_ptr->m_series.removeAll(series); - + disconnect(axis, &QAbstractAxis::reverseChanged, this, &ChartDataSet::reverseChanged); return true; } @@ -645,6 +645,13 @@ AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type) } } +void ChartDataSet::reverseChanged() +{ + QAbstractAxis *axis = qobject_cast(sender()); + if (axis) + m_glXYSeriesDataManager->handleAxisReverseChanged(axis->d_ptr->m_series); +} + #include "moc_chartdataset_p.cpp" QT_CHARTS_END_NAMESPACE diff --git a/src/charts/chartdataset_p.h b/src/charts/chartdataset_p.h index 85823c4..bc2917b 100644 --- a/src/charts/chartdataset_p.h +++ b/src/charts/chartdataset_p.h @@ -86,7 +86,8 @@ Q_SIGNALS: void axisRemoved(QAbstractAxis* axis); void seriesAdded(QAbstractSeries* series); void seriesRemoved(QAbstractSeries* series); - +public Q_SLOTS: + void reverseChanged(); private: void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation); QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation); diff --git a/src/charts/glwidget.cpp b/src/charts/glwidget.cpp index 5ea41f7..c0070dc 100644 --- a/src/charts/glwidget.cpp +++ b/src/charts/glwidget.cpp @@ -109,9 +109,10 @@ static const char *vertexSource = "uniform highp vec2 min;\n" "uniform highp vec2 delta;\n" "uniform highp float pointSize;\n" + "uniform highp mat4 matrix;\n" "void main() {\n" " vec2 normalPoint = vec2(-1, -1) + ((points - min) / delta);\n" - " gl_Position = vec4(normalPoint, 0, 1);\n" + " gl_Position = matrix * vec4(normalPoint, 0, 1);\n" " gl_PointSize = pointSize;\n" "}"; static const char *fragmentSource = @@ -138,6 +139,7 @@ void GLWidget::initializeGL() m_minUniformLoc = m_program->uniformLocation("min"); m_deltaUniformLoc = m_program->uniformLocation("delta"); m_pointSizeUniformLoc = m_program->uniformLocation("pointSize"); + m_matrixUniformLoc = m_program->uniformLocation("matrix"); // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x @@ -179,6 +181,7 @@ void GLWidget::paintGL() m_program->setUniformValue(m_colorUniformLoc, data->color); m_program->setUniformValue(m_minUniformLoc, data->min); m_program->setUniformValue(m_deltaUniformLoc, data->delta); + m_program->setUniformValue(m_matrixUniformLoc, data->matrix); if (!vbo) { vbo = new QOpenGLBuffer; diff --git a/src/charts/glwidget_p.h b/src/charts/glwidget_p.h index 920255f..024e096 100644 --- a/src/charts/glwidget_p.h +++ b/src/charts/glwidget_p.h @@ -79,6 +79,7 @@ private: int m_minUniformLoc; int m_deltaUniformLoc; int m_pointSizeUniformLoc; + int m_matrixUniformLoc; QOpenGLVertexArrayObject m_vao; QHash m_seriesBufferMap; diff --git a/src/charts/xychart/glxyseriesdata.cpp b/src/charts/xychart/glxyseriesdata.cpp index e5fc9e8..37da55b 100644 --- a/src/charts/xychart/glxyseriesdata.cpp +++ b/src/charts/xychart/glxyseriesdata.cpp @@ -74,16 +74,30 @@ void GLXYSeriesDataManager::setPoints(QXYSeries *series, const AbstractDomain *d QVector &array = data->array; bool logAxis = false; + bool reverseX = false; + bool reverseY = false; foreach (QAbstractAxis* axis, series->attachedAxes()) { if (axis->type() == QAbstractAxis::AxisTypeLogValue) { logAxis = true; - break; + } + if (axis->isReverse()) { + if (axis->orientation() == Qt::Horizontal) + reverseX = true; + else + reverseY = true; + if (reverseX && reverseY) + break; } } - int count = series->count(); int index = 0; array.resize(count * 2); + QMatrix4x4 matrix; + if (reverseX) + matrix.scale(-1.0, 1.0); + if (reverseY) + matrix.scale(1.0, -1.0); + data->matrix = matrix; if (logAxis) { // Use domain to resolve geometry points. Not as fast as shaders, but simpler that way QVector geometryPoints = domain->calculateGeometryPoints(series->pointsVector()); @@ -185,5 +199,35 @@ void GLXYSeriesDataManager::handleScatterMarkerSizeChange() } } +void GLXYSeriesDataManager::handleAxisReverseChanged(const QList &seriesList) +{ + bool reverseX = false; + bool reverseY = false; + foreach (QAbstractSeries *series, seriesList) { + if (QXYSeries *xyseries = qobject_cast(series)) { + GLXYSeriesData *data = m_seriesDataMap.value(xyseries); + if (data) { + foreach (QAbstractAxis* axis, xyseries->attachedAxes()) { + if (axis->isReverse()) { + if (axis->orientation() == Qt::Horizontal) + reverseX = true; + else + reverseY = true; + } + if (reverseX && reverseY) + break; + } + QMatrix4x4 matrix; + if (reverseX) + matrix.scale(-1.0, 1.0); + if (reverseY) + matrix.scale(1.0, -1.0); + data->matrix = matrix; + data->dirty = true; + } + } + } +} + QT_CHARTS_END_NAMESPACE diff --git a/src/charts/xychart/glxyseriesdata_p.h b/src/charts/xychart/glxyseriesdata_p.h index 71a800c..578ab21 100644 --- a/src/charts/xychart/glxyseriesdata_p.h +++ b/src/charts/xychart/glxyseriesdata_p.h @@ -44,6 +44,7 @@ #include #include #include +#include QT_CHARTS_BEGIN_NAMESPACE @@ -57,6 +58,19 @@ struct GLXYSeriesData { QAbstractSeries::SeriesType type; QVector2D min; QVector2D delta; + QMatrix4x4 matrix; +public: + GLXYSeriesData &operator=(const GLXYSeriesData &data) { + array = data.array; + dirty = data.dirty; + color = data.color; + width = data.width; + type = data.type; + min = data.min; + delta = data.delta; + matrix = data.matrix; + return *this; + } }; typedef QMap GLXYDataMap; @@ -83,6 +97,7 @@ public: foreach (GLXYSeriesData *data, m_seriesDataMap.values()) data->dirty = false; } + void handleAxisReverseChanged(const QList &seriesList); public Q_SLOTS: void cleanup(); diff --git a/src/chartsqml2/declarativerendernode.cpp b/src/chartsqml2/declarativerendernode.cpp index 66784ec..c11f6b0 100644 --- a/src/chartsqml2/declarativerendernode.cpp +++ b/src/chartsqml2/declarativerendernode.cpp @@ -96,9 +96,10 @@ static const char *vertexSource = "uniform highp vec2 min;\n" "uniform highp vec2 delta;\n" "uniform highp float pointSize;\n" + "uniform highp mat4 matrix;\n" "void main() {\n" " vec2 normalPoint = vec2(-1, -1) + ((points - min) / delta);\n" - " gl_Position = vec4(normalPoint, 0, 1);\n" + " gl_Position = matrix * vec4(normalPoint, 0, 1);\n" " gl_PointSize = pointSize;\n" "}"; static const char *fragmentSource = @@ -123,6 +124,7 @@ void DeclarativeRenderNode::initGL() m_minUniformLoc = m_program->uniformLocation("min"); m_deltaUniformLoc = m_program->uniformLocation("delta"); m_pointSizeUniformLoc = m_program->uniformLocation("pointSize"); + m_matrixUniformLoc = m_program->uniformLocation("matrix"); // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x // implementations this is optional and support may not be present @@ -183,13 +185,7 @@ void DeclarativeRenderNode::setSeriesData(bool mapDirty, const GLXYDataMap &data const GLXYSeriesData *newData = i.value(); if (!data || newData->dirty) { data = new GLXYSeriesData; - data->array = newData->array; - data->color = newData->color; - data->dirty = newData->dirty; - data->width = newData->width; - data->type = newData->type; - data->min = newData->min; - data->delta = newData->delta; + *data = *newData; } m_xyDataMap.insert(i.key(), data); } @@ -208,15 +204,8 @@ void DeclarativeRenderNode::setSeriesData(bool mapDirty, const GLXYDataMap &data const GLXYSeriesData *newData = i.value(); if (i.value()->dirty) { GLXYSeriesData *data = m_xyDataMap.value(i.key()); - if (data) { - data->array = newData->array; - data->color = newData->color; - data->dirty = newData->dirty; - data->width = newData->width; - data->type = newData->type; - data->min = newData->min; - data->delta = newData->delta; - } + if (data) + *data = *newData; } } } @@ -246,6 +235,7 @@ void DeclarativeRenderNode::renderGL() m_program->setUniformValue(m_colorUniformLoc, data->color); m_program->setUniformValue(m_minUniformLoc, data->min); m_program->setUniformValue(m_deltaUniformLoc, data->delta); + m_program->setUniformValue(m_matrixUniformLoc, data->matrix); if (!vbo) { vbo = new QOpenGLBuffer; diff --git a/src/chartsqml2/declarativerendernode.h b/src/chartsqml2/declarativerendernode.h index 3e3fe6a..b21fa20 100644 --- a/src/chartsqml2/declarativerendernode.h +++ b/src/chartsqml2/declarativerendernode.h @@ -74,6 +74,7 @@ private: int m_minUniformLoc; int m_deltaUniformLoc; int m_pointSizeUniformLoc; + int m_matrixUniformLoc; QOpenGLVertexArrayObject m_vao; QHash m_seriesBufferMap; bool m_renderNeeded;