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