File indexing completed on 2024-05-05 16:16:43

0001 /*
0002  * This file is part of KQuickCharts
0003  * SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006  */
0007 
0008 #include "PieChartMaterial.h"
0009 
0010 PieChartMaterial::PieChartMaterial()
0011 {
0012     setFlag(QSGMaterial::Blending);
0013 }
0014 
0015 PieChartMaterial::~PieChartMaterial()
0016 {
0017 }
0018 
0019 QSGMaterialType *PieChartMaterial::type() const
0020 {
0021     static QSGMaterialType type;
0022     return &type;
0023 }
0024 
0025 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0026 QSGMaterialShader *PieChartMaterial::createShader() const
0027 #else
0028 QSGMaterialShader *PieChartMaterial::createShader(QSGRendererInterface::RenderMode) const
0029 #endif
0030 {
0031     return new PieChartShader();
0032 }
0033 
0034 QVector2D PieChartMaterial::aspectRatio() const
0035 {
0036     return m_aspectRatio;
0037 }
0038 
0039 float PieChartMaterial::innerRadius() const
0040 {
0041     return m_innerRadius;
0042 }
0043 
0044 float PieChartMaterial::outerRadius() const
0045 {
0046     return m_outerRadius;
0047 }
0048 
0049 QColor PieChartMaterial::backgroundColor() const
0050 {
0051     return m_backgroundColor;
0052 }
0053 
0054 QVector<QVector2D> PieChartMaterial::segments() const
0055 {
0056     return m_segments;
0057 }
0058 
0059 QVector<QVector4D> PieChartMaterial::colors() const
0060 {
0061     return m_colors;
0062 }
0063 
0064 bool PieChartMaterial::smoothEnds() const
0065 {
0066     return m_smoothEnds;
0067 }
0068 
0069 float PieChartMaterial::fromAngle() const
0070 {
0071     return m_fromAngle;
0072 }
0073 
0074 float PieChartMaterial::toAngle() const
0075 {
0076     return m_toAngle;
0077 }
0078 
0079 void PieChartMaterial::setAspectRatio(const QVector2D &aspect)
0080 {
0081     m_aspectRatio = aspect;
0082 }
0083 
0084 void PieChartMaterial::setInnerRadius(float radius)
0085 {
0086     m_innerRadius = radius;
0087 }
0088 
0089 void PieChartMaterial::setOuterRadius(float radius)
0090 {
0091     m_outerRadius = radius;
0092 }
0093 
0094 void PieChartMaterial::setBackgroundColor(const QColor &color)
0095 {
0096     m_backgroundColor = color;
0097 }
0098 
0099 void PieChartMaterial::setSegments(const QVector<QVector2D> &segments)
0100 {
0101     m_segments = segments;
0102 }
0103 
0104 void PieChartMaterial::setColors(const QVector<QVector4D> &colors)
0105 {
0106     m_colors = colors;
0107 }
0108 
0109 void PieChartMaterial::setSmoothEnds(bool smooth)
0110 {
0111     m_smoothEnds = smooth;
0112 }
0113 
0114 void PieChartMaterial::setFromAngle(float angle)
0115 {
0116     m_fromAngle = angle;
0117 }
0118 
0119 void PieChartMaterial::setToAngle(float angle)
0120 {
0121     m_toAngle = angle;
0122 }
0123 
0124 PieChartShader::PieChartShader()
0125 {
0126     setShaders(QStringLiteral("piechart.vert"), QStringLiteral("piechart.frag"));
0127 }
0128 
0129 PieChartShader::~PieChartShader()
0130 {
0131 }
0132 
0133 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0134 const char *const *PieChartShader::attributeNames() const
0135 {
0136     static char const *const names[] = {"in_vertex", "in_uv", nullptr};
0137     return names;
0138 }
0139 
0140 void PieChartShader::initialize()
0141 {
0142     QSGMaterialShader::initialize();
0143     m_matrixLocation = program()->uniformLocation("matrix");
0144     m_opacityLocation = program()->uniformLocation("opacity");
0145     m_innerRadiusLocation = program()->uniformLocation("innerRadius");
0146     m_outerRadiusLocation = program()->uniformLocation("outerRadius");
0147     m_aspectLocation = program()->uniformLocation("aspect");
0148     m_backgroundColorLocation = program()->uniformLocation("backgroundColor");
0149     m_colorsLocation = program()->uniformLocation("colors");
0150     m_segmentsLocation = program()->uniformLocation("segments");
0151     m_segmentCountLocation = program()->uniformLocation("segmentCount");
0152     m_smoothEndsLocation = program()->uniformLocation("smoothEnds");
0153     m_fromAngleLocation = program()->uniformLocation("fromAngle");
0154     m_toAngleLocation = program()->uniformLocation("toAngle");
0155 }
0156 
0157 void PieChartShader::updateState(const QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
0158 {
0159     if (state.isMatrixDirty()) {
0160         program()->setUniformValue(m_matrixLocation, state.combinedMatrix());
0161     }
0162     if (state.isOpacityDirty()) {
0163         program()->setUniformValue(m_opacityLocation, state.opacity());
0164     }
0165 
0166     if (!oldMaterial || newMaterial->compare(oldMaterial) != 0) {
0167         PieChartMaterial *material = static_cast<PieChartMaterial *>(newMaterial);
0168         program()->setUniformValue(m_innerRadiusLocation, material->innerRadius());
0169         program()->setUniformValue(m_outerRadiusLocation, material->outerRadius());
0170         program()->setUniformValue(m_aspectLocation, material->aspectRatio());
0171         program()->setUniformValue(m_backgroundColorLocation, material->backgroundColor());
0172         program()->setUniformValueArray(m_colorsLocation, material->colors().constData(), material->colors().size());
0173         program()->setUniformValueArray(m_segmentsLocation, material->segments().constData(), material->segments().size());
0174         program()->setUniformValue(m_segmentCountLocation, material->segments().size());
0175         program()->setUniformValue(m_smoothEndsLocation, material->smoothEnds());
0176         program()->setUniformValue(m_fromAngleLocation, material->fromAngle());
0177         program()->setUniformValue(m_toAngleLocation, material->toAngle());
0178     }
0179 }
0180 #else
0181 bool PieChartShader::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
0182 {
0183     bool changed = false;
0184     QByteArray *buf = state.uniformData();
0185     Q_ASSERT(buf->size() >= 3332);
0186 
0187     if (state.isMatrixDirty()) {
0188         const QMatrix4x4 m = state.combinedMatrix();
0189         memcpy(buf->data(), m.constData(), 64);
0190         changed = true;
0191     }
0192 
0193     if (state.isOpacityDirty()) {
0194         const float opacity = state.opacity();
0195         memcpy(buf->data() + 72, &opacity, 4);
0196         changed = true;
0197     }
0198 
0199     if (!oldMaterial || newMaterial->compare(oldMaterial) != 0) {
0200         const auto material = static_cast<PieChartMaterial *>(newMaterial);
0201         const QVector2D aspect = material->aspectRatio();
0202         memcpy(buf->data() + 64, &aspect, 8);
0203         float f = material->innerRadius();
0204         memcpy(buf->data() + 76, &f, 4);
0205         f = material->outerRadius();
0206         memcpy(buf->data() + 80, &f, 4);
0207         float c[4];
0208         material->backgroundColor().getRgbF(&c[0], &c[1], &c[2], &c[3]);
0209         memcpy(buf->data() + 96, c, 16);
0210         bool b = material->smoothEnds();
0211         memcpy(buf->data() + 112, &b, 1);
0212         f = material->fromAngle();
0213         memcpy(buf->data() + 116, &f, 4);
0214         f = material->toAngle();
0215         memcpy(buf->data() + 120, &f, 4);
0216         const int segmentCount = material->segments().size();
0217         for (int i = 0; i < segmentCount; ++i) {
0218             const QVector2D v = material->segments().at(i);
0219             memcpy(buf->data() + 128 + (i * 16), &v, 8);
0220         }
0221         memcpy(buf->data() + 1728, material->colors().constData(), segmentCount * 16);
0222         memcpy(buf->data() + 3328, &segmentCount, 4);
0223         changed = true;
0224     }
0225 
0226     return changed;
0227 }
0228 #endif