##// END OF EJS Templates
Use pure white in the light end of gradients
Tero Ahola -
r656:fb0cd0785d0b
parent child
Show More
@@ -1,352 +1,352
1 #include "charttheme_p.h"
1 #include "charttheme_p.h"
2 #include "qchart.h"
2 #include "qchart.h"
3 #include "qchartview.h"
3 #include "qchartview.h"
4 #include "qlegend.h"
4 #include "qlegend.h"
5 #include "qchartaxis.h"
5 #include "qchartaxis.h"
6 #include <QTime>
6 #include <QTime>
7
7
8 //series
8 //series
9 #include "qbarset.h"
9 #include "qbarset.h"
10 #include "qbarseries.h"
10 #include "qbarseries.h"
11 #include "qstackedbarseries.h"
11 #include "qstackedbarseries.h"
12 #include "qpercentbarseries.h"
12 #include "qpercentbarseries.h"
13 #include "qlineseries.h"
13 #include "qlineseries.h"
14 #include "qareaseries.h"
14 #include "qareaseries.h"
15 #include "qscatterseries.h"
15 #include "qscatterseries.h"
16 #include "qpieseries.h"
16 #include "qpieseries.h"
17 #include "qpieslice.h"
17 #include "qpieslice.h"
18 #include "qsplineseries.h"
18 #include "qsplineseries.h"
19
19
20 //items
20 //items
21 #include "axisitem_p.h"
21 #include "axisitem_p.h"
22 #include "barpresenter_p.h"
22 #include "barpresenter_p.h"
23 #include "stackedbarpresenter_p.h"
23 #include "stackedbarpresenter_p.h"
24 #include "percentbarpresenter_p.h"
24 #include "percentbarpresenter_p.h"
25 #include "linechartitem_p.h"
25 #include "linechartitem_p.h"
26 #include "areachartitem_p.h"
26 #include "areachartitem_p.h"
27 #include "scatterchartitem_p.h"
27 #include "scatterchartitem_p.h"
28 #include "piechartitem_p.h"
28 #include "piechartitem_p.h"
29 #include "splinechartitem_p.h"
29 #include "splinechartitem_p.h"
30
30
31 //themes
31 //themes
32 #include "chartthemedefault_p.h"
32 #include "chartthemedefault_p.h"
33 #include "chartthemelight_p.h"
33 #include "chartthemelight_p.h"
34 #include "chartthemebluecerulean_p.h"
34 #include "chartthemebluecerulean_p.h"
35 #include "chartthemedark_p.h"
35 #include "chartthemedark_p.h"
36 #include "chartthemebrownsand_p.h"
36 #include "chartthemebrownsand_p.h"
37 #include "chartthemebluencs_p.h"
37 #include "chartthemebluencs_p.h"
38 #include "chartthemevanilla_p.h"
38 #include "chartthemevanilla_p.h"
39 #include "chartthemeicy_p.h"
39 #include "chartthemeicy_p.h"
40 #include "chartthemegrayscale_p.h"
40 #include "chartthemegrayscale_p.h"
41 #include "chartthemescientific_p.h"
41 #include "chartthemescientific_p.h"
42
42
43 QTCOMMERCIALCHART_BEGIN_NAMESPACE
43 QTCOMMERCIALCHART_BEGIN_NAMESPACE
44
44
45 ChartTheme::ChartTheme(QChart::ChartTheme id) :
45 ChartTheme::ChartTheme(QChart::ChartTheme id) :
46 m_masterFont(QFont()),
46 m_masterFont(QFont()),
47 m_titleBrush(QColor(QRgb(0x000000))),
47 m_titleBrush(QColor(QRgb(0x000000))),
48 m_axisLinePen(QPen(QRgb(0x000000))),
48 m_axisLinePen(QPen(QRgb(0x000000))),
49 m_axisLabelBrush(QColor(QRgb(0x000000))),
49 m_axisLabelBrush(QColor(QRgb(0x000000))),
50 m_backgroundShadesPen(Qt::NoPen),
50 m_backgroundShadesPen(Qt::NoPen),
51 m_backgroundShadesBrush(Qt::NoBrush),
51 m_backgroundShadesBrush(Qt::NoBrush),
52 m_backgroundShades(BackgroundShadesNone),
52 m_backgroundShades(BackgroundShadesNone),
53 m_gridLinePen(QPen(QRgb(0x000000)))
53 m_gridLinePen(QPen(QRgb(0x000000)))
54 {
54 {
55 m_id = id;
55 m_id = id;
56 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
56 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
57 }
57 }
58
58
59
59
60 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
60 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
61 {
61 {
62 switch(theme) {
62 switch(theme) {
63 case QChart::ChartThemeLight:
63 case QChart::ChartThemeLight:
64 return new ChartThemeLight();
64 return new ChartThemeLight();
65 case QChart::ChartThemeBlueCerulean:
65 case QChart::ChartThemeBlueCerulean:
66 return new ChartThemeBlueCerulean();
66 return new ChartThemeBlueCerulean();
67 case QChart::ChartThemeDark:
67 case QChart::ChartThemeDark:
68 return new ChartThemeDark();
68 return new ChartThemeDark();
69 case QChart::ChartThemeBrownSand:
69 case QChart::ChartThemeBrownSand:
70 return new ChartThemeBrownSand();
70 return new ChartThemeBrownSand();
71 case QChart::ChartThemeBlueNcs:
71 case QChart::ChartThemeBlueNcs:
72 return new ChartThemeBlueNcs();
72 return new ChartThemeBlueNcs();
73 case QChart::ChartThemeVanilla:
73 case QChart::ChartThemeVanilla:
74 return new ChartThemeVanilla();
74 return new ChartThemeVanilla();
75 case QChart::ChartThemeIcy:
75 case QChart::ChartThemeIcy:
76 return new ChartThemeIcy();
76 return new ChartThemeIcy();
77 case QChart::ChartThemeGrayscale:
77 case QChart::ChartThemeGrayscale:
78 return new ChartThemeGrayscale();
78 return new ChartThemeGrayscale();
79 case QChart::ChartThemeScientific:
79 case QChart::ChartThemeScientific:
80 return new ChartThemeScientific();
80 return new ChartThemeScientific();
81 default:
81 default:
82 return new ChartThemeDefault();
82 return new ChartThemeDefault();
83 }
83 }
84 }
84 }
85
85
86 void ChartTheme::decorate(QChart* chart,bool force)
86 void ChartTheme::decorate(QChart* chart,bool force)
87 {
87 {
88 QPen pen;
88 QPen pen;
89 QBrush brush;
89 QBrush brush;
90
90
91 if(brush == chart->backgroundBrush() || force)
91 if(brush == chart->backgroundBrush() || force)
92 {
92 {
93 if (m_backgroundShades == BackgroundShadesNone) {
93 if (m_backgroundShades == BackgroundShadesNone) {
94 chart->setBackgroundBrush(m_chartBackgroundGradient);
94 chart->setBackgroundBrush(m_chartBackgroundGradient);
95 }
95 }
96 else {
96 else {
97 chart->setBackgroundBrush(Qt::NoBrush);
97 chart->setBackgroundBrush(Qt::NoBrush);
98 }
98 }
99 }
99 }
100 chart->setTitleFont(m_masterFont);
100 chart->setTitleFont(m_masterFont);
101 chart->setTitleBrush(m_titleBrush);
101 chart->setTitleBrush(m_titleBrush);
102 }
102 }
103
103
104 void ChartTheme::decorate(QLegend* legend,bool force)
104 void ChartTheme::decorate(QLegend* legend,bool force)
105 {
105 {
106 QPen pen;
106 QPen pen;
107 QBrush brush;
107 QBrush brush;
108
108
109 if (pen == legend->pen() || force){
109 if (pen == legend->pen() || force){
110 //TODO:: legend->setPen();
110 //TODO:: legend->setPen();
111 }
111 }
112
112
113
113
114 if (brush == legend->brush() || force) {
114 if (brush == legend->brush() || force) {
115 legend->setBrush(m_chartBackgroundGradient);
115 legend->setBrush(m_chartBackgroundGradient);
116 }
116 }
117 }
117 }
118
118
119 void ChartTheme::decorate(QAreaSeries* series, int index,bool force)
119 void ChartTheme::decorate(QAreaSeries* series, int index,bool force)
120 {
120 {
121 QPen pen;
121 QPen pen;
122 QBrush brush;
122 QBrush brush;
123
123
124 if (pen == series->pen() || force){
124 if (pen == series->pen() || force){
125 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
125 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
126 pen.setWidthF(2);
126 pen.setWidthF(2);
127 series->setPen(pen);
127 series->setPen(pen);
128 }
128 }
129
129
130 if (brush == series->brush() || force) {
130 if (brush == series->brush() || force) {
131 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
131 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
132 series->setBrush(brush);
132 series->setBrush(brush);
133 }
133 }
134 }
134 }
135
135
136
136
137 void ChartTheme::decorate(QLineSeries* series,int index,bool force)
137 void ChartTheme::decorate(QLineSeries* series,int index,bool force)
138 {
138 {
139 QPen pen;
139 QPen pen;
140 if(pen == series->pen() || force ){
140 if(pen == series->pen() || force ){
141 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
141 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
142 pen.setWidthF(2);
142 pen.setWidthF(2);
143 series->setPen(pen);
143 series->setPen(pen);
144 }
144 }
145 }
145 }
146
146
147 void ChartTheme::decorate(QBarSeries* series, int index, bool force)
147 void ChartTheme::decorate(QBarSeries* series, int index, bool force)
148 {
148 {
149 QBrush brush;
149 QBrush brush;
150 QPen pen;
150 QPen pen;
151 QList<QBarSet*> sets = series->barSets();
151 QList<QBarSet*> sets = series->barSets();
152
152
153 for (int i(0); i < sets.count(); i++) {
153 for (int i(0); i < sets.count(); i++) {
154 qreal pos = 0.5;
154 qreal pos = 0.5;
155 if (sets.count() > 1)
155 if (sets.count() > 1)
156 pos = (qreal) i / (qreal) (sets.count() - 1);
156 pos = (qreal) i / (qreal) (sets.count() - 1);
157
157
158 if (brush == sets.at(i)->brush() || force ) {
158 if (brush == sets.at(i)->brush() || force ) {
159 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
159 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
160 sets.at(i)->setBrush(QBrush(c));
160 sets.at(i)->setBrush(QBrush(c));
161 }
161 }
162
162
163 // Pick label color from the opposite end of the gradient.
163 // Pick label color from the opposite end of the gradient.
164 // 0.3 as a boundary seems to work well.
164 // 0.3 as a boundary seems to work well.
165 if (pos < 0.3)
165 if (pos < 0.3)
166 sets.at(i)->setFloatingValuePen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
166 sets.at(i)->setFloatingValuePen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
167 else
167 else
168 sets.at(i)->setFloatingValuePen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
168 sets.at(i)->setFloatingValuePen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
169
169
170 if (pen == sets.at(i)->pen() || force) {
170 if (pen == sets.at(i)->pen() || force) {
171 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
171 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
172 sets.at(i)->setPen(c);
172 sets.at(i)->setPen(c);
173 }
173 }
174 }
174 }
175 }
175 }
176
176
177 void ChartTheme::decorate(QScatterSeries* series, int index,bool force)
177 void ChartTheme::decorate(QScatterSeries* series, int index,bool force)
178 {
178 {
179 QPen pen;
179 QPen pen;
180 QBrush brush;
180 QBrush brush;
181
181
182 if (pen == series->pen() || force) {
182 if (pen == series->pen() || force) {
183 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
183 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
184 pen.setWidthF(2);
184 pen.setWidthF(2);
185 series->setPen(pen);
185 series->setPen(pen);
186 }
186 }
187
187
188 if (brush == series->brush() || force) {
188 if (brush == series->brush() || force) {
189 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
189 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
190 series->setBrush(brush);
190 series->setBrush(brush);
191 }
191 }
192 }
192 }
193
193
194 void ChartTheme::decorate(QPieSeries* series, int index, bool force)
194 void ChartTheme::decorate(QPieSeries* series, int index, bool force)
195 {
195 {
196 QPen pen;
196 QPen pen;
197 QBrush brush;
197 QBrush brush;
198
198
199 for (int i(0); i < series->slices().count(); i++) {
199 for (int i(0); i < series->slices().count(); i++) {
200 if (pen == series->slices().at(i)->slicePen() || force) {
200 if (pen == series->slices().at(i)->slicePen() || force) {
201 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
201 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
202 series->slices().at(i)->setSlicePen(penColor);
202 series->slices().at(i)->setSlicePen(penColor);
203 }
203 }
204
204
205 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
205 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
206 qreal pos = (qreal) i / (qreal) series->count();
206 qreal pos = (qreal) i / (qreal) series->count();
207 if (brush == series->slices().at(i)->sliceBrush() || force) {
207 if (brush == series->slices().at(i)->sliceBrush() || force) {
208 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
208 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
209 series->slices().at(i)->setSliceBrush(brushColor);
209 series->slices().at(i)->setSliceBrush(brushColor);
210 }
210 }
211 }
211 }
212 }
212 }
213
213
214 void ChartTheme::decorate(QSplineSeries* series, int index, bool force)
214 void ChartTheme::decorate(QSplineSeries* series, int index, bool force)
215 {
215 {
216 QPen pen;
216 QPen pen;
217 if(pen == series->pen() || force){
217 if(pen == series->pen() || force){
218 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
218 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
219 pen.setWidthF(2);
219 pen.setWidthF(2);
220 series->setPen(pen);
220 series->setPen(pen);
221 }
221 }
222 }
222 }
223
223
224 void ChartTheme::decorate(QChartAxis* axis,bool axisX, bool force)
224 void ChartTheme::decorate(QChartAxis* axis,bool axisX, bool force)
225 {
225 {
226 QPen pen;
226 QPen pen;
227 QBrush brush;
227 QBrush brush;
228 QFont font;
228 QFont font;
229
229
230 if (axis->isAxisVisible()) {
230 if (axis->isAxisVisible()) {
231
231
232 if(brush == axis->labelsBrush() || force){
232 if(brush == axis->labelsBrush() || force){
233 axis->setLabelsBrush(m_axisLabelBrush);
233 axis->setLabelsBrush(m_axisLabelBrush);
234 }
234 }
235 if(pen == axis->labelsPen() || force){
235 if(pen == axis->labelsPen() || force){
236 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
236 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
237 }
237 }
238
238
239
239
240 if (axis->shadesVisible() || force) {
240 if (axis->shadesVisible() || force) {
241
241
242 if(brush == axis->shadesBrush() || force){
242 if(brush == axis->shadesBrush() || force){
243 axis->setShadesBrush(m_backgroundShadesBrush);
243 axis->setShadesBrush(m_backgroundShadesBrush);
244 }
244 }
245
245
246 if(pen == axis->shadesPen() || force){
246 if(pen == axis->shadesPen() || force){
247 axis->setShadesPen(m_backgroundShadesPen);
247 axis->setShadesPen(m_backgroundShadesPen);
248 }
248 }
249
249
250 if(force && (m_backgroundShades == BackgroundShadesBoth
250 if(force && (m_backgroundShades == BackgroundShadesBoth
251 || (m_backgroundShades == BackgroundShadesVertical && axisX)
251 || (m_backgroundShades == BackgroundShadesVertical && axisX)
252 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
252 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
253 axis->setShadesVisible(true);
253 axis->setShadesVisible(true);
254
254
255 }
255 }
256 }
256 }
257
257
258 if(pen == axis->axisPen() || force){
258 if(pen == axis->axisPen() || force){
259 axis->setAxisPen(m_axisLinePen);
259 axis->setAxisPen(m_axisLinePen);
260 }
260 }
261
261
262 if(pen == axis->gridLinePen() || force){
262 if(pen == axis->gridLinePen() || force){
263 axis->setGridLinePen(m_gridLinePen);
263 axis->setGridLinePen(m_gridLinePen);
264 }
264 }
265
265
266 if(font == axis->labelsFont() || force){
266 if(font == axis->labelsFont() || force){
267 axis->setLabelsFont(m_masterFont);
267 axis->setLabelsFont(m_masterFont);
268 }
268 }
269 }
269 }
270 }
270 }
271
271
272 void ChartTheme::generateSeriesGradients()
272 void ChartTheme::generateSeriesGradients()
273 {
273 {
274 // Generate gradients in HSV color space
274 // Generate gradients in HSV color space
275 foreach (QColor color, m_seriesColors) {
275 foreach (QColor color, m_seriesColors) {
276 QLinearGradient g;
276 QLinearGradient g;
277 qreal h = color.hsvHueF();
277 qreal h = color.hsvHueF();
278 qreal s = color.hsvSaturationF();
278 qreal s = color.hsvSaturationF();
279
279
280 // TODO: tune the algorithm to give nice results with most base colors defined in
280 // TODO: tune the algorithm to give nice results with most base colors defined in
281 // most themes. The rest of the gradients we can define manually in theme specific
281 // most themes. The rest of the gradients we can define manually in theme specific
282 // implementation.
282 // implementation.
283 QColor start = color;
283 QColor start = color;
284 start.setHsvF(h, 0.05, 0.95);
284 start.setHsvF(h, 0.0, 1.0);
285 g.setColorAt(0.0, start);
285 g.setColorAt(0.0, start);
286
286
287 g.setColorAt(0.5, color);
287 g.setColorAt(0.5, color);
288
288
289 QColor end = color;
289 QColor end = color;
290 end.setHsvF(h, s, 0.25);
290 end.setHsvF(h, s, 0.25);
291 g.setColorAt(1.0, end);
291 g.setColorAt(1.0, end);
292
292
293 m_seriesGradients << g;
293 m_seriesGradients << g;
294 }
294 }
295 }
295 }
296
296
297
297
298 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
298 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
299 {
299 {
300 Q_ASSERT(pos >=0.0 && pos <= 1.0);
300 Q_ASSERT(pos >=0.0 && pos <= 1.0);
301 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
301 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
302 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
302 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
303 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
303 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
304 QColor c;
304 QColor c;
305 c.setRgbF(r, g, b);
305 c.setRgbF(r, g, b);
306 return c;
306 return c;
307 }
307 }
308
308
309 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
309 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
310 {
310 {
311 Q_ASSERT(pos >=0 && pos <= 1.0);
311 Q_ASSERT(pos >=0 && pos <= 1.0);
312
312
313 // another possibility:
313 // another possibility:
314 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
314 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
315
315
316 QGradientStops stops = gradient.stops();
316 QGradientStops stops = gradient.stops();
317 int count = stops.count();
317 int count = stops.count();
318
318
319 // find previous stop relative to position
319 // find previous stop relative to position
320 QGradientStop prev = stops.first();
320 QGradientStop prev = stops.first();
321 for (int i=0; i<count; i++) {
321 for (int i=0; i<count; i++) {
322 QGradientStop stop = stops.at(i);
322 QGradientStop stop = stops.at(i);
323 if (pos > stop.first)
323 if (pos > stop.first)
324 prev = stop;
324 prev = stop;
325
325
326 // given position is actually a stop position?
326 // given position is actually a stop position?
327 if (pos == stop.first) {
327 if (pos == stop.first) {
328 //qDebug() << "stop color" << pos;
328 //qDebug() << "stop color" << pos;
329 return stop.second;
329 return stop.second;
330 }
330 }
331 }
331 }
332
332
333 // find next stop relative to position
333 // find next stop relative to position
334 QGradientStop next = stops.last();
334 QGradientStop next = stops.last();
335 for (int i=count-1; i>=0; i--) {
335 for (int i=count-1; i>=0; i--) {
336 QGradientStop stop = stops.at(i);
336 QGradientStop stop = stops.at(i);
337 if (pos < stop.first)
337 if (pos < stop.first)
338 next = stop;
338 next = stop;
339 }
339 }
340
340
341 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
341 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
342
342
343 qreal range = next.first - prev.first;
343 qreal range = next.first - prev.first;
344 qreal posDelta = pos - prev.first;
344 qreal posDelta = pos - prev.first;
345 qreal relativePos = posDelta / range;
345 qreal relativePos = posDelta / range;
346
346
347 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
347 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
348
348
349 return colorAt(prev.second, next.second, relativePos);
349 return colorAt(prev.second, next.second, relativePos);
350 }
350 }
351
351
352 QTCOMMERCIALCHART_END_NAMESPACE
352 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now