~cairo-dock-team/ubuntu/oneiric/cairo-dock/2.3.0-3

« back to all changes in this revision

Viewing changes to src/cairo-dock-graph.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Baerts (matttbe)
  • Date: 2010-08-09 23:26:12 UTC
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: james.westby@ubuntu.com-20100809232612-pocdxliaxjdetm37
Tags: upstream-2.2.0~0beta4
ImportĀ upstreamĀ versionĀ 2.2.0~0beta4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
* This file is a part of the Cairo-Dock project
3
 
*
4
 
* Copyright : (C) see the 'copyright' file.
5
 
* E-mail    : see the 'copyright' file.
6
 
*
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.
11
 
*
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/>.
18
 
*/
19
 
 
20
 
#include <string.h>
21
 
#include <stdlib.h>
22
 
#include <math.h>
23
 
 
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"
35
 
 
36
 
extern gboolean g_bUseOpenGL;
37
 
 
38
 
 
39
 
void cairo_dock_render_graph (CairoDockGraph *pGraph, cairo_t *pCairoContext)
40
 
{
41
 
        g_return_if_fail (pGraph != NULL && pCairoContext != NULL);
42
 
        g_return_if_fail (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS);
43
 
        
44
 
        CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
45
 
        CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
46
 
        
47
 
        if (pGraph->pBackgroundSurface != NULL)
48
 
        {
49
 
                cairo_set_source_surface (pCairoContext, pGraph->pBackgroundSurface, 0., 0.);
50
 
                cairo_paint (pCairoContext);
51
 
        }
52
 
        
53
 
        int iNbDrawings = pData->iNbValues / pRenderer->iRank;
54
 
        if (iNbDrawings == 0)
55
 
                return;
56
 
        
57
 
        double fMargin = pGraph->fMargin;
58
 
        double fWidth = pRenderer->iWidth - 2*fMargin;
59
 
        double fHeight = pRenderer->iHeight - 2*fMargin;
60
 
        fHeight /= iNbDrawings;
61
 
 
62
 
        double fValue;
63
 
        cairo_pattern_t *pGradationPattern;
64
 
        int i;
65
 
        for (i = 0; i < pData->iNbValues; i ++)
66
 
        {
67
 
                if (! pGraph->bMixGraphs)
68
 
                        cairo_translate (pCairoContext,
69
 
                                0.,
70
 
                                i * fHeight);
71
 
                pGradationPattern = pGraph->pGradationPatterns[i];
72
 
                if (pGradationPattern != NULL)
73
 
                        cairo_set_source (pCairoContext, pGradationPattern);
74
 
                else
75
 
                        cairo_set_source_rgb (pCairoContext,
76
 
                                pGraph->fLowColor[3*i+0],
77
 
                                pGraph->fLowColor[3*i+1],
78
 
                                pGraph->fLowColor[3*i+2]);
79
 
                
80
 
                if (pGraph->iType == CAIRO_DOCK_GRAPH2_LINE || pGraph->iType == CAIRO_DOCK_GRAPH2_PLAIN)
81
 
                {
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 ++)
88
 
                        {
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);
93
 
                        }
94
 
                        if (pGraph->iType == CAIRO_DOCK_GRAPH2_PLAIN)
95
 
                        {
96
 
                                cairo_line_to (pCairoContext,
97
 
                                        fMargin,
98
 
                                        fMargin + fHeight);
99
 
                                cairo_line_to (pCairoContext,
100
 
                                        fMargin + fWidth,
101
 
                                        fMargin + fHeight);
102
 
                                cairo_close_path (pCairoContext);
103
 
                                cairo_fill_preserve (pCairoContext);
104
 
                        }
105
 
                        cairo_stroke (pCairoContext);
106
 
                }
107
 
                else if (pGraph->iType == CAIRO_DOCK_GRAPH2_BAR)
108
 
                {
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 ++)
113
 
                        {
114
 
                                fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
115
 
                                cairo_move_to (pCairoContext,
116
 
                                        fMargin + (n - t) * fWidth / n,
117
 
                                        fMargin + fHeight);
118
 
                                cairo_rel_line_to (pCairoContext,
119
 
                                        0.,
120
 
                                        - fValue * fHeight);
121
 
                                cairo_stroke (pCairoContext);
122
 
                        }
123
 
                }
124
 
                else
125
 
                {
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)));
138
 
                        int t;
139
 
                        for (t = 1; t < pData->iMemorySize; t ++)
