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-backends-manager.h"
28 #include "cairo-dock-draw-opengl.h"
29 #include "cairo-dock-draw.h"
30 #include "cairo-dock-container.h"
31 #include "cairo-dock-icon-manager.h"  // myIconsParam.quickInfoTextDescription
32 #include "cairo-dock-graph.h"
33 
34 typedef struct _Graph {
35 	CairoDataRenderer dataRenderer;
36 	CairoDockTypeGraph iType;
37 	gdouble *fHighColor;  // iNbValues triplets (r,v,b).
38 	gdouble *fLowColor;  // idem.
39 	cairo_pattern_t **pGradationPatterns;  // iNbValues patterns.
40 	gdouble fBackGroundColor[4];
41 	cairo_surface_t *pBackgroundSurface;
42 	GLuint iBackgroundTexture;
43 	gint iMargin;
44 	gboolean bMixGraphs;
45 	} Graph;
46 
47 
48 extern gboolean g_bUseOpenGL;
49 
50 
render(Graph * pGraph,cairo_t * pCairoContext)51 static void render (Graph *pGraph, cairo_t *pCairoContext)
52 {
53 	g_return_if_fail (pGraph != NULL);
54 	g_return_if_fail (pCairoContext != NULL && cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS);
55 
56 	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
57 	CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
58 	int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
59 
60 	if (pGraph->pBackgroundSurface != NULL)
61 	{
62 		cairo_set_source_surface (pCairoContext, pGraph->pBackgroundSurface, 0., 0.);
63 		cairo_paint (pCairoContext);
64 	}
65 
66 	g_return_if_fail (pRenderer->iRank != 0); // workaround: FIXME
67 	int iNbDrawings = iNbValues / pRenderer->iRank;
68 	if (iNbDrawings == 0)
69 		return;
70 
71 	int iMargin = pGraph->iMargin;
72 	int iWidth = pRenderer->iWidth - 2*iMargin;
73 	double fHeight = pRenderer->iHeight - 2*iMargin;
74 	fHeight /= iNbDrawings;
75 
76 	double fValue;
77 	cairo_pattern_t *pGradationPattern;
78 	int t, n = MIN (pData->iMemorySize, iWidth);  // for iteration over the memorized values.
79 	int i, iCurrentGraph, iGraphTop, iGraphBottom, iHeight = 0;
80 	for (i = 0; i < iNbValues; i ++)
81 	{
82 		cairo_save (pCairoContext);
83 		if (pGraph->iType == CAIRO_DOCK_GRAPH_CIRCLE || pGraph->iType == CAIRO_DOCK_GRAPH_CIRCLE_PLAIN)
84 		{
85 			if (! pGraph->bMixGraphs)
86 				cairo_translate (pCairoContext,
87 					0.,
88 					i * fHeight);
89 		}
90 		else
91 		{
92 			iCurrentGraph = pGraph->bMixGraphs ? 0 : i;
93 			iGraphTop = floor (iCurrentGraph * fHeight) + iMargin; // Position of previous graph axis (if any).
94 			iGraphBottom = floor ((iCurrentGraph + 1) * fHeight) + iMargin; // Position of current graph axis
95 			iHeight = iGraphBottom - iGraphTop; // Current graph height.
96 			cairo_translate (pCairoContext,
97 				iMargin,
98 				iGraphTop);
99 		}
100 		pGradationPattern = pGraph->pGradationPatterns[i];
101 		if (pGradationPattern != NULL)
102 			cairo_set_source (pCairoContext, pGradationPattern);
103 		else
104 			cairo_set_source_rgb (pCairoContext,
105 				pGraph->fLowColor[3*i+0],
106 				pGraph->fLowColor[3*i+1],
107 				pGraph->fLowColor[3*i+2]);
108 
109 		switch (pGraph->iType)
110 		{
111 			case CAIRO_DOCK_GRAPH_LINE:
112 			case CAIRO_DOCK_GRAPH_PLAIN:
113 			default :
114 				cairo_set_line_width (pCairoContext, 1);
115 				cairo_set_line_join (pCairoContext, CAIRO_LINE_JOIN_ROUND);
116 				fValue = cairo_data_renderer_get_normalized_current_value (pRenderer, i);
117 				if (fValue <= CAIRO_DATA_RENDERER_UNDEF_VALUE+1)  // undef value -> let's draw 0
118 					fValue = 0;
119 				cairo_move_to (pCairoContext,
120 					iWidth - .5,
121 					(1 - fValue) * (iHeight - 1) + .5) ; // - .5 to align line draw on pixel and + 1 px down because size is reduced
122 				for (t = 1; t < n; t ++)
123 				{
124 					fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
125 					if (fValue <= CAIRO_DATA_RENDERER_UNDEF_VALUE+1)  // undef value -> let's draw 0
126 						fValue = 0;
127 					cairo_line_to (pCairoContext,
128 						iWidth - t - .5,
129 						(1 - fValue) * (iHeight - 1) + .5); // - .5 to align line draw on pixel and + 1 px down because size is reduced
130 				}
131 				if (pGraph->iType == CAIRO_DOCK_GRAPH_PLAIN)
132 				{
133 					cairo_line_to (pCairoContext,
134 						.5, // - .5 to align line draw on pixel and + 1 to align with last value position
135 						iHeight - .5); // - .5 to align next line draw on pixel
136 					cairo_rel_line_to (pCairoContext,
137 						iWidth - 1,
138 						0.);
139 					cairo_close_path (pCairoContext);
140 					cairo_fill_preserve (pCairoContext);
141 				}
142 				cairo_stroke (pCairoContext);
143 			break;
144 
145 			case CAIRO_DOCK_GRAPH_BAR:
146 			{
147 				cairo_set_line_width (pCairoContext, 1);
148 				for (t = 0; t < n; t ++)
149 				{
150 					fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
151 					if (fValue > CAIRO_DATA_RENDERER_UNDEF_VALUE+1)  // undef value -> no draw
152 					{
153 						cairo_move_to (pCairoContext,
154 							iWidth - t - .5, // - .5 to align line draw on pixel
155 							iHeight);
156 						cairo_rel_line_to (pCairoContext,
157 							0.,
158 							- fValue * iHeight);
159 						cairo_stroke (pCairoContext);
160 					}
161 				}
162 			}
163 			break;
164 
165 			case CAIRO_DOCK_GRAPH_CIRCLE:
166 			case CAIRO_DOCK_GRAPH_CIRCLE_PLAIN:
167 				cairo_set_line_width (pCairoContext, 1);
168 				cairo_set_line_join (pCairoContext, CAIRO_LINE_JOIN_ROUND);
169 				fValue = cairo_data_renderer_get_normalized_current_value (pRenderer, i);
170 				if (fValue <= CAIRO_DATA_RENDERER_UNDEF_VALUE+1)  // undef value -> let's draw 0
171 					fValue = 0;
172 				double angle, radius = MIN (iWidth, fHeight)/2;
173 				angle = -2*G_PI*(-.5/pData->iMemorySize);
174 				cairo_move_to (pCairoContext,
175 					iMargin + iWidth/2 + radius * (fValue * cos (angle)),
176 					iMargin + fHeight/2 + radius * (fValue * sin (angle)));
177 				angle = -2*G_PI*(.5/pData->iMemorySize);
178 				cairo_line_to (pCairoContext,
179 					iMargin + iWidth/2 + radius * (fValue * cos (angle)),
180 					iMargin + fHeight/2 + radius * (fValue * sin (angle)));
181 				for (t = 1; t < n; t ++)
182 				{
183 					fValue = cairo_data_renderer_get_normalized_value (pRenderer, i, -t);
184 					if (fValue <= CAIRO_DATA_RENDERER_UNDEF_VALUE+1)  // undef value -> let's draw 0
185 						fValue = 0;
186 					angle = -2*G_PI*((t-.5)/n);
187 					cairo_line_to (pCairoContext,
188 						iMargin + iWidth/2 + radius * (fValue * cos (angle)),
189 						iMargin + fHeight/2 + radius * (fValue * sin (angle)));
190 					angle = -2*G_PI*((t+.5)/n);
191 					cairo_line_to (pCairoContext,
192 						iMargin + iWidth/2 + radius * (fValue * cos (angle)),
193 						iMargin + fHeight/2 + radius * (fValue * sin (angle)));
194 				}
195 				if (pGraph->iType == CAIRO_DOCK_GRAPH_CIRCLE_PLAIN)
196 				{
197 					cairo_close_path (pCairoContext);
198 					cairo_fill_preserve (pCairoContext);
199 				}
200 				cairo_stroke (pCairoContext);
201 			break;
202 		}
203 		cairo_restore (pCairoContext);
204 
205 		cairo_dock_render_overlays_to_context (pRenderer, i, pCairoContext);
206 	}
207 }
208 /* not used
209 static void render_opengl (Graph *pGraph)
210 {
211 	g_return_if_fail (pGraph != NULL);
212 
213 	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
214 
215 	if (pGraph->iBackgroundTexture != 0)
216 	{
217 		_cairo_dock_enable_texture ();
218 		_cairo_dock_set_blend_pbuffer ();  // ceci reste un mystere...
219 		_cairo_dock_set_alpha (1.);
220 		_cairo_dock_apply_texture_at_size_with_alpha (pGraph->iBackgroundTexture, pRenderer->iWidth, pRenderer->iHeight, 1.);
221 		_cairo_dock_disable_texture ();
222 	}
223 
224 	/// to be continued ...
225 }
226 */
227 
_cairo_dock_create_graph_background(double fWidth,double fHeight,int iMargin,gdouble * pBackGroundColor,CairoDockTypeGraph iType,int iNbDrawings)228 static inline cairo_surface_t *_cairo_dock_create_graph_background (double fWidth, double fHeight, int iMargin, gdouble *pBackGroundColor, CairoDockTypeGraph iType, int iNbDrawings)
229 {
230 	// on cree la surface.
231 	cairo_surface_t *pBackgroundSurface = cairo_dock_create_blank_surface (
232 		fWidth,
233 		fHeight);
234 	cairo_t *pCairoContext = cairo_create (pBackgroundSurface);
235 
236 	// on trace le fond : un rectangle au coin arrondi.
237 	cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
238 	cairo_set_source_rgba (pCairoContext,
239 		pBackGroundColor[0],
240 		pBackGroundColor[1],
241 		pBackGroundColor[2],
242 		pBackGroundColor[3]);
243 
244 	// The first argument is the radius ratio factor to change how corners are displayed.
245 	// It can be adjusted between 1 (half radius space unused) to 2 (no radius space reserved).
246 	double fRadius = floor (1.5 * iMargin / (1. - sqrt(2)/2));
247 	cairo_set_line_width (pCairoContext, fRadius);
248 	cairo_set_line_join (pCairoContext, CAIRO_LINE_JOIN_ROUND);
249 	cairo_move_to (pCairoContext, .5*fRadius, .5*fRadius);
250 	cairo_rel_line_to (pCairoContext, fWidth - (fRadius), 0);
251 	cairo_rel_line_to (pCairoContext, 0, fHeight - (fRadius));
252 	cairo_rel_line_to (pCairoContext, -(fWidth - (fRadius)) ,0);
253 	cairo_close_path (pCairoContext);
254 	cairo_stroke (pCairoContext);  // on trace d'abord les contours arrondis.
255 
256 	cairo_rectangle (pCairoContext, fRadius, fRadius, (fWidth - 2*fRadius), (fHeight - 2*fRadius));
257 	cairo_fill (pCairoContext);  // puis on rempli l'interieur.
258 
259 	// on trace les axes.
260 	cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
261 	gldi_color_set_cairo_rgb (pCairoContext,
262 		&myIconsParam.quickInfoTextDescription.fBackgroundColor);  // meme couleur que le fond des info-rapides, mais opaque.
263 	cairo_set_line_width (pCairoContext, 1.);
264 	if (iType == CAIRO_DOCK_GRAPH_CIRCLE || iType == CAIRO_DOCK_GRAPH_CIRCLE_PLAIN)
265 	{
266 		double r = .5 * MIN (fWidth - 2*iMargin, (fHeight - 2*iMargin) / iNbDrawings);
267 		int i;
268 		for (i = 0; i < iNbDrawings; i ++)
269 		{
270 			cairo_arc (pCairoContext,
271 				fWidth/2,
272 				iMargin + r * (2 * i + 1),
273 				r,
274 				0.,
275 				360.);
276 			cairo_move_to (pCairoContext, fWidth/2, iMargin + r * (2 * i + 1));
277 			cairo_rel_line_to (pCairoContext, r, 0.);
278 			cairo_stroke (pCairoContext);
279 		}
280 	}
281 	else
282 	{
283 		// cairo_move_to (pCairoContext, iMargin-.5, iMargin-.5);
284 		// cairo_rel_line_to (pCairoContext, 0., fHeight - 2*iMargin);
285 		// cairo_stroke (pCairoContext);
286 		int i;
287 		for (i = 0; i < iNbDrawings; i ++)
288 		{
289 			cairo_move_to (pCairoContext,
290 				iMargin,
291 				floor ((fHeight - 2 * iMargin) * (i + 1) / iNbDrawings) + iMargin - .5);
292 			cairo_rel_line_to (pCairoContext, fWidth - 2*iMargin, 0.);
293 			cairo_stroke (pCairoContext);
294 		}
295 	}
296 
297 	cairo_destroy (pCairoContext);
298 	return  pBackgroundSurface;
299 }
_cairo_dock_create_graph_pattern(Graph * pGraph,gdouble * fLowColor,gdouble * fHighColor)300 static cairo_pattern_t *_cairo_dock_create_graph_pattern (Graph *pGraph, gdouble *fLowColor, gdouble *fHighColor)
301 {
302 	cairo_pattern_t *pGradationPattern = NULL;
303 	if (fLowColor[0] != fHighColor[0] || fLowColor[1] != fHighColor[1] || fLowColor[2] != fHighColor[2])  // un degrade existe.
304 	{
305 		int iMargin = pGraph->iMargin;
306 		double fWidth = pGraph->dataRenderer.iWidth - 2*iMargin;
307 		double fHeight = pGraph->dataRenderer.iHeight - 2*iMargin;
308 		double fHeightPerValue = fHeight / (pGraph->dataRenderer.data.iNbValues / pGraph->dataRenderer.iRank);
309 
310 		if (pGraph->iType == CAIRO_DOCK_GRAPH_CIRCLE || pGraph->iType == CAIRO_DOCK_GRAPH_CIRCLE_PLAIN)
311 		{
312 			double radius = MIN (fWidth, fHeightPerValue)/2.;
313 			pGradationPattern = cairo_pattern_create_radial (fWidth/2,
314 				iMargin + radius,
315 				0.,
316 				fWidth/2,
317 				iMargin + radius,
318 				radius);
319 		}
320 		else
321 		{
322 			pGradationPattern = cairo_pattern_create_linear (0.,
323 				floor (pGraph->bMixGraphs ? fHeight : fHeightPerValue),
324 				0.,
325 				0.);
326 		}
327 		g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, NULL);
328 
329 		cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_PAD);
330 		cairo_pattern_add_color_stop_rgba (pGradationPattern,
331 			0.,
332 			fLowColor[0],
333 			fLowColor[1],
334 			fLowColor[2],
335 			1.);
336 		cairo_pattern_add_color_stop_rgba (pGradationPattern,
337 			1.,
338 			fHighColor[0],
339 			fHighColor[1],
340 			fHighColor[2],
341 			1.);
342 	}
343 	return pGradationPattern;
344 }
345 #define dc .5
346 #define _guess_color(i) (((pGraph->fLowColor[i] < pGraph->fHighColor[i] && pGraph->fLowColor[i] > dc) || pGraph->fLowColor[i] > 1-dc) ? pGraph->fLowColor[i] - dc : pGraph->fLowColor[i] + dc)
347 //#define _guess_color(i) (1. - pGraph->fLowColor[i])
_set_overlay_zones(Graph * pGraph)348 static void _set_overlay_zones (Graph *pGraph)
349 {
350 	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
351 	int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
352 	int iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
353 	int i;
354 
355 	// on complete le data-renderer.
356 	int iNbDrawings = iNbValues / pRenderer->iRank;
357 	int iMargin = pGraph->iMargin;
358 	double fOneGraphHeight = iHeight - 2*iMargin;
359 	fOneGraphHeight /= iNbDrawings;
360 	double fOneGraphWidth = iWidth - 2*iMargin;
361 	fOneGraphWidth /= iNbDrawings;
362 	int iTextWidth = MIN (48, pRenderer->iWidth/2);  // on definit une taille pour les zones de texte.
363 	int iTextHeight = MIN (16, fOneGraphHeight/1.5);
364 	int iLabelWidth = MIN (48, pRenderer->iWidth/2);  // on definit une taille pour les zones de texte.
365 	int iLabelHeight = MIN (16, fOneGraphHeight/2.);
366 	int h = fOneGraphHeight/8;  // ecart du texte au-dessus de l'axe Ox.
367 	CairoDataRendererTextParam *pValuesText;
368 	CairoDataRendererText *pLabel;
369 	for (i = 0; i < iNbValues; i ++)
370 	{
371 		/// rajouter l'alignement gauche/centre/droit ...
372 		if (pRenderer->pLabels)  // les labels en haut a gauche.
373 		{
374 			pLabel = &pRenderer->pLabels[i];
375 			if (iLabelHeight > 8)  // sinon trop petit, et empiete sur la valeur.
376 			{
377 				if (pGraph->bMixGraphs)
378 				{
379 					pLabel->param.fX = (double)(iMargin + i * fOneGraphWidth + iLabelWidth/2) / iWidth - .5;
380 					pLabel->param.fY = (double)(iHeight - iMargin - iLabelHeight/2) / iHeight - .5;
381 				}
382 				else
383 				{
384 					pLabel->param.fX = (double) (iMargin + iLabelWidth/2) / iWidth - .5;
385 					pLabel->param.fY = .5 - (double)(iMargin + h + i * fOneGraphHeight + iLabelHeight/2) / iHeight;
386 				}
387 				pLabel->param.fWidth = (double)iLabelWidth / iWidth;
388 				pLabel->param.fHeight = (double)iLabelHeight / iHeight;
389 				pLabel->param.pColor[0] = 1.;
390 				pLabel->param.pColor[1] = 1.;
391 				pLabel->param.pColor[2] = 1.;
392 				pLabel->param.pColor[3] = 1.;  // white, a little transparent
393 			}
394 			else
395 			{
396 				pLabel->param.fWidth = pLabel->param.fHeight = 0;
397 			}
398 		}
399 		if (pRenderer->pValuesText)  // les valeurs en bas au milieu.
400 		{
401 			pValuesText = &pRenderer->pValuesText[i];
402 			if (pGraph->bMixGraphs)
403 			{
404 				pValuesText->fX = (double)(iMargin + i * fOneGraphWidth + iTextWidth/2) / iWidth - .5;
405 				pValuesText->fY = (double)(iMargin + h + iTextHeight/2) / iHeight - .5;
406 			}
407 			else
408 			{
409 				pValuesText->fX = (double)0.;  // centered.
410 				pValuesText->fY = .5 - (double)(iMargin + (i+1) * fOneGraphHeight - iTextHeight/2 - h) / iHeight;
411 			}
412 			pValuesText->fWidth = (double)iTextWidth / iWidth;
413 			pValuesText->fHeight = (double)iTextHeight / iHeight;
414 			if (pGraph->fBackGroundColor[3] > .2 && pGraph->fBackGroundColor[3] < .7)
415 			{
416 				pValuesText->pColor[0] = pGraph->fBackGroundColor[0];
417 				pValuesText->pColor[1] = pGraph->fBackGroundColor[1];
418 				pValuesText->pColor[2] = pGraph->fBackGroundColor[2];
419 				//g_print ("bg color: %.2f;%.2f;%.2f\n", pGraph->fBackGroundColor[0], pGraph->fBackGroundColor[1], pGraph->fBackGroundColor[2]);
420 			}
421 			else
422 			{
423 				pValuesText->pColor[0] = _guess_color (0);
424 				pValuesText->pColor[1] = _guess_color (1);
425 				pValuesText->pColor[2] = _guess_color (2);
426 				//g_print ("line color: %.2f;%.2f;%.2f\n", pGraph->fLowColor[0], pGraph->fLowColor[1], pGraph->fLowColor[2]);
427 			}
428 			//g_print ("text color: %.2f;%.2f;%.2f\n", pValuesText->pColor[0], pValuesText->pColor[1], pValuesText->pColor[2]);
429 			pValuesText->pColor[3] = 1.;
430 		}
431 	}
432 }
433 
load(Graph * pGraph,G_GNUC_UNUSED Icon * pIcon,CairoGraphAttribute * pAttribute)434 static void load (Graph *pGraph, G_GNUC_UNUSED Icon *pIcon, CairoGraphAttribute *pAttribute)
435 {
436 	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
437 
438 	int iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
439 	if (iWidth == 0 || iHeight == 0)
440 		return ;
441 
442 	int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
443 	pGraph->iType = pAttribute->iType;
444 	pGraph->bMixGraphs = pAttribute->bMixGraphs;
445 	pRenderer->iRank = (pAttribute->bMixGraphs ? iNbValues : 1);
446 
447 	pGraph->fHighColor = g_new0 (double, 3 * iNbValues);
448 	pGraph->fLowColor = g_new0 (double, 3 * iNbValues);
449 
450 	int i;
451 	pGraph->pGradationPatterns = g_new (cairo_pattern_t *, iNbValues);
452 	for (i = 0; i < iNbValues; i ++)
453 	{
454 		if (pAttribute->fHighColor != NULL)
455 			memcpy (&pGraph->fHighColor[3*i], pAttribute->fHighColor, 3 * sizeof (double));
456 		if (pAttribute->fLowColor != NULL)
457 			memcpy (&pGraph->fLowColor[3*i], pAttribute->fLowColor, 3 * sizeof (double));
458 		pGraph->pGradationPatterns[i] = _cairo_dock_create_graph_pattern (pGraph,
459 			&pGraph->fLowColor[3*i],
460 			&pGraph->fHighColor[3*i]);
461 	}
462 
463 	pGraph->iMargin = floor (MIN (iWidth, iHeight) / 32);
464 
465 	if (pAttribute->fBackGroundColor != NULL)
466 		memcpy (pGraph->fBackGroundColor, pAttribute->fBackGroundColor, 4 * sizeof (double));
467 	pGraph->pBackgroundSurface = _cairo_dock_create_graph_background (
468 		iWidth,
469 		iHeight,
470 		pGraph->iMargin,
471 		pGraph->fBackGroundColor,
472 		pGraph->iType,
473 		iNbValues / pRenderer->iRank);
474 	if (g_bUseOpenGL && 0)
475 		pGraph->iBackgroundTexture = cairo_dock_create_texture_from_surface (pGraph->pBackgroundSurface);
476 
477 	// on complete le data-renderer.
478 	_set_overlay_zones (pGraph);
479 }
480 
481 
reload(Graph * pGraph)482 static void reload (Graph *pGraph)
483 {
484 	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
485 	int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
486 	int iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
487 	pGraph->iMargin = floor (MIN (iWidth, iHeight) / 32);
488 	if (pGraph->pBackgroundSurface != NULL)
489 		cairo_surface_destroy (pGraph->pBackgroundSurface);
490 	pGraph->pBackgroundSurface = _cairo_dock_create_graph_background (iWidth, iHeight, pGraph->iMargin, pGraph->fBackGroundColor, pGraph->iType, iNbValues / pRenderer->iRank);
491 	if (pGraph->iBackgroundTexture != 0)
492 		_cairo_dock_delete_texture (pGraph->iBackgroundTexture);
493 	if (g_bUseOpenGL && 0)
494 		pGraph->iBackgroundTexture = cairo_dock_create_texture_from_surface (pGraph->pBackgroundSurface);
495 	else
496 		pGraph->iBackgroundTexture = 0;
497 	int i;
498 	for (i = 0; i < iNbValues; i ++)
499 	{
500 		if (pGraph->pGradationPatterns[i] != NULL)
501 			cairo_pattern_destroy (pGraph->pGradationPatterns[i]);
502 		pGraph->pGradationPatterns[i] = _cairo_dock_create_graph_pattern (pGraph,
503 			&pGraph->fLowColor[3*i],
504 			&pGraph->fHighColor[3*i]);
505 	}
506 
507 	// on re-complete le data-renderer.
508 	_set_overlay_zones (pGraph);
509 }
510 
511 
unload(Graph * pGraph)512 static void unload (Graph *pGraph)
513 {
514 	cd_debug ("");
515 	if (pGraph->pBackgroundSurface != NULL)
516 		cairo_surface_destroy (pGraph->pBackgroundSurface);
517 	if (pGraph->iBackgroundTexture != 0)
518 		_cairo_dock_delete_texture (pGraph->iBackgroundTexture);
519 
520 	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGraph);
521 	int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
522 	int i;
523 	for (i = 0; i < iNbValues; i ++)
524 	{
525 		if (pGraph->pGradationPatterns[i] != NULL)
526 			cairo_pattern_destroy (pGraph->pGradationPatterns[i]);
527 	}
528 
529 	g_free (pGraph->pGradationPatterns);
530 	g_free (pGraph->fHighColor);
531 	g_free (pGraph->fLowColor);
532 }
533 
534 
535 
536   //////////////////////////////////////////
537  /////////////// RENDERER /////////////////
538 //////////////////////////////////////////
cairo_dock_register_data_renderer_graph(void)539 void cairo_dock_register_data_renderer_graph (void)
540 {
541 	// create a new record
542 	CairoDockDataRendererRecord *pRecord = g_new0 (CairoDockDataRendererRecord, 1);
543 
544 	// fill the properties we need
545 	pRecord->interface.load              = (CairoDataRendererLoadFunc) load;
546 	pRecord->interface.render            = (CairoDataRendererRenderFunc) render;
547 	pRecord->interface.render_opengl     = (CairoDataRendererRenderOpenGLFunc) NULL;
548 	pRecord->interface.reload            = (CairoDataRendererReloadFunc) reload;
549 	pRecord->interface.unload            = (CairoDataRendererUnloadFunc) unload;
550 	pRecord->iStructSize                 = sizeof (Graph);
551 	pRecord->cThemeDirName               = NULL;
552 	pRecord->cDefaultTheme               = NULL;
553 
554 	// register
555 	cairo_dock_register_data_renderer ("graph", pRecord);
556 }
557