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/>.
20
/** Exemple of a gauge with text inside :
23
<name>Screenlets Vista'ish Default</name>
24
<author>(conversion by Nochka85)</author>
26
<file key="background">back.svg</file>
27
<file key="foreground">dialdot.svg</file>
31
<posStart>-130</posStart>
32
<posStop>130</posStop>
33
<file key="needle">dial.svg</file>
34
<offset_x>0</offset_x>
38
<x_center>-0,34</x_center>
39
<y_center>-0,47</y_center>
47
<x_center>-0,32</x_center>
48
<y_center>0,00</y_center>
57
<direction>1</direction>
58
<posStart>-128</posStart>
59
<posStop>128</posStop>
60
<file key="needle">dial2.svg</file>
61
<offset_x>0</offset_x>
65
<x_center>0,50</x_center>
66
<y_center>-0,00</y_center>
74
<x_center>0,50</x_center>
75
<y_center>0,30</y_center>
87
#include <libxml/tree.h>
88
#include <libxml/parser.h>
90
#include "../config.h"
91
#include "cairo-dock-log.h"
92
#include "cairo-dock-draw.h"
93
#include "cairo-dock-draw-opengl.h"
94
#include "cairo-dock-opengl-font.h"
95
#include "cairo-dock-packages.h"
96
#include "cairo-dock-surface-factory.h"
97
#include "cairo-dock-keyfile-utilities.h"
98
#include "cairo-dock-config.h"
99
#include "cairo-dock-backends-manager.h"
100
#include "cairo-dock-gauge.h"
102
#define CAIRO_DOCK_GAUGES_DIR "gauges"
104
extern gchar *g_cExtrasDirPath;
105
extern gboolean g_bUseOpenGL;
106
extern gboolean g_bEasterEggs;
108
////////////////////////////////////////////
109
/////////////// LOAD GAUGE /////////////////
110
////////////////////////////////////////////
111
/*void cairo_dock_xml_open_file (const gchar *filePath, const gchar *mainNodeName,xmlDocPtr *myXmlDoc,xmlNodePtr *myXmlNode)
113
xmlDocPtr doc = xmlParseFile (filePath);
116
cd_warning ("Impossible de lire le fichier XML.");
122
xmlNodePtr node = xmlDocGetRootElement (doc);
123
if (node == NULL || xmlStrcmp (node->name, (const xmlChar *) mainNodeName) != 0)
125
cd_warning ("Le format du fichier XML n'est pas valide.");
135
static double _str2double (gchar *s)
137
gchar *str = strchr (s, ',');
140
return g_ascii_strtod (s, NULL);
143
static void _cairo_dock_init_gauge_image (const gchar *cImagePath, GaugeImage *pGaugeImage)
145
// chargement du fichier.
146
pGaugeImage->pSvgHandle = rsvg_handle_new_from_file (cImagePath, NULL);
147
g_return_if_fail (pGaugeImage->pSvgHandle != NULL);
149
//On rĆ©cupĆØre la taille de l'image.
150
RsvgDimensionData SizeInfo;
151
rsvg_handle_get_dimensions (pGaugeImage->pSvgHandle, &SizeInfo);
152
pGaugeImage->sizeX = SizeInfo.width;
153
pGaugeImage->sizeY = SizeInfo.height;
155
static GaugeImage *_cairo_dock_new_gauge_image (const gchar *cImagePath)
157
GaugeImage *pGaugeImage = g_new0 (GaugeImage, 1);
159
_cairo_dock_init_gauge_image (cImagePath, pGaugeImage);
163
static void _cairo_dock_load_gauge_image (GaugeImage *pGaugeImage, int iWidth, int iHeight)
165
cd_message ("%s (%dx%d)", __func__, iWidth, iHeight);
166
if (pGaugeImage->pSurface != NULL)
167
cairo_surface_destroy (pGaugeImage->pSurface);
168
if (pGaugeImage->iTexture != 0)
169
_cairo_dock_delete_texture (pGaugeImage->iTexture);
171
if (pGaugeImage->pSvgHandle != NULL)
173
pGaugeImage->pSurface = cairo_dock_create_blank_surface (
177
cairo_t* pDrawingContext = cairo_create (pGaugeImage->pSurface);
179
cairo_scale (pDrawingContext,
180
(double) iWidth / (double) pGaugeImage->sizeX,
181
(double) iHeight / (double) pGaugeImage->sizeY);
183
rsvg_handle_render_cairo (pGaugeImage->pSvgHandle, pDrawingContext);
184
cairo_destroy (pDrawingContext);
188
pGaugeImage->iTexture = cairo_dock_create_texture_from_surface (pGaugeImage->pSurface);
193
pGaugeImage->pSurface = NULL;
194
pGaugeImage->iTexture = 0;
197
static void _cairo_dock_load_gauge_needle (GaugeIndicator *pGaugeIndicator, int iWidth, int iHeight)
199
cd_message ("%s (%dx%d)", __func__, iWidth, iHeight);
200
GaugeImage *pGaugeImage = pGaugeIndicator->pImageNeedle;
201
g_return_if_fail (pGaugeImage != NULL);
203
if (pGaugeImage->pSurface != NULL)
204
cairo_surface_destroy (pGaugeImage->pSurface);
205
if (pGaugeImage->iTexture != 0)
206
_cairo_dock_delete_texture (pGaugeImage->iTexture);
208
if (pGaugeImage->pSvgHandle != NULL)
210
int iSize = MIN (iWidth, iHeight);
211
//g_print ("size : applet : %d, image : %d\n", iSize, pGaugeImage->sizeX);
212
pGaugeIndicator->fNeedleScale = (double)iSize / (double) pGaugeImage->sizeX; // car l'aiguille est a l'horizontale dans le fichier svg.
213
pGaugeIndicator->iNeedleWidth = (double) pGaugeIndicator->iNeedleRealWidth * pGaugeIndicator->fNeedleScale;
214
pGaugeIndicator->iNeedleHeight = (double) pGaugeIndicator->iNeedleRealHeight * pGaugeIndicator->fNeedleScale;
215
//g_print (" + needle %dx%d\n", pGaugeIndicator->iNeedleWidth, pGaugeIndicator->iNeedleHeight);
217
cairo_surface_t *pNeedleSurface = cairo_dock_create_blank_surface ( pGaugeIndicator->iNeedleWidth, pGaugeIndicator->iNeedleHeight);
218
g_return_if_fail (cairo_surface_status (pNeedleSurface) == CAIRO_STATUS_SUCCESS);
220
cairo_t* pDrawingContext = cairo_create (pNeedleSurface);
221
g_return_if_fail (cairo_status (pDrawingContext) == CAIRO_STATUS_SUCCESS);
223
cairo_scale (pDrawingContext, pGaugeIndicator->fNeedleScale, pGaugeIndicator->fNeedleScale);
224
cairo_translate (pDrawingContext, pGaugeIndicator->iNeedleOffsetX, pGaugeIndicator->iNeedleOffsetY);
225
rsvg_handle_render_cairo (pGaugeImage->pSvgHandle, pDrawingContext);
226
cairo_destroy (pDrawingContext);
228
pGaugeImage->iTexture = cairo_dock_create_texture_from_surface (pNeedleSurface);
229
cairo_surface_destroy (pNeedleSurface);
233
pGaugeImage->pSurface = NULL;
234
pGaugeImage->iTexture = 0;
237
static gboolean _cairo_dock_load_gauge_theme (Gauge *pGauge, const gchar *cThemePath)
239
cd_debug ("%s (%s)", __func__, cThemePath);
240
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
241
if (iWidth == 0 || iHeight == 0)
243
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
245
g_return_val_if_fail (cThemePath != NULL, FALSE);
247
xmlDocPtr pGaugeTheme;
248
xmlNodePtr pGaugeMainNode;
249
gchar *cXmlFile = g_strdup_printf("%s/theme.xml",cThemePath);
250
//cairo_dock_xml_open_file (cXmlFile, "gauge",&pGaugeTheme,&pGaugeMainNode);
251
pGaugeTheme = cairo_dock_open_xml_file (cXmlFile, "gauge", &pGaugeMainNode, NULL);
253
g_return_val_if_fail (pGaugeTheme != NULL && pGaugeMainNode != NULL, FALSE);
256
xmlChar *cAttribute, *cNodeContent, *cTextNodeContent;
257
GString *sImagePath = g_string_new ("");
258
GaugeImage *pGaugeImage;
259
GaugeIndicator *pGaugeIndicator = NULL;
260
xmlNodePtr pGaugeNode;
262
for (pGaugeNode = pGaugeMainNode->children, i = 0; pGaugeNode != NULL; pGaugeNode = pGaugeNode->next, i ++)
264
if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "name") == 0)
266
pGauge->cThemeName = xmlNodeGetContent(pGaugeNode);
268
else if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "rank") == 0)
270
cNodeContent = xmlNodeGetContent (pGaugeNode);
271
CAIRO_DATA_RENDERER (pGauge)->iRank = atoi (cNodeContent);
272
xmlFree (cNodeContent);
274
else if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "file") == 0)
276
cNodeContent = xmlNodeGetContent (pGaugeNode);
277
g_string_printf (sImagePath, "%s/%s", cThemePath, cNodeContent);
278
ap = xmlHasProp (pGaugeNode, "key");
279
cAttribute = xmlNodeGetContent(ap->children);
280
if (xmlStrcmp (cAttribute, "background") == 0)
282
pGauge->pImageBackground = _cairo_dock_new_gauge_image (sImagePath->str);
283
_cairo_dock_load_gauge_image (pGauge->pImageBackground, iWidth, iHeight);
285
else if (xmlStrcmp (cAttribute, "foreground") == 0)
287
pGauge->pImageForeground = _cairo_dock_new_gauge_image (sImagePath->str);
288
_cairo_dock_load_gauge_image (pGauge->pImageForeground, iWidth, iHeight);
290
xmlFree (cNodeContent);
291
xmlFree (cAttribute);
293
else if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "indicator") == 0)
295
if (CAIRO_DATA_RENDERER (pGauge)->iRank == 0)
297
CAIRO_DATA_RENDERER (pGauge)->iRank = 1;
299
for (node = pGaugeNode->next; node != NULL; node = node->next)
301
if (xmlStrcmp (node->name, (const xmlChar *) "indicator") == 0)
302
CAIRO_DATA_RENDERER (pGauge)->iRank ++;
306
pGaugeIndicator = g_new0 (GaugeIndicator, 1);
307
pGaugeIndicator->direction = 1;
309
cd_debug ("gauge : On charge un indicateur");
310
xmlNodePtr pGaugeSubNode;
311
for (pGaugeSubNode = pGaugeNode->children; pGaugeSubNode != NULL; pGaugeSubNode = pGaugeSubNode->next)
313
if (xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "text") == 0)
315
//g_print ("+ %s\n", pGaugeSubNode->name);
316
cNodeContent = xmlNodeGetContent (pGaugeSubNode);
317
if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posX") == 0)
318
pGaugeIndicator->posX = _str2double (cNodeContent);
319
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posY") == 0)
320
pGaugeIndicator->posY = _str2double (cNodeContent);
321
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "text_zone") == 0)
323
xmlNodePtr pTextSubNode;
324
for (pTextSubNode = pGaugeSubNode->children; pTextSubNode != NULL; pTextSubNode = pTextSubNode->next)
326
cTextNodeContent = xmlNodeGetContent (pTextSubNode);
327
if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "x_center") == 0)
328
pGaugeIndicator->textZone.fX = _str2double (cTextNodeContent);
329
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "y_center") == 0)
330
pGaugeIndicator->textZone.fY = _str2double (cTextNodeContent);
331
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "width") == 0)
332
pGaugeIndicator->textZone.fWidth = _str2double (cTextNodeContent);
333
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "height") == 0)
334
pGaugeIndicator->textZone.fHeight = _str2double (cTextNodeContent);
335
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "red") == 0)
336
pGaugeIndicator->textZone.pColor[0] = _str2double (cTextNodeContent);
337
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "green") == 0)
338
pGaugeIndicator->textZone.pColor[1] = _str2double (cTextNodeContent);
339
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "blue") == 0)
340
pGaugeIndicator->textZone.pColor[2] = _str2double (cTextNodeContent);
343
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "logo_zone") == 0)
345
xmlNodePtr pLogoSubNode;
346
for (pLogoSubNode = pGaugeSubNode->children; pLogoSubNode != NULL; pLogoSubNode = pLogoSubNode->next)
348
cTextNodeContent = xmlNodeGetContent (pLogoSubNode);
349
if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "x_center") == 0)
350
pGaugeIndicator->emblem.fX = _str2double (cTextNodeContent);
351
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "y_center") == 0)
352
pGaugeIndicator->emblem.fY = _str2double (cTextNodeContent);
353
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "width") == 0)
354
pGaugeIndicator->emblem.fWidth = _str2double (cTextNodeContent);
355
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "height") == 0)
356
pGaugeIndicator->emblem.fHeight = _str2double (cTextNodeContent);
357
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "alpha") == 0)
358
pGaugeIndicator->emblem.fAlpha = _str2double (cTextNodeContent);
361
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "direction") == 0)
362
pGaugeIndicator->direction = _str2double (cNodeContent);
363
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posStart") == 0)
364
pGaugeIndicator->posStart = _str2double (cNodeContent);
365
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posStop") == 0)
366
pGaugeIndicator->posStop = _str2double (cNodeContent);
367
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "nb images") == 0)
368
pGaugeIndicator->iNbImages = atoi (cNodeContent);
369
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "offset_x") == 0)
371
pGaugeIndicator->iNeedleOffsetX = atoi (cNodeContent);
373
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "width") == 0)
375
pGaugeIndicator->iNeedleRealWidth = atoi (cNodeContent);
377
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "height") == 0)
379
pGaugeIndicator->iNeedleRealHeight = atoi (cNodeContent);
380
pGaugeIndicator->iNeedleOffsetY = .5 * pGaugeIndicator->iNeedleRealHeight;
382
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "file") == 0)
384
cd_debug("gauge : On charge un fichier (%s)",cNodeContent);
385
ap = xmlHasProp(pGaugeSubNode, "key");
386
cAttribute = xmlNodeGetContent(ap->children);
387
if (strcmp (cAttribute, "needle") == 0 && pGaugeIndicator->pImageNeedle == NULL)
389
g_string_printf (sImagePath, "%s/%s", cThemePath, cNodeContent);
390
pGaugeIndicator->pImageNeedle = _cairo_dock_new_gauge_image (sImagePath->str);
392
else if (strcmp (cAttribute,"image") == 0)
394
if (pGaugeIndicator->iNbImages == 0)
396
pGaugeIndicator->iNbImages = 1;
398
for (node = pGaugeSubNode->next; node != NULL; node = node->next)
400
if (xmlStrcmp (node->name, (const xmlChar *) "file") == 0)
401
pGaugeIndicator->iNbImages ++;
404
if (pGaugeIndicator->pImageList == NULL)
405
pGaugeIndicator->pImageList = g_new0 (GaugeImage, pGaugeIndicator->iNbImages);
407
if (pGaugeIndicator->iNbImageLoaded < pGaugeIndicator->iNbImages)
409
g_string_printf (sImagePath, "%s/%s", cThemePath, cNodeContent);
410
_cairo_dock_init_gauge_image (sImagePath->str, &pGaugeIndicator->pImageList[pGaugeIndicator->iNbImageLoaded]);
411
if (g_bUseOpenGL) // il faut les charger maintenant, car on ne peut pas le faire durant le dessin sur le pbuffer (le chargement n'est pas effectif tout de suite et ca donne des textures blanches).
412
_cairo_dock_load_gauge_image (&pGaugeIndicator->pImageList[pGaugeIndicator->iNbImageLoaded], iWidth, iHeight);
413
pGaugeIndicator->iNbImageLoaded ++;
416
xmlFree (cAttribute);
418
xmlFree (cNodeContent);
420
if (pGaugeIndicator->pImageNeedle != NULL) // on gere le cas d'une aiguille dont la taille est non fournie.
422
if (pGaugeIndicator->iNeedleRealHeight == 0)
424
pGaugeIndicator->iNeedleRealHeight = .12*pGaugeIndicator->pImageNeedle->sizeY; // 12px utiles sur les 100
425
pGaugeIndicator->iNeedleOffsetY = pGaugeIndicator->iNeedleRealHeight/2;
427
if (pGaugeIndicator->iNeedleRealWidth == 0)
429
pGaugeIndicator->iNeedleRealWidth = pGaugeIndicator->pImageNeedle->sizeY; // 100px utiles sur les 100
430
pGaugeIndicator->iNeedleOffsetX = 10;
432
if (g_bUseOpenGL) // meme remarque.
433
_cairo_dock_load_gauge_needle (pGaugeIndicator, iWidth, iHeight);
435
pGauge->pIndicatorList = g_list_append (pGauge->pIndicatorList, pGaugeIndicator);
438
cairo_dock_close_xml_file (pGaugeTheme);
439
g_string_free (sImagePath, TRUE);
441
g_return_val_if_fail (CAIRO_DATA_RENDERER (pGauge)->iRank != 0 && pGaugeIndicator != NULL, FALSE);
442
CAIRO_DATA_RENDERER (pGauge)->bCanRenderValueAsText = (pGaugeIndicator->textZone.fWidth != 0 && pGaugeIndicator->textZone.fHeight != 0);
446
static void cairo_dock_load_gauge (Gauge *pGauge, CairoContainer *pContainer, CairoGaugeAttribute *pAttribute)
448
_cairo_dock_load_gauge_theme (pGauge, pAttribute->cThemePath);
450
/// charger les emblemes...
454
////////////////////////////////////////////
455
////////////// RENDER GAUGE ////////////////
456
////////////////////////////////////////////
457
static void _draw_gauge_needle (cairo_t *pCairoContext, Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
459
GaugeImage *pGaugeImage = pGaugeIndicator->pImageNeedle;
460
if(pGaugeImage != NULL)
462
double fAngle = (pGaugeIndicator->posStart + fValue * (pGaugeIndicator->posStop - pGaugeIndicator->posStart)) * G_PI / 180.;
463
if (pGaugeIndicator->direction < 0)
466
double fHalfX = pGauge->pImageBackground->sizeX / 2.0f * (1 + pGaugeIndicator->posX);
467
double fHalfY = pGauge->pImageBackground->sizeY / 2.0f * (1 - pGaugeIndicator->posY);
469
cairo_save (pCairoContext);
471
cairo_scale (pCairoContext,
472
(double) CAIRO_DATA_RENDERER (pGauge)->iWidth / (double) pGaugeImage->sizeX,
473
(double) CAIRO_DATA_RENDERER (pGauge)->iHeight / (double) pGaugeImage->sizeY);
474
cairo_translate (pCairoContext, fHalfX, fHalfY);
475
cairo_rotate (pCairoContext, -G_PI/2 + fAngle);
477
rsvg_handle_render_cairo (pGaugeImage->pSvgHandle, pCairoContext);
479
cairo_restore (pCairoContext);
482
static void _draw_gauge_image (cairo_t *pCairoContext, Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
484
int iNumImage = fValue * (pGaugeIndicator->iNbImages - 1) + 0.5;
485
g_return_if_fail (iNumImage < pGaugeIndicator->iNbImages);
487
GaugeImage *pGaugeImage = &pGaugeIndicator->pImageList[iNumImage];
488
if (pGaugeImage->pSurface == NULL)
490
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
491
_cairo_dock_load_gauge_image (pGaugeImage, iWidth, iHeight);
494
if (pGaugeImage->pSurface != NULL)
496
cairo_set_source_surface (pCairoContext, pGaugeImage->pSurface, 0.0f, 0.0f);
497
cairo_paint (pCairoContext);
500
static void cairo_dock_draw_one_gauge (cairo_t *pCairoContext, Gauge *pGauge, int iDataOffset)
502
GaugeImage *pGaugeImage;
503
//\________________ On affiche le fond.
504
if(pGauge->pImageBackground != NULL)
506
pGaugeImage = pGauge->pImageBackground;
507
cairo_set_source_surface (pCairoContext, pGaugeImage->pSurface, 0.0f, 0.0f);
508
cairo_paint (pCairoContext);
511
//\________________ On represente l'indicateur de chaque valeur.
512
GList *pIndicatorElement;
515
GaugeIndicator *pIndicator;
516
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
517
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
519
for (i = iDataOffset, pIndicatorElement = pGauge->pIndicatorList; i < pData->iNbValues && pIndicatorElement != NULL; i++, pIndicatorElement = pIndicatorElement->next)
521
pIndicator = pIndicatorElement->data;
522
fValue = cairo_data_renderer_get_normalized_current_value (pRenderer, i);
524
if (pIndicator->pImageNeedle != NULL) // c'est une aiguille.
526
_draw_gauge_needle (pCairoContext, pGauge, pIndicator, fValue);
528
else // c'est une image.
530
_draw_gauge_image (pCairoContext, pGauge, pIndicator, fValue);
533
if (/**pRenderer->bWriteValues && */pIndicator->textZone.fWidth != 0 && pIndicator->textZone.fHeight != 0) // cet indicateur a un emplacement pour le texte de la valeur.
535
cairo_data_renderer_format_value (pRenderer, fValue, i);
536
//g_print (" >>>%s\n", pRenderer->cFormatBuffer);
537
cairo_save (pCairoContext);
538
cairo_set_source_rgb (pCairoContext, pIndicator->textZone.pColor[0], pIndicator->textZone.pColor[1], pIndicator->textZone.pColor[2]);
540
PangoLayout *pLayout = pango_cairo_create_layout (pCairoContext);
541
PangoFontDescription *fd = pango_font_description_from_string ("Monospace 12");
542
pango_layout_set_font_description (pLayout, fd);
544
PangoRectangle ink, log;
545
pango_layout_set_text (pLayout, pRenderer->cFormatBuffer, -1);
546
pango_layout_get_pixel_extents (pLayout, &ink, &log);
547
double fZoom = MIN (pIndicator->textZone.fWidth * pRenderer->iWidth / (log.width), pIndicator->textZone.fHeight * pRenderer->iHeight / log.height);
549
cairo_move_to (pCairoContext,
550
floor ((1. + pIndicator->textZone.fX) * pRenderer->iWidth/2 - log.width*fZoom/2),
551
floor ((1. - pIndicator->textZone.fY) * pRenderer->iHeight/2 - log.height*fZoom/2));
552
cairo_scale (pCairoContext,
555
pango_cairo_show_layout (pCairoContext, pLayout);
556
cairo_restore (pCairoContext);
560
//\________________ On affiche l'avant-plan.
561
if(pGauge->pImageForeground != NULL)
563
pGaugeImage = pGauge->pImageForeground;
564
cairo_set_source_surface (pCairoContext, pGaugeImage->pSurface, 0.0f, 0.0f);
565
cairo_paint (pCairoContext);
568
void cairo_dock_render_gauge (Gauge *pGauge, cairo_t *pCairoContext)
570
g_return_if_fail (pGauge != NULL && pGauge->pIndicatorList != NULL);
571
g_return_if_fail (pCairoContext != NULL && cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS);
573
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
574
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
575
int iNbDrawings = (int) ceil (1. * pData->iNbValues / pRenderer->iRank);
576
int i, iDataOffset = 0;
577
for (i = 0; i < iNbDrawings; i ++)
579
if (iNbDrawings > 1) // on va dessiner la jauges plusieurs fois, la 1ere en grand et les autres en petit autour.
581
cairo_save (pCairoContext);
584
cairo_scale (pCairoContext, 2./3, 2./3);
588
cairo_translate (pCairoContext, 2 * pRenderer->iWidth / 3, 2 * pRenderer->iHeight / 3);
589
cairo_scale (pCairoContext, 1./3, 1./3);
593
cairo_translate (pCairoContext, 2 * pRenderer->iWidth / 3, 0.);
594
cairo_scale (pCairoContext, 1./3, 1./3);
598
cairo_translate (pCairoContext, 0., 2 * pRenderer->iHeight / 3);
599
cairo_scale (pCairoContext, 1./3, 1./3);
601
else // 5 valeurs faut pas pousser non plus.
605
cairo_dock_draw_one_gauge (pCairoContext, pGauge, iDataOffset);
608
cairo_restore (pCairoContext);
610
iDataOffset += pRenderer->iRank;
614
///////////////////////////////////////////////
615
/////////////// RENDER OPENGL /////////////////
616
///////////////////////////////////////////////
617
static void _draw_gauge_image_opengl (Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
619
int iNumImage = fValue * (pGaugeIndicator->iNbImages - 1) + 0.5;
620
g_return_if_fail (iNumImage < pGaugeIndicator->iNbImages);
622
GaugeImage *pGaugeImage = &pGaugeIndicator->pImageList[iNumImage];
623
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
624
/*if (pGaugeImage->iTexture == 0)
626
_cairo_dock_load_gauge_image (NULL, pGaugeImage, iWidth, iHeight); // pas besoin d'un cairo_context pour creer une cairo_image_surface.
630
if (pGaugeImage->iTexture != 0)
632
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, iWidth, iHeight);
635
static void _draw_gauge_needle_opengl (Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
637
GaugeImage *pGaugeImage = pGaugeIndicator->pImageNeedle;
638
g_return_if_fail (pGaugeImage != NULL);
640
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
641
/*if (pGaugeImage->iTexture == 0)
643
_cairo_dock_load_gauge_needle (NULL, pGaugeIndicator, iWidth, iHeight); // pas besoin d'un cairo_context pour creer une cairo_image_surface.
647
if(pGaugeImage->iTexture != 0)
649
double fAngle = (pGaugeIndicator->posStart + fValue * (pGaugeIndicator->posStop - pGaugeIndicator->posStart));
650
if (pGaugeIndicator->direction < 0)
652
double fHalfX = iWidth / 2.0f * (0 + pGaugeIndicator->posX);
653
double fHalfY = iHeight / 2.0f * (0 + pGaugeIndicator->posY);
657
glTranslatef (fHalfX, fHalfY, 0.);
658
glRotatef (90. - fAngle, 0., 0., 1.);
659
glTranslatef (pGaugeIndicator->iNeedleWidth/2 - pGaugeIndicator->fNeedleScale * pGaugeIndicator->iNeedleOffsetX, 0., 0.);
660
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, pGaugeIndicator->iNeedleWidth, pGaugeIndicator->iNeedleHeight);
665
static void cairo_dock_draw_one_gauge_opengl (Gauge *pGauge, int iDataOffset)
667
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
668
GaugeImage *pGaugeImage;
670
//\________________ On affiche le fond.
671
if(pGauge->pImageBackground != NULL)
673
pGaugeImage = pGauge->pImageBackground;
674
if (pGaugeImage->iTexture != 0)
675
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, iWidth, iHeight);
678
//\________________ On represente l'indicateur de chaque valeur.
679
GList *pIndicatorElement;
682
GaugeIndicator *pIndicator;
683
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
684
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
686
for (i = iDataOffset, pIndicatorElement = pGauge->pIndicatorList; i < pData->iNbValues && pIndicatorElement != NULL; i++, pIndicatorElement = pIndicatorElement->next)
688
pIndicator = pIndicatorElement->data;
689
fValue = cairo_data_renderer_get_normalized_current_value_with_latency (pRenderer, i);
691
if (pIndicator->pImageNeedle != NULL) // c'est une aiguille.
693
_draw_gauge_needle_opengl (pGauge, pIndicator, fValue);
695
else // c'est une image.
697
_draw_gauge_image_opengl (pGauge, pIndicator, fValue);
700
if (/**pRenderer->bWriteValues && */pIndicator->textZone.fWidth != 0 && pIndicator->textZone.fHeight != 0) // cet indicateur a un emplacement pour le texte de la valeur.
702
cairo_data_renderer_format_value (pRenderer, fValue, i);
704
CairoDockGLFont *pFont = cairo_dock_get_default_data_renderer_font ();
705
glColor3f (pIndicator->textZone.pColor[0], pIndicator->textZone.pColor[1], pIndicator->textZone.pColor[2]);
708
cairo_dock_draw_gl_text_at_position_in_area (pRenderer->cFormatBuffer,
710
floor (pIndicator->textZone.fX * pRenderer->iWidth/2),
711
floor (pIndicator->textZone.fY * pRenderer->iHeight/2),
712
pIndicator->textZone.fWidth * pRenderer->iWidth,
713
pIndicator->textZone.fHeight * pRenderer->iHeight,
717
_cairo_dock_enable_texture ();
718
glColor3f (1.0, 1.0, 1.0);
722
//\________________ On affiche l'avant-plan.
723
if(pGauge->pImageForeground != NULL)
725
pGaugeImage = pGauge->pImageForeground;
726
if (pGaugeImage->iTexture != 0)
727
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, iWidth, iHeight);
730
static void cairo_dock_render_gauge_opengl (Gauge *pGauge)
732
g_return_if_fail (pGauge != NULL && pGauge->pIndicatorList != NULL);
734
_cairo_dock_enable_texture ();
735
_cairo_dock_set_blend_pbuffer (); // ceci reste un mystere...
736
_cairo_dock_set_alpha (1.);
738
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
739
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
740
int iNbDrawings = (int) ceil (1. * pData->iNbValues / pRenderer->iRank);
741
int i, iDataOffset = 0;
742
for (i = 0; i < iNbDrawings; i ++)
744
if (iNbDrawings > 1) // on va dessiner la jauges plusieurs fois, la 1ere en grand et les autres en petit autour.
749
glTranslatef (-pRenderer->iWidth / 6, pRenderer->iHeight / 6, 0.);
750
glScalef (2./3, 2./3, 1.);
754
glTranslatef (pRenderer->iWidth / 3, - pRenderer->iHeight / 3, 0.);
755
glScalef (1./3, 1./3, 1.);
759
glTranslatef (pRenderer->iWidth / 3, pRenderer->iHeight / 3, 0.);
760
glScalef (1./3, 1./3, 1.);
764
glTranslatef (-pRenderer->iWidth / 3, -pRenderer->iHeight / 3, 0.);
765
glScalef (1./3, 1./3, 1.);
767
else // 5 valeurs faut pas pousser non plus.
771
cairo_dock_draw_one_gauge_opengl (pGauge, iDataOffset);
776
iDataOffset += pRenderer->iRank;
778
_cairo_dock_disable_texture ();
782
//////////////////////////////////////////////
783
/////////////// RELOAD GAUGE /////////////////
784
//////////////////////////////////////////////
785
static void cairo_dock_reload_gauge (Gauge *pGauge)
787
//g_print ("%s (%dx%d)\n", __func__, iWidth, iHeight);
788
g_return_if_fail (pGauge != NULL);
790
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
791
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
792
if (pGauge->pImageBackground != NULL)
794
_cairo_dock_load_gauge_image (pGauge->pImageBackground, iWidth, iHeight);
797
if (pGauge->pImageForeground != NULL)
799
_cairo_dock_load_gauge_image (pGauge->pImageForeground, iWidth, iHeight);
802
GaugeIndicator *pGaugeIndicator;
803
GaugeImage *pGaugeImage;
805
GList *pElement, *pElement2;
806
for (pElement = pGauge->pIndicatorList; pElement != NULL; pElement = pElement->next)
808
pGaugeIndicator = pElement->data;
809
for (i = 0; i < pGaugeIndicator->iNbImages; i ++)
811
pGaugeImage = &pGaugeIndicator->pImageList[i];
812
_cairo_dock_load_gauge_image (pGaugeImage, iWidth, iHeight);
814
if (g_bUseOpenGL && pGaugeIndicator->pImageNeedle)
816
_cairo_dock_load_gauge_needle (pGaugeIndicator, iWidth, iHeight);
821
////////////////////////////////////////////
822
/////////////// FREE GAUGE /////////////////
823
////////////////////////////////////////////
824
static void _cairo_dock_free_gauge_image(GaugeImage *pGaugeImage, gboolean bFree)
826
if (pGaugeImage == NULL)
830
if(pGaugeImage->pSvgHandle != NULL)
831
rsvg_handle_free (pGaugeImage->pSvgHandle);
832
if(pGaugeImage->pSurface != NULL)
833
cairo_surface_destroy (pGaugeImage->pSurface);
834
if (pGaugeImage->iTexture != 0)
835
_cairo_dock_delete_texture (pGaugeImage->iTexture);
838
g_free (pGaugeImage);
840
static void _cairo_dock_free_gauge_indicator(GaugeIndicator *pGaugeIndicator)
842
if (pGaugeIndicator == NULL)
847
for (i = 0; i < pGaugeIndicator->iNbImages; i ++)
849
_cairo_dock_free_gauge_image (&pGaugeIndicator->pImageList[i], FALSE);
851
g_free (pGaugeIndicator->pImageList);
853
_cairo_dock_free_gauge_image (pGaugeIndicator->pImageNeedle, TRUE);
855
g_free (pGaugeIndicator);
857
static void cairo_dock_free_gauge (Gauge *pGauge)
863
_cairo_dock_free_gauge_image(pGauge->pImageBackground, TRUE);
864
_cairo_dock_free_gauge_image(pGauge->pImageForeground, TRUE);
867
for (pElement = pGauge->pIndicatorList; pElement != NULL; pElement = pElement->next)
869
_cairo_dock_free_gauge_indicator (pElement->data);
871
g_list_free (pGauge->pIndicatorList);
877
//////////////////////////////////////////
878
/////////////// RENDERER /////////////////
879
//////////////////////////////////////////
880
Gauge *cairo_dock_new_gauge (void)
882
Gauge *pGauge = g_new0 (Gauge, 1);
883
pGauge->dataRenderer.interface.new = (CairoDataRendererNewFunc) cairo_dock_new_gauge;
884
pGauge->dataRenderer.interface.load = (CairoDataRendererLoadFunc) cairo_dock_load_gauge;
885
pGauge->dataRenderer.interface.render = (CairoDataRendererRenderFunc) cairo_dock_render_gauge;
886
pGauge->dataRenderer.interface.render_opengl = (CairoDataRendererRenderOpenGLFunc) cairo_dock_render_gauge_opengl;
887
pGauge->dataRenderer.interface.reload = (CairoDataRendererReloadFunc) cairo_dock_reload_gauge;
888
pGauge->dataRenderer.interface.free = (CairoDataRendererFreeFunc) cairo_dock_free_gauge;
893
/////////////////////////////////////////////////
894
/////////////// LIST OF THEMES /////////////////
895
/////////////////////////////////////////////////
896
/*GHashTable *cairo_dock_list_available_gauges (void)
898
gchar *cGaugeShareDir = g_strdup (CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_GAUGES_DIR);
899
gchar *cGaugeUserDir = g_strdup_printf ("%s/%s", g_cExtrasDirPath, CAIRO_DOCK_GAUGES_DIR);
900
GHashTable *pGaugeTable = cairo_dock_list_packages (cGaugeShareDir, cGaugeUserDir, CAIRO_DOCK_GAUGES_DIR);
902
g_free (cGaugeShareDir);
903
g_free (cGaugeUserDir);
907
gchar *cairo_dock_get_gauge_theme_path (const gchar *cThemeName, CairoDockPackageType iType) // utile pour DBus aussi.
909
const gchar *cGaugeShareDir = CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_GAUGES_DIR;
910
gchar *cGaugeUserDir = g_strdup_printf ("%s/%s", g_cExtrasDirPath, CAIRO_DOCK_GAUGES_DIR);
911
gchar *cGaugePath = cairo_dock_get_package_path (cThemeName, cGaugeShareDir, cGaugeUserDir, CAIRO_DOCK_GAUGES_DIR, iType);
912
g_free (cGaugeUserDir);
916
gchar *cairo_dock_get_package_path_for_gauge (const gchar *cAppletConfFilePath, GKeyFile *pKeyFile, const gchar *cGroupName, const gchar *cKeyName, gboolean *bFlushConfFileNeeded, const gchar *cDefaultThemeName)
918
gchar *cChosenThemeName = cairo_dock_get_string_key_value (pKeyFile, cGroupName, cKeyName, bFlushConfFileNeeded, cDefaultThemeName, NULL, NULL);
919
if (cChosenThemeName == NULL)
920
cChosenThemeName = g_strdup ("Turbo-night-fuel");
922
CairoDockPackageType iType = cairo_dock_extract_package_type_from_name (cChosenThemeName);
923
gchar *cGaugePath = cairo_dock_get_gauge_theme_path (cChosenThemeName, iType);
925
if (cGaugePath == NULL) // theme introuvable.
926
cGaugePath = g_strdup (CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_GAUGES_DIR"/Turbo-night-fuel");
928
if (iType != CAIRO_DOCK_ANY_THEME)
930
g_key_file_set_string (pKeyFile, cGroupName, cKeyName, cChosenThemeName);
931
cairo_dock_write_keys_to_file (pKeyFile, cAppletConfFilePath);
933
cd_debug ("Theme de la jauge : %s", cGaugePath);
934
g_free (cChosenThemeName);
939
/// deprecated ... to be added in the DataRenderer API.
940
void cairo_dock_add_watermark_on_gauge (Gauge *pGauge, gchar *cImagePath, double fAlpha)
942
g_return_if_fail (pGauge != NULL && cImagePath != NULL);
944
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
945
cairo_surface_t *pWatermarkSurface = cairo_dock_create_surface_for_icon (cImagePath, pRenderer->iWidth/2, pRenderer->iHeight/2);
947
if (pGauge->pImageBackground == NULL)
949
pGauge->pImageBackground = g_new0 (GaugeImage, 1);
950
pGauge->pImageBackground->sizeX = pRenderer->iWidth;
951
pGauge->pImageBackground->sizeY = pRenderer->iHeight;
953
pGauge->pImageBackground->pSurface = cairo_dock_create_blank_surface (
958
cairo_t *pCairoContext = cairo_create (pGauge->pImageBackground->pSurface);
959
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
961
cairo_set_source_surface (pCairoContext, pWatermarkSurface, pRenderer->iWidth/4, pRenderer->iHeight/4);
962
cairo_paint_with_alpha (pCairoContext, fAlpha);
964
cairo_destroy (pCairoContext);
966
cairo_surface_destroy (pWatermarkSurface);