140
 
                        {
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)));
150
 
                        }
151
 
                        if (pGraph->iType == CAIRO_DOCK_GRAPH2_CIRCLE_PLAIN)
152
 
                        {
153
 
                                cairo_close_path (pCairoContext);
154
 
                                cairo_fill_preserve (pCairoContext);
155
 
                        }
156
 
                        cairo_stroke (pCairoContext);
157
 
                }
158
 
        }
159
 
}
160
 
 
161
 
 
162
 
static void cairo_dock_render_graph_opengl (CairoDockGraph *pGraph)
163
 
{
164
 
        g_return_if_fail (pGraph != NULL);
165
 
        
166
 
        CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
167
 
        CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
168
 
        
169
 
        if (pGraph->iBackgroundTexture != 0)
170
 
        {
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 ();
176
 
        }
177
 
        
178
 
        
179
 
}
180
 
 
181
 
 
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)
183
 
{
184
 
        // on cree la surface.
185
 
        cairo_surface_t *pBackgroundSurface = cairo_surface_create_similar (cairo_get_target (pSourceContext),
186
 
                CAIRO_CONTENT_COLOR_ALPHA,
187
 
                fWidth,
188
 
                fHeight);
189
 
        cairo_t *pCairoContext = cairo_create (pBackgroundSurface);
190
 
        
191
 
        // on trace le fond : un rectangle au coin arrondi.
192
 
        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
193
 
        cairo_set_source_rgba (pCairoContext,
194
 
                pBackGroundColor[0],
195
 
                pBackGroundColor[1],
196
 
                pBackGroundColor[2],
197
 
                pBackGroundColor[3]);
198
 
        
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.
208
 
        
209
 
        cairo_rectangle (pCairoContext, fRadius, fRadius, (fWidth - 2*fRadius), (fHeight - 2*fRadius));
210
 
        cairo_fill (pCairoContext);  // puis on rempli l'interieur.
211
 
        
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)
220
 
        {
221
 
                double r = .5 * MIN (fWidth - 2*fMargin, (fHeight - 2*fMargin) / iNbDrawings);
222
 
                int i;
223
 
                for (i = 0; i < iNbDrawings; i ++)
224
 
                {
225
 
                        cairo_arc (pCairoContext,
226
 
                                fWidth/2,
227
 
                                fMargin + r * (2 * i + 1),
228
 
                                r,
229
 
                                0.,
230
 
                                360.);
231
 
                        cairo_move_to (pCairoContext, fWidth/2, fMargin + r * (2 * i + 1));
232
 
                        cairo_rel_line_to (pCairoContext, r, 0.);
233
 
                        cairo_stroke (pCairoContext);
234
 
                }
235
 
        }
236
 
        else
237
 
        {
238
 
                cairo_move_to (pCairoContext, fMargin, fMargin);
239
 
                cairo_rel_line_to (pCairoContext, 0., fHeight - 2*fMargin);
240
 
                cairo_stroke (pCairoContext);
241
 
                int i;
242
 
                for (i = 0; i < iNbDrawings; i ++)
243
 
                {
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);
247
 
                }
248
 
        }
249
 
        
250
 
        cairo_destroy (pCairoContext);
251
 
        return  pBackgroundSurface;
252
 
}
253
 
static cairo_pattern_t *_cairo_dock_create_graph_pattern (CairoDockGraph *pGraph, gdouble *fLowColor, gdouble *fHighColor, double fOffsetY)
254
 
{
255
 
        cairo_pattern_t *pGradationPattern = NULL;
256
 
        if (fLowColor[0] != fHighColor[0] || fLowColor[1] != fHighColor[1] || fLowColor[2] != fHighColor[2])  // un degrade existe.
257
 
        {
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);
262
 
                
263
 
                if (pGraph->iType == CAIRO_DOCK_GRAPH2_CIRCLE || pGraph->iType == CAIRO_DOCK_GRAPH2_CIRCLE_PLAIN)
264
 
                {
265
 
                        double radius = MIN (fWidth, fHeight)/2;
266
 
                        pGradationPattern = cairo_pattern_create_radial (fWidth/2,
267
 
                                fMargin + radius + fOffsetY,
268
 
                                0.,
269
 
                                fWidth/2,
270
 
                                fMargin + radius + fOffsetY,
271
 
                                radius);
272
 
                }
273
 
                else
274
 
                        pGradationPattern = cairo_pattern_create_linear (0.,
275
 
                                fMargin + fHeight + fOffsetY,
276
 
                                0.,
277
 
                                fMargin + fOffsetY);
278
 
                g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, NULL);  
