2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#include "cairo-dock-log.h"
25
#include "cairo-dock-surface-factory.h"
26
#include "cairo-dock-dock-factory.h"
27
#include "cairo-dock-renderer-manager.h"
28
#include "cairo-dock-draw-opengl.h"
29
#include "cairo-dock-draw.h"
30
#include "cairo-dock-internal-labels.h"
31
#include "cairo-dock-internal-icons.h"
32
#include "cairo-dock-internal-background.h"
33
#include "cairo-dock-container.h"
34
#include "cairo-dock-graph.h"
36
extern gboolean g_bUseOpenGL;
39
void cairo_dock_render_graph (CairoDockGraph *pGraph, cairo_t *pCairoContext)
41
g_return_if_fail (pGraph != NULL && pCairoContext != NULL);
42
g_return_if_fail (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS);
44
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
45
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
47
if (pGraph->pBackgroundSurface != NULL)
49
cairo_set_source_surface (pCairoContext, pGraph->pBackgroundSurface, 0., 0.);
50
cairo_paint (pCairoContext);
53
int iNbDrawings = pData->iNbValues / pRenderer->iRank;
57
double fMargin = pGraph->fMargin;
58
double fWidth = pRenderer->iWidth - 2*fMargin;
59
double fHeight = pRenderer->iHeight - 2*fMargin;
60
fHeight /= iNbDrawings;
63
cairo_pattern_t *pGradationPattern;
65
for (i = 0; i < pData->iNbValues; i ++)
67
if (! pGraph->bMixGraphs)
68
cairo_translate (pCairoContext,
71
pGradationPattern = pGraph->pGradationPatterns[i];
72
if (pGradationPattern != NULL)
73
cairo_set_source (pCairoContext, pGradationPattern);
75
cairo_set_source_rgb (pCairoContext,
76
pGraph->fLowColor[3*i+0],
77
pGraph->fLowColor[3*i+1],
78
pGraph->fLowColor[3*i+2]);
80
if (pGraph->iType == CAIRO_DOCK_GRAPH2_LINE || pGraph->iType == CAIRO_DOCK_GRAPH2_PLAIN)
82
cairo_set_line_width (pCairoContext, 1);
83
cairo_set_line_join (pCairoContext, CAIRO_LINE_JOIN_ROUND);
84
fValue = cairo_data_renderer_get_normalized_current_value (pRenderer, i);
85
cairo_move_to (pCairoContext, fMargin + fWidth, fMargin + (1 - fValue) * fHeight);
86
int t, n = pData->iMemorySize - 1;
87
for (t = 1; t < pData->iMemorySize; t ++)
89
fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
90
cairo_line_to (pCairoContext,
91
fMargin + (n - t) * fWidth / n,
92
fMargin + (1 - fValue) * fHeight);
94
if (pGraph->iType == CAIRO_DOCK_GRAPH2_PLAIN)
96
cairo_line_to (pCairoContext,
99
cairo_line_to (pCairoContext,
102
cairo_close_path (pCairoContext);
103
cairo_fill_preserve (pCairoContext);
105
cairo_stroke (pCairoContext);
107
else if (pGraph->iType == CAIRO_DOCK_GRAPH2_BAR)
109
double fBarWidth = fWidth / pData->iMemorySize / 4;
110
cairo_set_line_width (pCairoContext, fBarWidth);
111
int t, n = pData->iMemorySize - 1;
112
for (t = 0; t < pData->iMemorySize; t ++)
114
fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
115
cairo_move_to (pCairoContext,
116
fMargin + (n - t) * fWidth / n,
118
cairo_rel_line_to (pCairoContext,
121
cairo_stroke (pCairoContext);
126
cairo_set_line_width (pCairoContext, 1);
127
cairo_set_line_join (pCairoContext, CAIRO_LINE_JOIN_ROUND);
128
fValue = cairo_data_renderer_get_normalized_current_value (pRenderer, i);
129
double angle, radius = MIN (fWidth, fHeight)/2;
130
angle = -2*G_PI*(-.5/pData->iMemorySize);
131
cairo_move_to (pCairoContext,
132
fMargin + fWidth/2 + radius * (fValue * cos (angle)),
133
fMargin + fHeight/2 + radius * (fValue * sin (angle)));
134
angle = -2*G_PI*(.5/pData->iMemorySize);
135
cairo_line_to (pCairoContext,
136
fMargin + fWidth/2 + radius * (fValue * cos (angle)),
137
fMargin + fHeight/2 + radius * (fValue * sin (angle)));
139
for (t = 1; t < pData->iMemorySize; t ++)
141
fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
142
angle = -2*G_PI*((t-.5)/pData->iMemorySize);
143
cairo_line_to (pCairoContext,
144
fMargin + fWidth/2 + radius * (fValue * cos (angle)),
145
fMargin + fHeight/2 + radius * (fValue * sin (angle)));
146
angle = -2*G_PI*((t+.5)/pData->iMemorySize);
147
cairo_line_to (pCairoContext,
148
fMargin + fWidth/2 + radius * (fValue * cos (angle)),
149
fMargin + fHeight/2 + radius * (fValue * sin (angle)));
151
if (pGraph->iType == CAIRO_DOCK_GRAPH2_CIRCLE_PLAIN)
153
cairo_close_path (pCairoContext);
154
cairo_fill_preserve (pCairoContext);
156
cairo_stroke (pCairoContext);
162
static void cairo_dock_render_graph_opengl (CairoDockGraph *pGraph)
164
g_return_if_fail (pGraph != NULL);
166
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
167
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
169
if (pGraph->iBackgroundTexture != 0)
171
_cairo_dock_enable_texture ();
172
_cairo_dock_set_blend_pbuffer (); // ceci reste un mystere...
173
_cairo_dock_set_alpha (1.);
174
_cairo_dock_apply_texture_at_size_with_alpha (pGraph->iBackgroundTexture, pRenderer->iWidth, pRenderer->iHeight, 1.);
175
_cairo_dock_disable_texture ();
182
static inline cairo_surface_t *_cairo_dock_create_graph_background (cairo_t *pSourceContext, double fWidth, double fHeight, int iRadius, double fMargin, gdouble *pBackGroundColor, CairoDockTypeGraph iType, int iNbDrawings)
184
// on cree la surface.
185
cairo_surface_t *pBackgroundSurface = cairo_surface_create_similar (cairo_get_target (pSourceContext),
186
CAIRO_CONTENT_COLOR_ALPHA,
189
cairo_t *pCairoContext = cairo_create (pBackgroundSurface);
191
// on trace le fond : un rectangle au coin arrondi.
192
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
193
cairo_set_source_rgba (pCairoContext,
197
pBackGroundColor[3]);
199
double fRadius = iRadius;
200
cairo_set_line_width (pCairoContext, fRadius);
201
cairo_set_line_join (pCairoContext, CAIRO_LINE_JOIN_ROUND);
202
cairo_move_to (pCairoContext, .5*fRadius, .5*fRadius);
203
cairo_rel_line_to (pCairoContext, fWidth - (fRadius), 0);
204
cairo_rel_line_to (pCairoContext, 0, fHeight - (fRadius));
205
cairo_rel_line_to (pCairoContext, -(fWidth - (fRadius)) ,0);
206
cairo_close_path (pCairoContext);
207
cairo_stroke (pCairoContext); // on trace d'abord les contours arrondis.
209
cairo_rectangle (pCairoContext, fRadius, fRadius, (fWidth - 2*fRadius), (fHeight - 2*fRadius));
210
cairo_fill (pCairoContext); // puis on rempli l'interieur.
212
// on trace les axes.
213
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
214
cairo_set_source_rgb (pCairoContext,
215
myLabels.quickInfoTextDescription.fBackgroundColor[0],
216
myLabels.quickInfoTextDescription.fBackgroundColor[1],
217
myLabels.quickInfoTextDescription.fBackgroundColor[2]); // meme couleur que le fond des info-rapides, mais opaque.
218
cairo_set_line_width (pCairoContext, 1.);
219
if (iType == CAIRO_DOCK_GRAPH2_CIRCLE || iType == CAIRO_DOCK_GRAPH2_CIRCLE_PLAIN)
221
double r = .5 * MIN (fWidth - 2*fMargin, (fHeight - 2*fMargin) / iNbDrawings);
223
for (i = 0; i < iNbDrawings; i ++)
225
cairo_arc (pCairoContext,
227
fMargin + r * (2 * i + 1),
231
cairo_move_to (pCairoContext, fWidth/2, fMargin + r * (2 * i + 1));
232
cairo_rel_line_to (pCairoContext, r, 0.);
233
cairo_stroke (pCairoContext);
238
cairo_move_to (pCairoContext, fMargin, fMargin);
239
cairo_rel_line_to (pCairoContext, 0., fHeight - 2*fMargin);
240
cairo_stroke (pCairoContext);
242
for (i = 0; i < iNbDrawings; i ++)
244
cairo_move_to (pCairoContext, fMargin, (fHeight - 2 * fMargin) * (i + 1) / iNbDrawings + fMargin);
245
cairo_rel_line_to (pCairoContext, fWidth - 2*fMargin, 0.);
246
cairo_stroke (pCairoContext);
250
cairo_destroy (pCairoContext);
251
return pBackgroundSurface;
253
static cairo_pattern_t *_cairo_dock_create_graph_pattern (CairoDockGraph *pGraph, gdouble *fLowColor, gdouble *fHighColor, double fOffsetY)
255
cairo_pattern_t *pGradationPattern = NULL;
256
if (fLowColor[0] != fHighColor[0] || fLowColor[1] != fHighColor[1] || fLowColor[2] != fHighColor[2]) // un degrade existe.
258
double fMargin = pGraph->fMargin;
259
double fWidth = pGraph->dataRenderer.iWidth - 2*fMargin;
260
double fHeight = pGraph->dataRenderer.iHeight - 2*fMargin;
261
fHeight /= (pGraph->dataRenderer.data.iNbValues / pGraph->dataRenderer.iRank);
263
if (pGraph->iType == CAIRO_DOCK_GRAPH2_CIRCLE || pGraph->iType == CAIRO_DOCK_GRAPH2_CIRCLE_PLAIN)
265
double radius = MIN (fWidth, fHeight)/2;
266
pGradationPattern = cairo_pattern_create_radial (fWidth/2,
267
fMargin + radius + fOffsetY,
270
fMargin + radius + fOffsetY,
274
pGradationPattern = cairo_pattern_create_linear (0.,
275
fMargin + fHeight + fOffsetY,
278
g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, NULL);
280
cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_PAD);
281
cairo_pattern_add_color_stop_rgba (pGradationPattern,
287
cairo_pattern_add_color_stop_rgba (pGradationPattern,
294
return pGradationPattern;
296
static void cairo_dock_load_graph (CairoDockGraph *pGraph, cairo_t *pSourceContext, CairoContainer *pContainer, CairoGraphAttribute *pAttribute)
298
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
299
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
301
int iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
302
if (iWidth == 0 || iHeight == 0)
305
pGraph->iType = pAttribute->iType;
306
pGraph->bMixGraphs = pAttribute->bMixGraphs;
307
pGraph->dataRenderer.iRank = (pAttribute->bMixGraphs ? pData->iNbValues : 1);
309
pGraph->fHighColor = g_new0 (double, 3 * pData->iNbValues);
310
if (pAttribute->fHighColor != NULL)
311
memcpy (pGraph->fHighColor, pAttribute->fHighColor, 3 * pData->iNbValues * sizeof (double));
312
pGraph->fLowColor = g_new0 (double, 3 * pData->iNbValues);
313
if (pAttribute->fLowColor != NULL)
314
memcpy (pGraph->fLowColor, pAttribute->fLowColor, 3 * pData->iNbValues * sizeof (double));
317
pGraph->pGradationPatterns = g_new (cairo_pattern_t *, pData->iNbValues);
318
for (i = 0; i < pData->iNbValues; i ++)
320
pGraph->pGradationPatterns[i] = _cairo_dock_create_graph_pattern (pGraph,
321
&pGraph->fLowColor[3*i],
322
&pGraph->fHighColor[3*i],
326
pGraph->iRadius = pAttribute->iRadius;
327
pGraph->fMargin = pGraph->iRadius * (1. - sqrt(2)/2);
328
if (pAttribute->fBackGroundColor != NULL)
329
memcpy (pGraph->fBackGroundColor, pAttribute->fBackGroundColor, 4 * sizeof (double));
330
pGraph->pBackgroundSurface = _cairo_dock_create_graph_background (pSourceContext,
335
pGraph->fBackGroundColor,
337
pData->iNbValues / pRenderer->iRank);
339
pGraph->iBackgroundTexture = cairo_dock_create_texture_from_surface (pGraph->pBackgroundSurface);
343
static void cairo_dock_reload_graph (CairoDockGraph *pGraph, cairo_t *pSourceContext)
345
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
346
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
347
int iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
348
if (pGraph->pBackgroundSurface != NULL)
349
cairo_surface_destroy (pGraph->pBackgroundSurface);
350
pGraph->pBackgroundSurface = _cairo_dock_create_graph_background (pSourceContext, iWidth, iHeight, pGraph->iRadius, pGraph->fMargin, pGraph->fBackGroundColor, pGraph->iType, pData->iNbValues / pRenderer->iRank);
351
if (pGraph->iBackgroundTexture != 0)
352
_cairo_dock_delete_texture (pGraph->iBackgroundTexture);
354
pGraph->iBackgroundTexture = cairo_dock_create_texture_from_surface (pGraph->pBackgroundSurface);
356
pGraph->iBackgroundTexture = 0;
358
for (i = 0; i < pGraph->dataRenderer.data.iNbValues; i ++)
360
if (pGraph->pGradationPatterns[i] != NULL)
361
cairo_pattern_destroy (pGraph->pGradationPatterns[i]);
362
pGraph->pGradationPatterns[i] = _cairo_dock_create_graph_pattern (pGraph, &pGraph->fLowColor[3*i], &pGraph->fHighColor[3*i], 0.);
367
static void cairo_dock_free_graph (CairoDockGraph *pGraph)
372
if (pGraph->pBackgroundSurface != NULL)
373
cairo_surface_destroy (pGraph->pBackgroundSurface);
374
if (pGraph->iBackgroundTexture != 0)
375
_cairo_dock_delete_texture (pGraph->iBackgroundTexture);
377
for (i = 0; i < pGraph->dataRenderer.data.iNbValues; i ++)
379
if (pGraph->pGradationPatterns[i] != NULL)
380
cairo_pattern_destroy (pGraph->pGradationPatterns[i]);
383
g_free (pGraph->pGradationPatterns);
384
g_free (pGraph->fHighColor);
385
g_free (pGraph->fLowColor);
391
//////////////////////////////////////////
392
/////////////// RENDERER /////////////////
393
//////////////////////////////////////////
394
CairoDockGraph *cairo_dock_new_graph (void)
396
CairoDockGraph *pGraph = g_new0 (CairoDockGraph, 1);
397
pGraph->dataRenderer.interface.new = (CairoDataRendererNewFunc) cairo_dock_new_graph;
398
pGraph->dataRenderer.interface.load = (CairoDataRendererLoadFunc) cairo_dock_load_graph;
399
pGraph->dataRenderer.interface.render = (CairoDataRendererRenderFunc) cairo_dock_render_graph;
400
pGraph->dataRenderer.interface.render_opengl = (CairoDataRendererRenderOpenGLFunc) NULL;
401
pGraph->dataRenderer.interface.reload = (CairoDataRendererReloadFunc) cairo_dock_reload_graph;
402
pGraph->dataRenderer.interface.free = (CairoDataRendererFreeFunc) cairo_dock_free_graph;