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 <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23
24 #include "gldi-config.h"
25 #include "cairo-dock-log.h"
26 #include "cairo-dock-backends-manager.h"
27 #include "cairo-dock-draw-opengl.h"
28 #include "cairo-dock-opengl-font.h"
29 #include "cairo-dock-animations.h"
30 #include "cairo-dock-desklet-manager.h" // CAIRO_CONTAINER_IS_OPENGL
31 #include "cairo-dock-dock-manager.h" // CAIRO_CONTAINER_IS_OPENGL
32 #include "cairo-dock-surface-factory.h"
33 #include "cairo-dock-draw.h"
34 #include "cairo-dock-container.h"
35 #include "cairo-dock-icon-factory.h"
36 #include "cairo-dock-icon-facility.h"
37 #include "cairo-dock-icon-manager.h" // myIconsParam, NOTIFICATION_UPDATE_ICON_SLOW
38 #include "cairo-dock-image-buffer.h"
39 #include "cairo-dock-keyfile-utilities.h"
40 #include "cairo-dock-packages.h"
41 #include "cairo-dock-overlay.h"
42 #include "cairo-dock-gauge.h"
43 #include "cairo-dock-graph.h"
44 #include "cairo-dock-progressbar.h"
45 #include "cairo-dock-data-renderer.h"
46
47 extern gboolean g_bUseOpenGL;
48
49 #define cairo_dock_set_data_renderer_on_icon(pIcon, pRenderer) (pIcon)->pDataRenderer = pRenderer
50 #define CD_MIN_TEXT_WITH 24
51
_cairo_dock_init_data_renderer(CairoDataRenderer * pRenderer,CairoDataRendererAttribute * pAttribute)52 static void _cairo_dock_init_data_renderer (CairoDataRenderer *pRenderer, CairoDataRendererAttribute *pAttribute)
53 {
54 //\_______________ On alloue la structure des donnees.
55 pRenderer->data.iNbValues = MAX (1, pAttribute->iNbValues);
56 pRenderer->data.iMemorySize = MAX (2, pAttribute->iMemorySize); // au moins la derniere valeur et la nouvelle.
57 pRenderer->data.pValuesBuffer = g_new0 (gdouble, pRenderer->data.iNbValues * pRenderer->data.iMemorySize);
58 pRenderer->data.pTabValues = g_new (gdouble *, pRenderer->data.iMemorySize);
59 int i;
60 for (i = 0; i < pRenderer->data.iMemorySize; i ++)
61 {
62 pRenderer->data.pTabValues[i] = &pRenderer->data.pValuesBuffer[i*pRenderer->data.iNbValues];
63 }
64 pRenderer->data.iCurrentIndex = -1;
65 pRenderer->data.pMinMaxValues = g_new (gdouble, 2 * pRenderer->data.iNbValues);
66 if (pAttribute->pMinMaxValues != NULL)
67 {
68 memcpy (pRenderer->data.pMinMaxValues, pAttribute->pMinMaxValues, 2 * pRenderer->data.iNbValues * sizeof (gdouble));
69 }
70 else
71 {
72 if (pAttribute->bUpdateMinMax)
73 {
74 for (i = 0; i < pRenderer->data.iNbValues; i ++)
75 {
76 pRenderer->data.pMinMaxValues[2*i] = 1.e6;
77 pRenderer->data.pMinMaxValues[2*i+1] = -1.e6;
78 }
79 }
80 else
81 {
82 for (i = 0; i < pRenderer->data.iNbValues; i ++)
83 {
84 pRenderer->data.pMinMaxValues[2*i] = 0.;
85 pRenderer->data.pMinMaxValues[2*i+1] = 1.;
86 }
87 }
88 }
89
90 if (pAttribute->cEmblems != NULL)
91 {
92 pRenderer->pEmblems = g_new0 (CairoDataRendererEmblem, pRenderer->data.iNbValues);
93 int i;
94 for (i = 0; i < pRenderer->data.iNbValues; i ++)
95 {
96 pRenderer->pEmblems[i].cImagePath = g_strdup (pAttribute->cEmblems[i]);
97 pRenderer->pEmblems[i].param.fAlpha = 1.;
98 }
99 }
100 if (pAttribute->cLabels != NULL)
101 {
102 pRenderer->pLabels = g_new0 (CairoDataRendererText, pRenderer->data.iNbValues);
103 int i;
104 for (i = 0; i < pRenderer->data.iNbValues; i ++)
105 {
106 pRenderer->pLabels[i].cText = g_strdup (pAttribute->cLabels[i]);
107 pRenderer->pLabels[i].param.pColor[3] = 1.;
108 }
109 }
110 pRenderer->pValuesText = g_new0 (CairoDataRendererTextParam, pRenderer->data.iNbValues);
111
112 //\_______________ On charge les parametres generaux.
113 pRenderer->bUpdateMinMax = pAttribute->bUpdateMinMax;
114 pRenderer->bWriteValues = pAttribute->bWriteValues;
115 pRenderer->iRotateTheme = pAttribute->iRotateTheme;
116 pRenderer->iLatencyTime = pAttribute->iLatencyTime;
117 pRenderer->iSmoothAnimationStep = 0;
118 pRenderer->format_value = pAttribute->format_value;
119 pRenderer->pFormatData = pAttribute->pFormatData;
120 }
121
cairo_data_renderer_get_size(CairoDataRenderer * pRenderer,gint * iWidth,gint * iHeight)122 void cairo_data_renderer_get_size (CairoDataRenderer *pRenderer, gint *iWidth, gint *iHeight)
123 {
124 if (pRenderer->bisRotate)
125 {
126 *iWidth = pRenderer->iHeight;
127 *iHeight = pRenderer->iWidth;
128 }
129 else
130 {
131 *iWidth = pRenderer->iWidth;
132 *iHeight = pRenderer->iHeight;
133 }
134 }
135
136
cairo_dock_render_overlays_to_texture(CairoDataRenderer * pRenderer,int iNumValue)137 void cairo_dock_render_overlays_to_texture (CairoDataRenderer *pRenderer, int iNumValue)
138 {
139 gint iWidth = pRenderer->iWidth, iHeight = pRenderer->iHeight;
140 cairo_data_renderer_get_size (pRenderer, &iWidth, &iHeight);
141 glPushMatrix ();
142 if (pRenderer->bisRotate)
143 glRotatef (90., 0., 0., 1.);
144
145 if (pRenderer->pEmblems != NULL)
146 {
147 _cairo_dock_enable_texture ();
148 _cairo_dock_set_blend_over ();
149
150 CairoDataRendererEmblem *pEmblem;
151 pEmblem = &pRenderer->pEmblems[iNumValue];
152 if (pEmblem->iTexture != 0)
153 {
154 glBindTexture (GL_TEXTURE_2D, pEmblem->iTexture);
155 _cairo_dock_set_alpha (pEmblem->param.fAlpha);
156 _cairo_dock_apply_current_texture_at_size_with_offset (
157 pEmblem->param.fWidth * iWidth,
158 pEmblem->param.fHeight * iHeight,
159 pEmblem->param.fX * iWidth,
160 pEmblem->param.fY * iHeight);
161 }
162 _cairo_dock_disable_texture ();
163 }
164
165 if (pRenderer->pLabels != NULL)
166 {
167 _cairo_dock_enable_texture ();
168 _cairo_dock_set_blend_pbuffer (); // rend mieux pour les textes
169
170 CairoDataRendererText *pLabel;
171 int w, h, dw, dh;
172 pLabel = &pRenderer->pLabels[iNumValue];
173 if (pLabel->iTexture != 0)
174 {
175 double f = MIN (pLabel->param.fWidth * iWidth / pLabel->iTextWidth, pLabel->param.fHeight * iHeight / pLabel->iTextHeight); // on garde le ratio du texte.
176 w = pLabel->iTextWidth * f;
177 h = pLabel->iTextHeight * f;
178 dw = w & 1;
179 dh = h & 1;
180
181 glBindTexture (GL_TEXTURE_2D, pLabel->iTexture);
182 _cairo_dock_set_alpha (pLabel->param.pColor[3]);
183 _cairo_dock_apply_current_texture_at_size_with_offset (
184 w + dw,
185 h + dh,
186 pLabel->param.fX * iWidth,
187 pLabel->param.fY * iHeight);
188 }
189 _cairo_dock_disable_texture ();
190 }
191
192 if (pRenderer->bWriteValues && pRenderer->bCanRenderValueAsText)
193 {
194 CairoDataRendererTextParam *pText;
195 pText = &pRenderer->pValuesText[iNumValue];
196 if (pText->fWidth != 0 && pText->fHeight != 0)
197 {
198 cairo_data_renderer_format_value (pRenderer, iNumValue);
199
200 CairoDockGLFont *pFont = cairo_dock_get_default_data_renderer_font ();
201 glColor3f (pText->pColor[0], pText->pColor[1], pText->pColor[2]);
202 glPushMatrix ();
203
204 int w = pText->fWidth * pRenderer->iWidth;
205 int h = pText->fHeight * pRenderer->iHeight;
206 int dw = w & 1;
207 int dh = h & 1;
208 cairo_dock_draw_gl_text_at_position_in_area ((guchar *) pRenderer->cFormatBuffer,
209 pFont,
210 floor (pText->fX * iWidth) + .5*dw,
211 floor (pText->fY * iHeight) + .5*dh,
212 w,
213 h,
214 TRUE);
215
216 glPopMatrix ();
217 glColor3f (1.0, 1.0, 1.0);
218 }
219 }
220 glPopMatrix ();
221 }
222
223
cairo_dock_render_overlays_to_context(CairoDataRenderer * pRenderer,int iNumValue,cairo_t * pCairoContext)224 void cairo_dock_render_overlays_to_context (CairoDataRenderer *pRenderer, int iNumValue, cairo_t *pCairoContext)
225 {
226 if (pRenderer->pEmblems != NULL)
227 {
228 CairoDataRendererEmblem *pEmblem;
229 pEmblem = &pRenderer->pEmblems[iNumValue];
230 if (pEmblem->pSurface != NULL)
231 {
232 cairo_set_source_surface (pCairoContext,
233 pEmblem->pSurface,
234 (.5 + pEmblem->param.fX - pEmblem->param.fWidth/2) * pRenderer->iWidth,
235 (.5 - pEmblem->param.fY - pEmblem->param.fHeight/2) * pRenderer->iHeight);
236 cairo_paint_with_alpha (pCairoContext, pEmblem->param.fAlpha);
237 }
238 }
239
240 if (pRenderer->pLabels != NULL)
241 {
242 CairoDataRendererText *pLabel;
243 pLabel = &pRenderer->pLabels[iNumValue];
244 if (pLabel->pSurface != NULL)
245 {
246 double f = MIN (pLabel->param.fWidth * pRenderer->iWidth / pLabel->iTextWidth, pLabel->param.fHeight * pRenderer->iHeight / pLabel->iTextHeight); // on garde le ratio du texte.
247 if (pLabel->iTextHeight * f > 7) // sinon illisible
248 {
249 cairo_save (pCairoContext);
250 cairo_scale (pCairoContext,
251 f,
252 f);
253 cairo_set_source_surface (pCairoContext,
254 pLabel->pSurface,
255 .5+floor ((.5 + pLabel->param.fX) * pRenderer->iWidth/f - pLabel->iTextWidth /2),
256 .5+floor ((.5 - pLabel->param.fY) * pRenderer->iHeight/f - pLabel->iTextHeight /2));
257 cairo_paint_with_alpha (pCairoContext, pLabel->param.pColor[3]);
258 cairo_restore (pCairoContext);
259 }
260 }
261 }
262
263 if (pRenderer->bWriteValues && pRenderer->bCanRenderValueAsText)
264 {
265 CairoDataRendererTextParam *pText;
266 pText = &pRenderer->pValuesText[iNumValue];
267 if (pText->fWidth != 0 && pText->fHeight != 0)
268 {
269 cairo_data_renderer_format_value (pRenderer, iNumValue);
270
271 cairo_save (pCairoContext);
272 cairo_set_source_rgb (pCairoContext, pText->pColor[0], pText->pColor[1], pText->pColor[2]);
273
274 PangoLayout *pLayout = pango_cairo_create_layout (pCairoContext);
275 PangoFontDescription *fd = pango_font_description_from_string ("Monospace 12");
276 pango_layout_set_font_description (pLayout, fd);
277
278 PangoRectangle log;
279 pango_layout_set_text (pLayout, pRenderer->cFormatBuffer, -1);
280 pango_layout_get_pixel_extents (pLayout, NULL, &log);
281 double fZoom = MIN (pText->fWidth * pRenderer->iWidth / (log.width), pText->fHeight * pRenderer->iHeight / log.height);
282
283 cairo_move_to (pCairoContext,
284 floor ((.5 + pText->fX) * pRenderer->iWidth - log.width*fZoom/2),
285 floor ((.5 - pText->fY) * pRenderer->iHeight - log.height*fZoom/2));
286 cairo_scale (pCairoContext,
287 fZoom,
288 fZoom);
289 pango_cairo_show_layout (pCairoContext, pLayout);
290 g_object_unref (pLayout);
291 cairo_restore (pCairoContext);
292 }
293 }
294 }
295
296
_cairo_dock_render_to_context(CairoDataRenderer * pRenderer,Icon * pIcon,GldiContainer * pContainer,cairo_t * pCairoContext)297 static void _cairo_dock_render_to_context (CairoDataRenderer *pRenderer, Icon *pIcon, GldiContainer *pContainer, cairo_t *pCairoContext)
298 {
299 cairo_t *ctx = NULL;
300 if (pRenderer->bUseOverlay && pRenderer->pOverlay != NULL)
301 {
302 CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
303 if (! pData->bHasValue) // if no value has been set yet, it's better to not draw anything, since the icon already has an image (we draw on an overlay).
304 return;
305 ctx = cairo_dock_begin_draw_image_buffer_cairo (&pRenderer->pOverlay->image, 0, NULL);
306 pCairoContext = ctx;
307 }
308 else
309 {
310 ctx = cairo_dock_begin_draw_icon_cairo (pIcon, 0, pCairoContext);
311 pCairoContext = ctx;
312 }
313 g_return_if_fail (pCairoContext != NULL);
314
315 //\________________ On dessine.
316 cairo_save (pCairoContext);
317 if ((pRenderer->iRotateTheme == CD_RENDERER_ROTATE_WITH_CONTAINER && pContainer->bIsHorizontal == CAIRO_DOCK_VERTICAL) || pRenderer->iRotateTheme == CD_RENDERER_ROTATE_YES)
318 {
319 //cairo_translate (pCairoContext, pRenderer->iWidth/2, pRenderer->iHeight/2);
320 cairo_rotate (pCairoContext, G_PI/2);
321 pRenderer->bisRotate = TRUE;
322 //cairo_translate (pCairoContext, -pRenderer->iHeight/2, -pRenderer->iWidth/2);
323 }
324
325 //cairo_save (pCairoContext);
326 pRenderer->interface.render (pRenderer, pCairoContext);
327 //cairo_restore (pCairoContext);
328
329 //\________________ On dessine les overlays.
330 /**int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
331 int i;
332 for (i = 0; i < iNbValues; i ++)
333 {
334 cairo_dock_render_overlays_to_context (pRenderer, i, pCairoContext);
335 }*/
336 cairo_restore (pCairoContext);
337
338 if (pRenderer->bUseOverlay && pRenderer->pOverlay != NULL)
339 cairo_dock_end_draw_image_buffer_cairo (&pRenderer->pOverlay->image);
340 else
341 cairo_dock_end_draw_image_buffer_cairo (&pIcon->image);
342 /**if (CAIRO_DOCK_CONTAINER_IS_OPENGL (pContainer))
343 {
344 if (pRenderer->bUseOverlay)
345 pRenderer->pOverlay->image.iTexture = cairo_dock_create_texture_from_surface (pRenderer->pOverlay->image.pSurface);
346 else
347 cairo_dock_update_icon_texture (pIcon);
348 }*/
349
350 if (ctx != pCairoContext)
351 cairo_destroy (ctx);
352 }
353
_cairo_dock_render_to_texture(CairoDataRenderer * pRenderer,Icon * pIcon,GldiContainer * pContainer)354 static void _cairo_dock_render_to_texture (CairoDataRenderer *pRenderer, Icon *pIcon, GldiContainer *pContainer)
355 {
356 if (pRenderer->bUseOverlay)
357 {
358 CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
359 if (! pData->bHasValue) // if no value has been set yet, it's better to not draw anything, since the icon already has an image (we draw on an overlay).
360 return;
361 if (! cairo_dock_begin_draw_image_buffer_opengl (&pRenderer->pOverlay->image, pContainer, 0))
362 {
363 pIcon->bDamaged = TRUE; // damage the icon so that it (and therefore its dada-renderer) will be redrawn.
364 return ;
365 }
366 }
367 else
368 {
369 if (! cairo_dock_begin_draw_icon (pIcon, 0))
370 return ;
371 }
372
373 //\________________ On dessine.
374 glPushMatrix ();
375 if ((pRenderer->iRotateTheme == CD_RENDERER_ROTATE_WITH_CONTAINER && pContainer->bIsHorizontal == CAIRO_DOCK_VERTICAL) || pRenderer->iRotateTheme == CD_RENDERER_ROTATE_YES)
376 {
377 glRotatef (-90., 0., 0., 1.);
378 pRenderer->bisRotate = TRUE;
379 }
380
381 //glPushMatrix ();
382 pRenderer->interface.render_opengl (pRenderer);
383 //glPopMatrix ();
384
385 //\________________ On dessine les overlays.
386 /**int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
387 int i;
388 for (i = 0; i < iNbValues; i ++)
389 {
390 cairo_dock_render_overlays_to_texture (pRenderer, i);
391 }*/
392 glPopMatrix ();
393
394 if (pRenderer->bUseOverlay)
395 {
396 cairo_dock_end_draw_image_buffer_opengl (&pRenderer->pOverlay->image, pContainer);
397 }
398 else
399 {
400 cairo_dock_end_draw_icon (pIcon);
401 }
402 }
403
_refresh(CairoDataRenderer * pRenderer,Icon * pIcon,GldiContainer * pContainer)404 static inline void _refresh (CairoDataRenderer *pRenderer, Icon *pIcon, GldiContainer *pContainer)
405 {
406 if (CAIRO_DOCK_CONTAINER_IS_OPENGL (pContainer) && pRenderer->interface.render_opengl)
407 {
408 _cairo_dock_render_to_texture (pRenderer, pIcon, pContainer);
409 }
410 else
411 {
412 _cairo_dock_render_to_context (pRenderer, pIcon, pContainer, NULL);
413 }
414 }
415
cairo_dock_update_icon_data_renderer_notification(G_GNUC_UNUSED gpointer pUserData,Icon * pIcon,GldiContainer * pContainer,gboolean * bContinueAnimation)416 static gboolean cairo_dock_update_icon_data_renderer_notification (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon, GldiContainer *pContainer, gboolean *bContinueAnimation)
417 {
418 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
419 if (pRenderer == NULL)
420 return GLDI_NOTIFICATION_LET_PASS;
421
422 if (pRenderer->iSmoothAnimationStep > 0)
423 {
424 pRenderer->iSmoothAnimationStep --;
425 int iDeltaT = cairo_dock_get_slow_animation_delta_t (pContainer);
426 int iNbIterations = pRenderer->iLatencyTime / iDeltaT;
427
428 pRenderer->fLatency = (double) pRenderer->iSmoothAnimationStep / iNbIterations;
429 _cairo_dock_render_to_texture (pRenderer, pIcon, pContainer);
430 cairo_dock_redraw_icon (pIcon);
431
432 if (pRenderer->iSmoothAnimationStep < iNbIterations)
433 *bContinueAnimation = TRUE;
434 }
435
436 return GLDI_NOTIFICATION_LET_PASS;
437 }
438
_cairo_dock_finish_load_data_renderer(CairoDataRenderer * pRenderer,gboolean bLoadTextures,Icon * pIcon)439 static void _cairo_dock_finish_load_data_renderer (CairoDataRenderer *pRenderer, gboolean bLoadTextures, Icon *pIcon)
440 {
441 int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
442 //\___________________ On charge les emblemes si l'implementation les a valides.
443 if (pRenderer->pEmblems != NULL)
444 {
445 CairoDataRendererEmblem *pEmblem;
446 cairo_surface_t *pSurface;
447 int i;
448 for (i = 0; i < iNbValues; i ++)
449 {
450 pEmblem = &pRenderer->pEmblems[i];
451 if (pEmblem->pSurface != NULL)
452 {
453 cairo_surface_destroy (pEmblem->pSurface);
454 pEmblem->pSurface = NULL;
455 }
456 if (pEmblem->iTexture != 0)
457 {
458 _cairo_dock_delete_texture (pEmblem->iTexture);
459 pEmblem->iTexture = 0;
460 }
461 if (pEmblem->param.fWidth != 0 && pEmblem->param.fHeight != 0 && pEmblem->cImagePath != NULL)
462 {
463 pSurface = cairo_dock_create_surface_from_image_simple (pEmblem->cImagePath,
464 pEmblem->param.fWidth * pRenderer->iWidth,
465 pEmblem->param.fHeight * pRenderer->iHeight);
466 if (bLoadTextures)
467 {
468 pEmblem->iTexture = cairo_dock_create_texture_from_surface (pSurface);
469 cairo_surface_destroy (pSurface);
470 }
471 else
472 pEmblem->pSurface = pSurface;
473 }
474 }
475 }
476
477 //\___________________ On charge les labels si l'implementation les a valides.
478 if (pRenderer->pLabels != NULL)
479 {
480 GldiTextDescription textDescription;
481 gldi_text_description_copy (&textDescription, &myIconsParam.quickInfoTextDescription);
482
483 CairoDataRendererText *pLabel;
484 cairo_surface_t *pSurface;
485 int i;
486 for (i = 0; i < iNbValues; i ++)
487 {
488 pLabel = &pRenderer->pLabels[i];
489 if (pLabel->pSurface != NULL)
490 {
491 cairo_surface_destroy (pLabel->pSurface);
492 pLabel->pSurface = NULL;
493 }
494 if (pLabel->iTexture != 0)
495 {
496 _cairo_dock_delete_texture (pLabel->iTexture);
497 pLabel->iTexture = 0;
498 }
499 if (pLabel->param.fWidth != 0 && pLabel->param.fHeight != 0 && pLabel->cText != NULL)
500 {
501 textDescription.bNoDecorations = TRUE;
502 textDescription.bUseDefaultColors = FALSE;
503 textDescription.iMargin = 0;
504 textDescription.bOutlined = TRUE; /// tester avec et sans ...
505 textDescription.fColorStart.rgba.red = pLabel->param.pColor[0];
506 textDescription.fColorStart.rgba.green = pLabel->param.pColor[1];
507 textDescription.fColorStart.rgba.blue = pLabel->param.pColor[2];
508 textDescription.fColorStart.rgba.alpha = 1.;
509 pSurface = cairo_dock_create_surface_from_text (pLabel->cText,
510 &textDescription,
511 &pLabel->iTextWidth, &pLabel->iTextHeight);
512 if (bLoadTextures)
513 {
514 pLabel->iTexture = cairo_dock_create_texture_from_surface (pSurface);
515 cairo_surface_destroy (pSurface);
516 }
517 else
518 pLabel->pSurface = pSurface;
519 }
520 }
521 }
522
523 //\___________________ On regarde si le texte dessine sur l'icone sera suffisamment lisible.
524 if (pRenderer->pValuesText != NULL)
525 {
526 CairoDataRendererTextParam *pText = &pRenderer->pValuesText[0];
527 //g_print ("+++++++pText->fWidth * pRenderer->iWidth : %.2f\n", pText->fWidth * pRenderer->iWidth);
528 pRenderer->bCanRenderValueAsText = (pText->fWidth * pRenderer->iWidth >= CD_MIN_TEXT_WITH);
529 }
530
531 if (pRenderer->bCanRenderValueAsText && pRenderer->bWriteValues)
532 gldi_icon_set_quick_info (pIcon, NULL);
533
534 //\___________________ Build an overlay if the renderer will use some.
535 if (pRenderer->bUseOverlay)
536 {
537 //g_print ("+ overlay %dx%d\n", pRenderer->iWidth, pRenderer->iHeight);
538 cairo_surface_t *pSurface = cairo_dock_create_blank_surface (pRenderer->iWidth, pRenderer->iHeight);
539 pRenderer->pOverlay = cairo_dock_add_overlay_from_surface (pIcon, pSurface, pRenderer->iWidth, pRenderer->iHeight, pRenderer->iOverlayPosition, (gpointer)"data-renderer"); // this string is constant; any previous overlay will be removed.
540 cairo_dock_set_overlay_scale (pRenderer->pOverlay, 0); // keep the original size of the image
541 }
542 }
543
cairo_dock_add_new_data_renderer_on_icon(Icon * pIcon,GldiContainer * pContainer,CairoDataRendererAttribute * pAttribute)544 void cairo_dock_add_new_data_renderer_on_icon (Icon *pIcon, GldiContainer *pContainer, CairoDataRendererAttribute *pAttribute)
545 {
546 //\___________________ if a previous renderer exists, keep its data alive.
547 CairoDataToRenderer *pData = NULL;
548 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
549 //g_print ("%s (%s, %p)\n", __func__, pIcon->cName, pRenderer);
550 if (pRenderer != NULL)
551 {
552 //\_____________ save the current data.
553 pAttribute->iNbValues = MAX (1, pAttribute->iNbValues);
554 if (pRenderer && cairo_data_renderer_get_nb_values (pRenderer) == pAttribute->iNbValues)
555 {
556 pData = g_memdup (&pRenderer->data, sizeof (CairoDataToRenderer));
557 memset (&pRenderer->data, 0, sizeof (CairoDataToRenderer));
558
559 pAttribute->iMemorySize = MAX (2, pAttribute->iMemorySize);
560 if (pData->iMemorySize != pAttribute->iMemorySize) // on redimensionne le tampon des valeurs.
561 {
562 int iOldMemorySize = pData->iMemorySize;
563 pData->iMemorySize = pAttribute->iMemorySize;
564 pData->pValuesBuffer = g_realloc (pData->pValuesBuffer, pData->iMemorySize * pData->iNbValues * sizeof (gdouble));
565 if (pData->iMemorySize > iOldMemorySize)
566 {
567 memset (&pData->pValuesBuffer[iOldMemorySize * pData->iNbValues], 0, (pData->iMemorySize - iOldMemorySize) * pData->iNbValues * sizeof (gdouble));
568 }
569
570 g_free (pData->pTabValues);
571 pData->pTabValues = g_new (gdouble *, pData->iMemorySize);
572 int i;
573 for (i = 0; i < pData->iMemorySize; i ++)
574 {
575 pData->pTabValues[i] = &pData->pValuesBuffer[i*pData->iNbValues];
576 }
577 if (pData->iCurrentIndex >= pData->iMemorySize)
578 pData->iCurrentIndex = pData->iMemorySize - 1;
579 }
580 }
581
582 //\_____________ remove the current data-renderer
583 cairo_dock_remove_data_renderer_on_icon (pIcon);
584 }
585
586 //\___________________ add a new data-renderer.
587 pRenderer = cairo_dock_new_data_renderer (pAttribute->cModelName);
588
589 cairo_dock_set_data_renderer_on_icon (pIcon, pRenderer);
590 if (pRenderer == NULL)
591 return ;
592
593 //\___________________ load it.
594 _cairo_dock_init_data_renderer (pRenderer, pAttribute);
595
596 pRenderer->iWidth = cairo_dock_icon_get_allocated_width (pIcon); // we don't need the icon to be loaded already, its allocated size is enough
597 pRenderer->iHeight = cairo_dock_icon_get_allocated_height (pIcon);
598 ///cairo_dock_get_icon_extent (pIcon, &pRenderer->iWidth, &pRenderer->iHeight);
599
600 gboolean bLoadTextures = FALSE;
601 if (CAIRO_DOCK_CONTAINER_IS_OPENGL (pContainer) && pRenderer->interface.render_opengl)
602 {
603 bLoadTextures = TRUE;
604 gldi_object_register_notification (pIcon,
605 NOTIFICATION_UPDATE_ICON_SLOW,
606 (GldiNotificationFunc) cairo_dock_update_icon_data_renderer_notification,
607 GLDI_RUN_AFTER, NULL); // pour l'affichage fluide.
608 }
609
610 pRenderer->interface.load (pRenderer, pIcon, pAttribute);
611
612 //\___________________ On charge les overlays si l'implementation les a valides.
613 _cairo_dock_finish_load_data_renderer (pRenderer, bLoadTextures, pIcon);
614
615 //\_____________ set back the previous data, if any.
616 if (pData != NULL)
617 {
618 memcpy (&pRenderer->data, pData, sizeof (CairoDataToRenderer));
619 g_free (pData);
620 _refresh (pRenderer, pIcon, pContainer);
621 }
622 }
623
624
_render_delayed(Icon * pIcon)625 static gboolean _render_delayed (Icon *pIcon)
626 {
627 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
628 g_return_val_if_fail (pRenderer != NULL, FALSE);
629
630 GldiContainer *pContainer = pIcon->pContainer;
631 if (pContainer)
632 {
633 cd_debug ("Render delayed: (%s, %dx%d)", pIcon->cName, pContainer->iWidth, pContainer->iHeight);
634 if (pContainer->iWidth == 1 && pContainer->iHeight == 1) // container not yet resized, retry later
635 return TRUE;
636
637 _cairo_dock_render_to_texture (pRenderer, pIcon, pContainer);
638 cairo_dock_redraw_icon (pIcon);
639 }
640
641 pRenderer->iSidRenderIdle = 0;
642 return FALSE;
643 }
cairo_dock_render_new_data_on_icon(Icon * pIcon,GldiContainer * pContainer,cairo_t * pCairoContext,double * pNewValues)644 void cairo_dock_render_new_data_on_icon (Icon *pIcon, GldiContainer *pContainer, cairo_t *pCairoContext, double *pNewValues)
645 {
646 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
647 g_return_if_fail (pRenderer != NULL);
648
649 //\___________________ On met a jour les valeurs du renderer.
650 CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
651 pData->iCurrentIndex ++;
652 if (pData->iCurrentIndex >= pData->iMemorySize)
653 pData->iCurrentIndex -= pData->iMemorySize;
654 double fNewValue;
655 int i;
656 for (i = 0; i < pData->iNbValues; i ++)
657 {
658 fNewValue = pNewValues[i];
659 if (pRenderer->bUpdateMinMax && fNewValue > CAIRO_DATA_RENDERER_UNDEF_VALUE + 1)
660 {
661 if (fNewValue < pData->pMinMaxValues[2*i])
662 pData->pMinMaxValues[2*i] = fNewValue;
663 if (fNewValue > pData->pMinMaxValues[2*i+1])
664 pData->pMinMaxValues[2*i+1] = MAX (fNewValue, pData->pMinMaxValues[2*i]+.1);
665 }
666 pData->pTabValues[pData->iCurrentIndex][i] = fNewValue;
667 }
668 pData->bHasValue = TRUE;
669
670 //\___________________ On met a jour le dessin de l'icone.
671 if (CAIRO_DOCK_CONTAINER_IS_OPENGL (pContainer) && pRenderer->interface.render_opengl)
672 {
673 if (pRenderer->iLatencyTime > 0 && pData->bHasValue)
674 {
675 int iDeltaT = cairo_dock_get_slow_animation_delta_t (pContainer);
676 int iNbIterations = MAX (1, pRenderer->iLatencyTime / iDeltaT);
677 pRenderer->iSmoothAnimationStep = iNbIterations;
678 cairo_dock_launch_animation (pContainer);
679 }
680 else
681 {
682 pRenderer->fLatency = 0;
683 if (pContainer->iWidth == 1 && pContainer->iHeight == 1 && gldi_container_is_visible (pContainer)) // container not yet resized, delay the rendering (OpenGL only).
684 {
685 if (pRenderer->iSidRenderIdle == 0)
686 pRenderer->iSidRenderIdle = g_timeout_add (250, (GSourceFunc)_render_delayed, pIcon); // if pIcon is freed, the data-renderer will be freed too, so this signal will vanish. avoid using 'g_idle_add', it is heavy on CPU; a 250ms delay won't be noticeable.
687 }
688 else
689 {
690 _cairo_dock_render_to_texture (pRenderer, pIcon, pContainer);
691 }
692 }
693 }
694 else
695 {
696 _cairo_dock_render_to_context (pRenderer, pIcon, pContainer, pCairoContext);
697 }
698
699 //\___________________ On met a jour l'info rapide si le renderer n'a pu ecrire les valeurs.
700 if (! pRenderer->bCanRenderValueAsText && pRenderer->bWriteValues) // on prend en charge l'ecriture des valeurs.
701 {
702 gchar *cBuffer = g_new0 (gchar, pData->iNbValues * (CAIRO_DOCK_DATA_FORMAT_MAX_LEN+1));
703 char *str = cBuffer;
704 for (i = 0; i < pData->iNbValues; i ++)
705 {
706 cairo_data_renderer_format_value_full (pRenderer, i, str);
707
708 if (i+1 < pData->iNbValues)
709 {
710 while (*str != '\0')
711 str ++;
712 *str = '\n';
713 str ++;
714 }
715 }
716 gldi_icon_set_quick_info (pIcon, cBuffer);
717 g_free (cBuffer);
718 }
719
720 cairo_dock_redraw_icon (pIcon);
721 }
722
723
724
cairo_dock_free_data_renderer(CairoDataRenderer * pRenderer)725 void cairo_dock_free_data_renderer (CairoDataRenderer *pRenderer)
726 {
727 if (pRenderer == NULL)
728 return ;
729
730 if (pRenderer->iSidRenderIdle != 0)
731 g_source_remove (pRenderer->iSidRenderIdle);
732
733 if (pRenderer->interface.unload)
734 pRenderer->interface.unload (pRenderer);
735
736 g_free (pRenderer->data.pValuesBuffer);
737 g_free (pRenderer->data.pTabValues);
738 g_free (pRenderer->data.pMinMaxValues);
739
740 int iNbValues = cairo_data_renderer_get_nb_values (pRenderer);
741 if (pRenderer->pEmblems != NULL)
742 {
743 CairoDataRendererEmblem *pEmblem;
744 int i;
745 for (i = 0; i < iNbValues; i ++)
746 {
747 pEmblem = &pRenderer->pEmblems[i];
748 if (pEmblem->pSurface != NULL)
749 cairo_surface_destroy (pEmblem->pSurface);
750 if (pEmblem->iTexture != 0)
751 _cairo_dock_delete_texture (pEmblem->iTexture);
752 }
753 g_free (pRenderer->pEmblems);
754 }
755
756 if (pRenderer->pLabels != NULL)
757 {
758 CairoDataRendererText *pText;
759 int i;
760 for (i = 0; i < iNbValues; i ++)
761 {
762 pText = &pRenderer->pLabels[i];
763 if (pText->pSurface != NULL)
764 cairo_surface_destroy (pText->pSurface);
765 if (pText->iTexture != 0)
766 _cairo_dock_delete_texture (pText->iTexture);
767 }
768 g_free (pRenderer->pLabels);
769 }
770
771 g_free (pRenderer->pValuesText);
772
773 gldi_object_unref (GLDI_OBJECT(pRenderer->pOverlay));
774
775 g_free (pRenderer);
776 }
777
cairo_dock_remove_data_renderer_on_icon(Icon * pIcon)778 void cairo_dock_remove_data_renderer_on_icon (Icon *pIcon)
779 {
780 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
781 if (pRenderer != NULL)
782 {
783 gldi_object_remove_notification (pIcon, NOTIFICATION_UPDATE_ICON_SLOW, (GldiNotificationFunc) cairo_dock_update_icon_data_renderer_notification, NULL);
784
785 if (! pRenderer->bCanRenderValueAsText && pRenderer->bWriteValues)
786 gldi_icon_set_quick_info (pIcon, NULL);
787
788 cairo_dock_free_data_renderer (pRenderer);
789 cairo_dock_set_data_renderer_on_icon (pIcon, NULL);
790 }
791 }
792
793
cairo_dock_reload_data_renderer_on_icon(Icon * pIcon,GldiContainer * pContainer)794 void cairo_dock_reload_data_renderer_on_icon (Icon *pIcon, GldiContainer *pContainer)
795 {
796 cd_debug ("%s (%s)", __func__, pIcon->cName);
797 //\_____________ update the renderer size.
798 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
799 g_return_if_fail (pRenderer != NULL && pRenderer->interface.reload != NULL);
800
801 cairo_dock_get_icon_extent (pIcon, &pRenderer->iWidth, &pRenderer->iHeight);
802
803 //\_____________ reload at the new size.
804 pRenderer->interface.reload (pRenderer);
805
806 gboolean bLoadTextures = (CAIRO_DOCK_CONTAINER_IS_OPENGL (pContainer) && pRenderer->interface.render_opengl);
807 _cairo_dock_finish_load_data_renderer (pRenderer, bLoadTextures, pIcon);
808
809 //\_____________ redraw.
810 _refresh (pRenderer, pIcon, pContainer);
811 }
812
813
cairo_dock_resize_data_renderer_history(Icon * pIcon,int iNewMemorySize)814 void cairo_dock_resize_data_renderer_history (Icon *pIcon, int iNewMemorySize)
815 {
816 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
817 g_return_if_fail (pRenderer != NULL);
818 CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
819
820 iNewMemorySize = MAX (2, iNewMemorySize);
821 //g_print ("iMemorySize : %d -> %d\n", pData->iMemorySize, iNewMemorySize);
822 if (pData->iMemorySize == iNewMemorySize)
823 return ;
824
825 int iOldMemorySize = pData->iMemorySize;
826 pData->iMemorySize = iNewMemorySize;
827 pData->pValuesBuffer = g_realloc (pData->pValuesBuffer, pData->iMemorySize * pData->iNbValues * sizeof (gdouble));
828 if (iNewMemorySize > iOldMemorySize)
829 {
830 memset (&pData->pValuesBuffer[iOldMemorySize * pData->iNbValues], 0, (iNewMemorySize - iOldMemorySize) * pData->iNbValues * sizeof (gdouble));
831 }
832
833 g_free (pData->pTabValues);
834 pData->pTabValues = g_new (gdouble *, pData->iMemorySize);
835 int i;
836 for (i = 0; i < pData->iMemorySize; i ++)
837 {
838 pData->pTabValues[i] = &pData->pValuesBuffer[i*pData->iNbValues];
839 }
840 if (pData->iCurrentIndex >= pData->iMemorySize)
841 pData->iCurrentIndex = pData->iMemorySize - 1;
842 }
843
cairo_dock_refresh_data_renderer(Icon * pIcon,GldiContainer * pContainer)844 void cairo_dock_refresh_data_renderer (Icon *pIcon, GldiContainer *pContainer)
845 {
846 CairoDataRenderer *pRenderer = cairo_dock_get_icon_data_renderer (pIcon);
847 g_return_if_fail (pRenderer != NULL);
848
849 _refresh (pRenderer, pIcon, pContainer);
850 }
851
852
cairo_dock_register_built_in_data_renderers(void)853 void cairo_dock_register_built_in_data_renderers (void) /// merge with init.
854 {
855 cairo_dock_register_data_renderer_graph ();
856 cairo_dock_register_data_renderer_gauge ();
857 cairo_dock_register_data_renderer_progressbar ();
858 }
859