279
 
                
280
 
                cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_PAD);
281
 
                cairo_pattern_add_color_stop_rgba (pGradationPattern,
282
 
                        0.,
283
 
                        fLowColor[0],
284
 
                        fLowColor[1],
285
 
                        fLowColor[2],
286
 
                        1.);
287
 
                cairo_pattern_add_color_stop_rgba (pGradationPattern,
288
 
                        1.,
289
 
                        fHighColor[0],
290
 
                        fHighColor[1],
291
 
                        fHighColor[2],
292
 
                        1.);
293
 
        }
294
 
        return pGradationPattern;
295
 
}
296
 
static void cairo_dock_load_graph (CairoDockGraph *pGraph, cairo_t *pSourceContext, CairoContainer *pContainer, CairoGraphAttribute *pAttribute)
297
 
{
298
 
        CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
299
 
        CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
300
 
        
301
 
        int iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
302
 
        if (iWidth == 0 || iHeight == 0)
303
 
                return ;
304
 
        
305
 
        pGraph->iType = pAttribute->iType;
306
 
        pGraph->bMixGraphs = pAttribute->bMixGraphs;
307
 
        pGraph->dataRenderer.iRank = (pAttribute->bMixGraphs ? pData->iNbValues : 1);
308
 
        
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));
315
 
 
316
 
        int i;
317
 
        pGraph->pGradationPatterns = g_new (cairo_pattern_t *, pData->iNbValues);
318
 
        for (i = 0; i < pData->iNbValues; i ++)
319
 
        {
320
 
                pGraph->pGradationPatterns[i] = _cairo_dock_create_graph_pattern (pGraph,
321
 
                        &pGraph->fLowColor[3*i],
322
 
                        &pGraph->fHighColor[3*i],
323
 
                        0.);
324
 
        }
325
 
        
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,
331
 
                iWidth,
332
 
                iHeight,
333
 
                pGraph->iRadius,
334
 
                pGraph->fMargin,
335
 
                pGraph->fBackGroundColor,
336
 
                pGraph->iType,
337
 
                pData->iNbValues / pRenderer->iRank);
338
 
        if (g_bUseOpenGL)
339
 
                pGraph->iBackgroundTexture = cairo_dock_create_texture_from_surface (pGraph->pBackgroundSurface);
340
 
}
341
 
 
342
 
 
343
 
static void cairo_dock_reload_graph (CairoDockGraph *pGraph, cairo_t *pSourceContext)
344
 
{
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);
353
 
        if (g_bUseOpenGL)
354
 
                pGraph->iBackgroundTexture = cairo_dock_create_texture_from_surface (pGraph->pBackgroundSurface);
355
 
        else
356
 
                pGraph->iBackgroundTexture = 0;
357
 
        int i;
358
 
        for (i = 0; i < pGraph->dataRenderer.data.iNbValues; i ++)
359
 
        {
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.);
363
 
        }
364
 
}
365
 
 
366
 
 
367
 
static void cairo_dock_free_graph (CairoDockGraph *pGraph)
368
 
{
369
 
        cd_debug ("");
370
 
        if (pGraph == NULL)
371
 
                return ;
372
 
        if (pGraph->pBackgroundSurface != NULL)
373
 
                cairo_surface_destroy (pGraph->pBackgroundSurface);
374
 
        if (pGraph->iBackgroundTexture != 0)
375
 
                _cairo_dock_delete_texture (pGraph->iBackgroundTexture);
376
 
        int i;
377
 
        for (i = 0; i < pGraph->dataRenderer.data.iNbValues; i ++)
378
 
        {
379
 
                if (pGraph->pGradationPatterns[i] != NULL)
380
 
                        cairo_pattern_destroy (pGraph->pGradationPatterns[i]);
381
 
        }
382
 
        
383
 
        g_free (pGraph->pGradationPatterns);
384
 
        g_free (pGraph->fHighColor);
385
 
        g_free (pGraph->fLowColor);
386
 
        g_free (pGraph);
387
 
}
388
 
 
389
 
 
390
 
 
391
 
  //////////////////////////////////////////
392
 
 /////////////// RENDERER /////////////////
393
 
//////////////////////////////////////////
394
 
CairoDockGraph *cairo_dock_new_graph (void)
395
 
{
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;
403
 
        return pGraph;
404
 
}